https://gcc.gnu.org/g:cdd015c4ddbb1ae71eea1e44654cee5ca29a6c64

commit r16-3223-gcdd015c4ddbb1ae71eea1e44654cee5ca29a6c64
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Aug 15 22:31:27 2025 +0200

    c++: Warn on #undef/#define of remaining cpp.predefined macros [PR120778]
    
    We already warn on #undef or pedwarn on #define (but not on #define
    after #undef) of some builtin macros mentioned in cpp.predefined.
    
    The C++26 P2843R3 paper changes it from (compile time) undefined behavior
    to ill-formed.  The following patch arranges for warning (for #undef)
    and pedwarn (on #define) for the remaining cpp.predefined macros.
    __cpp_* feature test macros only for C++20 which added some of them
    to cpp.predefined, in earlier C++ versions it was just an extension and
    for pedantic diagnostic I think we don't need to diagnose anything,
    __STDCPP_* and __cplusplus macros for all C++ versions where they appeared.
    
    Like the earlier posted -Wkeyword-macro diagnostics (which is done
    regardless whether the identifier is defined as a macro or not, obviously
    most likely none of the keywords are defined as macros initially), this
    one also warns on #undef when a macro isn't defined or later #define
    after #undef.
    
    2025-08-15  Jakub Jelinek  <ja...@redhat.com>
    
            PR preprocessor/120778
            PR target/121520
    gcc/c-family/
            * c-cppbuiltin.cc (c_cpp_builtins): Implement C++26 DR 2581.  Add
            cpp_define_warn lambda and use it as well as cpp_warn where needed.
            In the if (c_dialect_cxx ()) block with __cpp_* predefinitions add
            cpp_define lambda.  Formatting fixes.
    gcc/c/
            * c-decl.cc (c_init_decl_processing): Use cpp_warn instead of
            cpp_lookup and NODE_WARN bit setting.
    gcc/cp/
            * lex.cc (cxx_init): Remove warn_on lambda.  Use cpp_warn instead of
            cpp_lookup and NODE_WARN bit setting or warn_on.
    gcc/testsuite/
            * g++.dg/DRs/dr2581-1.C: New test.
            * g++.dg/DRs/dr2581-2.C: New test.
            * c-c++-common/cpp/pr92296-2.c: Expect warnings also on defining
            special macros after undefining them.
    libcpp/
            * include/cpplib.h (struct cpp_options): Add
            suppress_builtin_macro_warnings member.
            (cpp_warn): New inline functions.
            * init.cc (cpp_create_reader): Clear 
suppress_builtin_macro_warnings.
            (cpp_init_builtins): Call cpp_warn on __cplusplus, __STDC__,
            __STDC_VERSION__, __STDC_MB_MIGHT_NEQ_WC__ and
            __STDCPP_STRICT_POINTER_SAFETY__ when appropriate.
            * directives.cc (do_undef): Warn on undefining NODE_WARN macros if
            not cpp_keyword_p.  Don't emit any NODE_WARN related diagnostics
            if CPP_OPTION (pfile, suppress_builtin_macro_warnings).
            (cpp_define, _cpp_define_builtin, cpp_undef): Temporarily set
            CPP_OPTION (pfile, suppress_builtin_macro_warnings) around
            run_directive calls.
            * macro.cc (_cpp_create_definition): Warn on defining NODE_WARN
            macros if they weren't previously defined and not cpp_keyword_p.
            Ignore NODE_WARN for diagnostics if
            CPP_OPTION (pfile, suppress_builtin_macro_warnings).

Diff:
---
 gcc/c-family/c-cppbuiltin.cc               |  70 ++++++++++++++++---
 gcc/c/c-decl.cc                            |   5 +-
 gcc/cp/lex.cc                              |  41 +++++------
 gcc/testsuite/c-c++-common/cpp/pr92296-2.c |  12 ++--
 gcc/testsuite/g++.dg/DRs/dr2581-1.C        | 106 +++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/DRs/dr2581-2.C        | 106 +++++++++++++++++++++++++++++
 libcpp/directives.cc                       |  18 ++++-
 libcpp/include/cpplib.h                    |  19 ++++++
 libcpp/init.cc                             |  11 +++
 libcpp/macro.cc                            |  16 ++++-
 10 files changed, 357 insertions(+), 47 deletions(-)

diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 0ba6151245a0..fe80e1f80fff 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -913,23 +913,42 @@ c_cpp_builtins (cpp_reader *pfile)
 
   /* encoding definitions used by users and libraries  */
   builtin_define_with_value ("__GNUC_EXECUTION_CHARSET_NAME",
-    cpp_get_narrow_charset_name (pfile), 1);
+                            cpp_get_narrow_charset_name (pfile), 1);
   builtin_define_with_value ("__GNUC_WIDE_EXECUTION_CHARSET_NAME",
-    cpp_get_wide_charset_name (pfile), 1);
-
+                            cpp_get_wide_charset_name (pfile), 1);
 
   if (c_dialect_cxx ())
-  {
-    int major;
-    parse_basever (&major, NULL, NULL);
-    cpp_define_formatted (pfile, "__GNUG__=%d", major);
-  }
+    {
+      int major;
+      parse_basever (&major, NULL, NULL);
+      cpp_define_formatted (pfile, "__GNUG__=%d", major);
+    }
 
   /* For stddef.h.  They require macros defined in c-common.cc.  */
   c_stddef_cpp_builtins ();
 
+  /* Variant of cpp_define which arranges for diagnostics on user #define
+     or #undef of the macros.  */
+  auto cpp_define_warn = [] (cpp_reader *pfile, const char *def)
+    {
+      const char *end = strchr (def, '=');
+      cpp_define (pfile, def);
+      cpp_warn (pfile, def, end ? end - def : strlen (def));
+    };
+
   if (c_dialect_cxx ())
     {
+      /* Treat all cpp_define calls in this block for macros starting
+        with __cpp_ (for C++20 and later) or __STDCPP_ as cpp_define_warn.  */
+      auto cpp_define = [=] (cpp_reader *pfile, const char *def)
+       {
+         if ((cxx_dialect >= cxx20 && startswith (def, "__cpp_"))
+             || startswith (def, "__STDCPP_"))
+           cpp_define_warn (pfile, def);
+         else
+           ::cpp_define (pfile, def);
+       };
+
       if (flag_weak && SUPPORTS_ONE_ONLY)
        cpp_define (pfile, "__GXX_WEAK__=1");
       else
@@ -1101,42 +1120,65 @@ c_cpp_builtins (cpp_reader *pfile)
        }
       if (flag_concepts && cxx_dialect > cxx14)
        cpp_define (pfile, "__cpp_concepts=202002L");
+      else if (cxx_dialect >= cxx20)
+       cpp_warn (pfile, "__cpp_concepts");
       if (flag_contracts)
        {
          cpp_define (pfile, "__cpp_contracts=201906L");
          cpp_define (pfile, "__cpp_contracts_literal_semantics=201906L");
          cpp_define (pfile, "__cpp_contracts_roles=201906L");
        }
