Hello,I was asked to handle (const) fenv_t and fexcept_t the same way as FILE and const tm. Since these have special handling in quite a few places, it seems necessary to make their support a bit more generic first. If I didn't mess up, this patch should not change anything.
Bootstrap + testsuite on powerpc64le-unknown-linux-gnu. 2017-06-22 Marc Glisse <marc.gli...@inria.fr> gcc/ * tree.h (predeclared_type): New type. (predeclared_types): Declare new array. * tree.c (predeclared_types): New array. (free_lang_data, build_common_tree_nodes): Use it. gcc/c-family/ * c-common.c (c_common_nodes_and_builtins): Use predeclared_types. gcc/cp/ * decl.c (duplicate_decls): Use predeclared_types. gcc/lto/ * lto-lang.c (lto_init): Use predeclared_types. -- Marc Glisse
Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 249495) +++ gcc/c-family/c-common.c (working copy) @@ -4174,24 +4174,27 @@ c_common_nodes_and_builtins (void) lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION, TYPE_DECL, get_identifier (buf), COMPLEX_FLOATN_NX_TYPE_NODE (i))); } if (c_dialect_cxx ()) { /* For C++, make fileptr_type_node a distinct void * type until - FILE type is defined. */ - fileptr_type_node = build_variant_type_copy (ptr_type_node); - /* Likewise for const struct tm*. */ - const_tm_ptr_type_node = build_variant_type_copy (const_ptr_type_node); + FILE type is defined. Likewise for const struct tm*. */ + for (unsigned i = 0; + i < sizeof (predeclared_types) / sizeof (predeclared_type); + ++i) + predeclared_types[i].node = + build_variant_type_copy (predeclared_types[i].base); + } record_builtin_type (RID_VOID, NULL, void_type_node); /* Set the TYPE_NAME for any variants that were built before record_builtin_type gave names to the built-in types. */ { tree void_name = TYPE_NAME (void_type_node); TYPE_NAME (void_type_node) = NULL_TREE; TYPE_NAME (build_qualified_type (void_type_node, TYPE_QUAL_CONST)) Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 249495) +++ gcc/cp/decl.c (working copy) @@ -1463,67 +1463,55 @@ duplicate_decls (tree newdecl, tree oldd is also extern "C". */ gcc_assert (DECL_IS_BUILTIN (olddecl)); gcc_assert (DECL_EXTERN_C_P (olddecl)); if (!DECL_EXTERN_C_P (newdecl)) return NULL_TREE; for (t1 = TYPE_ARG_TYPES (TREE_TYPE (newdecl)), 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 (predeclared_types) + / sizeof (predeclared_type); + ++i) + if (TREE_VALUE (t2) == predeclared_types[i].node) { - tree oldargs = TYPE_ARG_TYPES (TREE_TYPE (olddecl)); + tree t = TREE_VALUE (t1); - 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 (predeclared_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; } - } - /* Likewise for const struct tm*. */ - else if (TREE_VALUE (t2) == const_tm_ptr_type_node) - { - 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; - } - } - 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, "declaration of %q+#D conflicts with built-in " "declaration %q#D", newdecl, olddecl); } else if ((DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl)) || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), TYPE_ARG_TYPES (TREE_TYPE (olddecl)))) Index: gcc/lto/lto-lang.c =================================================================== --- gcc/lto/lto-lang.c (revision 249495) +++ gcc/lto/lto-lang.c (working copy) @@ -1213,27 +1213,30 @@ lto_init (void) /* The global tree for the main identifier is filled in by language-specific front-end initialization that is not run in the LTO back-end. It appears that all languages that perform such initialization currently do so in the same way, so we do it here. */ if (main_identifier_node == NULL_TREE) main_identifier_node = get_identifier ("main"); /* In the C++ front-end, fileptr_type_node is defined as a variant copy of ptr_type_node, rather than ptr_node itself. The distinction should only be relevant to the front-end, so we - always use the C definition here in lto1. */ - gcc_assert (fileptr_type_node == ptr_type_node); - gcc_assert (TYPE_MAIN_VARIANT (fileptr_type_node) == ptr_type_node); - /* Likewise for const struct tm*. */ - gcc_assert (const_tm_ptr_type_node == const_ptr_type_node); - gcc_assert (TYPE_MAIN_VARIANT (const_tm_ptr_type_node) - == const_ptr_type_node); + always use the C definition here in lto1. + Likewise for const struct tm*. */ + for (unsigned i = 0; + i < sizeof (predeclared_types) / sizeof (predeclared_type); + ++i) + { + gcc_assert (predeclared_types[i].node == predeclared_types[i].base); + gcc_assert (TYPE_MAIN_VARIANT (predeclared_types[i].node) + == predeclared_types[i].base); + } lto_build_c_type_nodes (); gcc_assert (va_list_type_node); if (TREE_CODE (va_list_type_node) == ARRAY_TYPE) { tree x = build_pointer_type (TREE_TYPE (va_list_type_node)); lto_define_builtins (x, x); } else Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 249495) +++ gcc/tree.c (working copy) @@ -5976,22 +5976,24 @@ free_lang_data (void) while the slots are still in the way the frontends generated them. */ for (i = 0; i < itk_none; ++i) if (integer_types[i]) TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]); /* Traverse the IL resetting language specific information for operands, expressions, etc. */ free_lang_data_in_cgraph (); /* Create gimple variants for common types. */ - fileptr_type_node = ptr_type_node; - const_tm_ptr_type_node = const_ptr_type_node; + for (unsigned i = 0; + i < sizeof (predeclared_types) / sizeof (predeclared_type); + ++i) + predeclared_types[i].node = predeclared_types[i].base; /* Reset some langhooks. Do not reset types_compatible_p, it may still be used indirectly via the get_alias_set langhook. */ lang_hooks.dwarf_name = lhd_dwarf_name; lang_hooks.decl_printable_name = gimple_decl_printable_name; lang_hooks.gimplify_expr = lhd_gimplify_expr; /* We do not want the default decl_assembler_name implementation, rather if we have fixed everything we want a wrapper around it asserting that all non-local symbols already got their assembler @@ -10442,22 +10444,24 @@ build_common_tree_nodes (bool signed_cha void_node = make_node (VOID_CST); TREE_TYPE (void_node) = void_type_node; null_pointer_node = build_int_cst (build_pointer_type (void_type_node), 0); layout_type (TREE_TYPE (null_pointer_node)); ptr_type_node = build_pointer_type (void_type_node); const_ptr_type_node = build_pointer_type (build_type_variant (void_type_node, 1, 0)); - fileptr_type_node = ptr_type_node; - const_tm_ptr_type_node = const_ptr_type_node; + for (unsigned i = 0; + i < sizeof (predeclared_types) / sizeof (predeclared_type); + ++i) + predeclared_types[i].node = predeclared_types[i].base; pointer_sized_int_node = build_nonstandard_integer_type (POINTER_SIZE, 1); float_type_node = make_node (REAL_TYPE); TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE; layout_type (float_type_node); double_type_node = make_node (REAL_TYPE); TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE; layout_type (double_type_node); @@ -14537,20 +14541,30 @@ get_nonnull_args (const_tree fntype) for (tree idx = TREE_VALUE (attrs); idx; idx = TREE_CHAIN (idx)) { unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (idx)) - 1; bitmap_set_bit (argmap, val); } } return argmap; } +/* List of pointer types used to declare builtins before we have seen their + real declaration. + + Keep the size up to date in tree.h ! */ +const predeclared_type predeclared_types[2] = +{ + { fileptr_type_node, ptr_type_node, "FILE" }, + { const_tm_ptr_type_node, const_ptr_type_node, "tm" } +}; + #if CHECKING_P namespace selftest { /* Selftests for tree. */ /* Verify that integer constants are sane. */ static void test_integer_constants () Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 249495) +++ gcc/tree.h (working copy) @@ -5516,11 +5516,20 @@ desired_pro_or_demotion_p (const_tree to unsigned int to_type_precision = TYPE_PRECISION (to_type); /* OK to promote if to_type is no bigger than word_mode. */ if (to_type_precision <= GET_MODE_PRECISION (word_mode)) return true; /* Otherwise, allow only if narrowing or same precision conversions. */ return to_type_precision <= TYPE_PRECISION (from_type); } +/* Pointer type used to declare builtins before we have seen its real + declaration. */ +struct predeclared_type +{ + tree& node; + tree& base; + const char *str; +}; +extern const predeclared_type predeclared_types[2]; #endif /* GCC_TREE_H */