https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/180293
>From f80187c545b8a9775e0b2356fdc04ae3ae35fd2c Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk <[email protected]> Date: Fri, 6 Feb 2026 21:25:55 +0200 Subject: [PATCH 1/3] [Clang] fix crash when constexpr evaluation encounters uninitialized GCC vector --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ExprConstant.cpp | 20 ++++++++++++++++++- .../constexpr-vectors-access-elements.cpp | 16 +++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 24d4e07ca68b3..c9c50625a8590 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -243,6 +243,7 @@ Bug Fixes to C++ Support - Fixed a crash when instantiating ``requires`` expressions involving substitution failures in C++ concepts. (#GH176402) - Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639) - Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741) +- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index ff433ed729a28..e5732df75ec1e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3599,6 +3599,11 @@ static void expandArray(APValue &Array, unsigned Index) { Array.swap(NewValue); } +static void expandVector(APValue &Vec, unsigned NumElements) { + SmallVector<APValue, 4> Elts(NumElements, APValue::IndeterminateValue()); + Vec = APValue(Elts.data(), Elts.size()); +} + /// Determine whether a type would actually be read by an lvalue-to-rvalue /// conversion. If it's of class type, we may assume that the copy operation /// is trivial. Note that this is never true for a union type with fields @@ -4291,7 +4296,20 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, ObjType = VT->getElementType(); assert(I == N - 1 && "extracting subobject of scalar?"); - return handler.found(O->getVectorElt(Index), ObjType); + + if (O->isIndeterminate() || O->isAbsent()) { + if (isRead(handler.AccessKind)) { + Info.FFDiag(E); + return handler.failed(); + } + expandVector(*O, NumElements); + } + + if (O->isVector()) + return handler.found(O->getVectorElt(Index), ObjType); + + Info.FFDiag(E); + return handler.failed(); } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { if (Field->isMutable() && !Obj.mayAccessMutableMembers(Info, handler.AccessKind)) { diff --git a/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp b/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp index 58efcde414af2..a84bb319dc0dd 100644 --- a/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp +++ b/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp @@ -46,3 +46,19 @@ static_assert(&b[1]); // expected-error {{address of vector element requested}} constexpr const FourIntsExtVec *p = &b; static_assert(p->x == 1); } + +namespace GH180044 { +template <typename T> constexpr T test(char c) { + T v; + for (int i = 0; i < sizeof(T); ++i) + v[i] = c; + return v; +} + +using T = char __attribute__((vector_size(16))); +T t1 = test<T>(~1); + +constexpr T t2 = test<T>(~1); +static_assert(t2[0] == -2); +static_assert(t2[15] == -2); +} >From 56ddba28009be3eaa259383e9c7181f100ee3ea6 Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk <[email protected]> Date: Mon, 9 Feb 2026 15:20:56 +0200 Subject: [PATCH 2/3] add test to cover read access case --- .../constexpr-vectors-access-elements.cpp | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp b/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp index a84bb319dc0dd..481b80ceb9c1e 100644 --- a/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp +++ b/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 %s -Wno-uninitialized -std=c++17 -fsyntax-only -verify +// RUN: %clang_cc1 %s -Wno-uninitialized -std=c++17 -fsyntax-only -verify=expected,cpp17 +// RUN: %clang_cc1 %s -Wno-uninitialized -std=c++20 -fsyntax-only -verify=expected,cpp20 namespace Vector { @@ -48,17 +49,33 @@ static_assert(p->x == 1); } namespace GH180044 { -template <typename T> constexpr T test(char c) { +template <typename T> constexpr T test1(char c) { T v; for (int i = 0; i < sizeof(T); ++i) v[i] = c; return v; } -using T = char __attribute__((vector_size(16))); -T t1 = test<T>(~1); +using C = char __attribute__((vector_size(16))); +C t1 = test1<C>(~1); -constexpr T t2 = test<T>(~1); +constexpr C t2 = test1<C>(~1); static_assert(t2[0] == -2); static_assert(t2[15] == -2); + +using I = int __attribute__((vector_size(16))); + +// expected-error@+1 {{constexpr function never produces a constant expression}} +constexpr unsigned test2() { + // cpp17-warning@+1 {{uninitialized variable in a constexpr function is a C++20 extension}} + I v; + + // expected-note@+2 {{subexpression not valid in a constant expression}} + // expected-note@+1 {{subexpression not valid in a constant expression}} + return __builtin_bit_cast(unsigned, v[0]); +} + +// expected-error@+2 {{static assertion expression is not an integral constant expression}} +// expected-note@+1 {{in call to 'test2()'}} +static_assert(test2(), ""); } >From 40b3ab03f05ec1ee43bb1b08f4a6f7ecf49f9fbc Mon Sep 17 00:00:00 2001 From: Oleksandr Tarasiuk <[email protected]> Date: Mon, 9 Feb 2026 15:21:40 +0200 Subject: [PATCH 3/3] add asserts --- clang/lib/AST/ExprConstant.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index e5732df75ec1e..e24fdca90441e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3599,7 +3599,9 @@ static void expandArray(APValue &Array, unsigned Index) { Array.swap(NewValue); } +// Expand an indeterminate vector to materialize all elements. static void expandVector(APValue &Vec, unsigned NumElements) { + assert(Vec.isIndeterminate()); SmallVector<APValue, 4> Elts(NumElements, APValue::IndeterminateValue()); Vec = APValue(Elts.data(), Elts.size()); } @@ -4297,19 +4299,15 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, ObjType = VT->getElementType(); assert(I == N - 1 && "extracting subobject of scalar?"); - if (O->isIndeterminate() || O->isAbsent()) { + if (O->isIndeterminate()) { if (isRead(handler.AccessKind)) { Info.FFDiag(E); return handler.failed(); } expandVector(*O, NumElements); } - - if (O->isVector()) - return handler.found(O->getVectorElt(Index), ObjType); - - Info.FFDiag(E); - return handler.failed(); + assert(O->isVector() && "unexpected object during vector element access"); + return handler.found(O->getVectorElt(Index), ObjType); } else if (const FieldDecl *Field = getAsField(Sub.Entries[I])) { if (Field->isMutable() && !Obj.mayAccessMutableMembers(Info, handler.AccessKind)) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
