diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 24fbf9aef27..c56f75675eb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2006-08-25 Volker Reichelt + + PR c++/28852 + * cp-tree.h (grok_op_properties): Return bool instead of void. + * decl.c (grokfndecl): Discard invalid operator declarations. + (copy_fn_p): Revert change for PR 27547. + (grok_op_properties): Return error status (true on success). + * pt.c (tsubst_decl): Discard invalid operator declarations. + 2006-08-25 Mark Mitchell PR c++/28056 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 79018a40878..713d3711420 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3899,7 +3899,7 @@ extern int copy_fn_p (tree); extern tree get_scope_of_declarator (const cp_declarator *); extern void grok_special_member_properties (tree); extern int grok_ctor_properties (tree, tree); -extern void grok_op_properties (tree, bool); +extern bool grok_op_properties (tree, bool); extern tree xref_tag (enum tag_types, tree, tag_scope, bool); extern tree xref_tag_from_type (tree, tree, tag_scope); extern void xref_basetypes (tree, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2d69cdbae04..542fcbe40af 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6117,8 +6117,9 @@ grokfndecl (tree ctype, quals = TYPE_UNQUALIFIED; } - if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) - grok_op_properties (decl, /*complain=*/true); + if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)) + && !grok_op_properties (decl, /*complain=*/true)) + return NULL_TREE; if (ctype && decl_function_context (decl)) DECL_NO_STATIC_CHAIN (decl) = 1; @@ -8900,9 +8901,7 @@ copy_fn_p (tree d) tree arg_type; int result = 1; - if (!DECL_FUNCTION_MEMBER_P (d)) - /* Non-members are invalid. We complained, but kept the declaration. */ - return 0; + gcc_assert (DECL_FUNCTION_MEMBER_P (d)); if (TREE_CODE (d) == TEMPLATE_DECL || (DECL_TEMPLATE_INFO (d) @@ -9055,7 +9054,7 @@ unary_op_p (enum tree_code code) /* DECL is a declaration for an overloaded operator. If COMPLAIN is true, errors are issued for invalid declarations. */ -void +bool grok_op_properties (tree decl, bool complain) { tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); @@ -9141,9 +9140,15 @@ grok_op_properties (tree decl, bool complain) if (DECL_NAMESPACE_SCOPE_P (decl)) { if (CP_DECL_CONTEXT (decl) != global_namespace) - error ("%qD may not be declared within a namespace", decl); + { + error ("%qD may not be declared within a namespace", decl); + return false; + } else if (!TREE_PUBLIC (decl)) - error ("%qD may not be declared as static", decl); + { + error ("%qD may not be declared as static", decl); + return false; + } } } @@ -9165,7 +9170,7 @@ grok_op_properties (tree decl, bool complain) || operator_code == NOP_EXPR) { error ("%qD must be a nonstatic member function", decl); - return; + return false; } else { @@ -9175,14 +9180,14 @@ grok_op_properties (tree decl, bool complain) { error ("%qD must be either a non-static member " "function or a non-member function", decl); - return; + return false; } for (p = argtypes; p && p != void_list_node; p = TREE_CHAIN (p)) { tree arg = non_reference (TREE_VALUE (p)); if (arg == error_mark_node) - return; + return false; /* IS_AGGR_TYPE, rather than CLASS_TYPE_P, is used because these checks are performed even on @@ -9193,12 +9198,10 @@ grok_op_properties (tree decl, bool complain) if (!p || p == void_list_node) { - if (!complain) - return; - - error ("%qD must have an argument of class or " - "enumerated type", - decl); + if (complain) + error ("%qD must have an argument of class or " + "enumerated type", decl); + return false; } } } @@ -9206,7 +9209,7 @@ grok_op_properties (tree decl, bool complain) /* There are no restrictions on the arguments to an overloaded "operator ()". */ if (operator_code == CALL_EXPR) - return; + return true; /* Warn about conversion operators that will never be used. */ if (IDENTIFIER_TYPENAME_P (name) @@ -9246,9 +9249,13 @@ grok_op_properties (tree decl, bool complain) { /* 13.4.0.3 */ error ("ISO C++ prohibits overloading operator ?:"); + return false; } else if (ellipsis_p) - error ("%qD must not have variable number of arguments", decl); + { + error ("%qD must not have variable number of arguments", decl); + return false; + } else if (ambi_op_p (operator_code)) { if (arity == 1) @@ -9298,11 +9305,11 @@ grok_op_properties (tree decl, bool complain) { if (methodp) error ("postfix %qD must take % as its argument", - decl); + decl); else - error - ("postfix %qD must take % as its second argument", - decl); + error ("postfix %qD must take % as its second " + "argument", decl); + return false; } } else @@ -9311,6 +9318,7 @@ grok_op_properties (tree decl, bool complain) error ("%qD must take either zero or one argument", decl); else error ("%qD must take either one or two arguments", decl); + return false; } /* More Effective C++ rule 6. */ @@ -9349,6 +9357,7 @@ grok_op_properties (tree decl, bool complain) error ("%qD must take %", decl); else error ("%qD must take exactly one argument", decl); + return false; } } else /* if (binary_op_p (operator_code)) */ @@ -9359,6 +9368,7 @@ grok_op_properties (tree decl, bool complain) error ("%qD must take exactly one argument", decl); else error ("%qD must take exactly two arguments", decl); + return false; } /* More Effective C++ rule 7. */ @@ -9395,11 +9405,13 @@ grok_op_properties (tree decl, bool complain) pedwarn ("%qD cannot have default arguments", decl); } else - error ("%qD cannot have default arguments", decl); + { + error ("%qD cannot have default arguments", decl); + return false; + } } - } - + return true; } /* Return a string giving the keyword associate with CODE. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5843a50e57b..749291c63e3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6668,8 +6668,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) if (PRIMARY_TEMPLATE_P (gen_tmpl)) clone_function_decl (r, /*update_method_vec_p=*/0); } - else if (IDENTIFIER_OPNAME_P (DECL_NAME (r))) - grok_op_properties (r, (complain & tf_error) != 0); + else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)) + && !grok_op_properties (r, (complain & tf_error) != 0)) + return error_mark_node; if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t)) SET_DECL_FRIEND_CONTEXT (r, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f74ad90653a..8fa3f7f7893 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2006-08-25 Volker Reichelt + + PR c++/28852 + * g++.dg/other/operator1.C: Add error-marker. + * g++.dg/other/operator2.C: New test. + 2006-08-25 Joseph S. Myers PR c/27893 diff --git a/gcc/testsuite/g++.dg/other/operator1.C b/gcc/testsuite/g++.dg/other/operator1.C index 1760a1c385c..86841c99956 100644 --- a/gcc/testsuite/g++.dg/other/operator1.C +++ b/gcc/testsuite/g++.dg/other/operator1.C @@ -5,5 +5,5 @@ int operator=(int); // { dg-error "member function" } void foo() { - operator=(0); + operator=(0); // { dg-error "not defined" } } diff --git a/gcc/testsuite/g++.dg/other/operator2.C b/gcc/testsuite/g++.dg/other/operator2.C new file mode 100644 index 00000000000..4b952bf11eb --- /dev/null +++ b/gcc/testsuite/g++.dg/other/operator2.C @@ -0,0 +1,10 @@ +// PR c++/28852 +// { do-do compile } + +struct A +{ + operator int&(int); // { dg-error "void" } +}; + +A a; +int& i = a; // { dg-error "initialization" }