This is an archive of the discontinued LLVM Phabricator instance.

[Clang] Extend init-statement to allow alias-declaration
ClosedPublic

Authored by cor3ntin on Oct 5 2021, 12:04 PM.

Details

Summary

Implement P2360R0 in C++23 mode and as an extension in older
languages mode.

Diff Detail

Event Timeline

cor3ntin created this revision.Oct 5 2021, 12:04 PM
cor3ntin requested review of this revision.Oct 5 2021, 12:04 PM
Herald added a project: Restricted Project. · View Herald TranscriptOct 5 2021, 12:04 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Thank you for this new feature work! Adding a few more reviewers to the mix.

Can you also add a release note for the new functionality?

clang/include/clang/Basic/DiagnosticParseKinds.td
553

This diagnostic confuses me. An init-statement can be an expression-statement, simple-declaration, or alias-declaration. So if we're in an init-statement and see a using keyword, the only think we can be parsing is an alias declaration, right?

I guess I would have expected that we'd eventually wind up calling Parser::ParseAliasDeclarationAfterDeclarator() via ParseUsingDeclaration() and that would handle any parsing-related concerns with the construct.

Beyond that -- users don't really know what an init statement is, I think we'd usually call this a "condition" instead of an init statement in diagnostics.

555

Same concern here about "init statements", we probably should list the constructs specifically.

Also, I think we're missing the "is incompatible with standards before" variant of this extension diagnostic.

clang/lib/Parse/ParseExprCXX.cpp
1924–1928

Okay, to verify my understanding of the logic here: you call ParseUsingDeclaration(), but that may parse a using declaration or an alias declaration, so you need to handle the case where it parsed something that's not allowed.

Assuming that's correct, I think a better approach is for ParseUsingDeclaration() to pay attention to the DeclaratorContext it is given, and when it's an init statement, refuse to parse anything other than an alias declaration. Then you can get rid of err_expected_alias_after_using_in_init_statement entirely, as the user will get the typical parsing errors. If those diagnostics are low quality and we need a custom diagnostic instead, that logic can live in ParseUsingDeclaration() instead.

That just about obviates the need for ParseAliasDeclarationInInitStatement() entirely, but this function still adds value because of the extension/precompat warnings so I think it's worth keeping around.

rsmith added inline comments.Oct 6 2021, 12:11 PM
clang/include/clang/Basic/DiagnosticParseKinds.td
553

I think there's a more fundamental problem with this diagnostic: it's a compiler-oriented explanation of what went wrong *for us*, not a user-oriented explanation of what's wrong *with their code*. If the user wrote if (using X::A; A a = b) or if (using namespace N; ...), telling them that they could have written an alias declaration instead is not helpful -- that has no relevance to the problem they're trying to solve. It'd be better to say "using [namespace] declaration cannot appear here" and not mention alias declarations at all.

555

