summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-10-16 23:00:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-10-16 23:00:46 +0000
commit4dca855aadabe4348a36e07e20e41605eedcf212 (patch)
tree10fad724ebcba8ab12d674a6bc8a933dcba3908f /lib/Sema/SemaTemplateInstantiate.cpp
parentdc6d797fc1dcf1a26aceaf7422d0f5833108668c (diff)
Re-commit r217995 and follow-up patches (r217997, r218011, r218053). These were
reverted in r218058 because they triggered a rejects-valid bug in MSVC. Original commit message from r217995: Instantiate exception specifications when instantiating function types (other than the type of a function declaration). We previously didn't instantiate these at all! This also covers the pathological case where the only mention of a parameter pack is within the exception specification; this gives us a second way (other than alias templates) to reach the horrible state where a type contains an unexpanded pack, but its canonical type does not. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219977 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp62
1 files changed, 46 insertions, 16 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 9c1ffb0c65..a9aae00940 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -791,11 +791,17 @@ namespace {
ExprResult TransformFunctionParmPackExpr(FunctionParmPackExpr *E);
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL);
+ FunctionProtoTypeLoc TL) {
+ // Call the base version; it will forward to our overridden version below.
+ return inherited::TransformFunctionProtoType(TLB, TL);
+ }
+
+ template<typename Fn>
QualType TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals);
+ unsigned ThisTypeQuals,
+ Fn TransformExceptionSpec);
ParmVarDecl *TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
@@ -1327,21 +1333,16 @@ ExprResult TemplateInstantiator::TransformCXXDefaultArgExpr(
E->getParam());
}
-QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
- FunctionProtoTypeLoc TL) {
- // We need a local instantiation scope for this function prototype.
- LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
- return inherited::TransformFunctionProtoType(TLB, TL);
-}
-
+template<typename Fn>
QualType TemplateInstantiator::TransformFunctionProtoType(TypeLocBuilder &TLB,
FunctionProtoTypeLoc TL,
CXXRecordDecl *ThisContext,
- unsigned ThisTypeQuals) {
+ unsigned ThisTypeQuals,
+ Fn TransformExceptionSpec) {
// We need a local instantiation scope for this function prototype.
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
- return inherited::TransformFunctionProtoType(TLB, TL, ThisContext,
- ThisTypeQuals);
+ return inherited::TransformFunctionProtoType(
+ TLB, TL, ThisContext, ThisTypeQuals, TransformExceptionSpec);
}
ParmVarDecl *
@@ -1576,7 +1577,8 @@ static bool NeedsInstantiationAsFunctionType(TypeSourceInfo *T) {
/// A form of SubstType intended specifically for instantiating the
/// type of a FunctionDecl. Its purpose is solely to force the
-/// instantiation of default-argument expressions.
+/// instantiation of default-argument expressions and to avoid
+/// instantiating an exception-specification.
TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
const MultiLevelTemplateArgumentList &Args,
SourceLocation Loc,
@@ -1599,9 +1601,17 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
QualType Result;
- if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) {
- Result = Instantiator.TransformFunctionProtoType(TLB, Proto, ThisContext,
- ThisTypeQuals);
+ if (FunctionProtoTypeLoc Proto =
+ TL.IgnoreParens().getAs<FunctionProtoTypeLoc>()) {
+ // Instantiate the type, other than its exception specification. The
+ // exception specification is instantiated in InitFunctionInstantiation
+ // once we've built the FunctionDecl.
+ // FIXME: Set the exception specification to EST_Uninstantiated here,
+ // instead of rebuilding the function type again later.
+ Result = Instantiator.TransformFunctionProtoType(
+ TLB, Proto, ThisContext, ThisTypeQuals,
+ [](FunctionProtoType::ExceptionSpecInfo &ESI,
+ bool &Changed) { return false; });
} else {
Result = Instantiator.TransformType(TLB, TL);
}
@@ -1611,6 +1621,26 @@ TypeSourceInfo *Sema::SubstFunctionDeclType(TypeSourceInfo *T,
return TLB.getTypeSourceInfo(Context, Result);
}
+void Sema::SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto,
+ const MultiLevelTemplateArgumentList &Args) {
+ FunctionProtoType::ExceptionSpecInfo ESI =
+ Proto->getExtProtoInfo().ExceptionSpec;
+ assert(ESI.Type != EST_Uninstantiated);
+
+ TemplateInstantiator Instantiator(*this, Args, New->getLocation(),
+ New->getDeclName());
+
+ SmallVector<QualType, 4> ExceptionStorage;
+ bool Changed = false;
+ if (Instantiator.TransformExceptionSpec(
+ New->getTypeSourceInfo()->getTypeLoc().getLocEnd(), ESI,
+ ExceptionStorage, Changed))
+ // On error, recover by dropping the exception specification.
+ ESI.Type = EST_None;
+
+ UpdateExceptionSpec(New, ESI);
+}
+
ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
const MultiLevelTemplateArgumentList &TemplateArgs,
int indexAdjustment,