This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RFC] New g++ warning for inner-style forward class declarations


Attached is a patch to add a new warning to g++ for inner-style forward
class declarations that the compiler has ignored.  For example:

  struct Foo::Bar;  // Error, class Foo is not complete
  struct Foo { struct Bar {}; };
  struct Foo::Bar;  // No error, but pointless since Foo is complete

This patch adds a warning for the second use of 'struct Foo::Bar;' for
contexts where it is not an error, only an irrelevance.  This matches a
similar message emitted by the EDG parser (in Comeau C++, for example).

The patch includes a new test, to verify that the warning is emitted by
g++ when required, and also that g++ finds no false positives.

Regression tested with bootstrap and with the full g++ testsuite.


gcc/cp/ChangeLog
2007-06-20  Simon Baldwin <simonb@google.com>

	* parser.c (cp_parser_elaborated_type_specifier): Added a warning
	for inner-style nested forward declarations that don't declare
	anything useful.

gcc/testsuite/ChangeLog
2007-06-20  Simon Baldwin <simonb@google.com>

	* g++.dg/warn/forward-inner.C: New.


diff -Nrcp3 gcc_orig/gcc/cp/parser.c gcc/gcc/cp/parser.c
*** gcc_orig/gcc/cp/parser.c	Mon Jun 18 15:35:45 2007
--- gcc/gcc/cp/parser.c	Wed Jun 20 12:10:24 2007
*************** cp_parser_elaborated_type_specifier (cp_
*** 10907,10912 ****
--- 10907,10929 ----
                  return error_mark_node;
              }
  
+           /* Forward declarations of nested types, such as
+ 
+                class C1::C2;
+                class C1::C2::C3;
+ 
+              are invalid unless all components preceding the final '::'
+              are complete.  If all enclosing types are complete, these
+              declarations become merely pointless.
+ 
+              Invalid forward declarations of nested types are errors
+              caught elsewhere in parsing.  Those that are pointless arrive
+              here.  */
+ 
+           if (cp_parser_declares_only_class_p (parser)
+               && !is_friend && !processing_explicit_instantiation)
+             warning (0, "declaration %qD does not declare anything", decl);
+ 
  	  type = TREE_TYPE (decl);
  	}
        else
diff -Nrcp3 gcc_orig/gcc/testsuite/g++.dg/warn/forward-inner.C gcc/gcc/testsuite/g++.dg/warn/forward-inner.C
*** gcc_orig/gcc/testsuite/g++.dg/warn/forward-inner.C	Wed Dec 31 16:00:00 1969
--- gcc/gcc/testsuite/g++.dg/warn/forward-inner.C	Wed Jun 20 12:07:31 2007
***************
*** 0 ****
--- 1,81 ----
+ // Check that the compiler warns about inner-style forward declarations in
+ // contexts where they're not actually illegal, but merely useless.
+ 
+ // Verify warnings for and within classes, and by extension, struct and union.
+ class C1;
+ class C1::C2;      // { dg-error "does not name a type" }
+ class C1::C2::C3;  // { dg-error "has not been declared" }
+ 
+ class C1 {
+  public:
+   class C2;
+   class C2::C3;    // { dg-error "does not name a type" }
+   class C2 {
+    public:
+     class C3;
+     class C3 { };
+     class C3;
+   };
+   class C2;
+   class C2::C3;    // { dg-warning "declaration 'class C1::C2::C3' does not declare anything" }
+ };
+ 
+ class C1;
+ class C1::C2;      // { dg-warning "declaration 'class C1::C2' does not declare anything" }
+ class C1::C2::C3;  // { dg-warning "declaration 'class C1::C2::C3' does not declare anything" }
+ 
+ 
+ // Verify warnings for namespace scopes.
+ class N1::C4;      // { dg-error "has not been declared" }
+ class N1::N2::C5;  // { dg-error "has not been declared" }
+ 
+ namespace N1 {
+   class C4;
+   class C4 { };
+   class C4;
+ 
+   class N2::C5;    // { dg-error "has not been declared" }
+   namespace N2 {
+     class C5;
+     class C5 { };
+     class C5;
+   }
+   class N2::C5;    // { dg-warning "declaration 'class N1::N2::C5' does not declare anything" }
+ }
+ 
+ class N1::C4;      // { dg-warning "declaration 'class N1::C4' does not declare anything" }
+ class N1::N2::C5;  // { dg-warning "declaration 'class N1::N2::C5' does not declare anything" }
+ 
+ 
+ // Verify that using declarations related to namespaces don't generate a
+ // warning.
+ using namespace N1;
+ using namespace N1::N2;
+ 
+ namespace N3 {
+   using N1::C4;      // Valid using declaration, no warning
+   using N1::N2::C5;  // Valid using declaration, no warning
+ }
+ 
+ 
+ // Verify that explicit template instantiations, easy to confuse with
+ // forward declarations, don't generate a warning.
+ template<class C>
+ class TC6 {
+  public:
+   class TC7 { };
+ };
+ 
+ template class TC6<int>::TC7;  // Valid explicit instantiation, no warning
+ 
+ 
+ // Verify that friend declarations, also easy to confuse with forward
+ // declrations, are similarly not warned about.
+ class C8 {
+  public:
+   class C9 { };
+ };
+ class C10 {
+  public:
+   friend class C8::C9;         // Valid friend declaration, no warning
+ };


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]