| 1157 | } |
| 1158 | |
| 1159 | void CheckConditionImpl::checkIncorrectLogicOperator() |
| 1160 | { |
| 1161 | const bool printStyle = mSettings.severity.isEnabled(Severity::style); |
| 1162 | const bool printWarning = mSettings.severity.isEnabled(Severity::warning); |
| 1163 | if (!printWarning && !printStyle && !mSettings.isPremiumEnabled("incorrectLogicOperator")) |
| 1164 | return; |
| 1165 | const bool printInconclusive = mSettings.certainty.isEnabled(Certainty::inconclusive); |
| 1166 | |
| 1167 | logChecker("CheckCondition::checkIncorrectLogicOperator"); // style,warning |
| 1168 | |
| 1169 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 1170 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 1171 | |
| 1172 | for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { |
| 1173 | if (!Token::Match(tok, "%oror%|&&") || !tok->astOperand1() || !tok->astOperand2()) |
| 1174 | continue; |
| 1175 | |
| 1176 | |
| 1177 | // 'A && (!A || B)' is equivalent to 'A && B' |
| 1178 | // 'A || (!A && B)' is equivalent to 'A || B' |
| 1179 | // 'A && (A || B)' is equivalent to 'A' |
| 1180 | // 'A || (A && B)' is equivalent to 'A' |
| 1181 | if (printStyle && |
| 1182 | ((tok->str() == "||" && tok->astOperand2()->str() == "&&") || |
| 1183 | (tok->str() == "&&" && tok->astOperand2()->str() == "||"))) { |
| 1184 | const Token* tok2 = tok->astOperand2()->astOperand1(); |
| 1185 | if (isOppositeCond(true, tok->astOperand1(), tok2, mSettings, true, false)) { |
| 1186 | std::string expr1(tok->astOperand1()->expressionString()); |
| 1187 | std::string expr2(tok->astOperand2()->astOperand1()->expressionString()); |
| 1188 | std::string expr3(tok->astOperand2()->astOperand2()->expressionString()); |
| 1189 | // make copy for later because the original string might get overwritten |
| 1190 | const std::string expr1VerboseMsg = expr1; |
| 1191 | const std::string expr2VerboseMsg = expr2; |
| 1192 | const std::string expr3VerboseMsg = expr3; |
| 1193 | |
| 1194 | if (expr1.length() + expr2.length() + expr3.length() > 50U) { |
| 1195 | if (expr1[0] == '!' && expr2[0] != '!') { |
| 1196 | expr1 = "!A"; |
| 1197 | expr2 = "A"; |
| 1198 | } else { |
| 1199 | expr1 = "A"; |
| 1200 | expr2 = "!A"; |
| 1201 | } |
| 1202 | |
| 1203 | expr3 = "B"; |
| 1204 | } |
| 1205 | |
| 1206 | const std::string cond1 = expr1 + " " + tok->str() + " (" + expr2 + " " + tok->astOperand2()->str() + " " + expr3 + ")"; |
| 1207 | const std::string cond2 = expr1 + " " + tok->str() + " " + expr3; |
| 1208 | |
| 1209 | const std::string cond1VerboseMsg = expr1VerboseMsg + " " + tok->str() + " " + expr2VerboseMsg + " " + tok->astOperand2()->str() + " " + expr3VerboseMsg; |
| 1210 | const std::string cond2VerboseMsg = expr1VerboseMsg + " " + tok->str() + " " + expr3VerboseMsg; |
| 1211 | // for the --verbose message, transform the actual condition and print it |
| 1212 | const std::string msg = tok2->expressionString() + ". '" + cond1 + "' is equivalent to '" + cond2 + "'\n" |
| 1213 | "The condition '" + cond1VerboseMsg + "' is equivalent to '" + cond2VerboseMsg + "'."; |
| 1214 | redundantConditionError(tok, msg, false); |
| 1215 | continue; |
| 1216 | } |
no test coverage detected