diff options
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiateDecl.cpp')
| -rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 105 | 
1 files changed, 81 insertions, 24 deletions
| diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 40e86175b2cd..5c994f86bd2c 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -202,6 +202,31 @@ static void instantiateDependentEnableIfAttr(    New->addAttr(EIA);  } +// Constructs and adds to New a new instance of CUDALaunchBoundsAttr using +// template A as the base and arguments from TemplateArgs. +static void instantiateDependentCUDALaunchBoundsAttr( +    Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, +    const CUDALaunchBoundsAttr &Attr, Decl *New) { +  // The alignment expression is a constant expression. +  EnterExpressionEvaluationContext Unevaluated(S, Sema::ConstantEvaluated); + +  ExprResult Result = S.SubstExpr(Attr.getMaxThreads(), TemplateArgs); +  if (Result.isInvalid()) +    return; +  Expr *MaxThreads = Result.getAs<Expr>(); + +  Expr *MinBlocks = nullptr; +  if (Attr.getMinBlocks()) { +    Result = S.SubstExpr(Attr.getMinBlocks(), TemplateArgs); +    if (Result.isInvalid()) +      return; +    MinBlocks = Result.getAs<Expr>(); +  } + +  S.AddLaunchBoundsAttr(Attr.getLocation(), New, MaxThreads, MinBlocks, +                        Attr.getSpellingListIndex()); +} +  void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,                              const Decl *Tmpl, Decl *New,                              LateInstantiatedAttrVec *LateAttrs, @@ -233,6 +258,13 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,        continue;      } +    if (const CUDALaunchBoundsAttr *CUDALaunchBounds = +            dyn_cast<CUDALaunchBoundsAttr>(TmplAttr)) { +      instantiateDependentCUDALaunchBoundsAttr(*this, TemplateArgs, +                                               *CUDALaunchBounds, New); +      continue; +    } +      // Existing DLL attribute on the instantiation takes precedence.      if (TmplAttr->getKind() == attr::DLLExport ||          TmplAttr->getKind() == attr::DLLImport) { @@ -289,6 +321,11 @@ TemplateDeclInstantiator::VisitTranslationUnitDecl(TranslationUnitDecl *D) {  }  Decl * +TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) { +  llvm_unreachable("extern \"C\" context cannot be instantiated"); +} + +Decl *  TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) {    LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(),                                        D->getIdentifier()); @@ -1265,11 +1302,19 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {    // DR1484 clarifies that the members of a local class are instantiated as part    // of the instantiation of their enclosing entity.    if (D->isCompleteDefinition() && D->isLocalClass()) { +    Sema::SavePendingLocalImplicitInstantiationsRAII +        SavedPendingLocalImplicitInstantiations(SemaRef); +      SemaRef.InstantiateClass(D->getLocation(), Record, D, TemplateArgs,                               TSK_ImplicitInstantiation,                               /*Complain=*/true); +      SemaRef.InstantiateClassMembers(D->getLocation(), Record, TemplateArgs,                                      TSK_ImplicitInstantiation); + +    // This class may have local implicit instantiations that need to be +    // performed within this scope. +    SemaRef.PerformPendingInstantiations(/*LocalOnly=*/true);    }    SemaRef.DiagnoseUnusedNestedTypedefs(Record); @@ -3313,12 +3358,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,    // it marks vtables used in late parsed templates as used.    SavePendingLocalImplicitInstantiationsRAII        SavedPendingLocalImplicitInstantiations(*this); -  std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII> -      SavePendingInstantiationsAndVTableUses; -  if (Recursive) { -    SavePendingInstantiationsAndVTableUses.reset( -        new SavePendingInstantiationsAndVTableUsesRAII(*this)); -  } +  SavePendingInstantiationsAndVTableUsesRAII +      SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);    // Call the LateTemplateParser callback if there is a need to late parse    // a templated function definition. @@ -3463,8 +3504,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,      // instantiation of this template.      PerformPendingInstantiations(); -    // Restore PendingInstantiations and VTableUses. -    SavePendingInstantiationsAndVTableUses.reset(); +    // PendingInstantiations and VTableUses are restored through +    // SavePendingInstantiationsAndVTableUses's destructor.    }  } @@ -3780,12 +3821,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,        // If we're performing recursive template instantiation, create our own        // queue of pending implicit instantiations that we will instantiate        // later, while we're still within our own instantiation context. -      std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII> -          SavePendingInstantiationsAndVTableUses; -      if (Recursive) { -        SavePendingInstantiationsAndVTableUses.reset( -            new SavePendingInstantiationsAndVTableUsesRAII(*this)); -      } +      SavePendingInstantiationsAndVTableUsesRAII +          SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);        LocalInstantiationScope Local(*this); @@ -3812,8 +3849,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,          // instantiation of this template.          PerformPendingInstantiations(); -        // Restore PendingInstantiations and VTableUses. -        SavePendingInstantiationsAndVTableUses.reset(); +        // PendingInstantiations and VTableUses are restored through +        // SavePendingInstantiationsAndVTableUses's destructor.        }      } @@ -3899,12 +3936,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,    // while we're still within our own instantiation context.    SavePendingLocalImplicitInstantiationsRAII        SavedPendingLocalImplicitInstantiations(*this); -  std::unique_ptr<SavePendingInstantiationsAndVTableUsesRAII> -      SavePendingInstantiationsAndVTableUses; -  if (Recursive) { -    SavePendingInstantiationsAndVTableUses.reset( -        new SavePendingInstantiationsAndVTableUsesRAII(*this)); -  } +  SavePendingInstantiationsAndVTableUsesRAII +      SavePendingInstantiationsAndVTableUses(*this, /*Enabled=*/Recursive);    // Enter the scope of this instantiation. We don't use    // PushDeclContext because we don't have a scope. @@ -3970,8 +4003,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,      // instantiation of this template.      PerformPendingInstantiations(); -    // Restore PendingInstantiations and VTableUses. -    SavePendingInstantiationsAndVTableUses.reset(); +    // PendingInstantiations and VTableUses are restored through +    // SavePendingInstantiationsAndVTableUses's destructor.    }  } @@ -4409,6 +4442,30 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,      if (D->isInvalidDecl())        return nullptr; +    // Normally this function only searches for already instantiated declaration +    // however we have to make an exclusion for local types used before +    // definition as in the code: +    // +    //   template<typename T> void f1() { +    //     void g1(struct x1); +    //     struct x1 {}; +    //   } +    // +    // In this case instantiation of the type of 'g1' requires definition of +    // 'x1', which is defined later. Error recovery may produce an enum used +    // before definition. In these cases we need to instantiate relevant +    // declarations here. +    bool NeedInstantiate = false; +    if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) +      NeedInstantiate = RD->isLocalClass(); +    else +      NeedInstantiate = isa<EnumDecl>(D); +    if (NeedInstantiate) { +      Decl *Inst = SubstDecl(D, CurContext, TemplateArgs); +      CurrentInstantiationScope->InstantiatedLocal(D, Inst); +      return cast<TypeDecl>(Inst); +    } +      // If we didn't find the decl, then we must have a label decl that hasn't      // been found yet.  Lazily instantiate it and return it now.      assert(isa<LabelDecl>(D)); | 
