diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9829,14 +9829,21 @@ /// eagerly. SmallVector LateParsedInstantiations; + SmallVector, 8> SavedVTableUses; + SmallVector, 8> + SavedPendingInstantiations; + class GlobalEagerInstantiationScope { public: GlobalEagerInstantiationScope(Sema &S, bool Enabled) : S(S), Enabled(Enabled) { if (!Enabled) return; - SavedPendingInstantiations.swap(S.PendingInstantiations); - SavedVTableUses.swap(S.VTableUses); + S.SavedPendingInstantiations.emplace_back(); + S.SavedPendingInstantiations.back().swap(S.PendingInstantiations); + + S.SavedVTableUses.emplace_back(); + S.SavedVTableUses.back().swap(S.VTableUses); } void perform() { @@ -9852,26 +9859,28 @@ // Restore the set of pending vtables. assert(S.VTableUses.empty() && "VTableUses should be empty before it is discarded."); - S.VTableUses.swap(SavedVTableUses); + S.VTableUses.swap(S.SavedVTableUses.back()); + S.SavedVTableUses.pop_back(); // Restore the set of pending implicit instantiations. if (S.TUKind != TU_Prefix || !S.LangOpts.PCHInstantiateTemplates) { assert(S.PendingInstantiations.empty() && "PendingInstantiations should be empty before it is discarded."); - S.PendingInstantiations.swap(SavedPendingInstantiations); + S.PendingInstantiations.swap(S.SavedPendingInstantiations.back()); + S.SavedPendingInstantiations.pop_back(); } else { // Template instantiations in the PCH may be delayed until the TU. - S.PendingInstantiations.swap(SavedPendingInstantiations); - S.PendingInstantiations.insert(S.PendingInstantiations.end(), - SavedPendingInstantiations.begin(), - SavedPendingInstantiations.end()); + S.PendingInstantiations.swap(S.SavedPendingInstantiations.back()); + S.PendingInstantiations.insert( + S.PendingInstantiations.end(), + S.SavedPendingInstantiations.back().begin(), + S.SavedPendingInstantiations.back().end()); + S.SavedPendingInstantiations.pop_back(); } } private: Sema &S; - SmallVector SavedVTableUses; - std::deque SavedPendingInstantiations; bool Enabled; }; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -19897,6 +19897,18 @@ // multiple times. SemaRef.PendingInstantiations .push_back(std::make_pair(Var, PointOfInstantiation)); + } else { + for (auto &I : SemaRef.SavedPendingInstantiations) { + auto Iter = llvm::find_if( + I, [Var](const Sema::PendingImplicitInstantiation &P) { + return P.first == Var; + }); + if (Iter != I.end()) { + SemaRef.PendingInstantiations.push_back(*Iter); + I.erase(Iter); + break; + } + } } } } diff --git a/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp --- a/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp +++ b/clang/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp @@ -29,32 +29,56 @@ // ALL: @_ZN1AIbE1aE ={{.*}} global i32 10 template<> int A::a = 10; -// ALL: @llvm.global_ctors = appending global [8 x { i32, ptr, ptr }] +// ALL: @llvm.global_ctors = appending global [16 x { i32, ptr, ptr }] -// ELF: [{ i32, ptr, ptr } { i32 65535, ptr @[[unordered1:[^,]*]], ptr @_ZN1AIsE1aE }, -// MACHO: [{ i32, ptr, ptr } { i32 65535, ptr @[[unordered1:[^,]*]], ptr null }, +// ELF: [{ i32, ptr, ptr } { i32 65535, ptr @[[unordered:[^,]*]], ptr @_ZN1AIsE1aE }, +// MACHO: [{ i32, ptr, ptr } { i32 65535, ptr @[[unordered:[^,]*]], ptr null }, -// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered2:[^,]*]], ptr @_Z1xIsE }, -// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered2:[^,]*]], ptr null }, +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered7:[^,]*]], ptr @_Z1xIsE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered7:[^,]*]], ptr null }, -// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered3:[^,]*]], ptr @_ZN2ns1aIiE1iE }, -// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered3:[^,]*]], ptr null }, +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered10:[^,]*]], ptr @_ZN2ns1aIiE1iE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered10:[^,]*]], ptr null }, -// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered4:[^,]*]], ptr @_ZN2ns1b1iIiEE }, -// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered4:[^,]*]], ptr null }, +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered11:[^,]*]], ptr @_ZN2ns1b1iIiEE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered11:[^,]*]], ptr null }, -// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered5:[^,]*]], ptr @_ZN1AIvE1aE }, -// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered5:[^,]*]], ptr null }, +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered14:[^,]*]], ptr @_ZN1AIvE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered14:[^,]*]], ptr null }, -// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered6:[^,]*]], ptr @_Z1xIcE }, -// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered6:[^,]*]], ptr null }, +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered15:[^,]*]], ptr @_Z1xIcE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered15:[^,]*]], ptr null }, -// ALL: { i32, ptr, ptr } { i32 65535, ptr @[[unordered7:[^,]*]], ptr null }, +// ALL: { i32, ptr, ptr } { i32 65535, ptr @[[unordered16:[^,]*]], ptr null }, + +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered19:[^,]*]], ptr @_ZN3FibILi2EE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered19:[^,]*]], ptr null }, + +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered18:[^,]*]], ptr @_ZN3FibILi3EE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered18:[^,]*]], ptr null }, + +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered20:[^,]*]], ptr @_ZN3FibILi4EE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered20:[^,]*]], ptr null }, + +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered17:[^,]*]], ptr @_ZN3FibILi5EE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered17:[^,]*]], ptr null }, + +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered23:[^,]*]], ptr @_ZN4Fib2ILi2EE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered23:[^,]*]], ptr null }, + +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered24:[^,]*]], ptr @_ZN4Fib2ILi3EE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered24:[^,]*]], ptr null }, + +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered22:[^,]*]], ptr @_ZN4Fib2ILi4EE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered22:[^,]*]], ptr null }, + +// ELF: { i32, ptr, ptr } { i32 65535, ptr @[[unordered21:[^,]*]], ptr @_ZN4Fib2ILi5EE1aE }, +// MACHO: { i32, ptr, ptr } { i32 65535, ptr @[[unordered21:[^,]*]], ptr null }, // ALL: { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp, ptr null }] /// llvm.used ensures SHT_INIT_ARRAY in a section group cannot be GCed. -// ELF: @llvm.used = appending global [6 x ptr] [ptr @_ZN1AIsE1aE, ptr @_Z1xIsE, ptr @_ZN2ns1aIiE1iE, ptr @_ZN2ns1b1iIiEE, ptr @_ZN1AIvE1aE, ptr @_Z1xIcE] +// ELF: @llvm.used = appending global [14 x ptr] [ptr @_ZN1AIsE1aE, ptr @_Z1xIsE, ptr @_ZN2ns1aIiE1iE, ptr @_ZN2ns1b1iIiEE, ptr @_ZN1AIvE1aE, ptr @_Z1xIcE, ptr @_ZN3FibILi5EE1aE, ptr @_ZN3FibILi3EE1aE, ptr @_ZN3FibILi2EE1aE, ptr @_ZN3FibILi4EE1aE, ptr @_ZN4Fib2ILi5EE1aE, ptr @_ZN4Fib2ILi4EE1aE, ptr @_ZN4Fib2ILi2EE1aE, ptr @_ZN4Fib2ILi3EE1aE] template int A::a; // Unordered int b = foo(); @@ -94,43 +118,82 @@ } int *use_internal_a = &Internal::a; +template struct Fib { static int a; }; +template<> int Fib<0>::a = 0; +template<> int Fib<1>::a = 1; +template int Fib::a = Fib::a + Fib::a; +int f = Fib<5>::a; + +template struct Fib2 { static int a; }; +template<> int Fib2<0>::a = 0; +template<> int Fib2<1>::a = 1; +template int Fib2::a = Fib2::a + Fib2::a; +int f2 = Fib2<5>::a; + #endif -// ALL: define internal void @[[unordered1]]( +// ALL: define internal void @[[unordered]]( // ALL: call i32 @foo() // ALL: store {{.*}} @_ZN1AIsE1aE // ALL: ret -// ALL: define internal void @[[unordered2]]( +// ALL: define internal void @[[unordered7]]( // ALL: call i32 @foo() // ALL: store {{.*}} @_Z1xIsE // ALL: ret -// ALL: define internal void @[[unordered3]]( +// ALL: define internal void @[[unordered10]]( // ALL: call i32 @foo() // ALL: store {{.*}} @_ZN2ns1aIiE1iE // ALL: ret -// ALL: define internal void @[[unordered4]]( +// ALL: define internal void @[[unordered11]]( // ALL: call i32 @foo() // ALL: store {{.*}} @_ZN2ns1b1iIiEE // ALL: ret -// ALL: define internal void @[[unordered5]]( -// ALL: call i32 @foo() -// ALL: store {{.*}} @_ZN1AIvE1aE -// ALL: ret - -// ALL: define internal void @[[unordered6]]( +// ALL: define internal void @[[unordered15]]( // ALL: call i32 @foo() // ALL: store {{.*}} @_Z1xIcE // ALL: ret -// ALL: define internal void @[[unordered7]]( +// ALL: define internal void @[[unordered16]]( // ALL: call i32 @foo() // ALL: store {{.*}} @_ZN12_GLOBAL__N_18InternalIiE1aE // ALL: ret +// ALL: define internal void @[[unordered17]]( +// ALL: store {{.*}} @_ZN3FibILi5EE1aE +// ALL: ret + +// ALL: define internal void @[[unordered18]]( +// ALL: store {{.*}} @_ZN3FibILi3EE1aE +// ALL: ret + +// ALL: define internal void @[[unordered19]]( +// ALL: store {{.*}} @_ZN3FibILi2EE1aE +// ALL: ret + +// ALL: define internal void @[[unordered20]]( +// ALL: store {{.*}} @_ZN3FibILi4EE1aE +// ALL: ret + +// ALL: define internal void @[[unordered21]]( +// ALL: store {{.*}} @_ZN4Fib2ILi5EE1aE +// ALL: ret + +// ALL: define internal void @[[unordered22]]( +// ALL: store {{.*}} @_ZN4Fib2ILi4EE1aE +// ALL: ret + +// ALL: define internal void @[[unordered23]]( +// ALL: store {{.*}} @_ZN4Fib2ILi2EE1aE +// ALL: ret + +// ALL: define internal void @[[unordered24]]( +// ALL: store {{.*}} @_ZN4Fib2ILi3EE1aE +// ALL: ret + // ALL: define internal void @_GLOBAL__sub_I_static_member_variable_explicit_specialization.cpp() // We call unique stubs for every ordered dynamic initializer in the TU. // ALL: call @@ -141,5 +204,7 @@ // ALL: call // ALL: call // ALL: call +// ALL: call +// ALL: call // ALL-NOT: call // ALL: ret