diff options
63 files changed, 606 insertions, 1347 deletions
diff --git a/contrib/filter-clang-warnings.py b/contrib/filter-clang-warnings.py index 2ea7c71..b1b881e 100755 --- a/contrib/filter-clang-warnings.py +++ b/contrib/filter-clang-warnings.py @@ -41,22 +41,43 @@ def skip_warning(filename, message): '-Wignored-attributes', '-Wgnu-zero-variadic-macro-arguments', '-Wformat-security', '-Wundefined-internal', '-Wunknown-warning-option', '-Wc++20-extensions', - '-Wbitwise-instead-of-logical', 'egrep is obsolescent'], + '-Wbitwise-instead-of-logical', 'egrep is obsolescent', + '-Woverloaded-shift-op-parentheses', + '-Wunused-function', '-Wunneeded-internal-declaration', + '-Wvla-cxx-extension', '-Wunused-command-line-argument'], + + 'diagnostic-path-output.cc': ['m_logical_loc_mgr'], + 'fold-const-call.cc': ['-Wreturn-type'], + 'gimple-match': ['-Wunused-', '-Wtautological-compare'], + 'generic-match': ['-Wunused-', '-Wtautological-compare'], + 'genautomata.cc': ['-Wstring-plus-int'], + # Perhaps revisit when ATTR_FNSPEC_DECONST_WATERMARK ifdef case is + # made default or removed: + 'ipa-strub.cc': ['-Wunused-but-set-variable'], 'insn-modes.cc': ['-Wshift-count-overflow'], 'insn-emit.cc': ['-Wtautological-compare'], 'insn-attrtab.cc': ['-Wparentheses-equality'], - 'gimple-match.cc': ['-Wunused-', '-Wtautological-compare'], - 'generic-match.cc': ['-Wunused-', '-Wtautological-compare'], + 'omp-builtins.def': ['-Wc++11-narrowing'], + 'wide-int.h': ['-Wnontrivial-memcall'], 'i386.md': ['-Wparentheses-equality', '-Wtautological-compare', '-Wtautological-overlap-compare'], 'sse.md': ['-Wparentheses-equality', '-Wtautological-compare', '-Wconstant-logical-operand'], 'mmx.md': ['-Wtautological-compare'], - 'genautomata.cc': ['-Wstring-plus-int'], - 'fold-const-call.cc': ['-Wreturn-type'], - 'gfortran.texi': [''], - 'libtool': [''], 'lex.cc': ['-Wc++20-attribute-extensions'], + # Perhaps remove once PR 120960 is resolved: + 'analyzer/ana-state-to-diagnostic-state.h': ['-Wunused-private-field'], + 'analyzer/sm.cc': ['-Wunused-parameter'], + 'c-family/c-format.cc': ['-Wunused-private-field'], + 'm2/gm2-compiler-boot': ['-Wunused-'], + # Rust peopel promised to clean these warnings too + 'rust/': ['-Wunused-private-field'], + 'libiberty/sha1.c': ['-Wc23-extensions'], + 'avr-mmcu.texi': [''], + 'gfortran.texi': [''], + 'install.texi': [''], + 'libgccjit.texi': [''], + 'libtool': [''] } for name, ignore in ignores.items(): diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index ea04ed7..5d7a31f 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -2906,53 +2906,22 @@ handle_counted_by_attribute (tree *node, tree name, " declaration %q+D", name, decl); *no_add_attrs = true; } - /* This attribute only applies to a field with array type or pointer type. */ - else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE - && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) + /* This attribute only applies to field with array type. */ + else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) { error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a non-array" - " or non-pointer field", name); + "%qE attribute is not allowed for a non-array field", + name); *no_add_attrs = true; } /* This attribute only applies to a C99 flexible array member type. */ - else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE - && !c_flexible_array_member_type_p (TREE_TYPE (decl))) + else if (! c_flexible_array_member_type_p (TREE_TYPE (decl))) { error_at (DECL_SOURCE_LOCATION (decl), "%qE attribute is not allowed for a non-flexible" " array member field", name); *no_add_attrs = true; } - /* This attribute cannot be applied to a pointer to void type. */ - else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == VOID_TYPE) - { - error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a pointer to void", - name); - *no_add_attrs = true; - } - /* This attribute cannot be applied to a pointer to function type. */ - else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE) - { - error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a pointer to" - " function", name); - *no_add_attrs = true; - } - /* This attribute cannot be applied to a pointer to structure or union - with flexible array member. */ - else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE - && RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (decl))) - && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (TREE_TYPE (decl)))) - { - error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a pointer to" - " structure or union with flexible array member", name); - *no_add_attrs = true; - } /* The argument should be an identifier. */ else if (TREE_CODE (argval) != IDENTIFIER_NODE) { @@ -2961,8 +2930,7 @@ handle_counted_by_attribute (tree *node, tree name, *no_add_attrs = true; } /* Issue error when there is a counted_by attribute with a different - field as the argument for the same flexible array member or - pointer field. */ + field as the argument for the same flexible array member field. */ else if (old_counted_by != NULL_TREE) { tree old_fieldname = TREE_VALUE (TREE_VALUE (old_counted_by)); diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc index e905059..c6fb764 100644 --- a/gcc/c-family/c-gimplify.cc +++ b/gcc/c-family/c-gimplify.cc @@ -66,20 +66,6 @@ along with GCC; see the file COPYING3. If not see walk back up, we check that they fit our constraints, and copy them into temporaries if not. */ - -/* Check whether TP is an address computation whose base is a call to - .ACCESS_WITH_SIZE. */ - -static bool -is_address_with_access_with_size (tree tp) -{ - if (TREE_CODE (tp) == POINTER_PLUS_EXPR - && (TREE_CODE (TREE_OPERAND (tp, 0)) == INDIRECT_REF) - && (is_access_with_size_p (TREE_OPERAND (TREE_OPERAND (tp, 0), 0)))) - return true; - return false; -} - /* Callback for c_genericize. */ static tree @@ -135,20 +121,6 @@ ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data) walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset); walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset); } - else if (TREE_CODE (*tp) == INDIRECT_REF - && is_address_with_access_with_size (TREE_OPERAND (*tp, 0))) - { - ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), false); - /* Make sure ubsan_maybe_instrument_array_ref is not called again on - the POINTER_PLUS_EXPR, so ensure it is not walked again and walk - its subtrees manually. */ - tree aref = TREE_OPERAND (*tp, 0); - pset->add (aref); - *walk_subtrees = 0; - walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset); - } - else if (is_address_with_access_with_size (*tp)) - ubsan_maybe_instrument_array_ref (tp, true); return NULL_TREE; } diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc index 38514a4..78b7868 100644 --- a/gcc/c-family/c-ubsan.cc +++ b/gcc/c-family/c-ubsan.cc @@ -554,322 +554,38 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index, *index, bound); } - -/* Instrument array bounds for the pointer array address which is - an INDIRECT_REF to the call to .ACCESS_WITH_SIZE. We create special - builtin, that gets expanded in the sanopt pass, and make an array - dimention of it. POINTER_ADDR is the pointer array's base address. - *INDEX is an index to the array. - IGNORE_OFF_BY_ONE is true if the POINTER_ADDR is not inside an - INDIRECT_REF. - Return NULL_TREE if no instrumentation is emitted. */ - -tree -ubsan_instrument_bounds_pointer_address (location_t loc, tree pointer_addr, - tree *index, - bool ignore_off_by_one) -{ - gcc_assert (TREE_CODE (pointer_addr) == INDIRECT_REF); - tree call = TREE_OPERAND (pointer_addr, 0); - if (!is_access_with_size_p (call)) - return NULL_TREE; - tree bound = get_bound_from_access_with_size (call); - - if (ignore_off_by_one) - bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound, - build_int_cst (TREE_TYPE (bound), - 1)); - - /* Don't emit instrumentation in the most common cases. */ - tree idx = NULL_TREE; - if (TREE_CODE (*index) == INTEGER_CST) - idx = *index; - else if (TREE_CODE (*index) == BIT_AND_EXPR - && TREE_CODE (TREE_OPERAND (*index, 1)) == INTEGER_CST) - idx = TREE_OPERAND (*index, 1); - if (idx - && TREE_CODE (bound) == INTEGER_CST - && tree_int_cst_sgn (idx) >= 0 - && tree_int_cst_lt (idx, bound)) - return NULL_TREE; - - *index = save_expr (*index); - - /* Create an array_type for the corresponding pointer array. */ - tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE); - /* The array's element type can be get from the return type of the call to - .ACCESS_WITH_SIZE. */ - tree element_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (call))); - tree array_type = build_array_type (element_type, itype); - /* Create a "(T *) 0" tree node to describe the array type. */ - tree zero_with_type = build_int_cst (build_pointer_type (array_type), 0); - return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS, - void_type_node, 3, zero_with_type, - *index, bound); -} - -/* This structure is to combine a factor with its parent and its position - * in its parent tree. */ -struct factor_t -{ - tree factor; - tree parent; /* the parent tree of this factor. */ - int pos; /* the position of this factor in its parent tree. */ -}; - -/* for a multiply expression like: - ((long unsigned int) m * (long unsigned int) SAVE_EXPR <n>) * 4 - - locate all the factors, the parents of the factor and the position of - the factor in its parent, and put them to VEC_FACTORS. */ - -static void -get_factors_from_mul_expr (tree mult_expr, tree parent, - int pos, auto_vec<factor_t> *vec_factors) -{ - struct factor_t mult_factor = {0, 0, -1}; - mult_factor.factor = mult_expr; - mult_factor.parent = parent; - mult_factor.pos = pos; - - while (CONVERT_EXPR_CODE_P (TREE_CODE (mult_expr))) - { - mult_factor.parent = mult_expr; - mult_factor.pos = 0; - mult_expr = TREE_OPERAND (mult_expr, 0); - mult_factor.factor = mult_expr; - } - if (TREE_CODE (mult_expr) != MULT_EXPR) - vec_factors->safe_push (mult_factor); - else - { - get_factors_from_mul_expr (TREE_OPERAND (mult_expr, 0), mult_expr, - 0, vec_factors); - get_factors_from_mul_expr (TREE_OPERAND (mult_expr, 1), mult_expr, - 1, vec_factors); - } -} - -/* Given an OFFSET expression, and the ELEMENT_SIZE, - get the index expression from OFFSET and return it. - For example: - OFFSET: - ((long unsigned int) m * (long unsigned int) SAVE_EXPR <n>) * 4 - ELEMENT_SIZE: - (sizetype) SAVE_EXPR <n> * 4 - get the index as (long unsigned int) m, and return it. - The INDEX_P holds the pointer to the parent tree of the index, - INDEX_N holds the position of the index in its parent. */ - -static tree -get_index_from_offset (tree offset, tree *index_p, - int *index_n, tree element_size) -{ - if (TREE_CODE (offset) != MULT_EXPR) - return NULL_TREE; - - auto_vec<factor_t> e_factors, o_factors; - get_factors_from_mul_expr (element_size, NULL, -1, &e_factors); - get_factors_from_mul_expr (offset, *index_p, *index_n, &o_factors); - - if (e_factors.is_empty () || o_factors.is_empty ()) - return NULL_TREE; - - bool all_found = true; - for (unsigned i = 0; i < e_factors.length (); i++) - { - factor_t e_size_factor = e_factors[i]; - bool found = false; - for (unsigned j = 0; j < o_factors.length ();) - { - factor_t o_exp_factor = o_factors[j]; - if (operand_equal_p (e_size_factor.factor, o_exp_factor.factor)) - { - o_factors.unordered_remove (j); - found = true; - break; - } - else - j++; - } - if (!found) - all_found = false; - } - - if (!all_found) - return NULL_TREE; - - if (o_factors.length () != 1) - return NULL_TREE; - - *index_p = o_factors[0].parent; - *index_n = o_factors[0].pos; - return o_factors[0].factor; -} - -/* For an pointer + offset computation expression, such as, - *.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) - + (sizetype) ((long unsigned int) index * 4 - Return the index of this pointer array reference, - set the parent tree of INDEX to *INDEX_P. - set the operand position of the INDEX in the parent tree to *INDEX_N. - If failed, return NULL_TREE. */ - -static tree -get_index_from_pointer_addr_expr (tree pointer, tree *index_p, int *index_n) -{ - *index_p = NULL_TREE; - *index_n = -1; - if (TREE_CODE (TREE_OPERAND (pointer, 0)) != INDIRECT_REF) - return NULL_TREE; - tree call = TREE_OPERAND (TREE_OPERAND (pointer, 0), 0); - if (!is_access_with_size_p (call)) - return NULL_TREE; - - /* Get the pointee type of the call to .ACCESS_WITH_SIZE. - This should be the element type of the pointer array. */ - tree pointee_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (call))); - tree pointee_size = TYPE_SIZE_UNIT (pointee_type); - - tree index_exp = TREE_OPERAND (pointer, 1); - *index_p = pointer; - *index_n = 1; - - if (!(TREE_CODE (index_exp) != MULT_EXPR - && tree_int_cst_equal (pointee_size, integer_one_node))) - { - while (CONVERT_EXPR_CODE_P (TREE_CODE (index_exp))) - { - *index_p = index_exp; - *index_n = 0; - index_exp = TREE_OPERAND (index_exp, 0); - } - index_exp = get_index_from_offset (index_exp, index_p, - index_n, pointee_size); - - if (!index_exp) - return NULL_TREE; - } - - while (CONVERT_EXPR_CODE_P (TREE_CODE (index_exp))) - { - *index_p = index_exp; - *index_n = 0; - index_exp = TREE_OPERAND (index_exp, 0); - } - - return index_exp; -} - -/* Return TRUE when the EXPR is a pointer array address that could be - instrumented. - We only instrument an address computation similar as the following: - *.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) - + (sizetype) ((long unsigned int) index * 4) - if the EXPR is instrumentable, return TRUE and - set the index to *INDEX. - set the *.ACCESS_WITH_SIZE to *BASE. - set the parent tree of INDEX to *INDEX_P. - set the operand position of the INDEX in the parent tree to INDEX_N. */ - -static bool -is_instrumentable_pointer_array_address (tree expr, tree *base, - tree *index, tree *index_p, - int *index_n) -{ - /* For a poiner array address as: - (*.ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) - + (sizetype) ((long unsigned int) index * 4) - op0 is the call to *.ACCESS_WITH_SIZE; - op1 is the index. */ - if (TREE_CODE (expr) != POINTER_PLUS_EXPR) - return false; - - tree op0 = TREE_OPERAND (expr, 0); - if (TREE_CODE (op0) != INDIRECT_REF) - return false; - if (!is_access_with_size_p (TREE_OPERAND (op0, 0))) - return false; - tree op1 = get_index_from_pointer_addr_expr (expr, index_p, index_n); - if (op1 != NULL_TREE) - { - *base = op0; - *index = op1; - return true; - } - return false; -} - -/* Return true iff T is an array or an indirect reference that was - instrumented by SANITIZE_BOUNDS. */ +/* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */ bool -ubsan_array_ref_instrumented_p (tree t) +ubsan_array_ref_instrumented_p (const_tree t) { - if (TREE_CODE (t) != ARRAY_REF - && TREE_CODE (t) != MEM_REF) + if (TREE_CODE (t) != ARRAY_REF) return false; - bool is_array = (TREE_CODE (t) == ARRAY_REF); - tree op0 = NULL_TREE; - tree op1 = NULL_TREE; - tree index_p = NULL_TREE; - int index_n = 0; - if (is_array) - { - op1 = TREE_OPERAND (t, 1); - return TREE_CODE (op1) == COMPOUND_EXPR - && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR - && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE - && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; - } - else if (is_instrumentable_pointer_array_address (t, &op0, &op1, - &index_p, &index_n)) - return TREE_CODE (op1) == COMPOUND_EXPR - && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR - && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE - && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; - - return false; + tree op1 = TREE_OPERAND (t, 1); + return TREE_CODE (op1) == COMPOUND_EXPR + && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR + && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE + && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; } -/* Instrument an ARRAY_REF or an address computation whose base address is - a call to .ACCESS_WITH_SIZE, if it hasn't already been instrumented. - IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR, or the - address computation is not inside a INDIRECT_REF. */ +/* Instrument an ARRAY_REF, if it hasn't already been instrumented. + IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */ void ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one) { - tree e = NULL_TREE; - tree op0 = NULL_TREE; - tree op1 = NULL_TREE; - tree index_p = NULL_TREE; /* the parent tree of INDEX. */ - int index_n = 0; /* the operand position of INDEX in the parent tree. */ - if (!ubsan_array_ref_instrumented_p (*expr_p) && sanitize_flags_p (SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT) && current_function_decl != NULL_TREE) { - if (TREE_CODE (*expr_p) == ARRAY_REF) - { - op0 = TREE_OPERAND (*expr_p, 0); - op1 = TREE_OPERAND (*expr_p, 1); - index_p = *expr_p; - index_n = 1; - e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, - &op1, ignore_off_by_one); - } - else if (is_instrumentable_pointer_array_address (*expr_p, &op0, &op1, - &index_p, &index_n)) - e = ubsan_instrument_bounds_pointer_address (EXPR_LOCATION (*expr_p), - op0, &op1, - ignore_off_by_one); - - /* Replace the original INDEX with the instrumented INDEX. */ + tree op0 = TREE_OPERAND (*expr_p, 0); + tree op1 = TREE_OPERAND (*expr_p, 1); + tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, &op1, + ignore_off_by_one); if (e != NULL_TREE) - TREE_OPERAND (index_p, index_n) - = build2 (COMPOUND_EXPR, TREE_TYPE (op1), e, op1); + TREE_OPERAND (*expr_p, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1), + e, op1); } } diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 8af466d..6a55e71 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -397,6 +397,10 @@ Wassign-intercept ObjC ObjC++ Var(warn_assign_intercept) Warning Warn whenever an Objective-C assignment is being intercepted by the garbage collector. +Wabbreviated-auto-in-template-arg +C++ ObjC++ Warning Var(warn_abbev_auto_targ) Init(1) +Diagnose a placeholder type in a template argument in a function parameter type. + Wbad-function-cast C ObjC Var(warn_bad_function_cast) Warning Warn about casting functions to incompatible types. diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls index 65d1221..401e6e7 100644 --- a/gcc/c-family/c.opt.urls +++ b/gcc/c-family/c.opt.urls @@ -139,6 +139,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Warray-parameter) Wassign-intercept UrlSuffix(gcc/Objective-C-and-Objective-C_002b_002b-Dialect-Options.html#index-Wassign-intercept) +Wabbreviated-auto-in-template-arg +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wabbreviated-auto-in-template-arg) + Wbad-function-cast UrlSuffix(gcc/Warning-Options.html#index-Wbad-function-cast) diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 7e1c197..8bbd6eb 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9432,62 +9432,56 @@ c_update_type_canonical (tree t) } } -/* Verify the argument of the counted_by attribute of each of the - FIELDS_WITH_COUNTED_BY is a valid field of the containing structure, - STRUCT_TYPE, Report error and remove the corresponding attribute - when it's not. */ +/* Verify the argument of the counted_by attribute of the flexible array + member FIELD_DECL is a valid field of the containing structure, + STRUCT_TYPE, Report error and remove this attribute when it's not. */ static void -verify_counted_by_attribute (tree struct_type, - auto_vec<tree> *fields_with_counted_by) +verify_counted_by_attribute (tree struct_type, tree field_decl) { - for (tree field_decl : *fields_with_counted_by) - { - tree attr_counted_by = lookup_attribute ("counted_by", - DECL_ATTRIBUTES (field_decl)); + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); - if (!attr_counted_by) - continue; + if (!attr_counted_by) + return; + + /* If there is an counted_by attribute attached to the field, + verify it. */ - /* If there is an counted_by attribute attached to the field, - verify it. */ + tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); - tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); + /* Verify the argument of the attrbute is a valid field of the + containing structure. */ - /* Verify the argument of the attrbute is a valid field of the - containing structure. */ + tree counted_by_field = lookup_field (struct_type, fieldname); - tree counted_by_field = lookup_field (struct_type, fieldname); + /* Error when the field is not found in the containing structure and + remove the corresponding counted_by attribute from the field_decl. */ + if (!counted_by_field) + { + error_at (DECL_SOURCE_LOCATION (field_decl), + "argument %qE to the %<counted_by%> attribute" + " is not a field declaration in the same structure" + " as %qD", fieldname, field_decl); + DECL_ATTRIBUTES (field_decl) + = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); + } + else + /* Error when the field is not with an integer type. */ + { + while (TREE_CHAIN (counted_by_field)) + counted_by_field = TREE_CHAIN (counted_by_field); + tree real_field = TREE_VALUE (counted_by_field); - /* Error when the field is not found in the containing structure and - remove the corresponding counted_by attribute from the field_decl. */ - if (!counted_by_field) + if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field))) { error_at (DECL_SOURCE_LOCATION (field_decl), "argument %qE to the %<counted_by%> attribute" - " is not a field declaration in the same structure" - " as %qD", fieldname, field_decl); + " is not a field declaration with an integer type", + fieldname); DECL_ATTRIBUTES (field_decl) = remove_attribute ("counted_by", DECL_ATTRIBUTES (field_decl)); } - else - /* Error when the field is not with an integer type. */ - { - while (TREE_CHAIN (counted_by_field)) - counted_by_field = TREE_CHAIN (counted_by_field); - tree real_field = TREE_VALUE (counted_by_field); - - if (!INTEGRAL_TYPE_P (TREE_TYPE (real_field))) - { - error_at (DECL_SOURCE_LOCATION (field_decl), - "argument %qE to the %<counted_by%> attribute" - " is not a field declaration with an integer type", - fieldname); - DECL_ATTRIBUTES (field_decl) - = remove_attribute ("counted_by", - DECL_ATTRIBUTES (field_decl)); - } - } } } @@ -9562,7 +9556,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, until now.) */ bool saw_named_field = false; - auto_vec<tree> fields_with_counted_by; + tree counted_by_fam_field = NULL_TREE; for (x = fieldlist; x; x = DECL_CHAIN (x)) { /* Whether this field is the last field of the structure or union. @@ -9643,16 +9637,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, record it here and do more verification later after the whole structure is complete. */ if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x))) - fields_with_counted_by.safe_push (x); + counted_by_fam_field = x; } - if (TREE_CODE (TREE_TYPE (x)) == POINTER_TYPE) - /* If there is a counted_by attribute attached to this field, - record it here and do more verification later after the - whole structure is complete. */ - if (lookup_attribute ("counted_by", DECL_ATTRIBUTES (x))) - fields_with_counted_by.safe_push (x); - if (pedantic && TREE_CODE (t) == RECORD_TYPE && flexible_array_type_p (TREE_TYPE (x))) pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic, @@ -9951,8 +9938,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, struct_parse_info->struct_types.safe_push (t); } - if (fields_with_counted_by.length () > 0) - verify_counted_by_attribute (t, &fields_with_counted_by); + if (counted_by_fam_field) + verify_counted_by_attribute (t, counted_by_fam_field); return t; } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 7948106..e24629b 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -2922,8 +2922,8 @@ should_suggest_deref_p (tree datum_type) /* For a SUBDATUM field of a structure or union DATUM, generate a REF to the object that represents its counted_by per the attribute counted_by - attached to this field if it's a flexible array member or a pointer - field, otherwise return NULL_TREE. + attached to this field if it's a flexible array member field, otherwise + return NULL_TREE. Set COUNTED_BY_TYPE to the TYPE of the counted_by field. For example, if: @@ -2941,34 +2941,18 @@ should_suggest_deref_p (tree datum_type) */ static tree -build_counted_by_ref (location_t loc, tree datum, tree subdatum, - tree *counted_by_type) +build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type) { tree type = TREE_TYPE (datum); - tree sub_type = TREE_TYPE (subdatum); - if (!c_flexible_array_member_type_p (sub_type) - && TREE_CODE (sub_type) != POINTER_TYPE) + if (!c_flexible_array_member_type_p (TREE_TYPE (subdatum))) return NULL_TREE; - tree element_type = TREE_TYPE (sub_type); - tree attr_counted_by = lookup_attribute ("counted_by", DECL_ATTRIBUTES (subdatum)); tree counted_by_ref = NULL_TREE; *counted_by_type = NULL_TREE; if (attr_counted_by) { - /* Issue error when the element_type is a structure or - union including a flexible array member. */ - if (RECORD_OR_UNION_TYPE_P (element_type) - && TYPE_INCLUDES_FLEXARRAY (element_type)) - { - error_at (loc, - "%<counted_by%> attribute is not allowed for a pointer to" - " structure or union with flexible array member"); - return error_mark_node; - } - tree field_id = TREE_VALUE (TREE_VALUE (attr_counted_by)); counted_by_ref = build_component_ref (UNKNOWN_LOCATION, @@ -2991,11 +2975,8 @@ build_counted_by_ref (location_t loc, tree datum, tree subdatum, } /* Given a COMPONENT_REF REF with the location LOC, the corresponding - COUNTED_BY_REF, and the COUNTED_BY_TYPE, generate the corresponding - call to the internal function .ACCESS_WITH_SIZE. - - Generate an INDIRECT_REF to a call to the internal function - .ACCESS_WITH_SIZE. + COUNTED_BY_REF, and the COUNTED_BY_TYPE, generate an INDIRECT_REF + to a call to the internal function .ACCESS_WITH_SIZE. REF @@ -3005,15 +2986,17 @@ build_counted_by_ref (location_t loc, tree datum, tree subdatum, (TYPE_OF_ARRAY *)0)) NOTE: The return type of this function is the POINTER type pointing - to the original flexible array type or the original pointer type. - Then the type of the INDIRECT_REF is the original flexible array type - or the original pointer type. + to the original flexible array type. + Then the type of the INDIRECT_REF is the original flexible array type. + + The type of the first argument of this function is a POINTER type + to the original flexible array type. The 4th argument of the call is a constant 0 with the TYPE of the object pointed by COUNTED_BY_REF. - The 6th argument of the call is a constant 0 of the same TYPE as - the return type of the call. + The 6th argument of the call is a constant 0 with the pointer TYPE + to the original flexible array type. */ static tree @@ -3021,16 +3004,11 @@ build_access_with_size_for_counted_by (location_t loc, tree ref, tree counted_by_ref, tree counted_by_type) { - gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref)) - || TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE); - bool is_fam = c_flexible_array_member_type_p (TREE_TYPE (ref)); - tree first_param = is_fam ? array_to_pointer_conversion (loc, ref) - : build_unary_op (loc, ADDR_EXPR, ref, false); - - /* The result type of the call is a pointer to the original type - of the ref. */ + gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref))); + /* The result type of the call is a pointer to the flexible array type. */ tree result_type = c_build_pointer_type (TREE_TYPE (ref)); - first_param = c_fully_fold (first_param, false, NULL); + tree first_param + = c_fully_fold (array_to_pointer_conversion (loc, ref), false, NULL); tree second_param = c_fully_fold (counted_by_ref, false, NULL); @@ -3043,7 +3021,7 @@ build_access_with_size_for_counted_by (location_t loc, tree ref, build_int_cst (counted_by_type, 0), build_int_cst (integer_type_node, -1), build_int_cst (result_type, 0)); - /* Wrap the call with an INDIRECT_REF with the original type of the ref. */ + /* Wrap the call with an INDIRECT_REF with the flexible array type. */ call = build1 (INDIRECT_REF, TREE_TYPE (ref), call); SET_EXPR_LOCATION (call, loc); return call; @@ -3061,7 +3039,7 @@ handle_counted_by_for_component_ref (location_t loc, tree ref) tree datum = TREE_OPERAND (ref, 0); tree subdatum = TREE_OPERAND (ref, 1); tree counted_by_type = NULL_TREE; - tree counted_by_ref = build_counted_by_ref (loc, datum, subdatum, + tree counted_by_ref = build_counted_by_ref (datum, subdatum, &counted_by_type); if (counted_by_ref) ref = build_access_with_size_for_counted_by (loc, ref, diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 509ef4c..27efc91 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -5771,6 +5771,19 @@ (match_operand:TI 1 "register_operand")] "TARGET_SIMD && !TARGET_CSSC" { + /* For SVE we can do popcount on DImode chunks of the TImode argument + and then use a cheap ADDP reduction. The SVE CNT instruction requires + materializing a PTRUE so don't do this if optimizing for size. */ + if (TARGET_SVE && !optimize_function_for_size_p (cfun)) + { + rtx v = gen_reg_rtx (V2DImode); + rtx v1 = gen_reg_rtx (V2DImode); + emit_move_insn (v, gen_lowpart (V2DImode, operands[1])); + rtx p = aarch64_ptrue_reg (VNx2BImode, 16); + emit_insn (gen_aarch64_pred_popcountv2di (v1, p, v)); + emit_insn (gen_reduc_plus_scal_v2di (operands[0], v1)); + DONE; + } rtx v = gen_reg_rtx (V16QImode); rtx v1 = gen_reg_rtx (V16QImode); emit_move_insn (v, gen_lowpart (V16QImode, operands[1])); diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 440ce93..f6db36e 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -238,9 +238,6 @@ UNSPEC_VEC_MSUM - UNSPEC_VEC_VFMIN - UNSPEC_VEC_VFMAX - UNSPEC_VEC_VBLEND UNSPEC_VEC_VEVAL UNSPEC_VEC_VGEM @@ -253,6 +250,9 @@ UNSPEC_NNPA_VCFN_V8HI UNSPEC_NNPA_VCNF_V8HI + + UNSPEC_FMAX + UNSPEC_FMIN ]) ;; diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 7c706ec..26753c0 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -89,6 +89,13 @@ (define_mode_iterator VF_HW [(V4SF "TARGET_VXE") V2DF (V1TF "TARGET_VXE") (TF "TARGET_VXE")]) +; FP scalar and vector modes +(define_mode_iterator VFT_BFP [SF DF + (V1SF "TARGET_VXE") (V2SF "TARGET_VXE") (V4SF "TARGET_VXE") + V1DF V2DF + (V1TF "TARGET_VXE") (TF "TARGET_VXE")]) + + (define_mode_iterator V_8 [V1QI]) (define_mode_iterator V_16 [V2QI V1HI]) (define_mode_iterator V_32 [V4QI V2HI V1SI V1SF]) @@ -3602,3 +3609,21 @@ (umul_highpart:VIT_HW_VXE3_DT (match_operand:VIT_HW_VXE3_DT 1 "register_operand") (match_operand:VIT_HW_VXE3_DT 2 "register_operand")))] "TARGET_VX") + +; fmax +(define_expand "fmax<mode>3" + [(set (match_operand:VFT_BFP 0 "register_operand") + (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand") + (match_operand:VFT_BFP 2 "register_operand") + (const_int 4)] + UNSPEC_FMAX))] + "TARGET_VXE") + +; fmin +(define_expand "fmin<mode>3" + [(set (match_operand:VFT_BFP 0 "register_operand") + (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand") + (match_operand:VFT_BFP 2 "register_operand") + (const_int 4)] + UNSPEC_FMIN))] + "TARGET_VXE") diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md index 9e5d18b..9b89b13 100644 --- a/gcc/config/s390/vx-builtins.md +++ b/gcc/config/s390/vx-builtins.md @@ -2134,23 +2134,22 @@ "<vw>fche<sdx>bs\t%v2,%v0,%v1" [(set_attr "op_type" "VRR")]) - (define_insn "vfmin<mode>" - [(set (match_operand:VF_HW 0 "register_operand" "=v") - (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v") - (match_operand:VF_HW 2 "register_operand" "v") - (match_operand:QI 3 "const_mask_operand" "C")] - UNSPEC_VEC_VFMIN))] + [(set (match_operand:VFT_BFP 0 "register_operand" "=v") + (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "v") + (match_operand:VFT_BFP 2 "register_operand" "v") + (match_operand:QI 3 "const_mask_operand" "C")] + UNSPEC_FMIN))] "TARGET_VXE" "<vw>fmin<sdx>b\t%v0,%v1,%v2,%b3" [(set_attr "op_type" "VRR")]) (define_insn "vfmax<mode>" - [(set (match_operand:VF_HW 0 "register_operand" "=v") - (unspec:VF_HW [(match_operand:VF_HW 1 "register_operand" "v") - (match_operand:VF_HW 2 "register_operand" "v") - (match_operand:QI 3 "const_mask_operand" "C")] - UNSPEC_VEC_VFMAX))] + [(set (match_operand:VFT_BFP 0 "register_operand" "=v") + (unspec:VFT_BFP [(match_operand:VFT_BFP 1 "register_operand" "v") + (match_operand:VFT_BFP 2 "register_operand" "v") + (match_operand:QI 3 "const_mask_operand" "C")] + UNSPEC_FMAX))] "TARGET_VXE" "<vw>fmax<sdx>b\t%v0,%v1,%v2,%b3" [(set_attr "op_type" "VRR")]) diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc index 92a2364..8c43a69 100644 --- a/gcc/config/xtensa/xtensa.cc +++ b/gcc/config/xtensa/xtensa.cc @@ -159,6 +159,10 @@ static void xtensa_asm_trampoline_template (FILE *); static void xtensa_trampoline_init (rtx, tree, rtx); static bool xtensa_output_addr_const_extra (FILE *, rtx); static bool xtensa_cannot_force_const_mem (machine_mode, rtx); +static machine_mode xtensa_promote_function_mode (const_tree, + machine_mode, + int *, const_tree, + int); static reg_class_t xtensa_preferred_reload_class (rtx, reg_class_t); static reg_class_t xtensa_preferred_output_reload_class (rtx, reg_class_t); @@ -235,9 +239,7 @@ static HARD_REG_SET xtensa_zero_call_used_regs (HARD_REG_SET); #define TARGET_EXPAND_BUILTIN_VA_START xtensa_va_start #undef TARGET_PROMOTE_FUNCTION_MODE -#define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote -#undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true +#define TARGET_PROMOTE_FUNCTION_MODE xtensa_promote_function_mode #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory @@ -4801,6 +4803,19 @@ xtensa_insn_cost (rtx_insn *insn, bool speed) return pattern_cost (PATTERN (insn), speed); } +/* Worker function for TARGET_PROMOTE_FUNCTION_MODE. */ + +static machine_mode +xtensa_promote_function_mode (const_tree type, machine_mode mode, + int *punsignedp, const_tree, int) +{ + if (GET_MODE_CLASS (mode) == MODE_INT + && GET_MODE_SIZE (mode) < GET_MODE_SIZE (SImode)) + return SImode; + + return promote_mode (type, mode, punsignedp); +} + /* Worker function for TARGET_RETURN_IN_MEMORY. */ static bool diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 83c8e28..be26bd3 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -2014,8 +2014,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } /* For function versions, params and types match, but they are not ambiguous. */ - else if ((!DECL_FUNCTION_VERSIONED (newdecl) - && !DECL_FUNCTION_VERSIONED (olddecl)) + else if (((!DECL_FUNCTION_VERSIONED (newdecl) + && !DECL_FUNCTION_VERSIONED (olddecl)) + || !same_type_p (fndecl_declared_return_type (newdecl), + fndecl_declared_return_type (olddecl))) /* Let constrained hidden friends coexist for now, we'll check satisfaction later. */ && !member_like_constrained_friend_p (newdecl) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 44a7832..239e6f9 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -21021,9 +21021,6 @@ cp_parser_simple_type_specifier (cp_parser* parser, "only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); } - else if (parser->in_template_argument_list_p) - error_at (token->location, - "use of %<auto%> in template argument"); else if (!flag_concepts) pedwarn (token->location, OPT_Wc__20_extensions, "use of %<auto%> in parameter declaration " @@ -21033,6 +21030,11 @@ cp_parser_simple_type_specifier (cp_parser* parser, "use of %<auto%> in parameter declaration " "only available with " "%<-std=c++14%> or %<-std=gnu++14%>"); + + if (parser->in_template_argument_list_p) + permerror_opt (token->location, + OPT_Wabbreviated_auto_in_template_arg, + "use of %<auto%> in template argument"); } else type = make_auto (); @@ -21479,6 +21481,10 @@ cp_parser_placeholder_type_specifier (cp_parser *parser, location_t loc, error_at (loc, "cannot declare a parameter with %<decltype(auto)%>"); return error_mark_node; } + if (parser->in_template_argument_list_p) + permerror_opt (placeholder->location, + OPT_Wabbreviated_auto_in_template_arg, + "use of %<auto%> in template argument"); tree parm = build_constrained_parameter (con, proto, args); return synthesize_implicit_template_parm (parser, parm); } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index a119ad3..8c29e24 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7138,11 +7138,9 @@ The @code{aligned} attribute can also be used for functions @cindex @code{counted_by} variable attribute @item counted_by (@var{count}) The @code{counted_by} attribute may be attached to the C99 flexible array -member, or a pointer field of a structure. It indicates that the number -of the elements of the array that is held by the flexible array member -field, or is pointed to by the pointer field, is given by the field -"@var{count}" in the same structure as the flexible array member or the -pointer field. +member of a structure. It indicates that the number of the elements of the +array is given by the field "@var{count}" in the same structure as the +flexible array member. This attribute is available only in C for now. In C++ this attribute is ignored. @@ -7163,22 +7161,8 @@ struct P @{ @end smallexample @noindent -specifies that the @code{array} is a flexible array member whose number -of elements is given by the field @code{count} in the same structure. - -@smallexample -struct PP @{ - size_t count2; - char other1; - char *array2 __attribute__ ((counted_by (count2))); - int other2; -@} *pp; -@end smallexample - -@noindent -specifies that the @code{array2} is an array that is pointed by the -pointer field, and its number of elements is given by the field -@code{count2} in the same structure. +specifies that the @code{array} is a flexible array member whose number of +elements is given by the field @code{count} in the same structure. The field that represents the number of the elements should have an integer type. Otherwise, the compiler reports an error and ignores @@ -7187,12 +7171,6 @@ the attribute. When the field that represents the number of the elements is assigned a negative integer value, the compiler treats the value as zero. -The @code{counted_by} attribute is not allowed for a pointer to @code{void}, -a pointer to function, or a pointer to a structure or union that includes -a flexible array member. However, it is allowed for a pointer to -non-void incomplete structure or union types, as long as the type could -be completed before the first reference to the pointer. - An explicit @code{counted_by} annotation defines a relationship between two objects, @code{p->array} and @code{p->count}, and there are the following requirements on the relationship between this pair: @@ -7208,13 +7186,6 @@ available all the time. This relationship must hold even after any of these related objects are updated during the program. @end itemize -In addition to the above requirements, there is one more requirement -between this pair if and only if @code{p->array} is an array that is -pointed by the pointer field: - -@code{p->array} and @code{p->count} can only be changed by changing the -whole structure at the same time. - It's the programmer's responsibility to make sure the above requirements to be kept all the time. Otherwise the compiler reports warnings and the results of the array bound sanitizer and the @@ -7236,8 +7207,6 @@ In the above, @code{ref1} uses @code{val1} as the number of the elements in @code{p->array}, and @code{ref2} uses @code{val2} as the number of elements in @code{p->array}. -Note, however, the above feature is not valid for the pointer field. - @cindex @code{alloc_size} variable attribute @item alloc_size (@var{position}) @itemx alloc_size (@var{position-1}, @var{position-2}) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7640e7d..74f5ee2 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -3816,6 +3816,23 @@ Warn when a type with an ABI tag is used in a context that does not have that ABI tag. See @ref{C++ Attributes} for more information about ABI tags. +@opindex Wabbreviated-auto-in-template-arg +@opindex Wno-abbreviated-auto-in-template-arg +@item -Wno-abbreviated-auto-in-template-arg +Disable the error for an @code{auto} placeholder type used within a +template argument list to declare a C++20 abbreviated function +template, e.g. + +@smallexample +void f(S<auto>); +@end smallexample + +This feature was proposed in the Concepts TS, but was not adopted into +C++20; in the standard, a placeholder in a parameter declaration must +appear as a decl-specifier. The error can also be reduced to a +warning by @option{-fpermissive} or +@option{-Wno-error=abbreviated-auto-in-template-arg}. + @opindex Wcomma-subscript @opindex Wno-comma-subscript @item -Wcomma-subscript @r{(C++ and Objective-C++ only)} @@ -6443,6 +6460,7 @@ only by this flag, but it also downgrades some C and C++ diagnostics that have their own flag: @gccoptlist{ +-Wabbreviated-auto-in-template-arg @r{(C++ and Objective-C++ only)} -Wdeclaration-missing-parameter-type @r{(C and Objective-C only)} -Wimplicit-function-declaration @r{(C and Objective-C only)} -Wimplicit-int @r{(C and Objective-C only)} diff --git a/gcc/testsuite/g++.dg/concepts/auto7a.C b/gcc/testsuite/g++.dg/concepts/auto7a.C index 88868f4..f36038d 100644 --- a/gcc/testsuite/g++.dg/concepts/auto7a.C +++ b/gcc/testsuite/g++.dg/concepts/auto7a.C @@ -2,6 +2,7 @@ template <class T> struct A { }; void f(A<auto> a) { } // { dg-error "auto. in template argument" } +// { dg-message "in parameter declaration" "" { target c++17_down } .-1 } int main() { f(A<int>()); diff --git a/gcc/testsuite/g++.dg/concepts/auto7b.C b/gcc/testsuite/g++.dg/concepts/auto7b.C new file mode 100644 index 0000000..874192c --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/auto7b.C @@ -0,0 +1,10 @@ +// PR c++/120917 +// { dg-do compile { target c++14 } } +// { dg-additional-options "-fconcepts -Wno-abbreviated-auto-in-template-arg" } + +template <class T> struct A { }; +void f(A<auto> a) { } +int main() +{ + f(A<int>()); +} diff --git a/gcc/testsuite/g++.dg/concepts/auto7c.C b/gcc/testsuite/g++.dg/concepts/auto7c.C new file mode 100644 index 0000000..5b16027 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/auto7c.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++17 } } +// { dg-additional-options -fconcepts } + +template <class T> +concept True = true; + +template <class T> struct A { }; +void f(A<True auto> a) { } // { dg-error "use of .auto. in template argument" } +int main() +{ + f(A<int>()); +} diff --git a/gcc/testsuite/g++.dg/concepts/pr67249.C b/gcc/testsuite/g++.dg/concepts/pr67249.C index e0f8d5a..e97183d 100644 --- a/gcc/testsuite/g++.dg/concepts/pr67249.C +++ b/gcc/testsuite/g++.dg/concepts/pr67249.C @@ -4,4 +4,4 @@ template<class T> concept C1 = true; template<class A, class B> struct Pair {}; // We used to test "Pair<auto, C1 >". -void f(Pair<C1 auto, C1 auto>); +void f(Pair<C1 auto, C1 auto>); // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/concepts/pr67249a.C b/gcc/testsuite/g++.dg/concepts/pr67249a.C new file mode 100644 index 0000000..cb5d90e --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/pr67249a.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-fconcepts -Wno-abbreviated-auto-in-template-arg" } + +template<class T> concept C1 = true; +template<class A, class B> struct Pair {}; +// We used to test "Pair<auto, C1 >". +void f(Pair<C1 auto, C1 auto>); diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C new file mode 100644 index 0000000..557ecb9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic-a.C @@ -0,0 +1,15 @@ +// Basic generic lambda test +// { dg-do run { target c++14 } } +// { dg-additional-options -Wno-abbreviated-auto-in-template-arg } + +template <typename T, typename U> struct pair {}; +template <typename... T> struct tuple {}; + +int main() +{ + auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; + auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; + + a(1, pair<int, float>()); + b(2, pair<pair<short,char>, double>(), pair<pair<float,long>, int>()); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C index 6d2d250..971f58f 100644 --- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic.C @@ -6,8 +6,8 @@ template <typename... T> struct tuple {}; int main() { - auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; - auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; + auto a = [] (auto, pair<auto,auto> v) { return sizeof (v); }; // { dg-error "auto" } + auto b = [] (auto, pair<pair<auto,auto>,auto>... v) { return sizeof... (v); }; // { dg-error "auto" } a(1, pair<int, float>()); b(2, pair<pair<short,char>, double>(), pair<pair<float,long>, int>()); diff --git a/gcc/testsuite/g++.dg/cpp1y/pr85076.C b/gcc/testsuite/g++.dg/cpp1y/pr85076.C index 6d54dea..b68143b 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr85076.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr85076.C @@ -3,4 +3,4 @@ template<typename> struct A*; // { dg-error "expected unqualified-id before" } -auto a = [](A<auto>) {}; // { dg-error "is not a template|has incomplete type" } +auto a = [](A<auto>) {}; // { dg-error "is not a template|has incomplete type|auto" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C index a31750e..baddc1c 100644 --- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210.C @@ -7,4 +7,4 @@ concept C = true; template <class T> struct A {}; -void f(A<C<int> auto >) {} +void f(A<C<int> auto >) {} // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C new file mode 100644 index 0000000..1d63a84 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr67210a.C @@ -0,0 +1,11 @@ +// PR c++/67210 +// { dg-do compile { target c++20 } } +// { dg-additional-options -Wno-abbreviated-auto-in-template-arg } + +template <class T, class U> +concept C = true; + +template <class T> +struct A {}; + +void f(A<C<int> auto >) {} diff --git a/gcc/testsuite/g++.target/aarch64/pr119498.C b/gcc/testsuite/g++.target/aarch64/pr119498.C new file mode 100644 index 0000000..03f1659 --- /dev/null +++ b/gcc/testsuite/g++.target/aarch64/pr119498.C @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-ifunc "" } */ +/* { dg-options "-O0" } */ +/* { dg-additional-options "-Wno-experimental-fmv-target" } */ + +__attribute__ ((target_version ("default"))) int +foo (); + +__attribute__ ((target_version ("default"))) int +foo () { return 1; } /* { dg-message "old declaration" } */ + +__attribute__ ((target_version ("dotprod"))) float +foo () { return 3; } /* { dg-error "ambiguating new declaration" } */ + +__attribute__ ((target_version ("sve"))) int +foo2 () { return 1; } /* { dg-message "old declaration" } */ + +__attribute__ ((target_version ("dotprod"))) float +foo2 () { return 3; } /* { dg-error "ambiguating new declaration of" } */ diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by.c b/gcc/testsuite/gcc.dg/flex-array-counted-by.c index 4fa91ff..16eb2c6 100644 --- a/gcc/testsuite/gcc.dg/flex-array-counted-by.c +++ b/gcc/testsuite/gcc.dg/flex-array-counted-by.c @@ -10,7 +10,7 @@ int x __attribute ((counted_by (size))); /* { dg-error "attribute is not allowed struct trailing { int count; - int field __attribute ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-array or non-pointer field" } */ + int field __attribute ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-array field" } */ }; struct trailing_1 { diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-1.c b/gcc/testsuite/gcc.dg/pointer-counted-by-1.c deleted file mode 100644 index 395af34..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-1.c +++ /dev/null @@ -1,34 +0,0 @@ -/* More testing the correct usage of attribute counted_by for pointer field. */ -/* { dg-do compile } */ -/* { dg-options "-O0" } */ - -typedef struct item1 Item1; -typedef union item2 Item2; - -struct pointer_array { - int count1; - Item1 *array_1 __attribute__ ((counted_by (count1))); - Item2 *array_2 __attribute__ ((counted_by (count2))); - int count2; -} *pointer_data; - -struct item1 { - int a; - float b[]; -}; - -union item2 { - int c; - float d[]; -}; - -void foo () -{ - pointer_data - = (struct pointer_array *) __builtin_malloc (sizeof (struct pointer_array)); - pointer_data->array_1 /* { dg-error "attribute is not allowed for a pointer to structure or union with flexible array member" } */ - = (Item1 *) __builtin_malloc (sizeof (Item1) + 3 * sizeof (float)); - pointer_data->array_2 /* { dg-error "attribute is not allowed for a pointer to structure or union with flexible array member" } */ - = (Item2 *) __builtin_malloc (sizeof (Item2) + 3 * sizeof (float)); - return; -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-2.c b/gcc/testsuite/gcc.dg/pointer-counted-by-2.c deleted file mode 100644 index 1f4a278..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-2.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Testing the correct usage of attribute counted_by for pointer: _BitInt */ -/* { dg-do compile { target bitint } } */ -/* { dg-options "-O2 -std=c23" } */ - -struct pointer_array { - _BitInt(24) count; - int *array __attribute__ ((counted_by (count))); - int *array1 __attribute__ ((counted_by (count1))); - _BitInt(24) count1; -}; diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-3.c b/gcc/testsuite/gcc.dg/pointer-counted-by-3.c deleted file mode 100644 index 7005609..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-3.c +++ /dev/null @@ -1,127 +0,0 @@ - /* Testing the correct usage of attribute counted_by for pointer in c23, - multiple definitions of the same tag in same or different scopes. - { dg-do compile } - { dg-options "-std=c23" } - */ - -/* Allowed redefinitions of the same struct in the same scope, with the - same counted_by attribute. */ -struct f { - int b; - int c; - int *a __attribute__ ((counted_by (b))); }; -struct f { - int b; - int c; - int *a __attribute__ ((counted_by (b))); }; -struct f { - int b; - int c; - int *a; }; /* { dg-error "redefinition of struct or union" } */ - -/* Error when the counted_by attribute is defined differently. */ -struct f { - int b; - int c; - int *a __attribute__ ((counted_by (c))); }; /* { dg-error "redefinition of struct or union" } */ - -struct h { - int b; - int c; - int *a __attribute__ ((counted_by (b))); } p; - -void test (void) -{ - struct h { - int b; - int c; - int *a __attribute__ ((counted_by (b))); } x; - - p = x; -} - -void test1 (void) -{ - struct h { - int b; - int c; - int *a __attribute__ ((counted_by (c))); } y; - - p = y; /* { dg-error "incompatible types when assigning to type" } */ -} - -struct nested_f { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (b))); -}; - -struct nested_f { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (b))); -}; - -struct nested_f { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (n))); -}; /* { dg-error "redefinition of struct or union" } */ - -struct nested_h { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (b))); -} nested_p; - -void test_2 (void) -{ -struct nested_h { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (b))); -} nested_x; - - nested_p = nested_x; -} - -void test_3 (void) -{ -struct nested_h { - struct { - union { - int b; - float f; - }; - int n; - }; - char *c __attribute__ ((counted_by (n))); -} nested_y; - - nested_p = nested_y; /* { dg-error "incompatible types when assigning to type" } */ -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c deleted file mode 100644 index c404e5b..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -#define PTR_TYPE char -#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c deleted file mode 100644 index 383d8fb..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -#define PTR_TYPE float -#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c deleted file mode 100644 index 50246d2..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -struct A { - int a; - char *b; -}; -#define PTR_TYPE struct A -#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c deleted file mode 100644 index e786d99..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ -union A { - int a; - float b; -}; -#define PTR_TYPE union A -#include "pointer-counted-by-4.c" diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-4.c b/gcc/testsuite/gcc.dg/pointer-counted-by-4.c deleted file mode 100644 index c4b3631..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-4.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Test the attribute counted_by for pointer field and its usage in - * __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -#include "builtin-object-size-common.h" -#ifndef PTR_TYPE -#define PTR_TYPE int -#endif -struct pointer_array { - int b; - PTR_TYPE *c; -} *p_array; - -struct annotated { - PTR_TYPE *c __attribute__ ((counted_by (b))); - int b; -} *p_array_annotated; - -struct nested_annotated { - PTR_TYPE *c __attribute__ ((counted_by (b))); - struct { - union { - int b; - float f; - }; - int n; - }; -} *p_array_nested_annotated; - -void __attribute__((__noinline__)) setup (int normal_count, int attr_count) -{ - p_array - = (struct pointer_array *) malloc (sizeof (struct pointer_array)); - p_array->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * normal_count); - p_array->b = normal_count; - - p_array_annotated - = (struct annotated *) malloc (sizeof (struct annotated)); - p_array_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * attr_count); - p_array_annotated->b = attr_count; - - p_array_nested_annotated - = (struct nested_annotated *) malloc (sizeof (struct nested_annotated)); - p_array_nested_annotated->c = (PTR_TYPE *) malloc (sizeof (PTR_TYPE) * attr_count); - p_array_nested_annotated->b = attr_count; - - return; -} - -void __attribute__((__noinline__)) test () -{ - EXPECT(__builtin_dynamic_object_size(p_array->c, 1), -1); - EXPECT(__builtin_dynamic_object_size(p_array_annotated->c, 1), - p_array_annotated->b * sizeof (PTR_TYPE)); - EXPECT(__builtin_dynamic_object_size(p_array_nested_annotated->c, 1), - p_array_nested_annotated->b * sizeof (PTR_TYPE)); -} - -void cleanup () -{ - free (p_array->c); - free (p_array); - free (p_array_annotated->c); - free (p_array_annotated); - free (p_array_nested_annotated->c); - free (p_array_nested_annotated); -} - -int main(int argc, char *argv[]) -{ - setup (10,10); - test (); - DONE (); - cleanup (); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-5.c b/gcc/testsuite/gcc.dg/pointer-counted-by-5.c deleted file mode 100644 index b43ffdf..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-5.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - * __builtin_dynamic_object_size: when the counted_by field is negative. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -#include "builtin-object-size-common.h" - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *array_annotated; - -struct nested_annotated { - int *c __attribute__ ((counted_by (b))); - struct { - union { - int b; - float f; - }; - int n; - }; -} *array_nested_annotated; - -void __attribute__((__noinline__)) setup (int attr_count) -{ - array_annotated - = (struct annotated *)malloc (sizeof (struct annotated)); - array_annotated->b = attr_count; - - array_nested_annotated - = (struct nested_annotated *)malloc (sizeof (struct nested_annotated)); - array_nested_annotated->b = attr_count - 1; - - return; -} - -void __attribute__((__noinline__)) test () -{ - EXPECT(__builtin_dynamic_object_size(array_annotated->c, 1), 0); - EXPECT(__builtin_dynamic_object_size(array_nested_annotated->c, 1), 0); -} - -void cleanup () -{ - free (array_annotated); - free (array_nested_annotated); -} - -int main(int argc, char *argv[]) -{ - setup (-10); - test (); - DONE (); - cleanup (); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-6.c b/gcc/testsuite/gcc.dg/pointer-counted-by-6.c deleted file mode 100644 index 355558c..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-6.c +++ /dev/null @@ -1,56 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - * __builtin_dynamic_object_size: when the type of the pointer - * is casting to another type. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -#include "builtin-object-size-common.h" - -typedef unsigned short u16; - -struct info { - u16 data_len; - char *data __attribute__((counted_by(data_len))); -}; - -struct foo { - int a; - int b; -}; - -static __attribute__((__noinline__)) -struct info *setup () -{ - struct info *p; - size_t bytes = 3 * sizeof(struct foo); - - p = (struct info *) malloc (sizeof (struct info)); - p->data = (char *) malloc (bytes); - p->data_len = bytes; - - return p; -} - -static void -__attribute__((__noinline__)) report (struct info *p) -{ - struct foo *bar = (struct foo *)p->data; - EXPECT(__builtin_dynamic_object_size((char *)(bar + 1), 1), - sizeof (struct foo) * 2); - EXPECT(__builtin_dynamic_object_size((char *)(bar + 2), 1), - sizeof (struct foo)); -} - -void cleanup (struct info *p) -{ - free (p->data); - free (p); -} - -int main(int argc, char *argv[]) -{ - struct info *p = setup(); - report(p); - cleanup (p); - return 0; -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by-7.c b/gcc/testsuite/gcc.dg/pointer-counted-by-7.c deleted file mode 100644 index af1ab27..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by-7.c +++ /dev/null @@ -1,32 +0,0 @@ -/* Additional test of the attribute counted_by for pointer field and its usage - in __builtin_dynamic_object_size. */ -/* { dg-do run } */ -/* { dg-options "-O2" } */ - -#include "builtin-object-size-common.h" - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -}; - -struct annotated __attribute__((__noinline__)) setup (int attr_count) -{ - struct annotated p_array_annotated; - p_array_annotated.c = (int *) malloc (sizeof (int) * attr_count); - p_array_annotated.b = attr_count; - - return p_array_annotated; -} - -int main(int argc, char *argv[]) -{ - struct annotated x = setup (10); - int *p = x.c; - x = setup (20); - EXPECT(__builtin_dynamic_object_size (p, 1), 10 * sizeof (int)); - EXPECT(__builtin_dynamic_object_size (x.c, 1), 20 * sizeof (int)); - free (p); - free (x.c); - DONE (); -} diff --git a/gcc/testsuite/gcc.dg/pointer-counted-by.c b/gcc/testsuite/gcc.dg/pointer-counted-by.c deleted file mode 100644 index 0f18828..0000000 --- a/gcc/testsuite/gcc.dg/pointer-counted-by.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Testing the correct usage of attribute counted_by for pointer field. - and also mixed pointer field and FMA field in the same structure. */ -/* { dg-do compile } */ -/* { dg-options "-O0" } */ - -int size; -int *x __attribute__ ((counted_by (size))); /* { dg-error "attribute is not allowed for a non-field declaration" } */ - -struct pointer_array_0 { - int count; - int array __attribute__ ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-array or non-pointer field" } */ - int other; -}; - -int count; -struct pointer_array_1 { - int other; - int *array_1 __attribute__ ((counted_by (count))); /* { dg-error "attribute is not a field declaration in the same structure as" } */ - int array_fam[] __attribute__ ((counted_by (count))); /* { dg-error "attribute is not a field declaration in the same structure as" } */ -}; - -struct pointer_array_2 { - float count1; - float count2; - int *array_2 __attribute__ ((counted_by (count1))); /* { dg-error "attribute is not a field declaration with an integer type" } */ - int array_fam[] __attribute__ ((counted_by (count2))); /* { dg-error "attribute is not a field declaration with an integer type" } */ -}; - -struct pointer_array_3 { - int count; - int *array_3 __attribute__ ((counted_by (count))) __attribute__ ((counted_by (count))); -}; - -struct pointer_array_4 { - int count1; - int count2; - int *array_4 __attribute__ ((counted_by (count1))) __attribute__ ((counted_by (count2))); /* { dg-error "conflicts with previous declaration" } */ - float array_fam[] __attribute__ ((counted_by (count2))) __attribute__ ((counted_by (count1))); /* { dg-error "conflicts with previous declaration" } */ -}; - -struct pointer_array_5 { - _Bool count; - int *array_5 __attribute__ ((counted_by (count))); -}; - -enum week {Mon, Tue, Wed}; -struct pointer_array_6 { - enum week days; - int *array_6 __attribute__ ((counted_by (days))); -}; - -struct pointer_array_7 { - int count; - void *array_7 __attribute__ ((counted_by (count))); /* { dg-error "attribute is not allowed for a pointer to void" } */ -}; - -struct pointer_array_8 { - int count; - int (*fpr)(int,int) __attribute__ ((counted_by (count))); /* { dg-error "attribute is not allowed for a pointer to function" } */ -}; - -struct item1 { - int a; - float b; -}; - -union item2 { - char *a; - int *b; -}; - -typedef struct item3 Item3; -typedef union item4 Item4; - -struct item5 { - int a; - float b[]; -}; - -/* Incomplete structure and union are allowed. */ -struct pointer_array_9 { - int count1; - int count2; - int count3; - struct item1 *array_1 __attribute__ ((counted_by (count1))); - union item2 *array_2 __attribute__ ((counted_by (count2))); - Item3 *array_3 __attribute__ ((counted_by (count3))); - Item4 *array_4 __attribute__ ((counted_by (count4))); - int count4; - int count5; - /* structure with flexible array member is not allowed. */ - struct item5 *array_5 __attribute__ ((counted_by (count5))); /* { dg-error "attribute is not allowed for a pointer to structure or union with flexible array member" } */ -}; - -struct mixed_array { - int count1; - float *array_1 __attribute__ ((counted_by (count1))); - float *array_2 __attribute__ ((counted_by (count1))); - int count2; - long *array_3 __attribute__ ((counted_by (count2))); - long array_4[] __attribute__ ((counted_by (count2))); -}; - -struct mixed_array_2 { - float *array_1 __attribute__ ((counted_by (count1))); - int count1; - float *array_2 __attribute__ ((counted_by (count1))); - long *array_3 __attribute__ ((counted_by (count2))); - int count2; - long array_4[] __attribute__ ((counted_by (count2))); -}; diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-2.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-2.c deleted file mode 100644 index 0653ecc..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-2.c +++ /dev/null @@ -1,51 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - bounds sanitizer combined with VLA. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ -/* { dg-output "index 11 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 20 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 11 out of bounds for type 'int \\\[\\\*\\\]\\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*index 10 out of bounds for type 'int \\\[\\\*\\\]'\[^\n\r]*(\n|\r\n|\r)" } */ - - -#include <stdlib.h> - -void __attribute__((__noinline__)) setup_and_test_vla (int n, int m) -{ - struct foo { - int n; - int (*p)[n] __attribute__((counted_by(n))); - } *f; - - f = (struct foo *) malloc (sizeof (struct foo)); - f->p = (int (*)[n]) malloc (m * sizeof (int[n])); - f->n = m; - f->p[m][n-1] = 1; - free (f->p); - free (f); - return; -} - -void __attribute__((__noinline__)) setup_and_test_vla_1 (int n1, int n2, int m) -{ - struct foo { - int n; - int (*p)[n2][n1] __attribute__((counted_by(n))); - } *f; - - f = (struct foo *) malloc (sizeof(struct foo)); - f->p = (int (*)[n2][n1]) malloc (m * sizeof (int[n2][n1])); - f->n = m; - f->p[m][n2][n1] = 1; - free (f->p); - free (f); - return; -} - -int main(int argc, char *argv[]) -{ - setup_and_test_vla (10, 11); - setup_and_test_vla_1 (10, 11, 20); - return 0; -} - diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-3.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-3.c deleted file mode 100644 index 731422d..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-3.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in bounds - sanitizer. when counted_by field is negative value. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ - -#include <stdlib.h> - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *array_annotated; - -void __attribute__((__noinline__)) setup (int annotated_count) -{ - array_annotated - = (struct annotated *)malloc (sizeof (struct annotated)); - array_annotated->c = (int *) malloc (sizeof (int) * 10); - array_annotated->b = annotated_count; - - return; -} - -void __attribute__((__noinline__)) test (int annotated_index) -{ - array_annotated->c[annotated_index] = 2; -} - -void cleanup () -{ - free (array_annotated->c); - free (array_annotated); -} - -int main(int argc, char *argv[]) -{ - setup (-3); - test (2); - cleanup (); - return 0; -} - -/* { dg-output "25:21: runtime error: index 2 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-4.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-4.c deleted file mode 100644 index 52f202f..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-4.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in bounds - sanitizer. when counted_by field is zero value. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ - -#include <stdlib.h> - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *array_annotated; - -void __attribute__((__noinline__)) setup (int annotated_count) -{ - array_annotated - = (struct annotated *)malloc (sizeof (struct annotated)); - array_annotated->c = (int *)malloc (sizeof (int) * 10); - array_annotated->b = annotated_count; - - return; -} - -void __attribute__((__noinline__)) test (int annotated_index) -{ - array_annotated->c[annotated_index] = 2; -} - -void cleanup () -{ - free (array_annotated->c); - free (array_annotated); -} - -int main(int argc, char *argv[]) -{ - setup (0); - test (1); - cleanup (); - return 0; -} - -/* { dg-output "25:21: runtime error: index 1 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-5.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-5.c deleted file mode 100644 index 8ad7572..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-5.c +++ /dev/null @@ -1,40 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - bounds sanitizer. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ - -#include <stdlib.h> - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *p_array_annotated; - -void __attribute__((__noinline__)) setup (int annotated_count) -{ - p_array_annotated - = (struct annotated *)malloc (sizeof (struct annotated)); - p_array_annotated->c = (int *) malloc (annotated_count * sizeof (int)); - p_array_annotated->b = annotated_count; - - return; -} - -void cleanup () -{ - free (p_array_annotated->c); - free (p_array_annotated); -} - -int main(int argc, char *argv[]) -{ - int i; - setup (10); - for (i = 0; i < 11; i++) - p_array_annotated->c[i] = 2; // goes boom at i == 10 - cleanup (); - return 0; -} - - -/* { dg-output "34:25: runtime error: index 10 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds.c b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds.c deleted file mode 100644 index c5a1ac5..0000000 --- a/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Test the attribute counted_by for pointer fields and its usage in - bounds sanitizer. */ -/* { dg-do run } */ -/* { dg-options "-fsanitize=bounds" } */ - -#include <stdlib.h> - -struct pointer_array { - int b; - int *c; -} *p_array; - -struct annotated { - int b; - int *c __attribute__ ((counted_by (b))); -} *p_array_annotated; - -void __attribute__((__noinline__)) setup (int normal_count, int annotated_count) -{ - p_array - = (struct pointer_array *) malloc (sizeof (struct pointer_array)); - p_array->c = (int *) malloc (normal_count * sizeof (int)); - p_array->b = normal_count; - - p_array_annotated - = (struct annotated *) malloc (sizeof (struct annotated)); - p_array_annotated->c = (int *) malloc (annotated_count * sizeof (int)); - p_array_annotated->b = annotated_count; - - return; -} - -void __attribute__((__noinline__)) test (int normal_index, int annotated_index) -{ - p_array->c[normal_index] = 1; - p_array_annotated->c[annotated_index] = 2; -} - -int main(int argc, char *argv[]) -{ - setup (10, 10); - test (10, 10); - return 0; -} - -/* { dg-output "36:23: runtime error: index 10 out of bounds for type" } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr120817.c b/gcc/testsuite/gcc.dg/vect/pr120817.c index d8f55c9..199189a 100644 --- a/gcc/testsuite/gcc.dg/vect/pr120817.c +++ b/gcc/testsuite/gcc.dg/vect/pr120817.c @@ -1,5 +1,6 @@ /* { dg-additional-options "-O1" } */ -/* { dg-additional-options "-mcpu=neoverse-n2" { target aarch64*-*-* } } */ +/* { dg-require-effective-target aarch64_sve_hw { target aarch64*-*-* } } */ +/* { dg-additional-options "-march=armv8-a+sve -mtune=neoverse-n2" { target aarch64*-*-* } } */ #include "tree-vect.h" diff --git a/gcc/testsuite/gcc.target/aarch64/popcnt13.c b/gcc/testsuite/gcc.target/aarch64/popcnt13.c new file mode 100644 index 0000000..2a30e98 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/popcnt13.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#pragma GCC target "+nocssc+sve" + +/* +** h128: +** ldr q([0-9]+), \[x0\] +** ptrue p([0-9]+).b, vl16 +** cnt z([0-9]+).d, p\2/m, z\1.d +** addp d([0-9]+), v\3.2d +** fmov x0, d\4 +** ret +*/ + +unsigned h128 (const unsigned __int128 *a) { + return __builtin_popcountg (a[0]); +} + +/* There should be only one POPCOUNT. */ +/* { dg-final { scan-tree-dump-times "POPCOUNT " 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-not " __builtin_popcount" "optimized" } } */ + diff --git a/gcc/testsuite/gcc.target/aarch64/popcnt9.c b/gcc/testsuite/gcc.target/aarch64/popcnt9.c index c778fc7..cfed8c5 100644 --- a/gcc/testsuite/gcc.target/aarch64/popcnt9.c +++ b/gcc/testsuite/gcc.target/aarch64/popcnt9.c @@ -3,7 +3,7 @@ /* { dg-final { check-function-bodies "**" "" } } */ /* PR target/113042 */ -#pragma GCC target "+nocssc" +#pragma GCC target "+nocssc+nosve" /* ** h128: diff --git a/gcc/testsuite/gcc.target/s390/fminmax-1.c b/gcc/testsuite/gcc.target/s390/fminmax-1.c new file mode 100644 index 0000000..df10905 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/fminmax-1.c @@ -0,0 +1,77 @@ +/* Check fmin/fmax expanders for scalars on VXE targets. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -march=z14 -mzarch" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* +** dofmaxl: +** vl (%v.),0\(%r3\),3 +** vl (%v.),0\(%r4\),3 +** wfmaxxb (%v.),\1,\2,4 +** vst \3,0\(%r2\),3 +** br %r14 +*/ +long double +dofmaxl (long double d1, long double d2) +{ + return __builtin_fmaxl (d1, d2); +} + +/* +** dofminl: +** vl (%v.),0\(%r3\),3 +** vl (%v.),0\(%r4\),3 +** wfminxb (%v.),\1,\2,4 +** vst \3,0\(%r2\),3 +** br %r14 +*/ +long double +dofminl (long double d1, long double d2) +{ + return __builtin_fminl (d1, d2); +} + +/* +** dofmax: +** wfmaxdb %v0,%v0,%v2,4 +** br %r14 +*/ +double +dofmax (double d1, double d2) +{ + return __builtin_fmax (d1, d2); +} + +/* +** dofmin: +** wfmindb %v0,%v0,%v2,4 +** br %r14 +*/ +double +dofmin (double d1, double d2) +{ + return __builtin_fmin (d1, d2); +} + +/* +** dofmaxf: +** wfmaxsb %v0,%v0,%v2,4 +** br %r14 +*/ +float +dofmaxf (float f1, float f2) +{ + return __builtin_fmaxf (f1, f2); +} + +/* +** dofminf: +** wfminsb %v0,%v0,%v2,4 +** br %r14 +*/ +float +dofminf (float f1, float f2) +{ + return __builtin_fminf (f1, f2); +} diff --git a/gcc/testsuite/gcc.target/s390/fminmax-2.c b/gcc/testsuite/gcc.target/s390/fminmax-2.c new file mode 100644 index 0000000..ea37a0a --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/fminmax-2.c @@ -0,0 +1,29 @@ +/* Check fmin/fmax expanders for scalars on non-VXE targets. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -march=z13 -mzarch" } */ +/* { dg-final { scan-assembler-times "jg" 4 } } */ + +double +dofmax (double d1, double d2) +{ + return __builtin_fmax (d1, d2); +} + +double +dofmin (double d1, double d2) +{ + return __builtin_fmin (d1, d2); +} + +float +dofmaxf (float f1, float f2) +{ + return __builtin_fmaxf (f1, f2); +} + +float +dofminf (float f1, float f2) +{ + return __builtin_fminf (f1, f2); +} diff --git a/gcc/testsuite/gcc.target/xtensa/pr120888-1.c b/gcc/testsuite/gcc.target/xtensa/pr120888-1.c new file mode 100644 index 0000000..f438e4c --- /dev/null +++ b/gcc/testsuite/gcc.target/xtensa/pr120888-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-rtl-expand" } */ + +void u8(unsigned char c); +void cu8(unsigned char *p) +{ + u8(*p); +} + +/* { dg-final { scan-rtl-dump "zero_extend" "expand" } } */ +/* { dg-final { scan-rtl-dump-not "sign_extend" "expand" } } */ diff --git a/gcc/testsuite/gcc.target/xtensa/pr120888-2.c b/gcc/testsuite/gcc.target/xtensa/pr120888-2.c new file mode 100644 index 0000000..9b5caad --- /dev/null +++ b/gcc/testsuite/gcc.target/xtensa/pr120888-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-rtl-expand" } */ + +void s8(signed char c); +void cs8(signed char *p) +{ + s8(*p); +} + +/* { dg-final { scan-rtl-dump "sign_extend" "expand" } } */ +/* { dg-final { scan-rtl-dump-not "zero_extend" "expand" } } */ diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp index 97935cb..a2311de 100644 --- a/gcc/testsuite/lib/scanasm.exp +++ b/gcc/testsuite/lib/scanasm.exp @@ -1109,6 +1109,8 @@ proc check-function-bodies { args } { append function_regexp ".*" } elseif { [regexp {^\.L} $line] } { append function_regexp $line "\n" + } elseif { [regexp {^[0-9]+:} $line] } { + append function_regexp $line "\n" } else { append function_regexp $config(line_prefix) $line "\n" } diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc index a551f2b..2d13ab7 100644 --- a/gcc/tree-object-size.cc +++ b/gcc/tree-object-size.cc @@ -861,12 +861,10 @@ addr_object_size (struct object_size_info *osi, const_tree ptr, 4th argument TYPE_OF_SIZE: A constant 0 with its TYPE being the same as the TYPE of the object referenced by REF_TO_SIZE 6th argument: A constant 0 with the pointer TYPE to the original flexible - array type or pointer field type. + array type. The size of the element can be retrived from the TYPE of the 6th argument - of the call, which is the pointer to the original flexible array type or - the type of the original pointer field. */ - + of the call, which is the pointer to the array type. */ static tree access_with_size_object_size (const gcall *call, int object_size_type) { @@ -876,7 +874,7 @@ access_with_size_object_size (const gcall *call, int object_size_type) gcc_assert (gimple_call_internal_p (call, IFN_ACCESS_WITH_SIZE)); /* The type of the 6th argument type is the pointer TYPE to the original - flexible array type or to the original pointer type. */ + flexible array type. */ tree pointer_to_array_type = TREE_TYPE (gimple_call_arg (call, 5)); gcc_assert (POINTER_TYPE_P (pointer_to_array_type)); tree element_type = TREE_TYPE (TREE_TYPE (pointer_to_array_type)); @@ -1944,17 +1942,6 @@ collect_object_sizes_for (struct object_size_info *osi, tree var) if (TREE_CODE (rhs) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (rhs))) reexamine = merge_object_sizes (osi, var, rhs); - /* Handle the following stmt #2 to propagate the size from the - stmt #1 to #3: - 1 _1 = .ACCESS_WITH_SIZE (_3, _4, 1, 0, -1, 0B); - 2 _5 = *_1; - 3 _6 = __builtin_dynamic_object_size (_5, 1); - */ - else if (TREE_CODE (rhs) == MEM_REF - && POINTER_TYPE_P (TREE_TYPE (rhs)) - && TREE_CODE (TREE_OPERAND (rhs, 0)) == SSA_NAME - && integer_zerop (TREE_OPERAND (rhs, 1))) - reexamine = merge_object_sizes (osi, var, TREE_OPERAND (rhs, 0)); else expr_object_size (osi, var, rhs); } diff --git a/gcc/value-range.h b/gcc/value-range.h index 5c358f3..3bc02db 100644 --- a/gcc/value-range.h +++ b/gcc/value-range.h @@ -324,7 +324,7 @@ public: virtual void update_bitmask (const class irange_bitmask &) override; virtual irange_bitmask get_bitmask () const override; - virtual void verify_range () const; + virtual void verify_range () const override; protected: void maybe_resize (int needed); virtual void set (tree, tree, value_range_kind = VR_RANGE) override; @@ -422,7 +422,7 @@ public: bool contains_p (const wide_int &) const; wide_int lower_bound () const; wide_int upper_bound () const; - virtual void verify_range () const; + virtual void verify_range () const final override; irange_bitmask get_bitmask () const final override; void update_bitmask (const irange_bitmask &) final override; protected: @@ -594,7 +594,7 @@ public: bool nan_signbit_p (bool &signbit) const; bool known_isnormal () const; bool known_isdenormal_or_zero () const; - virtual void verify_range () const; + virtual void verify_range () const override; protected: virtual bool contains_p (tree cst) const override; virtual void set (tree, tree, value_range_kind = VR_RANGE) override; diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index 72cd569..75ee7e8 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -280,8 +280,8 @@ namespace __format // in the format-spec, e.g. "{:L%a}" is localized and locale-specific, // but "{:L}" is only localized and "{:%a}" is only locale-specific. unsigned _M_locale_specific : 1; - // Indicates that we are handling duration. - unsigned _M_time_only : 1; + // Indicates that we are handling time_point. + unsigned _M_time_point : 1; // Indicates that duration should be treated as floating point. unsigned _M_floating_point_rep : 1; // Indicate that duration uses user-defined representation. @@ -693,8 +693,11 @@ namespace __format __allowed_mods = _Mod_O; break; case 'j': - __needed = __spec._M_time_only ? _HoursMinutesSeconds - : _DayOfYear; + __needed = __parts & _DayOfYear; + // If we do not know day-of-year then we must have a duration, + // which is to be formatted as decimal number of days. + if (__needed == _None) + __needed = _HoursMinutesSeconds; break; case 'm': __needed = _Month; @@ -919,7 +922,13 @@ namespace __format { switch (__conv) { + case 'a': + case 'A': + case 'b': + case 'B': case 'c': + case 'h': + case 'p': case 'r': case 'x': case 'X': @@ -947,6 +956,32 @@ namespace __format return __out; } + void + _M_check_ok(const _ChronoData<_CharT>& __t, _CharT __conv) const + { + // n.b. for time point all date parts are computed, so + // they are always ok. + if (_M_spec._M_time_point || _M_spec._M_debug) + return; + + switch (__conv) + { + case 'a': + case 'A': + if (!__t._M_weekday.ok()) [[unlikely]] + __throw_format_error("format error: invalid weekday"); + return; + case 'b': + case 'h': + case 'B': + if (!__t._M_month.ok()) [[unlikely]] + __throw_format_error("format error: invalid month"); + return; + default: + return; + } + } + template<typename _OutIter, typename _FormatContext> _OutIter _M_format_to(const _ChronoData<_CharT>& __t, _OutIter __out, @@ -1003,6 +1038,8 @@ namespace __format do { _CharT __c = *__first++; + _M_check_ok(__t, __c); + if (__use_locale_fmt && _S_localized_spec(__c, __mod)) [[unlikely]] __out = _M_locale_fmt(std::move(__out), __fc.locale(), __tm, __c, __mod); @@ -1153,11 +1190,8 @@ namespace __format { // %a Locale's abbreviated weekday name. // %A Locale's full weekday name. - if (!__wd.ok()) + if (_M_spec._M_debug && !__wd.ok()) { - if (!_M_spec._M_debug) - __throw_format_error("format error: invalid weekday"); - _CharT __buf[3]; __out = __format::__write(std::move(__out), _S_str_d1(__buf, __wd.c_encoding())); @@ -1183,11 +1217,8 @@ namespace __format { // %b Locale's abbreviated month name. // %B Locale's full month name. - if (!__m.ok()) + if (_M_spec._M_debug && !__m.ok()) { - if (!_M_spec._M_debug) - __throw_format_error("format error: invalid month"); - _CharT __buf[3]; __out = __format::__write(std::move(__out), _S_str_d1(__buf, (unsigned)__m)); @@ -1419,7 +1450,7 @@ namespace __format _OutIter _M_j(const _ChronoData<_CharT>& __t, _OutIter __out) const { - if (_M_spec._M_time_only) + if (!_M_spec._M_needs(_ChronoParts::_DayOfYear)) { // Decimal number of days, without padding. auto __d = chrono::floor<chrono::days>(__t._M_hours).count(); @@ -1766,7 +1797,7 @@ namespace __format { if (__n < 100) [[likely]] return _S_two_digits(__n); - return _S_str_d3(__buf, __n); + return _S_str_d3(__buf, __n); } // Returns decimal representation of __n, padded to 3 digits. @@ -1811,7 +1842,7 @@ namespace __format using enum _ChronoParts; _ChronoSpec<_CharT> __res{}; - __res._M_time_only = (__parts & _Date) == 0; + __res._M_time_point = (__parts & _DateTime) == _DateTime; __res._M_floating_point_rep = chrono::treat_as_floating_point_v<_Rep>; __res._M_custom_rep = !is_arithmetic_v<_Rep>; __res._M_prec = chrono::hh_mm_ss<_Duration>::fractional_width; diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index a7188f4..75e794f 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1211,7 +1211,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else // Forward iterator requirements template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1220,7 +1220,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() == __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1229,7 +1229,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() == __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1238,7 +1238,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() != __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1248,15 +1248,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Random access iterator requirements template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR + _GLIBCXX_CONSTEXPR inline bool operator<(const __normal_iterator& __lhs, const __normal_iterator<_Iter, _Container>& __rhs) _GLIBCXX_NOEXCEPT { return __lhs.base() < __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX20_CONSTEXPR bool @@ -1265,15 +1266,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() < __rhs.base(); } template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR + _GLIBCXX_CONSTEXPR bool operator>(const __normal_iterator& __lhs, const __normal_iterator<_Iter, _Container>& __rhs) _GLIBCXX_NOEXCEPT { return __lhs.base() > __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1282,7 +1284,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() > __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1291,7 +1293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() <= __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1300,7 +1302,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() <= __rhs.base(); } template<typename _Iter> - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1309,7 +1311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() >= __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR bool @@ -1341,7 +1343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif { return __lhs.base() - __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR difference_type @@ -1349,7 +1351,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_NOEXCEPT { return __lhs.base() - __rhs.base(); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) friend _GLIBCXX_CONSTEXPR __normal_iterator diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index c72a640..4a06fb2 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -509,7 +509,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Layout, typename _Mapping> concept __mapping_of = - is_same_v<typename _Layout::mapping<typename _Mapping::extents_type>, + is_same_v<typename _Layout::template mapping<typename _Mapping::extents_type>, _Mapping>; template<typename _Mapping> diff --git a/libstdc++-v3/testsuite/ext/verify_neg.cc b/libstdc++-v3/testsuite/ext/verify_neg.cc new file mode 100644 index 0000000..ce03374 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/verify_neg.cc @@ -0,0 +1,28 @@ +// { dg-do compile { target c++11 } } + +#include <testsuite_hooks.h> + +struct X { explicit operator void*() const { return nullptr; } }; + +void +test_VERIFY(int i) +{ + // This should not be parsed as a function type bool(bool(i)): + VERIFY( bool(i) ); + + // This should not produce warnings about lambda in unevaluated context: + VERIFY( []{ return 1; }() ); + + // Only one expression allowed: + VERIFY(1, 2); // { dg-error "in expansion of macro" } + // { dg-error "compound expression in functional cast" "" { target *-*-* } 0 } + + // A scoped enum is not contextually convertible to bool: + enum class E { E0 }; + VERIFY( E::E0 ); // { dg-error "could not convert" } + + // explicit conversion to void* is not contextually convertible to bool: + X x; + VERIFY( x ); // { dg-error "in expansion of macro" } + // { dg-error "invalid cast .* to type 'bool'" "" { target *-*-* } 0 } +} diff --git a/libstdc++-v3/testsuite/std/time/format/format.cc b/libstdc++-v3/testsuite/std/time/format/format.cc index d6e3583..00affb9 100644 --- a/libstdc++-v3/testsuite/std/time/format/format.cc +++ b/libstdc++-v3/testsuite/std/time/format/format.cc @@ -78,6 +78,13 @@ test_bad_format_strings() VERIFY( not is_format_string_for("{:%OOy}", t) ); VERIFY( not is_format_string_for("{:%OEy}", t) ); VERIFY( not is_format_string_for("{:%EOy}", t) ); + + // weekday and month values for which ok() is false + VERIFY( not is_format_string_for("{:%a}", std::chrono::weekday(8)) ); + VERIFY( not is_format_string_for("{:%A}", std::chrono::weekday(8)) ); + VERIFY( not is_format_string_for("{:%b}", std::chrono::month(13)) ); + VERIFY( not is_format_string_for("{:%h}", std::chrono::month(13)) ); + VERIFY( not is_format_string_for("{:%B}", std::chrono::month(13)) ); } template<typename I> diff --git a/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc b/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc new file mode 100644 index 0000000..03b9496 --- /dev/null +++ b/libstdc++-v3/testsuite/std/time/format/pr117214_custom_timeput.cc @@ -0,0 +1,37 @@ +// { dg-do run { target c++20 } } + +#include <chrono> +#include <format> +#include <locale> +#include <testsuite_hooks.h> + +struct custom_time_put : std::time_put<char> +{ + iter_type + do_put(iter_type out, std::ios_base& io, char_type fill, const tm* t, + char format, char modifier) const override + { + using Base = std::time_put<char>; + + switch (format) { + case 'a': case 'A': case 'b': case 'h': case 'B': case 'p': + *out++ = '['; + *out++ = format; + *out++ = ']'; + } + return Base::do_put(out, io, fill, t, format, modifier); + } +}; + +int main() +{ + using namespace std::chrono; + std::locale loc(std::locale::classic(), new custom_time_put); +#define test(t, fmt, exp) VERIFY( std::format(loc, fmt, t) == exp ) + test(Monday, "{:L%a}", "[a]Mon"); + test(Monday, "{:L%A}", "[A]Monday"); + test(January, "{:L%b}", "[b]Jan"); + test(January, "{:L%h}", "[h]Jan"); + test(January, "{:L%B}", "[B]January"); + test(1h, "{:L%p}", "[p]AM"); +} diff --git a/libstdc++-v3/testsuite/util/testsuite_hooks.h b/libstdc++-v3/testsuite/util/testsuite_hooks.h index faa01ba..bf34fd1 100644 --- a/libstdc++-v3/testsuite/util/testsuite_hooks.h +++ b/libstdc++-v3/testsuite/util/testsuite_hooks.h @@ -58,16 +58,13 @@ # define _VERIFY_PRINT(S, F, L, P, C) __builtin_printf(S, F, L, P, C) #endif -#define VERIFY(fn) \ - do \ - { \ - if (! (fn)) \ - { \ - _VERIFY_PRINT("%s:%d: %s: Assertion '%s' failed.\n", \ - __FILE__, __LINE__, __PRETTY_FUNCTION__, #fn); \ - __builtin_abort(); \ - } \ - } while (false) +#define VERIFY(...) \ + ((void)((__VA_ARGS__) \ + ? (void)(true ? true : bool(__VA_ARGS__)) \ + : (_VERIFY_PRINT("%s:%d: %s: Assertion '%s' failed.\n", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, \ + #__VA_ARGS__), \ + __builtin_abort()))) #ifdef _GLIBCXX_HAVE_UNISTD_H # include <unistd.h> |