[cfe-commits] r112037 - in /cfe/trunk: lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/temp/temp.spec/temp.explicit/p3.cpp test/CodeGenCXX/explicit-instantiation.cpp
Chandler Carruth
chandlerc at gmail.com
Wed Aug 25 01:27:02 PDT 2010
Author: chandlerc
Date: Wed Aug 25 03:27:02 2010
New Revision: 112037
URL: http://llvm.org/viewvc/llvm-project?rev=112037&view=rev
Log:
Support explicit instantiation of function templates and members of class
templates when only the declaration is in scope. This requires deferring the
instantiation to be lazy, and ensuring the definition is required for that
translation unit. We re-use the existing pending instantiation queue,
previously only used to track implicit instantiations which were required to be
lazy. Fixes PR7979.
A subsequent change will rename *PendingImplicitInstantiations to
*PendingInstatiations for clarity given its broader role.
Modified:
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=112037&r1=112036&r2=112037&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Aug 25 03:27:02 2010
@@ -5071,8 +5071,7 @@
// Instantiate static data member.
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false,
- /*DefinitionRequired=*/true);
+ InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev);
// FIXME: Create an ExplicitInstantiation node?
return (Decl*) 0;
@@ -5179,8 +5178,7 @@
Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization,
- false, /*DefinitionRequired=*/true);
+ InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization);
// C++0x [temp.explicit]p2:
// If the explicit instantiation is for a member function, a member class
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=112037&r1=112036&r2=112037&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Aug 25 03:27:02 2010
@@ -2040,8 +2040,12 @@
Diag(PatternDecl->getLocation(),
diag::note_explicit_instantiation_here);
Function->setInvalidDecl();
+ } else if (Function->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDefinition) {
+ PendingImplicitInstantiations.push_back(
+ std::make_pair(Function, PointOfInstantiation));
}
-
+
return;
}
@@ -2176,8 +2180,12 @@
diag::err_explicit_instantiation_undefined_member)
<< 2 << Var->getDeclName() << Var->getDeclContext();
Diag(Def->getLocation(), diag::note_explicit_instantiation_here);
- }
-
+ } else if (Var->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDefinition) {
+ PendingImplicitInstantiations.push_back(
+ std::make_pair(Var, PointOfInstantiation));
+ }
+
return;
}
@@ -2714,8 +2722,10 @@
Function->getLocation(), *this,
Context.getSourceManager(),
"instantiating function definition");
-
- InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true);
+ bool DefinitionRequired = Function->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+ InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true,
+ DefinitionRequired);
continue;
}
@@ -2734,9 +2744,12 @@
case TSK_Undeclared:
assert(false && "Cannot instantitiate an undeclared specialization.");
case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
case TSK_ExplicitSpecialization:
- continue; // No longer need implicit instantiation.
+ continue; // No longer need to instantiate this type.
+ case TSK_ExplicitInstantiationDefinition:
+ // We only need an instantiation if the pending instantiation *is* the
+ // explicit instantiation.
+ if (Var != Var->getMostRecentDeclaration()) continue;
case TSK_ImplicitInstantiation:
break;
}
@@ -2746,7 +2759,10 @@
"instantiating static data member "
"definition");
- InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true);
+ bool DefinitionRequired = Var->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+ InstantiateStaticDataMemberDefinition(/*FIXME:*/Inst.second, Var, true,
+ DefinitionRequired);
}
}
Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp?rev=112037&r1=112036&r2=112037&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.explicit/p3.cpp Wed Aug 25 03:27:02 2010
@@ -2,8 +2,9 @@
// A declaration of a function template shall be in scope at the point of the
// explicit instantiation of the function template.
-template<typename T> void f0(T) { }
+template<typename T> void f0(T);
template void f0(int); // okay
+template<typename T> void f0(T) { }
// A definition of the class or class template containing a member function
// template shall be in scope at the point of the explicit instantiation of
@@ -47,3 +48,27 @@
template X2<int>::X2(const X2&); // expected-error{{not an instantiation}}
template X2<int>::~X2(); // expected-error{{not an instantiation}}
template X2<int> &X2<int>::operator=(const X2<int>&); // expected-error{{not an instantiation}}
+
+
+// A definition of a class template is sufficient to explicitly
+// instantiate a member of the class template which itself is not yet defined.
+namespace PR7979 {
+ template <typename T> struct S {
+ void f();
+ static void g();
+ static int i;
+ struct S2 {
+ void h();
+ };
+ };
+
+ template void S<int>::f();
+ template void S<int>::g();
+ template int S<int>::i;
+ template void S<int>::S2::h();
+
+ template <typename T> void S<T>::f() {}
+ template <typename T> void S<T>::g() {}
+ template <typename T> int S<T>::i;
+ template <typename T> void S<T>::S2::h() {}
+}
Modified: cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp?rev=112037&r1=112036&r2=112037&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp Wed Aug 25 03:27:02 2010
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o - %s | FileCheck %s
+// This check logically is attached to 'template int S<int>::i;' below.
+// CHECK: @_ZN1SIiE1iE = weak global i32
+
template<typename T, typename U, typename Result>
struct plus {
Result operator()(const T& t, const U& u) const;
@@ -12,3 +15,31 @@
// CHECK: define weak_odr i32 @_ZNK4plusIillEclERKiRKl
template struct plus<int, long, long>;
+
+// Check that we emit definitions from explicit instantiations even when they
+// occur prior to the definition itself.
+template <typename T> struct S {
+ void f();
+ static void g();
+ static int i;
+ struct S2 {
+ void h();
+ };
+};
+
+// CHECK: define weak_odr void @_ZN1SIiE1fEv
+template void S<int>::f();
+
+// CHECK: define weak_odr void @_ZN1SIiE1gEv
+template void S<int>::g();
+
+// See the check line at the top of the file.
+template int S<int>::i;
+
+// CHECK: define weak_odr void @_ZN1SIiE2S21hEv
+template void S<int>::S2::h();
+
+template <typename T> void S<T>::f() {}
+template <typename T> void S<T>::g() {}
+template <typename T> int S<T>::i;
+template <typename T> void S<T>::S2::h() {}
More information about the cfe-commits
mailing list