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