diff options
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 129 |
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); |