Author: Mariya Podchishchaeva Date: 2025-03-05T11:04:52+01:00 New Revision: 59169036ca0e064612886713d609873f776e85db
URL: https://github.com/llvm/llvm-project/commit/59169036ca0e064612886713d609873f776e85db DIFF: https://github.com/llvm/llvm-project/commit/59169036ca0e064612886713d609873f776e85db.diff LOG: [clang] Fix crash when #embed data does not fit into an array (#129567) Tune SemaInit code handling #embed to take into account how many array elements remains to initialize. Also issue a warning/error message when the array/struct is at the end but there is still #embed data left. Fixes https://github.com/llvm/llvm-project/issues/128987 Added: clang/test/CodeGen/excess-embed-data.c clang/test/Sema/excess-embed-data.c Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaInit.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5098e5e983103..38111db3e6919 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -243,6 +243,8 @@ Bug Fixes in This Version when it can affect template argument deduction (#GH122306). - Fix crash on code completion of function calls involving partial order of function templates (#GH125500). +- Fixed clang crash when #embed data does not fit into an array + (#GH128987). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 86f5a5c1d4434..56ec33fe37bf3 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -519,12 +519,13 @@ class InitListChecker { uint64_t ElsCount = 1; // Otherwise try to fill whole array with embed data. if (Entity.getKind() == InitializedEntity::EK_ArrayElement) { + unsigned ArrIndex = Entity.getElementIndex(); auto *AType = SemaRef.Context.getAsArrayType(Entity.getParent()->getType()); assert(AType && "expected array type when initializing array"); ElsCount = Embed->getDataElementCount(); if (const auto *CAType = dyn_cast<ConstantArrayType>(AType)) - ElsCount = std::min(CAType->getSize().getZExtValue(), + ElsCount = std::min(CAType->getSize().getZExtValue() - ArrIndex, ElsCount - CurEmbedIndex); if (ElsCount == Embed->getDataElementCount()) { CurEmbed = nullptr; @@ -1317,7 +1318,7 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, return; // Don't complain for incomplete types, since we'll get an error elsewhere. - if (Index < IList->getNumInits() && !T->isIncompleteType()) { + if ((Index < IList->getNumInits() || CurEmbed) && !T->isIncompleteType()) { // We have leftover initializers bool ExtraInitsIsError = SemaRef.getLangOpts().CPlusPlus || (SemaRef.getLangOpts().OpenCL && T->isVectorType()); @@ -2180,6 +2181,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, InitializedEntity ElementEntity = InitializedEntity::InitializeElement( SemaRef.Context, StructuredIndex, Entity); + ElementEntity.setElementIndex(elementIndex.getExtValue()); unsigned EmbedElementIndexBeforeInit = CurEmbedIndex; // Check this element. diff --git a/clang/test/CodeGen/excess-embed-data.c b/clang/test/CodeGen/excess-embed-data.c new file mode 100644 index 0000000000000..9143125ba2398 --- /dev/null +++ b/clang/test/CodeGen/excess-embed-data.c @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c23 -emit-llvm -triple x86_64 %s -o - | FileCheck %s + +struct S { + int arr[3]; +}; + +struct S1 { + struct S s; +}; + +// CHECK: @[[BConst:.*]] = private unnamed_addr constant [2 x i32] [i32 47, i32 47] +// CHECK: @[[DConst:.*]] = private unnamed_addr constant [2 x i8] c"//" +// CHECK: @[[SConst:.*]] = private unnamed_addr constant %struct.S { [3 x i32] [i32 47, i32 47, i32 32] } +// CHECK: @[[S1Const:.*]] = private unnamed_addr constant %struct.S1 { %struct.S { [3 x i32] [i32 47, i32 47, i32 32] } } + +void cases(int x) { + int a[3] = {x, x, +#embed __FILE__ + }; + + int b[2] = { +#embed __FILE__ + }; + + char d[2] = { +#embed __FILE__ + }; + + struct S s = { +#embed __FILE__ + , x + }; + + struct S1 s1 = { +#embed __FILE__ + , x + }; +} +// CHECK: define dso_local void @cases(i32 noundef %[[X:.*]]) +// CHECK: %[[A:.*]] = alloca [3 x i32] +// CHECK: %[[B:.*]] = alloca [2 x i32] +// CHECK: %[[D:.*]] = alloca [2 x i8] +// CHECK: %[[S:.*]] = alloca %struct.S +// CHECK: %[[S1:.*]] = alloca %struct.S1 +// CHECK: %[[LX:.*]] = load i32, ptr %[[X]].addr +// CHECK: store i32 %[[LX]], ptr %[[A]] +// CHECK: %[[GEP1:.*]] = getelementptr inbounds i32, ptr %[[A]], i64 1 +// CHECK: %[[LX1:.*]] = load i32, ptr %[[X]].addr +// CHECK: store i32 %1, ptr %arrayinit.element +// CHECK: %[[GEP1:.*]] = getelementptr inbounds i32, ptr %[[A]], i64 2 +// CHECK: store i32 47, ptr %[[GEP1]] +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[B]], ptr align 4 @[[BConst]], i64 8, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[D]], ptr align 1 @[[DConst]], i64 2, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[S]], ptr align 4 @[[SConst]], i64 12, i1 false) +// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[S1]], ptr align 4 @[[S1Const]], i64 12, i1 false) diff --git a/clang/test/Sema/excess-embed-data.c b/clang/test/Sema/excess-embed-data.c new file mode 100644 index 0000000000000..d5b84921abc89 --- /dev/null +++ b/clang/test/Sema/excess-embed-data.c @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify=c %s +// RUN: %clang_cc1 -fsyntax-only -verify=cpp -x c++ -Wno-c23-extensions %s + + +struct S { + int arr[3]; +}; + +struct S1 { + struct S s; +}; + +void cases(int x) { + int a[8] = {x, x, x, x, x, x, +#embed __FILE__ + // c-warning@-1{{excess elements in array initializer}} + // cpp-error@-2{{excess elements in array initializer}} +}; + int b[8] = { +#embed __FILE__ + // c-warning@-1{{excess elements in array initializer}} + // cpp-error@-2{{excess elements in array initializer}} +}; + int c[3000] = {x, x, x, x, x, x, +#embed __FILE__ + }; + char d[3] = { +#embed __FILE__ + // c-warning@-1{{initializer-string for char array is too long}} + // cpp-error@-2{{initializer-string for char array is too long}} + }; + +char e[3000] = { 1, +#embed __FILE__ +}; + +struct S s = { +#embed __FILE__ + // c-warning@-1{{excess elements in struct initializer}} + // cpp-error@-2{{excess elements in struct initializer}} + , x +}; + +struct S1 s1 = { +#embed __FILE__ + // c-warning@-1{{excess elements in struct initializer}} + // cpp-error@-2{{excess elements in struct initializer}} + , x +}; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits