Mordante marked 2 inline comments as done.
Mordante added a comment.

In D86559#2371058 <https://reviews.llvm.org/D86559#2371058>, @aaron.ballman 
wrote:

> In D86559#2369317 <https://reviews.llvm.org/D86559#2369317>, @Mordante wrote:
>
>> Then me try to clear up the confusion.
>>
>>> However, I could imagine there being cases when we might want a helper 
>>> function on `LabelDecl` that looks for attributes on the associated 
>>> `LabelStmt` and returns results about it if that helps ease implementation 
>>> or refactoring burdens.
>>
>> If we want that we need to change the `LabelDecl` to point to either a 
>> `LabelStmt` or an `AttributedStmt`. This was the approach I thought I had to 
>> take, but I found this solution. We can still take that direction if wanted. 
>> But then we need to place `DeclAttr` in an `AttributedStmt`, not sure how 
>> well that works and how much additional code needs to change to find the 
>> attributes there. Since in that case we to call this helper function at the 
>> appropriate places.
>
> Ah, I was thinking of something slightly different here. I was thinking that 
> `LabelDecl` would hold a `Stmt*` so that it could be either a label statement 
> or an attribute statement.

Yes I wanted to take that route. While investigating that route I found the 
current solution and it seemed less intrusive. So that's why I went for the 
current approach.

> The helper functions would give you access to the attributes of the statement 
> and to the `LabelStmt` itself (stripping off any attributed statements). Then 
> in Attr.td, we'd move attributes off the label declarations and onto the 
> label statements. At the end of the day, all attributes on labels would 
> appertain to the statement at the AST level, but you'd have an easier time 
> transitioning in some places if you could get to the attributes if the only 
> thing you have is the `LabelDecl`. (So this doesn't mix statement and 
> declaration attributes together, it shifts the model to putting all 
> attributes on labels on the statement level rather than having a somewhat odd 
> split between decl and statement.)

If we go that route, then we need to think about attributes that are normally 
allowed on declarations. For example

  def Unused : InheritableAttr {
    let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">,
                     C2x<"", "maybe_unused", 201904>];
    let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label,
                                Field, ObjCMethod, FunctionLike]>;
    let Documentation = [WarnMaybeUnusedDocs];
  }

It also seems attributes on the `LabelDecl` aren't visible in the AST at the 
moment. If I modify the example posted yesterday to:

  void foo() {
    [[likely, clang::annotate("foo")]] lbl:;
  }

The AST will become:

  `-FunctionDecl 0x5607f7dbb7a8 </tmp/x.cpp:1:1, line:3:1> line:1:6 foo 'void 
()'
    `-CompoundStmt 0x5607f7dbba60 <col:12, line:3:1>
      `-AttributedStmt 0x5607f7dbba48 <line:2:3, col:42>
        |-LikelyAttr 0x5607f7dbba20 <col:5>
        `-LabelStmt 0x5607f7dbba08 <col:38, col:42> 'lbl'
          `-NullStmt 0x5607f7dbb928 <col:42>

Maybe it would be a good idea to see whether the `LabelDecl` needs to be 
visible in the AST even if we proceed with the current approach.

>> Does this clear your confusion?
>> Do you agree with this approach or do you think changing the `LabelDecl` is 
>> the better solution?
>
> Thank you for the explanations, I understand your design better now. I'm not 
> certain what the right answer is yet, but thinking out loud about my 
> concerns: I worry that making a distinction between a label statement and a 
> label declaration (at least for attributes) generates heat without light. 
> Making the attribute author decide "which label construct should my attribute 
> appertain to" adds extra burden on attribute authors and I'm not sure I have 
> any advice for them on whether to use the decl or the statement -- it seems 
> entirely arbitrary. Coupled with the fact that the standard defines labels as 
> being statements, that suggests to me that putting all of the attributes on 
> the statement level is the right decision -- it's one place (removes 
> confusion about where it goes), it's the "obvious" place (matches where the 
> standard suggests that attributes live), and we should have all the machinery 
> in place to make it possible within the compiler (given that you can reach 
> the `LabelStmt` from the `LabelDecl`).

I agree it's not clear cut what the best way is. For example `unused` is a 
declaration attribute, but `likely` is a statement attribute. Both can be used 
on a label. I think for authors in most cases it will be clear, their attribute 
is also used on other declarations or statements. The harder case will be, when 
a label specific attribute is added, should it then go on the declaration or 
the statement. I foresee another issue when there will be attributes that can 
be attached to both a declaration and a statement, for example if we implement 
`[[clang::suppress("compiler.warning.12345")]]`. (But I suspect that attribute 
has more implementation challenges.) In the current approach that attribute 
will be attached to the declaration since that's parsed first. I think 
regardless of the final solution labels will remain a special case for 
attributes.

During the review of `[[clang::nomerge]]` the placement on labels was also 
discussed. I also see some threads on the dev-ml about making more use of 
attributes. For example to enhance the analyzers, which sounds very 
interesting. So I feel it's worth the effort to look for the "best" approach, 
even if the usefulness for the likelihood attributes is limited.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86559/new/

https://reviews.llvm.org/D86559

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to