X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcp%2Ftypeck2.c;h=6e32377c4a35f70c0eae3ed42f8359bb761fed6c;hb=7fb213d8e955ed3f21defe0d28ab63fe576574bd;hp=67d880905ddb24d7c8ecacc8f1850f7504e7951f;hpb=5aa3396cd44c61d134aab3b123b1f2a73aa9d1a9;p=gcc.git diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 67d880905dd..6e32377c4a3 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1,23 +1,24 @@ /* 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 + 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) 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 +along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -25,14 +26,12 @@ Boston, MA 02111-1307, USA. */ /* 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" @@ -40,14 +39,13 @@ Boston, MA 02111-1307, USA. */ #include "output.h" #include "diagnostic.h" -static tree process_init_constructor PARAMS ((tree, tree, tree *)); +static tree process_init_constructor (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); @@ -56,8 +54,7 @@ error_not_base_type (basetype, type) } 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); @@ -74,13 +71,10 @@ binfo_or_else (base, type) example, conversions to references.) */ void -readonly_error (arg, string, soft) - tree arg; - const char *string; - int soft; +readonly_error (tree arg, const char* string, int soft) { const char *fmt; - void (*fn) PARAMS ((const char *, ...)); + void (*fn) (const char *, ...); if (soft) fn = pedwarn; @@ -120,20 +114,169 @@ readonly_error (arg, string, soft) (*fn) ("%s of read-only location", string); } + +/* 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 = 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* pat1 = val1; + tree type2 = (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; + + my_friendly_assert (COMPLETE_TYPE_P (type), 20040620_3); + + 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; + my_friendly_assert (pat, 20040620_2); + + /* 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 diagostic if the type is abstract. */ + while (pat) + { + my_friendly_assert (type == pat->type, 20040620_4); + + /* 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, otherwise cp_error_at. */ + 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; - if (!CLASS_TYPE_P (type) || !CLASSTYPE_PURE_VIRTUALS (type)) + /* This function applies only to classes. Any other entity can never + be abstract. */ + if (!CLASS_TYPE_P (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; + + my_friendly_assert (!decl || (DECL_P (decl) + || TREE_CODE (decl) == IDENTIFIER_NODE), + 20040620_1); + + 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_alloc (sizeof (struct pending_abstract_type)); + pat->type = type; + pat->decl = decl; + pat->locus = ((decl && DECL_P (decl)) + ? DECL_SOURCE_LOCATION (decl) + : input_location); + + pat->next = *slot; + *slot = pat; + + return 0; + } + + if (!CLASSTYPE_PURE_VIRTUALS (type)) return 0; if (!TYPE_SIZE (type)) @@ -148,34 +291,45 @@ abstract_virtuals_error (decl, type) return 0; if (TREE_CODE (decl) == VAR_DECL) - error ("cannot declare variable `%D' to be of type `%T'", - decl, type); + cp_error_at ("cannot declare variable `%+D' to be of abstract " + "type `%T'", decl, type); else if (TREE_CODE (decl) == PARM_DECL) - error ("cannot declare parameter `%D' to be of type `%T'", - decl, type); + cp_error_at ("cannot declare parameter `%+D' to be of abstract " + "type `%T'", decl, type); else if (TREE_CODE (decl) == FIELD_DECL) - error ("cannot declare field `%D' to be of type `%T'", - decl, type); + cp_error_at ("cannot declare field `%+D' to be of abstract " + "type `%T'", 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); + cp_error_at ("invalid abstract return type for member function `%+#D'", + decl); else if (TREE_CODE (decl) == FUNCTION_DECL) - error ("invalid return type for function `%#D'", decl); + cp_error_at ("invalid abstract return type for function `%+#D'", + decl); + else if (TREE_CODE (decl) == IDENTIFIER_NODE) + /* Here we do not have location information, so use error instead + of cp_error_at. */ + error ("invalid abstract type `%T' for `%E'", type, decl); + else + cp_error_at ("invalid abstract type for `%+D'", decl); } else - error ("cannot allocate an object of type `%T'", type); + error ("cannot allocate an object of abstract type `%T'", type); /* Only go through this once. */ if (TREE_PURPOSE (u) == NULL_TREE) { TREE_PURPOSE (u) = error_mark_node; - error (" because the following virtual functions are abstract:"); + inform ("%J because the following virtual functions are pure " + "within `%T':", TYPE_MAIN_DECL (type), type); + for (tu = u; tu; tu = TREE_CHAIN (tu)) - cp_error_at ("\t%#D", TREE_VALUE (tu)); + inform ("%J\t%#D", TREE_VALUE (tu), TREE_VALUE (tu)); } else - error (" since type `%T' has abstract virtual functions", type); + inform ("%J since type `%T' has pure virtual functions", + TYPE_MAIN_DECL (type), type); return 1; } @@ -187,14 +341,11 @@ abstract_virtuals_error (decl, type) pedwarn. */ void -cxx_incomplete_type_diagnostic (value, type, diag_type) - tree value; - tree type; - int diag_type; +cxx_incomplete_type_diagnostic (tree value, tree type, int diag_type) { int decl = 0; - void (*p_msg) PARAMS ((const char *, ...)); - void (*p_msg_at) PARAMS ((const char *, ...)); + void (*p_msg) (const char *, ...); + void (*p_msg_at) (const char *, ...); if (diag_type == 1) { @@ -281,14 +432,112 @@ retry: required by ../tree.c. */ #undef cxx_incomplete_type_error void -cxx_incomplete_type_error (value, type) - tree value; - tree type; +cxx_incomplete_type_error (tree value, tree type) { cxx_incomplete_type_diagnostic (value, type, 0); } +/* 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) +{ + tree *pelt, elt, type = TREE_TYPE (dest); + tree sub, code, inner_type = NULL; + bool array_type_p = false; + + pelt = &CONSTRUCTOR_ELTS (init); + 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: + while ((elt = *pelt)) + { + tree field_index = TREE_PURPOSE (elt); + tree value = TREE_VALUE (elt); + + if (!array_type_p) + inner_type = TREE_TYPE (field_index); + + if (TREE_CODE (value) == CONSTRUCTOR) + { + if (array_type_p) + sub = build (ARRAY_REF, inner_type, dest, field_index, + NULL_TREE, NULL_TREE); + else + sub = build (COMPONENT_REF, inner_type, dest, field_index, + NULL_TREE); + + split_nonconstant_init_1 (sub, value); + } + else if (!initializer_constant_valid_p (value, inner_type)) + { + *pelt = TREE_CHAIN (elt); + + if (array_type_p) + sub = build (ARRAY_REF, inner_type, dest, field_index, + NULL_TREE, NULL_TREE); + else + sub = build (COMPONENT_REF, inner_type, dest, field_index, + NULL_TREE); + + code = build (MODIFY_EXPR, inner_type, sub, value); + code = build_stmt (EXPR_STMT, code); + add_stmt (code); + continue; + } + + pelt = &TREE_CHAIN (elt); + } + break; + + case VECTOR_TYPE: + if (!initializer_constant_valid_p (init, type)) + { + CONSTRUCTOR_ELTS (init) = NULL; + code = build (MODIFY_EXPR, type, dest, init); + code = build_stmt (EXPR_STMT, code); + add_stmt (code); + } + break; + + default: + abort (); + } +} + +/* 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 = build (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. @@ -304,15 +553,13 @@ cxx_incomplete_type_error (value, type) 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. */ @@ -320,12 +567,6 @@ 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 (! TYPE_HAS_TRIVIAL_INIT_REF (type) @@ -335,51 +576,15 @@ store_init_value (decl, init) 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)); - } -#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); - } + init = build_constructor (NULL_TREE, nreverse (init)); } -#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) { @@ -387,30 +592,14 @@ 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); + /* Digest the specified initializer into an expression. */ + value = digest_init (type, init, (tree *) 0); /* Store the expression if valid; else report error. */ @@ -420,35 +609,11 @@ store_init_value (decl, init) 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; + return build (INIT_EXPR, type, decl, 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 + || ! initializer_constant_valid_p (value, TREE_TYPE (value)))) + return split_nonconstant_init (decl, value); /* Store the VALUE in DECL_INITIAL. If we're building a statement-tree we will actually expand the initialization later @@ -457,27 +622,6 @@ store_init_value (decl, init) 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. */ - -tree -force_store_init_value (decl, init) - tree decl, init; -{ - tree type = TREE_TYPE (decl); - int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type); - - TYPE_NEEDS_CONSTRUCTING (type) = 0; - - init = store_init_value (decl, init); - if (init) - abort (); - - TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing; - - 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. @@ -489,15 +633,11 @@ force_store_init_value (decl, init) TYPE is an aggregate and INIT is not a constructor. */ tree -digest_init (type, init, tail) - tree type, init, *tail; +digest_init (tree type, tree init, tree* tail) { 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. */ @@ -514,7 +654,7 @@ digest_init (type, init, tail) if (TREE_CODE (init) == ERROR_MARK) /* __PRETTY_FUNCTION__'s initializer is a bogus expression inside - a template function. This gets substituted during instantiation. */ + a template function. This gets substituted during instantiation. */ return init; /* We must strip the outermost array type when completing the type, @@ -527,12 +667,7 @@ digest_init (type, init, tail) 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 + if (BRACE_ENCLOSED_INITIALIZER_P (init) && CONSTRUCTOR_ELTS (init) != 0 && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0) { @@ -583,8 +718,7 @@ digest_init (type, init, tail) 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 @@ -603,9 +737,9 @@ digest_init (type, init, tail) 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)) + || TYPE_PTR_TO_MEMBER_P (type)) { - if (raw_constructor) + if (BRACE_ENCLOSED_INITIALIZER_P (init)) { if (element == 0) { @@ -614,7 +748,7 @@ digest_init (type, init, tail) } init = element; } - while (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)) + while (BRACE_ENCLOSED_INITIALIZER_P (init)) { pedwarn ("braces around scalar initializer for `%T'", type); init = CONSTRUCTOR_ELTS (init); @@ -638,15 +772,16 @@ digest_init (type, init, tail) if (code == ARRAY_TYPE || code == VECTOR_TYPE || IS_AGGR_TYPE_CODE (code)) { - if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type) - && TREE_HAS_CONSTRUCTOR (init)) + if (BRACE_ENCLOSED_INITIALIZER_P (init)) { - error ("subobject of type `%T' must be initialized by constructor, not by `%E'", - type, init); - return error_mark_node; + if (TYPE_NON_AGGREGATE_CLASS (type)) + { + error ("subobject of type `%T' must be initialized by constructor, not by `%E'", + type, init); + return error_mark_node; + } + return process_init_constructor (type, init, (tree *)0); } - 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. */; @@ -688,14 +823,13 @@ digest_init (type, init, tail) constants that the assembler and linker can compute them. */ static tree -process_init_constructor (type, init, elts) - tree type, init, *elts; +process_init_constructor (tree type, tree init, tree* elts) { - register tree tail; + tree tail; /* List of the elements of the result constructor, in reverse order. */ - register tree members = NULL; - register tree next1; + tree members = NULL; + tree next1; tree result; int allconstant = 1; int allsimple = 1; @@ -719,8 +853,8 @@ process_init_constructor (type, init, elts) if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE) { - register long len; - register int i; + long len; + int i; if (TREE_CODE (type) == ARRAY_TYPE) { @@ -730,7 +864,7 @@ process_init_constructor (type, init, elts) - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)) + 1); else - len = -1; /* Take as many as there are */ + len = -1; /* Take as many as there are. */ } else { @@ -787,11 +921,13 @@ process_init_constructor (type, init, elts) 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 = build_constructor (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)); + next1 = 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. */ @@ -808,7 +944,7 @@ process_init_constructor (type, init, elts) } else if (TREE_CODE (type) == RECORD_TYPE) { - register tree field; + tree field; if (tail) { @@ -818,7 +954,7 @@ process_init_constructor (type, init, elts) return error_mark_node; } - if (TYPE_BINFO_BASETYPES (type)) + if (BINFO_BASE_BINFOS (TYPE_BINFO (type))) { sorry ("initializer list for object of class with base classes"); return error_mark_node; @@ -840,7 +976,7 @@ process_init_constructor (type, init, elts) continue; } - if (TREE_CODE (field) != FIELD_DECL) + if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; if (tail) @@ -878,8 +1014,7 @@ process_init_constructor (type, init, elts) NULL_TREE); else { - next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, - NULL_TREE); + next1 = build_constructor (NULL_TREE, NULL_TREE); if (init) TREE_HAS_CONSTRUCTOR (next1) = TREE_HAS_CONSTRUCTOR (init); @@ -888,15 +1023,14 @@ process_init_constructor (type, init, elts) /* Warn when some struct elements are implicitly initialized. */ if (extra_warnings - && (!init || TREE_HAS_CONSTRUCTOR (init))) + && (!init || BRACE_ENCLOSED_INITIALIZER_P (init))) warning ("missing initializer for member `%D'", field); } else { if (TREE_READONLY (field)) error ("uninitialized const member `%D'", field); - else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field)) - && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (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) @@ -905,11 +1039,13 @@ process_init_constructor (type, init, elts) /* Warn when some struct elements are implicitly initialized to zero. */ if (extra_warnings - && (!init || TREE_HAS_CONSTRUCTOR (init))) + && (!init || BRACE_ENCLOSED_INITIALIZER_P (init))) warning ("missing initializer for member `%D'", field); if (! zero_init_p (TREE_TYPE (field))) - next1 = build_forced_zero_init (TREE_TYPE (field)); + next1 = 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. */ @@ -929,12 +1065,11 @@ process_init_constructor (type, init, elts) /* If the initializer was empty, use default zero initialization. */ && tail) { - register tree field = TYPE_FIELDS (type); + 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)) + while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL)) field = TREE_CHAIN (field); /* If this element specifies a field, initialize via that field. */ @@ -1007,11 +1142,18 @@ process_init_constructor (type, init, elts) if (erroneous) return error_mark_node; - result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members)); + result = build_constructor (type, nreverse (members)); + 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; + if (allconstant) + { + TREE_CONSTANT (result) = 1; + TREE_INVARIANT (result) = 1; + if (allsimple) + TREE_STATIC (result) = 1; + } return result; } @@ -1044,10 +1186,7 @@ process_init_constructor (type, init, elts) binfo for the specific base subobject we want to convert to. */ tree -build_scoped_ref (datum, basetype, binfo_p) - tree datum; - tree basetype; - tree *binfo_p; +build_scoped_ref (tree datum, tree basetype, tree* binfo_p) { tree binfo; @@ -1078,51 +1217,49 @@ build_scoped_ref (datum, basetype, binfo_p) 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) { - rval = convert_from_reference (rval); - type = TREE_TYPE (rval); + expr = convert_from_reference (expr); + type = TREE_TYPE (expr); } 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))) { - 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) @@ -1135,10 +1272,20 @@ 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 build_indirect_ref (last_rval, NULL); + } if (types_memoized) error ("result of `operator->()' yields non-pointer result"); @@ -1147,73 +1294,31 @@ build_x_arrow (datum) 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; - 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) return error_mark_node; - objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); - - if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component))) - { - type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component))); - field_type = type; - } - 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 - things are not as complex as they are for references to - non-static data members. */ - field_type = cp_build_qualified_type (field_type, type_quals); - } - } - else + ptrmem_type = TREE_TYPE (component); + if (!TYPE_PTR_TO_MEMBER_P (ptrmem_type)) { error ("`%E' cannot be used as a member pointer, since it is of type `%T'", - component, TREE_TYPE (component)); + component, ptrmem_type); return error_mark_node; } - + + objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum)); if (! IS_AGGR_TYPE (objtype)) { error ("cannot apply member pointer `%E' to `%E', which is of non-aggregate type `%T'", @@ -1221,29 +1326,43 @@ build_m_component_ref (datum, component) return error_mark_node; } - binfo = lookup_base (objtype, TYPE_METHOD_BASETYPE (type), + type = TYPE_PTRMEM_POINTED_TO_TYPE (ptrmem_type); + binfo = lookup_base (objtype, TYPE_PTRMEM_CLASS_TYPE (ptrmem_type), ba_check, NULL); if (!binfo) { error ("member type `%T::' incompatible with object type `%T'", - TYPE_METHOD_BASETYPE (type), objtype); + type, objtype); 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)) + { + /* 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)))); + /* Build an expression for "object + offset" where offset is the + value stored in the pointer-to-data-member. */ + datum = build (PLUS_EXPR, build_pointer_type (type), + build_base_path (PLUS_EXPR, build_address (datum), + binfo, 1), + build_nop (ptrdiff_type_node, component)); + return build_indirect_ref (datum, 0); + } + else + return build (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) { /* This is either a call to a constructor, or a C cast in C++'s `functional' notation. */ @@ -1252,41 +1371,26 @@ build_functional_cast (exp, parms) 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 (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)) { - /* this must build a C cast */ + /* 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); - } + parms = build_x_compound_expr_from_list (parms, "functional cast"); return build_c_cast (type, parms); } @@ -1311,7 +1415,7 @@ build_functional_cast (exp, parms) if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type) && TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) { - exp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); + exp = build_constructor (type, NULL_TREE); return get_target_expr (exp); } @@ -1325,32 +1429,17 @@ 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; int diag_type = -1; /* none */ if (spec == error_mark_node) @@ -1365,16 +1454,16 @@ 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 = 1; + 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 @@ -1403,11 +1492,10 @@ add_exception_specifier (list, spec, complain) } /* 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; @@ -1445,8 +1533,7 @@ merge_exception_specifiers (list, add) function is defined or called. See also add_exception_specifier. */ void -require_complete_eh_spec_types (fntype, decl) - tree fntype, decl; +require_complete_eh_spec_types (tree fntype, tree decl) { tree raises; /* Don't complain about calls to op new. */ @@ -1468,3 +1555,6 @@ require_complete_eh_spec_types (fntype, decl) } } } + + +#include "gt-cp-typeck2.h"