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

Paolo Carlini paolo.carlini@oracle.com
Fri Nov 29 13:12:00 GMT 2019


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.

//////////////////////

-------------- next part --------------
/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.
-------------- next part --------------
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;


More information about the Gcc-patches mailing list