-
Notifications
You must be signed in to change notification settings - Fork 210
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
Add basic support for c++20 three-way comparison operator #219
Add basic support for c++20 three-way comparison operator #219
Conversation
Hello @i-garrison, Thank you for your interest to CDT project. There are several points to be completed to make CI happy:
|
@i-garrison Thank you for the PR. I put a callout on cdt-dev archives for some help reviewing this. |
8483ae5
to
f871e85
Compare
Hi @jonahgraham thanks for looking into this. |
I don't know. I have renewed my callout on cdt-dev and hope that someone will step forward. If not it sounds like I need to learn this area of the code as the original authors and subsequent maintainers are not active anymore. |
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.
Hi @i-garrison,
I haven't fixed anything in the cdt parser yet, so please take my suggestions with a grain of salt :)
What I did to review your code was testing some use cases and searching in the cdt code for greaterEqual
and in the tests for >=
in order to find the places in the code which might have to be adapted.
My findings [1]:
- The source code formatter is broken,
<=>
will be formatted to<= >
- A case switch for
op_threewaycomparison
seems to be missing inorg.eclipse.cdt.internal.core.dom.parser::VariableReadWriteFlags::rwInBinaryExpression
- You might want to add a test case for the comparator to
org.eclipse.cdt.core.parser.tests.ast2.AST2Tests::testCExpressions
- You might want to add a test case for the comparator to
/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterExpressionTestSource.awts
- As you mentioned, the three way operator support is not complete, and you already added some
// TODO
tasks to the code. I found two places in the code, where I think you could add some more tasks:
org.eclipse.cdt.internal.core.dom.rewrite.astwriter::ExpressionWriter::getBinaryExpressionOperator
org.eclipse.cdt.internal.ui.refactoring.include::BindingClassifier::leave
[1] I didn't find a way to add comments to files which are not part of the commit, is this possible with github?
core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTBinaryExpression.java
Show resolved
Hide resolved
.../org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java
Show resolved
Hide resolved
case IASTBinaryExpression.op_shiftLeft: | ||
case IASTBinaryExpression.op_shiftRight: | ||
return 8; |
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.
I struggled a little bit to understand the use case of the binary vs cast ambiguation, as I couldn't come up with any examples to test this. However your changes look reasonable, you just added <=> and gave it a higher precedence.
Thanks, I completely missed formatter changes here - will fix that. |
f871e85
to
999137a
Compare
Not possible, but there is a discussion about this feature community/community#9099 |
999137a
to
bf0d0cc
Compare
Fixed and added new test case to |
This requires parsing via C++20-enabled scanner which would recognize new It might be easier to look at second and following commits individually, as test case changes for |
Implemented this and also added support for C++20 syntax hint in awts. |
Add STD and GNU scanner configuration ids and pass these as needed instead of boolean flag useGNUExtensions. This will be used later by C++20 scanner tests.
8c26177
to
4223f05
Compare
Thank you @ddscharfe I fixed a couple of issues while doing tests (updated first commit with required changes.)
This needs a bit of research - need to pass the
This is now implemented to fix awst rewriter test.
I just left a shortcut for now in |
You could use the @Override
public IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {
final MultiPassContentFormatter formatter = new MultiPassContentFormatter(
getConfiguredDocumentPartitioning(sourceViewer), IDocument.DEFAULT_CONTENT_TYPE);
Supplier<Boolean> supportThreeway = () -> {
try {
if (fTextEditor instanceof ITranslationUnitHolder tuHolder) {
IASTTranslationUnit ast = ((CEditor) fTextEditor).getTranslationUnit().getAST();
if (ast != null) {
IASTPreprocessorMacroDefinition[] builtinMacroDefinitions = ast.getBuiltinMacroDefinitions();
// search for the threeway builtin macro
return true;
}
}
} catch (CoreException e) {
e.printStackTrace();
}
return false;
};
formatter.setMasterStrategy(new CFormattingStrategy(supportThreeway));
return formatter;
} However this brings me back your initial concern:
As far as I understand how CDT handled new language features until now (e.g. lambdas) was adding support in the parser, regardless of what compiler is used for building. So for instance when you have an old compiler which doesn't support lambdas, the C++ Editor will not mark lambdas as an error, unless you compile the project. |
To my mind this strategy will not work with new class A;
using Op = bool (&)(const A&, const A&);
template<Op op> class B;
bool operator<=(const A&, const A&);
using C = B<operator<=>; I have never encountered this in the wild though, so the example could be a bit synthetic. |
Good point, and I'm sure having compilers pre-c++20 will remain a use case for quiet some time, so this would be a problem indeed. I still think that not having a flag/setting might be the best solution, as it avoids introducing new complexity (plus the user has to know how to enable this). But maybe there already is some possibility for such a setting which we're not aware of. |
o.e.cdt.core 8.0.0 was released as part of CDT 11, so this new non-breaking API needs a version bump to 8.1.0.
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.
This looks promising so far. Not sure what it will take to see this to completion still, but with the feature flag we can probably merge sooner rather than later on it.
core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ValueFactory.java
Show resolved
Hide resolved
@@ -548,6 +548,7 @@ private IASTExpression expression(final ExprKind kind) throws EndOfFileException | |||
break; | |||
case IToken.tEQUAL: | |||
case IToken.tNOTEQUAL: | |||
case IToken.tTHREEWAYCOMPARISON: |
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.
In the C++ the <=>
has different precedence than =
and !=
, but in C it has the same.
Is <=>
part of C? I couldn't find reference to that in future C specs.
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.
Operator <=>
is C++ only because it's result is defined to be an object of ordering type defined in <compare>
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.
but in C it has the same
This is a bug, should not be in C
parser, dropped now.
.../org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/scanner/CPreprocessor.java
Show resolved
Hide resolved
core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java
Show resolved
Hide resolved
core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/Keywords.java
Show resolved
Hide resolved
@@ -234,6 +234,10 @@ public IType getExpressionType() { | |||
case op_notequals: | |||
return new CBasicType(Kind.eInt, 0, this); | |||
|
|||
case op_threewaycomparison: | |||
// TODO: implement for <=> |
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.
Does this need implementing support for strong and partial ordering? Or can this be folded into the above cases as a return new CBasicType(Kind.eInt, 0, this);
?
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.
I did not looked into this, complete implementation should somehow inject types from <compare>
header. This could be looked into later.
@@ -167,6 +167,10 @@ private ICPPFunction[] create() { | |||
comparison(true); | |||
break; | |||
|
|||
case THREEWAYCOMPARISON: | |||
// TODO: implement for <=> |
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.
I have run out of time on this first pass to understand what this bit of code does and what needs to be done.
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.
Planned to look into this later, together with synthesized comparison operators.
@@ -388,6 +389,10 @@ public IType computeType() { | |||
case op_notequals: | |||
return CPPBasicType.BOOLEAN; | |||
|
|||
case op_threewaycomparison: | |||
// TODO: implement for <=> | |||
return ProblemType.UNKNOWN_FOR_EXPRESSION; |
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.
Similar to other comment, does this todo require strong/partial ordering understanding, or can this just be a basic integer?
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.
I planned to look into evaluation stuff later, this needs more investigation.
For the remaining items, is this something that needs to be investigated/done before we merge, or as follow-up tasks later? If its the former, please move this to a draft. If it is the latter I will try to complete the review with that goal in mind. |
I believe remaining items can be done later. This change should already be useful since it fixes parse errors with c++20 code because standard library now uses |
@ddscharfe I would appreciate it if you could complete a final review before I merge this. @i-garrison I am happy to merge as is so that we can get this in 2023-03 M2 on Monday and get it out there so that we can get feedback sooner. I'm just going to wait for @ddscharfe's review in case he has anything to add before it goes in. |
Thanks for looking into this! |
My count was the diff was just < 1000 lines. Either way, there is some discretion involved here. As most of the lines of diff are in e1d429f which was changing the false/true to the enum, no need for review as that change is clearly not an IP concern. |
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.
My count was the diff was just < 1000 lines. Either way, there is some discretion involved here. As most of the lines of diff are in e1d429f which was changing the false/true to the enum, no need for review as that change is clearly not an IP concern.
+1
Thanks @i-garrison for improving user's experience with C++20. Thanks @ddscharfe for the reviews. |
This adds initial support for
operator<=>
, corresponding Lexer option is enabled if__cpp_impl_three_way_comparison
feature-test macro is found.Support is very rudimentary (e.g. return type deduction is not implemented, expression evaluation is not handled etc..)