https://github.com/AaronBallman updated 
https://github.com/llvm/llvm-project/pull/132097

>From 7882bfbbe7ada59de91625c5f0365cec1fbe3c5b Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Wed, 19 Mar 2025 16:50:12 -0400
Subject: [PATCH 1/2] [C23] Fix compound literals within function prototype

WG14 N2819 clarified that a compound literal within a function
prototype has a lifetime similar to that of a local variable within the
function, not a file scope variable.
---
 clang/docs/ReleaseNotes.rst          |  4 ++++
 clang/lib/Sema/SemaExpr.cpp          |  8 +++++++-
 clang/test/AST/ByteCode/literals.cpp |  6 ++----
 clang/test/C/C23/n2819.c             | 17 +++++++++--------
 clang/www/c_status.html              |  2 +-
 5 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 666bbf22acc93..768ba480a7ee7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -148,6 +148,10 @@ C23 Feature Support
   better diagnostic behavior for the ``va_start()`` macro in C23 and later.
   This also updates the definition of ``va_start()`` in ``<stdarg.h>`` to use
   the new builtin. Fixes #GH124031.
+- Implemented ``WG14 N2819 
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2819.pdf`_
+  which clarified that a compound literal used within a function prototype is
+  treated as if the compound literal were within the body rather than at file
+  scope.
 
 Non-comprehensive list of changes in this release
 -------------------------------------------------
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index a03acb5fbd273..fca3a2e8c19af 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7141,7 +7141,13 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, 
TypeSourceInfo *TInfo,
     return ExprError();
   LiteralExpr = Result.get();
 
-  bool isFileScope = !CurContext->isFunctionOrMethod();
+  // We treat the compound literal as being at file scope if it's not in a
+  // function or method body, or within the function's prototype scope. This
+  // means the following compound literal is not at file scope:
+  //   void func(char *para[(int [1]){ 0 }[0]);
+  const Scope *S = getCurScope();
+  bool isFileScope = !CurContext->isFunctionOrMethod() &&
+                     (!S || !S->isFunctionPrototypeScope());
 
   // In C, compound literals are l-values for some reason.
   // For GCC compatibility, in C++, file-scope array compound literals with
diff --git a/clang/test/AST/ByteCode/literals.cpp 
b/clang/test/AST/ByteCode/literals.cpp
index f206f020ecb47..a9b787892eff2 100644
--- a/clang/test/AST/ByteCode/literals.cpp
+++ b/clang/test/AST/ByteCode/literals.cpp
@@ -849,13 +849,11 @@ namespace CompoundLiterals {
   }
   static_assert(get5() == 5, "");
 
-  constexpr int get6(int f = (int[]){1,2,6}[2]) { // ref-note {{subexpression 
not valid in a constant expression}} \
-                                                  // ref-note {{declared here}}
+  constexpr int get6(int f = (int[]){1,2,6}[2]) {
     return f;
   }
   static_assert(get6(6) == 6, "");
-  // FIXME: Who's right here?
-  static_assert(get6() == 6, ""); // ref-error {{not an integral constant 
expression}}
+  static_assert(get6() == 6, "");
 
   constexpr int x = (int){3};
   static_assert(x == 3, "");
diff --git a/clang/test/C/C23/n2819.c b/clang/test/C/C23/n2819.c
index c428fbba80245..eb0f64a69f375 100644
--- a/clang/test/C/C23/n2819.c
+++ b/clang/test/C/C23/n2819.c
@@ -1,4 +1,4 @@
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 3
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 
UTC_ARGS: --version 5
 // RUN: %clang_cc1 -triple=x86_64 -emit-llvm -o - -std=c23 %s | FileCheck %s
 
 /* WG14 N2819: No
@@ -6,9 +6,10 @@
  */
 
 int *escaped;
+
 // CHECK-LABEL: define dso_local i32 @f(
 // CHECK-SAME: ptr noundef [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
-// CHECK-NEXT:  entry:
+// CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[PTR_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[PTR]], ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
@@ -19,23 +20,23 @@ int f(int *ptr) { escaped = ptr; return 1; }
 
 // CHECK-LABEL: define dso_local i32 @g(
 // CHECK-SAME: ptr noundef [[PARA:%.*]]) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
+// CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[PARA_ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT:    [[DOTCOMPOUNDLITERAL:%.*]] = alloca [27 x i32], align 4
 // CHECK-NEXT:    store ptr [[PARA]], ptr [[PARA_ADDR]], align 8
-// CHECK-NEXT:    [[CALL:%.*]] = call i32 @f(ptr noundef @.compoundliteral)
+// CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 4 
[[DOTCOMPOUNDLITERAL]], i8 0, i64 108, i1 false)
+// CHECK-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [27 x i32], ptr 
[[DOTCOMPOUNDLITERAL]], i64 0, i64 0
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @f(ptr noundef [[ARRAYDECAY]])
 // CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[CALL]] to i64
 // CHECK-NEXT:    ret i32 0
 //
-// FIXME: notice the we are using the global .compoundliteral object, not
-// allocating a new object on each call to g(). That's what was clarified by
-// N2819.
 int g(char *para [f(( int [27]) { 0 })]) {
   return 0;
 }
 
 // CHECK-LABEL: define dso_local i32 @main(
 // CHECK-SAME: ) #[[ATTR0]] {
-// CHECK-NEXT:  entry:
+// CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[RETVAL:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    store i32 0, ptr [[RETVAL]], align 4
 // CHECK-NEXT:    [[CALL:%.*]] = call i32 @g(ptr noundef null)
diff --git a/clang/www/c_status.html b/clang/www/c_status.html
index 7cf50bfdb6639..c9e2eda4304f3 100644
--- a/clang/www/c_status.html
+++ b/clang/www/c_status.html
@@ -715,7 +715,7 @@ <h2 id="c2x">C23 implementation status</h2>
     <tr>
       <td>Disambiguate the storage class of some compound literals</td>
       <td><a 
href="https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2819.pdf";>N2819</a></td>
-      <td class="none" align="center">No</td>
+      <td class="unreleased" align="center">Clang 21</td>
     </tr>
     <tr>
       <td>Add annotations for unreachable control flow v2</td>

>From 68a7a74819d0f2ef97270782988faee460a30553 Mon Sep 17 00:00:00 2001
From: Aaron Ballman <aa...@aaronballman.com>
Date: Wed, 19 Mar 2025 17:04:11 -0400
Subject: [PATCH 2/2] Fix broken RST

---
 clang/docs/ReleaseNotes.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 768ba480a7ee7..49b266ae8a5c5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -148,7 +148,7 @@ C23 Feature Support
   better diagnostic behavior for the ``va_start()`` macro in C23 and later.
   This also updates the definition of ``va_start()`` in ``<stdarg.h>`` to use
   the new builtin. Fixes #GH124031.
-- Implemented ``WG14 N2819 
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2819.pdf`_
+- Implemented ``WG14 N2819 
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2819.pdf>`_
   which clarified that a compound literal used within a function prototype is
   treated as if the compound literal were within the body rather than at file
   scope.

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to