https://github.com/Holo-xy created https://github.com/llvm/llvm-project/pull/204125
resolves: https://github.com/swiftlang/llvm-project/issues/13000 >From de5b08460f7fa330dedf287e2abf06dd4ddcb0d4 Mon Sep 17 00:00:00 2001 From: Holo-xy <[email protected]> Date: Sat, 13 Jun 2026 06:46:32 +0300 Subject: [PATCH] Introduce LateParsedAttrType AST placeholder type --- clang/include/clang/AST/ASTContext.h | 6 +++ clang/include/clang/AST/RecursiveASTVisitor.h | 6 +++ clang/include/clang/AST/TypeBase.h | 41 +++++++++++++++++++ clang/include/clang/AST/TypeLoc.h | 31 ++++++++++++++ clang/include/clang/AST/TypeProperties.td | 6 +++ clang/include/clang/Basic/TypeNodes.td | 1 + clang/lib/AST/ASTContext.cpp | 15 +++++++ clang/lib/AST/ASTImporter.cpp | 7 ++++ clang/lib/AST/ASTStructuralEquivalence.cpp | 7 ++++ clang/lib/AST/ItaniumMangle.cpp | 1 + clang/lib/AST/TypePrinter.cpp | 15 +++++++ clang/lib/Sema/TreeTransform.h | 20 +++++++++ clang/lib/Serialization/ASTReader.cpp | 4 ++ clang/lib/Serialization/ASTWriter.cpp | 7 ++++ clang/tools/libclang/CIndex.cpp | 4 ++ 15 files changed, 171 insertions(+) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index a4ed852d36442..2095bc1a1df67 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1630,6 +1630,12 @@ class ASTContext : public RefCountedBase<ASTContext> { bool OrNull, ArrayRef<TypeCoupledDeclRefInfo> DependentDecls) const; + /// Return a placeholder type for a late-parsed type attribute. + /// This type wraps another type and holds the LateParsedAttribute + /// that will be parsed later. + QualType getLateParsedAttrType(QualType Wrapped, + LateParsedTypeAttribute *LateParsedAttr) const; + /// Return the uniqued reference to a type adjusted from the original /// type to a new type. QualType getAdjustedType(QualType Orig, QualType New) const; diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 529d657fc01f5..5a72ef0f17785 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1164,6 +1164,9 @@ DEF_TRAVERSE_TYPE(CountAttributedType, { TRY_TO(TraverseType(T->desugar())); }) +DEF_TRAVERSE_TYPE(LateParsedAttrType, + { TRY_TO(TraverseType(T->getWrappedType())); }) + DEF_TRAVERSE_TYPE(BTFTagAttributedType, { TRY_TO(TraverseType(T->getWrappedType())); }) @@ -1522,6 +1525,9 @@ DEF_TRAVERSE_TYPELOC(AttributedType, DEF_TRAVERSE_TYPELOC(CountAttributedType, { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) +DEF_TRAVERSE_TYPELOC(LateParsedAttrType, + { TRY_TO(TraverseTypeLoc(TL.getInnerLoc())); }) + DEF_TRAVERSE_TYPELOC(BTFTagAttributedType, { TRY_TO(TraverseTypeLoc(TL.getWrappedLoc())); }) diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index e3844d0cefa78..dd46a58a6fa50 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -70,6 +70,7 @@ class TagDecl; class TemplateParameterList; class Type; class Attr; +struct LateParsedTypeAttribute; enum { TypeAlignmentInBits = 4, @@ -3545,6 +3546,46 @@ class CountAttributedType final StringRef getAttributeName(bool WithMacroPrefix) const; }; +/// Represents a placeholder type for late-parsed type attributes. +/// This type wraps another type and holds an opaque pointer to a +/// LateParsedAttribute that will be parsed later (e.g., in ActOnFields). +/// Once parsed, this type is replaced with the appropriate attributed type +/// (e.g., CountAttributedType for counted_by). +class LateParsedAttrType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; // ASTContext creates these. + + QualType WrappedTy; + LateParsedTypeAttribute *LateParsedTypeAttr; + + LateParsedAttrType(QualType Wrapped, QualType Canon, + LateParsedTypeAttribute *Attr) + : Type(LateParsedAttr, Canon, Wrapped->getDependence()), + WrappedTy(Wrapped), LateParsedTypeAttr(Attr) {} + +public: + QualType getWrappedType() const { return WrappedTy; } + LateParsedTypeAttribute *getLateParsedAttribute() const { + return LateParsedTypeAttr; + } + + bool isSugared() const { return true; } + QualType desugar() const { return WrappedTy; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, WrappedTy, LateParsedTypeAttr); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType Wrapped, + LateParsedTypeAttribute *Attr) { + ID.AddPointer(Wrapped.getAsOpaquePtr()); + ID.AddPointer(Attr); + } + + static bool classof(const Type *T) { + return T->getTypeClass() == LateParsedAttr; + } +}; + /// Represents a type which was implicitly adjusted by the semantic /// engine for arbitrary reasons. For example, array and function types can /// decay, and function types can have their calling conventions adjusted. diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 24df18dbaace4..2648806ac687a 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -1358,6 +1358,37 @@ class CountAttributedTypeLoc final SourceRange getLocalSourceRange() const; }; +struct LateParsedAttrLocInfo { + SourceLocation AttrNameLoc; +}; + +class LateParsedAttrTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, LateParsedAttrTypeLoc, + LateParsedAttrType, LateParsedAttrLocInfo> { +public: + TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } + + SourceLocation getAttrNameLoc() const { return getLocalData()->AttrNameLoc; } + + void setAttrNameLoc(SourceLocation Loc) { getLocalData()->AttrNameLoc = Loc; } + + SourceRange getLocalSourceRange() const { + return SourceRange(getAttrNameLoc(), getAttrNameLoc()); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setAttrNameLoc(Loc); + } + + unsigned getLocalDataSize() const { return sizeof(LateParsedAttrLocInfo); } + + QualType getInnerType() const { return getTypePtr()->getWrappedType(); } + + LateParsedTypeAttribute *getLateParsedAttribute() const { + return getTypePtr()->getLateParsedAttribute(); + } +}; + struct MacroQualifiedLocInfo { SourceLocation ExpansionLoc; }; diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index f16c10da430f9..c5402a1925d99 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -44,6 +44,12 @@ let Class = CountAttributedType in { def : Creator<[{ return ctx.getCountAttributedType(WrappedTy, CountExpr, CountInBytes, OrNull, CoupledDecls); }]>; } +let Class = LateParsedAttrType in { + // Note: LateParsedAttrType is a transient placeholder type that should + // normally be replaced before serialization. So this won't be serialized. + def : Creator<[{ (void)ctx; llvm_unreachable("unreachable for serialization"); }]>; +} + let Class = AdjustedType in { def : Property<"originalType", QualType> { let Read = [{ node->getOriginalType() }]; diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index a9965a4a89aa1..700a73f669690 100644 --- a/clang/include/clang/Basic/TypeNodes.td +++ b/clang/include/clang/Basic/TypeNodes.td @@ -105,6 +105,7 @@ def ObjCInterfaceType : TypeNode<ObjCObjectType>, AlwaysCanonical; def ObjCObjectPointerType : TypeNode<Type>; def BoundsAttributedType : TypeNode<Type, 1>; def CountAttributedType : TypeNode<BoundsAttributedType>, NeverCanonical; +def LateParsedAttrType : TypeNode<Type>, NeverCanonical; def PipeType : TypeNode<Type>; def AtomicType : TypeNode<Type>; def BitIntType : TypeNode<Type>; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index abf0cd5e18c2b..00818d94c3370 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3751,6 +3751,17 @@ QualType ASTContext::getCountAttributedType( return QualType(CATy, 0); } +QualType ASTContext::getLateParsedAttrType( + QualType WrappedTy, LateParsedTypeAttribute *LateParsedAttr) const { + QualType CanonTy = getCanonicalType(WrappedTy); + + auto *LPATy = new (*this, alignof(LateParsedAttrType)) + LateParsedAttrType(WrappedTy, CanonTy, LateParsedAttr); + + Types.push_back(LPATy); + return QualType(LPATy, 0); +} + QualType ASTContext::adjustType(QualType Orig, llvm::function_ref<QualType(QualType)> Adjust) const { @@ -14920,6 +14931,10 @@ static QualType getCommonSugarTypeNode(const ASTContext &Ctx, const Type *X, DX->isCountInBytes(), DX->isOrNull(), CDX); } + + case Type::LateParsedAttr: + return QualType(); + case Type::PredefinedSugar: assert(cast<PredefinedSugarType>(X)->getKind() != cast<PredefinedSugarType>(Y)->getKind()); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index f5848d154f49e..d91da096b2466 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1842,6 +1842,13 @@ ASTNodeImporter::VisitCountAttributedType(const CountAttributedType *T) { ArrayRef(CoupledDecls)); } +ExpectedType +ASTNodeImporter::VisitLateParsedAttrType(const LateParsedAttrType *T) { + // LateParsedAttrType is a transient placeholder that should not normally + // appear during AST import. Import as the wrapped type. + return import(T->getWrappedType()); +} + ExpectedType ASTNodeImporter::VisitTemplateTypeParmType( const TemplateTypeParmType *T) { Expected<TemplateTypeParmDecl *> ToDeclOrErr = import(T->getDecl()); diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index e0b62591a6a73..d8bbfbe5dac72 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1208,6 +1208,13 @@ bool ASTStructuralEquivalence::isEquivalent( return false; break; + case Type::LateParsedAttr: + if (!IsStructurallyEquivalent( + Context, cast<LateParsedAttrType>(T1)->getWrappedType(), + cast<LateParsedAttrType>(T2)->getWrappedType())) + return false; + break; + case Type::BTFTagAttributed: if (!IsStructurallyEquivalent( Context, cast<BTFTagAttributedType>(T1)->getWrappedType(), diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index e5cdd6f31c507..60e77b66d92cf 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2472,6 +2472,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty, case Type::BitInt: case Type::DependentBitInt: case Type::CountAttributed: + case Type::LateParsedAttr: llvm_unreachable("type is illegal as a nested name specifier"); case Type::SubstBuiltinTemplatePack: diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index 53b869e019074..ae9838413ab44 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -288,6 +288,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T, case Type::MacroQualified: case Type::OverflowBehavior: case Type::CountAttributed: + case Type::LateParsedAttr: CanPrefixQualifiers = false; break; @@ -1832,6 +1833,20 @@ void TypePrinter::printCountAttributedAfter(const CountAttributedType *T, printCountAttributedImpl(T, OS, Policy); } +void TypePrinter::printLateParsedAttrBefore(const LateParsedAttrType *T, + raw_ostream &OS) { + // LateParsedAttrType is a transient placeholder that should not appear + // in user-facing output. Just print the wrapped type. + printBefore(T->getWrappedType(), OS); +} + +void TypePrinter::printLateParsedAttrAfter(const LateParsedAttrType *T, + raw_ostream &OS) { + // LateParsedAttrType is a transient placeholder that should not appear + // in user-facing output. Just print the wrapped type. + printAfter(T->getWrappedType(), OS); +} + void TypePrinter::printAttributedBefore(const AttributedType *T, raw_ostream &OS) { // FIXME: Generate this with TableGen. diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 53107c827006d..50a9d4feb9b6d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -7768,6 +7768,26 @@ QualType TreeTransform<Derived>::TransformCountAttributedType( return Result; } +template <typename Derived> +QualType +TreeTransform<Derived>::TransformLateParsedAttrType(TypeLocBuilder &TLB, + LateParsedAttrTypeLoc TL) { + const LateParsedAttrType *OldTy = TL.getTypePtr(); + QualType InnerTy = getDerived().TransformType(TLB, TL.getInnerLoc()); + if (InnerTy.isNull()) + return QualType(); + + QualType Result = TL.getType(); + if (getDerived().AlwaysRebuild() || InnerTy != OldTy->getWrappedType()) { + Result = SemaRef.Context.getLateParsedAttrType( + InnerTy, OldTy->getLateParsedAttribute()); + } + + LateParsedAttrTypeLoc newTL = TLB.push<LateParsedAttrTypeLoc>(Result); + newTL.setAttrNameLoc(TL.getAttrNameLoc()); + return Result; +} + template <typename Derived> QualType TreeTransform<Derived>::TransformBTFTagAttributedType( TypeLocBuilder &TLB, BTFTagAttributedTypeLoc TL) { diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index f8a6a38bb9b5c..5c8827ea32514 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7701,6 +7701,10 @@ void TypeLocReader::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { // Nothing to do } +void TypeLocReader::VisitLateParsedAttrTypeLoc(LateParsedAttrTypeLoc TL) { + // Nothing to do +} + void TypeLocReader::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { // Nothing to do. } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 21dda6f3733e4..2c56a052a5fb4 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -156,6 +156,9 @@ static TypeCode getTypeCodeForTypeClass(Type::TypeClass id) { #define TYPE_BIT_CODE(CLASS_ID, CODE_ID, CODE_VALUE) \ case Type::CLASS_ID: return TYPE_##CODE_ID; #include "clang/Serialization/TypeBitCodes.def" + case Type::LateParsedAttr: + llvm_unreachable( + "should be replaced with a concrete type before serialization"); case Type::Builtin: llvm_unreachable("shouldn't be serializing a builtin type this way"); } @@ -587,6 +590,10 @@ void TypeLocWriter::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { // Nothing to do } +void TypeLocWriter::VisitLateParsedAttrTypeLoc(LateParsedAttrTypeLoc TL) { + // Nothing to do +} + void TypeLocWriter::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { // Nothing to do. } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index ac2fad38a1348..42d4b5bef7fb8 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1738,6 +1738,10 @@ bool CursorVisitor::VisitCountAttributedTypeLoc(CountAttributedTypeLoc TL) { return Visit(TL.getInnerLoc()); } +bool CursorVisitor::VisitLateParsedAttrTypeLoc(LateParsedAttrTypeLoc TL) { + return Visit(TL.getInnerLoc()); +} + bool CursorVisitor::VisitBTFTagAttributedTypeLoc(BTFTagAttributedTypeLoc TL) { return Visit(TL.getWrappedLoc()); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
