Commit d02f620d by Jason Merrill Committed by Jason Merrill

re PR c++/20332 (poor diagnostic when bind non lvalue to a reference for default arguments)

	PR c++/20332
	PR c++/21631
	* call.c (reference_binding): Treat lvalue/rvalue mismatch and
	dropped cv-quals as a bad conversion.
	(convert_like_real) [ck_ref_bind]: Explain them.
	(compare_ics): Check badness before stripping reference
	bindings.  Handle comparing bad reference bindings.
	* typeck.c (comp_cv_qualification): Add overload that just takes
	integers.
	* cp-tree.h: Declare it.

From-SVN: r210436
parent 89606913
2014-05-14 Jason Merrill <jason@redhat.com> 2014-05-14 Jason Merrill <jason@redhat.com>
PR c++/20332
PR c++/21631
* call.c (reference_binding): Treat lvalue/rvalue mismatch and
dropped cv-quals as a bad conversion.
(convert_like_real) [ck_ref_bind]: Explain them.
(compare_ics): Check badness before stripping reference
bindings. Handle comparing bad reference bindings.
* typeck.c (comp_cv_qualification): Add overload that just takes
integers.
* cp-tree.h: Declare it.
* call.c (struct conversion_info): Rename 'from_type' to 'from'. * call.c (struct conversion_info): Rename 'from_type' to 'from'.
(arg_conversion_rejection, bad_arg_conversion_rejection) (arg_conversion_rejection, bad_arg_conversion_rejection)
(explicit_conversion_rejection, template_conversion_rejection): Adjust. (explicit_conversion_rejection, template_conversion_rejection): Adjust.
......
...@@ -1540,15 +1540,11 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, ...@@ -1540,15 +1540,11 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
[8.5.3/5 dcl.init.ref] is changed to also require direct bindings for [8.5.3/5 dcl.init.ref] is changed to also require direct bindings for
const and rvalue references to rvalues of compatible class type. const and rvalue references to rvalues of compatible class type.
We should also do direct bindings for non-class xvalues. */ We should also do direct bindings for non-class xvalues. */
if (compatible_p if (related_p
&& (is_lvalue && (gl_kind
|| (((CP_TYPE_CONST_NON_VOLATILE_P (to) || (!(flags & LOOKUP_NO_TEMP_BIND)
&& !(flags & LOOKUP_NO_RVAL_BIND)) && (CLASS_TYPE_P (from)
|| TYPE_REF_IS_RVALUE (rto)) || TREE_CODE (from) == ARRAY_TYPE))))
&& (gl_kind
|| (!(flags & LOOKUP_NO_TEMP_BIND)
&& (CLASS_TYPE_P (from)
|| TREE_CODE (from) == ARRAY_TYPE))))))
{ {
/* [dcl.init.ref] /* [dcl.init.ref]
...@@ -1603,6 +1599,16 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, ...@@ -1603,6 +1599,16 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
&& !(flags & LOOKUP_PREFER_RVALUE)) && !(flags & LOOKUP_PREFER_RVALUE))
conv->bad_p = true; conv->bad_p = true;
/* Nor the reverse. */
if (!is_lvalue && !TYPE_REF_IS_RVALUE (rto)
&& (!CP_TYPE_CONST_NON_VOLATILE_P (to)
|| (flags & LOOKUP_NO_RVAL_BIND))
&& TREE_CODE (to) != FUNCTION_TYPE)
conv->bad_p = true;
if (!compatible_p)
conv->bad_p = true;
return conv; return conv;
} }
/* [class.conv.fct] A conversion function is never used to convert a /* [class.conv.fct] A conversion function is never used to convert a
...@@ -1647,24 +1653,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, ...@@ -1647,24 +1653,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
difference in top-level cv-qualification is subsumed by the difference in top-level cv-qualification is subsumed by the
initialization itself and does not constitute a conversion. */ initialization itself and does not constitute a conversion. */
/* [dcl.init.ref]
Otherwise, the reference shall be an lvalue reference to a
non-volatile const type, or the reference shall be an rvalue
reference. */
if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !TYPE_REF_IS_RVALUE (rto))
return NULL;
/* [dcl.init.ref]
Otherwise, a temporary of type "cv1 T1" is created and
initialized from the initializer expression using the rules for a
non-reference copy initialization. If T1 is reference-related to
T2, cv1 must be the same cv-qualification as, or greater
cv-qualification than, cv2; otherwise, the program is ill-formed. */
if (related_p && !at_least_as_qualified_p (to, from))
return NULL;
/* We're generating a temporary now, but don't bind any more in the /* We're generating a temporary now, but don't bind any more in the
conversion (specifically, don't slice the temporary returned by a conversion (specifically, don't slice the temporary returned by a
conversion operator). */ conversion operator). */
...@@ -1710,6 +1698,24 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, ...@@ -1710,6 +1698,24 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
conv->need_temporary_p = true; conv->need_temporary_p = true;
conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto); conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
/* [dcl.init.ref]
Otherwise, the reference shall be an lvalue reference to a
non-volatile const type, or the reference shall be an rvalue
reference. */
if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !TYPE_REF_IS_RVALUE (rto))
conv->bad_p = true;
/* [dcl.init.ref]
Otherwise, a temporary of type "cv1 T1" is created and
initialized from the initializer expression using the rules for a
non-reference copy initialization. If T1 is reference-related to
T2, cv1 must be the same cv-qualification as, or greater
cv-qualification than, cv2; otherwise, the program is ill-formed. */
if (related_p && !at_least_as_qualified_p (to, from))
conv->bad_p = true;
return conv; return conv;
} }
...@@ -6334,12 +6340,20 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, ...@@ -6334,12 +6340,20 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (convs->bad_p && !next_conversion (convs)->bad_p) if (convs->bad_p && !next_conversion (convs)->bad_p)
{ {
gcc_assert (TYPE_REF_IS_RVALUE (ref_type) tree extype = TREE_TYPE (expr);
&& (real_lvalue_p (expr) if (TYPE_REF_IS_RVALUE (ref_type)
|| next_conversion(convs)->kind == ck_rvalue)); && real_lvalue_p (expr))
error_at (loc, "cannot bind %qT lvalue to %qT",
error_at (loc, "cannot bind %qT lvalue to %qT", extype, totype);
TREE_TYPE (expr), totype); else if (!TYPE_REF_IS_RVALUE (ref_type) && !real_lvalue_p (expr)
&& !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
error_at (loc, "invalid initialization of non-const reference of "
"type %qT from an rvalue of type %qT", totype, extype);
else if (!reference_compatible_p (TREE_TYPE (totype), extype))
error_at (loc, "binding %qT to reference of type %qT "
"discards qualifiers", extype, totype);
else
gcc_unreachable ();
maybe_print_user_conv_context (convs); maybe_print_user_conv_context (convs);
if (fn) if (fn)
inform (input_location, inform (input_location,
...@@ -8230,6 +8244,12 @@ compare_ics (conversion *ics1, conversion *ics2) ...@@ -8230,6 +8244,12 @@ compare_ics (conversion *ics1, conversion *ics2)
conversion *ref_conv1; conversion *ref_conv1;
conversion *ref_conv2; conversion *ref_conv2;
/* Compare badness before stripping the reference conversion. */
if (ics1->bad_p > ics2->bad_p)
return -1;
else if (ics1->bad_p < ics2->bad_p)
return 1;
/* Handle implicit object parameters. */ /* Handle implicit object parameters. */
maybe_handle_implicit_object (&ics1); maybe_handle_implicit_object (&ics1);
maybe_handle_implicit_object (&ics2); maybe_handle_implicit_object (&ics2);
...@@ -8258,31 +8278,19 @@ compare_ics (conversion *ics1, conversion *ics2) ...@@ -8258,31 +8278,19 @@ compare_ics (conversion *ics1, conversion *ics2)
--a user-defined conversion sequence (_over.ics.user_) is a --a user-defined conversion sequence (_over.ics.user_) is a
better conversion sequence than an ellipsis conversion sequence better conversion sequence than an ellipsis conversion sequence
(_over.ics.ellipsis_). */ (_over.ics.ellipsis_). */
rank1 = CONVERSION_RANK (ics1); /* Use BAD_CONVERSION_RANK because we already checked for a badness
rank2 = CONVERSION_RANK (ics2); mismatch. If both ICS are bad, we try to make a decision based on
what would have happened if they'd been good. This is not an
extension, we'll still give an error when we build up the call; this
just helps us give a more helpful error message. */
rank1 = BAD_CONVERSION_RANK (ics1);
rank2 = BAD_CONVERSION_RANK (ics2);
if (rank1 > rank2) if (rank1 > rank2)
return -1; return -1;
else if (rank1 < rank2) else if (rank1 < rank2)
return 1; return 1;
if (rank1 == cr_bad)
{
/* Both ICS are bad. We try to make a decision based on what would
have happened if they'd been good. This is not an extension,
we'll still give an error when we build up the call; this just
helps us give a more helpful error message. */
rank1 = BAD_CONVERSION_RANK (ics1);
rank2 = BAD_CONVERSION_RANK (ics2);
if (rank1 > rank2)
return -1;
else if (rank1 < rank2)
return 1;
/* We couldn't make up our minds; try to figure it out below. */
}
if (ics1->ellipsis_p) if (ics1->ellipsis_p)
/* Both conversions are ellipsis conversions. */ /* Both conversions are ellipsis conversions. */
return 0; return 0;
...@@ -8602,13 +8610,30 @@ compare_ics (conversion *ics1, conversion *ics2) ...@@ -8602,13 +8610,30 @@ compare_ics (conversion *ics1, conversion *ics2)
|| (TYPE_REF_IS_RVALUE (ref_conv1->type) || (TYPE_REF_IS_RVALUE (ref_conv1->type)
!= TYPE_REF_IS_RVALUE (ref_conv2->type)))) != TYPE_REF_IS_RVALUE (ref_conv2->type))))
{ {
if (ref_conv1->bad_p
&& !same_type_p (TREE_TYPE (ref_conv1->type),
TREE_TYPE (ref_conv2->type)))
/* Don't prefer a bad conversion that drops cv-quals to a bad
conversion with the wrong rvalueness. */
return 0;
return (ref_conv1->rvaluedness_matches_p return (ref_conv1->rvaluedness_matches_p
- ref_conv2->rvaluedness_matches_p); - ref_conv2->rvaluedness_matches_p);
} }
if (same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2)) if (same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
return comp_cv_qualification (TREE_TYPE (ref_conv2->type), {
TREE_TYPE (ref_conv1->type)); int q1 = cp_type_quals (TREE_TYPE (ref_conv1->type));
int q2 = cp_type_quals (TREE_TYPE (ref_conv2->type));
if (ref_conv1->bad_p)
{
/* Prefer the one that drops fewer cv-quals. */
tree ftype = next_conversion (ref_conv1)->type;
int fquals = cp_type_quals (ftype);
q1 ^= fquals;
q2 ^= fquals;
}
return comp_cv_qualification (q2, q1);
}
} }
/* Neither conversion sequence is better than the other. */ /* Neither conversion sequence is better than the other. */
......
...@@ -6034,6 +6034,7 @@ extern bool comptypes (tree, tree, int); ...@@ -6034,6 +6034,7 @@ extern bool comptypes (tree, tree, int);
extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree); extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree);
extern bool compparms (const_tree, const_tree); extern bool compparms (const_tree, const_tree);
extern int comp_cv_qualification (const_tree, const_tree); extern int comp_cv_qualification (const_tree, const_tree);
extern int comp_cv_qualification (int, int);
extern int comp_cv_qual_signature (tree, tree); extern int comp_cv_qual_signature (tree, tree);
extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code, bool); extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code, bool);
extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool); extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool);
......
...@@ -1452,11 +1452,8 @@ at_least_as_qualified_p (const_tree type1, const_tree type2) ...@@ -1452,11 +1452,8 @@ at_least_as_qualified_p (const_tree type1, const_tree type2)
more cv-qualified that TYPE1, and 0 otherwise. */ more cv-qualified that TYPE1, and 0 otherwise. */
int int
comp_cv_qualification (const_tree type1, const_tree type2) comp_cv_qualification (int q1, int q2)
{ {
int q1 = cp_type_quals (type1);
int q2 = cp_type_quals (type2);
if (q1 == q2) if (q1 == q2)
return 0; return 0;
...@@ -1468,6 +1465,14 @@ comp_cv_qualification (const_tree type1, const_tree type2) ...@@ -1468,6 +1465,14 @@ comp_cv_qualification (const_tree type1, const_tree type2)
return 0; return 0;
} }
int
comp_cv_qualification (const_tree type1, const_tree type2)
{
int q1 = cp_type_quals (type1);
int q2 = cp_type_quals (type2);
return comp_cv_qualification (q1, q2);
}
/* Returns 1 if the cv-qualification signature of TYPE1 is a proper /* Returns 1 if the cv-qualification signature of TYPE1 is a proper
subset of the cv-qualification signature of TYPE2, and the types subset of the cv-qualification signature of TYPE2, and the types
are similar. Returns -1 if the other way 'round, and 0 otherwise. */ are similar. Returns -1 if the other way 'round, and 0 otherwise. */
......
...@@ -9,11 +9,11 @@ struct X { ...@@ -9,11 +9,11 @@ struct X {
} }
}; };
void add_one (X & ref) { /* { dg-message "in passing argument" } */ void add_one (X & ref) { /* { dg-message "argument" } */
++ ref.x; ++ ref.x;
} }
void foo() { void foo() {
X const a (2); X const a (2);
add_one(a); /* { dg-error "invalid initialization of reference of type" } */ add_one(a); /* { dg-error "discards qualifiers" } */
} }
// { dg-do compile { target c++11 } }
struct A {};
// We shouldn't arbitarily choose which of these is better.
void f (A&);
void f (const A&&);
// But do prefer the lvalue overload here.
void g (A&);
void g (A&&);
int main()
{
const A a;
f(a); // { dg-error "no match" }
// { dg-error "qualifiers" "" { target *-*-* } 15 }
// { dg-error "lvalue" "" { target *-*-* } 15 }
g(a); // { dg-error "qualifiers" }
}
...@@ -543,9 +543,9 @@ void ucr1111(const S&&) {} ...@@ -543,9 +543,9 @@ void ucr1111(const S&&) {}
int main() int main()
{ {
l0001(l); // { dg-error "lvalue" } l0001(l); // { dg-error "" }
l0010(l); // { dg-error "lvalue" } l0010(l); // { dg-error "" }
l0011(l); // { dg-error "lvalue" } l0011(l); // { dg-error "" }
l0100(l); l0100(l);
l0101(l); l0101(l);
l0110(l); l0110(l);
...@@ -564,8 +564,8 @@ int main() ...@@ -564,8 +564,8 @@ int main()
cl0101(cl); cl0101(cl);
cl0110(cl); cl0110(cl);
cl0111(cl); cl0111(cl);
cl1001(cl); // { dg-error "lvalue" } cl1001(cl); // { dg-error "" }
cl1011(cl); // { dg-error "lvalue" } cl1011(cl); // { dg-error "" }
cl1100(cl); cl1100(cl);
cl1101(cl); cl1101(cl);
cl1110(cl); cl1110(cl);
...@@ -617,8 +617,8 @@ int main() ...@@ -617,8 +617,8 @@ int main()
ncl0101(ncl); ncl0101(ncl);
ncl0110(ncl); ncl0110(ncl);
ncl0111(ncl); ncl0111(ncl);
ncl1001(ncl); // { dg-error "lvalue" } ncl1001(ncl); // { dg-error "" }
ncl1011(ncl); // { dg-error "lvalue" } ncl1011(ncl); // { dg-error "" }
ncl1100(ncl); ncl1100(ncl);
ncl1101(ncl); ncl1101(ncl);
ncl1110(ncl); ncl1110(ncl);
...@@ -644,8 +644,8 @@ int main() ...@@ -644,8 +644,8 @@ int main()
ncr0101(ncr); ncr0101(ncr);
ncr0110(ncr); ncr0110(ncr);
ncr0111(ncr); ncr0111(ncr);
ncr1001(ncr); // { dg-error "lvalue" } ncr1001(ncr); // { dg-error "" }
ncr1011(ncr); // { dg-error "lvalue" } ncr1011(ncr); // { dg-error "" }
ncr1100(ncr); ncr1100(ncr);
ncr1101(ncr); ncr1101(ncr);
ncr1110(ncr); ncr1110(ncr);
...@@ -671,8 +671,8 @@ int main() ...@@ -671,8 +671,8 @@ int main()
ucl0101(ucl()); ucl0101(ucl());
ucl0110(ucl()); ucl0110(ucl());
ucl0111(ucl()); ucl0111(ucl());
ucl1001(ucl()); // { dg-error "lvalue" } ucl1001(ucl()); // { dg-error "" }
ucl1011(ucl()); // { dg-error "lvalue" } ucl1011(ucl()); // { dg-error "" }
ucl1100(ucl()); ucl1100(ucl());
ucl1101(ucl()); ucl1101(ucl());
ucl1110(ucl()); ucl1110(ucl());
......
// PR c++/20332
struct bar {};
void foo1() {
bar& b = bar(); // { dg-error "rvalue" }
}
void foo(bar& b = bar()) {} // { dg-error "rvalue" }
// PR c++/21631
int f(int&);
int f();
int g(void)
{
return f(1); // { dg-error "rvalue" }
}
// PR c++/27666 // PR c++/27666
struct A { // { dg-message "A" } struct A { // { dg-message "A" }
A(int); // { dg-message "A" } A(int);
}; };
void foo(volatile A a) { void foo(volatile A a) {
1 ? a : 0; // { dg-error "match|temporary" } 1 ? a : 0; // { dg-error "qualifiers|lvalue|no match" }
1 ? 0 : a; // { dg-error "match|temporary" } 1 ? 0 : a; // { dg-error "qualifiers|lvalue|no match" }
} }
// PR c++/34180 // PR c++/34180
struct G { struct G {
G(); // { dg-message "" "candidate" } G();
G(G&); // { dg-message "" "candidate" } G(G&); // { dg-message "" "candidate" }
}; };
......
...@@ -3,15 +3,15 @@ ...@@ -3,15 +3,15 @@
template<class T> struct wrap {}; template<class T> struct wrap {};
template<typename T> bool& operator==(wrap<T>, wrap<T>); template<typename T> bool operator==(wrap<T>, wrap<T>);
template<typename T> template<typename T>
void g(T, wrap<wrap<int> > x) void g(T, wrap<wrap<int> > x)
{ {
bool& b = x == x; // { dg-bogus "invalid initialization of reference" "" { xfail *-*-*} } bool b = x == x; // { dg-bogus "" "" { xfail *-*-* } }
} }
template<typename T> int& operator==(wrap<wrap<T> >, wrap<wrap<T> >); template<typename T> void operator==(wrap<wrap<T> >, wrap<wrap<T> >);
void h() void h()
{ {
......
...@@ -10,7 +10,7 @@ struct A {}; ...@@ -10,7 +10,7 @@ struct A {};
struct B : A struct B : A
{ {
B(int); // { dg-message "B::B|no known conversion" "" } B(int);
B(B&); // { dg-message "note" "" } B(B&); // { dg-message "note" "" }
}; };
...@@ -18,5 +18,5 @@ void foo(B); // { dg-message "initializing" } ...@@ -18,5 +18,5 @@ void foo(B); // { dg-message "initializing" }
void bar() void bar()
{ {
foo(0); // { dg-error "no matching function" "no matching" } foo(0); // { dg-error "" }
} }
...@@ -11,7 +11,7 @@ void f() ...@@ -11,7 +11,7 @@ void f()
{ {
const int i = 42; const int i = 42;
A()(i); // { dg-message "<conversion>" } A()(i); // { dg-message "<conversion>" }
// { dg-error "qualifiers" "" { target *-*-* } 13 }
} }
// { dg-prune-output "no match" } // { dg-prune-output "no match" }
// { dg-prune-output "candidate" }
...@@ -4,7 +4,7 @@ struct A; ...@@ -4,7 +4,7 @@ struct A;
struct B struct B
{ {
B (A const &); // { dg-message "note" } B (A const &);
B (B &); // { dg-message "note" } B (B &); // { dg-message "note" }
}; };
...@@ -16,5 +16,5 @@ struct A ...@@ -16,5 +16,5 @@ struct A
B B
f (B const& b) f (B const& b)
{ {
return b; // { dg-error "matching" "matching" } return b; // { dg-error "" }
} }
// PR c++/48118 // PR c++/48118
// { dg-prune-output "note" }
struct A { }; struct A { };
...@@ -9,6 +8,6 @@ void (*g)(A); ...@@ -9,6 +8,6 @@ void (*g)(A);
int main() int main()
{ {
volatile A a; volatile A a;
f(a); // { dg-error "no match" } f(a); // { dg-error "" }
g(a); // { dg-error "no match" } g(a); // { dg-error "" }
} }
...@@ -38,19 +38,19 @@ void r() ...@@ -38,19 +38,19 @@ void r()
B b; B b;
A& a1 = dynamic_cast<A&>(b); A& a1 = dynamic_cast<A&>(b);
A& a2 = dynamic_cast<const A&>(b); // { dg-error "invalid" } A& a2 = dynamic_cast<const A&>(b); // { dg-error "" }
A& a3 = dynamic_cast<volatile A&>(b); // { dg-error "invalid" } A& a3 = dynamic_cast<volatile A&>(b); // { dg-error "" }
A& a4 = dynamic_cast<const volatile A&>(b); // { dg-error "invalid" } A& a4 = dynamic_cast<const volatile A&>(b); // { dg-error "" }
const A& ca1 = dynamic_cast<A&>(b); const A& ca1 = dynamic_cast<A&>(b);
const A& ca2 = dynamic_cast<const A&>(b); const A& ca2 = dynamic_cast<const A&>(b);
const A& ca3 = dynamic_cast<volatile A&>(b); // { dg-error "invalid" } const A& ca3 = dynamic_cast<volatile A&>(b); // { dg-error "" }
const A& ca4 = dynamic_cast<const volatile A&>(b); // { dg-error "invalid" } const A& ca4 = dynamic_cast<const volatile A&>(b); // { dg-error "" }
volatile A& va1 = dynamic_cast<A&>(b); volatile A& va1 = dynamic_cast<A&>(b);
volatile A& va2 = dynamic_cast<const A&>(b); // { dg-error "invalid" } volatile A& va2 = dynamic_cast<const A&>(b); // { dg-error "" }
volatile A& va3 = dynamic_cast<volatile A&>(b); volatile A& va3 = dynamic_cast<volatile A&>(b);
volatile A& va4 = dynamic_cast<const volatile A&>(b);// { dg-error "invalid" } volatile A& va4 = dynamic_cast<const volatile A&>(b);// { dg-error "" }
const volatile A& cva1 = dynamic_cast<A&>(b); const volatile A& cva1 = dynamic_cast<A&>(b);
const volatile A& cva2 = dynamic_cast<const A&>(b); const volatile A& cva2 = dynamic_cast<const A&>(b);
......
...@@ -6,9 +6,9 @@ ...@@ -6,9 +6,9 @@
struct A struct A
{ {
A(A&); // { dg-message "note" } A(A&); // { dg-message "A::A" }
template <class T> A(T); // { dg-message "note" } template <class T> A(T); // { dg-message "A::A" }
}; };
A a = 0; // { dg-error "no matching function" } A a = 0; // { dg-error "" }
...@@ -12,6 +12,6 @@ extern panama dig(); ...@@ -12,6 +12,6 @@ extern panama dig();
void foo() { void foo() {
panama obj; panama obj;
obj = dig(); // { dg-error "no match" } obj = dig(); // { dg-error "rvalue" }
} }
...@@ -44,5 +44,5 @@ public: ...@@ -44,5 +44,5 @@ public:
void void
foo (bar yylval, bar *yyvsp) foo (bar yylval, bar *yyvsp)
{ {
nnyacc::assign(yylval.valueList, yyvsp[0].valueList);// { dg-error "no matching" } nnyacc::assign(yylval.valueList, yyvsp[0].valueList);// { dg-error "no matching|rvalue" }
} }
...@@ -71,8 +71,8 @@ void t_1_assignment () ...@@ -71,8 +71,8 @@ void t_1_assignment ()
t_1_st_1 t_1_st_1_obj1; t_1_st_1 t_1_st_1_obj1;
t_1_st_1 t_1_st_1_obj2; t_1_st_1 t_1_st_1_obj2;
t_1_st_1_obj0 = t_1_st_0_obj0; // { dg-error "no match" } t_1_st_1_obj0 = t_1_st_0_obj0; // { dg-error "no match|conversion" }
t_1_st_1_obj1 = t_1_st_1 (t_1_st_0_obj0); // { dg-error "no match" } t_1_st_1_obj1 = t_1_st_1 (t_1_st_0_obj0); // { dg-error "no match|rvalue" }
} }
void t_1_local_init () void t_1_local_init ()
......
// { dg-do assemble } // { dg-do assemble }
struct A struct A
{ {
A(); // { dg-message "A::A|candidate expects" } candidate A();
A(A&); // { dg-message "A::A|no known conversion" } referenced below A(A&); // { dg-message "A::A|no known conversion" } referenced below
}; };
...@@ -10,7 +10,7 @@ main () ...@@ -10,7 +10,7 @@ main ()
{ {
try try
{ {
throw A(); // { dg-error "no matching" "match" } can't copy throw A(); // { dg-error "rvalue" "" } can't copy
// { dg-error "thrown expression" "expr" { target *-*-* } 13 } // { dg-error "thrown expression" "expr" { target *-*-* } 13 }
} }
catch (...) { } catch (...) { }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
class X // Indentation has been done so to see the similarities. class X // Indentation has been done so to see the similarities.
{ {
public: public:
X() {} // { dg-message "note" } referenced below X() {}
X(X& x) {x.i=7;} // { dg-message "note" } Both functions modify the X(X& x) {x.i=7;} // { dg-message "note" } Both functions modify the
void bar(X& x) {x.i=7;} // { dg-message "note" } reference parameter x. void bar(X& x) {x.i=7;} // { dg-message "note" } reference parameter x.
int i; int i;
...@@ -12,6 +12,6 @@ X foo() { X x; return x; } ...@@ -12,6 +12,6 @@ X foo() { X x; return x; }
int main() int main()
{ {
X x(foo()); // { dg-error "no match" } Compiler doesn't warn about temporary reference. X x(foo()); // { dg-error "rvalue" } Compiler doesn't warn about temporary reference.
x.bar(foo()); // { dg-error "no match" } The same mistake is warned about in this case. x.bar(foo()); // { dg-error "rvalue" } The same mistake is warned about in this case.
} }
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
// Compiles fine with Sun CC 2.1 // Compiles fine with Sun CC 2.1
void f(char *& x) // { dg-message "passing argument" } void f(const char *& x) // { dg-message "argument" }
{ {
x++; x++;
} }
......
...@@ -24,6 +24,6 @@ int main() ...@@ -24,6 +24,6 @@ int main()
Enum e = enumerator1; Enum e = enumerator1;
Struct s; Struct s;
int x = funct(e+1);// { dg-error "invalid" } int x = funct(e+1);// { dg-error "invalid" }
int y = s.getI(e+1);// { dg-error "match|conv" } int y = s.getI(e+1);// { dg-error "invalid" }
return x+y; return x+y;
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
const int ic = 1; const int ic = 1;
void f(int& arg) // { dg-message "passing argument 1" } void f(int& arg) // { dg-message "argument 1" }
{ {
if (arg) ; if (arg) ;
} }
...@@ -16,7 +16,7 @@ const int& icr = ic; ...@@ -16,7 +16,7 @@ const int& icr = ic;
int main(void) int main(void)
{ {
f(icr); // { dg-error "invalid initialization" } f(icr); // { dg-error "const" }
return 0; return 0;
} }
...@@ -16,5 +16,5 @@ public: ...@@ -16,5 +16,5 @@ public:
void void
test(B &b1, const B &b2) test(B &b1, const B &b2)
{ {
b1 = b2;// { dg-error "match" } b1 = b2;// { dg-error "const" }
} }
...@@ -11,14 +11,14 @@ public: ...@@ -11,14 +11,14 @@ public:
int bar; int bar;
}; };
void func(Base&); // { dg-message "passing argument 1" } void func(Base&); // { dg-message "argument 1" }
void func2(const Derived& d) { void func2(const Derived& d) {
func(d); // { dg-error "invalid initialization" } func(d); // { dg-error "" }
} }
void void
foo (int& a) // { dg-message "in passing argument 1" } foo (int& a) // { dg-message "argument 1" }
{ {
} }
...@@ -27,6 +27,6 @@ int main () ...@@ -27,6 +27,6 @@ int main ()
int b; int b;
const int*const a = &b; const int*const a = &b;
*a = 10; // { dg-error "read-only location" } *a = 10; // { dg-error "read-only location" }
foo (*a); // { dg-error "invalid initialization" } foo (*a); // { dg-error "qualifiers" }
return 0; return 0;
} }
...@@ -196,7 +196,7 @@ Pix ...@@ -196,7 +196,7 @@ Pix
List_DLS<T>::search(const T& item) const List_DLS<T>::search(const T& item) const
{ {
for (Pix x=this->first(); 0 != x; this->next(x)) { for (Pix x=this->first(); 0 != x; this->next(x)) {
if (item == this->operator()(x)) // { dg-error "match" } const subversion if (item == this->operator()(x)) // { dg-error "qualifiers" } const subversion
return x; return x;
} }
return 0; return 0;
...@@ -485,8 +485,8 @@ class STRLIdentifier { ...@@ -485,8 +485,8 @@ class STRLIdentifier {
char buf[10]; char buf[10];
}; };
extern int operator==(vertex<STRLIdentifier*>&, vertex<STRLIdentifier*>&); // { dg-message "note" } const subversion extern int operator==(vertex<STRLIdentifier*>&, vertex<STRLIdentifier*>&); // { dg-message "argument 1" } const subversion
extern int operator==(STRLIdentifier&, STRLIdentifier&); // { dg-message "note" } fn ref in err msg extern int operator==(STRLIdentifier&, STRLIdentifier&);
extern int x(List_DLSp<STRLIdentifier *>); extern int x(List_DLSp<STRLIdentifier *>);
......
...@@ -18,6 +18,6 @@ class C ...@@ -18,6 +18,6 @@ class C
C() C()
{ {
B b; B b;
A a = b;// { dg-error "match" } A a = b;// { dg-error "rvalue" }
} }
}; };
...@@ -19,5 +19,5 @@ void C::test() const ...@@ -19,5 +19,5 @@ void C::test() const
{ {
D d; D d;
d.a(*this); // { dg-error "match" } *this is const, so should get error d.a(*this); // { dg-error "const" } *this is const, so should get error
} }
...@@ -7,7 +7,7 @@ extern "C" ...@@ -7,7 +7,7 @@ extern "C"
} }
void Munge(int& x) // { dg-message "passing argument 1" } void Munge(int& x) // { dg-message "argument 1" }
{ {
x = 2; x = 2;
} }
...@@ -24,7 +24,7 @@ class A ...@@ -24,7 +24,7 @@ class A
void void
A::Safe() const A::Safe() const
{ {
Munge(i); // { dg-error "invalid initialization" } Munge(i); // { dg-error "const" }
} }
int main() int main()
......
...@@ -12,7 +12,7 @@ class foo { ...@@ -12,7 +12,7 @@ class foo {
static void iteratorTest(const foo &x) static void iteratorTest(const foo &x)
{ {
foo::const_iterator i = x.begin(); // { dg-error "incomplete type" "incomplete type" } foo::const_iterator i = x.begin(); // { dg-error "incomplete type" "incomplete type" }
// { dg-error "no matching|const foo" "no matching" { target *-*-* } 14 } // { dg-error "const foo" "" { target *-*-* } 14 }
for (; i; ++i) for (; i; ++i)
*i; *i;
} }
...@@ -15,6 +15,6 @@ ret_v_f_class() ...@@ -15,6 +15,6 @@ ret_v_f_class()
int main(void) int main(void)
{ {
volatile f_class vf; volatile f_class vf;
0 ? ret_v_f_class() : vf; // { dg-error "match" } can't copy volatile lvalue 0 ? ret_v_f_class() : vf; // { dg-error "volatile" } can't copy volatile lvalue
return 0; return 0;
} }
...@@ -11,7 +11,7 @@ template<typename X> struct auto_ptr { ...@@ -11,7 +11,7 @@ template<typename X> struct auto_ptr {
explicit auto_ptr(X* p =0) throw() : px(p) {} explicit auto_ptr(X* p =0) throw() : px(p) {}
auto_ptr(auto_ptr& r) throw() : px(r.release()) {} // { dg-message "note" } candidate auto_ptr(auto_ptr& r) throw() : px(r.release()) {} // { dg-message "note" } candidate
template<typename Y> template<typename Y>
auto_ptr(auto_ptr<Y>& r) throw() : px(r.release()) {}// { dg-message "note" } candidate auto_ptr(auto_ptr<Y>& r) throw() : px(r.release()) {}
auto_ptr& operator=(auto_ptr& r) throw() { auto_ptr& operator=(auto_ptr& r) throw() {
reset(r.release()); reset(r.release());
...@@ -30,7 +30,7 @@ template<typename X> struct auto_ptr { ...@@ -30,7 +30,7 @@ template<typename X> struct auto_ptr {
X* release() throw() { X* p=px; px=0; return p; } X* release() throw() { X* p=px; px=0; return p; }
void reset(X* p=0) throw() { if (px != p) delete px, px = p; } void reset(X* p=0) throw() { if (px != p) delete px, px = p; }
auto_ptr(auto_ptr_ref<X> r) throw() : px(r.py) {} // { dg-message "note" } auto_ptr(auto_ptr_ref<X> r) throw() : px(r.py) {}
template<typename Y> operator auto_ptr_ref<Y>() throw() { template<typename Y> operator auto_ptr_ref<Y>() throw() {
return auto_ptr_ref<Y>(release()); return auto_ptr_ref<Y>(release());
} }
...@@ -51,5 +51,5 @@ int main() { ...@@ -51,5 +51,5 @@ int main() {
auto_ptr<Derived> y(f()); auto_ptr<Derived> y(f());
x = y; x = y;
g(f()); g(f());
h(f()); // { dg-error "match" "match" } no usable copy ctor h(f()); // { dg-error "rvalue" "" } no usable copy ctor
} }
// { dg-do assemble } // { dg-do assemble }
template <class A> class B { // { dg-message "note" } template <class A> class B {
A a; A a;
public: public:
B(A&aa); // { dg-message "note" } B(A&aa); // { dg-message "note" }
~B(); ~B();
}; };
static B<int> b_int (3); // { dg-error "no matching function" } static B<int> b_int (3); // { dg-error "no match|rvalue" }
...@@ -28,7 +28,7 @@ template<class T, class A1, class A2> ...@@ -28,7 +28,7 @@ template<class T, class A1, class A2>
factory(A1&& a1, A2&& a2) factory(A1&& a1, A2&& a2)
{ {
return std::shared_ptr<T>(new T(std::forward<A1>(a1), return std::shared_ptr<T>(new T(std::forward<A1>(a1),
std::forward<A2>(a2))); // { dg-error "no matching function" } std::forward<A2>(a2))); // { dg-error "rvalue" }
} }
struct A struct A
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment