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