speed up checks by caching commonly looked up stuff in the symbol database (checkIncorrectLogicOperator). Ticket: #4266.
This commit is contained in:
parent
f82eff6589
commit
6578b78077
|
@ -1170,196 +1170,205 @@ void CheckOther::checkIncorrectLogicOperator()
|
||||||
if (!_settings->isEnabled("style"))
|
if (!_settings->isEnabled("style"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||||
// Find a pair of comparison expressions with or without parenthesis
|
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||||
// with a shared variable and constants and with a logical operator between them.
|
for (std::size_t ii = 0; ii < functions; ++ii) {
|
||||||
// e.g. if (x != 3 || x != 4)
|
const Scope * scope = symbolDatabase->functionScopes[ii];
|
||||||
const Token *term1Tok = NULL, *term2Tok = NULL;
|
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||||
const Token *op1Tok = NULL, *op2Tok = NULL, *op3Tok = NULL, *nextTok = NULL;
|
// Find a pair of comparison expressions with or without parenthesis
|
||||||
|
// with a shared variable and constants and with a logical operator between them.
|
||||||
|
// e.g. if (x != 3 || x != 4)
|
||||||
|
const Token *term1Tok = NULL, *term2Tok = NULL;
|
||||||
|
const Token *op1Tok = NULL, *op2Tok = NULL, *op3Tok = NULL, *nextTok = NULL;
|
||||||
|
|
||||||
if (Token::Match(tok, "( %any% !=|==|<|>|>=|<= %any% ) &&|%oror%")) {
|
if (Token::Match(tok, "( %any% %op% %any% ) &&|%oror%") &&
|
||||||
term1Tok = tok->next();
|
tok->tokAt(2)->isComparisonOp()) {
|
||||||
op1Tok = tok->tokAt(2);
|
term1Tok = tok->next();
|
||||||
op2Tok = tok->tokAt(5);
|
op1Tok = tok->tokAt(2);
|
||||||
} else if (Token::Match(tok, "%any% !=|==|<|>|>=|<= %any% &&|%oror%")) {
|
op2Tok = tok->tokAt(5);
|
||||||
term1Tok = tok;
|
} else if (Token::Match(tok, "%any% %op% %any% &&|%oror%") &&
|
||||||
op1Tok = tok->next();
|
tok->tokAt(1)->isComparisonOp()) {
|
||||||
op2Tok = tok->tokAt(3);
|
term1Tok = tok;
|
||||||
}
|
op1Tok = tok->next();
|
||||||
if (op2Tok) {
|
op2Tok = tok->tokAt(3);
|
||||||
if (Token::Match(op2Tok->next(), "( %any% !=|==|<|>|>=|<= %any% ) %any%")) {
|
|
||||||
term2Tok = op2Tok->tokAt(2);
|
|
||||||
op3Tok = op2Tok->tokAt(3);
|
|
||||||
nextTok = op2Tok->tokAt(6);
|
|
||||||
} else if (Token::Match(op2Tok->next(), "%any% !=|==|<|>|>=|<= %any% %any%")) {
|
|
||||||
term2Tok = op2Tok->next();
|
|
||||||
op3Tok = op2Tok->tokAt(2);
|
|
||||||
nextTok = op2Tok->tokAt(4);
|
|
||||||
}
|
}
|
||||||
}
|
if (op2Tok) {
|
||||||
|
if (Token::Match(op2Tok->next(), "( %any% %op% %any% ) %any%") &&
|
||||||
if (nextTok) {
|
op2Tok->tokAt(3)->isComparisonOp()) {
|
||||||
// Find the common variable and the two different-valued constants
|
term2Tok = op2Tok->tokAt(2);
|
||||||
std::string firstConstant, secondConstant;
|
op3Tok = op2Tok->tokAt(3);
|
||||||
bool varFirst1, varFirst2;
|
nextTok = op2Tok->tokAt(6);
|
||||||
unsigned int varId;
|
} else if (Token::Match(op2Tok->next(), "%any% %op% %any% %any%") &&
|
||||||
const Token *var1Tok = NULL, *var2Tok = NULL;
|
op2Tok->tokAt(2)->isComparisonOp()) {
|
||||||
if (Token::Match(term1Tok, "%var% %any% %num%")) {
|
term2Tok = op2Tok->next();
|
||||||
var1Tok = term1Tok;
|
op3Tok = op2Tok->tokAt(2);
|
||||||
varId = var1Tok->varId();
|
nextTok = op2Tok->tokAt(4);
|
||||||
if (!varId) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
varFirst1 = true;
|
|
||||||
firstConstant = term1Tok->strAt(2);
|
|
||||||
} else if (Token::Match(term1Tok, "%num% %any% %var%")) {
|
|
||||||
var1Tok = term1Tok->tokAt(2);
|
|
||||||
varId = var1Tok->varId();
|
|
||||||
if (!varId) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
varFirst1 = false;
|
|
||||||
firstConstant = term1Tok->str();
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(term2Tok, "%var% %any% %num%")) {
|
if (nextTok) {
|
||||||
var2Tok = term2Tok;
|
// Find the common variable and the two different-valued constants
|
||||||
varFirst2 = true;
|
std::string firstConstant, secondConstant;
|
||||||
secondConstant = term2Tok->strAt(2);
|
bool varFirst1, varFirst2;
|
||||||
} else if (Token::Match(term2Tok, "%num% %any% %var%")) {
|
unsigned int varId;
|
||||||
var2Tok = term2Tok->tokAt(2);
|
const Token *var1Tok = NULL, *var2Tok = NULL;
|
||||||
varFirst2 = false;
|
if (Token::Match(term1Tok, "%var% %any% %num%")) {
|
||||||
secondConstant = term2Tok->str();
|
var1Tok = term1Tok;
|
||||||
} else {
|
varId = var1Tok->varId();
|
||||||
continue;
|
if (!varId) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
if (varId != var2Tok->varId() || firstConstant.empty() || secondConstant.empty()) {
|
varFirst1 = true;
|
||||||
continue;
|
firstConstant = term1Tok->strAt(2);
|
||||||
}
|
} else if (Token::Match(term1Tok, "%num% %any% %var%")) {
|
||||||
|
var1Tok = term1Tok->tokAt(2);
|
||||||
enum LogicError { AlwaysFalse, AlwaysTrue, FirstTrue, FirstFalse, SecondTrue, SecondFalse };
|
varId = var1Tok->varId();
|
||||||
|
if (!varId) {
|
||||||
static const struct LinkedConditions {
|
continue;
|
||||||
const char *before;
|
}
|
||||||
Condition c1;
|
varFirst1 = false;
|
||||||
const char *op2TokStr;
|
firstConstant = term1Tok->str();
|
||||||
Condition c2;
|
} else {
|
||||||
const char *after;
|
continue;
|
||||||
Relation relation;
|
}
|
||||||
LogicError error;
|
|
||||||
} conditions[] = {
|
if (Token::Match(term2Tok, "%var% %any% %num%")) {
|
||||||
{ "!!&&", { NA, "!=" }, "%oror%", { NA, "!=" }, "!!&&", NotEqual, AlwaysTrue }, // (x != 1) || (x != 3) <- always true
|
var2Tok = term2Tok;
|
||||||
{ 0, { NA, "==" }, "&&", { NA, "==" }, 0, NotEqual, AlwaysFalse }, // (x == 1) && (x == 3) <- always false
|
varFirst2 = true;
|
||||||
{ "!!&&", { First, ">" }, "%oror%", { First, "<" }, "!!&&", Less, AlwaysTrue }, // (x > 3) || (x < 10) <- always true
|
secondConstant = term2Tok->strAt(2);
|
||||||
{ "!!&&", { First, ">=" }, "%oror%", { First, "<|<=" }, "!!&&", LessEqual, AlwaysTrue }, // (x >= 3) || (x < 10) <- always true
|
} else if (Token::Match(term2Tok, "%num% %any% %var%")) {
|
||||||
{ "!!&&", { First, ">" }, "%oror%", { First, "<=" }, "!!&&", LessEqual, AlwaysTrue }, // (x > 3) || (x <= 10) <- always true
|
var2Tok = term2Tok->tokAt(2);
|
||||||
{ 0, { First, "<" }, "&&", { First, ">" }, 0, LessEqual, AlwaysFalse }, // (x < 1) && (x > 3) <- always false
|
varFirst2 = false;
|
||||||
{ 0, { First, "<=" }, "&&", { First, ">|>=" }, 0, Less, AlwaysFalse }, // (x <= 1) && (x > 3) <- always false
|
secondConstant = term2Tok->str();
|
||||||
{ 0, { First, "<" }, "&&", { First, ">=" }, 0, Less, AlwaysFalse }, // (x < 1) && (x >= 3) <- always false
|
} else {
|
||||||
{ 0, { First, ">" }, "&&", { NA, "==" }, 0, MoreEqual, AlwaysFalse }, // (x > 5) && (x == 1) <- always false
|
continue;
|
||||||
{ 0, { First, "<" }, "&&", { NA, "==" }, 0, LessEqual, AlwaysFalse }, // (x < 1) && (x == 3) <- always false
|
}
|
||||||
{ 0, { First, ">=" }, "&&", { NA, "==" }, 0, More, AlwaysFalse }, // (x >= 5) && (x == 1) <- always false
|
|
||||||
{ 0, { First, "<=" }, "&&", { NA, "==" }, 0, Less, AlwaysFalse }, // (x <= 1) && (x == 3) <- always false
|
if (varId != var2Tok->varId() || firstConstant.empty() || secondConstant.empty()) {
|
||||||
{ "!!&&", { NA, "==" }, "%oror%", { First, ">" }, "!!&&", More, SecondTrue }, // (x == 4) || (x > 3) <- second expression always true
|
continue;
|
||||||
{ "!!&&", { NA, "==" }, "%oror%", { First, "<" }, "!!&&", Less, SecondTrue }, // (x == 4) || (x < 5) <- second expression always true
|
}
|
||||||
{ "!!&&", { NA, "==" }, "%oror%", { First, ">=" }, "!!&&", MoreEqual, SecondTrue }, // (x == 4) || (x >= 3) <- second expression always true
|
|
||||||
{ "!!&&", { NA, "==" }, "%oror%", { First, "<=" }, "!!&&", LessEqual, SecondTrue }, // (x == 4) || (x <= 5) <- second expression always true
|
enum LogicError { AlwaysFalse, AlwaysTrue, FirstTrue, FirstFalse, SecondTrue, SecondFalse };
|
||||||
{ "!!&&", { First, ">" }, "%oror%", { NA, "!=" }, "!!&&", MoreEqual, SecondTrue }, // (x > 5) || (x != 1) <- second expression always true
|
|
||||||
{ "!!&&", { First, "<" }, "%oror%", { NA, "!=" }, "!!&&", LessEqual, SecondTrue }, // (x < 1) || (x != 3) <- second expression always true
|
static const struct LinkedConditions {
|
||||||
{ "!!&&", { First, ">=" }, "%oror%", { NA, "!=" }, "!!&&", More, SecondTrue }, // (x >= 5) || (x != 1) <- second expression always true
|
const char *before;
|
||||||
{ "!!&&", { First, "<=" }, "%oror%", { NA, "!=" }, "!!&&", Less, SecondTrue }, // (x <= 1) || (x != 3) <- second expression always true
|
Condition c1;
|
||||||
{ 0, { First, ">" }, "&&", { NA, "!=" }, 0, MoreEqual, SecondTrue }, // (x > 5) && (x != 1) <- second expression always true
|
const char *op2TokStr;
|
||||||
{ 0, { First, "<" }, "&&", { NA, "!=" }, 0, LessEqual, SecondTrue }, // (x < 1) && (x != 3) <- second expression always true
|
Condition c2;
|
||||||
{ 0, { First, ">=" }, "&&", { NA, "!=" }, 0, More, SecondTrue }, // (x >= 5) && (x != 1) <- second expression always true
|
const char *after;
|
||||||
{ 0, { First, "<=" }, "&&", { NA, "!=" }, 0, Less, SecondTrue }, // (x <= 1) && (x != 3) <- second expression always true
|
Relation relation;
|
||||||
{ "!!&&", { First, ">|>=" }, "%oror%", { First, ">|>=" }, "!!&&", LessEqual, SecondTrue }, // (x > 4) || (x > 5) <- second expression always true
|
LogicError error;
|
||||||
{ "!!&&", { First, "<|<=" }, "%oror%", { First, "<|<=" }, "!!&&", MoreEqual, SecondTrue }, // (x < 5) || (x < 4) <- second expression always true
|
} conditions[] = {
|
||||||
{ 0, { First, ">|>=" }, "&&", { First, ">|>=" }, 0, MoreEqual, SecondTrue }, // (x > 4) && (x > 5) <- second expression always true
|
{ "!!&&", { NA, "!=" }, "%oror%", { NA, "!=" }, "!!&&", NotEqual, AlwaysTrue }, // (x != 1) || (x != 3) <- always true
|
||||||
{ 0, { First, "<|<=" }, "&&", { First, "<|<=" }, 0, MoreEqual, SecondTrue }, // (x < 5) && (x < 4) <- second expression always true
|
{ 0, { NA, "==" }, "&&", { NA, "==" }, 0, NotEqual, AlwaysFalse }, // (x == 1) && (x == 3) <- always false
|
||||||
{ 0, { NA, "==" }, "&&", { NA, "!=" }, 0, NotEqual, SecondTrue }, // (x == 3) && (x != 4) <- second expression always true
|
{ "!!&&", { First, ">" }, "%oror%", { First, "<" }, "!!&&", Less, AlwaysTrue }, // (x > 3) || (x < 10) <- always true
|
||||||
{ "!!&&", { NA, "==" }, "%oror%", { NA, "!=" }, "!!&&", NotEqual, SecondTrue }, // (x == 3) || (x != 4) <- second expression always true
|
{ "!!&&", { First, ">=" }, "%oror%", { First, "<|<=" }, "!!&&", LessEqual, AlwaysTrue }, // (x >= 3) || (x < 10) <- always true
|
||||||
{ 0, { NA, "!=" }, "&&", { NA, "==" }, 0, Equal, AlwaysFalse }, // (x != 3) && (x == 3) <- expression always false
|
{ "!!&&", { First, ">" }, "%oror%", { First, "<=" }, "!!&&", LessEqual, AlwaysTrue }, // (x > 3) || (x <= 10) <- always true
|
||||||
{ "!!&&", { NA, "!=" }, "%oror%", { NA, "==" }, "!!&&", Equal, AlwaysTrue }, // (x != 3) || (x == 3) <- expression always true
|
{ 0, { First, "<" }, "&&", { First, ">" }, 0, LessEqual, AlwaysFalse }, // (x < 1) && (x > 3) <- always false
|
||||||
};
|
{ 0, { First, "<=" }, "&&", { First, ">|>=" }, 0, Less, AlwaysFalse }, // (x <= 1) && (x > 3) <- always false
|
||||||
|
{ 0, { First, "<" }, "&&", { First, ">=" }, 0, Less, AlwaysFalse }, // (x < 1) && (x >= 3) <- always false
|
||||||
for (unsigned int i = 0; i < (sizeof(conditions) / sizeof(conditions[0])); i++) {
|
{ 0, { First, ">" }, "&&", { NA, "==" }, 0, MoreEqual, AlwaysFalse }, // (x > 5) && (x == 1) <- always false
|
||||||
if (!Token::Match(op2Tok, conditions[i].op2TokStr))
|
{ 0, { First, "<" }, "&&", { NA, "==" }, 0, LessEqual, AlwaysFalse }, // (x < 1) && (x == 3) <- always false
|
||||||
continue;
|
{ 0, { First, ">=" }, "&&", { NA, "==" }, 0, More, AlwaysFalse }, // (x >= 5) && (x == 1) <- always false
|
||||||
|
{ 0, { First, "<=" }, "&&", { NA, "==" }, 0, Less, AlwaysFalse }, // (x <= 1) && (x == 3) <- always false
|
||||||
if (conditions[i].before != 0 && !Token::Match(tok->previous(), conditions[i].before))
|
{ "!!&&", { NA, "==" }, "%oror%", { First, ">" }, "!!&&", More, SecondTrue }, // (x == 4) || (x > 3) <- second expression always true
|
||||||
continue;
|
{ "!!&&", { NA, "==" }, "%oror%", { First, "<" }, "!!&&", Less, SecondTrue }, // (x == 4) || (x < 5) <- second expression always true
|
||||||
|
{ "!!&&", { NA, "==" }, "%oror%", { First, ">=" }, "!!&&", MoreEqual, SecondTrue }, // (x == 4) || (x >= 3) <- second expression always true
|
||||||
if (conditions[i].after != 0 && !Token::Match(nextTok, conditions[i].after))
|
{ "!!&&", { NA, "==" }, "%oror%", { First, "<=" }, "!!&&", LessEqual, SecondTrue }, // (x == 4) || (x <= 5) <- second expression always true
|
||||||
continue;
|
{ "!!&&", { First, ">" }, "%oror%", { NA, "!=" }, "!!&&", MoreEqual, SecondTrue }, // (x > 5) || (x != 1) <- second expression always true
|
||||||
|
{ "!!&&", { First, "<" }, "%oror%", { NA, "!=" }, "!!&&", LessEqual, SecondTrue }, // (x < 1) || (x != 3) <- second expression always true
|
||||||
if (tok->previous()->isArithmeticalOp() || nextTok->isArithmeticalOp())
|
{ "!!&&", { First, ">=" }, "%oror%", { NA, "!=" }, "!!&&", More, SecondTrue }, // (x >= 5) || (x != 1) <- second expression always true
|
||||||
continue;
|
{ "!!&&", { First, "<=" }, "%oror%", { NA, "!=" }, "!!&&", Less, SecondTrue }, // (x <= 1) || (x != 3) <- second expression always true
|
||||||
|
{ 0, { First, ">" }, "&&", { NA, "!=" }, 0, MoreEqual, SecondTrue }, // (x > 5) && (x != 1) <- second expression always true
|
||||||
std::string cond1str = var1Tok->str() + " " + (varFirst1?op1Tok->str():invertOperatorForOperandSwap(op1Tok->str())) + " " + firstConstant;
|
{ 0, { First, "<" }, "&&", { NA, "!=" }, 0, LessEqual, SecondTrue }, // (x < 1) && (x != 3) <- second expression always true
|
||||||
std::string cond2str = var2Tok->str() + " " + (varFirst2?op3Tok->str():invertOperatorForOperandSwap(op3Tok->str())) + " " + secondConstant;
|
{ 0, { First, ">=" }, "&&", { NA, "!=" }, 0, More, SecondTrue }, // (x >= 5) && (x != 1) <- second expression always true
|
||||||
// cond1 op cond2
|
{ 0, { First, "<=" }, "&&", { NA, "!=" }, 0, Less, SecondTrue }, // (x <= 1) && (x != 3) <- second expression always true
|
||||||
bool error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, false, false,
|
{ "!!&&", { First, ">|>=" }, "%oror%", { First, ">|>=" }, "!!&&", LessEqual, SecondTrue }, // (x > 4) || (x > 5) <- second expression always true
|
||||||
varFirst1, varFirst2, firstConstant, secondConstant,
|
{ "!!&&", { First, "<|<=" }, "%oror%", { First, "<|<=" }, "!!&&", MoreEqual, SecondTrue }, // (x < 5) || (x < 4) <- second expression always true
|
||||||
op1Tok, op3Tok,
|
{ 0, { First, ">|>=" }, "&&", { First, ">|>=" }, 0, MoreEqual, SecondTrue }, // (x > 4) && (x > 5) <- second expression always true
|
||||||
conditions[i].relation);
|
{ 0, { First, "<|<=" }, "&&", { First, "<|<=" }, 0, MoreEqual, SecondTrue }, // (x < 5) && (x < 4) <- second expression always true
|
||||||
// inv(cond1) op cond2 // invert first condition
|
{ 0, { NA, "==" }, "&&", { NA, "!=" }, 0, NotEqual, SecondTrue }, // (x == 3) && (x != 4) <- second expression always true
|
||||||
if (!error && conditions[i].c1.position != NA)
|
{ "!!&&", { NA, "==" }, "%oror%", { NA, "!=" }, "!!&&", NotEqual, SecondTrue }, // (x == 3) || (x != 4) <- second expression always true
|
||||||
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, true, false,
|
{ 0, { NA, "!=" }, "&&", { NA, "==" }, 0, Equal, AlwaysFalse }, // (x != 3) && (x == 3) <- expression always false
|
||||||
!varFirst1, varFirst2, firstConstant, secondConstant,
|
{ "!!&&", { NA, "!=" }, "%oror%", { NA, "==" }, "!!&&", Equal, AlwaysTrue }, // (x != 3) || (x == 3) <- expression always true
|
||||||
op1Tok, op3Tok,
|
};
|
||||||
conditions[i].relation);
|
|
||||||
// cond1 op inv(cond2) // invert second condition
|
for (unsigned int i = 0; i < (sizeof(conditions) / sizeof(conditions[0])); i++) {
|
||||||
if (!error && conditions[i].c2.position != NA)
|
if (!Token::Match(op2Tok, conditions[i].op2TokStr))
|
||||||
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, false, true,
|
continue;
|
||||||
varFirst1, !varFirst2, firstConstant, secondConstant,
|
|
||||||
op1Tok, op3Tok,
|
if (conditions[i].before != 0 && !Token::Match(tok->previous(), conditions[i].before))
|
||||||
conditions[i].relation);
|
continue;
|
||||||
// inv(cond1) op inv(cond2) // invert both conditions
|
|
||||||
if (!error && conditions[i].c1.position != NA && conditions[i].c2.position != NA)
|
if (conditions[i].after != 0 && !Token::Match(nextTok, conditions[i].after))
|
||||||
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, true, true,
|
continue;
|
||||||
!varFirst1, !varFirst2, firstConstant, secondConstant,
|
|
||||||
op1Tok, op3Tok,
|
if (tok->previous()->isArithmeticalOp() || nextTok->isArithmeticalOp())
|
||||||
conditions[i].relation);
|
continue;
|
||||||
if (!error)
|
|
||||||
std::swap(cond1str, cond2str);
|
std::string cond1str = var1Tok->str() + " " + (varFirst1?op1Tok->str():invertOperatorForOperandSwap(op1Tok->str())) + " " + firstConstant;
|
||||||
// cond2 op cond1 // swap conditions
|
std::string cond2str = var2Tok->str() + " " + (varFirst2?op3Tok->str():invertOperatorForOperandSwap(op3Tok->str())) + " " + secondConstant;
|
||||||
if (!error)
|
// cond1 op cond2
|
||||||
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, false, false,
|
bool error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, false, false,
|
||||||
varFirst2, varFirst1, secondConstant, firstConstant,
|
varFirst1, varFirst2, firstConstant, secondConstant,
|
||||||
op3Tok, op1Tok,
|
op1Tok, op3Tok,
|
||||||
conditions[i].relation);
|
conditions[i].relation);
|
||||||
// cond2 op inv(cond1) // swap conditions; invert first condition
|
// inv(cond1) op cond2 // invert first condition
|
||||||
if (!error && conditions[i].c1.position != NA)
|
if (!error && conditions[i].c1.position != NA)
|
||||||
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, true, false,
|
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, true, false,
|
||||||
!varFirst2, varFirst1, secondConstant, firstConstant,
|
!varFirst1, varFirst2, firstConstant, secondConstant,
|
||||||
op3Tok, op1Tok,
|
op1Tok, op3Tok,
|
||||||
conditions[i].relation);
|
conditions[i].relation);
|
||||||
// inv(cond2) op cond1 // swap conditions; invert second condition
|
// cond1 op inv(cond2) // invert second condition
|
||||||
if (!error && conditions[i].c2.position != NA)
|
if (!error && conditions[i].c2.position != NA)
|
||||||
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, false, true,
|
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, false, true,
|
||||||
varFirst2, !varFirst1, secondConstant, firstConstant,
|
varFirst1, !varFirst2, firstConstant, secondConstant,
|
||||||
op3Tok, op1Tok,
|
op1Tok, op3Tok,
|
||||||
conditions[i].relation);
|
conditions[i].relation);
|
||||||
// inv(cond2) op inv(cond1) // swap conditions; invert both conditions
|
// inv(cond1) op inv(cond2) // invert both conditions
|
||||||
if (!error && conditions[i].c1.position != NA && conditions[i].c2.position != NA)
|
if (!error && conditions[i].c1.position != NA && conditions[i].c2.position != NA)
|
||||||
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, true, true,
|
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, true, true,
|
||||||
!varFirst2, !varFirst1, secondConstant, firstConstant,
|
!varFirst1, !varFirst2, firstConstant, secondConstant,
|
||||||
op3Tok, op1Tok,
|
op1Tok, op3Tok,
|
||||||
conditions[i].relation);
|
conditions[i].relation);
|
||||||
|
if (!error)
|
||||||
if (error) {
|
std::swap(cond1str, cond2str);
|
||||||
if (conditions[i].error == AlwaysFalse || conditions[i].error == AlwaysTrue) {
|
// cond2 op cond1 // swap conditions
|
||||||
const std::string text = cond1str + " " + op2Tok->str() + " " + cond2str;
|
if (!error)
|
||||||
incorrectLogicOperatorError(term1Tok, text, conditions[i].error == AlwaysTrue);
|
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, false, false,
|
||||||
} else {
|
varFirst2, varFirst1, secondConstant, firstConstant,
|
||||||
const std::string text = "If " + cond1str + ", the comparison " + cond2str +
|
op3Tok, op1Tok,
|
||||||
" is always " + ((conditions[i].error == SecondTrue || conditions[i].error == AlwaysTrue) ? "true" : "false") + ".";
|
conditions[i].relation);
|
||||||
redundantConditionError(term1Tok, text);
|
// cond2 op inv(cond1) // swap conditions; invert first condition
|
||||||
|
if (!error && conditions[i].c1.position != NA)
|
||||||
|
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, true, false,
|
||||||
|
!varFirst2, varFirst1, secondConstant, firstConstant,
|
||||||
|
op3Tok, op1Tok,
|
||||||
|
conditions[i].relation);
|
||||||
|
// inv(cond2) op cond1 // swap conditions; invert second condition
|
||||||
|
if (!error && conditions[i].c2.position != NA)
|
||||||
|
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, false, true,
|
||||||
|
varFirst2, !varFirst1, secondConstant, firstConstant,
|
||||||
|
op3Tok, op1Tok,
|
||||||
|
conditions[i].relation);
|
||||||
|
// inv(cond2) op inv(cond1) // swap conditions; invert both conditions
|
||||||
|
if (!error && conditions[i].c1.position != NA && conditions[i].c2.position != NA)
|
||||||
|
error = analyzeLogicOperatorCondition(conditions[i].c1, conditions[i].c2, true, true,
|
||||||
|
!varFirst2, !varFirst1, secondConstant, firstConstant,
|
||||||
|
op3Tok, op1Tok,
|
||||||
|
conditions[i].relation);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
if (conditions[i].error == AlwaysFalse || conditions[i].error == AlwaysTrue) {
|
||||||
|
const std::string text = cond1str + " " + op2Tok->str() + " " + cond2str;
|
||||||
|
incorrectLogicOperatorError(term1Tok, text, conditions[i].error == AlwaysTrue);
|
||||||
|
} else {
|
||||||
|
const std::string text = "If " + cond1str + ", the comparison " + cond2str +
|
||||||
|
" is always " + ((conditions[i].error == SecondTrue || conditions[i].error == AlwaysTrue) ? "true" : "false") + ".";
|
||||||
|
redundantConditionError(term1Tok, text);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,6 +190,9 @@ public:
|
||||||
return isOp() ||
|
return isOp() ||
|
||||||
_type == eExtendedOp;
|
_type == eExtendedOp;
|
||||||
}
|
}
|
||||||
|
bool isComparisonOp() const {
|
||||||
|
return _type == eComparisonOp;
|
||||||
|
}
|
||||||
bool isAssignmentOp() const {
|
bool isAssignmentOp() const {
|
||||||
return _type == eAssignmentOp;
|
return _type == eAssignmentOp;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue