[clang] [clang] Disallow VLA type compound literals (PR #91891)
Jim M. R. Teichgräber via cfe-commits
cfe-commits at lists.llvm.org
Mon May 13 04:34:33 PDT 2024
https://github.com/J-MR-T updated https://github.com/llvm/llvm-project/pull/91891
>From 9aab9284fc094d22e12a2ee1217a3bc99e5837b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jim=20M=2E=20R=2E=20Teichgr=C3=A4ber?=
<jimmr.teichgraeber at tum.de>
Date: Sun, 12 May 2024 13:33:37 +0200
Subject: [PATCH 1/2] [clang] Disallow VLA type compound literals C99-C23
6.5.2.5 says: The type name shall specify an object type or an array of
unknown size, but not a variable length array type Issue:
https://github.com/llvm/llvm-project/issues/89835
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 ++
clang/lib/Sema/SemaExpr.cpp | 19 +++++++++++++------
clang/test/C/C2x/n2900_n3011.c | 8 +++++++-
clang/test/C/C2x/n2900_n3011_2.c | 16 ----------------
clang/test/Sema/compound-literal.c | 15 +++++++++++++--
5 files changed, 35 insertions(+), 25 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d6863f90edb6e..008d7b2a29cd9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3371,6 +3371,8 @@ def err_field_with_address_space : Error<
"field may not be qualified with an address space">;
def err_compound_literal_with_address_space : Error<
"compound literal in function scope may not be qualified with an address space">;
+def err_compound_literal_with_vla_type : Error<
+ "compound literal has variable-length array type">;
def err_address_space_mismatch_templ_inst : Error<
"conflicting address space qualifiers are provided between types %0 and %1">;
def err_attr_objc_ownership_redundant : Error<
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c688cb21f2364..e62e3f3285e5d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7274,12 +7274,19 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
// init a VLA in C++ in all cases (such as with non-trivial constructors).
// FIXME: should we allow this construct in C++ when it makes sense to do
// so?
- std::optional<unsigned> NumInits;
- if (const auto *ILE = dyn_cast<InitListExpr>(LiteralExpr))
- NumInits = ILE->getNumInits();
- if ((LangOpts.CPlusPlus || NumInits.value_or(0)) &&
- !tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc,
- diag::err_variable_object_no_init))
+ //
+ // But: C99-C23 6.5.2.5 Compound literals constraint 1: The type name
+ // shall specify an object type or an array of unknown size, but not a
+ // variable length array type. This seems odd, as it allows int a[size] =
+ // {}; but forbids int a[size] = (int[size]){}; As this is what the
+ // standard says, this is what's implemented here for C (except for the
+ // extension that permits constant foldable size arrays)
+
+ auto diagID = LangOpts.CPlusPlus
+ ? diag::err_variable_object_no_init
+ : diag::err_compound_literal_with_vla_type;
+ if (!tryToFixVariablyModifiedVarType(TInfo, literalType, LParenLoc,
+ diagID))
return ExprError();
}
} else if (!literalType->isDependentType() &&
diff --git a/clang/test/C/C2x/n2900_n3011.c b/clang/test/C/C2x/n2900_n3011.c
index 4350aa140691b..f0be8b9e41861 100644
--- a/clang/test/C/C2x/n2900_n3011.c
+++ b/clang/test/C/C2x/n2900_n3011.c
@@ -27,8 +27,14 @@ void test(void) {
compat-warning {{use of an empty initializer is incompatible with C standards before C23}}
int vla[i] = {}; // compat-warning {{use of an empty initializer is incompatible with C standards before C23}} \
pedantic-warning {{use of an empty initializer is a C23 extension}}
+ // C99 6.5.2.5 Compound literals constraint 1: The type name shall specify an
+ // object type or an array of unknown size, but not a variable length array
+ // type.
int *compound_literal_vla = (int[i]){}; // compat-warning {{use of an empty initializer is incompatible with C standards before C23}} \
- pedantic-warning {{use of an empty initializer is a C23 extension}}
+ pedantic-warning {{use of an empty initializer is a C23 extension}}\
+ compat-error {{compound literal has variable-length array type}} \
+ pedantic-error {{compound literal has variable-length array type}}\
+
struct T {
int i;
diff --git a/clang/test/C/C2x/n2900_n3011_2.c b/clang/test/C/C2x/n2900_n3011_2.c
index eb15fbf905c86..ab659d636d155 100644
--- a/clang/test/C/C2x/n2900_n3011_2.c
+++ b/clang/test/C/C2x/n2900_n3011_2.c
@@ -76,22 +76,6 @@ void test_zero_size_vla() {
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[VLA]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false)
}
-void test_compound_literal_vla() {
- int num_elts = 12;
- int *compound_literal_vla = (int[num_elts]){};
- // CHECK: define {{.*}} void @test_compound_literal_vla
- // CHECK-NEXT: entry:
- // CHECK-NEXT: %[[NUM_ELTS_PTR:.+]] = alloca i32
- // CHECK-NEXT: %[[COMP_LIT_VLA:.+]] = alloca ptr
- // CHECK-NEXT: %[[COMP_LIT:.+]] = alloca i32
- // CHECK-NEXT: store i32 12, ptr %[[NUM_ELTS_PTR]]
- // CHECK-NEXT: %[[NUM_ELTS:.+]] = load i32, ptr %[[NUM_ELTS_PTR]]
- // CHECK-NEXT: %[[NUM_ELTS_EXT:.+]] = zext i32 %[[NUM_ELTS]] to i64
- // CHECK-NEXT: %[[BYTES_TO_COPY:.+]] = mul nuw i64 %[[NUM_ELTS_EXT]], 4
- // CHECK-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}} %[[COMP_LIT]], i8 0, i64 %[[BYTES_TO_COPY]], i1 false)
- // CHECK-NEXT: store ptr %[[COMP_LIT]], ptr %[[COMP_LIT_VLA]]
-}
-
void test_nested_structs() {
struct T t1 = { 1, {} };
struct T t2 = { 1, { 2, {} } };
diff --git a/clang/test/Sema/compound-literal.c b/clang/test/Sema/compound-literal.c
index a64b6f9e5dfa4..b845ff317225e 100644
--- a/clang/test/Sema/compound-literal.c
+++ b/clang/test/Sema/compound-literal.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -pedantic -Wno-comment %s
// REQUIRES: LP64
struct foo { int a, b; };
@@ -29,7 +29,7 @@ int main(int argc, char **argv) {
struct Incomplete; // expected-note{{forward declaration of 'struct Incomplete'}}
struct Incomplete* I1 = &(struct Incomplete){1, 2, 3}; // expected-error {{variable has incomplete type}}
void IncompleteFunc(unsigned x) {
- struct Incomplete* I2 = (struct foo[x]){1, 2, 3}; // expected-error {{variable-sized object may not be initialized}}
+ struct Incomplete* I2 = (struct foo[x]){1, 2, 3}; // expected-error {{compound literal has variable-length array type}}
(void){1,2,3}; // expected-error {{variable has incomplete type}}
(void(void)) { 0 }; // expected-error{{illegal initializer type 'void (void)'}}
}
@@ -42,3 +42,14 @@ int (^block)(int) = ^(int i) {
int *array = (int[]) {i, i + 2, i + 4};
return array[i];
};
+
+// C99 6.5.2.5 Compound literals constraint 1: The type name shall specify an object type or an array of unknown size, but not a variable length array type.
+// So check that VLA type compound literals are rejected (see https://github.com/llvm/llvm-project/issues/89835).
+void vla(int n) {
+ int size = 5;
+ (void)(int[size]){}; // expected-warning {{use of an empty initializer is a C23 extension}} \
+ expected-error {{compound literal has variable-length array type}}
+ (void)(int[size]){1}; // expected-error {{compound literal has variable-length array type}}
+ (void)(int[size]){1,2,3}; // expected-error {{compound literal has variable-length array type}}
+ (void)(int[size]){1,2,3,4,5}; // expected-error {{compound literal has variable-length array type}}
+}
>From f9e9f9a50547e4c4274f9ff907207b21873b1f72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jim=20M=2E=20R=2E=20Teichgr=C3=A4ber?=
<a at teichgraeber.digital>
Date: Mon, 13 May 2024 13:34:26 +0200
Subject: [PATCH 2/2] Update clang/include/clang/Basic/DiagnosticSemaKinds.td
Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 008d7b2a29cd9..25d925da7b748 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3372,7 +3372,7 @@ def err_field_with_address_space : Error<
def err_compound_literal_with_address_space : Error<
"compound literal in function scope may not be qualified with an address space">;
def err_compound_literal_with_vla_type : Error<
- "compound literal has variable-length array type">;
+ "compound literal cannot be of variable-length array type">;
def err_address_space_mismatch_templ_inst : Error<
"conflicting address space qualifiers are provided between types %0 and %1">;
def err_attr_objc_ownership_redundant : Error<
More information about the cfe-commits
mailing list