aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-15 02:42:50 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-15 02:42:50 +0000
commit37ce0104b182c9410cf2a76fe5a63a81dac876ac (patch)
tree7ae01b946200267b82d4c58b27551bd75cd5dce1
parent83587db1bda97f45d2b5a4189e584e2a18be511a (diff)
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
-rw-r--r--lib/Sema/SemaExpr.cpp24
-rw-r--r--test/SemaTemplate/constexpr-instantiate.cpp8
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<typename T> struct S { static const int k; };
+ const int n = S<int>::k; // expected-note {{here}}
+ template<typename T> const int S<T>::k = 0;
+ constexpr int m = S<int>::k; // ok
+ constexpr int o = n; // expected-error {{constant expression}} expected-note {{initializer of 'n'}}
+}