70 const std::list<ValueFlow::Value> &tokenValues = tok->
values();
72 return it == tokenValues.cend() ? nullptr : &*it;
77 if (formatStringArgNr <= 0 || formatStringArgNr > parameters.size())
79 if (parameters[formatStringArgNr - 1]->tokType() !=
Token::eString)
81 const std::string &formatString = parameters[formatStringArgNr - 1]->str();
82 bool percentCharFound =
false;
83 int outputStringSize = 0;
84 bool handleNextParameter =
false;
85 std::string digits_string;
86 bool i_d_x_f_found =
false;
87 int parameterLength = 0;
88 int inputArgNr = formatStringArgNr;
89 for (
int i = 1; i + 1 < formatString.length(); ++i) {
90 if (formatString[i] ==
'\\') {
91 if (i < formatString.length() - 1 && formatString[i + 1] ==
'0')
99 if (percentCharFound) {
100 switch (formatString[i]) {
105 i_d_x_f_found =
true;
106 handleNextParameter =
true;
117 handleNextParameter =
true;
121 i_d_x_f_found =
true;
123 if (inputArgNr < parameters.size() && parameters[inputArgNr]->hasKnownIntValue())
124 parameterLength = std::to_string(parameters[inputArgNr]->getKnownIntValue()).length();
126 handleNextParameter =
true;
130 if (inputArgNr < parameters.size() && parameters[inputArgNr]->tokType() ==
Token::eString)
133 handleNextParameter =
true;
138 if (formatString[i] ==
'%')
139 percentCharFound = !percentCharFound;
140 else if (percentCharFound) {
141 digits_string.append(1, formatString[i]);
144 if (!percentCharFound)
147 if (handleNextParameter) {
149 int tempDigits = std::abs(std::atoi(digits_string.c_str()));
151 tempDigits = std::max(tempDigits, 1);
153 if (digits_string.find(
'.') != std::string::npos) {
154 const std::string endStr = digits_string.substr(digits_string.find(
'.') + 1);
156 const int maxLen = std::max(std::abs(std::atoi(endStr.c_str())), 1);
158 if (formatString[i] ==
's') {
161 if (parameterLength > maxLen)
162 parameterLength = maxLen;
166 if (tempDigits < maxLen)
171 if (tempDigits < parameterLength)
172 outputStringSize += parameterLength;
174 outputStringSize += tempDigits;
177 digits_string.clear();
178 i_d_x_f_found =
false;
179 percentCharFound =
false;
180 handleNextParameter =
false;
185 return outputStringSize;
192 const Token *array = arrayToken;
197 dimensions = array->
variable()->dimensions();
198 if (dimensions[0].num <= 1 || !dimensions[0].tok) {
200 [&](
const Token *child) {
202 mightBeLarger = true;
203 return ChildrenToVisit::none;
213 dimensions.emplace_back(dim);
227 dimensions.emplace_back(dim);
229 return !dimensions.empty();
240 const Token* arrayToken,
241 const std::vector<Dimension>& dimensions,
242 const std::vector<const Token*>& indexTokens,
245 const Token *array = arrayToken;
249 bool isArrayIndex = tok->
str() ==
"[";
251 const Token* parent = tok;
255 isArrayIndex =
false;
258 bool overflow =
false;
259 std::vector<ValueFlow::Value> indexValues;
260 for (
int i = 0; i < dimensions.size() && i < indexTokens.size(); ++i) {
264 const bool zeroArray = array->
variable() && array->
variable()->isArray() && dimensions[i].num == 0;
265 std::vector<ValueFlow::Value> values = !zeroArray
267 : std::vector<ValueFlow::Value>{};
268 if (values.empty()) {
269 if (indexTokens[i]->hasKnownIntValue())
270 indexValues.push_back(indexTokens[i]->values().front());
276 indexValues.push_back(values.front());
288 if (tok->str() !=
"[")
295 if (!array->
scope()->isExecutable()) {
297 const Token *parent = tok;
300 if (!parent || parent == parent->
astParent()->astOperand1())
307 std::vector<const Token *> indexTokens;
308 for (
const Token *tok2 = tok; tok2 && tok2->
str() ==
"["; tok2 = tok2->link()->next()) {
309 if (!tok2->astOperand2()) {
313 indexTokens.emplace_back(tok2->astOperand2());
315 if (indexTokens.empty())
318 std::vector<Dimension> dimensions;
320 bool mightBeLarger =
false;
328 bool isChanged =
false;
341 if (!mightBeLarger) {
342 const std::vector<ValueFlow::Value>& indexValues =
344 if (!indexValues.empty())
350 std::vector<ValueFlow::Value> negativeIndexes;
351 for (
const Token * indexToken : indexTokens) {
354 negativeIndexes.emplace_back(*negativeValue);
366 static std::string
stringifyIndexes(
const std::string& array,
const std::vector<ValueFlow::Value>& indexValues)
368 if (indexValues.size() == 1)
369 return std::to_string(indexValues[0].intvalue);
371 std::ostringstream ret;
375 if (index.isNonValue())
378 ret << index.intvalue;
385 const std::vector<Dimension>& dimensions,
386 const std::vector<ValueFlow::Value>& indexValues,
387 const Token* condition)
389 auto add_dim = [](
const std::string &s,
const Dimension &dim) {
390 return s +
"[" + std::to_string(dim.num) +
"]";
392 const std::string array = std::accumulate(dimensions.cbegin(), dimensions.cend(), tok->
astOperand1()->expressionString(), std::move(add_dim));
394 std::ostringstream errmsg;
397 <<
" or the array '" << array <<
"' is accessed at index " <<
stringifyIndexes(tok->
astOperand1()->expressionString(), indexValues) <<
", which is out of bounds.";
399 errmsg <<
"Array '" << array <<
"' accessed at index " <<
stringifyIndexes(tok->
astOperand1()->expressionString(), indexValues) <<
", which is out of bounds.";
405 const std::vector<Dimension>& dimensions,
406 const std::vector<ValueFlow::Value>& indexes)
414 const Token *condition =
nullptr;
419 if (indexValue.condition)
420 condition = indexValue.condition;
421 if (!index || !indexValue.
errorPath.empty())
427 index->
condition ?
"arrayIndexOutOfBoundsCond" :
"arrayIndexOutOfBounds",
434 const std::vector<Dimension>& dimensions,
435 const std::vector<ValueFlow::Value>& indexes)
442 const Token *condition =
nullptr;
447 if (indexValue.condition)
448 condition = indexValue.condition;
449 if (!negativeValue || !indexValue.
errorPath.empty())
450 negativeValue = &indexValue;
468 logChecker(
"CheckBufferOverrun::pointerArithmetic");
473 if (!tok->valueType() || tok->valueType()->pointer == 0)
475 if (!tok->isBinaryOp())
477 if (!tok->astOperand1()->valueType() || !tok->astOperand2()->valueType())
480 const Token *arrayToken, *indexToken;
481 if (tok->astOperand1()->valueType()->pointer > 0) {
492 std::vector<Dimension> dimensions;
494 bool mightBeLarger =
false;
499 if (tok->str() ==
"+") {
501 if (!mightBeLarger) {
502 const std::vector<const Token *> indexTokens{indexToken};
503 const std::vector<ValueFlow::Value>& indexValues =
505 if (!indexValues.empty())
511 }
else if (tok->str() ==
"-") {
515 const Token *array = arrayToken;
537 errmsg =
"Undefined behaviour, when '" + indexToken->
expressionString() +
"' is " + std::to_string(indexValue->
intvalue) +
" the pointer arithmetic '" + tok->
expressionString() +
"' is out of bounds.";
539 errmsg =
"Undefined behaviour, pointer arithmetic '" + tok->
expressionString() +
"' is out of bounds.";
543 indexValue->
condition ?
"pointerOutOfBoundsCond" :
"pointerOutOfBounds",
589 const Token *
const arg = (minsize.
arg > 0 && minsize.
arg - 1 < args.size()) ? args[minsize.
arg - 1] :
nullptr;
590 const Token *
const arg2 = (minsize.
arg2 > 0 && minsize.
arg2 - 1 < args.size()) ? args[minsize.
arg2 - 1] :
nullptr;
592 switch (minsize.
type) {
607 myMinsize *= baseSize;
608 return myMinsize <= bufferSize;
623 myMinsize *= baseSize;
624 return myMinsize <= bufferSize;
635 logChecker(
"CheckBufferOverrun::bufferOverflow");
644 const std::vector<const Token *> args =
getArguments(tok);
645 for (
int argnr = 0; argnr < args.size(); ++argnr) {
646 if (!args[argnr]->valueType() || args[argnr]->valueType()->pointer == 0)
649 if (!minsizes || minsizes->empty())
652 const Token *argtok = args[argnr];
653 while (argtok && argtok->
isCast())
667 const Token *tok2 = argtok;
681 return checkBufferSize(tok, minsize, args, bufferSize.intvalue, *mSettings, mTokenizer);
702 logChecker(
"CheckBufferOverrun::arrayIndexThenCheck");
708 tok = tok->linkAt(1);
715 const int indexID = tok->next()->varId();
716 const std::string& indexName(tok->strAt(1));
719 const Token* tok2 = tok;
720 const Token* tok3 = tok2;
734 else if (
Token::Match(tok2,
"&& (| %any% >|>= %varid% !!+", indexID))
744 "$symbol:" + indexName +
"\n"
745 "Array index '$symbol' is used before limits check.\n"
746 "Defensive programming: The variable '$symbol' is used as an array index before it "
747 "is checked that is within limits. This can mean that the array might be accessed out of bounds. "
748 "Reorder conditions such as '(a[i] && i < 10)' to '(i < 10 && a[i])'. That way the array will "
760 logChecker(
"CheckBufferOverrun::stringNotZeroTerminated");
767 const std::vector<const Token *> args =
getArguments(tok);
768 if (args.size() != 3)
770 const Token *sizeToken = args[2];
777 const std::list<ValueFlow::Value>& contValues = args[1]->astOperand1()->astOperand1()->values();
778 auto it = std::find_if(contValues.cbegin(), contValues.cend(), [](
const ValueFlow::Value& value) {
779 return value.isContainerSizeValue() && !value.isImpossible();
789 bool isZeroTerminated =
false;
797 isZeroTerminated =
true;
799 if (isZeroTerminated)
809 const std::string shortMessage =
"The buffer '$symbol' may not be null-terminated after the call to strncpy().";
811 "$symbol:" + varname +
'\n' +
812 shortMessage +
'\n' +
814 "If the source string's size fits or exceeds the given size, strncpy() does not add a "
815 "zero at the end of the buffer. This causes bugs later in the code if the code "
826 logChecker(
"CheckBufferOverrun::argumentSize");
835 const Function *callfunc = tok->function();
836 const std::vector<const Token *> callargs =
getArguments(tok);
837 for (
nonneg int paramIndex = 0; paramIndex < callargs.size() && paramIndex < callfunc->argCount(); ++paramIndex) {
841 if (!argument->
valueType() || !callargs[paramIndex]->valueType())
843 if (argument->
valueType()->
type != callargs[paramIndex]->valueType()->type)
845 const Token * calldata = callargs[paramIndex];
853 for (
int d = 0; d < argument->
dimensions().size(); ++d) {
854 const auto& dim1 = calldata->
variable()->dimensions()[d];
856 if (!dim1.known || !dim2.known)
858 if (dim1.num < dim2.num)
862 argumentSizeError(tok, tok->str(), paramIndex, callargs[paramIndex]->expressionString(), calldata->
variable(), argument);
870 const std::string strParamNum = std::to_string(paramIndex + 1) +
getOrdinalText(paramIndex + 1);
872 errorPath.emplace_back(tok,
"Function '" + functionName +
"' is called");
874 errorPath.emplace_back(functionArg->
nameToken(),
"Declaration of " + strParamNum +
" function argument.");
876 errorPath.emplace_back(paramVar->
nameToken(),
"Passing buffer '" + paramVar->
name() +
"' to function that is declared here");
877 errorPath.emplace_back(tok,
"");
880 "$symbol:" + functionName +
'\n' +
881 "Buffer '" + paramExpression +
"' is too small, the function '" + functionName +
"' expects a bigger buffer in " + strParamNum +
" argument",
CWE_ARGUMENT_SIZE,
Certainty::normal);
891 inline namespace CheckBufferOverrun_internal
900 std::list<CTU::FileInfo::UnsafeUsage> unsafeArrayIndex;
903 std::list<CTU::FileInfo::UnsafeUsage> unsafePointerArith;
906 std::string
toString()
const override
909 if (!unsafeArrayIndex.empty())
910 xml =
" <array-index>\n" +
CTU::toString(unsafeArrayIndex) +
" </array-index>\n";
911 if (!unsafePointerArith.empty())
912 xml +=
" <pointer-arith>\n" +
CTU::toString(unsafePointerArith) +
" </pointer-arith>\n";
924 const Token *indexTok =
nullptr;
928 indexTok = (argtok == argtok->
astParent()->astOperand1()) ?
954 if (unsafeArrayIndex.empty() && unsafePointerArith.empty()) {
957 auto *fileInfo =
new MyFileInfo;
958 fileInfo->unsafeArrayIndex = unsafeArrayIndex;
959 fileInfo->unsafePointerArith = unsafePointerArith;
967 const std::string pointerArith(
"pointer-arith");
969 auto *fileInfo =
new MyFileInfo;
970 for (
const tinyxml2::XMLElement *e = xmlElement->FirstChildElement(); e; e = e->NextSiblingElement()) {
973 else if (e->Name() == pointerArith)
977 if (fileInfo->unsafeArrayIndex.empty() && fileInfo->unsafePointerArith.empty()) {
990 bool foundErrors =
false;
995 logChecker(
"CheckBufferOverrun::analyseWholeProgram");
997 const std::map<std::string, std::list<const CTU::FileInfo::CallBase *>> callsMap = ctu->
getCallsMap();
1000 const MyFileInfo *fi =
dynamic_cast<const MyFileInfo*
>(fi1);
1015 const std::list<ErrorMessage::FileLocation> &locationList =
1019 "Using argument ARG",
1022 if (locationList.empty())
1025 const char *errorId =
nullptr;
1030 errorId =
"ctuArrayIndex";
1031 if (unsafeUsage.
value > 0)
1032 errmsg =
"Array index out of bounds; '" + unsafeUsage.
myArgumentName +
"' buffer size is " + std::to_string(functionCall->
callArgValue) +
" and it is accessed at offset " + std::to_string(unsafeUsage.
value) +
".";
1034 errmsg =
"Array index out of bounds; buffer '" + unsafeUsage.
myArgumentName +
"' is accessed at offset " + std::to_string(unsafeUsage.
value) +
".";
1037 errorId =
"ctuPointerArith";
1038 errmsg =
"Pointer arithmetic overflow; '" + unsafeUsage.
myArgumentName +
"' buffer size is " + std::to_string(functionCall->
callArgValue);
1055 logChecker(
"CheckBufferOverrun::objectIndex");
1076 const Variable *var = v.tokvalue->variable();
1103 std::vector<ValueFlow::Value> idxValues;
1104 std::copy_if(idx->
values().cbegin(),
1106 std::back_inserter(idxValues),
1108 if (!vidx.isIntValue())
1110 return vidx.path == v.path || vidx.path == 0;
1112 if (std::any_of(idxValues.cbegin(), idxValues.cend(), [&](
const ValueFlow::Value& vidx) {
1113 if (vidx.isImpossible())
1114 return (vidx.intvalue == 0);
1115 return (vidx.intvalue != 0);
1138 errorPath.emplace_back(tok,
"");
1139 std::string verb = known ?
"is" :
"might be";
1143 "The address of variable '" +
name +
"' " + verb +
" accessed at non-zero index.",
1152 if (tok->
varId() != 0U)
1154 if (tok->
str() ==
"?") {
1166 logChecker(
"CheckBufferOverrun::negativeArraySize");
1169 if (!var || !var->isArray())
1171 const Token*
const nameToken = var->nameToken();
1182 if (!tok->isKeyword() || tok->str() !=
"new" || !tok->astOperand1() || tok->astOperand1()->str() !=
"[")
1196 const std::string arrayName = tok ? tok->
expressionString() : std::string();
1197 const std::string line1 = arrayName.empty() ? std::string() : (
"$symbol:" + arrayName +
'\n');
1200 "Declaration of array '" + arrayName +
"' with negative size is undefined behaviour",
CWE758,
Certainty::normal);
1205 const std::string msg =
"Memory allocation size is negative.";
bool astIsContainer(const Token *tok)
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Settings &settings, bool pure, bool followVar, ErrorPath *errors)
Token * findVariableChanged(Token *start, const Token *end, int indirect, const nonneg int exprid, bool globalvar, const Settings &settings, int depth)
bool isCPPCast(const Token *tok)
void visitAstNodes(T *ast, const TFunc &visitor)
Visit AST nodes recursively.
static bool isVLAIndex(const Token *tok)
static bool getDimensionsEtc(const Token *const arrayToken, const Settings &settings, std::vector< Dimension > &dimensions, ErrorPath &errorPath, bool &mightBeLarger, MathLib::bigint &path)
static const CWE CWE_BUFFER_UNDERRUN(786U)
static const CWE CWE_ARGUMENT_SIZE(398U)
static std::string stringifyIndexes(const std::string &array, const std::vector< ValueFlow::Value > &indexValues)
static const CWE CWE758(758U)
static const ValueFlow::Value * getBufferSizeValue(const Token *tok)
static const CWE CWE_BUFFER_OVERRUN(788U)
static const CWE CWE_POINTER_ARITHMETIC_OVERFLOW(758U)
static std::vector< ValueFlow::Value > getOverrunIndexValues(const Token *tok, const Token *arrayToken, const std::vector< Dimension > &dimensions, const std::vector< const Token * > &indexTokens, MathLib::bigint path)
static ValueFlow::Value makeSizeValue(MathLib::bigint size, MathLib::bigint path)
static const CWE CWE170(170U)
static const CWE CWE_ARRAY_INDEX_THEN_CHECK(398U)
static const CWE CWE131(131U)
static int getMinFormatStringOutputLength(const std::vector< const Token * > ¶meters, nonneg int formatStringArgNr)
static std::string arrayIndexMessage(const Token *tok, const std::vector< Dimension > &dimensions, const std::vector< ValueFlow::Value > &indexValues, const Token *condition)
static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::MinSize &minsize, const std::vector< const Token * > &args, const MathLib::bigint bufferSize, const Settings &settings, const Tokenizer *tokenizer)
MathLib::bigint callArgValue
static std::list< ErrorMessage::FileLocation > getErrorPath(InvalidValueType invalidValue, const UnsafeUsage &unsafeUsage, const std::map< std::string, std::list< const CallBase * >> &callsMap, const char info[], const FunctionCall **const functionCallPtr, bool warning)
std::map< std::string, std::list< const CallBase * > > getCallsMap() const
buffer overruns and array index out of bounds
void arrayIndexThenCheckError(const Token *tok, const std::string &indexName)
bool analyseWholeProgram(const CTU::FileInfo *ctu, const std::list< Check::FileInfo * > &fileInfo, const Settings &settings, ErrorLogger &errorLogger) override
Analyse all file infos for all TU.
static bool isCtuUnsafePointerArith(const Settings &settings, const Token *argtok, MathLib::bigint *offset)
static bool isCtuUnsafeBufferUsage(const Settings &settings, const Token *argtok, MathLib::bigint *offset, int type)
static bool isCtuUnsafeArrayIndex(const Settings &settings, const Token *argtok, MathLib::bigint *offset)
void stringNotZeroTerminated()
Check::FileInfo * loadFileInfoFromXml(const tinyxml2::XMLElement *xmlElement) const override
void negativeIndexError(const Token *tok, const std::vector< Dimension > &dimensions, const std::vector< ValueFlow::Value > &indexes)
ValueFlow::Value getBufferSize(const Token *bufTok) const
void pointerArithmeticError(const Token *tok, const Token *indexToken, const ValueFlow::Value *indexValue)
void negativeMemoryAllocationSizeError(const Token *tok, const ValueFlow::Value *value)
void arrayIndexError(const Token *tok, const std::vector< Dimension > &dimensions, const std::vector< ValueFlow::Value > &indexes)
static bool analyseWholeProgram1(const std::map< std::string, std::list< const CTU::FileInfo::CallBase * >> &callsMap, const CTU::FileInfo::UnsafeUsage &unsafeUsage, int type, ErrorLogger &errorLogger)
void arrayIndexThenCheck()
void terminateStrncpyError(const Token *tok, const std::string &varname)
void negativeArraySizeError(const Token *tok)
void argumentSizeError(const Token *tok, const std::string &functionName, nonneg int paramIndex, const std::string ¶mExpression, const Variable *paramVar, const Variable *functionArg)
Check::FileInfo * getFileInfo(const Tokenizer &tokenizer, const Settings &settings) const override
Parse current TU and extract file info.
void bufferOverflowError(const Token *tok, const ValueFlow::Value *value, Certainty certainty)
void objectIndexError(const Token *tok, const ValueFlow::Value *v, bool known)
Base class used for whole-program analysis.
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
const Settings *const mSettings
ErrorPath getErrorPath(const Token *errtok, const ValueFlow::Value *value, std::string bug) const
const Tokenizer *const mTokenizer
void logChecker(const char id[])
log checker
const std::string & name() const
class name, used to generate documentation
This is an interface, which the class responsible of error logging should implement.
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
Wrapper for error messages, provided by reportErr()
const Variable * getArgumentVar(nonneg int num) const
bool hasminsize(const Token *ftok) const
bool isargformatstr(const Token *ftok, int argnr) const
const std::vector< ArgumentChecks::MinSize > * argminsizes(const Token *ftok, int argnr) const
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
This is just a container for general settings so that we don't need to pass individual values to func...
bool isPremiumEnabled(const char id[]) const
Is checker id enabled by premiumArgs.
SimpleEnableGroup< Certainty > certainty
SimpleEnableGroup< Severity > severity
bool isEnabled(T flag) const
const std::vector< const Variable * > & variableList() const
std::vector< const Scope * > functionScopes
Fast access to function scopes.
The token list that the TokenList generates is a linked-list of this class.
bool hasKnownValue() const
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
const std::string & originalName() const
bool hasKnownIntValue() const
MathLib::bigint getKnownIntValue() const
const Token * getValueTokenMaxStrLength() const
const Token * getValueTokenMinStrSize(const Settings &settings, MathLib::bigint *path=nullptr) const
static nonneg int getStrLength(const Token *tok)
const ValueType * valueType() const
void astOperand1(Token *tok)
std::string expressionString() const
bool isUnaryOp(const std::string &s) const
const ValueFlow::Value * getValueGE(const MathLib::bigint val, const Settings &settings) const
static nonneg int getStrArraySize(const Token *tok)
Token::Type tokType() const
void astOperand2(Token *tok)
void scope(const Scope *s)
Associate this token with given scope.
void link(Token *linkToToken)
Create link to given token.
const Token * linkAt(int index) const
const ValueFlow::Value * getValueLE(const MathLib::bigint val, const Settings &settings) const
void variable(const Variable *v)
Associate this token with given variable.
const std::list< ValueFlow::Value > & values() const
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
void astParent(Token *tok)
The main purpose is to tokenize the source code.
nonneg int sizeOfType(const Token *type) const
Calculates sizeof value for given type.
const Token * tokens() const
const SymbolDatabase * getSymbolDatabase() const
enum ValueFlow::Value::ValueType valueType
MathLib::bigint path
Path id.
bool errorSeverity() const
const Token * condition
Condition that this value depends on.
const Token * tokvalue
token value - the token that has the value.
long long intvalue
int value (or sometimes bool value?)
bool isBufferSizeValue() const
bool isInconclusive() const
enum ValueType::Type type
MathLib::bigint typeSize(const Platform &platform, bool p=false) const
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
Information about a member variable.
bool isArgument() const
Is variable a function argument.
bool isReference() const
Is reference variable.
bool isRValueReference() const
Is reference variable.
const Scope * scope() const
Get Scope pointer of enclosing scope.
const std::string & name() const
Get name string.
bool isPointerArray() const
Is variable an array of pointers.
bool isArray() const
Is variable an array.
const Token * nameToken() const
Get name token.
nonneg int declarationId() const
Get declaration ID (varId used for variable in its declaration).
const std::vector< Dimension > & dimensions() const
Get array dimensions.
bool isPointer() const
Is pointer variable.
const ValueType * valueType() const
std::string toString(Color c)
static const std::string emptyString
std::list< ErrorPathItem > ErrorPath
@ portability
Portability warning.
@ error
Programming error.
CPPCHECKLIB std::list< FileInfo::UnsafeUsage > getUnsafeUsage(const Tokenizer &tokenizer, const Settings &settings, bool(*isUnsafeUsage)(const Settings &settings, const Token *argtok, MathLib::bigint *value))
CPPCHECKLIB std::string toString(const std::list< FileInfo::UnsafeUsage > &unsafeUsage)
CPPCHECKLIB std::list< FileInfo::UnsafeUsage > loadUnsafeUsageListFromXml(const tinyxml2::XMLElement *xmlElement)
std::string eitherTheConditionIsRedundant(const Token *condition)
std::vector< Value > isOutOfBounds(const Value &size, const Token *indexTok, bool possible=true)
CPPCHECKLIB std::vector< Value > getLifetimeObjValues(const Token *tok, bool inconclusive=false, MathLib::bigint path=0)
std::string myArgumentName
Array dimension information.
const Token * tok
size token
MathLib::bigint num
(assumed) dimension length when size is a number, 0 if not known
static const char * getOrdinalText(int i)