def : DiagGroup<"idiomatic-parentheses">;
def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">;
def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
+def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
def DanglingElse: DiagGroup<"dangling-else">;
def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
def : DiagGroup<"import">;
def note_logical_and_in_logical_or_silence : Note<
"place parentheses around the '&&' expression to silence this warning">;
+def warn_addition_in_bitshift : Warning<
+ "'%0' within '%1'">, InGroup<ShiftOpParentheses>;
+def note_addition_in_bitshift_silence : Note<
+ "place parentheses around the '%0' expression to silence this warning">;
+
def warn_self_assignment : Warning<
"explicitly assigning a variable of type %0 to itself">,
InGroup<SelfAssignment>, DefaultIgnore;
}
}
+static void DiagnoseAdditionInShift(Sema &S, SourceLocation OpLoc,
+ Expr *SubExpr, StringRef shift) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(SubExpr)) {
+ if (Bop->getOpcode() == BO_Add || Bop->getOpcode() == BO_Sub) {
+ StringRef op = Bop->getOpcode() == BO_Add ? "+" : "-";
+ S.Diag(Bop->getOperatorLoc(), diag::warn_addition_in_bitshift)
+ << Bop->getSourceRange() << OpLoc << op << shift;
+ SuggestParentheses(S, Bop->getOperatorLoc(),
+ S.PDiag(diag::note_addition_in_bitshift_silence) << op,
+ Bop->getSourceRange());
+ }
+ }
+}
+
/// DiagnoseBinOpPrecedence - Emit warnings for expressions with tricky
/// precedence.
static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, LHSExpr, RHSExpr);
DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, LHSExpr, RHSExpr);
}
+
+ if ((Opc == BO_Shl && LHSExpr->getType()->isIntegralType(Self.getASTContext()))
+ || Opc == BO_Shr) {
+ StringRef shift = Opc == BO_Shl ? "<<" : ">>";
+ DiagnoseAdditionInShift(Self, OpLoc, LHSExpr, shift);
+ DiagnoseAdditionInShift(Self, OpLoc, RHSExpr, shift);
+ }
}
// Binary Operators. 'Tok' is the token for the operator.
operator int();
Stream &operator<<(int);
Stream &operator<<(const char*);
+ Stream &operator>>(int);
+ Stream &operator>>(const char*);
};
void f(Stream& s, bool b) {
// Don't crash on unusual member call expressions.
(void)((s->*m_ptr)() ? "foo" : "bar");
}
+
+void test(int a, int b, int c) {
+ (void)(a >> b + c); // expected-warning {{'+' within '>>'}} \
+ expected-note {{place parentheses around the '+' expression to silence this warning}}
+ (void)(a - b << c); // expected-warning {{'-' within '<<'}} \
+ expected-note {{place parentheses around the '-' expression to silence this warning}}
+ Stream() << b + c;
+ Stream() >> b + c; // expected-warning {{'+' within '>>'}} \
+ expected-note {{place parentheses around the '+' expression to silence this warning}}
+}