r196318 - [objc] Emit warning when the implementation of a secondary initializer calls on
Argyrios Kyrtzidis
akyrtzi at gmail.com
Tue Dec 3 13:11:49 PST 2013
Author: akirtzidis
Date: Tue Dec 3 15:11:49 2013
New Revision: 196318
URL: http://llvm.org/viewvc/llvm-project?rev=196318&view=rev
Log:
[objc] Emit warning when the implementation of a secondary initializer calls on
super another initializer and when the implementation does not delegate to
another initializer via a call on 'self'.
A secondary initializer is an initializer method not marked as a designated
initializer within a class that has at least one initializer marked as a
designated initializer.
Modified:
cfe/trunk/include/clang/AST/DeclObjC.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/ScopeInfo.h
cfe/trunk/lib/AST/DeclObjC.cpp
cfe/trunk/lib/Sema/ScopeInfo.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
cfe/trunk/lib/Sema/SemaExprObjC.cpp
cfe/trunk/test/SemaObjC/attr-designated-init.m
Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Dec 3 15:11:49 2013
@@ -750,6 +750,10 @@ public:
/// marked with the 'objc_designated_initializer' attribute.
void setHasDesignatedInitializers();
+ /// Returns true if this interface decl contains at least one initializer
+ /// marked with the 'objc_designated_initializer' attribute.
+ bool hasDesignatedInitializers() const;
+
const ObjCProtocolList &getReferencedProtocols() const {
assert(hasDefinition() && "Caller did not check for forward reference!");
if (data().ExternallyCompleted)
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Dec 3 15:11:49 2013
@@ -2443,6 +2443,12 @@ def warn_objc_designated_init_non_super_
def warn_objc_designated_init_non_designated_init_call : Warning<
"designated initializer invoked a non-designated initializer">,
InGroup<ObjCDesignatedInit>;
+def warn_objc_secondary_init_super_init_call : Warning<
+ "secondary initializer should not invoke an initializer on 'super'">,
+ InGroup<ObjCDesignatedInit>;
+def warn_objc_secondary_init_missing_init_call : Warning<
+ "secondary initializer missing a 'self' call to another initializer">,
+ InGroup<ObjCDesignatedInit>;
def err_ns_bridged_not_interface : Error<
"parameter of 'ns_bridged' attribute does not name an Objective-C class">;
Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Tue Dec 3 15:11:49 2013
@@ -117,6 +117,14 @@ public:
/// the super class.
bool ObjCWarnForNoDesignatedInitChain;
+ /// True when this is an initializer method not marked as a designated
+ /// initializer within a class that has at least one initializer marked as a
+ /// designated initializer.
+ bool ObjCIsSecondaryInit;
+ /// This starts true for a secondary initializer method and will be set to
+ /// false if there is an invocation of an initializer on 'self'.
+ bool ObjCWarnForNoInitDelegation;
+
/// \brief Used to determine if errors occurred in this function or block.
DiagnosticErrorTrap ErrorTrap;
@@ -327,6 +335,8 @@ public:
ObjCShouldCallSuper(false),
ObjCIsDesignatedInit(false),
ObjCWarnForNoDesignatedInitChain(false),
+ ObjCIsSecondaryInit(false),
+ ObjCWarnForNoInitDelegation(false),
ErrorTrap(Diag) { }
virtual ~FunctionScopeInfo();
Modified: cfe/trunk/lib/AST/DeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclObjC.cpp (original)
+++ cfe/trunk/lib/AST/DeclObjC.cpp Tue Dec 3 15:11:49 2013
@@ -1197,6 +1197,14 @@ void ObjCInterfaceDecl::setHasDesignated
data().HasDesignatedInitializers = true;
}
+bool ObjCInterfaceDecl::hasDesignatedInitializers() const {
+ assert(hasDefinition() && "Forward declarations can't contain methods");
+ if (data().ExternallyCompleted)
+ LoadExternalDefinition();
+
+ return data().HasDesignatedInitializers;
+}
+
ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
if (const ObjCInterfaceDecl *Def = getDefinition()) {
if (data().ExternallyCompleted)
Modified: cfe/trunk/lib/Sema/ScopeInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ScopeInfo.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/ScopeInfo.cpp (original)
+++ cfe/trunk/lib/Sema/ScopeInfo.cpp Tue Dec 3 15:11:49 2013
@@ -30,6 +30,8 @@ void FunctionScopeInfo::Clear() {
ObjCShouldCallSuper = false;
ObjCIsDesignatedInit = false;
ObjCWarnForNoDesignatedInitChain = false;
+ ObjCIsSecondaryInit = false;
+ ObjCWarnForNoInitDelegation = false;
SwitchStack.clear();
Returns.clear();
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Dec 3 15:11:49 2013
@@ -9826,6 +9826,10 @@ Decl *Sema::ActOnFinishFunctionBody(Decl
diag::note_objc_designated_init_marked_here);
getCurFunction()->ObjCWarnForNoDesignatedInitChain = false;
}
+ if (getCurFunction()->ObjCWarnForNoInitDelegation) {
+ Diag(MD->getLocation(), diag::warn_objc_secondary_init_missing_init_call);
+ getCurFunction()->ObjCWarnForNoInitDelegation = false;
+ }
} else {
return 0;
}
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Dec 3 15:11:49 2013
@@ -391,8 +391,16 @@ void Sema::ActOnStartOfObjCMethodDef(Sco
MDecl->getLocation(), 0);
}
- if (MDecl->isDesignatedInitializerForTheInterface())
- getCurFunction()->ObjCIsDesignatedInit = true;
+ if (MDecl->getMethodFamily() == OMF_init) {
+ if (MDecl->isDesignatedInitializerForTheInterface()) {
+ getCurFunction()->ObjCIsDesignatedInit = true;
+ getCurFunction()->ObjCWarnForNoDesignatedInitChain =
+ IC->getSuperClass() != 0;
+ } else if (IC->hasDesignatedInitializers()) {
+ getCurFunction()->ObjCIsSecondaryInit = true;
+ getCurFunction()->ObjCWarnForNoInitDelegation = true;
+ }
+ }
// If this is "dealloc" or "finalize", set some bit here.
// Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
@@ -416,9 +424,6 @@ void Sema::ActOnStartOfObjCMethodDef(Sco
getCurFunction()->ObjCShouldCallSuper =
(SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());
}
-
- if (getCurFunction()->ObjCIsDesignatedInit)
- getCurFunction()->ObjCWarnForNoDesignatedInitChain = true;
}
}
}
Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Dec 3 15:11:49 2013
@@ -2476,6 +2476,16 @@ ExprResult Sema::BuildInstanceMessage(Ex
}
}
+ if (Method && Method->getMethodFamily() == OMF_init &&
+ getCurFunction()->ObjCIsSecondaryInit &&
+ (SuperLoc.isValid() || isSelfExpr(Receiver))) {
+ if (SuperLoc.isValid()) {
+ Diag(SelLoc, diag::warn_objc_secondary_init_super_init_call);
+ } else {
+ getCurFunction()->ObjCWarnForNoInitDelegation = false;
+ }
+ }
+
// Check the message arguments.
unsigned NumArgs = ArgsIn.size();
Expr **Args = ArgsIn.data();
Modified: cfe/trunk/test/SemaObjC/attr-designated-init.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/attr-designated-init.m?rev=196318&r1=196317&r2=196318&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/attr-designated-init.m (original)
+++ cfe/trunk/test/SemaObjC/attr-designated-init.m Tue Dec 3 15:11:49 2013
@@ -27,8 +27,9 @@ __attribute__((objc_root_class))
-(void)meth {}
-(id)init NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to methods of interface declarations}}
+(id)init { return 0; }
--(id)init3 { return 0; }
--(id)init4 NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to methods of interface declarations}}
+-(id)init3 { return 0; } // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
+-(id)init4 NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to methods of interface declarations}} \
+ // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
@end
__attribute__((objc_root_class))
@@ -40,7 +41,7 @@ __attribute__((objc_root_class))
@implementation B1
-(id)initB1 { return 0; }
--(id)initB2 { return 0; }
+-(id)initB2 { return 0; } // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
-(id)initB3 { return 0; }
@end
@@ -134,4 +135,43 @@ __attribute__((objc_root_class))
return [super initB3];
}
-(void)meth {}
+-(id)initS1 {
+ return 0;
+}
+-(id)initS2 {
+ return [super initB1];
+}
+ at end
+
+ at interface S6 : B1
+-(id)initS1 NS_DESIGNATED_INITIALIZER;
+-(id)initS2;
+-(id)initS3;
+-(id)initS4;
+ at end
+
+ at implementation S6
+-(id)initS1 {
+ return [super initB1];
+}
+-(id)initS2 { // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
+ return [super initB1]; // expected-warning {{secondary initializer should not invoke an initializer on 'super'}}
+}
+-(id)initS3 {
+ return [self initB1];
+}
+-(id)initS4 {
+ return [self initS1];
+}
+-(id)initS5 {
+ [super initB1]; // expected-warning {{secondary initializer should not invoke an initializer on 'super'}}
+ void (^blk)(void) = ^{
+ [super initB1];
+ };
+ return [self initS1];
+}
+-(id)initS6 { // expected-warning {{secondary initializer missing a 'self' call to another initializer}}
+ S6 *s;
+ return [s initS1];
+}
@end
More information about the cfe-commits
mailing list