Index: cfe/trunk/include/clang/Sema/ParsedAttr.h =================================================================== --- cfe/trunk/include/clang/Sema/ParsedAttr.h +++ cfe/trunk/include/clang/Sema/ParsedAttr.h @@ -55,8 +55,7 @@ bool isValid() const { return !Version.empty(); } }; -namespace { - +namespace detail { enum AvailabilitySlot { IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots }; @@ -78,6 +77,18 @@ } }; +struct TypeTagForDatatypeData { + ParsedType *MatchingCType; + unsigned LayoutCompatible : 1; + unsigned MustBeNull : 1; +}; +struct PropertyData { + IdentifierInfo *GetterId, *SetterId; + + PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId) + : GetterId(getterId), SetterId(setterId) {} +}; + } // namespace /// Wraps an identifier and optional source location for the identifier. @@ -103,7 +114,29 @@ /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. /// -class ParsedAttr { +class ParsedAttr final + : private llvm::TrailingObjects< + ParsedAttr, ArgsUnion, detail::AvailabilityData, + detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData> { + friend class llvm::TrailingObjects< + ParsedAttr, ArgsUnion, detail::AvailabilityData, + detail::TypeTagForDatatypeData, ParsedType, detail::PropertyData>; + + size_t numTrailingObjects(OverloadToken) const { return NumArgs; } + size_t numTrailingObjects(OverloadToken) const { + return IsAvailability; + } + size_t + numTrailingObjects(OverloadToken) const { + return IsTypeTagForDatatype; + } + size_t numTrailingObjects(OverloadToken) const { + return HasParsedType; + } + size_t numTrailingObjects(OverloadToken) const { + return IsProperty; + } + public: /// The style used to specify an attribute. enum Syntax { @@ -183,34 +216,18 @@ const Expr *MessageExpr; - /// Arguments, if any, are stored immediately following the object. - ArgsUnion *getArgsBuffer() { return reinterpret_cast(this + 1); } + ArgsUnion *getArgsBuffer() { return getTrailingObjects(); } ArgsUnion const *getArgsBuffer() const { - return reinterpret_cast(this + 1); + return getTrailingObjects(); } - /// Availability information is stored immediately following the arguments, - /// if any, at the end of the object. - AvailabilityData *getAvailabilityData() { - return reinterpret_cast(getArgsBuffer() + NumArgs); + detail::AvailabilityData *getAvailabilityData() { + return getTrailingObjects(); } - const AvailabilityData *getAvailabilityData() const { - return reinterpret_cast(getArgsBuffer() + NumArgs); + const detail::AvailabilityData *getAvailabilityData() const { + return getTrailingObjects(); } -public: - struct TypeTagForDatatypeData { - ParsedType *MatchingCType; - unsigned LayoutCompatible : 1; - unsigned MustBeNull : 1; - }; - struct PropertyData { - IdentifierInfo *GetterId, *SetterId; - - PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId) - : GetterId(getterId), SetterId(setterId) {} - }; - private: friend class AttributeFactory; friend class AttributePool; @@ -245,7 +262,7 @@ MessageExpr(messageExpr) { ArgsUnion PVal(Parm); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); - new (getAvailabilityData()) AvailabilityData( + new (getAvailabilityData()) detail::AvailabilityData( introduced, deprecated, obsoleted, strict, replacementExpr); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } @@ -279,7 +296,7 @@ HasProcessingCache(false) { ArgsUnion PVal(ArgKind); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); - TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); + detail::TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); new (&ExtraData.MatchingCType) ParsedType(matchingCType); ExtraData.LayoutCompatible = layoutCompatible; ExtraData.MustBeNull = mustBeNull; @@ -309,39 +326,36 @@ UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), HasProcessingCache(false) { - new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); + new (&getPropertyDataBuffer()) detail::PropertyData(getterId, setterId); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } /// Type tag information is stored immediately following the arguments, if /// any, at the end of the object. They are mutually exclusive with /// availability slots. - TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { - return *reinterpret_cast(getArgsBuffer()+NumArgs); + detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { + return *getTrailingObjects(); } - const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { - return *reinterpret_cast(getArgsBuffer() - + NumArgs); + const detail::TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { + return *getTrailingObjects(); } /// The type buffer immediately follows the object and are mutually exclusive /// with arguments. - ParsedType &getTypeBuffer() { - return *reinterpret_cast(this + 1); - } + ParsedType &getTypeBuffer() { return *getTrailingObjects(); } const ParsedType &getTypeBuffer() const { - return *reinterpret_cast(this + 1); + return *getTrailingObjects(); } /// The property data immediately follows the object is is mutually exclusive /// with arguments. - PropertyData &getPropertyDataBuffer() { + detail::PropertyData &getPropertyDataBuffer() { assert(IsProperty); - return *reinterpret_cast(this + 1); + return *getTrailingObjects(); } - const PropertyData &getPropertyDataBuffer() const { + const detail::PropertyData &getPropertyDataBuffer() const { assert(IsProperty); - return *reinterpret_cast(this + 1); + return *getTrailingObjects(); } size_t allocated_size() const; @@ -452,17 +466,17 @@ const AvailabilityChange &getAvailabilityIntroduced() const { assert(getKind() == AT_Availability && "Not an availability attribute"); - return getAvailabilityData()->Changes[IntroducedSlot]; + return getAvailabilityData()->Changes[detail::IntroducedSlot]; } const AvailabilityChange &getAvailabilityDeprecated() const { assert(getKind() == AT_Availability && "Not an availability attribute"); - return getAvailabilityData()->Changes[DeprecatedSlot]; + return getAvailabilityData()->Changes[detail::DeprecatedSlot]; } const AvailabilityChange &getAvailabilityObsoleted() const { assert(getKind() == AT_Availability && "Not an availability attribute"); - return getAvailabilityData()->Changes[ObsoletedSlot]; + return getAvailabilityData()->Changes[detail::ObsoletedSlot]; } SourceLocation getStrictLoc() const { @@ -508,9 +522,16 @@ return getTypeBuffer(); } - const PropertyData &getPropertyData() const { - assert(isDeclspecPropertyAttribute() && "Not a __delcspec(property) attribute"); - return getPropertyDataBuffer(); + IdentifierInfo *getPropertyDataGetter() const { + assert(isDeclspecPropertyAttribute() && + "Not a __delcspec(property) attribute"); + return getPropertyDataBuffer().GetterId; + } + + IdentifierInfo *getPropertyDataSetter() const { + assert(isDeclspecPropertyAttribute() && + "Not a __delcspec(property) attribute"); + return getPropertyDataBuffer().SetterId; } /// Get an index into the attribute spelling list @@ -553,20 +574,18 @@ class AttributeFactory { public: enum { - /// The required allocation size of an availability attribute, - /// which we want to ensure is a multiple of sizeof(void*). AvailabilityAllocSize = - sizeof(ParsedAttr) + - ((sizeof(AvailabilityData) + sizeof(void *) + sizeof(ArgsUnion) - 1) / - sizeof(void *) * sizeof(void *)), - TypeTagForDatatypeAllocSize = sizeof(ParsedAttr) + - (sizeof(ParsedAttr::TypeTagForDatatypeData) + - sizeof(void *) + sizeof(ArgsUnion) - 1) / - sizeof(void *) * sizeof(void *), + ParsedAttr::totalSizeToAlloc(1, 1, 0, 0, 0), + TypeTagForDatatypeAllocSize = + ParsedAttr::totalSizeToAlloc(0, 0, 1, 0, 0), PropertyAllocSize = - sizeof(ParsedAttr) + - (sizeof(ParsedAttr::PropertyData) + sizeof(void *) - 1) / - sizeof(void *) * sizeof(void *) + ParsedAttr::totalSizeToAlloc(0, 0, 0, 0, 1), }; private: @@ -657,7 +676,16 @@ ArgsUnion *args, unsigned numArgs, ParsedAttr::Syntax syntax, SourceLocation ellipsisLoc = SourceLocation()) { - void *memory = allocate(sizeof(ParsedAttr) + numArgs * sizeof(ArgsUnion)); + size_t temp = + ParsedAttr::totalSizeToAlloc(numArgs, 0, 0, 0, 0); + (void)temp; + void *memory = allocate( + ParsedAttr::totalSizeToAlloc(numArgs, 0, 0, 0, + 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, args, numArgs, syntax, ellipsisLoc)); } @@ -680,8 +708,10 @@ IdentifierInfo *scopeName, SourceLocation scopeLoc, IdentifierLoc *Param1, IdentifierLoc *Param2, IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { - size_t size = sizeof(ParsedAttr) + 3 * sizeof(ArgsUnion); - void *memory = allocate(size); + void *memory = allocate( + ParsedAttr::totalSizeToAlloc(3, 0, 0, 0, 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, Param1, Param2, Param3, syntax)); } @@ -703,7 +733,10 @@ IdentifierInfo *scopeName, SourceLocation scopeLoc, ParsedType typeArg, ParsedAttr::Syntax syntaxUsed) { - void *memory = allocate(sizeof(ParsedAttr) + sizeof(void *)); + void *memory = allocate( + ParsedAttr::totalSizeToAlloc(0, 0, 0, 1, 0)); return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, typeArg, syntaxUsed)); } Index: cfe/trunk/lib/Sema/ParsedAttr.cpp =================================================================== --- cfe/trunk/lib/Sema/ParsedAttr.cpp +++ cfe/trunk/lib/Sema/ParsedAttr.cpp @@ -41,8 +41,12 @@ else if (IsProperty) return AttributeFactory::PropertyAllocSize; else if (HasParsedType) - return sizeof(ParsedAttr) + sizeof(void *); - return (sizeof(ParsedAttr) + NumArgs * sizeof(ArgsUnion)); + return totalSizeToAlloc(0, 0, 0, 1, 0); + return totalSizeToAlloc(NumArgs, 0, 0, 0, 0); } AttributeFactory::AttributeFactory() { Index: cfe/trunk/lib/Sema/SemaDeclCXX.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp @@ -15476,9 +15476,10 @@ PrevDecl = nullptr; SourceLocation TSSL = D.getLocStart(); - const ParsedAttr::PropertyData &Data = MSPropertyAttr.getPropertyData(); - MSPropertyDecl *NewPD = MSPropertyDecl::Create( - Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId); + MSPropertyDecl *NewPD = + MSPropertyDecl::Create(Context, Record, Loc, II, T, TInfo, TSSL, + MSPropertyAttr.getPropertyDataGetter(), + MSPropertyAttr.getPropertyDataSetter()); ProcessDeclAttributes(TUScope, NewPD, D); NewPD->setAccess(AS);