llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Chen Miao (ChenMiaoi)

<details>
<summary>Changes</summary>

Instantiating a fixed-length `ext_vector_type` with a dependent element type 
could emit an invalid-element diagnostic without a source location.

For example:

```cc
struct S {};

template &lt;typename T&gt; struct Vector {
  typedef T type __attribute__((ext_vector_type(4)));
};

Vector&lt;S&gt; v;
```

Before:

```txt
error: invalid vector element type 'S'
repro.cc:7:11: note: in instantiation of template class 'Vector&lt;S&gt;' 
requested here
    7 | Vector&lt;S&gt; v;
      |           ^
1 error generated.
```

After:

```txt
repro.cc:4:33: error: invalid vector element type 'S'
    4 |   typedef T type __attribute__((ext_vector_type(4)));
      |                                 ^
repro.cc:7:11: note: in instantiation of template class 'Vector&lt;S&gt;' 
requested here
    7 | Vector&lt;S&gt; v;
      |           ^
1 error generated.
```

Record the attribute location in `ExtVectorTypeLoc` and preserve it through 
substitution, including when a dependent-sized vector becomes fixed-sized. Use 
the original type source information when substituting alias templates, while 
retaining the existing path for underlying types adjusted by `mode`.

Fixes #<!-- -->229300

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


5 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+3) 
- (modified) clang/lib/Sema/SemaTemplate.cpp (+12-3) 
- (modified) clang/lib/Sema/SemaType.cpp (+26-4) 
- (modified) clang/lib/Sema/TreeTransform.h (+3-4) 
- (modified) clang/test/SemaCXX/vector.cpp (+31) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7b878a0abbab3..f23217c1d286d 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -631,6 +631,9 @@ features cannot lower the translation-unit ABI level;
 
 #### Bug Fixes to Attribute Support
 
