]> granicus.if.org Git - clang/commitdiff
variable templates updated for PCH serialization... Still working on test cases...
authorLarisse Voufo <lvoufo@google.com>
Tue, 13 Aug 2013 02:02:26 +0000 (02:02 +0000)
committerLarisse Voufo <lvoufo@google.com>
Tue, 13 Aug 2013 02:02:26 +0000 (02:02 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188249 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclTemplate.h
lib/AST/DeclTemplate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/PCH/cxx1y-variable-templates.cpp [new file with mode: 0644]
test/SemaCXX/cxx1y-variable-templates_top_level.cpp

index 292d4f3327ce280716b4bb4fdde8b4556a958b75..9de98bb9ca0e82015d160f7ecd4bb3bec4631cee 100644 (file)
@@ -2722,6 +2722,8 @@ public:
     return getTemplatedDecl()->isThisDeclarationADefinition();
   }
 
+  VarTemplateDecl *getDefinition();
+
   /// \brief Create a variable template node.
   static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC,
                                  SourceLocation L, DeclarationName Name,
index 6e734a18c7598b9ba77fc3b9ed64cdd3f281e9cc..0b0228869efc013c92c262d0aaa7a68a1024e5a2 100644 (file)
@@ -963,6 +963,16 @@ void VarTemplateDecl::DeallocateCommon(void *Ptr) {
   static_cast<Common *>(Ptr)->~Common();
 }
 
+VarTemplateDecl *VarTemplateDecl::getDefinition() {
+  VarTemplateDecl *CurD = this;
+  while (CurD) {
+    if (CurD->isThisDeclarationADefinition())
+      return CurD;
+    CurD = CurD->getPreviousDecl();
+  }
+  return 0;
+}
+
 VarTemplateDecl *VarTemplateDecl::Create(ASTContext &C, DeclContext *DC,
                                          SourceLocation L, DeclarationName Name,
                                          TemplateParameterList *Params,
index 315a405c6d3f7bba3e3c161d4861e86c51500b11..5766afa1011cf7a85b83cfb15745d017a91866cc 100644 (file)
@@ -3481,11 +3481,22 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
     llvm::PointerUnion<VarTemplateDecl *,
                        VarTemplatePartialSpecializationDecl *> PatternPtr =
         VarSpec->getSpecializedTemplateOrPartial();
-    if (PatternPtr.is<VarTemplatePartialSpecializationDecl *>())
+    if (PatternPtr.is<VarTemplatePartialSpecializationDecl *>()) {
       PatternDecl = cast<VarDecl>(
           PatternPtr.get<VarTemplatePartialSpecializationDecl *>());
-    else
-      PatternDecl = (PatternPtr.get<VarTemplateDecl *>())->getTemplatedDecl();
+
+      // Find actual definition
+      if (VarDecl *Def = PatternDecl->getDefinition(getASTContext()))
+        PatternDecl = Def;
+    } else {
+      VarTemplateDecl *PatternTemplate = PatternPtr.get<VarTemplateDecl *>();
+
+      // Find actual definition
+      if (VarTemplateDecl *Def = PatternTemplate->getDefinition())
+        PatternTemplate = Def;
+
+      PatternDecl = PatternTemplate->getTemplatedDecl();
+    }
     assert(PatternDecl && "instantiating a non-template");
   }
 
index 60acbc585ba2910e2dcb89eeb16663f17631c412..bb7fd1edf6e2b1727dec061ca9171877f8933c42 100644 (file)
@@ -735,6 +735,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
       D->getInitStyle() == VarDecl::CInit &&
       D->getInit() == 0 &&
       !isa<ParmVarDecl>(D) &&
+      !isa<VarTemplateSpecializationDecl>(D) &&
       !D->isConstexpr() &&
       !SpecInfo)
     AbbrevToUse = Writer.getDeclVarAbbrev();
