Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Compound assignment chosen over postfix operator #388

Closed
JohelEGP opened this issue Apr 21, 2023 · 7 comments
Closed

[BUG] Compound assignment chosen over postfix operator #388

JohelEGP opened this issue Apr 21, 2023 · 7 comments
Labels
bug Something isn't working

Comments

@JohelEGP
Copy link
Contributor

Title: Compound assignment chosen over postfix operator

This seems at odds with
https://github.com/hsutter/cppfront/wiki/Design-note:-Unambiguous-parsing,
https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-operators, and
https://github.com/hsutter/cppfront/wiki/Design-note%3A-Postfix-unary-operators-vs-binary-operators.

Minimal reproducer (https://godbolt.org/z/PYEnvh6Px):

f4: (inout v0: i8, copy v1: *i8) = {
  v0&*= 1;
}
main: () = {
  v0: i8 = 1;
  f4(v0, v0&);
}

Commands:

cppfront x.cpp2
clang++17 -std=c++2b -stdlib=libc++ -I $CPPFRONT_INCLUDE_DIR x.cpp

Expected result:
*&v0 = 1 to be generated instead of
&v0 *= 1,
because v0&* can be parsed as a postfix-expression
because v0& can be parsed as a postfix-expression
because v0 can be parsed as a postfix-expression
and those match first,
before assignment-expression assignment-operator logical-or-expression
has a chance to use *= as an assignment-operator,
and because the leftover = 1 can match that assignment-operator logical-or-expression.

Actual result and error:

Generated Cpp1.
//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"



//=== Cpp2 type definitions and function declarations ===========================

#line 1 "/app/main.cpp2"
auto f4(cpp2::i8& v0, cpp2::i8* v1) -> void;
  

auto main() -> int;
  

//=== Cpp2 function definitions =================================================

#line 1 "/app/main.cpp2"
auto f4(cpp2::i8& v0, cpp2::i8* v1) -> void{
  &v0 *= 1;
}
auto main() -> int{
  cpp2::i8 v0 {1}; 
  f4(v0, &v0);
}
main.cpp2:2:7: error: invalid operands to binary expression ('cpp2::i8 *' (aka 'signed char *') and 'int')
  &v0 *= 1;
  ~~~ ^  ~
1 error generated.
@JohelEGP JohelEGP added the bug Something isn't working label Apr 21, 2023
@hsutter
Copy link
Owner

hsutter commented Apr 21, 2023

Thanks. It's max munch... *= is one token, so the above parses can't happen... the only * token in this code is on the parameter.

Distilling even slightly further:

p: *i8 = f();
p*= 1;

That should clearly be compound assignment [edit: and semantically illegal since we can't multiply-assign pointers] even without the whitespace, I think... what do you think?

@JohelEGP
Copy link
Contributor Author

It's max munch...

Thank you. I'll have to study this.

@hsutter
Copy link
Owner

hsutter commented Apr 21, 2023

I should distill even further:

i := 42;
i*= 1;

@JohelEGP
Copy link
Contributor Author

It's max munch...

Thank you. I'll have to study this.

Maybe later. I remembered what should be the source of this parsing terminology. Translation phase 3 tokenizes before phase 7 reads the sequence according to the grammar.

@JohelEGP
Copy link
Contributor Author

The max much rule must come from

(3.3)
Otherwise, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token, even if that would cause further lexical analysis to fail, except that a header-name ([lex.header]) is only formed
(3.3.1)
after the include or import preprocessing token in an #include ([cpp.include]) or import ([cpp.import]) directive, or
(3.3.2)
within a has-include-expression.

[Example 1: #define R "x"
const char* s = R"y"; // ill-formed raw string, not "x" "y"
— end example]

@JohelEGP
Copy link
Contributor Author

Is it safe to say that https://eel.is/c++draft/lex#digraph doesn't apply to Cpp2, and v0<:int = 0> should lower to v0<int{0}> and not interpret the <: as a [ (https://godbolt.org/z/oeKs3xad9)? If so, I think we can close this.

@hsutter
Copy link
Owner

hsutter commented Apr 22, 2023

Right, Cpp2 eliminates all the things on this cppreference page as special features... no digraphs or trigraphs as they aren't among the specified tokens, and no alternative operator macro names which were reclaimed for normal use in #328.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants