[clang] ea201e8 - [AST][ObjC] Fix crash when printing invalid objc categories

David Goldman via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 10 12:36:47 PDT 2020


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 at end"));
 }
+
+TEST(DeclPrinter, TestObjCCategoryInvalidInterface) {
+  ASSERT_TRUE(PrintedDeclObjCMatches(
+      "@interface I (Extension) @end",
+      namedDecl(hasName("Extension")).bind("id"),
+      "@interface <<error-type>>(Extension)\n at end", /*AllowError=*/true));
+}
+
+TEST(DeclPrinter, TestObjCCategoryImplInvalidInterface) {
+  ASSERT_TRUE(PrintedDeclObjCMatches(
+      "@implementation I (Extension) @end",
+      namedDecl(hasName("Extension")).bind("id"),
+      "@implementation <<error-type>>(Extension)\n at end", /*AllowError=*/true));
+}


        


More information about the cfe-commits mailing list