Merge pull request #651 from simartin/array_ptr
Properly differentiate arrays of pointers and pointers to arrays.
This commit is contained in:
commit
81a56293ae
|
@ -41,6 +41,13 @@ bool CheckAutoVariables::isPtrArg(const Token *tok)
|
|||
return (var && var->isArgument() && var->isPointer());
|
||||
}
|
||||
|
||||
bool CheckAutoVariables::isArrayArg(const Token *tok)
|
||||
{
|
||||
const Variable *var = tok->variable();
|
||||
|
||||
return (var && var->isArgument() && var->isArray());
|
||||
}
|
||||
|
||||
bool CheckAutoVariables::isRefPtrArg(const Token *tok)
|
||||
{
|
||||
const Variable *var = tok->variable();
|
||||
|
@ -183,7 +190,7 @@ void CheckAutoVariables::autoVariables()
|
|||
errorAutoVariableAssignment(tok->next(), false);
|
||||
}
|
||||
tok = tok->tokAt(4);
|
||||
} else if (Token::Match(tok, "[;{}] %var% [") && Token::Match(tok->linkAt(2), "] = & %var%") && isPtrArg(tok->next()) && isAutoVar(tok->linkAt(2)->tokAt(3))) {
|
||||
} else if (Token::Match(tok, "[;{}] %var% [") && Token::Match(tok->linkAt(2), "] = & %var%") && isArrayArg(tok->next()) && isAutoVar(tok->linkAt(2)->tokAt(3))) {
|
||||
const Token* const varTok = tok->linkAt(2)->tokAt(3);
|
||||
if (checkRvalueExpression(varTok))
|
||||
errorAutoVariableAssignment(tok->next(), false);
|
||||
|
|
|
@ -68,6 +68,7 @@ public:
|
|||
|
||||
private:
|
||||
static bool isPtrArg(const Token *tok);
|
||||
static bool isArrayArg(const Token *tok);
|
||||
static bool isRefPtrArg(const Token *tok);
|
||||
static bool isNonReferenceArg(const Token *tok);
|
||||
static bool isAutoVar(const Token *tok);
|
||||
|
|
|
@ -2382,7 +2382,9 @@ void CheckOther::checkIncompleteArrayFill()
|
|||
continue;
|
||||
|
||||
if (MathLib::toLongNumber(tok->linkAt(1)->strAt(-1)) == var->dimension(0)) {
|
||||
const unsigned int size = _tokenizer->sizeOfType(var->typeStartToken());
|
||||
unsigned int size = _tokenizer->sizeOfType(var->typeStartToken());
|
||||
if (size == 0 && var->typeStartToken()->next()->str() == "*")
|
||||
size = _settings->sizeof_pointer;
|
||||
if ((size != 1 && size != 100 && size != 0) || var->isPointer()) {
|
||||
if (printWarning)
|
||||
incompleteArrayFillError(tok, var->name(), tok->str(), false);
|
||||
|
|
|
@ -72,8 +72,10 @@ void CheckUninitVar::checkScope(const Scope* scope)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (i->isArray()) {
|
||||
if (i->isArray() || i->isPointerToArray()) {
|
||||
const Token *tok = i->nameToken()->next();
|
||||
if (i->isPointerToArray())
|
||||
tok = tok->next();
|
||||
while (Token::simpleMatch(tok->link(), "] ["))
|
||||
tok = tok->link()->next();
|
||||
if (Token::simpleMatch(tok->link(), "] ="))
|
||||
|
|
|
@ -1435,6 +1435,9 @@ const Token * Variable::declEndToken() const
|
|||
|
||||
void Variable::evaluate(const Library* lib)
|
||||
{
|
||||
if (_name)
|
||||
setFlag(fIsArray, arrayDimensions(lib));
|
||||
|
||||
const Token* tok = _start;
|
||||
while (tok && tok->previous() && tok->previous()->isName())
|
||||
tok = tok->previous();
|
||||
|
@ -1448,7 +1451,7 @@ void Variable::evaluate(const Library* lib)
|
|||
else if (tok->str() == "const")
|
||||
setFlag(fIsConst, true);
|
||||
else if (tok->str() == "*") {
|
||||
setFlag(fIsPointer, true);
|
||||
setFlag(fIsPointer, !isArray() || Token::Match(tok->previous(), "( * %name% )"));
|
||||
setFlag(fIsConst, false); // Points to const, isn't necessarily const itself
|
||||
} else if (tok->str() == "&") {
|
||||
if (isReference())
|
||||
|
@ -1470,8 +1473,6 @@ void Variable::evaluate(const Library* lib)
|
|||
while (_end && _end->previous() && _end->str() == "const")
|
||||
_end = _end->previous();
|
||||
|
||||
if (_name)
|
||||
setFlag(fIsArray, arrayDimensions(lib));
|
||||
if (_start) {
|
||||
setFlag(fIsClass, !_start->isStandardType() && !isPointer() && !isReference());
|
||||
setFlag(fIsStlType, Token::simpleMatch(_start, "std ::"));
|
||||
|
|
|
@ -374,7 +374,7 @@ public:
|
|||
* @return true if array, false if not
|
||||
*/
|
||||
bool isArray() const {
|
||||
return getFlag(fIsArray);
|
||||
return getFlag(fIsArray) && !getFlag(fIsPointer);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -385,6 +385,14 @@ public:
|
|||
return getFlag(fIsPointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is variable a pointer to an array
|
||||
* @return true if pointer to array, false otherwise
|
||||
*/
|
||||
bool isPointerToArray() const {
|
||||
return isPointer() && getFlag(fIsArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is array or pointer variable.
|
||||
* @return true if pointer or array, false otherwise
|
||||
|
|
|
@ -6964,12 +6964,6 @@ bool Tokenizer::simplifyRedundantParentheses()
|
|||
ret = true;
|
||||
}
|
||||
|
||||
if (Token::Match(tok->previous(), "%type% ( * %name% ) [") && tok->previous()->isStandardType()) {
|
||||
tok->link()->deleteThis();
|
||||
tok->deleteThis();
|
||||
ret = true;
|
||||
}
|
||||
|
||||
if (Token::Match(tok->previous(), "*|& ( %name% )")) {
|
||||
// We may have a variable declaration looking like "type_name *(var_name)"
|
||||
Token *tok2 = tok->tokAt(-2);
|
||||
|
|
|
@ -328,11 +328,11 @@ private:
|
|||
|
||||
void testautovar11() { // #4641 - fp, assign local struct member address to function parameter
|
||||
check("struct A {\n"
|
||||
" char *data[10];\n"
|
||||
" char (*data)[10];\n"
|
||||
"};\n"
|
||||
"void foo(char** p) {\n"
|
||||
" struct A a = bar();\n"
|
||||
" *p = &a.data[0];\n"
|
||||
" *p = &(*a.data)[0];\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
|
@ -542,13 +542,13 @@ private:
|
|||
" long *pKoeff[256];\n"
|
||||
" delete[] pKoeff;\n"
|
||||
"}");
|
||||
TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", "", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str());
|
||||
|
||||
check("int main() {\n"
|
||||
" long *pKoeff[256];\n"
|
||||
" free (pKoeff);\n"
|
||||
"}");
|
||||
TODO_ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", "", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Deallocation of an auto-variable results in undefined behaviour.\n", errout.str());
|
||||
|
||||
check("void foo() {\n"
|
||||
" const intPtr& intref = Getter();\n"
|
||||
|
|
|
@ -2283,7 +2283,7 @@ private:
|
|||
"{\n"
|
||||
"public:\n"
|
||||
" John() { }\n"
|
||||
" A *a[5];\n"
|
||||
" A (*a)[5];\n"
|
||||
"};");
|
||||
ASSERT_EQUALS("[test.cpp:5]: (warning) Member variable 'John::a' is not initialized in the constructor.\n", errout.str());
|
||||
}
|
||||
|
|
|
@ -5288,7 +5288,7 @@ private:
|
|||
" Foo a[5];\n"
|
||||
" memset(a, 'a', 5);\n"
|
||||
"}");
|
||||
TODO_ASSERT_EQUALS("[test.cpp:3]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*a)'?\n", "", errout.str());
|
||||
TODO_ASSERT_EQUALS("[test.cpp:4]: (warning, inconclusive) Array 'a' is filled incompletely. Did you forget to multiply the size given to 'memset()' with 'sizeof(*a)'?\n", "", errout.str());
|
||||
|
||||
check("void f() {\n"
|
||||
" Foo a[5];\n" // Size of foo is unknown
|
||||
|
|
|
@ -1453,7 +1453,7 @@ private:
|
|||
"type4 t4;";
|
||||
|
||||
// The expected result..
|
||||
const char expected[] = "char * t1 [ 10 ] ; "
|
||||
const char expected[] = "char ( * t1 ) [ 10 ] ; "
|
||||
"char ( * ( * tp1 ) [ 2 ] ) [ 10 ] ; "
|
||||
"char ( & t2 ) [ 10 ] ; "
|
||||
"char ( & t3 ) [ x ] ; "
|
||||
|
|
|
@ -496,14 +496,15 @@ private:
|
|||
|
||||
void test_isVariableDeclarationIdentifiesOfArrayPointers() {
|
||||
reset();
|
||||
givenACodeSampleToTokenize arr("A *a[5];");
|
||||
givenACodeSampleToTokenize arr("A (*a)[5];");
|
||||
bool result = si.isVariableDeclaration(arr.tokens(), vartok, typetok);
|
||||
ASSERT_EQUALS(true, result);
|
||||
ASSERT_EQUALS("a", vartok->str());
|
||||
ASSERT_EQUALS("A", typetok->str());
|
||||
Variable v(vartok, typetok, vartok->previous(), 0, Public, 0, 0, &settings.library);
|
||||
ASSERT(true == v.isArray());
|
||||
ASSERT(true == v.isPointer());
|
||||
ASSERT(false == v.isArray());
|
||||
ASSERT(true == v.isPointerToArray());
|
||||
ASSERT(false == v.isReference());
|
||||
}
|
||||
|
||||
|
|
|
@ -3300,7 +3300,7 @@ private:
|
|||
}
|
||||
|
||||
void removeParentheses18() {
|
||||
ASSERT_EQUALS("float * a [ 2 ] ;", tokenizeAndStringify("float(*a)[2];", false));
|
||||
ASSERT_EQUALS("float ( * a ) [ 2 ] ;", tokenizeAndStringify("float(*a)[2];", false));
|
||||
}
|
||||
|
||||
void removeParentheses19() {
|
||||
|
|
|
@ -641,6 +641,14 @@ private:
|
|||
" return j;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// Ticket #5646
|
||||
checkUninitVar("float foo() {\n"
|
||||
" float source[2] = {3.1, 3.1};\n"
|
||||
" float (*sink)[2] = &source;\n"
|
||||
" return (*sink)[0];\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
// Handling of unknown types. Assume they are POD in C.
|
||||
|
|
|
@ -1977,9 +1977,9 @@ private:
|
|||
|
||||
void varid_pointerToArray() {
|
||||
ASSERT_EQUALS("\n\n##file 0\n"
|
||||
"1: int * a1@1 [ 10 ] ;\n"
|
||||
"1: int ( * a1@1 ) [ 10 ] ;\n"
|
||||
"2: void f1 ( ) {\n"
|
||||
"3: int * a2@2 [ 10 ] ;\n"
|
||||
"3: int ( * a2@2 ) [ 10 ] ;\n"
|
||||
"4: int ( & a3@3 ) [ 10 ] ;\n"
|
||||
"5: }\n"
|
||||
"6: struct A {\n"
|
||||
|
|
Loading…
Reference in New Issue