From: Larisse Voufo Date: Tue, 13 Aug 2013 02:02:26 +0000 (+0000) Subject: variable templates updated for PCH serialization... Still working on test cases... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=439d665f4d1066ee5ebd8dd0938d85be83d490c4;p=clang variable templates updated for PCH serialization... Still working on test cases... git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188249 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 292d4f3327..9de98bb9ca 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -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, diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 6e734a18c7..0b0228869e 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -963,6 +963,16 @@ void VarTemplateDecl::DeallocateCommon(void *Ptr) { static_cast(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, diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 315a405c6d..5766afa101 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3481,11 +3481,22 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, llvm::PointerUnion PatternPtr = VarSpec->getSpecializedTemplateOrPartial(); - if (PatternPtr.is()) + if (PatternPtr.is()) { PatternDecl = cast( PatternPtr.get()); - else - PatternDecl = (PatternPtr.get())->getTemplatedDecl(); + + // Find actual definition + if (VarDecl *Def = PatternDecl->getDefinition(getASTContext())) + PatternDecl = Def; + } else { + VarTemplateDecl *PatternTemplate = PatternPtr.get(); + + // Find actual definition + if (VarTemplateDecl *Def = PatternTemplate->getDefinition()) + PatternTemplate = Def; + + PatternDecl = PatternTemplate->getTemplatedDecl(); + } assert(PatternDecl && "instantiating a non-template"); } diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 60acbc585b..bb7fd1edf6 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -735,6 +735,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { D->getInitStyle() == VarDecl::CInit && D->getInit() == 0 && !isa(D) && + !isa(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 index 0000000000..8bc2129ebd --- /dev/null +++ b/test/PCH/cxx1y-variable-templates.cpp @@ -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 T var0a = T(); +template extern T var0b; + +namespace join { + template T va = T(100); + template extern T vb; + + namespace diff_types { +#ifdef ERROR + template extern float err0; + template extern T err1; +#endif + template extern T def; + } + +} + +namespace spec { + template constexpr T va = T(10); + template<> constexpr float va = 1.5; + template constexpr int va; + + template T vb = T(); + template<> constexpr float vb = 1.5; + + template T vc = T(); + + template constexpr T vd = T(10); + template T* vd = new T(); +} + +namespace spec_join1 { + template T va = T(10); + template<> extern float va; + extern template int va; + + template T vb = T(10); + template<> extern float vb; + + template T vc = T(10); + + template T vd = T(10); + template extern T* vd; +} + +#endif + + +// *** HEADER2: Second header file -- including HEADER1 +#if defined(HEADER2) && !defined(HEADERUSE) + +namespace join { + template extern T va; + template<> constexpr float va = 2.5; + + template T vb = T(100); + + namespace diff_types { +#ifdef ERROR + template extern T err0; // expected-error {{redefinition of 'err0' with a different type: 'T' vs 'float'}} // expected-note@42 {{previous definition is here}} + template extern float err1; // expected-error {{redefinition of 'err1' with a different type: 'float' vs 'T'}} // expected-note@43 {{previous definition is here}} +#endif + template extern T def; + } +} + +namespace spec_join1 { + template extern T va; + template<> float va = 1.5; + extern template int va; + + template<> float vb = 1.5; + template int vb; + + template<> float vc = 1.5; + template int vc; + + template extern T vd; + template T* vd = new T(); +} + +#endif + +// *** HEADERUSE: File using both header files -- including HEADER2 +#ifdef HEADERUSE + +template int var0a; +float fvara = var0a; + +template extern T var0a; + +template T var0b = T(); +template int var0b; +float fvarb = var0b; + +namespace join { + template const int va; + template<> const int va = 50; + static_assert(va == 2.5, ""); + static_assert(va == 50, ""); + + template<> constexpr float vb = 2.5; + template const int vb; + static_assert(vb == 2.5, ""); + static_assert(vb == 100, ""); + + namespace diff_types { + template T def = T(); + } + +} + +namespace spec { + static_assert(va == 1.5, ""); + static_assert(va == 10, ""); + + template T* vb = new T(); + int* intpb = vb; + static_assert(vb == 1.5, ""); + + template T* vc = new T(); + template<> constexpr float vc = 1.5; + int* intpc = vc; + static_assert(vc == 1.5, ""); + + char* intpd = vd; +} + +namespace spec_join1 { + template int va; + int a = va; + + template extern T vb; + int b = vb; + + int* intpb = vd; +} + + +#endif diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp index 66ee4e1d4a..dc721ce10f 100644 --- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp +++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp @@ -14,6 +14,11 @@ T pi = T(3.1415926535897932385); // expected-note {{template is declared here}} template CONST T cpi = T(3.1415926535897932385); // expected-note {{template is declared here}} +template 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() {