]> granicus.if.org Git - clang/commitdiff
Diagnose attempts to implicitly instantiate a template before it is
authorJohn McCall <rjmccall@apple.com>
Wed, 27 Apr 2011 06:46:31 +0000 (06:46 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 27 Apr 2011 06:46:31 +0000 (06:46 +0000)
fully defined.  Somehow this escaped notice for a very long time.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130298 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplateInstantiate.cpp
test/CXX/class/class.mem/p2.cpp [new file with mode: 0644]
test/SemaCXX/PR9460.cpp
test/SemaCXX/PR9461.cpp

index f35d5c4b9bf18f2ff894acb7f6cc9c1b1edbd790..9a29ba2be0951312527c904af5b83a1280253cb6 100644 (file)
@@ -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<
index c951b2573a32e9a63b6d6792aac944243d3d35c6..749c4a18a4ed3a273b57523130696ed7419530e9 100644 (file)
@@ -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/test/CXX/class/class.mem/p2.cpp b/test/CXX/class/class.mem/p2.cpp
new file mode 100644 (file)
index 0000000..09040d8
--- /dev/null
@@ -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;
+  };
+}
index be8dc6eb3048a8aac31ebf4e879f2b629314a85e..2cc435e495d2a403364ad3c646541e217289f681 100644 (file)
@@ -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}}
 }
 }
 );
index e24bd4d35a80fd380939a48cdff0ac6c534cfdb1..ce17931324e0d67ddd9f4b87fe1d6397f9181fec 100644 (file)
@@ -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}}