<div dir="ltr">Sorry about that, fixed in r319817.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On 5 December 2017 at 10:38, Galina Kistanova via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Hello Richard,<br><br>This commit broke tests on one of our bots:<br><br><a href="http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/6568" target="_blank">http://lab.llvm.org:8011/<wbr>builders/llvm-clang-x86_64-<wbr>expensive-checks-win/builds/<wbr>6568</a><br><br>Failing Tests (3):<br>. . .<br>    Clang :: Modules/var-templates.cpp<br>. . . <br><br>Please have a look?<br><br>Thanks<br><br>Galina<br></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 4, 2017 at 5:31 PM, Richard Smith via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Mon Dec  4 17:31:47 2017<br>
New Revision: 319727<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=319727&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject?rev=319727&view=rev</a><br>
Log:<br>
Generalize "static data member instantiated" notification to cover variable templates too.<br>
<br>
While here, split the "point of instantiation changed" notification out from<br>
it; these two really are orthogonal changes.<br>
<br>
Added:<br>
    cfe/trunk/test/Modules/var-tem<wbr>plates.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/AST/AS<wbr>TMutationListener.h<br>
    cfe/trunk/include/clang/Sema/S<wbr>ema.h<br>
    cfe/trunk/include/clang/Serial<wbr>ization/ASTWriter.h<br>
    cfe/trunk/lib/AST/Decl.cpp<br>
    cfe/trunk/lib/Frontend/Multipl<wbr>exConsumer.cpp<br>
    cfe/trunk/lib/Sema/SemaExpr.cp<wbr>p<br>
    cfe/trunk/lib/Sema/SemaTemplat<wbr>e.cpp<br>
    cfe/trunk/lib/Sema/SemaTemplat<wbr>eInstantiate.cpp<br>
    cfe/trunk/lib/Sema/SemaTemplat<wbr>eInstantiateDecl.cpp<br>
    cfe/trunk/lib/Sema/SemaType.cp<wbr>p<br>
    cfe/trunk/lib/Serialization/AS<wbr>TCommon.h<br>
    cfe/trunk/lib/Serialization/AS<wbr>TReaderDecl.cpp<br>
    cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/AS<wbr>TMutationListener.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTMutationListener.h?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>AST/ASTMutationListener.h?rev=<wbr>319727&r1=319726&r2=319727&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/AS<wbr>TMutationListener.h (original)<br>
+++ cfe/trunk/include/clang/AST/AS<wbr>TMutationListener.h Mon Dec  4 17:31:47 2017<br>
@@ -36,6 +36,7 @@ namespace clang {<br>
   class QualType;<br>
   class RecordDecl;<br>
   class TagDecl;<br>
+  class ValueDecl;<br>
   class VarDecl;<br>
   class VarTemplateDecl;<br>
   class VarTemplateSpecializationDecl;<br>
@@ -87,8 +88,13 @@ public:<br>
   /// \brief An implicit member got a definition.<br>
   virtual void CompletedImplicitDefinition(co<wbr>nst FunctionDecl *D) {}<br>
<br>
-  /// \brief A static data member was implicitly instantiated.<br>
-  virtual void StaticDataMemberInstantiated(c<wbr>onst VarDecl *D) {}<br>
+  /// \brief The instantiation of a templated function or variable was<br>
+  /// requested. In particular, the point of instantiation and template<br>
+  /// specialization kind of \p D may have changed.<br>
+  virtual void InstantiationRequested(const ValueDecl *D) {}<br>
+<br>
+  /// \brief A templated variable's definition was implicitly instantiated.<br>
+  virtual void VariableDefinitionInstantiated<wbr>(const VarDecl *D) {}<br>
<br>
   /// \brief A function template's definition was instantiated.<br>
   virtual void FunctionDefinitionInstantiated<wbr>(const FunctionDecl *D) {}<br>
<br>
Modified: cfe/trunk/include/clang/Sema/S<wbr>ema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>Sema/Sema.h?rev=319727&r1=<wbr>319726&r2=319727&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Sema/S<wbr>ema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/S<wbr>ema.h Mon Dec  4 17:31:47 2017<br>
@@ -7790,11 +7790,6 @@ public:<br>
                                      VarDecl *Var, bool Recursive = false,<br>
                                      bool DefinitionRequired = false,<br>
                                      bool AtEndOfTU = false);<br>
