diff options
| author | Ben Hamilton <benhamilton@google.com> | 2018-04-27 18:51:12 +0000 |
|---|---|---|
| committer | Ben Hamilton <benhamilton@google.com> | 2018-04-27 18:51:12 +0000 |
| commit | 345f8739d80eda6d45722e42056d6b5a42a6dc87 (patch) | |
| tree | 0020620864678a9de04d65233431d5fb3d4efe5f /clang/lib/Format | |
| parent | 47aece134448f60b4091a882da604fd7500ae9bd (diff) | |
| download | bcm5719-llvm-345f8739d80eda6d45722e42056d6b5a42a6dc87.tar.gz bcm5719-llvm-345f8739d80eda6d45722e42056d6b5a42a6dc87.zip | |
[clang-format/ObjC] Use getIdentifierInfo() instead of tok::identifier
Summary:
Previously, we checked tokens for `tok::identifier` to see if they
were identifiers inside an Objective-C selector.
However, this missed C++ keywords like `new` and `delete`.
To fix this, this diff uses `getIdentifierInfo()` to find
identifiers or keywords inside Objective-C selectors.
Test Plan: New tests added. Ran tests with:
% make -j16 FormatTests && ./tools/clang/unittests/Format/FormatTests
Reviewers: djasper, jolesiak
Reviewed By: djasper
Subscribers: klimek, cfe-commits
Differential Revision: https://reviews.llvm.org/D46143
llvm-svn: 331067
Diffstat (limited to 'clang/lib/Format')
| -rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 49e21520b70..475eadd9f4c 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -25,6 +25,21 @@ namespace format { namespace { +/// \brief Returns \c true if the token can be used as an identifier in +/// an Objective-C \c @selector, \c false otherwise. +/// +/// Because getFormattingLangOpts() always lexes source code as +/// Objective-C++, C++ keywords like \c new and \c delete are +/// lexed as tok::kw_*, not tok::identifier, even for Objective-C. +/// +/// For Objective-C and Objective-C++, both identifiers and keywords +/// are valid inside @selector(...) (or a macro which +/// invokes @selector(...)). So, we allow treat any identifier or +/// keyword as a potential Objective-C selector component. +static bool canBeObjCSelectorComponent(const FormatToken &Tok) { + return Tok.Tok.getIdentifierInfo() != nullptr; +} + /// \brief A parser that gathers additional information about tokens. /// /// The \c TokenAnnotator tries to match parenthesis and square brakets and @@ -703,9 +718,10 @@ private: Tok->Type = TT_CtorInitializerColon; else Tok->Type = TT_InheritanceColon; - } else if (Tok->Previous->is(tok::identifier) && Tok->Next && + } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next && (Tok->Next->isOneOf(tok::r_paren, tok::comma) || - Tok->Next->startsSequence(tok::identifier, tok::colon))) { + (canBeObjCSelectorComponent(*Tok->Next) && Tok->Next->Next && + Tok->Next->Next->is(tok::colon)))) { // This handles a special macro in ObjC code where selectors including // the colon are passed as macro arguments. Tok->Type = TT_ObjCMethodExpr; @@ -1346,7 +1362,7 @@ private: TT_LeadingJavaAnnotation)) { Current.Type = Current.Previous->Type; } - } else if (Current.isOneOf(tok::identifier, tok::kw_new) && + } else if (canBeObjCSelectorComponent(Current) && // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen. Current.Previous && Current.Previous->is(TT_CastRParen) && Current.Previous->MatchingParen && @@ -2650,7 +2666,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (Line.Type == LT_ObjCMethodDecl) { if (Left.is(TT_ObjCMethodSpecifier)) return true; - if (Left.is(tok::r_paren) && Right.isOneOf(tok::identifier, tok::kw_new)) + if (Left.is(tok::r_paren) && canBeObjCSelectorComponent(Right)) // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a // keyword in Objective-C, and '+ (instancetype)new;' is a standard class // method declaration. @@ -3128,6 +3144,7 @@ void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) { for (unsigned i = 0, e = Tok->FakeLParens.size(); i != e; ++i) llvm::errs() << Tok->FakeLParens[i] << "/"; llvm::errs() << " FakeRParens=" << Tok->FakeRParens; + llvm::errs() << " II=" << Tok->Tok.getIdentifierInfo(); llvm::errs() << " Text='" << Tok->TokenText << "'\n"; if (!Tok->Next) assert(Tok == Line.Last); |