+      else if (cxx_dialect >= cxx26)
+       cpp_warn (pfile, "__cpp_contracts");
       if (flag_modules)
        /* The std-defined value is 201907L, but I don't think we can
           claim victory yet.  201810 is the p1103 date. */
        cpp_define (pfile, "__cpp_modules=201810L");
+      else if (cxx_dialect >= cxx20)
+       cpp_warn (pfile, "__cpp_modules");
       if (flag_coroutines)
        cpp_define (pfile, "__cpp_impl_coroutine=201902L"); /* n4861, DIS */
+      else if (cxx_dialect >= cxx20)
+       cpp_warn (pfile, "__cpp_impl_coroutine");
       if (flag_tm)
        /* Use a value smaller than the 201505 specified in
           the TS, since we don't yet support atomic_cancel.  */
        cpp_define (pfile, "__cpp_transactional_memory=201500L");
       if (flag_sized_deallocation)
        cpp_define (pfile, "__cpp_sized_deallocation=201309L");
+      else if (cxx_dialect >= cxx20)
+       cpp_warn (pfile, "__cpp_sized_deallocation");
       if (aligned_new_threshold)
        {
          cpp_define (pfile, "__cpp_aligned_new=201606L");
          cpp_define_formatted (pfile, "__STDCPP_DEFAULT_NEW_ALIGNMENT__=%d",
                                aligned_new_threshold);
        }
+      else if (cxx_dialect >= cxx20)
+       cpp_warn (pfile, "__cpp_aligned_new");
+      if (cxx_dialect >= cxx17)
+       cpp_warn (pfile, "__STDCPP_DEFAULT_NEW_ALIGNMENT__");
       if (flag_new_ttp)
        cpp_define (pfile, "__cpp_template_template_args=201611L");
+      else if (cxx_dialect >= cxx20)
+       cpp_warn (pfile, "__cpp_template_template_args");
       if (flag_threadsafe_statics)
        cpp_define (pfile, "__cpp_threadsafe_static_init=200806L");
+      else if (cxx_dialect >= cxx20)
+       cpp_warn (pfile, "__cpp_threadsafe_static_init");
       if (flag_char8_t)
        cpp_define (pfile, "__cpp_char8_t=202207L");
+      else if (cxx_dialect >= cxx20)
+       cpp_warn (pfile, "__cpp_char8_t");
 #ifndef THREAD_MODEL_SPEC
       /* Targets that define THREAD_MODEL_SPEC need to define
         __STDCPP_THREADS__ in their config/XXX/XXX-c.c themselves.  */
       if (cxx_dialect >= cxx11 && strcmp (thread_model, "single") != 0)
        cpp_define (pfile, "__STDCPP_THREADS__=1");
+      else
 #endif
+       if (cxx_dialect >= cxx11)
+         cpp_warn (pfile, "__STDCPP_THREADS__");
       if (flag_implicit_constexpr)
        cpp_define (pfile, "__cpp_implicit_constexpr=20211111L");
     }
@@ -1293,7 +1335,13 @@ c_cpp_builtins (cpp_reader *pfile)
        {
          char name[sizeof ("__STDCPP_FLOAT128_T__=1")];
          sprintf (name, "__STDCPP_FLOAT%d_T__=1", floatn_nx_types[i].n);
-         cpp_define (pfile, name);
+         cpp_define_warn (pfile, name);
+       }
+      else if (cxx_dialect >= cxx23)
+       {
+         char name[sizeof ("__STDCPP_FLOAT128_T__")];
+         sprintf (name, "__STDCPP_FLOAT%d_T__", floatn_nx_types[i].n);
+         cpp_warn (pfile, name);
        }
       char prefix[20], csuffix[20];
       sprintf (prefix, "FLT%d%s", floatn_nx_types[i].n,
@@ -1306,10 +1354,12 @@ c_cpp_builtins (cpp_reader *pfile)
   if (bfloat16_type_node)
     {
       if (c_dialect_cxx () && cxx_dialect > cxx20)
-       cpp_define (pfile, "__STDCPP_BFLOAT16_T__=1");
+       cpp_define_warn (pfile, "__STDCPP_BFLOAT16_T__=1");
       builtin_define_float_constants ("BFLT16", "BF16", "%s",
                                      "BF16", bfloat16_type_node);
     }
+  else if (cxx_dialect >= cxx23)
+    cpp_warn (pfile, "__STDCPP_BFLOAT16_T__");
 
   /* For float.h.  */
   if (targetm.decimal_float_supported_p ())
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 97b8021537e6..77006cacdb7e 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -4843,9 +4843,8 @@ c_init_decl_processing (void)
            tree id = get_identifier (c_common_reswords[i].word);
            if (C_IS_RESERVED_WORD (id)
                && C_RID_CODE (id) != RID_CXX_COMPAT_WARN)
-             cpp_lookup (parse_in,
-                         (const unsigned char *) IDENTIFIER_POINTER (id),
-                         IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+             cpp_warn (parse_in, IDENTIFIER_POINTER (id),
+                       IDENTIFIER_LENGTH (id));
          }
     }
 }
diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc
index fa377e7783b4..da86989a41d2 100644
--- a/gcc/cp/lex.cc
+++ b/gcc/cp/lex.cc
@@ -384,47 +384,42 @@ cxx_init (void)
            if (IDENTIFIER_KEYWORD_P (id)
                /* Don't register keywords with spaces.  */
                && IDENTIFIER_POINTER (id)[IDENTIFIER_LENGTH (id) - 1] != ' ')
-             cpp_lookup (parse_in,
-                         (const unsigned char *) IDENTIFIER_POINTER (id),
-                         IDENTIFIER_LENGTH (id))->flags |= NODE_WARN;
+             cpp_warn (parse_in, IDENTIFIER_POINTER (id),
+                       IDENTIFIER_LENGTH (id));
          }
-      auto warn_on = [] (const char *name) {
-       cpp_lookup (parse_in, (const unsigned char *) name,
-                   strlen (name))->flags |= NODE_WARN;
-      };
       if (cxx_dialect >= cxx11)
        {
-         warn_on ("final");
-         warn_on ("override");
-         warn_on ("noreturn");
+         cpp_warn (parse_in, "final");
+         cpp_warn (parse_in, "override");
+         cpp_warn (parse_in, "noreturn");
          if (cxx_dialect < cxx26)
-           warn_on ("carries_dependency");
+           cpp_warn (parse_in, "carries_dependency");
        }
       if (cxx_dialect >= cxx14)
-       warn_on ("deprecated");
+       cpp_warn (parse_in, "deprecated");
       if (cxx_dialect >= cxx17)
        {
-         warn_on ("fallthrough");
-         warn_on ("maybe_unused");
-         warn_on ("nodiscard");
+         cpp_warn (parse_in, "fallthrough");
+         cpp_warn (parse_in, "maybe_unused");
+         cpp_warn (parse_in, "nodiscard");
        }
       if (cxx_dialect >= cxx20)
        {
-         warn_on ("likely");
-         warn_on ("unlikely");
-         warn_on ("no_unique_address");
+         cpp_warn (parse_in, "likely");
+         cpp_warn (parse_in, "unlikely");
+         cpp_warn (parse_in, "no_unique_address");
        }
       if (flag_modules)
        {
-         warn_on ("import");
-         warn_on ("module");
+         cpp_warn (parse_in, "import");
+         cpp_warn (parse_in, "module");
        }
       if (cxx_dialect >= cxx23)
