diff options
| author | Richard Trieu <rtrieu@google.com> | 2013-04-17 02:12:45 +0000 |
|---|---|---|
| committer | Richard Trieu <rtrieu@google.com> | 2013-04-17 02:12:45 +0000 |
| commit | fe042e6aab263e0d9ff1556b8a27bc12d069ef58 (patch) | |
| tree | 76eb35b54a598ed8691abc52410d06bc0a5c904f | |
| parent | 37ae72b508d7f8974c143f017c01f6c27dc6805c (diff) | |
| download | bcm5719-llvm-fe042e6aab263e0d9ff1556b8a27bc12d069ef58.tar.gz bcm5719-llvm-fe042e6aab263e0d9ff1556b8a27bc12d069ef58.zip | |
Add warning group -Woverloaded-shift-op-parentheses to -Wparentheses. This
will fire on code such as:
cout << x == 0;
which the compiler will intrepret as
(cout << x) == 0;
This warning comes with two fixits attached to notes, one for parentheses to
silence the warning, and another to evaluate the comparison first.
llvm-svn: 179662
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticGroups.td | 2 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 7 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 32 | ||||
| -rw-r--r-- | clang/test/Sema/parentheses.cpp | 6 |
4 files changed, 47 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index a12a4f974ef..a7ef2185df2 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -122,6 +122,7 @@ def GlobalConstructors : DiagGroup<"global-constructors">; def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">; def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">; def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">; +def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">; def DanglingElse: DiagGroup<"dangling-else">; def DanglingField : DiagGroup<"dangling-field">; def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; @@ -352,6 +353,7 @@ def Parentheses : DiagGroup<"parentheses", [LogicalOpParentheses, BitwiseOpParentheses, ShiftOpParentheses, + OverloadedShiftOpParentheses, ParenthesesOnEquality, DanglingElse]>; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index fd9ea51df5b..1330ad68b6d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4041,6 +4041,13 @@ def warn_bitwise_and_in_bitwise_or : Warning< def warn_logical_and_in_logical_or : Warning< "'&&' within '||'">, InGroup<LogicalOpParentheses>; +def warn_overloaded_shift_in_comparison :Warning< + "overloaded operator %select{>>|<<}0 has lower precedence than " + "comparison operator">, + InGroup<OverloadedShiftOpParentheses>; +def note_evaluate_comparison_first :Note< + "place parentheses around comparison expression to evaluate it first">; + def warn_addition_in_bitshift : Warning< "operator '%0' has lower precedence than '%1'; " "'%1' will be evaluated first">, InGroup<ShiftOpParentheses>; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index cdfdc09e06e..ce60f9171fd 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8877,6 +8877,33 @@ static void DiagnoseAdditionInShift(Sema &S, SourceLocation OpLoc, } } +static void DiagnoseShiftCompare(Sema &S, SourceLocation OpLoc, + Expr *LHSExpr, Expr *RHSExpr) { + CXXOperatorCallExpr *OCE = dyn_cast<CXXOperatorCallExpr>(LHSExpr); + if (!OCE) + return; + + FunctionDecl *FD = OCE->getDirectCallee(); + if (!FD || !FD->isOverloadedOperator()) + return; + + OverloadedOperatorKind Kind = FD->getOverloadedOperator(); + if (Kind != OO_LessLess && Kind != OO_GreaterGreater) + return; + + S.Diag(OpLoc, diag::warn_overloaded_shift_in_comparison) + << LHSExpr->getSourceRange() << RHSExpr->getSourceRange() + << (Kind == OO_LessLess); + SuggestParentheses(S, OpLoc, + S.PDiag(diag::note_evaluate_comparison_first), + SourceRange(OCE->getArg(1)->getLocStart(), + RHSExpr->getLocEnd())); + SuggestParentheses(S, OCE->getOperatorLoc(), + S.PDiag(diag::note_precedence_silence) + << (Kind == OO_LessLess ? "<<" : ">>"), + OCE->getSourceRange()); +} + /// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky /// precedence. static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, @@ -8905,6 +8932,11 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc, DiagnoseAdditionInShift(Self, OpLoc, LHSExpr, Shift); DiagnoseAdditionInShift(Self, OpLoc, RHSExpr, Shift); } + + // Warn on overloaded shift operators and comparisons, such as: + // cout << 5 == 4; + if (BinaryOperator::isComparisonOp(Opc)) + DiagnoseShiftCompare(Self, OpLoc, LHSExpr, RHSExpr); } // Binary Operators. 'Tok' is the token for the operator. diff --git a/clang/test/Sema/parentheses.cpp b/clang/test/Sema/parentheses.cpp index 145414a53ac..58edc0ba294 100644 --- a/clang/test/Sema/parentheses.cpp +++ b/clang/test/Sema/parentheses.cpp @@ -29,6 +29,12 @@ void f(Stream& s, bool b) { (void)(s << b ? "foo" : "bar"); // expected-warning {{operator '?:' has lower precedence than '<<'}} \ // expected-note {{place parentheses around the '?:' expression to evaluate it first}} \ // expected-note {{place parentheses around the '<<' expression to silence this warning}} + (void)(s << 5 == 1); // expected-warning {{overloaded operator << has lower precedence than comparison operator}} \ + // expected-note {{place parentheses around the '<<' expression to silence this warning}} \ + // expected-note {{place parentheses around comparison expression to evaluate it first}} + (void)(s >> 5 == 1); // expected-warning {{overloaded operator >> has lower precedence than comparison operator}} \ + // expected-note {{place parentheses around the '>>' expression to silence this warning}} \ + // expected-note {{place parentheses around comparison expression to evaluate it first}} } struct S { |

