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);  | 
