I notied the __builtin_FUNCTION () builtin was using raw DECL_NAME, which for C++ dtors and conversion operators gives non-useful names. (no ~ and 'operator N' for N= some int).
This patch fixes its folder to use the lang hook that provides a printable name. I did contemplate passing 1 (add scope) to the hook, but decided against changing that.
Applied as obvious. nathan -- Nathan Sidwell
diff -p -U2 -r ./builtins.c /data/users/nathans/modules/src/gcc/builtins.c --- ./builtins.c 2017-06-26 07:48:42.206366313 -0700 +++ /data/users/nathans/modules/src/gcc/builtins.c 2017-06-28 13:52:53.026518086 -0700 @@ -8740,11 +8740,10 @@ static inline tree fold_builtin_FUNCTION () { + const char *name = ""; + if (current_function_decl) - { - const char *name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); - return build_string_literal (strlen (name) + 1, name); - } + name= lang_hooks.decl_printable_name (current_function_decl, 0); - return build_string_literal (1, ""); + return build_string_literal (strlen (name) + 1, name); } diff -p -U2 -r ./cp/call.c /data/users/nathans/modules/src/gcc/cp/call.c --- ./cp/call.c 2017-06-27 08:34:25.902966687 -0700 +++ /data/users/nathans/modules/src/gcc/cp/call.c 2017-06-28 12:05:23.188713566 -0700 @@ -232,7 +232,6 @@ check_dtor_name (tree basetype, tree nam { if ((MAYBE_CLASS_TYPE_P (basetype) - && name == constructor_name (basetype)) - || (TREE_CODE (basetype) == ENUMERAL_TYPE - && name == TYPE_IDENTIFIER (basetype))) + || TREE_CODE (basetype) == ENUMERAL_TYPE) + && name == constructor_name (basetype)) return true; else @@ -8879,5 +8878,5 @@ static char * name_as_c_string (tree name, tree type, bool *free_p) { - char *pretty_name; + const char *pretty_name; /* Assume that we will not allocate memory. */ @@ -8887,5 +8886,5 @@ name_as_c_string (tree name, tree type, { pretty_name - = CONST_CAST (char *, identifier_to_locale (IDENTIFIER_POINTER (constructor_name (type)))); + = identifier_to_locale (IDENTIFIER_POINTER (constructor_name (type))); /* For a destructor, add the '~'. */ if (IDENTIFIER_DTOR_P (name)) @@ -8906,7 +8905,7 @@ name_as_c_string (tree name, tree type, } else - pretty_name = CONST_CAST (char *, identifier_to_locale (IDENTIFIER_POINTER (name))); + pretty_name = identifier_to_locale (IDENTIFIER_POINTER (name)); - return pretty_name; + return CONST_CAST (char *, pretty_name); } @@ -9119,9 +9115,8 @@ build_new_method_call_1 (tree instance, } else - { - add_candidates (fns, first_mem_arg, user_args, optype, - explicit_targs, template_only, conversion_path, - access_binfo, flags, &candidates, complain); - } + add_candidates (fns, first_mem_arg, user_args, optype, + explicit_targs, template_only, conversion_path, + access_binfo, flags, &candidates, complain); + any_viable_p = false; candidates = splice_viable (candidates, false, &any_viable_p); @@ -9141,8 +9136,9 @@ build_new_method_call_1 (tree instance, tree arglist = build_tree_list_vec (user_args); tree errname = name; + bool twiddle = false; if (IDENTIFIER_CDTOR_P (errname)) { - tree fn = DECL_ORIGIN (OVL_FIRST (fns)); - errname = DECL_NAME (fn); + twiddle = IDENTIFIER_DTOR_P (errname); + errname = constructor_name (basetype); } if (explicit_targs) @@ -9150,6 +9146,6 @@ build_new_method_call_1 (tree instance, if (skip_first_for_error) arglist = TREE_CHAIN (arglist); - error ("no matching function for call to %<%T::%E(%A)%#V%>", - basetype, errname, arglist, + error ("no matching function for call to %<%T::%s%E(%A)%#V%>", + basetype, &"~"[!twiddle], errname, arglist, TREE_TYPE (instance)); } diff -p -U2 -r ./cp/class.c /data/users/nathans/modules/src/gcc/cp/class.c --- ./cp/class.c 2017-06-27 08:33:21.756909868 -0700 +++ /data/users/nathans/modules/src/gcc/cp/class.c 2017-06-28 15:50:01.612979147 -0700 @@ -6296,6 +6240,5 @@ include_empty_classes (record_layout_inf offset. However, now we need to make sure that RLI is big enough to reflect the entire class. */ - eoc = end_of_class (rli->t, - CLASSTYPE_AS_BASE (rli->t) != NULL_TREE); + eoc = end_of_class (rli->t, CLASSTYPE_AS_BASE (rli->t) != NULL_TREE); rli_size = rli_size_unit_so_far (rli); if (TREE_CODE (rli_size) == INTEGER_CST @@ -7445,5 +7342,5 @@ finish_struct (tree t, tree attributes) { tree fn = strip_using_decl (x); - if (is_overloaded_fn (fn)) + if (OVL_P (fn)) for (lkp_iterator iter (fn); iter; ++iter) add_method (t, *iter, true); @@ -8506,5 +8403,4 @@ get_vfield_name (tree type) { tree binfo, base_binfo; - char *buf; for (binfo = TYPE_BINFO (type); @@ -8520,8 +8416,8 @@ get_vfield_name (tree type) type = BINFO_TYPE (binfo); - buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT) - + TYPE_NAME_LENGTH (type) + 2); - sprintf (buf, VFIELD_NAME_FORMAT, - IDENTIFIER_POINTER (constructor_name (type))); + tree ctor_name = constructor_name (type); + char *buf = (char *) alloca (sizeof (VFIELD_NAME_FORMAT) + + IDENTIFIER_LENGTH (ctor_name) + 2); + sprintf (buf, VFIELD_NAME_FORMAT, IDENTIFIER_POINTER (ctor_name)); return get_identifier (buf); } @@ -8553,7 +8449,6 @@ void build_self_reference (void) { - tree name = constructor_name (current_class_type); + tree name = DECL_NAME (TYPE_NAME (current_class_type)); tree value = build_lang_decl (TYPE_DECL, name, current_class_type); - tree saved_cas; DECL_NONLOCAL (value) = 1; @@ -8566,5 +8461,5 @@ build_self_reference (void) value = push_template_decl (value); - saved_cas = current_access_specifier; + tree saved_cas = current_access_specifier; current_access_specifier = access_public_node; finish_member_declaration (value); diff -p -U2 -r ./cp/constraint.cc /data/users/nathans/modules/src/gcc/cp/constraint.cc --- ./cp/constraint.cc 2017-06-19 11:07:28.043486829 -0700 +++ /data/users/nathans/modules/src/gcc/cp/constraint.cc 2017-06-19 11:38:31.769616147 -0700 @@ -1581,5 +1581,5 @@ tsubst_check_constraint (tree t, tree ar /* Substitute through by building an template-id expression and then substituting into that. */ - tree expr = build_nt(TEMPLATE_ID_EXPR, tmpl, targs); + tree expr = build_nt (TEMPLATE_ID_EXPR, tmpl, targs); ++processing_template_decl; tree result = tsubst_expr (expr, args, complain, in_decl, false); diff -p -U2 -r ./cp/cp-tree.h /data/users/nathans/modules/src/gcc/cp/cp-tree.h --- ./cp/cp-tree.h 2017-06-29 04:12:52.660865522 -0700 +++ /data/users/nathans/modules/src/gcc/cp/cp-tree.h 2017-06-29 04:13:38.133894202 -0700 @@ -1815,5 +1887,5 @@ enum languages { lang_c, lang_cplusplus union type. */ #define SET_CLASS_TYPE_P(T, VAL) \ - (TYPE_LANG_FLAG_5 (T) = (VAL)) + (TYPE_LANG_FLAG_5 (RECORD_OR_UNION_CHECK (T)) = (VAL)) /* Nonzero if T is a class type. Zero for template type parameters, @@ -1824,5 +1896,5 @@ enum languages { lang_c, lang_cplusplus /* Nonzero if T is a class type but not an union. */ #define NON_UNION_CLASS_TYPE_P(T) \ - (CLASS_TYPE_P (T) && TREE_CODE (T) != UNION_TYPE) + (TREE_CODE (T) == RECORD_TYPE && TYPE_LANG_FLAG_5 (T)) /* Keep these checks in ascending code order. */ @@ -2557,5 +2631,7 @@ struct GTY(()) lang_decl_ns { vec<tree, va_gc> *inlinees; - /* Map from IDENTIFIER nodes to DECLS. */ + /* Map from IDENTIFIER nodes to DECLS. It'd be nice to have this + inline, but as the hash_map has a dtor, we can't then put this + struct into a union (until moving to c++11). */ hash_map<lang_identifier *, tree> *bindings; }; @@ -4313,5 +4383,6 @@ more_aggr_init_expr_args_p (const aggr_i /* For a pointer-to-member constant `X::Y' this is the _DECL for `Y'. */ -#define PTRMEM_CST_MEMBER(NODE) (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member) +#define PTRMEM_CST_MEMBER(NODE) \ + (((ptrmem_cst_t)PTRMEM_CST_CHECK (NODE))->member) /* The expression in question for a TYPEOF_TYPE. */ @@ -5193,12 +5264,4 @@ extern GTY(()) vec<tree, va_gc> *keyed_c #endif /* NO_DOT_IN_LABEL */ -#define THIS_NAME "this" - -#define IN_CHARGE_NAME "__in_chrg" - -#define VTBL_PTR_TYPE "__vtbl_ptr_type" -#define VTABLE_DELTA_NAME "__delta" -#define VTABLE_PFN_NAME "__pfn" - #define LAMBDANAME_PREFIX "__lambda" #define LAMBDANAME_FORMAT LAMBDANAME_PREFIX "%d" diff -p -U2 -r ./cp/cxx-pretty-print.c /data/users/nathans/modules/src/gcc/cp/cxx-pretty-print.c --- ./cp/cxx-pretty-print.c 2017-06-22 10:39:31.897661992 -0700 +++ /data/users/nathans/modules/src/gcc/cp/cxx-pretty-print.c 2017-06-27 12:53:41.365646106 -0700 @@ -89,12 +89,4 @@ pp_cxx_separate_with (cxx_pretty_printer /* Expressions. */ -static inline bool -is_destructor_name (tree name) -{ - return name == complete_dtor_identifier - || name == base_dtor_identifier - || name == deleting_dtor_identifier; -} - /* conversion-function-id: operator conversion-type-id @@ -163,14 +155,5 @@ pp_cxx_unqualified_id (cxx_pretty_printe pp_cxx_conversion_function_id (pp, t); else - { - if (is_destructor_name (t)) - { - pp_complement (pp); - /* FIXME: Why is this necessary? */ - if (TREE_TYPE (t)) - t = constructor_name (TREE_TYPE (t)); - } - pp_cxx_tree_identifier (pp, t); - } + pp_cxx_tree_identifier (pp, t); break; diff -p -U2 -r ./cp/decl.c /data/users/nathans/modules/src/gcc/cp/decl.c --- ./cp/decl.c 2017-06-29 04:12:52.657865521 -0700 +++ /data/users/nathans/modules/src/gcc/cp/decl.c 2017-06-29 04:13:36.819893373 -0700 @@ -3956,14 +3965,14 @@ initialize_predefined_identifiers (void) impossible for them to conflict with names written by users. */ {"__ct ", &ctor_identifier, cik_ctor}, - {"__base_ctor ", &base_ctor_identifier, cik_ctor}, - {"__comp_ctor ", &complete_ctor_identifier, cik_ctor}, + {"__ct_base ", &base_ctor_identifier, cik_ctor}, + {"__ct_comp ", &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}, + {"__dt_base ", &base_dtor_identifier, cik_dtor}, + {"__dt_comp ", &complete_dtor_identifier, cik_dtor}, + {"__dt_del ", &deleting_dtor_identifier, cik_dtor}, + {"__in_chrg", &in_charge_identifier, cik_normal}, + {"this", &this_identifier, cik_normal}, + {"__delta", &delta_identifier, cik_normal}, + {"__pfn", &pfn_identifier, cik_normal}, {"_vptr", &vptr_identifier, cik_normal}, {"__vtt_parm", &vtt_parm_identifier, cik_normal}, @@ -4095,5 +4111,5 @@ cxx_init_decl_processing (void) vtable_entry_type = build_pointer_type (vfunc_type); } - record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type); + record_builtin_type (RID_MAX, "__vtbl_ptr_type", vtable_entry_type); vtbl_type_node @@ -8503,7 +8515,9 @@ grokfndecl (tree ctype, SET_DECL_ALIGN (decl, MINIMUM_METHOD_BOUNDARY); } + DECL_ARGUMENTS (decl) = parms; for (t = parms; t; t = DECL_CHAIN (t)) DECL_CONTEXT (t) = decl; + /* Propagate volatile out from type to decl. */ if (TYPE_VOLATILE (type)) @@ -8525,11 +8541,9 @@ grokfndecl (tree ctype, } - if (friendp - && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR) + if (friendp && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR) { if (funcdef_flag) - error - ("defining explicit specialization %qD in friend declaration", - orig_declarator); + error ("defining explicit specialization %qD in friend declaration", + orig_declarator); else { @@ -8581,14 +8595,16 @@ grokfndecl (tree ctype, /* `main' and builtins have implicit 'C' linkage. */ - if ((MAIN_NAME_P (declarator) - || (IDENTIFIER_LENGTH (declarator) > 10 - && IDENTIFIER_POINTER (declarator)[0] == '_' - && IDENTIFIER_POINTER (declarator)[1] == '_' - && strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0) - || (targetcm.cxx_implicit_extern_c - && targetcm.cxx_implicit_extern_c(IDENTIFIER_POINTER (declarator)))) + if (ctype == NULL_TREE + && DECL_FILE_SCOPE_P (decl) && current_lang_name == lang_name_cplusplus - && ctype == NULL_TREE - && DECL_FILE_SCOPE_P (decl)) + && (MAIN_NAME_P (declarator) + || (IDENTIFIER_LENGTH (declarator) > 10 + && IDENTIFIER_POINTER (declarator)[0] == '_' + && IDENTIFIER_POINTER (declarator)[1] == '_' + && strncmp (IDENTIFIER_POINTER (declarator)+2, + "builtin_", 8) == 0) + || (targetcm.cxx_implicit_extern_c + && (targetcm.cxx_implicit_extern_c + (IDENTIFIER_POINTER (declarator)))))) SET_DECL_LANGUAGE (decl, lang_c); @@ -9133,5 +9151,4 @@ build_ptrmemfunc_type (tree type) simple equality check on the list of field members. */ - t = TYPE_PTRMEMFUNC_TYPE (type); if (t) @@ -10069,6 +10086,4 @@ grokdeclarator (const cp_declarator *dec case BIT_NOT_EXPR: { - tree type; - if (innermost_code != cdk_function) { @@ -10083,5 +10098,5 @@ grokdeclarator (const cp_declarator *dec } - type = TREE_OPERAND (decl, 0); + tree type = TREE_OPERAND (decl, 0); if (TYPE_P (type)) type = constructor_name (type); diff -p -U2 -r ./cp/decl2.c /data/users/nathans/modules/src/gcc/cp/decl2.c --- ./cp/decl2.c 2017-06-20 05:56:53.977776790 -0700 +++ /data/users/nathans/modules/src/gcc/cp/decl2.c 2017-06-22 08:40:53.100097292 -0700 @@ -1993,5 +1995,6 @@ decl_needed_p (tree decl) whether or not to emit it into the object file. */ if (TREE_USED (decl)) - return true; + return true; + /* Virtual functions might be needed for devirtualization. */ if (flag_devirtualize @@ -1999,4 +2002,5 @@ decl_needed_p (tree decl) && DECL_VIRTUAL_P (decl)) return true; + /* Otherwise, DECL does not need to be emitted -- yet. A subsequent reference to DECL might cause it to be emitted later. */ @@ -4804,5 +4806,4 @@ c_parse_final_cleanups (void) finish_repo (); - fini_constexpr (); Only in /data/users/nathans/modules/src/gcc/cp: fnfields.diff diff -p -U2 -r ./cp/lex.c /data/users/nathans/modules/src/gcc/cp/lex.c --- ./cp/lex.c 2017-06-28 06:34:12.298399329 -0700 +++ /data/users/nathans/modules/src/gcc/cp/lex.c 2017-06-22 10:01:29.141924137 -0700 @@ -739,22 +741,22 @@ copy_type (tree type MEM_STAT_DECL) /* Add a raw lang_type to T, a type, should it need one. */ -static bool +static bool maybe_add_lang_type_raw (tree t) { - bool add = (RECORD_OR_UNION_CODE_P (TREE_CODE (t)) - || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM); - if (add) - { - TYPE_LANG_SPECIFIC (t) - = (struct lang_type *) (ggc_internal_cleared_alloc - (sizeof (struct lang_type))); + if (!(RECORD_OR_UNION_CODE_P (TREE_CODE (t)) + || TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)) + return false; + + TYPE_LANG_SPECIFIC (t) + = (struct lang_type *) (ggc_internal_cleared_alloc + (sizeof (struct lang_type))); - if (GATHER_STATISTICS) - { - tree_node_counts[(int)lang_type] += 1; - tree_node_sizes[(int)lang_type] += sizeof (struct lang_type); - } + if (GATHER_STATISTICS) + { + tree_node_counts[(int)lang_type] += 1; + tree_node_sizes[(int)lang_type] += sizeof (struct lang_type); } - return add; + + return true; } Only in /data/users/nathans/modules/src/gcc/cp: method-vec-wip.diff diff -p -U2 -r ./cp/method.c /data/users/nathans/modules/src/gcc/cp/method.c --- ./cp/method.c 2017-06-26 07:48:57.522383330 -0700 +++ /data/users/nathans/modules/src/gcc/cp/method.c 2017-06-28 11:20:24.519984085 -0700 @@ -1983,5 +1983,4 @@ implicitly_declare_fn (special_function_ case sfk_inheriting_constructor: { - bool move_p; if (kind == sfk_copy_assignment || kind == sfk_move_assignment) @@ -2001,6 +2000,6 @@ implicitly_declare_fn (special_function_ else rhs_parm_type = type; - move_p = (kind == sfk_move_assignment - || kind == sfk_move_constructor); + bool move_p = (kind == sfk_move_assignment + || kind == sfk_move_constructor); rhs_parm_type = cp_build_reference_type (rhs_parm_type, move_p); diff -p -U2 -r ./cp/name-lookup.c /data/users/nathans/modules/src/gcc/cp/name-lookup.c --- ./cp/name-lookup.c 2017-06-27 07:47:20.224342991 -0700 +++ /data/users/nathans/modules/src/gcc/cp/name-lookup.c 2017-06-28 09:52:50.840498101 -0700 @@ -3189,5 +3724,7 @@ tree constructor_name (tree type) { - return TYPE_IDENTIFIER (TYPE_MAIN_VARIANT (type)); + tree decl = TYPE_NAME (TYPE_MAIN_VARIANT (type)); + + return decl ? DECL_NAME (decl) : NULL_TREE; } @@ -3200,10 +3737,4 @@ constructor_name_p (tree name, tree type gcc_assert (MAYBE_CLASS_TYPE_P (type)); - if (!name) - return false; - - if (!identifier_p (name)) - return false; - /* These don't have names. */ if (TREE_CODE (type) == DECLTYPE_TYPE @@ -3211,6 +3742,5 @@ constructor_name_p (tree name, tree type return false; - tree ctor_name = constructor_name (type); - if (name == ctor_name) + if (name && name == constructor_name (type)) return true; @@ -3963,5 +4579,5 @@ push_class_level_binding_1 (tree name, t || (TREE_CODE (x) == FIELD_DECL && DECL_CONTEXT (x) != current_class_type)) - && DECL_NAME (x) == constructor_name (current_class_type)) + && DECL_NAME (x) == DECL_NAME (TYPE_NAME (current_class_type))) { tree scope = context_for_name_lookup (x); diff -p -U2 -r ./cp/parser.c /data/users/nathans/modules/src/gcc/cp/parser.c --- ./cp/parser.c 2017-06-29 04:12:52.659865522 -0700 +++ /data/users/nathans/modules/src/gcc/cp/parser.c 2017-06-29 04:13:37.953894088 -0700 @@ -20107,24 +20308,6 @@ cp_parser_direct_declarator (cp_parser* { tree name_type = TREE_TYPE (unqualified_name); - if (class_type && same_type_p (name_type, class_type)) - { - if (qualifying_scope - && CLASSTYPE_USE_TEMPLATE (name_type)) - { - error_at (declarator_id_start_token->location, - "invalid use of constructor as a template"); - inform (declarator_id_start_token->location, - "use %<%T::%D%> instead of %<%T::%D%> to " - "name the constructor in a qualified name", - class_type, - DECL_NAME (TYPE_TI_TEMPLATE (class_type)), - class_type, name_type); - declarator = cp_error_declarator; - break; - } - else - unqualified_name = constructor_name (class_type); - } - else + + if (!class_type || !same_type_p (name_type, class_type)) { /* We do not attempt to print the declarator @@ -20136,4 +20319,19 @@ cp_parser_direct_declarator (cp_parser* break; } + else if (qualifying_scope + && CLASSTYPE_USE_TEMPLATE (name_type)) + { + error_at (declarator_id_start_token->location, + "invalid use of constructor as a template"); + inform (declarator_id_start_token->location, + "use %<%T::%D%> instead of %<%T::%D%> to " + "name the constructor in a qualified name", + class_type, + DECL_NAME (TYPE_TI_TEMPLATE (class_type)), + class_type, name_type); + declarator = cp_error_declarator; + break; + } + unqualified_name = constructor_name (class_type); } @@ -20165,12 +20363,8 @@ cp_parser_direct_declarator (cp_parser* friend void N::S(); }; */ - && !(friend_p - && class_type != qualifying_scope) + && (!friend_p || class_type == qualifying_scope) && constructor_name_p (unqualified_name, class_type)) - { - unqualified_name = constructor_name (class_type); - sfk = sfk_constructor; - } + sfk = sfk_constructor; else if (is_overloaded_fn (unqualified_name) && DECL_CONSTRUCTOR_P (get_first_fn diff -p -U2 -r ./cp/search.c /data/users/nathans/modules/src/gcc/cp/search.c --- ./cp/search.c 2017-06-27 08:35:45.619037145 -0700 +++ /data/users/nathans/modules/src/gcc/cp/search.c 2017-06-28 15:41:44.447588266 -0700 @@ -508,8 +458,11 @@ current_scope (void) current_class_type)))) return current_function_decl; + if (current_class_type) return current_class_type; + if (current_function_decl) return current_function_decl; + return current_namespace; } Only in /data/users/nathans/modules/src/gcc/testsuite/g++.dg/cpp1y: builtin_FUNCTION.C