[C++] A few more cp_expr_loc_or_input_loc and a diagnostic regression fix

Message ID 4d09ce98-58b8-1506-0dc5-2f7ff20241b1@oracle.com
State New
Headers show
Series
  • [C++] A few more cp_expr_loc_or_input_loc and a diagnostic regression fix
Related show

Commit Message

Paolo Carlini Nov. 29, 2019, 1:08 p.m.
Hi,

a few more rather straightforward uses for cp_expr_loc_or_input_loc.

Additionally, while working on the latter, I noticed that, compared to 
say, gcc-7, lately the code we have in cp_build_addr_expr_1 to diagnose 
taking the address of 'main' often doesn't work anymore, when the 
argument is wrapped in a location_wrapper. The below fixes that by using 
tree_strip_any_location_wrapper in the DECL_MAIN_P check, which works 
fine, but I can imagine various other ways to solve the issue... Tested 
x86_64-linux.

Thanks, Paolo.

//////////////////////
/cp
2019-11-29  Paolo Carlini  <paolo.carlini@oracle.com>

	* typeck.c (cp_build_addr_expr_1): Use cp_expr_loc_or_input_loc in a
	few additional places.
	(check_return_expr): Likewise.

	* typeck.c (cp_build_addr_expr_1): Use tree_strip_any_location_wrapper
	for address of main pedwarn.

/testsuite
2019-11-29  Paolo Carlini  <paolo.carlini@oracle.com>

	* g++.dg/diagnostic/inconsistent-deduction-1.C: New.
	* g++.dg/diagnostic/returning-a-value-1.C: Likewise.
	* g++.dg/cpp0x/decltype3.C: Check location(s) too.
	* g++.dg/cpp0x/decltype4.C: Likewise.
	* g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C: Likewise.
	* g++.dg/cpp2a/consteval13.C: Likewise.
	* g++.dg/expr/pmf-1.C: Likewise.
	* g++.dg/other/ptrmem2.C: Likewise.
	* g++.dg/template/ptrmem17.C: Likewise.
	* g++.old-deja/g++.bugs/900213_03.C: Likewise.
	* g++.old-deja/g++.other/pmf7.C: Likewise.
	* g++.old-deja/g++.other/ptrmem7.C: Likewise.

	* g++.dg/diagnostic/main2.C: New.

Comments

Jason Merrill Dec. 2, 2019, 6:58 p.m. | #1
On 11/29/19 8:08 AM, Paolo Carlini wrote:
> Hi,

> 

> a few more rather straightforward uses for cp_expr_loc_or_input_loc.

> 

> Additionally, while working on the latter, I noticed that, compared to 

> say, gcc-7, lately the code we have in cp_build_addr_expr_1 to diagnose 

> taking the address of 'main' often doesn't work anymore, when the 

> argument is wrapped in a location_wrapper. The below fixes that by using 

> tree_strip_any_location_wrapper in the DECL_MAIN_P check, which works 

> fine, but I can imagine various other ways to solve the issue...


Maybe

location_t loc = cp_expr_loc_or_input_loc (arg);
STRIP_ANY_LOCATION_WRAPPER (arg);

at the top?  In general I prefer the local variable to writing 
cp_expr_loc_or_input_loc in lots of places, whether or not we then strip 
wrappers.

Jason
Paolo Carlini Dec. 2, 2019, 10:22 p.m. | #2
Hi,

On 02/12/19 19:58, Jason Merrill wrote:
> On 11/29/19 8:08 AM, Paolo Carlini wrote:

>> Hi,

>>

>> a few more rather straightforward uses for cp_expr_loc_or_input_loc.

>>

>> Additionally, while working on the latter, I noticed that, compared 

>> to say, gcc-7, lately the code we have in cp_build_addr_expr_1 to 

>> diagnose taking the address of 'main' often doesn't work anymore, 

>> when the argument is wrapped in a location_wrapper. The below fixes 

>> that by using tree_strip_any_location_wrapper in the DECL_MAIN_P 

>> check, which works fine, but I can imagine various other ways to 

>> solve the issue...

>

> Maybe

>

> location_t loc = cp_expr_loc_or_input_loc (arg);

> STRIP_ANY_LOCATION_WRAPPER (arg);

>

> at the top?  In general I prefer the local variable to writing 

> cp_expr_loc_or_input_loc in lots of places, whether or not we then 

> strip wrappers.


Sure. In a few circumstances I hesitated because 
cp_expr_loc_or_input_loc isn't really trivial, boils down to quite a few 
conditionals, and adds a bit to the complexity of simple functions when 
in fact no errors nor warnings are issued. But certainly calling it at 
the top is often much cleaner. I changed both the functions.

