| 2871 | } |
| 2872 | |
| 2873 | void CheckOtherImpl::checkDuplicateExpression() |
| 2874 | { |
| 2875 | { |
| 2876 | const bool styleEnabled = mSettings.severity.isEnabled(Severity::style); |
| 2877 | const bool premiumEnabled = mSettings.isPremiumEnabled("oppositeExpression") || |
| 2878 | mSettings.isPremiumEnabled("duplicateExpression") || |
| 2879 | mSettings.isPremiumEnabled("duplicateAssignExpression") || |
| 2880 | mSettings.isPremiumEnabled("duplicateExpressionTernary") || |
| 2881 | mSettings.isPremiumEnabled("duplicateValueTernary") || |
| 2882 | mSettings.isPremiumEnabled("selfAssignment") || |
| 2883 | mSettings.isPremiumEnabled("knownConditionTrueFalse"); |
| 2884 | |
| 2885 | if (!styleEnabled && !premiumEnabled) |
| 2886 | return; |
| 2887 | } |
| 2888 | |
| 2889 | logChecker("CheckOther::checkDuplicateExpression"); // style,warning |
| 2890 | |
| 2891 | // Parse all executing scopes.. |
| 2892 | const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 2893 | |
| 2894 | std::list<const Function*> constFunctions; |
| 2895 | getConstFunctions(symbolDatabase, constFunctions); |
| 2896 | |
| 2897 | for (const Scope *scope : symbolDatabase->functionScopes) { |
| 2898 | for (const Token *tok = scope->bodyStart; tok != scope->bodyEnd; tok = tok->next()) { |
| 2899 | if (tok->str() == "=" && Token::Match(tok->astOperand1(), "%var%")) { |
| 2900 | const Token * endStatement = Token::findsimplematch(tok, ";"); |
| 2901 | if (Token::Match(endStatement, "; %type% %var% ;")) { |
| 2902 | endStatement = endStatement->tokAt(4); |
| 2903 | } |
| 2904 | if (Token::Match(endStatement, "%var% %assign%")) { |
| 2905 | const Token * nextAssign = endStatement->tokAt(1); |
| 2906 | const Token * var1 = tok->astOperand1(); |
| 2907 | const Token * var2 = nextAssign->astOperand1(); |
| 2908 | if (var1 && var2 && |
| 2909 | Token::Match(var1->previous(), ";|{|} %var%") && |
| 2910 | Token::Match(var2->previous(), ";|{|} %var%") && |
| 2911 | var2->valueType() && var1->valueType() && |
| 2912 | var2->valueType()->originalTypeName == var1->valueType()->originalTypeName && |
| 2913 | var2->valueType()->pointer == var1->valueType()->pointer && |
| 2914 | var2->valueType()->constness == var1->valueType()->constness && |
| 2915 | var2->varId() != var1->varId() && ( |
| 2916 | tok->astOperand2()->isArithmeticalOp() || |
| 2917 | tok->astOperand2()->str() == "." || |
| 2918 | Token::Match(tok->astOperand2()->previous(), "%name% (") |
| 2919 | ) && |
| 2920 | tok->next()->tokType() != Token::eType && |
| 2921 | isSameExpression(true, tok->next(), nextAssign->next(), mSettings, true, false) && |
| 2922 | isSameExpression(true, tok->astOperand2(), nextAssign->astOperand2(), mSettings, true, false) && |
| 2923 | tok->astOperand2()->expressionString() == nextAssign->astOperand2()->expressionString()) { |
| 2924 | bool differentDomain = false; |
| 2925 | const Scope * varScope = var1->scope() ? var1->scope() : scope; |
| 2926 | const Token* assignTok = Token::findsimplematch(var2, ";"); |
| 2927 | for (; assignTok && assignTok != varScope->bodyEnd; assignTok = assignTok->next()) { |
| 2928 | if (!Token::Match(assignTok, "%assign%|%comp%")) |
| 2929 | continue; |
| 2930 | if (!assignTok->astOperand1()) |
no test coverage detected