Skip to content

Commit b2f6e9e

Browse files
committed
library: improved handling of noreturn. The Tokenizer::isScopeNoReturn will now try to use the library to determine if scope is noreturn.
1 parent 7d23757 commit b2f6e9e

4 files changed

Lines changed: 52 additions & 7 deletions

File tree

lib/library.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Library::Library() : allocid(0)
3333
_dealloc["fclose"] = allocid;
3434
}
3535

36-
Library::Library(const Library &lib) : use(lib.use), ignore(lib.ignore), noreturn(lib.noreturn), allocid(lib.allocid), _alloc(lib._alloc), _dealloc(lib._dealloc)
36+
Library::Library(const Library &lib) : use(lib.use), ignore(lib.ignore), allocid(lib.allocid), _alloc(lib._alloc), _dealloc(lib._dealloc), _noreturn(lib._noreturn)
3737
{
3838

3939
}
@@ -69,9 +69,28 @@ bool Library::load(const char path[])
6969

7070
else if (strcmp(node->Name(),"ignore")==0)
7171
ignore.insert(node->GetText());
72-
else if (strcmp(node->Name(),"noreturn")==0)
73-
noreturn.insert(node->GetText());
74-
else
72+
else if (strcmp(node->Name(),"function")==0) {
73+
const char *name = node->Attribute("name");
74+
if (name == NULL)
75+
return false;
76+
77+
for (const tinyxml2::XMLElement *functionnode = node->FirstChildElement(); functionnode; functionnode = functionnode->NextSiblingElement()) {
78+
if (strcmp(functionnode->Name(),"noreturn")==0)
79+
_noreturn[name] = (strcmp(functionnode->GetText(), "true") == 0);
80+
else if (strcmp(functionnode->Name(),"arg")==0 && functionnode->Attribute("nr") != NULL) {
81+
const int nr = atoi(functionnode->Attribute("nr"));
82+
83+
const char *nullpointer = functionnode->Attribute("nullpointer");
84+
const char *uninitdata = functionnode->Attribute("uninitdata");
85+
const char *uninitderefdata = functionnode->Attribute("uninitderefdata");
86+
87+
functionArgument[name][nr].nullpointer = (nullpointer != NULL);
88+
functionArgument[name][nr].uninitdata = (uninitdata != NULL);
89+
functionArgument[name][nr].uninitderefdata = (uninitderefdata != NULL);
90+
} else
91+
return false;
92+
}
93+
} else
7594
return false;
7695
}
7796
return true;

lib/library.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,31 @@ class CPPCHECKLIB Library {
6060

6161
std::set<std::string> use;
6262
std::set<std::string> ignore;
63-
std::set<std::string> noreturn;
63+
64+
bool isnoreturn(const std::string &name) const {
65+
std::map<std::string,bool>::const_iterator it = _noreturn.find(name);
66+
return (it != _noreturn.end() && it->second);
67+
}
68+
69+
bool isnotnoreturn(const std::string &name) const {
70+
std::map<std::string,bool>::const_iterator it = _noreturn.find(name);
71+
return (it != _noreturn.end() && !it->second);
72+
}
73+
74+
struct Argument {
75+
bool nullpointer;
76+
bool uninitdata;
77+
bool uninitderefdata;
78+
};
79+
80+
// function name, argument nr => argument data
81+
std::map<std::string, std::map<int, Argument> > functionArgument;
6482

6583
private:
6684
int allocid;
6785
std::map<std::string, int> _alloc; // allocation functions
6886
std::map<std::string, int> _dealloc; // deallocation functions
87+
std::map<std::string, bool> _noreturn; // is function noreturn?
6988

7089
int getid(const std::map<std::string,int> &data, const std::string &name) const {
7190
const std::map<std::string,int>::const_iterator it = data.find(name);

lib/tokenize.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7731,7 +7731,7 @@ void Tokenizer::simplifyStd()
77317731

77327732
//---------------------------------------------------------------------------
77337733

7734-
bool Tokenizer::IsScopeNoReturn(const Token *endScopeToken, bool *unknown)
7734+
bool Tokenizer::IsScopeNoReturn(const Token *endScopeToken, bool *unknown) const
77357735
{
77367736
if (unknown)
77377737
*unknown = false;
@@ -7755,6 +7755,13 @@ bool Tokenizer::IsScopeNoReturn(const Token *endScopeToken, bool *unknown)
77557755
while (tok && (Token::Match(tok, "::|.") || tok->isName()))
77567756
tok = tok->previous();
77577757

7758+
if (Token::Match(tok, "[;{}] %var% (")) {
7759+
if (_settings->library.isnoreturn(tok->next()->str()))
7760+
return true;
7761+
if (_settings->library.isnotnoreturn(tok->next()->str()))
7762+
return false;
7763+
}
7764+
77587765
if (Token::Match(tok, "[;{}]")) {
77597766
if (unknown)
77607767
*unknown = true;

lib/tokenize.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class CPPCHECKLIB Tokenizer {
6363
* \param unknown set to true if it's unknown if the scope is noreturn
6464
* \return true if scope ends with a function call that might be 'noreturn'
6565
*/
66-
static bool IsScopeNoReturn(const Token *endScopeToken, bool *unknown = 0);
66+
bool IsScopeNoReturn(const Token *endScopeToken, bool *unknown = 0) const;
6767

6868
/**
6969
* Tokenize code

0 commit comments

Comments
 (0)