summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2018-04-06 14:26:03 +0000
committerpatrick <patrick@openbsd.org>2018-04-06 14:26:03 +0000
commitbdabc2f19ffb9e20600dad6e8a300842a7bda50e (patch)
treec50e7b2e5449b074651bb82a58517a8ebc4a8cf7 /gnu/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
parentPrint a 'p' flag for file descriptors that were opened after pledge(2). (diff)
downloadwireguard-openbsd-bdabc2f19ffb9e20600dad6e8a300842a7bda50e.tar.xz
wireguard-openbsd-bdabc2f19ffb9e20600dad6e8a300842a7bda50e.zip
Import LLVM 6.0.1 release including clang, lld and lldb.
"where is the kaboom?" deraadt@
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r--gnu/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp200
1 files changed, 127 insertions, 73 deletions
diff --git a/gnu/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/gnu/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 4a26efcc943..9163fbc6f7e 100644
--- a/gnu/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/gnu/llvm/tools/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1195,7 +1195,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
// Look for a previous declaration of the template in the owning
// context.
LookupResult R(SemaRef, Pattern->getDeclName(), Pattern->getLocation(),
- Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ Sema::LookupOrdinaryName,
+ SemaRef.forRedeclarationInCurContext());
SemaRef.LookupQualifiedName(R, DC);
if (R.isSingleResult()) {
@@ -1586,9 +1587,10 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context,
}
/// Normal class members are of more specific types and therefore
-/// don't make it here. This function serves two purposes:
+/// don't make it here. This function serves three purposes:
/// 1) instantiating function templates
/// 2) substituting friend declarations
+/// 3) substituting deduction guide declarations for nested class templates
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams) {
// Check whether there is already a function template specialization for
@@ -1649,14 +1651,19 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
TemplateArgs);
}
+ DeclarationNameInfo NameInfo
+ = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs);
+
FunctionDecl *Function;
- if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D))
+ if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) {
Function = CXXDeductionGuideDecl::Create(
- SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(),
- D->getNameInfo(), T, TInfo, D->getSourceRange().getEnd());
- else {
+ SemaRef.Context, DC, D->getInnerLocStart(), DGuide->isExplicit(),
+ NameInfo, T, TInfo, D->getSourceRange().getEnd());
+ if (DGuide->isCopyDeductionCandidate())
+ cast<CXXDeductionGuideDecl>(Function)->setIsCopyDeductionCandidate();
+ } else {
Function = FunctionDecl::Create(
- SemaRef.Context, DC, D->getInnerLocStart(), D->getNameInfo(), T, TInfo,
+ SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo,
D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(),
D->hasWrittenPrototype(), D->isConstexpr());
Function->setRangeEnd(D->getSourceRange().getEnd());
@@ -1685,7 +1692,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
Params[P]->setOwningFunction(Function);
Function->setParams(Params);
- SourceLocation InstantiateAtPOI;
if (TemplateParams) {
// Our resulting instantiation is actually a function template, since we
// are substituting only the outer template parameters. For example, given
@@ -1736,7 +1742,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
SemaRef, Function->getDeclName(), SourceLocation(),
D->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
: Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ D->isLocalExternDecl() ? Sema::ForExternalRedeclaration
+ : SemaRef.forRedeclarationInCurContext());
if (DependentFunctionTemplateSpecializationInfo *Info
= D->getDependentSpecializationInfo()) {
@@ -2054,7 +2061,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Method->setInvalidDecl();
LookupResult Previous(SemaRef, NameInfo, Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ Sema::ForExternalRedeclaration);
if (!FunctionTemplate || TemplateParams || isFriend) {
SemaRef.LookupQualifiedName(Previous, Record);
@@ -2493,7 +2500,7 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
bool CheckRedeclaration = Owner->isRecord();
LookupResult Prev(SemaRef, NameInfo, Sema::LookupUsingDeclName,
- Sema::ForRedeclaration);
+ Sema::ForVisibleRedeclaration);
UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
D->getUsingLoc(),
@@ -2712,7 +2719,7 @@ Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
return nullptr;
LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ Sema::ForExternalRedeclaration);
TemplateArgumentListInfo TemplateArgs;
TemplateArgumentListInfo *TemplateArgsPtr = nullptr;
@@ -2800,8 +2807,9 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner);
// Initializers instantiation sequence.
if (D->getInitializer()) {
- SemaRef.ActOnOpenMPDeclareReductionInitializerStart(
- /*S=*/nullptr, NewDRD);
+ VarDecl *OmpPrivParm =
+ SemaRef.ActOnOpenMPDeclareReductionInitializerStart(
+ /*S=*/nullptr, NewDRD);
const char *Names[] = {"omp_orig", "omp_priv"};
for (auto &Name : Names) {
DeclarationName DN(&SemaRef.Context.Idents.get(Name));
@@ -2809,17 +2817,28 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl(
auto Lookup = NewDRD->lookup(DN);
if (!OldLookup.empty() && !Lookup.empty()) {
assert(Lookup.size() == 1 && OldLookup.size() == 1);
- SemaRef.CurrentInstantiationScope->InstantiatedLocal(
- OldLookup.front(), Lookup.front());
+ auto *OldVD = cast<VarDecl>(OldLookup.front());
+ auto *NewVD = cast<VarDecl>(Lookup.front());
+ SemaRef.InstantiateVariableInitializer(NewVD, OldVD, TemplateArgs);
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldVD, NewVD);
}
}
- SubstInitializer =
- SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get();
- SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(NewDRD,
- SubstInitializer);
+ if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) {
+ SubstInitializer =
+ SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get();
+ } else {
+ IsCorrect = IsCorrect && OmpPrivParm->hasInit();
+ }
+ SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(
+ NewDRD, SubstInitializer, OmpPrivParm);
}
- IsCorrect = IsCorrect && SubstCombiner &&
- (!D->getInitializer() || SubstInitializer);
+ IsCorrect =
+ IsCorrect && SubstCombiner &&
+ (!D->getInitializer() ||
+ (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit &&
+ SubstInitializer) ||
+ (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit &&
+ !SubstInitializer && !SubstInitializer));
} else
IsCorrect = false;
@@ -3710,6 +3729,30 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,
return false;
}
+/// Instantiate (or find existing instantiation of) a function template with a
+/// given set of template arguments.
+///
+/// Usually this should not be used, and template argument deduction should be
+/// used in its place.
+FunctionDecl *
+Sema::InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
+ const TemplateArgumentList *Args,
+ SourceLocation Loc) {
+ FunctionDecl *FD = FTD->getTemplatedDecl();
+
+ sema::TemplateDeductionInfo Info(Loc);
+ InstantiatingTemplate Inst(
+ *this, Loc, FTD, Args->asArray(),
+ CodeSynthesisContext::ExplicitTemplateArgumentSubstitution, Info);
+ if (Inst.isInvalid())
+ return nullptr;
+
+ ContextRAII SavedContext(*this, FD);
+ MultiLevelTemplateArgumentList MArgs(*Args);
+
+ return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
+}
+
/// In the MS ABI, we need to instantiate default arguments of dllexported
/// default constructors along with the constructor definition. This allows IR
/// gen to emit a constructor closure which calls the default constructor with
@@ -3753,7 +3796,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
bool Recursive,
bool DefinitionRequired,
bool AtEndOfTU) {
- if (Function->isInvalidDecl() || Function->isDefined())
+ if (Function->isInvalidDecl() || Function->isDefined() ||
+ isa<CXXDeductionGuideDecl>(Function))
return;
// Never instantiate an explicit specialization except if it is a class scope
@@ -3792,7 +3836,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
PendingInstantiations.push_back(
std::make_pair(Function, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
- if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+ if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
+ !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
Diag(PointOfInstantiation, diag::warn_func_template_missing)
<< Function;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
@@ -3839,7 +3884,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
}
// Note, we should never try to instantiate a deleted function template.
- assert((Pattern || PatternDecl->isDefaulted()) &&
+ assert((Pattern || PatternDecl->isDefaulted() ||
+ PatternDecl->hasSkippedBody()) &&
"unexpected kind of function template definition");
// C++1y [temp.explicit]p10:
@@ -3911,29 +3957,33 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
TemplateArgs))
return;
- if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Function)) {
- // If this is a constructor, instantiate the member initializers.
- InstantiateMemInitializers(Ctor, cast<CXXConstructorDecl>(PatternDecl),
- TemplateArgs);
-
- // If this is an MS ABI dllexport default constructor, instantiate any
- // default arguments.
- if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
- Ctor->isDefaultConstructor()) {
- InstantiateDefaultCtorDefaultArgs(*this, Ctor);
+ if (PatternDecl->hasSkippedBody()) {
+ ActOnSkippedFunctionBody(Function);
+ } else {
+ if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Function)) {
+ // If this is a constructor, instantiate the member initializers.
+ InstantiateMemInitializers(Ctor, cast<CXXConstructorDecl>(PatternDecl),
+ TemplateArgs);
+
+ // If this is an MS ABI dllexport default constructor, instantiate any
+ // default arguments.
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+ Ctor->isDefaultConstructor()) {
+ InstantiateDefaultCtorDefaultArgs(*this, Ctor);
+ }
}
- }
- // Instantiate the function body.
- StmtResult Body = SubstStmt(Pattern, TemplateArgs);
+ // Instantiate the function body.
+ StmtResult Body = SubstStmt(Pattern, TemplateArgs);
- if (Body.isInvalid())
- Function->setInvalidDecl();
+ if (Body.isInvalid())
+ Function->setInvalidDecl();
- // FIXME: finishing the function body while in an expression evaluation
- // context seems wrong. Investigate more.
- ActOnFinishFunctionBody(Function, Body.get(),
- /*IsInstantiation=*/true);
+ // FIXME: finishing the function body while in an expression evaluation
+ // context seems wrong. Investigate more.
+ ActOnFinishFunctionBody(Function, Body.get(),
+ /*IsInstantiation=*/true);
+ }
PerformDependentDiagnostics(PatternDecl, TemplateArgs);
@@ -4005,6 +4055,8 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation(
VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
VarTemplateSpecializationDecl *VarSpec, VarDecl *PatternDecl,
const MultiLevelTemplateArgumentList &TemplateArgs) {
+ assert(PatternDecl->isThisDeclarationADefinition() &&
+ "don't have a definition to instantiate from");
// Do substitution on the type of the declaration
TypeSourceInfo *DI =
@@ -4016,6 +4068,9 @@ VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
// Update the type of this variable template specialization.
VarSpec->setType(DI->getType());
+ // Convert the declaration into a definition now.
+ VarSpec->setCompleteDefinition();
+
// Instantiate the initializer.
InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
@@ -4063,7 +4118,8 @@ void Sema::BuildVariableInstantiation(
*this, NewVar->getDeclName(), NewVar->getLocation(),
NewVar->isLocalExternDecl() ? Sema::LookupRedeclarationWithLinkage
: Sema::LookupOrdinaryName,
- Sema::ForRedeclaration);
+ NewVar->isLocalExternDecl() ? Sema::ForExternalRedeclaration
+ : forRedeclarationInCurContext());
if (NewVar->isLocalExternDecl() && OldVar->getPreviousDecl() &&
(!OldVar->getPreviousDecl()->getDeclContext()->isDependentContext() ||
@@ -4104,7 +4160,8 @@ void Sema::BuildVariableInstantiation(
// it right away if the type contains 'auto'.
if ((!isa<VarTemplateSpecializationDecl>(NewVar) &&
!InstantiatingVarTemplate &&
- !(OldVar->isInline() && OldVar->isThisDeclarationADefinition())) ||
+ !(OldVar->isInline() && OldVar->isThisDeclarationADefinition() &&
+ !NewVar->isThisDeclarationADefinition())) ||
NewVar->getType()->isUndeducedType())
InstantiateVariableInitializer(NewVar, OldVar, TemplateArgs);
@@ -4120,6 +4177,9 @@ void Sema::BuildVariableInstantiation(
void Sema::InstantiateVariableInitializer(
VarDecl *Var, VarDecl *OldVar,
const MultiLevelTemplateArgumentList &TemplateArgs) {
+ if (ASTMutationListener *L = getASTContext().getASTMutationListener())
+ L->VariableDefinitionInstantiated(Var);
+
// We propagate the 'inline' flag with the initializer, because it
// would otherwise imply that the variable is a definition for a
// non-static data member.
@@ -4129,12 +4189,8 @@ void Sema::InstantiateVariableInitializer(
Var->setImplicitlyInline();
if (OldVar->getInit()) {
- if (Var->isStaticDataMember() && !OldVar->isOutOfLine())
- PushExpressionEvaluationContext(
- Sema::ExpressionEvaluationContext::ConstantEvaluated, OldVar);
- else
- PushExpressionEvaluationContext(
- Sema::ExpressionEvaluationContext::PotentiallyEvaluated, OldVar);
+ EnterExpressionEvaluationContext Evaluated(
+ *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var);
// Instantiate the initializer.
ExprResult Init;
@@ -4162,8 +4218,6 @@ void Sema::InstantiateVariableInitializer(
// because of a bogus initializer.
Var->setInvalidDecl();
}
-
- PopExpressionEvaluationContext();
} else {
if (Var->isStaticDataMember()) {
if (!Var->isOutOfLine())
@@ -4188,26 +4242,16 @@ void Sema::InstantiateVariableInitializer(
///
/// \param PointOfInstantiation the point at which the instantiation was
/// required. Note that this is not precisely a "point of instantiation"
-/// for the function, but it's close.
+/// for the variable, but it's close.
///
-/// \param Var the already-instantiated declaration of a static member
-/// variable of a class template specialization.
+/// \param Var the already-instantiated declaration of a templated variable.
///
/// \param Recursive if true, recursively instantiates any functions that
/// are required by this instantiation.
///
/// \param DefinitionRequired if true, then we are performing an explicit
-/// instantiation where an out-of-line definition of the member variable
-/// is required. Complain if there is no such definition.
-void Sema::InstantiateStaticDataMemberDefinition(
- SourceLocation PointOfInstantiation,
- VarDecl *Var,
- bool Recursive,
- bool DefinitionRequired) {
- InstantiateVariableDefinition(PointOfInstantiation, Var, Recursive,
- DefinitionRequired);
-}
-
+/// instantiation where a definition of the variable is required. Complain
+/// if there is no such definition.
void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
VarDecl *Var, bool Recursive,
bool DefinitionRequired, bool AtEndOfTU) {
@@ -4264,6 +4308,11 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// If this is a static data member template, there might be an
// uninstantiated initializer on the declaration. If so, instantiate
// it now.
+ //
+ // FIXME: This largely duplicates what we would do below. The difference
+ // is that along this path we may instantiate an initializer from an
+ // in-class declaration of the template and instantiate the definition
+ // from a separate out-of-class definition.
if (PatternDecl->isStaticDataMember() &&
(PatternDecl = PatternDecl->getFirstDecl())->hasInit() &&
!Var->hasInit()) {
@@ -4324,7 +4373,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
std::make_pair(Var, PointOfInstantiation));
} else if (TSK == TSK_ImplicitInstantiation) {
// Warn about missing definition at the end of translation unit.
- if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) {
+ if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
+ !getSourceManager().isInSystemHeader(PatternDecl->getLocStart())) {
Diag(PointOfInstantiation, diag::warn_var_template_missing)
<< Var;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
@@ -4351,10 +4401,12 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
return;
// C++11 [temp.explicit]p10:
- // Except for inline functions, [...] explicit instantiation declarations
+ // Except for inline functions, const variables of literal types, variables
+ // of reference types, [...] explicit instantiation declarations
// have the effect of suppressing the implicit instantiation of the entity
// to which they refer.
- if (TSK == TSK_ExplicitInstantiationDeclaration)
+ if (TSK == TSK_ExplicitInstantiationDeclaration &&
+ !Var->isUsableInConstantExpressions(getASTContext()))
return;
// Make sure to pass the instantiated variable to the consumer at the end.
@@ -4427,7 +4479,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
// Merge the definition with the declaration.
LookupResult R(*this, Var->getDeclName(), Var->getLocation(),
- LookupOrdinaryName, ForRedeclaration);
+ LookupOrdinaryName, forRedeclarationInCurContext());
R.addDecl(OldVar);
MergeVarDecl(Var, R);
@@ -5179,7 +5231,9 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) {
case TSK_ExplicitInstantiationDefinition:
// We only need an instantiation if the pending instantiation *is* the
// explicit instantiation.
- if (Var != Var->getMostRecentDecl()) continue;
+ if (Var != Var->getMostRecentDecl())
+ continue;
+ break;
case TSK_ImplicitInstantiation:
break;
}