-       warn_on ("assume");
+       cpp_warn (parse_in, "assume");
       if (cxx_dialect >= cxx26)
        {
-         warn_on ("replaceable_if_eligible");
-         warn_on ("trivially_relocatable_if_eligible");
+         cpp_warn (parse_in, "replaceable_if_eligible");
+         cpp_warn (parse_in, "trivially_relocatable_if_eligible");
        }
     }
 
diff --git a/gcc/testsuite/c-c++-common/cpp/pr92296-2.c 
b/gcc/testsuite/c-c++-common/cpp/pr92296-2.c
index e3f74cd459cf..2594e47fc54b 100644
--- a/gcc/testsuite/c-c++-common/cpp/pr92296-2.c
+++ b/gcc/testsuite/c-c++-common/cpp/pr92296-2.c
@@ -39,42 +39,42 @@ filebase2 = __BASE_FILE__   /* { dg-final { scan-file-not 
pr92296-2.i "filebase2 =
 
 #pragma push_macro("__LINE__")
 #undef __LINE__                /* { dg-warning "undefining" } */
-#define __LINE__ 142
+#define __LINE__ 142   /* { dg-warning "defined" } */
 line1 = __LINE__       /* { dg-final { scan-file pr92296-2.i "line1 = 142" } } 
*/
 #pragma pop_macro("__LINE__")
 line2 = __LINE__       /* { dg-final { scan-file pr92296-2.i "line2 = 45" } } 
*/
 
 #pragma push_macro("__INCLUDE_LEVEL__")
 #undef __INCLUDE_LEVEL__       /* { dg-warning "undefining" } */
-#define __INCLUDE_LEVEL__ 42
+#define __INCLUDE_LEVEL__ 42   /* { dg-warning "defined" } */
 includelevel1 = __INCLUDE_LEVEL__      /* { dg-final { scan-file pr92296-2.i 
"includelevel1 = 42" } } */
 #pragma pop_macro("__INCLUDE_LEVEL__")
 includelevel2 = __INCLUDE_LEVEL__      /* { dg-final { scan-file pr92296-2.i 
"includelevel2 = 0" } } */
 
 #pragma push_macro("__COUNTER__")
 #undef __COUNTER__     /* { dg-warning "undefining" } */
-#define __COUNTER__ 172
+#define __COUNTER__ 172        /* { dg-warning "defined" } */
 counter1 = __COUNTER__ /* { dg-final { scan-file pr92296-2.i "counter1 = 172" 
} } */
 #pragma pop_macro("__COUNTER__")
 counter2 = __COUNTER__ /* { dg-final { scan-file-not pr92296-2.i "counter2 = 
172" } } */
 
 #pragma push_macro("__has_attribute")
 #undef __has_attribute /* { dg-warning "undefining" } */
-#define __has_attribute(x) 0
+#define __has_attribute(x) 0   /* { dg-warning "defined" } */
 hasattr1 = __has_attribute(noreturn)   /* { dg-final { scan-file pr92296-2.i 
"hasattr1 = 0" } } */
 #pragma pop_macro("__has_attribute")
 hasattr2 = __has_attribute(noreturn)   /* { dg-final { scan-file-not 
pr92296-2.i "hasattr2 = 0" } } */
 
 #pragma push_macro("__has_cpp_attribute")
 #undef __has_cpp_attribute     /* { dg-warning "undefining" } */
-#define __has_cpp_attribute(x) 0
+#define __has_cpp_attribute(x) 0       /* { dg-warning "defined" } */
 hasattrcpp1 = __has_cpp_attribute(noreturn)    /* { dg-final { scan-file 
pr92296-2.i "hasattrcpp1 = 0" } } */
 #pragma pop_macro("__has_cpp_attribute")
 hasattrcpp2 = __has_cpp_attribute(noreturn)    /* { dg-final { scan-file-not 
pr92296-2.i "hasattrcpp2 = 0" } } */
 
 #pragma push_macro("__has_builtin")
 #undef __has_builtin   /* { dg-warning "undefining" } */
