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 <[email protected]> Date: Tue, 6 Oct 2026 15:15:31 +0800 Subject: [PATCH 1/4] [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 <[email protected]> Date: Tue, 6 Oct 2026 15:15:31 +0800 Subject: [PATCH 2/4] [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 <[email protected]> Date: Sat, 10 Oct 2026 10:07:17 +0800 Subject: [PATCH 3/4] [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 <[email protected]> Date: Sun, 11 Oct 2026 01:32:34 +0800 Subject: [PATCH 4/4] [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@-5 {{zero vector size}} + vec<float, 2> a; // expected-error@-20 {{zero vector size}} vec<float, 0> b; // expected-note {{in instantiation of template type alias 'vec' requested here}} } +Alias<S> alias; // expected-error@-18 {{invalid vector element type 'S'}} expected-note {{in instantiation of template type alias 'Alias' requested here}} +Sized<S, 16> invalid_sized; // expected-error@-15 {{invalid vector element type 'S'}} expected-note {{in instantiation of template type alias 'Sized' requested here}} +Attributed<S> attributed; // expected-error@-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@-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; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
