https://github.com/michele-scandale updated 
https://github.com/llvm/llvm-project/pull/197624

>From 052e2b1e381145e1e90b6e48fc8f319e4fee5901 Mon Sep 17 00:00:00 2001
From: Michele Scandale <[email protected]>
Date: Thu, 25 Jun 2026 12:51:58 -0700
Subject: [PATCH 1/2] Fix vector types w.r.t. qualified element type.

This commit changes the way vector types are constructed to ensure that
qualifiers on the element type are moved to the vector type itself --
i.e. a canonical vector type has always an unqualified element type.

RFC: https://discourse.llvm.org/t/90783
---
 clang/include/clang/AST/ASTContext.h |   5 +-
 clang/include/clang/AST/TypeBase.h   |  36 +++++---
 clang/lib/AST/ASTContext.cpp         | 127 +++++++++++++--------------
 clang/lib/AST/Type.cpp               |  80 ++++++++++++++---
 clang/test/Sema/types.c              |  12 +++
 clang/test/SemaCXX/vector.cpp        |  14 +++
 6 files changed, 183 insertions(+), 91 deletions(-)

diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index c04b380f9ec5b..aedef5cd853d1 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -238,13 +238,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
   mutable std::vector<VariableArrayType*> VariableArrayTypes;
   mutable llvm::ContextualFoldingSet<DependentSizedArrayType, ASTContext &>
       DependentSizedArrayTypes;
-  mutable llvm::ContextualFoldingSet<DependentSizedExtVectorType, ASTContext &>
+  mutable llvm::FoldingSet<DependentSizedExtVectorType>
       DependentSizedExtVectorTypes;
   mutable llvm::ContextualFoldingSet<DependentAddressSpaceType, ASTContext &>
       DependentAddressSpaceTypes;
   mutable llvm::FoldingSet<VectorType> VectorTypes;
-  mutable llvm::ContextualFoldingSet<DependentVectorType, ASTContext &>
-      DependentVectorTypes;
+  mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes;
   mutable llvm::FoldingSet<ConstantMatrixType> MatrixTypes;
   mutable llvm::ContextualFoldingSet<DependentSizedMatrixType, ASTContext &>
       DependentSizedMatrixTypes;
diff --git a/clang/include/clang/AST/TypeBase.h 
b/clang/include/clang/AST/TypeBase.h
index c9658775f0470..88c31fc0bf037 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -4167,13 +4167,14 @@ class DependentSizedExtVectorType : public Type, public 
llvm::FoldingSetNode {
 
   Expr *SizeExpr;
 
-  /// The element type of the array.
+  /// The element type of the vector.
   QualType ElementType;
 
   SourceLocation loc;
+  const ASTContext &Context;
 
-  DependentSizedExtVectorType(QualType ElementType, QualType can,
-                              Expr *SizeExpr, SourceLocation loc);
+  DependentSizedExtVectorType(const ASTContext &Context, QualType ElementType,
+                              QualType can, Expr *SizeExpr, SourceLocation 
loc);
 
 public:
   Expr *getSizeExpr() const { return SizeExpr; }
@@ -4183,11 +4184,13 @@ class DependentSizedExtVectorType : public Type, public 
llvm::FoldingSetNode {
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
+  SplitQualType getSplitUnqualifiedType() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == DependentSizedExtVector;
   }
 
-  void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
+  void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, Context, getElementType(), getSizeExpr());
   }
 
