Author: David Goldman Date: 2020-07-10T15:35:14-04:00 New Revision: ea201e83e292f39c3ee7fe8810a348ee98000398
URL: https://github.com/llvm/llvm-project/commit/ea201e83e292f39c3ee7fe8810a348ee98000398 DIFF: https://github.com/llvm/llvm-project/commit/ea201e83e292f39c3ee7fe8810a348ee98000398.diff LOG: [AST][ObjC] Fix crash when printing invalid objc categories Summary: If no valid interface definition was found previously we would crash. With this change instead we just print `<<error-type>>` in place of the NULL interface. In the future this could be improved by saving the invalid interface's name and using that. Reviewers: sammccall, gribozavr Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D83513 Added: Modified: clang/lib/AST/DeclPrinter.cpp clang/unittests/AST/DeclPrinterTest.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp index 4df6512e6c76..2e48b2b46c4d 100644 --- a/clang/lib/AST/DeclPrinter.cpp +++ b/clang/lib/AST/DeclPrinter.cpp @@ -1374,7 +1374,12 @@ void DeclPrinter::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) { } void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { - Out << "@implementation " << *PID->getClassInterface() << '(' << *PID <<")\n"; + Out << "@implementation "; + if (const auto *CID = PID->getClassInterface()) + Out << *CID; + else + Out << "<<error-type>>"; + Out << '(' << *PID << ")\n"; VisitDeclContext(PID, false); Out << "@end"; @@ -1382,7 +1387,11 @@ void DeclPrinter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *PID) { } void DeclPrinter::VisitObjCCategoryDecl(ObjCCategoryDecl *PID) { - Out << "@interface " << *PID->getClassInterface(); + Out << "@interface "; + if (const auto *CID = PID->getClassInterface()) + Out << *CID; + else + Out << "<<error-type>>"; if (auto TypeParams = PID->getTypeParamList()) { PrintObjCTypeParams(TypeParams); } diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp index 018e99237ae9..939c8b52c12c 100644 --- a/clang/unittests/AST/DeclPrinterTest.cpp +++ b/clang/unittests/AST/DeclPrinterTest.cpp @@ -76,14 +76,16 @@ ::testing::AssertionResult PrintedDeclMatches(StringRef Code, const std::vector<std::string> &Args, const DeclarationMatcher &NodeMatch, StringRef ExpectedPrinted, StringRef FileName, - PrintingPolicyModifier PolicyModifier = nullptr) { + PrintingPolicyModifier PolicyModifier = nullptr, + bool AllowError = false) { PrintMatch Printer(PolicyModifier); MatchFinder Finder; Finder.addMatcher(NodeMatch, &Printer); std::unique_ptr<FrontendActionFactory> Factory( newFrontendActionFactory(&Finder)); - if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName)) + if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, FileName) && + !AllowError) return testing::AssertionFailure() << "Parsing error in \"" << Code.str() << "\""; @@ -170,16 +172,12 @@ PrintedDeclCXX1ZMatches(StringRef Code, const DeclarationMatcher &NodeMatch, "input.cc"); } -::testing::AssertionResult PrintedDeclObjCMatches( - StringRef Code, - const DeclarationMatcher &NodeMatch, - StringRef ExpectedPrinted) { +::testing::AssertionResult +PrintedDeclObjCMatches(StringRef Code, const DeclarationMatcher &NodeMatch, + StringRef ExpectedPrinted, bool AllowError = false) { std::vector<std::string> Args(1, ""); - return PrintedDeclMatches(Code, - Args, - NodeMatch, - ExpectedPrinted, - "input.m"); + return PrintedDeclMatches(Code, Args, NodeMatch, ExpectedPrinted, "input.m", + /*PolicyModifier=*/nullptr, AllowError); } } // unnamed namespace @@ -1321,3 +1319,17 @@ TEST(DeclPrinter, TestObjCProtocol2) { namedDecl(hasName("P1")).bind("id"), "@protocol P1<P2>\n@end")); } + +TEST(DeclPrinter, TestObjCCategoryInvalidInterface) { + ASSERT_TRUE(PrintedDeclObjCMatches( + "@interface I (Extension) @end", + namedDecl(hasName("Extension")).bind("id"), + "@interface <<error-type>>(Extension)\n@end", /*AllowError=*/true)); +} + +TEST(DeclPrinter, TestObjCCategoryImplInvalidInterface) { + ASSERT_TRUE(PrintedDeclObjCMatches( + "@implementation I (Extension) @end", + namedDecl(hasName("Extension")).bind("id"), + "@implementation <<error-type>>(Extension)\n@end", /*AllowError=*/true)); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits