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;

Reply via email to