From: John McCall Date: Wed, 11 Nov 2009 02:41:58 +0000 (+0000) Subject: Apparently the following idiom is specifically encouraged: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a52ef08b26420c8b7208c2fe7f3daf8802b22dd7;p=clang Apparently the following idiom is specifically encouraged: 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 --- diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index b8cca04f81..93c655b505 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -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", diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 285ae8f70d..e4ebb5ecc7 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; +def warn_condition_is_self_assignment : Warning<"using the result of an " + "assignment to 'self' as a condition without parentheses">, + InGroup>, DefaultIgnore; def warn_value_always_zero : Warning< "%0 is always %select{zero|false|NULL}1 in this context">; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index c29cfb7c5d..6bdcb0ed90 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(E)) { BinaryOperator *Op = cast(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(Op->getRHS()->IgnoreParenCasts())) + diagnostic = diag::warn_condition_is_self_assignment; + Loc = Op->getOperatorLoc(); } else if (isa(E)) { CXXOperatorCallExpr *Op = cast(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, ")"); diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m index a481cffd28..afd35a8e26 100644 --- a/test/SemaObjC/call-super-2.m +++ b/test/SemaObjC/call-super-2.m @@ -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