X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Ftypeck.c;h=e2853de98e93af714b7db522f78e8fa518c74b82;hp=76ae5104b16a44c6dcdd8932e814525d6f90207c;hb=4fd216d574350d23961db14d4b25f74ed20905f8;hpb=7654a35949466b9a18c80e715be43e0957859efe diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 76ae5104b16..e2853de98e9 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -107,12 +107,18 @@ complete_type (tree type) else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) { tree t = complete_type (TREE_TYPE (type)); + unsigned int needs_constructing, has_nontrivial_dtor; if (COMPLETE_TYPE_P (t) && !dependent_type_p (type)) layout_type (type); - TYPE_NEEDS_CONSTRUCTING (type) + needs_constructing = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t)); - TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) + has_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (t)); + for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) + { + TYPE_NEEDS_CONSTRUCTING (t) = needs_constructing; + TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = has_nontrivial_dtor; + } } else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type)) instantiate_class_template (TYPE_MAIN_VARIANT (type)); @@ -218,7 +224,7 @@ commonparms (tree p1, tree p2) /* Given a type, perhaps copied for a typedef, find the "original" version of it. */ -tree +static tree original_type (tree t) { while (TYPE_NAME (t) != NULL_TREE) @@ -1356,7 +1362,7 @@ decay_conversion (tree exp) return error_mark_node; } - exp = integral_constant_value (exp); + exp = decl_constant_value (exp); /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Leave such NOP_EXPRs, since RHS is being used in non-lvalue context. */ @@ -1822,7 +1828,7 @@ lookup_destructor (tree object, tree scope, tree dtor_name) tree dtor_type = TREE_OPERAND (dtor_name, 0); tree expr; - if (scope && !check_dtor_name (scope, dtor_name)) + if (scope && !check_dtor_name (scope, dtor_type)) { error ("qualified type %qT does not match destructor name ~%qT", scope, dtor_type); @@ -1841,16 +1847,70 @@ lookup_destructor (tree object, tree scope, tree dtor_name) return expr; } +/* An expression of the form "A::template B" has been resolved to + DECL. Issue a diagnostic if B is not a template or template + specialization. */ + +void +check_template_keyword (tree decl) +{ + /* The standard says: + + [temp.names] + + If a name prefixed by the keyword template is not a member + template, the program is ill-formed. + + DR 228 removed the restriction that the template be a member + template. + + DR 96, if accepted would add the further restriction that explicit + template arguments must be provided if the template keyword is + used, but, as of 2005-10-16, that DR is still in "drafting". If + this DR is accepted, then the semantic checks here can be + simplified, as the entity named must in fact be a template + specialization, rather than, as at present, a set of overloaded + functions containing at least one template function. */ + if (TREE_CODE (decl) != TEMPLATE_DECL + && TREE_CODE (decl) != TEMPLATE_ID_EXPR) + { + if (!is_overloaded_fn (decl)) + pedwarn ("%qD is not a template", decl); + else + { + tree fns; + fns = decl; + if (BASELINK_P (fns)) + fns = BASELINK_FUNCTIONS (fns); + while (fns) + { + tree fn = OVL_CURRENT (fns); + if (TREE_CODE (fn) == TEMPLATE_DECL + || TREE_CODE (fn) == TEMPLATE_ID_EXPR) + break; + if (TREE_CODE (fn) == FUNCTION_DECL + && DECL_USE_TEMPLATE (fn) + && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (fn))) + break; + fns = OVL_NEXT (fns); + } + if (!fns) + pedwarn ("%qD is not a template", decl); + } + } +} + /* This function is called by the parser to process a class member access expression of the form OBJECT.NAME. NAME is a node used by the parser to represent a name; it is not yet a DECL. It may, however, be a BASELINK where the BASELINK_FUNCTIONS is a TEMPLATE_ID_EXPR. Templates must be looked up by the parser, and there is no reason to do the lookup twice, so the parser keeps the - BASELINK. */ + BASELINK. TEMPLATE_P is true iff NAME was explicitly declared to + be a template via the use of the "A::template B" syntax. */ tree -finish_class_member_access_expr (tree object, tree name) +finish_class_member_access_expr (tree object, tree name, bool template_p) { tree expr; tree object_type; @@ -1904,11 +1964,8 @@ finish_class_member_access_expr (tree object, tree name) } if (BASELINK_P (name)) - { - /* A member function that has already been looked up. */ - gcc_assert (TREE_CODE (BASELINK_FUNCTIONS (name)) == TEMPLATE_ID_EXPR); - member = name; - } + /* A member function that has already been looked up. */ + member = name; else { bool is_template_id = false; @@ -1998,11 +2055,24 @@ finish_class_member_access_expr (tree object, tree name) if (TREE_DEPRECATED (member)) warn_deprecated_use (member); + if (template_p) + check_template_keyword (member); + expr = build_class_member_access_expr (object, member, access_path, /*preserve_reference=*/false); if (processing_template_decl && expr != error_mark_node) - return build_min_non_dep (COMPONENT_REF, expr, - orig_object, orig_name, NULL_TREE); + { + if (BASELINK_P (member)) + { + if (TREE_CODE (orig_name) == SCOPE_REF) + BASELINK_QUALIFIED_P (member) = 1; + orig_name = member; + } + return build_min_non_dep (COMPONENT_REF, expr, + orig_object, orig_name, + NULL_TREE); + } + return expr; } @@ -2183,15 +2253,7 @@ build_array_ref (tree array, tree idx) { tree rval, type; - /* Subscripting with type char is likely to lose - on a machine where chars are signed. - So warn on any machine, but optionally. - Don't warn for unsigned char since that type is safe. - Don't warn for signed char because anyone who uses that - must have done so deliberately. */ - if (warn_char_subscripts - && TYPE_MAIN_VARIANT (TREE_TYPE (idx)) == char_type_node) - warning (0, "array subscript has type %"); + warn_array_subscript_with_type_char (idx); if (!INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (idx))) { @@ -3025,8 +3087,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case EQ_EXPR: case NE_EXPR: - if (warn_float_equal && (code0 == REAL_TYPE || code1 == REAL_TYPE)) - warning (0, "comparing floating point with == or != is unsafe"); + if (code0 == REAL_TYPE || code1 == REAL_TYPE) + warning (OPT_Wfloat_equal, + "comparing floating point with == or != is unsafe"); + if ((TREE_CODE (orig_op0) == STRING_CST && !integer_zerop (op1)) + || (TREE_CODE (orig_op1) == STRING_CST && !integer_zerop (op0))) + warning (OPT_Wstring_literal_comparison, + "comparison with string literal"); build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE @@ -3132,6 +3199,11 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case GE_EXPR: case LT_EXPR: case GT_EXPR: + if (TREE_CODE (orig_op0) == STRING_CST + || TREE_CODE (orig_op1) == STRING_CST) + warning (OPT_Wstring_literal_comparison, + "comparison with string literal"); + build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) @@ -3626,7 +3698,7 @@ build_x_unary_op (enum tree_code code, tree xarg) } else { - error ("parenthesis around %qE cannot be used to form a" + error ("parentheses around %qE cannot be used to form a" " pointer-to-member-function", xarg); PTRMEM_OK_P (xarg) = 1; @@ -4046,10 +4118,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) is used here to remove this const from the diagnostics and the created OFFSET_REF. */ tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0))); - tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1))); + tree fn = get_first_fn (TREE_OPERAND (arg, 1)); if (! flag_ms_extensions) { + tree name = DECL_NAME (fn); if (current_class_type && TREE_OPERAND (arg, 0) == current_class_ref) /* An expression like &memfn. */ @@ -4063,7 +4136,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) " Say %<&%T::%D%>", base, name); } - arg = build_offset_ref (base, name, /*address_p=*/true); + arg = build_offset_ref (base, fn, /*address_p=*/true); } offset_ref: @@ -4120,75 +4193,93 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) break; } - /* Allow the address of a constructor if all the elements - are constant. */ - if (TREE_CODE (arg) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (arg) - && TREE_CONSTANT (arg)) - ; /* Anything not already handled and not a true memory reference is an error. */ - else if (TREE_CODE (argtype) != FUNCTION_TYPE - && TREE_CODE (argtype) != METHOD_TYPE - && TREE_CODE (arg) != OFFSET_REF - && !lvalue_or_else (arg, lv_addressof)) + if (TREE_CODE (argtype) != FUNCTION_TYPE + && TREE_CODE (argtype) != METHOD_TYPE + && TREE_CODE (arg) != OFFSET_REF + /* Permit users to take the address of a compound-literal + with sufficient simple elements. */ + && !(COMPOUND_LITERAL_P (arg) && TREE_STATIC (arg)) + && !lvalue_or_else (arg, lv_addressof)) return error_mark_node; if (argtype != error_mark_node) argtype = build_pointer_type (argtype); - { - tree addr; + /* In a template, we are processing a non-dependent expression + so we can just form an ADDR_EXPR with the correct type. */ + if (processing_template_decl) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + return val; + } - if (TREE_CODE (arg) != COMPONENT_REF - /* Inside a template, we are processing a non-dependent - expression so we can just form an ADDR_EXPR with the - correct type. */ - || processing_template_decl) - { - addr = build_address (arg); - if (TREE_CODE (arg) == OFFSET_REF) - PTRMEM_OK_P (addr) = PTRMEM_OK_P (arg); - } - else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) - { - tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); - - /* We can only get here with a single static member - function. */ - gcc_assert (TREE_CODE (fn) == FUNCTION_DECL - && DECL_STATIC_FUNCTION_P (fn)); - mark_used (fn); - addr = build_address (fn); - if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) - /* Do not lose object's side effects. */ - addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr), - TREE_OPERAND (arg, 0), addr); - } - else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) - { - error ("attempt to take address of bit-field structure member %qD", - TREE_OPERAND (arg, 1)); - return error_mark_node; - } - else - { - tree object = TREE_OPERAND (arg, 0); - tree field = TREE_OPERAND (arg, 1); - gcc_assert (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (object), decl_type_context (field))); - addr = build_address (arg); - } + /* If the user has taken the address of the compound literal, + create a variable to contain the value of the literal and + then return the address of that variable. */ + if (COMPOUND_LITERAL_P (arg)) + { + tree var; + gcc_assert (TREE_STATIC (arg)); + var = create_temporary_var (TREE_TYPE (arg)); + TREE_STATIC (var) = 1; + set_compound_literal_name (var); + initialize_artificial_var (var, arg); + arg = pushdecl (var); + /* Since each compound literal is unique, pushdecl should + never find a pre-existing variable with the same + name. */ + gcc_assert (arg == var); + } + + if (TREE_CODE (arg) != COMPONENT_REF) + { + val = build_address (arg); + if (TREE_CODE (arg) == OFFSET_REF) + PTRMEM_OK_P (val) = PTRMEM_OK_P (arg); + } + else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) + { + tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); + + /* We can only get here with a single static member + function. */ + gcc_assert (TREE_CODE (fn) == FUNCTION_DECL + && DECL_STATIC_FUNCTION_P (fn)); + mark_used (fn); + val = build_address (fn); + if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0))) + /* Do not lose object's side effects. */ + val = build2 (COMPOUND_EXPR, TREE_TYPE (val), + TREE_OPERAND (arg, 0), val); + } + else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) + { + error ("attempt to take address of bit-field structure member %qD", + TREE_OPERAND (arg, 1)); + return error_mark_node; + } + else + { + tree object = TREE_OPERAND (arg, 0); + tree field = TREE_OPERAND (arg, 1); + gcc_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (object), decl_type_context (field))); + val = build_address (arg); + } - if (TREE_CODE (argtype) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) - { - build_ptrmemfunc_type (argtype); - addr = build_ptrmemfunc (argtype, addr, 0, - /*c_cast_p=*/false); - } + if (TREE_CODE (argtype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) + { + build_ptrmemfunc_type (argtype); + val = build_ptrmemfunc (argtype, val, 0, + /*c_cast_p=*/false); + } - return addr; - } + return val; default: break; @@ -4489,8 +4580,8 @@ check_for_casting_away_constness (tree src_type, tree dest_type, const char *description) { if (diag_fn && casts_away_constness (src_type, dest_type)) - error ("%s from type %qT to type %qT casts away constness", - description, src_type, dest_type); + diag_fn ("%s from type %qT to type %qT casts away constness", + description, src_type, dest_type); } /* Convert EXPR (an expression with pointer-to-member type) to TYPE @@ -4949,6 +5040,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) { + tree sexpr = expr; + if (!c_cast_p) check_for_casting_away_constness (intype, type, error, "reinterpret_cast"); @@ -4963,6 +5056,11 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, "target type", intype, type); + /* We need to strip nops here, because the frontend likes to + create (int *)&a for array-to-pointer decay, instead of &a[0]. */ + STRIP_NOPS (sexpr); + strict_aliasing_warning (intype, type, sexpr); + return fold_if_not_in_template (build_nop (type, expr)); } else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype)) @@ -5015,9 +5113,9 @@ build_reinterpret_cast (tree type, tree expr) /* Perform a const_cast from EXPR to TYPE. If the cast is valid, return an appropriate expression. Otherwise, return error_mark_node. If the cast is not valid, and COMPLAIN is true, - then a diagnostic will be issued. If VALID_P is non-NULL, its - value upon return will indicate whether or not the conversion - succeeded. */ + then a diagnostic will be issued. If VALID_P is non-NULL, we are + performing a C-style cast, its value upon return will indicate + whether or not the conversion succeeded. */ static tree build_const_cast_1 (tree dst_type, tree expr, bool complain, @@ -5093,7 +5191,15 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, && comp_ptr_ttypes_const (dst_type, src_type)) { if (valid_p) - *valid_p = true; + { + *valid_p = true; + /* This cast is actually a C-style cast. Issue a warning if + the user is making a potentially unsafe cast. */ + if (warn_cast_qual) + check_for_casting_away_constness (src_type, dst_type, + warning0, + "cast"); + } if (reference_type) { expr = build_unary_op (ADDR_EXPR, expr, 0); @@ -6326,6 +6432,11 @@ check_return_expr (tree retval, bool *no_warning) /* The type the function is declared to return. */ tree functype = TREE_TYPE (TREE_TYPE (current_function_decl)); + /* The functype's return type will have been set to void, if it + was an incomplete type. Just treat this as 'return;' */ + if (VOID_TYPE_P (functype)) + return error_mark_node; + /* First convert the value to the function's return type, then to the type of return value's location to handle the case that functype is smaller than the valtype. */