diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H #define LLVM_CLANG_SEMA_ATTRIBUTELIST_H +#include "clang/AST/Attr.h" #include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Diagnostic.h" @@ -116,9 +117,10 @@ /// class ParsedAttr final : public AttributeCommonInfo, - private llvm::TrailingObjects< - ParsedAttr, ArgsUnion, detail::AvailabilityData, - detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> { + private llvm::TrailingObjects { friend TrailingObjects; size_t numTrailingObjects(OverloadToken) const { return NumArgs; } @@ -135,6 +137,7 @@ size_t numTrailingObjects(OverloadToken) const { return IsProperty; } + size_t numTrailingObjects(OverloadToken) const { return HasAttrPtr; } private: IdentifierInfo *MacroII = nullptr; @@ -143,7 +146,7 @@ /// The number of expression arguments this attribute has. /// The expressions themselves are stored after the object. - unsigned NumArgs : 16; + unsigned NumArgs : 15; /// True if already diagnosed as invalid. mutable unsigned Invalid : 1; @@ -166,6 +169,9 @@ /// True if this has a ParsedType unsigned HasParsedType : 1; + /// True if this has an attribute pointer. + unsigned HasAttrPtr : 1; + /// True if the processing cache is valid. mutable unsigned HasProcessingCache : 1; @@ -207,7 +213,8 @@ EllipsisLoc(ellipsisLoc), NumArgs(numArgs), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), - HasProcessingCache(false), IsPragmaClangAttribute(false) { + HasAttrPtr(false), HasProcessingCache(false), + IsPragmaClangAttribute(false) { if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); } @@ -224,8 +231,9 @@ syntaxUsed), NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), - HasProcessingCache(false), IsPragmaClangAttribute(false), - UnavailableLoc(unavailable), MessageExpr(messageExpr) { + HasAttrPtr(false), HasProcessingCache(false), + IsPragmaClangAttribute(false), UnavailableLoc(unavailable), + MessageExpr(messageExpr) { ArgsUnion PVal(Parm); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); new (getAvailabilityData()) detail::AvailabilityData( @@ -241,7 +249,7 @@ syntaxUsed), NumArgs(3), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), - HasParsedType(false), HasProcessingCache(false), + HasParsedType(false), HasAttrPtr(false), HasProcessingCache(false), IsPragmaClangAttribute(false) { ArgsUnion *Args = getArgsBuffer(); Args[0] = Parm1; @@ -258,7 +266,7 @@ syntaxUsed), NumArgs(1), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(true), IsProperty(false), - HasParsedType(false), HasProcessingCache(false), + HasParsedType(false), HasAttrPtr(false), HasProcessingCache(false), IsPragmaClangAttribute(false) { ArgsUnion PVal(ArgKind); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); @@ -276,7 +284,7 @@ syntaxUsed), NumArgs(0), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), - HasParsedType(true), HasProcessingCache(false), + HasParsedType(true), HasAttrPtr(false), HasProcessingCache(false), IsPragmaClangAttribute(false) { new (&getTypeBuffer()) ParsedType(typeArg); } @@ -290,11 +298,26 @@ syntaxUsed), NumArgs(0), Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), - HasParsedType(false), HasProcessingCache(false), + HasParsedType(false), HasAttrPtr(false), HasProcessingCache(false), IsPragmaClangAttribute(false) { new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId); } + /// Constructor for attributes with a single non-parsed attribute pointer as + /// argument. + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + Attr *attrPtrArg, AttributeCommonInfo::Kind Kind, + Syntax syntaxUsed) + : AttributeCommonInfo(attrName, scopeName, attrRange, scopeLoc, Kind, + syntaxUsed, SpellingNotCalculated), + NumArgs(0), Invalid(false), UsedAsTypeAttr(false), + IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), + HasParsedType(false), HasAttrPtr(true), HasProcessingCache(false), + IsPragmaClangAttribute(false) { + new (&getAttrPtrBuffer())(Attr *)(attrPtrArg); + } + /// Type tag information is stored immediately following the arguments, if /// any, at the end of the object. They are mutually exclusive with /// availability slots. @@ -312,6 +335,13 @@ return *getTrailingObjects(); } + /// The attribute pointer immediately follows the object and are mutually + /// exclusive with arguments. + Attr *&getAttrPtrBuffer() { return *getTrailingObjects(); } + Attr *const &getAttrPtrBuffer() const { + return *getTrailingObjects(); + } + /// The property data immediately follows the object is is mutually exclusive /// with arguments. detail::PropertyData &getPropertyDataBuffer() { @@ -336,6 +366,8 @@ bool hasParsedType() const { return HasParsedType; } + bool hasAttrPtr() const { return HasAttrPtr; } + /// Is this the Microsoft __declspec(property) attribute? bool isDeclspecPropertyAttribute() const { return IsProperty; @@ -457,6 +489,11 @@ return getTypeBuffer(); } + const Attr *getAttrPtr() const { + assert(hasAttrPtr() && "Not an attribute pointer attribute"); + return getAttrPtrBuffer(); + } + IdentifierInfo *getPropertyDataGetter() const { assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute"); @@ -546,18 +583,18 @@ class AttributeFactory { public: enum { - AvailabilityAllocSize = - ParsedAttr::totalSizeToAlloc(1, 1, 0, 0, 0), - TypeTagForDatatypeAllocSize = - ParsedAttr::totalSizeToAlloc(1, 0, 1, 0, 0), - PropertyAllocSize = - ParsedAttr::totalSizeToAlloc(0, 0, 0, 0, 1), + AvailabilityAllocSize = ParsedAttr::totalSizeToAlloc< + ArgsUnion, detail::AvailabilityData, detail::TypeTagForDatatypeData, + ParsedType, detail::PropertyData, Attr *>(1, 1, 0, 0, 0, 0), + TypeTagForDatatypeAllocSize = ParsedAttr::totalSizeToAlloc< + ArgsUnion, detail::AvailabilityData, detail::TypeTagForDatatypeData, + ParsedType, detail::PropertyData, Attr *>(1, 0, 1, 0, 0, 0), + PropertyAllocSize = ParsedAttr::totalSizeToAlloc< + ArgsUnion, detail::AvailabilityData, detail::TypeTagForDatatypeData, + ParsedType, detail::PropertyData, Attr *>(0, 0, 0, 0, 1, 0), + AttrPtrAllocSize = ParsedAttr::totalSizeToAlloc< + ArgsUnion, detail::AvailabilityData, detail::TypeTagForDatatypeData, + ParsedType, detail::PropertyData, Attr *>(0, 0, 0, 0, 0, 1), }; private: @@ -652,13 +689,14 @@ size_t temp = ParsedAttr::totalSizeToAlloc(numArgs, 0, 0, 0, 0); + detail::PropertyData, Attr *>(numArgs, 0, + 0, 0, 0, 0); (void)temp; void *memory = allocate( ParsedAttr::totalSizeToAlloc(numArgs, 0, 0, 0, - 0)); + detail::PropertyData, Attr *>(numArgs, 0, + 0, 0, 0, 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, args, numArgs, syntax, ellipsisLoc)); } @@ -684,7 +722,8 @@ void *memory = allocate( ParsedAttr::totalSizeToAlloc(3, 0, 0, 0, 0)); + detail::PropertyData, Attr *>(3, 0, 0, 0, + 0, 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, Param1, Param2, Param3, syntax)); } @@ -709,7 +748,8 @@ void *memory = allocate( ParsedAttr::totalSizeToAlloc(0, 0, 0, 1, 0)); + detail::PropertyData, Attr *>(0, 0, 0, 1, + 0, 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, typeArg, syntaxUsed)); } @@ -723,6 +763,17 @@ return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, getterId, setterId, syntaxUsed)); } + + ParsedAttr *createAttrPtrAttribute(IdentifierInfo *attrName, + SourceRange attrRange, + IdentifierInfo *scopeName, + SourceLocation scopeLoc, Attr *attrPtrArg, + AttributeCommonInfo::Kind Kind, + ParsedAttr::Syntax syntaxUsed) { + void *memory = allocate(AttributeFactory::AttrPtrAllocSize); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + attrPtrArg, Kind, syntaxUsed)); + } }; class ParsedAttributesView { @@ -923,6 +974,17 @@ return attr; } + ParsedAttr *addNewAttrPtrAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, + SourceLocation scopeLoc, Attr *attrPtrArg, + AttributeCommonInfo::Kind Kind, + ParsedAttr::Syntax syntaxUsed) { + ParsedAttr *attr = pool.createAttrPtrAttribute( + attrName, attrRange, scopeName, scopeLoc, attrPtrArg, Kind, syntaxUsed); + addAtEnd(attr); + return attr; + } + private: mutable AttributePool pool; }; diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp --- a/clang/lib/Sema/ParsedAttr.cpp +++ b/clang/lib/Sema/ParsedAttr.cpp @@ -42,10 +42,10 @@ else if (HasParsedType) return totalSizeToAlloc(0, 0, 0, 1, 0); + detail::PropertyData, Attr *>(0, 0, 0, 1, 0, 0); return totalSizeToAlloc(NumArgs, 0, 0, 0, 0); + detail::PropertyData, Attr *>(NumArgs, 0, 0, 0, 0, 0); } AttributeFactory::AttributeFactory() {