llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Michele Scandale (michele-scandale)

<details>
<summary>Changes</summary>

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

RFC: https://discourse.llvm.org/t/90783

---
Full diff: https://github.com/llvm/llvm-project/pull/197624.diff


4 Files Affected:

- (modified) clang/lib/AST/ASTContext.cpp (+62-60) 
- (modified) clang/lib/Sema/SemaTypeTraits.cpp (+4-2) 
- (modified) clang/test/Sema/types.c (+12) 
- (modified) clang/test/SemaCXX/vector.cpp (+14) 


``````````diff
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a0894318dbd53..2c9e852817b7a 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4654,11 +4654,13 @@ 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);
@@ -4674,37 +4676,36 @@ 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(
+        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(VecType, CanonTy, SizeExpr, AttrLoc, VecKind);
   Types.push_back(New);
   return QualType(New, 0);
 }
@@ -4726,11 +4727,13 @@ 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);
@@ -4744,42 +4747,41 @@ QualType ASTContext::getExtVectorType(QualType vecType,
 }
 
 QualType
-ASTContext::getDependentSizedExtVectorType(QualType vecType,
-                                           Expr *SizeExpr,
+ASTContext::getDependentSizedExtVectorType(QualType VecType, Expr *SizeExpr,
                                            SourceLocation AttrLoc) const {
+  assert(VecKind == VectorType::GenericVector ||
+         VecKind == VectorType::PackedVector);
+
+  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(
+        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(VecType, CanonTy, SizeExpr, AttrLoc);
   Types.push_back(New);
   return QualType(New, 0);
 }
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp 
b/clang/lib/Sema/SemaTypeTraits.cpp
index c79b3f7045ca6..ee89f5a20a289 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -1625,8 +1625,10 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, 
TypeTrait BTT,
   case BTT_TypeCompatible: {
     // GCC ignores cv-qualifiers on arrays for this builtin.
     Qualifiers LhsQuals, RhsQuals;
-    QualType Lhs = Self.getASTContext().getUnqualifiedArrayType(LhsT, 
LhsQuals);
-    QualType Rhs = Self.getASTContext().getUnqualifiedArrayType(RhsT, 
RhsQuals);
+    QualType Lhs = Self.getASTContext().getUnqualifiedArrayType(
+        LhsT.getCanonicalType(), LhsQuals);
+    QualType Rhs = Self.getASTContext().getUnqualifiedArrayType(
+        RhsT.getCanonicalType(), RhsQuals);
     return Self.Context.typesAreCompatible(Lhs, Rhs);
   }
   case BTT_IsConvertible:
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

``````````

</details>


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

Reply via email to