From 37ce0104b182c9410cf2a76fe5a63a81dac876ac Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 15 Feb 2012 02:42:50 +0000 Subject: [PATCH] If a static data member of a class template which could be used in a constant expression is referenced, defined, then referenced again, make sure we instantiate it the second time it's referenced. This is the static data member analogue of r150518. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150560 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 24 ++++++++++++--------- test/SemaTemplate/constexpr-instantiate.cpp | 8 +++++++ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 050386e299..a11cba1bfb 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9988,22 +9988,26 @@ static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, return; // Implicit instantiation of static data members of class templates. - if (Var->isStaticDataMember() && - Var->getInstantiatedFromStaticDataMember()) { + if (Var->isStaticDataMember() && Var->getInstantiatedFromStaticDataMember()) { MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo(); assert(MSInfo && "Missing member specialization information?"); - if (MSInfo->getPointOfInstantiation().isInvalid() && - MSInfo->getTemplateSpecializationKind()== TSK_ImplicitInstantiation) { - MSInfo->setPointOfInstantiation(Loc); - // This is a modification of an existing AST node. Notify listeners. - if (ASTMutationListener *L = SemaRef.getASTMutationListener()) - L->StaticDataMemberInstantiated(Var); + bool AlreadyInstantiated = !MSInfo->getPointOfInstantiation().isInvalid(); + if (MSInfo->getTemplateSpecializationKind() == TSK_ImplicitInstantiation && + (!AlreadyInstantiated || Var->isUsableInConstantExpressions())) { + if (!AlreadyInstantiated) { + // This is a modification of an existing AST node. Notify listeners. + if (ASTMutationListener *L = SemaRef.getASTMutationListener()) + L->StaticDataMemberInstantiated(Var); + MSInfo->setPointOfInstantiation(Loc); + } + SourceLocation PointOfInstantiation = MSInfo->getPointOfInstantiation(); if (Var->isUsableInConstantExpressions()) // Do not defer instantiations of variables which could be used in a // constant expression. - SemaRef.InstantiateStaticDataMemberDefinition(Loc, Var); + SemaRef.InstantiateStaticDataMemberDefinition(PointOfInstantiation,Var); else - SemaRef.PendingInstantiations.push_back(std::make_pair(Var, Loc)); + SemaRef.PendingInstantiations.push_back( + std::make_pair(Var, PointOfInstantiation)); } } diff --git a/test/SemaTemplate/constexpr-instantiate.cpp b/test/SemaTemplate/constexpr-instantiate.cpp index 69ac0e476b..316b088566 100644 --- a/test/SemaTemplate/constexpr-instantiate.cpp +++ b/test/SemaTemplate/constexpr-instantiate.cpp @@ -57,3 +57,11 @@ namespace OverloadResolution { S<4> &k = g(0); int *p, *q = h(p); } + +namespace DataMember { + template struct S { static const int k; }; + const int n = S::k; // expected-note {{here}} + template const int S::k = 0; + constexpr int m = S::k; // ok + constexpr int o = n; // expected-error {{constant expression}} expected-note {{initializer of 'n'}} +} -- 2.40.0