-
Notifications
You must be signed in to change notification settings - Fork 17
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
Emit a diagnostic warning about parsing ambiguity in a conjunction #55
Changes from 12 commits
378e907
53c7d38
98b0a59
32c3567
99e6528
44b62f0
a13d5e8
6772510
7be17b0
bfdfdd6
a736536
3554cdb
af2a8c1
5bb406e
a2aead4
07bba7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6750,6 +6750,21 @@ void Parser::ParseDeclaratorInternal(Declarator &D, | |
// Is a reference | ||
DeclSpec DS(AttrFactory); | ||
|
||
// Complain about parsing ambiguity of parsing reference types | ||
// inside expressions with reflection in C++2x | ||
if (D.getContext() == DeclaratorContext::ReflectOperator && | ||
!Tok.isOneOf(tok::r_paren, tok::semi)) { | ||
// parser already consumed '^' token before setting this context | ||
assert((Kind == tok::ampamp || Kind == tok::amp) && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately, there are a lot more cases here. I'm not sure this approach will work (although it might - not really sure one way or the other). r == ^int& ? 1 : 0
condition ? ^int& : ^int;
^int&(*)(bool)
^int& != r
^int& == r
constexpr auto r {^int&}; In addition to those, in the presence of some user-defined consteval result_type operator???(std::meta::info R, MyStupidClass); You could have Those are all the cases I can think of off the top of my head, but I may have forgotten some. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thank you! gonna think more how to address it |
||
"expected '&' or '&&'"); | ||
Diag(Loc, | ||
diag::warn_parsing_ambiguity_in_refl_expression_with_reference_types) | ||
<< (D.hasName() | ||
? Actions.GetNameForDeclarator(D).getName().getAsString() | ||
: "T") | ||
<< tok::getPunctuatorSpelling(Kind); | ||
} | ||
|
||
// Complain about rvalue references in C++03, but then go on and build | ||
// the declarator. | ||
if (Kind == tok::ampamp) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Copyright 2024 Bloomberg Finance L.P. | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// RUN: %clang_cc1 -std=c++26 -freflection -Wno-parentheses -verify %s | ||
|
||
|
||
enum MyEnum { x, y, e = -1, f, z = 99 }; | ||
|
||
void func(MyEnum && x) { // ok | ||
MyEnum value{}; | ||
MyEnum& ref = value; | ||
|
||
constexpr auto reflValue = ^value; | ||
|
||
constexpr bool test_comparison_0 = reflValue != (^MyEnum) && true; // ok | ||
constexpr bool test_comparison_1 = (reflValue != (^MyEnum) && true); // ok | ||
|
||
constexpr bool test_comparison_2 = ^MyEnum != (^MyEnum) && true; // ok | ||
constexpr bool test_comparison_3 = (^MyEnum != (^MyEnum) && true); // ok | ||
|
||
constexpr bool test_comparison_4 = (reflValue != (^MyEnum) & true); // ok | ||
|
||
constexpr bool test_comparison_5 = reflValue != ^MyEnum && true; | ||
// expected-warning@-1 {{given expression may be misinterpreted due to 'T &&' type parsing logic. did you mean '... (^T) && ...'?}} | ||
// expected-error@-2 {{expected ';' at end of declaration}} | ||
constexpr bool test_comparison_6 = reflValue != ^MyEnum & true; | ||
// expected-warning@-1 {{given expression may be misinterpreted due to 'T &' type parsing logic. did you mean '... (^T) & ...'?}} | ||
// expected-error@-2 {{expected ';' at end of declaration}} | ||
|
||
constexpr auto test_ref_type_0 = ^int &; // ok | ||
constexpr auto test_ref_type_1 = ^int &&; // ok | ||
constexpr auto test_ref_type_2 = (^int &); // ok | ||
constexpr auto test_ref_type_3 = (^int &&); // ok | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe something like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed. But I still cannot get name of type :(
So message looks like this:
token '&' binds left to type 'T &'; did you mean '(^T) &'?
I checked similar places in a code to get an idea where to get type name but in all methods names are empty for my tests.