On Mon, 27 Apr 2026 at 20:48, Harald Anlauf wrote: > Am 27.04.26 um 8:37 PM schrieb Andrew Pinski: >> On Thu, Apr 16, 2026 at 10:18 AM Christopher Albert <[email protected]> wrote: >>> >>> The Fortran preprocessor has never defined target-specific macros such as >>> __linux__, __unix__, __ELF__, __x86_64__, or __amd64__ that the C >>> preprocessor provides. This was caused by the TARGET_OS_CPP_BUILTINS, >>> TARGET_OBJFMT_CPP_BUILTINS, and TARGET_CPU_CPP_BUILTINS hooks being >>> disabled since 2008 (marked as "Pandora's Box") because several target >>> config headers use C-family-only functions. >>> >>> Fix by providing Fortran-compatible local helpers for >>> builtin_define_std, builtin_define_with_value, and >>> builtin_define_with_int_value (which in the C frontend live in >>> c-family/c-cppbuiltin.cc and use the C-family-only globals parse_in >>> and flag_iso), plus wrapper macros for c_dialect_cxx, flag_iso, and >>> other C-family identifiers referenced by target config headers. This >>> allows TARGET_OS_CPP_BUILTINS and TARGET_OBJFMT_CPP_BUILTINS to >>> execute in the Fortran frontend. >>> >>> Unlike the C frontend default (flag_iso=0, GNU extensions mode), the >>> Fortran wrapper sets flag_iso=1 to suppress user-namespace macros like >>> bare "unix" and "linux" that would conflict with Fortran identifiers. >>> Only the reserved-namespace forms (__unix__, __linux__, etc.) are >>> defined. Fortran has no -std=cNN equivalent to control this, so the >>> conservative choice avoids silent identifier replacement. >>> >>> For TARGET_CPU_CPP_BUILTINS, which on most architectures expands to a >>> function in a C-family-only object file (e.g., ix86_target_macros in >>> i386-c.cc), provide an x86 implementation directly in fortran/cpp.cc >>> that covers architecture identification and float-size macros. >>> ISA feature macros (__SSE__, __AVX__, etc.) are not included; if >>> needed, they could be factored out of i386-c.cc into a shared object. >>> >>> Remove the dead __attribute__((target(...))) block from >>> gfortran.dg/gomp/declare-variant-10.f90: it was guarded by >>> #if defined(__x86_64__) which was previously always false because >>> gfortran never defined these macros, and gfortran does not support >>> C-style __attribute__ syntax. >>> >>> Co-authored-by: Kai Tietz <[email protected]> >>> >>> PR fortran/42954 >>> >>> gcc/fortran/ChangeLog: >>> >>> * cpp.cc (gfc_builtin_define_std): New helper mirroring >>> builtin_define_std from c-family/c-cppbuiltin.cc. >>> (gfc_builtin_define_with_value): New helper mirroring >>> builtin_define_with_value from c-family/c-cppbuiltin.cc. >>> (gfc_define_ix86_target_macros): New function providing x86 CPU >>> identification macros for the Fortran preprocessor. >>> (gfc_darwin_cpp_builtins): New function providing Darwin platform >>> macros. >>> (cpp_define_builtins): Remove Pandora's Box FIXME. Add wrapper >>> macros for C-family functions and variables used in target config >>> headers. Set flag_iso=1 to suppress bare-name macros. Enable >>> TARGET_OS_CPP_BUILTINS and TARGET_OBJFMT_CPP_BUILTINS. Call >>> gfc_define_ix86_target_macros on x86 targets. >> >> THIS is all wrong and causes too many issues. Please revert this. > > I haven't pushed yet, so all should be fine. > >>> >>> gcc/testsuite/ChangeLog: >>> >>> * gfortran.dg/gomp/declare-variant-10.f90: Remove dead >>> __attribute__((target)) block that is now exposed by newly >>> defined target macros. >>> * gfortran.dg/pr42954-linux.f90: New test. >>> * gfortran.dg/pr42954-x86.f90: New test. >>> >>> Signed-off-by: Christopher Albert <[email protected]> >>> --- >>> gcc/fortran/cpp.cc | 178 ++++++++++++++++-- >>> .../gfortran.dg/gomp/declare-variant-10.f90 | 3 - >>> gcc/testsuite/gfortran.dg/pr42954-linux.f90 | 24 +++ >>> gcc/testsuite/gfortran.dg/pr42954-x86.f90 | 10 + >>> 4 files changed, 194 insertions(+), 21 deletions(-) >>> create mode 100644 gcc/testsuite/gfortran.dg/pr42954-linux.f90 >>> create mode 100644 gcc/testsuite/gfortran.dg/pr42954-x86.f90 >>> >>> diff --git a/gcc/fortran/cpp.cc b/gcc/fortran/cpp.cc >>> index 6b5f136e4f3..ada1bc1a211 100644 >>> --- a/gcc/fortran/cpp.cc >>> +++ b/gcc/fortran/cpp.cc >>> @@ -157,6 +157,126 @@ void pp_dir_change (cpp_reader *, const char *); >>> static int dump_macro (cpp_reader *, cpp_hashnode *, void *); >>> static void dump_queued_macros (cpp_reader *); >>> >>> +/* Fortran-local helpers that mirror builtin_define_std, >>> + builtin_define_with_value, and builtin_define_with_int_value from >>> + c-family/c-cppbuiltin.cc. Those functions use the C-family-only >>> + globals parse_in and flag_iso, so they cannot be called directly >>> + from the Fortran frontend. */ >>> + >>> +/* Given "unix", define __unix, __unix__, and (if DEFINE_USER) unix. */ >>> + >>> +static void >>> +gfc_builtin_define_std (cpp_reader *pfile, const char *macro, >>> + bool define_user) >>> +{ >>> + size_t len = strlen (macro); >>> + char *buff = (char *) alloca (len + 5); >>> + char *p = buff + 2; >>> + char *q = p + len; >>> + >>> + memcpy (p, macro, len + 1); >>> + if (!(*p == '_' && (p[1] == '_' || ISUPPER (p[1])))) >>> + { >>> + if (*p != '_') >>> + *--p = '_'; >>> + if (p[1] != '_') >>> + *--p = '_'; >>> + } >>> + cpp_define (pfile, p); >>> + >>> + if (p != buff + 2) >>> + { >>> + if (q[-1] != '_') >>> + *q++ = '_'; >>> + if (q[-2] != '_') >>> + *q++ = '_'; >>> + *q = '\0'; >>> + cpp_define (pfile, p); >>> + if (define_user) >>> + cpp_define (pfile, macro); >>> + } >>> +} >>> + >>> +/* Define MACRO to EXPANSION; if IS_STR, quote the expansion. */ >>> + >>> +static void >>> +gfc_builtin_define_with_value (cpp_reader *pfile, const char *macro, >>> + const char *expansion, int is_str) >>> +{ >>> + size_t mlen = strlen (macro); >>> + size_t elen = strlen (expansion); >>> + char *buf = (char *) alloca (mlen + elen + 4); >>> + if (is_str) >>> + sprintf (buf, "%s=\"%s\"", macro, expansion); >>> + else >>> + sprintf (buf, "%s=%s", macro, expansion); >>> + cpp_define (pfile, buf); >>> +} >>> + >>> +/* Provide x86 CPU identification macros for the Fortran preprocessor. >>> + TARGET_CPU_CPP_BUILTINS() cannot be called directly because it expands >>> + to ix86_target_macros() in i386-c.cc, which is only linked into >>> + C-family frontends. This covers architecture identification and >>> + float-size macros. ISA feature macros (__SSE__, __AVX__, etc.) and >>> + arch/tune macros (__znver4__, __skylake__, etc.) from >>> + ix86_target_macros_internal() are not included; if needed, they could >>> + be factored out of i386-c.cc into a shared object. */ >>> + >>> +#ifdef TARGET_80387 >> >> Please DON'T add target defines directly to the front-end. >> Please instead use a config file from the target instead. Like what is >> done for d, rust, etc. front-ends. >> Each target should have their a source file which does the cpp_ >> instead of inlining it in the fortran front-end. >> >> Thanks, >> Andrea > > Alright, back to Chris... > > Thanks for stepping in quickly! > > Harald > >>> +static void >>> +gfc_define_ix86_target_macros (cpp_reader *pfile) >>> +{ >>> + if (TARGET_64BIT) >>> + { >>> + cpp_assert (pfile, "cpu=x86_64"); >>> + cpp_assert (pfile, "machine=x86_64"); >>> + cpp_define (pfile, "__amd64"); >>> + cpp_define (pfile, "__amd64__"); >>> + cpp_define (pfile, "__x86_64"); >>> + cpp_define (pfile, "__x86_64__"); >>> + if (TARGET_X32) >>> + { >>> + cpp_define (pfile, "_ILP32"); >>> + cpp_define (pfile, "__ILP32__"); >>> + } >>> + } >>> + else >>> + { >>> + cpp_assert (pfile, "cpu=i386"); >>> + cpp_assert (pfile, "machine=i386"); >>> + gfc_builtin_define_std (pfile, "i386", false); >>> + cpp_define (pfile, "_ILP32"); >>> + cpp_define (pfile, "__ILP32__"); >>> + } >>> + >>> + if (!TARGET_80387) >>> + cpp_define (pfile, "_SOFT_FLOAT"); >>> + >>> + if (TARGET_LONG_DOUBLE_64) >>> + cpp_define (pfile, "__LONG_DOUBLE_64__"); >>> + >>> + if (TARGET_LONG_DOUBLE_128) >>> + cpp_define (pfile, "__LONG_DOUBLE_128__"); >>> + >>> + cpp_define_formatted (pfile, "__SIZEOF_FLOAT80__=%d", >>> + GET_MODE_SIZE (XFmode)); >>> + cpp_define (pfile, "__SIZEOF_FLOAT128__=16"); >>> +} >>> +#endif >>> + >>> +/* Provide essential Darwin platform macros for the Fortran preprocessor. >>> + The full darwin_cpp_builtins() in darwin-c.cc also defines >>> + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ and >>> + __CONSTANT_CFSTRINGS__, but those depend on functions only linked >>> + into C-family frontends. */ >>> + >>> +static void ATTRIBUTE_UNUSED >>> +gfc_darwin_cpp_builtins (cpp_reader *pfile) >>> +{ >>> + cpp_define (pfile, "__MACH__"); >>> + cpp_define (pfile, "__APPLE__"); >>> + gfc_builtin_define_with_value (pfile, "__APPLE_CC__", "1", false); >>> +} >>> >>> static void >>> cpp_define_builtins (cpp_reader *pfile) >>> @@ -177,33 +297,55 @@ cpp_define_builtins (cpp_reader *pfile) >>> if (flag_openmp) >>> cpp_define (pfile, "_OPENMP=202111"); >>> >>> - /* The defines below are necessary for the TARGET_* macros. >>> - >>> - FIXME: Note that builtin_define_std() actually is a function >>> - in c-cppbuiltin.cc which uses flags undefined for Fortran. >>> - Let's skip this for now. If needed, one needs to look into it >>> - once more. */ >>> + /* Wrapper macros for C-family identifiers used in target config >>> + headers. These allow TARGET_OS_CPP_BUILTINS and >>> + TARGET_OBJFMT_CPP_BUILTINS to compile in the Fortran frontend. */ >>> >>> # define builtin_define(TXT) cpp_define (pfile, TXT) >>> -# define builtin_define_std(TXT) >>> +# define builtin_define_std(TXT) gfc_builtin_define_std (pfile, TXT, >>> !flag_iso) >>> +# define builtin_define_with_value(MACRO, EXPANSION, IS_STR) \ >>> + gfc_builtin_define_with_value (pfile, MACRO, EXPANSION, IS_STR) >>> +# define builtin_define_with_int_value(MACRO, VALUE) \ >>> + cpp_define_formatted (pfile, "%s=" HOST_WIDE_INT_PRINT_DEC, \ >>> + MACRO, (HOST_WIDE_INT) (VALUE)) >>> # define builtin_assert(TXT) cpp_assert (pfile, TXT) >>> +# define c_dialect_cxx() 0 >>> +# define c_dialect_objc() 0 >>> +# define preprocessing_asm_p() 0 >>> +# define preprocessing_trad_p() 0 >>> + /* Fortran has no -std=cNN flag to control this. Set to 1 (ISO mode) >>> + so that builtin_define_std() only defines reserved-namespace macros >>> + like __unix__ and __linux__, not bare "unix" or "linux" which are >>> + valid Fortran identifiers and would cause silent replacement. */ >>> +# define flag_iso 1 >>> +# define flag_isoc94 0 >>> +# define flag_isoc99 0 >>> +# define flag_isoc11 0 >>> +# define flag_isoc23 0 >>> +# define darwin_cpp_builtins(PFILE) gfc_darwin_cpp_builtins (PFILE) >>> >>> - /* FIXME: Pandora's Box >>> - Using the macros below results in multiple breakages: >>> - - mingw will fail to compile this file as dependent macros >>> - assume to be used in c-cppbuiltin.cc only. Further, they use >>> - flags only valid/defined in C (same as noted above). >>> - [config/i386/mingw32.h, config/i386/cygming.h] >>> - - other platforms (not as popular) break similarly >>> - [grep for 'builtin_define_with_int_value' in gcc/config/] >>> - >>> - TARGET_CPU_CPP_BUILTINS (); >>> TARGET_OS_CPP_BUILTINS (); >>> - TARGET_OBJFMT_CPP_BUILTINS (); */ >>> + TARGET_OBJFMT_CPP_BUILTINS (); >>> + >>> +#ifdef TARGET_80387 >>> + gfc_define_ix86_target_macros (pfile); >>> +#endif >>> >>> #undef builtin_define >>> #undef builtin_define_std >>> +#undef builtin_define_with_value >>> +#undef builtin_define_with_int_value >>> #undef builtin_assert >>> +#undef c_dialect_cxx >>> +#undef c_dialect_objc >>> +#undef preprocessing_asm_p >>> +#undef preprocessing_trad_p >>> +#undef flag_iso >>> +#undef flag_isoc94 >>> +#undef flag_isoc99 >>> +#undef flag_isoc11 >>> +#undef flag_isoc23 >>> +#undef darwin_cpp_builtins >>> } >>> >>> bool >>> diff --git a/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 >>> b/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 >>> index 0e0ab518010..115195e1194 100644 >>> --- a/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 >>> +++ b/gcc/testsuite/gfortran.dg/gomp/declare-variant-10.f90 >>> @@ -64,9 +64,6 @@ contains >>> call f18 () ! { dg-final { scan-tree-dump-times "f18 >>> \\\(\\\);" 1 "gimple" } } */ >>> end subroutine >>> >>> -#if defined(__i386__) || defined(__x86_64__) >>> - __attribute__((target ("avx512f,avx512bw"))) >>> -#endif >>> subroutine test2 () >>> !$omp target >>> call f04 () ! { dg-final { scan-tree-dump-times "f03 \\\(\\\);" 1 >>> "gimple" { target { { i?86-*-* x86_64-*-* } && { ! ilp32 } } } } } >>> diff --git a/gcc/testsuite/gfortran.dg/pr42954-linux.f90 >>> b/gcc/testsuite/gfortran.dg/pr42954-linux.f90 >>> new file mode 100644 >>> index 00000000000..bd5efe7a237 >>> --- /dev/null >>> +++ b/gcc/testsuite/gfortran.dg/pr42954-linux.f90 >>> @@ -0,0 +1,24 @@ >>> +! { dg-do preprocess { target *-*-linux* } } >>> +! { dg-options "-cpp" } >>> +! >>> +! PR fortran/42954 - target macros missing in gfortran -cpp >>> + >>> +#ifndef __linux__ >>> +# error __linux__ not defined >>> +#endif >>> + >>> +#ifndef __linux >>> +# error __linux not defined >>> +#endif >>> + >>> +#ifndef __unix__ >>> +# error __unix__ not defined >>> +#endif >>> + >>> +#ifndef __unix >>> +# error __unix not defined >>> +#endif >>> + >>> +#ifndef __ELF__ >>> +# error __ELF__ not defined >>> +#endif >>> diff --git a/gcc/testsuite/gfortran.dg/pr42954-x86.f90 >>> b/gcc/testsuite/gfortran.dg/pr42954-x86.f90 >>> new file mode 100644 >>> index 00000000000..0a3b7eac8a2 >>> --- /dev/null >>> +++ b/gcc/testsuite/gfortran.dg/pr42954-x86.f90 >>> @@ -0,0 +1,10 @@ >>> +! { dg-do preprocess { target { i?86-*-* x86_64-*-* } } } >>> +! { dg-options "-cpp" } >>> +! >>> +! PR fortran/42954 - target macros missing in gfortran -cpp >>> + >>> +#if !defined(__i386__) && !defined(__i386) \ >>> + && !defined(__x86_64__) && !defined(__x86_64) \ >>> + && !defined(__amd64__) && !defined(__amd64) >>> +# error x86 target macros not defined >>> +#endif >>> -- >>> 2.53.0 >>> >>
Dear Andrea, thanks for checking this. I tried to keep the first version inside the Fortran frontend and overlooked the D/Rust frontend pattern you pointed out. I attached a smaller patch that adds a Fortran target hook and keeps the target-specific macro definitions in target config files. Could you check whether this structure looks right? If yes, I can extend it toward the fuller scope Harald asked for in the Bugzilla thread. Thanks, Chris
0001-fortran-add-target-hook-for-Fortran-preprocessor-mac.patch
Description: 0001-fortran-add-target-hook-for-Fortran-preprocessor-mac.patch
