X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Fdecl2.c;h=ae7c2ab4704b0adf41b041caf461b8fc0e2bfe28;hp=0e56c070456f8bc92fe7f31a269c3fd5c192f712;hb=b48186034999492fb05990f815702e81d214a61d;hpb=3bc1df45311c2c63dac648d2bd165d5506ec3edd diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0e56c070456..ae7c2ab4704 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1,6 +1,6 @@ /* Process declarations and variables for C++ compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) @@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-dump.h" #include "intl.h" #include "gimple.h" +#include "pointer-set.h" extern cpp_reader *parse_in; @@ -84,6 +85,7 @@ static void write_out_vars (tree); static void import_export_class (tree); static tree get_guard_bits (tree); static void determine_visibility_from_class (tree, tree); +static bool decl_defined_p (tree); /* A list of static class variables. This is needed, because a static class variable can be declared inside the class without @@ -94,6 +96,10 @@ static GTY(()) VEC(tree,gc) *pending_statics; may need to emit outline anyway. */ static GTY(()) VEC(tree,gc) *deferred_fns; +/* A list of decls that use types with no linkage, which we need to make + sure are defined. */ +static GTY(()) VEC(tree,gc) *no_linkage_decls; + /* Nonzero if we're done parsing and into end-of-file activities. */ int at_eof; @@ -108,31 +114,67 @@ tree build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals) { tree raises; + tree attrs; int type_quals; if (fntype == error_mark_node || ctype == error_mark_node) return error_mark_node; + gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE + || TREE_CODE (fntype) == METHOD_TYPE); + type_quals = quals & ~TYPE_QUAL_RESTRICT; ctype = cp_build_qualified_type (ctype, type_quals); + raises = TYPE_RAISES_EXCEPTIONS (fntype); + attrs = TYPE_ATTRIBUTES (fntype); fntype = build_method_type_directly (ctype, TREE_TYPE (fntype), (TREE_CODE (fntype) == METHOD_TYPE ? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) : TYPE_ARG_TYPES (fntype))); - raises = TYPE_RAISES_EXCEPTIONS (fntype); if (raises) fntype = build_exception_variant (fntype, raises); + if (attrs) + fntype = cp_build_type_attribute_variant (fntype, attrs); return fntype; } +/* Return a variant of FNTYPE, a FUNCTION_TYPE or METHOD_TYPE, with its + return type changed to NEW_RET. */ + +tree +change_return_type (tree new_ret, tree fntype) +{ + tree newtype; + tree args = TYPE_ARG_TYPES (fntype); + tree raises = TYPE_RAISES_EXCEPTIONS (fntype); + tree attrs = TYPE_ATTRIBUTES (fntype); + + if (same_type_p (new_ret, TREE_TYPE (fntype))) + return fntype; + + if (TREE_CODE (fntype) == FUNCTION_TYPE) + newtype = build_function_type (new_ret, args); + else + newtype = build_method_type_directly + (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), + new_ret, TREE_CHAIN (args)); + if (raises) + newtype = build_exception_variant (newtype, raises); + if (attrs) + newtype = cp_build_type_attribute_variant (newtype, attrs); + + return newtype; +} + /* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE appropriately. */ tree cp_build_parm_decl (tree name, tree type) { - tree parm = build_decl (PARM_DECL, name, type); + tree parm = build_decl (input_location, + PARM_DECL, name, type); /* DECL_ARG_TYPE is only used by the back end and the back end never sees templates. */ if (!processing_template_decl) @@ -230,6 +272,9 @@ maybe_retrofit_in_chrg (tree fn) if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) fntype = build_exception_variant (fntype, TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))); + if (TYPE_ATTRIBUTES (TREE_TYPE (fn))) + fntype = (cp_build_type_attribute_variant + (fntype, TYPE_ATTRIBUTES (TREE_TYPE (fn)))); TREE_TYPE (fn) = fntype; /* Now we've got the in-charge parameter. */ @@ -247,7 +292,7 @@ maybe_retrofit_in_chrg (tree fn) FUNCTION is a FUNCTION_DECL. It was created by `grokdeclarator'. FLAGS contains bits saying what's special about today's - arguments. 1 == DESTRUCTOR. 2 == OPERATOR. + arguments. DTOR_FLAG == DESTRUCTOR. If FUNCTION is a destructor, then we must add the `auto-delete' field as a second parameter. There is some hair associated with the fact @@ -354,7 +399,8 @@ grok_array_decl (tree array_expr, tree index_exp) if (array_expr == error_mark_node || index_exp == error_mark_node) error ("ambiguous conversion for array subscript"); - expr = build_array_ref (array_expr, index_exp, input_location); + expr = build_array_ref (input_location, array_expr, index_exp, + tf_warning_or_error); } if (processing_template_decl && expr != error_mark_node) return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp, @@ -572,9 +618,14 @@ check_classfn (tree ctype, tree function, tree template_parms) either were not passed, or they are the same of DECL_TEMPLATE_PARMS. */ if (TREE_CODE (function) == TEMPLATE_DECL) { - gcc_assert (!template_parms - || comp_template_parms (template_parms, - DECL_TEMPLATE_PARMS (function))); + if (template_parms + && !comp_template_parms (template_parms, + DECL_TEMPLATE_PARMS (function))) + { + error ("template parameter lists provided don't match the " + "template parameters of %qD", function); + return error_mark_node; + } template_parms = DECL_TEMPLATE_PARMS (function); } @@ -638,8 +689,9 @@ check_classfn (tree ctype, tree function, tree template_parms) return OVL_CURRENT (fndecls); } - error ("prototype for %q#D does not match any in class %qT", - function, ctype); + error_at (DECL_SOURCE_LOCATION (function), + "prototype for %q#D does not match any in class %qT", + function, ctype); is_conv_op = DECL_CONV_FN_P (fndecl); if (is_conv_op) @@ -691,12 +743,8 @@ check_classfn (tree ctype, tree function, tree template_parms) void note_vague_linkage_fn (tree decl) { - if (!DECL_DEFERRED_FN (decl)) - { - DECL_DEFERRED_FN (decl) = 1; - DECL_DEFER_OUTPUT (decl) = 1; - VEC_safe_push (tree, gc, deferred_fns, decl); - } + DECL_DEFER_OUTPUT (decl) = 1; + VEC_safe_push (tree, gc, deferred_fns, decl); } /* We have just processed the DECL, which is a static data member. @@ -734,13 +782,14 @@ finish_static_data_member_decl (tree decl, } init = NULL_TREE; } - /* Force the compiler to know when an uninitialized static const - member is being used. */ - if (CP_TYPE_CONST_P (TREE_TYPE (decl)) && init == 0) - TREE_USED (decl) = 1; + DECL_INITIAL (decl) = init; DECL_IN_AGGR_P (decl) = 1; + if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && TYPE_DOMAIN (TREE_TYPE (decl)) == NULL_TREE) + SET_VAR_HAD_UNKNOWN_BOUND (decl); + cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags); } @@ -758,6 +807,7 @@ grokfield (const cp_declarator *declarator, tree value; const char *asmspec = 0; int flags = LOOKUP_ONLYCONVERTING; + tree name; if (init && TREE_CODE (init) == TREE_LIST @@ -772,7 +822,7 @@ grokfield (const cp_declarator *declarator, if (TREE_CODE (value) == TYPE_DECL && init) { - error ("typedef %qD is initialized (use __typeof__ instead)", value); + error ("typedef %qD is initialized (use decltype instead)", value); init = NULL_TREE; } @@ -786,11 +836,21 @@ grokfield (const cp_declarator *declarator, && DECL_CONTEXT (value) != current_class_type) return value; - if (DECL_NAME (value) != NULL_TREE - && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' - && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr")) - error ("member %qD conflicts with virtual function table field name", - value); + name = DECL_NAME (value); + + if (name != NULL_TREE) + { + if (TREE_CODE (name) == TEMPLATE_ID_EXPR) + { + error ("explicit template argument list not allowed"); + return error_mark_node; + } + + if (IDENTIFIER_POINTER (name)[0] == '_' + && ! strcmp (IDENTIFIER_POINTER (name), "_vptr")) + error ("member %qD conflicts with virtual function table field name", + value); + } /* Stash away type declarations. */ if (TREE_CODE (value) == TYPE_DECL) @@ -802,7 +862,22 @@ grokfield (const cp_declarator *declarator, value = push_template_decl (value); if (attrlist) - cplus_decl_attributes (&value, attrlist, 0); + { + int attrflags = 0; + + /* If this is a typedef that names the class for linkage purposes + (7.1.3p8), apply any attributes directly to the type. */ + if (TAGGED_TYPE_P (TREE_TYPE (value)) + && value == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value)))) + attrflags = ATTR_FLAG_TYPE_IN_PLACE; + + cplus_decl_attributes (&value, attrlist, attrflags); + } + + if (declspecs->specs[(int)ds_typedef] + && TREE_TYPE (value) != error_mark_node + && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value) + cp_set_underlying_type (value); return value; } @@ -830,9 +905,7 @@ grokfield (const cp_declarator *declarator, } else if (init == ridpointers[(int)RID_DEFAULT]) { - if (!defaultable_fn_p (value)) - error ("%qD cannot be defaulted", value); - else + if (defaultable_fn_check (value)) { DECL_DEFAULTED_FN (value) = 1; DECL_INITIALIZED_IN_CLASS_P (value) = 1; @@ -841,8 +914,13 @@ grokfield (const cp_declarator *declarator, } else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE) { - gcc_assert (error_operand_p (init) || integer_zerop (init)); - DECL_PURE_VIRTUAL_P (value) = 1; + if (integer_zerop (init)) + DECL_PURE_VIRTUAL_P (value) = 1; + else if (error_operand_p (init)) + ; /* An error has already been reported. */ + else + error ("invalid initializer for member function %qD", + value); } else { @@ -945,7 +1023,7 @@ grokbitfield (const cp_declarator *declarator, if (TREE_CODE (value) == VOID_TYPE) return void_type_node; - if (!INTEGRAL_TYPE_P (TREE_TYPE (value)) + if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value)) && (POINTER_TYPE_P (value) || !dependent_type_p (TREE_TYPE (value)))) { @@ -982,7 +1060,7 @@ grokbitfield (const cp_declarator *declarator, error ("static member %qD cannot be a bit-field", value); return NULL_TREE; } - finish_decl (value, NULL_TREE, NULL_TREE); + cp_finish_decl (value, NULL_TREE, false, NULL_TREE, 0); if (width != error_mark_node) { @@ -1109,19 +1187,6 @@ save_template_attributes (tree *attr_p, tree *decl_p) if (!late_attrs) return; - /* Give this type a name so we know to look it up again at instantiation - time. */ - if (TREE_CODE (*decl_p) == TYPE_DECL - && DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE) - { - tree oldt = TREE_TYPE (*decl_p); - tree newt = build_variant_type_copy (oldt); - DECL_ORIGINAL_TYPE (*decl_p) = oldt; - TREE_TYPE (*decl_p) = newt; - TYPE_NAME (newt) = *decl_p; - TREE_USED (newt) = TREE_USED (*decl_p); - } - if (DECL_P (*decl_p)) q = &DECL_ATTRIBUTES (*decl_p); else @@ -1202,6 +1267,8 @@ cp_reconstruct_complex_type (tree type, tree bottom) else return bottom; + if (TYPE_ATTRIBUTES (type)) + outer = cp_build_type_attribute_variant (outer, TYPE_ATTRIBUTES (type)); return cp_build_qualified_type (outer, TYPE_QUALS (type)); } @@ -1281,8 +1348,10 @@ build_anon_union_vars (tree type, tree object) { tree base; - decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); + decl = build_decl (input_location, + VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); DECL_ANON_UNION_VAR_P (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; base = get_base_address (object); TREE_PUBLIC (decl) = TREE_PUBLIC (base); @@ -1348,6 +1417,7 @@ finish_anon_union (tree anon_union_decl) { /* Use main_decl to set the mangled name. */ DECL_NAME (anon_union_decl) = DECL_NAME (main_decl); + maybe_commonize_var (anon_union_decl); mangle_decl (anon_union_decl); DECL_NAME (anon_union_decl) = NULL_TREE; } @@ -1501,7 +1571,7 @@ void comdat_linkage (tree decl) { if (flag_weak) - make_decl_one_only (decl); + make_decl_one_only (decl, cxx_comdat_group (decl)); else if (TREE_CODE (decl) == FUNCTION_DECL || (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl))) /* We can just emit function and compiler-generated variables @@ -1542,8 +1612,7 @@ comdat_linkage (tree decl) } } - if (DECL_LANG_SPECIFIC (decl)) - DECL_COMDAT (decl) = 1; + DECL_COMDAT (decl) = 1; } /* For win32 we also want to put explicit instantiations in @@ -1573,7 +1642,7 @@ maybe_make_one_only (tree decl) || (! DECL_EXPLICIT_INSTANTIATION (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))) { - make_decl_one_only (decl); + make_decl_one_only (decl, cxx_comdat_group (decl)); if (TREE_CODE (decl) == VAR_DECL) { @@ -1584,6 +1653,24 @@ maybe_make_one_only (tree decl) } } +/* Returns true iff DECL, a FUNCTION_DECL or VAR_DECL, has vague linkage. + This predicate will give the right answer during parsing of the + function, which other tests may not. */ + +bool +vague_linkage_p (tree decl) +{ + /* Unfortunately, import_export_decl has not always been called + before the function is processed, so we cannot simply check + DECL_COMDAT. */ + return (DECL_COMDAT (decl) + || (((TREE_CODE (decl) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (decl)) + || (DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_INSTANTIATION (decl))) + && TREE_PUBLIC (decl))); +} + /* Determine whether or not we want to specifically import or export CTYPE, using various heuristics. */ @@ -1700,6 +1787,10 @@ decl_needed_p (tree decl) || (DECL_ASSEMBLER_NAME_SET_P (decl) && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))) return true; + /* Functions marked "dllexport" must be emitted so that they are + visible to other DLLs. */ + if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) + return true; /* Otherwise, DECL does not need to be emitted -- yet. A subsequent reference to DECL might cause it to be emitted later. */ return false; @@ -1757,7 +1848,7 @@ maybe_emit_vtables (tree ctype) if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0) { - tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl)); + tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), LOOKUP_NORMAL); /* It had better be all done at compile-time. */ gcc_assert (!expr); @@ -1832,7 +1923,9 @@ constrain_visibility (tree decl, int visibility) if (!DECL_EXTERN_C_P (decl)) { TREE_PUBLIC (decl) = 0; - DECL_ONE_ONLY (decl) = 0; + DECL_WEAK (decl) = 0; + DECL_COMMON (decl) = 0; + DECL_COMDAT_GROUP (decl) = NULL_TREE; DECL_INTERFACE_KNOWN (decl) = 1; if (DECL_LANG_SPECIFIC (decl)) DECL_NOT_REALLY_EXTERN (decl) = 1; @@ -1841,7 +1934,7 @@ constrain_visibility (tree decl, int visibility) else if (visibility > DECL_VISIBILITY (decl) && !DECL_VISIBILITY_SPECIFIED (decl)) { - DECL_VISIBILITY (decl) = visibility; + DECL_VISIBILITY (decl) = (enum symbol_visibility) visibility; return true; } return false; @@ -1905,6 +1998,8 @@ determine_visibility (tree decl) { tree class_type = NULL_TREE; bool use_template; + bool orig_visibility_specified; + enum symbol_visibility orig_visibility; /* Remember that all decls get VISIBILITY_DEFAULT when built. */ @@ -1917,6 +2012,9 @@ determine_visibility (tree decl) maybe_clone_body. */ gcc_assert (!DECL_CLONED_FUNCTION_P (decl)); + orig_visibility_specified = DECL_VISIBILITY_SPECIFIED (decl); + orig_visibility = DECL_VISIBILITY (decl); + if (TREE_CODE (decl) == TYPE_DECL) { if (CLASS_TYPE_P (TREE_TYPE (decl))) @@ -2045,6 +2143,25 @@ determine_visibility (tree decl) || ! DECL_VISIBILITY_SPECIFIED (decl)) constrain_visibility (decl, tvis); } + else if (no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/true)) + /* DR 757: A type without linkage shall not be used as the type of a + variable or function with linkage, unless + o the variable or function has extern "C" linkage (7.5 [dcl.link]), or + o the variable or function is not used (3.2 [basic.def.odr]) or is + defined in the same translation unit. + + Since non-extern "C" decls need to be defined in the same + translation unit, we can make the type internal. */ + constrain_visibility (decl, VISIBILITY_ANON); + + /* If visibility changed and DECL already has DECL_RTL, ensure + symbol flags are updated. */ + if ((DECL_VISIBILITY (decl) != orig_visibility + || DECL_VISIBILITY_SPECIFIED (decl) != orig_visibility_specified) + && ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)) + || TREE_CODE (decl) == FUNCTION_DECL) + && DECL_RTL_SET_P (decl)) + make_decl_rtl (decl); } /* By default, static data members and function members receive @@ -2470,13 +2587,16 @@ get_guard (tree decl) /* We use a type that is big enough to contain a mutex as well as an integer counter. */ guard_type = targetm.cxx.guard_type (); - guard = build_decl (VAR_DECL, sname, guard_type); + guard = build_decl (DECL_SOURCE_LOCATION (decl), + VAR_DECL, sname, guard_type); /* The guard should have the same linkage as what it guards. */ TREE_PUBLIC (guard) = TREE_PUBLIC (decl); TREE_STATIC (guard) = TREE_STATIC (decl); DECL_COMMON (guard) = DECL_COMMON (decl); - DECL_ONE_ONLY (guard) = DECL_ONE_ONLY (decl); + DECL_COMDAT (guard) = DECL_COMDAT (decl); + if (DECL_ONE_ONLY (decl)) + make_decl_one_only (guard, cxx_comdat_group (guard)); if (TREE_PUBLIC (decl)) DECL_WEAK (guard) = DECL_WEAK (decl); DECL_VISIBILITY (guard) = DECL_VISIBILITY (decl); @@ -2529,14 +2649,16 @@ get_guard_cond (tree guard) guard_value = integer_one_node; if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard))) guard_value = convert (TREE_TYPE (guard), guard_value); - guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value, + guard = cp_build_binary_op (input_location, + BIT_AND_EXPR, guard, guard_value, tf_warning_or_error); } guard_value = integer_zero_node; if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard))) guard_value = convert (TREE_TYPE (guard), guard_value); - return cp_build_binary_op (EQ_EXPR, guard, guard_value, + return cp_build_binary_op (input_location, + EQ_EXPR, guard, guard_value, tf_warning_or_error); } @@ -2604,7 +2726,6 @@ start_objects (int method_type, int initp) DECL_GLOBAL_CTOR_P (current_function_decl) = 1; else DECL_GLOBAL_DTOR_P (current_function_decl) = 1; - DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1; body = begin_compound_stmt (BCS_FN_BODY); @@ -2926,20 +3047,22 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp) last to destroy the variable. */ else if (initp) guard_cond - = cp_build_binary_op (EQ_EXPR, + = cp_build_binary_op (input_location, + EQ_EXPR, cp_build_unary_op (PREINCREMENT_EXPR, - guard, - /*noconvert=*/1, - tf_warning_or_error), + guard, + /*noconvert=*/1, + tf_warning_or_error), integer_one_node, tf_warning_or_error); else guard_cond - = cp_build_binary_op (EQ_EXPR, + = cp_build_binary_op (input_location, + EQ_EXPR, cp_build_unary_op (PREDECREMENT_EXPR, - guard, - /*noconvert=*/1, - tf_warning_or_error), + guard, + /*noconvert=*/1, + tf_warning_or_error), integer_zero_node, tf_warning_or_error); @@ -2992,7 +3115,8 @@ do_static_initialization_or_destruction (tree vars, bool initp) /* Build the outer if-stmt to check for initialization or destruction. */ init_if_stmt = begin_if_stmt (); cond = initp ? integer_one_node : integer_zero_node; - cond = cp_build_binary_op (EQ_EXPR, + cond = cp_build_binary_op (input_location, + EQ_EXPR, initialize_p_decl, cond, tf_warning_or_error); @@ -3025,7 +3149,8 @@ do_static_initialization_or_destruction (tree vars, bool initp) /* Conditionalize this initialization on being in the right priority and being initializing/finalizing appropriately. */ priority_if_stmt = begin_if_stmt (); - cond = cp_build_binary_op (EQ_EXPR, + cond = cp_build_binary_op (input_location, + EQ_EXPR, priority_decl, build_int_cst (NULL_TREE, priority), tf_warning_or_error); @@ -3223,11 +3348,11 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED) { case PTRMEM_CST: if (TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) - cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (t))); + cgraph_mark_address_taken_node (cgraph_node (PTRMEM_CST_MEMBER (t))); break; case BASELINK: if (TREE_CODE (BASELINK_FUNCTIONS (t)) == FUNCTION_DECL) - cgraph_mark_needed_node (cgraph_node (BASELINK_FUNCTIONS (t))); + cgraph_mark_address_taken_node (cgraph_node (BASELINK_FUNCTIONS (t))); break; case VAR_DECL: if (DECL_VTABLE_OR_VTT_P (t)) @@ -3241,6 +3366,7 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED) mark_decl_referenced (vtbl); } else if (DECL_CONTEXT (t) + && flag_use_repository && TREE_CODE (DECL_CONTEXT (t)) == FUNCTION_DECL) /* If we need a static variable in a function, then we need the containing function. */ @@ -3255,27 +3381,60 @@ cxx_callgraph_analyze_expr (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED) /* Java requires that we be able to reference a local address for a method, and not be confused by PLT entries. If hidden aliases are - supported, emit one for each java function that we've emitted. */ + supported, collect and return all the functions for which we should + emit a hidden alias. */ -static void -build_java_method_aliases (void) +static struct pointer_set_t * +collect_candidates_for_java_method_aliases (void) { struct cgraph_node *node; + struct pointer_set_t *candidates = NULL; #ifndef HAVE_GAS_HIDDEN - return; + return candidates; #endif for (node = cgraph_nodes; node ; node = node->next) { tree fndecl = node->decl; - if (TREE_ASM_WRITTEN (fndecl) - && DECL_CONTEXT (fndecl) + if (DECL_CONTEXT (fndecl) && TYPE_P (DECL_CONTEXT (fndecl)) && TYPE_FOR_JAVA (DECL_CONTEXT (fndecl)) && TARGET_USE_LOCAL_THUNK_ALIAS_P (fndecl)) { + if (candidates == NULL) + candidates = pointer_set_create (); + pointer_set_insert (candidates, fndecl); + } + } + + return candidates; +} + + +/* Java requires that we be able to reference a local address for a + method, and not be confused by PLT entries. If hidden aliases are + supported, emit one for each java function that we've emitted. + CANDIDATES is the set of FUNCTION_DECLs that were gathered + by collect_candidates_for_java_method_aliases. */ + +static void +build_java_method_aliases (struct pointer_set_t *candidates) +{ + struct cgraph_node *node; + +#ifndef HAVE_GAS_HIDDEN + return; +#endif + + for (node = cgraph_nodes; node ; node = node->next) + { + tree fndecl = node->decl; + + if (TREE_ASM_WRITTEN (fndecl) + && pointer_set_contains (candidates, fndecl)) + { /* Mangle the name in a predictable way; we need to reference this from a java compiled object file. */ tree oid, nid, alias; @@ -3297,6 +3456,40 @@ build_java_method_aliases (void) } } +/* Returns true iff there is a definition available for variable or + function DECL. */ + +static bool +decl_defined_p (tree decl) +{ + if (TREE_CODE (decl) == FUNCTION_DECL) + return (DECL_INITIAL (decl) != NULL_TREE); + else + { + gcc_assert (TREE_CODE (decl) == VAR_DECL); + return !DECL_EXTERNAL (decl); + } +} + +/* Complain that DECL uses a type with no linkage but is never defined. */ + +static void +no_linkage_error (tree decl) +{ + tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false); + if (TYPE_ANONYMOUS_P (t)) + { + permerror (0, "%q+#D, declared using anonymous type, " + "is used but never defined", decl); + if (is_typedef_decl (TYPE_NAME (t))) + permerror (0, "%q+#D does not refer to the unqualified type, " + "so it is not used for linkage", TYPE_NAME (t)); + } + else + permerror (0, "%q+#D, declared using local type %qT, " + "is used but never defined", decl, t); +} + /* This routine is called at the end of compilation. Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -3312,6 +3505,7 @@ cp_write_global_declarations (void) unsigned ssdf_count = 0; int retries = 0; tree decl; + struct pointer_set_t *candidates; locus = input_location; at_eof = 1; @@ -3465,7 +3659,7 @@ cp_write_global_declarations (void) for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i) { /* Does it need synthesizing? */ - if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl) + if (DECL_DEFAULTED_FN (decl) && ! DECL_INITIAL (decl) && (! DECL_REALLY_EXTERN (decl) || possibly_inlined_p (decl))) { /* Even though we're already at the top-level, we push @@ -3483,7 +3677,7 @@ cp_write_global_declarations (void) reconsider = true; } - if (!gimple_body (decl)) + if (!DECL_SAVED_TREE (decl)) continue; /* We lie to the back end, pretending that some functions @@ -3505,7 +3699,36 @@ cp_write_global_declarations (void) if (DECL_NOT_REALLY_EXTERN (decl) && DECL_INITIAL (decl) && decl_needed_p (decl)) - DECL_EXTERNAL (decl) = 0; + { + struct cgraph_node *node = cgraph_get_node (decl), *alias, *next; + + DECL_EXTERNAL (decl) = 0; + /* If we mark !DECL_EXTERNAL one of the same body aliases, + we need to mark all of them that way. */ + if (node && node->same_body) + { + DECL_EXTERNAL (node->decl) = 0; + for (alias = node->same_body; alias; alias = alias->next) + DECL_EXTERNAL (alias->decl) = 0; + } + /* If we mark !DECL_EXTERNAL one of the symbols in some comdat + group, we need to mark all symbols in the same comdat group + that way. */ + if (node->same_comdat_group) + for (next = node->same_comdat_group; + next != node; + next = next->same_comdat_group) + { + DECL_EXTERNAL (next->decl) = 0; + if (next->same_body) + { + for (alias = next->same_body; + alias; + alias = alias->next) + DECL_EXTERNAL (alias->decl) = 0; + } + } + } /* If we're going to need to write this function out, and there's already a body for it, create RTL for it now. @@ -3560,7 +3783,7 @@ cp_write_global_declarations (void) for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i) { if (/* Check online inline functions that were actually used. */ - TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl) + DECL_ODR_USED (decl) && DECL_DECLARED_INLINE_P (decl) /* If the definition actually was available here, then the fact that the function was not defined merely represents that for some reason (use of a template repository, @@ -3578,6 +3801,11 @@ cp_write_global_declarations (void) } } + /* So must decls that use a type with no linkage. */ + for (i = 0; VEC_iterate (tree, no_linkage_decls, i, decl); ++i) + if (!decl_defined_p (decl)) + no_linkage_error (decl); + /* We give C linkage to static constructors and destructors. */ push_lang_context (lang_name_c); @@ -3604,8 +3832,10 @@ cp_write_global_declarations (void) linkage now. */ pop_lang_context (); + /* Collect candidates for Java hidden aliases. */ + candidates = collect_candidates_for_java_method_aliases (); + cgraph_finalize_compilation_unit (); - cgraph_optimize (); /* Now, issue warnings about static, but not defined, functions, etc., and emit debugging information. */ @@ -3619,7 +3849,11 @@ cp_write_global_declarations (void) } /* Generate hidden aliases for Java. */ - build_java_method_aliases (); + if (candidates) + { + build_java_method_aliases (candidates); + pointer_set_destroy (candidates); + } finish_repo (); @@ -3653,18 +3887,18 @@ cp_write_global_declarations (void) /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the function to call in parse-tree form; it has not yet been semantically analyzed. ARGS are the arguments to the function. - They have already been semantically analyzed. */ + They have already been semantically analyzed. This may change + ARGS. */ tree -build_offset_ref_call_from_tree (tree fn, tree args) +build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args) { tree orig_fn; - tree orig_args; + VEC(tree,gc) *orig_args = NULL; tree expr; tree object; orig_fn = fn; - orig_args = args; object = TREE_OPERAND (fn, 0); if (processing_template_decl) @@ -3672,17 +3906,19 @@ build_offset_ref_call_from_tree (tree fn, tree args) gcc_assert (TREE_CODE (fn) == DOTSTAR_EXPR || TREE_CODE (fn) == MEMBER_REF); if (type_dependent_expression_p (fn) - || any_type_dependent_arguments_p (args)) - return build_nt_call_list (fn, args); + || any_type_dependent_arguments_p (*args)) + return build_nt_call_vec (fn, *args); + + orig_args = make_tree_vector_copy (*args); /* Transform the arguments and add the implicit "this" parameter. That must be done before the FN is transformed because we depend on the form of FN. */ - args = build_non_dependent_args (args); + make_args_non_dependent (*args); object = build_non_dependent_expr (object); if (TREE_CODE (fn) == DOTSTAR_EXPR) object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error); - args = tree_cons (NULL_TREE, object, args); + VEC_safe_insert (tree, gc, *args, 0, object); /* Now that the arguments are done, transform FN. */ fn = build_non_dependent_expr (fn); } @@ -3699,12 +3935,16 @@ build_offset_ref_call_from_tree (tree fn, tree args) tf_warning_or_error); fn = TREE_OPERAND (fn, 1); fn = get_member_function_from_ptrfunc (&object_addr, fn); - args = tree_cons (NULL_TREE, object_addr, args); + VEC_safe_insert (tree, gc, *args, 0, object_addr); } - expr = cp_build_function_call (fn, args, tf_warning_or_error); + expr = cp_build_function_call_vec (fn, args, tf_warning_or_error); if (processing_template_decl && expr != error_mark_node) - return build_min_non_dep_call_list (expr, orig_fn, orig_args); + expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args); + + if (orig_args != NULL) + release_tree_vector (orig_args); + return expr; } @@ -3735,7 +3975,7 @@ possibly_inlined_p (tree decl) gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); if (DECL_UNINLINABLE (decl)) return false; - if (!optimize) + if (!optimize || pragma_java_exceptions) return DECL_DECLARED_INLINE_P (decl); /* When optimizing, we might inline everything when flatten attribute or heuristics inlining for size or autoinlining @@ -3764,12 +4004,56 @@ mark_used (tree decl) decl = OVL_CURRENT (decl); } + /* Set TREE_USED for the benefit of -Wunused. */ TREE_USED (decl) = 1; if (DECL_CLONED_FUNCTION_P (decl)) TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1; + + if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_DELETED_FN (decl)) + { + if (DECL_ARTIFICIAL (decl)) + { + if (DECL_OVERLOADED_OPERATOR_P (decl) == TYPE_EXPR + && LAMBDA_TYPE_P (DECL_CONTEXT (decl))) + { + /* We mark a lambda conversion op as deleted if we can't + generate it properly; see maybe_add_lambda_conv_op. */ + sorry ("converting lambda which uses %<...%> to " + "function pointer"); + return; + } + } + error ("deleted function %q+D", decl); + error ("used here"); + return; + } /* If we don't need a value, then we don't need to synthesize DECL. */ - if (skip_evaluation) + if (cp_unevaluated_operand != 0) + return; + + /* We can only check DECL_ODR_USED on variables or functions with + DECL_LANG_SPECIFIC set, and these are also the only decls that we + might need special handling for. */ + if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) + || DECL_LANG_SPECIFIC (decl) == NULL + || DECL_THUNK_P (decl)) + return; + + /* We only want to do this processing once. We don't need to keep trying + to instantiate inline templates, because unit-at-a-time will make sure + we get them compiled before functions that want to inline them. */ + if (DECL_ODR_USED (decl)) return; + + /* If within finish_function, defer the rest until that function + finishes, otherwise it might recurse. */ + if (defer_mark_used_calls) + { + VEC_safe_push (tree, gc, deferred_mark_used_calls, decl); + return; + } + /* Normally, we can wait until instantiation-time to synthesize DECL. However, if DECL is a static data member initialized with a constant, we need the value right now because a reference to @@ -3795,59 +4079,64 @@ mark_used (tree decl) if (processing_template_decl) return; - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) - && !TREE_ASM_WRITTEN (decl)) - /* Remember it, so we can check it was defined. */ + DECL_ODR_USED (decl) = 1; + if (DECL_CLONED_FUNCTION_P (decl)) + DECL_ODR_USED (DECL_CLONED_FUNCTION (decl)) = 1; + + /* DR 757: A type without linkage shall not be used as the type of a + variable or function with linkage, unless + o the variable or function has extern "C" linkage (7.5 [dcl.link]), or + o the variable or function is not used (3.2 [basic.def.odr]) or is + defined in the same translation unit. */ + if (cxx_dialect > cxx98 + && decl_linkage (decl) != lk_none + && !DECL_EXTERN_C_P (decl) + && !DECL_ARTIFICIAL (decl) + && !decl_defined_p (decl) + && no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false)) { - if (DECL_DEFERRED_FN (decl)) - return; - - /* Remember the current location for a function we will end up - synthesizing. Then we can inform the user where it was - required in the case of error. */ - if (DECL_ARTIFICIAL (decl) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl) - && !DECL_THUNK_P (decl)) - DECL_SOURCE_LOCATION (decl) = input_location; - - note_vague_linkage_fn (decl); + if (is_local_extern (decl)) + /* There's no way to define a local extern, and adding it to + the vector interferes with GC, so give an error now. */ + no_linkage_error (decl); + else + VEC_safe_push (tree, gc, no_linkage_decls, decl); } - assemble_external (decl); + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) + && !DECL_INITIAL (decl) && !DECL_ARTIFICIAL (decl)) + /* Remember it, so we can check it was defined. */ + note_vague_linkage_fn (decl); /* Is it a synthesized method that needs to be synthesized? */ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl) && DECL_DEFAULTED_FN (decl) - && !DECL_THUNK_P (decl) - && ! DECL_INITIAL (decl) - /* Kludge: don't synthesize for default args. Unfortunately this - rules out initializers of namespace-scoped objects too, but - it's sort-of ok if the implicit ctor or dtor decl keeps - pointing to the class location. */ - && current_function_decl) + && ! DECL_INITIAL (decl)) { + /* Remember the current location for a function we will end up + synthesizing. Then we can inform the user where it was + required in the case of error. */ + DECL_SOURCE_LOCATION (decl) = input_location; + + /* Synthesizing an implicitly defined member function will result in + garbage collection. We must treat this situation as if we were + within the body of a function so as to avoid collecting live data + on the stack (such as overload resolution candidates). + + We could just let cp_write_global_declarations handle synthesizing + this function, since we just added it to deferred_fns, but doing + it at the use site produces better error messages. */ + ++function_depth; synthesize_method (decl); - /* If we've already synthesized the method we don't need to + --function_depth; + /* If this is a synthesized method we don't need to do the instantiation test below. */ } - else if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_DELETED_FN (decl)) - { - error ("deleted function %q+D", decl); - error ("used here"); - } - else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL) - && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) + else if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL) + && DECL_TEMPLATE_INFO (decl) && (!DECL_EXPLICIT_INSTANTIATION (decl) - || (TREE_CODE (decl) == FUNCTION_DECL - && possibly_inlined_p - (DECL_TEMPLATE_RESULT ( - template_for_substitution (decl)))) - /* We need to instantiate static data members so that there - initializers are available in integral constant - expressions. */ - || (TREE_CODE (decl) == VAR_DECL - && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)))) + || always_instantiate_p (decl))) /* If this is a function or variable that is an instance of some template, we now know that we will need to actually do the instantiation. We check that DECL is not an explicit