Patchwork PR 54930: add -Wreturn-local-addr

login
register
mail settings
Submitter Jonathan Wakely
Date Oct. 18, 2012, 6:28 p.m.
Message ID <CAH6eHdT8hcqASUSMduWLFoGpocZjtv+sCGxdu8pgUFyawz01GA@mail.gmail.com>
Download mbox | patch
Permalink /patch/192400/
State New
Headers show

Comments

Jonathan Wakely - Oct. 18, 2012, 6:28 p.m.
This adds a warning switch for the existing "returning address of
local variable" warnings in the C and C++ FEs which are enabled by
default but have no switch controlling them. Adding a switch allows it
to be turned into an error with -Werror=return-local-addr.  I've added
two tests checking the -Werror form works.

gcc/c-family:
        PR c++/54930
        * c.opt (Wreturn_local_addr): Define new option.

gcc/c:
        PR c++/54930
        * c-typeck.c (c_finish_return): Use OPT_Wreturn_local_addr.

gcc/cp:
        PR c++/54930
        * typeck.c (maybe_warn_about_returning_address_of_local): Use
        OPT_Wreturn_local_addr.

gcc:
        PR c++/54930
        * doc/invoke.texi (Warning Options): Document -Wno-return-local-addr.

gcc/testsuite:
        PR c++/54930
        * gcc.dg/Wreturn-local-addr.c: New.
        * g++.dg/warn/Wno-return-local-addr.C: New.
        * g++.dg/warn/Wreturn-local-addr.C: New.

Tested x86_64-linux, OK for trunk?
commit 77abe727e837e052680be8020fa2990cce4d1e9a
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Wed Oct 17 19:32:10 2012 +0100

    gcc/c-family:
    	PR c++/54930
    	* c.opt (Wreturn_local_addr): Define new option.
    
    gcc/c:
    	PR c++/54930
    	* c-typeck.c (c_finish_return): Use OPT_Wreturn_local_addr.
    
    gcc/cp:
    	PR c++/54930
    	* typeck.c (maybe_warn_about_returning_address_of_local): Use
    	OPT_Wreturn_local_addr.
    
    gcc:
    	PR c++/54930
    	* doc/invoke.texi (Warning Options): Document -Wno-return-local-addr.
    
    gcc/testsuite:
    	PR c++/54930
    	* gcc.dg/Wreturn-local-addr.c: New.
    	* g++.dg/warn/Wno-return-local-addr.C: New.
    	* g++.dg/warn/Wreturn-local-addr.C: New.
Joseph S. Myers - Oct. 19, 2012, 4:19 p.m.
On Thu, 18 Oct 2012, Jonathan Wakely wrote:

> This adds a warning switch for the existing "returning address of
> local variable" warnings in the C and C++ FEs which are enabled by
> default but have no switch controlling them. Adding a switch allows it
> to be turned into an error with -Werror=return-local-addr.  I've added
> two tests checking the -Werror form works.

The C front-end changes are OK.
Dodji Seketeli - Oct. 21, 2012, 9:25 p.m.
The C++ bits look good to my casual non-maintainer eyes.  Let's CC
Jason.

Thanks.

Jonathan Wakely <jwakely.gcc@gmail.com> a écrit:

