summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp129
1 files changed, 83 insertions, 46 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 96abeed82493..973f564d3058 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1,9 +1,8 @@
//===------- SemaTemplateInstantiate.cpp - C++ Template Instantiation ------===/
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//===----------------------------------------------------------------------===/
//
// This file implements C++ template instantiation.
@@ -26,6 +25,7 @@
#include "clang/Sema/Template.h"
#include "clang/Sema/TemplateDeduction.h"
#include "clang/Sema/TemplateInstCallback.h"
+#include "llvm/Support/TimeProfiler.h"
using namespace clang;
using namespace sema;
@@ -66,9 +66,12 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
if (!Ctx) {
Ctx = D->getDeclContext();
- // Add template arguments from a variable template instantiation.
- if (VarTemplateSpecializationDecl *Spec =
- dyn_cast<VarTemplateSpecializationDecl>(D)) {
+ // Add template arguments from a variable template instantiation. For a
+ // class-scope explicit specialization, there are no template arguments
+ // at this level, but there may be enclosing template arguments.
+ VarTemplateSpecializationDecl *Spec =
+ dyn_cast<VarTemplateSpecializationDecl>(D);
+ if (Spec && !Spec->isClassScopeExplicitSpecialization()) {
// We're done when we hit an explicit specialization.
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
!isa<VarTemplatePartialSpecializationDecl>(Spec))
@@ -111,8 +114,9 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
while (!Ctx->isFileContext()) {
// Add template arguments from a class template instantiation.
- if (ClassTemplateSpecializationDecl *Spec
- = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
+ ClassTemplateSpecializationDecl *Spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
+ if (Spec && !Spec->isClassScopeExplicitSpecialization()) {
// We're done when we hit an explicit specialization.
if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization &&
!isa<ClassTemplatePartialSpecializationDecl>(Spec))
@@ -129,9 +133,8 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
// Add template arguments from a function template specialization.
else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
if (!RelativeToPrimary &&
- (Function->getTemplateSpecializationKind() ==
- TSK_ExplicitSpecialization &&
- !Function->getClassScopeSpecializationPattern()))
+ Function->getTemplateSpecializationKindForInstantiation() ==
+ TSK_ExplicitSpecialization)
break;
if (const TemplateArgumentList *TemplateArgs
@@ -816,7 +819,19 @@ namespace {
SemaRef.InstantiateAttrs(TemplateArgs, Old, New);
}
- void transformedLocalDecl(Decl *Old, Decl *New) {
+ void transformedLocalDecl(Decl *Old, ArrayRef<Decl *> NewDecls) {
+ if (Old->isParameterPack()) {
+ SemaRef.CurrentInstantiationScope->MakeInstantiatedLocalArgPack(Old);
+ for (auto *New : NewDecls)
+ SemaRef.CurrentInstantiationScope->InstantiatedLocalPackArg(
+ Old, cast<VarDecl>(New));
+ return;
+ }
+
+ assert(NewDecls.size() == 1 &&
+ "should only have multiple expansions for a pack");
+ Decl *New = NewDecls.front();
+
// If we've instantiated the call operator of a lambda or the call
// operator template of a generic lambda, update the "instantiation of"
// information.
@@ -885,12 +900,11 @@ namespace {
ExprResult TransformSubstNonTypeTemplateParmPackExpr(
SubstNonTypeTemplateParmPackExpr *E);
- /// Rebuild a DeclRefExpr for a ParmVarDecl reference.
- ExprResult RebuildParmVarDeclRefExpr(ParmVarDecl *PD, SourceLocation Loc);
+ /// Rebuild a DeclRefExpr for a VarDecl reference.
+ ExprResult RebuildVarDeclRefExpr(VarDecl *PD, SourceLocation Loc);
- /// Transform a reference to a function parameter pack.
- ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E,
- ParmVarDecl *PD);
+ /// Transform a reference to a function or init-capture parameter pack.
+ ExprResult TransformFunctionParmPackRefExpr(DeclRefExpr *E, VarDecl *PD);
/// Transform a FunctionParmPackExpr which was built when we couldn't
/// expand a function parameter pack reference which refers to an expanded
@@ -1321,9 +1335,8 @@ TemplateInstantiator::TransformSubstNonTypeTemplateParmPackExpr(
Arg);
}
-ExprResult
-TemplateInstantiator::RebuildParmVarDeclRefExpr(ParmVarDecl *PD,
- SourceLocation Loc) {
+ExprResult TemplateInstantiator::RebuildVarDeclRefExpr(VarDecl *PD,
+ SourceLocation Loc) {
DeclarationNameInfo NameInfo(PD->getDeclName(), Loc);
return getSema().BuildDeclarationNameExpr(CXXScopeSpec(), NameInfo, PD);
}
@@ -1332,11 +1345,11 @@ ExprResult
TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
if (getSema().ArgumentPackSubstitutionIndex != -1) {
// We can expand this parameter pack now.
- ParmVarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex);
- ValueDecl *VD = cast_or_null<ValueDecl>(TransformDecl(E->getExprLoc(), D));
+ VarDecl *D = E->getExpansion(getSema().ArgumentPackSubstitutionIndex);
+ VarDecl *VD = cast_or_null<VarDecl>(TransformDecl(E->getExprLoc(), D));
if (!VD)
return ExprError();
- return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(VD), E->getExprLoc());
+ return RebuildVarDeclRefExpr(VD, E->getExprLoc());
}
QualType T = TransformType(E->getType());
@@ -1345,25 +1358,26 @@ TemplateInstantiator::TransformFunctionParmPackExpr(FunctionParmPackExpr *E) {
// Transform each of the parameter expansions into the corresponding
// parameters in the instantiation of the function decl.
- SmallVector<ParmVarDecl *, 8> Parms;
- Parms.reserve(E->getNumExpansions());
+ SmallVector<VarDecl *, 8> Vars;
+ Vars.reserve(E->getNumExpansions());
for (FunctionParmPackExpr::iterator I = E->begin(), End = E->end();
I != End; ++I) {
- ParmVarDecl *D =
- cast_or_null<ParmVarDecl>(TransformDecl(E->getExprLoc(), *I));
+ VarDecl *D = cast_or_null<VarDecl>(TransformDecl(E->getExprLoc(), *I));
if (!D)
return ExprError();
- Parms.push_back(D);
+ Vars.push_back(D);
}
- return FunctionParmPackExpr::Create(getSema().Context, T,
- E->getParameterPack(),
- E->getParameterPackLocation(), Parms);
+ auto *PackExpr =
+ FunctionParmPackExpr::Create(getSema().Context, T, E->getParameterPack(),
+ E->getParameterPackLocation(), Vars);
+ getSema().MarkFunctionParmPackReferenced(PackExpr);
+ return PackExpr;
}
ExprResult
TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
- ParmVarDecl *PD) {
+ VarDecl *PD) {
typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
llvm::PointerUnion<Decl *, DeclArgumentPack *> *Found
= getSema().CurrentInstantiationScope->findInstantiationOf(PD);
@@ -1377,8 +1391,10 @@ TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
QualType T = TransformType(E->getType());
if (T.isNull())
return ExprError();
- return FunctionParmPackExpr::Create(getSema().Context, T, PD,
- E->getExprLoc(), *Pack);
+ auto *PackExpr = FunctionParmPackExpr::Create(getSema().Context, T, PD,
+ E->getExprLoc(), *Pack);
+ getSema().MarkFunctionParmPackReferenced(PackExpr);
+ return PackExpr;
}
TransformedDecl = (*Pack)[getSema().ArgumentPackSubstitutionIndex];
@@ -1387,8 +1403,7 @@ TemplateInstantiator::TransformFunctionParmPackRefExpr(DeclRefExpr *E,
}
// We have either an unexpanded pack or a specific expansion.
- return RebuildParmVarDeclRefExpr(cast<ParmVarDecl>(TransformedDecl),
- E->getExprLoc());
+ return RebuildVarDeclRefExpr(cast<VarDecl>(TransformedDecl), E->getExprLoc());
}
ExprResult
@@ -1406,7 +1421,7 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {
}
// Handle references to function parameter packs.
- if (ParmVarDecl *PD = dyn_cast<ParmVarDecl>(D))
+ if (VarDecl *PD = dyn_cast<VarDecl>(D))
if (PD->isParameterPack())
return TransformFunctionParmPackRefExpr(E, PD);
@@ -2009,6 +2024,15 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Instantiation->getInstantiatedFromMemberClass(),
Pattern, PatternDef, TSK, Complain))
return true;
+
+ llvm::TimeTraceScope TimeScope("InstantiateClass", [&]() {
+ std::string Name;
+ llvm::raw_string_ostream OS(Name);
+ Instantiation->getNameForDiagnostic(OS, getPrintingPolicy(),
+ /*Qualified=*/true);
+ return Name;
+ });
+
Pattern = PatternDef;
// Record the point of instantiation.
@@ -2070,6 +2094,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
LateInstantiatedAttrVec LateAttrs;
Instantiator.enableLateAttributeInstantiation(&LateAttrs);
+ bool MightHaveConstexprVirtualFunctions = false;
for (auto *Member : Pattern->decls()) {
// Don't instantiate members not belonging in this semantic context.
// e.g. for:
@@ -2116,6 +2141,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Instantiation->setInvalidDecl();
break;
}
+ } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewMember)) {
+ if (MD->isConstexpr() && !MD->getFriendObjectKind() &&
+ (MD->isVirtualAsWritten() || Instantiation->getNumBases()))
+ MightHaveConstexprVirtualFunctions = true;
}
if (NewMember->isInvalidDecl())
@@ -2208,9 +2237,14 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Consumer.HandleTagDeclDefinition(Instantiation);
// Always emit the vtable for an explicit instantiation definition
- // of a polymorphic class template specialization.
+ // of a polymorphic class template specialization. Otherwise, eagerly
+ // instantiate only constexpr virtual functions in preparation for their use
+ // in constant evaluation.
if (TSK == TSK_ExplicitInstantiationDefinition)
MarkVTableUsed(PointOfInstantiation, Instantiation, true);
+ else if (MightHaveConstexprVirtualFunctions)
+ MarkVirtualMembersReferenced(PointOfInstantiation, Instantiation,
+ /*ConstexprOnly*/ true);
}
return Instantiation->isInvalidDecl();
@@ -2675,11 +2709,14 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
== TSK_ExplicitSpecialization)
continue;
- if ((Context.getTargetInfo().getCXXABI().isMicrosoft() ||
- Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) &&
+ if (Context.getTargetInfo().getTriple().isOSWindows() &&
TSK == TSK_ExplicitInstantiationDeclaration) {
- // In MSVC and Windows Itanium mode, explicit instantiation decl of the
- // outer class doesn't affect the inner class.
+ // On Windows, explicit instantiation decl of the outer class doesn't
+ // affect the inner class. Typically extern template declarations are
+ // used in combination with dll import/export annotations, but those
+ // are not propagated from the outer class templates to inner classes.
+ // Therefore, do not instantiate inner classes on this platform, so
+ // that users don't end up with undefined symbols during linking.
continue;
}
@@ -2887,7 +2924,7 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) {
unsigned i = PV->getFunctionScopeIndex();
// This parameter might be from a freestanding function type within the
// function and isn't necessarily referring to one of FD's parameters.
- if (FD->getParamDecl(i) == PV)
+ if (i < FD->getNumParams() && FD->getParamDecl(i) == PV)
return FD->getCanonicalDecl()->getParamDecl(i);
}
}
@@ -2959,14 +2996,14 @@ void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
#endif
Stored = Inst;
} else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) {
- Pack->push_back(cast<ParmVarDecl>(Inst));
+ Pack->push_back(cast<VarDecl>(Inst));
} else {
assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
}
}
void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
- ParmVarDecl *Inst) {
+ VarDecl *Inst) {
D = getCanonicalParmVarDecl(D);
DeclArgumentPack *Pack = LocalDecls[D].get<DeclArgumentPack *>();
Pack->push_back(Inst);