This is an archive of the discontinued LLVM Phabricator instance.

Suggest fix-it ':' when '=' used in for-range-declaration while initializing an auto
ClosedPublic

Authored by ismailp on Apr 14 2014, 1:04 PM.

Details

Reviewers
dblaikie
bkramer
Summary

I patched this during an evening at ACCU 2014 last week, but seems like I forgot to send it.

This is fix for PR19176:

int arr[] = {1, 2, 3, 4};
for (auto i = arr)
  (void)i;

possibly meant:

for (auto i : arr)

This is going to be issued iff for range declaration begins with auto keyword in C++11 mode.

Diff Detail

Event Timeline

rsmith added inline comments.Apr 14 2014, 5:53 PM
lib/Parse/ParseStmt.cpp
1479–1484

It's not really OK to use a tentative parse every time you see for (auto. Tentative parses aren't free, and that's a really common pattern.

An alternative approach would be to track (possibly on Declarator) whether we're parsing the first variable declared in a for statement. In that case, when we get to the end of the initializer, if the next token is ), then recover by correcting the = to a :.

That'll do the wrong thing for cases like int x[] = {1, 2, 3}; for (auto x = x) (name lookup will find the wrong x), but it's close enough.

ismailp updated this revision to Unknown Object (????).Apr 15 2014, 2:34 PM

TentativeParsingAction has been removed. Diagnostics has been moved into ParseDeclarationAfterDeclaratorAndAttributes. The note has been converted into a warning. We are trying to identify a single variable declaration in a for statement where type of variable is auto.

rsmith added inline comments.May 6 2014, 6:14 PM
include/clang/Basic/DiagnosticParseKinds.td
207

This should be an ExtWarn or (strongly preferably) just an Error. I don't see any good reason to support this as an extension.

include/clang/Parse/Parser.h
1731

You don't need this new flag. Use Declarator::isFirstDeclarator instead.

lib/Parse/ParseDecl.cpp
1837

Why check TypeContainsAuto? I don't think that's a good indicator either way.

1839–1840

Please try to avoid follow-on errors here. After giving your error message, perhaps mark Init as invalid, and make sure that the rest of the parsing code handles this without producing spurious diagnostics.

ismailp updated this revision to Diff 9188.May 7 2014, 1:56 PM
ismailp edited edge metadata.

Richard,

thank you for feedback. Briefly, changes since last revision:

  • Replaced warning with an error. This is going to be the only diagnostics emitted for this case.
  • TypeContainsAuto is removed from check; I thought auto (strongly) suggests that this is a range-based for, while an int, for example, is not that strong.
  • Pass ForRangeInit down to ParseDeclarationAfterDeclaratorAndAttributes to set ForRangeInit::ColonLoc; this tells parser to treat a for statement as a "range-based for".
  • Fix-it uses spelling location for replacement to handle macro expansions
rsmith added a comment.May 7 2014, 4:50 PM

Looks good with some minor tweaks.

lib/Parse/ParseDecl.cpp
1835–1836

Instead of checking for C++11 and ForContext here, just check FRI.

1839–1841

Please don't deviate from the usual convention here -- if we choose to apply typo-corrections within macros, that should be a centralized decision -- just pass in EqualLoc.

1845–1846

Also FRI->RangeExpr = Init; ?

1855–1856

I think the right thing to do here is to add tok::r_paren to the stop set if the context is ForContext.

Thank you, Richard. Changes:

  • Don't use spelling location.
  • Add tok::r_paren to stop set.
  • Check FRI instead of ForContext and CPlusPlus11.
  • Invalidate FRI->RangeExpr

Committed in r208299.

bkramer accepted this revision.May 9 2014, 10:41 AM
bkramer edited edge metadata.

Silly phab

This revision is now accepted and ready to land.May 9 2014, 10:41 AM
bkramer closed this revision.May 9 2014, 10:41 AM