This is an archive of the discontinued LLVM Phabricator instance.

Improve error recovery around colon.
AbandonedPublic

Authored by sepavloff on Feb 24 2014, 9:08 AM.

Details

Reviewers
None
Summary

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.

Diff Detail

Event Timeline

rsmith added inline comments.Feb 24 2014, 1:34 PM
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
474

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'.

sepavloff updated this revision to Unknown Object (????).Mar 5 2014, 8:15 PM

Updated patch

sepavloff added inline comments.Mar 5 2014, 8:21 PM
include/clang/Parse/Parser.h
172–181 ↗(On Diff #7321)

Remade patch excluding this context info.

lib/Parse/ParseExprCXX.cpp
474

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.

rsmith added inline comments.Mar 11 2014, 6:45 PM
include/clang/Basic/DiagnosticParseKinds.td
65–66

We already have this: diag::note_declared_at.

lib/Parse/ParseExprCXX.cpp
472

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.

473–474

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
550

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).

sepavloff updated this revision to Unknown Object (????).Mar 16 2014, 10:07 AM

Updated patch according to reviewer's notes.

sepavloff added inline comments.Mar 16 2014, 10:12 AM
include/clang/Basic/DiagnosticParseKinds.td
65–66

Overlooked it. Thank you for the hint.

lib/Parse/ParseExprCXX.cpp
472

Fixed.

473–474

IsValidIfFollowedByColon is removed, declaration of ActOnCXXNestedNameSpecifier changed accordingly.

lib/Parse/ParseStmt.cpp
641–648

Done.

lib/Sema/SemaCXXScopeSpec.cpp
550

Fixed.

rsmith added a comment.Apr 2 2014, 6:50 PM

Sorry for the delay!

include/clang/Basic/DiagnosticParseKinds.td
344–345

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
468–481

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
558

This will silently ignore the error if you're in DontReportWrongMember mode and name lookup finds something other than a single result.

563

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.

sepavloff updated this revision to Unknown Object (????).Apr 4 2014, 5:00 AM

Updated patch

Thank you for feedback!

include/clang/Basic/DiagnosticParseKinds.td
344–345

Yes, I see. Tried to make more descriptive message.
Also changed typos in diagnostic names :)

lib/Parse/ParseExprCXX.cpp
468–481

This is good approach. Looks like patch becomes more compact.

lib/Sema/SemaCXXScopeSpec.cpp
558

Remade this test.

rsmith accepted this revision.Apr 12 2014, 6:25 PM

This looks great, thanks! Some tiny tweaks, then please commit.

lib/Sema/SemaCXXScopeSpec.cpp
524

This check is redundant: we're already inside an if (!ErrorRecoveryLookup) check.

533

I assume this was supposed to say '::' -> ':' is not allowed?

534

Likewise.

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.

http://reviews.llvm.org/D2870

BRANCH

pr15133

ARCANIST PROJECT

clang
sepavloff removed a subscriber: cfe-commits.
This revision now requires review to proceed.Aug 14 2015, 11:33 AM
sepavloff abandoned this revision.Aug 14 2015, 11:34 AM

Committed in revision 206135.