Hi,

this diagnostic issue is about not even trying to print expressions in error messages involving operators, and print operand types instead. Just as an example, for:

struct X { int x; };
void trigger (X x []) { x [01] = 0; }

we currently print:

error: no match for ‘operator=’ in ‘*(x + 4u) = 0’

which the patch changes to:

error: no match for ‘operator=’ (operand types are ‘X’ and ‘int’)

Or, for the existing other/error10.C, from:

error: no match for ‘operator-’ in ‘-(* & a)’

to

error: no match for ‘operator-’ (operand type is ‘A<0>’)

Jon and Manuel checked clang and I checked what icc does: without the caret, I don't think we can do *much* better here, but, wrt the audit trail discussion, I'm proposing printing the actual operand types between parentheses - I got the general idea from icc - because we don't want to confuse parameters and arguments.

Tested x86_64-linux.

Thanks,
Paolo.

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




/cp
2012-03-21  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/49152
        * call.c (op_error): Don't try to print expressions, print types.

/testsuite
2012-03-21  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/49152
        * g++.dg/diagnostic/operator1.C: New.
        * g++.dg/ext/label5.C: Adjust.
        * g++.dg/ext/va-arg1.C: Likewise.
        * g++.dg/other/error20.C: Likewise.
        * g++.dg/other/error20.C: Likewise.
        * g++.dg/other/error16.C: Likewise.
        * g++.dg/other/error10.C: Likewise.
        * g++.dg/parse/error30.C: Likewise.
        * g++.dg/cpp0x/lambda/lambda-err1.C: Likewise.
Index: testsuite/g++.dg/ext/label5.C
===================================================================
--- testsuite/g++.dg/ext/label5.C       (revision 185603)
+++ testsuite/g++.dg/ext/label5.C       (working copy)
@@ -2,5 +2,5 @@
 // PR c++/24052
 
 struct A { };
-int main() { b: A() && && b; } // { dg-error "A\\(\\) && && *b" }
+int main() { b: A() && && b; } // { dg-error "operand types are 'A' and 
'void\\*'" }
 // { dg-message "candidate|operator&&|no known conversion" "additional" { 
target *-*-* } 5 }
Index: testsuite/g++.dg/ext/va-arg1.C
===================================================================
--- testsuite/g++.dg/ext/va-arg1.C      (revision 185603)
+++ testsuite/g++.dg/ext/va-arg1.C      (working copy)
@@ -4,5 +4,5 @@ struct A {};
 
 void foo()
 {
-  ++__builtin_va_arg(0, A); // { dg-error "'\\+\\+va_arg\\(0, A\\)'" }
+  ++__builtin_va_arg(0, A); // { dg-error "operand type is 'A'" }
 }
Index: testsuite/g++.dg/other/error20.C
===================================================================
--- testsuite/g++.dg/other/error20.C    (revision 185603)
+++ testsuite/g++.dg/other/error20.C    (working copy)
@@ -8,6 +8,6 @@ struct A                        // { dg-message "operator=|no 
known con
 
 void bar (A& a)
 {
-  a.foo () = 0; // { dg-error "A::foo\\(\\) = 0" }
+  a.foo () = 0; // { dg-error "operand types are 'A' and 'int'" }
   // { dg-message "candidate" "candidate note" { target *-*-* } 11 }
 }   
Index: testsuite/g++.dg/other/error16.C
===================================================================
--- testsuite/g++.dg/other/error16.C    (revision 185603)
+++ testsuite/g++.dg/other/error16.C    (working copy)
@@ -10,5 +10,5 @@ typedef Outer<X> XOuter;
 
 int main() {
   Outer<int>  ab;
-  ab.foo() == 1; // { dg-error "ab.Outer" }
+  ab.foo() == 1; // { dg-error "operand types are 'Outer<int>::Inner' and 
'int'" }
 }
Index: testsuite/g++.dg/other/error10.C
===================================================================
--- testsuite/g++.dg/other/error10.C    (revision 185603)
+++ testsuite/g++.dg/other/error10.C    (working copy)
@@ -6,10 +6,9 @@ template<int> struct A {};
 
 template<int N>
 void foo(const A<N> &a)
-{ -A<N>(a); } // { dg-error "\\(\\* & a\\)" "" }
+{ -A<N>(a); } // { dg-error "operand type is 'A<0>'" }
 
 void bar()
 {
     foo(A<0>()); // { dg-message "required from here" "" }
 }
-
Index: testsuite/g++.dg/diagnostic/operator1.C
===================================================================
--- testsuite/g++.dg/diagnostic/operator1.C     (revision 0)
+++ testsuite/g++.dg/diagnostic/operator1.C     (revision 0)
@@ -0,0 +1,4 @@
+// PR c++/49152
+
+struct X { int x; }; 
+void trigger (X x []) { x [01] = 0; } // { dg-error "operand types are 'X' and 
'int'" }
Index: testsuite/g++.dg/parse/error30.C
===================================================================
--- testsuite/g++.dg/parse/error30.C    (revision 185603)
+++ testsuite/g++.dg/parse/error30.C    (working copy)
@@ -8,5 +8,5 @@ struct A
   A(int);
 };
 
-A a = -A();    // { dg-error "10:no match for.*operator-.*in.*-A\\(\\)" }
-A b = -A(5);   // { dg-error "11:no match for.*operator-.*in.*-A\\(5\\)" }
+A a = -A();    // { dg-error "operand type is 'A'" }
+A b = -A(5);   // { dg-error "operand type is 'A'" }
Index: testsuite/g++.dg/cpp0x/lambda/lambda-err1.C
===================================================================
--- testsuite/g++.dg/cpp0x/lambda/lambda-err1.C (revision 185603)
+++ testsuite/g++.dg/cpp0x/lambda/lambda-err1.C (working copy)
@@ -4,5 +4,5 @@
 void foo()
 {
   int x[1];
-  [x]{} = 0;                   // { dg-error "lambda closure" }
+  [x]{} = 0;                   // { dg-error "lambda" }
 }
Index: cp/call.c
===================================================================
--- cp/call.c   (revision 185603)
+++ cp/call.c   (working copy)
@@ -4155,6 +4155,10 @@ op_error (enum tree_code code, enum tree_code code
 {
   const char *opname;
 
+  arg1 = arg1 ? TREE_TYPE (arg1) : NULL_TREE;
+  arg2 = arg2 ? TREE_TYPE (arg2) : NULL_TREE;
+  arg3 = arg3 ? TREE_TYPE (arg3) : NULL_TREE;
+
   if (code == MODIFY_EXPR)
     opname = assignment_operator_name_info[code2].name;
   else
@@ -4165,56 +4169,60 @@ op_error (enum tree_code code, enum tree_code code
     case COND_EXPR:
       if (match)
         error ("ambiguous overload for ternary %<operator?:%> "
-               "in %<%E ? %E : %E%>", arg1, arg2, arg3);
+              "(operand types are %qT, %qT, and %qT)",
+              arg1, arg2, arg3);
       else
         error ("no match for ternary %<operator?:%> "
-               "in %<%E ? %E : %E%>", arg1, arg2, arg3);
+               "(operand types are %qT, %qT, and %qT)",
+              arg1, arg2, arg3);
       break;
 
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
       if (match)
-        error ("ambiguous overload for %<operator%s%> in %<%E%s%>",
-               opname, arg1, opname);
+        error ("ambiguous overload for %<operator%s%> "
+              "(operand type is %qT)", opname, arg1);
       else
-        error ("no match for %<operator%s%> in %<%E%s%>", 
-               opname, arg1, opname);
+        error ("no match for %<operator%s%> "
+              "(operand type is %qT)", opname, arg1);
       break;
 
     case ARRAY_REF:
       if (match)
-        error ("ambiguous overload for %<operator[]%> in %<%E[%E]%>", 
-               arg1, arg2);
+        error ("ambiguous overload for %<operator[]%> "
+              "(operand types are %qT and %qT)", arg1, arg2);
       else
-        error ("no match for %<operator[]%> in %<%E[%E]%>", 
-               arg1, arg2);
+        error ("no match for %<operator[]%> "
+              "(operand types are %qT and %qT)", arg1, arg2);
       break;
 
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       if (match)
-        error ("ambiguous overload for %qs in %<%s %E%>", 
-               opname, opname, arg1);
+        error ("ambiguous overload for %qs (operand type is %qT)", 
+               opname, arg1);
       else
-        error ("no match for %qs in %<%s %E%>",
-               opname, opname, arg1);
+        error ("no match for %qs (operand type is %qT)",
+              opname, arg1);
       break;
 
     default:
       if (arg2)
         if (match)
-          error ("ambiguous overload for %<operator%s%> in %<%E %s %E%>",
-                  opname, arg1, opname, arg2);
+          error ("ambiguous overload for %<operator%s%> "
+                "(operand types are %qT and %qT)",
+                opname, arg1, arg2);
         else
-          error ("no match for %<operator%s%> in %<%E %s %E%>",
-                 opname, arg1, opname, arg2);
+         error ("no match for %<operator%s%> "
+                "(operand types are %qT and %qT)",
+                opname, arg1, arg2);
       else
         if (match)
-          error ("ambiguous overload for %<operator%s%> in %<%s%E%>",
-                 opname, opname, arg1);
+          error ("ambiguous overload for %<operator%s%> "
+                "(operand type is %qT)", opname, arg1);
         else
-          error ("no match for %<operator%s%> in %<%s%E%>",
-                 opname, opname, arg1);
+          error ("no match for %<operator%s%> (operand type is %qT)",
+                 opname, arg1);
       break;
     }
 }

Reply via email to