summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-09-17 23:57:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-09-17 23:57:05 +0000
commitfc3b7aaae094fccb1a8a39a5cb27cf6d4c0816e2 (patch)
tree05e33f58bfc5d4ebae918581253b9fd737d7f8e9 /lib/Sema/SemaTemplateInstantiateDecl.cpp
parent381a99ee4c8448750680790056b65b89290e4e60 (diff)
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@217995 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp168
1 files changed, 35 insertions, 133 deletions
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 62a3e11ac9..ddd47ee1e3 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2988,7 +2988,7 @@ TemplateDeclInstantiator::SubstFunctionType(FunctionDecl *D,
/// Introduce the instantiated function parameters into the local
/// instantiation scope, and set the parameter names to those used
/// in the template.
-static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
+static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
const FunctionDecl *PatternDecl,
LocalInstantiationScope &Scope,
const MultiLevelTemplateArgumentList &TemplateArgs) {
@@ -2999,15 +2999,22 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
// Simple case: not a parameter pack.
assert(FParamIdx < Function->getNumParams());
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
+ FunctionParam->setDeclName(PatternParam->getDeclName());
// If the parameter's type is not dependent, update it to match the type
// in the pattern. They can differ in top-level cv-qualifiers, and we want
// the pattern's type here. If the type is dependent, they can't differ,
- // per core issue 1668.
+ // per core issue 1668. Substitute into the type from the pattern, in case
+ // it's instantiation-dependent.
// FIXME: Updating the type to work around this is at best fragile.
- if (!PatternDecl->getType()->isDependentType())
- FunctionParam->setType(PatternParam->getType());
+ if (!PatternDecl->getType()->isDependentType()) {
+ QualType T = S.SubstType(PatternParam->getType(), TemplateArgs,
+ FunctionParam->getLocation(),
+ FunctionParam->getDeclName());
+ if (T.isNull())
+ return true;
+ FunctionParam->setType(T);
+ }
- FunctionParam->setDeclName(PatternParam->getDeclName());
Scope.InstantiatedLocal(PatternParam, FunctionParam);
++FParamIdx;
continue;
@@ -3019,136 +3026,27 @@ static void addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function,
= S.getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs);
assert(NumArgumentsInExpansion &&
"should only be called when all template arguments are known");
+ QualType PatternType =
+ PatternParam->getType()->castAs<PackExpansionType>()->getPattern();
for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) {
ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx);
- if (!PatternDecl->getType()->isDependentType())
- FunctionParam->setType(PatternParam->getType());
-
FunctionParam->setDeclName(PatternParam->getDeclName());
- Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
- ++FParamIdx;
- }
- }
-}
-
-static void InstantiateExceptionSpec(Sema &SemaRef, FunctionDecl *New,
- const FunctionProtoType *Proto,
- const MultiLevelTemplateArgumentList &TemplateArgs) {
- assert(Proto->getExceptionSpecType() != EST_Uninstantiated);
-
- // C++11 [expr.prim.general]p3:
- // If a declaration declares a member function or member function
- // template of a class X, the expression this is a prvalue of type
- // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq
- // and the end of the function-definition, member-declarator, or
- // declarator.
- CXXRecordDecl *ThisContext = nullptr;
- unsigned ThisTypeQuals = 0;
- if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(New)) {
- ThisContext = Method->getParent();
- ThisTypeQuals = Method->getTypeQualifiers();
- }
- Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, ThisTypeQuals,
- SemaRef.getLangOpts().CPlusPlus11);
-
- // The function has an exception specification or a "noreturn"
- // attribute. Substitute into each of the exception types.
- SmallVector<QualType, 4> Exceptions;
- for (unsigned I = 0, N = Proto->getNumExceptions(); I != N; ++I) {
- // FIXME: Poor location information!
- if (const PackExpansionType *PackExpansion
- = Proto->getExceptionType(I)->getAs<PackExpansionType>()) {
- // We have a pack expansion. Instantiate it.
- SmallVector<UnexpandedParameterPack, 2> Unexpanded;
- SemaRef.collectUnexpandedParameterPacks(PackExpansion->getPattern(),
- Unexpanded);
- assert(!Unexpanded.empty() &&
- "Pack expansion without parameter packs?");
-
- bool Expand = false;
- bool RetainExpansion = false;
- Optional<unsigned> NumExpansions = PackExpansion->getNumExpansions();
- if (SemaRef.CheckParameterPacksForExpansion(New->getLocation(),
- SourceRange(),
- Unexpanded,
- TemplateArgs,
- Expand,
- RetainExpansion,
- NumExpansions))
- break;
-
- if (!Expand) {
- // We can't expand this pack expansion into separate arguments yet;
- // just substitute into the pattern and create a new pack expansion
- // type.
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1);
- QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
- TemplateArgs,
- New->getLocation(), New->getDeclName());
+ if (!PatternDecl->getType()->isDependentType()) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, Arg);
+ QualType T = S.SubstType(PatternType, TemplateArgs,
+ FunctionParam->getLocation(),
+ FunctionParam->getDeclName());
if (T.isNull())
- break;
-
- T = SemaRef.Context.getPackExpansionType(T, NumExpansions);
- Exceptions.push_back(T);
- continue;
- }
-
- // Substitute into the pack expansion pattern for each template
- bool Invalid = false;
- for (unsigned ArgIdx = 0; ArgIdx != *NumExpansions; ++ArgIdx) {
- Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, ArgIdx);
-
- QualType T = SemaRef.SubstType(PackExpansion->getPattern(),
- TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull()) {
- Invalid = true;
- break;
- }
-
- Exceptions.push_back(T);
+ return true;
+ FunctionParam->setType(T);
}
- if (Invalid)
- break;
-
- continue;
- }
-
- QualType T
- = SemaRef.SubstType(Proto->getExceptionType(I), TemplateArgs,
- New->getLocation(), New->getDeclName());
- if (T.isNull() ||
- SemaRef.CheckSpecifiedExceptionType(T, New->getLocation()))
- continue;
-
- Exceptions.push_back(T);
- }
- Expr *NoexceptExpr = nullptr;
- if (Expr *OldNoexceptExpr = Proto->getNoexceptExpr()) {
- EnterExpressionEvaluationContext Unevaluated(SemaRef,
- Sema::ConstantEvaluated);
- ExprResult E = SemaRef.SubstExpr(OldNoexceptExpr, TemplateArgs);
- if (E.isUsable())
- E = SemaRef.CheckBooleanCondition(E.get(), E.get()->getLocStart());
-
- if (E.isUsable()) {
- NoexceptExpr = E.get();
- if (!NoexceptExpr->isTypeDependent() &&
- !NoexceptExpr->isValueDependent())
- NoexceptExpr
- = SemaRef.VerifyIntegerConstantExpression(NoexceptExpr,
- nullptr, diag::err_noexcept_needs_constant_expression,
- /*AllowFold*/ false).get();
+ Scope.InstantiatedLocalPackArg(PatternParam, FunctionParam);
+ ++FParamIdx;
}
}
- FunctionProtoType::ExceptionSpecInfo ESI;
- ESI.Type = Proto->getExceptionSpecType();
- ESI.Exceptions = Exceptions;
- ESI.NoexceptExpr = NoexceptExpr;
-
- SemaRef.UpdateExceptionSpec(New, ESI);
+ return false;
}
void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
@@ -3175,11 +3073,14 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true);
FunctionDecl *Template = Proto->getExceptionSpecTemplate();
- addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs);
+ if (addInstantiatedParametersToScope(*this, Decl, Template, Scope,
+ TemplateArgs)) {
+ UpdateExceptionSpec(Decl, EST_None);
+ return;
+ }
- ::InstantiateExceptionSpec(*this, Decl,
- Template->getType()->castAs<FunctionProtoType>(),
- TemplateArgs);
+ SubstExceptionSpec(Decl, Template->getType()->castAs<FunctionProtoType>(),
+ TemplateArgs);
}
/// \brief Initializes the common fields of an instantiation function
@@ -3248,7 +3149,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
New->setType(SemaRef.Context.getFunctionType(
NewProto->getReturnType(), NewProto->getParamTypes(), EPI));
} else {
- ::InstantiateExceptionSpec(SemaRef, New, Proto, TemplateArgs);
+ SemaRef.SubstExceptionSpec(New, Proto, TemplateArgs);
}
}
@@ -3438,8 +3339,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
MultiLevelTemplateArgumentList TemplateArgs =
getTemplateInstantiationArgs(Function, nullptr, false, PatternDecl);
- addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
- TemplateArgs);
+ if (addInstantiatedParametersToScope(*this, Function, PatternDecl, Scope,
+ TemplateArgs))
+ return;
// If this is a constructor, instantiate the member initializers.
if (const CXXConstructorDecl *Ctor =