From: Argyrios Kyrtzidis Date: Tue, 3 Dec 2013 21:11:43 +0000 (+0000) Subject: [objc] Emit warnings when the implementation of a designated initializer calls on X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2d9de48ac1dfe1d03cabb015846e24cebc408d4d;p=clang [objc] Emit warnings when the implementation of a designated initializer calls on super an initializer that is not a designated one or any initializer on self. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196317 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 774de1a4fe..12e2a0b727 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -457,7 +457,12 @@ public: /// Returns true if the method selector resolves to a designated initializer /// in the class's interface. - bool isDesignatedInitializerForTheInterface() const; + /// + /// \param InitMethod if non-null and the function returns true, it receives + /// the method declaration that was marked with the designated initializer + /// attribute. + bool isDesignatedInitializerForTheInterface( + const ObjCMethodDecl **InitMethod = 0) const; /// \brief Determine whether this method has a body. virtual bool hasBody() const { return Body.isValid(); } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 314d0375e6..52fc798103 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2437,6 +2437,12 @@ def warn_objc_designated_init_missing_super_call : Warning< InGroup; def note_objc_designated_init_marked_here : Note< "method marked as designated initializer of the class here">; +def warn_objc_designated_init_non_super_designated_init_call : Warning< + "designated initializer should only invoke a designated initializer on 'super'">, + InGroup; +def warn_objc_designated_init_non_designated_init_call : Warning< + "designated initializer invoked a non-designated initializer">, + InGroup; def err_ns_bridged_not_interface : Error< "parameter of 'ns_bridged' attribute does not name an Objective-C class">; diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index cb58ad482e..b392e2f661 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -655,12 +655,15 @@ bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const { hasAttr(); } -bool ObjCMethodDecl::isDesignatedInitializerForTheInterface() const { +bool ObjCMethodDecl::isDesignatedInitializerForTheInterface( + const ObjCMethodDecl **InitMethod) const { + if (getMethodFamily() != OMF_init) + return false; const DeclContext *DC = getDeclContext(); if (isa(DC)) return false; if (const ObjCInterfaceDecl *ID = getClassInterface()) - return ID->isDesignatedInitializer(getSelector()); + return ID->isDesignatedInitializer(getSelector(), InitMethod); return false; } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index c14cc4b861..f243c0e8d1 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9816,8 +9816,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) { const ObjCMethodDecl *InitMethod = 0; - bool isDesignated = MD->getClassInterface() - ->isDesignatedInitializer(MD->getSelector(), &InitMethod); + bool isDesignated = + MD->isDesignatedInitializerForTheInterface(&InitMethod); assert(isDesignated && InitMethod); (void)isDesignated; Diag(MD->getLocation(), diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 20f4b4f724..c452306457 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -2447,14 +2447,33 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } - if (SuperLoc.isValid() && getCurFunction()->ObjCIsDesignatedInit) { - if (const ObjCObjectPointerType * - OCIType = ReceiverType->getAsObjCInterfacePointerType()) { - if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) { - if (ID->isDesignatedInitializer(Sel)) - getCurFunction()->ObjCWarnForNoDesignatedInitChain = false; + if (Method && Method->getMethodFamily() == OMF_init && + getCurFunction()->ObjCIsDesignatedInit && + (SuperLoc.isValid() || isSelfExpr(Receiver))) { + bool isDesignatedInitChain = false; + if (SuperLoc.isValid()) { + if (const ObjCObjectPointerType * + OCIType = ReceiverType->getAsObjCInterfacePointerType()) { + if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) { + if (ID->isDesignatedInitializer(Sel)) { + isDesignatedInitChain = true; + getCurFunction()->ObjCWarnForNoDesignatedInitChain = false; + } + } } } + if (!isDesignatedInitChain) { + const ObjCMethodDecl *InitMethod = 0; + bool isDesignated = + getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod); + assert(isDesignated && InitMethod); + (void)isDesignated; + Diag(SelLoc, SuperLoc.isValid() ? + diag::warn_objc_designated_init_non_designated_init_call : + diag::warn_objc_designated_init_non_super_designated_init_call); + Diag(InitMethod->getLocation(), + diag::note_objc_designated_init_marked_here); + } } // Check the message arguments. diff --git a/test/SemaObjC/attr-designated-init.m b/test/SemaObjC/attr-designated-init.m index 3190d8a97f..59d1357d9e 100644 --- a/test/SemaObjC/attr-designated-init.m +++ b/test/SemaObjC/attr-designated-init.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) @@ -35,7 +35,7 @@ __attribute__((objc_root_class)) @interface B1 -(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} -(id)initB2; --(id)initB3 NS_DESIGNATED_INITIALIZER; +-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} @end @implementation B1 @@ -47,8 +47,8 @@ __attribute__((objc_root_class)) @interface S1 : B1 -(id)initS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} -(id)initS2 NS_DESIGNATED_INITIALIZER; --(id)initS3 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} --(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} +-(id)initS3 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} +-(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} -(id)initB1; @end @@ -60,10 +60,10 @@ __attribute__((objc_root_class)) return [super initB1]; } -(id)initS3 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} - return [super initB2]; + return [super initB2]; // expected-warning {{designated initializer invoked a non-designated initializer}} } -(id)initS4 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} - return [self initB1]; + return [self initB1]; // expected-warning {{designated initializer should only invoke a designated initializer on 'super'}} } -(id)initB1 { return [self initS1]; @@ -92,12 +92,12 @@ __attribute__((objc_root_class)) @end @interface SS3 : S3 --(id)initSS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} +-(id)initSS1 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} @end @implementation SS3 -(id)initSS1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} - return [super initB1]; + return [super initB1]; // expected-warning {{designated initializer invoked a non-designated initializer}} } @end @@ -116,6 +116,7 @@ __attribute__((objc_root_class)) @end @interface S5 : B1 +-(void)meth; @end @implementation S5 @@ -123,6 +124,14 @@ __attribute__((objc_root_class)) return 0; } -(id)initB3 { + [self initB1]; // expected-warning {{designated initializer should only invoke a designated initializer on 'super'}} + S5 *s; + [s initB1]; + [self meth]; + void (^blk)(void) = ^{ + [self initB1]; + }; return [super initB3]; } +-(void)meth {} @end