Author: Volodymyr Sapsai Date: 2023-06-09T17:09:28-07:00 New Revision: 2e16df352c7acb910313c80ac90b650ad9c14a3d
URL: https://github.com/llvm/llvm-project/commit/2e16df352c7acb910313c80ac90b650ad9c14a3d DIFF: https://github.com/llvm/llvm-project/commit/2e16df352c7acb910313c80ac90b650ad9c14a3d.diff LOG: [ASTStructuralEquivalence] Fix crash when ObjCCategoryDecl doesn't have corresponding ObjCInterfaceDecl. When this happens, it is invalid code and there is diagnostic ``` error: cannot find interface declaration for '...' ``` But clang shouldn't crash even if code is invalid. Though subsequent diagnostic can be imperfect because without ObjCInterfaceDecl we don't have a type for error messages. rdar://108818430 Differential Revision: https://reviews.llvm.org/D151523 Added: Modified: clang/lib/AST/ASTStructuralEquivalence.cpp clang/unittests/AST/StructuralEquivalenceTest.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index a9470782c634e..f867b6bf84beb 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -2057,8 +2057,13 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, if (!IsStructurallyEquivalent(D1->getIdentifier(), D2->getIdentifier())) return false; - if (!IsStructurallyEquivalent(D1->getClassInterface()->getIdentifier(), - D2->getClassInterface()->getIdentifier())) + const ObjCInterfaceDecl *Intf1 = D1->getClassInterface(), + *Intf2 = D2->getClassInterface(); + if ((!Intf1 || !Intf2) && (Intf1 != Intf2)) + return false; + + if (Intf1 && + !IsStructurallyEquivalent(Intf1->getIdentifier(), Intf2->getIdentifier())) return false; // Compare protocols. @@ -2077,7 +2082,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; // Compare ivars. - QualType D2Type = Context.ToCtx.getObjCInterfaceType(D2->getClassInterface()); + QualType D2Type = + Intf2 ? Context.ToCtx.getObjCInterfaceType(Intf2) : QualType(); ObjCCategoryDecl::ivar_iterator Ivar2 = D2->ivar_begin(), Ivar2End = D2->ivar_end(); for (ObjCCategoryDecl::ivar_iterator Ivar1 = D1->ivar_begin(), diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp index 8efb9a905c2f1..319eefe1e6ba3 100644 --- a/clang/unittests/AST/StructuralEquivalenceTest.cpp +++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp @@ -1143,6 +1143,18 @@ TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithDifferentNames) { EXPECT_FALSE(testStructuralMatch(t)); } +TEST_F(StructuralEquivalenceObjCCategoryTest, CategoriesWithoutInterfaces) { + auto t = makeDecls<ObjCCategoryDecl>(" @interface A(X) @end", + "@interface A @end @interface A(X) @end", + Lang_OBJC, objcCategoryDecl()); + EXPECT_FALSE(testStructuralMatch(t)); + + auto t2 = makeDecls<ObjCCategoryDecl>("@interface A(X) @end", + "@interface A(X) @end", + Lang_OBJC, objcCategoryDecl()); + EXPECT_TRUE(testStructuralMatch(t2)); +} + TEST_F(StructuralEquivalenceObjCCategoryTest, CategoryAndExtension) { auto t = makeDecls<ObjCCategoryDecl>("@interface A @end @interface A(X) @end", "@interface A @end @interface A() @end", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits