diff options
Diffstat (limited to 'gcc')
58 files changed, 2265 insertions, 162 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 78239f0..9004d1c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,65 @@ +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * tree-object-size.cc (access_with_size_object_size): Update comments + for pointers with .ACCESS_WITH_SIZE. + (collect_object_sizes_for): Propagate size info through GIMPLE_ASSIGN + for pointers with .ACCESS_WITH_SIZE. + +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * doc/extend.texi: Extend counted_by attribute to pointer fields in + structures. Add one more requirement to pointers with counted_by + attribute. + +2025-07-01 Jakub Jelinek <jakub@redhat.com> + + PR c++/120471 + * tree.h (address_invariant_p): New function. + * tree.cc (address_invariant_p): New function. + (tree_invariant_p_1): Use it for ADDR_EXPR handling. Formatting + tweak. + +2025-07-01 Remi Machet <rmachet@nvidia.com> + + * config/aarch64/aarch64-simd.md (*shrn_to_subhn_<mode>): Add pattern + converting mvn+shrn into mvni+subhn. + +2025-07-01 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/120608 + * passes.def (pass_musttail): Move before pass_sanopt. + * tree-tailcall.cc (empty_eh_cleanup): Handle GIMPLE_RESX + which doesn't throw externally through recursion on single + eh edge (if any and cnt still allows that). + (find_tail_calls): Add ESUCC, IGNORED_EDGES and MUST_SEE_BBS + arguments. Handle GIMPLE_CONDs for non-simplified cleanups with + finally_tmp temporaries both on backward and forward walks, adjust + recursive call. + (tree_optimize_tail_calls_1): Adjust find_tail_calls callers. + +2025-07-01 Ezra Sitorus <ezra.sitorus@arm.com> + + * config/aarch64/aarch64-sys-regs.def: Copy from Binutils. + +2025-07-01 H.J. Lu <hjl.tools@gmail.com> + + PR debug/120902 + * print-tree.cc (debug with const tree_node *): Call debug_tree + instead of debug. + +2025-07-01 Yuao Ma <c8ef@outlook.com> + + * fold-const-call.cc (fold_const_call_ss): Constant fold for + single arg pi-based trigonometric builtins. + (fold_const_call_sss): Constant fold for double arg pi-based + trigonometric builtins. + * fold-const.cc (negate_mathfn_p): asinpi/atanpi is odd func. + (tree_call_nonnegative_warnv_p): acospi always non-neg, + asinpi/atanpi non-neg iff arg non-neg. + * tree-call-cdce.cc (can_test_argument_range): Add acospi/asinpi. + (edom_only_function): Add acospi/asinpi/cospi/sinpi. + (get_no_error_domain): Add acospi/asinpi. + 2025-06-30 Jeff Law <jlaw@ventanamicro.com> PR rtl-optimization/120242 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ac92899..46e9463 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20250701 +20250702 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 88b27a8..8aaa006 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,405 @@ +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/120705 + * exp_ch6.adb (Needs_BIP_Collection): Always return False if the + type has relaxed finalization. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * libgnat/s-valuef.adb (Integer_to_Fixed): Restore rounding of the + first scaled divide operation. + +2025-07-01 Piotr Trojanek <trojanek@adacore.com> + + * gnat1drv.adb (Gnat1drv): Do minimal decoration of the spec and body + of an ignored ghost compilation unit. + +2025-07-01 Piotr Trojanek <trojanek@adacore.com> + + * ali.ads (Unit_Record): Fix grammar in comment. + * bindgen.adb (Num_Elab_Calls, Num_Primary_Stacks): Remove counters + that were only incremented and never actually used. + +2025-07-01 Tonu Naks <naks@adacore.com> + + * libgnat/s-valuer.adb (Scan_Decimal_Digits, + Scan_Integral_Digits): fix condition for rejecting + underscore. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * libgnat/s-valued.adb (Integer_To_Decimal): Deal specifically with + Val = 2**(Int'Size - 1) if Minus is not set. Exit the loops when V + saturates to 0 in the case of (huge) negative exponents. Use Base + instead of B consistently in unsigned computations. + * libgnat/s-valuef.adb (Integer_To_Fixed): Use Base instead of B + consistently in unsigned computations. + +2025-07-01 Piotr Trojanek <trojanek@adacore.com> + + * exp_ch4.adb (Fixup_Universal_Fixed_Operation): Move to spec. + * exp_ch4.ads (Fixup_Universal_Fixed_Operation): Move from body. + * exp_spark.adb (Expand_SPARK): Call a fixup expansion routine. + +2025-07-01 Gary Dismukes <dismukes@adacore.com> + + * exp_ch3.adb (Build_Heap_Or_Pool_Allocator): Test not Has_Relaxed_Finalization + as a guard against retrieving BIP_Collection formal (and related code). + +2025-07-01 Javier Miranda <miranda@adacore.com> + + * exp_ch3.adb (Build_Untagged_Record_Equality): Report the + warning when no component of an untagged record type U is a + record type, and the type C of some of its components has + defined its user-defined equality operator "=". + * exp_ch4.adb (Expand_Composite_Equality): Report the warning + calling Warn_On_Ignored_Equality_Operator. + * sem_warn.ads (Warn_On_Ignored_Equality_Operator): New subprogram. + * sem_warn.adb (Warn_On_Ignored_Equality_Operator): Factorize code + reporting the warning. + +2025-07-01 Tonu Naks <naks@adacore.com> + + * libgnat/a-ngelfu.adb: conditional computation of X^2 + +2025-07-01 Steve Baird <baird@adacore.com> + + * Makefile.rtl: Add entry for new unit's object file. + * libgnat/s-casuti.adb: Remove bodies of subprograms that were moved + to the new unit. + * libgnat/s-casuti.ads: Replace (with renamings) declarations for + subprograms that moved to the new unit. + * libgnat/s-cautns.adb: Body for new unit (a new source file). + * libgnat/s-cautns.ads: Spec for new unit (a new source file). + * libgnat/s-valuti.adb: Use the new unit instead of the old one. + * gcc-interface/Make-lang.in: Add entries for new unit's object file. + * gcc-interface/Makefile.in: Likewise. + +2025-07-01 Gary Dismukes <dismukes@adacore.com> + + * sem_ch3.adb (Constrain_Corresponding_Record): Inherit Class_Wide_Type on the + created constrained subtype. + +2025-07-01 Artur Pietrek <pietrek@adacore.com> + + * doc/gnat_ugn/building_executable_programs_with_gnat.rst: add + GNAT LLVM explicit selection in GPR file + * gnat_ugn.texi: Regenerate. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * exp_ch7.adb (Shift_Address_For_Descriptor): Add dummy variable + to make sure that System_Storage_Elements is loaded. + +2025-07-01 Ronan Desplanques <desplanques@adacore.com> + + * doc/gnat_rm/gnat_language_extensions.rst: Document new extension. + * gen_il-fields.ads (Opt_Field_Enum): Add new fields. + * gen_il-types.ads (N_Loop_Flow_Statement, N_Continue_Statement): New + node kinds. + * gen_il-gen-gen_nodes.adb (N_Loop_Flow_Statement): New abstract node + kind. + (N_Continue_Statement): New node kind. + (N_Exit_Statement): Reparent below N_Loop_Flow_Statement. + * sinfo.ads (N_Continue_Statement): Add description. + * sinfo-utils.ads (Loop_Flow_Keyword): New function. + * sinfo-utils.adb (Loop_Flow_Keyword): New function. + * gen_il-gen-gen_entities.adb (E_Loop): Add new field. + * einfo.ads (Continue_Mark): Document new field. + * sprint.adb (Sprint_Node_Actual): Update for new node kind. + * snames.ads-tmpl: Add new keyword. + * par-ch5.adb (P_Continue_Statement, Parse_Loop_Flow_Statement): New + functions. + (P_Sequence_Of_Statements): Handle continue statements. + (P_Exit_Statement): Use Parse_Loop_Flow_Statement. + * sem.adb (Analyze): Handle new node kind. + * sem_ch5.adb (Analyze_Loop_Flow_Statement): New function. + (Analyze_Continue_Statement): New procedure. + (Analyze_Exit_Statement): Use new Analyze_Loop_Flow_Statement function. + * sem_ch5.ads (Analyze_Continue_Statement): New procedure. + * expander.adb (Expand): Handle new node kind. + * exp_ch5.ads (Expand_N_Continue_Statement): New procedure. + * exp_ch5.adb (Expand_Loop_Flow_Statement): New procedure. + (Expand_N_Continue_Statement): New procedure. + (Expand_N_Exit_Statement): Use new Expand_Loop_Flow_Statement + procedure. + (Build_Formal_Container_Iteration): Always reuse original loop entity. + * gnat_rm.texi: Regenerate. + +2025-07-01 Bob Duff <duff@adacore.com> + + * repinfo.adb (List_Entities): + Disable output in case of object renamings. + +2025-07-01 Aleksandra Pasek <pasek@adacore.com> + + * libgnat/s-valuen.ads: Correct comment. + +2025-07-01 Alexandre Oliva <oliva@adacore.com> + + * init.c: Include string.h. + +2025-07-01 Tonu Naks <naks@adacore.com> + + * doc/gnat_rm.rst: remove ref to 2012 chapter + * doc/gnat_rm/about_this_guide.rst: remove ref to 2012 chapter + * doc/gnat_rm/compatibility_and_porting_guide.rst: update list of + supported versions + * doc/gnat_rm/implementation_of_ada_2012_features.rst: delete + * doc/gnat_rm/specialized_needs_annexes.rst: update list of + supported versions + * gnat_rm.texi: Regenerate. + +2025-07-01 Tonu Naks <naks@adacore.com> + + * doc/gnat_rm/implementation_advice.rst: remove GLADE + * doc/gnat_rm/implementation_defined_characteristics.rst: remove GLADE + * doc/gnat_rm/specialized_needs_annexes.rst: remove GLADE + * doc/gnat_rm/the_gnat_library.rst: remove GLADE + * gnat_rm.texi: Regenerate. + +2025-07-01 Alexandre Oliva <oliva@adacore.com> + + * adaint.c [__vxworks] (alloca): Redirect to builtin. + +2025-07-01 Ghjuvan Lacambre <lacambre@adacore.com> + + * freeze.adb (Freeze_Record_Type): Check for CodePeer_Mode. + +2025-07-01 Piotr Trojanek <trojanek@adacore.com> + + * sem_ch12.adb (Analyze_Subprogram_Instantiation): Move aspects when + instantiating subprogram as a library unit. + +2025-07-01 Ronan Desplanques <desplanques@adacore.com> + + * exp_ch5.adb (Expand_N_Loop_Statement): Remove useless subexpressions. + +2025-07-01 Jose Ruiz <ruiz@adacore.com> + + * doc/gnat_ugn/gnat_and_program_execution.rst: Add the + documentation about benefits of using sanitizers in + mixed-language applications. + * gnat_ugn.texi: Regenerate. + +2025-07-01 Viljar Indus <indus@adacore.com> + + * atree.ads (Compile_Time_Pragma_Warnings): Removed. + * errout.adb (Initialize): Remove initialization for + Compile_Time_Pragma_Warnings. + (Error_Msg_Internal): Use Warning_As_Error_Kind in the + Error_Msg_Object. Set its value based on the reason the + warning was changed to an error. + (Write_JSON_Span): Adjust the code for Warn_Err. + (Output_Messages): Update the calculation for actual warnings + and errors by just using Warnings_Treated_As_Errors. + (Set_Msg_Text): Simply mark that we are dealing with a + run time message here. Move the code for the Warning_Mode to + Error_Msg_Internal. + * erroutc-pretty_emitter.adb (Write_Error_Msg_Line): Adjust the code + for Warn_Err. Use the Warn_As_Err_Tag token. + * erroutc.adb (Compilation_Errors): Simplify the implementation so + that it only checks for errors and warnings treated as errors. + (Decrease_Error_Msg_Count): Remove the count for + Compile_Time_Pragma_Warnings. + (dmsg): Adjust the code for changes to Warn_Err. + (Increase_Error_Msg_Count): Likewise and remove the count for + Compile_Time_Pragma_Warnings. + (Output_Msg_Text): Warnings converted to error by the + Warning_As_Error pragma and -gnatwE now use the error prefix + in their messages but only warnings changed by the pragma get + the [warning-as-error] tag. + (Output_Text_Within): Adjust the variable name for + Is_Runtime_Raise_Msg. + (Write_Error_Summary): Adjust printing of warnings so that it + just uses the counts for Warnings_Detected and + Warnings_Treated_As_Errors. + * erroutc.ads (Is_Runtime_Raise): renamed to Is_Runtime_Raise_Msg. + (Warning_As_Error_Kind): New type for marking the warning message + is treated as an error which also captures the reason for the + change. Historically each of the reasons will have a different way + of displaying the warning message. + (Error_Msg_Object.Warn_Err): Change type to Warning_As_Error_Kind. + (Kind_To_String): Warnings treated as errors originating from + the pragma or -gnatwE will return error where as warnings + originating from -gnatwe will return warning. + (Compilation_Errors): Update the documentation. + (Warn_As_Err_Tag): Constant string to be used when printing warnings + as errors. + * errutil.adb (Error_Msg): Adjust the code for Warn_Err. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * exp_ch7.adb (Shift_Address_For_Descriptor): New function. + (Make_Address_For_Finalize): Call above function. + (Make_Finalize_Address_Stmts): Likewise. + * exp_util.ads (Is_Constr_Array_Subt_Of_Unc_With_Controlled): New + predicate. + * exp_util.adb (Is_Constr_Array_Subt_Of_Unc_With_Controlled): Ditto. + (Remove_Side_Effects): Call above predicate. + * sem_ch3.adb (Analyze_Object_Declaration): Likewise. + * sem_ch4.adb (Analyze_Allocator): Allocate the bounds by setting + Is_Constr_Array_Subt_With_Bounds when appropriate. + +2025-07-01 Javier Miranda <miranda@adacore.com> + + * sem_ch4.adb (Try_Object_Operation): Handle mutably tagged + class-wide type prefix. + +2025-07-01 Viljar Indus <indus@adacore.com> + + * errout.adb (Error_Msg_Internal): Use the new + Warning_Treated_As_Error function. + * erroutc.adb (Get_Warning_Option): Add new version of this + function that operates on the Error_Msg_Object directly instead + of the Error_Id. Update the existing function to call the new + version interanlly. + (Get_Warning_Tag): Likewise. + (Warning_Treated_As_Error): Add a new method that combines the + checks for the error message itself and its tag. + * erroutc.ads (Get_Warning_Option): Add new spec. + (Get_Warning_Option): Likewise. + (Get_Warning_Option): Likewise. + +2025-07-01 Viljar Indus <indus@adacore.com> + + * atree.ads: Add Compile_Time_Pragma_Warnings for counting + compile time warnings. + * errout.adb (Initialize): Initialize Compile_Time_Pragma_Warnings. + (Output_Messages): Use Compile_Time_Pragma_Warnings instead of + Count_Compile_Time_Pragma_Warnings. + * erroutc.adb (Compilation_Errors): Likewise. + (Count_Compile_Time_Pragma_Warnings): Removed. + (Decrease_Error_Msg_Count): Update Compile_Time_Pragma_Warnings. + (Increase_Error_Msg_Count): Likewise. + (Write_Error_Summary): Use Compile_Time_Pragma_Warnings instead of + Count_Compile_Time_Pragma_Warnings. + * erroutc.ads (Count_Compile_Time_Pragma_Warnings): Removed. + +2025-07-01 Viljar Indus <indus@adacore.com> + + * errout.adb (Delete_Warning_And_Continuations): Use + Decrease_Error_Msg_Count to update the message counts. + (Delete_Warning): Likewise. + (To_Be_Removed): Likewise. + +2025-07-01 Viljar Indus <indus@adacore.com> + + * errout.adb (Remove_Warning_Messages): Mark removed messages as + deleted. + * erroutc.adb (Purge_Messages): Likewise. + +2025-07-01 Martin Clochard <clochard@adacore.com> + + * frontend.adb (Frontend): do not override GNATprove's setting for + Warn_On_Non_Local_Exception + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * sem_ch4.adb (Analyze_Allocator): Do not set Etype to itself. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * exp_util.adb (Finalize_Address): Do not go to the root type for + array types. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * libgnat/s-valuer.ads (System.Value_R): Remove Round parameter. + (Scan_Raw_Real): Replace Extra with Extra2 and adjust the comment. + (Value_Raw_Real): Likewise. + * libgnat/s-valuer.adb (Round_Extra): Delete. + (Scan_Decimal_Digits): Replace Extra with Extra2 and adjust the + implementation. + (Scan_Integral_Digits): Replace Extra with Extra2 and Extra_Rounded + with Extra2_Filled and adjust the implementation. + (Scan_Raw_Real): Replace Extra with Extra2 and adjust the + implementation. + (Value_Raw_Real): Likewise. + * libgnat/s-valrea.adb (Impl): Remove actual for Round formal. + * libgnat/s-valued.adb (Impl): Likewise. + (Integer_to_Decimal): Replace Extra with Extra2 and adjust the + implementation. Rename Unsigned_To_Signed to To_Signed. + (Scan_Decimal): Replace Extra with Extra2 and adjust the + implementation. + (Value_Decimal): Likewise. + * libgnat/s-valuef.adb (Impl): Remove actual for Round formal. + (Integer_to_Fixed): Replace Extra with Extra2 and adjust the + implementation. Rename Unsigned_To_Signed to To_Signed. Only + round the last scaled divide operation. + (Scan_Fixed): Replace Extra with Extra2 and adjust the + implementation. + (Value_Fixed): Likewise. + +2025-07-01 Ronan Desplanques <desplanques@adacore.com> + + * libgnat/s-valuer.adb (Scan_Decimal_Digits, Scan_Integral_Digits): + Minor rephrasing. + +2025-07-01 Ronan Desplanques <desplanques@adacore.com> + + * sem_ch5.adb (Analyze_Loop_Parameter_Specification): Set ekind + earlier. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * exp_util.ads (Is_Finalizable_Access): New predicate. + (Is_Non_BIP_Func_Call): Delete. + (Is_Secondary_Stack_BIP_Func_Call): Likewise. + * exp_util.adb (Is_Finalizable_Access): New predicate. + (Initialized_By_Aliased_BIP_Func_Call): Delete. + (Initialized_By_Reference): Likewise. + (Is_Aliased): Only consider the nontransient object serviced by + the transient scope. + (Is_Part_Of_BIP_Return_Statement): Minor tweak. + (Is_Finalizable_Transient): Remove calls to Initialized_By_Reference + and Initialized_By_Aliased_BIP_Func_Call. + Call Is_Finalizable_Access for access objects. + (Is_Non_BIP_Func_Call): Delete. + (Is_Secondary_Stack_BIP_Func_Call): Likewise. + (Requires_Cleanup_Actions): Call Is_Finalizable_Access for access + objects. + (Side_Effect_Free): Return True for N_Reference. + * exp_ch7.adb (Build_Finalizer.Process_Declarations): Call + Is_Finalizable_Access for access objects. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * exp_util.adb (Is_Expression_Of_Func_Return): New predicate. + (Is_Related_To_Func_Return): Call Is_Expression_Of_Func_Return. + (Remove_Side_Effects): Generate a temporary for a function call + that returns a constrained array type with controlled component + and an unconstrained first subtype. + +2025-07-01 Piotr Trojanek <trojanek@adacore.com> + + * inline.adb (Rewrite_Procedure_Call): Replace with a simple rewriting + of procedure call into a single block node, i.e. remove broken + optimization. + * sem_util.adb (Next_Actual): Adapt GNATprove-specific code that peeks + into inlined calls. + +2025-07-01 Martin Clochard <clochard@adacore.com> + + * exp_util.adb (Is_Controlling_Formal_Ref): test scope against + derived subprogram as well. + +2025-07-01 Viljar Indus <indus@adacore.com> + + * errout.adb (Error_Msg_Internal): Relocate Warn_As_Err propagation + to Increase_Error_Msg_Counti. + (Delete_Warning_And_Continuations): Update + Warnings_Treated_As_Errors count. + (Delete_Warning): Likewise. + (To_Be_Removed): Likewise. + * erroutc.adb (Increase_Error_Msg_Count): Count warnings treated + as errors here and perform the propagation of this property to + the parent message. + (Output_Msg_Text): Remove counting of warnings as errors from + here. + (Decrease_Error_Msg_Count): Update Warnings_Treated_As_Errors + count. + 2025-06-30 Eric Botcazou <ebotcazou@adacore.com> PR ada/120106 diff --git a/gcc/ada/exp_ch6.adb b/gcc/ada/exp_ch6.adb index 26302ba..6216192 100644 --- a/gcc/ada/exp_ch6.adb +++ b/gcc/ada/exp_ch6.adb @@ -9575,9 +9575,8 @@ package body Exp_Ch6 is -- such build-in-place functions, primitive or not. return not Restriction_Active (No_Finalization) - and then ((Needs_Finalization (Typ) - and then not Has_Relaxed_Finalization (Typ)) - or else Is_Tagged_Type (Typ)) + and then (Needs_Finalization (Typ) or else Is_Tagged_Type (Typ)) + and then not Has_Relaxed_Finalization (Typ) and then not Has_Foreign_Convention (Typ); end Needs_BIP_Collection; diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 2cd02b0..dd2ae5c 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,25 @@ +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-gimplify.cc (is_address_with_access_with_size): New function. + (ubsan_walk_array_refs_r): Instrument an INDIRECT_REF whose base + address is .ACCESS_WITH_SIZE or an address computation whose base + address is .ACCESS_WITH_SIZE. + * c-ubsan.cc (ubsan_instrument_bounds_pointer_address): New function. + (struct factor_t): New structure. + (get_factors_from_mul_expr): New function. + (get_index_from_offset): New function. + (get_index_from_pointer_addr_expr): New function. + (is_instrumentable_pointer_array_address): New function. + (ubsan_array_ref_instrumented_p): Change prototype. + Handle MEM_REF in addtional to ARRAY_REF. + (ubsan_maybe_instrument_array_ref): Handle MEM_REF in addtional + to ARRAY_REF. + +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-attribs.cc (handle_counted_by_attribute): Accept counted_by + attribute for pointer fields. + 2025-06-30 Jakub Jelinek <jakub@redhat.com> PR c/120520 diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 5d7a31f..ea04ed7 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -2906,22 +2906,53 @@ handle_counted_by_attribute (tree *node, tree name, " declaration %q+D", name, decl); *no_add_attrs = true; } - /* This attribute only applies to field with array type. */ - else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) + /* 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) { error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a non-array field", - name); + "%qE attribute is not allowed for a non-array" + " or non-pointer field", name); *no_add_attrs = true; } /* This attribute only applies to a C99 flexible array member type. */ - else if (! c_flexible_array_member_type_p (TREE_TYPE (decl))) + else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && !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) { @@ -2930,7 +2961,8 @@ 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 field. */ + field as the argument for the same flexible array member or + pointer 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 c6fb764..e905059 100644 --- a/gcc/c-family/c-gimplify.cc +++ b/gcc/c-family/c-gimplify.cc @@ -66,6 +66,20 @@ 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 @@ -121,6 +135,20 @@ 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 78b7868..38514a4 100644 --- a/gcc/c-family/c-ubsan.cc +++ b/gcc/c-family/c-ubsan.cc @@ -554,38 +554,322 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index, *index, bound); } -/* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */ + +/* 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. */ bool -ubsan_array_ref_instrumented_p (const_tree t) +ubsan_array_ref_instrumented_p (tree t) { - if (TREE_CODE (t) != ARRAY_REF) + if (TREE_CODE (t) != ARRAY_REF + && TREE_CODE (t) != MEM_REF) 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; + 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; } -/* 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. */ +/* 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. */ 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) { - 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 (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. */ if (e != NULL_TREE) - TREE_OPERAND (*expr_p, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1), - e, op1); + TREE_OPERAND (index_p, index_n) + = build2 (COMPOUND_EXPR, TREE_TYPE (op1), e, op1); } } diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 89a3210..cb69b8c 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,17 @@ +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-decl.cc (verify_counted_by_attribute): Change the 2nd argument + to a vector of fields with counted_by attribute. Verify all fields + in this vector. + (finish_struct): Collect all the fields with counted_by attribute + to a vector and pass this vector to verify_counted_by_attribute. + * c-typeck.cc (build_counted_by_ref): Handle pointers with counted_by. + Add one more argument, issue error when the pointee type is a structure + or union including a flexible array member. + (build_access_with_size_for_counted_by): Handle pointers with counted_by. + (handle_counted_by_for_component_ref): Call build_counted_by_ref + with the new prototype. + 2025-06-23 Tobias Burnus <tburnus@baylibre.com> * c-parser.cc (OACC_WAIT_CLAUSE_MASK): Add if clause. diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 8bbd6eb..7e1c197 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -9432,56 +9432,62 @@ c_update_type_canonical (tree t) } } -/* 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. */ +/* 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. */ static void -verify_counted_by_attribute (tree struct_type, tree field_decl) +verify_counted_by_attribute (tree struct_type, + auto_vec<tree> *fields_with_counted_by) { - tree attr_counted_by = lookup_attribute ("counted_by", - DECL_ATTRIBUTES (field_decl)); - - if (!attr_counted_by) - return; + for (tree field_decl : *fields_with_counted_by) + { + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (field_decl)); - /* If there is an counted_by attribute attached to the field, - verify it. */ + if (!attr_counted_by) + continue; - tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); + /* If there is an counted_by attribute attached to the field, + verify it. */ - /* Verify the argument of the attrbute is a valid field of the - containing structure. */ + tree fieldname = TREE_VALUE (TREE_VALUE (attr_counted_by)); - tree counted_by_field = lookup_field (struct_type, fieldname); + /* Verify the argument of the attrbute is a valid field of the + containing structure. */ - /* 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); + tree counted_by_field = lookup_field (struct_type, fieldname); - if (!INTEGRAL_TYPE_P (TREE_TYPE (real_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) { error_at (DECL_SOURCE_LOCATION (field_decl), "argument %qE to the %<counted_by%> attribute" - " is not a field declaration with an integer type", - fieldname); + " 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); + + 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)); + } + } } } @@ -9556,7 +9562,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, until now.) */ bool saw_named_field = false; - tree counted_by_fam_field = NULL_TREE; + auto_vec<tree> fields_with_counted_by; for (x = fieldlist; x; x = DECL_CHAIN (x)) { /* Whether this field is the last field of the structure or union. @@ -9637,9 +9643,16 @@ 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))) - counted_by_fam_field = x; + fields_with_counted_by.safe_push (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, @@ -9938,8 +9951,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes, struct_parse_info->struct_types.safe_push (t); } - if (counted_by_fam_field) - verify_counted_by_attribute (t, counted_by_fam_field); + if (fields_with_counted_by.length () > 0) + verify_counted_by_attribute (t, &fields_with_counted_by); return t; } diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index e24629b..7948106 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 field, otherwise - return NULL_TREE. + attached to this field if it's a flexible array member or a pointer + field, otherwise return NULL_TREE. Set COUNTED_BY_TYPE to the TYPE of the counted_by field. For example, if: @@ -2941,18 +2941,34 @@ should_suggest_deref_p (tree datum_type) */ static tree -build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type) +build_counted_by_ref (location_t loc, tree datum, tree subdatum, + tree *counted_by_type) { tree type = TREE_TYPE (datum); - if (!c_flexible_array_member_type_p (TREE_TYPE (subdatum))) + tree sub_type = TREE_TYPE (subdatum); + if (!c_flexible_array_member_type_p (sub_type) + && TREE_CODE (sub_type) != POINTER_TYPE) 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, @@ -2975,8 +2991,11 @@ build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type) } /* Given a COMPONENT_REF REF with the location LOC, the corresponding - COUNTED_BY_REF, and the COUNTED_BY_TYPE, generate an INDIRECT_REF - to a call to the internal function .ACCESS_WITH_SIZE. + 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. REF @@ -2986,17 +3005,15 @@ build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type) (TYPE_OF_ARRAY *)0)) NOTE: The return type of this function is the POINTER type pointing - 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. + 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. 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 with the pointer TYPE - to the original flexible array type. + The 6th argument of the call is a constant 0 of the same TYPE as + the return type of the call. */ static tree @@ -3004,11 +3021,16 @@ 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))); - /* The result type of the call is a pointer to the flexible array 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. */ tree result_type = c_build_pointer_type (TREE_TYPE (ref)); - tree first_param - = c_fully_fold (array_to_pointer_conversion (loc, ref), false, NULL); + first_param = c_fully_fold (first_param, false, NULL); tree second_param = c_fully_fold (counted_by_ref, false, NULL); @@ -3021,7 +3043,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 flexible array type. */ + /* Wrap the call with an INDIRECT_REF with the original type of the ref. */ call = build1 (INDIRECT_REF, TREE_TYPE (ref), call); SET_EXPR_LOCATION (call, loc); return call; @@ -3039,7 +3061,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 (datum, subdatum, + tree counted_by_ref = build_counted_by_ref (loc, datum, subdatum, &counted_by_type); if (counted_by_ref) ref = build_access_with_size_for_counted_by (loc, ref, diff --git a/gcc/cobol/ChangeLog b/gcc/cobol/ChangeLog index 9b29af8..4b05399 100644 --- a/gcc/cobol/ChangeLog +++ b/gcc/cobol/ChangeLog @@ -1,3 +1,11 @@ +2025-07-01 James K. Lowden <jklowden@cobolworx.com> + + * Make-lang.in: Use && instead of semicolon between commands. + +2025-07-01 Robert Dubner <rdubner@symas.com> + + * parse.y: printf() of size_t is %zu, not %ld. + 2025-06-30 James K. Lowden <jklowden@cobolworx.com> PR cobol/120772 diff --git a/gcc/cobol/Make-lang.in b/gcc/cobol/Make-lang.in index 18eb3b0..e884212 100644 --- a/gcc/cobol/Make-lang.in +++ b/gcc/cobol/Make-lang.in @@ -287,7 +287,7 @@ cobol.install-common: installdirs rm -f $(DESTDIR)$(bindir)/$(GCOBOL_TARGET_INSTALL_NAME)$(exeext); \ rm -f $(DESTDIR)$(bindir)/$(GCOBC_TARGET_INSTALL_NAME)$(exeext); \ ( cd $(DESTDIR)$(bindir) && \ - $(LN) $(GCOBOL_INSTALL_NAME)$(exeext) $(GCOBOL_TARGET_INSTALL_NAME)$(exeext) ); \ + $(LN) $(GCOBOL_INSTALL_NAME)$(exeext) $(GCOBOL_TARGET_INSTALL_NAME)$(exeext) && \ $(LN) $(GCOBC_INSTALL_NAME)$(exeext) $(GCOBC_TARGET_INSTALL_NAME)$(exeext) ); \ fi; \ fi diff --git a/gcc/cobol/parse.y b/gcc/cobol/parse.y index 57a41bb..74637c9 100644 --- a/gcc/cobol/parse.y +++ b/gcc/cobol/parse.y @@ -12404,7 +12404,7 @@ numstr2i( const char input[], radix_t radix ) { return output; } if( erc == -1 ) { - yywarn("'%s' was accepted as %ld", input, integer); + yywarn("'%s' was accepted as %zu", input, integer); } return output; } diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index e771def..af574d5 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -5046,6 +5046,36 @@ DONE; }) +;; convert (truncate)(~x >> imm) into (truncate)(((u16)-1 - x) >> imm) +;; because it will result in the 'not' being replaced with a constant load +;; which allows for better loop optimization. +;; We limit this to truncations that take the upper half and shift it to the +;; lower half as we use subhn (patterns that would have generated an shrn +;; otherwise). +;; On some implementations the use of subhn also result in better throughput. +(define_insn_and_split "*shrn_to_subhn_<mode>" + [(set (match_operand:<VNARROWQ> 0 "register_operand" "=&w") + (truncate:<VNARROWQ> + (lshiftrt:VQN + (not:VQN (match_operand:VQN 1 "register_operand" "w")) + (match_operand:VQN 2 "aarch64_simd_shift_imm_vec_exact_top"))))] + "TARGET_SIMD" + "#" + "&& true" + [(const_int 0)] +{ + rtx tmp; + if (can_create_pseudo_p ()) + tmp = gen_reg_rtx (<MODE>mode); + else + tmp = gen_rtx_REG (<MODE>mode, REGNO (operands[0])); + emit_move_insn (tmp, CONSTM1_RTX (<MODE>mode)); + emit_insn (gen_aarch64_subhn<mode>_insn (operands[0], tmp, + operands[1], operands[2])); + DONE; +}) + + ;; pmul. (define_insn "aarch64_pmul<mode>" diff --git a/gcc/config/i386/driver-i386.cc b/gcc/config/i386/driver-i386.cc index 63c7d79..fe71f55 100644 --- a/gcc/config/i386/driver-i386.cc +++ b/gcc/config/i386/driver-i386.cc @@ -600,7 +600,7 @@ const char *host_detect_local_cpu (int argc, const char **argv) if (has_feature (FEATURE_AVX512F)) { /* Assume Diamond Rapids. */ - if (has_feature (FEATURE_AMX_TRANSPOSE)) + if (has_feature (FEATURE_AMX_FP8)) cpu = "diamondrapids"; /* Assume Granite Rapids D. */ else if (has_feature (FEATURE_AMX_COMPLEX)) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 318d0cd..ff7582d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2025-07-01 Jakub Jelinek <jakub@redhat.com> + + PR c++/120471 + * typeck.cc (cp_build_array_ref) <case COND_EXPR>: If idx is not + INTEGER_CST, don't optimize the case (but cp_default_conversion on + array early if it has ARRAY_TYPE) or use + SAVE_EXPR <op0>, SAVE_EXPR <idx>, SAVE_EXPR <op0> as new op0 depending + on flag_strong_eval_order and whether op1 and op2 are arrays with + invariant address or tree invariant pointers. Formatting fixes. + 2025-06-28 Nathaniel Shead <nathanieloshead@gmail.com> * module.cc (trees_out::walking_bit_field_unit): New flag. diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index f4b49b7..447fe81 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -4001,13 +4001,61 @@ cp_build_array_ref (location_t loc, tree array, tree idx, } case COND_EXPR: - ret = build_conditional_expr - (loc, TREE_OPERAND (array, 0), - cp_build_array_ref (loc, TREE_OPERAND (array, 1), idx, - complain), - cp_build_array_ref (loc, TREE_OPERAND (array, 2), idx, - complain), - complain); + tree op0, op1, op2; + op0 = TREE_OPERAND (array, 0); + op1 = TREE_OPERAND (array, 1); + op2 = TREE_OPERAND (array, 1); + if (TREE_SIDE_EFFECTS (idx) || !tree_invariant_p (idx)) + { + /* If idx could possibly have some SAVE_EXPRs, turning + (op0 ? op1 : op2)[idx] into + op0 ? op1[idx] : op2[idx] can lead into temporaries + initialized in one conditional path and uninitialized + uses of them in the other path. + And if idx is a really large expression, evaluating it + twice is also not optimal. + On the other side, op0 must be sequenced before evaluation + of op1 and op2 and for C++17 op0, op1 and op2 must be + sequenced before idx. + If idx is INTEGER_CST, we can just do the optimization + without any SAVE_EXPRs, if op1 and op2 are both ARRAY_TYPE + VAR_DECLs or COMPONENT_REFs thereof (so their address + is constant or relative to frame), optimize into + (SAVE_EXPR <op0>, SAVE_EXPR <idx>, SAVE_EXPR <op0>) + ? op1[SAVE_EXPR <idx>] : op2[SAVE_EXPR <idx>] + Otherwise avoid this optimization. */ + if (flag_strong_eval_order == 2) + { + if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) + { + if (!address_invariant_p (op1) || !address_invariant_p (op2)) + { + /* Force default conversion on array if + we can't optimize this and array is ARRAY_TYPE + COND_EXPR, we can't leave COND_EXPRs with + ARRAY_TYPE in the IL. */ + array = cp_default_conversion (array, complain); + if (error_operand_p (array)) + return error_mark_node; + break; + } + } + else if (!POINTER_TYPE_P (TREE_TYPE (array)) + || !tree_invariant_p (op1) + || !tree_invariant_p (op2)) + break; + } + if (TREE_SIDE_EFFECTS (idx)) + { + idx = save_expr (idx); + op0 = save_expr (op0); + tree tem = build_compound_expr (loc, op0, idx); + op0 = build_compound_expr (loc, tem, op0); + } + } + op1 = cp_build_array_ref (loc, op1, idx, complain); + op2 = cp_build_array_ref (loc, op2, idx, complain); + ret = build_conditional_expr (loc, op0, op1, op2, complain); protected_set_expr_location (ret, loc); return ret; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 046de36..70adf2d 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7138,9 +7138,11 @@ 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 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. +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. This attribute is available only in C for now. In C++ this attribute is ignored. @@ -7161,8 +7163,22 @@ 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. +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. The field that represents the number of the elements should have an integer type. Otherwise, the compiler reports an error and ignores @@ -7171,6 +7187,12 @@ 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: @@ -7186,6 +7208,13 @@ 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 @@ -7207,6 +7236,8 @@ 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/fortran/ChangeLog b/gcc/fortran/ChangeLog index 6b44a69..0ea9c39 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,25 @@ +2025-07-01 Harald Anlauf <anlauf@gmx.de> + + * coarray.cc (check_add_new_component): Treat pure and elemental + intrinsic functions the same as non-intrinsic ones. + (create_caf_add_data_parameter_type): Fix front-end memleaks. + * trans-intrinsic.cc (conv_caf_func_index): Likewise. + +2025-07-01 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/120847 + * coarray.cc (check_add_new_comp_handle_array): Make the count + of components static to be able to create more than one. Create + an array component only for array expressions. + +2025-07-01 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/120843 + * resolve.cc (resolve_operator): Report inconsistent coranks + only when not referencing this_image. + (gfc_op_rank_conformable): Treat coranks as inconformable only + when a coindex other then implicit this_image is used. + 2025-06-27 Harald Anlauf <anlauf@gmx.de> PR fortran/120784 diff --git a/gcc/fortran/coarray.cc b/gcc/fortran/coarray.cc index 2f067f8..ef8fd4e 100644 --- a/gcc/fortran/coarray.cc +++ b/gcc/fortran/coarray.cc @@ -503,7 +503,7 @@ check_add_new_comp_handle_array (gfc_expr *e, gfc_symbol *type, gfc_symbol *add_data) { gfc_component *comp; - int cnt = -1; + static int cnt = -1; gfc_symtree *caller_image; gfc_code *pre_code = caf_accessor_prepend; bool static_array_or_scalar = true; @@ -566,7 +566,7 @@ check_add_new_comp_handle_array (gfc_expr *e, gfc_symbol *type, else { comp->initializer = gfc_copy_expr (e); - if (e_attr.dimension) + if (e_attr.dimension && e->rank) { comp->attr.dimension = 1; comp->as = get_arrayspec_from_expr (e); @@ -697,7 +697,10 @@ check_add_new_component (gfc_symbol *type, gfc_expr *e, gfc_symbol *add_data) break; case EXPR_FUNCTION: if (!e->symtree->n.sym->attr.pure - && !e->symtree->n.sym->attr.elemental) + && !e->symtree->n.sym->attr.elemental + && !(e->value.function.isym + && (e->value.function.isym->pure + || e->value.function.isym->elemental))) /* Treat non-pure/non-elemental functions. */ check_add_new_comp_handle_array (e, type, add_data); else @@ -743,7 +746,6 @@ create_caf_add_data_parameter_type (gfc_expr *expr, gfc_namespace *ns, add_data->as->lower[0] = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind, &expr->where); - mpz_init (add_data->as->lower[0]->value.integer); mpz_set_si (add_data->as->lower[0]->value.integer, 1); for (gfc_ref *ref = expr->ref; ref; ref = ref->next) @@ -763,6 +765,7 @@ create_caf_add_data_parameter_type (gfc_expr *expr, gfc_namespace *ns, type->declared_at = expr->where; gfc_set_sym_referenced (type); gfc_commit_symbol (type); + free (name); return type; } diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index fce5ee2..f1bfd3e 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -1052,7 +1052,7 @@ conv_caf_func_index (stmtblock_t *block, gfc_namespace *ns, const char *pat, index_st->n.sym->value = gfc_get_constant_expr (BT_INTEGER, gfc_default_integer_kind, &gfc_current_locus); - mpz_init_set_si (index_st->n.sym->value->value.integer, -1); + mpz_set_si (index_st->n.sym->value->value.integer, -1); index_st->n.sym->ts.type = BT_INTEGER; index_st->n.sym->ts.kind = gfc_default_integer_kind; gfc_set_sym_referenced (index_st->n.sym); diff --git a/gcc/m2/ChangeLog b/gcc/m2/ChangeLog index 04211a0..f7254f9 100644 --- a/gcc/m2/ChangeLog +++ b/gcc/m2/ChangeLog @@ -1,3 +1,9 @@ +2025-07-01 Gaius Mulley <gaiusmod2@gmail.com> + + PR modula2/120912 + * gm2-libs-iso/IOChanUtils.def (GetFile): New procedure function. + * gm2-libs-iso/IOChanUtils.mod (GetFile): New procedure function. + 2025-06-29 Gaius Mulley <gaiusmod2@gmail.com> PR modula2/117203 diff --git a/gcc/m2/gm2-libs-iso/IOChanUtils.def b/gcc/m2/gm2-libs-iso/IOChanUtils.def index e38f83a..3a8a0c6 100644 --- a/gcc/m2/gm2-libs-iso/IOChanUtils.def +++ b/gcc/m2/gm2-libs-iso/IOChanUtils.def @@ -11,6 +11,7 @@ DEFINITION MODULE IOChanUtils ; *) FROM DynamicStrings IMPORT String ; +FROM FIO IMPORT File ; IMPORT IOChan ; @@ -24,4 +25,11 @@ IMPORT IOChan ; PROCEDURE GetFileName (c: IOChan.ChanId) : String ; +(* + GetFile - returns the FIO.File associated with ChanId c. +*) + +PROCEDURE GetFile (c: IOChan.ChanId) : File ; + + END IOChanUtils. diff --git a/gcc/m2/gm2-libs-iso/IOChanUtils.mod b/gcc/m2/gm2-libs-iso/IOChanUtils.mod index 5cbb2a9..168fe0d 100644 --- a/gcc/m2/gm2-libs-iso/IOChanUtils.mod +++ b/gcc/m2/gm2-libs-iso/IOChanUtils.mod @@ -11,8 +11,18 @@ IMPORT IOChan, SFIO, RTio ; PROCEDURE GetFileName (c: IOChan.ChanId) : String ; BEGIN - RETURN SFIO.GetFileName (RTio.GetFile (c)) + RETURN SFIO.GetFileName (GetFile (c)) END GetFileName ; +(* + GetFile - returns the FIO.File associated with ChanId c. +*) + +PROCEDURE GetFile (c: IOChan.ChanId) : File ; +BEGIN + RETURN RTio.GetFile (c) +END GetFile ; + + END IOChanUtils. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1e78e86..eaa08db 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,128 @@ +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * gcc.dg/ubsan/pointer-counted-by-bounds-2.c: New test. + * gcc.dg/ubsan/pointer-counted-by-bounds-3.c: New test. + * gcc.dg/ubsan/pointer-counted-by-bounds-4.c: New test. + * gcc.dg/ubsan/pointer-counted-by-bounds-5.c: New test. + * gcc.dg/ubsan/pointer-counted-by-bounds.c: New test. + +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * gcc.dg/pointer-counted-by-4-char.c: New test. + * gcc.dg/pointer-counted-by-4-float.c: New test. + * gcc.dg/pointer-counted-by-4-struct.c: New test. + * gcc.dg/pointer-counted-by-4-union.c: New test. + * gcc.dg/pointer-counted-by-4.c: New test. + * gcc.dg/pointer-counted-by-5.c: New test. + * gcc.dg/pointer-counted-by-6.c: New test. + * gcc.dg/pointer-counted-by-7.c: New test. + +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * gcc.dg/flex-array-counted-by.c: Update test. + * gcc.dg/pointer-counted-by-1.c: New test. + * gcc.dg/pointer-counted-by-2.c: New test. + * gcc.dg/pointer-counted-by-3.c: New test. + * gcc.dg/pointer-counted-by.c: New test. + +2025-07-01 Jakub Jelinek <jakub@redhat.com> + + PR testsuite/120919 + * gcc.target/powerpc/builtin_altivec_tr_stxvr_runnable.c (main): Change + sc, ss, si and sll vars from scalars to arrays of 2 elements, + initialize and test just the first one though. + +2025-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/specs/finalizable2.ads: New test. + +2025-07-01 Jakub Jelinek <jakub@redhat.com> + + * gcc.target/s390/vector/vec-abs-emu.c: Add -fno-stack-protector + to dg-options. + * gcc.target/s390/vector/vec-max-emu.c: Likewise. + * gcc.target/s390/vector/vec-min-emu.c: Likewise. + +2025-07-01 Robert Dubner <rdubner@symas.com> + + * cobol.dg/group2/Intrinsics_without_FUNCTION_keyword__2_.cob: + Append INTRINSIC keyword. + +2025-07-01 Jakub Jelinek <jakub@redhat.com> + + PR c++/120471 + * g++.dg/ubsan/pr120471.C: New test. + * g++.dg/parse/pr120471.C: New test. + +2025-07-01 Remi Machet <rmachet@nvidia.com> + + * gcc.target/aarch64/simd/shrn2subhn.c: New test. + +2025-07-01 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/120847 + * gfortran.dg/coarray/coindexed_7.f90: New test. + +2025-07-01 Jakub Jelinek <jakub@redhat.com> + + PR ipa/119318 + PR testsuite/120082 + * gcc.dg/ipa/pr119318.c (main): Expect different result on big endian + from little endian, on unexpected endianness or int/int128 sizes don't + test anything. Formatting fixes. + +2025-07-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.target/i386/preserve-none-1.c (dg-options): Add + -fomit-frame-pointer. + +2025-07-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * g++.target/i386/memset-pr101366-1.C (dg-options): Add + -fasynchronous-unwind-tables -fdwarf2-cfi-asm. + * g++.target/i386/memset-pr101366-2.C: Likewise. + * g++.target/i386/memset-pr118276-1a.C: Likewise. + * g++.target/i386/memset-pr118276-1b.C: Likewise. + * g++.target/i386/memset-pr118276-1c.C: Likewise. + * gcc.target/i386/memset-pr70308-1a.c: Likewise. + * gcc.target/i386/memset-strategy-25.c: Likewise. + * gcc.target/i386/memset-strategy-28.c: Likewise. + * gcc.target/i386/memset-strategy-29.c: Likewise. + * gcc.target/i386/memset-strategy-30.c: Likewise. + * gcc.target/i386/pr92080-17.c: Likewise. + * gcc.target/i386/memset-pr70308-1b.c: Likewise. Also add + -fomit-frame-pointer. + * g++.target/i386/memset-pr108585-1a.C: (dg-options): Add + -fasynchronous-unwind-tables -fdwarf2-cfi-asm. Also add + -mno-stackrealign -fomit-frame-pointer. + * g++.target/i386/memset-pr108585-1b.C: Likewise. + +2025-07-01 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/120608 + * c-c++-common/asan/pr120608-3.c: New test. + * c-c++-common/asan/pr120608-4.c: New test. + * g++.dg/asan/pr120608-3.C: New test. + * g++.dg/asan/pr120608-4.C: New test. + +2025-07-01 Andre Vehreschild <vehre@gcc.gnu.org> + + PR fortran/120843 + * gfortran.dg/coarray/coindexed_6.f90: New test. + +2025-07-01 Yuao Ma <c8ef@outlook.com> + + * lib/target-supports.exp (foldable_pi_based_trigonometry): New + effective target. + * gcc.dg/torture/builtin-math-9.c: New test. + +2025-07-01 Alexandre Oliva <oliva@adacore.com> + + PR middle-end/120631 + * gcc.dg/dfp/pr120631.c: Drop overrider of dg-do default action. + * gcc.dg/dfp/bitint-9.c: Likewise. + * gcc.dg/dfp/bitint-10.c: Likewise. + 2025-06-30 Jeff Law <jlaw@ventanamicro.com> PR rtl-optimization/120242 diff --git a/gcc/testsuite/cobol.dg/group2/Intrinsics_without_FUNCTION_keyword__2_.cob b/gcc/testsuite/cobol.dg/group2/Intrinsics_without_FUNCTION_keyword__2_.cob index b94adf5..39a0c5b 100644 --- a/gcc/testsuite/cobol.dg/group2/Intrinsics_without_FUNCTION_keyword__2_.cob +++ b/gcc/testsuite/cobol.dg/group2/Intrinsics_without_FUNCTION_keyword__2_.cob @@ -5,8 +5,8 @@ ENVIRONMENT DIVISION. CONFIGURATION SECTION. REPOSITORY. - FUNCTION PI - FUNCTION E. + FUNCTION PI INTRINSIC + FUNCTION E INTRINSIC. DATA DIVISION. WORKING-STORAGE SECTION. 01 Z PIC 99V99. diff --git a/gcc/testsuite/g++.dg/parse/pr120471.C b/gcc/testsuite/g++.dg/parse/pr120471.C new file mode 100644 index 0000000..ad47e38 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr120471.C @@ -0,0 +1,42 @@ +// PR c++/120471 +// { dg-do compile } + +extern int a1[], a2[], a3[], a4[]; + +int corge (int); + +int +foo (int p) +{ + return (p ? a1 : a2)[1]; +} + +int +bar (int p, int q) +{ + return (p ? a1 : a2)[q]; +} + +int +garply (int p, int q) +{ + return (p ? a1 : a2)[corge (q)]; +} + +int +baz (int p, int q) +{ + return (p ? q ? a1 : a2 : q ? a3 : a4)[1]; +} + +int +qux (int p, int q, int r) +{ + return (p ? q ? a1 : a2 : q ? a3 : a4)[r]; +} + +int +fred (int p, int q, int r) +{ + return (p ? q ? a1 : a2 : q ? a3 : a4)[corge (r)]; +} diff --git a/gcc/testsuite/g++.dg/ubsan/pr120471.C b/gcc/testsuite/g++.dg/ubsan/pr120471.C new file mode 100644 index 0000000..31b781f --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr120471.C @@ -0,0 +1,21 @@ +// PR c++/120471 +// { dg-do run } +// { dg-options "-fsanitize=undefined" } + +volatile int b[1], a[1]; + +void +foo (int x) +{ + volatile int c = 21; + volatile int v = (x % 2 ? b : a)[c % 3]; + if (v != 0) + __builtin_abort (); +} + +int +main () +{ + foo (1); + foo (2); +} diff --git a/gcc/testsuite/gcc.dg/flex-array-counted-by.c b/gcc/testsuite/gcc.dg/flex-array-counted-by.c index 16eb2c6..4fa91ff 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 field" } */ + int field __attribute ((counted_by (count))); /* { dg-error "attribute is not allowed for a non-array or non-pointer 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 new file mode 100644 index 0000000..395af34 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-1.c @@ -0,0 +1,34 @@ +/* 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 new file mode 100644 index 0000000..1f4a278 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-2.c @@ -0,0 +1,10 @@ +/* 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 new file mode 100644 index 0000000..7005609 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-3.c @@ -0,0 +1,127 @@ + /* 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 new file mode 100644 index 0000000..c404e5b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-char.c @@ -0,0 +1,6 @@ +/* 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 new file mode 100644 index 0000000..383d8fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-float.c @@ -0,0 +1,6 @@ +/* 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 new file mode 100644 index 0000000..50246d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-struct.c @@ -0,0 +1,10 @@ +/* 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 new file mode 100644 index 0000000..e786d99 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4-union.c @@ -0,0 +1,10 @@ +/* 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 new file mode 100644 index 0000000..c4b3631 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-4.c @@ -0,0 +1,77 @@ +/* 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 new file mode 100644 index 0000000..b43ffdf --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-5.c @@ -0,0 +1,56 @@ +/* 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 new file mode 100644 index 0000000..355558c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-6.c @@ -0,0 +1,56 @@ +/* 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 new file mode 100644 index 0000000..af1ab27 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by-7.c @@ -0,0 +1,32 @@ +/* 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 new file mode 100644 index 0000000..0f18828 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pointer-counted-by.c @@ -0,0 +1,111 @@ +/* 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 new file mode 100644 index 0000000..0653ecc --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-2.c @@ -0,0 +1,51 @@ +/* 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 new file mode 100644 index 0000000..731422d --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-3.c @@ -0,0 +1,42 @@ +/* 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 new file mode 100644 index 0000000..52f202f --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-4.c @@ -0,0 +1,42 @@ +/* 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 new file mode 100644 index 0000000..8ad7572 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds-5.c @@ -0,0 +1,40 @@ +/* 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 new file mode 100644 index 0000000..c5a1ac5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/pointer-counted-by-bounds.c @@ -0,0 +1,46 @@ +/* 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.target/aarch64/simd/shrn2subhn.c b/gcc/testsuite/gcc.target/aarch64/simd/shrn2subhn.c new file mode 100644 index 0000000..f90ea13 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/simd/shrn2subhn.c @@ -0,0 +1,36 @@ +/* This test case checks that replacing a not+shift by a sub -1 works. */ +/* { dg-do compile } */ +/* { dg-additional-options "-O1" } */ +/* { dg-final { scan-assembler-times "\\tsubhn\\t" 6 } } */ + +#include<arm_neon.h> + +uint8x8_t neg_narrow_v8hi(uint16x8_t a) { + uint16x8_t b = vmvnq_u16(a); + return vshrn_n_u16(b, 8); +} + +uint8x8_t neg_narrow_vsubhn_v8hi(uint16x8_t a) { + uint16x8_t ones = vdupq_n_u16(0xffff); + return vsubhn_u16(ones, a); +} + +uint16x4_t neg_narrow_v4si(uint32x4_t a) { + uint32x4_t b = vmvnq_u32(a); + return vshrn_n_u32(b, 16); +} + +uint16x4_t neg_narrow_vsubhn_v4si(uint32x4_t a) { + uint32x4_t ones = vdupq_n_u32(0xffffffff); + return vsubhn_u32(ones, a); +} + +uint32x2_t neg_narrow_v2di(uint64x2_t a) { + uint64x2_t b = ~a; + return vshrn_n_u64(b, 32); +} + +uint32x2_t neg_narrow_vsubhn_v2di(uint64x2_t a) { + uint64x2_t ones = vdupq_n_u64(0xffffffffffffffff); + return vsubhn_u64(ones, a); +} diff --git a/gcc/testsuite/gcc.target/powerpc/builtin_altivec_tr_stxvr_runnable.c b/gcc/testsuite/gcc.target/powerpc/builtin_altivec_tr_stxvr_runnable.c index 4b90437..fab7a52 100644 --- a/gcc/testsuite/gcc.target/powerpc/builtin_altivec_tr_stxvr_runnable.c +++ b/gcc/testsuite/gcc.target/powerpc/builtin_altivec_tr_stxvr_runnable.c @@ -27,10 +27,10 @@ int main () { int i; signed long sl; - signed char sc, expected_sc; - signed short ss, expected_ss; - signed int si, expected_si; - signed long long int sll, expected_sll; + signed char sc[2], expected_sc; + signed short ss[2], expected_ss; + signed int si[2], expected_si; + signed long long int sll[2], expected_sll; signed char *psc; signed short *pss; signed int *psi; @@ -41,56 +41,56 @@ main () { printf("Data to store [%d] = 0x%llx %llx\n", i, val.ull[1], val.ull[0]); #endif - psc = ≻ - pss = &ss; - psi = &si; - psll = &sll; + psc = &sc[0]; + pss = &ss[0]; + psi = &si[0]; + psll = &sll[0]; sl = 1; - sc = 0xA1; + sc[0] = 0xA1; expected_sc = 0xA1; __builtin_altivec_tr_stxvrbx (store_data, sl, psc); - if (expected_sc != sc & 0xFF) + if (expected_sc != sc[0] & 0xFF) #if DEBUG printf(" ERROR: Signed char = 0x%x doesn't match expected value 0x%x\n", - sc & 0xFF, expected_sc); + sc[0] & 0xFF, expected_sc); #else abort(); #endif - ss = 0x52; + ss[0] = 0x52; expected_ss = 0x1752; __builtin_altivec_tr_stxvrhx (store_data, sl, pss); - if (expected_ss != ss & 0xFFFF) + if (expected_ss != ss[0] & 0xFFFF) #if DEBUG printf(" ERROR: Signed short = 0x%x doesn't match expected value 0x%x\n", - ss, expected_ss) & 0xFFFF; + ss[0], expected_ss) & 0xFFFF; #else abort(); #endif - si = 0x21; + si[0] = 0x21; expected_si = 0x54321721; __builtin_altivec_tr_stxvrwx (store_data, sl, psi); - if (expected_si != si) + if (expected_si != si[0]) #if DEBUG printf(" ERROR: Signed int = 0x%x doesn't match expected value 0x%x\n", - si, expected_si); + si[0], expected_si); #else abort(); #endif - sll = 0x12FFULL; + sll[0] = 0x12FFULL; expected_sll = 0xdcba9876543217FF; __builtin_altivec_tr_stxvrdx (store_data, sl, psll); - if (expected_sll != sll) + if (expected_sll != sll[0]) #if DEBUG printf(" ERROR: Signed long long int = 0x%llx doesn't match expected value 0x%llx\n", - sll, expected_sll); + sll[0], expected_sll); #else abort(); #endif diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-abs-emu.c b/gcc/testsuite/gcc.target/s390/vector/vec-abs-emu.c index e0dd222..2fcaa95 100644 --- a/gcc/testsuite/gcc.target/s390/vector/vec-abs-emu.c +++ b/gcc/testsuite/gcc.target/s390/vector/vec-abs-emu.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O3 -mzarch -march=z13 -save-temps" } */ +/* { dg-options "-O3 -mzarch -march=z13 -save-temps -fno-stack-protector" } */ /* { dg-require-effective-target int128 } */ /* { dg-final { check-function-bodies "**" "" "" } } */ /* { dg-final { scan-assembler-not {\tvlpq\t} } } */ diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-max-emu.c b/gcc/testsuite/gcc.target/s390/vector/vec-max-emu.c index 12c7e76..16afd1d 100644 --- a/gcc/testsuite/gcc.target/s390/vector/vec-max-emu.c +++ b/gcc/testsuite/gcc.target/s390/vector/vec-max-emu.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O3 -mzarch -march=z13 -save-temps" } */ +/* { dg-options "-O3 -mzarch -march=z13 -save-temps -fno-stack-protector" } */ /* { dg-require-effective-target int128 } */ /* { dg-final { check-function-bodies "**" "" "" } } */ /* { dg-final { scan-assembler-not {\tvmxq\t} } } */ diff --git a/gcc/testsuite/gcc.target/s390/vector/vec-min-emu.c b/gcc/testsuite/gcc.target/s390/vector/vec-min-emu.c index a9bcba3..0eb0916 100644 --- a/gcc/testsuite/gcc.target/s390/vector/vec-min-emu.c +++ b/gcc/testsuite/gcc.target/s390/vector/vec-min-emu.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-O3 -mzarch -march=z13 -save-temps" } */ +/* { dg-options "-O3 -mzarch -march=z13 -save-temps -fno-stack-protector" } */ /* { dg-require-effective-target int128 } */ /* { dg-final { check-function-bodies "**" "" "" } } */ /* { dg-final { scan-assembler-not {\tvmnq\t} } } */ diff --git a/gcc/testsuite/gfortran.dg/coarray/coindexed_7.f90 b/gcc/testsuite/gfortran.dg/coarray/coindexed_7.f90 new file mode 100644 index 0000000..0663970 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/coarray/coindexed_7.f90 @@ -0,0 +1,24 @@ +!{ dg-do compile } + +! Check PR120847 is fixed. + +program p + implicit none + + type T + integer, allocatable :: i(:, :) [:] + end type T + + type(T) :: o + integer, allocatable :: c[:] + integer :: i + + c = 7 + + allocate(o%i(4, 5)[*], source=6) + + do i = 1, 4 + c = o%i(mod(i, 2), mod(i, 3))[1] + end do + +end program p diff --git a/gcc/testsuite/gnat.dg/specs/finalizable2.ads b/gcc/testsuite/gnat.dg/specs/finalizable2.ads new file mode 100644 index 0000000..b4a6bb1 --- /dev/null +++ b/gcc/testsuite/gnat.dg/specs/finalizable2.ads @@ -0,0 +1,21 @@ +-- { dg-do compile } +-- { dg-options "-gnatX0" } + +package Finalizable2 is + + type Root is abstract tagged limited null record + with Finalizable => (Initialize => Initialize); + + procedure Initialize (this : in out Root) is abstract; + + type Ext (L : Natural) is new Root with record + A : String (1 .. L); + end record; + + overriding procedure Initialize (this : in out Ext) is null; + + function Make return Ext is (L => 3, A => "asd"); + + Obj : Ext := Make; + +end Finalizable2; diff --git a/gcc/tree-object-size.cc b/gcc/tree-object-size.cc index f348673..ec4419f 100644 --- a/gcc/tree-object-size.cc +++ b/gcc/tree-object-size.cc @@ -773,10 +773,12 @@ 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. + array type or pointer field 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 array type. */ + of the call, which is the pointer to the original flexible array type or + the type of the original pointer field. */ + static tree access_with_size_object_size (const gcall *call, int object_size_type) { @@ -786,7 +788,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. */ + flexible array type or to the original pointer 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)); @@ -1854,6 +1856,17 @@ 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/tree-vect-loop.cc b/gcc/tree-vect-loop.cc index 575987e..2782d61 100644 --- a/gcc/tree-vect-loop.cc +++ b/gcc/tree-vect-loop.cc @@ -3792,6 +3792,7 @@ vect_analyze_loop (class loop *loop, gimple *loop_vectorized_call, /* When we selected a first vectorized epilogue, see if the target suggests to have another one. */ if (!unlimited_cost_model (loop) + && !LOOP_VINFO_USING_PARTIAL_VECTORS_P (orig_loop_vinfo) && (orig_loop_vinfo->vector_costs->suggested_epilogue_mode () != VOIDmode)) { diff --git a/gcc/tree.cc b/gcc/tree.cc index e9a83e4..6a055c8 100644 --- a/gcc/tree.cc +++ b/gcc/tree.cc @@ -4015,6 +4015,38 @@ decl_address_ip_invariant_p (const_tree op) return false; } +/* Return true if T is an object with invariant address. */ + +bool +address_invariant_p (tree t) +{ + while (handled_component_p (t)) + { + switch (TREE_CODE (t)) + { + case ARRAY_REF: + case ARRAY_RANGE_REF: + if (!tree_invariant_p (TREE_OPERAND (t, 1)) + || TREE_OPERAND (t, 2) != NULL_TREE + || TREE_OPERAND (t, 3) != NULL_TREE) + return false; + break; + + case COMPONENT_REF: + if (TREE_OPERAND (t, 2) != NULL_TREE) + return false; + break; + + default: + break; + } + t = TREE_OPERAND (t, 0); + } + + STRIP_ANY_LOCATION_WRAPPER (t); + return CONSTANT_CLASS_P (t) || decl_address_invariant_p (t); +} + /* Return true if T is function-invariant (internal function, does not handle arithmetic; that's handled in skip_simple_arithmetic and @@ -4023,10 +4055,7 @@ decl_address_ip_invariant_p (const_tree op) static bool tree_invariant_p_1 (tree t) { - tree op; - - if (TREE_CONSTANT (t) - || (TREE_READONLY (t) && !TREE_SIDE_EFFECTS (t))) + if (TREE_CONSTANT (t) || (TREE_READONLY (t) && !TREE_SIDE_EFFECTS (t))) return true; switch (TREE_CODE (t)) @@ -4036,30 +4065,7 @@ tree_invariant_p_1 (tree t) return true; case ADDR_EXPR: - op = TREE_OPERAND (t, 0); - while (handled_component_p (op)) - { - switch (TREE_CODE (op)) - { - case ARRAY_REF: - case ARRAY_RANGE_REF: - if (!tree_invariant_p (TREE_OPERAND (op, 1)) - || TREE_OPERAND (op, 2) != NULL_TREE - || TREE_OPERAND (op, 3) != NULL_TREE) - return false; - break; - - case COMPONENT_REF: - if (TREE_OPERAND (op, 2) != NULL_TREE) - return false; - break; - - default:; - } - op = TREE_OPERAND (op, 0); - } - - return CONSTANT_CLASS_P (op) || decl_address_invariant_p (op); + return address_invariant_p (TREE_OPERAND (t, 0)); default: break; @@ -5347,6 +5347,10 @@ extern tree staticp (tree); extern tree save_expr (tree); +/* Return true if T is an object with invariant address. */ + +extern bool address_invariant_p (tree); + /* Return true if T is function-invariant. */ extern bool tree_invariant_p (tree); |