2014-01-04 20:57:02 +01:00
|
|
|
/*
|
|
|
|
* Cppcheck - A tool for static C/C++ code analysis
|
2019-02-09 07:24:06 +01:00
|
|
|
* Copyright (C) 2007-2019 Cppcheck team.
|
2014-01-04 20:57:02 +01:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
#ifndef valueflowH
|
|
|
|
#define valueflowH
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
2017-05-27 04:33:47 +02:00
|
|
|
#include "config.h"
|
2019-07-15 13:47:17 +02:00
|
|
|
#include "utils.h"
|
2017-05-27 04:33:47 +02:00
|
|
|
|
2017-05-15 20:05:11 +02:00
|
|
|
#include <list>
|
2015-07-29 19:54:57 +02:00
|
|
|
#include <string>
|
2017-05-27 04:33:47 +02:00
|
|
|
#include <utility>
|
2019-09-11 19:25:09 +02:00
|
|
|
#include <vector>
|
2015-07-29 19:54:57 +02:00
|
|
|
|
2014-01-05 20:06:46 +01:00
|
|
|
class ErrorLogger;
|
|
|
|
class Settings;
|
2017-05-27 04:33:47 +02:00
|
|
|
class SymbolDatabase;
|
|
|
|
class Token;
|
|
|
|
class TokenList;
|
Set correct type and size of string and char literals (#2275)
* Set correct type and size of string and char literals
Use that string and char literal tokens store the prefix. This makes
it possible to distinghuish between different type of string literals
(i.e., utf8 encoded strings, utf16, wide strings, etc) which have
different type.
When the tokens holding the string and character values have the correct
type, it is possible to improve Token::getStrSize() to give the correct
result for all string types. Previously, it would return the number of
characters in the string, i.e., it would give the wrong size unless
the type of the string was char*.
Since strings now can have different size (in number of bytes) and
length (in number of elements), add a new helper function that returns
the number of characters. Checkers have been updated to use the correct
functions.
Having the size makes it possible to find more problems with prefixed
strings, and to reduce false positives, for example in the buffer
overflow checker.
Also, improve the stringLiteralWrite error message to also print the
prefix of the string (if there is one).
* Add comment and update string length
2019-10-20 07:11:57 +02:00
|
|
|
class ValueType;
|
2019-01-23 07:29:16 +01:00
|
|
|
class Variable;
|
2014-01-04 20:57:02 +01:00
|
|
|
|
|
|
|
namespace ValueFlow {
|
2019-09-20 15:07:27 +02:00
|
|
|
struct increment {
|
|
|
|
template <class T>
|
|
|
|
void operator()(T& x) const {
|
|
|
|
x++;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
struct decrement {
|
|
|
|
template <class T>
|
|
|
|
void operator()(T& x) const {
|
|
|
|
x--;
|
|
|
|
}
|
|
|
|
};
|
2015-10-07 13:38:34 +02:00
|
|
|
class CPPCHECKLIB Value {
|
2014-01-07 19:20:56 +01:00
|
|
|
public:
|
2017-05-16 22:38:13 +02:00
|
|
|
typedef std::pair<const Token *, std::string> ErrorPathItem;
|
|
|
|
typedef std::list<ErrorPathItem> ErrorPath;
|
|
|
|
|
2019-01-29 09:47:52 +01:00
|
|
|
explicit Value(long long val = 0)
|
2019-07-10 14:04:56 +02:00
|
|
|
: valueType(ValueType::INT),
|
2019-09-20 15:06:37 +02:00
|
|
|
bound(Bound::Point),
|
2019-01-29 09:47:52 +01:00
|
|
|
intvalue(val),
|
|
|
|
tokvalue(nullptr),
|
|
|
|
floatValue(0.0),
|
2019-07-10 15:27:07 +02:00
|
|
|
moveKind(MoveKind::NonMovedVariable),
|
2019-01-29 09:47:52 +01:00
|
|
|
varvalue(val),
|
|
|
|
condition(nullptr),
|
|
|
|
varId(0U),
|
2019-07-25 17:19:51 +02:00
|
|
|
safe(false),
|
2019-01-29 09:47:52 +01:00
|
|
|
conditional(false),
|
|
|
|
defaultArg(false),
|
2019-08-17 07:36:41 +02:00
|
|
|
indirect(0),
|
2019-07-16 10:51:07 +02:00
|
|
|
lifetimeKind(LifetimeKind::Object),
|
2019-07-16 11:12:35 +02:00
|
|
|
lifetimeScope(LifetimeScope::Local),
|
2019-01-29 09:47:52 +01:00
|
|
|
valueKind(ValueKind::Possible)
|
|
|
|
{}
|
2017-05-16 23:12:35 +02:00
|
|
|
Value(const Token *c, long long val);
|
2014-01-18 19:30:44 +01:00
|
|
|
|
2019-09-05 15:15:58 +02:00
|
|
|
bool equalValue(const ValueFlow::Value& rhs) const {
|
2016-11-13 22:33:39 +01:00
|
|
|
if (valueType != rhs.valueType)
|
|
|
|
return false;
|
|
|
|
switch (valueType) {
|
2019-07-10 14:04:56 +02:00
|
|
|
case ValueType::INT:
|
2016-11-13 22:33:39 +01:00
|
|
|
if (intvalue != rhs.intvalue)
|
|
|
|
return false;
|
|
|
|
break;
|
2019-07-10 14:04:56 +02:00
|
|
|
case ValueType::TOK:
|
2016-11-13 22:33:39 +01:00
|
|
|
if (tokvalue != rhs.tokvalue)
|
|
|
|
return false;
|
|
|
|
break;
|
2019-07-10 14:04:56 +02:00
|
|
|
case ValueType::FLOAT:
|
2016-11-13 22:59:56 +01:00
|
|
|
// TODO: Write some better comparison
|
|
|
|
if (floatValue > rhs.floatValue || floatValue < rhs.floatValue)
|
|
|
|
return false;
|
|
|
|
break;
|
2019-07-10 14:04:56 +02:00
|
|
|
case ValueType::MOVED:
|
2016-11-20 15:14:49 +01:00
|
|
|
if (moveKind != rhs.moveKind)
|
|
|
|
return false;
|
|
|
|
break;
|
2019-07-10 14:04:56 +02:00
|
|
|
case ValueType::UNINIT:
|
2017-04-23 18:05:14 +02:00
|
|
|
break;
|
2019-07-10 14:04:56 +02:00
|
|
|
case ValueType::BUFFER_SIZE:
|
2019-03-17 13:09:15 +01:00
|
|
|
if (intvalue != rhs.intvalue)
|
|
|
|
return false;
|
|
|
|
break;
|
2019-07-10 14:04:56 +02:00
|
|
|
case ValueType::CONTAINER_SIZE:
|
2018-08-10 11:29:16 +02:00
|
|
|
if (intvalue != rhs.intvalue)
|
|
|
|
return false;
|
2018-11-10 16:40:40 +01:00
|
|
|
break;
|
2019-07-10 14:04:56 +02:00
|
|
|
case ValueType::LIFETIME:
|
2018-11-10 16:40:40 +01:00
|
|
|
if (tokvalue != rhs.tokvalue)
|
|
|
|
return false;
|
2019-06-30 21:43:25 +02:00
|
|
|
}
|
2019-09-05 15:15:58 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-09-20 15:06:37 +02:00
|
|
|
template <class F>
|
2019-09-20 15:07:27 +02:00
|
|
|
void visitValue(F f) {
|
2019-09-20 15:06:37 +02:00
|
|
|
switch (valueType) {
|
|
|
|
case ValueType::INT:
|
|
|
|
case ValueType::BUFFER_SIZE:
|
|
|
|
case ValueType::CONTAINER_SIZE: {
|
|
|
|
f(intvalue);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ValueType::FLOAT: {
|
|
|
|
f(floatValue);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ValueType::UNINIT:
|
|
|
|
case ValueType::TOK:
|
|
|
|
case ValueType::LIFETIME:
|
|
|
|
case ValueType::MOVED:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-05 15:15:58 +02:00
|
|
|
bool operator==(const Value &rhs) const {
|
|
|
|
if (!equalValue(rhs))
|
|
|
|
return false;
|
2016-11-13 22:33:39 +01:00
|
|
|
|
|
|
|
return varvalue == rhs.varvalue &&
|
2016-08-15 14:19:35 +02:00
|
|
|
condition == rhs.condition &&
|
|
|
|
varId == rhs.varId &&
|
|
|
|
conditional == rhs.conditional &&
|
|
|
|
defaultArg == rhs.defaultArg &&
|
2019-08-17 07:36:41 +02:00
|
|
|
indirect == rhs.indirect &&
|
2016-08-15 14:19:35 +02:00
|
|
|
valueKind == rhs.valueKind;
|
|
|
|
}
|
|
|
|
|
2019-09-05 15:15:58 +02:00
|
|
|
bool operator!=(const Value &rhs) const {
|
|
|
|
return !(*this == rhs);
|
|
|
|
}
|
|
|
|
|
2019-09-20 15:07:27 +02:00
|
|
|
void decreaseRange() {
|
2019-09-20 15:06:37 +02:00
|
|
|
if (bound == Bound::Lower)
|
|
|
|
visitValue(increment{});
|
|
|
|
else if (bound == Bound::Upper)
|
|
|
|
visitValue(decrement{});
|
|
|
|
}
|
|
|
|
|
2019-09-20 15:07:27 +02:00
|
|
|
void invertRange() {
|
2019-09-20 15:06:37 +02:00
|
|
|
if (bound == Bound::Lower)
|
|
|
|
bound = Bound::Upper;
|
|
|
|
else if (bound == Bound::Upper)
|
|
|
|
bound = Bound::Lower;
|
|
|
|
decreaseRange();
|
|
|
|
}
|
|
|
|
|
2017-05-19 16:32:58 +02:00
|
|
|
std::string infoString() const;
|
|
|
|
|
2019-03-17 13:09:15 +01:00
|
|
|
enum ValueType { INT, TOK, FLOAT, MOVED, UNINIT, CONTAINER_SIZE, LIFETIME, BUFFER_SIZE } valueType;
|
2016-11-13 22:33:39 +01:00
|
|
|
bool isIntValue() const {
|
2019-07-10 14:04:56 +02:00
|
|
|
return valueType == ValueType::INT;
|
2016-11-13 22:33:39 +01:00
|
|
|
}
|
|
|
|
bool isTokValue() const {
|
2019-07-10 14:04:56 +02:00
|
|
|
return valueType == ValueType::TOK;
|
2016-11-13 22:33:39 +01:00
|
|
|
}
|
2016-11-13 22:59:56 +01:00
|
|
|
bool isFloatValue() const {
|
2019-07-10 14:04:56 +02:00
|
|
|
return valueType == ValueType::FLOAT;
|
2016-11-13 22:59:56 +01:00
|
|
|
}
|
2016-11-20 15:14:49 +01:00
|
|
|
bool isMovedValue() const {
|
2019-07-10 14:04:56 +02:00
|
|
|
return valueType == ValueType::MOVED;
|
2016-11-20 15:14:49 +01:00
|
|
|
}
|
2017-04-23 18:05:14 +02:00
|
|
|
bool isUninitValue() const {
|
2019-07-10 14:04:56 +02:00
|
|
|
return valueType == ValueType::UNINIT;
|
2017-04-23 18:05:14 +02:00
|
|
|
}
|
2018-08-10 11:29:16 +02:00
|
|
|
bool isContainerSizeValue() const {
|
2019-07-10 14:04:56 +02:00
|
|
|
return valueType == ValueType::CONTAINER_SIZE;
|
2018-08-10 11:29:16 +02:00
|
|
|
}
|
2018-11-10 16:40:40 +01:00
|
|
|
bool isLifetimeValue() const {
|
2019-07-10 14:04:56 +02:00
|
|
|
return valueType == ValueType::LIFETIME;
|
2018-11-10 16:40:40 +01:00
|
|
|
}
|
2019-03-17 13:09:15 +01:00
|
|
|
bool isBufferSizeValue() const {
|
2019-07-10 14:04:56 +02:00
|
|
|
return valueType == ValueType::BUFFER_SIZE;
|
2019-03-17 13:09:15 +01:00
|
|
|
}
|
2016-11-13 22:33:39 +01:00
|
|
|
|
2019-01-29 09:48:18 +01:00
|
|
|
bool isLocalLifetimeValue() const {
|
2019-07-16 11:12:35 +02:00
|
|
|
return valueType == ValueType::LIFETIME && lifetimeScope == LifetimeScope::Local;
|
2019-01-29 09:48:18 +01:00
|
|
|
}
|
2019-01-29 09:47:52 +01:00
|
|
|
|
2019-01-29 09:48:18 +01:00
|
|
|
bool isArgumentLifetimeValue() const {
|
2019-07-16 11:12:35 +02:00
|
|
|
return valueType == ValueType::LIFETIME && lifetimeScope == LifetimeScope::Argument;
|
2019-01-29 09:48:18 +01:00
|
|
|
}
|
2019-01-29 09:47:52 +01:00
|
|
|
|
2019-08-16 07:48:54 +02:00
|
|
|
bool isNonValue() const {
|
|
|
|
return isMovedValue() || isUninitValue() || isLifetimeValue();
|
|
|
|
}
|
|
|
|
|
2019-09-20 15:06:37 +02:00
|
|
|
/** The value bound */
|
|
|
|
enum class Bound { Upper, Lower, Point } bound;
|
|
|
|
|
2014-01-18 19:30:44 +01:00
|
|
|
/** int value */
|
2014-04-02 20:09:53 +02:00
|
|
|
long long intvalue;
|
2014-01-18 19:30:44 +01:00
|
|
|
|
2014-08-03 20:11:22 +02:00
|
|
|
/** token value - the token that has the value. this is used for pointer aliases, strings, etc. */
|
|
|
|
const Token *tokvalue;
|
|
|
|
|
2016-11-13 22:59:56 +01:00
|
|
|
/** float value */
|
|
|
|
double floatValue;
|
|
|
|
|
2016-11-20 15:14:49 +01:00
|
|
|
/** kind of moved */
|
2019-07-10 15:27:07 +02:00
|
|
|
enum class MoveKind {NonMovedVariable, MovedVariable, ForwardedVariable} moveKind;
|
2016-11-20 15:14:49 +01:00
|
|
|
|
2014-01-20 21:45:30 +01:00
|
|
|
/** For calculated values - variable value that calculated value depends on */
|
2014-04-02 20:09:53 +02:00
|
|
|
long long varvalue;
|
|
|
|
|
2017-05-16 22:38:13 +02:00
|
|
|
/** Condition that this value depends on */
|
2014-05-19 14:37:54 +02:00
|
|
|
const Token *condition;
|
|
|
|
|
2017-05-16 22:38:13 +02:00
|
|
|
ErrorPath errorPath;
|
2017-05-15 20:05:11 +02:00
|
|
|
|
2014-05-19 14:37:54 +02:00
|
|
|
/** For calculated values - varId that calculated value depends on */
|
2019-07-15 13:47:17 +02:00
|
|
|
nonneg int varId;
|
2014-05-19 14:37:54 +02:00
|
|
|
|
2019-07-25 17:19:51 +02:00
|
|
|
/** value relies on safe checking */
|
|
|
|
bool safe;
|
|
|
|
|
2014-04-02 20:09:53 +02:00
|
|
|
/** Conditional value */
|
|
|
|
bool conditional;
|
|
|
|
|
2015-02-01 15:23:15 +01:00
|
|
|
/** Is this value passed as default parameter to the function? */
|
2015-02-01 15:05:00 +01:00
|
|
|
bool defaultArg;
|
2018-11-10 21:30:01 +01:00
|
|
|
|
2019-08-17 07:36:41 +02:00
|
|
|
int indirect;
|
|
|
|
|
2019-07-16 10:51:07 +02:00
|
|
|
enum class LifetimeKind {Object, Lambda, Iterator, Address} lifetimeKind;
|
2015-07-16 17:33:16 +02:00
|
|
|
|
2019-07-16 11:12:35 +02:00
|
|
|
enum class LifetimeScope { Local, Argument } lifetimeScope;
|
2019-01-29 09:47:52 +01:00
|
|
|
|
2016-11-20 15:14:49 +01:00
|
|
|
static const char * toString(MoveKind moveKind) {
|
|
|
|
switch (moveKind) {
|
2019-07-10 15:27:07 +02:00
|
|
|
case MoveKind::NonMovedVariable:
|
2016-12-12 14:29:27 +01:00
|
|
|
return "NonMovedVariable";
|
2019-07-10 15:27:07 +02:00
|
|
|
case MoveKind::MovedVariable:
|
2016-11-20 15:14:49 +01:00
|
|
|
return "MovedVariable";
|
2019-07-10 15:27:07 +02:00
|
|
|
case MoveKind::ForwardedVariable:
|
2016-11-20 15:14:49 +01:00
|
|
|
return "ForwardedVariable";
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2015-07-16 17:33:16 +02:00
|
|
|
/** How known is this value */
|
2018-12-31 17:05:46 +01:00
|
|
|
enum class ValueKind {
|
2015-07-16 17:33:16 +02:00
|
|
|
/** This value is possible, other unlisted values may also be possible */
|
|
|
|
Possible,
|
|
|
|
/** Only listed values are possible */
|
2017-09-20 22:41:36 +02:00
|
|
|
Known,
|
|
|
|
/** Inconclusive */
|
2019-09-20 15:06:37 +02:00
|
|
|
Inconclusive,
|
|
|
|
/** Listed values are impossible */
|
|
|
|
Impossible
|
2015-07-16 17:33:16 +02:00
|
|
|
} valueKind;
|
2015-07-25 19:36:29 +02:00
|
|
|
|
|
|
|
void setKnown() {
|
|
|
|
valueKind = ValueKind::Known;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isKnown() const {
|
|
|
|
return valueKind == ValueKind::Known;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setPossible() {
|
|
|
|
valueKind = ValueKind::Possible;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isPossible() const {
|
|
|
|
return valueKind == ValueKind::Possible;
|
|
|
|
}
|
|
|
|
|
2019-09-20 15:07:27 +02:00
|
|
|
bool isImpossible() const {
|
|
|
|
return valueKind == ValueKind::Impossible;
|
|
|
|
}
|
2019-09-20 15:06:37 +02:00
|
|
|
|
2019-09-20 15:07:27 +02:00
|
|
|
void setImpossible() {
|
|
|
|
valueKind = ValueKind::Impossible;
|
|
|
|
}
|
2019-09-20 15:06:37 +02:00
|
|
|
|
2017-09-20 22:41:36 +02:00
|
|
|
void setInconclusive(bool inconclusive = true) {
|
|
|
|
if (inconclusive)
|
|
|
|
valueKind = ValueKind::Inconclusive;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isInconclusive() const {
|
|
|
|
return valueKind == ValueKind::Inconclusive;
|
|
|
|
}
|
|
|
|
|
2015-07-25 19:36:29 +02:00
|
|
|
void changeKnownToPossible() {
|
|
|
|
if (isKnown())
|
|
|
|
valueKind = ValueKind::Possible;
|
|
|
|
}
|
2017-05-23 11:43:56 +02:00
|
|
|
|
|
|
|
bool errorSeverity() const {
|
|
|
|
return !condition && !defaultArg;
|
|
|
|
}
|
2014-01-04 20:57:02 +01:00
|
|
|
};
|
|
|
|
|
2016-05-07 20:18:07 +02:00
|
|
|
/// Constant folding of expression. This can be used before the full ValueFlow has been executed (ValueFlow::setValues).
|
2019-06-16 10:09:38 +02:00
|
|
|
const ValueFlow::Value * valueFlowConstantFoldAST(Token *expr, const Settings *settings);
|
2016-05-07 20:18:07 +02:00
|
|
|
|
|
|
|
/// Perform valueflow analysis.
|
2015-02-01 12:10:20 +01:00
|
|
|
void setValues(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings);
|
2015-07-29 19:54:57 +02:00
|
|
|
|
|
|
|
std::string eitherTheConditionIsRedundant(const Token *condition);
|
Set correct type and size of string and char literals (#2275)
* Set correct type and size of string and char literals
Use that string and char literal tokens store the prefix. This makes
it possible to distinghuish between different type of string literals
(i.e., utf8 encoded strings, utf16, wide strings, etc) which have
different type.
When the tokens holding the string and character values have the correct
type, it is possible to improve Token::getStrSize() to give the correct
result for all string types. Previously, it would return the number of
characters in the string, i.e., it would give the wrong size unless
the type of the string was char*.
Since strings now can have different size (in number of bytes) and
length (in number of elements), add a new helper function that returns
the number of characters. Checkers have been updated to use the correct
functions.
Having the size makes it possible to find more problems with prefixed
strings, and to reduce false positives, for example in the buffer
overflow checker.
Also, improve the stringLiteralWrite error message to also print the
prefix of the string (if there is one).
* Add comment and update string length
2019-10-20 07:11:57 +02:00
|
|
|
|
|
|
|
size_t getSizeOf(const ValueType &vt, const Settings *settings);
|
2014-01-04 20:57:02 +01:00
|
|
|
}
|
|
|
|
|
2019-09-11 19:25:09 +02:00
|
|
|
struct LifetimeToken {
|
|
|
|
const Token* token;
|
|
|
|
bool addressOf;
|
|
|
|
ValueFlow::Value::ErrorPath errorPath;
|
|
|
|
bool inconclusive;
|
|
|
|
|
|
|
|
LifetimeToken() : token(nullptr), addressOf(false), errorPath(), inconclusive(false) {}
|
|
|
|
|
|
|
|
LifetimeToken(const Token* token, ValueFlow::Value::ErrorPath errorPath)
|
|
|
|
: token(token), addressOf(false), errorPath(std::move(errorPath)), inconclusive(false)
|
|
|
|
{}
|
|
|
|
|
|
|
|
LifetimeToken(const Token* token, bool addressOf, ValueFlow::Value::ErrorPath errorPath)
|
|
|
|
: token(token), addressOf(addressOf), errorPath(std::move(errorPath)), inconclusive(false)
|
|
|
|
{}
|
|
|
|
|
|
|
|
static std::vector<LifetimeToken> setAddressOf(std::vector<LifetimeToken> v, bool b) {
|
|
|
|
for (LifetimeToken& x : v)
|
|
|
|
x.addressOf = b;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::vector<LifetimeToken> setInconclusive(std::vector<LifetimeToken> v, bool b) {
|
|
|
|
for (LifetimeToken& x : v)
|
|
|
|
x.inconclusive = b;
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<LifetimeToken> getLifetimeTokens(const Token* tok, ValueFlow::Value::ErrorPath errorPath = ValueFlow::Value::ErrorPath{}, int depth = 20);
|
|
|
|
|
2019-09-02 06:58:09 +02:00
|
|
|
const Variable* getLifetimeVariable(const Token* tok, ValueFlow::Value::ErrorPath& errorPath, bool* addressOf = nullptr);
|
2019-01-23 07:29:16 +01:00
|
|
|
|
2019-05-05 11:40:59 +02:00
|
|
|
bool isLifetimeBorrowed(const Token *tok, const Settings *settings);
|
|
|
|
|
2019-01-29 09:47:52 +01:00
|
|
|
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val);
|
|
|
|
|
2019-07-18 10:56:44 +02:00
|
|
|
std::string lifetimeMessage(const Token *tok, const ValueFlow::Value *val, ValueFlow::Value::ErrorPath &errorPath);
|
|
|
|
|
2019-05-31 11:16:04 +02:00
|
|
|
ValueFlow::Value getLifetimeObjValue(const Token *tok);
|
|
|
|
|
2014-01-04 20:57:02 +01:00
|
|
|
#endif // valueflowH
|