However, using STRIP_ANY_LOCATION_WRAPPER at the beginning of 
cp_build_addr_expr_1 doesn't seem straightforward, causes a few 
regressions (wrong location for conversion/Wwrite-strings.C; even an ICE 
for cpp1z/constexpr-lambda23.C; cpp1z/decomp48.C). The function doesn't 
seem trivial from this point of view, there is already a localized 
tree_strip_any_location_wrapper near the end, for 
processing_template_decl. I would rather further investigate that kind 
of simplification in a separate patch, beyond the regression fix. 
(before I would like to improve the locations for all the various kinds 
of cast, quite a few changes)

Thanks, Paolo.

///////////////////////
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 278911)
+++ cp/typeck.c	(working copy)
@@ -6061,6 +6061,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 {
   tree argtype;
   tree val;
+  location_t loc;
 
   if (!arg || error_operand_p (arg))
     return error_mark_node;
@@ -6070,6 +6071,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
     return error_mark_node;
 
   argtype = lvalue_type (arg);
+  loc = cp_expr_loc_or_input_loc (arg);
 
   gcc_assert (!(identifier_p (arg) && IDENTIFIER_ANY_OP_P (arg)));
 
@@ -6103,12 +6105,14 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	  else if (current_class_type
 		   && TREE_OPERAND (arg, 0) == current_class_ref)
 	    /* An expression like &memfn.  */
-	    permerror (input_location, "ISO C++ forbids taking the address of an unqualified"
+	    permerror (loc,
+		       "ISO C++ forbids taking the address of an unqualified"
 		       " or parenthesized non-static member function to form"
 		       " a pointer to member function.  Say %<&%T::%D%>",
 		       base, name);
 	  else
-	    permerror (input_location, "ISO C++ forbids taking the address of a bound member"
+	    permerror (loc,
+		       "ISO C++ forbids taking the address of a bound member"
 		       " function to form a pointer to member function."
 		       "  Say %<&%T::%D%>",
 		       base, name);
@@ -6135,7 +6139,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
       if (kind == clk_none)
 	{
 	  if (complain & tf_error)
-	    lvalue_error (cp_expr_loc_or_input_loc (arg), lv_addressof);
+	    lvalue_error (loc, lv_addressof);
 	  return error_mark_node;
 	}
       if (strict_lvalue && (kind & (clk_rvalueref|clk_class)))
@@ -6143,8 +6147,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	  if (!(complain & tf_error))
 	    return error_mark_node;
 	  /* Make this a permerror because we used to accept it.  */
-	  permerror (cp_expr_loc_or_input_loc (arg),
-		     "taking address of rvalue");
+	  permerror (loc, "taking address of rvalue");
 	}
     }
 
@@ -6154,13 +6157,13 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
       arg = build1 (CONVERT_EXPR, type, arg);
       return arg;
     }
-  else if (pedantic && DECL_MAIN_P (arg))
+  else if (pedantic && DECL_MAIN_P (tree_strip_any_location_wrapper (arg)))
     {
       /* ARM $3.4 */
       /* Apparently a lot of autoconf scripts for C++ packages do this,
 	 so only complain if -Wpedantic.  */
       if (complain & (flag_pedantic_errors ? tf_error : tf_warning))
-	pedwarn (input_location, OPT_Wpedantic,
+	pedwarn (loc, OPT_Wpedantic,
 		 "ISO C++ forbids taking address of function %<::main%>");
       else if (flag_pedantic_errors)
 	return error_mark_node;
@@ -6218,7 +6221,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	if (TYPE_REF_P (TREE_TYPE (t)))
 	  {
 	    if (complain & tf_error)
-	      error ("cannot create pointer to reference member %qD", t);
+	      error_at (loc,
+			"cannot create pointer to reference member %qD", t);
 	    return error_mark_node;
 	  }
 
@@ -6238,8 +6242,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
   if (bitfield_p (arg))
     {
       if (complain & tf_error)
-	error_at (cp_expr_loc_or_input_loc (arg),
-		  "attempt to take address of bit-field");
+	error_at (loc, "attempt to take address of bit-field");
       return error_mark_node;
     }
 
@@ -6254,8 +6257,8 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	      || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl)))
 	{
 	  if (complain & tf_error)
-	    error ("taking address of an immediate function %qD",
-		   stripped_arg);
+	    error_at (loc, "taking address of an immediate function %qD",
+		      stripped_arg);
 	  return error_mark_node;
 	}
       if (TREE_CODE (stripped_arg) == FUNCTION_DECL
@@ -9676,6 +9679,7 @@ check_return_expr (tree retval, bool *no_warning)
      the declared type is incomplete.  */
   tree functype;
   int fn_returns_value_p;
+  location_t loc = cp_expr_loc_or_input_loc (retval);
 
   *no_warning = false;
 
@@ -9689,7 +9693,7 @@ check_return_expr (tree retval, bool *no_warning)
   if (DECL_DESTRUCTOR_P (current_function_decl))
     {
       if (retval)
-	error ("returning a value from a destructor");
+	error_at (loc, "returning a value from a destructor");
       return NULL_TREE;
     }
   else if (DECL_CONSTRUCTOR_P (current_function_decl))
@@ -9700,7 +9704,7 @@ check_return_expr (tree retval, bool *no_warning)
 	error ("cannot return from a handler of a function-try-block of a constructor");
       else if (retval)
 	/* You can't return a value from a constructor.  */
-	error ("returning a value from a constructor");
+	error_at (loc, "returning a value from a constructor");
       return NULL_TREE;
     }
 
