forked from OSchip/llvm-project
[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
This commit is contained in:
parent
9bf6354301
commit
ea201e83e2
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -76,14 +76,16 @@ public:
|
|||
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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue