diff --git a/lib/check64bit.cpp b/lib/check64bit.cpp index ec2897c8d..81fc94610 100644 --- a/lib/check64bit.cpp +++ b/lib/check64bit.cpp @@ -65,11 +65,25 @@ void Check64BitPortability::pointerassignment() continue; for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { - if (Token::Match(tok, "return %var% [;+]")) { - const Variable *var = tok->next()->variable(); - if (retPointer && isint(var)) + if (Token::Match(tok, "return %var%|%num% [;+]")) { + enum { NO, INT, PTR, PTRDIFF } type = NO; + for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { + if ((type == NO || type == INT) && isaddr(tok2->variable())) + type = PTR; + else if (type == NO && (tok2->isNumber() || isint(tok2->variable()))) + type = INT; + else if (type == PTR && Token::Match(tok2, "- %var%") && isaddr(tok2->next()->variable())) + type = PTRDIFF; + else if (Token::Match(tok2, "%type% (")) { + type = NO; + break; + } else if (tok2->str() == ";") + break; + } + + if (retPointer && (type == INT || type == PTRDIFF)) returnIntegerError(tok); - else if (!retPointer && isaddr(var)) + else if (!retPointer && type == PTR) returnPointerError(tok); } } diff --git a/test/test64bit.cpp b/test/test64bit.cpp index 7ad7593c4..2919ddc8f 100644 --- a/test/test64bit.cpp +++ b/test/test64bit.cpp @@ -161,10 +161,20 @@ private: "}\n"); ASSERT_EQUALS("[test.cpp:2]: (portability) Returning an address value in a function with integer return type is not portable.\n", errout.str()); + check("int foo(char* c) {\n" + " return 1+c;\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2]: (portability) Returning an address value in a function with integer return type is not portable.\n", errout.str()); + check("std::string foo(char* c) {\n" " return c;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("int foo(char *a, char *b) {\n" // #4486 + " return a + 1 - b;\n" + "}"); + ASSERT_EQUALS("", errout.str()); } };