]> granicus.if.org Git - clang/commitdiff
Apparently the following idiom is specifically encouraged:
authorJohn McCall <rjmccall@apple.com>
Wed, 11 Nov 2009 02:41:58 +0000 (02:41 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 11 Nov 2009 02:41:58 +0000 (02:41 +0000)
  if (self = [super init])
Recognize it and only warn if -Wparentheses is explicitly enabled.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86790 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticGroups.td
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/SemaObjC/call-super-2.m

index b8cca04f81c2d115646f7ecd689e192030fea4bb..93c655b505008aef90ea0444b0d1141be673a1a9 100644 (file)
@@ -40,6 +40,7 @@ def FormatExtraArgs : DiagGroup<"format-extra-args">;
 def FormatZeroLength : DiagGroup<"format-zero-length">;
 
 def FourByteMultiChar : DiagGroup<"four-char-constants">;
+def : DiagGroup<"idiomatic-parentheses">;
 def : DiagGroup<"import">;
 def : DiagGroup<"init-self">;
 def : DiagGroup<"inline">;
@@ -63,7 +64,6 @@ def : DiagGroup<"old-style-definition">;
 def : DiagGroup<"overflow">;
 def : DiagGroup<"overloaded-virtual">;
 def : DiagGroup<"packed">;
-def Parentheses : DiagGroup<"parentheses">;
 def PointerArith : DiagGroup<"pointer-arith">;
 def : DiagGroup<"pointer-to-int-cast">;
 def : DiagGroup<"redundant-decls">;
@@ -117,6 +117,10 @@ def CharSubscript : DiagGroup<"char-subscripts">;
 
 // Aggregation warning settings.
 
+// -Widiomatic-parentheses contains warnings about 'idiomatic'
+// missing parentheses;  it is off by default.
+def Parentheses : DiagGroup<"parentheses", [DiagGroup<"idiomatic-parentheses">]>;
+
 // -Wconversion has its own warnings, but we split this one out for
 // legacy reasons.
 def Conversion : DiagGroup<"conversion",
index 285ae8f70db25987af512009117b7a6ed11a0d99..e4ebb5ecc7cca79718307afdbdef7979cb22f943 100644 (file)
@@ -1806,6 +1806,9 @@ def err_incomplete_object_call : Error<
 def warn_condition_is_assignment : Warning<"using the result of an "
   "assignment as a condition without parentheses">,
   InGroup<Parentheses>;
+def warn_condition_is_self_assignment : Warning<"using the result of an "
+  "assignment to 'self' as a condition without parentheses">,
+  InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore;
 
 def warn_value_always_zero : Warning<
   "%0 is always %select{zero|false|NULL}1 in this context">;
index c29cfb7c5d22b4411adb8d67f9fed0e705d9a9c7..6bdcb0ed902e7be4f71190dde214ba0588f42095 100644 (file)
@@ -6510,11 +6510,22 @@ bool Sema::CheckCallReturnType(QualType ReturnType, SourceLocation Loc,
 void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
   SourceLocation Loc;
 
+  unsigned diagnostic = diag::warn_condition_is_assignment;
+
   if (isa<BinaryOperator>(E)) {
     BinaryOperator *Op = cast<BinaryOperator>(E);
     if (Op->getOpcode() != BinaryOperator::Assign)
       return;
 
+    // Greylist the following Cocoa ObjC idiom by putting it into a
+    // warning subcategory which defaults off:
+    //   if (self = [super init])
+    // The selector can vary, and it's possible that the base might,
+    // too, so we just recognize any message call.
+    if (isSelfExpr(Op->getLHS()) &&
+        isa<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts()))
+      diagnostic = diag::warn_condition_is_self_assignment;
+
     Loc = Op->getOperatorLoc();
   } else if (isa<CXXOperatorCallExpr>(E)) {
     CXXOperatorCallExpr *Op = cast<CXXOperatorCallExpr>(E);
@@ -6530,7 +6541,7 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *E) {
   SourceLocation Open = E->getSourceRange().getBegin();
   SourceLocation Close = PP.getLocForEndOfToken(E->getSourceRange().getEnd());
   
-  Diag(Loc, diag::warn_condition_is_assignment)
+  Diag(Loc, diagnostic)
     << E->getSourceRange()
     << CodeModificationHint::CreateInsertion(Open, "(")
     << CodeModificationHint::CreateInsertion(Close, ")");
index a481cffd2886defb5693074b9361ff597d122d75..afd35a8e263081daf9c1cb0f940b88744949fa06 100644 (file)
@@ -6,6 +6,7 @@ typedef struct objc_object *id;
 id objc_getClass(const char *s);
 
 @interface Object 
+- (id) initWithInt: (int) i;
 @end
 
 @protocol Func
@@ -28,6 +29,7 @@ id objc_getClass(const char *s);
 - (int) instance_func5;
 - (int) instance_func6;
 - (int) instance_func7;
+- (id) initWithInt: (int) i;
 @end
 
 @implementation Derived
@@ -94,5 +96,13 @@ id objc_getClass(const char *s);
 {
    return [objc_getClass("Derived") class_func1];
 }
+- (id) initWithInt: (int) i
+{
+   // Don't warn about parentheses here.
+   if (self = [super initWithInt: i]) {
+     [self instance_func1];
+   }
+   return self;
+}
 @end