Fixed #9860 (unused template not removed properly by default)
This commit is contained in:
parent
28bc823264
commit
2cd8ea83a7
|
@ -293,18 +293,14 @@ void Token::deleteThis()
|
||||||
takeData(mNext);
|
takeData(mNext);
|
||||||
mNext->link(nullptr); // mark as unlinked
|
mNext->link(nullptr); // mark as unlinked
|
||||||
deleteNext();
|
deleteNext();
|
||||||
} else if (mPrevious && mPrevious->mPrevious) { // Copy previous to this and delete previous
|
} else if (mPrevious) { // Copy previous to this and delete previous
|
||||||
takeData(mPrevious);
|
takeData(mPrevious);
|
||||||
|
mPrevious->link(nullptr);
|
||||||
Token* toDelete = mPrevious;
|
deletePrevious();
|
||||||
mPrevious = mPrevious->mPrevious;
|
|
||||||
mPrevious->mNext = this;
|
|
||||||
|
|
||||||
delete toDelete;
|
|
||||||
} else {
|
} else {
|
||||||
// We are the last token in the list, we can't delete
|
// We are the last token in the list, we can't delete
|
||||||
// ourselves, so just make us empty
|
// ourselves, so just make us empty
|
||||||
str("");
|
str(";");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4365,7 +4365,7 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
||||||
|
|
||||||
reportUnknownMacros();
|
reportUnknownMacros();
|
||||||
|
|
||||||
simplifyHeaders();
|
simplifyHeadersAndUnusedTemplates();
|
||||||
|
|
||||||
// Remove __asm..
|
// Remove __asm..
|
||||||
simplifyAsm();
|
simplifyAsm();
|
||||||
|
@ -5027,7 +5027,7 @@ void Tokenizer::dump(std::ostream &out) const
|
||||||
list.front()->printValueFlow(true, out);
|
list.front()->printValueFlow(true, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tokenizer::simplifyHeaders()
|
void Tokenizer::simplifyHeadersAndUnusedTemplates()
|
||||||
{
|
{
|
||||||
if (mSettings->checkHeaders && mSettings->checkUnusedTemplates)
|
if (mSettings->checkHeaders && mSettings->checkUnusedTemplates)
|
||||||
// Full analysis. All information in the headers are kept.
|
// Full analysis. All information in the headers are kept.
|
||||||
|
@ -5053,7 +5053,13 @@ void Tokenizer::simplifyHeaders()
|
||||||
// functions and types to keep
|
// functions and types to keep
|
||||||
std::set<std::string> keep;
|
std::set<std::string> keep;
|
||||||
for (const Token *tok = list.front(); tok; tok = tok->next()) {
|
for (const Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
if (!tok->isName())
|
if (isCPP() && Token::simpleMatch(tok, "template <")) {
|
||||||
|
const Token *closingBracket = tok->next()->findClosingBracket();
|
||||||
|
if (Token::Match(closingBracket, "> class|struct %name% {"))
|
||||||
|
tok = closingBracket->linkAt(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tok->isName() || tok->isKeyword())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!checkHeaders && tok->fileIndex() != 0)
|
if (!checkHeaders && tok->fileIndex() != 0)
|
||||||
|
@ -5088,49 +5094,42 @@ void Tokenizer::simplifyHeaders()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Token::Match(tok, "[;{}]")) {
|
if (!tok->previous() || Token::Match(tok->previous(), "[;{}]")) {
|
||||||
// Remove unused function declarations
|
// Remove unused function declarations
|
||||||
if (isIncluded && removeUnusedIncludedFunctions) {
|
if (isIncluded && removeUnusedIncludedFunctions) {
|
||||||
while (1) {
|
while (1) {
|
||||||
Token *start = tok->next();
|
Token *start = tok;
|
||||||
while (start && functionStart.find(start->str()) != functionStart.end())
|
while (start && functionStart.find(start->str()) != functionStart.end())
|
||||||
start = start->next();
|
start = start->next();
|
||||||
if (Token::Match(start, "%name% (") && Token::Match(start->linkAt(1), ") const| ;") && keep.find(start->str()) == keep.end())
|
if (Token::Match(start, "%name% (") && Token::Match(start->linkAt(1), ") const| ;") && keep.find(start->str()) == keep.end()) {
|
||||||
Token::eraseTokens(tok, start->linkAt(1)->tokAt(2));
|
Token::eraseTokens(tok, start->linkAt(1)->tokAt(2));
|
||||||
else
|
tok->deleteThis();
|
||||||
|
} else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isIncluded && removeUnusedIncludedClasses) {
|
if (isIncluded && removeUnusedIncludedClasses) {
|
||||||
if (Token::Match(tok, "[;{}] class|struct %name% [:{]") && keep.find(tok->strAt(2)) == keep.end()) {
|
if (Token::Match(tok, "class|struct %name% [:{]") && keep.find(tok->strAt(1)) == keep.end()) {
|
||||||
// Remove this class/struct
|
// Remove this class/struct
|
||||||
const Token *endToken = tok->tokAt(3);
|
const Token *endToken = tok->tokAt(2);
|
||||||
if (endToken->str() == ":") {
|
if (endToken->str() == ":") {
|
||||||
endToken = endToken->next();
|
endToken = endToken->next();
|
||||||
while (Token::Match(endToken, "%name%|,"))
|
while (Token::Match(endToken, "%name%|,"))
|
||||||
endToken = endToken->next();
|
endToken = endToken->next();
|
||||||
}
|
}
|
||||||
if (endToken && endToken->str() == "{" && Token::simpleMatch(endToken->link(), "} ;"))
|
if (endToken && endToken->str() == "{" && Token::simpleMatch(endToken->link(), "} ;")) {
|
||||||
Token::eraseTokens(tok, endToken->link()->next());
|
Token::eraseTokens(tok, endToken->link()->next());
|
||||||
|
tok->deleteThis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removeUnusedTemplates || (isIncluded && removeUnusedIncludedTemplates)) {
|
if (removeUnusedTemplates || (isIncluded && removeUnusedIncludedTemplates)) {
|
||||||
if (Token::Match(tok->next(), "template < %name%")) {
|
if (Token::Match(tok, "template < %name%")) {
|
||||||
const Token *tok2 = tok->tokAt(3);
|
const Token *closingBracket = tok->next()->findClosingBracket();
|
||||||
while (Token::Match(tok2, "%name% %name% [,=>]") || Token::Match(tok2, "typename|class ... %name% [,>]")) {
|
if (Token::Match(closingBracket, "> class|struct %name% [;:{]") && keep.find(closingBracket->strAt(2)) == keep.end()) {
|
||||||
if (Token::Match(tok2, "typename|class ..."))
|
const Token *endToken = closingBracket->tokAt(3);
|
||||||
tok2 = tok2->tokAt(3);
|
|
||||||
else
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
if (Token::Match(tok2, "= %name% [,>]"))
|
|
||||||
tok2 = tok2->tokAt(2);
|
|
||||||
if (tok2->str() == ",")
|
|
||||||
tok2 = tok2->next();
|
|
||||||
}
|
|
||||||
if (Token::Match(tok2, "> class|struct %name% [;:{]") && keep.find(tok2->strAt(2)) == keep.end()) {
|
|
||||||
const Token *endToken = tok2->tokAt(3);
|
|
||||||
if (endToken->str() == ":") {
|
if (endToken->str() == ":") {
|
||||||
endToken = endToken->next();
|
endToken = endToken->next();
|
||||||
while (Token::Match(endToken, "%name%|,"))
|
while (Token::Match(endToken, "%name%|,"))
|
||||||
|
@ -5138,11 +5137,14 @@ void Tokenizer::simplifyHeaders()
|
||||||
}
|
}
|
||||||
if (endToken && endToken->str() == "{")
|
if (endToken && endToken->str() == "{")
|
||||||
endToken = endToken->link()->next();
|
endToken = endToken->link()->next();
|
||||||
if (endToken && endToken->str() == ";")
|
if (endToken && endToken->str() == ";") {
|
||||||
Token::eraseTokens(tok, endToken);
|
Token::eraseTokens(tok, endToken);
|
||||||
} else if (Token::Match(tok2, "> %type% %name% (") && Token::simpleMatch(tok2->linkAt(3), ") {") && keep.find(tok2->strAt(2)) == keep.end()) {
|
tok->deleteThis();
|
||||||
const Token *endToken = tok2->linkAt(3)->linkAt(1)->next();
|
}
|
||||||
|
} else if (Token::Match(closingBracket, "> %type% %name% (") && Token::simpleMatch(closingBracket->linkAt(3), ") {") && keep.find(closingBracket->strAt(2)) == keep.end()) {
|
||||||
|
const Token *endToken = closingBracket->linkAt(3)->linkAt(1)->next();
|
||||||
Token::eraseTokens(tok, endToken);
|
Token::eraseTokens(tok, endToken);
|
||||||
|
tok->deleteThis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ public:
|
||||||
* - All executable code.
|
* - All executable code.
|
||||||
* - Unused types/variables/etc
|
* - Unused types/variables/etc
|
||||||
*/
|
*/
|
||||||
void simplifyHeaders();
|
void simplifyHeadersAndUnusedTemplates();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes dead code between 'begin' and 'end'.
|
* Deletes dead code between 'begin' and 'end'.
|
||||||
|
|
|
@ -31,11 +31,11 @@ public:
|
||||||
private:
|
private:
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
void check(const char code[], bool showAll = false) {
|
void check(const char code[], bool inconclusive = false) {
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
settings.inconclusive = showAll;
|
settings.inconclusive = inconclusive;
|
||||||
|
|
||||||
// Tokenize..
|
// Tokenize..
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
@ -348,16 +348,6 @@ private:
|
||||||
" int x;\n"
|
" int x;\n"
|
||||||
"};");
|
"};");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
check("template <class T> struct A {\n"
|
|
||||||
" A<T>() : x(0) { }\n"
|
|
||||||
" A<T>(const T & t) : x(t.x) { }\n"
|
|
||||||
"private:\n"
|
|
||||||
" int x;\n"
|
|
||||||
" int y;\n"
|
|
||||||
"};");
|
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (warning) Member variable 'A::y' is not initialized in the constructor.\n"
|
|
||||||
"[test.cpp:3]: (warning) Member variable 'A::y' is not initialized in the constructor.\n", errout.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void simple7() { // ticket #4531
|
void simple7() { // ticket #4531
|
||||||
|
|
|
@ -1378,7 +1378,7 @@ private:
|
||||||
);
|
);
|
||||||
|
|
||||||
// #3449
|
// #3449
|
||||||
ASSERT_EQUALS("template < typename T > struct A ;\n"
|
ASSERT_EQUALS(";\n"
|
||||||
"struct B { template < typename T > struct C } ;\n"
|
"struct B { template < typename T > struct C } ;\n"
|
||||||
"{ } ;",
|
"{ } ;",
|
||||||
checkCode("template<typename T> struct A;\n"
|
checkCode("template<typename T> struct A;\n"
|
||||||
|
|
|
@ -6101,10 +6101,14 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
check("template<int n> void foo(unsigned int x) {\n"
|
{
|
||||||
"if (x <= 0);\n"
|
Settings keepTemplates;
|
||||||
"}\n");
|
keepTemplates.checkUnusedTemplates = true;
|
||||||
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout.str());
|
check("template<int n> void foo(unsigned int x) {\n"
|
||||||
|
"if (x <= 0);\n"
|
||||||
|
"}\n", &keepTemplates);
|
||||||
|
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x' is less than zero.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
// #8836
|
// #8836
|
||||||
check("uint32_t value = 0xFUL;\n"
|
check("uint32_t value = 0xFUL;\n"
|
||||||
|
@ -8743,11 +8747,14 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void forwardAndUsed() {
|
void forwardAndUsed() {
|
||||||
|
Settings keepTemplates;
|
||||||
|
keepTemplates.checkUnusedTemplates = true;
|
||||||
|
|
||||||
check("template<typename T>\n"
|
check("template<typename T>\n"
|
||||||
"void f(T && t) {\n"
|
"void f(T && t) {\n"
|
||||||
" g(std::forward<T>(t));\n"
|
" g(std::forward<T>(t));\n"
|
||||||
" T s = t;\n"
|
" T s = t;\n"
|
||||||
"}");
|
"}", &keepTemplates);
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (warning) Access of forwarded variable 't'.\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:4]: (warning) Access of forwarded variable 't'.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,9 @@ private:
|
||||||
void run() OVERRIDE {
|
void run() OVERRIDE {
|
||||||
settings.addEnabled("portability");
|
settings.addEnabled("portability");
|
||||||
|
|
||||||
|
// If there are unused templates, keep those
|
||||||
|
settings.checkUnusedTemplates = true;
|
||||||
|
|
||||||
TEST_CASE(template1);
|
TEST_CASE(template1);
|
||||||
TEST_CASE(template2);
|
TEST_CASE(template2);
|
||||||
TEST_CASE(template3);
|
TEST_CASE(template3);
|
||||||
|
@ -458,7 +461,8 @@ private:
|
||||||
|
|
||||||
// The expected result..
|
// The expected result..
|
||||||
const char expected[] = "class A<int> ; "
|
const char expected[] = "class A<int> ; "
|
||||||
"void f ( ) { A<int> a ; } ; "
|
"void f ( ) { A<int> a ; } "
|
||||||
|
"template < typename T > class B { void g ( ) { A < T > b ; b = A < T > :: h ( ) ; } } ; "
|
||||||
"class A<int> { } ;";
|
"class A<int> { } ;";
|
||||||
|
|
||||||
ASSERT_EQUALS(expected, tok(code));
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
|
@ -1472,6 +1476,7 @@ private:
|
||||||
"template <class T, unsigned S> C3<T, S>::C3(const C3<T, S> &v) { C1<T *> c1; }\n"
|
"template <class T, unsigned S> C3<T, S>::C3(const C3<T, S> &v) { C1<T *> c1; }\n"
|
||||||
"C3<int,6> c3;";
|
"C3<int,6> c3;";
|
||||||
const char exp[] = "struct C1<int*> ; "
|
const char exp[] = "struct C1<int*> ; "
|
||||||
|
"template < class T > void f ( ) { x = y ? ( C1 < int > :: allocate ( 1 ) ) : 0 ; } "
|
||||||
"class C3<int,6> ; "
|
"class C3<int,6> ; "
|
||||||
"C3<int,6> c3 ; "
|
"C3<int,6> c3 ; "
|
||||||
"class C3<int,6> { } ; "
|
"class C3<int,6> { } ; "
|
||||||
|
@ -2549,8 +2554,8 @@ private:
|
||||||
"template <typename T> class Fred {};\n"
|
"template <typename T> class Fred {};\n"
|
||||||
"ObjectCache<Fred> _cache;";
|
"ObjectCache<Fred> _cache;";
|
||||||
const char exp[] = "class ObjectCache<Fred> ; "
|
const char exp[] = "class ObjectCache<Fred> ; "
|
||||||
"ObjectCache<Fred> _cache ; "
|
"template < typename T > class Fred { } ; "
|
||||||
"class ObjectCache<Fred> { } ;";
|
"ObjectCache<Fred> _cache ; class ObjectCache<Fred> { } ;";
|
||||||
ASSERT_EQUALS(exp, tok(code));
|
ASSERT_EQUALS(exp, tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4092,7 +4097,8 @@ private:
|
||||||
"template < class T > struct Unconst < const T & > { } ; "
|
"template < class T > struct Unconst < const T & > { } ; "
|
||||||
"template < class T > struct Unconst < T * const > { } ; "
|
"template < class T > struct Unconst < T * const > { } ; "
|
||||||
"template < class T1 , class T2 > struct type_equal { enum Anonymous0 { value = 0 } ; } ; "
|
"template < class T1 , class T2 > struct type_equal { enum Anonymous0 { value = 0 } ; } ; "
|
||||||
"template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ;";
|
"template < class T > struct type_equal < T , T > { enum Anonymous1 { value = 1 } ; } ; "
|
||||||
|
"template < class T > struct template_is_const { enum Anonymous2 { value = ! type_equal < T , Unconst < T > :: type > :: value } ; } ;";
|
||||||
ASSERT_EQUALS(exp1, tok(code1));
|
ASSERT_EQUALS(exp1, tok(code1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4372,7 +4378,7 @@ private:
|
||||||
const char code[] = "class Fred {\n"
|
const char code[] = "class Fred {\n"
|
||||||
" template<class T> explicit Fred(T t) { }\n"
|
" template<class T> explicit Fred(T t) { }\n"
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS("class Fred { }", tok(code));
|
ASSERT_EQUALS("class Fred { template < class T > explicit Fred ( T t ) { } }", tok(code));
|
||||||
|
|
||||||
// #3532
|
// #3532
|
||||||
const char code2[] = "class Fred {\n"
|
const char code2[] = "class Fred {\n"
|
||||||
|
|
|
@ -46,6 +46,12 @@ private:
|
||||||
settings1.addEnabled("style");
|
settings1.addEnabled("style");
|
||||||
settings_windows.addEnabled("portability");
|
settings_windows.addEnabled("portability");
|
||||||
|
|
||||||
|
// If there are unused templates, keep those
|
||||||
|
settings0.checkUnusedTemplates = true;
|
||||||
|
settings1.checkUnusedTemplates = true;
|
||||||
|
settings_std.checkUnusedTemplates = true;
|
||||||
|
settings_windows.checkUnusedTemplates = true;
|
||||||
|
|
||||||
// Make sure the Tokenizer::simplifyTokenList works.
|
// Make sure the Tokenizer::simplifyTokenList works.
|
||||||
// The order of the simplifications is important. So this test
|
// The order of the simplifications is important. So this test
|
||||||
// case shall make sure the simplifications are done in the
|
// case shall make sure the simplifications are done in the
|
||||||
|
@ -2883,7 +2889,7 @@ private:
|
||||||
{
|
{
|
||||||
const char code[] = "namespace std { }";
|
const char code[] = "namespace std { }";
|
||||||
|
|
||||||
ASSERT_EQUALS("", tok(code));
|
ASSERT_EQUALS(";", tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,11 @@ private:
|
||||||
settings0.addEnabled("style");
|
settings0.addEnabled("style");
|
||||||
settings2.addEnabled("style");
|
settings2.addEnabled("style");
|
||||||
|
|
||||||
|
// If there are unused templates, keep those
|
||||||
|
settings0.checkUnusedTemplates = true;
|
||||||
|
settings1.checkUnusedTemplates = true;
|
||||||
|
settings2.checkUnusedTemplates = true;
|
||||||
|
|
||||||
TEST_CASE(simplifyTypedef1);
|
TEST_CASE(simplifyTypedef1);
|
||||||
TEST_CASE(simplifyTypedef2);
|
TEST_CASE(simplifyTypedef2);
|
||||||
TEST_CASE(simplifyTypedef3);
|
TEST_CASE(simplifyTypedef3);
|
||||||
|
@ -1797,7 +1802,7 @@ private:
|
||||||
|
|
||||||
void simplifyTypedef75() { // ticket #2426
|
void simplifyTypedef75() { // ticket #2426
|
||||||
const char code[] = "typedef _Packed struct S { long l; };";
|
const char code[] = "typedef _Packed struct S { long l; };";
|
||||||
ASSERT_EQUALS("", tok(code, true, Settings::Native, false));
|
ASSERT_EQUALS(";", tok(code, true, Settings::Native, false));
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2047,7 +2052,7 @@ private:
|
||||||
const char code[] = "typedef long Long;\n"
|
const char code[] = "typedef long Long;\n"
|
||||||
"namespace NS {\n"
|
"namespace NS {\n"
|
||||||
"}";
|
"}";
|
||||||
ASSERT_EQUALS("", tok(code));
|
ASSERT_EQUALS(";", tok(code));
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2532,7 +2537,8 @@ private:
|
||||||
"template <long, class> struct c; "
|
"template <long, class> struct c; "
|
||||||
"template <int g> struct d { enum { e = c<g, b>::f }; };";
|
"template <int g> struct d { enum { e = c<g, b>::f }; };";
|
||||||
const char exp [] = "class a ; "
|
const char exp [] = "class a ; "
|
||||||
"template < long , class > struct c ;";
|
"template < long , class > struct c ; "
|
||||||
|
"template < int g > struct d { enum Anonymous0 { e = c < g , int ( a :: * ) > :: f } ; } ;";
|
||||||
ASSERT_EQUALS(exp, tok(code, false));
|
ASSERT_EQUALS(exp, tok(code, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,11 @@ private:
|
||||||
settings0.addEnabled("style");
|
settings0.addEnabled("style");
|
||||||
settings2.addEnabled("style");
|
settings2.addEnabled("style");
|
||||||
|
|
||||||
|
// If there are unused templates, keep those
|
||||||
|
settings0.checkUnusedTemplates = true;
|
||||||
|
settings1.checkUnusedTemplates = true;
|
||||||
|
settings2.checkUnusedTemplates = true;
|
||||||
|
|
||||||
TEST_CASE(simplifyUsing1);
|
TEST_CASE(simplifyUsing1);
|
||||||
TEST_CASE(simplifyUsing2);
|
TEST_CASE(simplifyUsing2);
|
||||||
TEST_CASE(simplifyUsing3);
|
TEST_CASE(simplifyUsing3);
|
||||||
|
@ -492,7 +497,8 @@ private:
|
||||||
"class c { "
|
"class c { "
|
||||||
"int i ; i = 0 ; "
|
"int i ; i = 0 ; "
|
||||||
"c ( ) { i -- ; } "
|
"c ( ) { i -- ; } "
|
||||||
"} ;";
|
"} ; "
|
||||||
|
"template < class T > class s { } ;";
|
||||||
|
|
||||||
ASSERT_EQUALS(exp, tok(code, true, Settings::Win64));
|
ASSERT_EQUALS(exp, tok(code, true, Settings::Win64));
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,10 @@ private:
|
||||||
LOAD_LIB_2(settings1.library, "std.cfg");
|
LOAD_LIB_2(settings1.library, "std.cfg");
|
||||||
settings2.platform(Settings::Unspecified);
|
settings2.platform(Settings::Unspecified);
|
||||||
|
|
||||||
|
// If there are unused templates, keep those
|
||||||
|
settings1.checkUnusedTemplates = true;
|
||||||
|
settings2.checkUnusedTemplates = true;
|
||||||
|
|
||||||
TEST_CASE(array);
|
TEST_CASE(array);
|
||||||
TEST_CASE(stlarray1);
|
TEST_CASE(stlarray1);
|
||||||
TEST_CASE(stlarray2);
|
TEST_CASE(stlarray2);
|
||||||
|
|
|
@ -47,6 +47,12 @@ private:
|
||||||
void run() OVERRIDE {
|
void run() OVERRIDE {
|
||||||
LOAD_LIB_2(settings_windows.library, "windows.cfg");
|
LOAD_LIB_2(settings_windows.library, "windows.cfg");
|
||||||
|
|
||||||
|
// If there are unused templates, keep those
|
||||||
|
settings0.checkUnusedTemplates = true;
|
||||||
|
settings1.checkUnusedTemplates = true;
|
||||||
|
settings2.checkUnusedTemplates = true;
|
||||||
|
settings_windows.checkUnusedTemplates = true;
|
||||||
|
|
||||||
TEST_CASE(tokenize1);
|
TEST_CASE(tokenize1);
|
||||||
TEST_CASE(tokenize2);
|
TEST_CASE(tokenize2);
|
||||||
TEST_CASE(tokenize4);
|
TEST_CASE(tokenize4);
|
||||||
|
@ -95,7 +101,8 @@ private:
|
||||||
|
|
||||||
TEST_CASE(longtok);
|
TEST_CASE(longtok);
|
||||||
|
|
||||||
TEST_CASE(removeUnusedTemplates);
|
TEST_CASE(simplifyHeadersAndUnusedTemplates1);
|
||||||
|
TEST_CASE(simplifyHeadersAndUnusedTemplates2);
|
||||||
|
|
||||||
TEST_CASE(simplifyCasts1);
|
TEST_CASE(simplifyCasts1);
|
||||||
TEST_CASE(simplifyCasts2);
|
TEST_CASE(simplifyCasts2);
|
||||||
|
@ -1028,7 +1035,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void removeUnusedTemplates() {
|
void simplifyHeadersAndUnusedTemplates1() {
|
||||||
Settings s;
|
Settings s;
|
||||||
s.checkUnusedTemplates = false;
|
s.checkUnusedTemplates = false;
|
||||||
ASSERT_EQUALS(";",
|
ASSERT_EQUALS(";",
|
||||||
|
@ -1044,6 +1051,22 @@ private:
|
||||||
"}", s));
|
"}", s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyHeadersAndUnusedTemplates2() {
|
||||||
|
const char code[] = "; template< typename T, u_int uBAR = 0 >\n"
|
||||||
|
"class Foo {\n"
|
||||||
|
"public:\n"
|
||||||
|
" void FooBar() {\n"
|
||||||
|
" new ( (uBAR ? uBAR : sizeof(T))) T;\n"
|
||||||
|
" }\n"
|
||||||
|
"};";
|
||||||
|
|
||||||
|
Settings s;
|
||||||
|
s.checkUnusedTemplates = false;
|
||||||
|
ASSERT_EQUALS(";", tokenizeAndStringify(code, s));
|
||||||
|
|
||||||
|
s.checkUnusedTemplates = true;
|
||||||
|
ASSERT_THROW(tokenizeAndStringify(code, s), InternalError);
|
||||||
|
}
|
||||||
|
|
||||||
// Don’t remove "(int *)"..
|
// Don’t remove "(int *)"..
|
||||||
void simplifyCasts1() {
|
void simplifyCasts1() {
|
||||||
|
@ -7467,11 +7490,11 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplifyEmptyNamespaces() {
|
void simplifyEmptyNamespaces() {
|
||||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace { }"));
|
ASSERT_EQUALS(";", tokenizeAndStringify("namespace { }"));
|
||||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace foo { }"));
|
ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { }"));
|
||||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace foo { namespace { } }"));
|
ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { namespace { } }"));
|
||||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace { namespace { } }")); // Ticket #9512
|
ASSERT_EQUALS(";", tokenizeAndStringify("namespace { namespace { } }")); // Ticket #9512
|
||||||
ASSERT_EQUALS("", tokenizeAndStringify("namespace foo { namespace bar { } }"));
|
ASSERT_EQUALS(";", tokenizeAndStringify("namespace foo { namespace bar { } }"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareTernaryOpForAST() {
|
void prepareTernaryOpForAST() {
|
||||||
|
@ -8625,12 +8648,12 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string checkHeaders(const char code[], bool f) {
|
std::string checkHeaders(const char code[], bool checkHeadersFlag) {
|
||||||
// Clear the error buffer..
|
// Clear the error buffer..
|
||||||
errout.str("");
|
errout.str("");
|
||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.checkHeaders = f;
|
settings.checkHeaders = checkHeadersFlag;
|
||||||
|
|
||||||
// Raw tokens..
|
// Raw tokens..
|
||||||
std::vector<std::string> files(1, "test.cpp");
|
std::vector<std::string> files(1, "test.cpp");
|
||||||
|
@ -8670,12 +8693,11 @@ private:
|
||||||
"5: } ; void A :: g<int> ( int x ) { a = 2 ; }\n",
|
"5: } ; void A :: g<int> ( int x ) { a = 2 ; }\n",
|
||||||
checkHeaders(code, true));
|
checkHeaders(code, true));
|
||||||
|
|
||||||
ASSERT_EQUALS("\n\n##file 1\n"
|
ASSERT_EQUALS("\n\n##file 1\n\n"
|
||||||
"1: struct A {\n"
|
"1:\n"
|
||||||
"2: int a ; a = 1 ;\n"
|
"|\n"
|
||||||
"3: void f ( ) ;\n"
|
|
||||||
"4:\n"
|
"4:\n"
|
||||||
"5: } ;\n",
|
"5: ;\n",
|
||||||
checkHeaders(code, false));
|
checkHeaders(code, false));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -221,6 +221,7 @@ private:
|
||||||
settings.platform(Settings::Unix64);
|
settings.platform(Settings::Unix64);
|
||||||
settings.standards.c = Standards::C89;
|
settings.standards.c = Standards::C89;
|
||||||
settings.standards.cpp = Standards::CPP11;
|
settings.standards.cpp = Standards::CPP11;
|
||||||
|
settings.checkUnusedTemplates = true;
|
||||||
|
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
|
@ -239,6 +240,7 @@ private:
|
||||||
settings.platform(Settings::Unix64);
|
settings.platform(Settings::Unix64);
|
||||||
settings.standards.c = Standards::C89;
|
settings.standards.c = Standards::C89;
|
||||||
settings.standards.cpp = Standards::CPP11;
|
settings.standards.cpp = Standards::CPP11;
|
||||||
|
settings.checkUnusedTemplates = true;
|
||||||
|
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
|
@ -257,6 +259,7 @@ private:
|
||||||
settings.platform(Settings::Unix64);
|
settings.platform(Settings::Unix64);
|
||||||
settings.standards.c = Standards::C89;
|
settings.standards.c = Standards::C89;
|
||||||
settings.standards.cpp = Standards::CPP11;
|
settings.standards.cpp = Standards::CPP11;
|
||||||
|
settings.checkUnusedTemplates = true;
|
||||||
|
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
|
|
Loading…
Reference in New Issue