@@ -9762,11 +9766,11 @@ check_return_expr (tree retval, bool *no_warning)
       else if (!same_type_p (type, functype))
 	{
 	  if (LAMBDA_FUNCTION_P (current_function_decl))
-	    error ("inconsistent types %qT and %qT deduced for "
-		   "lambda return type", functype, type);
+	    error_at (loc, "inconsistent types %qT and %qT deduced for "
+		      "lambda return type", functype, type);
 	  else
-	    error ("inconsistent deduction for auto return type: "
-		   "%qT and then %qT", functype, type);
+	    error_at (loc, "inconsistent deduction for auto return type: "
+		      "%qT and then %qT", functype, type);
 	}
       functype = type;
     }
@@ -9800,8 +9804,7 @@ check_return_expr (tree retval, bool *no_warning)
 	   its side-effects.  */
 	finish_expr_stmt (retval);
       else if (retval != error_mark_node)
-	permerror (input_location,
-		   "return-statement with a value, in function "
+	permerror (loc, "return-statement with a value, in function "
 		   "returning %qT", valtype);
       current_function_returns_null = 1;
 
@@ -9857,7 +9860,8 @@ check_return_expr (tree retval, bool *no_warning)
 	}
 
       if (warn)
-	warning (OPT_Weffc__, "%<operator=%> should return a reference to %<*this%>");
+	warning_at (loc, OPT_Weffc__,
+		    "%<operator=%> should return a reference to %<*this%>");
     }
 
   if (dependent_type_p (functype)
Index: testsuite/g++.dg/cpp0x/decltype3.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype3.C	(revision 278911)
+++ testsuite/g++.dg/cpp0x/decltype3.C	(working copy)
@@ -54,7 +54,7 @@ class B {
 }; 
 
 CHECK_DECLTYPE(decltype(aa.*&A::a), int&);
-decltype(aa.*&A::b) zz; // { dg-error "cannot create pointer to reference member" "cannot" }
+decltype(aa.*&A::b) zz; // { dg-error "18:cannot create pointer to reference member" "cannot" }
 
 CHECK_DECLTYPE(decltype(caa.*&A::a), const int&);
 
Index: testsuite/g++.dg/cpp0x/decltype4.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype4.C	(revision 278911)
+++ testsuite/g++.dg/cpp0x/decltype4.C	(working copy)
@@ -23,7 +23,7 @@ struct A {
 }; 
 
 CHECK_DECLTYPE(decltype(&A::x), int A::*);
-decltype(&A::y) Ay; // { dg-error "cannot create pointer to reference member|invalid type" }
+decltype(&A::y) Ay; // { dg-error "14:cannot create pointer to reference member|invalid type" }
 CHECK_DECLTYPE(decltype(&A::foo), int (A::*) (char));
 CHECK_DECLTYPE(decltype(&A::bar), int& (A::*) () const);
 
Index: testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C
===================================================================
--- testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C	(revision 278911)
+++ testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C	(working copy)
@@ -11,7 +11,7 @@ template <class T> int f (T t) {
     if (b)
       return t.fn1();
     else
-      return t.fn2();		// { dg-error "inconsistent types" }
+      return t.fn2();		// { dg-error "19:inconsistent types" }
   }(t);
 }
 
