ChuanqiXu accepted this revision.
ChuanqiXu added a comment.
This revision is now accepted and ready to land.
LGTM basically. Our discussion is mainly about the future work in Attr.td and
not this patch. So I think they are not blocking issues.
================
Comment at: clang/lib/AST/ODRDiagsEmitter.cpp:337-354
+ if (!LHS || !RHS || LHS->getKind() != RHS->getKind()) {
+ DiagError(AttributeKind)
+ << (LHS != nullptr) << LHS << FirstDecl->getSourceRange();
+ DiagNoteAttrLoc(LHS);
+ DiagNote(AttributeKind)
+ << (RHS != nullptr) << RHS << SecondDecl->getSourceRange();
+ DiagNoteAttrLoc(RHS);
----------------
vsapsai wrote:
> ChuanqiXu wrote:
> > vsapsai wrote:
> > > ChuanqiXu wrote:
> > > > I feel like we can merge these two statements.
> > > Sorry, I don't really get what two statements you are talking about. Is
> > > it
> > > * `!LHS || !RHS || LHS->getKind() != RHS->getKind()`
> > > * `ComputeAttrODRHash(LHS) != ComputeAttrODRHash(RHS)`
> > > ?
> > Sorry for the ambiguity. Since `LHS->getKind() != RHS->getKind()` is
> > covered by `ComputeAttrODRHash(LHS) != ComputeAttrODRHash(RHS)`. I feel
> > like it is reasonable to:
> >
> > ```
> > if (!LHS || !RHS || ComputeAttrODRHash(LHS) != ComputeAttrODRHash(RHS)) {
> > DiagError();
> > DiagNote();
> > DiagNote();
> > DiagNoteAttrLoc();
> > return true;
> > }
> > ```
> There are 2 separate cases to improve the diagnostic. In the first case we'd
> have
> ```
> ... first difference is definition in module 'FirstModule' found attribute
> 'enum_extensibility'
> attribute specified here
> but in 'SecondModule' found no attribute
> ```
>
> And if we reach the second ones, it implies the kind of attributes is the
> same and the only difference is attribute arguments, so the diagnostics are
> like
> ```
> first difference is definition in module 'FirstModule' found attribute '
> __attribute__((enum_extensibility("open")))'
> attribute specified here
> but in 'SecondModule' found different attribute argument '
> __attribute__((enum_extensibility("closed")))'
> attribute specified here
> ```
>
> From my limited experience, it is actually useful to have more details than
> trying to figure out the difference in attributes.
Agreed. I just wanted to say the codes can be further be shorten by making the
diagnostic kinds contains more cases:
```
%select {
|
|
...
}
```
We have some such examples before. But this is not required. Since it actually
moves the complexity from the source codes to the table gen. And the
implementation doesn't look bad.
================
Comment at: clang/lib/AST/ODRHash.cpp:479-480
+
+ llvm::copy_if(D->attrs(), std::back_inserter(HashableAttrs),
+ [](const Attr *A) { return !A->isImplicit(); });
+}
----------------
aaron.ballman wrote:
> ChuanqiXu wrote:
> > aaron.ballman wrote:
> > > ChuanqiXu wrote:
> > > > vsapsai wrote:
> > > > > vsapsai wrote:
> > > > > > erichkeane wrote:
> > > > > > > aaron.ballman wrote:
> > > > > > > > ChuanqiXu wrote:
> > > > > > > > > vsapsai wrote:
> > > > > > > > > > I'm not sure `isImplicit` is the best indicator of
> > > > > > > > > > attributes to check, so suggestions in this area are
> > > > > > > > > > welcome. I think we can start strict and relax some of the
> > > > > > > > > > checks if needed.
> > > > > > > > > >
> > > > > > > > > > If people have strong opinions that some attributes
> > > > > > > > > > shouldn't be ignored, we can add them to the tests to avoid
> > > > > > > > > > regressions. Personally, I believe that alignment and
> > > > > > > > > > packed attributes should never be silently ignored.
> > > > > > > > > Agreed. I feel `isImplicit` is enough for now.
> > > > > > > > The tricky part is -- sometimes certain attributes add
> > > > > > > > additional implicit attributes and those implicit attributes
> > > > > > > > matter
> > > > > > > > (https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaDeclAttr.cpp#L9380).
> > > > > > > > And some attributes seem to just do the wrong thing entirely:
> > > > > > > > https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaDeclAttr.cpp#L7344
> > > > > > > >
> > > > > > > > So I think `isImplicit()` is a good approximation, but I'm more
> > > > > > > > wondering what the principle is for whether an attribute should
> > > > > > > > or should not be considered part of the ODR hash. Type
> > > > > > > > attributes, attributes that impact object layout, etc all seem
> > > > > > > > like they should almost certainly be part of ODR hashing.
> > > > > > > > Others are a bit more questionable though.
> > > > > > > >
> > > > > > > > I think this is something that may need a per-attribute flag in
> > > > > > > > Attr.td so attributes can opt in or out of it because I'm not
> > > > > > > > certain what ODR issues could stem from `[[maybe_unused]]` or
> > > > > > > > `[[deprecated]]` disagreements across module boundaries.
> > > > > > > I don't think 'isImplicit' is particularly good. I think the
> > > > > > > idea of auto-adding 'type' attributes and having the 'rest' be
> > > > > > > analyzed to figure out which are important.
> > > > > > >
> > > > > > > Alternatively, I wonder if we're better off just adding ALL
> > > > > > > attributes and seeing what the fallout is. We can later decide
> > > > > > > when we don't want them to be ODR significant (which, might be
> > > > > > > OTHERWISE meaningful later!).
> > > > > > One criteria to decide which attributes should be hashed is if they
> > > > > > affect IRGen. But that's not exhaustive and I'm not sure how
> > > > > > practical it is.
> > > > > >
> > > > > > The rule I'm trying to follow right now is if declarations with
> > > > > > different attributes can be substituted instead of each other. For
> > > > > > example, structs with different memory layout cannot be
> > > > > > interchanged, so it is reasonable to reject them.
> > > > > >
> > > > > > But maybe we should review attributes on case-by-case basis. For
> > > > > > example, for `[[deprecated]]` I think the best for developers is
> > > > > > not to complain about it but merge the attributes and then have
> > > > > > regular diagnostic about using a deprecated entity.
> > > > > One option was to hash `isa<InheritedAttr>` attributes as they are
> > > > > "sticky" and should be more significant, so shouldn't be ignored. But
> > > > > I don't think this argument is particularly convincing.
> > > > >
> > > > > At this stage I think we can still afford to add all attributes and
> > > > > exclude some as-needed because modules adoption is still limited.
> > > > > Though I don't have strong feelings about this approach, just getting
> > > > > more restrictive later can be hard.
> > > > It looks not a bad idea to add all attributes as experiments, @vsapsai
> > > > how do you feel about this?
> > > My intuition is that we're going to want this to be controlled from
> > > Attr.td on a case-by-case basis and to automatically generate the ODR
> > > hash code for attribute arguments.
> > >
> > > We can either force every attribute to decide explicitly (this seems
> > > pretty disruptive as a final design but would be a really good way to
> > > ensure we audit all attributes if done as an experiment), or we can pick
> > > a default behavior to ODR hash/not. I suspect we're going to want to pick
> > > a default behavior based on whatever the audit tells us the most common
> > > situation is.
> > >
> > > I think we're going to need something a bit more nuanced than "this
> > > attribute matters for ODR" because there are attribute arguments that
> > > don't always contribute to the entity (for example, we have "fake"
> > > arguments that are used to give the semantic attribute more information,
> > > there may also be cases where one argument matter and another argument
> > > does not such as `enable_if` where the condition matters greatly but the
> > > message doesn't matter much). So we might need a marking on the attribute
> > > level *and* on the parameter level to determine what all factors into
> > > attribute identity for generating the ODR hashing code. Hopefully we can
> > > avoid needing more granularity than that.
> > I feel the default behavior would be to do ODR hashes. I just took a quick
> > look in Attr.td. And I feel most of them affecting the code generation. For
> > example, there're a lot of attributes which is hardware related.
> >
> > > because there are attribute arguments that don't always contribute to the
> > > entity
> >
> > When you're talking about "entities", I'm not sure if you're talking the
> > "entities" in the language spec or a general abstract ones. I mean, for
> > example, the `always_inline` attribute doesn't contribute to the
> > declaration from the language perspective. But it'll be super odd if we
> > lost it. So I feel it may be better to change the requirement to be
> > "affecting code generation"
> >
> > Also, to be honest, I am even not sure if we should take "affecting code
> > generation " as the requirement. For example, for the `preferred_name`
> > attribute, this is used for better printing names. It doesn't affect code
> > generation nor the entity you mentioned. But if we drop it, then the
> > printing name may not be what users want. I'm not sure if this is desired.
> > I feel the default behavior would be to do ODR hashes. I just took a quick
> > look in Attr.td. And I feel most of them affecting the code generation. For
> > example, there're a lot of attributes which is hardware related.
>
> Hmmm, I'm seeing a reasonably even split. We definitely have a ton of
> attributes like multiversioning, interrupts, calling conventions,
> availability, etc that I think all should be part of an ODR hash. We also
> have a ton of other ones that don't seem like they should matter for ODR
> hashing like hot/cold, consumed/returns retained, constructor/destructor,
> deprecated, nodiscard, maybe_unused, etc.
>
> Then we have the really fun ones where I think we'll want them to be in the
> ODR hash but maybe we don't, like `[[clang::annotate]]`, restrict, etc.
>
> So I think we really do need an actual audit of the attributes to decide what
> the default should be (if there should even be one).
>
> > When you're talking about "entities", I'm not sure if you're talking the
> > "entities" in the language spec or a general abstract ones. I mean, for
> > example, the always_inline attribute doesn't contribute to the declaration
> > from the language perspective. But it'll be super odd if we lost it. So I
> > feel it may be better to change the requirement to be "affecting code
> > generation"
>
> Not in a language spec meaning -- I meant mostly that there's some notion of
> identify for the one definition rule and not all attribute arguments
> contribute to that identity the same way.
>
> I don't know that "affecting code gen" really captures the whole of it. For
> example, whether a function is/is not marked hot or cold affects codegen, but
> really has nothing to do with the identity of the function (it's the same
> function whether the hint is there or not). `preferred_name` is another
> example -- do we really think a structure with that attribute is
> fundamentally a different thing than one without that attribute? I don't
> think so.
>
> To me, it's more about what cross-TU behaviors you'll get if the attribute is
> only present on one side. Things like ABI tags, calling conventions,
> attributes that behave like qualifiers, etc all contribute to the identity of
> something where a mismatch will impact the correctness of the program. But
> things like optimization hints and diagnostic hints don't seem like they
> contribute to the identity of something because they don't impact correctness.
I got your point. But from my developing experience, I want to say the
optimization hints matters too. And I am wondering how about checking the ODR
for all attributes. It would emit error if the attributes that affecting the
correctness mismatches. And if the other attributes mismatches, a warning
enough. (If we worry about the compile time performance, I feel it won't take
too long. And we can have an option to control it actually.)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D135472/new/
https://reviews.llvm.org/D135472
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits