diff options
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r-- | gcc/cp/tree.c | 123 |
1 files changed, 93 insertions, 30 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 36305660372..4b1142b1154 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */ #include "insn-config.h" #include "integrate.h" #include "tree-inline.h" +#include "target.h" static tree bot_manip PARAMS ((tree *, int *, void *)); static tree bot_replace PARAMS ((tree *, int *, void *)); @@ -39,7 +40,7 @@ static tree build_cplus_array_type_1 PARAMS ((tree, tree)); static int list_hash_eq PARAMS ((const void *, const void *)); static hashval_t list_hash_pieces PARAMS ((tree, tree, tree)); static hashval_t list_hash PARAMS ((const void *)); -static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int)); +static cp_lvalue_kind lvalue_p_1 PARAMS ((tree, int, int)); static tree no_linkage_helper PARAMS ((tree *, int *, void *)); static tree build_srcloc PARAMS ((const char *, int)); static tree mark_local_for_remap_r PARAMS ((tree *, int *, void *)); @@ -56,12 +57,13 @@ static tree handle_init_priority_attribute PARAMS ((tree *, tree, tree, int, boo /* If REF is an lvalue, returns the kind of lvalue that REF is. Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is - non-zero, rvalues of class type are considered lvalues. */ + nonzero, rvalues of class type are considered lvalues. */ static cp_lvalue_kind -lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) +lvalue_p_1 (ref, treat_class_rvalues_as_lvalues, allow_cast_as_lvalue) tree ref; int treat_class_rvalues_as_lvalues; + int allow_cast_as_lvalue; { cp_lvalue_kind op1_lvalue_kind = clk_none; cp_lvalue_kind op2_lvalue_kind = clk_none; @@ -84,16 +86,28 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) case WITH_CLEANUP_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: - /* This shouldn't be here, but there are lots of places in the compiler - that are sloppy about tacking on NOP_EXPRs to the same type when - no actual conversion is happening. */ - case NOP_EXPR: return lvalue_p_1 (TREE_OPERAND (ref, 0), - treat_class_rvalues_as_lvalues); + treat_class_rvalues_as_lvalues, + allow_cast_as_lvalue); + + case NOP_EXPR: + /* If expression doesn't change the type, we consider it as an + lvalue even when cast_as_lvalue extension isn't selected. + That's because parts of the compiler are alleged to be sloppy + about sticking in NOP_EXPR node for no good reason. */ + if (allow_cast_as_lvalue || + same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ref)), + TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (ref, 0))))) + return lvalue_p_1 (TREE_OPERAND (ref, 0), + treat_class_rvalues_as_lvalues, + allow_cast_as_lvalue); + else + return clk_none; case COMPONENT_REF: op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0), - treat_class_rvalues_as_lvalues); + treat_class_rvalues_as_lvalues, + allow_cast_as_lvalue); if (op1_lvalue_kind /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some situations. */ @@ -134,16 +148,20 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) case MAX_EXPR: case MIN_EXPR: op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0), - treat_class_rvalues_as_lvalues); + treat_class_rvalues_as_lvalues, + allow_cast_as_lvalue); op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1), - treat_class_rvalues_as_lvalues); + treat_class_rvalues_as_lvalues, + allow_cast_as_lvalue); break; case COND_EXPR: op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1), - treat_class_rvalues_as_lvalues); + treat_class_rvalues_as_lvalues, + allow_cast_as_lvalue); op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2), - treat_class_rvalues_as_lvalues); + treat_class_rvalues_as_lvalues, + allow_cast_as_lvalue); break; case MODIFY_EXPR: @@ -151,7 +169,8 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) case COMPOUND_EXPR: return lvalue_p_1 (TREE_OPERAND (ref, 1), - treat_class_rvalues_as_lvalues); + treat_class_rvalues_as_lvalues, + allow_cast_as_lvalue); case TARGET_EXPR: return treat_class_rvalues_as_lvalues ? clk_class : clk_none; @@ -196,7 +215,7 @@ cp_lvalue_kind real_lvalue_p (ref) tree ref; { - return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0); + return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/ 0, /*cast*/ 1); } /* This differs from real_lvalue_p in that class rvalues are @@ -207,7 +226,15 @@ lvalue_p (ref) tree ref; { return - (lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none); + (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 1) != clk_none); +} + +int +non_cast_lvalue_p (ref) + tree ref; +{ + return + (lvalue_p_1 (ref, /*class rvalue ok*/ 1, /*cast*/ 0) != clk_none); } /* Return nonzero if REF is an lvalue valid for this language; @@ -218,7 +245,20 @@ lvalue_or_else (ref, string) tree ref; const char *string; { - int win = lvalue_p (ref); + int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 1); + int win = (ret != clk_none); + if (! win) + error ("non-lvalue in %s", string); + return win; +} + +int +non_cast_lvalue_or_else (ref, string) + tree ref; + const char *string; +{ + int ret = lvalue_p_1 (ref, /* class rvalue ok */ 1, /* cast ok */ 0); + int win = (ret != clk_none); if (! win) error ("non-lvalue in %s", string); return win; @@ -537,6 +577,11 @@ cp_build_qualified_type_real (type, type_quals, complain) { tree result; int bad_quals = TYPE_UNQUALIFIED; + /* We keep bad function qualifiers separate, so that we can decide + whether to implement DR 295 or not. DR 295 break existing code, + unfortunately. Remove this variable to implement the defect + report. */ + int bad_func_quals = TYPE_UNQUALIFIED; if (type == error_mark_node) return type; @@ -552,6 +597,8 @@ cp_build_qualified_type_real (type, type_quals, complain) || TREE_CODE (type) == METHOD_TYPE)) { bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); + if (TREE_CODE (type) != REFERENCE_TYPE) + bad_func_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); } @@ -570,21 +617,23 @@ cp_build_qualified_type_real (type, type_quals, complain) /*OK*/; else if (!(complain & (tf_error | tf_ignore_bad_quals))) return error_mark_node; + else if (bad_func_quals && !(complain & tf_error)) + return error_mark_node; else { if (complain & tf_ignore_bad_quals) /* We're not going to warn about constifying things that can't be constified. */ bad_quals &= ~TYPE_QUAL_CONST; + bad_quals |= bad_func_quals; if (bad_quals) { tree bad_type = build_qualified_type (ptr_type_node, bad_quals); - if (!(complain & tf_ignore_bad_quals)) + if (!(complain & tf_ignore_bad_quals) + || bad_func_quals) error ("`%V' qualifiers cannot be applied to `%T'", bad_type, type); - else if (complain & tf_warning) - warning ("ignoring `%V' qualifiers on `%T'", bad_type, type); } } @@ -963,9 +1012,10 @@ really_overloaded_fn (x) x = TREE_OPERAND (x, 1); if (BASELINK_P (x)) x = BASELINK_FUNCTIONS (x); - return (TREE_CODE (x) == OVERLOAD - && (OVL_CHAIN (x) - || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x)))); + + return ((TREE_CODE (x) == OVERLOAD && OVL_CHAIN (x)) + || DECL_FUNCTION_TEMPLATE_P (OVL_CURRENT (x)) + || TREE_CODE (x) == TEMPLATE_ID_EXPR); } /* Return the OVERLOAD or FUNCTION_DECL inside FNS. FNS can be an @@ -987,7 +1037,7 @@ get_first_fn (from) tree from; { my_friendly_assert (is_overloaded_fn (from), 9); - /* A baselink is also considered an overloaded function. */ + /* A baselink is also considered an overloaded function. */ if (BASELINK_P (from)) from = BASELINK_FUNCTIONS (from); return OVL_CURRENT (from); @@ -1004,7 +1054,7 @@ bound_pmf_p (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1)))); } -/* Return a new OVL node, concatenating it with the old one. */ +/* Return a new OVL node, concatenating it with the old one. */ tree ovl_cons (decl, chain) @@ -1043,7 +1093,7 @@ is_aggr_type_2 (t1, t2) return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2); } -/* Returns non-zero if CODE is the code for a statement. */ +/* Returns nonzero if CODE is the code for a statement. */ int cp_statement_code_p (code) @@ -1858,7 +1908,7 @@ maybe_dummy_object (type, binfop) if (current_class_ref && context == current_class_type /* Kludge: Make sure that current_class_type is actually correct. It might not be if we're in the middle of - tsubst_default_argument. */ + tsubst_default_argument. */ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)), current_class_type)) decl = current_class_ref; @@ -1888,6 +1938,8 @@ pod_type_p (t) { t = strip_array_types (t); + if (t == error_mark_node) + return 1; if (INTEGRAL_TYPE_P (t)) return 1; /* integral, character or enumeral type */ if (FLOAT_TYPE_P (t)) @@ -1915,6 +1967,9 @@ zero_init_p (t) { t = strip_array_types (t); + if (t == error_mark_node) + return 1; + /* NULL pointers to data members are initialized with -1. */ if (TYPE_PTRMEM_P (t)) return 0; @@ -2030,7 +2085,7 @@ handle_init_priority_attribute (node, name, args, flags, no_add_attrs) /* Static objects in functions are initialized the first time control passes through that function. This is not precise enough to pin down an - init_priority value, so don't allow it. */ + init_priority value, so don't allow it. */ || current_function_decl) { error ("can only use `%s' attribute on file-scope definitions of objects of class type", @@ -2180,6 +2235,14 @@ cp_cannot_inline_tree_fn (fnp) return 1; } + /* Don't auto-inline anything that might not be bound within + this unit of translation. */ + if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn)) + { + DECL_UNINLINABLE (fn) = 1; + return 1; + } + if (varargs_function_p (fn)) { DECL_UNINLINABLE (fn) = 1; @@ -2305,7 +2368,7 @@ cp_copy_res_decl_for_inlining (result, fn, caller, decl_map_, return var; } -/* Record that we're about to start inlining FN, and return non-zero if +/* Record that we're about to start inlining FN, and return nonzero if that's OK. Used for lang_hooks.tree_inlining.start_inlining. */ int @@ -2492,7 +2555,7 @@ name_p (tree node) || TREE_CODE (node) == SCOPE_REF); } -/* Returns non-zero if TYPE is a character type, including wchar_t. */ +/* Returns nonzero if TYPE is a character type, including wchar_t. */ int char_type_p (type) |