Index: testsuite/g++.dg/cpp2a/consteval13.C
===================================================================
--- testsuite/g++.dg/cpp2a/consteval13.C	(revision 278911)
+++ testsuite/g++.dg/cpp2a/consteval13.C	(working copy)
@@ -10,8 +10,8 @@ void
 foo ()
 {
    auto qux = [] (fnptr a = quux ()) consteval { return a (); };
-   constexpr auto c = qux (baz);	// { dg-error "taking address of an immediate function" }
-   constexpr auto d = qux (bar);	// { dg-error "taking address of an immediate function" }
+   constexpr auto c = qux (baz);	// { dg-error "28:taking address of an immediate function" }
+   constexpr auto d = qux (bar);	// { dg-error "28:taking address of an immediate function" }
    static_assert (c == 1);
    static_assert (d == 42);
 }
Index: testsuite/g++.dg/diagnostic/inconsistent-deduction-1.C
===================================================================
--- testsuite/g++.dg/diagnostic/inconsistent-deduction-1.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/inconsistent-deduction-1.C	(working copy)
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++14 } }
+
+void foo();
+
+auto bar(bool b)
+{
+  if (b)
+    return 0;
+  return foo(); // { dg-error "13:inconsistent deduction for auto return type: .int. and then .void." }
+}
Index: testsuite/g++.dg/diagnostic/main2.C
===================================================================
--- testsuite/g++.dg/diagnostic/main2.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/main2.C	(working copy)
@@ -0,0 +1,12 @@
+int main ();
+
+typedef int (*fptr) ();
+
+void foo (fptr);
+
+fptr bar ()
+{
+  foo (main);  // { dg-error "8:ISO C\\+\\+ forbids taking address of function" }
+
+  return main;  // { dg-error "10:ISO C\\+\\+ forbids taking address of function" }
+}
Index: testsuite/g++.dg/diagnostic/returning-a-value-1.C
===================================================================
--- testsuite/g++.dg/diagnostic/returning-a-value-1.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/returning-a-value-1.C	(working copy)
@@ -0,0 +1,8 @@
+int foo();
+
+struct A
+{
+  A() { return foo(); }  // { dg-error "19:returning a value" }
+  ~A() { return foo(); }  // { dg-error "20:returning a value" }
+  void bar() { return foo(); }  // { dg-error "26:return-statement with a value" }
+};
Index: testsuite/g++.dg/expr/pmf-1.C
===================================================================
--- testsuite/g++.dg/expr/pmf-1.C	(revision 278911)
+++ testsuite/g++.dg/expr/pmf-1.C	(working copy)
@@ -13,7 +13,7 @@ struct A
   void h()
   {
     void (A::*p)() = &A::f;
-    void (A::*q)() = &(A::f);       // { dg-error "parenthesized" }
+    void (A::*q)() = &(A::f);       // { dg-error "27:ISO C\\+\\+ forbids taking the address of an unqualified or parenthesized" }
     foo(&g<int>);                   // { dg-error "cannot convert" }
   }
 };
Index: testsuite/g++.dg/other/ptrmem2.C
===================================================================
--- testsuite/g++.dg/other/ptrmem2.C	(revision 278911)
+++ testsuite/g++.dg/other/ptrmem2.C	(working copy)
@@ -19,7 +19,7 @@ template<class T> int f2(T x);
 
 int D::Foo ()
 {
-  f1( &D::m);   // { dg-error "cannot create pointer to ref" }
+  f1( &D::m);   // { dg-error "11:cannot create pointer to ref" }
   f1( &(D::m));	// ok
   f2( &D::s);   // ok
   f2( &(D::s)); // ok
@@ -28,7 +28,7 @@ int D::Foo ()
 
 int Foo ()
 {
-  f1( &D::m);    // { dg-error "cannot create pointer to ref" }
+  f1( &D::m);    // { dg-error "11:cannot create pointer to ref" }
   f1( &(D::m));  // { dg-error "non-static" }
   f2( &D::s);    // ok
   f2( &(D::s));  // ok
Index: testsuite/g++.dg/template/ptrmem17.C
===================================================================
--- testsuite/g++.dg/template/ptrmem17.C	(revision 278911)
+++ testsuite/g++.dg/template/ptrmem17.C	(working copy)
@@ -4,7 +4,7 @@ template<int> struct A
 {
   int& i;
   A();
-  ~A() { &A::i; } // { dg-error "reference" }
+  ~A() { &A::i; } // { dg-error "14:cannot create pointer to reference" }
 };
 
 A<0> a;
Index: testsuite/g++.old-deja/g++.bugs/900213_03.C
===================================================================
--- testsuite/g++.old-deja/g++.bugs/900213_03.C	(revision 278911)
+++ testsuite/g++.old-deja/g++.bugs/900213_03.C	(working copy)
@@ -21,7 +21,7 @@ struct0 *ptr;
 
 void global_function_0 ()
 {
-  fmp = &ptr->function_member;	// { dg-error "" } 
+  fmp = &ptr->function_member;	// { dg-error "15:ISO C\\+\\+ forbids taking the address of a bound member function" } 
   //dmp = &ptr->data_member;	//  caught by g++, missed by cfront
 }
 
Index: testsuite/g++.old-deja/g++.other/pmf7.C
===================================================================
--- testsuite/g++.old-deja/g++.other/pmf7.C	(revision 278911)
+++ testsuite/g++.old-deja/g++.other/pmf7.C	(working copy)
@@ -12,5 +12,5 @@ int main ()
 {
   A a;
   &a.f;				// { dg-error "" } overloaded
-  &a.g;				// { dg-error "" } can't write a pmf like this
+  &a.g;				// { dg-error "6:ISO C\\+\\+ forbids taking the address of a bound member function" } can't write a pmf like this
 }
Index: testsuite/g++.old-deja/g++.other/ptrmem7.C
===================================================================
--- testsuite/g++.old-deja/g++.other/ptrmem7.C	(revision 278911)
+++ testsuite/g++.old-deja/g++.other/ptrmem7.C	(working copy)
@@ -36,7 +36,7 @@ void A::foo ()
   int (A::*ptr14) (int) = single;         // { dg-error "cannot convert" }
 
   int (A::*ptr20) (int) = &(A::ns);       // { dg-error "pointer to member" }
-  int (A::*ptr21) (int) = &(A::single);   // { dg-error "pointer to member" }
+  int (A::*ptr21) (int) = &(A::single);   // { dg-error "32:ISO C\\+\\+ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member" }
 
   int (*ptr31) (short) = &A::sole;
   int (*ptr32) (short) = A::sole;
Jason Merrill Dec. 3, 2019, 7:19 p.m. | #3
On 12/2/19 5:22 PM, Paolo Carlini wrote:
> Hi,

> 

> On 02/12/19 19:58, Jason Merrill wrote:

>> On 11/29/19 8:08 AM, Paolo Carlini wrote:

>>> Hi,

>>>

>>> a few more rather straightforward uses for cp_expr_loc_or_input_loc.

>>>

>>> Additionally, while working on the latter, I noticed that, compared 

>>> to say, gcc-7, lately the code we have in cp_build_addr_expr_1 to 

>>> diagnose taking the address of 'main' often doesn't work anymore, 

>>> when the argument is wrapped in a location_wrapper. The below fixes 

>>> that by using tree_strip_any_location_wrapper in the DECL_MAIN_P 

>>> check, which works fine, but I can imagine various other ways to 

>>> solve the issue...

>>

>> Maybe

>>

>> location_t loc = cp_expr_loc_or_input_loc (arg);

>> STRIP_ANY_LOCATION_WRAPPER (arg);

>>

>> at the top?  In general I prefer the local variable to writing 

>> cp_expr_loc_or_input_loc in lots of places, whether or not we then 

>> strip wrappers.

> 

> Sure. In a few circumstances I hesitated because 

> cp_expr_loc_or_input_loc isn't really trivial, boils down to quite a few 

> conditionals, and adds a bit to the complexity of simple functions when 

> in fact no errors nor warnings are issued. But certainly calling it at 

> the top is often much cleaner. I changed both the functions.

> 

> However, using STRIP_ANY_LOCATION_WRAPPER at the beginning of 

> cp_build_addr_expr_1 doesn't seem straightforward, causes a few 

> regressions (wrong location for conversion/Wwrite-strings.C; even an ICE 

> for cpp1z/constexpr-lambda23.C; cpp1z/decomp48.C). The function doesn't 

> seem trivial from this point of view, there is already a localized 

> tree_strip_any_location_wrapper near the end, for 

> processing_template_decl. I would rather further investigate that kind 

> of simplification in a separate patch, beyond the regression fix. 

> (before I would like to improve the locations for all the various kinds 

> of cast, quite a few changes)


Absolutely, if it isn't simple don't bother.

> @@ -6061,6 +6061,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue

>  {

>    tree argtype;

>    tree val;

> +  location_t loc;

>  

>    if (!arg || error_operand_p (arg))

>      return error_mark_node;

> @@ -6070,6 +6071,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue

>      return error_mark_node;

>  

>    argtype = lvalue_type (arg);

> +  loc = cp_expr_loc_or_input_loc (arg);


You don't need to separately declare the variable at the top of the 
function anymore.  OK with that change.

Jason

Patch

Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 278834)
+++ cp/typeck.c	(working copy)
@@ -6103,12 +6103,14 @@  cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	  else if (current_class_type
 		   && TREE_OPERAND (arg, 0) == current_class_ref)
 	    /* An expression like &memfn.  */
-	    permerror (input_location, "ISO C++ forbids taking the address of an unqualified"
+	    permerror (cp_expr_loc_or_input_loc (arg),
+		       "ISO C++ forbids taking the address of an unqualified"
 		       " or parenthesized non-static member function to form"
 		       " a pointer to member function.  Say %<&%T::%D%>",
 		       base, name);
 	  else
-	    permerror (input_location, "ISO C++ forbids taking the address of a bound member"
+	    permerror (cp_expr_loc_or_input_loc (arg),
+		       "ISO C++ forbids taking the address of a bound member"
 		       " function to form a pointer to member function."
 		       "  Say %<&%T::%D%>",
 		       base, name);
@@ -6154,13 +6156,13 @@  cp_build_addr_expr_1 (tree arg, bool strict_lvalue
       arg = build1 (CONVERT_EXPR, type, arg);
       return arg;
     }
-  else if (pedantic && DECL_MAIN_P (arg))
+  else if (pedantic && DECL_MAIN_P (tree_strip_any_location_wrapper (arg)))
     {
       /* ARM $3.4 */
       /* Apparently a lot of autoconf scripts for C++ packages do this,
 	 so only complain if -Wpedantic.  */
       if (complain & (flag_pedantic_errors ? tf_error : tf_warning))
-	pedwarn (input_location, OPT_Wpedantic,
+	pedwarn (cp_expr_loc_or_input_loc (arg), OPT_Wpedantic,
 		 "ISO C++ forbids taking address of function %<::main%>");
       else if (flag_pedantic_errors)
 	return error_mark_node;
@@ -6218,7 +6220,8 @@  cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	if (TYPE_REF_P (TREE_TYPE (t)))
 	  {
 	    if (complain & tf_error)
-	      error ("cannot create pointer to reference member %qD", t);
+	      error_at (cp_expr_loc_or_input_loc (arg),
+			"cannot create pointer to reference member %qD", t);
 	    return error_mark_node;
 	  }
 
@@ -6254,8 +6257,9 @@  cp_build_addr_expr_1 (tree arg, bool strict_lvalue
 	      || !DECL_IMMEDIATE_FUNCTION_P (current_function_decl)))
 	{
 	  if (complain & tf_error)
-	    error ("taking address of an immediate function %qD",
-		   stripped_arg);
+	    error_at (cp_expr_loc_or_input_loc (arg),
+		      "taking address of an immediate function %qD",
+		      stripped_arg);
 	  return error_mark_node;
 	}
       if (TREE_CODE (stripped_arg) == FUNCTION_DECL
@@ -9689,7 +9693,8 @@  check_return_expr (tree retval, bool *no_warning)
   if (DECL_DESTRUCTOR_P (current_function_decl))
     {
       if (retval)
-	error ("returning a value from a destructor");
+	error_at (cp_expr_loc_or_input_loc (retval),
+		  "returning a value from a destructor");
       return NULL_TREE;
     }
   else if (DECL_CONSTRUCTOR_P (current_function_decl))
@@ -9700,7 +9705,8 @@  check_return_expr (tree retval, bool *no_warning)
 	error ("cannot return from a handler of a function-try-block of a constructor");
       else if (retval)
 	/* You can't return a value from a constructor.  */
-	error ("returning a value from a constructor");
+	error_at (cp_expr_loc_or_input_loc (retval),
+		  "returning a value from a constructor");
       return NULL_TREE;
     }
 
@@ -9762,11 +9768,13 @@  check_return_expr (tree retval, bool *no_warning)
       else if (!same_type_p (type, functype))
 	{
 	  if (LAMBDA_FUNCTION_P (current_function_decl))
-	    error ("inconsistent types %qT and %qT deduced for "
-		   "lambda return type", functype, type);
+	    error_at (cp_expr_loc_or_input_loc (retval),
+		      "inconsistent types %qT and %qT deduced for "
+		      "lambda return type", functype, type);
 	  else
-	    error ("inconsistent deduction for auto return type: "
-		   "%qT and then %qT", functype, type);
+	    error_at (cp_expr_loc_or_input_loc (retval),
+		      "inconsistent deduction for auto return type: "
+		      "%qT and then %qT", functype, type);
 	}
       functype = type;
     }
@@ -9800,7 +9808,7 @@  check_return_expr (tree retval, bool *no_warning)
 	   its side-effects.  */
 	finish_expr_stmt (retval);
       else if (retval != error_mark_node)
-	permerror (input_location,
+	permerror (cp_expr_loc_or_input_loc (retval),
 		   "return-statement with a value, in function "
 		   "returning %qT", valtype);
       current_function_returns_null = 1;
Index: testsuite/g++.dg/cpp0x/decltype3.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype3.C	(revision 278834)
+++ testsuite/g++.dg/cpp0x/decltype3.C	(working copy)
@@ -54,7 +54,7 @@  class B {
 }; 
 
 CHECK_DECLTYPE(decltype(aa.*&A::a), int&);
-decltype(aa.*&A::b) zz; // { dg-error "cannot create pointer to reference member" "cannot" }
+decltype(aa.*&A::b) zz; // { dg-error "18:cannot create pointer to reference member" "cannot" }
 
 CHECK_DECLTYPE(decltype(caa.*&A::a), const int&);
 
Index: testsuite/g++.dg/cpp0x/decltype4.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype4.C	(revision 278834)
+++ testsuite/g++.dg/cpp0x/decltype4.C	(working copy)
@@ -23,7 +23,7 @@  struct A {
 }; 
 
 CHECK_DECLTYPE(decltype(&A::x), int A::*);
-decltype(&A::y) Ay; // { dg-error "cannot create pointer to reference member|invalid type" }
+decltype(&A::y) Ay; // { dg-error "14:cannot create pointer to reference member|invalid type" }
 CHECK_DECLTYPE(decltype(&A::foo), int (A::*) (char));
 CHECK_DECLTYPE(decltype(&A::bar), int& (A::*) () const);
 
Index: testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C
===================================================================
--- testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C	(revision 278834)
+++ testsuite/g++.dg/cpp0x/lambda/lambda-deduce-ext-neg.C	(working copy)
@@ -11,7 +11,7 @@  template <class T> int f (T t) {
     if (b)
       return t.fn1();
     else
-      return t.fn2();		// { dg-error "inconsistent types" }
+      return t.fn2();		// { dg-error "19:inconsistent types" }
   }(t);
 }
 
Index: testsuite/g++.dg/cpp2a/consteval13.C
===================================================================
--- testsuite/g++.dg/cpp2a/consteval13.C	(revision 278834)
+++ testsuite/g++.dg/cpp2a/consteval13.C	(working copy)
@@ -10,8 +10,8 @@  void
 foo ()
 {
    auto qux = [] (fnptr a = quux ()) consteval { return a (); };
-   constexpr auto c = qux (baz);	// { dg-error "taking address of an immediate function" }
-   constexpr auto d = qux (bar);	// { dg-error "taking address of an immediate function" }
+   constexpr auto c = qux (baz);	// { dg-error "28:taking address of an immediate function" }
+   constexpr auto d = qux (bar);	// { dg-error "28:taking address of an immediate function" }
    static_assert (c == 1);
    static_assert (d == 42);
 }
Index: testsuite/g++.dg/diagnostic/inconsistent-deduction-1.C
===================================================================
--- testsuite/g++.dg/diagnostic/inconsistent-deduction-1.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/inconsistent-deduction-1.C	(working copy)
@@ -0,0 +1,9 @@ 
+// { dg-do compile { target c++14 } }
+
+void foo();
+auto bar(bool b)
+{
+  if (b)
+    return 0;
+  return foo(); // { dg-error "13:inconsistent deduction for auto return type: .int. and then .void." }
+}
Index: testsuite/g++.dg/diagnostic/main2.C
===================================================================
--- testsuite/g++.dg/diagnostic/main2.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/main2.C	(working copy)
@@ -0,0 +1,8 @@ 
+int main ();
+
+void foo (int (*) ());
+
+void bar ()
+{
+  foo (main);  // { dg-error "8:ISO C\\+\\+ forbids taking address of function" }
+}
Index: testsuite/g++.dg/diagnostic/returning-a-value-1.C
===================================================================
--- testsuite/g++.dg/diagnostic/returning-a-value-1.C	(nonexistent)
+++ testsuite/g++.dg/diagnostic/returning-a-value-1.C	(working copy)
@@ -0,0 +1,8 @@ 
+int foo();
+
+struct A
+{
+  A() { return foo(); }  // { dg-error "19:returning a value" }
+  ~A() { return foo(); }  // { dg-error "20:returning a value" }
+  void bar() { return foo(); }  // { dg-error "26:return-statement with a value" }
+};
Index: testsuite/g++.dg/expr/pmf-1.C
===================================================================
--- testsuite/g++.dg/expr/pmf-1.C	(revision 278834)
+++ testsuite/g++.dg/expr/pmf-1.C	(working copy)
@@ -13,7 +13,7 @@  struct A
   void h()
   {
     void (A::*p)() = &A::f;
-    void (A::*q)() = &(A::f);       // { dg-error "parenthesized" }
+    void (A::*q)() = &(A::f);       // { dg-error "27:ISO C\\+\\+ forbids taking the address of an unqualified or parenthesized" }
     foo(&g<int>);                   // { dg-error "cannot convert" }
   }
 };
Index: testsuite/g++.dg/other/ptrmem2.C
===================================================================
--- testsuite/g++.dg/other/ptrmem2.C	(revision 278834)
+++ testsuite/g++.dg/other/ptrmem2.C	(working copy)
@@ -19,7 +19,7 @@  template<class T> int f2(T x);
 
 int D::Foo ()
 {
-  f1( &D::m);   // { dg-error "cannot create pointer to ref" }
+  f1( &D::m);   // { dg-error "11:cannot create pointer to ref" }
   f1( &(D::m));	// ok
   f2( &D::s);   // ok
   f2( &(D::s)); // ok
@@ -28,7 +28,7 @@  int D::Foo ()
 
 int Foo ()
 {
-  f1( &D::m);    // { dg-error "cannot create pointer to ref" }
+  f1( &D::m);    // { dg-error "11:cannot create pointer to ref" }
   f1( &(D::m));  // { dg-error "non-static" }
   f2( &D::s);    // ok
   f2( &(D::s));  // ok
Index: testsuite/g++.dg/template/ptrmem17.C
===================================================================
--- testsuite/g++.dg/template/ptrmem17.C	(revision 278834)
+++ testsuite/g++.dg/template/ptrmem17.C	(working copy)
@@ -4,7 +4,7 @@  template<int> struct A
 {
   int& i;
   A();
-  ~A() { &A::i; } // { dg-error "reference" }
+  ~A() { &A::i; } // { dg-error "14:cannot create pointer to reference" }
 };
 
 A<0> a;
Index: testsuite/g++.old-deja/g++.bugs/900213_03.C
===================================================================
--- testsuite/g++.old-deja/g++.bugs/900213_03.C	(revision 278834)
+++ testsuite/g++.old-deja/g++.bugs/900213_03.C	(working copy)
@@ -21,7 +21,7 @@  struct0 *ptr;
 
 void global_function_0 ()
 {
-  fmp = &ptr->function_member;	// { dg-error "" } 
+  fmp = &ptr->function_member;	// { dg-error "15:ISO C\\+\\+ forbids taking the address of a bound member function" } 
   //dmp = &ptr->data_member;	//  caught by g++, missed by cfront
 }
 
Index: testsuite/g++.old-deja/g++.other/pmf7.C
===================================================================
--- testsuite/g++.old-deja/g++.other/pmf7.C	(revision 278834)
+++ testsuite/g++.old-deja/g++.other/pmf7.C	(working copy)
@@ -12,5 +12,5 @@  int main ()
 {
   A a;
   &a.f;				// { dg-error "" } overloaded
-  &a.g;				// { dg-error "" } can't write a pmf like this
+  &a.g;				// { dg-error "6:ISO C\\+\\+ forbids taking the address of a bound member function" } can't write a pmf like this
 }
Index: testsuite/g++.old-deja/g++.other/ptrmem7.C
===================================================================
--- testsuite/g++.old-deja/g++.other/ptrmem7.C	(revision 278834)
+++ testsuite/g++.old-deja/g++.other/ptrmem7.C	(working copy)
@@ -36,7 +36,7 @@  void A::foo ()
   int (A::*ptr14) (int) = single;         // { dg-error "cannot convert" }
 
   int (A::*ptr20) (int) = &(A::ns);       // { dg-error "pointer to member" }
-  int (A::*ptr21) (int) = &(A::single);   // { dg-error "pointer to member" }
+  int (A::*ptr21) (int) = &(A::single);   // { dg-error "32:ISO C\\+\\+ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member" }
 
   int (*ptr31) (short) = &A::sole;
   int (*ptr32) (short) = A::sole;