X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Fcp%2Ftypeck2.c;fp=gcc%2Fcp%2Ftypeck2.c;h=021f11f3f4651e5c1b3c107c5f735dadd88dcff1;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=4e1acc4bebf2f643fa98e740595911fe8181eed6;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 4e1acc4b..021f11f3 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1,65 +1,64 @@ /* Report error messages, build initializers, and perform some front-end optimizations for C++ compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify +GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. -GNU CC is distributed in the hope that it will be useful, +GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* This file is part of the C++ front end. It contains routines to build C++ expressions given their operands, including computing the types of the result, C and C++ specific error - checks, and some optimization. - - There are also routines to build RETURN_STMT nodes and CASE_STMT nodes, - and to process initializations in declarations (since they work - like a strange sort of assignment). */ + checks, and some optimization. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "cp-tree.h" #include "flags.h" #include "toplev.h" #include "output.h" #include "diagnostic.h" +#include "real.h" + +static tree +process_init_constructor (tree type, tree init); -static tree process_init_constructor PARAMS ((tree, tree, tree *)); /* Print an error message stemming from an attempt to use BASETYPE as a base class for TYPE. */ tree -error_not_base_type (basetype, type) - tree basetype, type; +error_not_base_type (tree basetype, tree type) { if (TREE_CODE (basetype) == FUNCTION_DECL) basetype = DECL_CONTEXT (basetype); - error ("type `%T' is not a base type for type `%T'", basetype, type); + error ("type %qT is not a base type for type %qT", basetype, type); return error_mark_node; } tree -binfo_or_else (base, type) - tree base, type; +binfo_or_else (tree base, tree type) { - tree binfo = lookup_base (type, base, ba_ignore, NULL); + tree binfo = lookup_base (type, base, ba_unique, NULL); if (binfo == error_mark_node) return NULL_TREE; @@ -69,134 +68,283 @@ binfo_or_else (base, type) } /* According to ARM $7.1.6, "A `const' object may be initialized, but its - value may not be changed thereafter. Thus, we emit hard errors for these, - rather than just pedwarns. If `SOFT' is 1, then we just pedwarn. (For - example, conversions to references.) */ + value may not be changed thereafter. */ void -readonly_error (arg, string, soft) - tree arg; - const char *string; - int soft; +readonly_error (tree arg, const char* string) { const char *fmt; - void (*fn) PARAMS ((const char *, ...)); - - if (soft) - fn = pedwarn; - else - fn = error; if (TREE_CODE (arg) == COMPONENT_REF) { if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) - fmt = "%s of data-member `%D' in read-only structure"; + fmt = "%s of data-member %qD in read-only structure"; else - fmt = "%s of read-only data-member `%D'"; - (*fn) (fmt, string, TREE_OPERAND (arg, 1)); + fmt = "%s of read-only data-member %qD"; + error (fmt, string, TREE_OPERAND (arg, 1)); } else if (TREE_CODE (arg) == VAR_DECL) { if (DECL_LANG_SPECIFIC (arg) && DECL_IN_AGGR_P (arg) && !TREE_STATIC (arg)) - fmt = "%s of constant field `%D'"; + fmt = "%s of constant field %qD"; else - fmt = "%s of read-only variable `%D'"; - (*fn) (fmt, string, arg); + fmt = "%s of read-only variable %qD"; + error (fmt, string, arg); } else if (TREE_CODE (arg) == PARM_DECL) - (*fn) ("%s of read-only parameter `%D'", string, arg); + error ("%s of read-only parameter %qD", string, arg); else if (TREE_CODE (arg) == INDIRECT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE - && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL - || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL)) - (*fn) ("%s of read-only reference `%D'", string, TREE_OPERAND (arg, 0)); + && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE + && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL + || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL)) + error ("%s of read-only reference %qD", string, TREE_OPERAND (arg, 0)); else if (TREE_CODE (arg) == RESULT_DECL) - (*fn) ("%s of read-only named return value `%D'", string, arg); + error ("%s of read-only named return value %qD", string, arg); else if (TREE_CODE (arg) == FUNCTION_DECL) - (*fn) ("%s of function `%D'", string, arg); + error ("%s of function %qD", string, arg); else - (*fn) ("%s of read-only location", string); + error ("%s of read-only location %qE", string, arg); +} + + +/* Structure that holds information about declarations whose type was + incomplete and we could not check whether it was abstract or not. */ + +struct pending_abstract_type GTY((chain_next ("%h.next"))) +{ + /* Declaration which we are checking for abstractness. It is either + a DECL node, or an IDENTIFIER_NODE if we do not have a full + declaration available. */ + tree decl; + + /* Type which will be checked for abstractness. */ + tree type; + + /* Position of the declaration. This is only needed for IDENTIFIER_NODEs, + because DECLs already carry locus information. */ + location_t locus; + + /* Link to the next element in list. */ + struct pending_abstract_type* next; +}; + + +/* Compute the hash value of the node VAL. This function is used by the + hash table abstract_pending_vars. */ + +static hashval_t +pat_calc_hash (const void* val) +{ + const struct pending_abstract_type *pat = + (const struct pending_abstract_type *) val; + return (hashval_t) TYPE_UID (pat->type); +} + + +/* Compare node VAL1 with the type VAL2. This function is used by the + hash table abstract_pending_vars. */ + +static int +pat_compare (const void* val1, const void* val2) +{ + const struct pending_abstract_type *const pat1 = + (const struct pending_abstract_type *) val1; + const_tree const type2 = (const_tree)val2; + + return (pat1->type == type2); } +/* Hash table that maintains pending_abstract_type nodes, for which we still + need to check for type abstractness. The key of the table is the type + of the declaration. */ +static GTY ((param_is (struct pending_abstract_type))) +htab_t abstract_pending_vars = NULL; + + +/* This function is called after TYPE is completed, and will check if there + are pending declarations for which we still need to verify the abstractness + of TYPE, and emit a diagnostic (through abstract_virtuals_error) if TYPE + turned out to be incomplete. */ + +void +complete_type_check_abstract (tree type) +{ + void **slot; + struct pending_abstract_type *pat; + location_t cur_loc = input_location; + + gcc_assert (COMPLETE_TYPE_P (type)); + + if (!abstract_pending_vars) + return; + + /* Retrieve the list of pending declarations for this type. */ + slot = htab_find_slot_with_hash (abstract_pending_vars, type, + (hashval_t)TYPE_UID (type), NO_INSERT); + if (!slot) + return; + pat = (struct pending_abstract_type*)*slot; + gcc_assert (pat); + + /* If the type is not abstract, do not do anything. */ + if (CLASSTYPE_PURE_VIRTUALS (type)) + { + struct pending_abstract_type *prev = 0, *next; + + /* Reverse the list to emit the errors in top-down order. */ + for (; pat; pat = next) + { + next = pat->next; + pat->next = prev; + prev = pat; + } + pat = prev; + + /* Go through the list, and call abstract_virtuals_error for each + element: it will issue a diagnostic if the type is abstract. */ + while (pat) + { + gcc_assert (type == pat->type); + + /* Tweak input_location so that the diagnostic appears at the correct + location. Notice that this is only needed if the decl is an + IDENTIFIER_NODE. */ + input_location = pat->locus; + abstract_virtuals_error (pat->decl, pat->type); + pat = pat->next; + } + } + + htab_clear_slot (abstract_pending_vars, slot); + + input_location = cur_loc; +} + + /* If TYPE has abstract virtual functions, issue an error about trying to create an object of that type. DECL is the object declared, or NULL_TREE if the declaration is unavailable. Returns 1 if an error occurred; zero if all was well. */ int -abstract_virtuals_error (decl, type) - tree decl; - tree type; +abstract_virtuals_error (tree decl, tree type) { - tree u; - tree tu; + VEC(tree,gc) *pure; - if (processing_template_decl) - /* If we are processing a template, TYPE may be a template - class where CLASSTYPE_PURE_VIRTUALS always contains - inline friends. */ + /* This function applies only to classes. Any other entity can never + be abstract. */ + if (!CLASS_TYPE_P (type)) return 0; - if (!CLASS_TYPE_P (type) || !CLASSTYPE_PURE_VIRTUALS (type)) - return 0; + /* If the type is incomplete, we register it within a hash table, + so that we can check again once it is completed. This makes sense + only for objects for which we have a declaration or at least a + name. */ + if (!COMPLETE_TYPE_P (type)) + { + void **slot; + struct pending_abstract_type *pat; + + gcc_assert (!decl || DECL_P (decl) + || TREE_CODE (decl) == IDENTIFIER_NODE); + + if (!abstract_pending_vars) + abstract_pending_vars = htab_create_ggc (31, &pat_calc_hash, + &pat_compare, NULL); + + slot = htab_find_slot_with_hash (abstract_pending_vars, type, + (hashval_t)TYPE_UID (type), INSERT); + + pat = GGC_NEW (struct pending_abstract_type); + pat->type = type; + pat->decl = decl; + pat->locus = ((decl && DECL_P (decl)) + ? DECL_SOURCE_LOCATION (decl) + : input_location); + + pat->next = (struct pending_abstract_type *) *slot; + *slot = pat; + + return 0; + } if (!TYPE_SIZE (type)) /* TYPE is being defined, and during that time CLASSTYPE_PURE_VIRTUALS holds the inline friends. */ return 0; - u = CLASSTYPE_PURE_VIRTUALS (type); + pure = CLASSTYPE_PURE_VIRTUALS (type); + if (!pure) + return 0; + if (decl) { if (TREE_CODE (decl) == RESULT_DECL) return 0; if (TREE_CODE (decl) == VAR_DECL) - error ("cannot declare variable `%D' to be of type `%T'", - decl, type); + error ("cannot declare variable %q+D to be of abstract " + "type %qT", decl, type); else if (TREE_CODE (decl) == PARM_DECL) - error ("cannot declare parameter `%D' to be of type `%T'", - decl, type); + error ("cannot declare parameter %q+D to be of abstract type %qT", + decl, type); else if (TREE_CODE (decl) == FIELD_DECL) - error ("cannot declare field `%D' to be of type `%T'", - decl, type); + error ("cannot declare field %q+D to be of abstract type %qT", + decl, type); else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) - error ("invalid return type for member function `%#D'", decl); + error ("invalid abstract return type for member function %q+#D", decl); else if (TREE_CODE (decl) == FUNCTION_DECL) - error ("invalid return type for function `%#D'", decl); + error ("invalid abstract return type for function %q+#D", decl); + else if (TREE_CODE (decl) == IDENTIFIER_NODE) + /* Here we do not have location information. */ + error ("invalid abstract type %qT for %qE", type, decl); + else + error ("invalid abstract type for %q+D", decl); } else - error ("cannot allocate an object of type `%T'", type); + error ("cannot allocate an object of abstract type %qT", type); /* Only go through this once. */ - if (TREE_PURPOSE (u) == NULL_TREE) + if (VEC_length (tree, pure)) { - TREE_PURPOSE (u) = error_mark_node; - - error (" because the following virtual functions are abstract:"); - for (tu = u; tu; tu = TREE_CHAIN (tu)) - cp_error_at ("\t%#D", TREE_VALUE (tu)); + unsigned ix; + tree fn; + + inform (input_location, "%J because the following virtual functions are pure " + "within %qT:", TYPE_MAIN_DECL (type), type); + + for (ix = 0; VEC_iterate (tree, pure, ix, fn); ix++) + inform (input_location, "\t%+#D", fn); + /* Now truncate the vector. This leaves it non-null, so we know + there are pure virtuals, but empty so we don't list them out + again. */ + VEC_truncate (tree, pure, 0); } else - error (" since type `%T' has abstract virtual functions", type); + inform (input_location, "%J since type %qT has pure virtual functions", + TYPE_MAIN_DECL (type), type); return 1; } /* Print an error message for invalid use of an incomplete type. VALUE is the expression that was used (or 0 if that isn't known) - and TYPE is the type that was invalid. */ + and TYPE is the type that was invalid. DIAG_KIND indicates the + type of diagnostic (see diagnostic.def). */ void -incomplete_type_error (value, type) - tree value; - tree type; +cxx_incomplete_type_diagnostic (const_tree value, const_tree type, + diagnostic_t diag_kind) { int decl = 0; - + + gcc_assert (diag_kind == DK_WARNING + || diag_kind == DK_PEDWARN + || diag_kind == DK_ERROR); + /* Avoid duplicate error message. */ if (TREE_CODE (type) == ERROR_MARK) return; @@ -205,10 +353,11 @@ incomplete_type_error (value, type) || TREE_CODE (value) == PARM_DECL || TREE_CODE (value) == FIELD_DECL)) { - cp_error_at ("`%D' has incomplete type", value); + emit_diagnostic (diag_kind, input_location, 0, + "%q+D has incomplete type", value); decl = 1; } -retry: + retry: /* We must print an error message. Be clever about what it says. */ switch (TREE_CODE (type)) @@ -217,52 +366,208 @@ retry: case UNION_TYPE: case ENUMERAL_TYPE: if (!decl) - error ("invalid use of undefined type `%#T'", type); + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of incomplete type %q#T", type); if (!TYPE_TEMPLATE_INFO (type)) - cp_error_at ("forward declaration of `%#T'", type); + emit_diagnostic (diag_kind, input_location, 0, + "forward declaration of %q+#T", type); else - cp_error_at ("declaration of `%#T'", type); + emit_diagnostic (diag_kind, input_location, 0, + "declaration of %q+#T", type); break; case VOID_TYPE: - error ("invalid use of `%T'", type); + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of %qT", type); break; case ARRAY_TYPE: if (TYPE_DOMAIN (type)) - { - type = TREE_TYPE (type); - goto retry; - } - error ("invalid use of array with unspecified bounds"); + { + type = TREE_TYPE (type); + goto retry; + } + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of array with unspecified bounds"); break; case OFFSET_TYPE: bad_member: - error ("invalid use of member (did you forget the `&' ?)"); + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of member (did you forget the %<&%> ?)"); break; case TEMPLATE_TYPE_PARM: - error ("invalid use of template type parameter"); + if (is_auto (type)) + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of %"); + else + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of template type parameter %qT", type); + break; + + case BOUND_TEMPLATE_TEMPLATE_PARM: + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of template template parameter %qT", + TYPE_NAME (type)); + break; + + case TYPENAME_TYPE: + emit_diagnostic (diag_kind, input_location, 0, + "invalid use of dependent type %qT", type); break; case UNKNOWN_TYPE: if (value && TREE_CODE (value) == COMPONENT_REF) - goto bad_member; + goto bad_member; else if (value && TREE_CODE (value) == ADDR_EXPR) - error ("address of overloaded function with no contextual type information"); + emit_diagnostic (diag_kind, input_location, 0, + "address of overloaded function with no contextual " + "type information"); else if (value && TREE_CODE (value) == OVERLOAD) - error ("overloaded function with no contextual type information"); + emit_diagnostic (diag_kind, input_location, 0, + "overloaded function with no contextual type information"); else - error ("insufficient contextual information to determine type"); + emit_diagnostic (diag_kind, input_location, 0, + "insufficient contextual information to determine type"); break; - + default: - abort (); + gcc_unreachable (); } } +/* Backward-compatibility interface to incomplete_type_diagnostic; + required by ../tree.c. */ +#undef cxx_incomplete_type_error +void +cxx_incomplete_type_error (const_tree value, const_tree type) +{ + cxx_incomplete_type_diagnostic (value, type, DK_ERROR); +} + +/* The recursive part of split_nonconstant_init. DEST is an lvalue + expression to which INIT should be assigned. INIT is a CONSTRUCTOR. */ + +static void +split_nonconstant_init_1 (tree dest, tree init) +{ + unsigned HOST_WIDE_INT idx; + tree field_index, value; + tree type = TREE_TYPE (dest); + tree inner_type = NULL; + bool array_type_p = false; + + switch (TREE_CODE (type)) + { + case ARRAY_TYPE: + inner_type = TREE_TYPE (type); + array_type_p = true; + /* FALLTHRU */ + + case RECORD_TYPE: + case UNION_TYPE: + case QUAL_UNION_TYPE: + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, + field_index, value) + { + /* The current implementation of this algorithm assumes that + the field was set for all the elements. This is usually done + by process_init_constructor. */ + gcc_assert (field_index); + + if (!array_type_p) + inner_type = TREE_TYPE (field_index); + + if (TREE_CODE (value) == CONSTRUCTOR) + { + tree sub; + + if (array_type_p) + sub = build4 (ARRAY_REF, inner_type, dest, field_index, + NULL_TREE, NULL_TREE); + else + sub = build3 (COMPONENT_REF, inner_type, dest, field_index, + NULL_TREE); + + split_nonconstant_init_1 (sub, value); + } + else if (!initializer_constant_valid_p (value, inner_type)) + { + tree code; + tree sub; + + /* FIXME: Ordered removal is O(1) so the whole function is + worst-case quadratic. This could be fixed using an aside + bitmap to record which elements must be removed and remove + them all at the same time. Or by merging + split_non_constant_init into process_init_constructor_array, + that is separating constants from non-constants while building + the vector. */ + VEC_ordered_remove (constructor_elt, CONSTRUCTOR_ELTS (init), + idx); + --idx; + + if (array_type_p) + sub = build4 (ARRAY_REF, inner_type, dest, field_index, + NULL_TREE, NULL_TREE); + else + sub = build3 (COMPONENT_REF, inner_type, dest, field_index, + NULL_TREE); + + code = build2 (INIT_EXPR, inner_type, sub, value); + code = build_stmt (EXPR_STMT, code); + add_stmt (code); + continue; + } + } + break; + + case VECTOR_TYPE: + if (!initializer_constant_valid_p (init, type)) + { + tree code; + tree cons = copy_node (init); + CONSTRUCTOR_ELTS (init) = NULL; + code = build2 (MODIFY_EXPR, type, dest, cons); + code = build_stmt (EXPR_STMT, code); + add_stmt (code); + } + break; + + default: + gcc_unreachable (); + } + + /* The rest of the initializer is now a constant. */ + TREE_CONSTANT (init) = 1; +} + +/* A subroutine of store_init_value. Splits non-constant static + initializer INIT into a constant part and generates code to + perform the non-constant part of the initialization to DEST. + Returns the code for the runtime init. */ + +static tree +split_nonconstant_init (tree dest, tree init) +{ + tree code; + + if (TREE_CODE (init) == CONSTRUCTOR) + { + code = push_stmt_list (); + split_nonconstant_init_1 (dest, init); + code = pop_stmt_list (code); + DECL_INITIAL (dest) = init; + TREE_READONLY (dest) = 0; + } + else + code = build2 (INIT_EXPR, TREE_TYPE (dest), dest, init); + + return code; +} + /* Perform appropriate conversions on the initial value of a variable, store it in the declaration DECL, and print any error messages that are appropriate. @@ -278,15 +583,13 @@ retry: into a CONSTRUCTOR and use standard initialization techniques. Perhaps a warning should be generated? - Returns value of initializer if initialization could not be - performed for static variable. In that case, caller must do - the storing. */ + Returns code to be executed if initialization could not be performed + for static variable. In that case, caller must emit the code. */ tree -store_init_value (decl, init) - tree decl, init; +store_init_value (tree decl, tree init) { - register tree value, type; + tree value, type; /* If variable's type was invalidly declared, just ignore it. */ @@ -294,66 +597,24 @@ store_init_value (decl, init) if (TREE_CODE (type) == ERROR_MARK) return NULL_TREE; -#if 0 - /* This breaks arrays, and should not have any effect for other decls. */ - /* Take care of C++ business up here. */ - type = TYPE_MAIN_VARIANT (type); -#endif - - if (IS_AGGR_TYPE (type)) + if (MAYBE_CLASS_TYPE_P (type)) { - if (! TYPE_HAS_TRIVIAL_INIT_REF (type) - && TREE_CODE (init) != CONSTRUCTOR) - abort (); + gcc_assert (TYPE_HAS_TRIVIAL_INIT_REF (type) + || TREE_CODE (init) == CONSTRUCTOR); if (TREE_CODE (init) == TREE_LIST) { - error ("constructor syntax used, but no constructor declared for type `%T'", type); - init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init)); + error ("constructor syntax used, but no constructor declared " + "for type %qT", type); + init = build_constructor_from_list (init_list_type_node, nreverse (init)); } -#if 0 - if (TREE_CODE (init) == CONSTRUCTOR) - { - tree field; - - /* Check that we're really an aggregate as ARM 8.4.1 defines it. */ - if (CLASSTYPE_N_BASECLASSES (type)) - cp_error_at ("initializer list construction invalid for derived class object `%D'", decl); - if (CLASSTYPE_VTBL_PTR (type)) - cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl); - if (TYPE_NEEDS_CONSTRUCTING (type)) - { - cp_error_at ("initializer list construction invalid for `%D'", decl); - error ("due to the presence of a constructor"); - } - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) - if (TREE_PRIVATE (field) || TREE_PROTECTED (field)) - { - cp_error_at ("initializer list construction invalid for `%D'", decl); - cp_error_at ("due to non-public access of member `%D'", field); - } - for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field)) - if (TREE_PRIVATE (field) || TREE_PROTECTED (field)) - { - cp_error_at ("initializer list construction invalid for `%D'", decl); - cp_error_at ("due to non-public access of member `%D'", field); - } - } -#endif } else if (TREE_CODE (init) == TREE_LIST && TREE_TYPE (init) != unknown_type_node) { if (TREE_CODE (decl) == RESULT_DECL) - { - if (TREE_CHAIN (init)) - { - warning ("comma expression used to initialize return value"); - init = build_compound_expr (init); - } - else - init = TREE_VALUE (init); - } + init = build_x_compound_expr_from_list (init, + "return value initializer"); else if (TREE_CODE (init) == TREE_LIST && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) { @@ -361,638 +622,593 @@ store_init_value (decl, init) return NULL_TREE; } else - { - /* We get here with code like `int a (2);' */ - - if (TREE_CHAIN (init) != NULL_TREE) - { - pedwarn ("initializer list being treated as compound expression"); - init = build_compound_expr (init); - } - else - init = TREE_VALUE (init); - } + /* We get here with code like `int a (2);' */ + init = build_x_compound_expr_from_list (init, "initializer"); } /* End of special C++ code. */ - /* We might have already run this bracketed initializer through - digest_init. Don't do so again. */ - if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init) - && TREE_TYPE (init) - && TYPE_MAIN_VARIANT (TREE_TYPE (init)) == TYPE_MAIN_VARIANT (type)) - value = init; - else - /* Digest the specified initializer into an expression. */ - value = digest_init (type, init, (tree *) 0); - - /* Store the expression if valid; else report error. */ - - if (TREE_CODE (value) == ERROR_MARK) - ; - /* Other code expects that initializers for objects of types that need - constructing never make it into DECL_INITIAL, and passes 'init' to - build_aggr_init without checking DECL_INITIAL. So just return. */ - else if (TYPE_NEEDS_CONSTRUCTING (type)) - return value; - else if (TREE_STATIC (decl) - && (! TREE_CONSTANT (value) - || ! initializer_constant_valid_p (value, TREE_TYPE (value)) -#if 0 - /* A STATIC PUBLIC int variable doesn't have to be - run time inited when doing pic. (mrs) */ - /* Since ctors and dtors are the only things that can - reference vtables, and they are always written down - the vtable definition, we can leave the - vtables in initialized data space. - However, other initialized data cannot be initialized - this way. Instead a global file-level initializer - must do the job. */ - || (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl)) -#endif - )) - - return value; -#if 0 /* No, that's C. jason 9/19/94 */ - else - { - if (pedantic && TREE_CODE (value) == CONSTRUCTOR) - { - if (! TREE_CONSTANT (value) || ! TREE_STATIC (value)) - pedwarn ("ISO C++ forbids non-constant aggregate initializer expressions"); - } - } -#endif - - /* Store the VALUE in DECL_INITIAL. If we're building a - statement-tree we will actually expand the initialization later - when we output this function. */ + /* Digest the specified initializer into an expression. */ + value = digest_init (type, init); + /* If the initializer is not a constant, fill in DECL_INITIAL with + the bits that are constant, and then return an expression that + will perform the dynamic initialization. */ + if (value != error_mark_node + && (TREE_SIDE_EFFECTS (value) + || ! initializer_constant_valid_p (value, TREE_TYPE (value)))) + return split_nonconstant_init (decl, value); + /* If the value is a constant, just put it in DECL_INITIAL. If DECL + is an automatic variable, the middle end will turn this into a + dynamic initialization later. */ DECL_INITIAL (decl) = value; return NULL_TREE; } -/* Same as store_init_value, but used for known-to-be-valid static - initializers. Used to introduce a static initializer even in data - structures that may require dynamic initialization. */ + +/* Give errors about narrowing conversions within { }. */ -tree -force_store_init_value (decl, init) - tree decl, init; +void +check_narrowing (tree type, tree init) { - tree type = TREE_TYPE (decl); - int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type); + tree ftype = unlowered_expr_type (init); + bool ok = true; + REAL_VALUE_TYPE d; + bool was_decl = false; - TYPE_NEEDS_CONSTRUCTING (type) = 0; + if (DECL_P (init)) + { + was_decl = true; + init = decl_constant_value (init); + } + + if (TREE_CODE (type) == INTEGER_TYPE + && TREE_CODE (ftype) == REAL_TYPE) + ok = false; + else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype) + && CP_INTEGRAL_TYPE_P (type)) + { + if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype) + && (TREE_CODE (init) != INTEGER_CST + || !int_fits_type_p (init, type))) + ok = false; + } + else if (TREE_CODE (ftype) == REAL_TYPE + && TREE_CODE (type) == REAL_TYPE) + { + if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype)) + { + if (TREE_CODE (init) == REAL_CST) + { + /* Issue 703: Loss of precision is OK as long as the value is + within the representable range of the new type. */ + REAL_VALUE_TYPE r; + d = TREE_REAL_CST (init); + real_convert (&r, TYPE_MODE (type), &d); + if (real_isinf (&r)) + ok = false; + } + else + ok = false; + } + } + else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype) + && TREE_CODE (type) == REAL_TYPE) + { + ok = false; + if (TREE_CODE (init) == INTEGER_CST) + { + d = real_value_from_int_cst (0, init); + if (exact_real_truncate (TYPE_MODE (type), &d)) + ok = true; + } + } - init = store_init_value (decl, init); - if (init) - abort (); + if (!ok) + permerror (input_location, "narrowing conversion of %qE from %qT to %qT inside { }", + init, ftype, type); +} - TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing; +/* Process the initializer INIT for a variable of type TYPE, emitting + diagnostics for invalid initializers and converting the initializer as + appropriate. - return init; -} - -/* Digest the parser output INIT as an initializer for type TYPE. - Return a C expression of type TYPE to represent the initial value. + For aggregate types, it assumes that reshape_init has already run, thus the + initializer will have the right shape (brace elision has been undone). - If TAIL is nonzero, it points to a variable holding a list of elements - of which INIT is the first. We update the list stored there by - removing from the head all the elements that we use. - Normally this is only one; we use more than one element only if - TYPE is an aggregate and INIT is not a constructor. */ + NESTED is true iff we are being called for an element of a CONSTRUCTOR. */ -tree -digest_init (type, init, tail) - tree type, init, *tail; +static tree +digest_init_r (tree type, tree init, bool nested) { enum tree_code code = TREE_CODE (type); - tree element = NULL_TREE; - tree old_tail_contents = NULL_TREE; - /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR - tree node which has no TREE_TYPE. */ - int raw_constructor; - - /* By default, assume we use one element from a list. - We correct this later in the sole case where it is not true. */ - if (tail) - { - old_tail_contents = *tail; - *tail = TREE_CHAIN (*tail); - } - - if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST - && TREE_VALUE (init) == error_mark_node)) + if (init == error_mark_node) return error_mark_node; - if (TREE_CODE (init) == ERROR_MARK) - /* __PRETTY_FUNCTION__'s initializer is a bogus expression inside - a template function. This gets substituted during instantiation. */ - return init; + gcc_assert (init); /* We must strip the outermost array type when completing the type, because the its bounds might be incomplete at the moment. */ if (!complete_type_or_else (TREE_CODE (type) == ARRAY_TYPE ? TREE_TYPE (type) : type, NULL_TREE)) return error_mark_node; - - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ + + /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue + (g++.old-deja/g++.law/casts2.C). */ if (TREE_CODE (init) == NON_LVALUE_EXPR) init = TREE_OPERAND (init, 0); - if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type) - return init; - - raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0; - - if (raw_constructor - && CONSTRUCTOR_ELTS (init) != 0 - && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0) - { - element = TREE_VALUE (CONSTRUCTOR_ELTS (init)); - /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ - if (element && TREE_CODE (element) == NON_LVALUE_EXPR) - element = TREE_OPERAND (element, 0); - if (element == error_mark_node) - return element; - } - - /* Initialization of an array of chars from a string constant - optionally enclosed in braces. */ - + /* Initialization of an array of chars from a string constant. The initializer + can be optionally enclosed in braces, but reshape_init has already removed + them if they were present. */ if (code == ARRAY_TYPE) { - tree typ1; - - if (TREE_CODE (init) == TREE_LIST) - { - error ("initializing array with parameter list"); - return error_mark_node; - } - - typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); + tree typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); if (char_type_p (typ1) - && ((init && TREE_CODE (init) == STRING_CST) - || (element && TREE_CODE (element) == STRING_CST))) + /*&& init */ + && TREE_CODE (init) == STRING_CST) { - tree string = element ? element : init; + tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init))); - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) - != char_type_node) - && TYPE_PRECISION (typ1) == BITS_PER_UNIT) + if (TYPE_PRECISION (typ1) == BITS_PER_UNIT) { - error ("char-array initialized from wide string"); - return error_mark_node; + if (char_type != char_type_node) + { + error ("char-array initialized from wide string"); + return error_mark_node; + } } - if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) - == char_type_node) - && TYPE_PRECISION (typ1) != BITS_PER_UNIT) + else { - error ("int-array initialized from non-wide string"); - return error_mark_node; + if (char_type == char_type_node) + { + error ("int-array initialized from non-wide string"); + return error_mark_node; + } + else if (char_type != typ1) + { + error ("int-array initialized from incompatible wide string"); + return error_mark_node; + } } - TREE_TYPE (string) = type; - if (TYPE_DOMAIN (type) != 0 - && TREE_CONSTANT (TYPE_SIZE (type))) + TREE_TYPE (init) = type; + if (TYPE_DOMAIN (type) != 0 && TREE_CONSTANT (TYPE_SIZE (type))) { - register int size - = TREE_INT_CST_LOW (TYPE_SIZE (type)); + int size = TREE_INT_CST_LOW (TYPE_SIZE (type)); size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; /* In C it is ok to subtract 1 from the length of the string because it's ok to ignore the terminating null char that is counted in the length of the constant, but in C++ this would be invalid. */ - if (size < TREE_STRING_LENGTH (string)) - pedwarn ("initializer-string for array of chars is too long"); + if (size < TREE_STRING_LENGTH (init)) + permerror (input_location, "initializer-string for array of chars is too long"); } - return string; + return init; } } - /* Handle scalar types, including conversions, - and signature pointers and references. */ - - if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE - || code == ENUMERAL_TYPE || code == REFERENCE_TYPE - || code == BOOLEAN_TYPE || code == COMPLEX_TYPE - || TYPE_PTRMEMFUNC_P (type)) + /* Handle scalar types (including conversions) and references. */ + if ((TREE_CODE (type) != COMPLEX_TYPE + || BRACE_ENCLOSED_INITIALIZER_P (init)) + && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE)) { - if (raw_constructor) - { - if (element == 0) - { - error ("initializer for scalar variable requires one element"); - return error_mark_node; - } - init = element; - } - while (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)) - { - pedwarn ("braces around scalar initializer for `%T'", type); - init = CONSTRUCTOR_ELTS (init); - if (TREE_CHAIN (init)) - pedwarn ("ignoring extra initializers for `%T'", type); - init = TREE_VALUE (init); - } + tree *exp; - return convert_for_initialization (0, type, init, LOOKUP_NORMAL, - "initialization", NULL_TREE, 0); - } + if (cxx_dialect != cxx98 && nested) + check_narrowing (type, init); + init = convert_for_initialization (0, type, init, LOOKUP_NORMAL, + "initialization", NULL_TREE, 0, + tf_warning_or_error); + exp = &init; - /* Come here only for records and arrays (and unions with constructors). */ + /* Skip any conversions since we'll be outputting the underlying + constant. */ + while (CONVERT_EXPR_P (*exp) + || TREE_CODE (*exp) == NON_LVALUE_EXPR) + exp = &TREE_OPERAND (*exp, 0); - if (COMPLETE_TYPE_P (type) && ! TREE_CONSTANT (TYPE_SIZE (type))) - { - error ("variable-sized object of type `%T' may not be initialized", - type); - return error_mark_node; + *exp = cplus_expand_constant (*exp); + + return init; } - if (code == ARRAY_TYPE || code == VECTOR_TYPE || IS_AGGR_TYPE_CODE (code)) + /* Come here only for aggregates: records, arrays, unions, complex numbers + and vectors. */ + gcc_assert (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == VECTOR_TYPE + || TREE_CODE (type) == RECORD_TYPE + || TREE_CODE (type) == UNION_TYPE + || TREE_CODE (type) == COMPLEX_TYPE); + + if (BRACE_ENCLOSED_INITIALIZER_P (init) + && !TYPE_NON_AGGREGATE_CLASS (type)) + return process_init_constructor (type, init); + else { - if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type) - && TREE_HAS_CONSTRUCTOR (init)) + if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE) { - error ("subobject of type `%T' must be initialized by constructor, not by `%E'", - type, init); + error ("cannot initialize aggregate of type %qT with " + "a compound literal", type); + return error_mark_node; } - else if (raw_constructor) - return process_init_constructor (type, init, (tree *)0); - else if (can_convert_arg (type, TREE_TYPE (init), init) - || TYPE_NON_AGGREGATE_CLASS (type)) - /* These are never initialized from multiple constructor elements. */; - else if (tail != 0) - { - *tail = old_tail_contents; - return process_init_constructor (type, 0, tail); - } - if (code != ARRAY_TYPE) + if (TREE_CODE (type) == ARRAY_TYPE + && TREE_CODE (init) != CONSTRUCTOR) { - int flags = LOOKUP_NORMAL; - /* Initialization from { } is copy-initialization. */ - if (tail) - flags |= LOOKUP_ONLYCONVERTING; - - return convert_for_initialization (NULL_TREE, type, init, flags, - "initialization", NULL_TREE, 0); + error ("array must be initialized with a brace-enclosed" + " initializer"); + return error_mark_node; } + + return convert_for_initialization (NULL_TREE, type, init, + LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING, + "initialization", NULL_TREE, 0, + tf_warning_or_error); } +} - error ("invalid initializer"); - return error_mark_node; +tree +digest_init (tree type, tree init) +{ + return digest_init_r (type, init, false); } -/* Process a constructor for a variable of type TYPE. - The constructor elements may be specified either with INIT or with ELTS, - only one of which should be non-null. +/* Set of flags used within process_init_constructor to describe the + initializers. */ +#define PICFLAG_ERRONEOUS 1 +#define PICFLAG_NOT_ALL_CONSTANT 2 +#define PICFLAG_NOT_ALL_SIMPLE 4 - If INIT is specified, it is a CONSTRUCTOR node which is specifically - and solely for initializing this datum. +/* Given an initializer INIT, return the flag (PICFLAG_*) which better + describe it. */ - If ELTS is specified, it is the address of a variable containing - a list of expressions. We take as many elements as we need - from the head of the list and update the list. +static int +picflag_from_initializer (tree init) +{ + if (init == error_mark_node) + return PICFLAG_ERRONEOUS; + else if (!TREE_CONSTANT (init)) + return PICFLAG_NOT_ALL_CONSTANT; + else if (!initializer_constant_valid_p (init, TREE_TYPE (init))) + return PICFLAG_NOT_ALL_SIMPLE; + return 0; +} - In the resulting constructor, TREE_CONSTANT is set if all elts are - constant, and TREE_STATIC is set if, in addition, all elts are simple enough - constants that the assembler and linker can compute them. */ +/* Subroutine of process_init_constructor, which will process an initializer + INIT for an array or vector of type TYPE. Returns the flags (PICFLAG_*) + which describe the initializers. */ -static tree -process_init_constructor (type, init, elts) - tree type, init, *elts; +static int +process_init_constructor_array (tree type, tree init) { - register tree tail; - /* List of the elements of the result constructor, - in reverse order. */ - register tree members = NULL; - register tree next1; - tree result; - int allconstant = 1; - int allsimple = 1; - int erroneous = 0; - - /* Make TAIL be the list of elements to use for the initialization, - no matter how the data was given to us. */ - - if (elts) + unsigned HOST_WIDE_INT i, len = 0; + int flags = 0; + bool unbounded = false; + constructor_elt *ce; + VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (init); + + gcc_assert (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == VECTOR_TYPE); + + if (TREE_CODE (type) == ARRAY_TYPE) { - if (warn_missing_braces) - warning ("aggregate has a partly bracketed initializer"); - tail = *elts; + tree domain = TYPE_DOMAIN (type); + if (domain) + len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)) + - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)) + + 1); + else + unbounded = true; /* Take as many as there are. */ } else - tail = CONSTRUCTOR_ELTS (init); + /* Vectors are like simple fixed-size arrays. */ + len = TYPE_VECTOR_SUBPARTS (type); - /* Gobble as many elements as needed, and make a constructor or initial value - for each element of this aggregate. Chain them together in result. - If there are too few, use 0 for each scalar ultimate component. */ + /* There must not be more initializers than needed. */ + if (!unbounded && VEC_length (constructor_elt, v) > len) + error ("too many initializers for %qT", type); - if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE) + for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i) { - register long len; - register int i; - - if (TREE_CODE (type) == ARRAY_TYPE) + if (ce->index) { - tree domain = TYPE_DOMAIN (type); - if (domain) - len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)) - - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)) - + 1); - else - len = -1; /* Take as many as there are */ + gcc_assert (TREE_CODE (ce->index) == INTEGER_CST); + if (compare_tree_int (ce->index, i) != 0) + { + ce->value = error_mark_node; + sorry ("non-trivial designated initializers not supported"); + } } else + ce->index = size_int (i); + gcc_assert (ce->value); + ce->value = digest_init_r (TREE_TYPE (type), ce->value, true); + + if (ce->value != error_mark_node) + gcc_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (type), TREE_TYPE (ce->value))); + + flags |= picflag_from_initializer (ce->value); + } + + /* No more initializers. If the array is unbounded, we are done. Otherwise, + we must add initializers ourselves. */ + if (!unbounded) + for (; i < len; ++i) + { + tree next; + + if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) + { + /* If this type needs constructors run for default-initialization, + we can't rely on the back end to do it for us, so build up + TARGET_EXPRs. If the type in question is a class, just build + one up; if it's an array, recurse. */ + if (MAYBE_CLASS_TYPE_P (TREE_TYPE (type))) + next = build_functional_cast (TREE_TYPE (type), NULL_TREE, + tf_warning_or_error); + else + next = build_constructor (init_list_type_node, NULL); + next = digest_init (TREE_TYPE (type), next); + } + else if (!zero_init_p (TREE_TYPE (type))) + next = build_zero_init (TREE_TYPE (type), + /*nelts=*/NULL_TREE, + /*static_storage_p=*/false); + else + /* The default zero-initialization is fine for us; don't + add anything to the CONSTRUCTOR. */ + break; + + flags |= picflag_from_initializer (next); + CONSTRUCTOR_APPEND_ELT (v, size_int (i), next); + } + + CONSTRUCTOR_ELTS (init) = v; + return flags; +} + +/* Subroutine of process_init_constructor, which will process an initializer + INIT for a class of type TYPE. Returns the flags (PICFLAG_*) which describe + the initializers. */ + +static int +process_init_constructor_record (tree type, tree init) +{ + VEC(constructor_elt,gc) *v = NULL; + int flags = 0; + tree field; + unsigned HOST_WIDE_INT idx = 0; + + gcc_assert (TREE_CODE (type) == RECORD_TYPE); + gcc_assert (!CLASSTYPE_VBASECLASSES (type)); + gcc_assert (!TYPE_BINFO (type) + || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type))); + gcc_assert (!TYPE_POLYMORPHIC_P (type)); + + /* Generally, we will always have an index for each initializer (which is + a FIELD_DECL, put by reshape_init), but compound literals don't go trough + reshape_init. So we need to handle both cases. */ + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + { + tree next; + tree type; + + if (!DECL_NAME (field) && DECL_C_BIT_FIELD (field)) { - /* Vectors are like simple fixed-size arrays. */ - len = TYPE_VECTOR_SUBPARTS (type); + flags |= picflag_from_initializer (integer_zero_node); + CONSTRUCTOR_APPEND_ELT (v, field, integer_zero_node); + continue; } - for (i = 0; len < 0 || i < len; i++) + if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) + continue; + + /* If this is a bitfield, first convert to the declared type. */ + type = TREE_TYPE (field); + if (DECL_BIT_FIELD_TYPE (field)) + type = DECL_BIT_FIELD_TYPE (field); + + if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init))) { - if (tail) + constructor_elt *ce = VEC_index (constructor_elt, + CONSTRUCTOR_ELTS (init), idx); + if (ce->index) { - if (TREE_PURPOSE (tail) - && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST - || compare_tree_int (TREE_PURPOSE (tail), i) != 0)) - sorry ("non-trivial labeled initializers"); - - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; - next1 = digest_init (TREE_TYPE (type), - TREE_VALUE (tail), &tail1); - if (next1 == error_mark_node) - return next1; - my_friendly_assert - (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (type), TREE_TYPE (next1)), - 981123); - my_friendly_assert (tail1 == 0 - || TREE_CODE (tail1) == TREE_LIST, 319); - if (tail == tail1 && len < 0) - { - error ("non-empty initializer for array of empty elements"); - /* Just ignore what we were supposed to use. */ - tail1 = NULL_TREE; - } - tail = tail1; - } - else + /* We can have either a FIELD_DECL or an IDENTIFIER_NODE. The + latter case can happen in templates where lookup has to be + deferred. */ + gcc_assert (TREE_CODE (ce->index) == FIELD_DECL + || TREE_CODE (ce->index) == IDENTIFIER_NODE); + if (ce->index != field + && ce->index != DECL_NAME (field)) { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); + ce->value = error_mark_node; + sorry ("non-trivial designated initializers not supported"); } } - else if (len < 0) - /* We're done. */ - break; - else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) - { - /* If this type needs constructors run for - default-initialization, we can't rely on the backend to do it - for us, so build up TARGET_EXPRs. If the type in question is - a class, just build one up; if it's an array, recurse. */ - if (IS_AGGR_TYPE (TREE_TYPE (type))) - next1 = build_functional_cast (TREE_TYPE (type), NULL_TREE); - else - next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE); - next1 = digest_init (TREE_TYPE (type), next1, 0); - } - else if (! zero_init_p (TREE_TYPE (type))) - next1 = build_forced_zero_init (TREE_TYPE (type)); + gcc_assert (ce->value); + next = digest_init_r (type, ce->value, true); + ++idx; + } + else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) + { + /* If this type needs constructors run for + default-initialization, we can't rely on the back end to do it + for us, so build up TARGET_EXPRs. If the type in question is + a class, just build one up; if it's an array, recurse. */ + if (MAYBE_CLASS_TYPE_P (TREE_TYPE (field))) + next = build_functional_cast (TREE_TYPE (field), NULL_TREE, + tf_warning_or_error); + else + next = build_constructor (init_list_type_node, NULL); + + next = digest_init_r (TREE_TYPE (field), next, true); + + /* Warn when some struct elements are implicitly initialized. */ + warning (OPT_Wmissing_field_initializers, + "missing initializer for member %qD", field); + } + else + { + if (TREE_READONLY (field)) + error ("uninitialized const member %qD", field); + else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field))) + error ("member %qD with uninitialized const fields", field); + else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) + error ("member %qD is uninitialized reference", field); + + /* Warn when some struct elements are implicitly initialized + to zero. */ + warning (OPT_Wmissing_field_initializers, + "missing initializer for member %qD", field); + + if (!zero_init_p (TREE_TYPE (field))) + next = build_zero_init (TREE_TYPE (field), /*nelts=*/NULL_TREE, + /*static_storage_p=*/false); else /* The default zero-initialization is fine for us; don't - add anything to the CONSTRUCTOR. */ - break; - - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) - allsimple = 0; - members = tree_cons (size_int (i), next1, members); + add anything to the CONSTRUCTOR. */ + continue; } - } - else if (TREE_CODE (type) == RECORD_TYPE) - { - register tree field; - if (tail) - { - if (TYPE_USES_VIRTUAL_BASECLASSES (type)) - { - sorry ("initializer list for object of class with virtual base classes"); - return error_mark_node; - } + /* If this is a bitfield, now convert to the lowered type. */ + if (type != TREE_TYPE (field)) + next = cp_convert_and_check (TREE_TYPE (field), next); + flags |= picflag_from_initializer (next); + CONSTRUCTOR_APPEND_ELT (v, field, next); + } - if (TYPE_BINFO_BASETYPES (type)) - { - sorry ("initializer list for object of class with base classes"); - return error_mark_node; - } + if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init))) + error ("too many initializers for %qT", type); + + CONSTRUCTOR_ELTS (init) = v; + return flags; +} - if (TYPE_POLYMORPHIC_P (type)) - { - sorry ("initializer list for object using virtual functions"); - return error_mark_node; - } - } +/* Subroutine of process_init_constructor, which will process a single + initializer INIT for a union of type TYPE. Returns the flags (PICFLAG_*) + which describe the initializer. */ - for (field = TYPE_FIELDS (type); field; - field = TREE_CHAIN (field)) - { - if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field)) - { - members = tree_cons (field, integer_zero_node, members); - continue; - } +static int +process_init_constructor_union (tree type, tree init) +{ + constructor_elt *ce; + int len; - if (TREE_CODE (field) != FIELD_DECL) - continue; + /* If the initializer was empty, use default zero initialization. */ + if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init))) + return 0; - if (tail) - { - if (TREE_PURPOSE (tail) - && TREE_PURPOSE (tail) != field - && TREE_PURPOSE (tail) != DECL_NAME (field)) - sorry ("non-trivial labeled initializers"); + len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)); + if (len > 1) + { + error ("too many initializers for %qT", type); + VEC_block_remove (constructor_elt, CONSTRUCTOR_ELTS (init), 1, len-1); + } - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; + ce = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (init), 0); - next1 = digest_init (TREE_TYPE (field), - TREE_VALUE (tail), &tail1); - my_friendly_assert (tail1 == 0 - || TREE_CODE (tail1) == TREE_LIST, 320); - tail = tail1; - } - else - { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); - } - } - else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) - { - /* If this type needs constructors run for - default-initialization, we can't rely on the backend to do it - for us, so build up TARGET_EXPRs. If the type in question is - a class, just build one up; if it's an array, recurse. */ - - if (IS_AGGR_TYPE (TREE_TYPE (field))) - next1 = build_functional_cast (TREE_TYPE (field), - NULL_TREE); - else - { - next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, - NULL_TREE); - if (init) - TREE_HAS_CONSTRUCTOR (next1) - = TREE_HAS_CONSTRUCTOR (init); - } - next1 = digest_init (TREE_TYPE (field), next1, 0); - - /* Warn when some struct elements are implicitly initialized. */ - if (extra_warnings - && (!init || TREE_HAS_CONSTRUCTOR (init))) - warning ("missing initializer for member `%D'", field); - } - else + /* If this element specifies a field, initialize via that field. */ + if (ce->index) + { + if (TREE_CODE (ce->index) == FIELD_DECL) + ; + else if (TREE_CODE (ce->index) == IDENTIFIER_NODE) + { + /* This can happen within a cast, see g++.dg/opt/cse2.C. */ + tree name = ce->index; + tree field; + for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + if (DECL_NAME (field) == name) + break; + if (!field) { - if (TREE_READONLY (field)) - error ("uninitialized const member `%D'", field); - else if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field))) - error ("member `%D' with uninitialized const fields", - field); - else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) - error ("member `%D' is uninitialized reference", field); - - /* Warn when some struct elements are implicitly initialized - to zero. */ - if (extra_warnings - && (!init || TREE_HAS_CONSTRUCTOR (init))) - warning ("missing initializer for member `%D'", field); - - if (! zero_init_p (TREE_TYPE (field))) - next1 = build_forced_zero_init (TREE_TYPE (field)); - else - /* The default zero-initialization is fine for us; don't - add anything to the CONSTRUCTOR. */ - continue; + error ("no field %qD found in union being initialized", field); + ce->value = error_mark_node; } - - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) - allsimple = 0; - members = tree_cons (field, next1, members); + ce->index = field; + } + else + { + gcc_assert (TREE_CODE (ce->index) == INTEGER_CST + || TREE_CODE (ce->index) == RANGE_EXPR); + error ("index value instead of field name in union initializer"); + ce->value = error_mark_node; } } - else if (TREE_CODE (type) == UNION_TYPE - /* If the initializer was empty, use default zero initialization. */ - && tail) + else { - register tree field = TYPE_FIELDS (type); - /* Find the first named field. ANSI decided in September 1990 that only named fields count here. */ - while (field && (DECL_NAME (field) == 0 - || TREE_CODE (field) != FIELD_DECL)) + tree field = TYPE_FIELDS (type); + while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL)) field = TREE_CHAIN (field); - - /* If this element specifies a field, initialize via that field. */ - if (TREE_PURPOSE (tail) != NULL_TREE) - { - int win = 0; - - if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL) - /* Handle the case of a call by build_c_cast. */ - field = TREE_PURPOSE (tail), win = 1; - else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE) - error ("index value instead of field name in union initializer"); - else - { - tree temp; - for (temp = TYPE_FIELDS (type); - temp; - temp = TREE_CHAIN (temp)) - if (DECL_NAME (temp) == TREE_PURPOSE (tail)) - break; - if (temp) - field = temp, win = 1; - else - error ("no field `%D' in union being initialized", - TREE_PURPOSE (tail)); - } - if (!win) - TREE_VALUE (tail) = error_mark_node; - } - else if (field == 0) + if (field == NULL_TREE) { - error ("union `%T' with no named members cannot be initialized", - type); - TREE_VALUE (tail) = error_mark_node; + error ("too many initializers for %qT", type); + ce->value = error_mark_node; } + ce->index = field; + } - if (TREE_VALUE (tail) != 0) - { - tree tail1 = tail; + if (ce->value && ce->value != error_mark_node) + ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true); - next1 = digest_init (TREE_TYPE (field), - TREE_VALUE (tail), &tail1); - if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) - abort (); - tail = tail1; - } - else - { - next1 = error_mark_node; - tail = TREE_CHAIN (tail); - } + return picflag_from_initializer (ce->value); +} - if (next1 == error_mark_node) - erroneous = 1; - else if (!TREE_CONSTANT (next1)) - allconstant = 0; - else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) - allsimple = 0; - members = tree_cons (field, next1, members); - } +/* Process INIT, a constructor for a variable of aggregate type TYPE. The + constructor is a brace-enclosed initializer, and will be modified in-place. + + Each element is converted to the right type through digest_init, and + missing initializers are added following the language rules (zero-padding, + etc.). + + After the execution, the initializer will have TREE_CONSTANT if all elts are + constant, and TREE_STATIC set if, in addition, all elts are simple enough + constants that the assembler and linker can compute them. + + The function returns the initializer itself, or error_mark_node in case + of error. */ + +static tree +process_init_constructor (tree type, tree init) +{ + int flags; - /* If arguments were specified as a list, just remove the ones we used. */ - if (elts) - *elts = tail; - /* If arguments were specified as a constructor, - complain unless we used all the elements of the constructor. */ - else if (tail) - pedwarn ("excess elements in aggregate initializer"); + gcc_assert (BRACE_ENCLOSED_INITIALIZER_P (init)); - if (erroneous) + if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE) + flags = process_init_constructor_array (type, init); + else if (TREE_CODE (type) == RECORD_TYPE) + flags = process_init_constructor_record (type, init); + else if (TREE_CODE (type) == UNION_TYPE) + flags = process_init_constructor_union (type, init); + else + gcc_unreachable (); + + if (flags & PICFLAG_ERRONEOUS) return error_mark_node; - result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members)); + TREE_TYPE (init) = type; if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE) - complete_array_type (type, result, /*do_default=*/0); - if (init) - TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init); - if (allconstant) TREE_CONSTANT (result) = 1; - if (allconstant && allsimple) TREE_STATIC (result) = 1; - return result; + cp_complete_array_type (&TREE_TYPE (init), init, /*do_default=*/0); + if (!(flags & PICFLAG_NOT_ALL_CONSTANT)) + { + TREE_CONSTANT (init) = 1; + if (!(flags & PICFLAG_NOT_ALL_SIMPLE)) + TREE_STATIC (init) = 1; + } + return init; } /* Given a structure or union value DATUM, construct and return the structure or union component which results from narrowing - that value by the type specified in BASETYPE. For example, given the + that value to the base specified in BASETYPE. For example, given the hierarchy class L { int ii; }; @@ -1013,29 +1229,33 @@ process_init_constructor (type, init, elts) I used to think that this was nonconformant, that the standard specified that first we look up ii in A, then convert x to an L& and pull out the ii part. But in fact, it does say that we convert x to an A&; A here - is known as the "naming class". (jason 2000-12-19) */ + is known as the "naming class". (jason 2000-12-19) + + BINFO_P points to a variable initialized either to NULL_TREE or to the + binfo for the specific base subobject we want to convert to. */ tree -build_scoped_ref (datum, basetype) - tree datum; - tree basetype; +build_scoped_ref (tree datum, tree basetype, tree* binfo_p) { - tree ref; tree binfo; if (datum == error_mark_node) return error_mark_node; - binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL); + if (*binfo_p) + binfo = *binfo_p; + else + binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL); - if (binfo == error_mark_node) - return error_mark_node; - if (!binfo) - return error_not_base_type (TREE_TYPE (datum), basetype); - - ref = build_unary_op (ADDR_EXPR, datum, 0); - ref = build_base_path (PLUS_EXPR, ref, binfo, 1); + if (!binfo || binfo == error_mark_node) + { + *binfo_p = NULL_TREE; + if (!binfo) + error_not_base_type (basetype, TREE_TYPE (datum)); + return error_mark_node; + } - return build_indirect_ref (ref, "(compiler error in build_scoped_ref)"); + *binfo_p = binfo; + return build_base_path (PLUS_EXPR, datum, binfo, 1); } /* Build a reference to an object specified by the C++ `->' operator. @@ -1046,56 +1266,49 @@ build_scoped_ref (datum, basetype) delegation is detected. */ tree -build_x_arrow (datum) - tree datum; +build_x_arrow (tree expr) { + tree orig_expr = expr; tree types_memoized = NULL_TREE; - register tree rval = datum; - tree type = TREE_TYPE (rval); + tree type = TREE_TYPE (expr); tree last_rval = NULL_TREE; if (type == error_mark_node) return error_mark_node; if (processing_template_decl) - return build_min_nt (ARROW_EXPR, rval); - - if (TREE_CODE (rval) == OFFSET_REF) { - rval = resolve_offset_ref (datum); - type = TREE_TYPE (rval); + if (type_dependent_expression_p (expr)) + return build_min_nt (ARROW_EXPR, expr); + expr = build_non_dependent_expr (expr); } - if (TREE_CODE (type) == REFERENCE_TYPE) + if (MAYBE_CLASS_TYPE_P (type)) { - rval = convert_from_reference (rval); - type = TREE_TYPE (rval); - } - - if (IS_AGGR_TYPE (type)) - { - while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, - NULL_TREE, NULL_TREE))) + while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr, + NULL_TREE, NULL_TREE, + /*overloaded_p=*/NULL, + tf_warning_or_error))) { - if (rval == error_mark_node) + if (expr == error_mark_node) return error_mark_node; - if (value_member (TREE_TYPE (rval), types_memoized)) + if (value_member (TREE_TYPE (expr), types_memoized)) { error ("circular pointer delegation detected"); return error_mark_node; } else { - types_memoized = tree_cons (NULL_TREE, TREE_TYPE (rval), + types_memoized = tree_cons (NULL_TREE, TREE_TYPE (expr), types_memoized); } - last_rval = rval; - } + last_rval = expr; + } if (last_rval == NULL_TREE) { - error ("base operand of `->' has non-pointer type `%T'", type); + error ("base operand of %<->%> has non-pointer type %qT", type); return error_mark_node; } @@ -1103,167 +1316,164 @@ build_x_arrow (datum) last_rval = convert_from_reference (last_rval); } else - last_rval = default_conversion (rval); + last_rval = decay_conversion (expr); if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE) - return build_indirect_ref (last_rval, NULL); + { + if (processing_template_decl) + { + expr = build_min_non_dep (ARROW_EXPR, last_rval, orig_expr); + /* It will be dereferenced. */ + TREE_TYPE (expr) = TREE_TYPE (TREE_TYPE (last_rval)); + return expr; + } + + return cp_build_indirect_ref (last_rval, NULL, tf_warning_or_error); + } if (types_memoized) - error ("result of `operator->()' yields non-pointer result"); + error ("result of %()%> yields non-pointer result"); else - error ("base operand of `->' is not a pointer"); + error ("base operand of %<->%> is not a pointer"); return error_mark_node; } -/* Make an expression to refer to the COMPONENT field of - structure or union value DATUM. COMPONENT is an arbitrary - expression. DATUM has not already been checked out to be of - aggregate type. - - For C++, COMPONENT may be a TREE_LIST. This happens when we must - return an object of member type to a method of the current class, - but there is not yet enough typing information to know which one. - As a special case, if there is only one method by that name, - it is returned. Otherwise we return an expression which other - routines will have to know how to deal with later. */ +/* Return an expression for "DATUM .* COMPONENT". DATUM has not + already been checked out to be of aggregate type. */ tree -build_m_component_ref (datum, component) - tree datum, component; +build_m_component_ref (tree datum, tree component) { - tree type; + tree ptrmem_type; tree objtype; - tree field_type; - int type_quals; + tree type; tree binfo; + tree ctype; - if (processing_template_decl) - return build_min_nt (DOTSTAR_EXPR, datum, component); - - datum = decay_conversion (datum); - - if (datum == error_mark_node || component == error_mark_node) + if (error_operand_p (datum) || error_operand_p (component)) return error_mark_node; - objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); - - if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component))) + ptrmem_type = TREE_TYPE (component); + if (!TYPE_PTR_TO_MEMBER_P (ptrmem_type)) { - type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component))); - field_type = type; + error ("%qE cannot be used as a member pointer, since it is of " + "type %qT", + component, ptrmem_type); + return error_mark_node; } - else if (TYPE_PTRMEM_P (TREE_TYPE (component))) - { - type = TREE_TYPE (TREE_TYPE (component)); - field_type = TREE_TYPE (type); - - /* Compute the type of the field, as described in [expr.ref]. */ - type_quals = TYPE_UNQUALIFIED; - if (TREE_CODE (field_type) == REFERENCE_TYPE) - /* The standard says that the type of the result should be the - type referred to by the reference. But for now, at least, - we do the conversion from reference type later. */ - ; - else - { - type_quals = (cp_type_quals (field_type) - | cp_type_quals (TREE_TYPE (datum))); - /* There's no such thing as a mutable pointer-to-member, so - we don't need to deal with that here like we do in - build_component_ref. */ - field_type = cp_build_qualified_type (field_type, type_quals); - } - } - else + objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); + if (! MAYBE_CLASS_TYPE_P (objtype)) { - error ("`%E' cannot be used as a member pointer, since it is of type `%T'", - component, TREE_TYPE (component)); + error ("cannot apply member pointer %qE to %qE, which is of " + "non-class type %qT", + component, datum, objtype); return error_mark_node; } - if (! IS_AGGR_TYPE (objtype)) + type = TYPE_PTRMEM_POINTED_TO_TYPE (ptrmem_type); + ctype = complete_type (TYPE_PTRMEM_CLASS_TYPE (ptrmem_type)); + + if (!COMPLETE_TYPE_P (ctype)) { - error ("cannot apply member pointer `%E' to `%E', which is of non-aggregate type `%T'", - component, datum, objtype); - return error_mark_node; + if (!same_type_p (ctype, objtype)) + goto mismatch; + binfo = NULL; } - - binfo = lookup_base (objtype, TYPE_METHOD_BASETYPE (type), - ba_check, NULL); - if (!binfo) + else { - error ("member type `%T::' incompatible with object type `%T'", - TYPE_METHOD_BASETYPE (type), objtype); - return error_mark_node; + binfo = lookup_base (objtype, ctype, ba_check, NULL); + + if (!binfo) + { + mismatch: + error ("pointer to member type %qT incompatible with object " + "type %qT", + type, objtype); + return error_mark_node; + } + else if (binfo == error_mark_node) + return error_mark_node; } - else if (binfo == error_mark_node) - return error_mark_node; - component = build (OFFSET_REF, field_type, datum, component); - if (TREE_CODE (type) == OFFSET_TYPE) - component = resolve_offset_ref (component); - return component; + if (TYPE_PTRMEM_P (ptrmem_type)) + { + tree ptype; + + /* Compute the type of the field, as described in [expr.ref]. + There's no such thing as a mutable pointer-to-member, so + things are not as complex as they are for references to + non-static data members. */ + type = cp_build_qualified_type (type, + (cp_type_quals (type) + | cp_type_quals (TREE_TYPE (datum)))); + + datum = build_address (datum); + + /* Convert object to the correct base. */ + if (binfo) + datum = build_base_path (PLUS_EXPR, datum, binfo, 1); + + /* Build an expression for "object + offset" where offset is the + value stored in the pointer-to-data-member. */ + ptype = build_pointer_type (type); + datum = build2 (POINTER_PLUS_EXPR, ptype, + fold_convert (ptype, datum), + build_nop (sizetype, component)); + return cp_build_indirect_ref (datum, 0, tf_warning_or_error); + } + else + return build2 (OFFSET_REF, type, datum, component); } /* Return a tree node for the expression TYPENAME '(' PARMS ')'. */ tree -build_functional_cast (exp, parms) - tree exp; - tree parms; +build_functional_cast (tree exp, tree parms, tsubst_flags_t complain) { /* This is either a call to a constructor, or a C cast in C++'s `functional' notation. */ + + /* The type to which we are casting. */ tree type; if (exp == error_mark_node || parms == error_mark_node) return error_mark_node; - if (TREE_CODE (exp) == IDENTIFIER_NODE) - { - if (IDENTIFIER_HAS_TYPE_VALUE (exp)) - /* Either an enum or an aggregate type. */ - type = IDENTIFIER_TYPE_VALUE (exp); - else - { - type = lookup_name (exp, 1); - if (!type || TREE_CODE (type) != TYPE_DECL) - { - error ("`%T' fails to be a typedef or built-in type", exp); - return error_mark_node; - } - type = TREE_TYPE (type); - } - } - else if (TREE_CODE (exp) == TYPE_DECL) + if (TREE_CODE (exp) == TYPE_DECL) type = TREE_TYPE (exp); else type = exp; + if (TREE_CODE (type) == REFERENCE_TYPE && !parms) + { + error ("invalid value-initialization of reference types"); + return error_mark_node; + } + if (processing_template_decl) - return build_min (CAST_EXPR, type, parms); + { + tree t = build_min (CAST_EXPR, type, parms); + /* We don't know if it will or will not have side effects. */ + TREE_SIDE_EFFECTS (t) = 1; + return t; + } - if (! IS_AGGR_TYPE (type)) + if (! MAYBE_CLASS_TYPE_P (type)) { - /* this must build a C cast */ if (parms == NULL_TREE) - parms = integer_zero_node; - else - { - if (TREE_CHAIN (parms) != NULL_TREE) - pedwarn ("initializer list being treated as compound expression"); - parms = build_compound_expr (parms); - } + return cp_convert (type, integer_zero_node); - return build_c_cast (type, parms); + /* This must build a C cast. */ + parms = build_x_compound_expr_from_list (parms, "functional cast"); + return cp_build_c_cast (type, parms, complain); } /* Prepare to evaluate as a call to a constructor. If this expression is actually used, for example, - + return X (arg1, arg2, ...); - + then the slot being initialized will be filled in. */ if (!complete_type_or_else (type, NULL_TREE)) @@ -1271,20 +1481,33 @@ build_functional_cast (exp, parms) if (abstract_virtuals_error (NULL_TREE, type)) return error_mark_node; + /* [expr.type.conv] + + If the expression list is a single-expression, the type + conversion is equivalent (in definedness, and if defined in + meaning) to the corresponding cast expression. */ if (parms && TREE_CHAIN (parms) == NULL_TREE) - return build_c_cast (type, TREE_VALUE (parms)); + return cp_build_c_cast (type, TREE_VALUE (parms), complain); + + /* [expr.type.conv] - /* We need to zero-initialize POD types. Let's do that for everything - that doesn't need a constructor. */ - if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type) - && TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) + The expression T(), where T is a simple-type-specifier for a + non-array complete object type or the (possibly cv-qualified) + void type, creates an rvalue of the specified type, which is + value-initialized. */ + + if (parms == NULL_TREE + /* If there's a user-defined constructor, value-initialization is + just calling the constructor, so fall through. */ + && !TYPE_HAS_USER_CONSTRUCTOR (type)) { - exp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); + exp = build_value_init (type); return get_target_expr (exp); } - exp = build_method_call (NULL_TREE, complete_ctor_identifier, parms, - TYPE_BINFO (type), LOOKUP_NORMAL); + /* Call the constructor. */ + exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms, + type, LOOKUP_NORMAL, complain); if (exp == error_mark_node) return error_mark_node; @@ -1293,38 +1516,24 @@ build_functional_cast (exp, parms) } -/* Complain about defining new types in inappropriate places. We give an - exception for C-style casts, to accommodate GNU C stylings. */ - -void -check_for_new_type (string, inptree) - const char *string; - flagged_type_tree inptree; -{ - if (inptree.new_type_flag - && (pedantic || strcmp (string, "cast") != 0)) - pedwarn ("ISO C++ forbids defining types within %s", string); -} - /* Add new exception specifier SPEC, to the LIST we currently have. If it's already in LIST then do nothing. Moan if it's bad and we're allowed to. COMPLAIN < 0 means we know what we're doing. */ tree -add_exception_specifier (list, spec, complain) - tree list, spec; - int complain; +add_exception_specifier (tree list, tree spec, int complain) { - int ok; + bool ok; tree core = spec; - int is_ptr; - + bool is_ptr; + diagnostic_t diag_type = DK_UNSPECIFIED; /* none */ + if (spec == error_mark_node) return list; - - my_friendly_assert (spec && (!list || TREE_VALUE (list)), 19990317); - + + gcc_assert (spec && (!list || TREE_VALUE (list))); + /* [except.spec] 1, type in an exception specifier shall not be incomplete, or pointer or ref to incomplete other than pointer to cv void. */ @@ -1332,41 +1541,48 @@ add_exception_specifier (list, spec, complain) if (is_ptr || TREE_CODE (core) == REFERENCE_TYPE) core = TREE_TYPE (core); if (complain < 0) - ok = 1; + ok = true; else if (VOID_TYPE_P (core)) ok = is_ptr; else if (TREE_CODE (core) == TEMPLATE_TYPE_PARM) - ok = 1; + ok = true; else if (processing_template_decl) - ok = 1; + ok = true; else - ok = COMPLETE_TYPE_P (complete_type (core)); + { + ok = true; + /* 15.4/1 says that types in an exception specifier must be complete, + but it seems more reasonable to only require this on definitions + and calls. So just give a pedwarn at this point; we will give an + error later if we hit one of those two cases. */ + if (!COMPLETE_TYPE_P (complete_type (core))) + diag_type = DK_PEDWARN; /* pedwarn */ + } if (ok) { tree probe; - + for (probe = list; probe; probe = TREE_CHAIN (probe)) - if (same_type_p (TREE_VALUE (probe), spec)) - break; + if (same_type_p (TREE_VALUE (probe), spec)) + break; if (!probe) - { - spec = build_tree_list (NULL_TREE, spec); - TREE_CHAIN (spec) = list; - list = spec; - } + list = tree_cons (NULL_TREE, spec, list); } - else if (complain) - incomplete_type_error (NULL_TREE, core); + else + diag_type = DK_ERROR; /* error */ + + if (diag_type != DK_UNSPECIFIED && complain) + cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type); + return list; } /* Combine the two exceptions specifier lists LIST and ADD, and return - their union. */ + their union. */ tree -merge_exception_specifiers (list, add) - tree list, add; +merge_exception_specifiers (tree list, tree add) { if (!list || !add) return NULL_TREE; @@ -1377,22 +1593,55 @@ merge_exception_specifiers (list, add) else { tree orig_list = list; - + for (; add; add = TREE_CHAIN (add)) - { - tree spec = TREE_VALUE (add); - tree probe; - - for (probe = orig_list; probe; probe = TREE_CHAIN (probe)) - if (same_type_p (TREE_VALUE (probe), spec)) - break; - if (!probe) - { - spec = build_tree_list (NULL_TREE, spec); - TREE_CHAIN (spec) = list; - list = spec; - } - } + { + tree spec = TREE_VALUE (add); + tree probe; + + for (probe = orig_list; probe; probe = TREE_CHAIN (probe)) + if (same_type_p (TREE_VALUE (probe), spec)) + break; + if (!probe) + { + spec = build_tree_list (NULL_TREE, spec); + TREE_CHAIN (spec) = list; + list = spec; + } + } } return list; } + +/* Subroutine of build_call. Ensure that each of the types in the + exception specification is complete. Technically, 15.4/1 says that + they need to be complete when we see a declaration of the function, + but we should be able to get away with only requiring this when the + function is defined or called. See also add_exception_specifier. */ + +void +require_complete_eh_spec_types (tree fntype, tree decl) +{ + tree raises; + /* Don't complain about calls to op new. */ + if (decl && DECL_ARTIFICIAL (decl)) + return; + for (raises = TYPE_RAISES_EXCEPTIONS (fntype); raises; + raises = TREE_CHAIN (raises)) + { + tree type = TREE_VALUE (raises); + if (type && !COMPLETE_TYPE_P (type)) + { + if (decl) + error + ("call to function %qD which throws incomplete type %q#T", + decl, type); + else + error ("call to function which throws incomplete type %q#T", + decl); + } + } +} + + +#include "gt-cp-typeck2.h"