aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-11-12 00:06:05 +0000
committerJohn McCall <rjmccall@apple.com>2009-11-12 00:06:05 +0000
commitc8d8ac5f454311d0154d2d080196cc150edbb2d6 (patch)
treef9c26e4ab4d26f06844f3ab6a81d77b65d2c6052
parenteaf75f4e0f65444bb122ade7725a4a32badcbf77 (diff)
Add <foo> = [<bar> nextObject] to the -Widiomatic-parentheses category,
and give that category an explicit test. Generalize the internal diagnostic name. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86905 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td5
-rw-r--r--lib/Sema/SemaExpr.cpp25
-rw-r--r--test/SemaObjC/idiomatic-parentheses.m35
3 files changed, 55 insertions, 10 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 3abacd9b3a..26693aa78c 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1815,8 +1815,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">,
+// Completely identical except off by default.
+def warn_condition_is_idiomatic_assignment : Warning<"using the result "
+ "of an assignment as a condition without parentheses">,
InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore;
def warn_value_always_zero : Warning<
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5050dbcce8..9d6af7a1b8 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -6517,14 +6517,23 @@ void Sema::DiagnoseAssignmentAsCondition(Expr *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;
+ // Greylist some idioms by putting them into a warning subcategory.
+ if (ObjCMessageExpr *ME
+ = dyn_cast<ObjCMessageExpr>(Op->getRHS()->IgnoreParenCasts())) {
+ Selector Sel = ME->getSelector();
+
+ llvm::errs() << "selector is '" << Sel.getIdentifierInfoForSlot(0)->getName() << "'\n";
+
+ // self = [<foo> init...]
+ if (isSelfExpr(Op->getLHS())
+ && Sel.getIdentifierInfoForSlot(0)->getName().startswith("init"))
+ diagnostic = diag::warn_condition_is_idiomatic_assignment;
+
+ // <foo> = [<bar> nextObject]
+ else if (Sel.isUnarySelector() &&
+ Sel.getIdentifierInfoForSlot(0)->getName() == "nextObject")
+ diagnostic = diag::warn_condition_is_idiomatic_assignment;
+ }
Loc = Op->getOperatorLoc();
} else if (isa<CXXOperatorCallExpr>(E)) {
diff --git a/test/SemaObjC/idiomatic-parentheses.m b/test/SemaObjC/idiomatic-parentheses.m
new file mode 100644
index 0000000000..b4c52fa0d1
--- /dev/null
+++ b/test/SemaObjC/idiomatic-parentheses.m
@@ -0,0 +1,35 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Don't warn about some common ObjC idioms unless we have -Wparentheses on.
+// <rdar://problem/7382435>
+
+@interface Object
+- (id) init;
+- (id) initWithInt: (int) i;
+- (void) iterate: (id) coll;
+- (id) nextObject;
+@end
+
+@implementation Object
+- (id) init {
+ if (self = [self init]) {
+ }
+ return self;
+}
+
+- (id) initWithInt: (int) i {
+ if (self = [self initWithInt: i]) {
+ }
+ return self;
+}
+
+- (void) iterate: (id) coll {
+ id cur;
+ while (cur = [coll nextObject]) {
+ }
+}
+
+- (id) nextObject {
+ return self;
+}
+@end