-#define __has_builtin(x) 0
+#define __has_builtin(x) 0     /* { dg-warning "defined" } */
 hasbuiltin1 = __has_builtin(__builtin_expect)  /* { dg-final { scan-file 
pr92296-2.i "hasbuiltin1 = 0" } } */
 #pragma pop_macro("__has_builtin")
 hasbuiltin2 = __has_builtin(__builtin_expect)  /* { dg-final { scan-file 
pr92296-2.i "hasbuiltin2 = 1" } } */
diff --git a/gcc/testsuite/g++.dg/DRs/dr2581-1.C 
b/gcc/testsuite/g++.dg/DRs/dr2581-1.C
new file mode 100644
index 000000000000..56ccb606c504
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2581-1.C
@@ -0,0 +1,106 @@
+// DR 2581 - Undefined behavior for predefined macros
+// { dg-do preprocess }
+// { dg-additional-options "-fcontracts" { target c++26 } }
+// { dg-additional-options "-fmodules -fcoroutines" { target c++20 } }
+
+#undef defined                         // { dg-error "'defined' cannot be used 
as a macro name" }
+#undef __cplusplus                     // { dg-warning "undefining 
'__cplusplus'" }
+#undef __DATE__                                // { dg-warning "undefining 
'__DATE__'" }
+#undef __FILE__                                // { dg-warning "undefining 
'__FILE__'" }
+#undef __LINE__                                // { dg-warning "undefining 
'__LINE__'" }
+#undef __STDC_EMBED_NOT_FOUND__                // { dg-warning "undefining 
'__STDC_EMBED_NOT_FOUND__'" }
+#undef __STDC_EMBED_FOUND__            // { dg-warning "undefining 
'__STDC_EMBED_FOUND__'" }
+#undef __STDC_EMBED_EMPTY__            // { dg-warning "undefining 
'__STDC_EMBED_EMPTY__'" }
+#undef __STDC_HOSTED__                 // { dg-warning "undefining 
'__STDC_HOSTED__'" }
+#undef __STDCPP_DEFAULT_NEW_ALIGNMENT__        // { dg-warning "undefining 
'__STDCPP_DEFAULT_NEW_ALIGNMENT__'" "" { target c++17 } }
+#undef __STDCPP_FLOAT16_T__            // { dg-warning "undefining 
'__STDCPP_FLOAT16_T__'" "" { target c++23 } }
+#undef __STDCPP_FLOAT32_T__            // { dg-warning "undefining 
'__STDCPP_FLOAT32_T__'" "" { target c++23 } }
+#undef __STDCPP_FLOAT64_T__            // { dg-warning "undefining 
'__STDCPP_FLOAT64_T__'" "" { target c++23 } }
+#undef __STDCPP_FLOAT128_T__           // { dg-warning "undefining 
'__STDCPP_FLOAT128_T__'" "" { target c++23 } }
+#undef __STDCPP_BFLOAT16_T__           // { dg-warning "undefining 
'__STDCPP_BFLOAT16_T__'" "" { target c++23 } }
+#undef __TIME__                                // { dg-warning "undefining 
'__TIME__'" }
+#undef __STDC__                                // { dg-warning "undefining 
'__STDC__'" }
+#undef __STDC_MB_MIGHT_NEQ_WC__                // { dg-warning "undefining 
'__STDC_MB_MIGHT_NEQ_WC__'" "" { target c++11 } }
+#undef __STDC_VERSION__                        // { dg-warning "undefining 
'__STDC_VERSION__'" "" { target c++11 } }
+#undef __STDC_ISO_10646__              // { dg-warning "undefining 
'__STDC_ISO_10646__'" }
+#undef __STDCPP_THREADS__              // { dg-warning "undefining 
'__STDCPP_THREADS__'" "" { target c++11 } }
+#undef __STDCPP_STRICT_POINTER_SAFETY__        // { dg-warning "undefining 
'__STDCPP_STRICT_POINTER_SAFETY__'" "" { target { c++11 && c++20_down } } }
+#undef __cpp_aggregate_bases           // { dg-warning "undefining 
'__cpp_aggregate_bases'" "" { target c++20 } }
+#undef __cpp_aggregate_nsdmi           // { dg-warning "undefining 
'__cpp_aggregate_nsdmi'" "" { target c++20 } }
+#undef __cpp_aggregate_paren_init      // { dg-warning "undefining 
'__cpp_aggregate_paren_init'" "" { target c++20 } }
+#undef __cpp_alias_templates           // { dg-warning "undefining 
'__cpp_alias_templates'" "" { target c++20 } }
+#undef __cpp_aligned_new               // { dg-warning "undefining 
'__cpp_aligned_new'" "" { target c++20 } }
+#undef __cpp_attributes                        // { dg-warning "undefining 
'__cpp_attributes'" "" { target c++20 } }
+#undef __cpp_auto_cast                 // { dg-warning "undefining 
'__cpp_auto_cast'" "" { target c++23 } }
+#undef __cpp_binary_literals           // { dg-warning "undefining 
'__cpp_binary_literals'" "" { target c++20 } }
+#undef __cpp_capture_star_this         // { dg-warning "undefining 
'__cpp_capture_star_this'" "" { target c++20 } }
+#undef __cpp_char8_t                   // { dg-warning "undefining 
'__cpp_char8_t'" "" { target c++20 } }
+#undef __cpp_concepts                  // { dg-warning "undefining 
'__cpp_concepts'" "" { target c++20 } }
+#undef __cpp_conditional_explicit      // { dg-warning "undefining 
'__cpp_conditional_explicit'" "" { target c++20 } }
+#undef __cpp_constexpr                 // { dg-warning "undefining 
'__cpp_constexpr'" "" { target c++20 } }
+#undef __cpp_constexpr_dynamic_alloc   // { dg-warning "undefining 
'__cpp_constexpr_dynamic_alloc'" "" { target c++20 } }
+#undef __cpp_constexpr_exceptions      // { dg-warning "undefining 
'__cpp_constexpr_exceptions'" "" { target c++26 } }
+#undef __cpp_constexpr_in_decltype     // { dg-warning "undefining 
'__cpp_constexpr_in_decltype'" "" { target c++20 } }
+#undef __cpp_constexpr_virtual_inheritance // { dg-warning "undefining 
'__cpp_constexpr_virtual_inheritance'" "" { target c++26 } }
+#undef __cpp_consteval                 // { dg-warning "undefining 
'__cpp_consteval'" "" { target c++20 } }
+#undef __cpp_constinit                 // { dg-warning "undefining 
'__cpp_constinit'" "" { target c++20 } }
+#undef __cpp_contracts                 // { dg-warning "undefining 
'__cpp_contracts'" "" { target c++26 } }
+#undef __cpp_decltype                  // { dg-warning "undefining 
'__cpp_decltype'" "" { target c++20 } }
+#undef __cpp_decltype_auto             // { dg-warning "undefining 
'__cpp_decltype_auto'" "" { target c++20 } }
+#undef __cpp_deduction_guides          // { dg-warning "undefining 
'__cpp_deduction_guides'" "" { target c++20 } }
+#undef __cpp_delegating_constructors   // { dg-warning "undefining 
'__cpp_delegating_constructors'" "" { target c++20 } }
+#undef __cpp_deleted_function          // { dg-warning "undefining 
'__cpp_deleted_function'" "" { target c++26 } }
+#undef __cpp_designated_initializers   // { dg-warning "undefining 
'__cpp_designated_initializers'" "" { target c++20 } }
+#undef __cpp_enumerator_attributes     // { dg-warning "undefining 
'__cpp_enumerator_attributes'" "" { target c++20 } }
+#undef __cpp_expansion_statements      // { dg-warning "undefining 
'__cpp_expansion_statements'" "" { target c++26 } }
+#undef __cpp_explicit_this_parameter   // { dg-warning "undefining 
'__cpp_explicit_this_parameter'" "" { target c++23 } }
+#undef __cpp_fold_expressions          // { dg-warning "undefining 
'__cpp_fold_expressions'" "" { target c++20 } }
+#undef __cpp_generic_lambdas           // { dg-warning "undefining 
'__cpp_generic_lambdas'" "" { target c++20 } }
+#undef __cpp_guaranteed_copy_elision   // { dg-warning "undefining 
'__cpp_guaranteed_copy_elision'" "" { target c++20 } }
+#undef __cpp_hex_float                 // { dg-warning "undefining 
'__cpp_hex_float'" "" { target c++20 } }
+#undef __cpp_if_consteval              // { dg-warning "undefining 
'__cpp_if_consteval'" "" { target c++23 } }
+#undef __cpp_if_constexpr              // { dg-warning "undefining 
'__cpp_if_constexpr'" "" { target c++20 } }
+#undef __cpp_impl_coroutine            // { dg-warning "undefining 
'__cpp_impl_coroutine'" "" { target c++20 } }
+#undef __cpp_impl_destroying_delete    // { dg-warning "undefining 
'__cpp_impl_destroying_delete'" "" { target c++20 } }
+#undef __cpp_impl_three_way_comparison // { dg-warning "undefining 
'__cpp_impl_three_way_comparison'" "" { target c++20 } }
+#undef __cpp_impl_reflection
+#undef __cpp_implicit_move             // { dg-warning "undefining 
'__cpp_implicit_move'" "" { target c++23 } }
+#undef __cpp_inheriting_constructors   // { dg-warning "undefining 
'__cpp_inheriting_constructors'" "" { target c++20 } }
+#undef __cpp_init_captures             // { dg-warning "undefining 
'__cpp_init_captures'" "" { target c++20 } }
+#undef __cpp_initializer_lists         // { dg-warning "undefining 
'__cpp_initializer_lists'" "" { target c++20 } }
+#undef __cpp_inline_variables          // { dg-warning "undefining 
'__cpp_inline_variables'" "" { target c++20 } }
+#undef __cpp_lambdas                   // { dg-warning "undefining 
'__cpp_lambdas'" "" { target c++20 } }
+#undef __cpp_modules                   // { dg-warning "undefining 
'__cpp_modules'" "" { target c++20 } }
+#undef __cpp_multidimensional_subscript        // { dg-warning "undefining 
'__cpp_multidimensional_subscript'" "" { target c++23 } }
+#undef __cpp_named_character_escapes   // { dg-warning "undefining 
'__cpp_named_character_escapes'" "" { target c++23 } }
+#undef __cpp_namespace_attributes      // { dg-warning "undefining 
'__cpp_namespace_attributes'" "" { target c++20 } }
+#undef __cpp_noexcept_function_type    // { dg-warning "undefining 
'__cpp_noexcept_function_type'" "" { target c++20 } }
+#undef __cpp_nontype_template_args     // { dg-warning "undefining 
'__cpp_nontype_template_args'" "" { target c++20 } }
+#undef __cpp_nontype_template_parameter_auto // { dg-warning "undefining 
'__cpp_nontype_template_parameter_auto'" "" { target c++20 } }
+#undef __cpp_nsdmi                     // { dg-warning "undefining 
'__cpp_nsdmi'" "" { target c++20 } }
+#undef __cpp_pack_indexing             // { dg-warning "undefining 
'__cpp_pack_indexing'" "" { target c++26 } }
+#undef __cpp_placeholder_variables     // { dg-warning "undefining 
'__cpp_placeholder_variables'" "" { target c++26 } }
+#undef __cpp_pp_embed                  // { dg-warning "undefining 
'__cpp_pp_embed'" "" { target c++26 } }
+#undef __cpp_range_based_for           // { dg-warning "undefining 
'__cpp_range_based_for'" "" { target c++20 } }
+#undef __cpp_raw_strings               // { dg-warning "undefining 
'__cpp_raw_strings'" "" { target c++20 } }
+#undef __cpp_ref_qualifiers            // { dg-warning "undefining 
'__cpp_ref_qualifiers'" "" { target c++20 } }
+#undef __cpp_return_type_deduction     // { dg-warning "undefining 
'__cpp_return_type_deduction'" "" { target c++20 } }
+#undef __cpp_rvalue_references         // { dg-warning "undefining 
'__cpp_rvalue_references'" "" { target c++20 } }
+#undef __cpp_size_t_suffix             // { dg-warning "undefining 
'__cpp_size_t_suffix'" "" { target c++23 } }
+#undef __cpp_sized_deallocation                // { dg-warning "undefining 
'__cpp_sized_deallocation'" "" { target c++20 } }
+#undef __cpp_static_assert             // { dg-warning "undefining 
'__cpp_static_assert'" "" { target c++20 } }
+#undef __cpp_static_call_operator      // { dg-warning "undefining 
'__cpp_static_call_operator'" "" { target c++23 } }
+#undef __cpp_structured_bindings       // { dg-warning "undefining 
'__cpp_structured_bindings'" "" { target c++20 } }
+#undef __cpp_template_parameters
+#undef __cpp_template_template_args    // { dg-warning "undefining 
'__cpp_template_template_args'" "" { target c++20 } }
+#undef __cpp_threadsafe_static_init    // { dg-warning "undefining 
'__cpp_threadsafe_static_init'" "" { target c++20 } }
+#undef __cpp_trivial_relocatability    // { dg-warning "undefining 
'__cpp_trivial_relocatability'" "" { target c++26 } }
+#undef __cpp_trivial_union
+#undef __cpp_unicode_characters                // { dg-warning "undefining 
'__cpp_unicode_characters'" "" { target c++20 } }
+#undef __cpp_unicode_literals          // { dg-warning "undefining 
'__cpp_unicode_literals'" "" { target c++20 } }
+#undef __cpp_user_defined_literals     // { dg-warning "undefining 
'__cpp_user_defined_literals'" "" { target c++20 } }
+#undef __cpp_using_enum                        // { dg-warning "undefining 
'__cpp_using_enum'" "" { target c++20 } }
+#undef __cpp_variable_templates                // { dg-warning "undefining 
'__cpp_variable_templates'" "" { target c++20 } }
+#undef __cpp_variadic_friend           // { dg-warning "undefining 
'__cpp_variadic_friend'" "" { target c++26 } }
+#undef __cpp_variadic_templates                // { dg-warning "undefining 
'__cpp_variadic_templates'" "" { target c++20 } }
+#undef __cpp_variadic_using            // { dg-warning "undefining 
'__cpp_variadic_using'" "" { target c++20 } }
diff --git a/gcc/testsuite/g++.dg/DRs/dr2581-2.C 
b/gcc/testsuite/g++.dg/DRs/dr2581-2.C
new file mode 100644
index 000000000000..1ecbe1cb4b6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/DRs/dr2581-2.C
@@ -0,0 +1,106 @@
+// DR 2581 - Undefined behavior for predefined macros
+// { dg-do preprocess }
+// { dg-additional-options "-fcontracts" { target c++26 } }
+// { dg-additional-options "-fmodules -fcoroutines" { target c++20 } }
+
+#define defined defined                                // { dg-error 
"'defined' cannot be used as a macro name" }
+#define __cplusplus 202400L                    // { dg-error "'__cplusplus' 
redefined" }
+#define __DATE__                               // { dg-error "'__DATE__' 
redefined" }
+#define __FILE__                               // { dg-error "'__FILE__' 
redefined" }
+#define __LINE__                               // { dg-error "'__LINE__' 
redefined" }
+#define __STDC_EMBED_NOT_FOUND__ 0             // { dg-error 
"'__STDC_EMBED_NOT_FOUND__' redefined" }
+#define __STDC_EMBED_FOUND__ 1                 // { dg-error 
"'__STDC_EMBED_FOUND__' redefined" }
+#define __STDC_EMBED_EMPTY__ 2                 // { dg-error 
"'__STDC_EMBED_EMPTY__' redefined" }
+#define __STDC_HOSTED__        1                       // { dg-error 
"'__STDC_HOSTED__' redefined" }
+#define __STDCPP_DEFAULT_NEW_ALIGNMENT__ 1     // { dg-error 
"'__STDCPP_DEFAULT_NEW_ALIGNMENT__' redefined" "" { target c++17 } }
+#define __STDCPP_FLOAT16_T__ 1                 // { dg-message 
"'__STDCPP_FLOAT16_T__' (?:re)?defined" "" { target c++23 } } 
+#define __STDCPP_FLOAT32_T__ 1                 // { dg-message 
"'__STDCPP_FLOAT32_T__' (?:re)?defined" "" { target c++23 } } 
+#define __STDCPP_FLOAT64_T__ 1                 // { dg-message 
"'__STDCPP_FLOAT64_T__' (?:re)?defined" "" { target c++23 } } 
+#define __STDCPP_FLOAT128_T__ 1                        // { dg-message 
"'__STDCPP_FLOAT128_T__' (?:re)?defined" "" { target c++23 } } 
+#define __STDCPP_BFLOAT16_T__ 1                        // { dg-message 
"'__STDCPP_BFLOAT16_T__' (?:re)?defined" "" { target c++23 } } 
+#define __TIME__                               // { dg-error "'__TIME__' 
redefined" }
+#define __STDC__                               // { dg-error "'__STDC__' 
redefined" }
+#define __STDC_MB_MIGHT_NEQ_WC__               // { dg-warning 
"'__STDC_MB_MIGHT_NEQ_WC__' defined" "" { target c++11 } }
+#define __STDC_VERSION__                       // { dg-warning 
"'__STDC_VERSION__' defined" "" { target c++11 } }
+#define __STDC_ISO_10646__                     // { dg-error 
"'__STDC_ISO_10646__' redefined" }
+#define __STDCPP_THREADS__                     // { dg-message 
"'__STDCPP_THREADS__' (?:re)?defined" "" { target c++11 } }
+#define __STDCPP_STRICT_POINTER_SAFETY__       // { dg-warning 
"'__STDCPP_STRICT_POINTER_SAFETY__' defined" "" { target { c++11 && c++20_down 
} } }
+#define __cpp_aggregate_bases 201603L          // { dg-error 
"'__cpp_aggregate_bases' redefined" "" { target c++20 } }
+#define __cpp_aggregate_nsdmi 201304L          // { dg-error 
"'__cpp_aggregate_nsdmi' redefined" "" { target c++20 } }
+#define __cpp_aggregate_paren_init 201902L     // { dg-error 
"'__cpp_aggregate_paren_init' redefined" "" { target c++20 } }
+#define __cpp_alias_templates 200704L          // { dg-error 
"'__cpp_alias_templates' redefined" "" { target c++20 } }
+#define __cpp_aligned_new 201606L              // { dg-error 
"'__cpp_aligned_new' redefined" "" { target c++20 } }
+#define __cpp_attributes 200809L               // { dg-error 
"'__cpp_attributes' redefined" "" { target c++20 } }
+#define __cpp_auto_cast 202110L                        // { dg-error 
"'__cpp_auto_cast' redefined" "" { target c++23 } }
+#define __cpp_binary_literals 201304L          // { dg-error 
"'__cpp_binary_literals' redefined" "" { target c++20 } }
+#define __cpp_capture_star_this 201603L                // { dg-error 
"'__cpp_capture_star_this' redefined" "" { target c++20 } }
+#define __cpp_char8_t 202207L                  // { dg-error "'__cpp_char8_t' 
redefined" "" { target c++20 } }
+#define __cpp_concepts 202002L                 // { dg-error "'__cpp_concepts' 
redefined" "" { target c++20 } }
+#define __cpp_conditional_explicit 201806L     // { dg-error 
"'__cpp_conditional_explicit' redefined" "" { target c++20 } }
+#define __cpp_constexpr 202406L                        // { dg-error 
"'__cpp_constexpr' redefined" "" { target c++11 } }
+#define __cpp_constexpr_dynamic_alloc 201907L  // { dg-error 
"'__cpp_constexpr_dynamic_alloc' redefined" "" { target c++20 } }
+#define __cpp_constexpr_exceptions 202411L     // { dg-error 
"'__cpp_constexpr_exceptions' redefined" "" { target c++26 } }
+#define __cpp_constexpr_in_decltype 201711L    // { dg-error 
"'__cpp_constexpr_in_decltype' redefined" "" { target c++20 } }
+#define __cpp_constexpr_virtual_inheritance 202506L // { dg-error 
"'__cpp_constexpr_virtual_inheritance' redefined" "" { target c++26 } }
+#define __cpp_consteval 202211L                        // { dg-error 
"'__cpp_consteval' redefined" "" { target c++20 } }
+#define __cpp_constinit 201907L                        // { dg-error 
"'__cpp_constinit' redefined" "" { target c++20 } }
+#define __cpp_contracts 202502L                        // { dg-error 
"'__cpp_contracts' redefined" "" { target c++26 } }
+#define __cpp_decltype 200707L                 // { dg-error "'__cpp_decltype' 
redefined" "" { target c++20 } }
+#define __cpp_decltype_auto 201304L            // { dg-error 
"'__cpp_decltype_auto' redefined" "" { target c++20 } }
+#define __cpp_deduction_guides 201907L         // { dg-error 
"'__cpp_deduction_guides' redefined" "" { target c++17 } }
+#define __cpp_delegating_constructors 200604L  // { dg-error 
"'__cpp_delegating_constructors' redefined" "" { target c++20 } }
+#define __cpp_deleted_function 202403L         // { dg-error 
"'__cpp_deleted_function' redefined" "" { target c++26 } }
+#define __cpp_designated_initializers 201707L  // { dg-error 
"'__cpp_designated_initializers' redefined" "" { target c++20 } }
+#define __cpp_enumerator_attributes 201411L    // { dg-error 
"'__cpp_enumerator_attributes' redefined" "" { target c++20 } }
+#define __cpp_expansion_statements 202506L     // { dg-error 
"'__cpp_expansion_statements' redefined" "" { target c++26 } }
+#define __cpp_explicit_this_parameter 202110L  // { dg-error 
"'__cpp_explicit_this_parameter' redefined" "" { target c++23 } }
+#define __cpp_fold_expressions 201603L         // { dg-error 
"'__cpp_fold_expressions' redefined" "" { target c++20 } }
+#define __cpp_generic_lambdas 201707L          // { dg-error 
"'__cpp_generic_lambdas' redefined" "" { target c++14 } }
+#define __cpp_guaranteed_copy_elision 201606L  // { dg-error 
"'__cpp_guaranteed_copy_elision' redefined" "" { target c++20 } }
+#define __cpp_hex_float 201603L                        // { dg-error 
"'__cpp_hex_float' redefined" "" { target c++20 } }
+#define __cpp_if_consteval 202106L             // { dg-error 
"'__cpp_if_consteval' redefined" "" { target c++23 } }
+#define __cpp_if_constexpr 201606L             // { dg-error 
"'__cpp_if_constexpr' redefined" "" { target c++20 } }
+#define __cpp_impl_coroutine 201902L           // { dg-error 
"'__cpp_impl_coroutine' redefined" "" { target c++20 } }
+#define __cpp_impl_destroying_delete 201806L   // { dg-error 
"'__cpp_impl_destroying_delete' redefined" "" { target c++20 } }
+#define __cpp_impl_three_way_comparison 201907L        // { dg-error 
"'__cpp_impl_three_way_comparison' redefined" "" { target c++20 } }
+#define __cpp_impl_reflection 202506L
+#define __cpp_implicit_move 202207L            // { dg-error 
"'__cpp_implicit_move' redefined" "" { target c++23 } }
+#define __cpp_inheriting_constructors 201511L  // { dg-error 
"'__cpp_inheriting_constructors' redefined" "" { target c++20 } }
+#define __cpp_init_captures 201803L            // { dg-error 
"'__cpp_init_captures' redefined" "" { target c++14 } }
+#define __cpp_initializer_lists 200806L                // { dg-error 
"'__cpp_initializer_lists' redefined" "" { target c++20 } }
+#define __cpp_inline_variables 201606L         // { dg-error 
"'__cpp_inline_variables' redefined" "" { target c++20 } }
+#define __cpp_lambdas 200907L                  // { dg-error "'__cpp_lambdas' 
redefined" "" { target c++20 } }
+#define __cpp_modules 201907L                  // { dg-error "'__cpp_modules' 
redefined" "" { target c++20 } }
+#define __cpp_multidimensional_subscript 202211L // { dg-error 
"'__cpp_multidimensional_subscript' redefined" "" { target c++23 } }
+#define __cpp_named_character_escapes 202207L  // { dg-error 
"'__cpp_named_character_escapes' redefined" "" { target c++23 } }
+#define __cpp_namespace_attributes 201411L     // { dg-error 
"'__cpp_namespace_attributes' redefined" "" { target c++20 } }
+#define __cpp_noexcept_function_type 201510L   // { dg-error 
"'__cpp_noexcept_function_type' redefined" "" { target c++20 } }
+#define __cpp_nontype_template_args 201911L    // { dg-error 
"'__cpp_nontype_template_args' redefined" "" { target c++17 } }
+#define __cpp_nontype_template_parameter_auto 201606L // { dg-error 
"'__cpp_nontype_template_parameter_auto' redefined" "" { target c++20 } }
+#define __cpp_nsdmi 200809L                    // { dg-error "'__cpp_nsdmi' 
redefined" "" { target c++20 } }
+#define __cpp_pack_indexing 202311L            // { dg-error 
"'__cpp_pack_indexing' redefined" "" { target c++26 } }
+#define __cpp_placeholder_variables 202306L    // { dg-error 
"'__cpp_placeholder_variables' redefined" "" { target c++26 } }
+#define __cpp_pp_embed 202502L                 // { dg-error "'__cpp_pp_embed' 
redefined" "" { target c++26 } }
+#define __cpp_range_based_for 202211L          // { dg-error 
"'__cpp_range_based_for' redefined" "" { target c++11 } }
+#define __cpp_raw_strings 200710L              // { dg-error 
"'__cpp_raw_strings' redefined" "" { target c++20 } }
+#define __cpp_ref_qualifiers 200710L           // { dg-error 
"'__cpp_ref_qualifiers' redefined" "" { target c++20 } }
+#define __cpp_return_type_deduction 201304L    // { dg-error 
"'__cpp_return_type_deduction' redefined" "" { target c++20 } }
+#define __cpp_rvalue_references 200610L                // { dg-error 
"'__cpp_rvalue_references' redefined" "" { target c++20 } }
+#define __cpp_size_t_suffix 202011L            // { dg-error 
"'__cpp_size_t_suffix' redefined" "" { target c++23 } }
+#define __cpp_sized_deallocation 201309L       // { dg-error 
"'__cpp_sized_deallocation' redefined" "" { target c++20 } }
+#define __cpp_static_assert 202306L            // { dg-error 
"'__cpp_static_assert' redefined" "" { target c++11 } }
+#define __cpp_static_call_operator 202207L     // { dg-error 
"'__cpp_static_call_operator' redefined" "" { target c++23 } }
+#define __cpp_structured_bindings 202411L      // { dg-error 
"'__cpp_structured_bindings' redefined" "" { target c++17 } }
+#define __cpp_template_parameters 202502L
+#define __cpp_template_template_args 201611L   // { dg-error 
"'__cpp_template_template_args' redefined" "" { target c++20 } }
+#define __cpp_threadsafe_static_init 200806L   // { dg-error 
"'__cpp_threadsafe_static_init' redefined" "" { target c++20 } }
+#define __cpp_trivial_relocatability 202502L   // { dg-error 
"'__cpp_trivial_relocatability' redefined" "" { target c++26 } }
+#define __cpp_trivial_union 202502L
+#define __cpp_unicode_characters 200704L       // { dg-error 
"'__cpp_unicode_characters' redefined" "" { target c++17 } }
+#define __cpp_unicode_literals 200710L         // { dg-error 
"'__cpp_unicode_literals' redefined" "" { target c++20 } }
+#define __cpp_user_defined_literals 200809L    // { dg-error 
"'__cpp_user_defined_literals' redefined" "" { target c++20 } }
+#define __cpp_using_enum 201907L               // { dg-error 
"'__cpp_using_enum' redefined" "" { target c++20 } }
+#define __cpp_variable_templates 201304L       // { dg-error 
"'__cpp_variable_templates' redefined" "" { target c++20 } }
+#define __cpp_variadic_friend 202403L          // { dg-error 
"'__cpp_variadic_friend' redefined" "" { target c++26 } }
+#define __cpp_variadic_templates 200704L       // { dg-error 
"'__cpp_variadic_templates' redefined" "" { target c++20 } }
+#define __cpp_variadic_using 201611L           // { dg-error 
"'__cpp_variadic_using' redefined" "" { target c++20 } }
diff --git a/libcpp/directives.cc b/libcpp/directives.cc
index 47fb8fbdd131..b6dd36a88c52 100644
--- a/libcpp/directives.cc
+++ b/libcpp/directives.cc
@@ -736,7 +736,9 @@ do_undef (cpp_reader *pfile)
 
       /* Handle -Wkeyword-macro registered identifiers.  */
       bool diagnosed = false;
