diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 357 |
1 files changed, 277 insertions, 80 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 64500d0a26d54..2efb7acb97245 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -8,7 +8,7 @@ // This file implements C++ template instantiation for declarations. // //===----------------------------------------------------------------------===/ -#include "clang/Sema/SemaInternal.h" + #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTMutationListener.h" @@ -19,8 +19,11 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateInstCallback.h" #include "llvm/Support/TimeProfiler.h" @@ -393,50 +396,39 @@ static void instantiateOMPDeclareVariantAttr( VariantFuncRef = Subst(E); } + // Copy the template version of the OMPTraitInfo and run substitute on all + // score and condition expressiosn. + OMPTraitInfo &TI = S.getASTContext().getNewOMPTraitInfo(); + TI = *Attr.getTraitInfos(); + + // Try to substitute template parameters in score and condition expressions. + auto SubstScoreOrConditionExpr = [&S, Subst](Expr *&E, bool) { + if (E) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult ER = Subst(E); + if (ER.isUsable()) + E = ER.get(); + else + return true; + } + return false; + }; + if (TI.anyScoreOrCondition(SubstScoreOrConditionExpr)) + return; + // Check function/variant ref. Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = - S.checkOpenMPDeclareVariantFunction( - S.ConvertDeclToDeclGroup(New), VariantFuncRef.get(), Attr.getRange()); + S.checkOpenMPDeclareVariantFunction(S.ConvertDeclToDeclGroup(New), + VariantFuncRef.get(), TI, + Attr.getRange()); + if (!DeclVarData) return; - SmallVector<Sema::OMPCtxSelectorData, 4> Data; - for (unsigned I = 0, E = Attr.scores_size(); I < E; ++I) { - ExprResult Score; - if (Expr *E = *std::next(Attr.scores_begin(), I)) - Score = Subst(E); - // Instantiate the attribute. - auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( - *std::next(Attr.ctxSelectorSets_begin(), I)); - auto Ctx = static_cast<OpenMPContextSelectorKind>( - *std::next(Attr.ctxSelectors_begin(), I)); - switch (CtxSet) { - case OMP_CTX_SET_implementation: - switch (Ctx) { - case OMP_CTX_vendor: - Data.emplace_back(CtxSet, Ctx, Score, Attr.implVendors()); - break; - case OMP_CTX_kind: - case OMP_CTX_unknown: - llvm_unreachable("Unexpected context selector kind."); - } - break; - case OMP_CTX_SET_device: - switch (Ctx) { - case OMP_CTX_kind: - Data.emplace_back(CtxSet, Ctx, Score, Attr.deviceKinds()); - break; - case OMP_CTX_vendor: - case OMP_CTX_unknown: - llvm_unreachable("Unexpected context selector kind."); - } - break; - case OMP_CTX_SET_unknown: - llvm_unreachable("Unexpected context selector set kind."); - } - } + S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first, - DeclVarData.getValue().second, - Attr.getRange(), Data); + DeclVarData.getValue().second, TI, + Attr.getRange()); } static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( @@ -706,6 +698,10 @@ TemplateDeclInstantiator::VisitExternCContextDecl(ExternCContextDecl *D) { llvm_unreachable("extern \"C\" context cannot be instantiated"); } +Decl *TemplateDeclInstantiator::VisitMSGuidDecl(MSGuidDecl *D) { + llvm_unreachable("GUID declaration cannot be instantiated"); +} + Decl * TemplateDeclInstantiator::VisitLabelDecl(LabelDecl *D) { LabelDecl *Inst = LabelDecl::Create(SemaRef.Context, Owner, D->getLocation(), @@ -1837,6 +1833,23 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( return nullptr; QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); + if (TemplateParams && TemplateParams->size()) { + auto *LastParam = + dyn_cast<TemplateTypeParmDecl>(TemplateParams->asArray().back()); + if (LastParam && LastParam->isImplicit() && + LastParam->hasTypeConstraint()) { + // In abbreviated templates, the type-constraints of invented template + // type parameters are instantiated with the function type, invalidating + // the TemplateParameterList which relied on the template type parameter + // not having a type constraint. Recreate the TemplateParameterList with + // the updated parameter list. + TemplateParams = TemplateParameterList::Create( + SemaRef.Context, TemplateParams->getTemplateLoc(), + TemplateParams->getLAngleLoc(), TemplateParams->asArray(), + TemplateParams->getRAngleLoc(), TemplateParams->getRequiresClause()); + } + } + NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, @@ -1848,6 +1861,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( // FIXME: Concepts: Do not substitute into constraint expressions Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); if (TrailingRequiresClause) { + EnterExpressionEvaluationContext ConstantEvaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, TemplateArgs); if (SubstRC.isInvalid()) @@ -1896,6 +1911,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( D->hasWrittenPrototype(), D->getConstexprKind(), TrailingRequiresClause); Function->setRangeEnd(D->getSourceRange().getEnd()); + Function->setUsesFPIntrin(D->usesFPIntrin()); } if (D->isInlined()) @@ -2029,7 +2045,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl( // Look only into the namespace where the friend would be declared to // find a previous declaration. This is the innermost enclosing namespace, // as described in ActOnFriendFunctionDecl. - SemaRef.LookupQualifiedName(Previous, DC); + SemaRef.LookupQualifiedName(Previous, DC->getRedeclContext()); // In C++, the previous declaration we find might be a tag type // (class or enum). In this case, the new declaration will hide the @@ -2175,6 +2191,23 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( return nullptr; QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo); + if (TemplateParams && TemplateParams->size()) { + auto *LastParam = + dyn_cast<TemplateTypeParmDecl>(TemplateParams->asArray().back()); + if (LastParam && LastParam->isImplicit() && + LastParam->hasTypeConstraint()) { + // In abbreviated templates, the type-constraints of invented template + // type parameters are instantiated with the function type, invalidating + // the TemplateParameterList which relied on the template type parameter + // not having a type constraint. Recreate the TemplateParameterList with + // the updated parameter list. + TemplateParams = TemplateParameterList::Create( + SemaRef.Context, TemplateParams->getTemplateLoc(), + TemplateParams->getLAngleLoc(), TemplateParams->asArray(), + TemplateParams->getRAngleLoc(), TemplateParams->getRequiresClause()); + } + } + NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc(); if (QualifierLoc) { QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc, @@ -2186,6 +2219,11 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( // FIXME: Concepts: Do not substitute into constraint expressions Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); if (TrailingRequiresClause) { + EnterExpressionEvaluationContext ConstantEvaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); + auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); + Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, + D->getMethodQualifiers(), ThisContext); ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, TemplateArgs); if (SubstRC.isInvalid()) @@ -2518,28 +2556,34 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( Inst->setAccess(AS_public); Inst->setImplicit(D->isImplicit()); if (auto *TC = D->getTypeConstraint()) { - // TODO: Concepts: do not instantiate the constraint (delayed constraint - // substitution) - const ASTTemplateArgumentListInfo *TemplArgInfo - = TC->getTemplateArgsAsWritten(); - TemplateArgumentListInfo InstArgs; - - if (TemplArgInfo) { - InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); - InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); - if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), - TemplArgInfo->NumTemplateArgs, - InstArgs, TemplateArgs)) + if (!D->isImplicit()) { + // Invented template parameter type constraints will be instantiated with + // the corresponding auto-typed parameter as it might reference other + // parameters. + + // TODO: Concepts: do not instantiate the constraint (delayed constraint + // substitution) + const ASTTemplateArgumentListInfo *TemplArgInfo + = TC->getTemplateArgsAsWritten(); + TemplateArgumentListInfo InstArgs; + + if (TemplArgInfo) { + InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); + InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); + if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), + TemplArgInfo->NumTemplateArgs, + InstArgs, TemplateArgs)) + return nullptr; + } + if (SemaRef.AttachTypeConstraint( + TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), + TC->getNamedConcept(), &InstArgs, Inst, + D->isParameterPack() + ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) + ->getEllipsisLoc() + : SourceLocation())) return nullptr; } - if (SemaRef.AttachTypeConstraint( - TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), - TC->getNamedConcept(), &InstArgs, Inst, - D->isParameterPack() - ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) - ->getEllipsisLoc() - : SourceLocation())) - return nullptr; } if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { TypeSourceInfo *InstantiatedDefaultArg = @@ -2685,6 +2729,16 @@ Decl *TemplateDeclInstantiator::VisitNonTypeTemplateParmDecl( D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getPosition(), D->getIdentifier(), T, D->isParameterPack(), DI); + if (AutoTypeLoc AutoLoc = DI->getTypeLoc().getContainedAutoTypeLoc()) + if (AutoLoc.isConstrained()) + if (SemaRef.AttachTypeConstraint( + AutoLoc, Param, + IsExpandedParameterPack + ? DI->getTypeLoc().getAs<PackExpansionTypeLoc>() + .getEllipsisLoc() + : SourceLocation())) + Invalid = true; + Param->setAccess(AS_public); Param->setImplicit(D->isImplicit()); if (Invalid) @@ -3571,6 +3625,9 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( if (InsertPos) VarTemplate->AddSpecialization(Var, InsertPos); + if (SemaRef.getLangOpts().OpenCL) + SemaRef.deduceOpenCLAddressSpace(Var); + // Substitute the nested name specifier, if any. if (SubstQualifier(D, Var)) return nullptr; @@ -3600,6 +3657,12 @@ Decl *TemplateDeclInstantiator::VisitConceptDecl(ConceptDecl *D) { llvm_unreachable("Concept definitions cannot reside inside a template"); } +Decl * +TemplateDeclInstantiator::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { + return RequiresExprBodyDecl::Create(SemaRef.Context, D->getDeclContext(), + D->getBeginLoc()); +} + Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) { llvm_unreachable("Unexpected decl"); } @@ -3659,6 +3722,8 @@ FunctionDecl *Sema::SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD, // access and function-definition and in the same class scope as the // three-way comparison operator function MultiLevelTemplateArgumentList NoTemplateArgs; + NoTemplateArgs.setKind(TemplateSubstitutionKind::Rewrite); + NoTemplateArgs.addOuterRetainedLevels(RD->getTemplateDepth()); TemplateDeclInstantiator Instantiator(*this, RD, NoTemplateArgs); Decl *R; if (auto *MD = dyn_cast<CXXMethodDecl>(Spaceship)) { @@ -3713,6 +3778,8 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) { // checking satisfaction. Expr *InstRequiresClause = nullptr; if (Expr *E = L->getRequiresClause()) { + EnterExpressionEvaluationContext ConstantEvaluated( + SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); ExprResult Res = SemaRef.SubstExpr(E, TemplateArgs); if (Res.isInvalid() || !Res.isUsable()) { return nullptr; @@ -4163,6 +4230,94 @@ static bool addInstantiatedParametersToScope(Sema &S, FunctionDecl *Function, return false; } +bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, + ParmVarDecl *Param) { + assert(Param->hasUninstantiatedDefaultArg()); + Expr *UninstExpr = Param->getUninstantiatedDefaultArg(); + + EnterExpressionEvaluationContext EvalContext( + *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); + + // Instantiate the expression. + // + // FIXME: Pass in a correct Pattern argument, otherwise + // getTemplateInstantiationArgs uses the lexical context of FD, e.g. + // + // template<typename T> + // struct A { + // static int FooImpl(); + // + // template<typename Tp> + // // bug: default argument A<T>::FooImpl() is evaluated with 2-level + // // template argument list [[T], [Tp]], should be [[Tp]]. + // friend A<Tp> Foo(int a); + // }; + // + // template<typename T> + // A<T> Foo(int a = A<T>::FooImpl()); + MultiLevelTemplateArgumentList TemplateArgs + = getTemplateInstantiationArgs(FD, nullptr, /*RelativeToPrimary=*/true); + + InstantiatingTemplate Inst(*this, CallLoc, Param, + TemplateArgs.getInnermost()); + if (Inst.isInvalid()) + return true; + if (Inst.isAlreadyInstantiating()) { + Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD; + Param->setInvalidDecl(); + return true; + } + + ExprResult Result; + { + // C++ [dcl.fct.default]p5: + // The names in the [default argument] expression are bound, and + // the semantic constraints are checked, at the point where the + // default argument expression appears. + ContextRAII SavedContext(*this, FD); + LocalInstantiationScope Local(*this); + + FunctionDecl *Pattern = FD->getTemplateInstantiationPattern( + /*ForDefinition*/ false); + if (addInstantiatedParametersToScope(*this, FD, Pattern, Local, + TemplateArgs)) + return true; + + runWithSufficientStackSpace(CallLoc, [&] { + Result = SubstInitializer(UninstExpr, TemplateArgs, + /*DirectInit*/false); + }); + } + if (Result.isInvalid()) + return true; + + // Check the expression as an initializer for the parameter. + InitializedEntity Entity + = InitializedEntity::InitializeParameter(Context, Param); + InitializationKind Kind = InitializationKind::CreateCopy( + Param->getLocation(), + /*FIXME:EqualLoc*/ UninstExpr->getBeginLoc()); + Expr *ResultE = Result.getAs<Expr>(); + + InitializationSequence InitSeq(*this, Entity, Kind, ResultE); + Result = InitSeq.Perform(*this, Entity, Kind, ResultE); + if (Result.isInvalid()) + return true; + + Result = + ActOnFinishFullExpr(Result.getAs<Expr>(), Param->getOuterLocStart(), + /*DiscardedValue*/ false); + if (Result.isInvalid()) + return true; + + // Remember the instantiated default argument. + Param->setDefaultArg(Result.getAs<Expr>()); + if (ASTMutationListener *L = getASTMutationListener()) + L->DefaultArgumentInstantiated(Param); + + return false; +} + void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionDecl *Decl) { const FunctionProtoType *Proto = Decl->getType()->castAs<FunctionProtoType>(); @@ -4193,6 +4348,10 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true); + // FIXME: We can't use getTemplateInstantiationPattern(false) in general + // here, because for a non-defining friend declaration in a class template, + // we don't store enough information to map back to the friend declaration in + // the template. FunctionDecl *Template = Proto->getExceptionSpecTemplate(); if (addInstantiatedParametersToScope(*this, Decl, Template, Scope, TemplateArgs)) { @@ -4224,24 +4383,29 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints( Sema::ContextRAII savedContext(*this, Decl); LocalInstantiationScope Scope(*this); - MultiLevelTemplateArgumentList MLTAL = - getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true); - // If this is not an explicit specialization - we need to get the instantiated // version of the template arguments and add them to scope for the // substitution. if (Decl->isTemplateInstantiation()) { InstantiatingTemplate Inst(*this, Decl->getPointOfInstantiation(), InstantiatingTemplate::ConstraintsCheck{}, Decl->getPrimaryTemplate(), - MLTAL.getInnermost(), SourceRange()); + TemplateArgs, SourceRange()); if (Inst.isInvalid()) return true; - if (addInstantiatedParametersToScope(*this, Decl, - Decl->getTemplateInstantiationPattern(), - Scope, MLTAL)) + MultiLevelTemplateArgumentList MLTAL( + *Decl->getTemplateSpecializationArgs()); + if (addInstantiatedParametersToScope( + *this, Decl, Decl->getPrimaryTemplate()->getTemplatedDecl(), + Scope, MLTAL)) return true; } - + Qualifiers ThisQuals; + CXXRecordDecl *Record = nullptr; + if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { + ThisQuals = Method->getMethodQualifiers(); + Record = Method->getParent(); + } + CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs, PointOfInstantiation, Satisfaction); } @@ -4297,7 +4461,7 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, EPI.ExceptionSpec.Type != EST_None && EPI.ExceptionSpec.Type != EST_DynamicNone && EPI.ExceptionSpec.Type != EST_BasicNoexcept && - !Tmpl->isLexicallyWithinFunctionOrMethod()) { + !Tmpl->isInLocalScopeForInstantiation()) { FunctionDecl *ExceptionSpecTemplate = Tmpl; if (EPI.ExceptionSpec.Type == EST_Uninstantiated) ExceptionSpecTemplate = EPI.ExceptionSpec.SourceTemplate; @@ -4734,6 +4898,9 @@ VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( // Instantiate the initializer. InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs); + if (getLangOpts().OpenCL) + deduceOpenCLAddressSpace(VarSpec); + return VarSpec; } @@ -4774,6 +4941,7 @@ void Sema::BuildVariableInstantiation( NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl()); NewVar->setObjCForDecl(OldVar->isObjCForDecl()); NewVar->setConstexpr(OldVar->isConstexpr()); + MaybeAddCUDAConstantAttr(NewVar); NewVar->setInitCapture(OldVar->isInitCapture()); NewVar->setPreviousDeclInSameBlockScope( OldVar->isPreviousDeclInSameBlockScope()); @@ -5537,6 +5705,20 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, } else return DC; } +/// Determine whether the given context is dependent on template parameters at +/// level \p Level or below. +/// +/// Sometimes we only substitute an inner set of template arguments and leave +/// the outer templates alone. In such cases, contexts dependent only on the +/// outer levels are not effectively dependent. +static bool isDependentContextAtLevel(DeclContext *DC, unsigned Level) { + if (!DC->isDependentContext()) + return false; + if (!Level) + return true; + return cast<Decl>(DC)->getTemplateDepth() > Level; +} + /// Find the instantiation of the given declaration within the /// current instantiation. /// @@ -5567,6 +5749,10 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, bool FindingInstantiatedContext) { DeclContext *ParentDC = D->getDeclContext(); + // Determine whether our parent context depends on any of the tempalte + // arguments we're currently substituting. + bool ParentDependsOnArgs = isDependentContextAtLevel( + ParentDC, TemplateArgs.getNumRetainedOuterLevels()); // FIXME: Parmeters of pointer to functions (y below) that are themselves // parameters (p below) can have their ParentDC set to the translation-unit // - thus we can not consistently check if the ParentDC of such a parameter @@ -5583,15 +5769,14 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // - as long as we have a ParmVarDecl whose parent is non-dependent and // whose type is not instantiation dependent, do nothing to the decl // - otherwise find its instantiated decl. - if (isa<ParmVarDecl>(D) && !ParentDC->isDependentContext() && + if (isa<ParmVarDecl>(D) && !ParentDependsOnArgs && !cast<ParmVarDecl>(D)->getType()->isInstantiationDependentType()) return D; if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || - ((ParentDC->isFunctionOrMethod() || - isa<OMPDeclareReductionDecl>(ParentDC) || - isa<OMPDeclareMapperDecl>(ParentDC)) && - ParentDC->isDependentContext()) || + (ParentDependsOnArgs && (ParentDC->isFunctionOrMethod() || + isa<OMPDeclareReductionDecl>(ParentDC) || + isa<OMPDeclareMapperDecl>(ParentDC))) || (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) { // D is a local of some kind. Look into the map of local // declarations to their instantiations. @@ -5634,6 +5819,9 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, bool NeedInstantiate = false; if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) NeedInstantiate = RD->isLocalClass(); + else if (isa<TypedefNameDecl>(D) && + isa<CXXDeductionGuideDecl>(D->getDeclContext())) + NeedInstantiate = true; else NeedInstantiate = isa<EnumDecl>(D); if (NeedInstantiate) { @@ -5742,7 +5930,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, // anonymous unions in class templates). } - if (!ParentDC->isDependentContext()) + if (!ParentDependsOnArgs) return D; ParentDC = FindInstantiatedContext(Loc, ParentDC, TemplateArgs); @@ -5811,10 +5999,11 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, if (!Result) { if (isa<UsingShadowDecl>(D)) { // UsingShadowDecls can instantiate to nothing because of using hiding. - } else if (Diags.hasErrorOccurred()) { - // We've already complained about something, so most likely this - // declaration failed to instantiate. There's no point in complaining - // further, since this is normal in invalid code. + } else if (Diags.hasUncompilableErrorOccurred()) { + // We've already complained about some ill-formed code, so most likely + // this declaration failed to instantiate. There's no point in + // complaining further, since this is normal in invalid code. + // FIXME: Use more fine-grained 'invalid' tracking for this. } else if (IsBeingInstantiated) { // The class in which this member exists is currently being // instantiated, and we haven't gotten around to instantiating this @@ -5854,6 +6043,7 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, /// Performs template instantiation for all implicit template /// instantiations we have seen until this point. void Sema::PerformPendingInstantiations(bool LocalOnly) { + std::deque<PendingImplicitInstantiation> delayedPCHInstantiations; while (!PendingLocalImplicitInstantiations.empty() || (!LocalOnly && !PendingInstantiations.empty())) { PendingImplicitInstantiation Inst; @@ -5884,6 +6074,10 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { if (Function->isDefined()) Function->setInstantiationIsPending(false); } + // Definition of a PCH-ed template declaration may be available only in the TU. + if (!LocalOnly && LangOpts.PCHInstantiateTemplates && + TUKind == TU_Prefix && Function->instantiationIsPending()) + delayedPCHInstantiations.push_back(Inst); continue; } @@ -5929,6 +6123,9 @@ void Sema::PerformPendingInstantiations(bool LocalOnly) { InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true, DefinitionRequired, true); } + + if (!LocalOnly && LangOpts.PCHInstantiateTemplates) + PendingInstantiations.swap(delayedPCHInstantiations); } void Sema::PerformDependentDiagnostics(const DeclContext *Pattern, |