Testing and some minor fixes for explicit template instantiation.

llvm-svn: 84129
This commit is contained in:
Douglas Gregor
2009-10-14 20:14:33 +00:00
parent a39f121155
commit 3c74d41d27
11 changed files with 131 additions and 11 deletions

View File

@@ -174,7 +174,7 @@ class ASTContext {
/// This mapping will contain an entry that maps from the VarDecl for
/// X<int>::value to the corresponding VarDecl for X<T>::value (within the
/// class template X) and will be marked TSK_ImplicitInstantiation.
llvm::DenseMap<VarDecl *, MemberSpecializationInfo *>
llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>
InstantiatedFromStaticDataMember;
/// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls
@@ -267,7 +267,8 @@ public:
/// \brief If this variable is an instantiated static data member of a
/// class template specialization, returns the templated static data member
/// from which it was instantiated.
MemberSpecializationInfo *getInstantiatedFromStaticDataMember(VarDecl *Var);
MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
const VarDecl *Var);
/// \brief Note that the static data member \p Inst is an instantiation of
/// the static data member template \p Tmpl of a class template.

View File

@@ -591,7 +591,7 @@ public:
/// \brief If this variable is a static data member, determine what kind of
/// template specialization or instantiation this is.
TemplateSpecializationKind getTemplateSpecializationKind();
TemplateSpecializationKind getTemplateSpecializationKind() const;
/// \brief If this variable is an instantiation of a static data member of a
/// class template specialization, retrieves the member specialization

View File

@@ -1104,7 +1104,9 @@ def err_explicit_instantiation_ambiguous : Error<
"partial ordering for explicit instantiation of %0 is ambiguous">;
def note_explicit_instantiation_candidate : Note<
"explicit instantiation candidate function template here %0">;
def err_explicit_instantiation_inline : Error<
"explicit instantiation cannot be 'inline'">;
// C++ typename-specifiers
def err_typename_nested_not_found : Error<"no type named %0 in %1">;
def err_typename_nested_not_type : Error<

View File

@@ -233,9 +233,9 @@ void ASTContext::InitBuiltinTypes() {
}
MemberSpecializationInfo *
ASTContext::getInstantiatedFromStaticDataMember(VarDecl *Var) {
ASTContext::getInstantiatedFromStaticDataMember(const VarDecl *Var) {
assert(Var->isStaticDataMember() && "Not a static data member");
llvm::DenseMap<VarDecl *, MemberSpecializationInfo *>::iterator Pos
llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *>::iterator Pos
= InstantiatedFromStaticDataMember.find(Var);
if (Pos == InstantiatedFromStaticDataMember.end())
return 0;

View File

@@ -380,7 +380,7 @@ VarDecl *VarDecl::getInstantiatedFromStaticDataMember() {
return 0;
}
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() {
TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const {
if (MemberSpecializationInfo *MSI
= getASTContext().getInstantiatedFromStaticDataMember(this))
return MSI->getTemplateSpecializationKind();

View File

@@ -1836,7 +1836,7 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
if (RD->isAbstract())
AbstractClassUsageDiagnoser(*this, RD);
if (!RD->isDependentType())
if (!RD->isDependentType() && !RD->isInvalidDecl())
AddImplicitlyDeclaredMembersToClass(RD);
}

View File

@@ -3647,6 +3647,19 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return true;
}
// C++0x [temp.explicit]p1:
// [...] An explicit instantiation of a function template shall not use the
// inline or constexpr specifiers.
// Presumably, this also applies to member functions of class templates as
// well.
if (D.getDeclSpec().isInlineSpecified() && getLangOptions().CPlusPlus0x)
Diag(D.getDeclSpec().getInlineSpecLoc(),
diag::err_explicit_instantiation_inline)
<< CodeModificationHint::CreateRemoval(
SourceRange(D.getDeclSpec().getInlineSpecLoc()));
// FIXME: check for constexpr specifier.
// Determine what kind of explicit instantiation we have.
TemplateSpecializationKind TSK
= ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition

View File

@@ -808,9 +808,12 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
ActOnFields(0, Instantiation->getLocation(), DeclPtrTy::make(Instantiation),
Fields.data(), Fields.size(), SourceLocation(), SourceLocation(),
0);
if (Instantiation->isInvalidDecl())
Invalid = true;
// Add any implicitly-declared members that we might need.
AddImplicitlyDeclaredMembersToClass(Instantiation);
if (!Invalid)
AddImplicitlyDeclaredMembersToClass(Instantiation);
// Exit the scope of this instantiation.
CurContext = PreviousContext;

View File

@@ -246,8 +246,10 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
D->getTypeSpecStartLoc(),
D->getAccess(),
0);
if (!Field)
if (!Field) {
cast<Decl>(Owner)->setInvalidDecl();
return 0;
}
if (Invalid)
Field->setInvalidDecl();

View File

@@ -0,0 +1,10 @@
// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s
template<typename T>
struct X {
void f();
};
template inline void X<int>::f(); // expected-error{{'inline'}}
// FIXME: test constexpr

View File

@@ -0,0 +1,89 @@
// RUN: clang-cc -fsyntax-only -verify %s
struct C { };
template<typename T>
struct X0 {
T value; // expected-error{{incomplete}}
};
// Explicitly instantiate a class template specialization
template struct X0<int>;
template struct X0<void>; // expected-note{{instantiation}}
// Explicitly instantiate a function template specialization
template<typename T>
void f0(T t) {
++t; // expected-error{{cannot modify}}
}
template void f0(int);
template void f0<long>(long);
template void f0<>(unsigned);
template void f0(int C::*); // expected-note{{instantiation}}
// Explicitly instantiate a member template specialization
template<typename T>
struct X1 {
template<typename U>
struct Inner {
T member1;
U member2; // expected-error{{incomplete}}
};
template<typename U>
void f(T& t, U u) {
t = u; // expected-error{{incompatible}}
}
};
template struct X1<int>::Inner<float>;
template struct X1<int>::Inner<double>;
template struct X1<int>::Inner<void>; // expected-note{{instantiation}}
template void X1<int>::f(int&, float);
template void X1<int>::f<long>(int&, long);
template void X1<int>::f<>(int&, double);
template void X1<int>::f<>(int&, int*); // expected-note{{instantiation}}
// Explicitly instantiate members of a class template
struct Incomplete; // expected-note{{forward declaration}}
struct NonDefaultConstructible {
NonDefaultConstructible(int);
};
template<typename T, typename U>
struct X2 {
void f(T &t, U u) {
t = u; // expected-error{{incompatible}}
}
struct Inner {
T member1;
U member2; // expected-error{{incomplete}}
};
static T static_member1;
static U static_member2;
};
template<typename T, typename U>
T X2<T, U>::static_member1 = 17; // expected-error{{incompatible type}}
template<typename T, typename U>
U X2<T, U>::static_member2; // expected-error{{no matching}}
template void X2<int, float>::f(int &, float);
template void X2<int, float>::f(int &, double); // expected-error{{does not refer}}
template void X2<int, int*>::f(int&, int*); // expected-note{{instantiation}}
template struct X2<int, float>::Inner;
template struct X2<int, Incomplete>::Inner; // expected-note{{instantiation}}
template int X2<int, float>::static_member1;
template int* X2<int*, float>::static_member1; // expected-note{{instantiation}}
template
NonDefaultConstructible X2<NonDefaultConstructible, int>::static_member1;
template
NonDefaultConstructible X2<int, NonDefaultConstructible>::static_member2; // expected-note{{instantiation}}