mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 03:56:16 +08:00
Testing and some minor fixes for explicit template instantiation.
llvm-svn: 84129
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
10
clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
Normal file
10
clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
Normal 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
|
||||
89
clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp
Normal file
89
clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp
Normal 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}}
|
||||
Reference in New Issue
Block a user