static int doAssignment(Variables &variables, const Token *tok, bool dereference, const Scope *scope) { // a = a + b; if (Token::Match(tok, "%var% = %var% !!;") && tok->str() == tok->strAt(2)) { return 2; } int next = 0; // check for aliased variable const unsigned int varid1 = tok->varId(); Variables::VariableUsage *var1 = variables.find(varid1); if (var1) { Variables::VariableUsage *var2 = 0; int start = 1; // search for '=' while (tok->strAt(start) != "=") start++; start++; if (Token::Match(tok->tokAt(start), "&| %var%") || Token::Match(tok->tokAt(start), "( const| struct|union| %type% *| ) &| %var%") || Token::Match(tok->tokAt(start), "( const| struct|union| %type% *| ) ( &| %var%") || Token::Match(tok->tokAt(start+1), "< const| struct|union| %type% *| > ( &| %var%")) { unsigned char offset = 0; unsigned int varid2; bool addressOf = false; if (Token::Match(tok->tokAt(start), "%var% .")) variables.use(tok->tokAt(start)->varId()); // use = read + write // check for C style cast if (tok->strAt(start) == "(") { if (tok->strAt(start + 1) == "const") offset++; if (Token::Match(tok->tokAt(start + 1 + offset), "struct|union")) offset++; if (tok->strAt(start + 2 + offset) == "*") offset++; if (tok->strAt(start + 3 + offset) == "&") { addressOf = true; next = start + 4 + offset; } else if (tok->strAt(start + 3 + offset) == "(") { if (tok->strAt(start + 4 + offset) == "&") { addressOf = true; next = start + 5 + offset; } else next = start + 4 + offset; } else next = start + 3 + offset; } // check for C++ style cast else if (tok->strAt(start).find("cast") != std::string::npos && tok->strAt(start + 1) == "<") { if (tok->strAt(start + 2) == "const") offset++; if (Token::Match(tok->tokAt(start + 2 + offset), "struct|union")) offset++; if (tok->strAt(start + 3 + offset) == "*") offset++; if (tok->strAt(start + 5 + offset) == "&") { addressOf = true; next = start + 6 + offset; } else next = start + 5 + offset; } // check for var ? ... else if (Token::Match(tok->tokAt(start), "%var% ?")) { next = start; } // no cast else { if (tok->strAt(start) == "&") { addressOf = true; next = start + 1; } else if (tok->strAt(start) == "new") return 0; else next = start; } // check if variable is local varid2 = tok->tokAt(next)->varId(); var2 = variables.find(varid2); if (var2) { // local variable (alias or read it) if (var1->_type == Variables::pointer) { if (dereference) variables.read(varid2); else { if (addressOf || var2->_type == Variables::array || var2->_type == Variables::pointer) { bool replace = true; // check if variable declared in same scope if (scope == var1->_scope) replace = true; // not in same scope as declaration else { // no other assignment in this scope if (var1->_assignments.find(scope) == var1->_assignments.end()) { // nothing to replace if (var1->_assignments.empty()) replace = false; // this variable has previous assignments else { /** * @todo determine if existing aliases should be replaced or merged */ replace = false; } } // assignment in this scope else { // replace when only one other assignment if (var1->_assignments.size() == 1) replace = true; // otherwise, merge them else replace = false; } } variables.alias(varid1, varid2, replace); } else if (tok->strAt(next + 1) == "?") { if (var2->_type == Variables::reference) variables.readAliases(varid2); else variables.read(varid2); } } } else if (var1->_type == Variables::reference) { variables.alias(varid1, varid2, true); } else { if (var2->_type == Variables::pointer && tok->strAt(next + 1) == "[") variables.readAliases(varid2); variables.read(varid2); } } else { // not a local variable (or an unsupported local variable) if (var1->_type == Variables::pointer && !dereference) { // check if variable declaration is in this scope if (var1->_scope == scope) variables.clearAliases(varid1); else { // no other assignment in this scope if (var1->_assignments.find(scope) == var1->_assignments.end()) { /** * @todo determine if existing aliases should be discarded */ } // this assignment replaces the last assignment in this scope else { // aliased variables in a larger scope are not supported // remove all aliases variables.clearAliases(varid1); } } } } } var1->_assignments.insert(scope); } // check for alias to struct member // char c[10]; a.b = c; else if (Token::Match(tok->tokAt(-2), "%var% .")) { if (Token::Match(tok->tokAt(2), "%var%")) { unsigned int varid2 = tok->tokAt(2)->varId(); Variables::VariableUsage *var2 = variables.find(varid2); // struct member aliased to local variable if (var2 && (var2->_type == Variables::array || var2->_type == Variables::pointer)) { // erase aliased variable and all variables that alias it // to prevent false positives variables.eraseAll(varid2); } } } return next; }