https://github.com/daniel-petrovic created https://github.com/llvm/llvm-project/pull/225125
d=c on _Atomic vector crashed during the overflow check because isVectorType() doesn't look through _Atomic. Strip _Atomic before checking operand types. Fixes #225039 >From 301e3f9939948495a573eacff3b2db20e5e052ba Mon Sep 17 00:00:00 2001 From: Daniel Petrovic <[email protected]> Date: Mon, 21 Sep 2026 17:52:29 +0200 Subject: [PATCH] [clang] Fix crash on assigning to _Atomic vectors d=c on _Atomic vector crashed during the overflow check because isVectorType() doesn't look through _Atomic. Strip _Atomic before checking operand types. Fixes #225039 --- clang/lib/AST/ByteCode/Compiler.cpp | 21 ++++++++++++++------- clang/lib/AST/ExprConstant.cpp | 8 +++++--- clang/test/Sema/vector-assign.c | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 38a095f8a1164..747b55b6d8a57 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -1862,12 +1862,19 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) { const Expr *RHS = E->getRHS(); assert(!E->isCommaOp() && "Comma op should be handled in VisitBinaryOperator"); + + QualType LHSType = LHS->getType(); + if (const auto *AT = LHSType->getAs<AtomicType>()) + LHSType = AT->getValueType(); + QualType RHSType = RHS->getType(); + if (const auto *AT = RHSType->getAs<AtomicType>()) + RHSType = AT->getValueType(); assert(E->getType()->isVectorType()); - assert(LHS->getType()->isVectorType()); - assert(RHS->getType()->isVectorType()); + assert(LHSType->isVectorType()); + assert(RHSType->isVectorType()); // We can only handle vectors with primitive element types. - if (!canClassify(LHS->getType()->castAs<VectorType>()->getElementType())) + if (!canClassify(LHSType->castAs<VectorType>()->getElementType())) return false; // Prepare storage for result. @@ -1884,14 +1891,14 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) { ? BinaryOperator::getOpForCompoundAssignment(E->getOpcode()) : E->getOpcode(); - PrimType ElemT = this->classifyVectorElementType(LHS->getType()); - PrimType RHSElemT = this->classifyVectorElementType(RHS->getType()); + PrimType ElemT = this->classifyVectorElementType(LHSType); + PrimType RHSElemT = this->classifyVectorElementType(RHSType); PrimType ResultElemT = this->classifyVectorElementType(E->getType()); if (E->getOpcode() == BO_Assign) { assert(Ctx.getASTContext().hasSameUnqualifiedType( - LHS->getType()->castAs<VectorType>()->getElementType(), - RHS->getType()->castAs<VectorType>()->getElementType())); + LHSType->castAs<VectorType>()->getElementType(), + RHSType->castAs<VectorType>()->getElementType())); if (!this->visit(LHS)) return false; if (!this->visit(RHS)) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 9242491832841..d43c55d4ec4c7 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12236,13 +12236,15 @@ bool VectorExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { Expr *LHS = E->getLHS(); Expr *RHS = E->getRHS(); - assert(LHS->getType()->isVectorType() && RHS->getType()->isVectorType() && + QualType LHSType = LHS->getType().getAtomicUnqualifiedType(); + QualType RHSType = RHS->getType().getAtomicUnqualifiedType(); + assert(LHSType->isVectorType() && RHSType->isVectorType() && "Must both be vector types"); // Checking JUST the types are the same would be fine, except shifts don't // need to have their types be the same (since you always shift by an int). - assert(LHS->getType()->castAs<VectorType>()->getNumElements() == + assert(LHSType->castAs<VectorType>()->getNumElements() == E->getType()->castAs<VectorType>()->getNumElements() && - RHS->getType()->castAs<VectorType>()->getNumElements() == + RHSType->castAs<VectorType>()->getNumElements() == E->getType()->castAs<VectorType>()->getNumElements() && "All operands must be the same size."); diff --git a/clang/test/Sema/vector-assign.c b/clang/test/Sema/vector-assign.c index 119a320585ef6..b0a0125ab92de 100644 --- a/clang/test/Sema/vector-assign.c +++ b/clang/test/Sema/vector-assign.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -verify -fsyntax-only -Wvector-conversion +// RUN: %clang_cc1 %s -verify -fsyntax-only -Wvector-conversion -fexperimental-new-constant-interpreter typedef unsigned int v2u __attribute__ ((vector_size (8))); typedef signed int v2s __attribute__ ((vector_size (8))); typedef signed int v1s __attribute__ ((vector_size (4))); @@ -51,3 +52,17 @@ void test3a(longlongvec *); // expected-note{{passing argument to parameter here void test3(const unsigned *src) { test3a(src); // expected-error {{incompatible pointer types passing 'const unsigned int *' to parameter of type 'longlongvec *'}} } + +// GH#225039: assignment to an `_Atomic` vector used to assert in the +// VectorExprEvaluator during the signed-overflow check because the operands +// have _Atomic-qualified (non-vector) types. +typedef unsigned gh225039_vec __attribute__((vector_size(16))); +typedef signed int gh225039_vec_i32 __attribute__((vector_size(16))); +void test4(void) { + gh225039_vec c; + _Atomic gh225039_vec d; + d = c; + d += c; + _Atomic gh225039_vec_i32 e, f; + e = f; +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
