| 2044 | } |
| 2045 | |
| 2046 | bool isConstFunctionCall(const Token* ftok, const Library& library) |
| 2047 | { |
| 2048 | if (isUnevaluated(ftok)) |
| 2049 | return true; |
| 2050 | if (!Token::Match(ftok, "%name% (")) |
| 2051 | return false; |
| 2052 | if (const Function* f = ftok->function()) { |
| 2053 | if (f->isAttributePure() || f->isAttributeConst()) |
| 2054 | return true; |
| 2055 | // Any modified arguments |
| 2056 | if (functionModifiesArguments(f)) |
| 2057 | return false; |
| 2058 | if (Function::returnsVoid(f)) |
| 2059 | return false; |
| 2060 | // Member function call |
| 2061 | if (Token::simpleMatch(ftok->previous(), ".") || exprDependsOnThis(ftok->next())) { |
| 2062 | if (f->isConst()) |
| 2063 | return true; |
| 2064 | // Check for const overloaded function that just return the const version |
| 2065 | if (!Function::returnsConst(f)) { |
| 2066 | std::vector<const Function*> fs = f->getOverloadedFunctions(); |
| 2067 | if (std::any_of(fs.cbegin(), fs.cend(), [&](const Function* g) { |
| 2068 | if (f == g) |
| 2069 | return false; |
| 2070 | if (f->argumentList.size() != g->argumentList.size()) |
| 2071 | return false; |
| 2072 | if (functionModifiesArguments(g)) |
| 2073 | return false; |
| 2074 | if (g->isConst() && Function::returnsConst(g)) |
| 2075 | return true; |
| 2076 | return false; |
| 2077 | })) |
| 2078 | return true; |
| 2079 | } |
| 2080 | return false; |
| 2081 | } |
| 2082 | if (f->argumentList.empty()) |
| 2083 | return f->isConstexpr(); |
| 2084 | } else if (Token::Match(ftok->previous(), ". %name% (") && ftok->previous()->originalName() != "->" && |
| 2085 | astIsSmartPointer(ftok->previous()->astOperand1())) { |
| 2086 | return Token::Match(ftok, "get|get_deleter ( )"); |
| 2087 | } else if (Token::Match(ftok->previous(), ". %name% (") && astIsContainer(ftok->previous()->astOperand1())) { |
| 2088 | const Library::Container* container = ftok->previous()->astOperand1()->valueType()->container; |
| 2089 | if (!container) |
| 2090 | return false; |
| 2091 | if (container->getYield(ftok->str()) != Library::Container::Yield::NO_YIELD) |
| 2092 | return true; |
| 2093 | if (container->getAction(ftok->str()) == Library::Container::Action::FIND_CONST) |
| 2094 | return true; |
| 2095 | return false; |
| 2096 | } else if (const Library::Function* lf = library.getFunction(ftok)) { |
| 2097 | if (lf->ispure) |
| 2098 | return true; |
| 2099 | if (lf->containerYield != Library::Container::Yield::NO_YIELD) |
| 2100 | return true; |
| 2101 | if (lf->containerAction == Library::Container::Action::FIND_CONST) |
| 2102 | return true; |
| 2103 | return false; |
no test coverage detected