llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-debuginfo Author: Yeoul Na (rapidsna) <details> <summary>Changes</summary> This commit implements proper handling of bounds-safety attributes (counted_by, counted_by_or_null, sized_by, sized_by_or_null) when they appear in type attribute positions, correctly treating them as type attributes rather than declaration attributes. Previously, these attributes in type positions (e.g., `int * __counted_by(count) buf`) were incorrectly treated as declaration attributes, leading to: 1. Inability to reference struct members declared later (in late-parse mode) 2. Incorrect acceptance of attributes on nested pointer types 3. Attributes being attached to the wrong type level This commit ensures that these attributes are correctly added to type positions even when it's not late parsed. The key changes: - Introduce LateParsedAttrType placeholder type to defer attribute processing until the complete struct definition is available (for late-parse mode). The placeholder is then transformed to a concrete type (e.g., CountAttributedType) via TreeTransform - Move LateParsedDeclaration and LateParsedAttribute types to DeclSpec.h out of Parser, so these types can be used in DeclSpec and Declarator and DeclChunk (forward declaration did not work because these are nested classes of Parser) - Introduce LateParsedTypeAttribute which is a child of LateParsedAttribute to make it clear when late parsed attribute is handled as type attribute - Add LateParsedAttribute vector to DeclaratorChunk, Declarator, and DeclSpec to track late type attributes at each declarator level, similar to existing ParsedAttr handling - Implement proper attribute distribution to nested type levels during type construction in GetTypeForDeclarator - Add more semantic checks to reject attributes on nested pointers Issue #<!-- -->166411 --- Patch is 148.46 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/179612.diff 46 Files Affected: - (modified) clang/include/clang/AST/ASTContext.h (+7) - (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+6) - (modified) clang/include/clang/AST/TypeBase.h (+41) - (modified) clang/include/clang/AST/TypeLoc.h (+21) - (modified) clang/include/clang/AST/TypeProperties.td (+8) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3) - (modified) clang/include/clang/Basic/TypeNodes.td (+1) - (modified) clang/include/clang/Parse/Parser.h (+25-73) - (modified) clang/include/clang/Sema/DeclSpec.h (+162-8) - (modified) clang/include/clang/Sema/Sema.h (+4-1) - (modified) clang/lib/AST/ASTContext.cpp (+17) - (modified) clang/lib/AST/ASTImporter.cpp (+7) - (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+7) - (modified) clang/lib/AST/ItaniumMangle.cpp (+1) - (modified) clang/lib/AST/TypeLoc.cpp (+9) - (modified) clang/lib/AST/TypePrinter.cpp (+15) - (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+1) - (modified) clang/lib/CodeGen/CodeGenFunction.cpp (+1) - (modified) clang/lib/Parse/ParseCXXInlineMethods.cpp (+12-7) - (modified) clang/lib/Parse/ParseDecl.cpp (+148-29) - (modified) clang/lib/Sema/Sema.cpp (+2-1) - (modified) clang/lib/Sema/SemaBoundsSafety.cpp (+77-3) - (modified) clang/lib/Sema/SemaDecl.cpp (+321-1) - (modified) clang/lib/Sema/SemaDeclAttr.cpp (+3-49) - (modified) clang/lib/Sema/SemaExpr.cpp (+1) - (modified) clang/lib/Sema/SemaType.cpp (+234-1) - (modified) clang/lib/Sema/TreeTransform.h (+18) - (modified) clang/lib/Serialization/ASTReader.cpp (+4) - (modified) clang/lib/Serialization/ASTWriter.cpp (+6) - (modified) clang/test/AST/attr-counted-by-or-null-struct-ptrs.c (-23) - (modified) clang/test/AST/attr-counted-by-struct-ptrs.c (-26) - (modified) clang/test/AST/attr-sized-by-or-null-struct-ptrs.c (-24) - (modified) clang/test/AST/attr-sized-by-struct-ptrs.c (-24) - (added) clang/test/Sema/attr-bounds-safety-function-ptr-param.c (+173) - (modified) clang/test/Sema/attr-counted-by-late-parsed-struct-ptrs.c (+28-46) - (modified) clang/test/Sema/attr-counted-by-or-null-last-field.c (+1-3) - (modified) clang/test/Sema/attr-counted-by-or-null-late-parsed-struct-ptrs.c (+14-46) - (modified) clang/test/Sema/attr-counted-by-or-null-struct-ptrs-completable-incomplete-pointee.c (+17-20) - (modified) clang/test/Sema/attr-counted-by-or-null-struct-ptrs.c (+8-6) - (modified) clang/test/Sema/attr-counted-by-struct-ptrs-completable-incomplete-pointee.c (+15-17) - (modified) clang/test/Sema/attr-counted-by-struct-ptrs.c (+10-8) - (modified) clang/test/Sema/attr-sized-by-late-parsed-struct-ptrs.c (+12-38) - (modified) clang/test/Sema/attr-sized-by-or-null-late-parsed-struct-ptrs.c (+15-38) - (modified) clang/test/Sema/attr-sized-by-or-null-struct-ptrs.c (+8-6) - (modified) clang/test/Sema/attr-sized-by-struct-ptrs.c (+8-4) - (modified) clang/tools/libclang/CIndex.cpp (+4) ``````````diff diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 68205dd1c1fd9..ac70c99d855c1 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -101,6 +101,7 @@ class CXXConstructorDecl; class CXXMethodDecl; class CXXRecordDecl; class DiagnosticsEngine; +struct LateParsedTypeAttribute; class DynTypedNodeList; class Expr; enum class FloatModeKind; @@ -1584,6 +1585,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 ddec2c52fb681..49e3a870fc10d 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -1154,6 +1154,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())); }) @@ -1509,6 +1512,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 b0fdf178ab3cc..f061ad89f3632 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, @@ -3484,6 +3485,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 2cefaa9611c98..85d6937f3bbb9 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -1329,6 +1329,27 @@ class CountAttributedTypeLoc final SourceRange getLocalSourceRange() const; }; +struct LateParsedAttrLocInfo {}; // Nothing. + +class LateParsedAttrTypeLoc + : public ConcreteTypeLoc<UnqualTypeLoc, LateParsedAttrTypeLoc, + LateParsedAttrType, LateParsedAttrLocInfo> { +public: + TypeLoc getInnerLoc() const { return getInnerTypeLoc(); } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + // Nothing to initialize + } + + SourceRange getLocalSourceRange() const; + + 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 b150ac2e1cbe3..854752f0fcb30 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -44,6 +44,14 @@ 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. If serialized, we just + // serialize the wrapped type, losing the late-parsed attribute pointer + // (which wouldn't be valid after deserialization anyway). + 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/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4f7934b328d9f..63d6c30f9faca 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7065,6 +7065,9 @@ def err_builtin_counted_by_ref_invalid_use : Error< "value returned by '__builtin_counted_by_ref' cannot be used in " "%select{an array subscript|a binary}0 expression">; +def err_counted_by_on_nested_pointer : Error< + "'%select{counted_by|sized_by|counted_by_or_null|sized_by_or_null}0' attribute on nested pointer type is not allowed">; + let CategoryName = "ARC Semantic Issue" in { // ARC-mode diagnostics. diff --git a/clang/include/clang/Basic/TypeNodes.td b/clang/include/clang/Basic/TypeNodes.td index db43a8529f02b..b65fa0d5b786d 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/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index e03d7994e2fa5..560eeca13623e 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -197,6 +197,8 @@ class Parser : public CodeCompletionHandler { friend class PoisonSEHIdentifiersRAIIObject; friend class ParenBraceBracketBalancer; friend class BalancedDelimiterTracker; + friend struct LateParsedAttribute; + friend struct LateParsedTypeAttribute; Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); ~Parser() override; @@ -942,7 +944,6 @@ class Parser : public CodeCompletionHandler { void SkipFunctionBody(); struct ParsedTemplateInfo; - class LateParsedAttrList; /// ParseFunctionDefinition - We parsed and verified that the specified /// Declarator is well formed. If this is a K&R-style function, read the @@ -1107,25 +1108,6 @@ class Parser : public CodeCompletionHandler { private: struct ParsingClass; - /// [class.mem]p1: "... the class is regarded as complete within - /// - function bodies - /// - default arguments - /// - exception-specifications (TODO: C++0x) - /// - and brace-or-equal-initializers for non-static data members - /// (including such things in nested classes)." - /// LateParsedDeclarations build the tree of those elements so they can - /// be parsed after parsing the top-level class. - class LateParsedDeclaration { - public: - virtual ~LateParsedDeclaration(); - - virtual void ParseLexedMethodDeclarations(); - virtual void ParseLexedMemberInitializers(); - virtual void ParseLexedMethodDefs(); - virtual void ParseLexedAttributes(); - virtual void ParseLexedPragmas(); - }; - /// Inner node of the LateParsedDeclaration tree that parses /// all its members recursively. class LateParsedClass : public LateParsedDeclaration { @@ -1148,29 +1130,6 @@ class Parser : public CodeCompletionHandler { ParsingClass *Class; }; - /// Contains the lexed tokens of an attribute with arguments that - /// may reference member variables and so need to be parsed at the - /// end of the class declaration after parsing all other member - /// member declarations. - /// FIXME: Perhaps we should change the name of LateParsedDeclaration to - /// LateParsedTokens. - struct LateParsedAttribute : public LateParsedDeclaration { - Parser *Self; - CachedTokens Toks; - IdentifierInfo &AttrName; - IdentifierInfo *MacroII = nullptr; - SourceLocation AttrNameLoc; - SmallVector<Decl *, 2> Decls; - - explicit LateParsedAttribute(Parser *P, IdentifierInfo &Name, - SourceLocation Loc) - : Self(P), AttrName(Name), AttrNameLoc(Loc) {} - - void ParseLexedAttributes() override; - - void addDecl(Decl *D) { Decls.push_back(D); } - }; - /// Contains the lexed tokens of a pragma with arguments that /// may reference member variables and so need to be parsed at the /// end of the class declaration after parsing all other member @@ -1191,26 +1150,6 @@ class Parser : public CodeCompletionHandler { void ParseLexedPragmas() override; }; - // A list of late-parsed attributes. Used by ParseGNUAttributes. - class LateParsedAttrList : public SmallVector<LateParsedAttribute *, 2> { - public: - LateParsedAttrList(bool PSoon = false, - bool LateAttrParseExperimentalExtOnly = false) - : ParseSoon(PSoon), - LateAttrParseExperimentalExtOnly(LateAttrParseExperimentalExtOnly) {} - - bool parseSoon() { return ParseSoon; } - /// returns true iff the attribute to be parsed should only be late parsed - /// if it is annotated with `LateAttrParseExperimentalExt` - bool lateAttrParseExperimentalExtOnly() { - return LateAttrParseExperimentalExtOnly; - } - - private: - bool ParseSoon; // Are we planning to parse these shortly after creation? - bool LateAttrParseExperimentalExtOnly; - }; - /// Contains the lexed tokens of a member function definition /// which needs to be parsed at the end of the class declaration /// after parsing all other member declarations. @@ -1487,6 +1426,11 @@ class Parser : public CodeCompletionHandler { void ParseLexedCAttribute(LateParsedAttribute &LA, bool EnterScope, ParsedAttributes *OutAttrs = nullptr); + + void ParseLexedTypeAttribute(LateParsedTypeAttribute &LA, bool EnterScope, ParsedAttributes &OutAttrs); + + static void LateTypeAttrParserCallback(void *P, void *LA, bool EnterScope, ParsedAttributes &OutAttrs); + void ParseLexedPragmas(ParsingClass &Class); void ParseLexedPragma(LateParsedPragma &LP); @@ -1889,10 +1833,12 @@ class Parser : public CodeCompletionHandler { DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, LateParsedAttrList *LateAttrs = nullptr); - void ParseSpecifierQualifierList( - DeclSpec &DS, AccessSpecifier AS = AS_none, - DeclSpecContext DSC = DeclSpecContext::DSC_normal) { - ParseSpecifierQualifierList(DS, getImplicitTypenameContext(DSC), AS, DSC); + void + ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none, + DeclSpecContext DSC = DeclSpecContext::DSC_normal, + LateParsedAttrList *LateAttrs = nullptr) { + ParseSpecifierQualifierList(DS, getImplicitTypenameContext(DSC), AS, DSC, + LateAttrs); } /// ParseSpecifierQualifierList @@ -1903,10 +1849,12 @@ class Parser : public CodeCompletionHandler { /// [GNU] attributes specifier-qualifier-list[opt] /// \endverbatim /// - void ParseSpecifierQualifierList( - DeclSpec &DS, ImplicitTypenameContext AllowImplicitTypename, - AccessSpecifier AS = AS_none, - DeclSpecContext DSC = DeclSpecContext::DSC_normal); + void + ParseSpecifierQualifierList(DeclSpec &DS, + ImplicitTypenameContext AllowImplicitTypename, + AccessSpecifier AS = AS_none, + DeclSpecContext DSC = DeclSpecContext::DSC_normal, + LateParsedAttrList *LateAttrs = nullptr); /// ParseEnumSpecifier /// \verbatim @@ -2174,6 +2122,8 @@ class Parser : public CodeCompletionHandler { ParsedAttributes Attrs(AttrFactory); ParseGNUAttributes(Attrs, LateAttrs, &D); D.takeAttributesAppending(Attrs); + if (LateAttrs) + D.takeLateTypeAttributesAppending(*LateAttrs); } } @@ -2444,7 +2394,8 @@ class Parser : public CodeCompletionHandler { SourceLocation ScopeLoc, ParsedAttr::Form Form); - void DistributeCLateParsedAttrs(Decl *Dcl, LateParsedAttrList *LateAttrs); + void DistributeCLateParsedAttrs(Declarator &D, Decl *Dcl, + LateParsedAttrList *LateAttrs); /// Bounds attributes (e.g., counted_by): /// \verbatim @@ -2610,7 +2561,8 @@ class Parser : public CodeCompletionHandler { void ParseTypeQualifierListOpt( DeclSpec &DS, unsigned AttrReqs = AR_AllAttributesParsed, bool AtomicOrPtrauthAllowed = true, bool IdentifierRequired = false, - llvm::function_ref<void()> CodeCompletionHandler = {}); + llvm::function_ref<void()> CodeCompletionHandler = {}, + LateParsedAttrList *LateAttrs = nullptr); /// ParseDirectDeclarator /// \verbatim diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 43a48c92fc305..a44757664a58d 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -49,6 +49,138 @@ namespace clang { class Sema; class Declarator; struct TemplateIdAnnotation; + class Parser; + + /// A set of tokens that has been cached for later parsing. + typedef SmallVector<Token, 4> CachedTokens; + + /// [class.mem]p1: "... the class is regarded as complete within + /// - function bodies + /// - default arguments + /// - exception-specifications (TODO: C++0x) + /// - and brace-or-equal-initializers for non-static data members + /// (including such things in nested classes)." + /// LateParsedDeclarations build the tree of those elements so they can + /// be parsed after parsing the top-level class. + class LateParsedDeclaration { + public: + virtual ~LateParsedDeclaration(); + + virtual void ParseLexedMethodDeclarations(); + virtual void ParseLexedMemberInitializers(); + virtual void ParseLexedMethodDefs(); + virtual void ParseLexedAttributes(); + virtual void ParseLexedTypeAttributes(); + virtual void ParseLexedPragmas(); + }; + +/// Contains the lexed tokens of an attribute with arguments that +/// may reference member variables and so need to be parsed at the +/// end of the class declaration after parsing all other member +/// member declarations. +/// FIXME: Perhaps we should change the name of LateParsedDeclaration to +/// LateParsedTokens. +struct LateParsedAttribute : public LateParsedDeclaration { + + enum LPA_Kind { + LPA_Declaration, + LPA_Type, + }; + + Parser *Self; + CachedTokens Toks; + IdentifierInfo &AttrName; + IdentifierInfo *MacroII = nullptr; + SourceLocation AttrNameLoc; + SmallVector<Decl *, 2> Decls; + +private: + LPA_Kind Kind; + +public: + explicit LateParsedAttribute(Parser *P, IdentifierInfo &Name, + SourceLocation Loc, + LPA_Kind Kind = LPA_Declaration) + : Self(P), AttrName(Name), AttrNameLoc(Loc), Kind(Kind) {} + + void ParseLexedAttributes() override; + + void addDecl(Decl *D) { Decls.push_back(D); } + + LPA_Kind getKind() const { return Kind; } + + // LLVM-style RTTI support + static bool classof(const LateParsedAttribute* LA) { + // LateParsedAttribute matches both Declaration and Type kinds + return LA->getKind() == LPA_Declaration || LA->getKind() == LPA_Type; + } +}; + +/// Contains the lexed tokens of an attribute with arguments that +/// may reference member variables and so need to be parsed at the +/// end of the class declaration after parsing all other member +/// member declarations. +/// FIXME: Perhaps we should change the name of LateParsedDeclaration to +/// LateParsedTokens. +struct LateParsedTypeAttribute : public LateParsedAttribute { + + explicit LateParsedTypeAttribute(Parser *P, IdentifierInfo &Name, + SourceLocation Loc) + : LateParsedAttribute(P, Name, Loc, LPA_Type) {} + + void ParseLexedAttributes() override; + void ParseLexedTypeAttributes() override; + + void addDecl(Decl *D) { Decls.push_back(D); } + + /// Parse this late-parsed type attribute and store results in OutAttrs. + /// This method can be called from Sema during type transformation to + /// parse the cached tokens and produce the final attribute. + void ParseInto(ParsedAttributes &OutAttrs); + + // LLVM-style RTTI support + static bool classof(const LateParsedAttribute* LA) { + return LA->getKind() == LPA_Type; + } +}; + +// A list of late-parsed attributes. Used by ParseGNUAttributes. +class LateParsedAttrList : public SmallVector<LateParsedAttribute *, 2> { +public: + LateParsedAttrList(bool PSoon = false, + bool LateAttrParseExperimentalExtOnly = false, + bool LateAttrParseTypeAttrOnly = false) + : ParseSoon(PSoon), + LateAttrParseExperimentalExtOnly(LateAttrParseExperimentalExtOnly), + LateAttrParseTypeAttrOnly(LateAttrParseTypeAttrOnly) {} + + bool parseSoon() { return ParseSoon; } + /// returns true iff the attribute to be parsed should only be late parsed + /// if it is annotated with `LateAttrParseExperimentalExt` + bool lateAttrParseExperimentalExtOnly() { + return LateAttrParseExperimentalExtOnly; + } + + bool lateAttrParseTypeAttrOnly() { + return LateAttrParseTypeAttrOnly; + } + + void takeTypeAttrsAppendingFrom(LateParsedAttrList &Other) { + auto it = std::remove_if(Other.begin(), Other.end(), [&](LateParsedAttribute *LA){ + if (auto *LTA = dyn_cast<LateParsedTypeAttribute>(LA)) { + push_back(LTA); + return true; + } + return false; + }); + Other.erase(it, Other.end()); + } + +private: + bool ParseSoon; // Are we planning to parse these shortly after creation? + bool LateAttrParseExperimentalExtOnly; + bool LateAttrParseTypeAttrOnly; +}; /// Represents a C++ nested-name-specifier or a global scope specifier. /// @@ -391,6 +523,9 @@ class DeclSpec { // attributes. ParsedAttributes Attrs; + // late attributes + LateParsedAttrList LateParsedAttrs; + // Scope specifier for the type spec, if applicable. CXXScopeSpec TypeScope; @@ -465,7 +600,7 @@ class DeclSpec { FS_noreturn_specified(false), Frien... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/179612 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
