benhamilton created this revision. benhamilton added reviewers: djasper, jolesiak. Herald added subscribers: cfe-commits, klimek.
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 Repository: rC Clang https://reviews.llvm.org/D46143 Files: lib/Format/TokenAnnotator.cpp unittests/Format/FormatTestObjC.cpp Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -945,15 +945,26 @@ " }]) {\n}"); } -TEST_F(FormatTestObjC, ObjCNew) { +TEST_F(FormatTestObjC, ObjCCxxKeywords) { verifyFormat("+ (instancetype)new {\n" " return nil;\n" "}\n"); verifyFormat("+ (instancetype)myNew {\n" " return [self new];\n" "}\n"); verifyFormat("SEL NewSelector(void) { return @selector(new); }\n"); verifyFormat("SEL MacroSelector(void) { return MACRO(new); }\n"); + verifyFormat("+ (instancetype)delete {\n" + " return nil;\n" + "}\n"); + verifyFormat("+ (instancetype)myDelete {\n" + " return [self delete];\n" + "}\n"); + verifyFormat("SEL DeleteSelector(void) { return @selector(delete); }\n"); + verifyFormat("SEL MacroSelector(void) { return MACRO(delete); }\n"); + verifyFormat("MACRO(new:)\n"); + verifyFormat("MACRO(delete:)\n"); + verifyFormat("foo = @{MACRO(new:) : MACRO(delete:)}\n"); } TEST_F(FormatTestObjC, ObjCLiterals) { Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -703,9 +703,10 @@ Tok->Type = TT_CtorInitializerColon; else Tok->Type = TT_InheritanceColon; - } else if (Tok->Previous->is(tok::identifier) && Tok->Next && + } else if (Tok->Previous->Tok.getIdentifierInfo() && Tok->Next && (Tok->Next->isOneOf(tok::r_paren, tok::comma) || - Tok->Next->startsSequence(tok::identifier, tok::colon))) { + (Tok->Next->Tok.getIdentifierInfo() && 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 +1347,7 @@ TT_LeadingJavaAnnotation)) { Current.Type = Current.Previous->Type; } - } else if (Current.isOneOf(tok::identifier, tok::kw_new) && + } else if (Current.Tok.getIdentifierInfo() && // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen. Current.Previous && Current.Previous->is(TT_CastRParen) && Current.Previous->MatchingParen && @@ -2650,7 +2651,7 @@ 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) && Right.Tok.getIdentifierInfo()) // 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 +3129,7 @@ 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);
Index: unittests/Format/FormatTestObjC.cpp =================================================================== --- unittests/Format/FormatTestObjC.cpp +++ unittests/Format/FormatTestObjC.cpp @@ -945,15 +945,26 @@ " }]) {\n}"); } -TEST_F(FormatTestObjC, ObjCNew) { +TEST_F(FormatTestObjC, ObjCCxxKeywords) { verifyFormat("+ (instancetype)new {\n" " return nil;\n" "}\n"); verifyFormat("+ (instancetype)myNew {\n" " return [self new];\n" "}\n"); verifyFormat("SEL NewSelector(void) { return @selector(new); }\n"); verifyFormat("SEL MacroSelector(void) { return MACRO(new); }\n"); + verifyFormat("+ (instancetype)delete {\n" + " return nil;\n" + "}\n"); + verifyFormat("+ (instancetype)myDelete {\n" + " return [self delete];\n" + "}\n"); + verifyFormat("SEL DeleteSelector(void) { return @selector(delete); }\n"); + verifyFormat("SEL MacroSelector(void) { return MACRO(delete); }\n"); + verifyFormat("MACRO(new:)\n"); + verifyFormat("MACRO(delete:)\n"); + verifyFormat("foo = @{MACRO(new:) : MACRO(delete:)}\n"); } TEST_F(FormatTestObjC, ObjCLiterals) { Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -703,9 +703,10 @@ Tok->Type = TT_CtorInitializerColon; else Tok->Type = TT_InheritanceColon; - } else if (Tok->Previous->is(tok::identifier) && Tok->Next && + } else if (Tok->Previous->Tok.getIdentifierInfo() && Tok->Next && (Tok->Next->isOneOf(tok::r_paren, tok::comma) || - Tok->Next->startsSequence(tok::identifier, tok::colon))) { + (Tok->Next->Tok.getIdentifierInfo() && 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 +1347,7 @@ TT_LeadingJavaAnnotation)) { Current.Type = Current.Previous->Type; } - } else if (Current.isOneOf(tok::identifier, tok::kw_new) && + } else if (Current.Tok.getIdentifierInfo() && // FIXME(bug 36976): ObjC return types shouldn't use TT_CastRParen. Current.Previous && Current.Previous->is(TT_CastRParen) && Current.Previous->MatchingParen && @@ -2650,7 +2651,7 @@ 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) && Right.Tok.getIdentifierInfo()) // 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 +3129,7 @@ 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);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits