From c91ac9ed498eea96e135c3433e690edf5f951b74 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 20 Jan 2015 20:41:36 +0000 Subject: [PATCH] Fix crashes on missing @interface for category In a few places we didn't check that Category->getClassInterface() was not null before using it. llvm-svn: 226605 --- clang/lib/Sema/SemaDecl.cpp | 5 ++++- clang/lib/Sema/SemaDeclAttr.cpp | 10 ++++++++-- clang/lib/Sema/SemaExpr.cpp | 4 ++-- clang/test/SemaObjC/attr-deprecated.m | 11 +++++++++++ clang/test/SemaObjC/attr-designated-init.m | 8 ++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9eb5993..8fbe82f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13979,7 +13979,10 @@ Decl *Sema::getObjCDeclContext() const { } AvailabilityResult Sema::getCurContextAvailability() const { - const Decl *D = cast(getCurObjCLexicalContext()); + const Decl *D = cast_or_null(getCurObjCLexicalContext()); + if (!D) + return AR_Available; + // If we are within an Objective-C method, we should consult // both the availability of the method as well as the // enclosing class. If the class is (say) deprecated, diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8837bbd..c17451ea 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3783,6 +3783,10 @@ static void handleObjCDesignatedInitializer(Sema &S, Decl *D, IFace = CatDecl->getClassInterface(); else IFace = cast(D->getDeclContext()); + + if (!IFace) + return; + IFace->setHasDesignatedInitializers(); D->addAttr(::new (S.Context) ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context, @@ -5059,7 +5063,8 @@ static bool isDeclDeprecated(Decl *D) { return true; // A category implicitly has the availability of the interface. if (const ObjCCategoryDecl *CatD = dyn_cast(D)) - return CatD->getClassInterface()->isDeprecated(); + if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface()) + return Interface->isDeprecated(); } while ((D = cast_or_null(D->getDeclContext()))); return false; } @@ -5070,7 +5075,8 @@ static bool isDeclUnavailable(Decl *D) { return true; // A category implicitly has the availability of the interface. if (const ObjCCategoryDecl *CatD = dyn_cast(D)) - return CatD->getClassInterface()->isUnavailable(); + if (const ObjCInterfaceDecl *Interface = CatD->getClassInterface()) + return Interface->isUnavailable(); } while ((D = cast_or_null(D->getDeclContext()))); return false; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index fba7a2d..74779bc 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -76,8 +76,8 @@ bool Sema::CanUseDecl(NamedDecl *D) { static void DiagnoseUnusedOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc) { // Warn if this is used but marked unused. if (D->hasAttr()) { - const Decl *DC = cast(S.getCurObjCLexicalContext()); - if (!DC->hasAttr()) + const Decl *DC = cast_or_null(S.getCurObjCLexicalContext()); + if (DC && !DC->hasAttr()) S.Diag(Loc, diag::warn_used_but_marked_unused) << D->getDeclName(); } } diff --git a/clang/test/SemaObjC/attr-deprecated.m b/clang/test/SemaObjC/attr-deprecated.m index 13ba68d..14d33d3 100644 --- a/clang/test/SemaObjC/attr-deprecated.m +++ b/clang/test/SemaObjC/attr-deprecated.m @@ -284,3 +284,14 @@ void f(id a) { void g(id a) { [a anotherPartiallyUnavailableMethod]; // no warning, `a` could be an InterfaceWithImplementation. } + +typedef struct {} S1 __attribute__((unavailable)); // expected-note2{{marked unavailable here}} +typedef struct {} S2 __attribute__((deprecated)); // expected-note2{{marked deprecated here}} +@interface ExtensionForMissingInterface() // expected-error{{cannot find interface declaration}} +- (void)method1:(S1) x; // expected-error{{is unavailable}} +- (void)method2:(S2) x; // expected-warning{{is deprecated}} +@end +@interface CategoryForMissingInterface(Cat) // expected-error{{cannot find interface declaration}} +- (void)method1:(S1) x; // expected-error{{is unavailable}} +- (void)method2:(S2) x; // expected-warning{{is deprecated}} +@end diff --git a/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m index 5350657..a8673e1 100644 --- a/clang/test/SemaObjC/attr-designated-init.m +++ b/clang/test/SemaObjC/attr-designated-init.m @@ -410,3 +410,11 @@ __attribute__((objc_root_class)) return [super init]; } @end + +@interface ExtensionForMissingInterface() // expected-error{{cannot find interface declaration}} +- (instancetype)init NS_DESIGNATED_INITIALIZER; +@end + +@interface CategoryForMissingInterface(Cat) // expected-error{{cannot find interface declaration}} +- (instancetype)init NS_DESIGNATED_INITIALIZER; // expected-error{{only applies to init methods of interface or class extension declarations}} +@end -- 2.7.4