> This adds a warning switch for the existing "returning address of
> local variable" warnings in the C and C++ FEs which are enabled by
> default but have no switch controlling them. Adding a switch allows it
> to be turned into an error with -Werror=return-local-addr.  I've added
> two tests checking the -Werror form works.
>
> gcc/c-family:
>         PR c++/54930
>         * c.opt (Wreturn_local_addr): Define new option.
>
> gcc/c:
>         PR c++/54930
>         * c-typeck.c (c_finish_return): Use OPT_Wreturn_local_addr.
>
> gcc/cp:
>         PR c++/54930
>         * typeck.c (maybe_warn_about_returning_address_of_local): Use
>         OPT_Wreturn_local_addr.
>
> gcc:
>         PR c++/54930
>         * doc/invoke.texi (Warning Options): Document -Wno-return-local-addr.
>
> gcc/testsuite:
>         PR c++/54930
>         * gcc.dg/Wreturn-local-addr.c: New.
>         * g++.dg/warn/Wno-return-local-addr.C: New.
>         * g++.dg/warn/Wreturn-local-addr.C: New.
>
> Tested x86_64-linux, OK for trunk?
>
> commit 77abe727e837e052680be8020fa2990cce4d1e9a
> Author: Jonathan Wakely <jwakely.gcc@gmail.com>
> Date:   Wed Oct 17 19:32:10 2012 +0100
>
>     gcc/c-family:
>     	PR c++/54930
>     	* c.opt (Wreturn_local_addr): Define new option.
>     
>     gcc/c:
>     	PR c++/54930
>     	* c-typeck.c (c_finish_return): Use OPT_Wreturn_local_addr.
>     
>     gcc/cp:
>     	PR c++/54930
>     	* typeck.c (maybe_warn_about_returning_address_of_local): Use
>     	OPT_Wreturn_local_addr.
>     
>     gcc:
>     	PR c++/54930
>     	* doc/invoke.texi (Warning Options): Document -Wno-return-local-addr.
>     
>     gcc/testsuite:
>     	PR c++/54930
>     	* gcc.dg/Wreturn-local-addr.c: New.
>     	* g++.dg/warn/Wno-return-local-addr.C: New.
>     	* g++.dg/warn/Wreturn-local-addr.C: New.
>
> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
> index 3166984..f75b58c 100644
> --- a/gcc/c-family/c.opt
> +++ b/gcc/c-family/c.opt
> @@ -601,6 +601,10 @@ Wreorder
>  C++ ObjC++ Var(warn_reorder) Warning LangEnabledBy(C++ ObjC++,Wall)
>  Warn when the compiler reorders code
>  
> +Wreturn-local-addr
> +C ObjC C++ ObjC++ Var(warn_return_local_addr) Init(1) Warning
> +Warn about returning a pointer/reference to a local or temporary variable.
> +
>  Wreturn-type
>  C ObjC C++ ObjC++ Var(warn_return_type) Warning
>  Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++)
> diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
> index 4855933..cf63355 100644
> --- a/gcc/c/c-typeck.c
> +++ b/gcc/c/c-typeck.c
> @@ -8742,7 +8742,8 @@ c_finish_return (location_t loc, tree retval, tree origtype)
>  		  && !TREE_STATIC (inner)
>  		  && DECL_CONTEXT (inner) == current_function_decl)
>  		warning_at (loc,
> -			    0, "function returns address of local variable");
> +			    OPT_Wreturn_local_addr, "function returns address "
> +			    "of local variable");
>  	      break;
>  
>  	    default:
> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
> index eaa0935..d2944d3 100644
> --- a/gcc/cp/typeck.c
> +++ b/gcc/cp/typeck.c
> @@ -8019,14 +8019,14 @@ maybe_warn_about_returning_address_of_local (tree retval)
>        if (TREE_CODE (whats_returned) == AGGR_INIT_EXPR
>  	  || TREE_CODE (whats_returned) == TARGET_EXPR)
>  	{
> -	  warning (0, "returning reference to temporary");
> +	  warning (OPT_Wreturn_local_addr, "returning reference to temporary");
>  	  return;
>  	}
>        if (TREE_CODE (whats_returned) == VAR_DECL
>  	  && DECL_NAME (whats_returned)
>  	  && TEMP_NAME_P (DECL_NAME (whats_returned)))
>  	{
> -	  warning (0, "reference to non-lvalue returned");
> +	  warning (OPT_Wreturn_local_addr, "reference to non-lvalue returned");
>  	  return;
>  	}
>      }
> @@ -8042,10 +8042,10 @@ maybe_warn_about_returning_address_of_local (tree retval)
>  	   || TREE_PUBLIC (whats_returned)))
>      {
>        if (TREE_CODE (valtype) == REFERENCE_TYPE)
> -	warning (0, "reference to local variable %q+D returned",
> +	warning (OPT_Wreturn_local_addr, "reference to local variable %q+D returned",
>  		 whats_returned);
>        else
> -	warning (0, "address of local variable %q+D returned",
> +	warning (OPT_Wreturn_local_addr, "address of local variable %q+D returned",
>  		 whats_returned);
>        return;
>      }
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index f8c9230..2e36de1 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -261,7 +261,7 @@ Objective-C and Objective-C++ Dialects}.
>  -Woverlength-strings  -Wpacked  -Wpacked-bitfield-compat  -Wpadded @gol
>  -Wparentheses  -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
>  -Wpointer-arith  -Wno-pointer-to-int-cast @gol
> --Wredundant-decls @gol
> +-Wredundant-decls  -Wno-return-local-addr @gol
>  -Wreturn-type  -Wsequence-point  -Wshadow @gol
>  -Wsign-compare  -Wsign-conversion  -Wsizeof-pointer-memaccess @gol
>  -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
> @@ -3526,6 +3526,12 @@ definitions, may be found on the GCC readings page, at
>  
>  This warning is enabled by @option{-Wall} for C and C++.
>  
> +@item -Wno-return-local-addr
> +@opindex Wno-return-local-addr
> +@opindex Wreturn-local-addr
> +Do not warn about returning a pointer (or in C++, a reference) to a
> +variable that goes out of scope after the function returns.
> +
>  @item -Wreturn-type
>  @opindex Wreturn-type
>  @opindex Wno-return-type
> diff --git a/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C b/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
> new file mode 100644
> index 0000000..e15bfa2
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
> @@ -0,0 +1,26 @@
> +// { dg-do assemble  }
> +// { dg-options "-Wno-return-local-addr" }
> +
> +int& bad1()
> +{
> +  int x = 0;
> +  return x;
> +}
> +
> +int* bad2()
> +{
> +  int x = 0;
> +  return &x;
> +}
> +
> +int f();
> +
> +const int& bad3()
> +{
> +  return f();
> +}
> +
> +const int& bad4()
> +{
> +  return int();
> +}
> diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
> new file mode 100644
> index 0000000..faa3a34
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
> @@ -0,0 +1,20 @@
> +// { dg-do assemble  }
> +// { dg-options "-Werror=return-local-addr" }
> +// { dg-message "some warnings being treated as errors" "" {target "*-*-*"} 0 }
> +
> +int& bad1()
> +{
> +  int x = 0;		// { dg-error "reference to local variable" }
> +  return x;
> +}
> +
> +int* bad2()
> +{
> +  int x = 0;		// { dg-error "address of local variable" }
> +  return &x;
> +}
> +
> +const int& bad4()
> +{
> +  return int();		// { dg-error "returning reference to temporary" }
> +}
> diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr.c
> new file mode 100644
> index 0000000..d496d20
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr.c
> @@ -0,0 +1,9 @@
> +/* { dg-do assemble  } */
> +/* { dg-options "-Werror=return-local-addr" } */
> +/* { dg-message "some warnings being treated as errors" "" {target "*-*-*"} 0 } */
> +
> +int* bad()
> +{
> +  int x = 0;
> +  return &x;		/* { dg-error "address of local variable" } */
> +}
Jonathan Wakely - Oct. 29, 2012, 8:51 p.m.
Ping - can I get this reviewed before stage 1 ends?


On 21 October 2012 22:25, Dodji Seketeli <dodji@seketeli.org> wrote:
> The C++ bits look good to my casual non-maintainer eyes.  Let's CC
> Jason.
>
> Thanks.
>
> Jonathan Wakely <jwakely.gcc@gmail.com> a écrit:
>
>> This adds a warning switch for the existing "returning address of
>> local variable" warnings in the C and C++ FEs which are enabled by
>> default but have no switch controlling them. Adding a switch allows it
>> to be turned into an error with -Werror=return-local-addr.  I've added
>> two tests checking the -Werror form works.
>>
>> gcc/c-family:
>>         PR c++/54930
>>         * c.opt (Wreturn_local_addr): Define new option.
>>
>> gcc/c:
>>         PR c++/54930
>>         * c-typeck.c (c_finish_return): Use OPT_Wreturn_local_addr.
>>
>> gcc/cp:
>>         PR c++/54930
>>         * typeck.c (maybe_warn_about_returning_address_of_local): Use
>>         OPT_Wreturn_local_addr.
>>
>> gcc:
>>         PR c++/54930
>>         * doc/invoke.texi (Warning Options): Document -Wno-return-local-addr.
>>
>> gcc/testsuite:
>>         PR c++/54930
>>         * gcc.dg/Wreturn-local-addr.c: New.
>>         * g++.dg/warn/Wno-return-local-addr.C: New.
>>         * g++.dg/warn/Wreturn-local-addr.C: New.
>>
>> Tested x86_64-linux, OK for trunk?
>>
>> commit 77abe727e837e052680be8020fa2990cce4d1e9a
>> Author: Jonathan Wakely <jwakely.gcc@gmail.com>
>> Date:   Wed Oct 17 19:32:10 2012 +0100
>>
>>     gcc/c-family:
>>       PR c++/54930
>>       * c.opt (Wreturn_local_addr): Define new option.
>>
>>     gcc/c:
>>       PR c++/54930
>>       * c-typeck.c (c_finish_return): Use OPT_Wreturn_local_addr.
>>
>>     gcc/cp:
>>       PR c++/54930
>>       * typeck.c (maybe_warn_about_returning_address_of_local): Use
>>       OPT_Wreturn_local_addr.
>>
>>     gcc:
>>       PR c++/54930
>>       * doc/invoke.texi (Warning Options): Document -Wno-return-local-addr.
>>
>>     gcc/testsuite:
>>       PR c++/54930
>>       * gcc.dg/Wreturn-local-addr.c: New.
>>       * g++.dg/warn/Wno-return-local-addr.C: New.
>>       * g++.dg/warn/Wreturn-local-addr.C: New.
>>
>> diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
>> index 3166984..f75b58c 100644
>> --- a/gcc/c-family/c.opt
>> +++ b/gcc/c-family/c.opt
>> @@ -601,6 +601,10 @@ Wreorder
>>  C++ ObjC++ Var(warn_reorder) Warning LangEnabledBy(C++ ObjC++,Wall)
>>  Warn when the compiler reorders code
>>
>> +Wreturn-local-addr
>> +C ObjC C++ ObjC++ Var(warn_return_local_addr) Init(1) Warning
>> +Warn about returning a pointer/reference to a local or temporary variable.
>> +
>>  Wreturn-type
>>  C ObjC C++ ObjC++ Var(warn_return_type) Warning
>>  Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++)
>> diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
>> index 4855933..cf63355 100644
>> --- a/gcc/c/c-typeck.c
>> +++ b/gcc/c/c-typeck.c
>> @@ -8742,7 +8742,8 @@ c_finish_return (location_t loc, tree retval, tree origtype)
>>                 && !TREE_STATIC (inner)
>>                 && DECL_CONTEXT (inner) == current_function_decl)
>>               warning_at (loc,
>> -                         0, "function returns address of local variable");
>> +                         OPT_Wreturn_local_addr, "function returns address "
>> +                         "of local variable");
>>             break;
>>
>>           default:
>> diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
>> index eaa0935..d2944d3 100644
>> --- a/gcc/cp/typeck.c
>> +++ b/gcc/cp/typeck.c
>> @@ -8019,14 +8019,14 @@ maybe_warn_about_returning_address_of_local (tree retval)
>>        if (TREE_CODE (whats_returned) == AGGR_INIT_EXPR
>>         || TREE_CODE (whats_returned) == TARGET_EXPR)
>>       {
>> -       warning (0, "returning reference to temporary");
>> +       warning (OPT_Wreturn_local_addr, "returning reference to temporary");
>>         return;
>>       }
>>        if (TREE_CODE (whats_returned) == VAR_DECL
>>         && DECL_NAME (whats_returned)
>>         && TEMP_NAME_P (DECL_NAME (whats_returned)))
>>       {
>> -       warning (0, "reference to non-lvalue returned");
>> +       warning (OPT_Wreturn_local_addr, "reference to non-lvalue returned");
>>         return;
>>       }
>>      }
>> @@ -8042,10 +8042,10 @@ maybe_warn_about_returning_address_of_local (tree retval)
>>          || TREE_PUBLIC (whats_returned)))
>>      {
>>        if (TREE_CODE (valtype) == REFERENCE_TYPE)
>> -     warning (0, "reference to local variable %q+D returned",
>> +     warning (OPT_Wreturn_local_addr, "reference to local variable %q+D returned",
>>                whats_returned);
>>        else
>> -     warning (0, "address of local variable %q+D returned",
>> +     warning (OPT_Wreturn_local_addr, "address of local variable %q+D returned",
>>                whats_returned);
>>        return;
>>      }
>> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
>> index f8c9230..2e36de1 100644
>> --- a/gcc/doc/invoke.texi
>> +++ b/gcc/doc/invoke.texi
>> @@ -261,7 +261,7 @@ Objective-C and Objective-C++ Dialects}.
>>  -Woverlength-strings  -Wpacked  -Wpacked-bitfield-compat  -Wpadded @gol
>>  -Wparentheses  -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
>>  -Wpointer-arith  -Wno-pointer-to-int-cast @gol
>> --Wredundant-decls @gol
>> +-Wredundant-decls  -Wno-return-local-addr @gol
>>  -Wreturn-type  -Wsequence-point  -Wshadow @gol
>>  -Wsign-compare  -Wsign-conversion  -Wsizeof-pointer-memaccess @gol
>>  -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
>> @@ -3526,6 +3526,12 @@ definitions, may be found on the GCC readings page, at
>>
>>  This warning is enabled by @option{-Wall} for C and C++.
>>
>> +@item -Wno-return-local-addr
>> +@opindex Wno-return-local-addr
>> +@opindex Wreturn-local-addr
>> +Do not warn about returning a pointer (or in C++, a reference) to a
>> +variable that goes out of scope after the function returns.
>> +
>>  @item -Wreturn-type
>>  @opindex Wreturn-type
>>  @opindex Wno-return-type
>> diff --git a/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C b/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
>> new file mode 100644
>> index 0000000..e15bfa2
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
>> @@ -0,0 +1,26 @@
>> +// { dg-do assemble  }
>> +// { dg-options "-Wno-return-local-addr" }
>> +
>> +int& bad1()
>> +{
>> +  int x = 0;
>> +  return x;
>> +}
>> +
>> +int* bad2()
>> +{
>> +  int x = 0;
>> +  return &x;
>> +}
>> +
>> +int f();
>> +
>> +const int& bad3()
>> +{
>> +  return f();
>> +}
>> +
>> +const int& bad4()
>> +{
>> +  return int();
>> +}
>> diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
>> new file mode 100644
>> index 0000000..faa3a34
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
>> @@ -0,0 +1,20 @@
>> +// { dg-do assemble  }
>> +// { dg-options "-Werror=return-local-addr" }
>> +// { dg-message "some warnings being treated as errors" "" {target "*-*-*"} 0 }
>> +
>> +int& bad1()
>> +{
>> +  int x = 0;         // { dg-error "reference to local variable" }
>> +  return x;
>> +}
>> +
>> +int* bad2()
>> +{
>> +  int x = 0;         // { dg-error "address of local variable" }
>> +  return &x;
>> +}
>> +
>> +const int& bad4()
>> +{
>> +  return int();              // { dg-error "returning reference to temporary" }
>> +}
>> diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr.c
>> new file mode 100644
>> index 0000000..d496d20
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr.c
>> @@ -0,0 +1,9 @@
>> +/* { dg-do assemble  } */
>> +/* { dg-options "-Werror=return-local-addr" } */
>> +/* { dg-message "some warnings being treated as errors" "" {target "*-*-*"} 0 } */
>> +
>> +int* bad()
>> +{
>> +  int x = 0;
>> +  return &x;         /* { dg-error "address of local variable" } */
>> +}
>
> --
>                 Dodji
Jason Merrill - Oct. 29, 2012, 9:26 p.m.
OK.

Jason
Jonathan Wakely - Oct. 29, 2012, 11:23 p.m.
On 29 October 2012 21:26, Jason Merrill wrote:
> OK.

Thanks, committed.

Patch

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 3166984..f75b58c 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -601,6 +601,10 @@  Wreorder
 C++ ObjC++ Var(warn_reorder) Warning LangEnabledBy(C++ ObjC++,Wall)
 Warn when the compiler reorders code
 
+Wreturn-local-addr
+C ObjC C++ ObjC++ Var(warn_return_local_addr) Init(1) Warning
+Warn about returning a pointer/reference to a local or temporary variable.
+
 Wreturn-type
 C ObjC C++ ObjC++ Var(warn_return_type) Warning
 Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++)
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 4855933..cf63355 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -8742,7 +8742,8 @@  c_finish_return (location_t loc, tree retval, tree origtype)
 		  && !TREE_STATIC (inner)
 		  && DECL_CONTEXT (inner) == current_function_decl)
 		warning_at (loc,
-			    0, "function returns address of local variable");
+			    OPT_Wreturn_local_addr, "function returns address "
+			    "of local variable");
 	      break;
 
 	    default:
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index eaa0935..d2944d3 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8019,14 +8019,14 @@  maybe_warn_about_returning_address_of_local (tree retval)
       if (TREE_CODE (whats_returned) == AGGR_INIT_EXPR
 	  || TREE_CODE (whats_returned) == TARGET_EXPR)
 	{
-	  warning (0, "returning reference to temporary");
+	  warning (OPT_Wreturn_local_addr, "returning reference to temporary");
 	  return;
 	}
       if (TREE_CODE (whats_returned) == VAR_DECL
 	  && DECL_NAME (whats_returned)
 	  && TEMP_NAME_P (DECL_NAME (whats_returned)))
 	{
-	  warning (0, "reference to non-lvalue returned");
+	  warning (OPT_Wreturn_local_addr, "reference to non-lvalue returned");
 	  return;
 	}
     }
