From 378e907bafa95c4cceb84add49ea84b989a6b2e3 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Tue, 28 May 2024 00:43:09 +0100 Subject: [PATCH 01/16] feat: first version of implementation Signed-off-by: Valentyn Yukhymenko --- .../clang/Basic/DiagnosticParseKinds.td | 4 +++ clang/lib/Parse/ParseDecl.cpp | 25 ++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 35cd8e2d4dba6..00075e052658d 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1713,6 +1713,10 @@ let CategoryName = "Reflection Issue" in { def err_cannot_reflect_entity : Error<"cannot reflect entity">; def err_expansion_statements_disabled : Error< "'template for' statements are not enabled; use '-fexpansion-statements'">; + +def warn_parsing_ambiguity_in_refl_expression_with_ampamp_token : Warning < + "the compound condition may be misinterpreted due to '%0 &&' type parsing logic. did you mean '... (^%0) && ...'?" + >; } let CategoryName = "Generics Issue" in { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index caa626d04c85e..9b60b95ed1738 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6750,12 +6750,25 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Is a reference DeclSpec DS(AttrFactory); - // Complain about rvalue references in C++03, but then go on and build - // the declarator. - if (Kind == tok::ampamp) - Diag(Loc, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_rvalue_reference : - diag::ext_rvalue_reference); + // Complain about: + // - rvalue references in C++03, + // - `^T &&` parsing ambiguity in C++2x + // but then go on and build the declarator. + if (Kind == tok::ampamp) { + if (D.getContext() == DeclaratorContext::ReflectOperator) { + std::string typeName = "T"; + if (D.hasName()) { + typeName = Actions.GetNameForDeclarator(D).getName().getAsString(); + } + Diag(Loc, + diag::warn_parsing_ambiguity_in_refl_expression_with_ampamp_token) + << typeName; + } + + Diag(Loc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_rvalue_reference + : diag::ext_rvalue_reference); + } // GNU-style and C++11 attributes are allowed here, as is restrict. ParseTypeQualifierListOpt(DS); From 53c7d38d1896781d90f9a3e0828d28c3e9a9d02b Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Wed, 29 May 2024 00:03:47 +0100 Subject: [PATCH 02/16] test: add basic test for parsing Signed-off-by: Valentyn Yukhymenko --- .../test/Parser/cxx2x-ambig-reflect-expr.cpp | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 clang/test/Parser/cxx2x-ambig-reflect-expr.cpp diff --git a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp new file mode 100644 index 0000000000000..69e3c3483d426 --- /dev/null +++ b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// 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 -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; + // expected-warning@28 {{the compound condition may be misinterpreted due to 'T &&' type parsing logic. did you mean '... (^T) && ...'?}} + // expected-error@28 {{expected ';' at end of declaration}} +} + From 98b0a5922a4eb231d9f4791516fdc20448f5c8f6 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Wed, 29 May 2024 00:31:49 +0100 Subject: [PATCH 03/16] minor refactoring Signed-off-by: Valentyn Yukhymenko --- clang/lib/Parse/ParseDecl.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 9b60b95ed1738..20ad465550f82 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6751,18 +6751,17 @@ void Parser::ParseDeclaratorInternal(Declarator &D, DeclSpec DS(AttrFactory); // Complain about: - // - rvalue references in C++03, - // - `^T &&` parsing ambiguity in C++2x + // - rvalue references in C++03 + // - `^T &&` parsing ambiguity of compound expression with reflection in C++2x // but then go on and build the declarator. if (Kind == tok::ampamp) { if (D.getContext() == DeclaratorContext::ReflectOperator) { - std::string typeName = "T"; - if (D.hasName()) { - typeName = Actions.GetNameForDeclarator(D).getName().getAsString(); - } + // parser already consumed '^' token before setting this context Diag(Loc, diag::warn_parsing_ambiguity_in_refl_expression_with_ampamp_token) - << typeName; + << (D.hasName() + ? Actions.GetNameForDeclarator(D).getName().getAsString() + : "T"); } Diag(Loc, getLangOpts().CPlusPlus11 From 32c356786a879980103f941506cbd0466d1ba3c5 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Thu, 30 May 2024 20:45:49 +0100 Subject: [PATCH 04/16] fix: add suppressing of introduced warning Signed-off-by: Valentyn Yukhymenko --- clang/include/clang/Basic/DiagnosticGroups.td | 3 +++ clang/include/clang/Basic/DiagnosticParseKinds.td | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 6b595a3567932..7a204a70dd2f5 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1532,3 +1532,6 @@ def BitIntExtension : DiagGroup<"bit-int-extension">; // Warnings about misuse of ExtractAPI options. def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">; + +// Warning related to reflection +def ReflExprParsingAmbiguity : DiagGroup<"reflect-parsing-ambiguity">; \ No newline at end of file diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 00075e052658d..95e85c58560f5 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1715,8 +1715,10 @@ def err_expansion_statements_disabled : Error< "'template for' statements are not enabled; use '-fexpansion-statements'">; def warn_parsing_ambiguity_in_refl_expression_with_ampamp_token : Warning < - "the compound condition may be misinterpreted due to '%0 &&' type parsing logic. did you mean '... (^%0) && ...'?" - >; + "the compound condition may be misinterpreted due to '%0 &&'" + " type parsing logic. did you mean '... (^%0) && ...'?" + >, + InGroup; } let CategoryName = "Generics Issue" in { From 99e65280048417706ee6b22468d8182878a9670b Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Thu, 30 May 2024 22:35:13 +0100 Subject: [PATCH 05/16] feat: add warning for parsing of '&' token in reflection expr Signed-off-by: Valentyn Yukhymenko --- .../clang/Basic/DiagnosticParseKinds.td | 6 ++-- clang/lib/Parse/ParseDecl.cpp | 29 ++++++++++--------- .../test/Parser/cxx2x-ambig-reflect-expr.cpp | 13 ++++++--- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 95e85c58560f5..db110e71bae73 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1714,9 +1714,9 @@ def err_cannot_reflect_entity : Error<"cannot reflect entity">; def err_expansion_statements_disabled : Error< "'template for' statements are not enabled; use '-fexpansion-statements'">; -def warn_parsing_ambiguity_in_refl_expression_with_ampamp_token : Warning < - "the compound condition may be misinterpreted due to '%0 &&'" - " type parsing logic. did you mean '... (^%0) && ...'?" +def warn_parsing_ambiguity_in_refl_expression_with_reference_types : Warning < + "the compound condition may be misinterpreted due to '%0 %1'" + " type parsing logic. did you mean '... (^%0) %1 ...'?" >, InGroup; } diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 20ad465550f82..36902405f4b42 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6750,20 +6750,23 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Is a reference DeclSpec DS(AttrFactory); - // Complain about: - // - rvalue references in C++03 - // - `^T &&` parsing ambiguity of compound expression with reflection in C++2x - // but then go on and build the declarator. + // Complain about parsing ambiguity of parsing reference types + // inside expressions with reflection in C++2x + if (D.getContext() == DeclaratorContext::ReflectOperator) { + // parser already consumed '^' token before setting this context + assert((Kind == tok::ampamp || Kind == tok::amp) && + "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) { - if (D.getContext() == DeclaratorContext::ReflectOperator) { - // parser already consumed '^' token before setting this context - Diag(Loc, - diag::warn_parsing_ambiguity_in_refl_expression_with_ampamp_token) - << (D.hasName() - ? Actions.GetNameForDeclarator(D).getName().getAsString() - : "T"); - } - Diag(Loc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_rvalue_reference : diag::ext_rvalue_reference); diff --git a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp index 69e3c3483d426..206b0a8e0377e 100644 --- a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp +++ b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp @@ -8,7 +8,7 @@ // //===----------------------------------------------------------------------===// // -// RUN: %clang_cc1 -std=c++26 -freflection -verify %s +// RUN: %clang_cc1 -std=c++26 -freflection -Wno-parentheses -verify %s enum MyEnum { x, y, e = -1, f, z = 99 }; @@ -25,8 +25,13 @@ void func(MyEnum && x) { // 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; - // expected-warning@28 {{the compound condition may be misinterpreted due to 'T &&' type parsing logic. did you mean '... (^T) && ...'?}} - // expected-error@28 {{expected ';' at end of declaration}} + constexpr bool test_comparison_4 = (reflValue != (^MyEnum) & true); // ok + + constexpr bool test_comparison_5 = reflValue != ^MyEnum && true; + // expected-warning@30 {{the compound condition may be misinterpreted due to 'T &&' type parsing logic. did you mean '... (^T) && ...'?}} + // expected-error@30 {{expected ';' at end of declaration}} + constexpr bool test_comparison_6 = reflValue != ^MyEnum & true; + // expected-warning@33 {{the compound condition may be misinterpreted due to 'T &' type parsing logic. did you mean '... (^T) & ...'?}} + // expected-error@33 {{expected ';' at end of declaration}} } From 44b62f00517f3510d5f377d2e2b979f0e9b537f5 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Thu, 30 May 2024 22:39:53 +0100 Subject: [PATCH 06/16] style: revert some changes Signed-off-by: Valentyn Yukhymenko --- clang/lib/Parse/ParseDecl.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 36902405f4b42..c3c10f10e37fc 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6766,11 +6766,10 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Complain about rvalue references in C++03, but then go on and build // the declarator. - if (Kind == tok::ampamp) { - Diag(Loc, getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_rvalue_reference - : diag::ext_rvalue_reference); - } + if (Kind == tok::ampamp) + Diag(Loc, getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_rvalue_reference : + diag::ext_rvalue_reference); // GNU-style and C++11 attributes are allowed here, as is restrict. ParseTypeQualifierListOpt(DS); From a13d5e8ced0963293a9f33f6ebacff8210433d19 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Thu, 30 May 2024 22:44:38 +0100 Subject: [PATCH 07/16] style: remove tabs Signed-off-by: Valentyn Yukhymenko --- clang/lib/Parse/ParseDecl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index c3c10f10e37fc..631adb7947450 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6768,8 +6768,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // the declarator. if (Kind == tok::ampamp) Diag(Loc, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_rvalue_reference : - diag::ext_rvalue_reference); + diag::warn_cxx98_compat_rvalue_reference : + diag::ext_rvalue_reference); // GNU-style and C++11 attributes are allowed here, as is restrict. ParseTypeQualifierListOpt(DS); From 67725102639c94a846b53f6b691f70f97ff2177b Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Thu, 30 May 2024 22:45:53 +0100 Subject: [PATCH 08/16] style: remove tabs Signed-off-by: Valentyn Yukhymenko --- clang/lib/Parse/ParseDecl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 631adb7947450..307e07deca791 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6768,8 +6768,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // the declarator. if (Kind == tok::ampamp) Diag(Loc, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_rvalue_reference : - diag::ext_rvalue_reference); + diag::warn_cxx98_compat_rvalue_reference : + diag::ext_rvalue_reference); // GNU-style and C++11 attributes are allowed here, as is restrict. ParseTypeQualifierListOpt(DS); From 7be17b07e88f4c2be9ca9814964247915aaea2b6 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Fri, 31 May 2024 10:56:02 +0100 Subject: [PATCH 09/16] refactor: improve wording in warning Signed-off-by: Valentyn Yukhymenko --- clang/include/clang/Basic/DiagnosticParseKinds.td | 2 +- clang/test/Parser/cxx2x-ambig-reflect-expr.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index db110e71bae73..4271fdf144b43 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1715,7 +1715,7 @@ def err_expansion_statements_disabled : Error< "'template for' statements are not enabled; use '-fexpansion-statements'">; def warn_parsing_ambiguity_in_refl_expression_with_reference_types : Warning < - "the compound condition may be misinterpreted due to '%0 %1'" + "given expression may be misinterpreted due to '%0 %1'" " type parsing logic. did you mean '... (^%0) %1 ...'?" >, InGroup; diff --git a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp index 206b0a8e0377e..a612b520b2888 100644 --- a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp +++ b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp @@ -28,10 +28,10 @@ void func(MyEnum && x) { // ok constexpr bool test_comparison_4 = (reflValue != (^MyEnum) & true); // ok constexpr bool test_comparison_5 = reflValue != ^MyEnum && true; - // expected-warning@30 {{the compound condition may be misinterpreted due to 'T &&' type parsing logic. did you mean '... (^T) && ...'?}} + // expected-warning@30 {{given expression may be misinterpreted due to 'T &&' type parsing logic. did you mean '... (^T) && ...'?}} // expected-error@30 {{expected ';' at end of declaration}} constexpr bool test_comparison_6 = reflValue != ^MyEnum & true; - // expected-warning@33 {{the compound condition may be misinterpreted due to 'T &' type parsing logic. did you mean '... (^T) & ...'?}} + // expected-warning@33 {{given expression may be misinterpreted due to 'T &' type parsing logic. did you mean '... (^T) & ...'?}} // expected-error@33 {{expected ';' at end of declaration}} } From bfdfdd6b561fa4e724ab75522fa218b6054ffe68 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Sun, 9 Jun 2024 16:05:34 +0100 Subject: [PATCH 10/16] refactor: replace hardcoded lines in tests Signed-off-by: Valentyn Yukhymenko --- clang/test/Parser/cxx2x-ambig-reflect-expr.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp index a612b520b2888..a050264a7dace 100644 --- a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp +++ b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp @@ -28,10 +28,10 @@ void func(MyEnum && x) { // ok constexpr bool test_comparison_4 = (reflValue != (^MyEnum) & true); // ok constexpr bool test_comparison_5 = reflValue != ^MyEnum && true; - // expected-warning@30 {{given expression may be misinterpreted due to 'T &&' type parsing logic. did you mean '... (^T) && ...'?}} - // expected-error@30 {{expected ';' at end of declaration}} + // 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@33 {{given expression may be misinterpreted due to 'T &' type parsing logic. did you mean '... (^T) & ...'?}} - // expected-error@33 {{expected ';' at end of declaration}} + // 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}} } From a7365364da1a4a782c0ed47e4d30b99e6f101d1c Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Sun, 9 Jun 2024 16:32:03 +0100 Subject: [PATCH 11/16] fix: false positive warning during parsing rvalue of type `meta::info` Signed-off-by: Valentyn Yukhymenko --- clang/lib/Parse/ParseDecl.cpp | 3 ++- clang/test/Parser/cxx2x-ambig-reflect-expr.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 307e07deca791..41b115df13672 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6752,7 +6752,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Complain about parsing ambiguity of parsing reference types // inside expressions with reflection in C++2x - if (D.getContext() == DeclaratorContext::ReflectOperator) { + 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) && "expected '&' or '&&'"); diff --git a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp index a050264a7dace..08cb0500c3ddd 100644 --- a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp +++ b/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp @@ -33,5 +33,10 @@ void func(MyEnum && x) { // ok 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 } From 3554cdbc04571bc89e4fa4200399e3accbf6cb54 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Sun, 9 Jun 2024 17:03:53 +0100 Subject: [PATCH 12/16] refactor: rename and move test to Reflection folder Signed-off-by: Valentyn Yukhymenko --- .../ambig-reflect-expr-parsing.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename clang/test/{Parser/cxx2x-ambig-reflect-expr.cpp => Reflection/ambig-reflect-expr-parsing.cpp} (100%) diff --git a/clang/test/Parser/cxx2x-ambig-reflect-expr.cpp b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp similarity index 100% rename from clang/test/Parser/cxx2x-ambig-reflect-expr.cpp rename to clang/test/Reflection/ambig-reflect-expr-parsing.cpp From af2a8c1a74ec6565876d547845fb9787202f3e79 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Sun, 9 Jun 2024 17:12:08 +0100 Subject: [PATCH 13/16] refactor: change wording in warning Signed-off-by: Valentyn Yukhymenko --- clang/include/clang/Basic/DiagnosticParseKinds.td | 4 ++-- clang/test/Reflection/ambig-reflect-expr-parsing.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 4271fdf144b43..145569dff4c1d 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1715,8 +1715,8 @@ def err_expansion_statements_disabled : Error< "'template for' statements are not enabled; use '-fexpansion-statements'">; def warn_parsing_ambiguity_in_refl_expression_with_reference_types : Warning < - "given expression may be misinterpreted due to '%0 %1'" - " type parsing logic. did you mean '... (^%0) %1 ...'?" + "token '%1' binds left to type '%0 %1'; " + "did you mean '(^%0) %1'?" >, InGroup; } diff --git a/clang/test/Reflection/ambig-reflect-expr-parsing.cpp b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp index 08cb0500c3ddd..1538243680ef3 100644 --- a/clang/test/Reflection/ambig-reflect-expr-parsing.cpp +++ b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp @@ -28,10 +28,10 @@ void func(MyEnum && x) { // 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-warning@-1 {{token '&' binds left to type 'T &&'; 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-warning@-1 {{token '&' binds left to type 'T &'; did you mean '(^T) &'?}} // expected-error@-2 {{expected ';' at end of declaration}} constexpr auto test_ref_type_0 = ^int &; // ok From 5bb406e9893a5f45febcd8857b5f125a8607a377 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Sun, 9 Jun 2024 17:13:06 +0100 Subject: [PATCH 14/16] fix typo Signed-off-by: Valentyn Yukhymenko --- clang/test/Reflection/ambig-reflect-expr-parsing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Reflection/ambig-reflect-expr-parsing.cpp b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp index 1538243680ef3..95f238d3276ca 100644 --- a/clang/test/Reflection/ambig-reflect-expr-parsing.cpp +++ b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp @@ -28,7 +28,7 @@ void func(MyEnum && x) { // ok constexpr bool test_comparison_4 = (reflValue != (^MyEnum) & true); // ok constexpr bool test_comparison_5 = reflValue != ^MyEnum && true; - // expected-warning@-1 {{token '&' binds left to type 'T &&'; did you mean '(^T) &&'?}} + // expected-warning@-1 {{token '&&' binds left to type 'T &&'; did you mean '(^T) &&'?}} // expected-error@-2 {{expected ';' at end of declaration}} constexpr bool test_comparison_6 = reflValue != ^MyEnum & true; // expected-warning@-1 {{token '&' binds left to type 'T &'; did you mean '(^T) &'?}} From a2aead445e68e5dad89999ae33989b9714e3ad3f Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Sun, 9 Jun 2024 18:22:05 +0100 Subject: [PATCH 15/16] test: add more test cases Signed-off-by: Valentyn Yukhymenko --- .../Reflection/ambig-reflect-expr-parsing.cpp | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/clang/test/Reflection/ambig-reflect-expr-parsing.cpp b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp index 95f238d3276ca..c46ecf255efa7 100644 --- a/clang/test/Reflection/ambig-reflect-expr-parsing.cpp +++ b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp @@ -34,9 +34,30 @@ void func(MyEnum && x) { // ok // expected-warning@-1 {{token '&' binds left to type 'T &'; 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 + constexpr bool test_comparison_7 = ^MyEnum& == reflValue; // ok + constexpr bool test_comparison_8 = ^MyEnum& != reflValue; // ok + + constexpr bool test_comparison_9 = ^MyEnum& < reflValue; + // expected-error@-1 {{invalid operands to binary expression ('meta::info' and 'const meta::info')}} + constexpr bool test_comparison_10 = ^MyEnum& > reflValue; + // expected-error@-1 {{invalid operands to binary expression ('meta::info' and 'const meta::info')}} + constexpr bool test_comparison_11 = ^MyEnum& <= reflValue; + // expected-error@-1 {{invalid operands to binary expression ('meta::info' and 'const meta::info')}} + constexpr bool test_comparison_12 = ^MyEnum& >= reflValue; + // expected-error@-1 {{invalid operands to binary expression ('meta::info' and 'const meta::info')}} + + constexpr auto test_comparison_13 = reflValue != ^MyEnum&& || true; // ok + constexpr auto test_comparison_14 = reflValue != ^MyEnum& | true; // ok + + constexpr auto test_ref_type_0 = ^MyEnum &; // ok + constexpr auto test_ref_type_1 = ^MyEnum &&; // ok + constexpr auto test_ref_type_2 = (^MyEnum &); // ok + constexpr auto test_ref_type_3 = (^MyEnum &&); // ok + + constexpr auto ternary_comparison_test_0 = reflValue == ^MyEnum& ? 1 : 0; // ok + constexpr auto ternary_comparison_test_1 = (2 > 0) ? ^MyEnum& : ^MyEnum; // ok + + constexpr auto test_init_0 {^MyEnum&}; // ok + constexpr auto test_type_id_0 = ^MyEnum&(*)(bool); // ok } From 07bba7b21a471a883d078a835e31b34dbc94bf22 Mon Sep 17 00:00:00 2001 From: Valentyn Yukhymenko Date: Tue, 11 Jun 2024 21:29:56 +0100 Subject: [PATCH 16/16] test: add more test cases Signed-off-by: Valentyn Yukhymenko --- clang/test/Reflection/ambig-reflect-expr-parsing.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clang/test/Reflection/ambig-reflect-expr-parsing.cpp b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp index c46ecf255efa7..0a9ade3ef0d04 100644 --- a/clang/test/Reflection/ambig-reflect-expr-parsing.cpp +++ b/clang/test/Reflection/ambig-reflect-expr-parsing.cpp @@ -47,7 +47,10 @@ void func(MyEnum && x) { // ok // expected-error@-1 {{invalid operands to binary expression ('meta::info' and 'const meta::info')}} constexpr auto test_comparison_13 = reflValue != ^MyEnum&& || true; // ok - constexpr auto test_comparison_14 = reflValue != ^MyEnum& | true; // ok + constexpr auto test_comparison_14 = reflValue != ^MyEnum& | true; // ok + + constexpr auto test_comparison_15 = reflValue != ^MyEnum&; // ok + constexpr auto test_comparison_16 = reflValue == ^MyEnum&; // ok constexpr auto test_ref_type_0 = ^MyEnum &; // ok constexpr auto test_ref_type_1 = ^MyEnum &&; // ok @@ -56,6 +59,7 @@ void func(MyEnum && x) { // ok constexpr auto ternary_comparison_test_0 = reflValue == ^MyEnum& ? 1 : 0; // ok constexpr auto ternary_comparison_test_1 = (2 > 0) ? ^MyEnum& : ^MyEnum; // ok + constexpr auto ternary_comparison_test_2 = (2 > 0) ? ^MyEnum : ^MyEnum&; // ok constexpr auto test_init_0 {^MyEnum&}; // ok constexpr auto test_type_id_0 = ^MyEnum&(*)(bool); // ok