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: -Wmissing-pure/-Wmissing-const/-Wmissing-nothrow


> 2009/7/2 Jan Hubicka <hubicka@ucw.cz>:
> >> 2009/7/2 Jan Hubicka <hubicka@ucw.cz>:
> >
> > Well, I added it there just because other warnings was there. ?I can put
> > it to tree.h, but tree.h looks bit too generic...
> 
> warn_deprecated_use is defined in toplev.c, so at least it makes sense
> it is declared in toplevel.h. But it is only used by the C and C++

I also need to include toplev.h for warning function itself.

Here is updated patch.  It adds comment about warnings being more active
at hither optimization levels (nothrow is to limited degree done at -O0
too, const/pure needs -O1 ATM), it also moves declaration to tree.h,
updates the hashtable query.  I didn't updated the -Wmidding-attribute=
but if it seems better, I will do that as followup.

Regtested x86_64-linux, I am re-bootstrapping now, OK?

	* doc/invoke.texi (-Wmissing-const, -Wmissing-pure, -Wmissing-nothrow):
	Document.
	* tree.h (warn_function_nothrow): Declare.
	* ipa-pure-const.c: Include toplev.h, flags.h and pointer-set.h.
	(function_always_visible_to_compiler_p, warn_function_nothrow,
	warn_function_pure, warn_function_const): New functions.
	(check_call): Improve debug info.
	(analyze_function): Do not check availability.
	(add_new_function): Check availability.
	(propagate): Output warnings.
	(skip_function_for_local_pure_const): New function.
	(local_pure_const): Use it; output warnings.
	* except.c (set_nothrow_function_flags): Output warnings.
	(common.opt): Add Wmissing-const, Wmissing-nothrow, Wmissing-pure.


	* cp/decl.c (finish_function): Call warn_function_nothrow.

	* g++.dg/opt/nothrow2.C: New testcase.
	* gcc.dg/pure-2.c: New testcase.
	* gcc.dg/const-1.c: New testcase.
Index: doc/invoke.texi
===================================================================
*** doc/invoke.texi	(revision 149206)
--- doc/invoke.texi	(working copy)
*************** Objective-C and Objective-C++ Dialects}.
*** 244,252 ****
  -Wno-int-to-pointer-cast -Wno-invalid-offsetof @gol
  -Winvalid-pch -Wlarger-than=@var{len}  -Wunsafe-loop-optimizations @gol
  -Wlogical-op -Wlong-long @gol
! -Wmain  -Wmissing-braces  -Wmissing-field-initializers @gol
  -Wmissing-format-attribute  -Wmissing-include-dirs @gol
! -Wmissing-noreturn  -Wno-mudflap @gol
  -Wno-multichar  -Wnonnull  -Wno-overflow @gol
  -Woverlength-strings  -Wpacked  -Wpacked-bitfield-compat  -Wpadded @gol
  -Wparentheses  -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
--- 244,252 ----
  -Wno-int-to-pointer-cast -Wno-invalid-offsetof @gol
  -Winvalid-pch -Wlarger-than=@var{len}  -Wunsafe-loop-optimizations @gol
  -Wlogical-op -Wlong-long @gol
! -Wmain  -Wmissing-braces -Wmissing-const -Wmissing-field-initializers @gol
  -Wmissing-format-attribute  -Wmissing-include-dirs @gol
! -Wmissing-noreturn  -Wmissing-nothrow -Wmissing-pure -Wno-mudflap @gol
  -Wno-multichar  -Wnonnull  -Wno-overflow @gol
  -Woverlength-strings  -Wpacked  -Wpacked-bitfield-compat  -Wpadded @gol
  -Wparentheses  -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
*************** adding the @code{noreturn} attribute, ot
*** 3952,3957 ****
--- 3952,3982 ----
  bugs could be introduced.  You will not get a warning for @code{main} in
  hosted C environments.
  
