Author: Oleksandr Tarasiuk Date: 2026-02-13T17:38:05+02:00 New Revision: ca8a6b8cb14e7006b041da889ba16110ec2cd673
URL: https://github.com/llvm/llvm-project/commit/ca8a6b8cb14e7006b041da889ba16110ec2cd673 DIFF: https://github.com/llvm/llvm-project/commit/ca8a6b8cb14e7006b041da889ba16110ec2cd673.diff LOG: [Clang] fix crash when constexpr evaluation encounters uninitialized GCC vector (#180293) Fixes #180044 --- This patch addresses the regression caused by https://github.com/llvm/llvm-project/commit/77534291fcbd2c784c54e39a60895e4f60f19742. The crash happens because https://github.com/llvm/llvm-project/blob/85d94e17144f2ca250c91b827b59e6ddea675d31/clang/lib/AST/ExprConstant.cpp#L4294 tries to read a vector element when the `APValue` is still `Indeterminate` or `Absent`. These changes _populate_ vector `APValue` to ensure elements exist before access. Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constexpr-vectors-access-elements.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 4f732ba81d78f..92731326ca1bf 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -278,6 +278,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 23a40c9bfd118..2c13befec02f2 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3599,6 +3599,13 @@ 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()); +} + /// 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,6 +4298,15 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, ObjType = VT->getElementType(); assert(I == N - 1 && "extracting subobject of scalar?"); + + if (O->isIndeterminate()) { + if (isRead(handler.AccessKind)) { + Info.FFDiag(E); + return handler.failed(); + } + expandVector(*O, NumElements); + } + 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() && diff --git a/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp b/clang/test/SemaCXX/constexpr-vectors-access-elements.cpp index 58efcde414af2..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 { @@ -46,3 +47,35 @@ 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 test1(char c) { + T v; + for (int i = 0; i < sizeof(T); ++i) + v[i] = c; + return v; +} + +using C = char __attribute__((vector_size(16))); +C t1 = test1<C>(~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(), ""); +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
