Parse of nested name specifier is modified so that it properly recovers
if colon is mistyped as double colon in case statement.
This patch fixes PR15133.
Details
- Reviewers
- None
Diff Detail
Event Timeline
include/clang/Parse/Parser.h | ||
---|---|---|
172–181 ↗ | (On Diff #7321) | Do we really need this? I would think looking at ColonIsSacred should be enough. That flag is also set for range-based for loops, bit-fields, class base-specifiers, enum underlying type specifiers, and ?:, and in each of these cases we want this behavior. |
lib/Parse/ParseExprCXX.cpp | ||
476 | Should this be a 'break' rather than a 'return'? We should presumably still annotate the prior tokens as a scope specifier. | |
test/Parser/recovery.cpp | ||
152–153 | These diagnostics could be better. Ideally we'd only issue one error, and it would say something like 'V1' cannot appear before '::' because it is not a class, namespace, or scoped enumeration; did you mean ':'? ... maybe with a note pointing to the declaration of 'V1'. | |
160 | You don't have any tests for this case: case V1:: func_1(0); ... which might go down a different path in the parser because it's got an identifier after the '::'. | |
test/SemaCXX/nested-name-spec.cpp | ||
16 | Can you split this change out into a separate patch? Also, it'd be great to fix the diagnostic as described above to more clearly explain the problem: 'ax' cannot appear before '::' because it is not a class, namespace, or scoped enumeration ... with a note pointing to the declaration of 'ax'. |
include/clang/Parse/Parser.h | ||
---|---|---|
172–181 ↗ | (On Diff #7321) | Remade patch excluding this context info. |
lib/Parse/ParseExprCXX.cpp | ||
476 | This function doesn't do much after exit from loop, but using 'break' is better of course. | |
test/Parser/recovery.cpp | ||
152–153 | Implemented in this way. | |
160 | Indeed, this case didn't handled properly. |
include/clang/Basic/DiagnosticParseKinds.td | ||
---|---|---|
65–66 | We already have this: diag::note_declared_at. | |
lib/Parse/ParseExprCXX.cpp | ||
474 | Why do you exclude the ObjectType case here? If we have: struct S { int n; } s; int k = true ? s.n :: 0; ... we should issue the correction. | |
475–476 | I don't like coupling this check to the check in ActOnCXXNestedNameSpecifier. If these don't match *exactly*, we can fail to emit a diagnostic for the failed lookup here. Can you instead pass in a bool *, have ActOnCXXNestedNameSpecifier set it if finds the nested name specifier names something that's not valid on the LHS of a ::, and check that flag here? (And remove IsValidIfFollowedByColon.) | |
lib/Parse/ParseStmt.cpp | ||
641–648 | Please fold these together: } else if (TryConsumeToken(tok::semi, ColonLoc) || TryConsumeToken(tok::coloncolon, ColonLoc)) { | |
lib/Sema/SemaCXXScopeSpec.cpp | ||
513 | I think we should do this if SS is not set too (that is, if we have an ObjectType, we should perform qualified lookup into it, rather than unqualified lookup). |
include/clang/Basic/DiagnosticParseKinds.td | ||
---|---|---|
65–66 | Overlooked it. Thank you for the hint. | |
lib/Parse/ParseExprCXX.cpp | ||
474 | Fixed. | |
475–476 | IsValidIfFollowedByColon is removed, declaration of ActOnCXXNestedNameSpecifier changed accordingly. | |
lib/Parse/ParseStmt.cpp | ||
641–648 | Done. | |
lib/Sema/SemaCXXScopeSpec.cpp | ||
513 | Fixed. |
Sorry for the delay!
include/clang/Basic/DiagnosticParseKinds.td | ||
---|---|---|
342–343 | Either the second thing here should be %1 (and you pass in tok::colon), or this diagnostic should have a better name. "did you mean ':'?" is not an obvious thing to say about a nested name specifier =) Also, using %1 will let you merge this with the previous diagnostic. While you're here, please change unexected to unexpected in both diagnostic names. :) | |
lib/Parse/ParseExprCXX.cpp | ||
470–483 | I think it'd be cleaner to pass a bool *CorrectToColon into ActOnCXXNestedNameSpecifier, and issue the diagnostics there (so this diagnostic is not split into two disparate places). Then, if the flag is set, just fix up the token stream here. | |
lib/Sema/SemaCXXScopeSpec.cpp | ||
521 | This will silently ignore the error if you're in DontReportWrongMember mode and name lookup finds something other than a single result. | |
526 | This should probably be an else. If the caller picks DontReportWrongMember, IdDeclPtr is mandatory as they otherwise wouldn't know whether they're required to emit a diagnostic. |
Thank you for feedback!
include/clang/Basic/DiagnosticParseKinds.td | ||
---|---|---|
342–343 | Yes, I see. Tried to make more descriptive message. | |
lib/Parse/ParseExprCXX.cpp | ||
470–483 | This is good approach. Looks like patch becomes more compact. | |
lib/Sema/SemaCXXScopeSpec.cpp | ||
521 | Remade this test. |
Thank you!
2014-04-13 8:25 GMT+07:00 Richard Smith <richard@metafoo.co.uk>:
This looks great, thanks! Some tiny tweaks, then please commit.Comment at: lib/Sema/SemaCXXScopeSpec.cpp:533
@@ +532,3 @@
+ }
+ // Replacement '::' -> is not allowed, just issue respective error.+ if (!ErrorRecoveryLookup) {
I assume this was supposed to say '::' -> ':' is not allowed?
Comment at: lib/Sema/SemaCXXScopeSpec.cpp:524
@@ +523,3 @@
+ *IsCorrectedToColon = true;
+ if (!ErrorRecoveryLookup) {+ Diag(CCLoc, diag::err_nested_name_spec_is_not_class)
This check is redundant: we're already inside an `if
(!ErrorRecoveryLookup)` check.Comment at: lib/Sema/SemaCXXScopeSpec.cpp:534
@@ +533,3 @@
+ // Replacement '::' -> is not allowed, just issue respective error.
+ if (!ErrorRecoveryLookup) {+ Diag(R.getNameLoc(), diag::err_expected_class_or_namespace)
Likewise.
BRANCH
pr15133ARCANIST PROJECT
clang
We already have this: diag::note_declared_at.