[gcc r15-4495] Fortran: Add range-based diagnostic
https://gcc.gnu.org/g:ffdfc5b045d7364f76d1f41022b2286108898699 commit r15-4495-gffdfc5b045d7364f76d1f41022b2286108898699 Author: Tobias Burnus Date: Sat Oct 19 10:18:30 2024 +0200 Fortran: Add range-based diagnostic GCC's diagnostic engine gained a while ago support for ranges, i.e. instead of pointing at a single character '^', it can also have a '^~' range. This patch adds support for this and adds 9 users for it, which covers the most common cases. A single '^' can be still useful. Some location data in gfortran is rather bad - often the matching pattern includes whitespace such that the before or after location points to the beginning/end of the whitespace, which can be far of especially when comments and/or continuation lines are involed. Otherwise, often a '^' still sufficient, albeit wrong location data only becomes obvious once starting to use ranges. The 'locus' is extended to support two ways to store the data; hereby gfc_current_locus always contains the old format (at least during parsing) and gfc_current_locus shall not be used in trans*.cc. The latter permits a nice cleanup to just use input_location. Otherwise, the new format is only used when switching to ranges. The only reason to convert from location_t to locus occurs in trans*.cc for the gfc_error (etc.) diagnostic and for gfc_trans_runtime_check; there are 5 currently 5 such cases. For gfc_* diagnostic, we could think of another letter besides %L or a modifier like '%lL', if deemed useful. In any case, the new format is just: locus->u.location = linemap_position_for_loc_and_offset (line_table, loc->u.lb->location, loc->nextc - loc->u.lb->line); locus->nextc = (gfc_char_t *) -1; /* Marker for new format. */ i.e. using the existing location_t location in in the linebuffer (which points to column 0) and add as offset the actually used column number. As location_t handles ranges, we just use it also to store them via: location = make_location (caret, begin, end) There are a few convenience macros/functions but that's all. Alongside, a few minor fixes were done: linemap_location_before_p replaces a line-number based comparison, which does not handle multiple statements in the same line that ';' allows for. gcc/fortran/ChangeLog: * data.cc (gfc_assign_data_value): Use linemap_location_before_p and GFC_LOCUS_IS_SET. * decl.cc (gfc_verify_c_interop_param): Make better translatable. (build_sym, variable_decl, gfc_match_formal_arglist, gfc_match_subroutine): Add range-based locations, use it in diagnostic and gobble whitespace for better locations. * error.cc (gfc_get_location_with_offset): Handle new format. (gfc_get_location_range): New. * expr.cc (gfc_check_assign): Use GFC_LOCUS_IS_SET. * frontend-passes.cc (check_locus_code, check_locus_expr): Likewise. (runtime_error_ne): Use GFC_LOCUS_IS_SET. * gfortran.h (locus): Change lb to union with lb and location. (GFC_LOCUS_IS_SET): Define. (gfc_get_location_range): New prototype. (gfc_new_symbol, gfc_get_symbol, gfc_get_sym_tree, gfc_get_ha_symbol, gfc_get_ha_sym_tree): Take optional locus argument. * io.cc (io_constraint): Use GFC_LOCUS_IS_SET. * match.cc (gfc_match_sym_tree): Use range locus. * openmp.cc (gfc_match_omp_variable_list, gfc_match_omp_doacross_sink): Likewise. * parse.cc (next_free): Update for locus struct change. * primary.cc (gfc_match_varspec): Likewise. (match_variable): Use range locus. * resolve.cc (find_array_spec): Use GFC_LOCUS_IS_SET. * scanner.cc (gfc_at_eof, gfc_at_bol, gfc_start_source_files, gfc_advance_line, gfc_define_undef_line, skip_fixed_comments, gfc_gobble_whitespace, include_stmt, gfc_new_file): Update for locus struct change. * symbol.cc (gfc_new_symbol, gfc_get_sym_tree, gfc_get_symbol, gfc_get_ha_sym_tree, gfc_get_ha_symbol): Take optional locus. * trans-array.cc (gfc_trans_array_constructor_value): Use %L not %C. (gfc_trans_g77_array, gfc_trans_dummy_array_bias, gfc_trans_class_array, gfc_trans_deferred_array): Replace gfc_{save,set,restore}_backend_locus by directly using input_location. * trans-common.cc (build_equiv_decl, get_init_field): Likewise. * trans-decl.cc (gfc_get_extern_function_decl, build_function_decl, build_entry_thunks, gfc_null_and_pass_deferred_len, gfc_trans_deferred_vars, gfc_trans_use_stmts, finish_oacc_declare, gfc_generate_bl
[gcc r15-4494] Fix an ICE with UNSIGNED in match_sym_complex_part.
https://gcc.gnu.org/g:4f9b1735ab5eaf93d07d65c81d83cd123a8f3478 commit r15-4494-g4f9b1735ab5eaf93d07d65c81d83cd123a8f3478 Author: Thomas Koenig Date: Sat Oct 19 10:26:17 2024 +0200 Fix an ICE with UNSIGNED in match_sym_complex_part. gcc/fortran/ChangeLog: PR fortran/117225 * primary.cc (match_sym_complex_part): An UNSIGNED in a complex part is an error. gcc/testsuite/ChangeLog: PR fortran/117225 * gfortran.dg/unsigned_38.f90: New test. Diff: --- gcc/fortran/primary.cc| 3 +++ gcc/testsuite/gfortran.dg/unsigned_38.f90 | 6 ++ 2 files changed, 9 insertions(+) diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc index c11359a559b2..e114bf1375f0 100644 --- a/gcc/fortran/primary.cc +++ b/gcc/fortran/primary.cc @@ -1471,6 +1471,9 @@ match_sym_complex_part (gfc_expr **result) goto error; break; +case BT_UNSIGNED: + goto error; + default: gfc_internal_error ("gfc_match_sym_complex_part(): Bad type"); } diff --git a/gcc/testsuite/gfortran.dg/unsigned_38.f90 b/gcc/testsuite/gfortran.dg/unsigned_38.f90 new file mode 100644 index ..0d169ac92d3c --- /dev/null +++ b/gcc/testsuite/gfortran.dg/unsigned_38.f90 @@ -0,0 +1,6 @@ +! { dg-do compile } +! { dg-options "-funsigned" } +program main + unsigned, parameter :: u = 7u + print *,mod(-(u+1u),u) +end program main
[gcc r15-4497] PR modula2/115328 The FORWARD keyword is not implemented
https://gcc.gnu.org/g:e751639e3d20efe97186faa7dca33e7761ba1e79 commit r15-4497-ge751639e3d20efe97186faa7dca33e7761ba1e79 Author: Gaius Mulley Date: Sat Oct 19 13:30:28 2024 +0100 PR modula2/115328 The FORWARD keyword is not implemented This patch implements the FORWARD keyword found in the ISO standard. The patch checks incoming parameters against the prior declaration found in definition/forward sections and will issue an error based on virtual tokens highlighing the full parameter declaration. gcc/m2/ChangeLog: PR modula2/115328 * gm2-compiler/M2MetaError.def: Extend comment documentating new format specifiers. * gm2-compiler/M2MetaError.mod (GetTokProcedure): New declaration. (doErrorScopeModule): New procedure. (doErrorScopeForward): Ditto. (doErrorScopeMod): Reimplement. (doErrorScopeFor): New procedure. (declarationMod): Ditto. (doErrorScopeDefinition): Ditto. (doErrorScopeDef): Reimplement. (declaredDef): New procedure. (declaredFor): Ditto. (doErrorScopeProc): Ditto. (declaredVar): Ditto. (declaredType): Ditto. (declaredFull): Ditto. * gm2-compiler/M2Options.mod (SetAutoInit): Add missing return type. (GetDumpGimple): Remove duplicate implementation. * gm2-compiler/M2Quads.def (DupFrame): New procedure. * gm2-compiler/M2Quads.mod (DupFrame): New procedure. * gm2-compiler/M2Reserved.def (ForwardTok): New variable. * gm2-compiler/M2Reserved.mod (ForwardTok): Initialize variable. * gm2-compiler/M2Scaffold.mod (DeclareArgEnvParams): Add tokno parameter for call to PutParam. * gm2-compiler/P0SymBuild.def (EndForward): New procedure. * gm2-compiler/P0SymBuild.mod (EndForward): New procedure. * gm2-compiler/P0SyntaxCheck.bnf (BlockAssert): New procedure. (ProcedureDeclaration): Reimplement rule. (PostProcedureHeading): New rule. (ForwardDeclaration): Ditto. (ProperProcedure): Ditto. * gm2-compiler/P1Build.bnf (ProcedureDeclaration): Reimplement rule. (PostProcedureHeading): New rule. (ForwardDeclaration): Ditto. (ProperProcedure): Ditto. * gm2-compiler/P1SymBuild.def (Export): Removed unnecessary export. (EndBuildForward): New procedure. * gm2-compiler/P1SymBuild.mod (StartBuildProcedure): Reimplement. (EndBuildProcedure): Ditto. (EndBuildForward): Ditto. * gm2-compiler/P2Build.bnf (ProcedureDeclaration): Reimplement rule. (PostProcedureHeading): New rule. (ForwardDeclaration): Ditto. (ProperProcedure): Ditto. * gm2-compiler/P2SymBuild.def (BuildProcedureDefinedByForward): New procedure. (BuildProcedureDefinedByProper): Ditto. (CheckProcedure): Ditto. (EndBuildForward): Ditto. * gm2-compiler/P2SymBuild.mod (EndBuildProcedure): Reimplement. (EndBuildForward): New procedure. (BuildFPSection): Reimplement to allow forward declaration or checking of parameters. (BuildProcedureDefinedByProper): New procedure. (BuildProcedureDefinedByForward): Ditto (FailParameter): Remove. (ParameterError): New procedure. (ParameterMismatch): Ditto. (EndBuildFormalParameters): Add parameter number check. (GetComparison): New procedure function. (GetSourceDesc): Ditto. (GetCurSrcDesc): Ditto. (GetDeclared): New procedure. (ReturnTypeMismatch): Ditto. (BuildFunction): Reimplement. (CheckProcedure): New procedure. (CheckFormalParameterSection): Reimplement using ParameterError. * gm2-compiler/P3Build.bnf (ProcedureDeclaration): Reimplement rule. (PostProcedureHeading): New rule. (ForwardDeclaration): Ditto. (ProperProcedure): Ditto. * gm2-compiler/P3SymBuild.def (Export): Remove unnecessary export. (EndBuildForward): New procedure. * gm2-compiler/P3SymBuild.mod (EndBuildForward): New procedure. * gm2-compiler/PCBuild.bnf (ProcedureDeclaration): Reimplement rule. (PostProcedureHeading): New rule. (ForwardDeclaration): Ditto. (ProperProcedure): Ditto. * gm2-compiler/PCSymBuild.def (EndBuildForward): New procedure. * gm2-compiler/PCSymBuild.mod (EndBuildForward): Ditto. * gm2-compiler/PHBuild.bnf (ProcedureDeclaration): Reimplement rule. (PostProcedureHeading): New rule. (Forwa
[gcc r15-4503] phiopt: do factor_out_conditional_operation for all phis [PR112418]
https://gcc.gnu.org/g:8d6d6d537fdc754a429b08091422c307188f3c82 commit r15-4503-g8d6d6d537fdc754a429b08091422c307188f3c82 Author: Andrew Pinski Date: Wed Sep 4 12:11:43 2024 -0700 phiopt: do factor_out_conditional_operation for all phis [PR112418] Sometimes factor_out_conditional_operation can factor out an operation that causes a phi node to become the same element. Other times, we want to factor out a binary operator because it can improve code generation, an example is PR 110015 (openjpeg). Note this includes a heuristic to decide if factoring out the operation is profitable or not. It can be expanded to include a better live range extend detector. Right now it has a simple one where if it is live on a dominating path, it is considered a live or if there are a small # of assign statements (defaults to 5), then it does not extend the live range too much. Bootstrapped and tested on x86_64-linux-gnu. PR tree-optimization/112418 gcc/ChangeLog: * tree-ssa-phiopt.cc (is_factor_profitable): New function. (factor_out_conditional_operation): Add merge argument. Remove arg0/arg1 arguments. Return bool instead of the new phi. Early return for virtual ops. Call is_factor_profitable to check if the factoring would be profitable. (pass_phiopt::execute): Call factor_out_conditional_operation on all phis instead of just singleton phi. * doc/invoke.texi (--param phiopt-factor-max-stmts-live=): Document. * params.opt (--param=phiopt-factor-max-stmts-live=): New opt. gcc/testsuite/ChangeLog: * gcc.dg/tree-ssa/factor_op_phi-1.c: New test. * gcc.dg/tree-ssa/factor_op_phi-2.c: New test. * gcc.dg/tree-ssa/factor_op_phi-3.c: New test. * gcc.dg/tree-ssa/factor_op_phi-4.c: New test. Signed-off-by: Andrew Pinski Diff: --- gcc/doc/invoke.texi | 4 + gcc/params.opt | 4 + gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-1.c | 27 +++ gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-2.c | 29 gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-3.c | 33 gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-4.c | 29 gcc/tree-ssa-phiopt.cc | 209 +--- 7 files changed, 272 insertions(+), 63 deletions(-) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 8437b2029ede..aebcc9082ff6 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -15473,6 +15473,10 @@ In each case, the @var{value} is an integer. The following choices of @var{name} are recognized for all targets: @table @gcctabopt +@item phiopt-factor-max-stmts-live +When factoring statements out of if/then/else, this is the max # of statements +after the defining statement to be allow to extend the lifetime of a name + @item predictable-branch-outcome When branch is predicted to be taken with probability lower than this threshold (in percent), then it is considered well predictable. diff --git a/gcc/params.opt b/gcc/params.opt index a08e4c1042da..24f440bbe71f 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -861,6 +861,10 @@ Enum(parloops_schedule_type) String(runtime) Value(PARLOOPS_SCHEDULE_RUNTIME) Common Joined UInteger Var(param_partial_inlining_entry_probability) Init(70) Optimization IntegerRange(0, 100) Param Maximum probability of the entry BB of split region (in percent relative to entry BB of the function) to make partial inlining happen. +-param=phiopt-factor-max-stmts-live= +Common Joined UInteger Var(param_phiopt_factor_max_stmts_live) Init(5) Optimization IntegerRange(0, 100) Param +Maximum number of statements allowed inbetween the statement and the end to considered not extending the liferange. + -param=predictable-branch-outcome= Common Joined UInteger Var(param_predictable_branch_outcome) Init(2) IntegerRange(0, 50) Param Optimization Maximal estimated outcome of branch considered predictable. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-1.c b/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-1.c new file mode 100644 index ..6c0971ff8014 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/factor_op_phi-1.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-phiopt1-details -fdump-tree-optimized" } */ + +/* PR tree-optimization/112418 */ + +int f(int a, int b, int d) +{ + int c; + if (a < 0) + { +a = -a; +c = d > 0 ? d : -d; + } + else + { +a = a; +c = d > 0 ? d : -d; + } + return a + c; +} + +/* ABS should be able to pull out of the if statement early on in phiopt1. */ +/* { dg-final { scan-tree-dump "changed to factor operation out from " "phiopt1" } } */ +/* { dg-final { scan-tree-dump-not "if " "phiopt1" } } */ +/* { dg-final { scan-tree-dump-times "ABS_EXPR "
[gcc r15-4501] Add missing dg-error to unsigned_38.f90.
https://gcc.gnu.org/g:a8f36de5aa52db2864a4c068dd0b4c9464385159 commit r15-4501-ga8f36de5aa52db2864a4c068dd0b4c9464385159 Author: Thomas Koenig Date: Sat Oct 19 16:21:48 2024 +0200 Add missing dg-error to unsigned_38.f90. gcc/testsuite/ChangeLog: PR fortran/117225 * gfortran.dg/unsigned_38.f90: Add missing dg-error directive. Diff: --- gcc/testsuite/gfortran.dg/unsigned_38.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/testsuite/gfortran.dg/unsigned_38.f90 b/gcc/testsuite/gfortran.dg/unsigned_38.f90 index 0d169ac92d3c..d549483b269a 100644 --- a/gcc/testsuite/gfortran.dg/unsigned_38.f90 +++ b/gcc/testsuite/gfortran.dg/unsigned_38.f90 @@ -2,5 +2,5 @@ ! { dg-options "-funsigned" } program main unsigned, parameter :: u = 7u - print *,mod(-(u+1u),u) + print *,mod(-(u+1u),u) ! { dg-error "Operand of unary numeric operator" } end program main
[gcc r15-4496] Fortran: Fix translatability of diagnostic strings
https://gcc.gnu.org/g:efae253b9f863b066e899106d7f3ad9ef0cd3c58 commit r15-4496-gefae253b9f863b066e899106d7f3ad9ef0cd3c58 Author: Tobias Burnus Date: Sat Oct 19 10:19:14 2024 +0200 Fortran: Fix translatability of diagnostic strings gcc/fortran/ChangeLog: * check.cc (is_c_interoperable): Use _(...) around to mark strings as translatable. * data.cc (gfc_assign_data_value): Move string literal to gfc_error to make it translatable. * resolve.cc (resolve_fl_variable, resolve_equivalence): Use G_(...) around string literals. * scanner.cc (skip_fixed_omp_sentinel): Replace '...' by %<...%>. * trans-openmp.cc (gfc_split_omp_clauses, gfc_trans_omp_declare_variant): Likewise. Diff: --- gcc/fortran/check.cc| 20 ++-- gcc/fortran/data.cc | 6 +++--- gcc/fortran/resolve.cc | 20 ++-- gcc/fortran/scanner.cc | 2 +- gcc/fortran/trans-openmp.cc | 4 ++-- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc index 79e6668d0afe..e90073ad4b04 100644 --- a/gcc/fortran/check.cc +++ b/gcc/fortran/check.cc @@ -5615,32 +5615,32 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr) if (expr->expr_type == EXPR_NULL && expr->ts.type == BT_UNKNOWN) { - *msg = "NULL() is not interoperable"; + *msg = _("NULL() is not interoperable"); return false; } if (expr->ts.type == BT_BOZ) { - *msg = "BOZ literal constant"; + *msg = _("BOZ literal constant"); return false; } if (expr->ts.type == BT_CLASS) { - *msg = "Expression is polymorphic"; + *msg = _("Expression is polymorphic"); return false; } if (expr->ts.type == BT_DERIVED && !expr->ts.u.derived->attr.is_bind_c && !expr->ts.u.derived->ts.is_iso_c) { - *msg = "Expression is a noninteroperable derived type"; + *msg = _("Expression is a noninteroperable derived type"); return false; } if (expr->ts.type == BT_PROCEDURE) { - *msg = "Procedure unexpected as argument"; + *msg = _("Procedure unexpected as argument"); return false; } @@ -5650,14 +5650,14 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr) for (i = 0; gfc_logical_kinds[i].kind; i++) if (gfc_logical_kinds[i].kind == expr->ts.kind) return true; - *msg = "Extension to use a non-C_Bool-kind LOGICAL"; + *msg = _("Extension to use a non-C_Bool-kind LOGICAL"); return false; } if (gfc_notification_std (GFC_STD_GNU) && expr->ts.type == BT_CHARACTER && expr->ts.kind != 1) { - *msg = "Extension to use a non-C_CHAR-kind CHARACTER"; + *msg = _("Extension to use a non-C_CHAR-kind CHARACTER"); return false; } @@ -5678,7 +5678,7 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr) && expr->ts.u.cl && !gfc_length_one_character_type_p (&expr->ts)) { - *msg = "Type shall have a character length of 1"; + *msg = _("Type shall have a character length of 1"); return false; } } @@ -5689,7 +5689,7 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr) if (gfc_is_coarray (expr)) { - *msg = "Coarrays are not interoperable"; + *msg = _("Coarrays are not interoperable"); return false; } @@ -5700,7 +5700,7 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr) gfc_array_ref *ar = gfc_find_array_ref (expr); if (ar->type == AR_FULL && ar->as->type == AS_ASSUMED_SIZE) { - *msg = "Assumed-size arrays are not interoperable"; + *msg = _("Assumed-size arrays are not interoperable"); return false; } } diff --git a/gcc/fortran/data.cc b/gcc/fortran/data.cc index c0974be88b22..e7202455b3ec 100644 --- a/gcc/fortran/data.cc +++ b/gcc/fortran/data.cc @@ -272,8 +272,6 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index, gfc_symbol *symbol; gfc_typespec *last_ts; mpz_t offset; - const char *msg = "F18(R841): data-implied-do object at %L is neither an " - "array-element nor a scalar-structure-component"; symbol = lvalue->symtree->n.sym; init = symbol->value; @@ -523,7 +521,9 @@ gfc_assign_data_value (gfc_expr *lvalue, gfc_expr *rvalue, mpz_t index, violates F18(R841). If the error is removed, the expected result is obtained. Leaving the code in place ensures a clean error recovery. */ - gfc_error (msg, &lvalue->where); + gfc_error ("data-implied-do object at %L is neither an array-element " +"nor a scalar-structure-component (F2018: R841)", +
[gcc r15-4504] modula2: Tidyup gm2-compiler/M2MetaError.mod
https://gcc.gnu.org/g:7fa9fd47f161d6b8177439ae2b46a2048a5eaa24 commit r15-4504-g7fa9fd47f161d6b8177439ae2b46a2048a5eaa24 Author: Gaius Mulley Date: Sat Oct 19 20:35:26 2024 +0100 modula2: Tidyup gm2-compiler/M2MetaError.mod This patch is a tidyup for gm2-compiler/M2MetaError.mod. gcc/m2/ChangeLog: * gm2-compiler/M2MetaError.mod (op): Alphabetically order each case label and comment. Signed-off-by: Gaius Mulley Diff: --- gcc/m2/gm2-compiler/M2MetaError.mod | 51 +++-- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/gcc/m2/gm2-compiler/M2MetaError.mod b/gcc/m2/gm2-compiler/M2MetaError.mod index 007c10b28bdf..e9f3127925c4 100644 --- a/gcc/m2/gm2-compiler/M2MetaError.mod +++ b/gcc/m2/gm2-compiler/M2MetaError.mod @@ -1684,8 +1684,9 @@ END copySym ; (* - op := {'a'|'q'|'t'|'d'|'n'|'s'|'B'|'D'|'F'|'G'|'H'|'M'|'U'|'E'|'V'|'W'|'A'} then =: - op := {'a'|'q'|'t'|'d'|'n'|'s'| 'u' |'D'|'F'|'G'|'M'|'U'|'E'|'W'} then =: + op := {'!'|'a'|'c'|'d'|'k'|'q'|'t'|'p'|'n'|'s'|'u'| + 'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'K'|'M'|'N'| + 'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'X'|'Y'|'Z'} then =: *) PROCEDURE op (VAR eb: errorBlock; @@ -1701,43 +1702,43 @@ BEGIN '!': eb.positive := NOT eb.positive | 'a': doName (eb, sym, bol) | + 'c': eb.currentCol := readColor (eb) ; +DEC (eb.ini) | + 'd': doDesc (eb, sym, bol) | + 'k': unquotedKeyword (eb) ; +DEC (eb.ini) | 'q': doQualified (eb, sym, bol) | 't': doType (eb, sym, bol) | - 'd': doDesc (eb, sym, bol) | + 'p': popColor (eb) | 'n': doNumber (eb, sym, bol) | - 'N': doCount (eb, sym, bol) | 's': doSkipType (eb, sym, bol) | - 'B': declaredType (eb, sym, bol) | - 'H': declaredFull (eb, sym, bol) | - 'V': declaredVar (eb, sym, bol) | - 'G': declaredFor (eb, sym, bol) | - 'M': declaredMod (eb, sym, bol) | - 'D': declaredDef (eb, sym, bol) | - 'U': used (eb, sym, bol) | - 'E': eb.type := error | + 'u': eb.quotes := FALSE | 'A': eb.type := aborta ; seenAbort := TRUE | - 'W': eb.type := warning | - 'O': eb.type := note | + 'B': declaredType (eb, sym, bol) | 'C': eb.chain := TRUE | - 'R': eb.root := TRUE | - 'S': doGetSkipType (eb, sym, bol) | - 'T': doGetType (eb, sym, bol) | - 'P': pushColor (eb) | - 'p': popColor (eb) | - 'c': eb.currentCol := readColor (eb) ; + 'D': declaredDef (eb, sym, bol) | + 'E': eb.type := error | + 'F': filename (eb) ; DEC (eb.ini) | + 'G': declaredFor (eb, sym, bol) | + 'H': declaredFull (eb, sym, bol) | 'K': keyword (eb) ; DEC (eb.ini) | - 'k': unquotedKeyword (eb) ; -DEC (eb.ini) | + 'M': declaredMod (eb, sym, bol) | + 'N': doCount (eb, sym, bol) | + 'O': eb.type := note | + 'P': pushColor (eb) | 'Q': resetDictionary | + 'R': eb.root := TRUE | + 'S': doGetSkipType (eb, sym, bol) | + 'T': doGetType (eb, sym, bol) | + 'U': used (eb, sym, bol) | + 'V': declaredVar (eb, sym, bol) | + 'W': eb.type := warning | 'X': pushOutput (eb) | 'Y': processDefine (eb) | 'Z': popOutput (eb) | - 'F': filename (eb) ; -DEC (eb.ini) | - 'u': eb.quotes := FALSE | ':': ifNonNulThen (eb, sym) ; DEC (eb.ini) | '1': InternalError ('incorrect format spec, expecting %1 rather than % spec 1') |
[gcc r15-4498] [PATCH 4/7] RISC-V: Honour -mrvv-max-lmul in riscv_vector::expand_block_move
https://gcc.gnu.org/g:b5aa63b1c81b91fed9bbf89c0ad7551c3f98b9f6 commit r15-4498-gb5aa63b1c81b91fed9bbf89c0ad7551c3f98b9f6 Author: Craig Blackmore Date: Sat Oct 19 06:57:06 2024 -0600 [PATCH 4/7] RISC-V: Honour -mrvv-max-lmul in riscv_vector::expand_block_move Unlike the other vector string ops, expand_block_move was using max LMUL m8 regardless of TARGET_MAX_LMUL. The check for whether to generate inline vector code for movmem has been moved from movmem to riscv_vector::expand_block_move to avoid maintaining multiple versions of similar logic. They already differed on the minimum length for which they would generate vector code. Now that the expand_block_move value is used, movmem will be generated for smaller lengths. Limiting memcpy to m1 caused some memcpy loops to be generated in the calling convention tests which makes it awkward to add suitable scan assembler tests checking the return value being set, so -mrvv-max-lmul=m8 has been added to these tests. Other tests have been adjusted to expect the new memcpy m1 generation where reasonably straight-forward, otherwise -mrvv-max-lmul=m8 has been added. pr111720-[0-9].c regressed because a memcpy loop is generated instead of straight-line. This reveals an existing issue where a redundant straight-line memcpy gets eliminated but a memcpy loop does not (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117205). For example, on pr111720-0.c after this patch: -mrvv-max-lmul=m8: test: lui a5,%hi(.LANCHOR0) li a4,32 addisp,sp,-32 addia5,a5,%lo(.LANCHOR0) vsetvli zero,a4,e8,m1,ta,ma vle8.v v8,0(a5) addisp,sp,32 jr ra -mrvv-max-lmul=m1: test: addisp,sp,-32 lui a5,%hi(.LANCHOR0) addia5,a5,%lo(.LANCHOR0) mv a2,sp li a3,32 .L2: vsetvli a4,a3,e8,m1,ta,ma vle8.v v8,0(a5) sub a3,a3,a4 add a5,a5,a4 vse8.v v8,0(a2) add a2,a2,a4 bne a3,zero,.L2 li a5,32 vsetvli zero,a5,e8,m1,ta,ma vle8.v v8,0(sp) addisp,sp,32 jr ra I have added -mrvv-max-lmul=m8 to pr111720-[0-9].c so that we continue to test the elimination of straight-line memcpy. gcc/ChangeLog: * config/riscv/riscv-protos.h (get_lmul_mode): New prototype. (expand_block_move): Add bool parameter for movmem_p. * config/riscv/riscv-string.cc (riscv_expand_block_move_scalar): Pass movmem_p as false to riscv_vector::expand_block_move. (expand_block_move): Add movmem_p parameter. Return false if loop needed and movmem_p is true. Respect TARGET_MAX_LMUL. * config/riscv/riscv-v.cc (get_lmul_mode): New function. * config/riscv/riscv.md (movmem): Move checking for whether to generate inline vector code to riscv_vector::expand_block_move by passing movmem_p as true. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/pr113206-1.c: Add -mrvv-max-lmul=m8. * gcc.target/riscv/rvv/autovec/pr113206-2.c: Likewise. * gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c: Add -mrvv-max-lmul=m8 and adjust assembly scans. * gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c: Likewise. * gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c: Likewise. * gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c: Likewise. * gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c: Likewise. * gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c: Likewise. * gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c: Likewise. * gcc.target/riscv/rvv/autovec/vls/spill-4.c: Add -mrvv-max-lmul=m8. * gcc.target/riscv/rvv/autovec/vls/spill-7.c: Likewise. * gcc.target/riscv/rvv/base/cpymem-1.c: Expect m1 in f1 and f2. * gcc.target/riscv/rvv/base/cpymem-2.c: Add -mrvv-max-lmul=m8. * gcc.target/riscv/rvv/base/movmem-1.c: Adjust f1 to a length that will not get vectorized. * gcc.target/riscv/rvv/base/pr111720-0.c: Add -mrvv-max-lmul=m8. * gcc.target/riscv/rvv/base/pr111720-1.c: Likewise. * gcc.target/riscv/rvv/base/pr111720-2.c: Likewise. * gcc.target/riscv/rvv/base/pr111720-3.c: Likewise. * gcc.target/riscv/rvv/base/pr111720-4.c: Likewise. * gcc.target/riscv/rvv/base/pr111720-5.c: Likewise. * gcc.
[gcc r15-4499] [PATCH 5/7] RISC-V: Move vector memcpy decision making to separate function [NFC]
https://gcc.gnu.org/g:12deddebf63217ffe26858c4a89f7aba5133f04c commit r15-4499-g12deddebf63217ffe26858c4a89f7aba5133f04c Author: Craig Blackmore Date: Sat Oct 19 07:00:47 2024 -0600 [PATCH 5/7] RISC-V: Move vector memcpy decision making to separate function [NFC] This moves the code for deciding whether to generate a vectorized memcpy, what vector mode to use and whether a loop is needed out of riscv_vector::expand_block_move and into a new function riscv_vector::use_stringop_p so that it can be reused for other string operations. gcc/ChangeLog: * config/riscv/riscv-string.cc (struct stringop_info): New. (expand_block_move): Move decision making code to... (use_vector_stringop_p): ...here. Diff: --- gcc/config/riscv/riscv-string.cc | 143 --- 1 file changed, 87 insertions(+), 56 deletions(-) diff --git a/gcc/config/riscv/riscv-string.cc b/gcc/config/riscv/riscv-string.cc index 64fd6b290921..118c02a40212 100644 --- a/gcc/config/riscv/riscv-string.cc +++ b/gcc/config/riscv/riscv-string.cc @@ -1051,35 +1051,31 @@ riscv_expand_block_clear (rtx dest, rtx length) namespace riscv_vector { -/* Used by cpymemsi in riscv.md . */ +struct stringop_info { + rtx avl; + bool need_loop; + machine_mode vmode; +}; -bool -expand_block_move (rtx dst_in, rtx src_in, rtx length_in, bool movmem_p) -{ - /* -memcpy: - mv a3, a0 # Copy destination -loop: - vsetvli t0, a2, e8, m8, ta, ma # Vectors of 8b - vle8.v v0, (a1) # Load bytes - add a1, a1, t0 # Bump pointer - sub a2, a2, t0 # Decrement count - vse8.v v0, (a3) # Store bytes - add a3, a3, t0 # Bump pointer - bnez a2, loop # Any more? - ret # Return - */ - gcc_assert (TARGET_VECTOR); +/* If a vectorized stringop should be used populate INFO and return TRUE. + Otherwise return false and leave INFO unchanged. - HOST_WIDE_INT potential_ew -= (MIN (MIN (MEM_ALIGN (src_in), MEM_ALIGN (dst_in)), BITS_PER_WORD) - / BITS_PER_UNIT); - machine_mode vmode = VOIDmode; + MAX_EW is the maximum element width that the caller wants to use and + LENGTH_IN is the length of the stringop in bytes. +*/ + +static bool +use_vector_stringop_p (struct stringop_info &info, HOST_WIDE_INT max_ew, + rtx length_in) +{ bool need_loop = true; - bool size_p = optimize_function_for_size_p (cfun); - rtx src, dst; - rtx vec; - rtx length_rtx = length_in; + machine_mode vmode = VOIDmode; + /* The number of elements in the stringop. */ + rtx avl = length_in; + HOST_WIDE_INT potential_ew = max_ew; + + if (!TARGET_VECTOR || !(stringop_strategy & STRATEGY_VECTOR)) +return false; if (CONST_INT_P (length_in)) { @@ -1113,17 +1109,7 @@ expand_block_move (rtx dst_in, rtx src_in, rtx length_in, bool movmem_p) for small element widths, we might allow larger element widths for loops too. */ if (need_loop) - { - if (movmem_p) - /* Inlining general memmove is a pessimisation: we can't avoid - having to decide which direction to go at runtime, which is - costly in instruction count however for situations where the - entire move fits in one vector operation we can do all reads - before doing any writes so we don't have to worry so generate - the inline vector code in such situations. */ - return false; - potential_ew = 1; - } + potential_ew = 1; for (; potential_ew; potential_ew >>= 1) { scalar_int_mode elem_mode; @@ -1193,7 +1179,7 @@ expand_block_move (rtx dst_in, rtx src_in, rtx length_in, bool movmem_p) gcc_assert (potential_ew > 1); } if (potential_ew > 1) - length_rtx = GEN_INT (length / potential_ew); + avl = GEN_INT (length / potential_ew); } else { @@ -1203,35 +1189,80 @@ expand_block_move (rtx dst_in, rtx src_in, rtx length_in, bool movmem_p) /* A memcpy libcall in the worst case takes 3 instructions to prepare the arguments + 1 for the call. When RVV should take 7 instructions and we're optimizing for size a libcall may be preferable. */ - if (size_p && need_loop) + if (optimize_function_for_size_p (cfun) && need_loop) return false; - /* length_rtx holds the (remaining) length of the required copy. + info.need_loop = need_loop; + info.vmode = vmode; + info.avl = avl; + return true; +} + +/* Used by cpymemsi in riscv.md . */ + +bool +expand_block_move (rtx dst_in, rtx src_in, rtx length_in, bool movmem_p) +{ + /* +memcpy: + mv a3, a0 # Copy destination +loop: + vsetvli t0, a2, e8, m8, ta, ma # Vectors of 8b +
[gcc r15-4500] [PATCH 7/7] RISC-V: Disable by pieces for vector setmem length > UNITS_PER_WORD
https://gcc.gnu.org/g:72ceddbfb78dbb95f0808c3eca1765e8cd48b023 commit r15-4500-g72ceddbfb78dbb95f0808c3eca1765e8cd48b023 Author: Craig Blackmore Date: Sat Oct 19 07:08:31 2024 -0600 [PATCH 7/7] RISC-V: Disable by pieces for vector setmem length > UNITS_PER_WORD For fast unaligned access targets, by pieces uses up to UNITS_PER_WORD size pieces resulting in more store instructions than needed. For example gcc.target/riscv/rvv/base/setmem-1.c:f1 built with `-O3 -march=rv64gcv -mtune=thead-c906`: ``` f1: vsetivlizero,8,e8,mf2,ta,ma vmv.v.x v1,a1 vsetivlizero,0,e32,mf2,ta,ma sb a1,14(a0) vmv.x.s a4,v1 vsetivlizero,8,e16,m1,ta,ma vmv.x.s a5,v1 vse8.v v1,0(a0) sw a4,8(a0) sh a5,12(a0) ret ``` The slow unaligned access version built with `-O3 -march=rv64gcv` used 15 sb instructions: ``` f1: sb a1,0(a0) sb a1,1(a0) sb a1,2(a0) sb a1,3(a0) sb a1,4(a0) sb a1,5(a0) sb a1,6(a0) sb a1,7(a0) sb a1,8(a0) sb a1,9(a0) sb a1,10(a0) sb a1,11(a0) sb a1,12(a0) sb a1,13(a0) sb a1,14(a0) ret ``` After this patch, the following is generated in both cases: ``` f1: vsetivlizero,15,e8,m1,ta,ma vmv.v.x v1,a1 vse8.v v1,0(a0) ret ``` gcc/ChangeLog: * config/riscv/riscv.cc (riscv_use_by_pieces_infrastructure_p): New function. (TARGET_USE_BY_PIECES_INFRASTRUCTURE_P): Define. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/pr113469.c: Expect mf2 setmem. * gcc.target/riscv/rvv/base/setmem-2.c: Update f1 to expect straight-line vector memset. * gcc.target/riscv/rvv/base/setmem-3.c: Likewise. Diff: --- gcc/config/riscv/riscv.cc | 19 +++ gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113469.c | 3 ++- gcc/testsuite/gcc.target/riscv/rvv/base/setmem-2.c| 12 +++- gcc/testsuite/gcc.target/riscv/rvv/base/setmem-3.c| 12 +++- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 3ac40234345a..fc2a83b21876 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -12583,6 +12583,22 @@ riscv_stack_clash_protection_alloca_probe_range (void) return STACK_CLASH_CALLER_GUARD; } +static bool +riscv_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, + unsigned alignment, + enum by_pieces_operation op, bool speed_p) +{ + /* For set/clear with size > UNITS_PER_WORD, by pieces uses vector broadcasts + with UNITS_PER_WORD size pieces. Use setmem instead which can use + bigger chunks. */ + if (TARGET_VECTOR && stringop_strategy & STRATEGY_VECTOR + && (op == CLEAR_BY_PIECES || op == SET_BY_PIECES) + && speed_p && size > UNITS_PER_WORD) +return false; + + return default_use_by_pieces_infrastructure_p (size, alignment, op, speed_p); +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -12948,6 +12964,9 @@ riscv_stack_clash_protection_alloca_probe_range (void) #undef TARGET_C_MODE_FOR_FLOATING_TYPE #define TARGET_C_MODE_FOR_FLOATING_TYPE riscv_c_mode_for_floating_type +#undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P +#define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P riscv_use_by_pieces_infrastructure_p + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h" diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113469.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113469.c index d1c118c02d6e..f86084bdb40f 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113469.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr113469.c @@ -51,4 +51,5 @@ void p(int buf, __builtin_va_list ab, int q) { } while (k); } -/* { dg-final { scan-assembler-times {vsetivli\tzero,\s*4,\s*e8,\s*mf4,\s*t[au],\s*m[au]} 2 } } */ +/* { dg-final { scan-assembler-times {vsetivli\tzero,\s*4,\s*e8,\s*mf4,\s*t[au],\s*m[au]} 1 } } */ +/* { dg-final { scan-assembler-times {vsetivli\tzero,\s*8,\s*e8,\s*mf2,\s*t[au],\s*m[au]} 1 } } */ diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/setmem-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/setmem-2.c index faea442a4bdc..838fbebadff3 100644 --- a/gcc/testsuite/gcc.target/riscv/rvv/base/setmem-2.c +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/setmem-2.c @@ -5,15 +5,17 @@ #define
[gcc r15-4502] [PATCH][v5] RISC-V: add option -m(no-)autovec-segment
https://gcc.gnu.org/g:f2989316139c3e7a99b1babe2606833c05b8a12f commit r15-4502-gf2989316139c3e7a99b1babe2606833c05b8a12f Author: Greg McGary Date: Sat Oct 19 08:21:56 2024 -0600 [PATCH][v5] RISC-V: add option -m(no-)autovec-segment Add option -m(no-)autovec-segment to enable/disable autovectorizer from emitting vector segment load/store instructions. This is useful for performance experiments. gcc/ChangeLog: * config/riscv/autovec.md (vec_mask_len_load_lanes, vec_mask_len_store_lanes): Predicate with TARGET_VECTOR_AUTOVEC_SEGMENT * config/riscv/riscv-opts.h (TARGET_VECTOR_AUTOVEC_SEGMENT): New macro. * config/riscv/riscv.opt (-m(no-)autovec-segment): New option. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg-1.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg-2.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg-3.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg-4.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg-5.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg-6.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg-7.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg_run-1.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg_run-2.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg_run-3.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg_run-4.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg_run-5.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg_run-6.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_load_noseg_run-7.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg-1.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg-2.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg-3.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg-4.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg-5.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg-6.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg-7.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg_run-1.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg_run-2.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg_run-3.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg_run-4.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg_run-5.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg_run-6.c: New test. * gcc.target/riscv/rvv/autovec/struct/mask_struct_store_noseg_run-7.c: New test. * gcc.target/riscv/rvv/autovec/no-segment.c: New test. Diff: --- gcc/config/riscv/autovec.md| 4 +- gcc/config/riscv/riscv-opts.h | 5 ++ gcc/config/riscv/riscv.opt | 4 ++ .../gcc.target/riscv/rvv/autovec/no-segment.c | 61 ++ .../rvv/autovec/struct/mask_struct_load_noseg-1.c | 6 +++ .../rvv/autovec/struct/mask_struct_load_noseg-2.c | 6 +++ .../rvv/autovec/struct/mask_struct_load_noseg-3.c | 6 +++ .../rvv/autovec/struct/mask_struct_load_noseg-4.c | 6 +++ .../rvv/autovec/struct/mask_struct_load_noseg-5.c | 6 +++ .../rvv/autovec/struct/mask_struct_load_noseg-6.c | 6 +++ .../rvv/autovec/struct/mask_struct_load_noseg-7.c | 6 +++ .../autovec/struct/mask_struct_load_noseg_run-1.c | 4 ++ .../autovec/struct/mask_struct_load_noseg_run-2.c | 4 ++ .../autovec/struct/mask_struct_load_noseg_run-3.c | 4 ++ .../autovec/struct/mask_struct_load_noseg_run-4.c | 4 ++ .../autovec/struct/mask_struct_load_noseg_run-5.c | 4 ++ .../autovec/struct/mask_struct_load_noseg_run-6.c | 4 ++ .../autovec/struct/mask_struct_load_noseg_run-7.c | 4 ++ .../rvv/autovec/struct/mask_struct_store_noseg-1.c | 6 +++ .../rvv/autovec/struct/mask_struct_store_noseg-2.c | 6 +++ .../rvv/autovec/s
[gcc r15-4505] diagnostics: libcpp: Improve locations for _Pragma lexing diagnostics [PR114423]
https://gcc.gnu.org/g:65c5bbe1c92f9c08e99d3a37c136f2ef9804a37f commit r15-4505-g65c5bbe1c92f9c08e99d3a37c136f2ef9804a37f Author: Lewis Hyatt Date: Fri Mar 22 12:55:27 2024 -0400 diagnostics: libcpp: Improve locations for _Pragma lexing diagnostics [PR114423] libcpp is not currently set up to be able to generate valid locations for tokens lexed from a _Pragma string. Instead, after obtaining the tokens, it sets their locations all to the location of the _Pragma operator itself. This makes things like _Pragma("GCC diagnostic") work well enough, but if any diagnostics are issued during lexing, prior to resetting the token locations, those diagnostics get issued at the invalid locations. Fix that up by adding a new field pfile->diagnostic_override_loc that instructs libcpp to issue diagnostics at the alternate location. libcpp/ChangeLog: PR preprocessor/114423 * internal.h (struct cpp_reader): Add DIAGNOSTIC_OVERRIDE_LOC field. * directives.cc (destringize_and_run): Set the new field to the location of the _Pragma operator. * errors.cc (cpp_diagnostic_at): Support DIAGNOSTIC_OVERRIDE_LOC to temporarily issue diagnostics at a different location. (cpp_diagnostic_with_line): Likewise. gcc/testsuite/ChangeLog: PR preprocessor/114423 * c-c++-common/cpp/pragma-diagnostic-loc.c: New test. * c-c++-common/cpp/diagnostic-pragma-1.c: Adjust expected output. * g++.dg/pch/operator-1.C: Likewise. Diff: --- gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c | 9 - .../c-c++-common/cpp/pragma-diagnostic-loc.c | 17 + gcc/testsuite/g++.dg/pch/operator-1.C| 8 +++- libcpp/directives.cc | 7 +++ libcpp/errors.cc | 20 ++-- libcpp/internal.h| 4 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c b/gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c index 9867c94a8ddc..6e37294fd2ba 100644 --- a/gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c +++ b/gcc/testsuite/c-c++-common/cpp/diagnostic-pragma-1.c @@ -3,9 +3,8 @@ #pragma GCC warning "warn-a" // { dg-warning warn-a } #pragma GCC error "err-b" // { dg-error err-b } -#define CONST1 _Pragma("GCC warning \"warn-c\"") 1 -#define CONST2 _Pragma("GCC error \"err-d\"") 2 - -char a[CONST1]; // { dg-warning warn-c } -char b[CONST2]; // { dg-error err-d } +#define CONST1 _Pragma("GCC warning \"warn-c\"") 1 // { dg-warning warn-c } +#define CONST2 _Pragma("GCC error \"err-d\"") 2 // { dg-error err-d } +char a[CONST1]; // { dg-note "in expansion of macro 'CONST1'" } +char b[CONST2]; // { dg-note "in expansion of macro 'CONST2'" } diff --git a/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc.c b/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc.c new file mode 100644 index ..4ef40420cdd3 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cpp/pragma-diagnostic-loc.c @@ -0,0 +1,17 @@ +/* { dg-do preprocess } */ +/* PR preprocessor/114423 */ +/* Check that we now issue diagnostics at the location of the _Pragma + instead of an invalid location. If we someday manage to issue + diagnostics at better locations in the future, this will need + updating. */ +_Pragma("GCC warning \"warning1\"") /* { dg-warning "1:warning1" } */ +#define P _Pragma("GCC warning \"warning2\"") /* { dg-warning "11:warning2" } */ +P /* { dg-note "in expansion of macro" } */ +#define S "GCC warning \"warning3\"" +/**/ _Pragma(S) /* { dg-warning "6:warning3" } */ + +/* This diagnostic uses a different code path (cpp_diagnostic_at() rather + than cpp_error_with_line()). Also make sure that the dg-note location + does not get overridden to the _Pragma location. */ +#pragma GCC poison xyz /* { dg-note "poisoned here" } */ +/* */ _Pragma("xyz") /* { dg-error "7:attempt to use poisoned" } */ diff --git a/gcc/testsuite/g++.dg/pch/operator-1.C b/gcc/testsuite/g++.dg/pch/operator-1.C index 290b5f7ab210..1138a9695361 100644 --- a/gcc/testsuite/g++.dg/pch/operator-1.C +++ b/gcc/testsuite/g++.dg/pch/operator-1.C @@ -1,2 +1,8 @@ #include "operator-1.H" -int main(void){ major(0);} /* { dg-warning "Did not Work" } */ +int main(void){ major(0);} /* { dg-note "in expansion of macro 'major'" } */ +/* Line numbers below pertain to the header file. */ +/* { dg-warning "Did not Work" "" { target *-*-* } 1 } */ +/* { dg-note "in expansion of macro '__glibc_macro_warning1'" "" { target *-*-* } 3 } */ +/* { dg-note "in expansion of macro '__glibc_macro_warning'" "" { target *-*-* } 4 } */ +/* { dg-note "in expansion of macro '__SYSMACROS_DM1'" "" { target *-*-* } 6 } */ +/* { dg-note "in expansion of macro '__SYSMACROS_DM'" "" { targe