diff options
author | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-06-26 14:32:30 +0000 |
---|---|---|
committer | jamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4> | 2017-06-26 14:32:30 +0000 |
commit | 1ade4d1864f2cf61eb5c045f57c0bcac80943c04 (patch) | |
tree | c3c6b4d4ec193b3cc7ee538e3209377b2964b28f /gcc/cp | |
parent | 34d0ee70079ea0967450877b1a6c5281569d0366 (diff) | |
parent | e76fa056805f0aeb36583a27b02f4a4adbfd0004 (diff) | |
download | gcc-1ade4d1864f2cf61eb5c045f57c0bcac80943c04.tar.gz |
Merged trunk revision 249638 into the hsa branch
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/hsa@249651 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 285 | ||||
-rw-r--r-- | gcc/cp/call.c | 408 | ||||
-rw-r--r-- | gcc/cp/class.c | 48 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 28 | ||||
-rw-r--r-- | gcc/cp/cp-cilkplus.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 606 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 154 | ||||
-rw-r--r-- | gcc/cp/cp-ubsan.c | 3 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 321 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 91 | ||||
-rw-r--r-- | gcc/cp/dump.c | 4 | ||||
-rw-r--r-- | gcc/cp/error.c | 2 | ||||
-rw-r--r-- | gcc/cp/except.c | 12 | ||||
-rw-r--r-- | gcc/cp/init.c | 4 | ||||
-rw-r--r-- | gcc/cp/lambda.c | 16 | ||||
-rw-r--r-- | gcc/cp/lex.c | 86 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 32 | ||||
-rw-r--r-- | gcc/cp/method.c | 10 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 173 | ||||
-rw-r--r-- | gcc/cp/operators.def | 15 | ||||
-rw-r--r-- | gcc/cp/parser.c | 125 | ||||
-rw-r--r-- | gcc/cp/pt.c | 272 | ||||
-rw-r--r-- | gcc/cp/ptree.c | 3 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 467 | ||||
-rw-r--r-- | gcc/cp/search.c | 6 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 21 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 23 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 3 |
29 files changed, 2064 insertions, 1158 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6d2f28b8751..a06de8ba8c7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,288 @@ +2017-06-24 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/62315 + * parser.c (cp_parser_diagnose_invalid_type_name): Don't print + 'typename' in error messages about missing 'typename'. + +2017-06-23 Jason Merrill <jason@redhat.com> + + PR c++/79056 - C++17 ICE with invalid template syntax. + * parser.c (cp_parser_simple_type_specifier): Don't assume that type + is a TYPE_DECL. + (cp_parser_check_for_invalid_template_id): Handle TYPE_DECL. + * pt.c (template_placeholder_p): New. + * cp-tree.h: Declare it. + +2017-06-23 Marc Glisse <marc.glisse@inria.fr> + + * decl.c (duplicate_decls): Use builtin_structptr_types. + +2017-06-22 Nathan Sidwell <nathan@acm.org> + + Reorder IDENTIFIER flags + gcc/cp/ + * cp-tree.h (enum cp_identifier_kind): New. + (IDENTIFIER_KIND_BIT_0, IDENTIFIER_KIND_BIT_1, + IDENTIFIER_KIND_BIT_2): New. + (IDENTIFIER_MARKED): Move to TREE_LANG_FLAG_4. + (IDENTIFIER_VIRTUAL_P, IDENTIFIER_REPO_CHOSEN): Add IDENTIFIER_CHECK. + (C_IS_RESERVED_WORD): Replace with ... + (IDENTIFIER_KEYWORD_P): ... this. + (IDENTIFIER_CTOR_OR_DTOR_P): Replace with ... + (IDENTIFIER_CDTOR_P): ... this. + (IDENTIFIER_CTOR_P, IDENTIFIER_DTOR_P): New. + (IDENTIFIER_OPNAME_P): Replace with ... + (IDENTIFIER_ANY_OP_P): ... this. + (IDENTIFIER_ASSIGN_OP_P): New. + (IDENTIFIER_TYPENAME_P): Replace with ... + (IDENTIFIER_CONV_OP_P): ... this. + (NEW_DELETE_OPNAME_P): Replace with ... + (IDENTIFIER_NEWDEL_OP_P): ... this. + (DECL_CONV_FN_P, DECL_OVERLOADED_OPERATOR_P): Adjust. + (get_identifier_kind_name, set_identifier_kind): Declare. + * lex.c (get_identifier_kind_name, set_identifier_kind): New. + (init_operators): Adjust to avoid keywords, use + set_identifier_kind. Copy TYPE_EXPR slot. + (init_reswords): Call set_identifier_kind. + (unqualified_name_lookup_error): Adjust. + * operators.def (TYPE_EXPR): Remove. + * decl.c (struct predefined_identifier): Move into ... + (initialize_predefined_identifiers): ... here. Call + set_identifier_kind. + (grokfndecl, check_var_type, grokdeclarator): Adjust. + (grok_op_properties): Use IDENTIFIER_ANY_ASSIGN_OP to halve search + space. Adjust. + * call.c (name_as_c_string): Adjust. + (build_new_method_call_1): Likewise. + * cp-cilkplus.c (is_conversion_operator_function_decl_p): Likewise. + * cxx-pretty-print.c (pp_cxx_unqualified_id): Adjust. + * dump.c (cp_dump_tree): Adjust. + * error.c (dump_decl_name): Adjust. + * mangle.c (write_unqualified_id, write_member_name, + write_expression): Adjust. + (mangle_conv_op_name_for_type): Use set_identifier_kind. + * name-lookup.c (do_class_using_decl): Adjust. + (lookup_name_fuzzy, lookup_name_real_1): Likewise. + * parser.c (cp_lexer_get_preprocessor_token, + cp_parser_direct_declarator): Likewise. + * pt.c (push_template_decl_real, tsubst_decl, tsubst_baselink, + tsubst_copy, tsubst_copy_and_build): Adjust. + * ptree.c (cxx_print_identifier): Print identifier kind. + * search.c (lookup_field_r, lookup_member, + lookup_fnfields_idx_nolazy): Adjust. + * semantics.c (finish_id_expression): Adjust.. + * typeck.c (cp_build_addr_expr_1): Adjust. + +2017-06-21 Jakub Jelinek <jakub@redhat.com> + + PR c++/81154 + * semantics.c (handle_omp_array_sections_1, finish_omp_clauses): + Complain about t not being a variable if t is OVERLOAD even + when processing_template_decl. + +2017-06-21 David Malcolm <dmalcolm@redhat.com> + + * parser.c (get_cast_suggestion): New function. + (maybe_add_cast_fixit): New function. + (cp_parser_cast_expression): Capture the location of the closing + parenthesis. Call maybe_add_cast_fixit when emitting warnings + about old-style casts. + +2017-06-20 Jason Merrill <jason@redhat.com> + + PR c++/80972 - C++17 ICE with attribute packed. + * call.c (build_over_call): Allow a TARGET_EXPR from reference + binding. + +2017-06-20 Nathan Sidwell <nathan@acm.org> + + * cp-tree.h (CPTI_NELTS_IDENTIFIER): Delete. + (nelts_identifier): Delete. + * decl.c (initialize_predefined_identifiers): Remove nelts. + + PR c++/67074 - namespace aliases + * decl.c (duplicate_decls): Don't error here on mismatched + namespace alias. + * name-lookup.c (name_lookup::add_value): Matching namespaces are + not ambiguous. + (diagnose_name_conflict): Namespaces are never redeclarations. + (update_binding): An alias can match a real namespace. + +2017-06-19 Jason Merrill <jason@redhat.com> + + PR c++/80562 - ICE with constexpr if. + * semantics.c (finish_if_stmt_cond): Call + instantiate_non_dependent_expr. + + PR c++/80829 - ICE with constexpr copy of base subobject. + * constexpr.c (clear_no_implicit_zero): New. + (cxx_eval_call_expression): Call it. + +2017-06-19 Nathan Sidwell <nathan@acm.org> + + PR c++/81124 + PR c++/79766 + * name-lookup.c (set_decl_namespace): Don't follow using + directives and ignore using decls. Only check overly-explicit + scope after discovering decl. + +2017-06-19 Jason Merrill <jason@redhat.com> + + PR c++/81073 - constexpr and static var in statement-expression. + * typeck2.c (store_init_value): Always call + require_potential_constant_expression. + * pt.c (convert_nontype_argument): Likewise. + * constexpr.c (potential_constant_expression_1): Adjust message. + Use decl_maybe_constant_var_p instead of decl_constant_var_p. + * decl2.c (decl_maybe_constant_var_p): Consider initializer. + +2017-06-19 Nathan Sidwell <nathan@acm.org> + + * pt.c (coerce_template_parms): Fix indentation. + (tsubst_decl): Remove repeated SET_DECL_RTL. Move VAR_P handling + in to single block. + + PR c++/81119 + * name-lookup.c (update_binding): Only warn about constructors + hidden by functions. + +2017-06-17 Jason Merrill <jason@redhat.com> + + PR c++/60063 - -Wunused-local-typedefs and templates. + * decl2.c (is_late_template_attribute): Return false for "used". + + PR c++/70844 - -Wuseless-cast and inheriting constructor. + * method.c (forward_parm): Suppress warn_useless_cast. + +2017-06-16 Jason Merrill <jason@redhat.com> + + PR c++/81045 - Wrong type-dependence with auto return type. + * pt.c (type_dependent_expression_p): An undeduced auto outside the + template isn't dependent. + * call.c (build_over_call): Instantiate undeduced auto even in a + template. + + PR c++/80465 - ICE with generic lambda with noexcept-specifier. + * lambda.c (maybe_add_lambda_conv_op): Keep processing_template_decl + set longer for a generic lambda. + + PR c++/80614 - Wrong mangling for C++17 noexcept type + * mangle.c (write_type): Put the eh spec back on the function type. + + PR c++/81102 - Wrong error with partial specialization. + * pt.c (unify) [TEMPLATE_PARM_INDEX]: Strip reference when comparing + types. Do type deduction later. + + PR c++/81074 - ICE with partial specialization of member template. + PR c++/71747 + * pt.c (get_partial_spec_bindings): Only coerce innermost args. + + PR c++/80831 - ICE with -fsyntax-only. + * decl2.c (c_parse_final_cleanups): Use cgraph_node::get_create. + + PR c++/80639 - ICE with invalid PMF initialization. + PR c++/80043 - ICE with -fpermissive + * typeck.c (convert_for_assignment): Recurse when instantiate_type + returns without an error. + +2017-06-16 Nathan Sidwell <nathan@acm.org> + + * pt.c (tsubst_baselink): Fix & clarify formatting. + + * cp-tree.h (build_this_parm, cp_build_parm_decl, + build_artificial_parm): Add FN parm. + * decl.c (start_cleanup_fn): Adjust. + (build_this_parm): Add FN parm, pass it through. + (grokfndecl): Adjust parm building. + * decl2.c (cp_build_parm_decl): Add FN parm, set context. + (build_artificial_parm): Add FN parm, pass through. + (maybe_retrofit_in_chrg): Adjust parm building. + (start_static_storage_duration_function): Likwise. + * lambda.c (maybe_aadd_lambda_conv_op): Likewise. + * method.c (implicitly_declare_fn): Likewise. + * parser.c (inject_this_parameter): Likewise. + + Symbol tables are insert only. + * cp-tree.h (default_hash_traits <lang_identifier *>): Don't + derive from pointer_hash. Make undeletable. + + * class.c (resort_type_method_vec): Avoid potential unsigned + overflow. + + Don't defer noexcept_deferred_spec. + * cp-tree.h (unevaluated_noexcept_spec): Don't declare. + * decl.c (cxx_init_decl_processing): Initialize + noexcept_deferred_spec. + * except.c (unevaluated_noexcept_spec): Delete. + * class.c (deduce_noexcept_on_destructor): Use + noexcept_deferred_spec directly. + * method.c (implicitly_declare_fn): Likewise. + + Make keyed_classes a vector. + * cp-tree.h (CPTI_KEYED_CLASSES, keyed_classes): Delete. + (keyed_classes): Declare as vector. + * decl.c (keyed_classes): Define. + (cxx_init_decl_processing): Allocate it. + (record_key_method_defined): Use vec_safe_push. + * class.c (finish_struct_1): Likewise. + * pt.c (instantiate_class_template_1): Likewise. + * decl2.c (c_parse_final_cleanups): Reverse iterate keyed_classes. + + Make rtti lazier + * rtti.c (enum tinfo_kind): Add TK_DERIVED_TYPES, + TK_VMI_CLASS_TYPES, TK_MAX. Delete TK_FIXED. + (tinfo_names): New. + (typeid_ok_p): Add quotes to error messages. Use get_tinfo_desc. + (get_tinfo_decl): Use get_tinfo_desc. + (get_pseudo_ti_init): Likewise. Adjust VMI construction. + (create_pseudo_type_info): Delete. + (get_pseudo_ti_index): Just determine the index. + (get_tinfo_desc): New. Create all types lazily. + (create_tinfo_types): Just allocate the descriptor array. + (emit_support_tinfos): Use non-inserting type lookup. Set builtin + location. + +2017-06-15 Martin Sebor <msebor@redhat.com> + + PR c++/80560 + * call.c (first_non_public_field, maybe_warn_class_memaccess): New + functions. + (has_trivial_copy_assign_p, has_trivial_copy_p): Ditto. + (build_cxx_call): Call maybe_warn_class_memaccess. + +2017-06-14 Jakub Jelinek <jakub@redhat.com> + + * cp-gimplify.c (cp_genericize_r): Turn most of the function + into a switch (TREE_CODE (stmt)) statement from long else if + sequence. + +2017-06-13 Jakub Jelinek <jakub@redhat.com> + + PR c++/80973 + * cp-gimplify.c (cp_genericize_r): Don't instrument MEM_REF second + argument even if it has REFERENCE_TYPE. + + PR c++/80984 + * cp-gimplify.c (cp_genericize): Only look for VAR_DECLs in + BLOCK_VARS (outer) chain. + (cxx_omp_const_qual_no_mutable): Likewise. + +2017-06-13 Martin Liska <mliska@suse.cz> + + PR sanitize/78204 + * class.c (build_base_path): Use sanitize_flags_p. + * cp-gimplify.c (cp_genericize_r): Likewise. + (cp_genericize_tree): Likewise. + (cp_genericize): Likewise. + * cp-ubsan.c (cp_ubsan_instrument_vptr_p): Likewise. + * decl.c (compute_array_index_type): Likewise. + (start_preparsed_function): Likewise. + * decl2.c (one_static_initialization_or_destruction): Likewise. + * init.c (finish_length_check): Likewise. + * lambda.c (maybe_add_lambda_conv_op): Likewise. + * typeck.c (cp_build_binary_op): Likewise. + (build_static_cast_1): Likewise. + 2017-06-11 Jason Merrill <jason@redhat.com> * error.c (dump_expr): Use is_this_parameter. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ef9968340c6..2fc29da1c7a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7584,6 +7584,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) const tree *argarray; unsigned int nargs; + if (undeduced_auto_decl (fn)) + mark_used (fn, complain); + return_type = TREE_TYPE (TREE_TYPE (fn)); nargs = vec_safe_length (args); if (first_arg == NULL_TREE) @@ -8022,6 +8025,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) subobject. */ if (CHECKING_P && cxx_dialect >= cxx1z) gcc_assert (TREE_CODE (arg) != TARGET_EXPR + /* It's from binding the ref parm to a packed field. */ + || convs[0]->need_temporary_p || seen_error () /* See unsafe_copy_elision_p. */ || DECL_BASE_CONSTRUCTOR_P (fn)); @@ -8184,6 +8189,393 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) return call; } +/* Return the DECL of the first non-public data member of class TYPE + or null if none can be found. */ + +static tree +first_non_public_field (tree type) +{ + if (!CLASS_TYPE_P (type)) + return NULL_TREE; + + for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) + { + if (TREE_CODE (field) != FIELD_DECL) + continue; + if (TREE_STATIC (field)) + continue; + if (TREE_PRIVATE (field) || TREE_PROTECTED (field)) + return field; + } + + int i = 0; + + for (tree base_binfo, binfo = TYPE_BINFO (type); + BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + { + tree base = TREE_TYPE (base_binfo); + + if (tree field = first_non_public_field (base)) + return field; + } + + return NULL_TREE; +} + +/* Return true if all copy and move assignment operator overloads for + class TYPE are trivial and at least one of them is not deleted and, + when ACCESS is set, accessible. Return false otherwise. Set + HASASSIGN to true when the TYPE has a (not necessarily trivial) + copy or move assignment. */ + +static bool +has_trivial_copy_assign_p (tree type, bool access, bool *hasassign) +{ + tree fns = cp_assignment_operator_id (NOP_EXPR); + fns = lookup_fnfields_slot (type, fns); + + bool all_trivial = true; + + /* Iterate over overloads of the assignment operator, checking + accessible copy assignments for triviality. */ + + for (ovl_iterator oi (fns); oi; ++oi) + { + tree f = *oi; + + /* Skip operators that aren't copy assignments. */ + if (!copy_fn_p (f)) + continue; + + bool accessible = (!access || !(TREE_PRIVATE (f) || TREE_PROTECTED (f)) + || accessible_p (TYPE_BINFO (type), f, true)); + + /* Skip template assignment operators and deleted functions. */ + if (TREE_CODE (f) != FUNCTION_DECL || DECL_DELETED_FN (f)) + continue; + + if (accessible) + *hasassign = true; + + if (!accessible || !trivial_fn_p (f)) + all_trivial = false; + + /* Break early when both properties have been determined. */ + if (*hasassign && !all_trivial) + break; + } + + /* Return true if they're all trivial and one of the expressions + TYPE() = TYPE() or TYPE() = (TYPE&)() is valid. */ + tree ref = cp_build_reference_type (type, false); + return (all_trivial + && (is_trivially_xible (MODIFY_EXPR, type, type) + || is_trivially_xible (MODIFY_EXPR, type, ref))); +} + +/* Return true if all copy and move ctor overloads for class TYPE are + trivial and at least one of them is not deleted and, when ACCESS is + set, accessible. Return false otherwise. Set each element of HASCTOR[] + to true when the TYPE has a (not necessarily trivial) default and copy + (or move) ctor, respectively. */ + +static bool +has_trivial_copy_p (tree type, bool access, bool hasctor[2]) +{ + tree fns = lookup_fnfields_slot (type, complete_ctor_identifier); + + bool all_trivial = true; + + for (ovl_iterator oi (fns); oi; ++oi) + { + tree f = *oi; + + /* Skip template constructors. */ + if (TREE_CODE (f) != FUNCTION_DECL) + continue; + + bool cpy_or_move_ctor_p = copy_fn_p (f); + + /* Skip ctors other than default, copy, and move. */ + if (!cpy_or_move_ctor_p && !default_ctor_p (f)) + continue; + + if (DECL_DELETED_FN (f)) + continue; + + bool accessible = (!access || !(TREE_PRIVATE (f) || TREE_PROTECTED (f)) + || accessible_p (TYPE_BINFO (type), f, true)); + + if (accessible) + hasctor[cpy_or_move_ctor_p] = true; + + if (cpy_or_move_ctor_p && (!accessible || !trivial_fn_p (f))) + all_trivial = false; + + /* Break early when both properties have been determined. */ + if (hasctor[0] && hasctor[1] && !all_trivial) + break; + } + + return all_trivial; +} + +/* Issue a warning on a call to the built-in function FNDECL if it is + a raw memory write whose destination is not an object of (something + like) trivial or standard layout type with a non-deleted assignment + and copy ctor. Detects const correctness violations, corrupting + references, virtual table pointers, and bypassing non-trivial + assignments. */ + +static void +maybe_warn_class_memaccess (location_t loc, tree fndecl, tree *args) +{ + /* Except for bcopy where it's second, the destination pointer is + the first argument for all functions handled here. Compute + the index of the destination and source arguments. */ + unsigned dstidx = DECL_FUNCTION_CODE (fndecl) == BUILT_IN_BCOPY; + unsigned srcidx = !dstidx; + + tree dest = args[dstidx]; + if (!dest || !TREE_TYPE (dest) || !POINTER_TYPE_P (TREE_TYPE (dest))) + return; + + STRIP_NOPS (dest); + + tree srctype = NULL_TREE; + + /* Determine the type of the pointed-to object and whether it's + a complete class type. */ + tree desttype = TREE_TYPE (TREE_TYPE (dest)); + + if (!desttype || !COMPLETE_TYPE_P (desttype) || !CLASS_TYPE_P (desttype)) + return; + + /* Check to see if the raw memory call is made by a ctor or dtor + with this as the destination argument for the destination type. + If so, be more permissive. */ + if (current_function_decl + && (DECL_CONSTRUCTOR_P (current_function_decl) + || DECL_DESTRUCTOR_P (current_function_decl)) + && is_this_parameter (dest)) + { + tree ctx = DECL_CONTEXT (current_function_decl); + bool special = same_type_ignoring_top_level_qualifiers_p (ctx, desttype); + + tree binfo = TYPE_BINFO (ctx); + + /* A ctor and dtor for a class with no bases and no virtual functions + can do whatever they want. Bail early with no further checking. */ + if (special && !BINFO_VTABLE (binfo) && !BINFO_N_BASE_BINFOS (binfo)) + return; + } + + /* True if the class is trivial. */ + bool trivial = trivial_type_p (desttype); + + /* Set to true if DESTYPE has an accessible copy assignment. */ + bool hasassign = false; + /* True if all of the class' overloaded copy assignment operators + are all trivial (and not deleted) and at least one of them is + accessible. */ + bool trivassign = has_trivial_copy_assign_p (desttype, true, &hasassign); + + /* Set to true if DESTTYPE has an accessible default and copy ctor, + respectively. */ + bool hasctors[2] = { false, false }; + + /* True if all of the class' overloaded copy constructors are all + trivial (and not deleted) and at least one of them is accessible. */ + bool trivcopy = has_trivial_copy_p (desttype, true, hasctors); + + /* Set FLD to the first private/protected member of the class. */ + tree fld = trivial ? first_non_public_field (desttype) : NULL_TREE; + + /* The warning format string. */ + const char *warnfmt = NULL; + /* A suggested alternative to offer instead of the raw memory call. + Empty string when none can be come up with. */ + const char *suggest = ""; + bool warned = false; + + switch (DECL_FUNCTION_CODE (fndecl)) + { + case BUILT_IN_MEMSET: + if (!integer_zerop (args[1])) + { + /* Diagnose setting non-copy-assignable or non-trivial types, + or types with a private member, to (potentially) non-zero + bytes. Since the value of the bytes being written is unknown, + suggest using assignment instead (if one exists). Also warn + for writes into objects for which zero-initialization doesn't + mean all bits clear (pointer-to-member data, where null is all + bits set). Since the value being written is (most likely) + non-zero, simply suggest assignment (but not copy assignment). */ + suggest = "; use assignment instead"; + if (!trivassign) + warnfmt = G_("%qD writing to an object of type %#qT with " + "no trivial copy-assignment"); + else if (!trivial) + warnfmt = G_("%qD writing to an object of non-trivial type %#qT%s"); + else if (fld) + { + const char *access = TREE_PRIVATE (fld) ? "private" : "protected"; + warned = warning_at (loc, OPT_Wclass_memaccess, + "%qD writing to an object of type %#qT with " + "%qs member %qD", + fndecl, desttype, access, fld); + } + else if (!zero_init_p (desttype)) + warnfmt = G_("%qD writing to an object of type %#qT containing " + "a pointer to data member%s"); + + break; + } + /* Fall through. */ + + case BUILT_IN_BZERO: + /* Similarly to the above, diagnose clearing non-trivial or non- + standard layout objects, or objects of types with no assignmenmt. + Since the value being written is known to be zero, suggest either + copy assignment, copy ctor, or default ctor as an alternative, + depending on what's available. */ + + if (hasassign && hasctors[0]) + suggest = G_("; use assignment or value-initialization instead"); + else if (hasassign) + suggest = G_("; use assignment instead"); + else if (hasctors[0]) + suggest = G_("; use value-initialization instead"); + + if (!trivassign) + warnfmt = G_("%qD clearing an object of type %#qT with " + "no trivial copy-assignment%s"); + else if (!trivial) + warnfmt = G_("%qD clearing an object of non-trivial type %#qT%s"); + else if (!zero_init_p (desttype)) + warnfmt = G_("%qD clearing an object of type %#qT containing " + "a pointer-to-member%s"); + break; + + case BUILT_IN_BCOPY: + case BUILT_IN_MEMCPY: + case BUILT_IN_MEMMOVE: + case BUILT_IN_MEMPCPY: + /* Determine the type of the source object. */ + srctype = STRIP_NOPS (args[srcidx]); + srctype = TREE_TYPE (TREE_TYPE (srctype)); + + /* Since it's impossible to determine wheter the byte copy is + being used in place of assignment to an existing object or + as a substitute for initialization, assume it's the former. + Determine the best alternative to use instead depending on + what's not deleted. */ + if (hasassign && hasctors[1]) + suggest = G_("; use copy-assignment or copy-initialization instead"); + else if (hasassign) + suggest = G_("; use copy-assignment instead"); + else if (hasctors[1]) + suggest = G_("; use copy-initialization instead"); + + if (!trivassign) + warnfmt = G_("%qD writing to an object of type %#qT with no trivial " + "copy-assignment%s"); + else if (!trivially_copyable_p (desttype)) + warnfmt = G_("%qD writing to an object of non-trivially copyable " + "type %#qT%s"); + else if (!trivcopy) + warnfmt = G_("%qD writing to an object with a deleted copy constructor"); + + else if (!trivial + && !VOID_TYPE_P (srctype) + && !char_type_p (TYPE_MAIN_VARIANT (srctype)) + && !same_type_ignoring_top_level_qualifiers_p (desttype, + srctype)) + { + /* Warn when copying into a non-trivial object from an object + of a different type other than void or char. */ + warned = warning_at (loc, OPT_Wclass_memaccess, + "%qD copying an object of non-trivial type " + "%#qT from an array of %#qT", + fndecl, desttype, srctype); + } + else if (fld + && !VOID_TYPE_P (srctype) + && !char_type_p (TYPE_MAIN_VARIANT (srctype)) + && !same_type_ignoring_top_level_qualifiers_p (desttype, + srctype)) + { + const char *access = TREE_PRIVATE (fld) ? "private" : "protected"; + warned = warning_at (loc, OPT_Wclass_memaccess, + "%qD copying an object of type %#qT with " + "%qs member %qD from an array of %#qT; use " + "assignment or copy-initialization instead", + fndecl, desttype, access, fld, srctype); + } + else if (!trivial && TREE_CODE (args[2]) == INTEGER_CST) + { + /* Finally, warn on partial copies. */ + unsigned HOST_WIDE_INT typesize + = tree_to_uhwi (TYPE_SIZE_UNIT (desttype)); + if (unsigned HOST_WIDE_INT partial + = tree_to_uhwi (args[2]) % typesize) + warned = warning_at (loc, OPT_Wclass_memaccess, + (typesize - partial > 1 + ? G_("%qD writing to an object of " + "a non-trivial type %#qT leaves %wu " + "bytes unchanged") + : G_("%qD writing to an object of " + "a non-trivial type %#qT leaves %wu " + "byte unchanged")), + fndecl, desttype, typesize - partial); + } + break; + + case BUILT_IN_REALLOC: + + if (!trivially_copyable_p (desttype)) + warnfmt = G_("%qD moving an object of non-trivially copyable type " + "%#qT; use %<new%> and %<delete%> instead"); + else if (!trivcopy) + warnfmt = G_("%qD moving an object of type %#qT with deleted copy " + "constructor; use %<new%> and %<delete%> instead"); + else if (!get_dtor (desttype, tf_none)) + warnfmt = G_("%qD moving an object of type %#qT with deleted " + "destructor"); + else if (!trivial + && TREE_CODE (args[1]) == INTEGER_CST + && tree_int_cst_lt (args[1], TYPE_SIZE_UNIT (desttype))) + { + /* Finally, warn on reallocation into insufficient space. */ + warned = warning_at (loc, OPT_Wclass_memaccess, + "%qD moving an object of non-trivial type " + "%#qT and size %E into a region of size %E", + fndecl, desttype, TYPE_SIZE_UNIT (desttype), + args[1]); + } + break; + + default: + return; + } + + if (!warned && !warnfmt) + return; + + if (warnfmt) + { + if (suggest) + warned = warning_at (loc, OPT_Wclass_memaccess, + warnfmt, fndecl, desttype, suggest); + else + warned = warning_at (loc, OPT_Wclass_memaccess, + warnfmt, fndecl, desttype); + } + + if (warned) + inform (location_of (desttype), "%#qT declared here", desttype); +} + /* Build and return a call to FN, using NARGS arguments in ARGARRAY. This function performs no overload resolution, conversion, or other high-level operations. */ @@ -8216,6 +8608,10 @@ build_cxx_call (tree fn, int nargs, tree *argarray, if (!check_builtin_function_arguments (EXPR_LOCATION (fn), vNULL, fndecl, nargs, argarray)) return error_mark_node; + + /* Warn if the built-in writes to an object of a non-trivial type. */ + if (nargs) + maybe_warn_class_memaccess (loc, fndecl, argarray); } /* If it is a built-in array notation function, then the return type of @@ -8488,21 +8884,19 @@ name_as_c_string (tree name, tree type, bool *free_p) /* Assume that we will not allocate memory. */ *free_p = false; /* Constructors and destructors are special. */ - if (IDENTIFIER_CTOR_OR_DTOR_P (name)) + if (IDENTIFIER_CDTOR_P (name)) { pretty_name = CONST_CAST (char *, identifier_to_locale (IDENTIFIER_POINTER (constructor_name (type)))); /* For a destructor, add the '~'. */ - if (name == complete_dtor_identifier - || name == base_dtor_identifier - || name == deleting_dtor_identifier) + if (IDENTIFIER_DTOR_P (name)) { pretty_name = concat ("~", pretty_name, NULL); /* Remember that we need to free the memory allocated. */ *free_p = true; } } - else if (IDENTIFIER_TYPENAME_P (name)) + else if (IDENTIFIER_CONV_OP_P (name)) { pretty_name = concat ("operator ", type_as_string_translate (TREE_TYPE (name), @@ -8619,7 +9013,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, pointer if this is a call to a base-class constructor or destructor. */ skip_first_for_error = false; - if (IDENTIFIER_CTOR_OR_DTOR_P (name)) + if (IDENTIFIER_CDTOR_P (name)) { /* Callers should explicitly indicate whether they want to construct the complete object or just the part without virtual bases. */ @@ -8747,7 +9141,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, { tree arglist = build_tree_list_vec (user_args); tree errname = name; - if (IDENTIFIER_CTOR_OR_DTOR_P (errname)) + if (IDENTIFIER_CDTOR_P (errname)) { tree fn = DECL_ORIGIN (OVL_FIRST (fns)); errname = DECL_NAME (fn); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 66f42627715..1243f33605f 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "gimplify.h" #include "intl.h" +#include "asan.h" /* Id for dumping the class hierarchy. */ int class_dump_id; @@ -462,7 +463,8 @@ build_base_path (enum tree_code code, else { tree t = expr; - if ((flag_sanitize & SANITIZE_VPTR) && fixed_type_p == 0) + if (sanitize_flags_p (SANITIZE_VPTR) + && fixed_type_p == 0) { t = cp_ubsan_maybe_instrument_cast_to_vbase (input_location, probe, expr); @@ -2326,25 +2328,25 @@ resort_type_method_vec (void* obj, gt_pointer_operator new_value, void* cookie) { - vec<tree, va_gc> *method_vec = (vec<tree, va_gc> *) obj; - int len = vec_safe_length (method_vec); - size_t slot; - tree fn; + if (vec<tree, va_gc> *method_vec = (vec<tree, va_gc> *) obj) + { + int len = method_vec->length (); + int slot; - /* The type conversion ops have to live at the front of the vec, so we - can't sort them. */ - for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; - vec_safe_iterate (method_vec, slot, &fn); - ++slot) - if (!DECL_CONV_FN_P (OVL_FIRST (fn))) - break; + /* The type conversion ops have to live at the front of the vec, so we + can't sort them. */ + for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; + slot < len; slot++) + if (!DECL_CONV_FN_P (OVL_FIRST ((*method_vec)[slot]))) + break; - if (len - slot > 1) - { - resort_data.new_value = new_value; - resort_data.cookie = cookie; - qsort (method_vec->address () + slot, len - slot, sizeof (tree), - resort_method_name_cmp); + if (len > slot + 1) + { + resort_data.new_value = new_value; + resort_data.cookie = cookie; + qsort (method_vec->address () + slot, len - slot, sizeof (tree), + resort_method_name_cmp); + } } } @@ -5023,10 +5025,8 @@ void deduce_noexcept_on_destructor (tree dtor) { if (!TYPE_RAISES_EXCEPTIONS (TREE_TYPE (dtor))) - { - tree eh_spec = unevaluated_noexcept_spec (); - TREE_TYPE (dtor) = build_exception_variant (TREE_TYPE (dtor), eh_spec); - } + TREE_TYPE (dtor) = build_exception_variant (TREE_TYPE (dtor), + noexcept_deferred_spec); } /* For each destructor in T, deduce noexcept: @@ -7187,8 +7187,8 @@ finish_struct_1 (tree t) in every translation unit where the class definition appears. If we're devirtualizing, we can look into the vtable even if we aren't emitting it. */ - if (CLASSTYPE_KEY_METHOD (t) == NULL_TREE) - keyed_classes = tree_cons (NULL_TREE, t, keyed_classes); + if (!CLASSTYPE_KEY_METHOD (t)) + vec_safe_push (keyed_classes, t); } /* Layout the class itself. */ diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index ae24e4010ff..5a574524866 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1394,6 +1394,21 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t, return t; } +/* Clean CONSTRUCTOR_NO_IMPLICIT_ZERO from CTOR and its sub-aggregates. */ + +static void +clear_no_implicit_zero (tree ctor) +{ + if (CONSTRUCTOR_NO_IMPLICIT_ZERO (ctor)) + { + CONSTRUCTOR_NO_IMPLICIT_ZERO (ctor) = false; + tree elt; unsigned HOST_WIDE_INT idx; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), idx, elt) + if (TREE_CODE (elt) == CONSTRUCTOR) + clear_no_implicit_zero (elt); + } +} + /* Subroutine of cxx_eval_constant_expression. Evaluate the call expression tree T in the context of OLD_CALL expression evaluation. */ @@ -1697,7 +1712,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, /* The result of a constexpr function must be completely initialized. */ if (TREE_CODE (result) == CONSTRUCTOR) - CONSTRUCTOR_NO_IMPLICIT_ZERO (result) = false; + clear_no_implicit_zero (result); pop_cx_call_context (); return unshare_constructor (result); @@ -5212,10 +5227,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, if (want_rval && !var_in_maybe_constexpr_fn (t) && !type_dependent_expression_p (t) - && !decl_constant_var_p (t) + && !decl_maybe_constant_var_p (t) && (strict || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t)) - || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t)) + || (DECL_INITIAL (t) + && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t))) && COMPLETE_TYPE_P (TREE_TYPE (t)) && !is_really_empty_class (TREE_TYPE (t))) { @@ -5540,21 +5556,21 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, { if (flags & tf_error) error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared " - "%<static%> in %<constexpr%> function", tmp); + "%<static%> in %<constexpr%> context", tmp); return false; } else if (CP_DECL_THREAD_LOCAL_P (tmp)) { if (flags & tf_error) error_at (DECL_SOURCE_LOCATION (tmp), "%qD declared " - "%<thread_local%> in %<constexpr%> function", tmp); + "%<thread_local%> in %<constexpr%> context", tmp); return false; } else if (!DECL_NONTRIVIALLY_INITIALIZED_P (tmp)) { if (flags & tf_error) error_at (DECL_SOURCE_LOCATION (tmp), "uninitialized " - "variable %qD in %<constexpr%> function", tmp); + "variable %qD in %<constexpr%> context", tmp); return false; } } diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c index 7c664482371..5ccf5d3385d 100644 --- a/gcc/cp/cp-cilkplus.c +++ b/gcc/cp/cp-cilkplus.c @@ -36,7 +36,7 @@ is_conversion_operator_function_decl_p (tree t) if (TREE_CODE (t) != FUNCTION_DECL) return false; - return DECL_NAME (t) && IDENTIFIER_TYPENAME_P (DECL_NAME (t)); + return DECL_CONV_FN_P (t); } /* Recursively traverse EXP to search for a CILK_SPAWN_STMT subtree. diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index e3802f1820b..f010f6c63be 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-ubsan.h" #include "cilk.h" #include "cp-cilkplus.h" +#include "asan.h" /* Forward declarations. */ @@ -1117,132 +1118,135 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) return NULL_TREE; } - if (TREE_CODE (stmt) == ADDR_EXPR - && is_invisiref_parm (TREE_OPERAND (stmt, 0))) + switch (TREE_CODE (stmt)) { - /* If in an OpenMP context, note var uses. */ - if (__builtin_expect (wtd->omp_ctx != NULL, 0) - && omp_var_to_track (TREE_OPERAND (stmt, 0))) - omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0)); - *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); - *walk_subtrees = 0; - } - else if (TREE_CODE (stmt) == RETURN_EXPR - && TREE_OPERAND (stmt, 0) - && is_invisiref_parm (TREE_OPERAND (stmt, 0))) - /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ - *walk_subtrees = 0; - else if (TREE_CODE (stmt) == OMP_CLAUSE) - switch (OMP_CLAUSE_CODE (stmt)) - { - case OMP_CLAUSE_LASTPRIVATE: - /* Don't dereference an invisiref in OpenMP clauses. */ - if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) - { - *walk_subtrees = 0; - if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt)) - cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt), - cp_genericize_r, data, NULL); - } - break; - case OMP_CLAUSE_PRIVATE: - /* Don't dereference an invisiref in OpenMP clauses. */ - if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) + case ADDR_EXPR: + if (is_invisiref_parm (TREE_OPERAND (stmt, 0))) + { + /* If in an OpenMP context, note var uses. */ + if (__builtin_expect (wtd->omp_ctx != NULL, 0) + && omp_var_to_track (TREE_OPERAND (stmt, 0))) + omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0)); + *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); *walk_subtrees = 0; - else if (wtd->omp_ctx != NULL) - { - /* Private clause doesn't cause any references to the - var in outer contexts, avoid calling - omp_cxx_notice_variable for it. */ - struct cp_genericize_omp_taskreg *old = wtd->omp_ctx; - wtd->omp_ctx = NULL; - cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r, - data, NULL); - wtd->omp_ctx = old; + } + break; + + case RETURN_EXPR: + if (TREE_OPERAND (stmt, 0) && is_invisiref_parm (TREE_OPERAND (stmt, 0))) + /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ + *walk_subtrees = 0; + break; + + case OMP_CLAUSE: + switch (OMP_CLAUSE_CODE (stmt)) + { + case OMP_CLAUSE_LASTPRIVATE: + /* Don't dereference an invisiref in OpenMP clauses. */ + if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) + { + *walk_subtrees = 0; + if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt)) + cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt), + cp_genericize_r, data, NULL); + } + break; + case OMP_CLAUSE_PRIVATE: + /* Don't dereference an invisiref in OpenMP clauses. */ + if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) *walk_subtrees = 0; - } - break; - case OMP_CLAUSE_SHARED: - case OMP_CLAUSE_FIRSTPRIVATE: - case OMP_CLAUSE_COPYIN: - case OMP_CLAUSE_COPYPRIVATE: - /* Don't dereference an invisiref in OpenMP clauses. */ - if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) - *walk_subtrees = 0; - break; - case OMP_CLAUSE_REDUCTION: - /* Don't dereference an invisiref in reduction clause's - OMP_CLAUSE_DECL either. OMP_CLAUSE_REDUCTION_{INIT,MERGE} - still needs to be genericized. */ - if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) - { + else if (wtd->omp_ctx != NULL) + { + /* Private clause doesn't cause any references to the + var in outer contexts, avoid calling + omp_cxx_notice_variable for it. */ + struct cp_genericize_omp_taskreg *old = wtd->omp_ctx; + wtd->omp_ctx = NULL; + cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r, + data, NULL); + wtd->omp_ctx = old; + *walk_subtrees = 0; + } + break; + case OMP_CLAUSE_SHARED: + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_COPYIN: + case OMP_CLAUSE_COPYPRIVATE: + /* Don't dereference an invisiref in OpenMP clauses. */ + if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) *walk_subtrees = 0; - if (OMP_CLAUSE_REDUCTION_INIT (stmt)) - cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (stmt), - cp_genericize_r, data, NULL); - if (OMP_CLAUSE_REDUCTION_MERGE (stmt)) - cp_walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (stmt), - cp_genericize_r, data, NULL); - } - break; - default: - break; - } - else if (IS_TYPE_OR_DECL_P (stmt)) - *walk_subtrees = 0; - - /* Due to the way voidify_wrapper_expr is written, we don't get a chance - to lower this construct before scanning it, so we need to lower these - before doing anything else. */ - else if (TREE_CODE (stmt) == CLEANUP_STMT) - *stmt_p = build2_loc (EXPR_LOCATION (stmt), - CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR - : TRY_FINALLY_EXPR, - void_type_node, - CLEANUP_BODY (stmt), - CLEANUP_EXPR (stmt)); - - else if (TREE_CODE (stmt) == IF_STMT) - { + break; + case OMP_CLAUSE_REDUCTION: + /* Don't dereference an invisiref in reduction clause's + OMP_CLAUSE_DECL either. OMP_CLAUSE_REDUCTION_{INIT,MERGE} + still needs to be genericized. */ + if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) + { + *walk_subtrees = 0; + if (OMP_CLAUSE_REDUCTION_INIT (stmt)) + cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (stmt), + cp_genericize_r, data, NULL); + if (OMP_CLAUSE_REDUCTION_MERGE (stmt)) + cp_walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (stmt), + cp_genericize_r, data, NULL); + } + break; + default: + break; + } + break; + + /* Due to the way voidify_wrapper_expr is written, we don't get a chance + to lower this construct before scanning it, so we need to lower these + before doing anything else. */ + case CLEANUP_STMT: + *stmt_p = build2_loc (EXPR_LOCATION (stmt), + CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR + : TRY_FINALLY_EXPR, + void_type_node, + CLEANUP_BODY (stmt), + CLEANUP_EXPR (stmt)); + break; + + case IF_STMT: genericize_if_stmt (stmt_p); /* *stmt_p has changed, tail recurse to handle it again. */ return cp_genericize_r (stmt_p, walk_subtrees, data); - } - /* COND_EXPR might have incompatible types in branches if one or both - arms are bitfields. Fix it up now. */ - else if (TREE_CODE (stmt) == COND_EXPR) - { - tree type_left - = (TREE_OPERAND (stmt, 1) - ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1)) - : NULL_TREE); - tree type_right - = (TREE_OPERAND (stmt, 2) - ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2)) - : NULL_TREE); - if (type_left - && !useless_type_conversion_p (TREE_TYPE (stmt), - TREE_TYPE (TREE_OPERAND (stmt, 1)))) - { - TREE_OPERAND (stmt, 1) - = fold_convert (type_left, TREE_OPERAND (stmt, 1)); - gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), - type_left)); - } - if (type_right - && !useless_type_conversion_p (TREE_TYPE (stmt), - TREE_TYPE (TREE_OPERAND (stmt, 2)))) - { - TREE_OPERAND (stmt, 2) - = fold_convert (type_right, TREE_OPERAND (stmt, 2)); - gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), - type_right)); - } - } + /* COND_EXPR might have incompatible types in branches if one or both + arms are bitfields. Fix it up now. */ + case COND_EXPR: + { + tree type_left + = (TREE_OPERAND (stmt, 1) + ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1)) + : NULL_TREE); + tree type_right + = (TREE_OPERAND (stmt, 2) + ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2)) + : NULL_TREE); + if (type_left + && !useless_type_conversion_p (TREE_TYPE (stmt), + TREE_TYPE (TREE_OPERAND (stmt, 1)))) + { + TREE_OPERAND (stmt, 1) + = fold_convert (type_left, TREE_OPERAND (stmt, 1)); + gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), + type_left)); + } + if (type_right + && !useless_type_conversion_p (TREE_TYPE (stmt), + TREE_TYPE (TREE_OPERAND (stmt, 2)))) + { + TREE_OPERAND (stmt, 2) + = fold_convert (type_right, TREE_OPERAND (stmt, 2)); + gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), + type_right)); + } + } + break; - else if (TREE_CODE (stmt) == BIND_EXPR) - { + case BIND_EXPR: if (__builtin_expect (wtd->omp_ctx != NULL, 0)) { tree decl; @@ -1262,8 +1266,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) : OMP_CLAUSE_DEFAULT_PRIVATE); } } - if (flag_sanitize - & (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR)) + if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR)) { /* The point here is to not sanitize static initializers. */ bool no_sanitize_p = wtd->no_sanitize_p; @@ -1281,113 +1284,118 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) cp_walk_tree (&BIND_EXPR_BODY (stmt), cp_genericize_r, data, NULL); wtd->bind_expr_stack.pop (); - } + break; - else if (TREE_CODE (stmt) == USING_STMT) - { - tree block = NULL_TREE; + case USING_STMT: + { + tree block = NULL_TREE; + + /* Get the innermost inclosing GIMPLE_BIND that has a non NULL + BLOCK, and append an IMPORTED_DECL to its + BLOCK_VARS chained list. */ + if (wtd->bind_expr_stack.exists ()) + { + int i; + for (i = wtd->bind_expr_stack.length () - 1; i >= 0; i--) + if ((block = BIND_EXPR_BLOCK (wtd->bind_expr_stack[i]))) + break; + } + if (block) + { + tree using_directive; + gcc_assert (TREE_OPERAND (stmt, 0)); - /* Get the innermost inclosing GIMPLE_BIND that has a non NULL - BLOCK, and append an IMPORTED_DECL to its - BLOCK_VARS chained list. */ - if (wtd->bind_expr_stack.exists ()) + using_directive = make_node (IMPORTED_DECL); + TREE_TYPE (using_directive) = void_type_node; + + IMPORTED_DECL_ASSOCIATED_DECL (using_directive) + = TREE_OPERAND (stmt, 0); + DECL_CHAIN (using_directive) = BLOCK_VARS (block); + BLOCK_VARS (block) = using_directive; + } + /* The USING_STMT won't appear in GENERIC. */ + *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); + *walk_subtrees = 0; + } + break; + + case DECL_EXPR: + if (TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL) { - int i; - for (i = wtd->bind_expr_stack.length () - 1; i >= 0; i--) - if ((block = BIND_EXPR_BLOCK (wtd->bind_expr_stack[i]))) - break; + /* Using decls inside DECL_EXPRs are just dropped on the floor. */ + *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); + *walk_subtrees = 0; } - if (block) + else { - tree using_directive; - gcc_assert (TREE_OPERAND (stmt, 0)); - - using_directive = make_node (IMPORTED_DECL); - TREE_TYPE (using_directive) = void_type_node; - - IMPORTED_DECL_ASSOCIATED_DECL (using_directive) - = TREE_OPERAND (stmt, 0); - DECL_CHAIN (using_directive) = BLOCK_VARS (block); - BLOCK_VARS (block) = using_directive; + tree d = DECL_EXPR_DECL (stmt); + if (VAR_P (d)) + gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d)); } - /* The USING_STMT won't appear in GENERIC. */ - *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); - *walk_subtrees = 0; - } - - else if (TREE_CODE (stmt) == DECL_EXPR - && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL) - { - /* Using decls inside DECL_EXPRs are just dropped on the floor. */ - *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); - *walk_subtrees = 0; - } - else if (TREE_CODE (stmt) == DECL_EXPR) - { - tree d = DECL_EXPR_DECL (stmt); - if (VAR_P (d)) - gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d)); - } - else if (TREE_CODE (stmt) == OMP_PARALLEL - || TREE_CODE (stmt) == OMP_TASK - || TREE_CODE (stmt) == OMP_TASKLOOP) - { - struct cp_genericize_omp_taskreg omp_ctx; - tree c, decl; - splay_tree_node n; + break; - *walk_subtrees = 0; - cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL); - omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL; - omp_ctx.default_shared = omp_ctx.is_parallel; - omp_ctx.outer = wtd->omp_ctx; - omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0); - wtd->omp_ctx = &omp_ctx; - for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c)) - switch (OMP_CLAUSE_CODE (c)) - { - case OMP_CLAUSE_SHARED: - case OMP_CLAUSE_PRIVATE: - case OMP_CLAUSE_FIRSTPRIVATE: - case OMP_CLAUSE_LASTPRIVATE: - decl = OMP_CLAUSE_DECL (c); - if (decl == error_mark_node || !omp_var_to_track (decl)) + case OMP_PARALLEL: + case OMP_TASK: + case OMP_TASKLOOP: + { + struct cp_genericize_omp_taskreg omp_ctx; + tree c, decl; + splay_tree_node n; + + *walk_subtrees = 0; + cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL); + omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL; + omp_ctx.default_shared = omp_ctx.is_parallel; + omp_ctx.outer = wtd->omp_ctx; + omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0); + wtd->omp_ctx = &omp_ctx; + for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c)) + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_SHARED: + case OMP_CLAUSE_PRIVATE: + case OMP_CLAUSE_FIRSTPRIVATE: + case OMP_CLAUSE_LASTPRIVATE: + decl = OMP_CLAUSE_DECL (c); + if (decl == error_mark_node || !omp_var_to_track (decl)) + break; + n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl); + if (n != NULL) + break; + splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl, + OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED + ? OMP_CLAUSE_DEFAULT_SHARED + : OMP_CLAUSE_DEFAULT_PRIVATE); + if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE && omp_ctx.outer) + omp_cxx_notice_variable (omp_ctx.outer, decl); break; - n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl); - if (n != NULL) + case OMP_CLAUSE_DEFAULT: + if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED) + omp_ctx.default_shared = true; + default: break; - splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl, - OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED - ? OMP_CLAUSE_DEFAULT_SHARED - : OMP_CLAUSE_DEFAULT_PRIVATE); - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE - && omp_ctx.outer) - omp_cxx_notice_variable (omp_ctx.outer, decl); - break; - case OMP_CLAUSE_DEFAULT: - if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED) - omp_ctx.default_shared = true; - default: - break; - } - if (TREE_CODE (stmt) == OMP_TASKLOOP) - genericize_omp_for_stmt (stmt_p, walk_subtrees, data); - else - cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL); - wtd->omp_ctx = omp_ctx.outer; - splay_tree_delete (omp_ctx.variables); - } - else if (TREE_CODE (stmt) == TRY_BLOCK) - { - *walk_subtrees = 0; - tree try_block = wtd->try_block; - wtd->try_block = stmt; - cp_walk_tree (&TRY_STMTS (stmt), cp_genericize_r, data, NULL); - wtd->try_block = try_block; - cp_walk_tree (&TRY_HANDLERS (stmt), cp_genericize_r, data, NULL); - } - else if (TREE_CODE (stmt) == MUST_NOT_THROW_EXPR) - { + } + if (TREE_CODE (stmt) == OMP_TASKLOOP) + genericize_omp_for_stmt (stmt_p, walk_subtrees, data); + else + cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL); + wtd->omp_ctx = omp_ctx.outer; + splay_tree_delete (omp_ctx.variables); + } + break; + + case TRY_BLOCK: + { + *walk_subtrees = 0; + tree try_block = wtd->try_block; + wtd->try_block = stmt; + cp_walk_tree (&TRY_STMTS (stmt), cp_genericize_r, data, NULL); + wtd->try_block = try_block; + cp_walk_tree (&TRY_HANDLERS (stmt), cp_genericize_r, data, NULL); + } + break; + + case MUST_NOT_THROW_EXPR: /* MUST_NOT_THROW_COND might be something else with TM. */ if (MUST_NOT_THROW_COND (stmt) == NULL_TREE) { @@ -1397,68 +1405,99 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL); wtd->try_block = try_block; } - } - else if (TREE_CODE (stmt) == THROW_EXPR) - { - location_t loc = location_of (stmt); - if (TREE_NO_WARNING (stmt)) - /* Never mind. */; - else if (wtd->try_block) - { - if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR - && warning_at (loc, OPT_Wterminate, - "throw will always call terminate()") - && cxx_dialect >= cxx11 - && DECL_DESTRUCTOR_P (current_function_decl)) - inform (loc, "in C++11 destructors default to noexcept"); - } - else - { - if (warn_cxx11_compat && cxx_dialect < cxx11 - && DECL_DESTRUCTOR_P (current_function_decl) - && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)) - == NULL_TREE) - && (get_defaulted_eh_spec (current_function_decl) - == empty_except_spec)) - warning_at (loc, OPT_Wc__11_compat, - "in C++11 this throw will terminate because " - "destructors default to noexcept"); - } - } - else if (TREE_CODE (stmt) == CONVERT_EXPR) - gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt)); - else if (TREE_CODE (stmt) == FOR_STMT) - genericize_for_stmt (stmt_p, walk_subtrees, data); - else if (TREE_CODE (stmt) == WHILE_STMT) - genericize_while_stmt (stmt_p, walk_subtrees, data); - else if (TREE_CODE (stmt) == DO_STMT) - genericize_do_stmt (stmt_p, walk_subtrees, data); - else if (TREE_CODE (stmt) == SWITCH_STMT) - genericize_switch_stmt (stmt_p, walk_subtrees, data); - else if (TREE_CODE (stmt) == CONTINUE_STMT) - genericize_continue_stmt (stmt_p); - else if (TREE_CODE (stmt) == BREAK_STMT) - genericize_break_stmt (stmt_p); - else if (TREE_CODE (stmt) == OMP_FOR - || TREE_CODE (stmt) == OMP_SIMD - || TREE_CODE (stmt) == OMP_DISTRIBUTE) - genericize_omp_for_stmt (stmt_p, walk_subtrees, data); - else if (TREE_CODE (stmt) == PTRMEM_CST) - { + break; + + case THROW_EXPR: + { + location_t loc = location_of (stmt); + if (TREE_NO_WARNING (stmt)) + /* Never mind. */; + else if (wtd->try_block) + { + if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR + && warning_at (loc, OPT_Wterminate, + "throw will always call terminate()") + && cxx_dialect >= cxx11 + && DECL_DESTRUCTOR_P (current_function_decl)) + inform (loc, "in C++11 destructors default to noexcept"); + } + else + { + if (warn_cxx11_compat && cxx_dialect < cxx11 + && DECL_DESTRUCTOR_P (current_function_decl) + && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)) + == NULL_TREE) + && (get_defaulted_eh_spec (current_function_decl) + == empty_except_spec)) + warning_at (loc, OPT_Wc__11_compat, + "in C++11 this throw will terminate because " + "destructors default to noexcept"); + } + } + break; + + case CONVERT_EXPR: + gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt)); + break; + + case FOR_STMT: + genericize_for_stmt (stmt_p, walk_subtrees, data); + break; + + case WHILE_STMT: + genericize_while_stmt (stmt_p, walk_subtrees, data); + break; + + case DO_STMT: + genericize_do_stmt (stmt_p, walk_subtrees, data); + break; + + case SWITCH_STMT: + genericize_switch_stmt (stmt_p, walk_subtrees, data); + break; + + case CONTINUE_STMT: + genericize_continue_stmt (stmt_p); + break; + + case BREAK_STMT: + genericize_break_stmt (stmt_p); + break; + + case OMP_FOR: + case OMP_SIMD: + case OMP_DISTRIBUTE: + genericize_omp_for_stmt (stmt_p, walk_subtrees, data); + break; + + case PTRMEM_CST: /* By the time we get here we're handing off to the back end, so we don't need or want to preserve PTRMEM_CST anymore. */ *stmt_p = cplus_expand_constant (stmt); *walk_subtrees = 0; - } - else if ((flag_sanitize - & (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR)) - && !wtd->no_sanitize_p) - { - if ((flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT)) - && TREE_CODE (stmt) == NOP_EXPR + break; + + case MEM_REF: + /* For MEM_REF, make sure not to sanitize the second operand even + if it has reference type. It is just an offset with a type + holding other information. There is no other processing we + need to do for INTEGER_CSTs, so just ignore the second argument + unconditionally. */ + cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL); + *walk_subtrees = 0; + break; + + case NOP_EXPR: + if (!wtd->no_sanitize_p + && sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT) && TREE_CODE (TREE_TYPE (stmt)) == REFERENCE_TYPE) ubsan_maybe_instrument_reference (stmt_p); - else if (TREE_CODE (stmt) == CALL_EXPR) + break; + + case CALL_EXPR: + if (!wtd->no_sanitize_p + && sanitize_flags_p ((SANITIZE_NULL + | SANITIZE_ALIGNMENT | SANITIZE_VPTR))) { tree fn = CALL_EXPR_FN (stmt); if (fn != NULL_TREE @@ -1470,12 +1509,18 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) = TREE_CODE (fn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)); - if (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT)) + if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT)) ubsan_maybe_instrument_member_call (stmt, is_ctor); - if ((flag_sanitize & SANITIZE_VPTR) && !is_ctor) + if (sanitize_flags_p (SANITIZE_VPTR) && !is_ctor) cp_ubsan_maybe_instrument_member_call (stmt); } } + break; + + default: + if (IS_TYPE_OR_DECL_P (stmt)) + *walk_subtrees = 0; + break; } p_set->add (*stmt_p); @@ -1499,7 +1544,7 @@ cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p) cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL); delete wtd.p_set; wtd.bind_expr_stack.release (); - if (flag_sanitize & SANITIZE_VPTR) + if (sanitize_flags_p (SANITIZE_VPTR)) cp_ubsan_instrument_member_accesses (t_p); } @@ -1590,7 +1635,8 @@ cp_genericize (tree fndecl) if (outer) for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) - if (DECL_NAME (t) == DECL_NAME (var) + if (VAR_P (var) + && DECL_NAME (t) == DECL_NAME (var) && DECL_HAS_VALUE_EXPR_P (var) && DECL_VALUE_EXPR (var) == t) { @@ -1622,8 +1668,7 @@ cp_genericize (tree fndecl) walk_tree's hash functionality. */ cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true); - if (flag_sanitize & SANITIZE_RETURN - && do_ubsan_in_current_function ()) + if (sanitize_flags_p (SANITIZE_RETURN)) cp_ubsan_maybe_instrument_return (fndecl); /* Do everything else. */ @@ -1837,7 +1882,8 @@ cxx_omp_const_qual_no_mutable (tree decl) if (outer) for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) - if (DECL_NAME (decl) == DECL_NAME (var) + if (VAR_P (var) + && DECL_NAME (decl) == DECL_NAME (var) && (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (var)))) { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5dd6023be16..33dde158dae 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -136,7 +136,6 @@ enum cp_tree_index CPTI_DELTA_IDENTIFIER, CPTI_IN_CHARGE_IDENTIFIER, CPTI_VTT_PARM_IDENTIFIER, - CPTI_NELTS_IDENTIFIER, CPTI_THIS_IDENTIFIER, CPTI_PFN_IDENTIFIER, CPTI_VPTR_IDENTIFIER, @@ -169,8 +168,6 @@ enum cp_tree_index CPTI_DSO_HANDLE, CPTI_DCAST, - CPTI_KEYED_CLASSES, - CPTI_NULLPTR, CPTI_NULLPTR_TYPE, @@ -236,7 +233,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; /* The name of the parameter that contains a pointer to the VTT to use for this subobject constructor or destructor. */ #define vtt_parm_identifier cp_global_trees[CPTI_VTT_PARM_IDENTIFIER] -#define nelts_identifier cp_global_trees[CPTI_NELTS_IDENTIFIER] #define this_identifier cp_global_trees[CPTI_THIS_IDENTIFIER] #define pfn_identifier cp_global_trees[CPTI_PFN_IDENTIFIER] #define vptr_identifier cp_global_trees[CPTI_VPTR_IDENTIFIER] @@ -290,11 +286,6 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; destructors. */ #define vtt_parm_type cp_global_trees[CPTI_VTT_PARM_TYPE] -/* A TREE_LIST of the dynamic classes whose vtables may have to be - emitted in this translation unit. */ - -#define keyed_classes cp_global_trees[CPTI_KEYED_CLASSES] - /* A node which matches any template argument. */ #define any_targ_node cp_global_trees[CPTI_ANY_TARG] @@ -307,7 +298,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; #include "name-lookup.h" /* Usage of TREE_LANG_FLAG_?: - 0: IDENTIFIER_MARKED (IDENTIFIER_NODEs) + 0: IDENTIFIER_KIND_BIT_0 (in IDENTIFIER_NODE) NEW_EXPR_USE_GLOBAL (in NEW_EXPR). COND_EXPR_IS_VEC_DELETE (in COND_EXPR). DELETE_EXPR_USE_GLOBAL (in DELETE_EXPR). @@ -348,7 +339,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; IF_STMT_CONSTEXPR_P (IF_STMT) TEMPLATE_TYPE_PARM_FOR_CLASS (TEMPLATE_TYPE_PARM) DECL_NAMESPACE_INLINE_P (in NAMESPACE_DECL) - 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) + 1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. DELETE_EXPR_USE_VEC (in DELETE_EXPR). @@ -366,7 +357,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; TINFO_USED_TEMPLATE_ID (in TEMPLATE_INFO) PACK_EXPANSION_SIZEOF_P (in *_PACK_EXPANSION) OVL_USING_P (in OVERLOAD) - 2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE) + 2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE) ICS_THIS_FLAG (in _CONV) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST) @@ -381,21 +372,20 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; 3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). ICS_BAD_FLAG (in _CONV) FN_TRY_BLOCK_P (in TRY_BLOCK) - IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE) BIND_EXPR_BODY_BLOCK (in BIND_EXPR) DECL_NON_TRIVIALLY_INITIALIZED_P (in VAR_DECL) CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE) CONSTUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR) OVL_NESTED_P (in OVERLOAD) - 4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, + 4: IDENTIFIER_MARKED (IDENTIFIER_NODEs) + TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, CALL_EXPR, or FIELD_DECL). - IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE) DECL_TINFO_P (in VAR_DECL) FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) OVL_LOOKUP_P (in OVERLOAD) LOOKUP_FOUND_P (in RECORD_TYPE, UNION_TYPE, NAMESPACE_DECL) - 5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE) + 5: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) DECL_VTABLE_OR_VTT_P (in VAR_DECL) FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE) CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR) @@ -557,7 +547,7 @@ identifier_p (tree t) template <> struct default_hash_traits <lang_identifier *> - : pointer_hash <tree_node>, ggc_remove <tree> + : pointer_hash <tree_node> { /* Use a regular tree as the type, to make using the hash table simpler. We'll get dynamic type checking with the hash function @@ -565,16 +555,15 @@ struct default_hash_traits <lang_identifier *> GTY((skip)) typedef tree value_type; GTY((skip)) typedef tree compare_type; - static hashval_t hash (const value_type &id) + static hashval_t hash (const value_type id) { return IDENTIFIER_HASH_VALUE (id); } -}; - -/* In an IDENTIFIER_NODE, nonzero if this identifier is actually a - keyword. C_RID_CODE (node) is then the RID_* value of the keyword. */ -#define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_5 (ID) + /* Nothing is deletable. Everything is insertable. */ + static bool is_deleted (value_type) { return false; } + static void remove (value_type) { gcc_unreachable (); } +}; #define LANG_IDENTIFIER_CAST(NODE) \ ((struct lang_identifier*)IDENTIFIER_NODE_CHECK (NODE)) @@ -992,29 +981,89 @@ enum GTY(()) abstract_class_use { #define SET_IDENTIFIER_LABEL_VALUE(NODE, VALUE) \ IDENTIFIER_LABEL_VALUE (NODE) = (VALUE) -/* Nonzero if this identifier is used as a virtual function name somewhere - (optimizes searches). */ -#define IDENTIFIER_VIRTUAL_P(NODE) TREE_LANG_FLAG_1 (NODE) +/* Kinds of identifiers. Values are carefully chosen. */ +enum cp_identifier_kind { + cik_normal = 0, /* Not a special identifier. */ + cik_keyword = 1, /* A keyword. */ + cik_ctor = 2, /* Constructor (in-chg, complete or base). */ + cik_dtor = 3, /* Destructor (in-chg, deleting, complete or + base). */ + cik_simple_op = 4, /* Non-assignment operator name. */ + cik_newdel_op = 5, /* New or delete operator name. */ + cik_assign_op = 6, /* An assignment operator name. */ + cik_conv_op = 7, /* Conversion operator name. */ + cik_max +}; -/* Nonzero if this identifier is the prefix for a mangled C++ operator - name. */ -#define IDENTIFIER_OPNAME_P(NODE) TREE_LANG_FLAG_2 (NODE) +/* Kind bits. */ +#define IDENTIFIER_KIND_BIT_0(NODE) \ + TREE_LANG_FLAG_0 (IDENTIFIER_NODE_CHECK (NODE)) +#define IDENTIFIER_KIND_BIT_1(NODE) \ + TREE_LANG_FLAG_1 (IDENTIFIER_NODE_CHECK (NODE)) +#define IDENTIFIER_KIND_BIT_2(NODE) \ + TREE_LANG_FLAG_2 (IDENTIFIER_NODE_CHECK (NODE)) -/* Nonzero if this identifier is the name of a type-conversion - operator. */ -#define IDENTIFIER_TYPENAME_P(NODE) \ - TREE_LANG_FLAG_4 (NODE) +/* Used by various search routines. */ +#define IDENTIFIER_MARKED(NODE) \ + TREE_LANG_FLAG_4 (IDENTIFIER_NODE_CHECK (NODE)) -/* Nonzero if this identifier is the name of a constructor or - destructor. */ -#define IDENTIFIER_CTOR_OR_DTOR_P(NODE) \ - TREE_LANG_FLAG_3 (NODE) +/* Nonzero if this identifier is used as a virtual function name somewhere + (optimizes searches). */ +#define IDENTIFIER_VIRTUAL_P(NODE) \ + TREE_LANG_FLAG_5 (IDENTIFIER_NODE_CHECK (NODE)) /* True iff NAME is the DECL_ASSEMBLER_NAME for an entity with vague linkage which the prelinker has assigned to this translation unit. */ #define IDENTIFIER_REPO_CHOSEN(NAME) \ - (TREE_LANG_FLAG_6 (NAME)) + (TREE_LANG_FLAG_6 (IDENTIFIER_NODE_CHECK (NAME))) + +/* True if this identifier is a reserved word. C_RID_CODE (node) is + then the RID_* value of the keyword. Value 1. */ +#define IDENTIFIER_KEYWORD_P(NODE) \ + ((!IDENTIFIER_KIND_BIT_2 (NODE)) \ + & (!IDENTIFIER_KIND_BIT_1 (NODE)) \ + & IDENTIFIER_KIND_BIT_0 (NODE)) + +/* True if this identifier is the name of a constructor or + destructor. Value 2 or 3. */ +#define IDENTIFIER_CDTOR_P(NODE) \ + ((!IDENTIFIER_KIND_BIT_2 (NODE)) \ + & IDENTIFIER_KIND_BIT_1 (NODE)) + +/* True if this identifier is the name of a constructor. Value 2. */ +#define IDENTIFIER_CTOR_P(NODE) \ + (IDENTIFIER_CDTOR_P(NODE) \ + & (!IDENTIFIER_KIND_BIT_0 (NODE))) + +/* True if this identifier is the name of a destructor. Value 3. */ +#define IDENTIFIER_DTOR_P(NODE) \ + (IDENTIFIER_CDTOR_P(NODE) \ + & IDENTIFIER_KIND_BIT_0 (NODE)) + +/* True if this identifier is for any operator name (including + conversions). Value 4, 5, 6 or 7. */ +#define IDENTIFIER_ANY_OP_P(NODE) \ + (IDENTIFIER_KIND_BIT_2 (NODE)) + +/* True if this identifier is for new or delete operator. Value 5. */ +#define IDENTIFIER_NEWDEL_OP_P(NODE) \ + (IDENTIFIER_KIND_BIT_2 (NODE) \ + & (!IDENTIFIER_KIND_BIT_1 (NODE)) \ + & IDENTIFIER_KIND_BIT_0 (NODE)) + +/* True if this identifier is for any assignment. Values 6. */ +#define IDENTIFIER_ASSIGN_OP_P(NODE) \ + (IDENTIFIER_KIND_BIT_2 (NODE) \ + & IDENTIFIER_KIND_BIT_1 (NODE) \ + & (!IDENTIFIER_KIND_BIT_0 (NODE))) + +/* True if this identifier is the name of a type-conversion + operator. Value 7. */ +#define IDENTIFIER_CONV_OP_P(NODE) \ + (IDENTIFIER_KIND_BIT_2 (NODE) \ + & IDENTIFIER_KIND_BIT_1 (NODE) \ + & IDENTIFIER_KIND_BIT_0 (NODE)) /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is read-only. */ #define C_TYPE_FIELDS_READONLY(TYPE) \ @@ -1723,14 +1772,6 @@ struct GTY(()) language_function { #define current_function_auto_return_pattern \ (cp_function_chain->x_auto_return_pattern) -/* True if NAME is the IDENTIFIER_NODE for an overloaded "operator - new" or "operator delete". */ -#define NEW_DELETE_OPNAME_P(NAME) \ - ((NAME) == cp_operator_id (NEW_EXPR) \ - || (NAME) == cp_operator_id (VEC_NEW_EXPR) \ - || (NAME) == cp_operator_id (DELETE_EXPR) \ - || (NAME) == cp_operator_id (VEC_DELETE_EXPR)) - #define cp_operator_id(CODE) \ (operator_name_info[(int) (CODE)].identifier) #define cp_assignment_operator_id(CODE) \ @@ -2318,9 +2359,6 @@ struct GTY(()) lang_type { /* Nonzero if this BINFO is a primary base class. */ #define BINFO_PRIMARY_P(NODE) BINFO_FLAG_5(NODE) - -/* Used by various search routines. */ -#define IDENTIFIER_MARKED(NODE) TREE_LANG_FLAG_0 (NODE) /* A vec<tree_pair_s> of the vcall indices associated with the class NODE. The PURPOSE of each element is a FUNCTION_DECL for a virtual @@ -2771,7 +2809,7 @@ struct GTY(()) lang_decl { /* Nonzero if NODE is a user-defined conversion operator. */ #define DECL_CONV_FN_P(NODE) \ - (DECL_NAME (NODE) && IDENTIFIER_TYPENAME_P (DECL_NAME (NODE))) + (DECL_NAME (NODE) && IDENTIFIER_CONV_OP_P (DECL_NAME (NODE))) /* If FN is a conversion operator, the type to which it converts. Otherwise, NULL_TREE. */ @@ -2805,7 +2843,7 @@ struct GTY(()) lang_decl { value of ERROR_MARK is zero, this macro can be used as a predicate to test whether or not NODE is an overloaded operator. */ #define DECL_OVERLOADED_OPERATOR_P(NODE) \ - (IDENTIFIER_OPNAME_P (DECL_NAME (NODE)) \ + (IDENTIFIER_ANY_OP_P (DECL_NAME (NODE)) \ ? LANG_DECL_FN_CHECK (NODE)->operator_code : ERROR_MARK) /* Nonzero if NODE is an assignment operator (including += and such). */ @@ -5107,6 +5145,10 @@ extern GTY(()) vec<tree, va_gc> *local_classes; /* An array of static vars & fns. */ extern GTY(()) vec<tree, va_gc> *static_decls; +/* An array of vtable-needing types that have no key function, or have + an emitted key function. */ +extern GTY(()) vec<tree, va_gc> *keyed_classes; + /* Here's where we control how name mangling takes place. */ @@ -6077,7 +6119,7 @@ extern int cp_complete_array_type_or_error (tree *, tree, bool, tsubst_flags_t); extern tree build_ptrmemfunc_type (tree); extern tree build_ptrmem_type (tree, tree); /* the grokdeclarator prototype is in decl.h */ -extern tree build_this_parm (tree, cp_cv_quals); +extern tree build_this_parm (tree, tree, cp_cv_quals); extern tree grokparms (tree, tree *); extern int copy_fn_p (const_tree); extern bool move_fn_p (const_tree); @@ -6178,7 +6220,7 @@ extern void check_default_args (tree); extern bool mark_used (tree); extern bool mark_used (tree, tsubst_flags_t); extern void finish_static_data_member_decl (tree, tree, bool, tree, int); -extern tree cp_build_parm_decl (tree, tree); +extern tree cp_build_parm_decl (tree, tree, tree); extern tree get_guard (tree); extern tree get_guard_cond (tree, bool); extern tree set_guard (tree); @@ -6187,7 +6229,7 @@ extern void mark_needed (tree); extern bool decl_needed_p (tree); extern void note_vague_linkage_fn (tree); extern void note_variable_template_instantiation (tree); -extern tree build_artificial_parm (tree, tree); +extern tree build_artificial_parm (tree, tree, tree); extern bool possibly_inlined_p (tree); extern int parm_index (tree); extern tree vtv_start_verification_constructor_init_function (void); @@ -6306,6 +6348,8 @@ extern tree copy_decl (tree CXX_MEM_STAT_INFO); extern tree copy_type (tree CXX_MEM_STAT_INFO); extern tree cxx_make_type (enum tree_code); extern tree make_class_type (enum tree_code); +extern const char *get_identifier_kind_name (tree); +extern void set_identifier_kind (tree, cp_identifier_kind); extern bool cxx_init (void); extern void cxx_finish (void); extern bool in_main_input_context (void); @@ -6320,7 +6364,6 @@ extern tree forward_parm (tree); extern bool is_trivially_xible (enum tree_code, tree, tree); extern bool is_xible (enum tree_code, tree, tree); extern tree get_defaulted_eh_spec (tree); -extern tree unevaluated_noexcept_spec (void); extern void after_nsdmi_defaulted_late_checks (tree); extern bool maybe_explain_implicit_delete (tree); extern void explain_implicit_non_constexpr (tree); @@ -6370,6 +6413,7 @@ extern void check_template_variable (tree); extern tree make_auto (void); extern tree make_decltype_auto (void); extern tree make_template_placeholder (tree); +extern bool template_placeholder_p (tree); extern tree do_auto_deduction (tree, tree, tree); extern tree do_auto_deduction (tree, tree, tree, tsubst_flags_t, diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c index 71d315ec2b4..f00f870bd3e 100644 --- a/gcc/cp/cp-ubsan.c +++ b/gcc/cp/cp-ubsan.c @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "cp-tree.h" #include "ubsan.h" +#include "asan.h" /* Test if we should instrument vptr access. */ @@ -32,7 +33,7 @@ cp_ubsan_instrument_vptr_p (tree type) if (!flag_rtti || flag_sanitize_undefined_trap_on_error) return false; - if (!do_ubsan_in_current_function ()) + if (!sanitize_flags_p (SANITIZE_VPTR)) return false; if (type) diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index b74a56f4200..5398e3dd87d 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -159,7 +159,7 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t) case IDENTIFIER_NODE: if (t == NULL) pp->translate_string ("<unnamed>"); - else if (IDENTIFIER_TYPENAME_P (t)) + else if (IDENTIFIER_CONV_OP_P (t)) pp_cxx_conversion_function_id (pp, t); else { diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b0df3c9835c..0361357a14e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -51,6 +51,7 @@ along with GCC; see the file COPYING3. If not see #include "cilk.h" #include "builtins.h" #include "gimplify.h" +#include "asan.h" /* Possible cases of bad specifiers type used by bad_specifiers. */ enum bad_spec_place { @@ -159,6 +160,9 @@ tree integer_two_node; /* vector of static decls. */ vec<tree, va_gc> *static_decls; +/* vector of keyed classes. */ +vec<tree, va_gc> *keyed_classes; + /* Used only for jumps to as-yet undefined labels, since jumps to defined labels can have their validity checked immediately. */ @@ -1466,53 +1470,41 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) t2 = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); t1 || t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2)) - if (!t1 || !t2) - break; - /* Deal with fileptr_type_node. FILE type is not known - at the time we create the builtins. */ - else if (TREE_VALUE (t2) == fileptr_type_node) - { - tree t = TREE_VALUE (t1); - - if (TYPE_PTR_P (t) - && TYPE_IDENTIFIER (TREE_TYPE (t)) - == get_identifier ("FILE") - && compparms (TREE_CHAIN (t1), TREE_CHAIN (t2))) + { + if (!t1 || !t2) + break; + /* FILE, tm types are not known at the time + we create the builtins. */ + for (unsigned i = 0; + i < sizeof (builtin_structptr_types) + / sizeof (builtin_structptr_type); + ++i) + if (TREE_VALUE (t2) == builtin_structptr_types[i].node) { - tree oldargs = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); - - TYPE_ARG_TYPES (TREE_TYPE (olddecl)) - = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); - types_match = decls_match (newdecl, olddecl); - if (types_match) - return duplicate_decls (newdecl, olddecl, - newdecl_is_friend); - TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs; - } - } - /* Likewise for const struct tm*. */ - else if (TREE_VALUE (t2) == const_tm_ptr_type_node) - { - tree t = TREE_VALUE (t1); + tree t = TREE_VALUE (t1); - if (TYPE_PTR_P (t) - && TYPE_IDENTIFIER (TREE_TYPE (t)) - == get_identifier ("tm") - && compparms (TREE_CHAIN (t1), TREE_CHAIN (t2))) - { - tree oldargs = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); - - TYPE_ARG_TYPES (TREE_TYPE (olddecl)) - = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); - types_match = decls_match (newdecl, olddecl); - if (types_match) - return duplicate_decls (newdecl, olddecl, - newdecl_is_friend); - TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs; + if (TYPE_PTR_P (t) + && TYPE_IDENTIFIER (TREE_TYPE (t)) + == get_identifier (builtin_structptr_types[i].str) + && compparms (TREE_CHAIN (t1), TREE_CHAIN (t2))) + { + tree oldargs = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); + + TYPE_ARG_TYPES (TREE_TYPE (olddecl)) + = TYPE_ARG_TYPES (TREE_TYPE (newdecl)); + types_match = decls_match (newdecl, olddecl); + if (types_match) + return duplicate_decls (newdecl, olddecl, + newdecl_is_friend); + TYPE_ARG_TYPES (TREE_TYPE (olddecl)) = oldargs; + } + goto next_arg; } - } - else if (! same_type_p (TREE_VALUE (t1), TREE_VALUE (t2))) - break; + + if (! same_type_p (TREE_VALUE (t1), TREE_VALUE (t2))) + break; +next_arg:; + } warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wbuiltin_declaration_mismatch, @@ -1747,17 +1739,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) && (DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))) return olddecl; - /* [namespace.alias] - - A namespace-name or namespace-alias shall not be declared as - the name of any other entity in the same declarative region. - A namespace-name defined at global scope shall not be - declared as the name of any other entity in any global scope - of the program. */ - error ("conflicting declaration of namespace %q+D", newdecl); - inform (DECL_SOURCE_LOCATION (olddecl), - "previous declaration of namespace %qD here", olddecl); - return error_mark_node; + + /* Leave it to update_binding to merge or report error. */ + return NULL_TREE; } else { @@ -3952,63 +3936,56 @@ record_unknown_type (tree type, const char* name) SET_TYPE_MODE (type, TYPE_MODE (void_type_node)); } -/* A string for which we should create an IDENTIFIER_NODE at - startup. */ - -struct predefined_identifier -{ - /* The name of the identifier. */ - const char *const name; - /* The place where the IDENTIFIER_NODE should be stored. */ - tree *const node; - /* Nonzero if this is the name of a constructor or destructor. */ - const int ctor_or_dtor_p; -}; - /* Create all the predefined identifiers. */ static void initialize_predefined_identifiers (void) { - const predefined_identifier *pid; + struct predefined_identifier + { + const char *name; /* Name. */ + tree *node; /* Node to store it in. */ + cp_identifier_kind kind; /* Kind of identifier. */ + }; /* A table of identifiers to create at startup. */ static const predefined_identifier predefined_identifiers[] = { - { "C++", &lang_name_cplusplus, 0 }, - { "C", &lang_name_c, 0 }, + {"C++", &lang_name_cplusplus, cik_normal}, + {"C", &lang_name_c, cik_normal}, /* Some of these names have a trailing space so that it is impossible for them to conflict with names written by users. */ - { "__ct ", &ctor_identifier, 1 }, - { "__base_ctor ", &base_ctor_identifier, 1 }, - { "__comp_ctor ", &complete_ctor_identifier, 1 }, - { "__dt ", &dtor_identifier, 1 }, - { "__comp_dtor ", &complete_dtor_identifier, 1 }, - { "__base_dtor ", &base_dtor_identifier, 1 }, - { "__deleting_dtor ", &deleting_dtor_identifier, 1 }, - { IN_CHARGE_NAME, &in_charge_identifier, 0 }, - { "nelts", &nelts_identifier, 0 }, - { THIS_NAME, &this_identifier, 0 }, - { VTABLE_DELTA_NAME, &delta_identifier, 0 }, - { VTABLE_PFN_NAME, &pfn_identifier, 0 }, - { "_vptr", &vptr_identifier, 0 }, - { "__vtt_parm", &vtt_parm_identifier, 0 }, - { "::", &global_identifier, 0 }, - { "std", &std_identifier, 0 }, + {"__ct ", &ctor_identifier, cik_ctor}, + {"__base_ctor ", &base_ctor_identifier, cik_ctor}, + {"__comp_ctor ", &complete_ctor_identifier, cik_ctor}, + {"__dt ", &dtor_identifier, cik_dtor}, + {"__comp_dtor ", &complete_dtor_identifier, cik_dtor}, + {"__base_dtor ", &base_dtor_identifier, cik_dtor}, + {"__deleting_dtor ", &deleting_dtor_identifier, cik_dtor}, + {IN_CHARGE_NAME, &in_charge_identifier, cik_normal}, + {THIS_NAME, &this_identifier, cik_normal}, + {VTABLE_DELTA_NAME, &delta_identifier, cik_normal}, + {VTABLE_PFN_NAME, &pfn_identifier, cik_normal}, + {"_vptr", &vptr_identifier, cik_normal}, + {"__vtt_parm", &vtt_parm_identifier, cik_normal}, + {"::", &global_identifier, cik_normal}, + {"std", &std_identifier, cik_normal}, /* The demangler expects anonymous namespaces to be called something starting with '_GLOBAL__N_'. It no longer needs to be unique to the TU. */ - { "_GLOBAL__N_1", &anon_identifier, 0 }, - { "auto", &auto_identifier, 0 }, - { "decltype(auto)", &decltype_auto_identifier, 0 }, - { "initializer_list", &init_list_identifier, 0 }, - { NULL, NULL, 0 } + {"_GLOBAL__N_1", &anon_identifier, cik_normal}, + {"auto", &auto_identifier, cik_normal}, + {"decltype(auto)", &decltype_auto_identifier, cik_normal}, + {"initializer_list", &init_list_identifier, cik_normal}, + {NULL, NULL, cik_normal} }; - for (pid = predefined_identifiers; pid->name; ++pid) + for (const predefined_identifier *pid = predefined_identifiers; + pid->name; ++pid) { *pid->node = get_identifier (pid->name); - if (pid->ctor_or_dtor_p) - IDENTIFIER_CTOR_OR_DTOR_P (*pid->node) = 1; + /* Some of these identifiers already have a special kind. */ + if (pid->kind != cik_normal) + set_identifier_kind (*pid->node, pid->kind); } } @@ -4063,6 +4040,9 @@ cxx_init_decl_processing (void) /* Guess at the initial static decls size. */ vec_alloc (static_decls, 500); + /* ... and keyed classes. */ + vec_alloc (keyed_classes, 100); + record_builtin_type (RID_BOOL, "bool", boolean_type_node); truthvalue_type_node = boolean_type_node; truthvalue_false_node = boolean_false_node; @@ -4071,6 +4051,8 @@ cxx_init_decl_processing (void) empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE); noexcept_true_spec = build_tree_list (boolean_true_node, NULL_TREE); noexcept_false_spec = build_tree_list (boolean_false_node, NULL_TREE); + noexcept_deferred_spec = build_tree_list (make_node (DEFERRED_NOEXCEPT), + NULL_TREE); #if 0 record_builtin_type (RID_MAX, NULL, string_type_node); @@ -7814,10 +7796,7 @@ start_cleanup_fn (void) /* Build the parameter. */ if (use_cxa_atexit) { - tree parmdecl; - - parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node); - DECL_CONTEXT (parmdecl) = fndecl; + tree parmdecl = cp_build_parm_decl (fndecl, NULL_TREE, ptr_type_node); TREE_USED (parmdecl) = 1; DECL_READ_P (parmdecl) = 1; DECL_ARGUMENTS (fndecl) = parmdecl; @@ -8358,12 +8337,12 @@ check_class_member_definition_namespace (tree decl) decl, DECL_CONTEXT (decl)); } -/* Build a PARM_DECL for the "this" parameter. TYPE is the +/* Build a PARM_DECL for the "this" parameter of FN. TYPE is the METHOD_TYPE for a non-static member function; QUALS are the cv-qualifiers that apply to the function. */ tree -build_this_parm (tree type, cp_cv_quals quals) +build_this_parm (tree fn, tree type, cp_cv_quals quals) { tree this_type; tree qual_type; @@ -8382,7 +8361,7 @@ build_this_parm (tree type, cp_cv_quals quals) assigned to. */ this_quals = (quals & TYPE_QUAL_RESTRICT) | TYPE_QUAL_CONST; qual_type = cp_build_qualified_type (this_type, this_quals); - parm = build_artificial_parm (this_identifier, qual_type); + parm = build_artificial_parm (fn, this_identifier, qual_type); cp_apply_type_quals_to_decl (this_quals, parm); return parm; } @@ -8516,8 +8495,7 @@ grokfndecl (tree ctype, if (TREE_CODE (type) == METHOD_TYPE) { - tree parm; - parm = build_this_parm (type, quals); + tree parm = build_this_parm (decl, type, quals); DECL_CHAIN (parm) = parms; parms = parm; @@ -8725,7 +8703,7 @@ grokfndecl (tree ctype, error_at (location, "deduction guide %qD must not have a function body", decl); } - else if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)) + else if (IDENTIFIER_ANY_OP_P (DECL_NAME (decl)) && !grok_op_properties (decl, /*complain=*/true)) return NULL_TREE; else if (UDLIT_OPER_P (DECL_NAME (decl))) @@ -9524,8 +9502,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) stabilize_vla_size (itype); - if (flag_sanitize & SANITIZE_VLA - && do_ubsan_in_current_function ()) + if (sanitize_flags_p (SANITIZE_VLA)) { /* We have to add 1 -- in the ubsan routine we generate LE_EXPR rather than LT_EXPR. */ @@ -9778,7 +9755,7 @@ check_var_type (tree identifier, tree type) error ("unnamed variable or field declared void"); else if (identifier_p (identifier)) { - gcc_assert (!IDENTIFIER_OPNAME_P (identifier)); + gcc_assert (!IDENTIFIER_ANY_OP_P (identifier)); error ("variable or field %qE declared void", identifier); } else @@ -10119,12 +10096,7 @@ grokdeclarator (const cp_declarator *declarator, dname = fns; if (!identifier_p (dname)) - { - if (variable_template_p (dname)) - dname = DECL_NAME (dname); - else - dname = OVL_NAME (dname); - } + dname = OVL_NAME (dname); } /* Fall through. */ @@ -10132,13 +10104,13 @@ grokdeclarator (const cp_declarator *declarator, if (identifier_p (decl)) dname = decl; - if (C_IS_RESERVED_WORD (dname)) + if (IDENTIFIER_KEYWORD_P (dname)) { error ("declarator-id missing; using reserved word %qD", dname); name = identifier_to_locale (IDENTIFIER_POINTER (dname)); } - else if (!IDENTIFIER_TYPENAME_P (dname)) + else if (!IDENTIFIER_CONV_OP_P (dname)) name = identifier_to_locale (IDENTIFIER_POINTER (dname)); else { @@ -10197,26 +10169,27 @@ grokdeclarator (const cp_declarator *declarator, return error_mark_node; } - if (dname - && identifier_p (dname) - && UDLIT_OPER_P (dname) - && innermost_code != cdk_function) + if (dname && identifier_p (dname)) { - error ("declaration of %qD as non-function", dname); - return error_mark_node; - } - - if (dname && IDENTIFIER_OPNAME_P (dname)) - { - if (typedef_p) + if (UDLIT_OPER_P (dname) + && innermost_code != cdk_function) { - error ("declaration of %qD as %<typedef%>", dname); + error ("declaration of %qD as non-function", dname); return error_mark_node; } - else if (decl_context == PARM || decl_context == CATCHPARM) + + if (IDENTIFIER_ANY_OP_P (dname)) { - error ("declaration of %qD as parameter", dname); - return error_mark_node; + if (typedef_p) + { + error ("declaration of %qD as %<typedef%>", dname); + return error_mark_node; + } + else if (decl_context == PARM || decl_context == CATCHPARM) + { + error ("declaration of %qD as parameter", dname); + return error_mark_node; + } } } @@ -11617,7 +11590,8 @@ grokdeclarator (const cp_declarator *declarator, args && args != void_list_node; args = TREE_CHAIN (args)) { - tree decl = cp_build_parm_decl (NULL_TREE, TREE_VALUE (args)); + tree decl = cp_build_parm_decl (NULL_TREE, NULL_TREE, + TREE_VALUE (args)); DECL_CHAIN (decl) = decls; decls = decl; @@ -11712,22 +11686,20 @@ grokdeclarator (const cp_declarator *declarator, return error_mark_node; } - /* Only functions may be declared using an operator-function-id. */ - if (unqualified_id - && IDENTIFIER_OPNAME_P (unqualified_id) - && TREE_CODE (type) != FUNCTION_TYPE - && TREE_CODE (type) != METHOD_TYPE) + if (!FUNC_OR_METHOD_TYPE_P (type)) { - error ("declaration of %qD as non-function", unqualified_id); - return error_mark_node; - } + /* Only functions may be declared using an operator-function-id. */ + if (dname && IDENTIFIER_ANY_OP_P (dname)) + { + error ("declaration of %qD as non-function", dname); + return error_mark_node; + } - if (reqs - && TREE_CODE (type) != FUNCTION_TYPE - && TREE_CODE (type) != METHOD_TYPE) - error_at (location_of (reqs), - "requires-clause on declaration of non-function type %qT", - type); + if (reqs) + error_at (location_of (reqs), + "requires-clause on declaration of non-function type %qT", + type); + } /* We don't check parameter types here because we can emit a better error message later. */ @@ -11772,7 +11744,8 @@ grokdeclarator (const cp_declarator *declarator, } if (ctype && TREE_CODE (type) == FUNCTION_TYPE && staticp < 2 - && !NEW_DELETE_OPNAME_P (unqualified_id)) + && !(identifier_p (unqualified_id) + && IDENTIFIER_NEWDEL_OP_P (unqualified_id))) { cp_cv_quals real_quals = memfn_quals; if (cxx_dialect < cxx14 && constexpr_p @@ -11786,7 +11759,7 @@ grokdeclarator (const cp_declarator *declarator, if (decl_context == PARM) { - decl = cp_build_parm_decl (unqualified_id, type); + decl = cp_build_parm_decl (NULL_TREE, unqualified_id, type); DECL_ARRAY_PARAMETER_P (decl) = array_parameter_p; bad_specifiers (decl, BSP_PARM, virtualp, @@ -11883,15 +11856,13 @@ grokdeclarator (const cp_declarator *declarator, return error_mark_node; } - if (NEW_DELETE_OPNAME_P (unqualified_id)) + if (virtualp + && identifier_p (unqualified_id) + && IDENTIFIER_NEWDEL_OP_P (unqualified_id)) { - if (virtualp) - { - error ("%qD cannot be declared %<virtual%>, since it " - "is always static", - unqualified_id); - virtualp = 0; - } + error ("%qD cannot be declared %<virtual%>, since it " + "is always static", unqualified_id); + virtualp = 0; } } @@ -12153,6 +12124,7 @@ grokdeclarator (const cp_declarator *declarator, original_name = dname; else original_name = unqualified_id; + // FIXME:gcc_assert (original_name == dname); if (storage_class == sc_auto) error ("storage class %<auto%> invalid for function %qs", name); @@ -12947,27 +12919,24 @@ grok_op_properties (tree decl, bool complain) if (class_type && !CLASS_TYPE_P (class_type)) class_type = NULL_TREE; - if (DECL_CONV_FN_P (decl)) + if (IDENTIFIER_CONV_OP_P (name)) operator_code = TYPE_EXPR; else - do - { -#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \ - if (cp_operator_id (CODE) == name) \ - { \ - operator_code = (CODE); \ - break; \ - } \ - else if (cp_assignment_operator_id (CODE) == name) \ - { \ - operator_code = (CODE); \ - DECL_ASSIGNMENT_OPERATOR_P (decl) = 1; \ - break; \ - } - + { + /* It'd be nice to hang something else of the identifier to + find CODE more directly. */ + const operator_name_info_t *oni + = (IDENTIFIER_ASSIGN_OP_P (name) + ? assignment_operator_name_info : operator_name_info); + DECL_ASSIGNMENT_OPERATOR_P (decl) = IDENTIFIER_ASSIGN_OP_P (name); + if (false) + ; +#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, KIND) \ + else if (oni[int (CODE)].identifier == name) \ + operator_code = (CODE); #include "operators.def" #undef DEF_OPERATOR - + else gcc_unreachable (); } while (0); @@ -13086,7 +13055,7 @@ grok_op_properties (tree decl, bool complain) return true; /* Warn about conversion operators that will never be used. */ - if (IDENTIFIER_TYPENAME_P (name) + if (IDENTIFIER_CONV_OP_P (name) && ! DECL_TEMPLATE_INFO (decl) && warn_conversion /* Warn only declaring the function; there is no need to @@ -15108,7 +15077,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) if (!processing_template_decl && DECL_CONSTRUCTOR_P (decl1) - && (flag_sanitize & SANITIZE_VPTR) + && sanitize_flags_p (SANITIZE_VPTR) && !DECL_CLONED_FUNCTION_P (decl1) && !implicit_default_ctor_p (decl1)) cp_ubsan_maybe_initialize_vtbl_ptrs (current_class_ptr); @@ -15438,7 +15407,7 @@ record_key_method_defined (tree fndecl) { tree fnclass = DECL_CONTEXT (fndecl); if (fndecl == CLASSTYPE_KEY_METHOD (fnclass)) - keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes); + vec_safe_push (keyed_classes, fnclass); } } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index d3d90020c05..a4751460e06 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -192,14 +192,16 @@ change_return_type (tree new_ret, tree fntype) return newtype; } -/* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE +/* Build a PARM_DECL of FN with NAME and TYPE, and set DECL_ARG_TYPE appropriately. */ tree -cp_build_parm_decl (tree name, tree type) +cp_build_parm_decl (tree fn, tree name, tree type) { tree parm = build_decl (input_location, PARM_DECL, name, type); + DECL_CONTEXT (parm) = fn; + /* DECL_ARG_TYPE is only used by the back end and the back end never sees templates. */ if (!processing_template_decl) @@ -208,13 +210,13 @@ cp_build_parm_decl (tree name, tree type) return parm; } -/* Returns a PARM_DECL for a parameter of the indicated TYPE, with the +/* Returns a PARM_DECL of FN for a parameter of the indicated TYPE, with the indicated NAME. */ tree -build_artificial_parm (tree name, tree type) +build_artificial_parm (tree fn, tree name, tree type) { - tree parm = cp_build_parm_decl (name, type); + tree parm = cp_build_parm_decl (fn, name, type); DECL_ARTIFICIAL (parm) = 1; /* All our artificial parms are implicitly `const'; they cannot be assigned to. */ @@ -265,7 +267,7 @@ maybe_retrofit_in_chrg (tree fn) pass us a pointer to our VTT. */ if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn))) { - parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type); + parm = build_artificial_parm (fn, vtt_parm_identifier, vtt_parm_type); /* First add it to DECL_ARGUMENTS between 'this' and the real args... */ DECL_CHAIN (parm) = parms; @@ -278,7 +280,7 @@ maybe_retrofit_in_chrg (tree fn) } /* Then add the in-charge parm (before the VTT parm). */ - parm = build_artificial_parm (in_charge_identifier, integer_type_node); + parm = build_artificial_parm (fn, in_charge_identifier, integer_type_node); DECL_CHAIN (parm) = parms; parms = parm; arg_types = hash_tree_chain (integer_type_node, arg_types); @@ -1089,9 +1091,10 @@ is_late_template_attribute (tree attr, tree decl) if (is_attribute_p ("weak", name)) return true; - /* Attribute unused is applied directly, as it appertains to + /* Attributes used and unused are applied directly, as they appertain to decls. */ - if (is_attribute_p ("unused", name)) + if (is_attribute_p ("unused", name) + || is_attribute_p ("used", name)) return false; /* Attribute tls_model wants to modify the symtab. */ @@ -3502,12 +3505,10 @@ start_static_storage_duration_function (unsigned count) /* Create the argument list. */ initialize_p_decl = cp_build_parm_decl - (get_identifier (INITIALIZE_P_IDENTIFIER), integer_type_node); - DECL_CONTEXT (initialize_p_decl) = ssdf_decl; + (ssdf_decl, get_identifier (INITIALIZE_P_IDENTIFIER), integer_type_node); TREE_USED (initialize_p_decl) = 1; priority_decl = cp_build_parm_decl - (get_identifier (PRIORITY_IDENTIFIER), integer_type_node); - DECL_CONTEXT (priority_decl) = ssdf_decl; + (ssdf_decl, get_identifier (PRIORITY_IDENTIFIER), integer_type_node); TREE_USED (priority_decl) = 1; DECL_CHAIN (initialize_p_decl) = priority_decl; @@ -3737,7 +3738,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp) if (init) { finish_expr_stmt (init); - if (flag_sanitize & SANITIZE_ADDRESS) + if (sanitize_flags_p (SANITIZE_ADDRESS, decl)) { varpool_node *vnode = varpool_node::get (decl); if (vnode) @@ -4144,10 +4145,19 @@ decl_maybe_constant_var_p (tree decl) /* A proxy isn't constant. */ return false; if (TREE_CODE (type) == REFERENCE_TYPE) - /* References can be constant. */ + /* References can be constant. */; + else if (CP_TYPE_CONST_NON_VOLATILE_P (type) + && INTEGRAL_OR_ENUMERATION_TYPE_P (type)) + /* And const integers. */; + else + return false; + + if (DECL_INITIAL (decl) + && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)) + /* We know the initializer, and it isn't constant. */ + return false; + else return true; - return (CP_TYPE_CONST_NON_VOLATILE_P (type) - && INTEGRAL_OR_ENUMERATION_TYPE_P (type)); } /* Complain that DECL uses a type with no linkage. In C++98 mode this is @@ -4511,37 +4521,18 @@ c_parse_final_cleanups (void) instantiate_pending_templates (retries); ggc_collect (); - /* Write out virtual tables as required. Note that writing out - the virtual table for a template class may cause the + /* Write out virtual tables as required. Writing out the + virtual table for a template class may cause the instantiation of members of that class. If we write out vtables then we remove the class from our list so we don't have to look at it again. */ - - while (keyed_classes != NULL_TREE - && maybe_emit_vtables (TREE_VALUE (keyed_classes))) - { - reconsider = true; - keyed_classes = TREE_CHAIN (keyed_classes); - } - - t = keyed_classes; - if (t != NULL_TREE) - { - tree next = TREE_CHAIN (t); - - while (next) - { - if (maybe_emit_vtables (TREE_VALUE (next))) - { - reconsider = true; - TREE_CHAIN (t) = TREE_CHAIN (next); - } - else - t = next; - - next = TREE_CHAIN (t); - } - } + for (i = keyed_classes->length (); + keyed_classes->iterate (--i, &t);) + if (maybe_emit_vtables (t)) + { + reconsider = true; + keyed_classes->unordered_remove (i); + } /* Write out needed type info variables. We have to be careful looping through unemitted decls, because emit_tinfo_decl may @@ -4646,6 +4637,8 @@ c_parse_final_cleanups (void) if (!DECL_SAVED_TREE (decl)) continue; + cgraph_node *node = cgraph_node::get_create (decl); + /* We lie to the back end, pretending that some functions are not defined when they really are. This keeps these functions from being put out unnecessarily. But, we must @@ -4666,9 +4659,6 @@ c_parse_final_cleanups (void) && DECL_INITIAL (decl) && decl_needed_p (decl)) { - struct cgraph_node *node, *next; - - node = cgraph_node::get (decl); if (node->cpp_implicit_alias) node = node->get_alias_target (); @@ -4678,7 +4668,8 @@ c_parse_final_cleanups (void) group, we need to mark all symbols in the same comdat group that way. */ if (node->same_comdat_group) - for (next = dyn_cast<cgraph_node *> (node->same_comdat_group); + for (cgraph_node *next + = dyn_cast<cgraph_node *> (node->same_comdat_group); next != node; next = dyn_cast<cgraph_node *> (next->same_comdat_group)) next->call_for_symbol_thunks_and_aliases (clear_decl_external, @@ -4692,7 +4683,7 @@ c_parse_final_cleanups (void) if (!DECL_EXTERNAL (decl) && decl_needed_p (decl) && !TREE_ASM_WRITTEN (decl) - && !cgraph_node::get (decl)->definition) + && !node->definition) { /* We will output the function; no longer consider it in this loop. */ diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c index 080fa1a978d..6fafa5b792e 100644 --- a/gcc/cp/dump.c +++ b/gcc/cp/dump.c @@ -226,12 +226,12 @@ cp_dump_tree (void* dump_info, tree t) switch (code) { case IDENTIFIER_NODE: - if (IDENTIFIER_OPNAME_P (t)) + if (IDENTIFIER_ANY_OP_P (t)) { dump_string_field (di, "note", "operator"); return true; } - else if (IDENTIFIER_TYPENAME_P (t)) + else if (IDENTIFIER_CONV_OP_P (t)) { dump_child ("tynm", TREE_TYPE (t)); return true; diff --git a/gcc/cp/error.c b/gcc/cp/error.c index a2f35c1c410..94a38da8b17 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -1051,7 +1051,7 @@ dump_decl_name (cxx_pretty_printer *pp, tree t, int flags) { /* These special cases are duplicated here so that other functions can feed identifiers to error and get them demangled properly. */ - if (IDENTIFIER_TYPENAME_P (t)) + if (IDENTIFIER_CONV_OP_P (t)) { pp_cxx_ws_string (pp, "operator"); /* Not exactly IDENTIFIER_TYPE_VALUE. */ diff --git a/gcc/cp/except.c b/gcc/cp/except.c index ab7ab5db158..9e41ec451af 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1197,18 +1197,6 @@ build_noexcept_spec (tree expr, int complain) } } -/* Returns a noexcept-specifier to be evaluated later, for an - implicitly-declared or explicitly defaulted special member function. */ - -tree -unevaluated_noexcept_spec (void) -{ - if (!noexcept_deferred_spec) - noexcept_deferred_spec - = build_noexcept_spec (make_node (DEFERRED_NOEXCEPT), tf_none); - return noexcept_deferred_spec; -} - /* Returns a TRY_CATCH_EXPR that will put TRY_LIST and CATCH_LIST in the TRY and CATCH locations. CATCH_LIST must be a STATEMENT_LIST */ diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 4ad2cae541e..90abd23a267 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "c-family/c-ubsan.h" #include "intl.h" +#include "asan.h" static bool begin_init_stmts (tree *, tree *); static tree finish_init_stmts (bool, tree, tree); @@ -3911,8 +3912,7 @@ finish_length_check (tree atype, tree iterator, tree obase, unsigned n) } /* Don't check an array new when -fno-exceptions. */ } - else if (flag_sanitize & SANITIZE_BOUNDS - && do_ubsan_in_current_function ()) + else if (sanitize_flags_p (SANITIZE_BOUNDS)) { /* Make sure the last element of the initializer is in bounds. */ finish_expr_stmt diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 5587f6021ea..41d4921c1db 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -987,6 +987,8 @@ maybe_add_lambda_conv_op (tree type) null_pointer_node); if (generic_lambda_p) { + ++processing_template_decl; + /* Prepare the dependent member call for the static member function '_FUN' and, potentially, prepare another call to be used in a decltype return expression for a deduced return call op to allow for simple @@ -1036,9 +1038,7 @@ maybe_add_lambda_conv_op (tree type) if (generic_lambda_p) { - ++processing_template_decl; tree a = forward_parm (tgt); - --processing_template_decl; CALL_EXPR_ARG (call, ix) = a; if (decltype_call) @@ -1062,11 +1062,9 @@ maybe_add_lambda_conv_op (tree type) { if (decltype_call) { - ++processing_template_decl; fn_result = finish_decltype_type (decltype_call, /*id_expression_or_member_access_p=*/false, tf_warning_or_error); - --processing_template_decl; } } else @@ -1084,6 +1082,9 @@ maybe_add_lambda_conv_op (tree type) && TYPE_NOTHROW_P (TREE_TYPE (callop))) stattype = build_exception_variant (stattype, noexcept_true_spec); + if (generic_lambda_p) + --processing_template_decl; + /* First build up the conversion op. */ tree rettype = build_pointer_type (stattype); @@ -1102,7 +1103,8 @@ maybe_add_lambda_conv_op (tree type) DECL_ARTIFICIAL (fn) = 1; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; - DECL_ARGUMENTS (fn) = build_this_parm (fntype, TYPE_QUAL_CONST); + DECL_ARGUMENTS (fn) = build_this_parm (fn, fntype, TYPE_QUAL_CONST); + if (nested_def) DECL_INTERFACE_KNOWN (fn) = 1; @@ -1150,9 +1152,7 @@ maybe_add_lambda_conv_op (tree type) { /* Don't UBsan this function; we're deliberately calling op() with a null object argument. */ - tree attrs = build_tree_list (get_identifier ("no_sanitize_undefined"), - NULL_TREE); - cplus_decl_attributes (&fn, attrs, 0); + add_no_sanitize_value (fn, SANITIZE_UNDEFINED); } add_method (type, fn, false); diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index cf7c0d11ab3..2fa26739c80 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -89,6 +89,37 @@ operator_name_info_t assignment_operator_name_info[(int) MAX_TREE_CODES]; #include "operators.def" #undef DEF_OPERATOR +/* Get the name of the kind of identifier T. */ + +const char * +get_identifier_kind_name (tree id) +{ + /* Keep in sync with cp_id_kind enumeration. */ + static const char *const names[cik_max] = { + "normal", "keyword", "constructor", "destructor", + "assign-op", "op-assign-op", "simple-op", "conv-op", }; + + unsigned kind = 0; + kind |= IDENTIFIER_KIND_BIT_2 (id) << 2; + kind |= IDENTIFIER_KIND_BIT_1 (id) << 1; + kind |= IDENTIFIER_KIND_BIT_0 (id) << 0; + + return names[kind]; +} + +/* Set the identifier kind, which we expect to currently be zero. */ + +void +set_identifier_kind (tree id, cp_identifier_kind kind) +{ + gcc_checking_assert (!IDENTIFIER_KIND_BIT_2 (id) + & !IDENTIFIER_KIND_BIT_1 (id) + & !IDENTIFIER_KIND_BIT_0 (id)); + IDENTIFIER_KIND_BIT_2 (id) |= (kind >> 2) & 1; + IDENTIFIER_KIND_BIT_1 (id) |= (kind >> 1) & 1; + IDENTIFIER_KIND_BIT_0 (id) |= (kind >> 0) & 1; +} + static void init_operators (void) { @@ -96,22 +127,26 @@ init_operators (void) char buffer[256]; struct operator_name_info_t *oni; -#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \ - sprintf (buffer, ISALPHA (NAME[0]) ? "operator %s" : "operator%s", NAME); \ - identifier = get_identifier (buffer); \ - IDENTIFIER_OPNAME_P (identifier) = 1; \ - \ - oni = (ASSN_P \ - ? &assignment_operator_name_info[(int) CODE] \ - : &operator_name_info[(int) CODE]); \ - oni->identifier = identifier; \ - oni->name = NAME; \ - oni->mangled_name = MANGLING; \ +#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, KIND) \ + sprintf (buffer, "operator%s%s", !NAME[0] \ + || NAME[0] == '_' || ISALPHA (NAME[0]) ? " " : "", NAME); \ + identifier = get_identifier (buffer); \ + \ + if (KIND != cik_simple_op || !IDENTIFIER_ANY_OP_P (identifier)) \ + set_identifier_kind (identifier, KIND); \ + \ + oni = (KIND == cik_assign_op \ + ? &assignment_operator_name_info[(int) CODE] \ + : &operator_name_info[(int) CODE]); \ + oni->identifier = identifier; \ + oni->name = NAME; \ + oni->mangled_name = MANGLING; \ oni->arity = ARITY; #include "operators.def" #undef DEF_OPERATOR + operator_name_info[(int) TYPE_EXPR] = operator_name_info[(int) CAST_EXPR]; operator_name_info[(int) ERROR_MARK].identifier = get_identifier ("<invalid operator>"); @@ -123,6 +158,7 @@ init_operators (void) operator_name_info [(int) INIT_EXPR].name = operator_name_info [(int) MODIFY_EXPR].name; + operator_name_info [(int) EXACT_DIV_EXPR].name = "(ceiling /)"; operator_name_info [(int) CEIL_DIV_EXPR].name = "(ceiling /)"; operator_name_info [(int) FLOOR_DIV_EXPR].name = "(floor /)"; @@ -130,26 +166,20 @@ init_operators (void) operator_name_info [(int) CEIL_MOD_EXPR].name = "(ceiling %)"; operator_name_info [(int) FLOOR_MOD_EXPR].name = "(floor %)"; operator_name_info [(int) ROUND_MOD_EXPR].name = "(round %)"; + operator_name_info [(int) ABS_EXPR].name = "abs"; operator_name_info [(int) TRUTH_AND_EXPR].name = "strict &&"; operator_name_info [(int) TRUTH_OR_EXPR].name = "strict ||"; operator_name_info [(int) RANGE_EXPR].name = "..."; operator_name_info [(int) UNARY_PLUS_EXPR].name = "+"; - assignment_operator_name_info [(int) EXACT_DIV_EXPR].name - = "(exact /=)"; - assignment_operator_name_info [(int) CEIL_DIV_EXPR].name - = "(ceiling /=)"; - assignment_operator_name_info [(int) FLOOR_DIV_EXPR].name - = "(floor /=)"; - assignment_operator_name_info [(int) ROUND_DIV_EXPR].name - = "(round /=)"; - assignment_operator_name_info [(int) CEIL_MOD_EXPR].name - = "(ceiling %=)"; - assignment_operator_name_info [(int) FLOOR_MOD_EXPR].name - = "(floor %=)"; - assignment_operator_name_info [(int) ROUND_MOD_EXPR].name - = "(round %=)"; + assignment_operator_name_info [(int) EXACT_DIV_EXPR].name = "(exact /=)"; + assignment_operator_name_info [(int) CEIL_DIV_EXPR].name = "(ceiling /=)"; + assignment_operator_name_info [(int) FLOOR_DIV_EXPR].name = "(floor /=)"; + assignment_operator_name_info [(int) ROUND_DIV_EXPR].name = "(round /=)"; + assignment_operator_name_info [(int) CEIL_MOD_EXPR].name = "(ceiling %=)"; + assignment_operator_name_info [(int) FLOOR_MOD_EXPR].name = "(floor %=)"; + assignment_operator_name_info [(int) ROUND_MOD_EXPR].name = "(round %=)"; } /* Initialize the reserved words. */ @@ -184,7 +214,7 @@ init_reswords (void) C_SET_RID_CODE (id, c_common_reswords[i].rid); ridpointers [(int) c_common_reswords[i].rid] = id; if (! (c_common_reswords[i].disable & mask)) - C_IS_RESERVED_WORD (id) = 1; + set_identifier_kind (id, cik_keyword); } for (i = 0; i < NUM_INT_N_ENTS; i++) @@ -193,7 +223,7 @@ init_reswords (void) sprintf (name, "__int%d", int_n_data[i].bitsize); id = get_identifier (name); C_SET_RID_CODE (id, RID_FIRST_INT_N + i); - C_IS_RESERVED_WORD (id) = 1; + set_identifier_kind (id, cik_keyword); } } @@ -431,7 +461,7 @@ unqualified_name_lookup_error (tree name, location_t loc) if (loc == UNKNOWN_LOCATION) loc = EXPR_LOC_OR_LOC (name, input_location); - if (IDENTIFIER_OPNAME_P (name)) + if (IDENTIFIER_ANY_OP_P (name)) { if (name != cp_operator_id (ERROR_MARK)) error_at (loc, "%qD not defined", name); diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index e866675bed9..e23591315c9 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1261,9 +1261,9 @@ write_template_prefix (const tree node) static void write_unqualified_id (tree identifier) { - if (IDENTIFIER_TYPENAME_P (identifier)) + if (IDENTIFIER_CONV_OP_P (identifier)) write_conversion_operator_name (TREE_TYPE (identifier)); - else if (IDENTIFIER_OPNAME_P (identifier)) + else if (IDENTIFIER_ANY_OP_P (identifier)) { int i; const char *mangled_name = NULL; @@ -2100,6 +2100,11 @@ write_type (tree type) || TREE_CODE (t) == METHOD_TYPE) { t = build_ref_qualified_type (t, type_memfn_rqual (type)); + if (flag_noexcept_type) + { + tree r = TYPE_RAISES_EXCEPTIONS (type); + t = build_exception_variant (t, r); + } if (abi_version_at_least (8) || type == TYPE_MAIN_VARIANT (type)) /* Avoid adding the unqualified function type as a substitution. */ @@ -2820,14 +2825,16 @@ write_template_args (tree args) static void write_member_name (tree member) { - if (abi_version_at_least (11) && IDENTIFIER_OPNAME_P (member)) + if (identifier_p (member)) { - write_string ("on"); - if (abi_warn_or_compat_version_crosses (11)) - G.need_abi_warning = 1; + if (abi_version_at_least (11) && IDENTIFIER_ANY_OP_P (member)) + { + write_string ("on"); + if (abi_warn_or_compat_version_crosses (11)) + G.need_abi_warning = 1; + } + write_unqualified_id (member); } - if (identifier_p (member)) - write_unqualified_id (member); else if (DECL_P (member)) write_unqualified_name (member); else if (TREE_CODE (member) == TEMPLATE_ID_EXPR) @@ -3045,7 +3052,7 @@ write_expression (tree expr) /* An operator name appearing as a dependent name needs to be specially marked to disambiguate between a use of the operator name and a use of the operator in an expression. */ - if (IDENTIFIER_OPNAME_P (expr)) + if (IDENTIFIER_ANY_OP_P (expr)) write_string ("on"); write_unqualified_id (expr); } @@ -3053,7 +3060,7 @@ write_expression (tree expr) { tree fn = TREE_OPERAND (expr, 0); fn = OVL_NAME (fn); - if (IDENTIFIER_OPNAME_P (fn)) + if (IDENTIFIER_ANY_OP_P (fn)) write_string ("on"); write_unqualified_id (fn); write_template_args (TREE_OPERAND (expr, 1)); @@ -4236,9 +4243,8 @@ mangle_conv_op_name_for_type (const tree type) when performing conversions. */ TREE_TYPE (identifier) = type; - /* Set bits on the identifier so we know later it's a conversion. */ - IDENTIFIER_OPNAME_P (identifier) = 1; - IDENTIFIER_TYPENAME_P (identifier) = 1; + /* Set the identifier kind so we know later it's a conversion. */ + set_identifier_kind (identifier, cik_conv_op); } return identifier; diff --git a/gcc/cp/method.c b/gcc/cp/method.c index aa607d53346..fe4b2afe7db 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -486,6 +486,7 @@ forward_parm (tree parm) type = PACK_EXPANSION_PATTERN (type); if (TREE_CODE (type) != REFERENCE_TYPE) type = cp_build_reference_type (type, /*rval=*/true); + warning_sentinel w (warn_useless_cast); exp = build_static_cast (type, exp, tf_warning_or_error); if (DECL_PACK_P (parm)) exp = make_pack_expansion (exp); @@ -2023,7 +2024,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, } else if (cxx_dialect >= cxx11) { - raises = unevaluated_noexcept_spec (); + raises = noexcept_deferred_spec; synthesized_method_walk (type, kind, const_p, NULL, &trivial_p, &deleted_p, &constexpr_p, false, inherited_ctor, inherited_parms); @@ -2072,7 +2073,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we want its type to be included in the mangled function name. */ - tree decl = cp_build_parm_decl (NULL_TREE, rhs_parm_type); + tree decl = cp_build_parm_decl (fn, NULL_TREE, rhs_parm_type); TREE_READONLY (decl) = 1; retrofit_lang_decl (decl); DECL_PARM_INDEX (decl) = DECL_PARM_LEVEL (decl) = 1; @@ -2085,11 +2086,10 @@ implicitly_declare_fn (special_function_kind kind, tree type, for (tree parm = inherited_parms; parm && parm != void_list_node; parm = TREE_CHAIN (parm)) { - *p = cp_build_parm_decl (NULL_TREE, TREE_VALUE (parm)); + *p = cp_build_parm_decl (fn, NULL_TREE, TREE_VALUE (parm)); retrofit_lang_decl (*p); DECL_PARM_LEVEL (*p) = 1; DECL_PARM_INDEX (*p) = index++; - DECL_CONTEXT (*p) = fn; p = &DECL_CHAIN (*p); } SET_DECL_INHERITED_CTOR (fn, inherited_ctor); @@ -2103,7 +2103,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, constexpr_p = DECL_DECLARED_CONSTEXPR_P (inherited_ctor); } /* Add the "this" parameter. */ - this_parm = build_this_parm (fn_type, TYPE_UNQUALIFIED); + this_parm = build_this_parm (fn, fn_type, TYPE_UNQUALIFIED); DECL_CHAIN (this_parm) = DECL_ARGUMENTS (fn); DECL_ARGUMENTS (fn) = this_parm; diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 6ed164d4645..0df546a2e6a 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -450,7 +450,13 @@ name_lookup::add_value (tree new_val) else if ((TREE_CODE (value) == TYPE_DECL && TREE_CODE (new_val) == TYPE_DECL && same_type_p (TREE_TYPE (value), TREE_TYPE (new_val)))) - ; + /* Typedefs to the same type. */; + else if (TREE_CODE (value) == NAMESPACE_DECL + && TREE_CODE (new_val) == NAMESPACE_DECL + && ORIGINAL_NAMESPACE (value) == ORIGINAL_NAMESPACE (new_val)) + /* Namespace (possibly aliased) to the same namespace. Locate + the namespace*/ + value = ORIGINAL_NAMESPACE (value); else { if (deduping) @@ -1630,10 +1636,10 @@ static void diagnose_name_conflict (tree decl, tree bval) { if (TREE_CODE (decl) == TREE_CODE (bval) - && (TREE_CODE (decl) != TYPE_DECL - || (DECL_ARTIFICIAL (decl) && DECL_ARTIFICIAL (bval)) - || (!DECL_ARTIFICIAL (decl) && !DECL_ARTIFICIAL (bval))) + && TREE_CODE (decl) != NAMESPACE_DECL && !DECL_DECLARES_FUNCTION_P (decl) + && (TREE_CODE (decl) != TYPE_DECL + || DECL_ARTIFICIAL (decl) == DECL_ARTIFICIAL (bval)) && CP_DECL_CONTEXT (decl) == CP_DECL_CONTEXT (bval)) error ("redeclaration of %q#D", decl); else @@ -1784,6 +1790,14 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, else goto conflict; + if (to_type != old_type + && warn_shadow + && MAYBE_CLASS_TYPE_P (TREE_TYPE (to_type)) + && !(DECL_IN_SYSTEM_HEADER (decl) + && DECL_IN_SYSTEM_HEADER (to_type))) + warning (OPT_Wshadow, "%q#D hides constructor for %q#D", + decl, to_type); + to_val = ovl_insert (decl, old); } else if (!old) @@ -1801,15 +1815,14 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, } else if (TREE_CODE (old) == NAMESPACE_DECL) { - if (DECL_NAMESPACE_ALIAS (old) && DECL_NAMESPACE_ALIAS (decl) - && ORIGINAL_NAMESPACE (old) == ORIGINAL_NAMESPACE (decl)) - /* In a declarative region, a namespace-alias-definition can be - used to redefine a namespace-alias declared in that declarative - region to refer only to the namespace to which it already - refers. [namespace.alias] */ - return old; - else + /* Two maybe-aliased namespaces. If they're to the same target + namespace, that's ok. */ + if (ORIGINAL_NAMESPACE (old) != ORIGINAL_NAMESPACE (decl)) goto conflict; + + /* The new one must be an alias at this point. */ + gcc_assert (DECL_NAMESPACE_ALIAS (decl)); + return old; } else if (TREE_CODE (old) == VAR_DECL) { @@ -1849,21 +1862,6 @@ update_binding (cp_binding_level *level, cxx_binding *binding, tree *slot, add_decl_to_level (level, to_add); } - if (to_type != old_type) - { - gcc_checking_assert (!old_type - && TREE_CODE (to_type) == TYPE_DECL - && DECL_ARTIFICIAL (to_type)); - - tree type = TREE_TYPE (to_type); - if (to_type != decl - && MAYBE_CLASS_TYPE_P (type) && warn_shadow - && (!DECL_IN_SYSTEM_HEADER (decl) - || !DECL_IN_SYSTEM_HEADER (to_type))) - warning (OPT_Wshadow, "%q#D hides constructor for %q#T", - decl, type); - } - if (slot) { if (STAT_HACK_P (*slot)) @@ -4163,7 +4161,7 @@ do_class_using_decl (tree scope, tree name) scope_dependent_p = dependent_scope_p (scope); name_dependent_p = (scope_dependent_p - || (IDENTIFIER_TYPENAME_P (name) + || (IDENTIFIER_CONV_OP_P (name) && dependent_type_p (TREE_TYPE (name)))); bases_dependent_p = any_dependent_bases_p (); @@ -4273,8 +4271,6 @@ set_global_binding (tree name, tree val) void set_decl_namespace (tree decl, tree scope, bool friendp) { - tree old; - /* Get rid of namespace aliases. */ scope = ORIGINAL_NAMESPACE (scope); @@ -4284,41 +4280,49 @@ set_decl_namespace (tree decl, tree scope, bool friendp) decl, scope); DECL_CONTEXT (decl) = FROB_CONTEXT (scope); - /* Writing "int N::i" to declare a variable within "N" is invalid. */ - if (scope == current_namespace) - { - if (at_namespace_scope_p ()) - error ("explicit qualification in declaration of %qD", - decl); - return; - } + /* See whether this has been declared in the namespace or inline + children. */ + tree old = NULL_TREE; + { + name_lookup lookup (DECL_NAME (decl), LOOKUP_HIDDEN); + if (!lookup.search_qualified (scope, /*usings=*/false)) + /* No old declaration at all. */ + goto not_found; + old = lookup.value; + } - /* See whether this has been declared in the namespace. */ - old = lookup_qualified_name (scope, DECL_NAME (decl), /*type*/false, - /*complain*/true, /*hidden*/true); - if (old == error_mark_node) - /* No old declaration at all. */ - goto complain; /* If it's a TREE_LIST, the result of the lookup was ambiguous. */ if (TREE_CODE (old) == TREE_LIST) { + ambiguous: + DECL_CONTEXT (decl) = FROB_CONTEXT (scope); error ("reference to %qD is ambiguous", decl); print_candidates (old); return; } - if (!OVL_P (decl)) + + if (!DECL_DECLARES_FUNCTION_P (decl)) { - /* We might have found OLD in an inline namespace inside SCOPE. */ - if (TREE_CODE (decl) == TREE_CODE (old)) - DECL_CONTEXT (decl) = DECL_CONTEXT (old); /* Don't compare non-function decls with decls_match here, since it can't check for the correct constness at this - point. pushdecl will find those errors later. */ + point. pushdecl will find those errors later. */ + + /* We might have found it in an inline namespace child of SCOPE. */ + if (TREE_CODE (decl) == TREE_CODE (old)) + DECL_CONTEXT (decl) = DECL_CONTEXT (old); + + found: + /* Writing "N::i" to declare something directly in "N" is invalid. */ + if (CP_DECL_CONTEXT (decl) == current_namespace + && at_namespace_scope_p ()) + error ("explicit qualification in declaration of %qD", decl); return; } + /* Since decl is a function, old should contain a function decl. */ if (!OVL_P (old)) - goto complain; + goto not_found; + /* We handle these in check_explicit_instantiation_namespace. */ if (processing_explicit_instantiation) return; @@ -4332,53 +4336,48 @@ set_decl_namespace (tree decl, tree scope, bool friendp) friends in any namespace. */ if (friendp && DECL_USE_TEMPLATE (decl)) return; - if (OVL_P (old)) + + tree found; + found = NULL_TREE; + + for (lkp_iterator iter (old); iter; ++iter) { - tree found = NULL_TREE; + if (iter.using_p ()) + continue; - for (ovl_iterator iter (old); iter; ++iter) - { - tree ofn = *iter; - /* Adjust DECL_CONTEXT first so decls_match will return true - if DECL will match a declaration in an inline namespace. */ - DECL_CONTEXT (decl) = DECL_CONTEXT (ofn); - if (decls_match (decl, ofn)) - { - if (found && !decls_match (found, ofn)) - { - DECL_CONTEXT (decl) = FROB_CONTEXT (scope); - error ("reference to %qD is ambiguous", decl); - print_candidates (old); - return; - } - found = ofn; - } - } - if (found) + tree ofn = *iter; + + /* Adjust DECL_CONTEXT first so decls_match will return true + if DECL will match a declaration in an inline namespace. */ + DECL_CONTEXT (decl) = DECL_CONTEXT (ofn); + if (decls_match (decl, ofn)) { - if (!is_nested_namespace (scope, CP_DECL_CONTEXT (found), true)) - goto complain; - if (DECL_HIDDEN_FRIEND_P (found)) + if (found) { - pedwarn (DECL_SOURCE_LOCATION (decl), 0, - "%qD has not been declared within %qD", decl, scope); - inform (DECL_SOURCE_LOCATION (found), - "only here as a %<friend%>"); + /* We found more than one matching declaration. */ + DECL_CONTEXT (decl) = FROB_CONTEXT (scope); + goto ambiguous; } - DECL_CONTEXT (decl) = DECL_CONTEXT (found); - return; + found = ofn; } } - else + + if (found) { - DECL_CONTEXT (decl) = DECL_CONTEXT (old); - if (decls_match (decl, old)) - return; + if (DECL_HIDDEN_FRIEND_P (found)) + { + pedwarn (DECL_SOURCE_LOCATION (decl), 0, + "%qD has not been declared within %qD", decl, scope); + inform (DECL_SOURCE_LOCATION (found), + "only here as a %<friend%>"); + } + DECL_CONTEXT (decl) = DECL_CONTEXT (found); + goto found; } + not_found: /* It didn't work, go back to the explicit scope. */ DECL_CONTEXT (decl) = FROB_CONTEXT (scope); - complain: error ("%qD should have been declared inside %qD", decl, scope); } @@ -5067,7 +5066,7 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind) /* Only consider reserved words that survived the filtering in init_reswords (e.g. for -std). */ - if (!C_IS_RESERVED_WORD (resword_identifier)) + if (!IDENTIFIER_KEYWORD_P (resword_identifier)) continue; bm.consider (IDENTIFIER_POINTER (resword_identifier)); @@ -5229,7 +5228,7 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p, /* Conversion operators are handled specially because ordinary unqualified name lookup will not find template conversion operators. */ - if (IDENTIFIER_TYPENAME_P (name)) + if (IDENTIFIER_CONV_OP_P (name)) { cp_binding_level *level; diff --git a/gcc/cp/operators.def b/gcc/cp/operators.def index d26f2a1a15a..7dfdd227241 100644 --- a/gcc/cp/operators.def +++ b/gcc/cp/operators.def @@ -67,20 +67,20 @@ along with GCC; see the file COPYING3. If not see an ASSIGNMENT_P argument; it is always zero. */ #define DEF_SIMPLE_OPERATOR(NAME, CODE, MANGLING, ARITY) \ - DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, 0) + DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, cik_simple_op) /* Use DEF_ASSN_OPERATOR to define an assignment operator. Its arguments are as for DEF_OPERATOR, but there is no need to provide an ASSIGNMENT_P argument; it is always one. */ #define DEF_ASSN_OPERATOR(NAME, CODE, MANGLING, ARITY) \ - DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, 1) + DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, cik_assign_op) /* Memory allocation operators. */ -DEF_SIMPLE_OPERATOR ("new", NEW_EXPR, "nw", -1) -DEF_SIMPLE_OPERATOR ("new []", VEC_NEW_EXPR, "na", -1) -DEF_SIMPLE_OPERATOR ("delete", DELETE_EXPR, "dl", -1) -DEF_SIMPLE_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", -1) +DEF_OPERATOR ("new", NEW_EXPR, "nw", -1, cik_newdel_op) +DEF_OPERATOR ("new []", VEC_NEW_EXPR, "na", -1, cik_newdel_op) +DEF_OPERATOR ("delete", DELETE_EXPR, "dl", -1, cik_newdel_op) +DEF_OPERATOR ("delete []", VEC_DELETE_EXPR, "da", -1, cik_newdel_op) /* Unary operators. */ DEF_SIMPLE_OPERATOR ("+", UNARY_PLUS_EXPR, "ps", 1) @@ -97,8 +97,7 @@ DEF_SIMPLE_OPERATOR ("alignof", ALIGNOF_EXPR, "az", 1) DEF_SIMPLE_OPERATOR ("__imag__", IMAGPART_EXPR, "v18__imag__", 1) DEF_SIMPLE_OPERATOR ("__real__", REALPART_EXPR, "v18__real__", 1) -/* The cast operator. */ -DEF_SIMPLE_OPERATOR ("", TYPE_EXPR, "cv", 1) +/* The cast operators. */ DEF_SIMPLE_OPERATOR ("", CAST_EXPR, "cv", 1) DEF_SIMPLE_OPERATOR ("dynamic_cast", DYNAMIC_CAST_EXPR, "dc", 1) DEF_SIMPLE_OPERATOR ("reinterpret_cast", REINTERPRET_CAST_EXPR, "rc", 1) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index d02ad360d16..634047e5d05 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -806,7 +806,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token) /* Check to see if this token is a keyword. */ if (token->type == CPP_NAME) { - if (C_IS_RESERVED_WORD (token->u.value)) + if (IDENTIFIER_KEYWORD_P (token->u.value)) { /* Mark this token as a keyword. */ token->type = CPP_KEYWORD; @@ -2983,7 +2983,9 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser, if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) { - if (TYPE_P (type)) + if (TREE_CODE (type) == TYPE_DECL) + type = TREE_TYPE (type); + if (TYPE_P (type) && !template_placeholder_p (type)) error_at (location, "%qT is not a template", type); else if (identifier_p (type)) { @@ -3270,9 +3272,21 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, } else if (TYPE_P (parser->scope) && dependent_scope_p (parser->scope)) - error_at (location, "need %<typename%> before %<%T::%E%> because " - "%qT is a dependent scope", - parser->scope, id, parser->scope); + { + if (TREE_CODE (parser->scope) == TYPENAME_TYPE) + error_at (location, + "need %<typename%> before %<%T::%D::%E%> because " + "%<%T::%D%> is a dependent scope", + TYPE_CONTEXT (parser->scope), + TYPENAME_TYPE_FULLNAME (parser->scope), + id, + TYPE_CONTEXT (parser->scope), + TYPENAME_TYPE_FULLNAME (parser->scope)); + else + error_at (location, "need %<typename%> before %<%T::%E%> because " + "%qT is a dependent scope", + parser->scope, id, parser->scope); + } else if (TYPE_P (parser->scope)) { if (!COMPLETE_TYPE_P (parser->scope)) @@ -8636,6 +8650,85 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser) } } +/* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR, trying them + in the order: const_cast, static_cast, reinterpret_cast. + + Don't suggest dynamic_cast. + + Return the first legal cast kind found, or NULL otherwise. */ + +static const char * +get_cast_suggestion (tree dst_type, tree orig_expr) +{ + tree trial; + + /* Reuse the parser logic by attempting to build the various kinds of + cast, with "complain" disabled. + Identify the first such cast that is valid. */ + + /* Don't attempt to run such logic within template processing. */ + if (processing_template_decl) + return NULL; + + /* First try const_cast. */ + trial = build_const_cast (dst_type, orig_expr, tf_none); + if (trial != error_mark_node) + return "const_cast"; + + /* If that fails, try static_cast. */ + trial = build_static_cast (dst_type, orig_expr, tf_none); + if (trial != error_mark_node) + return "static_cast"; + + /* Finally, try reinterpret_cast. */ + trial = build_reinterpret_cast (dst_type, orig_expr, tf_none); + if (trial != error_mark_node) + return "reinterpret_cast"; + + /* No such cast possible. */ + return NULL; +} + +/* If -Wold-style-cast is enabled, add fix-its to RICHLOC, + suggesting how to convert a C-style cast of the form: + + (DST_TYPE)ORIG_EXPR + + to a C++-style cast. + + The primary range of RICHLOC is asssumed to be that of the original + expression. OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the locations + of the parens in the C-style cast. */ + +static void +maybe_add_cast_fixit (rich_location *rich_loc, location_t open_paren_loc, + location_t close_paren_loc, tree orig_expr, + tree dst_type) +{ + /* This function is non-trivial, so bail out now if the warning isn't + going to be emitted. */ + if (!warn_old_style_cast) + return; + + /* Try to find a legal C++ cast, trying them in order: + const_cast, static_cast, reinterpret_cast. */ + const char *cast_suggestion = get_cast_suggestion (dst_type, orig_expr); + if (!cast_suggestion) + return; + + /* Replace the open paren with "CAST_SUGGESTION<". */ + pretty_printer pp; + pp_printf (&pp, "%s<", cast_suggestion); + rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text (&pp)); + + /* Replace the close paren with "> (". */ + rich_loc->add_fixit_replace (close_paren_loc, "> ("); + + /* Add a closing paren after the expr (the primary range of RICH_LOC). */ + rich_loc->add_fixit_insert_after (")"); +} + + /* Parse a cast-expression. cast-expression: @@ -8671,6 +8764,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, /* Consume the `('. */ cp_token *open_paren = cp_lexer_consume_token (parser->lexer); location_t open_paren_loc = open_paren->location; + location_t close_paren_loc = UNKNOWN_LOCATION; /* A very tricky bit is that `(struct S) { 3 }' is a compound-literal (which we permit in C++ as an extension). @@ -8733,7 +8827,10 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, /* Look for the type-id. */ type = cp_parser_type_id (parser); /* Look for the closing `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + cp_token *close_paren + = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + if (close_paren) + close_paren_loc = close_paren->location; parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; } @@ -8763,8 +8860,13 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, && !in_system_header_at (input_location) && !VOID_TYPE_P (type) && current_lang_name != lang_name_c) - warning (OPT_Wold_style_cast, - "use of old-style cast to %qT", type); + { + gcc_rich_location rich_loc (input_location); + maybe_add_cast_fixit (&rich_loc, open_paren_loc, close_paren_loc, + expr, type); + warning_at_rich_loc (&rich_loc, OPT_Wold_style_cast, + "use of old-style cast to %qT", type); + } /* Only type conversions to integral or enumeration types can be used in constant-expressions. */ @@ -16972,7 +17074,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, /* There is no valid C++ program where a non-template type is followed by a "<". That usually indicates that the user thought that the type was a template. */ - cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type), + cp_parser_check_for_invalid_template_id (parser, type, none_type, token->location); } @@ -20001,7 +20103,8 @@ cp_parser_direct_declarator (cp_parser* parser, { if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR) sfk = sfk_destructor; - else if (IDENTIFIER_TYPENAME_P (unqualified_name)) + else if (identifier_p (unqualified_name) + && IDENTIFIER_CONV_OP_P (unqualified_name)) sfk = sfk_conversion; else if (/* There's no way to declare a constructor for an unnamed type, even if the type @@ -20451,7 +20554,7 @@ inject_this_parameter (tree ctype, cp_cv_quals quals) return; } - this_parm = build_this_parm (ctype, quals); + this_parm = build_this_parm (NULL_TREE, ctype, quals); /* Clear this first to avoid shortcut in cp_build_indirect_ref. */ current_class_ptr = NULL_TREE; current_class_ref diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8a61b74a149..392fba07714 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5333,11 +5333,11 @@ push_template_decl_real (tree decl, bool is_friend) error ("destructor %qD declared as member template", decl); return error_mark_node; } - if (NEW_DELETE_OPNAME_P (DECL_NAME (decl)) + if (IDENTIFIER_NEWDEL_OP_P (DECL_NAME (decl)) && (!prototype_p (TREE_TYPE (decl)) || TYPE_ARG_TYPES (TREE_TYPE (decl)) == void_list_node || !TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))) - || (TREE_CHAIN (TYPE_ARG_TYPES ((TREE_TYPE (decl)))) + || (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))) == void_list_node))) { /* [basic.stc.dynamic.allocation] @@ -6585,10 +6585,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) if (complain & tf_error) { int errs = errorcount, warns = warningcount + werrorcount; - if (processing_template_decl - && !require_potential_constant_expression (expr)) - return NULL_TREE; - expr = cxx_constant_value (expr); + if (!require_potential_constant_expression (expr)) + expr = error_mark_node; + else + expr = cxx_constant_value (expr); if (errorcount > errs || warningcount + werrorcount > warns) inform (loc, "in template argument for type %qT ", type); if (expr == error_mark_node) @@ -8101,10 +8101,10 @@ coerce_template_parms (tree parms, parm = TREE_VEC_ELT (parms, parm_idx); if (parm == error_mark_node) - { - TREE_VEC_ELT (new_inner_args, arg_idx) = error_mark_node; - continue; - } + { + TREE_VEC_ELT (new_inner_args, arg_idx) = error_mark_node; + continue; + } /* Calculate the next argument. */ if (arg_idx < nargs) @@ -10864,9 +10864,9 @@ instantiate_class_template_1 (tree type) /* The vtable for a template class can be emitted in any translation unit in which the class is instantiated. When there is no key method, however, finish_struct_1 will already have added TYPE to - the keyed_classes list. */ + the keyed_classes. */ if (TYPE_CONTAINS_VPTR_P (type) && CLASSTYPE_KEY_METHOD (type)) - keyed_classes = tree_cons (NULL_TREE, type, keyed_classes); + vec_safe_push (keyed_classes, type); return type; } @@ -12416,7 +12416,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) /* If we aren't complaining now, return on error before we register the specialization so that we'll complain eventually. */ if ((complain & tf_error) == 0 - && IDENTIFIER_OPNAME_P (DECL_NAME (r)) + && IDENTIFIER_ANY_OP_P (DECL_NAME (r)) && !grok_op_properties (r, /*complain=*/false)) RETURN (error_mark_node); @@ -12487,7 +12487,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) clone_function_decl (r, /*update_methods=*/false); } else if ((complain & tf_error) != 0 - && IDENTIFIER_OPNAME_P (DECL_NAME (r)) + && IDENTIFIER_ANY_OP_P (DECL_NAME (r)) && !grok_op_properties (r, /*complain=*/true)) RETURN (error_mark_node); @@ -12947,13 +12947,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) /* The initializer must not be expanded until it is required; see [temp.inst]. */ DECL_INITIAL (r) = NULL_TREE; - if (VAR_P (r)) - SET_DECL_MODE (r, VOIDmode); - if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL)) - SET_DECL_RTL (r, NULL); DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0; if (VAR_P (r)) { + SET_DECL_MODE (r, VOIDmode); + /* Possibly limit visibility based on template args. */ DECL_VISIBILITY (r) = VISIBILITY_DEFAULT; if (DECL_VISIBILITY_SPECIFIED (t)) @@ -14215,93 +14213,89 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) } } -/* Like tsubst_expr for a BASELINK. OBJECT_TYPE, if non-NULL, is the - type of the expression on the left-hand side of the "." or "->" - operator. */ +/* tsubst a BASELINK. OBJECT_TYPE, if non-NULL, is the type of the + expression on the left-hand side of the "." or "->" operator. A + baselink indicates a function from a base class. Both the + BASELINK_ACCESS_BINFO and the base class referenced may indicate + bases of the template class, rather than the instantiated class. + In addition, lookups that were not ambiguous before may be + ambiguous now. Therefore, we perform the lookup again. */ static tree tsubst_baselink (tree baselink, tree object_type, tree args, tsubst_flags_t complain, tree in_decl) { - tree name; - tree qualifying_scope; - tree fns; - tree optype; - tree template_args = 0; - bool template_id_p = false; - bool qualified = BASELINK_QUALIFIED_P (baselink); - - /* A baselink indicates a function from a base class. Both the - BASELINK_ACCESS_BINFO and the base class referenced may - indicate bases of the template class, rather than the - instantiated class. In addition, lookups that were not - ambiguous before may be ambiguous now. Therefore, we perform - the lookup again. */ - qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink)); - qualifying_scope = tsubst (qualifying_scope, args, - complain, in_decl); - fns = BASELINK_FUNCTIONS (baselink); - optype = tsubst (BASELINK_OPTYPE (baselink), args, complain, in_decl); - if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) - { - template_id_p = true; - template_args = TREE_OPERAND (fns, 1); - fns = TREE_OPERAND (fns, 0); - if (template_args) - template_args = tsubst_template_args (template_args, args, - complain, in_decl); - } - name = OVL_NAME (fns); - if (IDENTIFIER_TYPENAME_P (name)) - name = mangle_conv_op_name_for_type (optype); - baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1); - if (!baselink) - { - if (constructor_name_p (name, qualifying_scope)) - { - if (complain & tf_error) - error ("cannot call constructor %<%T::%D%> directly", - qualifying_scope, name); - } - return error_mark_node; - } + bool qualified = BASELINK_QUALIFIED_P (baselink); + + tree qualifying_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (baselink)); + qualifying_scope = tsubst (qualifying_scope, args, complain, in_decl); - /* If lookup found a single function, mark it as used at this - point. (If it lookup found multiple functions the one selected - later by overload resolution will be marked as used at that - point.) */ - if (BASELINK_P (baselink)) - fns = BASELINK_FUNCTIONS (baselink); - if (!template_id_p && !really_overloaded_fn (fns) - && !mark_used (OVL_FIRST (fns), complain) && !(complain & tf_error)) + tree optype = BASELINK_OPTYPE (baselink); + optype = tsubst (optype, args, complain, in_decl); + + tree template_args = NULL_TREE; + bool template_id_p = false; + tree fns = BASELINK_FUNCTIONS (baselink); + if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) + { + template_id_p = true; + template_args = TREE_OPERAND (fns, 1); + fns = TREE_OPERAND (fns, 0); + if (template_args) + template_args = tsubst_template_args (template_args, args, + complain, in_decl); + } + + tree name = OVL_NAME (fns); + if (IDENTIFIER_CONV_OP_P (name)) + name = mangle_conv_op_name_for_type (optype); + + baselink = lookup_fnfields (qualifying_scope, name, /*protect=*/1); + if (!baselink) + { + if ((complain & tf_error) && constructor_name_p (name, qualifying_scope)) + error ("cannot call constructor %<%T::%D%> directly", + qualifying_scope, name); return error_mark_node; + } + + /* If lookup found a single function, mark it as used at this point. + (If it lookup found multiple functions the one selected later by + overload resolution will be marked as used at that point.) */ + if (BASELINK_P (baselink)) + fns = BASELINK_FUNCTIONS (baselink); + if (!template_id_p && !really_overloaded_fn (fns) + && !mark_used (OVL_FIRST (fns), complain) && !(complain & tf_error)) + return error_mark_node; + + if (BASELINK_P (baselink)) + { + /* Add back the template arguments, if present. */ + if (template_id_p) + BASELINK_FUNCTIONS (baselink) + = build2 (TEMPLATE_ID_EXPR, unknown_type_node, + BASELINK_FUNCTIONS (baselink), template_args); - /* Add back the template arguments, if present. */ - if (BASELINK_P (baselink) && template_id_p) - BASELINK_FUNCTIONS (baselink) - = build2 (TEMPLATE_ID_EXPR, - unknown_type_node, - BASELINK_FUNCTIONS (baselink), - template_args); - /* Update the conversion operator type. */ - if (BASELINK_P (baselink)) + /* Update the conversion operator type. */ BASELINK_OPTYPE (baselink) = optype; + } - if (!object_type) - object_type = current_class_type; + if (!object_type) + object_type = current_class_type; - if (qualified || name == complete_dtor_identifier) - { - baselink = adjust_result_of_qualified_name_lookup (baselink, - qualifying_scope, - object_type); - if (!qualified) - /* We need to call adjust_result_of_qualified_name_lookup in case the - destructor names a base class, but we unset BASELINK_QUALIFIED_P - so that we still get virtual function binding. */ - BASELINK_QUALIFIED_P (baselink) = false; - } - return baselink; + if (qualified || name == complete_dtor_identifier) + { + baselink = adjust_result_of_qualified_name_lookup (baselink, + qualifying_scope, + object_type); + if (!qualified) + /* We need to call adjust_result_of_qualified_name_lookup in case the + destructor names a base class, but we unset BASELINK_QUALIFIED_P + so that we still get virtual function binding. */ + BASELINK_QUALIFIED_P (baselink) = false; + } + + return baselink; } /* Like tsubst_expr for a SCOPE_REF, given by QUALIFIED_ID. DONE is @@ -15041,7 +15035,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) t = DECL_NAME (t); /* Fall through. */ case IDENTIFIER_NODE: - if (IDENTIFIER_TYPENAME_P (t)) + if (IDENTIFIER_CONV_OP_P (t)) { tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); return mangle_conv_op_name_for_type (new_type); @@ -16674,7 +16668,7 @@ tsubst_copy_and_build (tree t, bool non_integral_constant_expression_p; const char *error_msg; - if (IDENTIFIER_TYPENAME_P (t)) + if (IDENTIFIER_CONV_OP_P (t)) { tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl); t = mangle_conv_op_name_for_type (new_type); @@ -20632,18 +20626,6 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, return x; } - if (cxx_dialect >= cxx1z - /* We deduce from array bounds in try_array_deduction. */ - && !(strict & UNIFY_ALLOW_INTEGER) - && uses_template_parms (TREE_TYPE (parm)) - && !type_uses_auto (TREE_TYPE (parm))) - { - tree atype = TREE_TYPE (arg); - RECUR_AND_CHECK_FAILURE (tparms, targs, - TREE_TYPE (parm), atype, - UNIFY_ALLOW_NONE, explain_p); - } - /* [temp.deduct.type] If, in the declaration of a function template with a non-type template-parameter, the non-type template-parameter is used in an expression in the function @@ -20664,7 +20646,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* Template-parameter dependent expression. Just accept it for now. It will later be processed in convert_template_argument. */ ; - else if (same_type_p (TREE_TYPE (arg), tparm)) + else if (same_type_p (non_reference (TREE_TYPE (arg)), + non_reference (tparm))) /* OK */; else if ((strict & UNIFY_ALLOW_INTEGER) && CP_INTEGRAL_TYPE_P (tparm)) @@ -20673,9 +20656,22 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, corresponding parameter. */ arg = fold (build_nop (tparm, arg)); else if (uses_template_parms (tparm)) - /* We haven't deduced the type of this parameter yet. Try again - later. */ - return unify_success (explain_p); + { + /* We haven't deduced the type of this parameter yet. */ + if (cxx_dialect >= cxx1z + /* We deduce from array bounds in try_array_deduction. */ + && !(strict & UNIFY_ALLOW_INTEGER)) + { + /* Deduce it from the non-type argument. */ + tree atype = TREE_TYPE (arg); + RECUR_AND_CHECK_FAILURE (tparms, targs, + tparm, atype, + UNIFY_ALLOW_NONE, explain_p); + } + else + /* Try again later. */ + return unify_success (explain_p); + } else return unify_type_mismatch (explain_p, tparm, TREE_TYPE (arg)); @@ -21676,9 +21672,11 @@ get_partial_spec_bindings (tree tmpl, tree spec_tmpl, tree args) `T' is `A' but unify () does not check whether `typename T::X' is `int'. */ spec_args = tsubst (spec_args, deduced_args, tf_none, NULL_TREE); - spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), - spec_args, tmpl, - tf_none, false, false); + + if (spec_args != error_mark_node) + spec_args = coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (tmpl), + INNERMOST_TEMPLATE_ARGS (spec_args), + tmpl, tf_none, false, false); pop_tinst_level (); @@ -24011,17 +24009,35 @@ type_dependent_expression_p (tree expression) return true; /* A function or variable template-id is type-dependent if it has any - dependent template arguments. Note that we only consider the innermost - template arguments here, since those are the ones that come from the - template-id; the template arguments for the enclosing class do not make it - type-dependent, they only make a member function value-dependent. */ + dependent template arguments. */ if (VAR_OR_FUNCTION_DECL_P (expression) && DECL_LANG_SPECIFIC (expression) - && DECL_TEMPLATE_INFO (expression) - && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression)) - && (any_dependent_template_arguments_p - (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression))))) - return true; + && DECL_TEMPLATE_INFO (expression)) + { + /* Consider the innermost template arguments, since those are the ones + that come from the template-id; the template arguments for the + enclosing class do not make it type-dependent unless they are used in + the type of the decl. */ + if (PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (expression)) + && (any_dependent_template_arguments_p + (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression))))) + return true; + + /* Otherwise, if the decl isn't from a dependent scope, it can't be + type-dependent. Checking this is important for functions with auto + return type, which looks like a dependent type. */ + if (TREE_CODE (expression) == FUNCTION_DECL + && (!DECL_CLASS_SCOPE_P (expression) + || !dependent_type_p (DECL_CONTEXT (expression))) + && (!DECL_FRIEND_CONTEXT (expression) + || !dependent_type_p (DECL_FRIEND_CONTEXT (expression))) + && !DECL_LOCAL_FUNCTION_P (expression)) + { + gcc_assert (!dependent_type_p (TREE_TYPE (expression)) + || undeduced_auto_decl (expression)); + return false; + } + } /* Always dependent, on the number of arguments if nothing else. */ if (TREE_CODE (expression) == EXPR_PACK_EXPANSION) @@ -24783,6 +24799,14 @@ make_template_placeholder (tree tmpl) return t; } +/* True iff T is a C++17 class template deduction placeholder. */ + +bool +template_placeholder_p (tree t) +{ + return is_auto (t) && CLASS_PLACEHOLDER_TEMPLATE (t); +} + /* Make a "constrained auto" type-specifier. This is an auto type with constraints that must be associated after deduction. The constraint is formed from the given diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 5775e07dbbd..7b69dbe2b89 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -178,7 +178,8 @@ cxx_print_identifier (FILE *file, tree node, int indent) fprintf (file, " "); else indent_to (file, indent + 4); - fprintf (file, "local bindings <%p>", (void *) IDENTIFIER_BINDING (node)); + fprintf (file, "%s local bindings <%p>", get_identifier_kind_name (node), + (void *) IDENTIFIER_BINDING (node)); print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4); print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4); } diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 89d18914adf..ff72ce538b2 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -75,7 +75,8 @@ enum tinfo_kind { TK_TYPE_INFO_TYPE, /* abi::__type_info_pseudo */ TK_BASE_TYPE, /* abi::__base_class_type_info */ - TK_BUILTIN_TYPE, /* abi::__fundamental_type_info */ + TK_DERIVED_TYPES, /* Start of types derived from abi::__type_info */ + TK_BUILTIN_TYPE = TK_DERIVED_TYPES, /* abi::__fundamental_type_info */ TK_ARRAY_TYPE, /* abi::__array_type_info */ TK_FUNCTION_TYPE, /* abi::__function_type_info */ TK_ENUMERAL_TYPE, /* abi::__enum_type_info */ @@ -83,8 +84,26 @@ enum tinfo_kind TK_POINTER_MEMBER_TYPE, /* abi::__pointer_to_member_type_info */ TK_CLASS_TYPE, /* abi::__class_type_info */ TK_SI_CLASS_TYPE, /* abi::__si_class_type_info */ - TK_FIXED /* end of fixed descriptors. */ - /* ... abi::__vmi_type_info<I> */ + TK_VMI_CLASS_TYPES, /* abi::__vmi_class_type_info<int> */ + TK_MAX +}; + +/* Names of the tinfo types. Must be same order as TK enumeration + above. */ + +static const char *const tinfo_names[TK_MAX] = +{ + "__type_info", + "__base_class_type_info", + "__fundamental_type_info", + "__array_type_info", + "__function_type_info", + "__enum_type_info", + "__pointer_type_info", + "__pointer_to_member_type_info", + "__class_type_info", + "__si_class_type_info", + "__vmi_class_type_info" }; /* Helper macro to get maximum scalar-width of pointer or of the 'long'-type. @@ -115,9 +134,9 @@ static tree generic_initializer (tinfo_s *, tree); static tree ptr_initializer (tinfo_s *, tree); static tree ptm_initializer (tinfo_s *, tree); static tree class_initializer (tinfo_s *, tree, unsigned, ...); -static void create_pseudo_type_info (int, const char *, ...); static tree get_pseudo_ti_init (tree, unsigned); static unsigned get_pseudo_ti_index (tree); +static tinfo_s *get_tinfo_desc (unsigned); static void create_tinfo_types (void); static bool typeinfo_in_lib_p (tree); @@ -289,30 +308,27 @@ get_tinfo_decl_dynamic (tree exp, tsubst_flags_t complain) static bool typeid_ok_p (void) { - tree pseudo_type_info, type_info_type; - if (! flag_rtti) { - error ("cannot use typeid with -fno-rtti"); + error ("cannot use %<typeid%> with -fno-rtti"); return false; } if (!COMPLETE_TYPE_P (const_type_info_type_node)) { - error ("must #include <typeinfo> before using typeid"); + error ("must %<#include <typeinfo>%> before using %<typeid%>"); return false; } - pseudo_type_info = (*tinfo_descs)[TK_TYPE_INFO_TYPE].type; - type_info_type = TYPE_MAIN_VARIANT (const_type_info_type_node); + tree pseudo = TYPE_MAIN_VARIANT (get_tinfo_desc (TK_TYPE_INFO_TYPE)->type); + tree real = TYPE_MAIN_VARIANT (const_type_info_type_node); /* Make sure abi::__type_info_pseudo has the same alias set as std::type_info. */ - if (! TYPE_ALIAS_SET_KNOWN_P (pseudo_type_info)) - TYPE_ALIAS_SET (pseudo_type_info) = get_alias_set (type_info_type); + if (! TYPE_ALIAS_SET_KNOWN_P (pseudo)) + TYPE_ALIAS_SET (pseudo) = get_alias_set (real); else - gcc_assert (TYPE_ALIAS_SET (pseudo_type_info) - == get_alias_set (type_info_type)); + gcc_assert (TYPE_ALIAS_SET (pseudo) == get_alias_set (real)); return true; } @@ -428,8 +444,8 @@ get_tinfo_decl (tree type) if (!d) { int ix = get_pseudo_ti_index (type); - tinfo_s *ti = &(*tinfo_descs)[ix]; - + const tinfo_s *ti = get_tinfo_desc (ix); + d = build_lang_decl (VAR_DECL, name, ti->type); SET_DECL_ASSEMBLER_NAME (d, name); /* Remember the type it is for. */ @@ -1105,7 +1121,7 @@ typeinfo_in_lib_p (tree type) static tree get_pseudo_ti_init (tree type, unsigned tk_index) { - tinfo_s *ti = &(*tinfo_descs)[tk_index]; + tinfo_s *ti = get_tinfo_desc (tk_index); gcc_assert (at_eof); switch (tk_index) @@ -1140,22 +1156,18 @@ get_pseudo_ti_init (tree type, unsigned tk_index) int hint = ((CLASSTYPE_REPEATED_BASE_P (type) << 0) | (CLASSTYPE_DIAMOND_SHAPED_P (type) << 1)); tree binfo = TYPE_BINFO (type); - int nbases = BINFO_N_BASE_BINFOS (binfo); + unsigned nbases = BINFO_N_BASE_BINFOS (binfo); vec<tree, va_gc> *base_accesses = BINFO_BASE_ACCESSES (binfo); tree offset_type = LONGPTR_T; - tree base_inits = NULL_TREE; - int ix; vec<constructor_elt, va_gc> *init_vec = NULL; - constructor_elt *e; - gcc_assert (tk_index >= TK_FIXED); + gcc_assert (tk_index - TK_VMI_CLASS_TYPES + 1 == nbases); vec_safe_grow (init_vec, nbases); /* Generate the base information initializer. */ - for (ix = nbases; ix--;) + for (unsigned ix = nbases; ix--;) { tree base_binfo = BINFO_BASE_BINFO (binfo, ix); - tree base_init; int flags = 0; tree tinfo; tree offset; @@ -1185,12 +1197,12 @@ get_pseudo_ti_init (tree type, unsigned tk_index) vec_alloc (v, 2); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, tinfo); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, offset); - base_init = build_constructor (init_list_type_node, v); - e = &(*init_vec)[ix]; + tree base_init = build_constructor (init_list_type_node, v); + constructor_elt *e = &(*init_vec)[ix]; e->index = NULL_TREE; e->value = base_init; } - base_inits = build_constructor (init_list_type_node, init_vec); + tree base_inits = build_constructor (init_list_type_node, init_vec); /* get_tinfo_ptr might have reallocated the tinfo_descs vector. */ ti = &(*tinfo_descs)[tk_index]; @@ -1202,69 +1214,6 @@ get_pseudo_ti_init (tree type, unsigned tk_index) } } -/* Generate the RECORD_TYPE containing the data layout of a type_info - derivative as used by the runtime. This layout must be consistent with - that defined in the runtime support. Also generate the VAR_DECL for the - type's vtable. We explicitly manage the vtable member, and name it for - real type as used in the runtime. The RECORD type has a different name, - to avoid collisions. Return a TREE_LIST who's TINFO_PSEUDO_TYPE - is the generated type and TINFO_VTABLE_NAME is the name of the - vtable. We have to delay generating the VAR_DECL of the vtable - until the end of the translation, when we'll have seen the library - definition, if there was one. - - REAL_NAME is the runtime's name of the type. Trailing arguments are - additional FIELD_DECL's for the structure. The final argument must be - NULL. */ - -static void -create_pseudo_type_info (int tk, const char *real_name, ...) -{ - tinfo_s *ti; - tree pseudo_type; - char *pseudo_name; - tree fields; - tree field_decl; - va_list ap; - - va_start (ap, real_name); - - /* Generate the pseudo type name. */ - pseudo_name = (char *) alloca (strlen (real_name) + 30); - strcpy (pseudo_name, real_name); - strcat (pseudo_name, "_pseudo"); - if (tk >= TK_FIXED) - sprintf (pseudo_name + strlen (pseudo_name), "%d", tk - TK_FIXED); - - /* First field is the pseudo type_info base class. */ - fields = build_decl (input_location, - FIELD_DECL, NULL_TREE, - (*tinfo_descs)[TK_TYPE_INFO_TYPE].type); - - /* Now add the derived fields. */ - while ((field_decl = va_arg (ap, tree))) - { - DECL_CHAIN (field_decl) = fields; - fields = field_decl; - } - - /* Create the pseudo type. */ - pseudo_type = make_class_type (RECORD_TYPE); - finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE); - CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type; - - ti = &(*tinfo_descs)[tk]; - ti->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST); - ti->name = get_identifier (real_name); - ti->vtable = NULL_TREE; - - /* Pretend this is public so determine_visibility doesn't give vtables - internal linkage. */ - TREE_PUBLIC (TYPE_MAIN_DECL (ti->type)) = 1; - - va_end (ap); -} - /* Return the index of a pseudo type info type node used to describe TYPE. TYPE must be a complete type (or cv void), except at the end of the translation unit. */ @@ -1299,23 +1248,16 @@ get_pseudo_ti_index (tree type) case UNION_TYPE: case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (type)) - { - ix = TK_POINTER_MEMBER_TYPE; - break; - } + ix = TK_POINTER_MEMBER_TYPE; else if (!COMPLETE_TYPE_P (type)) { if (!at_eof) cxx_incomplete_type_error (NULL_TREE, type); ix = TK_CLASS_TYPE; - break; } else if (!TYPE_BINFO (type) || !BINFO_N_BASE_BINFOS (TYPE_BINFO (type))) - { - ix = TK_CLASS_TYPE; - break; - } + ix = TK_CLASS_TYPE; else { tree binfo = TYPE_BINFO (type); @@ -1327,49 +1269,13 @@ get_pseudo_ti_index (tree type) && (*base_accesses)[0] == access_public_node && !BINFO_VIRTUAL_P (base_binfo) && integer_zerop (BINFO_OFFSET (base_binfo))) - { - /* single non-virtual public. */ - ix = TK_SI_CLASS_TYPE; - break; - } + /* single non-virtual public. */ + ix = TK_SI_CLASS_TYPE; else - { - tinfo_s *ti; - tree array_domain, base_array; - - ix = TK_FIXED + num_bases; - if (vec_safe_length (tinfo_descs) <= ix) - { - /* too short, extend. */ - unsigned len = vec_safe_length (tinfo_descs); - - vec_safe_grow (tinfo_descs, ix + 1); - while (tinfo_descs->iterate (len++, &ti)) - ti->type = ti->vtable = ti->name = NULL_TREE; - } - else if ((*tinfo_descs)[ix].type) - /* already created. */ - break; - - /* Create the array of __base_class_type_info entries. */ - array_domain = build_index_type (size_int (num_bases - 1)); - base_array = build_array_type ((*tinfo_descs)[TK_BASE_TYPE].type, - array_domain); - - push_abi_namespace (); - create_pseudo_type_info - (ix, "__vmi_class_type_info", - build_decl (input_location, - FIELD_DECL, NULL_TREE, integer_type_node), - build_decl (input_location, - FIELD_DECL, NULL_TREE, integer_type_node), - build_decl (input_location, - FIELD_DECL, NULL_TREE, base_array), - NULL); - pop_abi_namespace (); - break; - } + ix = TK_VMI_CLASS_TYPES + num_bases - 1; } + break; + default: ix = TK_BUILTIN_TYPE; break; @@ -1377,107 +1283,202 @@ get_pseudo_ti_index (tree type) return ix; } -/* Make sure the required builtin types exist for generating the type_info - variable definitions. */ +/* Return pointer to tinfo descriptor. Possibly creating the tinfo + descriptor in the first place. */ -static void -create_tinfo_types (void) +static tinfo_s * +get_tinfo_desc (unsigned ix) { - tinfo_s *ti; + unsigned len = tinfo_descs->length (); - gcc_assert (!tinfo_descs); + if (len <= ix) + { + /* too short, extend. */ + len = ix + 1 - len; + vec_safe_reserve (tinfo_descs, len); + tinfo_s elt; + elt.type = elt.vtable = elt.name = NULL_TREE; + while (len--) + tinfo_descs->quick_push (elt); + } - vec_safe_grow (tinfo_descs, TK_FIXED); + tinfo_s *res = &(*tinfo_descs)[ix]; - push_abi_namespace (); + if (res->type) + return res; - /* Create the internal type_info structure. This is used as a base for - the other structures. */ - { - tree field, fields; - - field = build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, const_ptr_type_node); - fields = field; - - field = build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, const_string_type_node); - DECL_CHAIN (field) = fields; - fields = field; - - ti = &(*tinfo_descs)[TK_TYPE_INFO_TYPE]; - ti->type = make_class_type (RECORD_TYPE); - ti->vtable = NULL_TREE; - ti->name = NULL_TREE; - finish_builtin_struct (ti->type, "__type_info_pseudo", - fields, NULL_TREE); - } + /* Ok, we have to create it. This layout must be consistent with + that defined in the runtime support. We explicitly manage the + vtable member, and name it for real type as used in the runtime. + The RECORD type has a different name, to avoid collisions. We + have to delay generating the VAR_DECL of the vtable until the end + of the translation, when we'll have seen the library definition, + if there was one. */ + + /* Fields to add, chained in reverse order. */ + tree fields = NULL_TREE; + + if (ix >= TK_DERIVED_TYPES) + { + /* First field is the pseudo type_info base class. */ + tree fld_base = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, + get_tinfo_desc (TK_TYPE_INFO_TYPE)->type); + + DECL_CHAIN (fld_base) = fields; + fields = fld_base; + } + + switch (ix) + { + case TK_TYPE_INFO_TYPE: + { + tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, const_ptr_type_node); + fields = fld_ptr; + + tree fld_str = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, const_string_type_node); + DECL_CHAIN (fld_str) = fields; + fields = fld_str; + break; + } - /* Fundamental type_info */ - create_pseudo_type_info (TK_BUILTIN_TYPE, "__fundamental_type_info", NULL); + case TK_BASE_TYPE: + { + /* Base class internal helper. Pointer to base type, offset to + base, flags. */ + tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, type_info_ptr_type); + DECL_CHAIN (fld_ptr) = fields; + fields = fld_ptr; + + tree fld_flag = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, LONGPTR_T); + DECL_CHAIN (fld_flag) = fields; + fields = fld_flag; + break; + } - /* Array, function and enum type_info. No additional fields. */ - create_pseudo_type_info (TK_ARRAY_TYPE, "__array_type_info", NULL); - create_pseudo_type_info (TK_FUNCTION_TYPE, "__function_type_info", NULL); - create_pseudo_type_info (TK_ENUMERAL_TYPE, "__enum_type_info", NULL); + case TK_BUILTIN_TYPE: + /* Fundamental type_info */ + break; - /* Class type_info. No additional fields. */ - create_pseudo_type_info (TK_CLASS_TYPE, "__class_type_info", NULL); + case TK_ARRAY_TYPE: + break; - /* Single public non-virtual base class. Add pointer to base class. - This is really a descendant of __class_type_info. */ - create_pseudo_type_info (TK_SI_CLASS_TYPE, "__si_class_type_info", - build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, type_info_ptr_type), - NULL); + case TK_FUNCTION_TYPE: + break; - /* Base class internal helper. Pointer to base type, offset to base, - flags. */ - { - tree field, fields; + case TK_ENUMERAL_TYPE: + break; + + case TK_POINTER_TYPE: + case TK_POINTER_MEMBER_TYPE: + { + /* Pointer type_info. Adds two fields, qualification mask and + pointer to the pointed to type. This is really a + descendant of __pbase_type_info. */ + tree fld_mask = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, integer_type_node); + DECL_CHAIN (fld_mask) = fields; + fields = fld_mask; + + tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, type_info_ptr_type); + DECL_CHAIN (fld_ptr) = fields; + fields = fld_ptr; + + if (ix == TK_POINTER_MEMBER_TYPE) + { + /* Add a pointer to the class too. */ + tree fld_cls = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, type_info_ptr_type); + DECL_CHAIN (fld_cls) = fields; + fields = fld_cls; + } + break; + } + + case TK_CLASS_TYPE: + /* Class type_info. No additional fields. */ + break; + + case TK_SI_CLASS_TYPE: + { + /* Single public non-virtual base class. Add pointer to base + class. This is really a descendant of + __class_type_info. */ + tree fld_ptr = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, type_info_ptr_type); + DECL_CHAIN (fld_ptr) = fields; + fields = fld_ptr; + break; + } - field = build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, type_info_ptr_type); - fields = field; + default: /* Multiple inheritance. */ + { + unsigned num_bases = ix - TK_VMI_CLASS_TYPES + 1; + + tree fld_flg = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, integer_type_node); + DECL_CHAIN (fld_flg) = fields; + fields = fld_flg; + + tree fld_cnt = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, integer_type_node); + DECL_CHAIN (fld_cnt) = fields; + fields = fld_cnt; + + /* Create the array of __base_class_type_info entries. */ + tree domain = build_index_type (size_int (num_bases - 1)); + tree array = build_array_type (get_tinfo_desc (TK_BASE_TYPE)->type, + domain); + tree fld_ary = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, array); + DECL_CHAIN (fld_ary) = fields; + fields = fld_ary; + break; + } + } - field = build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, LONGPTR_T); - DECL_CHAIN (field) = fields; - fields = field; + push_abi_namespace (); - ti = &(*tinfo_descs)[TK_BASE_TYPE]; + /* Generate the pseudo type name. */ + const char *real_name = tinfo_names[ix < TK_VMI_CLASS_TYPES + ? ix : unsigned (TK_VMI_CLASS_TYPES)]; + size_t name_len = strlen (real_name); + char *pseudo_name = (char *) alloca (name_len + 30); + memcpy (pseudo_name, real_name, name_len); + /* Those >= TK_VMI_CLASS_TYPES need a discriminator, may as well + apply it to all. See get_peudo_tinfo_index where we make use of + this. */ + sprintf (pseudo_name + name_len, "_pseudo_%d", ix); - ti->type = make_class_type (RECORD_TYPE); - ti->vtable = NULL_TREE; - ti->name = NULL_TREE; - finish_builtin_struct (ti->type, "__base_class_type_info_pseudo", - fields, NULL_TREE); - } + /* Create the pseudo type. */ + tree pseudo_type = make_class_type (RECORD_TYPE); + /* Pass the fields chained in reverse. */ + finish_builtin_struct (pseudo_type, pseudo_name, fields, NULL_TREE); + CLASSTYPE_AS_BASE (pseudo_type) = pseudo_type; - /* Pointer type_info. Adds two fields, qualification mask - and pointer to the pointed to type. This is really a descendant of - __pbase_type_info. */ - create_pseudo_type_info (TK_POINTER_TYPE, "__pointer_type_info", - build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, integer_type_node), - build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, type_info_ptr_type), - NULL); - - /* Pointer to member data type_info. Add qualifications flags, - pointer to the member's type info and pointer to the class. - This is really a descendant of __pbase_type_info. */ - create_pseudo_type_info (TK_POINTER_MEMBER_TYPE, - "__pointer_to_member_type_info", - build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, integer_type_node), - build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, type_info_ptr_type), - build_decl (BUILTINS_LOCATION, - FIELD_DECL, NULL_TREE, type_info_ptr_type), - NULL); + res->type = cp_build_qualified_type (pseudo_type, TYPE_QUAL_CONST); + res->name = get_identifier (real_name); + + /* Pretend this is public so determine_visibility doesn't give vtables + internal linkage. */ + TREE_PUBLIC (TYPE_MAIN_DECL (res->type)) = 1; pop_abi_namespace (); + return res; +} + +/* We lazily create the type info types. */ + +static void +create_tinfo_types (void) +{ + gcc_assert (!tinfo_descs); + + vec_alloc (tinfo_descs, TK_MAX + 20); } /* Helper for emit_support_tinfos. Emits the type_info descriptor of @@ -1545,18 +1546,23 @@ emit_support_tinfos (void) 0 }; int ix; - tree bltn_type, dtor; - push_abi_namespace (); - bltn_type = xref_tag (class_type, - get_identifier ("__fundamental_type_info"), - /*tag_scope=*/ts_current, false); - pop_abi_namespace (); + /* Look for a defined class. */ + tree bltn_type = lookup_qualified_name + (abi_node, get_identifier ("__fundamental_type_info"), true, false, false); + if (TREE_CODE (bltn_type) != TYPE_DECL) + return; + + bltn_type = TREE_TYPE (bltn_type); if (!COMPLETE_TYPE_P (bltn_type)) return; - dtor = CLASSTYPE_DESTRUCTORS (bltn_type); + tree dtor = CLASSTYPE_DESTRUCTORS (bltn_type); if (!dtor || DECL_EXTERNAL (dtor)) return; + + /* All these are really builtins. So set the location. */ + location_t saved_loc = input_location; + input_location = BUILTINS_LOCATION; doing_runtime = 1; for (ix = 0; fundamentals[ix]; ix++) emit_support_tinfo_1 (*fundamentals[ix]); @@ -1568,6 +1574,7 @@ emit_support_tinfos (void) } for (tree t = registered_builtin_types; t; t = TREE_CHAIN (t)) emit_support_tinfo_1 (TREE_VALUE (t)); + input_location = saved_loc; } /* Finish a type info decl. DECL_PTR is a pointer to an unemitted diff --git a/gcc/cp/search.c b/gcc/cp/search.c index d8ad40a98a7..00f895c5d7d 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1187,7 +1187,7 @@ lookup_field_r (tree binfo, void *data) done: /* Don't look for constructors or destructors in base classes. */ - if (IDENTIFIER_CTOR_OR_DTOR_P (lfi->name)) + if (IDENTIFIER_CDTOR_P (lfi->name)) return dfs_skip_bases; return NULL_TREE; } @@ -1352,7 +1352,7 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type, if (rval && is_overloaded_fn (rval)) rval = build_baselink (rval_binfo, basetype_path, rval, - (IDENTIFIER_TYPENAME_P (name) + (IDENTIFIER_CONV_OP_P (name) ? TREE_TYPE (name): NULL_TREE)); return rval; } @@ -1595,7 +1595,7 @@ lookup_fnfields_idx_nolazy (tree type, tree name) fn = CLASSTYPE_DESTRUCTORS (type); return fn ? CLASSTYPE_DESTRUCTOR_SLOT : -1; } - if (IDENTIFIER_TYPENAME_P (name)) + if (IDENTIFIER_CONV_OP_P (name)) return lookup_conversion_operator (type, TREE_TYPE (name)); /* Skip the conversion operators. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 5b5ec5483d1..9589b47dd64 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -733,7 +733,10 @@ finish_if_stmt_cond (tree cond, tree if_stmt) if (IF_STMT_CONSTEXPR_P (if_stmt) && require_potential_rvalue_constant_expression (cond) && !value_dependent_expression_p (cond)) - cond = cxx_constant_value (cond, NULL_TREE); + { + cond = instantiate_non_dependent_expr (cond); + cond = cxx_constant_value (cond, NULL_TREE); + } finish_cond (&IF_COND (if_stmt), cond); add_stmt (if_stmt); THEN_CLAUSE (if_stmt) = push_stmt_list (); @@ -3493,7 +3496,7 @@ finish_id_expression (tree id_expression, && (!TYPE_P (scope) || (!dependent_type_p (scope) && !(identifier_p (id_expression) - && IDENTIFIER_TYPENAME_P (id_expression) + && IDENTIFIER_CONV_OP_P (id_expression) && dependent_type_p (TREE_TYPE (id_expression)))))) { /* If the qualifying type is non-dependent (and the name @@ -4586,7 +4589,7 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, } if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { - if (processing_template_decl) + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) return NULL_TREE; if (DECL_P (t)) error_at (OMP_CLAUSE_LOCATION (c), @@ -6106,7 +6109,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL && (!field_ok || TREE_CODE (t) != FIELD_DECL)) { - if (processing_template_decl) + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) error ("%qD is not a variable in clause %qs", t, @@ -6178,7 +6181,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) && ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP || TREE_CODE (t) != FIELD_DECL)) { - if (processing_template_decl) + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) error ("%qD is not a variable in clause %<firstprivate%>", t); @@ -6221,7 +6224,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) && ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP || TREE_CODE (t) != FIELD_DECL)) { - if (processing_template_decl) + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) error ("%qD is not a variable in clause %<lastprivate%>", t); @@ -6584,7 +6587,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { - if (processing_template_decl) + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) error ("%qD is not a variable in %<aligned%> clause", t); @@ -6666,7 +6669,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) remove = true; else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { - if (processing_template_decl) + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (DECL_P (t)) error ("%qD is not a variable in %<depend%> clause", t); @@ -6797,7 +6800,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { - if (processing_template_decl) + if (processing_template_decl && TREE_CODE (t) != OVERLOAD) break; if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 34d475b98f0..1c15f29eb3d 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-ubsan.h" #include "params.h" #include "gcc-rich-location.h" +#include "asan.h" static tree cp_build_addr_expr_strict (tree, tsubst_flags_t); static tree cp_build_function_call (tree, tree, tsubst_flags_t); @@ -5253,10 +5254,9 @@ cp_build_binary_op (location_t location, if (build_type == NULL_TREE) build_type = result_type; - if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE - | SANITIZE_FLOAT_DIVIDE)) + if (sanitize_flags_p ((SANITIZE_SHIFT + | SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE)) && !processing_template_decl - && do_ubsan_in_current_function () && (doing_div_or_mod || doing_shift)) { /* OP0 and/or OP1 might have side-effects. */ @@ -5264,8 +5264,8 @@ cp_build_binary_op (location_t location, op1 = cp_save_expr (op1); op0 = fold_non_dependent_expr (op0); op1 = fold_non_dependent_expr (op1); - if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE - | SANITIZE_FLOAT_DIVIDE))) + if (doing_div_or_mod + && sanitize_flags_p (SANITIZE_DIVIDE | SANITIZE_FLOAT_DIVIDE)) { /* For diagnostics we want to use the promoted types without shorten_binary_op. So convert the arguments to the @@ -5278,7 +5278,7 @@ cp_build_binary_op (location_t location, cop1 = cp_convert (orig_type, op1, complain); instrument_expr = ubsan_instrument_division (location, cop0, cop1); } - else if (doing_shift && (flag_sanitize & SANITIZE_SHIFT)) + else if (doing_shift && sanitize_flags_p (SANITIZE_SHIFT)) instrument_expr = ubsan_instrument_shift (location, code, op0, op1); } @@ -5652,7 +5652,7 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) arg = mark_lvalue_use (arg); argtype = lvalue_type (arg); - gcc_assert (!identifier_p (arg) || !IDENTIFIER_OPNAME_P (arg)); + gcc_assert (!(identifier_p (arg) && IDENTIFIER_ANY_OP_P (arg))); if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg) && !really_overloaded_fn (arg)) @@ -6823,7 +6823,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, NULL, complain); expr = build_address (expr); - if (flag_sanitize & SANITIZE_VPTR) + if (sanitize_flags_p (SANITIZE_VPTR)) { tree ubsan_check = cp_ubsan_maybe_instrument_downcast (input_location, type, @@ -6967,7 +6967,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false, complain); - if (flag_sanitize & SANITIZE_VPTR) + if (sanitize_flags_p (SANITIZE_VPTR)) { tree ubsan_check = cp_ubsan_maybe_instrument_downcast (input_location, type, @@ -8590,9 +8590,10 @@ convert_for_assignment (tree type, tree rhs, if (rhstype == unknown_type_node) { tree r = instantiate_type (type, rhs, tf_warning_or_error); - /* -fpermissive might allow this. */ + /* -fpermissive might allow this; recurse. */ if (!seen_error ()) - return r; + return convert_for_assignment (type, r, errtype, fndecl, + parmnum, complain, flags); } else if (fndecl) error ("cannot convert %qH to %qI for argument %qP to %qD", diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 4623d6d9197..430ba30536a 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -821,8 +821,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) || (DECL_IN_AGGR_P (decl) && !DECL_VAR_DECLARED_INLINE_P (decl))) { /* Diagnose a non-constant initializer for constexpr. */ - if (processing_template_decl - && !require_potential_constant_expression (value)) + if (!require_potential_constant_expression (value)) value = error_mark_node; else value = cxx_constant_value (value, decl); |