-      if (CPP_OPTION (pfile, cpp_warn_keyword_macro) && cpp_keyword_p (node))
+      if (CPP_OPTION (pfile, cpp_warn_keyword_macro)
+         && !CPP_OPTION (pfile, suppress_builtin_macro_warnings)
+         && cpp_keyword_p (node))
        {
          if (CPP_OPTION (pfile, cpp_pedantic)
              && CPP_OPTION (pfile, cplusplus)
@@ -752,7 +754,8 @@ do_undef (cpp_reader *pfile)
         identifier is not currently defined as a macro name.  */
       if (cpp_macro_p (node))
        {
-         if (node->flags & NODE_WARN)
+         if ((node->flags & NODE_WARN)
+             && !CPP_OPTION (pfile, suppress_builtin_macro_warnings))
            {
              if (!diagnosed)
                cpp_error (pfile, CPP_DL_WARNING,
@@ -769,6 +772,11 @@ do_undef (cpp_reader *pfile)
 
          _cpp_free_definition (node);
        }
+      else if ((node->flags & NODE_WARN)
+              && !CPP_OPTION (pfile, suppress_builtin_macro_warnings)
+              && !diagnosed
+              && !cpp_keyword_p (node))
+       cpp_error (pfile, CPP_DL_WARNING, "undefining %qs", NODE_NAME (node));
     }
 
   check_eol (pfile, false);
@@ -3087,7 +3095,9 @@ cpp_define (cpp_reader *pfile, const char *str)
     }
   buf[count] = '\n';
 
+  CPP_OPTION (pfile, suppress_builtin_macro_warnings) = 1;
   run_directive (pfile, T_DEFINE, buf, count);
+  CPP_OPTION (pfile, suppress_builtin_macro_warnings) = 0;
 }
 
 /* Like cpp_define, but does not warn about unused macro.  */
@@ -3141,7 +3151,9 @@ _cpp_define_builtin (cpp_reader *pfile, const char *str)
   char *buf = (char *) alloca (len + 1);
   memcpy (buf, str, len);
   buf[len] = '\n';
+  CPP_OPTION (pfile, suppress_builtin_macro_warnings) = 1;
   run_directive (pfile, T_DEFINE, buf, len);
+  CPP_OPTION (pfile, suppress_builtin_macro_warnings) = 0;
 }
 
 /* Process MACRO as if it appeared as the body of an #undef.  */