+ @item -Wmissing-const
+ @opindex Wmissing-const
+ @opindex Wno-missing-const
+ @item -Wmissing-pure
+ @opindex Wmissing-pure
+ @opindex Wno-missing-pure
+ Warn about functions which might be candidates for attribute @code{const} and @code{pure}.
+ Warning is not output for functions where compiler can fully decide by itself, only
+ for functions visible in other compilation units and/or those where compiler can not
+ easilly prove fact, that functions is not infinite and thus call to it can be removed
+ when return value is unused.
+ 
+ The amount of detected functions improve with higher optimization levels, at minimum
+ @code{-O1} is needed for warning to be effective.
+ 
+ @item -Wmissing-nothrow
+ @opindex Wmissing-nothrow
+ @opindex Wno-missing-nothrow
+ Warn about functions which might be candidates for attribute @code{nothrow} or,
+ in C++, for decoration via @code{throw ()}.  Warning is not output for
+ functions where compiler can fully decide by itself, only for functions visible
+ in other compilation units.
+ 
+ The amount of nothrow candidates improve with higher optimization levels.
+ 
  @item -Wmissing-format-attribute
  @opindex Wmissing-format-attribute
  @opindex Wno-missing-format-attribute
Index: tree.h
===================================================================
*** tree.h	(revision 149206)
--- tree.h	(working copy)
*************** void init_inline_once (void);
*** 5186,5191 ****
--- 5186,5194 ----
  /* In ipa-reference.c.  Used for parsing attributes of asm code.  */
  extern GTY(()) tree memory_identifier_string;
  
+ /* In ipa-pure-const.c  */
+ extern void warn_function_nothrow (tree);
+ 
  /* Compute the number of operands in an expression node NODE.  For 
     tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
     otherwise it is looked up from the node's code.  */
Index: testsuite/gcc.dg/tree-ssa/local-pure-const.c
===================================================================
*** testsuite/gcc.dg/tree-ssa/local-pure-const.c	(revision 149206)
--- testsuite/gcc.dg/tree-ssa/local-pure-const.c	(working copy)
*************** t(int a, int b, int c)
*** 12,14 ****
--- 12,28 ----
  /* { dg-final { scan-tree-dump-times "local memory is OK" 1 "local-pure-const1"} } */
  /* { dg-final { scan-tree-dump-times "found to be const" 1 "local-pure-const1"} } */
  /* { dg-final { cleanup-tree-dump "local-pure-const1" } } */
+ /* { dg-do compile } */
+ /* { dg-options "-O1 -fdump-tree-local-pure-const1" } */
+ t(int a, int b, int c)
+ {
+   int *p;
+   if (a)
+     p = &a;
+   else
+     p = &c;
+   return *p;
+ }
+ /* { dg-final { scan-tree-dump-times "local memory is OK" 1 "local-pure-const1"} } */
+ /* { dg-final { scan-tree-dump-times "found to be const" 1 "local-pure-const1"} } */
+ /* { dg-final { cleanup-tree-dump "local-pure-const1" } } */
Index: cp/decl.c
===================================================================
*** cp/decl.c	(revision 149206)
--- cp/decl.c	(working copy)
*************** finish_function (int flags)
*** 12299,12305 ****
        && !cp_function_chain->can_throw
        && !flag_non_call_exceptions
        && !DECL_REPLACEABLE_P (fndecl))
