<div dir="ltr">Here is an example of where I annotate a function declaration after the fact<div><br></div><div>AnnotatedTokens(L=1):<br> M=0 C=0 T=FunctionDeclarationReturnType S=1 F=0 B=0 BK=0 P=0 Name=void L=4 PPK=2 FakeLParens= FakeRParens=0 II=0x1f9f89f7628 Text='void'<br> M=0 C=1 T=FunctionDeclarationName S=1 F=0 B=0 BK=0 P=80 Name=identifier L=8 PPK=2 FakeLParens= FakeRParens=0 II=0x1f9f89f5358 Text='Bar'<br> M=0 C=0 T=FunctionDeclarationLParan S=0 F=0 B=0 BK=0 P=23 Name=l_paren L=9 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text='('<br> M=0 C=1 T=FunctionDeclarationParameterType S=0 F=0 B=0 BK=0 P=140 Name=identifier L=12 PPK=2 FakeLParens=1/ FakeRParens=0 II=0x1f9f89f5358 Text='Bar'<br> M=0 C=0 T=FunctionDeclarationParameterComma S=0 F=0 B=0 BK=0 P=41 Name=comma L=13 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=','<br> M=0 C=1 T=Unknown S=1 F=0 B=0 BK=0 P=41 Name=const L=19 PPK=2 FakeLParens= FakeRParens=0 II=0x1f9f89f70c8 Text='const'<br> M=0 C=0 T=FunctionDeclarationParameterType S=1 F=0 B=0 BK=0 P=43 Name=int L=23 PPK=2 FakeLParens= FakeRParens=0 II=0x1f9f89f7340 Text='int'<br> M=0 C=1 T=PointerOrReference S=1 F=0 B=0 BK=0 P=230 Name=star L=25 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text='*'<br> M=0 C=1 T=StartOfName S=0 F=0 B=0 BK=0 P=240 Name=identifier L=26 PPK=2 FakeLParens= FakeRParens=0 II=0x1f9f89f53e8 Text='b'<br> M=0 C=1 T=PointerOrReference S=1 F=0 B=0 BK=0 P=230 Name=star L=28 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text='*'<br> M=0 C=0 T=FunctionDeclarationParameterComma S=0 F=0 B=0 BK=0 P=54 Name=comma L=29 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=','<br> M=0 C=1 T=FunctionDeclarationParameterType S=1 F=0 B=0 BK=0 P=41 Name=int L=33 PPK=2 FakeLParens= FakeRParens=0 II=0x1f9f89f7340 Text='int'<br> M=0 C=1 T=StartOfName S=1 F=0 B=0 BK=0 P=240 Name=identifier L=35 PPK=2 FakeLParens= FakeRParens=1 II=0x1f9f89f5418 Text='c'<br> M=0 C=0 T=FunctionDeclarationRParan S=0 F=0 B=0 BK=0 P=43 Name=r_paren L=36 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=')'<br> M=0 C=0 T=Unknown S=0 F=0 B=0 BK=0 P=23 Name=semi L=37 PPK=2 FakeLParens= FakeRParens=0 II=0x0 Text=';'<br></div><div><br></div><div>This doesn't fix my exact issue, but if we could perform this kind of annotation across all code it might help to break down some of the ambiguities </div><div><br></div><div>MyDeveloperDay</div><div><br></div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Dec 2, 2021 at 7:38 PM Björn Schäpers via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Am 02.12.2021 um 12:01 schrieb MyDeveloper Day via cfe-dev:<br>
> I've recently been looking into a bug in clang format, that incorrectly treats * <br>
> as a TT_PointerOrReference<br>
> <br>
> void f() { operator+(a, b *b); }<br>
> <br>
> Actually the misinterpretation of * and & as BinaryOperators or <br>
> PointerOrReference is a major source of bugs for clang-format, this is because <br>
> we don't have semantic information and often we are looking very myopically at <br>
> adjacent tokens and there just isn't enough context to disambiguate.<br>
> <br>
> So whilst we see b * b this a easily (b x b)<br>
> <br>
> This is actually just<br>
> <br>
> tok::identifier->tok::star->tok::identifier<br>
> <br>
> Which is indistinguishable from<br>
> <br>
> MyClass *b<br>
> <br>
> which I think we'd all see as (class ptr b), but in all cases we have no <br>
> additional information, other than perhaps scanning up and down the line to find <br>
> something relevant.<br>
> <br>
> This literally drops out the bottom of determineStarAmpUsage() with a<br>
> return TT_PointerOrReference;<br>
> <br>
> For the bug I'm looking at, given the following example the first f() puts the * <br>
> as a pointer when actually its a multiply;<br>
> <br>
> void f() { operator+(Bar, Foo *Foo); }<br>
> <br>
> class A {<br>
>    void operator+(Bar, Foo *Foo);<br>
> }<br>
> <br>
> Effectively these two instances of operator appears as the same with almost no <br>
> difference in terms of tokens,<br>
> <br>
> Looking at the token annotations, there is almost nothing that distinguishes <br>
> between the two.<br>
> <br>
> [snip]<br>
> <br>
> We've always known this is an issue, and it's to do with the fact that we don't <br>
> have information near the "*" that tells us in what context it is.<br>
> <br>
> I feel that actually part of the problem is that we are not setting the <br>
> "setType" on the tokens i.e. T=Unknown in all cases, I think we have more <br>
> contextual information<br>
> than we think, I just feel like we throw it away a lot of the time.<br>
> <br>
> Think about how you look at the code visually.. how do you determine that its a <br>
> definition rather than a declaration? Both bits of code are almost<br>
> identical so what is it that's forcing us to see the difference?<br>
> <br>
> Somehow I feel we should be classifying as many of the tokens as we process <br>
> them. Every (){} and , every type or return type. I feel with more information <br>
> we could<br>
> solve these types of issues.<br>
> <br>
> By introducing a few more types and then systematically trying to annotate all <br>
> the tokens we could have greater inference.<br>
> <br>
> To me I feel, that given that we see operator as FunctionDeclarationName we <br>
> should then change the ( and ) to be OverloadedOperatorDeclarationLParen and <br>
> OverloadedOperatorDeclarationRParen<br>
> <br>
> We should classify the "," in the declaration as FunctionDeclarationComma<br>
> <br>
>  From that we could determine that Bar and Foo (1st) were Type declarations, and <br>
> that would make a rule for determining the * to be almost trivial.<br>
> <br>
> I think in clang-format we need to take a more holistic approach to <br>
> TokenAnnotations, classify as many tokens as we can as accurately as we can. <br>
> T=Unknown is almost useless to us, and that<br>
> lack of context easily means we misinterpret.<br>
> <br>
> Any thoughts?<br>
> <br>
> MyDeveloperDay<br>
> <br>
<br>
Seems reasonable to me. I also think we should add and keep more information in <br>
the unwrapped line parser.<br>
<br>
Kind regards,<br>
Björn.<br>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div>