Author: rsmith Date: Mon Dec 4 17:31:47 2017 New Revision: 319727 URL: http://llvm.org/viewvc/llvm-project?rev=319727&view=rev Log: Generalize "static data member instantiated" notification to cover variable templates too.
While here, split the "point of instantiation changed" notification out from it; these two really are orthogonal changes. Added: cfe/trunk/test/Modules/var-templates.cpp Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/include/clang/Serialization/ASTWriter.h cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/Frontend/MultiplexConsumer.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/lib/Serialization/ASTCommon.h cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp Modified: cfe/trunk/include/clang/AST/ASTMutationListener.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTMutationListener.h (original) +++ cfe/trunk/include/clang/AST/ASTMutationListener.h Mon Dec 4 17:31:47 2017 @@ -36,6 +36,7 @@ namespace clang { class QualType; class RecordDecl; class TagDecl; + class ValueDecl; class VarDecl; class VarTemplateDecl; class VarTemplateSpecializationDecl; @@ -87,8 +88,13 @@ public: /// \brief An implicit member got a definition. virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} - /// \brief A static data member was implicitly instantiated. - virtual void StaticDataMemberInstantiated(const VarDecl *D) {} + /// \brief The instantiation of a templated function or variable was + /// requested. In particular, the point of instantiation and template + /// specialization kind of \p D may have changed. + virtual void InstantiationRequested(const ValueDecl *D) {} + + /// \brief A templated variable's definition was implicitly instantiated. + virtual void VariableDefinitionInstantiated(const VarDecl *D) {} /// \brief A function template's definition was instantiated. virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {} Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Mon Dec 4 17:31:47 2017 @@ -7790,11 +7790,6 @@ public: VarDecl *Var, bool Recursive = false, bool DefinitionRequired = false, bool AtEndOfTU = false); - void InstantiateStaticDataMemberDefinition( - SourceLocation PointOfInstantiation, - VarDecl *Var, - bool Recursive = false, - bool DefinitionRequired = false); void InstantiateMemInitializers(CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTWriter.h (original) +++ cfe/trunk/include/clang/Serialization/ASTWriter.h Mon Dec 4 17:31:47 2017 @@ -727,10 +727,11 @@ private: const FunctionDecl *Delete, Expr *ThisArg) override; void CompletedImplicitDefinition(const FunctionDecl *D) override; - void StaticDataMemberInstantiated(const VarDecl *D) override; + void InstantiationRequested(const ValueDecl *D) override; + void VariableDefinitionInstantiated(const VarDecl *D) override; + void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void DefaultArgumentInstantiated(const ParmVarDecl *D) override; void DefaultMemberInitializerInstantiated(const FieldDecl *D) override; - void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) override; void DeclarationMarkedUsed(const Decl *D) override; Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Mon Dec 4 17:31:47 2017 @@ -2418,15 +2418,21 @@ void VarDecl::setTemplateSpecializationK dyn_cast<VarTemplateSpecializationDecl>(this)) { Spec->setSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && - Spec->getPointOfInstantiation().isInvalid()) + Spec->getPointOfInstantiation().isInvalid()) { Spec->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } } if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) { MSI->setTemplateSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && - MSI->getPointOfInstantiation().isInvalid()) + MSI->getPointOfInstantiation().isInvalid()) { MSI->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } } } @@ -3442,15 +3448,21 @@ FunctionDecl::setTemplateSpecializationK FTSInfo->setTemplateSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && - FTSInfo->getPointOfInstantiation().isInvalid()) + FTSInfo->getPointOfInstantiation().isInvalid()) { FTSInfo->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } } else if (MemberSpecializationInfo *MSInfo = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) { MSInfo->setTemplateSpecializationKind(TSK); if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() && - MSInfo->getPointOfInstantiation().isInvalid()) + MSInfo->getPointOfInstantiation().isInvalid()) { MSInfo->setPointOfInstantiation(PointOfInstantiation); + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->InstantiationRequested(this); + } } else llvm_unreachable("Function cannot have a template specialization kind"); } Modified: cfe/trunk/lib/Frontend/MultiplexConsumer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/MultiplexConsumer.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Frontend/MultiplexConsumer.cpp (original) +++ cfe/trunk/lib/Frontend/MultiplexConsumer.cpp Mon Dec 4 17:31:47 2017 @@ -119,12 +119,13 @@ public: const FunctionDecl *Delete, Expr *ThisArg) override; void CompletedImplicitDefinition(const FunctionDecl *D) override; - void StaticDataMemberInstantiated(const VarDecl *D) override; + void InstantiationRequested(const ValueDecl *D) override; + void VariableDefinitionInstantiated(const VarDecl *D) override; + void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void DefaultArgumentInstantiated(const ParmVarDecl *D) override; void DefaultMemberInitializerInstantiated(const FieldDecl *D) override; void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) override; - void FunctionDefinitionInstantiated(const FunctionDecl *D) override; void DeclarationMarkedUsed(const Decl *D) override; void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, @@ -193,10 +194,19 @@ void MultiplexASTMutationListener::Compl for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->CompletedImplicitDefinition(D); } -void MultiplexASTMutationListener::StaticDataMemberInstantiated( - const VarDecl *D) { +void MultiplexASTMutationListener::InstantiationRequested(const ValueDecl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->InstantiationRequested(D); +} +void MultiplexASTMutationListener::VariableDefinitionInstantiated( + const VarDecl *D) { for (size_t i = 0, e = Listeners.size(); i != e; ++i) - Listeners[i]->StaticDataMemberInstantiated(D); + Listeners[i]->VariableDefinitionInstantiated(D); +} +void MultiplexASTMutationListener::FunctionDefinitionInstantiated( + const FunctionDecl *D) { + for (auto &Listener : Listeners) + Listener->FunctionDefinitionInstantiated(D); } void MultiplexASTMutationListener::DefaultArgumentInstantiated( const ParmVarDecl *D) { @@ -214,11 +224,6 @@ void MultiplexASTMutationListener::Added for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->AddedObjCCategoryToInterface(CatD, IFD); } -void MultiplexASTMutationListener::FunctionDefinitionInstantiated( - const FunctionDecl *D) { - for (auto &Listener : Listeners) - Listener->FunctionDefinitionInstantiated(D); -} void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) { for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->DeclarationMarkedUsed(D); Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Dec 4 17:31:47 2017 @@ -13960,29 +13960,21 @@ void Sema::MarkFunctionReferenced(Source // Implicit instantiation of function templates and member functions of // class templates. if (Func->isImplicitlyInstantiable()) { - bool AlreadyInstantiated = false; - SourceLocation PointOfInstantiation = Loc; - if (FunctionTemplateSpecializationInfo *SpecInfo - = Func->getTemplateSpecializationInfo()) { - if (SpecInfo->getPointOfInstantiation().isInvalid()) - SpecInfo->setPointOfInstantiation(Loc); - else if (SpecInfo->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) { - AlreadyInstantiated = true; - PointOfInstantiation = SpecInfo->getPointOfInstantiation(); - } - } else if (MemberSpecializationInfo *MSInfo - = Func->getMemberSpecializationInfo()) { - if (MSInfo->getPointOfInstantiation().isInvalid()) - MSInfo->setPointOfInstantiation(Loc); - else if (MSInfo->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) { - AlreadyInstantiated = true; - PointOfInstantiation = MSInfo->getPointOfInstantiation(); - } + TemplateSpecializationKind TSK = Func->getTemplateSpecializationKind(); + SourceLocation PointOfInstantiation = Func->getPointOfInstantiation(); + bool FirstInstantiation = PointOfInstantiation.isInvalid(); + if (FirstInstantiation) { + PointOfInstantiation = Loc; + Func->setTemplateSpecializationKind(TSK, PointOfInstantiation); + } else if (TSK != TSK_ImplicitInstantiation) { + // Use the point of use as the point of instantiation, instead of the + // point of explicit instantiation (which we track as the actual point of + // instantiation). This gives better backtraces in diagnostics. + PointOfInstantiation = Loc; } - if (!AlreadyInstantiated || Func->isConstexpr()) { + if (FirstInstantiation || TSK != TSK_ImplicitInstantiation || + Func->isConstexpr()) { if (isa<CXXRecordDecl>(Func->getDeclContext()) && cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass() && CodeSynthesisContexts.size()) @@ -14859,22 +14851,14 @@ static void DoMarkVarDeclReferenced(Sema TSK == TSK_ImplicitInstantiation || (TSK == TSK_ExplicitInstantiationDeclaration && UsableInConstantExpr); - if (TryInstantiating && !isa<VarTemplateSpecializationDecl>(Var)) { - if (Var->getPointOfInstantiation().isInvalid()) { - // This is a modification of an existing AST node. Notify listeners. - if (ASTMutationListener *L = SemaRef.getASTMutationListener()) - L->StaticDataMemberInstantiated(Var); - } else if (!UsableInConstantExpr) - // Don't bother trying to instantiate it again, unless we might need - // its initializer before we get to the end of the TU. - TryInstantiating = false; - } - - if (Var->getPointOfInstantiation().isInvalid()) - Var->setTemplateSpecializationKind(TSK, Loc); - if (TryInstantiating) { SourceLocation PointOfInstantiation = Var->getPointOfInstantiation(); + bool FirstInstantiation = PointOfInstantiation.isInvalid(); + if (FirstInstantiation) { + PointOfInstantiation = Loc; + Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); + } + bool InstantiationDependent = false; bool IsNonDependent = VarSpec ? !TemplateSpecializationType::anyDependentTemplateArguments( @@ -14884,10 +14868,16 @@ static void DoMarkVarDeclReferenced(Sema // Do not instantiate specializations that are still type-dependent. if (IsNonDependent) { if (UsableInConstantExpr) { - // Do not defer instantiations of variables which could be used in a + // Do not defer instantiations of variables that could be used in a // constant expression. SemaRef.InstantiateVariableDefinition(PointOfInstantiation, Var); - } else { + } else if (FirstInstantiation || + isa<VarTemplateSpecializationDecl>(Var)) { + // FIXME: For a specialization of a variable template, we don't + // distinguish between "declaration and type implicitly instantiated" + // and "implicit instantiation of definition requested", so we have + // no direct way to avoid enqueueing the pending instantiation + // multiple times. SemaRef.PendingInstantiations .push_back(std::make_pair(Var, PointOfInstantiation)); } Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Dec 4 17:31:47 2017 @@ -9071,7 +9071,6 @@ DeclResult Sema::ActOnExplicitInstantiat if (!HasNoEffect) { // Instantiate static data member or variable template. - Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); if (PrevTemplate) { // Merge attributes. Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon Dec 4 17:31:47 2017 @@ -2613,7 +2613,7 @@ Sema::InstantiateClassMembers(SourceLoca continue; Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); - InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var); + InstantiateVariableDefinition(PointOfInstantiation, Var); } else { Var->setTemplateSpecializationKind(TSK, PointOfInstantiation); } Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Dec 4 17:31:47 2017 @@ -4142,6 +4142,9 @@ void Sema::BuildVariableInstantiation( void Sema::InstantiateVariableInitializer( VarDecl *Var, VarDecl *OldVar, const MultiLevelTemplateArgumentList &TemplateArgs) { + if (ASTMutationListener *L = getASTContext().getASTMutationListener()) + L->VariableDefinitionInstantiated(Var); + // We propagate the 'inline' flag with the initializer, because it // would otherwise imply that the variable is a definition for a // non-static data member. @@ -4204,36 +4207,22 @@ void Sema::InstantiateVariableInitialize /// /// \param PointOfInstantiation the point at which the instantiation was /// required. Note that this is not precisely a "point of instantiation" -/// for the function, but it's close. +/// for the variable, but it's close. /// -/// \param Var the already-instantiated declaration of a static member -/// variable of a class template specialization. +/// \param Var the already-instantiated declaration of a templated variable. /// /// \param Recursive if true, recursively instantiates any functions that /// are required by this instantiation. /// /// \param DefinitionRequired if true, then we are performing an explicit -/// instantiation where an out-of-line definition of the member variable -/// is required. Complain if there is no such definition. -void Sema::InstantiateStaticDataMemberDefinition( - SourceLocation PointOfInstantiation, - VarDecl *Var, - bool Recursive, - bool DefinitionRequired) { - InstantiateVariableDefinition(PointOfInstantiation, Var, Recursive, - DefinitionRequired); -} - +/// instantiation where a definition of the variable is required. Complain +/// if there is no such definition. void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive, bool DefinitionRequired, bool AtEndOfTU) { if (Var->isInvalidDecl()) return; - // FIXME: We're missing ASTMutationListener notifications for all of the work - // done here. (Some of our callers notify the listeners for the static data - // member case, but not in general.) - VarTemplateSpecializationDecl *VarSpec = dyn_cast<VarTemplateSpecializationDecl>(Var); VarDecl *PatternDecl = nullptr, *Def = nullptr; @@ -4284,6 +4273,11 @@ void Sema::InstantiateVariableDefinition // If this is a static data member template, there might be an // uninstantiated initializer on the declaration. If so, instantiate // it now. + // + // FIXME: This largely duplicates what we would do below. The difference + // is that along this path we may instantiate an initializer from an + // in-class declaration of the template and instantiate the definition + // from a separate out-of-class definition. if (PatternDecl->isStaticDataMember() && (PatternDecl = PatternDecl->getFirstDecl())->hasInit() && !Var->hasInit()) { Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Mon Dec 4 17:31:47 2017 @@ -7268,32 +7268,28 @@ static void processTypeAttrs(TypeProcess void Sema::completeExprArrayBound(Expr *E) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) { if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (isTemplateInstantiation(Var->getTemplateSpecializationKind())) { + if (isTemplateInstantiation(Var->getTemplateSpecializationKind()) && + !Var->getDefinition()) { SourceLocation PointOfInstantiation = E->getExprLoc(); + InstantiateVariableDefinition(PointOfInstantiation, Var); + auto *Def = Var->getDefinition(); - if (MemberSpecializationInfo *MSInfo = - Var->getMemberSpecializationInfo()) { - // If we don't already have a point of instantiation, this is it. - if (MSInfo->getPointOfInstantiation().isInvalid()) { - MSInfo->setPointOfInstantiation(PointOfInstantiation); - - // This is a modification of an existing AST node. Notify - // listeners. - if (ASTMutationListener *L = getASTMutationListener()) - L->StaticDataMemberInstantiated(Var); - } - } else { - VarTemplateSpecializationDecl *VarSpec = - cast<VarTemplateSpecializationDecl>(Var); - if (VarSpec->getPointOfInstantiation().isInvalid()) - VarSpec->setPointOfInstantiation(PointOfInstantiation); + // If we don't already have a point of instantiation, and we managed to + // instantiate a definition, this is the point of instantiation. + // Otherwise, we don't request an end-of-TU instantiation, so this is + // not a point of instantiation. + // FIXME: Is this really the right behavior? + if (Var->getPointOfInstantiation().isInvalid() && Def) { + assert(Var->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation && + "explicit instantiation with no point of instantiation"); + Var->setTemplateSpecializationKind( + Var->getTemplateSpecializationKind(), PointOfInstantiation); } - InstantiateVariableDefinition(PointOfInstantiation, Var); - // Update the type to the newly instantiated definition's type both // here and within the expression. - if (VarDecl *Def = Var->getDefinition()) { + if (Def) { DRE->setDecl(Def); QualType T = Def->getType(); DRE->setType(T); Modified: cfe/trunk/lib/Serialization/ASTCommon.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.h?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTCommon.h (original) +++ cfe/trunk/lib/Serialization/ASTCommon.h Mon Dec 4 17:31:47 2017 @@ -27,7 +27,8 @@ enum DeclUpdateKind { UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, UPD_CXX_ADDED_FUNCTION_DEFINITION, - UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, + UPD_CXX_ADDED_VAR_DEFINITION, + UPD_CXX_POINT_OF_INSTANTIATION, UPD_CXX_INSTANTIATED_CLASS_DEFINITION, UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT, UPD_CXX_INSTANTIATED_DEFAULT_MEMBER_INITIALIZER, Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Mon Dec 4 17:31:47 2017 @@ -3984,10 +3984,8 @@ void ASTDeclReader::UpdateDecl(Decl *D, break; } - case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: { + case UPD_CXX_ADDED_VAR_DEFINITION: { VarDecl *VD = cast<VarDecl>(D); - VD->getMemberSpecializationInfo()->setPointOfInstantiation( - ReadSourceLocation()); VD->NonParmVarDeclBits.IsInline = Record.readInt(); VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt(); uint64_t Val = Record.readInt(); @@ -4001,6 +3999,25 @@ void ASTDeclReader::UpdateDecl(Decl *D, } break; } + + case UPD_CXX_POINT_OF_INSTANTIATION: { + SourceLocation POI = Record.readSourceLocation(); + if (VarTemplateSpecializationDecl *VTSD = + dyn_cast<VarTemplateSpecializationDecl>(D)) { + VTSD->setPointOfInstantiation(POI); + } else if (auto *VD = dyn_cast<VarDecl>(D)) { + VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); + } else { + auto *FD = cast<FunctionDecl>(D); + if (auto *FTSInfo = FD->TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo *>()) + FTSInfo->setPointOfInstantiation(POI); + else + FD->TemplateOrSpecialization.get<MemberSpecializationInfo *>() + ->setPointOfInstantiation(POI); + } + break; + } case UPD_CXX_INSTANTIATED_DEFAULT_ARGUMENT: { auto Param = cast<ParmVarDecl>(D); Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=319727&r1=319726&r2=319727&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Mon Dec 4 17:31:47 2017 @@ -5135,9 +5135,13 @@ void ASTWriter::WriteDeclUpdatesBlocks(R case UPD_CXX_ADDED_FUNCTION_DEFINITION: break; - case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: { - const VarDecl *VD = cast<VarDecl>(D); + case UPD_CXX_POINT_OF_INSTANTIATION: + // FIXME: Do we need to also save the template specialization kind here? Record.AddSourceLocation(Update.getLoc()); + break; + + case UPD_CXX_ADDED_VAR_DEFINITION: { + const VarDecl *VD = cast<VarDecl>(D); Record.push_back(VD->isInline()); Record.push_back(VD->isInlineSpecified()); if (VD->getInit()) { @@ -6256,6 +6260,15 @@ void ASTWriter::CompletedImplicitDefinit DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } +void ASTWriter::VariableDefinitionInstantiated(const VarDecl *D) { + if (Chain && Chain->isProcessingUpdateRecords()) return; + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) + return; + + DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_VAR_DEFINITION)); +} + void ASTWriter::FunctionDefinitionInstantiated(const FunctionDecl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); @@ -6265,7 +6278,7 @@ void ASTWriter::FunctionDefinitionInstan DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_ADDED_FUNCTION_DEFINITION)); } -void ASTWriter::StaticDataMemberInstantiated(const VarDecl *D) { +void ASTWriter::InstantiationRequested(const ValueDecl *D) { if (Chain && Chain->isProcessingUpdateRecords()) return; assert(!WritingAST && "Already writing the AST!"); if (!D->isFromASTFile()) @@ -6273,9 +6286,12 @@ void ASTWriter::StaticDataMemberInstanti // Since the actual instantiation is delayed, this really means that we need // to update the instantiation location. - DeclUpdates[D].push_back( - DeclUpdate(UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, - D->getMemberSpecializationInfo()->getPointOfInstantiation())); + SourceLocation POI; + if (auto *VD = dyn_cast<VarDecl>(D)) + POI = VD->getPointOfInstantiation(); + else + POI = cast<FunctionDecl>(D)->getPointOfInstantiation(); + DeclUpdates[D].push_back(DeclUpdate(UPD_CXX_POINT_OF_INSTANTIATION, POI)); } void ASTWriter::DefaultArgumentInstantiated(const ParmVarDecl *D) { Added: cfe/trunk/test/Modules/var-templates.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/var-templates.cpp?rev=319727&view=auto ============================================================================== --- cfe/trunk/test/Modules/var-templates.cpp (added) +++ cfe/trunk/test/Modules/var-templates.cpp Mon Dec 4 17:31:47 2017 @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fmodules -std=c++14 -emit-llvm %s -o - | FileCheck %s + +#pragma clang module build A +module A {} +#pragma clang module contents +#pragma clang module begin A +template<int> int n = 42; +decltype(n<0>) f(); +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module build B +module B {} +#pragma clang module contents +#pragma clang module begin B +#pragma clang module import A +inline int f() { return n<0>; } +#pragma clang module end +#pragma clang module endbuild + +#pragma clang module import B + +// CHECK: @_Z1nILi0EE = linkonce_odr global i32 42, comdat +int g() { return f(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits