aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaExpr.cpp25
1 files changed, 19 insertions, 6 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7a73ad633f..4728b0d199 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -7352,11 +7352,21 @@ static bool EvaluatesAsTrue(Sema &S, Expr *E) {
return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && Res;
}
+/// \brief Returns true if the given expression can be evaluated as a constant
+/// 'false'.
+static bool EvaluatesAsFalse(Sema &S, Expr *E) {
+ bool Res;
+ return E->EvaluateAsBooleanCondition(Res, S.getASTContext()) && !Res;
+}
+
/// \brief Look for '&&' in the left hand of a '||' expr.
static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
- Expr *E) {
- if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {
+ Expr *OrLHS, Expr *OrRHS) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrLHS)) {
if (Bop->getOpcode() == BO_LAnd) {
+ // If it's "a && b || 0" don't warn since the precedence doesn't matter.
+ if (EvaluatesAsFalse(S, OrRHS))
+ return;
// If it's "1 && a || b" don't warn since the precedence doesn't matter.
if (!EvaluatesAsTrue(S, Bop->getLHS()))
return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop);
@@ -7373,9 +7383,12 @@ static void DiagnoseLogicalAndInLogicalOrLHS(Sema &S, SourceLocation OpLoc,
/// \brief Look for '&&' in the right hand of a '||' expr.
static void DiagnoseLogicalAndInLogicalOrRHS(Sema &S, SourceLocation OpLoc,
- Expr *E) {
- if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E)) {
+ Expr *OrLHS, Expr *OrRHS) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(OrRHS)) {
if (Bop->getOpcode() == BO_LAnd) {
+ // If it's "0 || a && b" don't warn since the precedence doesn't matter.
+ if (EvaluatesAsFalse(S, OrLHS))
+ return;
// If it's "a || b && 1" don't warn since the precedence doesn't matter.
if (!EvaluatesAsTrue(S, Bop->getRHS()))
return EmitDiagnosticForLogicalAndInLogicalOr(S, OpLoc, Bop);
@@ -7394,8 +7407,8 @@ static void DiagnoseBinOpPrecedence(Sema &Self, BinaryOperatorKind Opc,
// Warn about arg1 || arg2 && arg3, as GCC 4.3+ does.
// We don't warn for 'assert(a || b && "bad")' since this is safe.
if (Opc == BO_LOr && !OpLoc.isMacroID()/* Don't warn in macros. */) {
- DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, lhs);
- DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, rhs);
+ DiagnoseLogicalAndInLogicalOrLHS(Self, OpLoc, lhs, rhs);
+ DiagnoseLogicalAndInLogicalOrRHS(Self, OpLoc, lhs, rhs);
}
}