summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ASTContext.h5
-rw-r--r--clang/include/clang/AST/Decl.h2
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/lib/AST/ASTContext.cpp4
-rw-r--r--clang/lib/AST/Decl.cpp2
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp13
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp7
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp4
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp10
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp89
11 files changed, 131 insertions, 11 deletions
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 63f909146e9..106d568c9b2 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -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.
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 7c326dee338..972e1f69007 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -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
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b03676d877e..d799bb52b98 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 85b4fd6d6cc..e028186d46e 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -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;
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 429729ea3b0..a908299bfe0 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -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();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index acb2a677702..419c8a13c2d 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -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);
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index d56b4e114e7..457b219bb06 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -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
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 65260c8e1e6..24b83704eba 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -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;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 33fa28866e5..28c0fa6ab97 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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();
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
new file mode 100644
index 00000000000..becdd6b606b
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
@@ -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
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp
new file mode 100644
index 00000000000..896e30efb88
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp
@@ -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}}
OpenPOWER on IntegriCloud