This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
On 10/17/16 20:05, Joseph Myers wrote: > On Sun, 16 Oct 2016, Bernd Edlinger wrote: > >> Second, the declaration in the glibc header files simply look wrong, >> because the type of argv, and envp is "char *const *" while the >> builtin function wants "const char**", thus only the array of char* >> itself is const, not the actual char stings they point to. > > char *const * is the POSIX type. (It can't be const char ** or const char > *const * because you can't convert char ** implicitly to those types in > ISO C.) You'd need to check the list archives for rationale for the > built-in functions doing something different. > Yes, that was discussed here: https://gcc.gnu.org/ml/gcc-patches/2004-03/msg01148.html No mention why the BT_PTR_CONST_TYPE does not match the posix type. But the right types were used on __gcov_execv/e/p stubs, so the author did know the right types at least. So I think that was broken from the beginning, but that was hidden by the loose checking in the C FE and not warning in the C++ FE when prototypes don't match. >> Third, in C the builtins are not diagnosed, because C does only look >> at the mode of the parameters see match_builtin_function_types in >> c/c-decl.c, which may itself be wrong, because that makes an ABI >> decision dependent on the mode of the parameter. > > The matching needs to be loose because of functions using types such as > FILE * where the compiler doesn't know the exact contents of the type when > processing built-in function definitions. (Historically there were also > issues with pre-ISO headers, but that may be less relevant now.) > The C++ FE has exactly the same problem with FILE* and struct tm* but it solves it differently and "learns" the type but only for FILE* and with this patch also for const struct tm*. It is a lot more restrictive than C, but that is because of the ++ ;) Well in that case the posix functions have to use the prototypes from POSIX.1.2008 although their rationale is a bit silly... This updated patch fixes the prototype of execv/p/e, and adds a new test case that checks that no type conflict exists in the execve built-in any more. Now we have no -Wsystem-headers warnings with glibc-headers any more. And the gcov builtin also is working with C++. Bootstrapped and reg-tested on x86_64-pc-linux-gnu. Is it OK for trunk? Thanks Bernd.
Attachment:
changelog-pr71973.txt
Description: changelog-pr71973.txt
Index: gcc/builtin-types.def =================================================================== --- gcc/builtin-types.def (revision 241271) +++ gcc/builtin-types.def (working copy) @@ -103,6 +103,7 @@ DEF_PRIMITIVE_TYPE (BT_COMPLEX_LONGDOUBLE, complex DEF_PRIMITIVE_TYPE (BT_PTR, ptr_type_node) DEF_PRIMITIVE_TYPE (BT_FILEPTR, fileptr_type_node) +DEF_PRIMITIVE_TYPE (BT_CONST_TM_PTR, const_tm_ptr_type_node) DEF_PRIMITIVE_TYPE (BT_CONST_PTR, const_ptr_type_node) DEF_PRIMITIVE_TYPE (BT_VOLATILE_PTR, build_pointer_type @@ -146,7 +147,12 @@ DEF_PRIMITIVE_TYPE (BT_I16, builtin_type_for_size DEF_PRIMITIVE_TYPE (BT_BND, pointer_bounds_type_node) -DEF_POINTER_TYPE (BT_PTR_CONST_STRING, BT_CONST_STRING) +/* The C type `char * const *'. */ +DEF_PRIMITIVE_TYPE (BT_PTR_CONST_STRING, + build_pointer_type + (build_qualified_type (string_type_node, + TYPE_QUAL_CONST))) + DEF_POINTER_TYPE (BT_PTR_UINT, BT_UINT) DEF_POINTER_TYPE (BT_PTR_LONG, BT_LONG) DEF_POINTER_TYPE (BT_PTR_ULONG, BT_ULONG) @@ -511,8 +517,8 @@ DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZ BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR) DEF_FUNCTION_TYPE_4 (BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG, BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING, BT_VALIST_ARG) -DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, - BT_SIZE, BT_STRING, BT_SIZE, BT_CONST_STRING, BT_CONST_PTR) +DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_TM_PTR, + BT_SIZE, BT_STRING, BT_SIZE, BT_CONST_STRING, BT_CONST_TM_PTR) DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, BT_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE, BT_SIZE) DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_INT_SIZE_SIZE, Index: gcc/builtins.def =================================================================== --- gcc/builtins.def (revision 241271) +++ gcc/builtins.def (working copy) @@ -866,7 +866,7 @@ DEF_GCC_BUILTIN (BUILT_IN_RETURN_ADDRESS, " DEF_GCC_BUILTIN (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL) DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_RT_NOTHROW_LEAF_LIST) DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_STRFMON_NOTHROW_3_4) -DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0) +DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_TM_PTR, ATTR_FORMAT_STRFTIME_NOTHROW_3_0) DEF_GCC_BUILTIN (BUILT_IN_TRAP, "trap", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_UNREACHABLE, "unreachable", BT_FN_VOID, ATTR_CONST_NORETURN_NOTHROW_LEAF_LIST) DEF_GCC_BUILTIN (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, ATTR_NULL) Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 241271) +++ gcc/c-family/c-common.c (working copy) @@ -4278,9 +4278,13 @@ c_common_nodes_and_builtins (void) } 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); + { + /* 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); + } record_builtin_type (RID_VOID, NULL, void_type_node); Index: gcc/c-family/c.opt =================================================================== --- gcc/c-family/c.opt (revision 241271) +++ gcc/c-family/c.opt (working copy) @@ -323,6 +323,10 @@ Wframe-address C ObjC C++ ObjC++ Var(warn_frame_address) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn when __builtin_frame_address or __builtin_return_address is used unsafely. +Wbuiltin-function-redefined +C++ ObjC++ Var(warn_builtin_function_redefined) Warning LangEnabledBy(C++ ObjC++,Wall) +Warn when a built-in function is redefined. + Wbuiltin-macro-redefined C ObjC C++ ObjC++ CPP(warn_builtin_macro_redefined) CppReason(CPP_W_BUILTIN_MACRO_REDEFINED) Var(cpp_warn_builtin_macro_redefined) Init(1) Warning Warn when a built-in preprocessor macro is undefined or redefined. Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 241271) +++ gcc/cp/decl.c (working copy) @@ -1489,10 +1489,15 @@ duplicate_decls (tree newdecl, tree olddecl, bool explicitly declared. */ if (DECL_ANTICIPATED (olddecl)) { - /* Deal with fileptr_type_node. FILE type is not known - at the time we create the builtins. */ tree t1, t2; + /* A new declaration doesn't match a built-in one unless it + 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; @@ -1499,6 +1504,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool 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); @@ -1519,8 +1526,34 @@ duplicate_decls (tree newdecl, tree olddecl, bool 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); + + 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; + + warning_at (DECL_SOURCE_LOCATION (newdecl), + OPT_Wbuiltin_function_redefined, + "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)) @@ -1574,7 +1607,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool /* Whether or not the builtin can throw exceptions has no bearing on this declarator. */ - TREE_NOTHROW (olddecl) = 0; + TREE_NOTHROW (olddecl) = TREE_NOTHROW (newdecl); if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl)) { Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 241271) +++ gcc/doc/invoke.texi (working copy) @@ -256,7 +256,7 @@ Objective-C and Objective-C++ Dialects}. -pedantic-errors @gol -w -Wextra -Wall -Waddress -Waggregate-return @gol -Wno-aggressive-loop-optimizations -Warray-bounds -Warray-bounds=@var{n} @gol --Wno-attributes -Wbool-compare -Wbool-operation @gol +-Wno-attributes -Wbool-compare -Wbool-operation -Wbuiltin-function-redefined @gol -Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol -Wc++-compat -Wc++11-compat -Wc++14-compat -Wcast-align -Wcast-qual @gol -Wchar-subscripts -Wclobbered -Wcomment -Wconditionally-supported @gol @@ -3673,6 +3673,7 @@ Options} and @ref{Objective-C and Objective-C++ Di -Warray-bounds=1 @r{(only with} @option{-O2}@r{)} @gol -Wbool-compare @gol -Wbool-operation @gol +-Wbuiltin-function-redefined @r{(C++ and Objective-C++ only)} @gol -Wc++11-compat -Wc++14-compat@gol -Wchar-subscripts @gol -Wcomment @gol @@ -5793,6 +5794,13 @@ unrecognized attributes, function attributes appli etc. This does not stop errors for incorrect use of supported attributes. +@item -Wbuiltin-function-redefined @r{(C++ and Objective-C++ only)} +@opindex Wbuiltin-function-redefined +@opindex Wno-builtin-function-redefined +Do warn if built-in functions are redefined. This option is only +supported for C++ and Objective-C++. It is implied by @option{-Wall}, +which can be disabled with @option{-Wno-builtin-function-redefined}. + @item -Wno-builtin-macro-redefined @opindex Wno-builtin-macro-redefined @opindex Wbuiltin-macro-redefined Index: gcc/lto/lto-lang.c =================================================================== --- gcc/lto/lto-lang.c (revision 241271) +++ gcc/lto/lto-lang.c (working copy) @@ -1266,6 +1266,10 @@ lto_init (void) 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); ptrdiff_type_node = integer_type_node; Index: gcc/testsuite/g++.dg/lookup/extern-c-redecl4.C =================================================================== --- gcc/testsuite/g++.dg/lookup/extern-c-redecl4.C (revision 241271) +++ gcc/testsuite/g++.dg/lookup/extern-c-redecl4.C (working copy) @@ -3,7 +3,6 @@ // { dg-options "" } // { dg-do compile } -// { dg-final { scan-assembler "call\[\t \]+\[^\$\]*?_Z4forkv" { target i?86-*-* x86_64-*-* } } } class frok { @@ -14,5 +13,5 @@ class frok void foo () { - fork (); + fork (); // { dg-error "was not declared in this scope" } } Index: gcc/testsuite/g++.dg/pr71973-1.C =================================================================== --- gcc/testsuite/g++.dg/pr71973-1.C (revision 0) +++ gcc/testsuite/g++.dg/pr71973-1.C (working copy) @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-Wall -fdump-tree-eh" } + +extern "C" +void fork () // { dg-warning "conflicts with built-in declaration" } +__attribute__ ((__nothrow__)); + +void foo () throw () +{ + fork (); +} + +// { dg-final { scan-tree-dump-not "eh_dispatch" "eh" } } +// { dg-final { scan-tree-dump-not "resx" "eh" } } Index: gcc/testsuite/g++.dg/pr71973-2.C =================================================================== --- gcc/testsuite/g++.dg/pr71973-2.C (revision 0) +++ gcc/testsuite/g++.dg/pr71973-2.C (working copy) @@ -0,0 +1,18 @@ +// { dg-do compile } +// { dg-options "-Wall -fdump-tree-eh" } + +typedef __SIZE_TYPE__ size_t; +struct tm; + +extern "C" +size_t strftime (char*, size_t, const char*, const struct tm*) +__attribute__ ((__nothrow__)); + +void foo () throw () +{ + strftime (0,0,0,0); // { dg-warning "null argument where non-null required" } + // { dg-warning "too many arguments for format" "" { target *-*-* } .-1 } +} + +// { dg-final { scan-tree-dump-not "eh_dispatch" "eh" } } +// { dg-final { scan-tree-dump-not "resx" "eh" } } Index: gcc/testsuite/g++.dg/pr71973-3.C =================================================================== --- gcc/testsuite/g++.dg/pr71973-3.C (revision 0) +++ gcc/testsuite/g++.dg/pr71973-3.C (working copy) @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-Wall -fdump-tree-eh" } + +extern "C" +int execve (const char *__path, char *const __argv[], char *const __envp[]) +__attribute__ ((__nothrow__)); + +void foo () throw () +{ + execve (0,0,0); +} + +// { dg-final { scan-tree-dump-not "eh_dispatch" "eh" } } +// { dg-final { scan-tree-dump-not "resx" "eh" } } Index: gcc/tree-core.h =================================================================== --- gcc/tree-core.h (revision 241271) +++ gcc/tree-core.h (working copy) @@ -615,6 +615,7 @@ enum tree_index { TI_VA_LIST_FPR_COUNTER_FIELD, TI_BOOLEAN_TYPE, TI_FILEPTR_TYPE, + TI_CONST_TM_PTR_TYPE, TI_POINTER_SIZED_TYPE, TI_POINTER_BOUNDS_TYPE, Index: gcc/tree.c =================================================================== --- gcc/tree.c (revision 241271) +++ gcc/tree.c (working copy) @@ -6006,6 +6006,7 @@ free_lang_data (void) /* Create gimple variants for common types. */ ptrdiff_type_node = integer_type_node; fileptr_type_node = ptr_type_node; + const_tm_ptr_type_node = const_ptr_type_node; /* Reset some langhooks. Do not reset types_compatible_p, it may still be used indirectly via the get_alias_set langhook. */ @@ -10310,6 +10311,7 @@ build_common_tree_nodes (bool signed_char) 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; pointer_sized_int_node = build_nonstandard_integer_type (POINTER_SIZE, 1); Index: gcc/tree.h =================================================================== --- gcc/tree.h (revision 241271) +++ gcc/tree.h (working copy) @@ -3667,6 +3667,8 @@ tree_operand_check_code (const_tree __t, enum tree #define va_list_fpr_counter_field global_trees[TI_VA_LIST_FPR_COUNTER_FIELD] /* The C type `FILE *'. */ #define fileptr_type_node global_trees[TI_FILEPTR_TYPE] +/* The C type `const struct tm *'. */ +#define const_tm_ptr_type_node global_trees[TI_CONST_TM_PTR_TYPE] #define pointer_sized_int_node global_trees[TI_POINTER_SIZED_TYPE] #define boolean_type_node global_trees[TI_BOOLEAN_TYPE]
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |