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

commit r15-7755-gb510c53b18b7255bc43de1c45b700e0206ca27f0
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Feb 28 15:17:37 2025 +0100

    c++: Adjust #embed support for P1967R14
    
    Now that the #embed paper has been voted in, the following patch
    removes the pedwarn for C++26 on it (and adjusts pedwarn warning for
    older C++ versions) and predefines __cpp_pp_embed FTM.
    
    Also, the patch changes cpp_error to cpp_pedwarning with for C++
    -Wc++26-extensions guarding, and for C add -Wc11-c23-compat warning
    about #embed.
    
    I believe we otherwise implement everything in the paper already,
    except I'm really confused by the
     [Example:
    
     #embed <data.dat> limit(__has_include("a.h"))
    
     #if __has_embed(<data.dat> limit(__has_include("a.h")))
     // ill-formed: __has_include [cpp.cond] cannot appear here
     #endif
    
     — end example]
    part.  My reading of both C23 and C++ with the P1967R14 paper in
    is that the first case (#embed with __has_include or __has_embed in its
    clauses) is what is clearly invalid and so the ill-formed note should be
    for #embed.  And the __has_include/__has_embed in __has_embed is actually
    questionable.
    Both C and C++ have something like
    "The identifiers __has_include, __has_embed, and __has_c_attribute
    shall not appear in any context not mentioned in this subclause."
    or
    "The identifiers __has_include and __has_cpp_attribute shall not appear
    in any context not mentioned in this subclause."
    (into which P1967R14 adds __has_embed) in the conditional inclusion
    subclause.  #embed is defined in a different one, so using those in there
    is invalid (unless "using the rules specified for conditional inclusion"
    wording e.g. in limit clause overrides that).
    The reason why I think it is fuzzy for __has_embed is that __has_embed
    is actually defined in the Conditional inclusion subclause (so that
    would mean one can use __has_include, __has_embed and __has_*attribute
    in there) but its clauses are described in a different one.
    
    GCC currently accepts
     #embed __FILE__ limit (__has_include (<stdarg.h>))
     #if __has_embed (__FILE__ limit (__has_include (<stdarg.h>)))
     #endif
     #embed __FILE__ limit (__has_embed (__FILE__))
     #if __has_embed (__FILE__ limit (__has_embed (__FILE__)))
     #endif
    Note, it isn't just about limit clause, but also about
    prefix/suffix/if_empty, except that in those cases the "using the rules
    specified for conditional inclusion" doesn't apply.
    
    In any case, I'd hope that can be dealt with incrementally (and should
    be handled the same for both C and C++).
    
    2025-02-28  Jakub Jelinek  <ja...@redhat.com>
    
    libcpp/
            * include/cpplib.h (enum cpp_warning_reason): Add
            CPP_W_CXX26_EXTENSIONS enumerator.
            * init.cc (lang_defaults): Set embed for GNUCXX26 and CXX26.
            * directives.cc (do_embed): Adjust pedwarn wording for embed in C++,
            use cpp_pedwarning instead of cpp_error and add CPP_W_C11_C23_COMPAT
            warning of cpp_pedwarning hasn't diagnosed anything.
    gcc/c-family/
            * c.opt (Wc++26-extensions): Add CppReason(CPP_W_CXX26_EXTENSIONS).
            * c-cppbuiltin.cc (c_cpp_builtins): Predefine __cpp_pp_embed=202502
            for C++26.
    gcc/testsuite/
            * g++.dg/cpp/embed-1.C: Adjust for pedwarn wording change and don't
            expect any error for C++26.
            * g++.dg/cpp/embed-2.C: Adjust for pedwarn wording change and don't
            expect any warning for C++26.
            * g++.dg/cpp26/feat-cxx26.C: Test __cpp_pp_embed value.
            * gcc.dg/cpp/embed-17.c: New test.

