[PATCH] MS ABI: Improve selection of an inheritance model
Aaron Ballman
aaron at aaronballman.com
Wed Jan 15 09:39:55 PST 2014
On Wed, Jan 15, 2014 at 12:27 PM, David Majnemer
<david.majnemer at gmail.com> wrote:
>
>
> On Wednesday, January 15, 2014, Aaron Ballman <aaron at aaronballman.com>
> wrote:
>>
>> Some attribute-related nits below, but aside from those, LGTM (though
>> I would get secondary confirmation).
>>
>> > Index: include/clang/AST/DeclCXX.h
>> > ===================================================================
>> > --- include/clang/AST/DeclCXX.h
>> > +++ include/clang/AST/DeclCXX.h
>> > @@ -261,9 +261,7 @@
>> > /// The inheritance model to use for member pointers of a given
>> > CXXRecordDecl.
>> > enum MSInheritanceModel {
>> > MSIM_Single,
>> > - MSIM_SinglePolymorphic,
>> > MSIM_Multiple,
>> > - MSIM_MultiplePolymorphic,
>> > MSIM_Virtual,
>> > MSIM_Unspecified
>> > };
>> > @@ -1609,6 +1607,7 @@
>> >
>> > /// \brief Returns the inheritance model used for this record.
>> > MSInheritanceModel getMSInheritanceModel() const;
>> > + void setMSInheritanceModel();
>> >
>> > /// \brief Determine whether this lambda expression was known to be
>> > dependent
>> > /// at the time it was created, even if its context does not appear
>> > to be
>> > Index: include/clang/Basic/Attr.td
>> > ===================================================================
>> > --- include/clang/Basic/Attr.td
>> > +++ include/clang/Basic/Attr.td
>> > @@ -1354,7 +1354,12 @@
>> > Accessor<"IsUnspecified", [Keyword<"">]>];
>> > // This index is based off the Spellings list and corresponds to the
>> > empty
>> > // keyword "spelling."
>> > - let AdditionalMembers = [{static const int UnspecifiedSpellingIndex =
>> > 3;}];
>> > + let AdditionalMembers = [{
>> > + static const unsigned SingleSpellingIndex = 0;
>> > + static const unsigned MultipleSpellingIndex = 1;
>> > + static const unsigned VirtualSpellingIndex = 2;
>> > + static const unsigned UnspecifiedSpellingIndex = 3;
>>
>> I'd rather to go great length to avoid exposing these further...
>>
>> let AdditionalMembers = [{
>> // Note: these correspond to the spelling list index for a reason,
>> so keep them in sync.
>> enum Type {
>> Single,
>> Multiple,
>> Virtual,
>> Unspecified
>> };
>>
>> static MSInheritanceAttr *Create(SourceRange R, ASTContext &C, Type T) {
>> return ::new (C) MSInheritanceAttr(R, C, T);
>> }
>> }];
>>
>> This keeps all of the crazy and fragile in one spot. Once you land
>> that, I can change the usage in SemaType.cpp over to the new style,
>> and remove the old spelling list constant.
>>
>> > + }];
>> > }
>> >
>> > def Unaligned : IgnoredAttr {
>> > Index: lib/AST/MicrosoftCXXABI.cpp
>> > ===================================================================
>> > --- lib/AST/MicrosoftCXXABI.cpp
>> > +++ lib/AST/MicrosoftCXXABI.cpp
>> > @@ -92,7 +92,8 @@
>> > return false;
>> > }
>> >
>> > -static MSInheritanceModel MSInheritanceAttrToModel(MSInheritanceAttr
>> > *Attr) {
>> > +static MSInheritanceModel
>> > +MSInheritanceAttrToModel(const MSInheritanceAttr *Attr) {
>> > if (Attr->IsSingle())
>> > return MSIM_Single;
>> > else if (Attr->IsMultiple())
>> > @@ -104,16 +105,44 @@
>> > return MSIM_Unspecified;
>> > }
>> >
>> > +static unsigned MSInheritanceModelToSpellingKind(MSInheritanceModel
>> > MSIM) {
>> > + switch (MSIM) {
>> > + case MSIM_Single:
>> > + return MSInheritanceAttr::SingleSpellingIndex;
>> > + case MSIM_Multiple:
>> > + return MSInheritanceAttr::MultipleSpellingIndex;
>> > + case MSIM_Virtual:
>> > + return MSInheritanceAttr::VirtualSpellingIndex;
>> > + case MSIM_Unspecified:
>> > + return MSInheritanceAttr::UnspecifiedSpellingIndex;
>> > + }
>> > +}
>> > +
>> > +
>> > +static MSInheritanceModel calculateInheritanceModel(const CXXRecordDecl
>> > *RD) {
>> > + if (!RD->hasDefinition())
>> > + return MSIM_Unspecified;
>> > + if (RD->getNumVBases() > 0)
>> > + return MSIM_Virtual;
>> > + if (usesMultipleInheritanceModel(RD))
>> > + return MSIM_Multiple;
>> > + return MSIM_Single;
>> > +}
>> > +
>> > MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const {
>> > - if (MSInheritanceAttr *IA = this->getAttr<MSInheritanceAttr>())
>> > + if (MSInheritanceAttr *IA = getAttr<MSInheritanceAttr>())
>> > return MSInheritanceAttrToModel(IA);
>> > - // If there was no explicit attribute, the record must be defined
>> > already, and
>> > - // we can figure out the inheritance model from its other properties.
>> > - if (this->getNumVBases() > 0)
>> > - return MSIM_Virtual;
>> > - if (usesMultipleInheritanceModel(this))
>> > - return this->isPolymorphic() ? MSIM_MultiplePolymorphic :
>> > MSIM_Multiple;
>> > - return this->isPolymorphic() ? MSIM_SinglePolymorphic : MSIM_Single;
>> > +
>> > + return calculateInheritanceModel(this);
>> > +}
>> > +
>> > +void CXXRecordDecl::setMSInheritanceModel() {
>> > + if (hasAttr<MSInheritanceAttr>())
>> > + return;
>> > +
>> > + MSInheritanceModel MSIM = calculateInheritanceModel(this);
>> > + addAttr(::new (getASTContext()) MSInheritanceAttr(
>> > + SourceRange(), getASTContext(),
>> > MSInheritanceModelToSpellingKind(MSIM)));
>>
>> This should be using the source range for the record decl (better
>> error reporting if it ever comes up).
>
> I chose not to because I wanted a way to mark the Attr implicit so that
> tooling, AST dumps and diagnostics wouldn't believe there was one in the
> source. I can change it to use the record decl's range but could we
> (eventually) get a way to say it was manufactured by clang?
That's on "The List" for someday. We have this problem all over the
source base (usually I whine about it when I see a new usage, too).
> P.S. Personally, I think it would be confusing to use the source range of
> this, or any, implicit Attr. The diagnostics wouldn't really make sense to
> the user.
I can see some logic on that, but then again, at least pointing the
user "here's the thing that's affected" would be a kindness. However,
it could also be argued that most implicit attributes shouldn't cause
errors or warnings in an ideal world.
~Aaron
More information about the cfe-commits
mailing list