-  void InstantiateStaticDataMemberDef<wbr>inition(<br>
-                                     SourceLocation PointOfInstantiation,<br>
-                                     VarDecl *Var,<br>
-                                     bool Recursive = false,<br>
-                                     bool DefinitionRequired = false);<br>
<br>
   void InstantiateMemInitializers(CXX<wbr>ConstructorDecl *New,<br>
                                   const CXXConstructorDecl *Tmpl,<br>
<br>
Modified: cfe/trunk/include/clang/Serial<wbr>ization/ASTWriter.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/include/clang/<wbr>Serialization/ASTWriter.h?rev=<wbr>319727&r1=319726&r2=319727&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Serial<wbr>ization/ASTWriter.h (original)<br>
+++ cfe/trunk/include/clang/Serial<wbr>ization/ASTWriter.h Mon Dec  4 17:31:47 2017<br>
@@ -727,10 +727,11 @@ private:<br>
                               const FunctionDecl *Delete,<br>
                               Expr *ThisArg) override;<br>
   void CompletedImplicitDefinition(co<wbr>nst FunctionDecl *D) override;<br>
-  void StaticDataMemberInstantiated(c<wbr>onst VarDecl *D) override;<br>
+  void InstantiationRequested(const ValueDecl *D) override;<br>
+  void VariableDefinitionInstantiated<wbr>(const VarDecl *D) override;<br>
+  void FunctionDefinitionInstantiated<wbr>(const FunctionDecl *D) override;<br>
   void DefaultArgumentInstantiated(co<wbr>nst ParmVarDecl *D) override;<br>
   void DefaultMemberInitializerInstan<wbr>tiated(const FieldDecl *D) override;<br>
-  void FunctionDefinitionInstantiated<wbr>(const FunctionDecl *D) override;<br>
   void AddedObjCCategoryToInterface(c<wbr>onst ObjCCategoryDecl *CatD,<br>
                                     const ObjCInterfaceDecl *IFD) override;<br>
   void DeclarationMarkedUsed(const Decl *D) override;<br>
<br>
Modified: cfe/trunk/lib/AST/Decl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/AST/Decl.<wbr>cpp?rev=319727&r1=319726&r2=<wbr>319727&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/Decl.cpp (original)<br>
+++ cfe/trunk/lib/AST/Decl.cpp Mon Dec  4 17:31:47 2017<br>
@@ -2418,15 +2418,21 @@ void VarDecl::setTemplateSpecializa<wbr>tionK<br>
           dyn_cast<VarTemplateSpecializ<wbr>ationDecl>(this)) {<br>
     Spec->setSpecializationKind(T<wbr>SK);<br>
     if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&<br>
-        Spec->getPointOfInstantiation(<wbr>).isInvalid())<br>
+        Spec->getPointOfInstantiation(<wbr>).isInvalid()) {<br>
       Spec-><wbr>setPointOfInstantiation(PointO<wbr>fInstantiation);<br>
+      if (ASTMutationListener *L = getASTContext().getASTMutation<wbr>Listener())<br>
+        L->InstantiationRequested(this<wbr>);<br>
+    }<br>
   }<br>
<br>
   if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) {<br>
     MSI->setTemplateSpecializatio<wbr>nKind(TSK);<br>
     if (TSK != TSK_ExplicitSpecialization && PointOfInstantiation.isValid() &&<br>
-        MSI->getPointOfInstantiation()<wbr>.isInvalid())<br>
+        MSI->getPointOfInstantiation()<wbr>.isInvalid()) {<br>
       MSI->setPointOfInstantiation(<wbr>PointOfInstantiation);<br>
+      if (ASTMutationListener *L = getASTContext().getASTMutation<wbr>Listener())<br>
+        L->InstantiationRequested(this<wbr>);<br>
+    }<br>
   }<br>
 }<br>
<br>
@@ -3442,15 +3448,21 @@ FunctionDecl::setTemplateSpeci<wbr>alizationK<br>
     FTSInfo->setTemplateSpecializ<wbr>ationKind(TSK);<br>
     if (TSK != TSK_ExplicitSpecialization &&<br>
         PointOfInstantiation.isValid(<wbr>) &&<br>
-        FTSInfo->getPointOfInstantiati<wbr>on().isInvalid())<br>
+        FTSInfo->getPointOfInstantiati<wbr>on().isInvalid()) {<br>
       FTSInfo->setPointOfInstantiat<wbr>ion(PointOfInstantiation);<br>
+      if (ASTMutationListener *L = getASTContext().getASTMutation<wbr>Listener())<br>
+        L->InstantiationRequested(this<wbr>);<br>
+    }<br>
   } else if (MemberSpecializationInfo *MSInfo<br>
              = TemplateOrSpecialization.dyn_c<wbr>ast<MemberSpecializationInfo*><wbr>()) {<br>
     MSInfo->setTemplateSpecializa<wbr>tionKind(TSK);<br>
     if (TSK != TSK_ExplicitSpecialization &&<br>
         PointOfInstantiation.isValid(<wbr>) &&<br>
-        MSInfo->getPointOfInstantiatio<wbr>n().isInvalid())<br>
+        MSInfo->getPointOfInstantiatio<wbr>n().isInvalid()) {<br>
       MSInfo->setPointOfInstantiati<wbr>on(PointOfInstantiation);<br>
+      if (ASTMutationListener *L = getASTContext().getASTMutation<wbr>Listener())<br>
+        L->InstantiationRequested(this<wbr>);<br>
+    }<br>
   } else<br>
     llvm_unreachable("Function cannot have a template specialization kind");<br>
 }<br>
