Hi! I've backorted following 10 patches from trunk to 9 branch, bootstrapped/regtested them on x86_64-linux and i686-linux and committed.
Jakub
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-10-21 Jakub Jelinek <ja...@redhat.com> PR c++/92015 * constexpr.c (cxx_eval_component_reference, cxx_eval_bit_field_ref): Use STRIP_ANY_LOCATION_WRAPPER on CONSTRUCTOR elts. * g++.dg/cpp0x/constexpr-92015.C: New test. --- gcc/cp/constexpr.c (revision 277266) +++ gcc/cp/constexpr.c (revision 277267) @@ -2887,7 +2887,10 @@ cxx_eval_component_reference (const cons : field == part) { if (value) - return value; + { + STRIP_ANY_LOCATION_WRAPPER (value); + return value; + } else /* We're in the middle of initializing it. */ break; @@ -2977,6 +2980,7 @@ cxx_eval_bit_field_ref (const constexpr_ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value) { tree bitpos = bit_position (field); + STRIP_ANY_LOCATION_WRAPPER (value); if (bitpos == start && DECL_SIZE (field) == TREE_OPERAND (t, 1)) return value; if (TREE_CODE (TREE_TYPE (field)) == INTEGER_TYPE --- gcc/testsuite/g++.dg/cpp0x/constexpr-92015.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp0x/constexpr-92015.C (revision 277267) @@ -0,0 +1,7 @@ +// PR c++/92015 +// { dg-do compile { target c++11 } } + +struct S1 { char c[6] {'h', 'e', 'l', 'l', 'o', 0}; }; +struct S2 { char c[6] = "hello"; }; +static_assert (S1{}.c[0] == 'h', ""); +static_assert (S2{}.c[0] == 'h', "");
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-10-22 Tamar Christina <tamar.christ...@arm.com> PR sanitizer/92154 * sanitizer_common/sanitizer_platform_limits_posix.cc: Cherry-pick compiler-rt revision r375220. --- libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc (revision 277290) +++ libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc (revision 277291) @@ -1126,8 +1126,12 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, uid); CHECK_SIZE_AND_OFFSET(ipc_perm, gid); CHECK_SIZE_AND_OFFSET(ipc_perm, cuid); CHECK_SIZE_AND_OFFSET(ipc_perm, cgid); -#if !defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21) +#if (!defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \ + !defined(__arm__) /* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */ +/* On Arm glibc 2.31 and later provide a different mode field, this field is + never used by libsanitizer so we can simply ignore this assert for all glibc + versions. */ CHECK_SIZE_AND_OFFSET(ipc_perm, mode); #endif
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-10-22 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/85887 * decl.c (expand_static_init): Drop ECF_LEAF from __cxa_guard_acquire and __cxa_guard_release. --- gcc/cp/decl.c (revision 277292) +++ gcc/cp/decl.c (revision 277293) @@ -8589,14 +8589,14 @@ expand_static_init (tree decl, tree init (acquire_name, build_function_type_list (integer_type_node, TREE_TYPE (guard_addr), NULL_TREE), - NULL_TREE, ECF_NOTHROW | ECF_LEAF); + NULL_TREE, ECF_NOTHROW); if (!release_fn || !abort_fn) vfntype = build_function_type_list (void_type_node, TREE_TYPE (guard_addr), NULL_TREE); if (!release_fn) release_fn = push_library_fn (release_name, vfntype, NULL_TREE, - ECF_NOTHROW | ECF_LEAF); + ECF_NOTHROW); if (!abort_fn) abort_fn = push_library_fn (abort_name, vfntype, NULL_TREE, ECF_NOTHROW | ECF_LEAF);
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-10-27 Jakub Jelinek <ja...@redhat.com> * locales.c (iso_3166): Add missing comma after "United-States". --- gcc/ada/locales.c (revision 277491) +++ gcc/ada/locales.c (revision 277492) @@ -529,7 +529,7 @@ static char* iso_3166[] = "UM", "United States Minor Outlying Islands", "US", "United States", "US", "United States of America", - "US", "United-States" + "US", "United-States", "UY", "Uruguay", "UZ", "Uzbekistan",
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-10-29 Jakub Jelinek <ja...@redhat.com> * doc/install.texi (--enable-offload-targets): Fix up a typo in the example, use actual names of supported offload targets. --- gcc/doc/install.texi (revision 277551) +++ gcc/doc/install.texi (revision 277552) @@ -2158,7 +2158,7 @@ specifying paths @var{path1}, @dots{}, @ @smallexample % @var{srcdir}/configure \ - --enable-offload-target=i686-unknown-linux-gnu=/path/to/i686/compiler,x86_64-pc-linux-gnu + --enable-offload-targets=x86_64-intelmicemul-linux-gnu=/path/to/x86_64/compiler,nvptx-none,hsa @end smallexample If @samp{hsa} is specified as one of the targets, the compiler will be
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-10-31 Jakub Jelinek <ja...@redhat.com> PR c++/90947 * tree.h (type_initializer_zero_p): Remove. * tree.c (type_initializer_zero_p): Remove. * cp-tree.h (type_initializer_zero_p): Declare. * decl.c (reshape_init_array_1): Formatting fix. * tree.c (type_initializer_zero_p): New function. Moved from ../tree.c, use next_initializable_field, formatting fix. Return false for TYPE_NON_AGGREGATE_CLASS types. --- gcc/tree.c (revision 277655) +++ gcc/tree.c (revision 277656) @@ -11123,73 +11123,6 @@ initializer_each_zero_or_onep (const_tre } } -/* Given an initializer INIT for a TYPE, return true if INIT is zero - so that it can be replaced by value initialization. This function - distinguishes betwen empty strings as initializers for arrays and - for pointers (which make it return false). */ - -bool -type_initializer_zero_p (tree type, tree init) -{ - if (type == error_mark_node || init == error_mark_node) - return false; - - STRIP_NOPS (init); - - if (POINTER_TYPE_P (type)) - return TREE_CODE (init) != STRING_CST && initializer_zerop (init); - - if (TREE_CODE (init) != CONSTRUCTOR) - return initializer_zerop (init); - - if (TREE_CODE (type) == ARRAY_TYPE) - { - tree elt_type = TREE_TYPE (type); - elt_type = TYPE_MAIN_VARIANT (elt_type); - if (elt_type == char_type_node) - return initializer_zerop (init); - - tree elt_init; - unsigned HOST_WIDE_INT i; - FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init) - if (!type_initializer_zero_p (elt_type, elt_init)) - return false; - return true; - } - - if (TREE_CODE (type) != RECORD_TYPE) - return initializer_zerop (init); - - tree fld = TYPE_FIELDS (type); - - tree fld_init; - unsigned HOST_WIDE_INT i; - FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init) - { - /* Advance to the next member, skipping over everything that - canot be initialized (including unnamed bit-fields). */ - while (TREE_CODE (fld) != FIELD_DECL - || DECL_ARTIFICIAL (fld) - || (DECL_BIT_FIELD (fld) && !DECL_NAME (fld))) - { - fld = DECL_CHAIN (fld); - if (!fld) - return true; - continue; - } - - tree fldtype = TREE_TYPE (fld); - if (!type_initializer_zero_p (fldtype, fld_init)) - return false; - - fld = DECL_CHAIN (fld); - if (!fld) - break; - } - - return true; -} - /* Check if vector VEC consists of all the equal elements and that the number of elements corresponds to the type of VEC. The function returns first element of the vector --- gcc/tree.h (revision 277655) +++ gcc/tree.h (revision 277656) @@ -4690,12 +4690,6 @@ extern tree first_field (const_tree); extern bool initializer_zerop (const_tree, bool * = NULL); extern bool initializer_each_zero_or_onep (const_tree); -/* Analogous to initializer_zerop but also examines the type for - which the initializer is being used. Unlike initializer_zerop, - considers empty strings to be zero initializers for arrays and - non-zero for pointers. */ -extern bool type_initializer_zero_p (tree, tree); - extern wide_int vector_cst_int_elt (const_tree, unsigned int); extern tree vector_cst_elt (const_tree, unsigned int); --- gcc/cp/decl.c (revision 277655) +++ gcc/cp/decl.c (revision 277656) @@ -5973,9 +5973,8 @@ reshape_init_array_1 (tree elt_type, tre /* Pointers initialized to strings must be treated as non-zero even if the string is empty. */ tree init_type = TREE_TYPE (elt_init); - if ((POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type))) - last_nonzero = index; - else if (!type_initializer_zero_p (elt_type, elt_init)) + if (POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type) + || !type_initializer_zero_p (elt_type, elt_init)) last_nonzero = index; /* This can happen with an invalid initializer (c++/54501). */ --- gcc/cp/tree.c (revision 277655) +++ gcc/cp/tree.c (revision 277656) @@ -5540,6 +5540,68 @@ maybe_warn_zero_as_null_pointer_constant return false; } +/* Given an initializer INIT for a TYPE, return true if INIT is zero + so that it can be replaced by value initialization. This function + distinguishes betwen empty strings as initializers for arrays and + for pointers (which make it return false). */ + +bool +type_initializer_zero_p (tree type, tree init) +{ + if (type == error_mark_node || init == error_mark_node) + return false; + + STRIP_NOPS (init); + + if (POINTER_TYPE_P (type)) + return TREE_CODE (init) != STRING_CST && initializer_zerop (init); + + if (TREE_CODE (init) != CONSTRUCTOR) + return initializer_zerop (init); + + if (TREE_CODE (type) == ARRAY_TYPE) + { + tree elt_type = TREE_TYPE (type); + elt_type = TYPE_MAIN_VARIANT (elt_type); + if (elt_type == char_type_node) + return initializer_zerop (init); + + tree elt_init; + unsigned HOST_WIDE_INT i; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, elt_init) + if (!type_initializer_zero_p (elt_type, elt_init)) + return false; + return true; + } + + if (TREE_CODE (type) != RECORD_TYPE) + return initializer_zerop (init); + + if (TYPE_NON_AGGREGATE_CLASS (type)) + return false; + + tree fld = TYPE_FIELDS (type); + + tree fld_init; + unsigned HOST_WIDE_INT i; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), i, fld_init) + { + fld = next_initializable_field (fld); + if (!fld) + return true; + + tree fldtype = TREE_TYPE (fld); + if (!type_initializer_zero_p (fldtype, fld_init)) + return false; + + fld = DECL_CHAIN (fld); + if (!fld) + break; + } + + return true; +} + #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) /* Complain that some language-specific thing hanging off a tree node has been accessed improperly. */ --- gcc/cp/cp-tree.h (revision 277655) +++ gcc/cp/cp-tree.h (revision 277656) @@ -7382,6 +7382,11 @@ extern tree cxx_copy_lang_qualifiers (c extern void cxx_print_statistics (void); extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t); +/* Analogous to initializer_zerop but also examines the type for + which the initializer is being used. Unlike initializer_zerop, + considers empty strings to be zero initializers for arrays and + non-zero for pointers. */ +extern bool type_initializer_zero_p (tree, tree); /* in ptree.c */ extern void cxx_print_xnode (FILE *, tree, int); --- gcc/testsuite/g++.dg/init/array54.C (nonexistent) +++ gcc/testsuite/g++.dg/init/array54.C (revision 277656) @@ -0,0 +1,13 @@ +// PR c++/90947 +// { dg-do run { target c++11 } } + +#include <atomic> + +static std::atomic<int> a[1] { {1} }; + +int +main () +{ + if (a[0].load () != 1) + __builtin_abort (); +}
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-10-31 Jakub Jelinek <ja...@redhat.com> PR middle-end/92231 * tree.h (fndecl_built_in_p): Use fndecl_built_in_p instead of DECL_BUILT_IN in comment. Remove redundant ()s around return argument. * tree.c (free_lang_data_in_decl): Check if var is FUNCTION_DECL before calling fndecl_built_in_p. * gimple-fold.c (gimple_fold_stmt_to_constant_1): Check if TREE_OPERAND (fn, 0) is a FUNCTION_DECL before calling fndecl_built_in_p on it. * lto-lang.c (handle_const_attribute): Don't call fndecl_built_in_p on *node that is not FUNCTION_DECL. * gcc.c-torture/compile/pr92231.c: New test. --- gcc/tree.c (revision 277659) +++ gcc/tree.c (revision 277660) @@ -5805,7 +5805,8 @@ free_lang_data_in_decl (tree decl, class while (*nextp) { tree var = *nextp; - if (fndecl_built_in_p (var)) + if (TREE_CODE (var) == FUNCTION_DECL + && fndecl_built_in_p (var)) *nextp = TREE_CHAIN (var); else nextp = &TREE_CHAIN (var); --- gcc/tree.h (revision 277659) +++ gcc/tree.h (revision 277660) @@ -6119,12 +6119,12 @@ type_has_mode_precision_p (const_tree t) Note that it is different from the DECL_IS_BUILTIN accessor. For instance, user declared prototypes of C library functions are not - DECL_IS_BUILTIN but may be DECL_BUILT_IN. */ + DECL_IS_BUILTIN but may be fndecl_built_in_p. */ inline bool fndecl_built_in_p (const_tree node) { - return (DECL_BUILT_IN_CLASS (node) != NOT_BUILT_IN); + return DECL_BUILT_IN_CLASS (node) != NOT_BUILT_IN; } /* Return true if a FUNCTION_DECL NODE is a GCC built-in function @@ -6133,7 +6133,7 @@ fndecl_built_in_p (const_tree node) inline bool fndecl_built_in_p (const_tree node, built_in_class klass) { - return (fndecl_built_in_p (node) && DECL_BUILT_IN_CLASS (node) == klass); + return fndecl_built_in_p (node) && DECL_BUILT_IN_CLASS (node) == klass; } /* Return true if a FUNCTION_DECL NODE is a GCC built-in function --- gcc/gimple-fold.c (revision 277659) +++ gcc/gimple-fold.c (revision 277660) @@ -6439,6 +6439,7 @@ gimple_fold_stmt_to_constant_1 (gimple * fn = (*valueize) (gimple_call_fn (stmt)); if (TREE_CODE (fn) == ADDR_EXPR + && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL && fndecl_built_in_p (TREE_OPERAND (fn, 0)) && gimple_builtin_call_types_compatible_p (stmt, TREE_OPERAND (fn, 0))) --- gcc/lto/lto-lang.c (revision 277659) +++ gcc/lto/lto-lang.c (revision 277660) @@ -305,7 +305,8 @@ handle_const_attribute (tree *node, tree tree ARG_UNUSED (args), int ARG_UNUSED (flags), bool * ARG_UNUSED (no_add_attrs)) { - if (!fndecl_built_in_p (*node)) + if (TREE_CODE (*node) != FUNCTION_DECL + || !fndecl_built_in_p (*node)) inform (UNKNOWN_LOCATION, "%s:%s: %E: %E", __FILE__, __func__, *node, name); tree type = TREE_TYPE (*node); --- gcc/testsuite/gcc.c-torture/compile/pr92231.c (nonexistent) +++ gcc/testsuite/gcc.c-torture/compile/pr92231.c (revision 277660) @@ -0,0 +1,9 @@ +/* PR middle-end/92231 */ + +extern int bar (void); + +int +foo (void) +{ + return (&bar + 4096) (); +}
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-10-31 Jakub Jelinek <ja...@redhat.com> PR preprocessor/92296 * internal.h (struct def_pragma_macro): Add is_builtin bitfield. (_cpp_restore_special_builtin): Declare. * init.c (_cpp_restore_special_builtin): New function. * directives.c (do_pragma_push_macro): For NT_BUILTIN_MACRO set is_builtin and don't try to grab definition. (cpp_pop_definition): Use _cpp_restore_special_builtin to restore builtin macros. * c-c++-common/cpp/pr92296-1.c: New test. * c-c++-common/cpp/pr92296-2.c: New test. --- libcpp/directives.c (revision 277684) +++ libcpp/directives.c (revision 277685) @@ -1582,6 +1582,8 @@ do_pragma_push_macro (cpp_reader *pfile) node = _cpp_lex_identifier (pfile, c->name); if (node->type == NT_VOID) c->is_undef = 1; + else if (node->type == NT_BUILTIN_MACRO) + c->is_builtin = 1; else { defn = cpp_macro_definition (pfile, node); @@ -2470,6 +2472,11 @@ cpp_pop_definition (cpp_reader *pfile, s if (c->is_undef) return; + if (c->is_builtin) + { + _cpp_restore_special_builtin (pfile, c); + return; + } { size_t namelen; --- libcpp/init.c (revision 277684) +++ libcpp/init.c (revision 277685) @@ -497,6 +497,25 @@ cpp_init_special_builtins (cpp_reader *p } } +/* Restore macro C to builtin macro definition. */ + +void +_cpp_restore_special_builtin (cpp_reader *pfile, struct def_pragma_macro *c) +{ + size_t len = strlen (c->name); + + for (const struct builtin_macro *b = builtin_array; + b < builtin_array + ARRAY_SIZE (builtin_array); b++) + if (b->len == len && memcmp (c->name, b->name, len + 1) == 0) + { + cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len); + hp->type = NT_BUILTIN_MACRO; + if (b->always_warn_if_redefined) + hp->flags |= NODE_WARN; + hp->value.builtin = (enum cpp_builtin_type) b->value; + } +} + /* Read the builtins table above and enter them, and language-specific macros, into the hash table. HOSTED is true if this is a hosted environment. */ --- libcpp/internal.h (revision 277684) +++ libcpp/internal.h (revision 277685) @@ -391,6 +391,8 @@ struct def_pragma_macro { /* Mark if we save an undefined macro. */ unsigned int is_undef : 1; + /* Nonzero if it was a builtin macro. */ + unsigned int is_builtin : 1; }; /* A cpp_reader encapsulates the "state" of a pre-processor run. @@ -722,6 +724,8 @@ extern void *_cpp_commit_buff (cpp_reade /* In init.c. */ extern void _cpp_maybe_push_include_file (cpp_reader *); extern const char *cpp_named_operator2name (enum cpp_ttype type); +extern void _cpp_restore_special_builtin (cpp_reader *pfile, + struct def_pragma_macro *); /* In directives.c */ extern int _cpp_test_assertion (cpp_reader *, unsigned int *); --- gcc/testsuite/c-c++-common/cpp/pr92296-1.c (nonexistent) +++ gcc/testsuite/c-c++-common/cpp/pr92296-1.c (revision 277685) @@ -0,0 +1,32 @@ +/* PR preprocessor/92296 */ +/* { dg-do preprocess } */ + +#pragma push_macro("__TIMESTAMP__") +#pragma pop_macro("__TIMESTAMP__") + +#pragma push_macro("__TIME__") +#pragma pop_macro("__TIME__") + +#pragma push_macro("__DATE__") +#pragma pop_macro("__DATE__") + +#pragma push_macro("__FILE__") +#pragma pop_macro("__FILE__") + +#pragma push_macro("__BASE_FILE__") +#pragma pop_macro("__BASE_FILE__") + +#pragma push_macro("__LINE__") +#pragma pop_macro("__LINE__") + +#pragma push_macro("__INCLUDE_LEVEL__") +#pragma pop_macro("__INCLUDE_LEVEL__") + +#pragma push_macro("__COUNTER__") +#pragma pop_macro("__COUNTER__") + +#pragma push_macro("__has_attribute") +#pragma pop_macro("__has_attribute") + +#pragma push_macro("__has_cpp_attribute") +#pragma pop_macro("__has_cpp_attribute") --- gcc/testsuite/c-c++-common/cpp/pr92296-2.c (nonexistent) +++ gcc/testsuite/c-c++-common/cpp/pr92296-2.c (revision 277685) @@ -0,0 +1,73 @@ +/* PR preprocessor/92296 */ +/* { dg-do preprocess } */ +/* { dg-options "-Wno-builtin-macro-redefined" } */ + +#pragma push_macro("__TIMESTAMP__") +#undef __TIMESTAMP__ +#define __TIMESTAMP__ "Thu Oct 31 12:00:00 2019" +timestamp1 = __TIMESTAMP__ +#pragma pop_macro("__TIMESTAMP__") +timestamp2 = __TIMESTAMP__ + +#pragma push_macro("__TIME__") +#undef __TIME__ +#define __TIME__ "12:00:00" +time1 = __TIME__ +#pragma pop_macro("__TIME__") +time2 = __TIME__ + +#pragma push_macro("__DATE__") +#undef __DATE__ +#define __DATE__ "Oct 31 2019" +date1 = __DATE__ +#pragma pop_macro("__DATE__") +date2 = __DATE__ + +#pragma push_macro("__FILE__") +#undef __FILE__ +#define __FILE__ "pr92296-3.c" +file1 = __FILE__ /* { dg-final { scan-file pr92296-2.i "file1 = \"pr92296-3.c\"" } } */ +#pragma pop_macro("__FILE__") +file2 = __FILE__ /* { dg-final { scan-file-not pr92296-2.i "file2 = \"pr92296-3.c\"" } } */ + +#pragma push_macro("__BASE_FILE__") +#undef __BASE_FILE__ +#define __BASE_FILE__ "pr92296-4.c" +filebase1 = __BASE_FILE__ /* { dg-final { scan-file pr92296-2.i "filebase1 = \"pr92296-4.c\"" } } */ +#pragma pop_macro("__BASE_FILE__") +filebase2 = __BASE_FILE__ /* { dg-final { scan-file-not pr92296-2.i "filebase2 = \"pr92296-4.c\"" } } */ + +#pragma push_macro("__LINE__") +#undef __LINE__ /* { dg-warning "undefining" } */ +#define __LINE__ 142 +line1 = __LINE__ /* { dg-final { scan-file pr92296-2.i "line1 = 142" } } */ +#pragma pop_macro("__LINE__") +line2 = __LINE__ /* { dg-final { scan-file pr92296-2.i "line2 = 45" } } */ + +#pragma push_macro("__INCLUDE_LEVEL__") +#undef __INCLUDE_LEVEL__ /* { dg-warning "undefining" } */ +#define __INCLUDE_LEVEL__ 42 +includelevel1 = __INCLUDE_LEVEL__ /* { dg-final { scan-file pr92296-2.i "includelevel1 = 42" } } */ +#pragma pop_macro("__INCLUDE_LEVEL__") +includelevel2 = __INCLUDE_LEVEL__ /* { dg-final { scan-file pr92296-2.i "includelevel2 = 0" } } */ + +#pragma push_macro("__COUNTER__") +#undef __COUNTER__ /* { dg-warning "undefining" } */ +#define __COUNTER__ 172 +counter1 = __COUNTER__ /* { dg-final { scan-file pr92296-2.i "counter1 = 172" } } */ +#pragma pop_macro("__COUNTER__") +counter2 = __COUNTER__ /* { dg-final { scan-file-not pr92296-2.i "counter2 = 172" } } */ + +#pragma push_macro("__has_attribute") +#undef __has_attribute /* { dg-warning "undefining" } */ +#define __has_attribute(x) 0 +hasattr1 = __has_attribute(noreturn) /* { dg-final { scan-file pr92296-2.i "hasattr1 = 0" } } */ +#pragma pop_macro("__has_attribute") +hasattr2 = __has_attribute(noreturn) /* { dg-final { scan-file-not pr92296-2.i "hasattr2 = 0" } } */ + +#pragma push_macro("__has_cpp_attribute") +#undef __has_cpp_attribute /* { dg-warning "undefining" } */ +#define __has_cpp_attribute(x) 0 +hasattrcpp1 = __has_cpp_attribute(noreturn) /* { dg-final { scan-file pr92296-2.i "hasattrcpp1 = 0" } } */ +#pragma pop_macro("__has_cpp_attribute") +hasattrcpp2 = __has_cpp_attribute(noreturn) /* { dg-final { scan-file-not pr92296-2.i "hasattrcpp2 = 0" } } */
2019-11-08 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2019-11-05 Jakub Jelinek <ja...@redhat.com> PR c++/92343 * constexpr.c (potential_constant_expression_1): Return true rather than false for PREDICT_EXPR. * g++.dg/cpp2a/attr-likely6.C: New test. --- gcc/cp/constexpr.c (revision 277818) +++ gcc/cp/constexpr.c (revision 277819) @@ -6493,6 +6493,7 @@ potential_constant_expression_1 (tree t, case LABEL_DECL: case LABEL_EXPR: case CASE_LABEL_EXPR: + case PREDICT_EXPR: case CONST_DECL: case SIZEOF_EXPR: case ALIGNOF_EXPR: @@ -7354,7 +7355,6 @@ potential_constant_expression_1 (tree t, return true; case EMPTY_CLASS_EXPR: - case PREDICT_EXPR: return false; case GOTO_EXPR: --- gcc/testsuite/g++.dg/cpp2a/attr-likely6.C (nonexistent) +++ gcc/testsuite/g++.dg/cpp2a/attr-likely6.C (revision 277819) @@ -0,0 +1,14 @@ +// PR c++/92343 +// { dg-do compile { target c++14 } } + +constexpr bool +foo (bool x) +{ + if (x) + [[unlikely]] return true; + else + [[likely]] return false; +} + +static_assert (foo (true), ""); +static_assert (!foo (false), "");
2019-11-08 Jakub Jelinek <ja...@redhat.com> PR c++/92384 * function.c (assign_parm_setup_block, assign_parm_setup_stack): Don't copy TYPE_EMPTY_P arguments from data->entry_parm to data->stack_parm slot. (assign_parms): For TREE_ADDRESSABLE parms with TYPE_EMPTY_P type force creation of a unique data.stack_parm slot. * g++.dg/torture/pr92384.C: New test. --- gcc/function.c (revision 277961) +++ gcc/function.c (revision 277962) @@ -3087,7 +3087,7 @@ assign_parm_setup_block (struct assign_p move_block_from_reg (REGNO (entry_parm), mem, size_stored / UNITS_PER_WORD); } - else if (data->stack_parm == 0) + else if (data->stack_parm == 0 && !TYPE_EMPTY_P (data->passed_type)) { push_to_sequence2 (all->first_conversion_insn, all->last_conversion_insn); emit_block_move (stack_parm, data->entry_parm, GEN_INT (size), @@ -3488,7 +3488,9 @@ assign_parm_setup_stack (struct assign_p dest = validize_mem (copy_rtx (data->stack_parm)); src = validize_mem (copy_rtx (data->entry_parm)); - if (MEM_P (src)) + if (TYPE_EMPTY_P (data->passed_type)) + /* Empty types don't really need to be copied. */; + else if (MEM_P (src)) { /* Use a block move to handle potentially misaligned entry_parm. */ if (!to_conversion) @@ -3643,6 +3645,16 @@ assign_parms (tree fndecl) { assign_parm_find_stack_rtl (parm, &data); assign_parm_adjust_entry_rtl (&data); + /* For arguments that occupy no space in the parameter + passing area, have non-zero size and have address taken, + force creation of a stack slot so that they have distinct + address from other parameters. */ + if (TYPE_EMPTY_P (data.passed_type) + && TREE_ADDRESSABLE (parm) + && data.entry_parm == data.stack_parm + && MEM_P (data.entry_parm) + && int_size_in_bytes (data.passed_type)) + data.stack_parm = NULL_RTX; } /* Record permanently how this parm was passed. */ if (data.arg.pass_by_reference) --- gcc/testsuite/g++.dg/torture/pr92384.C (nonexistent) +++ gcc/testsuite/g++.dg/torture/pr92384.C (revision 277962) @@ -0,0 +1,38 @@ +// PR c++/92384 +// { dg-do run } + +struct S {}; +struct T : public S { S a, b, c, d, e, f, g, h, i, j, k, l, m; }; +struct U { long long a, b, c; }; + +U +foo (S, S, S, T, T, T, U g) +{ + return g; +} + +__attribute__((noipa)) bool +bar (S a, S b, S c, T d, T e, T f, U g, void **h) +{ + h[0] = (void *) &a; + h[1] = (void *) &b; + h[2] = (void *) &c; + h[3] = (void *) &d; + h[4] = (void *) &e; + h[5] = (void *) &f; + h[6] = (void *) &g; + asm volatile ("" : : "r" (h) : "memory"); + return (h[0] != h[1] && h[1] != h[2] && h[2] != h[3] + && h[3] != h[4] && h[4] != h[5] && h[5] != h[6]); +} + +int +main () +{ + S a; + T b; + U c = { 1, 2, 3 }; + void *d[7]; + if (!bar (a, a, a, b, b, b, c, d)) + __builtin_abort (); +}