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;
}
}