Diff:
---
 gcc/c-family/c-cppbuiltin.cc            |  1 +
 gcc/c-family/c.opt                      |  2 +-
 gcc/testsuite/g++.dg/cpp/embed-1.C      |  4 ++--
 gcc/testsuite/g++.dg/cpp/embed-2.C      |  4 ++--
 gcc/testsuite/g++.dg/cpp26/feat-cxx26.C |  6 ++++++
 gcc/testsuite/gcc.dg/cpp/embed-17.c     | 14 ++++++++++++++
 libcpp/directives.cc                    | 15 ++++++++++-----
 libcpp/include/cpplib.h                 |  1 +
 libcpp/init.cc                          |  4 ++--
 9 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 17a3d0827cfd..4589ee4a3a62 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -1093,6 +1093,7 @@ c_cpp_builtins (cpp_reader *pfile)
          cpp_define (pfile, "__cpp_deleted_function=202403L");
          cpp_define (pfile, "__cpp_variadic_friend=202403L");
          cpp_define (pfile, "__cpp_pack_indexing=202311L");
+         cpp_define (pfile, "__cpp_pp_embed=202502L");
        }
       if (flag_concepts && cxx_dialect > cxx14)
        cpp_define (pfile, "__cpp_concepts=202002L");
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 15698dc65bb2..f432203b2ebc 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -513,7 +513,7 @@ C++ ObjC++ Var(warn_cxx23_extensions) Warning Init(1) 
CppReason(CPP_W_CXX23_EXTE
 Warn about C++23 constructs in code compiled with an older standard.
 
 Wc++26-extensions
-C++ ObjC++ Var(warn_cxx26_extensions) Warning Init(1)
+C++ ObjC++ Var(warn_cxx26_extensions) Warning Init(1) 
CppReason(CPP_W_CXX26_EXTENSIONS)
 Warn about C++26 constructs in code compiled with an older standard.
 
 Wcalloc-transposed-args
diff --git a/gcc/testsuite/g++.dg/cpp/embed-1.C 
b/gcc/testsuite/g++.dg/cpp/embed-1.C
index e7e0b8327a0d..a28eb6a39405 100644
--- a/gcc/testsuite/g++.dg/cpp/embed-1.C
+++ b/gcc/testsuite/g++.dg/cpp/embed-1.C
@@ -6,9 +6,9 @@
 #endif
 
 int a =
-#embed __FILE__ limit (1) // { dg-error "'#embed' is a GCC extension" }
+#embed __FILE__ limit (1) // { dg-error "'#embed' before C\\\+\\\+26 is a GCC 
extension" "" { target c++23_down } }
 ;
 int b =
 (__extension__
-#embed __FILE__ limit (1) // { dg-error "'#embed' is a GCC extension" }
+#embed __FILE__ limit (1) // { dg-error "'#embed' before C\\\+\\\+26 is a GCC 
extension" "" { target c++23_down } }
 );
diff --git a/gcc/testsuite/g++.dg/cpp/embed-2.C 
b/gcc/testsuite/g++.dg/cpp/embed-2.C
index 6c2393f9c0d9..ddc368aa10cc 100644
--- a/gcc/testsuite/g++.dg/cpp/embed-2.C
+++ b/gcc/testsuite/g++.dg/cpp/embed-2.C
@@ -6,9 +6,9 @@
 #endif
 
 int a =
-#embed __FILE__ limit (1) // { dg-warning "'#embed' is a GCC extension" }
+#embed __FILE__ limit (1) // { dg-warning "'#embed' before C\\\+\\\+26 is a 
GCC extension" "" { target c++23_down } }
 ;
 int b =
 (__extension__
-#embed __FILE__ limit (1) // { dg-warning "'#embed' is a GCC extension" }
+#embed __FILE__ limit (1) // { dg-warning "'#embed' before C\\\+\\\+26 is a 
GCC extension" "" { target c++23_down } }
 );
diff --git a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C 
b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
index d74ff0e427bd..66e2d85ece6b 100644
--- a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
+++ b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
@@ -628,3 +628,9 @@
 #elif __cpp_pack_indexing != 202311
 #  error "__cpp_pack_indexing != 202311"
 #endif
+
+#ifndef __cpp_pp_embed
+# error "__cpp_pp_embed"
+#elif __cpp_pp_embed != 202502
+#  error "__cpp_pp_embed != 202502"
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/embed-17.c 
b/gcc/testsuite/gcc.dg/cpp/embed-17.c
new file mode 100644
index 000000000000..97bf62c14603
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/embed-17.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23 -Wc11-c23-compat" } */
+
+#if __has_embed (__FILE__ limit (1)) != 1
+#error "__has_embed failed"
+#endif
+
+int a =
+#embed __FILE__ limit (1) /* { dg-warning "'#embed' is a C23 feature" } */
+;
+int b =
+(__extension__
+#embed __FILE__ limit (1)
+);
diff --git a/libcpp/directives.cc b/libcpp/directives.cc
index 6b0d691f491a..4d06caa9b565 100644
--- a/libcpp/directives.cc
+++ b/libcpp/directives.cc
@@ -1349,7 +1349,7 @@ do_embed (cpp_reader *pfile)
 {
   int angle_brackets;
   struct cpp_embed_params params = {};
-  bool ok;
+  bool ok, warned = false;
   const char *fname = NULL;
 
   /* Tell the lexer this is an embed directive.  */
@@ -1366,12 +1366,17 @@ do_embed (cpp_reader *pfile)
   if (CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, embed))
     {
       if (CPP_OPTION (pfile, cplusplus))
-       cpp_error (pfile, CPP_DL_PEDWARN,
-                  "%<#%s%> is a GCC extension", "embed");
+       warned = cpp_pedwarning (pfile, CPP_W_CXX26_EXTENSIONS,
+                                "%<#%s%> before C++26 is a GCC extension",
+                                "embed");
       else
-       cpp_error (pfile, CPP_DL_PEDWARN,
-                  "%<#%s%> before C23 is a GCC extension", "embed");
+       warned = cpp_pedwarning (pfile, CPP_W_PEDANTIC,
+                                "%<#%s%> before C23 is a GCC extension",
+                                "embed");
     }
+  if (!warned && CPP_OPTION (pfile, cpp_warn_c11_c23_compat) > 0)
+    cpp_warning (pfile, CPP_W_C11_C23_COMPAT,
+                "%<#%s%> is a C23 feature", "embed");
 
   fname = parse_include (pfile, &angle_brackets, NULL, &params.loc);
   if (!fname)
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 90aa3160ebfb..3bf33ab48842 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -749,6 +749,7 @@ enum cpp_warning_reason {
   CPP_W_CXX17_EXTENSIONS,
   CPP_W_CXX20_EXTENSIONS,
   CPP_W_CXX23_EXTENSIONS,
+  CPP_W_CXX26_EXTENSIONS,
   CPP_W_EXPANSION_TO_DEFINED,
   CPP_W_BIDIRECTIONAL,
   CPP_W_INVALID_UTF8,
diff --git a/libcpp/init.cc b/libcpp/init.cc
index db17ea6c68fe..e9732afeb2c6 100644
--- a/libcpp/init.cc
+++ b/libcpp/init.cc
@@ -149,8 +149,8 @@ static const struct lang_flags lang_defaults[] = {
   /* CXX20    */ { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,1,0,0,1 },
   /* GNUCXX23 */ { 1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,0,0,1 },
   /* CXX23    */ { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,0,0,1 },
-  /* GNUCXX26 */ { 1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,0,0,1 },
-  /* CXX26    */ { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,0,0,1 },
+  /* GNUCXX26 */ { 1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,0,1 },
+  /* CXX26    */ { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,0,1,1,1,1,1,0,1,1,0,1 },
   /* ASM      */ { 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
 };

Reply via email to