@@ -4243,12 +4246,14 @@ class VectorType : public Type, public 
llvm::FoldingSetNode {
   /// The element type of the vector.
   QualType ElementType;
 
-  VectorType(QualType vecType, unsigned nElements, QualType canonType,
-             VectorKind vecKind);
+  const ASTContext &Context;
 
-  VectorType(TypeClass tc, QualType vecType, unsigned nElements,
+  VectorType(const ASTContext &Context, QualType vecType, unsigned nElements,
              QualType canonType, VectorKind vecKind);
 
+  VectorType(const ASTContext &Context, TypeClass tc, QualType vecType,
+             unsigned nElements, QualType canonType, VectorKind vecKind);
+
 public:
   QualType getElementType() const { return ElementType; }
   unsigned getNumElements() const { return VectorTypeBits.NumElements; }
@@ -4256,6 +4261,8 @@ class VectorType : public Type, public 
llvm::FoldingSetNode {
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
+  SplitQualType getSplitUnqualifiedType() const;
+
   VectorKind getVectorKind() const {
     return VectorKind(VectorTypeBits.VecKind);
   }
@@ -4294,9 +4301,11 @@ class DependentVectorType : public Type, public 
llvm::FoldingSetNode {
   QualType ElementType;
   Expr *SizeExpr;
   SourceLocation Loc;
+  const ASTContext &Context;
 
-  DependentVectorType(QualType ElementType, QualType CanonType, Expr *SizeExpr,
-                      SourceLocation Loc, VectorKind vecKind);
+  DependentVectorType(const ASTContext &Context, QualType ElementType,
+                      QualType CanonType, Expr *SizeExpr, SourceLocation Loc,
+                      VectorKind vecKind);
 
 public:
   Expr *getSizeExpr() const { return SizeExpr; }
@@ -4309,11 +4318,13 @@ class DependentVectorType : public Type, public 
llvm::FoldingSetNode {
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
+  SplitQualType getSplitUnqualifiedType() const;
+
   static bool classof(const Type *T) {
     return T->getTypeClass() == DependentVector;
   }
 
-  void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
+  void Profile(llvm::FoldingSetNodeID &ID) {
     Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind());
   }
 
@@ -4331,8 +4342,9 @@ class DependentVectorType : public Type, public 
llvm::FoldingSetNode {
 class ExtVectorType : public VectorType {
   friend class ASTContext; // ASTContext creates these.
 
-  ExtVectorType(QualType vecType, unsigned nElements, QualType canonType)
-      : VectorType(ExtVector, vecType, nElements, canonType,
+  ExtVectorType(const ASTContext &Context, QualType vecType, unsigned 
nElements,
+                QualType canonType)
+      : VectorType(Context, ExtVector, vecType, nElements, canonType,
                    VectorKind::Generic) {}
 
 public:
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 525d0b6619119..8060b018b66a5 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -931,8 +931,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager 
&SM,
                        IdentifierTable &idents, SelectorTable &sels,
                        Builtin::Context &builtins, TranslationUnitKind TUKind)
     : ConstantArrayTypes(this_(), ConstantArrayTypesLog2InitSize),
-      DependentSizedArrayTypes(this_()), DependentSizedExtVectorTypes(this_()),
-      DependentAddressSpaceTypes(this_()), DependentVectorTypes(this_()),
+      DependentSizedArrayTypes(this_()), DependentAddressSpaceTypes(this_()),
       DependentSizedMatrixTypes(this_()),
       FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize),
       DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()),
@@ -4717,18 +4716,20 @@ QualType ASTContext::getVectorType(QualType vecType, 
unsigned NumElts,
   if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(VTP, 0);
 
-  // If the element type isn't canonical, this won't be a canonical type 
either,
-  // so fill in the canonical type field.
+  // If the element type isn't canonical or has qualifiers, this won't be a
+  // canonical type either, so fill in the canonical type field.
   QualType Canonical;
-  if (!vecType.isCanonical()) {
-    Canonical = getVectorType(getCanonicalType(vecType), NumElts, VecKind);
+  if (!vecType.isCanonical() || vecType.hasLocalQualifiers()) {
+    SplitQualType canonSplit = getCanonicalType(vecType).split();
+    Canonical = getVectorType(QualType(canonSplit.Ty, 0), NumElts, VecKind);
+    Canonical = getQualifiedType(Canonical, canonSplit.Quals);
 
     // Get the new insert position for the node we care about.
     VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
     assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
   }
   auto *New = new (*this, alignof(VectorType))
-      VectorType(vecType, NumElts, Canonical, VecKind);
+      VectorType(*this, vecType, NumElts, Canonical, VecKind);
   VectorTypes.InsertNode(New, InsertPos);
   Types.push_back(New);
   return QualType(New, 0);
@@ -4737,37 +4738,37 @@ QualType ASTContext::getVectorType(QualType vecType, 
unsigned NumElts,
 QualType ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr,
                                             SourceLocation AttrLoc,
                                             VectorKind VecKind) const {
+  SplitQualType CanonVecType = getCanonicalType(VecType).split();
+
   llvm::FoldingSetNodeID ID;
-  DependentVectorType::Profile(ID, *this, getCanonicalType(VecType), SizeExpr,
-                               VecKind);
+  DependentVectorType::Profile(ID, *this, QualType(CanonVecType.Ty, 0),
+                               SizeExpr, VecKind);
   void *InsertPos = nullptr;
   DependentVectorType *Canon =
       DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
-  DependentVectorType *New;
 
-  if (Canon) {
-    New = new (*this, alignof(DependentVectorType)) DependentVectorType(
-        VecType, QualType(Canon, 0), SizeExpr, AttrLoc, VecKind);
-  } else {
-    QualType CanonVecTy = getCanonicalType(VecType);
-    if (CanonVecTy == VecType) {
-      New = new (*this, alignof(DependentVectorType))
-          DependentVectorType(VecType, QualType(), SizeExpr, AttrLoc, VecKind);
-
-      DependentVectorType *CanonCheck =
-          DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
-      assert(!CanonCheck &&
-             "Dependent-sized vector_size canonical type broken");
-      (void)CanonCheck;
-      DependentVectorTypes.InsertNode(New, InsertPos);
-    } else {
-      QualType CanonTy = getDependentVectorType(CanonVecTy, SizeExpr,
-                                                SourceLocation(), VecKind);
-      New = new (*this, alignof(DependentVectorType))
-          DependentVectorType(VecType, CanonTy, SizeExpr, AttrLoc, VecKind);
-    }
+  // If we don't have one, build one.
+  if (!Canon) {
+    Canon = new (*this, TypeAlignment)
+        DependentVectorType(*this, QualType(CanonVecType.Ty, 0), QualType(),
+                            SizeExpr, AttrLoc, VecKind);
+    DependentVectorTypes.InsertNode(Canon, InsertPos);
+    Types.push_back(Canon);
   }
 
+  // Apply qualifiers from the element type to the vector.
+  QualType CanonTy = getQualifiedType(QualType(Canon, 0), CanonVecType.Quals);
+
+  // If we didn't need extra canonicalization for the element type or the size
+  // expression, then just use that as our result.
+  if (QualType(CanonVecType.Ty, 0) == VecType &&
+      Canon->getSizeExpr() == SizeExpr)
+    return CanonTy;
+
+  // Otherwise, we need to build a type which follows the spelling
+  // of the element type.
+  auto *New = new (*this, TypeAlignment)
+      DependentVectorType(*this, VecType, CanonTy, SizeExpr, AttrLoc, VecKind);
   Types.push_back(New);
   return QualType(New, 0);
 }
@@ -4789,60 +4790,58 @@ QualType ASTContext::getExtVectorType(QualType vecType,
   if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos))
     return QualType(VTP, 0);
 
-  // If the element type isn't canonical, this won't be a canonical type 
either,
-  // so fill in the canonical type field.
+  // If the element type isn't canonical or has qualifiers, this won't be a
+  // canonical type either, so fill in the canonical type field.
   QualType Canonical;
-  if (!vecType.isCanonical()) {
-    Canonical = getExtVectorType(getCanonicalType(vecType), NumElts);
+  if (!vecType.isCanonical() || vecType.hasLocalQualifiers()) {
+    SplitQualType canonSplit = getCanonicalType(vecType).split();
+    Canonical = getExtVectorType(QualType(canonSplit.Ty, 0), NumElts);
+    Canonical = getQualifiedType(Canonical, canonSplit.Quals);
 
     // Get the new insert position for the node we care about.
     VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos);
     assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
   }
   auto *New = new (*this, alignof(ExtVectorType))
-      ExtVectorType(vecType, NumElts, Canonical);
+      ExtVectorType(*this, vecType, NumElts, Canonical);
   VectorTypes.InsertNode(New, InsertPos);
   Types.push_back(New);
   return QualType(New, 0);
 }
 
 QualType
-ASTContext::getDependentSizedExtVectorType(QualType vecType,
-                                           Expr *SizeExpr,
+ASTContext::getDependentSizedExtVectorType(QualType VecType, Expr *SizeExpr,
                                            SourceLocation AttrLoc) const {
+  SplitQualType CanonVecType = getCanonicalType(VecType).split();
+
   llvm::FoldingSetNodeID ID;
-  DependentSizedExtVectorType::Profile(ID, *this, getCanonicalType(vecType),
+  DependentSizedExtVectorType::Profile(ID, *this, QualType(CanonVecType.Ty, 0),
                                        SizeExpr);
-
   void *InsertPos = nullptr;
   DependentSizedExtVectorType *Canon
     = DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
-  DependentSizedExtVectorType *New;
-  if (Canon) {
-    // We already have a canonical version of this array type; use it as
-    // the canonical type for a newly-built type.
-    New = new (*this, alignof(DependentSizedExtVectorType))
-        DependentSizedExtVectorType(vecType, QualType(Canon, 0), SizeExpr,
-                                    AttrLoc);
-  } else {
-    QualType CanonVecTy = getCanonicalType(vecType);
-    if (CanonVecTy == vecType) {
-      New = new (*this, alignof(DependentSizedExtVectorType))
-          DependentSizedExtVectorType(vecType, QualType(), SizeExpr, AttrLoc);
-
-      DependentSizedExtVectorType *CanonCheck
-        = DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
-      assert(!CanonCheck && "Dependent-sized ext_vector canonical type 
broken");
-      (void)CanonCheck;
-      DependentSizedExtVectorTypes.InsertNode(New, InsertPos);
-    } else {
-      QualType CanonExtTy = getDependentSizedExtVectorType(CanonVecTy, 
SizeExpr,
-                                                           SourceLocation());
-      New = new (*this, alignof(DependentSizedExtVectorType))
-          DependentSizedExtVectorType(vecType, CanonExtTy, SizeExpr, AttrLoc);
-    }
+
+  // If we don't have one, build one.
+  if (!Canon) {
+    Canon = new (*this, TypeAlignment) DependentSizedExtVectorType(
+        *this, QualType(CanonVecType.Ty, 0), QualType(), SizeExpr, AttrLoc);
+    DependentSizedExtVectorTypes.InsertNode(Canon, InsertPos);
+    Types.push_back(Canon);
   }
 
+  // Apply qualifiers from the element type to the vector.
+  QualType CanonTy = getQualifiedType(QualType(Canon, 0), CanonVecType.Quals);
+
+  // If we didn't need extra canonicalization for the element type or the size
+  // expression, then just use that as our result.
+  if (QualType(CanonVecType.Ty, 0) == VecType &&
+      Canon->getSizeExpr() == SizeExpr)
+    return CanonTy;
+
+  // Otherwise, we need to build a type which follows the spelling
+  // of the element type.
+  auto *New = new (*this, TypeAlignment)
+      DependentSizedExtVectorType(*this, VecType, CanonTy, SizeExpr, AttrLoc);
   Types.push_back(New);
   return QualType(New, 0);
 }
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 42d148715bc40..8256188212edc 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -335,7 +335,8 @@ void 
DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
     E->Profile(ID, Context, true);
 }
 
-DependentVectorType::DependentVectorType(QualType ElementType,
+DependentVectorType::DependentVectorType(const ASTContext &Context,
+                                         QualType ElementType,
                                          QualType CanonType, Expr *SizeExpr,
                                          SourceLocation Loc, VectorKind 
VecKind)
     : Type(DependentVector, CanonType,
@@ -343,10 +344,21 @@ DependentVectorType::DependentVectorType(QualType 
ElementType,
                ElementType->getDependence() |
                (SizeExpr ? toTypeDependence(SizeExpr->getDependence())
                          : TypeDependence::None)),
-      ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) {
+      ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc), Context(Context) 
{
   VectorTypeBits.VecKind = llvm::to_underlying(VecKind);
 }
 
+SplitQualType DependentVectorType::getSplitUnqualifiedType() const {
+  auto SplitElem = ElementType.getSplitUnqualifiedType();
+  QualType UnqualElemTy(SplitElem.Ty, 0);
+  if (UnqualElemTy == ElementType)
+    return SplitQualType(this, Qualifiers());
+
+  auto UnqualVecTy = Context.getDependentVectorType(
+      UnqualElemTy, getSizeExpr(), getAttributeLoc(), getVectorKind());
+  return SplitQualType(UnqualVecTy.getTypePtr(), SplitElem.Quals);
+}
+
 void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID,
                                   const ASTContext &Context,
                                   QualType ElementType, const Expr *SizeExpr,
@@ -356,16 +368,27 @@ void DependentVectorType::Profile(llvm::FoldingSetNodeID 
&ID,
   SizeExpr->Profile(ID, Context, true);
 }
 
-DependentSizedExtVectorType::DependentSizedExtVectorType(QualType ElementType,
-                                                         QualType can,
-                                                         Expr *SizeExpr,
-                                                         SourceLocation loc)
+DependentSizedExtVectorType::DependentSizedExtVectorType(
+    const ASTContext &Context, QualType ElementType, QualType can,
+    Expr *SizeExpr, SourceLocation loc)
     : Type(DependentSizedExtVector, can,
            TypeDependence::DependentInstantiation |
                ElementType->getDependence() |
                (SizeExpr ? toTypeDependence(SizeExpr->getDependence())
                          : TypeDependence::None)),
-      SizeExpr(SizeExpr), ElementType(ElementType), loc(loc) {}
+      SizeExpr(SizeExpr), ElementType(ElementType), loc(loc), Context(Context) 
{
+}
+
+SplitQualType DependentSizedExtVectorType::getSplitUnqualifiedType() const {
+  auto SplitElem = ElementType.getSplitUnqualifiedType();
+  QualType UnqualElemTy(SplitElem.Ty, 0);
+  if (UnqualElemTy == ElementType)
+    return SplitQualType(this, Qualifiers());
+
+  auto UnqualVecTy = Context.getDependentSizedExtVectorType(
+      UnqualElemTy, getSizeExpr(), getAttributeLoc());
+  return SplitQualType(UnqualVecTy.getTypePtr(), SplitElem.Quals);
+}
 
 void DependentSizedExtVectorType::Profile(llvm::FoldingSetNodeID &ID,
                                           const ASTContext &Context,
@@ -441,17 +464,34 @@ void 
DependentSizedMatrixType::Profile(llvm::FoldingSetNodeID &ID,
   ColumnExpr->Profile(ID, CTX, true);
 }
 
-VectorType::VectorType(QualType vecType, unsigned nElements, QualType 
canonType,
+VectorType::VectorType(const ASTContext &Context, QualType vecType,
+                       unsigned nElements, QualType canonType,
                        VectorKind vecKind)
-    : VectorType(Vector, vecType, nElements, canonType, vecKind) {}
+    : VectorType(Context, Vector, vecType, nElements, canonType, vecKind) {}
 
-VectorType::VectorType(TypeClass tc, QualType vecType, unsigned nElements,
-                       QualType canonType, VectorKind vecKind)
-    : Type(tc, canonType, vecType->getDependence()), ElementType(vecType) {
+VectorType::VectorType(const ASTContext &Context, TypeClass tc,
+                       QualType vecType, unsigned nElements, QualType 
canonType,
+                       VectorKind vecKind)
+    : Type(tc, canonType, vecType->getDependence()), ElementType(vecType),
+      Context(Context) {
   VectorTypeBits.VecKind = llvm::to_underlying(vecKind);
   VectorTypeBits.NumElements = nElements;
 }
 
+SplitQualType VectorType::getSplitUnqualifiedType() const {
+  auto SplitElem = ElementType.getSplitUnqualifiedType();
+  QualType UnqualElemTy(SplitElem.Ty, 0);
+  if (UnqualElemTy == ElementType)
+    return SplitQualType(this, Qualifiers());
+
+  auto UnqualVecTy =
+      getTypeClass() == ExtVector
+          ? Context.getExtVectorType(UnqualElemTy, getNumElements())
+          : Context.getVectorType(UnqualElemTy, getNumElements(),
+                                  getVectorKind());
+  return SplitQualType(UnqualVecTy.getTypePtr(), SplitElem.Quals);
+}
+
 bool Type::isPackedVectorBoolType(const ASTContext &ctx) const {
   if (ctx.getLangOpts().HLSL)
     return false;
@@ -628,6 +668,22 @@ SplitQualType 
QualType::getSplitUnqualifiedTypeImpl(QualType type) {
   }
 
 done:
+  // Vector types can have qualified element type. We need to recursively
+  // process the element type, and possibly construct a new vector type with 
the
+  // unqualified version of the element type.
+  SplitQualType SplitVec;
+  if (auto *VTy = dyn_cast<VectorType>(split.Ty))
+    SplitVec = VTy->getSplitUnqualifiedType();
+  else if (auto *DVTy = dyn_cast<DependentVectorType>(split.Ty))
+    SplitVec = DVTy->getSplitUnqualifiedType();
+  else if (auto *DSEVTy = dyn_cast<DependentSizedExtVectorType>(split.Ty))
+    SplitVec = DSEVTy->getSplitUnqualifiedType();
+
+  if (SplitVec.Ty) {
+    quals.addConsistentQualifiers(SplitVec.Quals);
+    return SplitQualType(SplitVec.Ty, quals);
+  }
+
   return SplitQualType(lastTypeWithQuals, quals);
 }
 
diff --git a/clang/test/Sema/types.c b/clang/test/Sema/types.c
index 2be0e6544f3d7..21ee2feabc965 100644
--- a/clang/test/Sema/types.c
+++ b/clang/test/Sema/types.c
@@ -75,6 +75,18 @@ typedef int __attribute__((ext_vector_type(0x100000000))) 
e2;      // expected-e
 typedef int __attribute__((vector_size((__int128_t)1 << 100))) e3; // 
expected-error {{vector size too large}}
 typedef int __attribute__((ext_vector_type(0))) e4;                // 
expected-error {{zero vector size}}
 
+typedef const int cint;
+typedef int __attribute__((vector_size(16))) vec4_int;
+typedef cint __attribute__((vector_size(16))) vec4_cint;
+_Static_assert(__builtin_types_compatible_p(vec4_int, const vec4_int), 
"'vec4_int' and 'const vec4_int' are not compatible");
+_Static_assert(__builtin_types_compatible_p(vec4_int, volatile vec4_int), 
"'vec4_int' and 'const vec4_int' are not compatible");
+_Static_assert(__builtin_types_compatible_p(const vec4_int, vec4_cint), 
"'const vec4_int' and 'vec4_cint' are not compatible");
+typedef int __attribute__((ext_vector_type(4))) ext_vec4_int;
+typedef cint __attribute__((ext_vector_type(4))) ext_vec4_cint;
+_Static_assert(__builtin_types_compatible_p(ext_vec4_int, const ext_vec4_int), 
"'ext_vec4_int' and 'const ext_vec4_int' are not compatible");
+_Static_assert(__builtin_types_compatible_p(ext_vec4_int, volatile 
ext_vec4_int), "'ext_vec4_int' and 'const ext_vec4_int' are not compatible");
+_Static_assert(__builtin_types_compatible_p(const ext_vec4_int, 
ext_vec4_cint), "'const ext_vec4_int' and 'ext_vec4_cint' are not compatible'");
+
 // no support for vector enum type
 enum { e_2 } x3 __attribute__((vector_size(64))); // expected-error {{invalid 
vector element type}}
 
diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp
index 355d93a2b8cee..ef91848c7d31a 100644
--- a/clang/test/SemaCXX/vector.cpp
+++ b/clang/test/SemaCXX/vector.cpp
@@ -817,3 +817,17 @@ namespace GH173347 {
 typedef short __attribute__((__vector_size__(8))) V;
 template <int N> V test(V x) { return (x % 5) * N; }
 }
+
+namespace test_canonical_quals {
+typedef const int cint;
+typedef int __attribute__((vector_size(16))) vec4_int;
+typedef cint __attribute__((vector_size(16))) vec4_cint;
+_Static_assert(!__is_same(vec4_int, const vec4_int), "'vec4_int' and 'const 
vec4_int' are not different");
+_Static_assert(!__is_same(vec4_int, volatile vec4_int), "'vec4_int' and 'const 
vec4_int' are not different");
+_Static_assert(__is_same(const vec4_int, vec4_cint), "'const vec4_int' and 
'vec4_cint' are different");
+typedef int __attribute__((ext_vector_type(4))) ext_vec4_int;
+typedef cint __attribute__((ext_vector_type(4))) ext_vec4_cint;
+_Static_assert(!__is_same(ext_vec4_int, const ext_vec4_int), "'ext_vec4_int' 
and 'const ext_vec4_int' are not different");
+_Static_assert(!__is_same(ext_vec4_int, volatile ext_vec4_int), 
"'ext_vec4_int' and 'const ext_vec4_int' are not different");
+_Static_assert(__is_same(const ext_vec4_int, ext_vec4_cint), "'const 
ext_vec4_int' and 'ext_vec4_cint' are different");
+} // namespace test_canonical_quals

>From 76e3dafca51cc268bd8c1bceca189391716b7503 Mon Sep 17 00:00:00 2001
From: Michele Scandale <[email protected]>
Date: Thu, 25 Jun 2026 13:18:15 -0700
Subject: [PATCH 2/2] [libcxx] Drop qualifiers on element type for
 `__simd_vector<T, N>`.

---
 libcxx/include/__algorithm/simd_utils.h       | 20 +++++++++++--------
 .../include/__cxx03/__algorithm/simd_utils.h  | 16 +++++++++------
 2 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/libcxx/include/__algorithm/simd_utils.h 
b/libcxx/include/__algorithm/simd_utils.h
index 495aed4e21216..dcd6daf6377be 100644
--- a/libcxx/include/__algorithm/simd_utils.h
+++ b/libcxx/include/__algorithm/simd_utils.h
@@ -15,6 +15,7 @@
 #include <__bit/countr.h>
 #include <__config>
 #include <__cstddef/size_t.h>
+#include <__type_traits/remove_cv.h>
 #include <__utility/integer_sequence.h>
 #include <cstdint>
 
@@ -88,7 +89,10 @@ inline constexpr size_t __native_vector_size = 1;
 #  endif
 
 template <class _ArithmeticT, size_t _Np>
-using __simd_vector __attribute__((__ext_vector_type__(_Np))) _LIBCPP_NODEBUG 
= _ArithmeticT;
+using __simd_vector_impl __attribute__((__ext_vector_type__(_Np))) 
_LIBCPP_NODEBUG = _ArithmeticT;
+
+template <class _ArithmeticT, size_t _Np>
+using __simd_vector _LIBCPP_NODEBUG = 
__simd_vector_impl<__remove_cv_t<_ArithmeticT>, _Np>;
 
 _LIBCPP_DIAGNOSTIC_PUSH
 _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wpsabi")
@@ -99,10 +103,10 @@ inline constexpr size_t __simd_vector_size_v = []<bool 
_False = false>() -> size
 }();
 
 template <class _Tp, size_t _Np>
-inline constexpr size_t __simd_vector_size_v<__simd_vector<_Tp, _Np>> = _Np;
+inline constexpr size_t __simd_vector_size_v<__simd_vector_impl<_Tp, _Np>> = 
_Np;
 
 template <class _Tp, size_t _Np>
-_LIBCPP_HIDE_FROM_ABI _Tp 
__simd_vector_underlying_type_impl(__simd_vector<_Tp, _Np>) {
+_LIBCPP_HIDE_FROM_ABI _Tp 
__simd_vector_underlying_type_impl(__simd_vector_impl<_Tp, _Np>) {
   return _Tp{};
 }
 
@@ -127,22 +131,22 @@ template <class _VecT, size_t _Np, class _Iter>
 }
 
 template <class _Tp, size_t _Np>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __any_of(__simd_vector<_Tp, _Np> 
__vec) noexcept {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __any_of(__simd_vector_impl<_Tp, 
_Np> __vec) noexcept {
   return __builtin_reduce_or(__builtin_convertvector(__vec, 
__simd_vector<bool, _Np>));
 }
 
 template <class _Tp, size_t _Np>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> 
__vec) noexcept {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector_impl<_Tp, 
_Np> __vec) noexcept {
   return __builtin_reduce_and(__builtin_convertvector(__vec, 
__simd_vector<bool, _Np>));
 }
 
 template <class _Tp, size_t _Np>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __none_of(__simd_vector<_Tp, _Np> 
__vec) noexcept {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __none_of(__simd_vector_impl<_Tp, 
_Np> __vec) noexcept {
   return !__builtin_reduce_or(__builtin_convertvector(__vec, 
__simd_vector<bool, _Np>));
 }
 
 template <class _Tp, size_t _Np>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_set(__simd_vector_impl<_Tp, _Np> __vec) noexcept {
   using __mask_vec = __simd_vector<bool, _Np>;
 
   // This has MSan disabled du to https://llvm.org/PR85876
@@ -171,7 +175,7 @@ template <class _Tp, size_t _Np>
 }
 
 template <class _Tp, size_t _Np>
-[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_not_set(__simd_vector_impl<_Tp, _Np> __vec) noexcept {
   return std::__find_first_set(~__vec);
 }
 _LIBCPP_DIAGNOSTIC_POP
diff --git a/libcxx/include/__cxx03/__algorithm/simd_utils.h 
b/libcxx/include/__cxx03/__algorithm/simd_utils.h
index 7b0e825afaa1f..7758aee7e74bd 100644
--- a/libcxx/include/__cxx03/__algorithm/simd_utils.h
+++ b/libcxx/include/__cxx03/__algorithm/simd_utils.h
@@ -15,6 +15,7 @@
 #include <__cxx03/__config>
 #include <__cxx03/__type_traits/is_arithmetic.h>
 #include <__cxx03/__type_traits/is_same.h>
+#include <__cxx03/__type_traits/remove_cv.h>
 #include <__cxx03/__utility/integer_sequence.h>
 #include <__cxx03/cstddef>
 #include <__cxx03/cstdint>
@@ -85,7 +86,10 @@ inline constexpr size_t __native_vector_size = 1;
 #  endif
 
 template <class _ArithmeticT, size_t _Np>
-using __simd_vector __attribute__((__ext_vector_type__(_Np))) = _ArithmeticT;
+using __simd_vector_impl __attribute__((__ext_vector_type__(_Np))) = 
_ArithmeticT;
+
+template <class _ArithmeticT, size_t _Np>
+using __simd_vector = __simd_vector_impl<__remove_cv_t<_ArithmeticT>, _Np>;
 
 template <class _VecT>
 inline constexpr size_t __simd_vector_size_v = []<bool _False = false>() -> 
size_t {
@@ -93,10 +97,10 @@ inline constexpr size_t __simd_vector_size_v = []<bool 
_False = false>() -> size
 }();
 
 template <class _Tp, size_t _Np>
-inline constexpr size_t __simd_vector_size_v<__simd_vector<_Tp, _Np>> = _Np;
+inline constexpr size_t __simd_vector_size_v<__simd_vector_impl<_Tp, _Np>> = 
_Np;
 
 template <class _Tp, size_t _Np>
-_LIBCPP_HIDE_FROM_ABI _Tp 
__simd_vector_underlying_type_impl(__simd_vector<_Tp, _Np>) {
+_LIBCPP_HIDE_FROM_ABI _Tp 
__simd_vector_underlying_type_impl(__simd_vector_impl<_Tp, _Np>) {
   return _Tp{};
 }
 
@@ -112,12 +116,12 @@ _LIBCPP_NODISCARD _LIBCPP_ALWAYS_INLINE 
_LIBCPP_HIDE_FROM_ABI _VecT __load_vecto
 }
 
 template <class _Tp, size_t _Np>
-_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector<_Tp, _Np> 
__vec) noexcept {
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI bool __all_of(__simd_vector_impl<_Tp, 
_Np> __vec) noexcept {
   return __builtin_reduce_and(__builtin_convertvector(__vec, 
__simd_vector<bool, _Np>));
 }
 
 template <class _Tp, size_t _Np>
-_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_set(__simd_vector<_Tp, _Np> __vec) noexcept {
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_set(__simd_vector_impl<_Tp, _Np> __vec) noexcept {
   using __mask_vec = __simd_vector<bool, _Np>;
 
   // This has MSan disabled du to 
https://github.com/llvm/llvm-project/issues/85876
@@ -146,7 +150,7 @@ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_set(__simd_vector<_T
 }
 
 template <class _Tp, size_t _Np>
-_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_not_set(__simd_vector<_Tp, _Np> __vec) noexcept {
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI size_t 
__find_first_not_set(__simd_vector_impl<_Tp, _Np> __vec) noexcept {
   return std::__find_first_set(~__vec);
 }
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to