diff --git a/test/PCH/cxx1y-variable-templates.cpp b/test/PCH/cxx1y-variable-templates.cpp
new file mode 100644 (file)
index 0000000..8bc2129
--- /dev/null
@@ -0,0 +1,172 @@
+// No PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s -DNONPCH
+// RUN: %clang_cc1 -pedantic -std=c++1y -include %s -include %s -verify %s -DNONPCH -DERROR
+//
+// With PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t.a -DHEADER1
+// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.a -emit-pch %s -o %t.b -DHEADER2
+// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t.b -verify %s -DHEADERUSE
+
+#ifndef ERROR
+// expected-no-diagnostics
+#endif
+
+#ifdef NONPCH
+#if !defined(HEADER1)
+#define HEADER1
+#undef HEADER2
+#undef HEADERUSE
+#elif !defined(HEADER2)
+#define HEADER2
+#undef HEADERUSE
+#else
+#define HEADERUSE
+#undef HEADER1
+#undef HEADER2
+#endif
+#endif
+
+
+// *** HEADER1: First header file
+#if defined(HEADER1) && !defined(HEADER2) && !defined(HEADERUSE)
+
+template<typename T> T var0a = T();
+template<typename T> extern T var0b;
+
+namespace join {
+  template<typename T> T va = T(100);
+  template<typename T> extern T vb;
+
+  namespace diff_types {
+#ifdef ERROR
+    template<typename T> extern float err0;
+    template<typename T> extern T err1;
+#endif
+    template<typename T> extern T def;
+  }
+
+}
+
+namespace spec {
+  template<typename T> constexpr T va = T(10);
+  template<> constexpr float va<float> = 1.5;
+  template constexpr int va<int>;
+
+  template<typename T> T vb = T();
+  template<> constexpr float vb<float> = 1.5;
+
+  template<typename T> T vc = T();
+
+  template<typename T> constexpr T vd = T(10);
+  template<typename T> T* vd<T> = new T();
+}
+
+namespace spec_join1 {
+  template<typename T> T va = T(10);
+  template<> extern float va<float>;
+  extern template int va<int>;
+
+  template<typename T> T vb = T(10);
+  template<> extern float vb<float>;
+
+  template<typename T> T vc = T(10);
+
+  template<typename T> T vd = T(10);
+  template<typename T> extern T* vd<T>;
+}
+
+#endif
+
+
+// *** HEADER2: Second header file -- including HEADER1
+#if defined(HEADER2) && !defined(HEADERUSE)
+
+namespace join {
+  template<typename T> extern T va;
+  template<> constexpr float va<float> = 2.5;
+
+  template<typename T> T vb = T(100);
+
+  namespace diff_types {
+#ifdef ERROR
+    template<typename T> extern T err0; // expected-error {{redefinition of 'err0' with a different type: 'T' vs 'float'}}  // expected-note@42 {{previous definition is here}}
+    template<typename T> extern float err1; // expected-error {{redefinition of 'err1' with a different type: 'float' vs 'T'}} // expected-note@43 {{previous definition is here}}
+#endif
+    template<typename T> extern T def;
+  }
+}
+
+namespace spec_join1 {
+  template<typename T> extern T va;
+  template<> float va<float> = 1.5;
+  extern template int va<int>;
+  
+  template<> float vb<float> = 1.5;
+  template int vb<int>;
+
+  template<> float vc<float> = 1.5;
+  template int vc<int>;
+  
+  template<typename T> extern T vd;
+  template<typename T> T* vd<T> = new T();
+}
+
+#endif
+
+// *** HEADERUSE: File using both header files -- including HEADER2
+#ifdef HEADERUSE
+
+template int var0a<int>;
+float fvara = var0a<float>;
+
+template<typename T> extern T var0a; 
+
+template<typename T> T var0b = T(); 
+template int var0b<int>;
+float fvarb = var0b<float>;
+
+namespace join {
+  template const int va<const int>;
+  template<> const int va<int> = 50;
+  static_assert(va<float> == 2.5, "");
+  static_assert(va<int> == 50, "");
+
+  template<> constexpr float vb<float> = 2.5;
+  template const int vb<const int>;
+  static_assert(vb<float> == 2.5, "");
+  static_assert(vb<const int> == 100, "");
+
+  namespace diff_types {
+    template<typename T> T def = T();
+  }
+
+}
+
+namespace spec {
+  static_assert(va<float> == 1.5, "");
+  static_assert(va<int> == 10, "");
+
+  template<typename T> T* vb<T> = new T();
+  int* intpb = vb<int>;
+  static_assert(vb<float> == 1.5, "");
+
+  template<typename T> T* vc<T> = new T();
+  template<> constexpr float vc<float> = 1.5;
+  int* intpc = vc<int>;
+  static_assert(vc<float> == 1.5, "");
+
+  char* intpd = vd<char>;
+}
+
+namespace spec_join1 {
+  template int va<int>;
+  int a = va<int>;
+
+  template<typename T> extern T vb;
+  int b = vb<int>;
+
+  int* intpb = vd<int>;
+}
+
+
+#endif
index 66ee4e1d4ab6e84e216038499f8c3a5e5b51e59c..dc721ce10fd44dca324cd3d2d1662a1cd70a28a2 100644 (file)
@@ -14,6 +14,11 @@ T pi = T(3.1415926535897932385); // expected-note {{template is declared here}}
 template<typename T> 
 CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}}
 
+template<typename T> extern CONST T vc;
+#ifdef CXX11
+// expected-error@-2 {{constexpr variable declaration must be a definition}}
+#endif
+
 namespace use_in_top_level_funcs {
 
   void good() {