We could use a %select to specify the context instead of saying "init statement", but actually describing the contexts seems hard to do succinctly and clearly. In this case I think it'd be OK to just say "in this context" or similar if we don't want to mention init-statements. (As far as I can tell, literally no-one outside a C++ parser's test suite has ever put a typedef in an init-statement, so we should similarly assume this feature will never be used outside our own tests. The %select is probably not worth the effort.)

I agree with aaron, the ParseUsingDeclaration bit should be aware of the DeclaratorContext and emit the error there, rather than try to parse it as whatever and THEN error.

The problem is the user-interface at that point, which is to spend a few cycles correcting one of the other forms, just to then tell them it isn't permitted. This is a case where erroring 'early' in this case would be a much better user experience.

clang/include/clang/Parse/Parser.h
2401

Slight preference for reversing these conditions

clang/lib/Parse/ParseExprCXX.cpp
2047

single line if/else don't get '{' or '}'.

cor3ntin planned changes to this revision.Oct 6 2021, 2:57 PM
cor3ntin added inline comments.
clang/include/clang/Basic/DiagnosticParseKinds.td
553

We do but ParseUsingDeclaration can parse other things, which are not allowed there.
I will try to modify ParseUsingDeclaration, which might not lead to better diagnostics, but at least won't be compiler-oriented.

555

This was my justification for not doing more work. I agree that "in this context" is better

clang/lib/Parse/ParseExprCXX.cpp
1924–1928

Yes, I considered modifying ParseUsingDeclaration but wanted to keep the change somewhat localized, and keep ParseUsingDeclaration as is on the basis that no other place in the standard only accept alias-declaration. But the solution you suggest is certainly possible.
I don't know how much better the diagnostic would be.

cor3ntin updated this revision to Diff 377755.Oct 7 2021, 12:29 AM
cor3ntin marked an inline comment as done.
  • Modify ParseUsingDeclaration to only parse an alias in init statememts
  • Make the c++23 extebsion warning clearer
  • Nitpicks.

The error is now 'expected '=', which seems good enough in that scenario.

cor3ntin marked 2 inline comments as done.Oct 7 2021, 12:30 AM
cor3ntin updated this revision to Diff 377756.Oct 7 2021, 12:32 AM

Update release notes

aaron.ballman added inline comments.Oct 7 2021, 9:39 AM
clang/include/clang/Basic/DiagnosticParseKinds.td
552–553

Can you also add the "incompatible with standards before C++2b" variant of this diagnostic?

clang/lib/Parse/ParseDeclCXX.cpp
720–722 ↗(On Diff #377756)
clang/lib/Parse/ParseExprCXX.cpp
1927–1930

Though I suspect this will change somewhat when you add the precompat warning.

2050–2053
clang/lib/Parse/ParseTentative.cpp
486–489

No else after a return, and can drop the curly braces, per coding standard.

cor3ntin updated this revision to Diff 377921.Oct 7 2021, 11:20 AM
cor3ntin marked 3 inline comments as done.

Add C++20 compat warning, fix style.

erichkeane added inline comments.Oct 7 2021, 11:26 AM
clang/test/Parser/cxx2b-init-statement.cpp
20

Is there any way to have this elaborate more? The 'expected 'TOKEN'' is my least favorite type of error. Could we change this to be something like, 'expected '=' in type alias' or something?

Just nits from me, but otherwise LGTM!

clang/include/clang/Basic/DiagnosticParseKinds.td
556
clang/include/clang/Parse/Parser.h
1982
clang/lib/Parse/ParseExprCXX.cpp
1915
clang/test/Parser/cxx2b-init-statement.cpp
20

FWIW, I'm fine with the diagnostic as-is because I don't expect anyone to actually *use* this functionality, so I don't expect a ton of users to hit this. I'd say it's fine to address when a user files a bug showing some code where the diagnostic is unclear.

cor3ntin updated this revision to Diff 377929.Oct 7 2021, 11:39 AM

fix diagnostic, nits

cor3ntin updated this revision to Diff 377930.Oct 7 2021, 11:41 AM

Fix version in diagnostics in the right direction (23 => 2b)

erichkeane added inline comments.Oct 7 2021, 11:43 AM
clang/test/Parser/cxx2b-init-statement.cpp
20

I'm sad by this, and Aaron points out it is a bit of a hassle, so I can disagree & commit here.

erichkeane accepted this revision.Oct 7 2021, 11:47 AM
This revision is now accepted and ready to land.Oct 7 2021, 11:47 AM
cor3ntin added inline comments.Oct 7 2021, 11:49 AM
clang/test/Parser/cxx2b-init-statement.cpp
20

Yeah, i guess we could but i really do not expect that feature to have a lot of uses. So i tried to keep the patch minimal.

erichkeane added inline comments.Oct 7 2021, 11:54 AM
clang/test/Parser/cxx2b-init-statement.cpp
20

Aaron and I discussed it, and I'm willing to relent, so feel free to land. In Aaron's opinion right now:

Effort to improve diagnostic >(greatly) Chance of someone running into it

I'm willing to wait until there is proof of the RHS of that equation being of greater magnitude before being willing to ask for the effort on the LHS.

aaron.ballman closed this revision.Oct 8 2021, 4:15 AM

I've commit on your behalf in ff013b61004b01043bdbebb6416c30ecb3d3d48c, thank you for the new functionality!