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]

Re: PATCH RFA: Support -Wmissing-declarations in C++


Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> (2) That assumption used to hold 20 years ago for C++.  However, it is less
>     verified for modern C++.  For good or bad, most of libraries
>     come in header files (because they are either templates or inline
>     functions) and there no longer is a clear separation between
>     implementation and "interfaces" (and those are subject to pretty
>     strong ODR requirements, which makes the kind of mistakes you
>     would like to prevent very unlikely, but the implementation would
>     generate lot of noise).
> 
>     Consequently, the premise (1) when mechanically enforced without
>     considerations of how modern C++ programs are written will act
>     like a virus: it will fired up not only in the implementation
>     files that was supposed to be checked, but also in third party
>     libraries used as components (because many of them come in header
>     files).  [This has been happening for real with -Weffc++.]
> 
>     You can reduce the virus effect by not flagging inline functions,
>     function templates (whether declared inline of not).
> 
>     It is also helpful to consider libraries freely available to see
>     how people write codes and how it will affect them.

The code already ignores templates.  I modified it to also ignore
functions explicitly declared inline.  What do you think of this
version of the patch?

If you don't like it, please try to give me an example of code which
you don't want to see a warning about.  It's easy to give very small
examples for this kind of warning.  Just look at the test case
included in the patch.  Thanks.

(I will try to say again what I tried to say earlier: this warning is
for a particular coding style.  If you don't use that coding style,
then don't use this warning.  gcc has dozens of warnings.  I think
it's silly to argue that each warning not included in -Wall
constitutes a moral hazard.  People who enable warnings get what they
asked for.)

Ian


gcc/ChangeLog:

2006-12-14  Ian Lance Taylor  <iant@google.com>

	* c.opt (Wmissing-declarations): Add C++ and ObjC++.
	* doc/invoke.texi (Warning Options): -Wmissing-declarations now
	works for C++.

gcc/cp/ChangeLog:

2006-12-14  Ian Lance Taylor  <iant@google.com>

	* decl.c (start_preparsed_function): Add support for
	-Wmissing-declarations.

gcc/testsuite/ChangeLog:

2006-12-14  Ian Lance Taylor  <iant@google.com>

	* g++.dg/warn/Wmissing-declarations-1.C: New test.


Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 119818)
+++ gcc/doc/invoke.texi	(working copy)
@@ -3215,12 +3215,13 @@ declaration.  This warning is issued eve
 provides a prototype.  The aim is to detect global functions that fail
 to be declared in header files.
 
-@item -Wmissing-declarations @r{(C only)}
+@item -Wmissing-declarations @r{(C and C++ only)}
 @opindex Wmissing-declarations
 Warn if a global function is defined without a previous declaration.
 Do so even if the definition itself provides a prototype.
 Use this option to detect global functions that are not declared in
-header files.
+header files.  In C++, no warnings are issued for functions which are
+explicitly declared inline, or for templatized functions.
 
 @item -Wmissing-field-initializers
 @opindex Wmissing-field-initializers
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 119818)
+++ gcc/cp/decl.c	(working copy)
@@ -10570,9 +10570,41 @@ start_preparsed_function (tree decl1, tr
 	       parsing the body of the function.  */
 	    ;
 	  else
-	    /* Otherwise, OLDDECL is either a previous declaration of
-	       the same function or DECL1 itself.  */
-	    decl1 = olddecl;
+	    {
+	      /* Otherwise, OLDDECL is either a previous declaration
+		 of the same function or DECL1 itself.  */
+
+	      if (warn_missing_declarations
+		  && olddecl == decl1
+		  && !DECL_MAIN_P (decl1)
+		  && TREE_PUBLIC (decl1)
+		  && !DECL_DECLARED_INLINE_P (decl1))
+		{
+		  bool anon;
+		  tree context;
+
+		  /* Check whether DECL1 is in an anonymous
+		     namespace.  */
+		  anon = false;
+		  for (context = DECL_CONTEXT (decl1);
+		       context;
+		       context = DECL_CONTEXT (context))
+		    {
+		      if (TREE_CODE (context) == NAMESPACE_DECL
+			  && DECL_NAME (context) == NULL_TREE)
+			{
+			  anon = true;
+			  break;
+			}
+		    }
+
+		  if (!anon)
+		    warning (OPT_Wmissing_declarations,
+			     "no previous declaration for %q+D", decl1);
+		}
+
+	      decl1 = olddecl;
+	    }
 	}
       else
 	{
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 119818)
+++ gcc/c.opt	(working copy)
@@ -260,7 +260,7 @@ C ObjC C++ ObjC++ Var(warn_missing_brace
 Warn about possibly missing braces around initializers
 
 Wmissing-declarations
-C ObjC Var(warn_missing_declarations)
+C ObjC C++ ObjC++ Var(warn_missing_declarations)
 Warn about global functions without previous declarations
 
 Wmissing-field-initializers
Index: gcc/testsuite/g++.dg/warn/Wmissing-declarations-1.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wmissing-declarations-1.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wmissing-declarations-1.C	(revision 0)
@@ -0,0 +1,45 @@
+// { dg-options "-Wmissing-declarations" }
+
+void fn1() { }		// { dg-warning "no previous declaration" }
+namespace ns {
+  void fn2() { }	// { dg-warning "no previous declaration" }
+}
+namespace {
+  void fn3() { }
+}
+static void fn4() { }
+
+void fn5();
+namespace ns {
+  void fn6();
+}
+
+void fn5() { }
+namespace ns {
+  void fn6() { }
+}
+
+inline void fn7() { }
+
+class c {
+  void cfn1() { }
+  static void cfn2() { }
+  void cfn3();
+  static void cfn4();
+};
+
+void c::cfn3() { }
+void c::cfn4() { }
+
+static struct {
+  void sfn1() { }
+  static void sfn2() { }
+} s;
+
+template<typename C>
+void tfn1() { }
+
+template void tfn1<c>();
+
+class d { };
+template<> void tfn1<d>() { }


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