Implemented support for 'using namespace std;': Add std:: prefix to names that are known to be in std namespace. Simplify namespace (std::)tr1:: if C++11 flag is set.
This commit is contained in:
parent
ef2395f4e1
commit
e9182f1fcc
|
@ -1727,6 +1727,9 @@ bool Tokenizer::tokenize(std::istream &code,
|
||||||
// remove unnecessary member qualification..
|
// remove unnecessary member qualification..
|
||||||
removeUnnecessaryQualification();
|
removeUnnecessaryQualification();
|
||||||
|
|
||||||
|
// Add std:: in front of std classes, when using namespace std; was given
|
||||||
|
simplifyNamespaceStd();
|
||||||
|
|
||||||
// remove Microsoft MFC..
|
// remove Microsoft MFC..
|
||||||
simplifyMicrosoftMFC();
|
simplifyMicrosoftMFC();
|
||||||
|
|
||||||
|
@ -2698,7 +2701,7 @@ void Tokenizer::setVarId()
|
||||||
(tok->isName() && tok->str().at(tok->str().length()-1U) == ':')) {
|
(tok->isName() && tok->str().at(tok->str().length()-1U) == ':')) {
|
||||||
|
|
||||||
// No variable declarations in sizeof
|
// No variable declarations in sizeof
|
||||||
if (Token::Match(tok->previous(), "sizeof (")) {
|
if (Token::simpleMatch(tok->previous(), "sizeof (")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5889,7 +5892,7 @@ bool Tokenizer::simplifyKnownVariablesGetData(unsigned int varid, Token **_tok2,
|
||||||
Token *tok2 = *_tok2;
|
Token *tok2 = *_tok2;
|
||||||
Token *tok3 = *_tok3;
|
Token *tok3 = *_tok3;
|
||||||
|
|
||||||
if (Token::Match(tok2->tokAt(-2), "for (")) {
|
if (Token::simpleMatch(tok2->tokAt(-2), "for (")) {
|
||||||
// only specific for loops is handled
|
// only specific for loops is handled
|
||||||
if (!Token::Match(tok2, "%varid% = %num% ; %varid% <|<= %num% ; ++| %varid% ++| ) {", varid))
|
if (!Token::Match(tok2, "%varid% = %num% ; %varid% <|<= %num% ; ++| %varid% ++| ) {", varid))
|
||||||
return false;
|
return false;
|
||||||
|
@ -8551,6 +8554,73 @@ void Tokenizer::simplifyBuiltinExpect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Add std:: in front of std classes, when using namespace std; was given
|
||||||
|
void Tokenizer::simplifyNamespaceStd()
|
||||||
|
{
|
||||||
|
if (!isCPP())
|
||||||
|
return;
|
||||||
|
|
||||||
|
static const char* stdTypes_[] = { // Types and objects in std namespace that are neither functions nor templates
|
||||||
|
"string", "wstring",
|
||||||
|
"iostream", "ostream", "ofstream", "ostringstream", "istream", "ifstream", "istringstream", "fstream", "stringstream",
|
||||||
|
"stringbuf", "streambuf", "ios", "filebuf", "ios_base",
|
||||||
|
"exception", "bad_exception",
|
||||||
|
"logic_error", "domain_error", "invalid_argument_", "length_error", "out_of_rage", "runtime_error", "range_error", "overflow_error", "underflow_error",
|
||||||
|
"locale",
|
||||||
|
"cout", "cerr", "clog", "cin",
|
||||||
|
"fpos", "streamoff", "streampos", "streamsize"
|
||||||
|
};
|
||||||
|
static const std::set<std::string> stdTypes(stdTypes_, stdTypes_+sizeof(stdTypes_)/sizeof(*stdTypes_));
|
||||||
|
static const char* stdTemplates_[] = {
|
||||||
|
"basic_string", "bitset", "deque", "list", "map", "multimap", "priority_queue", "queue", "set", "stack", "vector", "pair",
|
||||||
|
"iterator", "iterator_traits"
|
||||||
|
};
|
||||||
|
static const std::set<std::string> stdTemplates(stdTemplates_, stdTemplates_+sizeof(stdTemplates_)/sizeof(*stdTemplates_));
|
||||||
|
static const char* stdFunctions_[] = {
|
||||||
|
"getline",
|
||||||
|
"for_each", "find", "find_if", "find_end", "find_first_of", "adjacent_find", "count", "count_if", "mismatch", "equal", "search", "search_n",
|
||||||
|
"copy", "copy_backward", "swap", "swap_ranges", "iter_swap", "transform", "replace", "replace_if", "replace_copy", "replace_copy_if", "fill", "fill_n", "generate", "generate_n", "remove",
|
||||||
|
"remove_if", "remove_copy", "remove_copy_if", "unique", "unique_copy", "reverse", "reverse_copy", "rotate", "rotate_copy", "random_shuffle", "partition", "stable_partition",
|
||||||
|
"sort", "stable_sort", "partial_sort", "partial_sort_copy", "nth_element", "lower_bound", "upper_bound", "equal_range", "binary_search", "merge", "inplace_merge", "includes",
|
||||||
|
"set_union", "set_intersection", "set_difference", "set_symmetric_difference", "push_heap", "pop_heap", "make_heap", "sort_heap",
|
||||||
|
"min", "max", "min_element", "max_element", "lexicographical_compare", "next_permutation", "prev_permutation",
|
||||||
|
"advance", "back_inserter", "distance", "front_inserter", "inserter",
|
||||||
|
"make_pair"
|
||||||
|
};
|
||||||
|
static const std::set<std::string> stdFunctions(stdFunctions_, stdFunctions_+sizeof(stdFunctions_)/sizeof(*stdFunctions_));
|
||||||
|
|
||||||
|
for (Token* tok = const_cast<Token*>(Token::findsimplematch(list.front(), "using namespace std ;")); tok; tok = tok->next()) {
|
||||||
|
bool insert = false;
|
||||||
|
if (Token::Match(tok, "%var% (") && !Token::Match(tok->previous(), ".|::") && stdFunctions.find(tok->str()) != stdFunctions.end())
|
||||||
|
insert = true;
|
||||||
|
else if (Token::Match(tok, "%var% <") && !Token::Match(tok->previous(), ".|::") && stdTemplates.find(tok->str()) != stdTemplates.end())
|
||||||
|
insert = true;
|
||||||
|
else if (tok->isName() && !Token::Match(tok->next(), "(|<") && !Token::Match(tok->previous(), ".|::") && stdTypes.find(tok->str()) != stdTypes.end())
|
||||||
|
insert = true;
|
||||||
|
|
||||||
|
if (insert) {
|
||||||
|
tok->previous()->insertToken("std");
|
||||||
|
tok->previous()->linenr(tok->linenr()); // For stylistic reasons we put the std:: in the same line as the following token
|
||||||
|
tok->previous()->fileIndex(tok->fileIndex());
|
||||||
|
tok->previous()->insertToken("::");
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (_settings->standards.cpp11 && Token::Match(tok, "!!:: tr1 ::"))
|
||||||
|
tok->next()->str("std");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Token* tok = list.front(); tok; tok = tok->next()) {
|
||||||
|
if (_settings->standards.cpp11 && Token::Match(tok, "std :: tr1 ::"))
|
||||||
|
Token::eraseTokens(tok, tok->tokAt(3));
|
||||||
|
|
||||||
|
else if (Token::Match(tok, "using namespace std ;")) {
|
||||||
|
Token::eraseTokens(tok, tok->tokAt(4));
|
||||||
|
tok->deleteThis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Remove Microsoft MFC 'DECLARE_MESSAGE_MAP()'
|
// Remove Microsoft MFC 'DECLARE_MESSAGE_MAP()'
|
||||||
void Tokenizer::simplifyMicrosoftMFC()
|
void Tokenizer::simplifyMicrosoftMFC()
|
||||||
{
|
{
|
||||||
|
|
|
@ -608,6 +608,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void unnecessaryQualificationError(const Token *tok, const std::string &qualification) const;
|
void unnecessaryQualificationError(const Token *tok, const std::string &qualification) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add std:: in front of std classes, when using namespace std; was given
|
||||||
|
*/
|
||||||
|
void simplifyNamespaceStd();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove Microsoft MFC 'DECLARE_MESSAGE_MAP()'
|
* Remove Microsoft MFC 'DECLARE_MESSAGE_MAP()'
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2316,7 +2316,7 @@ private:
|
||||||
{
|
{
|
||||||
const char code[] = "using namespace std; namespace a{ namespace b{ void f(){} } }";
|
const char code[] = "using namespace std; namespace a{ namespace b{ void f(){} } }";
|
||||||
|
|
||||||
const std::string expected("using namespace std ; namespace a { namespace b { void f ( ) { } } }");
|
const std::string expected("namespace a { namespace b { void f ( ) { } } }");
|
||||||
|
|
||||||
ASSERT_EQUALS(expected, tok(code));
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
}
|
}
|
||||||
|
|
|
@ -387,6 +387,8 @@ private:
|
||||||
TEST_CASE(bitfields12); // ticket #3485 (segmentation fault)
|
TEST_CASE(bitfields12); // ticket #3485 (segmentation fault)
|
||||||
TEST_CASE(bitfields13); // ticket #3502 (segmentation fault)
|
TEST_CASE(bitfields13); // ticket #3502 (segmentation fault)
|
||||||
|
|
||||||
|
TEST_CASE(simplifyNamespaceStd);
|
||||||
|
|
||||||
TEST_CASE(microsoftMFC);
|
TEST_CASE(microsoftMFC);
|
||||||
TEST_CASE(microsoftMemory);
|
TEST_CASE(microsoftMemory);
|
||||||
|
|
||||||
|
@ -433,12 +435,13 @@ private:
|
||||||
TEST_CASE(platformUnix64);
|
TEST_CASE(platformUnix64);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Unspecified, const char* filename = "test.cpp") {
|
std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Unspecified, const char* filename = "test.cpp", bool cpp11 = false) {
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.debugwarnings = true;
|
settings.debugwarnings = true;
|
||||||
settings.platform(platform);
|
settings.platform(platform);
|
||||||
|
settings.standards.cpp11 = cpp11;
|
||||||
|
|
||||||
// tokenize..
|
// tokenize..
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
@ -6180,6 +6183,48 @@ private:
|
||||||
ASSERT_EQUALS("x y ;", tokenizeAndStringify("struct{x y:};\n",false));
|
ASSERT_EQUALS("x y ;", tokenizeAndStringify("struct{x y:};\n",false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyNamespaceStd() {
|
||||||
|
static const char code1[] = "map<foo, bar> m;"; // namespace std is not used
|
||||||
|
ASSERT_EQUALS("map < foo , bar > m ;", tokenizeAndStringify(code1, false));
|
||||||
|
|
||||||
|
static const char code2[] = "using namespace std;\n"
|
||||||
|
"map<foo, bar> m;";
|
||||||
|
ASSERT_EQUALS("std :: map < foo , bar > m ;", tokenizeAndStringify(code2, false));
|
||||||
|
|
||||||
|
static const char code3[] = "using namespace std;\n"
|
||||||
|
"string s;";
|
||||||
|
ASSERT_EQUALS("std :: string s ;", tokenizeAndStringify(code3, false));
|
||||||
|
|
||||||
|
static const char code4[] = "using namespace std;\n"
|
||||||
|
"void foo() {swap(a, b); }";
|
||||||
|
ASSERT_EQUALS("void foo ( ) { std :: swap ( a , b ) ; }", tokenizeAndStringify(code4, false));
|
||||||
|
|
||||||
|
static const char code5[] = "using namespace std;\n"
|
||||||
|
"void foo() {map(a, b); }"; // Thats obviously not std::map<>
|
||||||
|
ASSERT_EQUALS("void foo ( ) { map ( a , b ) ; }", tokenizeAndStringify(code5, false));
|
||||||
|
|
||||||
|
static const char code6[] = "using namespace std;\n"
|
||||||
|
"string<wchar_t> s;"; // Thats obviously not std::string
|
||||||
|
ASSERT_EQUALS("string < wchar_t > s ;", tokenizeAndStringify(code6, false));
|
||||||
|
|
||||||
|
static const char code7[] = "using namespace std;\n"
|
||||||
|
"swap s;"; // Thats obviously not std::swap
|
||||||
|
ASSERT_EQUALS("swap s ;", tokenizeAndStringify(code7, false));
|
||||||
|
|
||||||
|
static const char code8[] = "using namespace std;\n"
|
||||||
|
"std::string s;";
|
||||||
|
ASSERT_EQUALS("std :: string s ;", tokenizeAndStringify(code8, false));
|
||||||
|
|
||||||
|
static const char code9[] = "using namespace std;\n"
|
||||||
|
"tr1::function <void(int)> f;";
|
||||||
|
ASSERT_EQUALS("tr1 :: function < void ( int ) > f ;", tokenizeAndStringify(code9, false, true, Settings::Unspecified, "test.cpp", false));
|
||||||
|
ASSERT_EQUALS("std :: function < void ( int ) > f ;", tokenizeAndStringify(code9, false, true, Settings::Unspecified, "test.cpp", true));
|
||||||
|
|
||||||
|
static const char code10[] = "std::tr1::function <void(int)> f;";
|
||||||
|
ASSERT_EQUALS("std :: tr1 :: function < void ( int ) > f ;", tokenizeAndStringify(code10, false, true, Settings::Unspecified, "test.cpp", false));
|
||||||
|
ASSERT_EQUALS("std :: function < void ( int ) > f ;", tokenizeAndStringify(code10, false, true, Settings::Unspecified, "test.cpp", true));
|
||||||
|
}
|
||||||
|
|
||||||
void microsoftMFC() {
|
void microsoftMFC() {
|
||||||
const char code1[] = "class MyDialog : public CDialog { DECLARE_MESSAGE_MAP() private: CString text; };";
|
const char code1[] = "class MyDialog : public CDialog { DECLARE_MESSAGE_MAP() private: CString text; };";
|
||||||
ASSERT_EQUALS("class MyDialog : public CDialog { private: CString text ; } ;", tokenizeAndStringify(code1,false,true,Settings::Win32A));
|
ASSERT_EQUALS("class MyDialog : public CDialog { private: CString text ; } ;", tokenizeAndStringify(code1,false,true,Settings::Win32A));
|
||||||
|
|
Loading…
Reference in New Issue