summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2013-12-03 21:11:43 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2013-12-03 21:11:43 +0000
commitfcded9b93a96e9a88405325b30caa4cd11120aee (patch)
treec06abf22140d0af2b7fe042a8be53f012ae1bb3e
parent22bfa2c28bdbca09949ba4cf8670c310d3e42c71 (diff)
downloadbcm5719-llvm-fcded9b93a96e9a88405325b30caa4cd11120aee.tar.gz
bcm5719-llvm-fcded9b93a96e9a88405325b30caa4cd11120aee.zip
[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. llvm-svn: 196317
-rw-r--r--clang/include/clang/AST/DeclObjC.h7
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--clang/lib/AST/DeclObjC.cpp7
-rw-r--r--clang/lib/Sema/SemaDecl.cpp4
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp31
-rw-r--r--clang/test/SemaObjC/attr-designated-init.m25
6 files changed, 61 insertions, 19 deletions
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index 774de1a4fed..12e2a0b727a 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/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/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 314d0375e67..52fc7981031 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2437,6 +2437,12 @@ def warn_objc_designated_init_missing_super_call : Warning<
InGroup<ObjCDesignatedInit>;
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<ObjCDesignatedInit>;
+def warn_objc_designated_init_non_designated_init_call : Warning<
+ "designated initializer invoked a non-designated initializer">,
+ InGroup<ObjCDesignatedInit>;
def err_ns_bridged_not_interface : Error<
"parameter of 'ns_bridged' attribute does not name an Objective-C class">;
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index cb58ad482e1..b392e2f6619 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -655,12 +655,15 @@ bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
hasAttr<ObjCDesignatedInitializerAttr>();
}
-bool ObjCMethodDecl::isDesignatedInitializerForTheInterface() const {
+bool ObjCMethodDecl::isDesignatedInitializerForTheInterface(
+ const ObjCMethodDecl **InitMethod) const {
+ if (getMethodFamily() != OMF_init)
+ return false;
const DeclContext *DC = getDeclContext();
if (isa<ObjCProtocolDecl>(DC))
return false;
if (const ObjCInterfaceDecl *ID = getClassInterface())
- return ID->isDesignatedInitializer(getSelector());
+ return ID->isDesignatedInitializer(getSelector(), InitMethod);
return false;
}
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index c14cc4b8619..f243c0e8d18 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/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/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 20f4b4f7248..c4523064579 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/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/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m
index 3190d8a97fe..59d1357d9e2 100644
--- a/clang/test/SemaObjC/attr-designated-init.m
+++ b/clang/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
OpenPOWER on IntegriCloud