From: Douglas Gregor Date: Fri, 3 Jun 2011 14:28:43 +0000 (+0000) Subject: Improve the instantiation of static data members in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=36f255c324d37dd8e0e5ab2e026814e8396a05aa;p=clang Improve the instantiation of static data members in Sema::RequireCompleteExprType() a bit more, setting the point of instantiation if needed, and skipping explicit specializations entirely. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@132547 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 02bcb2b89e..3c4e09ae86 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -15,6 +15,7 @@ #include "clang/Sema/Template.h" #include "clang/Basic/OpenCL.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" @@ -3277,14 +3278,31 @@ bool Sema::RequireCompleteExprType(Expr *E, const PartialDiagnostic &PD, if (VarDecl *Var = dyn_cast(DRE->getDecl())) { if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) { - InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var); - // Update the type to the newly instantiated definition's type both - // here and within the expression. - if (VarDecl *Def = Var->getDefinition()) { - DRE->setDecl(Def); - T = Def->getType(); - DRE->setType(T); - E->setType(T); + + MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); + assert(MSInfo && "Missing member specialization information?"); + if (MSInfo->getTemplateSpecializationKind() + != TSK_ExplicitSpecialization) { + // If we don't already have a point of instantiation, this is it. + if (MSInfo->getPointOfInstantiation().isInvalid()) { + MSInfo->setPointOfInstantiation(E->getLocStart()); + + // This is a modification of an existing AST node. Notify + // listeners. + if (ASTMutationListener *L = getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); + } + + InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var); + + // Update the type to the newly instantiated definition's type both + // here and within the expression. + if (VarDecl *Def = Var->getDefinition()) { + DRE->setDecl(Def); + T = Def->getType(); + DRE->setType(T); + E->setType(T); + } } // We still go on to try to complete the type independently, as it diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp index ce2c1633b1..f0ca9a5b21 100644 --- a/test/SemaTemplate/instantiate-init.cpp +++ b/test/SemaTemplate/instantiate-init.cpp @@ -78,21 +78,32 @@ namespace PR7985 { template struct integral_c { }; template - integral_c array_lengthof(T (&x)[N]) { return integral_c(); } + integral_c array_lengthof(T (&x)[N]) { return integral_c(); } // expected-note 2{{candidate template ignored: failed template argument deduction}} + template struct Data { - int x; + T x; }; template struct Description { - static const Data data[]; + static const Data data[]; }; template - const Data Description::data[] = {{ 0 }}; + const Data Description::data[] = {{ 1 }}; // expected-error{{cannot initialize a member subobject of type 'int *' with an rvalue of type 'int'}} + + template<> + Data Description::data[]; void test() { integral_c<1> ic1 = array_lengthof(Description::data); + (void)sizeof(array_lengthof(Description::data)); + + sizeof(array_lengthof( // expected-error{{no matching function for call to 'array_lengthof'}} + Description::data // expected-note{{in instantiation of static data member 'PR7985::Description::data' requested here}} + )); + + array_lengthof(Description::data); // expected-error{{no matching function for call to 'array_lengthof'}} } }