https://github.com/ChenMiaoi created 
https://github.com/llvm/llvm-project/pull/229328

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 <typename T> struct Vector {
  typedef T type __attribute__((ext_vector_type(4)));
};

Vector<S> v;
```

Before:

```txt
error: invalid vector element type 'S'
repro.cc:7:11: note: in instantiation of template class 'Vector<S>' requested 
here
    7 | Vector<S> 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<S>' requested 
here
    7 | Vector<S> 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

>From d5b5b9d45dd38a6731021bb1c8fa53de043b23be Mon Sep 17 00:00:00 2001
From: Chen Miao <[email protected]>
Date: Tue, 6 Oct 2026 15:15:31 +0800
Subject: [PATCH] [clang] Preserve ext_vector_type locations during template
 substitution

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 <typename T> struct Vector {
  typedef T type __attribute__((ext_vector_type(4)));
};

Vector<S> v;
```

Before:

```txt
error: invalid vector element type 'S'
repro.cc:7:11: note: in instantiation of template class 'Vector<S>' requested 
here
    7 | Vector<S> 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<S>' requested 
here
    7 | Vector<S> 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
---
 clang/docs/ReleaseNotes.md      |  3 +++
 clang/lib/Sema/SemaTemplate.cpp | 15 ++++++++++++---
 clang/lib/Sema/SemaType.cpp     | 30 ++++++++++++++++++++++++++----
 clang/lib/Sema/TreeTransform.h  |  7 +++----
 clang/test/SemaCXX/vector.cpp   | 31 +++++++++++++++++++++++++++++++
 5 files changed, 75 insertions(+), 11 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7b878a0abbab3c3..f23217c1d286db2 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 8e7433bc7128133..191fba99f635c1b 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 e1481b437df9e09..9608c367eccf51b 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 73367d6bea063d1..845c3ac32f3360c 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 581d829560ea69f..0bbec3e661104c2 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

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

Reply via email to