<br>
Modified: cfe/trunk/lib/Frontend/Multipl<wbr>exConsumer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/MultiplexConsumer.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Frontend/<wbr>MultiplexConsumer.cpp?rev=<wbr>319727&r1=319726&r2=319727&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Frontend/Multipl<wbr>exConsumer.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/Multipl<wbr>exConsumer.cpp Mon Dec  4 17:31:47 2017<br>
@@ -119,12 +119,13 @@ public:<br>
                               const FunctionDecl *Delete,<br>
                               Expr *ThisArg) override;<br>
   void CompletedImplicitDefinition(co<wbr>nst FunctionDecl *D) override;<br>
-  void StaticDataMemberInstantiated(c<wbr>onst VarDecl *D) override;<br>
+  void InstantiationRequested(const ValueDecl *D) override;<br>
+  void VariableDefinitionInstantiated<wbr>(const VarDecl *D) override;<br>
+  void FunctionDefinitionInstantiated<wbr>(const FunctionDecl *D) override;<br>
   void DefaultArgumentInstantiated(co<wbr>nst ParmVarDecl *D) override;<br>
   void DefaultMemberInitializerInstan<wbr>tiated(const FieldDecl *D) override;<br>
   void AddedObjCCategoryToInterface(c<wbr>onst ObjCCategoryDecl *CatD,<br>
                                     const ObjCInterfaceDecl *IFD) override;<br>
-  void FunctionDefinitionInstantiated<wbr>(const FunctionDecl *D) override;<br>
   void DeclarationMarkedUsed(const Decl *D) override;<br>
   void DeclarationMarkedOpenMPThreadP<wbr>rivate(const Decl *D) override;<br>
   void DeclarationMarkedOpenMPDeclare<wbr>Target(const Decl *D,<br>
@@ -193,10 +194,19 @@ void MultiplexASTMutationListener::<wbr>Compl<br>
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)<br>
     Listeners[i]->CompletedImplic<wbr>itDefinition(D);<br>
 }<br>
-void MultiplexASTMutationListener::<wbr>StaticDataMemberInstantiated(<br>
-                                                             const VarDecl *D) {<br>
+void MultiplexASTMutationListener::<wbr>InstantiationRequested(const ValueDecl *D) {<br>
+  for (size_t i = 0, e = Listeners.size(); i != e; ++i)<br>
+    Listeners[i]->InstantiationReq<wbr>uested(D);<br>
+}<br>
+void MultiplexASTMutationListener::<wbr>VariableDefinitionInstantiated<wbr>(<br>
+    const VarDecl *D) {<br>
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)<br>
-    Listeners[i]->StaticDataMember<wbr>Instantiated(D);<br>
+    Listeners[i]->VariableDefiniti<wbr>onInstantiated(D);<br>
+}<br>
+void MultiplexASTMutationListener::<wbr>FunctionDefinitionInstantiated<wbr>(<br>
+    const FunctionDecl *D) {<br>
+  for (auto &Listener : Listeners)<br>
+    Listener->FunctionDefinitionIn<wbr>stantiated(D);<br>
 }<br>
 void MultiplexASTMutationListener::<wbr>DefaultArgumentInstantiated(<br>
                                                          const ParmVarDecl *D) {<br>
@@ -214,11 +224,6 @@ void MultiplexASTMutationListener::<wbr>Added<br>
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)<br>
     Listeners[i]->AddedObjCCatego<wbr>ryToInterface(CatD, IFD);<br>
 }<br>
