Fixed #5906 (false negative: 'else if' expression is always false (use library to determine if function is pure))

This commit is contained in:
Aneesh Azhakesan S 2015-01-10 12:21:55 +01:00 committed by Daniel Marjamäki
parent 332254e0af
commit fe5d2fc245
2 changed files with 56 additions and 0 deletions

View File

@ -9210,6 +9210,12 @@ void Tokenizer::simplifyDeclspec()
void Tokenizer::simplifyAttribute() void Tokenizer::simplifyAttribute()
{ {
for (Token *tok = list.front(); tok; tok = tok->next()) { for (Token *tok = list.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "%type% (") && !_settings->library.isNotLibraryFunction(tok)) {
if (_settings->library.functionpure.find(tok->str()) != _settings->library.functionpure.end())
tok->isAttributePure(true);
if (_settings->library.functionconst.find(tok->str()) != _settings->library.functionconst.end())
tok->isAttributeConst(true);
}
while (Token::Match(tok, "__attribute__|__attribute (") && tok->next()->link() && tok->next()->link()->next()) { while (Token::Match(tok, "__attribute__|__attribute (") && tok->next()->link() && tok->next()->link()->next()) {
if (Token::Match(tok->tokAt(2), "( constructor|__constructor__")) { if (Token::Match(tok->tokAt(2), "( constructor|__constructor__")) {
// prototype for constructor is: void func(void); // prototype for constructor is: void func(void);

View File

@ -21,6 +21,7 @@
#include "checkcondition.h" #include "checkcondition.h"
#include "testsuite.h" #include "testsuite.h"
#include <sstream> #include <sstream>
#include <tinyxml2.h>
extern std::ostringstream errout; extern std::ostringstream errout;
@ -319,8 +320,57 @@ private:
" else { if (x & 1); }\n" " else { if (x & 1); }\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 3.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) Expression is always false because 'else if' condition matches previous condition at line 3.\n", errout.str());
check("extern int bar() __attribute__((pure));\n"
"void foo(int x)\n"
"{\n"
" if ( bar() >1 && b) {}\n"
" else if (bar() >1 && b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (style) Expression is always false because 'else if' condition matches previous condition at line 4.\n", errout.str());
checkPureFunction("extern int bar();\n"
"void foo(int x)\n"
"{\n"
" if ( bar() >1 && b) {}\n"
" else if (bar() >1 && b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (style) Expression is always false because 'else if' condition matches previous condition at line 4.\n", errout.str());
} }
void checkPureFunction(const char code[]) {
// Clear the error buffer..
errout.str("");
const char cfg[] = "<?xml version=\"1.0\"?>\n"
"<def>\n"
" <function name=\"bar\"> <pure/> </function>\n"
"</def>";
tinyxml2::XMLDocument xmldoc;
xmldoc.Parse(cfg, sizeof(cfg));
Settings settings;
settings.addEnabled("style");
settings.addEnabled("warning");
settings.library.load(xmldoc);
// Tokenize..
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
CheckCondition checkCondition;
checkCondition.runChecks(&tokenizer, &settings, this);
const std::string str1(tokenizer.tokens()->stringifyList(0,true));
tokenizer.simplifyTokenList2();
const std::string str2(tokenizer.tokens()->stringifyList(0,true));
checkCondition.runSimplifiedChecks(&tokenizer, &settings, this);
// Ensure that the test case is not bad.
if (str1 != str2) {
warnUnsimplified(str1, str2);
}
}
void duplicateIf() { void duplicateIf() {
check("void f(int a, int &b) {\n" check("void f(int a, int &b) {\n"
" if (a) { b = 1; }\n" " if (a) { b = 1; }\n"