@@ -3152,7 +3164,9 @@ cpp_undef (cpp_reader *pfile, const char *macro)
   char *buf = (char *) alloca (len + 1);
   memcpy (buf, macro, len);
   buf[len] = '\n';
+  CPP_OPTION (pfile, suppress_builtin_macro_warnings) = 1;
   run_directive (pfile, T_UNDEF, buf, len);
+  CPP_OPTION (pfile, suppress_builtin_macro_warnings) = 0;
 }
 
 /* Replace a previous definition DEF of the macro STR.  If DEF is NULL,
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index bbd88e56f585..5190ff7d08fe 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -435,6 +435,10 @@ struct cpp_options
      Presumably the usage is protected by the appropriate #ifdef.  */
   unsigned char warn_variadic_macros;
 
+  /* Non-zero means suppress diagnostics for NODE_WARN #define or #undef.
+     Used for cpp_define/cpp_undef.  */
+  unsigned char suppress_builtin_macro_warnings;
+
   /* Nonzero means warn about builtin macros that are redefined or
      explicitly undefined.  */
   unsigned char warn_builtin_macro_redefined;
@@ -1526,6 +1530,21 @@ extern cpp_comment_table *cpp_get_comments (cpp_reader 
*);
 extern cpp_hashnode *cpp_lookup (cpp_reader *, const unsigned char *,
                                 unsigned int);
 
