summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-04-27 06:46:31 +0000
committerJohn McCall <rjmccall@apple.com>2011-04-27 06:46:31 +0000
commit5476666d173861917bab2d35c5402ab4f9bf1672 (patch)
tree926344c53237dbb21486e828ec22d772a274f159
parentda6c89de486300c894a4178848ba02058377f0e9 (diff)
downloadbcm5719-llvm-5476666d173861917bab2d35c5402ab4f9bf1672.tar.gz
bcm5719-llvm-5476666d173861917bab2d35c5402ab4f9bf1672.zip
Diagnose attempts to implicitly instantiate a template before it is
fully defined. Somehow this escaped notice for a very long time. llvm-svn: 130298
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp13
-rw-r--r--clang/test/CXX/class/class.mem/p2.cpp31
-rw-r--r--clang/test/SemaCXX/PR9460.cpp6
-rw-r--r--clang/test/SemaCXX/PR9461.cpp4
5 files changed, 50 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f35d5c4b9bf..9a29ba2be09 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1863,6 +1863,9 @@ def err_template_recursion_depth_exceeded : Error<
def note_template_recursion_depth : Note<
"use -ftemplate-depth-N to increase recursive template instantiation depth">;
+def err_template_instantiate_within_definition : Error<
+ "%select{implicit|explicit}0 instantiation of template %1 within its"
+ " own definition">;
def err_template_instantiate_undefined : Error<
"%select{implicit|explicit}0 instantiation of undefined template %1">;
def err_implicit_instantiate_member_undefined : Error<
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index c951b2573a3..749c4a18a4e 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1650,9 +1650,18 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *PatternDef
= cast_or_null<CXXRecordDecl>(Pattern->getDefinition());
- if (!PatternDef) {
- if (!Complain) {
+ if (!PatternDef || PatternDef->isBeingDefined()) {
+ if (!Complain || (PatternDef && PatternDef->isInvalidDecl())) {
// Say nothing
+ } else if (PatternDef) {
+ assert(PatternDef->isBeingDefined());
+ Diag(PointOfInstantiation,
+ diag::err_template_instantiate_within_definition)
+ << (TSK != TSK_ImplicitInstantiation)
+ << Context.getTypeDeclType(Instantiation);
+ // Not much point in noting the template declaration here, since
+ // we're lexically inside it.
+ Instantiation->setInvalidDecl();
} else if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
Diag(PointOfInstantiation,
diag::err_implicit_instantiate_member_undefined)
diff --git a/clang/test/CXX/class/class.mem/p2.cpp b/clang/test/CXX/class/class.mem/p2.cpp
new file mode 100644
index 00000000000..09040d859c8
--- /dev/null
+++ b/clang/test/CXX/class/class.mem/p2.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// C++11 [class.mem]p2:
+// A class is considered a completely-defined object type (or
+// complete type) at the closing } of the class-specifier. Within
+// the class member-specification, the class is regarded as complete
+// within function bodies, default arguments,
+// exception-specifications, and brace-or-equal-initializers for
+// non-static data members (including such things in nested classes).
+// Otherwise it is regarded as incomplete within its own class
+// member-specification.
+
+namespace test0 {
+ struct A { // expected-note {{definition of 'test0::A' is not complete until the closing '}'}}
+ A x; // expected-error {{field has incomplete type 'test0::A'}}
+ };
+}
+
+namespace test1 {
+ template <class T> struct A {
+ A<int> x; // expected-error {{implicit instantiation of template 'test1::A<int>' within its own definition}}
+ };
+}
+
+namespace test2 {
+ template <class T> struct A;
+ template <> struct A<int> {};
+ template <class T> struct A {
+ A<int> x;
+ };
+}
diff --git a/clang/test/SemaCXX/PR9460.cpp b/clang/test/SemaCXX/PR9460.cpp
index be8dc6eb304..2cc435e495d 100644
--- a/clang/test/SemaCXX/PR9460.cpp
+++ b/clang/test/SemaCXX/PR9460.cpp
@@ -8,11 +8,11 @@ struct basic_string{
basic_string(aT*);
};
-struct runtime_error{
-runtime_error(
+struct runtime_error{ // expected-note {{candidate constructor}}
+ runtime_error( // expected-note {{candidate constructor}}
basic_string<char> struct{ // expected-error {{cannot combine with previous 'type-name' declaration specifier}}
a(){ // expected-error {{requires a type specifier}}
-runtime_error(0);
+ runtime_error(0); // expected-error {{no matching conversion}}
}
}
);
diff --git a/clang/test/SemaCXX/PR9461.cpp b/clang/test/SemaCXX/PR9461.cpp
index e24bd4d35a8..ce17931324e 100644
--- a/clang/test/SemaCXX/PR9461.cpp
+++ b/clang/test/SemaCXX/PR9461.cpp
@@ -26,7 +26,7 @@ basic_string<_CharT,_Traits,_Alloc>::basic_string(const _CharT*,const _Alloc&)
:us(_S_construct)
{string a;}
-struct runtime_error{runtime_error(string);};
+struct runtime_error{runtime_error(string);}; // expected-note 2 {{candidate constructor}}
struct system_error:runtime_error{ // expected-note {{to match}} expected-note {{specified here}}
-system_error():time_error("" // expected-error 4 {{expected}} expected-error {{initializer}} expected-note {{to match}}
+system_error():time_error("" // expected-error 4 {{expected}} expected-error {{initializer}} expected-note {{to match}} expected-error {{no matching constructor}}
OpenPOWER on IntegriCloud