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">;
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">;
// 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",
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">;
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);
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, ")");
id objc_getClass(const char *s);
@interface Object
+- (id) initWithInt: (int) i;
@end
@protocol Func
- (int) instance_func5;
- (int) instance_func6;
- (int) instance_func7;
+- (id) initWithInt: (int) i;
@end
@implementation Derived
{
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