!     TREE_NOTHROW (fndecl) = 1;
  
    /* This must come after expand_function_end because cleanups might
       have declarations (from inline functions) that need to go into
--- 12299,12308 ----
        && !cp_function_chain->can_throw
        && !flag_non_call_exceptions
        && !DECL_REPLACEABLE_P (fndecl))
!     {
!       TREE_NOTHROW (fndecl) = 1;
!       warn_function_nothrow (fndecl);
!     }
  
    /* This must come after expand_function_end because cleanups might
       have declarations (from inline functions) that need to go into
Index: ipa-pure-const.c
===================================================================
*** ipa-pure-const.c	(revision 149206)
--- ipa-pure-const.c	(working copy)
*************** along with GCC; see the file COPYING3.  
*** 51,58 ****
--- 51,61 ----
  #include "diagnostic.h"
  #include "langhooks.h"
  #include "target.h"
+ #include "flags.h"
+ #include "pointer-set.h"
  #include "cfgloop.h"
  #include "tree-scalar-evolution.h"
+ #include "toplev.h"
  
  static struct pointer_set_t *visited_nodes;
  
*************** static struct cgraph_node_hook_list *fun
*** 104,109 ****
--- 107,197 ----
  static struct cgraph_2node_hook_list *node_duplication_hook_holder;
  static struct cgraph_node_hook_list *node_removal_hook_holder;
  
+ /* Try to guess if function body will always be visible to compiler
+    when compiling the call and whether compiler will be able
+    to propagate the information by itself.  */
+ 
+ static bool
+ function_always_visible_to_compiler_p (tree decl)
+ {
+   if (!TREE_PUBLIC (decl)
+       || DECL_DECLARED_INLINE_P (decl))
+     return true;
+   return false;
+ }
+ 
+ void
+ warn_function_nothrow (tree decl)
+ {
+   static struct pointer_set_t *warned_about;
+ 
+   if (!warn_missing_nothrow || TREE_THIS_VOLATILE (decl))
+     return;
+   if (function_always_visible_to_compiler_p (decl))
+     return;
+   
+   if (!warned_about)
+     warned_about = pointer_set_create ();
+   if (pointer_set_contains (warned_about, decl))
+     return;
+   pointer_set_insert (warned_about, decl);
+   warning (OPT_Wmissing_nothrow, "%Jfunction might be possible candidate "
+            "for attribute %<nothrow%> or %<throw ()%> marker in C++ code",
+ 	   decl);
+ }
+ 
+ static void
+ warn_function_pure (tree decl, bool known_finite)
+ {
+   static struct pointer_set_t *warned_about;
+ 
+   if (!warn_missing_pure || TREE_THIS_VOLATILE (decl))
+     return;
+   if (known_finite && function_always_visible_to_compiler_p (decl))
+     return;
+   if (!warned_about)
+     warned_about = pointer_set_create ();
+   if (pointer_set_contains (warned_about, decl))
+     return;
+   pointer_set_insert (warned_about, decl);
+   warning (OPT_Wmissing_pure,
+   	   known_finite
+ 	   ? "%Jfunction might be possible candidate "
+              "for attribute %<pure%>"
+            : "%Jfunction might be possible candidate "
+ 	     "for attribute %<pure%> if it is known to be finite",
+ 	   decl);
+ }
+ 
+ static void
+ warn_function_const (tree decl, bool known_finite)
+ {
+   static struct pointer_set_t *warned_about;
+ 
+   if (!warn_missing_const || TREE_THIS_VOLATILE (decl))
+     return;
+   if (known_finite && function_always_visible_to_compiler_p (decl))
+     return;
+   if (!warned_about)
+     warned_about = pointer_set_create ();
+   if (pointer_set_contains (warned_about, decl))
+     return;
+   pointer_set_insert (warned_about, decl);
+   if (!known_finite)
+     {
+       warning (OPT_Wmissing_const, "%Jfunction might be possible candidate "
+                "for attribute %<const%> if it is known to be finite.",
+ 	       decl);
+       return;
+     }
+   warning (OPT_Wmissing_const,
+   	   known_finite
+   	   ? "%Jfunction might be possible candidate "
+              "for attribute %<const%>"
+   	   : "%Jfunction might be possible candidate "
+              "for attribute %<const%> if it is known to be finite",
+ 	   decl);
+ }
  /* Init the function state.  */
  
  static void
*************** check_call (funct_state local, gimple ca
*** 328,334 ****
  
    /* When not in IPA mode, we can still handle self recursion.  */
    if (!ipa && callee_t == current_function_decl)
!     local->looping = true;
    /* The callee is either unknown (indirect call) or there is just no
       scannable code for it (external call) .  We look to see if there
       are any bits available for the callee (such as by declaration or
--- 416,426 ----
  
    /* When not in IPA mode, we can still handle self recursion.  */
    if (!ipa && callee_t == current_function_decl)
!     {
!       if (dump_file)
!         fprintf (dump_file, "    Recursive call can loop.\n");
!       local->looping = true;
!     }
    /* The callee is either unknown (indirect call) or there is just no
       scannable code for it (external call) .  We look to see if there
       are any bits available for the callee (such as by declaration or
*************** check_call (funct_state local, gimple ca
*** 357,368 ****
        if (flags & ECF_CONST) 
  	{
            if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
!             local->looping = true;
  	 }
        else if (flags & ECF_PURE) 
  	{
            if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
!             local->looping = true;
  	  if (dump_file)
  	    fprintf (dump_file, "    pure function call in not const\n");
  	  if (local->pure_const_state == IPA_CONST)
--- 449,468 ----
        if (flags & ECF_CONST) 
  	{
            if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
! 	    {
! 	      if (dump_file)
! 		fprintf (dump_file, "    calls looping pure.\n");
!               local->looping = true;
! 	    }
  	 }
        else if (flags & ECF_PURE) 
  	{
            if (callee_t && DECL_LOOPING_CONST_OR_PURE_P (callee_t))
! 	    {
! 	      if (dump_file)
! 		fprintf (dump_file, "    calls looping const.\n");
!               local->looping = true;
! 	    }
  	  if (dump_file)
  	    fprintf (dump_file, "    pure function call in not const\n");
  	  if (local->pure_const_state == IPA_CONST)
*************** analyze_function (struct cgraph_node *fn
*** 488,500 ****
    funct_state l;
    basic_block this_block;
  
-   if (cgraph_function_body_availability (fn) <= AVAIL_OVERWRITABLE)
-     {
-       if (dump_file)
-         fprintf (dump_file, "Function is not available or overwrittable; not analyzing.\n");
-       return NULL;
-     }
- 
    l = XCNEW (struct funct_state_d);
    l->pure_const_state = IPA_CONST;
    l->state_previously_known = IPA_NEITHER;
--- 588,593 ----
*************** add_new_function (struct cgraph_node *no
*** 612,618 ****
       since all we would be interested in are the addressof
       operations.  */
    visited_nodes = pointer_set_create ();
!   set_function_state (node, analyze_function (node, true));
    pointer_set_destroy (visited_nodes);
    visited_nodes = NULL;
  }
