Author: Daniel Petrovic
Date: 2026-09-23T10:53:19+02:00
New Revision: c41e1ef6e1cc650cd05328155408ecb705986f09

URL: 
https://github.com/llvm/llvm-project/commit/c41e1ef6e1cc650cd05328155408ecb705986f09
DIFF: 
https://github.com/llvm/llvm-project/commit/c41e1ef6e1cc650cd05328155408ecb705986f09.diff

LOG: [clang] Fix crash on assigning to _Atomic vectors (#225125)

As described in the issue itself: 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

bt:
<img width="1908" height="825" alt="225039_crash_atomic_vector"
src="https://github.com/user-attachments/assets/c5d48ba5-fa9b-43f8-a555-8b9bbe558152";
/>

Co-authored-by: Timm Baeder <[email protected]>

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Compiler.cpp
    clang/lib/AST/ExprConstant.cpp
    clang/test/Sema/vector-assign.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 99ad69562e314..16f2a768fe06c 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -1881,12 +1881,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.
@@ -1903,14 +1910,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 9749d0b43a629..bb7721df5a28b 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -12244,13 +12244,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..15e13492b49b9 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,15 @@ 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 *'}}
 }
+
+// #225039: assignment to an _Atomic vector
+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

Reply via email to