C++ constant expression handling: eagerly instantiate static const integral data
members of class templates so that their values can be used in ICEs. This
required reverting r105465, to get such instantiated members to be included in
serialized ASTs.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147023 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 6543903..3a61fe5 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -9526,7 +9526,12 @@
         // This is a modification of an existing AST node. Notify listeners.
         if (ASTMutationListener *L = getASTMutationListener())
           L->StaticDataMemberInstantiated(Var);
-        PendingInstantiations.push_back(std::make_pair(Var, Loc));
+        QualType T = Var->getType();
+        if (T.isConstQualified() && !T.isVolatileQualified() &&
+            T->isIntegralOrEnumerationType())
+          InstantiateStaticDataMemberDefinition(Loc, Var);
+        else
+          PendingInstantiations.push_back(std::make_pair(Var, Loc));
       }
     }
 
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index b2208b6..53adf68 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -359,8 +359,7 @@
   SemaRef.CheckVariableDeclaration(Var, Previous);
 
   if (D->isOutOfLine()) {
-    if (!D->isStaticDataMember())
-      D->getLexicalDeclContext()->addDecl(Var);
+    D->getLexicalDeclContext()->addDecl(Var);
     Owner->makeDeclVisibleInContext(Var);
   } else {
     Owner->addDecl(Var);
diff --git a/test/PCH/chain-cxx.cpp b/test/PCH/chain-cxx.cpp
index c42ee7d..0d50e61 100644
--- a/test/PCH/chain-cxx.cpp
+++ b/test/PCH/chain-cxx.cpp
@@ -38,9 +38,12 @@
 template <typename T>
 struct TS3 {
   static const int value = 0;
+  static const int value2;
 };
 template <typename T>
 const int TS3<T>::value;
+template <typename T>
+const int TS3<T>::value2 = 1;
 // Instantiate struct, but not value.
 struct instantiate : TS3<int> {};
 
@@ -96,8 +99,9 @@
 struct A { };
 struct B : A { };
 
-// Instantiate TS3's member.
+// Instantiate TS3's members.
 static const int ts3m1 = TS3<int>::value;
+extern int arr[TS3<int>::value2];
 
 // Redefinition of typedef
 typedef int Integer;
@@ -132,6 +136,7 @@
 
 // Should have remembered that there is a definition.
 static const int ts3m2 = TS3<int>::value;
+int arr[TS3<int>::value2];
 
 //===----------------------------------------------------------------------===//
 #endif
diff --git a/test/SemaTemplate/instantiate-declref-ice.cpp b/test/SemaTemplate/instantiate-declref-ice.cpp
index 0f3c08b..49b1b63 100644
--- a/test/SemaTemplate/instantiate-declref-ice.cpp
+++ b/test/SemaTemplate/instantiate-declref-ice.cpp
@@ -31,4 +31,4 @@
 template<typename T>
 const unsigned X1<T>::value = sizeof(T);
 
-int array3[X1<int>::value == sizeof(int)? 1 : -1]; // expected-error{{variable length array declaration not allowed at file scope}}
+int array3[X1<int>::value == sizeof(int)? 1 : -1];