Only notify consumers about static data members of class templates once

llvm-svn: 234675
This commit is contained in:
Reid Kleckner 2015-04-11 01:25:36 +00:00
parent 63ffa21d90
commit 620d0ce55c
2 changed files with 44 additions and 7 deletions

View File

@ -3865,6 +3865,17 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
if (TSK == TSK_ExplicitInstantiationDeclaration)
return;
// We may be explicitly instantiating something we've already implicitly
// instantiated.
VarDecl *InstantiatedDef = Var->getDefinition();
if (InstantiatedDef)
InstantiatedDef->setTemplateSpecializationKind(TSK, PointOfInstantiation);
// If we've already instantiated the definition and we're not
// re-instantiating it explicitly, we don't need to do anything.
if (InstantiatedDef && TSK != TSK_ExplicitInstantiationDefinition)
return;
// Make sure to pass the instantiated variable to the consumer at the end.
struct PassToConsumerRAII {
ASTConsumer &Consumer;
@ -3878,14 +3889,10 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
}
} PassToConsumerRAII(Consumer, Var);
// If we already have a definition, we're done.
if (VarDecl *Def = Var->getDefinition()) {
// We may be explicitly instantiating something we've already implicitly
// instantiated.
Def->setTemplateSpecializationKind(Var->getTemplateSpecializationKind(),
PointOfInstantiation);
// If we already implicitly instantiated this, just let the consumer know that
// it needs to handle an explicit instantiation now.
if (InstantiatedDef && TSK == TSK_ExplicitInstantiationDefinition)
return;
}
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst.isInvalid())

View File

@ -0,0 +1,30 @@
// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
template <typename T>
struct HasStaticInit {
static const int index;
};
int the_count = 0;
template <typename T>
const int HasStaticInit<T>::index = the_count++;
template <typename T> int func_tmpl1() { return HasStaticInit<T>::index; }
template <typename T> int func_tmpl2() { return HasStaticInit<T>::index; }
template <typename T> int func_tmpl3() { return HasStaticInit<T>::index; }
void useit() {
func_tmpl1<int>();
func_tmpl2<int>();
func_tmpl3<int>();
}
// Throw in a final explicit instantiation to see that it doesn't screw things
// up.
template struct HasStaticInit<int>;
// There should only be one entry, not 3.
// CHECK: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }]
// There should only be one update to @the_count.
// CHECK-NOT: store i32 %{{.*}}, i32* @the_count
// CHECK: store i32 %{{.*}}, i32* @the_count
// CHECK-NOT: store i32 %{{.*}}, i32* @the_count