-void MultiplexASTMutationListener::<wbr>FunctionDefinitionInstantiated<wbr>(<br>
-    const FunctionDecl *D) {<br>
-  for (auto &Listener : Listeners)<br>
-    Listener->FunctionDefinitionIn<wbr>stantiated(D);<br>
-}<br>
 void MultiplexASTMutationListener::<wbr>DeclarationMarkedUsed(const Decl *D) {<br>
   for (size_t i = 0, e = Listeners.size(); i != e; ++i)<br>
     Listeners[i]->DeclarationMark<wbr>edUsed(D);<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cp<wbr>p<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Sema/SemaE<wbr>xpr.cpp?rev=319727&r1=319726&<wbr>r2=319727&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cp<wbr>p (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cp<wbr>p Mon Dec  4 17:31:47 2017<br>
@@ -13960,29 +13960,21 @@ void Sema::MarkFunctionReferenced(S<wbr>ource<br>
   // Implicit instantiation of function templates and member functions of<br>
   // class templates.<br>
   if (Func->isImplicitlyInstantiabl<wbr>e()) {<br>
-    bool AlreadyInstantiated = false;<br>
-    SourceLocation PointOfInstantiation = Loc;<br>
-    if (FunctionTemplateSpecializatio<wbr>nInfo *SpecInfo<br>
-                              = Func->getTemplateSpecializatio<wbr>nInfo()) {<br>
-      if (SpecInfo->getPointOfInstantia<wbr>tion().isInvalid())<br>
-        SpecInfo->setPointOfInstantiat<wbr>ion(Loc);<br>
-      else if (SpecInfo->getTemplateSpeciali<wbr>zationKind()<br>
-                 == TSK_ImplicitInstantiation) {<br>
-        AlreadyInstantiated = true;<br>
-        PointOfInstantiation = SpecInfo->getPointOfInstantiat<wbr>ion();<br>
-      }<br>
-    } else if (MemberSpecializationInfo *MSInfo<br>
-                                = Func->getMemberSpecializationI<wbr>nfo()) {<br>
-      if (MSInfo->getPointOfInstantiati<wbr>on().isInvalid())<br>
-        MSInfo->setPointOfInstantiatio<wbr>n(Loc);<br>
-      else if (MSInfo->getTemplateSpecializa<wbr>tionKind()<br>
-                 == TSK_ImplicitInstantiation) {<br>
-        AlreadyInstantiated = true;<br>
-        PointOfInstantiation = MSInfo->getPointOfInstantiatio<wbr>n();<br>
-      }<br>
+    TemplateSpecializationKind TSK = Func->getTemplateSpecializatio<wbr>nKind();<br>
+    SourceLocation PointOfInstantiation = Func->getPointOfInstantiation(<wbr>);<br>
+    bool FirstInstantiation = PointOfInstantiation.isInvalid<wbr>();<br>
+    if (FirstInstantiation) {<br>
+      PointOfInstantiation = Loc;<br>
+      Func->setTemplateSpecializatio<wbr>nKind(TSK, PointOfInstantiation);<br>
+    } else if (TSK != TSK_ImplicitInstantiation) {<br>
+      // Use the point of use as the point of instantiation, instead of the<br>
+      // point of explicit instantiation (which we track as the actual point of<br>
+      // instantiation). This gives better backtraces in diagnostics.<br>
+      PointOfInstantiation = Loc;<br>
     }<br>
<br>
-    if (!AlreadyInstantiated || Func->isConstexpr()) {<br>
+    if (FirstInstantiation || TSK != TSK_ImplicitInstantiation ||<br>
+        Func->isConstexpr()) {<br>
       if (isa<CXXRecordDecl>(Func->getD<wbr>eclContext()) &&<br>
           cast<CXXRecordDecl>(Func->get<wbr>DeclContext())->isLocalClass() &&<br>
           CodeSynthesisContexts.size())<br>
@@ -14859,22 +14851,14 @@ static void DoMarkVarDeclReferenced(Sema<br>
         TSK == TSK_ImplicitInstantiation ||<br>
         (TSK == TSK_ExplicitInstantiationDecla<wbr>ration && UsableInConstantExpr);<br>
<br>
-    if (TryInstantiating && !isa<VarTemplateSpecialization<wbr>Decl>(Var)) {<br>
-      if (Var->getPointOfInstantiation(<wbr>).isInvalid()) {<br>
-        // This is a modification of an existing AST node. Notify listeners.<br>
-        if (ASTMutationListener *L = SemaRef.getASTMutationListener<wbr>())<br>
-          L->StaticDataMemberInstantiate<wbr>d(Var);<br>
-      } else if (!UsableInConstantExpr)<br>
-        // Don't bother trying to instantiate it again, unless we might need<br>
-        // its initializer before we get to the end of the TU.<br>
-        TryInstantiating = false;<br>
-    }<br>
-<br>
-    if (Var->getPointOfInstantiation(<wbr>).isInvalid())<br>
-      Var->setTemplateSpecialization<wbr>Kind(TSK, Loc);<br>
-<br>
     if (TryInstantiating) {<br>
       SourceLocation PointOfInstantiation = Var->getPointOfInstantiation()<wbr>;<br>
+      bool FirstInstantiation = PointOfInstantiation.isInvalid<wbr>();<br>
+      if (FirstInstantiation) {<br>
+        PointOfInstantiation = Loc;<br>
+        Var->setTemplateSpecialization<wbr>Kind(TSK, PointOfInstantiation);<br>
+      }<br>
+<br>
       bool InstantiationDependent = false;<br>
       bool IsNonDependent =<br>
           VarSpec ? !TemplateSpecializationType::a<wbr>nyDependentTemplateArguments(<br>
@@ -14884,10 +14868,16 @@ static void DoMarkVarDeclReferenced(Sema<br>
       // Do not instantiate specializations that are still type-dependent.<br>
       if (IsNonDependent) {<br>
         if (UsableInConstantExpr) {<br>
-          // Do not defer instantiations of variables which could be used in a<br>
+          // Do not defer instantiations of variables that could be used in a<br>
           // constant expression.<br>
           SemaRef.InstantiateVariableDe<wbr>finition(PointOfInstantiation, Var);<br>
-        } else {<br>
+        } else if (FirstInstantiation ||<br>
+                   isa<VarTemplateSpecialization<wbr>Decl>(Var)) {<br>
+          // FIXME: For a specialization of a variable template, we don't<br>
+          // distinguish between "declaration and type implicitly instantiated"<br>
+          // and "implicit instantiation of definition requested", so we have<br>
+          // no direct way to avoid enqueueing the pending instantiation<br>
+          // multiple times.<br>
           SemaRef.PendingInstantiations<br>
               .push_back(std::make_pair(<wbr>Var, PointOfInstantiation));<br>
         }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplat<wbr>e.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Sema/SemaT<wbr>emplate.cpp?rev=319727&r1=<wbr>319726&r2=319727&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaTemplat<wbr>e.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplat<wbr>e.cpp Mon Dec  4 17:31:47 2017<br>
@@ -9071,7 +9071,6 @@ DeclResult Sema::ActOnExplicitInstantiat<br>
<br>
     if (!HasNoEffect) {<br>
       // Instantiate static data member or variable template.<br>
-<br>
       Prev->setTemplateSpecializati<wbr>onKind(TSK, D.getIdentifierLoc());<br>
       if (PrevTemplate) {<br>
         // Merge attributes.<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplat<wbr>eInstantiate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Sema/SemaT<wbr>emplateInstantiate.cpp?rev=<wbr>319727&r1=319726&r2=319727&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaTemplat<wbr>eInstantiate.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplat<wbr>eInstantiate.cpp Mon Dec  4 17:31:47 2017<br>
@@ -2613,7 +2613,7 @@ Sema::InstantiateClassMembers(<wbr>SourceLoca<br>
             continue;<br>
<br>
           Var->setTemplateSpecializatio<wbr>nKind(TSK, PointOfInstantiation);<br>
-          InstantiateStaticDataMemberDef<wbr>inition(PointOfInstantiation, Var);<br>
+          InstantiateVariableDefinition(<wbr>PointOfInstantiation, Var);<br>
         } else {<br>
           Var->setTemplateSpecializatio<wbr>nKind(TSK, PointOfInstantiation);<br>
         }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaTemplat<wbr>eInstantiateDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Sema/SemaT<wbr>emplateInstantiateDecl.cpp?<wbr>rev=319727&r1=319726&r2=319727<wbr>&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaTemplat<wbr>eInstantiateDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaTemplat<wbr>eInstantiateDecl.cpp Mon Dec  4 17:31:47 2017<br>
@@ -4142,6 +4142,9 @@ void Sema::BuildVariableInstantiati<wbr>on(<br>
 void Sema::InstantiateVariableIniti<wbr>alizer(<br>
     VarDecl *Var, VarDecl *OldVar,<br>
     const MultiLevelTemplateArgumentList &TemplateArgs) {<br>
+  if (ASTMutationListener *L = getASTContext().getASTMutation<wbr>Listener())<br>
+    L->VariableDefinitionInstantia<wbr>ted(Var);<br>
+<br>
   // We propagate the 'inline' flag with the initializer, because it<br>
   // would otherwise imply that the variable is a definition for a<br>
   // non-static data member.<br>
@@ -4204,36 +4207,22 @@ void Sema::InstantiateVariableIniti<wbr>alize<br>
 ///<br>
 /// \param PointOfInstantiation the point at which the instantiation was<br>
 /// required. Note that this is not precisely a "point of instantiation"<br>
-/// for the function, but it's close.<br>
+/// for the variable, but it's close.<br>
 ///<br>
-/// \param Var the already-instantiated declaration of a static member<br>
-/// variable of a class template specialization.<br>
+/// \param Var the already-instantiated declaration of a templated variable.<br>
 ///<br>
 /// \param Recursive if true, recursively instantiates any functions that<br>
 /// are required by this instantiation.<br>
 ///<br>
 /// \param DefinitionRequired if true, then we are performing an explicit<br>
-/// instantiation where an out-of-line definition of the member variable<br>
-/// is required. Complain if there is no such definition.<br>
-void Sema::InstantiateStaticDataMem<wbr>berDefinition(<br>
-                                          SourceLocation PointOfInstantiation,<br>
-                                                 VarDecl *Var,<br>
-                                                 bool Recursive,<br>
-                                                 bool DefinitionRequired) {<br>
-  InstantiateVariableDefinition(<wbr>PointOfInstantiation, Var, Recursive,<br>
-                                DefinitionRequired);<br>
-}<br>
-<br>
+/// instantiation where a definition of the variable is required. Complain<br>
+/// if there is no such definition.<br>
 void Sema::InstantiateVariableDefin<wbr>ition(SourceLocation PointOfInstantiation,<br>
                                          VarDecl *Var, bool Recursive,<br>
                                       bool DefinitionRequired, bool AtEndOfTU) {<br>
   if (Var->isInvalidDecl())<br>
     return;<br>
<br>
-  // FIXME: We're missing ASTMutationListener notifications for all of the work<br>
-  // done here. (Some of our callers notify the listeners for the static data<br>
-  // member case, but not in general.)<br>
-<br>
   VarTemplateSpecializationDecl *VarSpec =<br>
       dyn_cast<VarTemplateSpecializ<wbr>ationDecl>(Var);<br>
   VarDecl *PatternDecl = nullptr, *Def = nullptr;<br>
@@ -4284,6 +4273,11 @@ void Sema::InstantiateVariableDefin<wbr>ition<br>
     // If this is a static data member template, there might be an<br>
     // uninstantiated initializer on the declaration. If so, instantiate<br>
     // it now.<br>
+    //<br>
+    // FIXME: This largely duplicates what we would do below. The difference<br>
+    // is that along this path we may instantiate an initializer from an<br>
+    // in-class declaration of the template and instantiate the definition<br>
+    // from a separate out-of-class definition.<br>
     if (PatternDecl->isStaticDataMemb<wbr>er() &&<br>
         (PatternDecl = PatternDecl->getFirstDecl())-><wbr>hasInit() &&<br>
         !Var->hasInit()) {<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaType.cp<wbr>p<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Sema/SemaT<wbr>ype.cpp?rev=319727&r1=319726&<wbr>r2=319727&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaType.cp<wbr>p (original)<br>
+++ cfe/trunk/lib/Sema/SemaType.cp<wbr>p Mon Dec  4 17:31:47 2017<br>
@@ -7268,32 +7268,28 @@ static void processTypeAttrs(TypeProcess<br>
 void Sema::completeExprArrayBound(E<wbr>xpr *E) {<br>
   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->Ignor<wbr>eParens())) {<br>
     if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl<wbr>())) {<br>
-      if (isTemplateInstantiation(Var-><wbr>getTemplateSpecializationKind(<wbr>))) {<br>
+      if (isTemplateInstantiation(Var-><wbr>getTemplateSpecializationKind(<wbr>)) &&<br>
+          !Var->getDefinition()) {<br>
         SourceLocation PointOfInstantiation = E->getExprLoc();<br>
+        InstantiateVariableDefinition(<wbr>PointOfInstantiation, Var);<br>
+        auto *Def = Var->getDefinition();<br>
<br>
-        if (MemberSpecializationInfo *MSInfo =<br>
-                Var->getMemberSpecializationIn<wbr>fo()) {<br>
-          // If we don't already have a point of instantiation, this is it.<br>
-          if (MSInfo->getPointOfInstantiati<wbr>on().isInvalid()) {<br>
-            MSInfo->setPointOfInstantiatio<wbr>n(PointOfInstantiation);<br>
-<br>
-            // This is a modification of an existing AST node. Notify<br>
-            // listeners.<br>
-            if (ASTMutationListener *L = getASTMutationListener())<br>
-              L->StaticDataMemberInstantiate<wbr>d(Var);<br>
-          }<br>
-        } else {<br>
-          VarTemplateSpecializationDecl *VarSpec =<br>
-              cast<VarTemplateSpecialization<wbr>Decl>(Var);<br>
-          if (VarSpec->getPointOfInstantiat<wbr>ion().isInvalid())<br>
-            VarSpec->setPointOfInstantiati<wbr>on(PointOfInstantiation);<br>
+        // If we don't already have a point of instantiation, and we managed to<br>
+        // instantiate a definition, this is the point of instantiation.<br>
+        // Otherwise, we don't request an end-of-TU instantiation, so this is<br>
+        // not a point of instantiation.<br>
+        // FIXME: Is this really the right behavior?<br>
+        if (Var->getPointOfInstantiation(<wbr>).isInvalid() && Def) {<br>
+          assert(Var->getTemplateSpecial<wbr>izationKind() ==<br>
+                     TSK_ImplicitInstantiation &&<br>
+                 "explicit instantiation with no point of instantiation");<br>
+          Var->setTemplateSpecialization<wbr>Kind(<br>
+              Var->getTemplateSpecialization<wbr>Kind(), PointOfInstantiation);<br>
         }<br>
<br>
-        InstantiateVariableDefinition(<wbr>PointOfInstantiation, Var);<br>
-<br>
         // Update the type to the newly instantiated definition's type both<br>
         // here and within the expression.<br>
-        if (VarDecl *Def = Var->getDefinition()) {<br>
+        if (Def) {<br>
           DRE->setDecl(Def);<br>
           QualType T = Def->getType();<br>
           DRE->setType(T);<br>
<br>
Modified: cfe/trunk/lib/Serialization/AS<wbr>TCommon.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.h?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Serializat<wbr>ion/ASTCommon.h?rev=319727&r1=<wbr>319726&r2=319727&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/AS<wbr>TCommon.h (original)<br>
+++ cfe/trunk/lib/Serialization/AS<wbr>TCommon.h Mon Dec  4 17:31:47 2017<br>
@@ -27,7 +27,8 @@ enum DeclUpdateKind {<br>
   UPD_CXX_ADDED_TEMPLATE_SPECIA<wbr>LIZATION,<br>
   UPD_CXX_ADDED_ANONYMOUS_NAMES<wbr>PACE,<br>
   UPD_CXX_ADDED_FUNCTION_DEFINI<wbr>TION,<br>
-  UPD_CXX_INSTANTIATED_STATIC_DA<wbr>TA_MEMBER,<br>
+  UPD_CXX_ADDED_VAR_DEFINITION,<br>
+  UPD_CXX_POINT_OF_INSTANTIATION<wbr>,<br>
   UPD_CXX_INSTANTIATED_CLASS_DE<wbr>FINITION,<br>
   UPD_CXX_INSTANTIATED_DEFAULT_<wbr>ARGUMENT,<br>
   UPD_CXX_INSTANTIATED_DEFAULT_<wbr>MEMBER_INITIALIZER,<br>
<br>
Modified: cfe/trunk/lib/Serialization/AS<wbr>TReaderDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Serializat<wbr>ion/ASTReaderDecl.cpp?rev=<wbr>319727&r1=319726&r2=319727&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/AS<wbr>TReaderDecl.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/AS<wbr>TReaderDecl.cpp Mon Dec  4 17:31:47 2017<br>
@@ -3984,10 +3984,8 @@ void ASTDeclReader::UpdateDecl(Decl *D,<br>
       break;<br>
     }<br>
<br>
-    case UPD_CXX_INSTANTIATED_STATIC_DA<wbr>TA_MEMBER: {<br>
+    case UPD_CXX_ADDED_VAR_DEFINITION: {<br>
       VarDecl *VD = cast<VarDecl>(D);<br>
-      VD->getMemberSpecializationInf<wbr>o()->setPointOfInstantiation(<br>
-          ReadSourceLocation());<br>
       VD->NonParmVarDeclBits.IsInli<wbr>ne = Record.readInt();<br>
       VD->NonParmVarDeclBits.IsInli<wbr>neSpecified = Record.readInt();<br>
       uint64_t Val = Record.readInt();<br>
@@ -4001,6 +3999,25 @@ void ASTDeclReader::UpdateDecl(Decl *D,<br>
       }<br>
       break;<br>
     }<br>
+<br>
+    case UPD_CXX_POINT_OF_INSTANTIATION<wbr>: {<br>
+      SourceLocation POI = Record.readSourceLocation();<br>
+      if (VarTemplateSpecializationDecl *VTSD =<br>
+              dyn_cast<VarTemplateSpecializa<wbr>tionDecl>(D)) {<br>
+        VTSD->setPointOfInstantiation(<wbr>POI);<br>
+      } else if (auto *VD = dyn_cast<VarDecl>(D)) {<br>
+        VD->getMemberSpecializationInf<wbr>o()->setPointOfInstantiation(<wbr>POI);<br>
+      } else {<br>
+        auto *FD = cast<FunctionDecl>(D);<br>
+        if (auto *FTSInfo = FD->TemplateOrSpecialization<br>
+                    .dyn_cast<FunctionTemplateSpec<wbr>ializationInfo *>())<br>
+          FTSInfo->setPointOfInstantiati<wbr>on(POI);<br>
+        else<br>
+          FD->TemplateOrSpecialization.g<wbr>et<MemberSpecializationInfo *>()<br>
+              ->setPointOfInstantiation(POI)<wbr>;<br>
+      }<br>
+      break;<br>
+    }<br>
<br>
     case UPD_CXX_INSTANTIATED_DEFAULT_A<wbr>RGUMENT: {<br>
       auto Param = cast<ParmVarDecl>(D);<br>
<br>
Modified: cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=319727&r1=319726&r2=319727&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/lib/Serializat<wbr>ion/ASTWriter.cpp?rev=319727&<wbr>r1=319726&r2=319727&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/AS<wbr>TWriter.cpp Mon Dec  4 17:31:47 2017<br>
@@ -5135,9 +5135,13 @@ void ASTWriter::WriteDeclUpdatesBlo<wbr>cks(R<br>
       case UPD_CXX_ADDED_FUNCTION_DEFINIT<wbr>ION:<br>
         break;<br>
<br>
-      case UPD_CXX_INSTANTIATED_STATIC_DA<wbr>TA_MEMBER: {<br>
-        const VarDecl *VD = cast<VarDecl>(D);<br>
+      case UPD_CXX_POINT_OF_INSTANTIATION<wbr>:<br>
+        // FIXME: Do we need to also save the template specialization kind here?<br>
         Record.AddSourceLocation(Upda<wbr>te.getLoc());<br>
+        break;<br>
+<br>
+      case UPD_CXX_ADDED_VAR_DEFINITION: {<br>
+        const VarDecl *VD = cast<VarDecl>(D);<br>
         Record.push_back(VD-><wbr>isInline());<br>
         Record.push_back(VD->isInline<wbr>Specified());<br>
         if (VD->getInit()) {<br>
@@ -6256,6 +6260,15 @@ void ASTWriter::CompletedImplicitDe<wbr>finit<br>
   DeclUpdates[D].push_back(Decl<wbr>Update(UPD_CXX_ADDED_FUNCTION_<wbr>DEFINITION));<br>
 }<br>
<br>
+void ASTWriter::VariableDefinitionI<wbr>nstantiated(const VarDecl *D) {<br>
+  if (Chain && Chain->isProcessingUpdateRecor<wbr>ds()) return;<br>
+  assert(!WritingAST && "Already writing the AST!");<br>
+  if (!D->isFromASTFile())<br>
+    return;<br>
+<br>
+  DeclUpdates[D].push_back(DeclU<wbr>pdate(UPD_CXX_ADDED_VAR_DEFINI<wbr>TION));<br>
+}<br>
+<br>
 void ASTWriter::FunctionDefinitionI<wbr>nstantiated(const FunctionDecl *D) {<br>
   if (Chain && Chain->isProcessingUpdateRecor<wbr>ds()) return;<br>
   assert(!WritingAST && "Already writing the AST!");<br>
@@ -6265,7 +6278,7 @@ void ASTWriter::FunctionDefinitionI<wbr>nstan<br>
   DeclUpdates[D].push_back(Decl<wbr>Update(UPD_CXX_ADDED_FUNCTION_<wbr>DEFINITION));<br>
 }<br>
<br>
-void ASTWriter::StaticDataMemberIns<wbr>tantiated(const VarDecl *D) {<br>
+void ASTWriter::InstantiationReques<wbr>ted(const ValueDecl *D) {<br>
   if (Chain && Chain->isProcessingUpdateRecor<wbr>ds()) return;<br>
   assert(!WritingAST && "Already writing the AST!");<br>
   if (!D->isFromASTFile())<br>
@@ -6273,9 +6286,12 @@ void ASTWriter::StaticDataMemberIns<wbr>tanti<br>
<br>
   // Since the actual instantiation is delayed, this really means that we need<br>
   // to update the instantiation location.<br>
-  DeclUpdates[D].push_back(<br>
-      DeclUpdate(UPD_CXX_INSTANTIATE<wbr>D_STATIC_DATA_MEMBER,<br>
-       D->getMemberSpecializationInf<wbr>o()->getPointOfInstantiation()<wbr>));<br>
+  SourceLocation POI;<br>
+  if (auto *VD = dyn_cast<VarDecl>(D))<br>
+    POI = VD->getPointOfInstantiation();<br>
+  else<br>
+    POI = cast<FunctionDecl>(D)->getPoin<wbr>tOfInstantiation();<br>
+  DeclUpdates[D].push_back(DeclU<wbr>pdate(UPD_CXX_POINT_OF_INSTANT<wbr>IATION, POI));<br>
 }<br>
<br>
 void ASTWriter::DefaultArgumentInst<wbr>antiated(const ParmVarDecl *D) {<br>
<br>
Added: cfe/trunk/test/Modules/var-tem<wbr>plates.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/var-templates.cpp?rev=319727&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-pr<wbr>oject/cfe/trunk/test/Modules/<wbr>var-templates.cpp?rev=319727&<wbr>view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Modules/var-tem<wbr>plates.cpp (added)<br>
+++ cfe/trunk/test/Modules/var-tem<wbr>plates.cpp Mon Dec  4 17:31:47 2017<br>
@@ -0,0 +1,24 @@<br>
+// RUN: %clang_cc1 -fmodules -std=c++14 -emit-llvm %s -o - | FileCheck %s<br>
+<br>
+#pragma clang module build A<br>
+module A {}<br>
+#pragma clang module contents<br>
+#pragma clang module begin A<br>
+template<int> int n = 42;<br>
+decltype(n<0>) f();<br>
+#pragma clang module end<br>
+#pragma clang module endbuild<br>
+<br>
+#pragma clang module build B<br>
+module B {}<br>
+#pragma clang module contents<br>
+#pragma clang module begin B<br>
+#pragma clang module import A<br>
+inline int f() { return n<0>; }<br>
+#pragma clang module end<br>
+#pragma clang module endbuild<br>
+<br>
+#pragma clang module import B<br>
+<br>
+// CHECK: @_Z1nILi0EE = linkonce_odr global i32 42, comdat<br>
+int g() { return f(); }<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>
</div></div><br>______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
<br></blockquote></div><br></div>