+- Fixed missing source locations for diagnostics when instantiating
+  `ext_vector_type` with a fixed length and a dependent element type. 
(#GH229300)
+
 - Fixed crash (assertion) when the `alloc_align` attribute was applied to a 
declaration whose type has a `FunctionProtoType` but which is not itself a 
`FunctionDecl`, such as a function-pointer variable. (#GH122058)
 
 - Fixed a crash on `bool` vectors declared with `ext_vector_type` and more than
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 8e7433bc71281..191fba99f635c 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3911,9 +3911,18 @@ QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword 
Keyword,
     if (!AliasTemplate->getDeclContext()->isFileContext())
       SavedContext.emplace(*this, AliasTemplate->getDeclContext());
 
-    CanonType =
-        SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
-                  AliasTemplate->getLocation(), AliasTemplate->getDeclName());
+    if (Pattern->isModed()) {
+      // The mode attribute changes the underlying type without updating the
+      // type source information.
+      CanonType =
+          SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
+                    AliasTemplate->getLocation(), 
AliasTemplate->getDeclName());
+    } else {
+      TypeSourceInfo *SubstTypeInfo =
+          SubstType(Pattern->getTypeSourceInfo(), TemplateArgLists,
+                    AliasTemplate->getLocation(), 
AliasTemplate->getDeclName());
+      CanonType = SubstTypeInfo ? SubstTypeInfo->getType() : QualType();
+    }
     if (CanonType.isNull()) {
       // If this was enable_if and we failed to find the nested type
       // within enable_if in a SFINAE context, dig out the specific
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index e1481b437df9e..9608c367eccf5 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -216,6 +216,9 @@ namespace {
     /// stored in a MacroQualifiedTypeLoc.
     llvm::DenseMap<const MacroQualifiedType *, SourceLocation> LocsForMacros;
 
+    /// Locations of ext_vector_type attributes for fixed-size vectors.
+    llvm::DenseMap<const ExtVectorType *, SourceLocation> LocsForExtVectors;
+
     /// Flag to indicate we parsed a noderef attribute. This is used for
     /// validating that noderef was used on a pointer or array.
     bool parsedNoDeref;
@@ -363,6 +366,15 @@ namespace {
       LocsForMacros[MQT] = Loc;
     }
 
+    SourceLocation getAttrLocForExtVectorType(const ExtVectorType *T) const {
+      return LocsForExtVectors.lookup(T);
+    }
+
+    void setAttrLocForExtVectorType(const ExtVectorType *T,
+                                    SourceLocation Loc) {
+      LocsForExtVectors[T] = Loc;
+    }
+
     void setParsedNoDeref(bool parsed) { parsedNoDeref = parsed; }
 
     bool didParseNoDeref() const { return parsedNoDeref; }
@@ -6011,6 +6023,10 @@ namespace {
     // Allow to fill pointee's type locations, e.g.,
     //   int __attr * __attr * __attr *p;
     void VisitPointerTypeLoc(PointerTypeLoc TL) { Visit(TL.getNextTypeLoc()); }
+    void VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
+      TL.setNameLoc(State.getAttrLocForExtVectorType(TL.getTypePtr()));
+      Visit(TL.getElementLoc());
+    }
     void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
       if (DS.getTypeSpecType() == TST_typename) {
         TypeSourceInfo *TInfo = nullptr;
@@ -6354,7 +6370,9 @@ namespace {
       TL.setNameLoc(Chunk.Loc);
     }
     void VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
-      TL.setNameLoc(Chunk.Loc);
+      SourceLocation AttrLoc =
+          State.getAttrLocForExtVectorType(TL.getTypePtr());
+      TL.setNameLoc(AttrLoc.isValid() ? AttrLoc : Chunk.Loc);
     }
     void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
       fillAtomicQualLoc(TL, Chunk);
@@ -8552,7 +8570,8 @@ static void HandleVectorSizeAttr(QualType &CurType, const 
ParsedAttr &Attr,
 /// Process the OpenCL-like ext_vector_type attribute when it occurs on
 /// a type.
 static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
-                                    Sema &S) {
+                                    TypeProcessingState &State) {
+  Sema &S = State.getSema();
   // check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
     S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
@@ -8562,8 +8581,11 @@ static void HandleExtVectorTypeAttr(QualType &CurType, 
const ParsedAttr &Attr,
 
   Expr *SizeExpr = Attr.getArgAsExpr(0);
   QualType T = S.BuildExtVectorType(CurType, SizeExpr, Attr.getLoc());
-  if (!T.isNull())
+  if (!T.isNull()) {
     CurType = T;
+    if (const auto *VT = dyn_cast<ExtVectorType>(T.getTypePtr()))
+      State.setAttrLocForExtVectorType(VT, Attr.getLoc());
+  }
 }
 
 static bool isPermittedNeonBaseType(QualType &Ty, VectorKind VecKind, Sema &S) 
{
@@ -9211,7 +9233,7 @@ static void processTypeAttrs(TypeProcessingState &state, 
QualType &type,
       attr.setUsedAsTypeAttr();
       break;
     case ParsedAttr::AT_ExtVectorType:
-      HandleExtVectorTypeAttr(type, attr, state.getSema());
+      HandleExtVectorTypeAttr(type, attr, state);
       attr.setUsedAsTypeAttr();
       break;
     case ParsedAttr::AT_NeonVectorType:
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 73367d6bea063..845c3ac32f336 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -6280,7 +6280,7 @@ QualType 
TreeTransform<Derived>::TransformDependentSizedExtVectorType(
     NewTL.setNameLoc(TL.getNameLoc());
   } else {
     ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
-    NewTL.setNameLoc(TL.getNameLoc());
+    NewTL.setNameLoc(T->getAttributeLoc());
   }
 
   return Result;
@@ -6445,9 +6445,8 @@ QualType 
TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
   QualType Result = TL.getType();
   if (getDerived().AlwaysRebuild() ||
       ElementType != T->getElementType()) {
-    Result = getDerived().RebuildExtVectorType(ElementType,
-                                               T->getNumElements(),
-                                               /*FIXME*/ SourceLocation());
+    Result = getDerived().RebuildExtVectorType(ElementType, 
T->getNumElements(),
+                                               TL.getNameLoc());
     if (Result.isNull())
       return QualType();
   }
diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp
index 581d829560ea6..0bbec3e661104 100644
--- a/clang/test/SemaCXX/vector.cpp
+++ b/clang/test/SemaCXX/vector.cpp
@@ -5,6 +5,7 @@
 // RUN: %clang_cc1 -flax-vector-conversions=all -triple x86_64-apple-darwin10 
-fsyntax-only -verify -std=c++20 %s
 // RUN: %clang_cc1 -flax-vector-conversions=integer -triple 
x86_64-apple-darwin10 -fsyntax-only -verify %s -DNO_LAX_FLOAT
 // RUN: %clang_cc1 -flax-vector-conversions=none -triple x86_64-apple-darwin10 
-fsyntax-only -verify %s -DNO_LAX_FLOAT -DNO_LAX_INT
+// RUN: not %clang_cc1 -flax-vector-conversions=all -triple 
x86_64-apple-darwin10 -fsyntax-only -ferror-limit 0 %s 2>&1 | FileCheck %s 
--check-prefix=LOCATION
 
 typedef char char16 __attribute__ ((__vector_size__ (16)));
 typedef long long longlong16 __attribute__ ((__vector_size__ (16)));
@@ -337,6 +338,36 @@ const int &reference_to_vec_element = vi4(1).x;
 typedef bool bad __attribute__((__vector_size__(16)));  // expected-error 
{{invalid vector element type 'bool'}}
 
 namespace Templates {
+struct InvalidElement {};
+
+template <typename T> struct GH229300 {
+  // LOCATION: vector.cpp:[[@LINE+1]]:33: error: invalid vector element type 
'Templates::InvalidElement'
+  typedef T type __attribute__((ext_vector_type(4))); // expected-error 
{{invalid vector element type 'Templates::InvalidElement'}}
+};
+GH229300<InvalidElement> invalid_vector; // expected-note {{in instantiation 
of template class 'Templates::GH229300<Templates::InvalidElement>' requested 
here}}
+
+template <typename T> struct GH229300Paren {
+  typedef T
+    (type)
+    // LOCATION: vector.cpp:[[@LINE+1]]:20: error: invalid vector element type 
'Templates::InvalidElement'
+    __attribute__((ext_vector_type(4))); // expected-error {{invalid vector 
element type 'Templates::InvalidElement'}}
+};
+GH229300Paren<InvalidElement> invalid_paren_vector; // expected-note {{in 
instantiation of template class 
'Templates::GH229300Paren<Templates::InvalidElement>' requested here}}
+
+#if __cplusplus >= 201103L
+template <typename T> using GH229300Alias =
+  // LOCATION: vector.cpp:[[@LINE+1]]:20: error: invalid vector element type 
'InvalidElement'
+  T __attribute__((ext_vector_type(4))); // expected-error {{invalid vector 
element type 'InvalidElement'}}
+GH229300Alias<InvalidElement> invalid_alias_vector; // expected-note {{in 
instantiation of template type alias 'GH229300Alias' requested here}}
+
+template <int N> struct GH229300DependentSize {
+  template <typename T> using type =
+    // LOCATION: vector.cpp:[[@LINE+1]]:22: error: invalid vector element type 
'InvalidElement'
+    T __attribute__((ext_vector_type(N))); // expected-error {{invalid vector 
element type 'InvalidElement'}}
+};
+GH229300DependentSize<4>::type<InvalidElement> invalid_dependent_vector; // 
expected-note {{in instantiation of template type alias 'type' requested here}}
+#endif
+
 template <typename Elt, unsigned long long Size>
 struct TemplateVectorType {
   typedef Elt __attribute__((__vector_size__(Size))) type; // #1

``````````

</details>


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

Reply via email to