@@ -8042,10 +8042,10 @@  maybe_warn_about_returning_address_of_local (tree retval)
 	   || TREE_PUBLIC (whats_returned)))
     {
       if (TREE_CODE (valtype) == REFERENCE_TYPE)
-	warning (0, "reference to local variable %q+D returned",
+	warning (OPT_Wreturn_local_addr, "reference to local variable %q+D returned",
 		 whats_returned);
       else
-	warning (0, "address of local variable %q+D returned",
+	warning (OPT_Wreturn_local_addr, "address of local variable %q+D returned",
 		 whats_returned);
       return;
     }
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f8c9230..2e36de1 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -261,7 +261,7 @@  Objective-C and Objective-C++ Dialects}.
 -Woverlength-strings  -Wpacked  -Wpacked-bitfield-compat  -Wpadded @gol
 -Wparentheses  -Wpedantic-ms-format -Wno-pedantic-ms-format @gol
 -Wpointer-arith  -Wno-pointer-to-int-cast @gol
--Wredundant-decls @gol
+-Wredundant-decls  -Wno-return-local-addr @gol
 -Wreturn-type  -Wsequence-point  -Wshadow @gol
 -Wsign-compare  -Wsign-conversion  -Wsizeof-pointer-memaccess @gol
 -Wstack-protector -Wstack-usage=@var{len} -Wstrict-aliasing @gol
@@ -3526,6 +3526,12 @@  definitions, may be found on the GCC readings page, at
 
 This warning is enabled by @option{-Wall} for C and C++.
 
+@item -Wno-return-local-addr
+@opindex Wno-return-local-addr
+@opindex Wreturn-local-addr
+Do not warn about returning a pointer (or in C++, a reference) to a
+variable that goes out of scope after the function returns.
+
 @item -Wreturn-type
 @opindex Wreturn-type
 @opindex Wno-return-type
diff --git a/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C b/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
new file mode 100644
index 0000000..e15bfa2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wno-return-local-addr.C
@@ -0,0 +1,26 @@ 
+// { dg-do assemble  }
+// { dg-options "-Wno-return-local-addr" }
+
+int& bad1()
+{
+  int x = 0;
+  return x;
+}
+
+int* bad2()
+{
+  int x = 0;
+  return &x;
+}
+
+int f();
+
+const int& bad3()
+{
+  return f();
+}
+
+const int& bad4()
+{
+  return int();
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
new file mode 100644
index 0000000..faa3a34
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wreturn-local-addr.C
@@ -0,0 +1,20 @@ 
+// { dg-do assemble  }
+// { dg-options "-Werror=return-local-addr" }
+// { dg-message "some warnings being treated as errors" "" {target "*-*-*"} 0 }
+
+int& bad1()
+{
+  int x = 0;		// { dg-error "reference to local variable" }
+  return x;
+}
+
+int* bad2()
+{
+  int x = 0;		// { dg-error "address of local variable" }
+  return &x;
+}
+
+const int& bad4()
+{
+  return int();		// { dg-error "returning reference to temporary" }
+}
diff --git a/gcc/testsuite/gcc.dg/Wreturn-local-addr.c b/gcc/testsuite/gcc.dg/Wreturn-local-addr.c
new file mode 100644
index 0000000..d496d20
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wreturn-local-addr.c
@@ -0,0 +1,9 @@ 
+/* { dg-do assemble  } */
+/* { dg-options "-Werror=return-local-addr" } */
+/* { dg-message "some warnings being treated as errors" "" {target "*-*-*"} 0 } */
+
+int* bad()
+{
+  int x = 0;
+  return &x;		/* { dg-error "address of local variable" } */
+}