+/* Set NODE_WARN flag for NAME, such that there will be diagnostics
+   for #define or #undef of NAME.  */
+
+inline void
+cpp_warn (cpp_reader *pfile, const char *name, unsigned int len)
+{
+  cpp_lookup (pfile, (const unsigned char *) name, len)->flags |= NODE_WARN;
+}
+
+inline void
+cpp_warn (cpp_reader *pfile, const char *name)
+{
+  cpp_warn (pfile, name, strlen (name));
+}
+
 typedef int (*cpp_cb) (cpp_reader *, cpp_hashnode *, void *);
 extern void cpp_forall_identifiers (cpp_reader *, cpp_cb, void *);
 
diff --git a/libcpp/init.cc b/libcpp/init.cc
index e9732afeb2c6..eb495e26effc 100644
--- a/libcpp/init.cc
+++ b/libcpp/init.cc
@@ -246,6 +246,7 @@ cpp_create_reader (enum c_lang lang, cpp_hash_table *table,
   CPP_OPTION (pfile, dollars_in_ident) = 1;
   CPP_OPTION (pfile, warn_dollars) = 1;
   CPP_OPTION (pfile, warn_variadic_macros) = 1;
+  CPP_OPTION (pfile, suppress_builtin_macro_warnings) = 0;
   CPP_OPTION (pfile, warn_builtin_macro_redefined) = 1;
   CPP_OPTION (pfile, cpp_warn_implicit_fallthrough) = 0;
   CPP_OPTION (pfile, warn_header_guard) = 0;
@@ -593,6 +594,8 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
       && (! CPP_OPTION (pfile, stdc_0_in_system_headers)
          || CPP_OPTION (pfile, std)))
     _cpp_define_builtin (pfile, "__STDC__ 1");
