[clang] [clang] Preserve ext_vector_type locations during template substitution (PR #229328)
Chen Miao via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 10 10:43:48 PDT 2026
https://github.com/ChenMiaoi updated https://github.com/llvm/llvm-project/pull/229328
>From d5b5b9d45dd38a6731021bb1c8fa53de043b23be Mon Sep 17 00:00:00 2001
From: Chen Miao <chenmiao.ku at gmail.com>
Date: Tue, 6 Oct 2026 15:15:31 +0800
Subject: [PATCH 1/5] [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 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
>From 275329259592bfa7ba82ed649da31184fc29f207 Mon Sep 17 00:00:00 2001
From: Chen Miao <chenmiao.ku at gmail.com>
Date: Tue, 6 Oct 2026 15:15:31 +0800
Subject: [PATCH 2/5] [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 0aa17906efeb7..0bb17b28e78da 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -638,6 +638,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 202bd486321f9..c09295b4562a4 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 fd6127a33f1ae..0694f6bb4f0c1 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)));
@@ -354,6 +355,36 @@ Vector<int> int_vector;
} // namespace GH225037
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
>From 000617ce86050f31945c91562e8da21c5abdb71e Mon Sep 17 00:00:00 2001
From: Chen Miao <chenmiao.ku at gmail.com>
Date: Sat, 10 Oct 2026 10:07:17 +0800
Subject: [PATCH 3/5] [clang] Withdraw previous ext_vector_type location fix
---
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, 11 insertions(+), 75 deletions(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 5ec6a5e8c3b1e..78c4f585b56b9 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -696,9 +696,6 @@ 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 an assertion failure when parsing malformed GNU `__attribute__`
syntax followed by a parenthesized expression list in C code. (#GH225045)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 191fba99f635c..8e7433bc71281 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3911,18 +3911,9 @@ QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword Keyword,
if (!AliasTemplate->getDeclContext()->isFileContext())
SavedContext.emplace(*this, AliasTemplate->getDeclContext());
- 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();
- }
+ CanonType =
+ SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
+ AliasTemplate->getLocation(), AliasTemplate->getDeclName());
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 30b09f163fe65..1cb96b556971a 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -216,9 +216,6 @@ 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;
@@ -366,15 +363,6 @@ 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; }
@@ -6032,10 +6020,6 @@ 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;
@@ -6379,9 +6363,7 @@ namespace {
TL.setNameLoc(Chunk.Loc);
}
void VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
- SourceLocation AttrLoc =
- State.getAttrLocForExtVectorType(TL.getTypePtr());
- TL.setNameLoc(AttrLoc.isValid() ? AttrLoc : Chunk.Loc);
+ TL.setNameLoc(Chunk.Loc);
}
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
fillAtomicQualLoc(TL, Chunk);
@@ -8579,8 +8561,7 @@ 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,
- TypeProcessingState &State) {
- Sema &S = State.getSema();
+ Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
@@ -8590,11 +8571,8 @@ 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) {
@@ -9242,7 +9220,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_ExtVectorType:
- HandleExtVectorTypeAttr(type, attr, state);
+ HandleExtVectorTypeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
case ParsedAttr::AT_NeonVectorType:
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 845c3ac32f336..73367d6bea063 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(T->getAttributeLoc());
+ NewTL.setNameLoc(TL.getNameLoc());
}
return Result;
@@ -6445,8 +6445,9 @@ QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB,
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() ||
ElementType != T->getElementType()) {
- Result = getDerived().RebuildExtVectorType(ElementType, T->getNumElements(),
- TL.getNameLoc());
+ Result = getDerived().RebuildExtVectorType(ElementType,
+ T->getNumElements(),
+ /*FIXME*/ SourceLocation());
if (Result.isNull())
return QualType();
}
diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp
index 0694f6bb4f0c1..fd6127a33f1ae 100644
--- a/clang/test/SemaCXX/vector.cpp
+++ b/clang/test/SemaCXX/vector.cpp
@@ -5,7 +5,6 @@
// 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)));
@@ -355,36 +354,6 @@ Vector<int> int_vector;
} // namespace GH225037
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
>From d8c75d6276fe2ff4421418efac73a8d846ca30ea Mon Sep 17 00:00:00 2001
From: Chen Miao <chenmiao.ku at gmail.com>
Date: Sun, 11 Oct 2026 01:32:34 +0800
Subject: [PATCH 4/5] [clang] Preserve vector type source information for
diagnostics
---
clang/docs/ReleaseNotes.md | 3 +
clang/include/clang/AST/ASTNodeTraverser.h | 11 ++-
clang/include/clang/AST/RecursiveASTVisitor.h | 15 ++--
clang/include/clang/AST/TypeLoc.h | 73 +++++++++++++++++--
clang/lib/Sema/SemaTemplate.cpp | 2 +
clang/lib/Sema/SemaType.cpp | 32 ++++++--
clang/lib/Sema/TreeTransform.h | 40 ++++++----
clang/lib/Serialization/ASTReader.cpp | 8 +-
clang/lib/Serialization/ASTWriter.cpp | 8 +-
.../PCH/cxx-dependent-sized-ext-vector.cpp | 23 +++++-
clang/test/SemaCXX/vector.cpp | 6 +-
clang/test/SemaTemplate/ext-vector-type.cpp | 30 +++++++-
clang/unittests/AST/SourceLocationTest.cpp | 29 ++++++++
13 files changed, 241 insertions(+), 39 deletions(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 78c4f585b56b9..df0c03ae8b849 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -347,6 +347,9 @@ features cannot lower the translation-unit ABI level;
### Improvements to Clang's diagnostics
+- Errors for invalid element types during instantiation of an `ext_vector_type`
+ now include a source location, including in alias templates. (#GH229300)
+
- Fixed spurious `-Wimplicit-void-ptr-cast` warnings in C for parenthesized
null pointer macros such as `(NULL)`. (#GH171874)
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 8e09c49982e5d..c287c100fab88 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -525,7 +525,16 @@ class ASTNodeTraverser
Visit(TL.getSizeExpr());
}
void VisitDependentSizedExtVectorTypeLoc(DependentSizedExtVectorTypeLoc TL) {
- Visit(cast<DependentSizedExtVectorType>(TL.getType())->getSizeExpr());
+ Expr *Size = TL.getSizeExpr();
+ Visit(Size ? Size : TL.getTypePtr()->getSizeExpr());
+ }
+ void VisitVectorTypeLoc(VectorTypeLoc TL) {
+ if (Expr *Size = TL.getSizeExpr())
+ Visit(Size);
+ }
+ void VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) {
+ Expr *Size = TL.getSizeExpr();
+ Visit(Size ? Size : TL.getTypePtr()->getSizeExpr());
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
Visit(TL.getUnderlyingExpr());
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index f144c890f6ee6..02137e8101969 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1381,25 +1381,30 @@ DEF_TRAVERSE_TYPELOC(DependentAddressSpaceType, {
// FIXME: order? why not size expr first?
// FIXME: base VectorTypeLoc is unfinished
DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, {
- if (TL.getTypePtr()->getSizeExpr())
- TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ Expr *Size = TL.getSizeExpr();
+ if (!Size)
+ Size = TL.getTypePtr()->getSizeExpr();
+ TRY_TO(TraverseStmt(Size));
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
// FIXME: VectorTypeLoc is unfinished
DEF_TRAVERSE_TYPELOC(VectorType, {
+ TRY_TO(TraverseStmt(TL.getSizeExpr()));
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
DEF_TRAVERSE_TYPELOC(DependentVectorType, {
- if (TL.getTypePtr()->getSizeExpr())
- TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ Expr *Size = TL.getSizeExpr();
+ if (!Size)
+ Size = TL.getTypePtr()->getSizeExpr();
+ TRY_TO(TraverseStmt(Size));
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
-// FIXME: size and attributes
// FIXME: base VectorTypeLoc is unfinished
DEF_TRAVERSE_TYPELOC(ExtVectorType, {
+ TRY_TO(TraverseStmt(TL.getSizeExpr()));
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
})
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index b3cb4d0f33629..d19b91a62e572 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2062,25 +2062,52 @@ class DependentAddressSpaceTypeLoc
//
//===----------------------------------------------------------------------===//
-// FIXME: size expression and attribute locations (or keyword if we
-// ever fully support altivec syntax).
+// FIXME: keyword location if we ever fully support altivec syntax.
struct VectorTypeLocInfo {
SourceLocation NameLoc;
+ SourceLocation AttrLoc;
+ Expr *SizeExpr;
};
+// FIXME: Make VectorTypeLoc a common base for fixed-size and dependent vector
+// type locations, similar to MatrixTypeLoc.
class VectorTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, VectorTypeLoc,
VectorType, VectorTypeLocInfo> {
public:
+ /// The location used for the vector type's local source range, e.g.
+ /// int __attribute__((vector_size(16)))
+ /// ^~~
+ /// int __attribute__((ext_vector_type(4)))
+ /// ^~~
SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; }
-
void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; }
+ /// The location of the attribute name, i.e.
+ /// int __attribute__((vector_size(16)))
+ /// ^~~~~~~~~~~
+ /// int __attribute__((ext_vector_type(4)))
+ /// ^~~~~~~~~~~~~~~
+ SourceLocation getAttrNameLoc() const { return getLocalData()->AttrLoc; }
+ void setAttrNameLoc(SourceLocation Loc) { getLocalData()->AttrLoc = Loc; }
+
+ /// The attribute's size operand, if it has one.
+ /// int __attribute__((vector_size(16)))
+ /// ^~
+ /// int __attribute__((ext_vector_type(4)))
+ /// ^
+ ///
+ /// The size is in bytes for vector_size and in elements for ext_vector_type.
+ Expr *getSizeExpr() const { return getLocalData()->SizeExpr; }
+ void setSizeExpr(Expr *E) { getLocalData()->SizeExpr = E; }
+
SourceRange getLocalSourceRange() const {
return SourceRange(getNameLoc(), getNameLoc());
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setNameLoc(Loc);
+ setAttrNameLoc(Loc);
+ setSizeExpr(nullptr);
}
TypeLoc getElementLoc() const { return getInnerTypeLoc(); }
@@ -2088,22 +2115,37 @@ class VectorTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, VectorTypeLoc,
QualType getInnerType() const { return this->getTypePtr()->getElementType(); }
};
-// FIXME: size expression and attribute locations (or keyword if we
-// ever fully support altivec syntax).
class DependentVectorTypeLoc
: public ConcreteTypeLoc<UnqualTypeLoc, DependentVectorTypeLoc,
DependentVectorType, VectorTypeLocInfo> {
public:
- SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; }
+ /// The location used for the vector type's local source range, e.g.
+ /// T __attribute__((vector_size(N)))
+ /// ^
+ SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; }
void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; }
+ /// The location of the attribute name, i.e.
+ /// T __attribute__((vector_size(N)))
+ /// ^~~~~~~~~~~
+ SourceLocation getAttrNameLoc() const { return getLocalData()->AttrLoc; }
+ void setAttrNameLoc(SourceLocation Loc) { getLocalData()->AttrLoc = Loc; }
+
+ /// The attribute's size operand in bytes, if it has one.
+ /// T __attribute__((vector_size(N)))
+ /// ^
+ Expr *getSizeExpr() const { return getLocalData()->SizeExpr; }
+ void setSizeExpr(Expr *E) { getLocalData()->SizeExpr = E; }
+
SourceRange getLocalSourceRange() const {
return SourceRange(getNameLoc(), getNameLoc());
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setNameLoc(Loc);
+ setAttrNameLoc(Loc);
+ setSizeExpr(nullptr);
}
TypeLoc getElementLoc() const { return getInnerTypeLoc(); }
@@ -2111,27 +2153,42 @@ class DependentVectorTypeLoc
QualType getInnerType() const { return this->getTypePtr()->getElementType(); }
};
-// FIXME: size expression and attribute locations.
class ExtVectorTypeLoc
: public InheritingConcreteTypeLoc<VectorTypeLoc, ExtVectorTypeLoc,
ExtVectorType> {};
-// FIXME: attribute locations.
// For some reason, this isn't a subtype of VectorType.
class DependentSizedExtVectorTypeLoc
: public ConcreteTypeLoc<UnqualTypeLoc, DependentSizedExtVectorTypeLoc,
DependentSizedExtVectorType, VectorTypeLocInfo> {
public:
+ /// The location used for the vector type's local source range, e.g.
+ /// T __attribute__((ext_vector_type(N)))
+ /// ^
SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; }
void setNameLoc(SourceLocation Loc) { this->getLocalData()->NameLoc = Loc; }
+ /// The location of the attribute name, i.e.
+ /// T __attribute__((ext_vector_type(N)))
+ /// ^~~~~~~~~~~~~~~
+ SourceLocation getAttrNameLoc() const { return getLocalData()->AttrLoc; }
+ void setAttrNameLoc(SourceLocation Loc) { getLocalData()->AttrLoc = Loc; }
+
+ /// The attribute's size operand in elements, if it has one.
+ /// T __attribute__((ext_vector_type(N)))
+ /// ^
+ Expr *getSizeExpr() const { return getLocalData()->SizeExpr; }
+ void setSizeExpr(Expr *E) { getLocalData()->SizeExpr = E; }
+
SourceRange getLocalSourceRange() const {
return SourceRange(getNameLoc(), getNameLoc());
}
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setNameLoc(Loc);
+ setAttrNameLoc(Loc);
+ setSizeExpr(nullptr);
}
TypeLoc getElementLoc() const { return getInnerTypeLoc(); }
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 8e7433bc71281..ac7c3aff80bfd 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3911,6 +3911,8 @@ QualType Sema::CheckTemplateIdType(ElaboratedTypeKeyword Keyword,
if (!AliasTemplate->getDeclContext()->isFileContext())
SavedContext.emplace(*this, AliasTemplate->getDeclContext());
+ // FIXME: Preserve the pattern's type source information during substitution
+ // while respecting underlying type changes made by mode attributes.
CanonType =
SubstType(Pattern->getUnderlyingType(), TemplateArgLists,
AliasTemplate->getLocation(), AliasTemplate->getDeclName());
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 1cb96b556971a..a5f16e3d17940 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -5958,6 +5958,26 @@ static void fillMatrixTypeLoc(MatrixTypeLoc MTL,
llvm_unreachable("no matrix_type attribute found at the expected location!");
}
+// FIXME: Also handle attributes on the decl-specifier, declarator and
+// declaration. Matrix type locations need the same handling.
+static void fillVectorTypeLoc(VectorTypeLoc VTL,
+ const ParsedAttributesView &Attrs) {
+ auto Kind = isa<ExtVectorType>(VTL.getTypePtr())
+ ? ParsedAttr::AT_ExtVectorType
+ : ParsedAttr::AT_VectorSize;
+ for (const ParsedAttr &AL : Attrs) {
+ if (AL.getKind() == Kind && !AL.isInvalid() && AL.getNumArgs() == 1) {
+ VTL.setAttrNameLoc(AL.getLoc());
+ VTL.setSizeExpr(AL.getArgAsExpr(0));
+ return;
+ }
+ }
+
+ // The attribute may be on the declarator rather than this chunk, or the
+ // vector may use a target-specific attribute. Keep the default locations
+ // when no matching attribute is present.
+}
+
static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
SourceLocation Loc;
switch (Chunk.Kind) {
@@ -6358,19 +6378,19 @@ namespace {
void VisitMacroQualifiedTypeLoc(MacroQualifiedTypeLoc TL) {
TL.setExpansionLoc(Chunk.Loc);
}
- void VisitVectorTypeLoc(VectorTypeLoc TL) { TL.setNameLoc(Chunk.Loc); }
- void VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) {
- TL.setNameLoc(Chunk.Loc);
+ void VisitVectorTypeLoc(VectorTypeLoc TL) {
+ TL.initializeLocal(Context, Chunk.Loc);
+ fillVectorTypeLoc(TL, Chunk.getAttrs());
}
- void VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
- TL.setNameLoc(Chunk.Loc);
+ void VisitDependentVectorTypeLoc(DependentVectorTypeLoc TL) {
+ TL.initializeLocal(Context, Chunk.Loc);
}
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
fillAtomicQualLoc(TL, Chunk);
}
void
VisitDependentSizedExtVectorTypeLoc(DependentSizedExtVectorTypeLoc TL) {
- TL.setNameLoc(Chunk.Loc);
+ TL.initializeLocal(Context, Chunk.Loc);
}
void VisitMatrixTypeLoc(MatrixTypeLoc TL) {
fillMatrixTypeLoc(TL, Chunk.getAttrs());
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 73367d6bea063..39a7c168b28f6 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -6215,14 +6215,17 @@ QualType TreeTransform<Derived>::TransformDependentVectorType(
EnterExpressionEvaluationContext Unevaluated(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+ Expr *OrigSize = TL.getSizeExpr();
+ if (!OrigSize)
+ OrigSize = T->getSizeExpr();
+ ExprResult Size = getDerived().TransformExpr(OrigSize);
Size = SemaRef.ActOnConstantExpression(Size);
if (Size.isInvalid())
return QualType();
QualType Result = TL.getType();
if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() ||
- Size.get() != T->getSizeExpr()) {
+ Size.get() != OrigSize) {
Result = getDerived().RebuildDependentVectorType(
ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind());
if (Result.isNull())
@@ -6234,9 +6237,13 @@ QualType TreeTransform<Derived>::TransformDependentVectorType(
DependentVectorTypeLoc NewTL =
TLB.push<DependentVectorTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.setAttrNameLoc(TL.getAttrNameLoc());
+ NewTL.setSizeExpr(Size.get());
} else {
VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.setAttrNameLoc(TL.getAttrNameLoc());
+ NewTL.setSizeExpr(Size.get());
}
return Result;
@@ -6248,7 +6255,6 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
DependentSizedExtVectorTypeLoc TL) {
const DependentSizedExtVectorType *T = TL.getTypePtr();
- // FIXME: ext vector locs should be nested
QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());
if (ElementType.isNull())
return QualType();
@@ -6257,18 +6263,19 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
EnterExpressionEvaluationContext Unevaluated(
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
+ Expr *OrigSize = TL.getSizeExpr();
+ if (!OrigSize)
+ OrigSize = T->getSizeExpr();
+ ExprResult Size = getDerived().TransformExpr(OrigSize);
Size = SemaRef.ActOnConstantExpression(Size);
if (Size.isInvalid())
return QualType();
QualType Result = TL.getType();
- if (getDerived().AlwaysRebuild() ||
- ElementType != T->getElementType() ||
- Size.get() != T->getSizeExpr()) {
- Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,
- Size.get(),
- T->getAttributeLoc());
+ if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() ||
+ Size.get() != OrigSize) {
+ Result = getDerived().RebuildDependentSizedExtVectorType(
+ ElementType, Size.get(), T->getAttributeLoc());
if (Result.isNull())
return QualType();
}
@@ -6278,9 +6285,13 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
DependentSizedExtVectorTypeLoc NewTL
= TLB.push<DependentSizedExtVectorTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.setAttrNameLoc(TL.getAttrNameLoc());
+ NewTL.setSizeExpr(Size.get());
} else {
ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.setAttrNameLoc(TL.getAttrNameLoc());
+ NewTL.setSizeExpr(Size.get());
}
return Result;
@@ -6430,6 +6441,8 @@ QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB,
VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.setAttrNameLoc(TL.getAttrNameLoc());
+ NewTL.setSizeExpr(TL.getSizeExpr());
return Result;
}
@@ -6445,15 +6458,16 @@ 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.getAttrNameLoc());
if (Result.isNull())
return QualType();
}
ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result);
NewTL.setNameLoc(TL.getNameLoc());
+ NewTL.setAttrNameLoc(TL.getAttrNameLoc());
+ NewTL.setSizeExpr(TL.getSizeExpr());
return Result;
}
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 0a897a49d1165..dd0bf801fe548 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7666,19 +7666,25 @@ void TypeLocReader::VisitDependentAddressSpaceTypeLoc(
void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
DependentSizedExtVectorTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
+ TL.setAttrNameLoc(readSourceLocation());
+ TL.setSizeExpr(Reader.readExpr());
}
void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
+ TL.setAttrNameLoc(readSourceLocation());
+ TL.setSizeExpr(Reader.readExpr());
}
void TypeLocReader::VisitDependentVectorTypeLoc(
DependentVectorTypeLoc TL) {
TL.setNameLoc(readSourceLocation());
+ TL.setAttrNameLoc(readSourceLocation());
+ TL.setSizeExpr(Reader.readExpr());
}
void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
- TL.setNameLoc(readSourceLocation());
+ VisitVectorTypeLoc(TL);
}
void TypeLocReader::VisitConstantMatrixTypeLoc(ConstantMatrixTypeLoc TL) {
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 0afba1c84fd62..81b2849ec849f 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -433,19 +433,25 @@ void TypeLocWriter::VisitDependentAddressSpaceTypeLoc(
void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc(
DependentSizedExtVectorTypeLoc TL) {
addSourceLocation(TL.getNameLoc());
+ addSourceLocation(TL.getAttrNameLoc());
+ Record.AddStmt(TL.getSizeExpr());
}
void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
addSourceLocation(TL.getNameLoc());
+ addSourceLocation(TL.getAttrNameLoc());
+ Record.AddStmt(TL.getSizeExpr());
}
void TypeLocWriter::VisitDependentVectorTypeLoc(
DependentVectorTypeLoc TL) {
addSourceLocation(TL.getNameLoc());
+ addSourceLocation(TL.getAttrNameLoc());
+ Record.AddStmt(TL.getSizeExpr());
}
void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
- addSourceLocation(TL.getNameLoc());
+ VisitVectorTypeLoc(TL);
}
void TypeLocWriter::VisitConstantMatrixTypeLoc(ConstantMatrixTypeLoc TL) {
diff --git a/clang/test/PCH/cxx-dependent-sized-ext-vector.cpp b/clang/test/PCH/cxx-dependent-sized-ext-vector.cpp
index 93fb56161dfc0..23345a03c0663 100644
--- a/clang/test/PCH/cxx-dependent-sized-ext-vector.cpp
+++ b/clang/test/PCH/cxx-dependent-sized-ext-vector.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -std=c++11 -emit-pch %s -o %t
// RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s
+// RUN: not %clang_cc1 -std=c++11 -include-pch %t -fno-caret-diagnostics %s 2>&1 | FileCheck %s --implicit-check-not='error:'
// RUN: %clang_cc1 -std=c++11 -emit-pch -fpch-instantiate-templates %s -o %t
// RUN: %clang_cc1 -std=c++11 -include-pch %t -verify %s
@@ -9,13 +10,33 @@
#define HEADER_INCLUDED
template<typename T, int N>
+// CHECK: :[[#@LINE+1]]:30: error: zero vector size
using vec = T __attribute__((ext_vector_type(N)));
+struct S {};
+
+template <class T>
+// CHECK: :[[#@LINE+1]]:1: error: invalid vector element type 'S'
+using Alias = T __attribute__((ext_vector_type(4)));
+
+template <class T, int N>
+// CHECK: :[[#@LINE+1]]:32: error: invalid vector element type 'S'
+using Sized = T __attribute__((vector_size(N)));
+
+template <class T> struct Attributed {
+ // CHECK: :[[#@LINE+1]]:29: error: invalid vector element type 'S'
+ typedef T (__attribute__((ext_vector_type(4))) Type);
+};
+
#else
void test() {
- vec<float, 2> a; // expected-error at -5 {{zero vector size}}
+ vec<float, 2> a; // expected-error at -20 {{zero vector size}}
vec<float, 0> b; // expected-note {{in instantiation of template type alias 'vec' requested here}}
}
+Alias<S> alias; // expected-error at -18 {{invalid vector element type 'S'}} expected-note {{in instantiation of template type alias 'Alias' requested here}}
+Sized<S, 16> invalid_sized; // expected-error at -15 {{invalid vector element type 'S'}} expected-note {{in instantiation of template type alias 'Sized' requested here}}
+Attributed<S> attributed; // expected-error at -12 {{invalid vector element type 'S'}} expected-note {{in instantiation of template class 'Attributed<S>' requested here}}
+
#endif
diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp
index fd6127a33f1ae..6ae7d3103d3f5 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 -fno-caret-diagnostics %s 2>&1 | FileCheck %s
typedef char char16 __attribute__ ((__vector_size__ (16)));
typedef long long longlong16 __attribute__ ((__vector_size__ (16)));
@@ -346,8 +347,8 @@ typedef ScopedE ScopedEnumSizeVector __attribute__((vector_size(16))); // expect
#endif
template <typename T> struct Vector {
- // Rebuilding a fixed-size extended vector currently loses the attribute location.
- typedef T type __attribute__((ext_vector_type(4))); // expected-error@*:* {{invalid vector element type 'GH225037::E'}}
+ // CHECK: :[[#@LINE+1]]:11: error: invalid vector element type 'GH225037::E'
+ typedef T type __attribute__((ext_vector_type(4))); // expected-error {{invalid vector element type 'GH225037::E'}}
};
Vector<E> enum_vector; // expected-note {{in instantiation of template class 'GH225037::Vector<GH225037::E>' requested here}}
Vector<int> int_vector;
@@ -546,6 +547,7 @@ namespace PR48540 {
// The below used to cause an OOM error, or an assert, make sure it is still
// valid.
int (__attribute__((vector_size(16))) a);
+int (parenthesized_vector) __attribute__((vector_size(16)));
template <typename T, int I>
struct S {
diff --git a/clang/test/SemaTemplate/ext-vector-type.cpp b/clang/test/SemaTemplate/ext-vector-type.cpp
index f968c13f10238..6d4a250361aa7 100644
--- a/clang/test/SemaTemplate/ext-vector-type.cpp
+++ b/clang/test/SemaTemplate/ext-vector-type.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: not %clang_cc1 -std=c++11 -fsyntax-only -fno-caret-diagnostics %s 2>&1 | FileCheck %s
template<typename T, unsigned Length>
struct make1 {
typedef T __attribute__((ext_vector_type(Length))) type;
@@ -92,3 +93,30 @@ namespace Deduction {
int array2[X0<float2>::value == 2? 1 : -1];
int array3[X0<float4>::value == 3? 1 : -1];
}
+
+// The primary error should retain a source location, independently of the
+// template instantiation notes.
+struct S {};
+
+template <class T> struct Parenthesized {
+ typedef T (Type)
+ // CHECK: :[[#@LINE-1]]:13: error: invalid vector element type 'S'
+ __attribute__((ext_vector_type(4))); // expected-error at -2 {{invalid vector element type 'S'}}
+};
+Parenthesized<S> parenthesized; // expected-note {{in instantiation of template class 'Parenthesized<S>' requested here}}
+
+template <class T>
+// CHECK: :[[#@LINE+1]]:1: error: invalid vector element type 'S'
+using Alias = T __attribute__((ext_vector_type(4))); // expected-error {{invalid vector element type 'S'}}
+Alias<S> alias; // expected-note {{in instantiation of template type alias 'Alias' requested here}}
+Alias<int> valid_alias;
+
+// The source location must also survive conversion from a dependent-sized
+// vector to a fixed-size vector whose element type is still dependent.
+template <int N> struct TwoStage {
+ template <class T>
+ // CHECK: :[[#@LINE+1]]:3: error: invalid vector element type 'S'
+ using Type = T __attribute__((ext_vector_type(N))); // expected-error {{invalid vector element type 'S'}}
+};
+TwoStage<4>::Type<S> two_stage; // expected-note {{in instantiation of template type alias 'Type' requested here}}
+TwoStage<4>::Type<int> valid_two_stage;
diff --git a/clang/unittests/AST/SourceLocationTest.cpp b/clang/unittests/AST/SourceLocationTest.cpp
index 021b2dfac4060..671cb8b809154 100644
--- a/clang/unittests/AST/SourceLocationTest.cpp
+++ b/clang/unittests/AST/SourceLocationTest.cpp
@@ -230,6 +230,35 @@ TEST(TypeLoc, LongRange) {
EXPECT_TRUE(Verifier.match("long a;", typeLoc()));
}
+TEST(TypeLoc, VectorSourceInfo) {
+ llvm::Annotations Code(R"cpp(
+ typedef int (__attribute__(($Vector^vector_size($VectorSize[[8 * 2]]))) Vector);
+ typedef int (__attribute__(($Extended^ext_vector_type($ExtendedSize[[4]]))) Extended);
+ )cpp");
+ auto AST = tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{});
+ ASSERT_TRUE(AST);
+
+ ASTContext &Ctx = AST->getASTContext();
+ const SourceManager &SM = Ctx.getSourceManager();
+ auto Matches = match(
+ typedefNameDecl(hasAnyName("Vector", "Extended")).bind("decl"), Ctx);
+ ASSERT_EQ(Matches.size(), 2u);
+ for (const auto &Match : Matches) {
+ const auto *Decl = Match.getNodeAs<TypedefNameDecl>("decl");
+ std::string Name = Decl->getNameAsString();
+ auto TL = Decl->getTypeSourceInfo()->getTypeLoc().getAs<VectorTypeLoc>();
+ ASSERT_TRUE(TL) << Name;
+ ASSERT_TRUE(TL.getAttrNameLoc().isValid()) << Name;
+ EXPECT_EQ(SM.getFileOffset(TL.getAttrNameLoc()), Code.point(Name)) << Name;
+ ASSERT_TRUE(TL.getSizeExpr()) << Name;
+ auto Range = Lexer::getAsCharRange(TL.getSizeExpr()->getSourceRange(), SM,
+ Ctx.getLangOpts());
+ auto Expected = Code.range(Name + "Size");
+ EXPECT_EQ(SM.getFileOffset(Range.getBegin()), Expected.Begin) << Name;
+ EXPECT_EQ(SM.getFileOffset(Range.getEnd()), Expected.End) << Name;
+ }
+}
+
TEST(TypeLoc, DecltypeTypeLocRange) {
llvm::Annotations Code(R"(
$full1[[decltype(1)]] a;
>From 9876a47a783d7e60981307b84b82bc0df6571a58 Mon Sep 17 00:00:00 2001
From: Chen Miao <chenmiao.ku at gmail.com>
Date: Sun, 11 Oct 2026 01:43:32 +0800
Subject: [PATCH 5/5] [clang] Format DependentVectorTypeLoc declaration
---
clang/include/clang/AST/TypeLoc.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index d19b91a62e572..5cc50f84eff8f 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2119,7 +2119,6 @@ class DependentVectorTypeLoc
: public ConcreteTypeLoc<UnqualTypeLoc, DependentVectorTypeLoc,
DependentVectorType, VectorTypeLocInfo> {
public:
-
/// The location used for the vector type's local source range, e.g.
/// T __attribute__((vector_size(N)))
/// ^
More information about the cfe-commits
mailing list