--- 705,712 ----
       since all we would be interested in are the addressof
       operations.  */
    visited_nodes = pointer_set_create ();
!   if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
!     set_function_state (node, analyze_function (node, true));
    pointer_set_destroy (visited_nodes);
    visited_nodes = NULL;
  }
*************** propagate (void)
*** 783,801 ****
  	  switch (this_state)
  	    {
  	    case IPA_CONST:
! 	      if (!TREE_READONLY (w->decl) && dump_file)
! 		fprintf (dump_file, "Function found to be %sconst: %s\n",  
! 			 this_looping ? "looping " : "",
! 			 cgraph_node_name (w)); 
  	      TREE_READONLY (w->decl) = 1;
  	      DECL_LOOPING_CONST_OR_PURE_P (w->decl) = this_looping;
  	      break;
  	      
  	    case IPA_PURE:
! 	      if (!DECL_PURE_P (w->decl) && dump_file)
! 		fprintf (dump_file, "Function found to be %spure: %s\n",  
! 			 this_looping ? "looping " : "",
! 			 cgraph_node_name (w)); 
  	      DECL_PURE_P (w->decl) = 1;
  	      DECL_LOOPING_CONST_OR_PURE_P (w->decl) = this_looping;
  	      break;
--- 877,903 ----
  	  switch (this_state)
  	    {
  	    case IPA_CONST:
! 	      if (!TREE_READONLY (w->decl))
! 		{
! 	          warn_function_const (w->decl, !this_looping);
! 		  if (dump_file)
! 		    fprintf (dump_file, "Function found to be %sconst: %s\n",  
! 			     this_looping ? "looping " : "",
! 			     cgraph_node_name (w)); 
! 		}
  	      TREE_READONLY (w->decl) = 1;
  	      DECL_LOOPING_CONST_OR_PURE_P (w->decl) = this_looping;
  	      break;
  	      
  	    case IPA_PURE:
! 	      if (!DECL_PURE_P (w->decl))
! 		{
! 	          warn_function_pure (w->decl, !this_looping);
! 		  if (dump_file)
! 		    fprintf (dump_file, "Function found to be %spure: %s\n",  
! 			     this_looping ? "looping " : "",
! 			     cgraph_node_name (w)); 
! 		}
  	      DECL_PURE_P (w->decl) = 1;
  	      DECL_LOOPING_CONST_OR_PURE_P (w->decl) = this_looping;
  	      break;
*************** propagate (void)
*** 876,881 ****
--- 978,984 ----
  	    {
  	      struct cgraph_edge *e;
  	      TREE_NOTHROW (w->decl) = true;
+ 	      warn_function_nothrow (w->decl);
  	      for (e = w->callers; e; e = e->next_caller)
  	        e->can_throw_external = false;
  	      if (dump_file)
*************** struct ipa_opt_pass_d pass_ipa_pure_cons
*** 943,958 ****
   NULL					/* variable_transform */
  };
  
! /* Simple local pass for pure const discovery reusing the analysis from
!    ipa_pure_const.   This pass is effective when executed together with
!    other optimization passes in early optimization pass queue.  */
  
! static unsigned int
! local_pure_const (void)
  {
-   bool changed = false;
-   funct_state l;
- 
    /* Because we do not schedule pass_fixup_cfg over whole program after early optimizations
       we must not promote functions that are called by already processed functions.  */
  
--- 1046,1056 ----
   NULL					/* variable_transform */
  };
  
! /* Return true if function should be skipped for local pure const analysis.  */
  
! static bool
! skip_function_for_local_pure_const (void)
  {
    /* Because we do not schedule pass_fixup_cfg over whole program after early optimizations
       we must not promote functions that are called by already processed functions.  */
  
*************** local_pure_const (void)
*** 960,984 ****
      {
        if (dump_file)
          fprintf (dump_file, "Function called in recursive cycle; ignoring\n");
!       return 0;
      }
! 
!   l = analyze_function (cgraph_node (current_function_decl), false);
!   if (!l)
      {
        if (dump_file)
!         fprintf (dump_file, "Function has wrong visibility; ignoring\n");
!       return 0;
      }
  
    switch (l->pure_const_state)
      {
      case IPA_CONST:
        if (!TREE_READONLY (current_function_decl))
  	{
! 	  TREE_READONLY (current_function_decl) = 1;
! 	  DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = l->looping;
! 	  changed = true;
  	  if (dump_file)
  	    fprintf (dump_file, "Function found to be %sconst: %s\n",
  		     l->looping ? "looping " : "",
--- 1058,1104 ----
      {
        if (dump_file)
          fprintf (dump_file, "Function called in recursive cycle; ignoring\n");
!       return true;
      }
!   if (cgraph_function_body_availability (cgraph_node (current_function_decl))
!       <= AVAIL_OVERWRITABLE)
      {
        if (dump_file)
!         fprintf (dump_file, "Function is not available or overwrittable; not analyzing.\n");
!       return true;
      }
+   return false;
+ }
+ 
+ /* Simple local pass for pure const discovery reusing the analysis from
+    ipa_pure_const.   This pass is effective when executed together with
+    other optimization passes in early optimization pass queue.  */
+ 
+ static unsigned int
+ local_pure_const (void)
+ {
+   bool changed = false;
+   funct_state l;
+   bool skip;
+ 
+   skip = skip_function_for_local_pure_const ();
+   if (!warn_missing_const && !warn_missing_nothrow && !warn_missing_pure
+       && skip)
+     return 0;
+   l = analyze_function (cgraph_node (current_function_decl), false);
  
    switch (l->pure_const_state)
      {
      case IPA_CONST:
        if (!TREE_READONLY (current_function_decl))
  	{
! 	  warn_function_const (current_function_decl, !l->looping);
! 	  if (!skip)
! 	    {
! 	      TREE_READONLY (current_function_decl) = 1;
! 	      DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = l->looping;
! 	      changed = true;
! 	    }
  	  if (dump_file)
  	    fprintf (dump_file, "Function found to be %sconst: %s\n",
  		     l->looping ? "looping " : "",
*************** local_pure_const (void)
*** 988,995 ****
        else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
  	       && !l->looping)
  	{
! 	  DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = false;
! 	  changed = true;
  	  if (dump_file)
  	    fprintf (dump_file, "Function found to be non-looping: %s\n",
  		     lang_hooks.decl_printable_name (current_function_decl,
--- 1108,1118 ----
        else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
  	       && !l->looping)
  	{
! 	  if (!skip)
! 	    {
! 	      DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = false;
! 	      changed = true;
! 	    }
  	  if (dump_file)
  	    fprintf (dump_file, "Function found to be non-looping: %s\n",
  		     lang_hooks.decl_printable_name (current_function_decl,
*************** local_pure_const (void)
*** 998,1008 ****
        break;
  
      case IPA_PURE:
!       if (!TREE_READONLY (current_function_decl))
  	{
! 	  DECL_PURE_P (current_function_decl) = 1;
! 	  DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = l->looping;
! 	  changed = true;
  	  if (dump_file)
  	    fprintf (dump_file, "Function found to be %spure: %s\n",
  		     l->looping ? "looping " : "",
--- 1121,1135 ----
        break;
  
      case IPA_PURE:
!       if (!DECL_PURE_P (current_function_decl))
  	{
! 	  if (!skip)
! 	    {
! 	      DECL_PURE_P (current_function_decl) = 1;
! 	      DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = l->looping;
! 	      changed = true;
! 	    }
! 	  warn_function_pure (current_function_decl, !l->looping);
  	  if (dump_file)
  	    fprintf (dump_file, "Function found to be %spure: %s\n",
  		     l->looping ? "looping " : "",
*************** local_pure_const (void)
*** 1012,1019 ****
        else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
  	       && !l->looping)
  	{
! 	  DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = false;
! 	  changed = true;
  	  if (dump_file)
  	    fprintf (dump_file, "Function found to be non-looping: %s\n",
  		     lang_hooks.decl_printable_name (current_function_decl,
--- 1139,1149 ----
        else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
  	       && !l->looping)
  	{
! 	  if (!skip)
! 	    {
! 	      DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) = false;
! 	      changed = true;
! 	    }
  	  if (dump_file)
  	    fprintf (dump_file, "Function found to be non-looping: %s\n",
  		     lang_hooks.decl_printable_name (current_function_decl,
*************** local_pure_const (void)
*** 1026,1038 ****
      }
    if (!l->can_throw && !TREE_NOTHROW (current_function_decl))
      {
!       struct cgraph_edge *e;
! 
!       TREE_NOTHROW (current_function_decl) = true;
!       for (e = cgraph_node (current_function_decl)->callers;
!            e; e = e->next_caller)
! 	e->can_throw_external = false;
!       changed = true;
        if (dump_file)
  	fprintf (dump_file, "Function found to be nothrow: %s\n",
  		 lang_hooks.decl_printable_name (current_function_decl,
--- 1156,1171 ----
      }
    if (!l->can_throw && !TREE_NOTHROW (current_function_decl))
      {
!       warn_function_nothrow (current_function_decl);
!       if (!skip)
! 	{
! 	  struct cgraph_edge *e;
! 	  TREE_NOTHROW (current_function_decl) = true;
! 	  for (e = cgraph_node (current_function_decl)->callers;
! 	       e; e = e->next_caller)
! 	    e->can_throw_external = false;
! 	  changed = true;
! 	}
        if (dump_file)
  	fprintf (dump_file, "Function found to be nothrow: %s\n",
  		 lang_hooks.decl_printable_name (current_function_decl,
Index: opts.c
===================================================================
*** opts.c	(revision 149206)
--- opts.c	(working copy)
*************** decode_options (unsigned int argc, const
*** 831,836 ****
--- 831,843 ----
  	    }
  	}
      }
+ 
+   if (warn_missing_pure && !optimize)
+     warning (0, "command line option \"-Wmissing-pure\""
+     		" is effective only during optimizing compilation");
+   if (warn_missing_const && !optimize)
+     warning (0, "command line option \"-Wmissing-const\""
+     		" is effective only during optimizing compilation");
    
    /* Use priority coloring if cover classes is not defined for the
       target.  */
Index: except.c
===================================================================
*** except.c	(revision 149206)
--- except.c	(working copy)
*************** set_nothrow_function_flags (void)
*** 3369,3374 ****
--- 3369,3376 ----
  	    return 0;
  	  }
        }
+   if (crtl->nothrow)
+     warn_function_nothrow (current_function_decl);
    if (crtl->nothrow
        && (cgraph_function_body_availability (cgraph_node
  					     (current_function_decl))
Index: common.opt
===================================================================
*** common.opt	(revision 149206)
--- common.opt	(working copy)
*************** Wunsafe-loop-optimizations
*** 132,141 ****
--- 132,153 ----
  Common Var(warn_unsafe_loop_optimizations) Warning
  Warn if the loop cannot be optimized due to nontrivial assumptions.
  
+ Wmissing-const
+ Common Var(warn_missing_const) Warning
+ Warn about functions which might be candidates for __attribute__((const))
+ 
+ Wmissing-nothrow
+ Common Var(warn_missing_nothrow) Warning
+ Warn about functions which might be candidates for __attribute__((nothrow))
+ 
  Wmissing-noreturn
  Common Var(warn_missing_noreturn) Warning
  Warn about functions which might be candidates for __attribute__((noreturn))
  
+ Wmissing-pure
+ Common Var(warn_missing_pure) Warning
+ Warn about functions which might be candidates for __attribute__((pure))
+ 
  Wmudflap
  Common Var(warn_mudflap) Init(1) Warning
  Warn about constructs not instrumented by -fmudflap
Index: testsuite/gcc.dg/pure-2.c
===================================================================
*** testsuite/gcc.dg/pure-2.c	(revision 0)
--- testsuite/gcc.dg/pure-2.c	(revision 0)
***************
*** 0 ****
--- 1,57 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -Wmissing-pure" } */
+ 
+ extern int extern_const(int a) __attribute__ ((pure));
+ extern int v;
+ 
+ /* Trivial.  */
+ int
+ foo1(int a)
+ {
+   return v;
+ } /* { dg-warning "candidate for attribute 'const'" "detect const candidate" } */
+ 
+ /* Loops known to be finite and extern const calls should be safe.  */
+ int __attribute__ ((noinline))
+ foo2(int n)
+ {
+   int ret = 0;
+   int i;
+   for (i=0; i<n; i++)
+     ret+=extern_const (i);
+   return ret;
+ } /* { dg-warning "candidate for attribute 'const'" "detect const candidate" } */
+ 
+ /* No warning here; we can work it by ourselves.  */
+ static int __attribute__ ((noinline))
+ foo2b(int n)
+ {
+   int ret = 0;
+   int i;
+   for (i=0; i<n; i++)
+     ret+=extern_const (i);
+   return ret;
+ }
+ 
+ /* Unbounded loops are not safe.  */
+ static int __attribute__ ((noinline))
+ foo3(int n)
+ {
+   int ret = 0;
+   int i;
+   for (i=0; extern_const (i+n); n++)
+     ret+=extern_const (i);
+   return ret;
+ } /* { dg-warning "candidate for attribute 'const' if known to be finite" "detect const candidate" } */
+ 
+ int
+ foo4(int n)
+ {
+   return foo3(n) + foo2b(n);
+ } /* { dg-warning "candidate for attribute 'const' if known to be finite" "detect const candidate" } */
+ 
+ int
+ foo5(int n)
+ {
+   return foo2(n);
+ } /* { dg-warning "candidate for attribute 'const'" "detect const candidate" } */
Index: testsuite/gcc.dg/const-1.c
===================================================================
*** testsuite/gcc.dg/const-1.c	(revision 0)
--- testsuite/gcc.dg/const-1.c	(revision 0)
***************
*** 0 ****
--- 1,56 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -Wmissing-const" } */
+ 
+ extern int extern_const(int a) __attribute__ ((const));
+ 
+ /* Trivial.  */
+ int
+ foo1(int a)
+ {
+   return extern_const (a);
+ } /* { dg-warning "candidate for attribute 'const'" "detect const candidate" } */
+ 
+ /* Loops known to be finite and extern const calls should be safe.  */
+ int __attribute__ ((noinline))
+ foo2(int n)
+ {
+   int ret = 0;
+   int i;
+   for (i=0; i<n; i++)
+     ret+=extern_const (i);
+   return ret;
+ } /* { dg-warning "candidate for attribute 'const'" "detect const candidate" } */
+ 
+ /* No warning here; we can work it by ourselves.  */
+ static int __attribute__ ((noinline))
+ foo2b(int n)
+ {
+   int ret = 0;
+   int i;
+   for (i=0; i<n; i++)
+     ret+=extern_const (i);
+   return ret;
+ }
+ 
+ /* Unbounded loops are not safe.  */
+ static int __attribute__ ((noinline))
+ foo3(int n)
+ {
+   int ret = 0;
+   int i;
+   for (i=0; extern_const (i+n); n++)
+     ret+=extern_const (i);
+   return ret;
+ } /* { dg-warning "candidate for attribute 'const' if known to be finite" "detect const candidate" } */
+ 
+ int
+ foo4(int n)
+ {
+   return foo3(n) + foo2b(n);
+ } /* { dg-warning "candidate for attribute 'const' if known to be finite" "detect const candidate" } */
+ 
+ int
+ foo5(int n)
+ {
+   return foo2(n);
+ } /* { dg-warning "candidate for attribute 'const'" "detect const candidate" } */
Index: testsuite/g++.dg/opt/nothrow2.C
===================================================================
*** testsuite/g++.dg/opt/nothrow2.C	(revision 0)
--- testsuite/g++.dg/opt/nothrow2.C	(revision 0)
***************
*** 0 ****
--- 1,6 ----
+ // { dg-options "-O2 -Wmissing-nothrow" }
+ 
+ int t ()
+ {
+   return 1;
+ } // { dg-warning "candidate for attribute `nothrow`" }


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