+  else if (CPP_OPTION (pfile, cplusplus))
+    cpp_warn (pfile, "__STDC__");
 
   if (CPP_OPTION (pfile, cplusplus))
     {
@@ -618,6 +621,14 @@ cpp_init_builtins (cpp_reader *pfile, int hosted)
        _cpp_define_builtin (pfile, "__cplusplus 201103L");
       else
        _cpp_define_builtin (pfile, "__cplusplus 199711L");
+      cpp_warn (pfile, "__cplusplus");
+      if (CPP_OPTION (pfile, lang) >= CLK_GNUCXX11)
+       {
+         cpp_warn (pfile, "__STDC_VERSION__");
+         cpp_warn (pfile, "__STDC_MB_MIGHT_NEQ_WC__");
+         if (CPP_OPTION (pfile, lang) < CLK_GNUCXX23)
+           cpp_warn (pfile, "__STDCPP_STRICT_POINTER_SAFETY__");
+       }
     }
   else if (CPP_OPTION (pfile, lang) == CLK_ASM)
     _cpp_define_builtin (pfile, "__ASSEMBLER__ 1");
diff --git a/libcpp/macro.cc b/libcpp/macro.cc
index a47e1feb8207..9867098225f7 100644
--- a/libcpp/macro.cc
+++ b/libcpp/macro.cc
@@ -3412,8 +3412,11 @@ warn_of_redefinition (cpp_reader *pfile, cpp_hashnode 
*node,
   /* Some redefinitions need to be warned about regardless.  */
   if (node->flags & NODE_WARN)
     {
-      /* Ignore NODE_WARN on -Wkeyword-macro registered identifiers though.  */
-      if (!CPP_OPTION (pfile, cpp_warn_keyword_macro) || !cpp_keyword_p (node))
+      /* Ignore NODE_WARN on -Wkeyword-macro registered identifiers though
+        or during cpp_define.  */
+      if (!CPP_OPTION (pfile, suppress_builtin_macro_warnings)
+         && (!CPP_OPTION (pfile, cpp_warn_keyword_macro)
+             || !cpp_keyword_p (node)))
        return true;
     }
 
@@ -3954,7 +3957,9 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode 
*node,
     macro->line = name_loc;
 
   /* Handle -Wkeyword-macro registered identifiers.  */
-  if (CPP_OPTION (pfile, cpp_warn_keyword_macro) && cpp_keyword_p (node))
+  if (CPP_OPTION (pfile, cpp_warn_keyword_macro)
+      && !CPP_OPTION (pfile, suppress_builtin_macro_warnings)
+      && cpp_keyword_p (node))
     {
       if (macro->fun_like
          && CPP_OPTION (pfile, cplusplus)
@@ -3994,6 +3999,11 @@ _cpp_create_definition (cpp_reader *pfile, cpp_hashnode 
*node,
        }
       _cpp_free_definition (node);
     }
+  else if ((node->flags & NODE_WARN)
+          && !CPP_OPTION (pfile, suppress_builtin_macro_warnings)
+          && !cpp_keyword_p (node))
+    cpp_error_with_line (pfile, CPP_DL_WARNING, macro->line, 0,
+                        "%qs defined", NODE_NAME (node));
 
   /* Enter definition in hash table.  */
   node->type = NT_USER_MACRO;

Reply via email to