Skip to content

Commit 714e49d

Browse files
author
Your Name
committed
Use settings flag
1 parent 0e15903 commit 714e49d

5 files changed

Lines changed: 77 additions & 3 deletions

File tree

cli/cmdlineparser.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,11 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
15481548
// TODO: bail out when no placeholders are found?
15491549
}
15501550

1551+
// Recreate the symbol database etc. after each template type deduction round
1552+
// instead of updating them incrementally - for testing and debugging
1553+
else if (std::strcmp(argv[i], "--template-full-rebuild") == 0)
1554+
mSettings.templateFullRebuild = true;
1555+
15511556
else if (std::strncmp(argv[i], "--template-location=", 20) == 0) {
15521557
mSettings.templateLocation = argv[i] + 20;
15531558
// TODO: bail out when no template is provided?

lib/settings.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,11 @@ class CPPCHECKLIB WARN_UNUSED Settings {
466466
e.g. "{severity} {file}:{line} {message} {id}" */
467467
std::string templateFormat;
468468

469+
/** @brief Is --template-full-rebuild given? Recreate the symbol database etc. from
470+
* scratch after each template type deduction round instead of updating them
471+
* incrementally. For testing and debugging. */
472+
bool templateFullRebuild{};
473+
469474
/** @brief The output format in which the error locations are printed in
470475
* text mode, e.g. "{file}:{line} {info}" */
471476
std::string templateLocation;

lib/tokenize.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4287,8 +4287,7 @@ void Tokenizer::simplifyTemplatesUsingTypeInformation()
42874287

42884288
// for testing and debugging: recreate the symbol database etc. from scratch after
42894289
// each deduction round instead of updating them incrementally
4290-
const char* fullRebuildEnv = std::getenv("CPPCHECK_TEMPLATE_FULL_REBUILD");
4291-
const bool allowIncremental = !fullRebuildEnv || (std::strcmp(fullRebuildEnv, "1") != 0);
4290+
const bool allowIncremental = !mSettings.templateFullRebuild;
42924291

42934292
bool finalized = false;
42944293

test/testcmdlineparser.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ class TestCmdlineParser : public TestFixture {
383383
TEST_CASE(performanceValueflowMaxTimeInvalid);
384384
TEST_CASE(performanceValueFlowMaxIfCount);
385385
TEST_CASE(performanceValueFlowMaxIfCountInvalid);
386+
TEST_CASE(templateFullRebuild);
386387
TEST_CASE(templateMaxTime);
387388
TEST_CASE(templateMaxTimeInvalid);
388389
TEST_CASE(templateMaxTimeInvalid2);
@@ -2535,6 +2536,13 @@ class TestCmdlineParser : public TestFixture {
25352536
ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-if-count=' is not valid - not an integer (invalid_argument).\n", logger->str());
25362537
}
25372538

2539+
void templateFullRebuild() {
2540+
REDIRECT;
2541+
const char * const argv[] = {"cppcheck", "--template-full-rebuild", "file.cpp"};
2542+
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv));
2543+
ASSERT_EQUALS(true, settings->templateFullRebuild);
2544+
}
2545+
25382546
void templateMaxTime() {
25392547
REDIRECT;
25402548
const char * const argv[] = {"cppcheck", "--template-max-time=12", "file.cpp"};

test/testsimplifytemplate.cpp

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ class TestSimplifyTemplate : public TestFixture {
4242
const Settings settings = settingsBuilder().severity(Severity::portability).build();
4343
const Settings settings1 = settingsBuilder(settings).library("std.cfg").build();
4444
const Settings settings1_d = settingsBuilder(settings1).debugwarnings().build();
45+
const Settings settings1_fr = makeFullRebuildSettings(settings1);
46+
47+
static Settings makeFullRebuildSettings(const Settings& base) {
48+
Settings s = base;
49+
s.templateFullRebuild = true;
50+
return s;
51+
}
4552

4653
void run() override {
4754
TEST_CASE(template1);
@@ -294,6 +301,7 @@ class TestSimplifyTemplate : public TestFixture {
294301
TEST_CASE(templateTypeDeduction13); // members declared after the member function are visible
295302
TEST_CASE(templateTypeDeduction14); // a non template overload might be a better match
296303
TEST_CASE(templateTypeDeduction15); // final classes
304+
TEST_CASE(templateTypeDeductionFullRebuild); // --template-full-rebuild gives the same result
297305

298306
TEST_CASE(simplifyTemplateArgs1);
299307
TEST_CASE(simplifyTemplateArgs2);
@@ -352,12 +360,19 @@ class TestSimplifyTemplate : public TestFixture {
352360
struct CheckOptions
353361
{
354362
bool debugwarnings = false;
363+
bool templateFullRebuild = false;
355364
};
356365

366+
const Settings& checkOptionsSettings(const CheckOptions& options) const {
367+
if (options.templateFullRebuild)
368+
return settings1_fr;
369+
return options.debugwarnings ? settings1_d : settings1;
370+
}
371+
357372
#define tok(...) tok_(__FILE__, __LINE__, __VA_ARGS__)
358373
template<size_t size>
359374
std::string tok_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) {
360-
const Settings& s = options.debugwarnings ? settings1_d : settings1;
375+
const Settings& s = checkOptionsSettings(options);
361376
SimpleTokenizer tokenizer(s, *this);
362377

363378
ASSERT_LOC(tokenizer.tokenize(code), file, line);
@@ -6871,6 +6886,48 @@ class TestSimplifyTemplate : public TestFixture {
68716886
}
68726887
}
68736888

6889+
void templateTypeDeductionFullRebuild()
6890+
{ // --template-full-rebuild recreates the symbol database etc. after each type
6891+
// deduction round instead of updating them incrementally - the result must be
6892+
// the same
6893+
{
6894+
// deduction from variables and expressions
6895+
const char code[] = "template <typename T> void f(T n) { (void)n; }\n"
6896+
"struct MyClass { int m; };\n"
6897+
"void func(MyClass mc, unsigned long long ull, double d) {\n"
6898+
" f(mc);\n"
6899+
" f(ull);\n"
6900+
" f(d + 1.5);\n"
6901+
"}";
6902+
const std::string expected = tok(code);
6903+
ASSERT(expected.find("f<MyClass>") != std::string::npos);
6904+
ASSERT_EQUALS(expected, tok(code, dinit(CheckOptions, $.templateFullRebuild = true)));
6905+
}
6906+
{
6907+
// base class member template: the instantiated declaration is removed in a
6908+
// finalize step
6909+
const char code[] = "struct Base {\n"
6910+
" template<class T> void btf(T t) { (void)t; }\n"
6911+
" int bm;\n"
6912+
"};\n"
6913+
"struct Derived : public Base {\n"
6914+
" void use() { btf(bm); }\n"
6915+
"};";
6916+
const std::string expected = tok(code);
6917+
ASSERT(expected.find("Base :: btf<int>") != std::string::npos);
6918+
ASSERT_EQUALS(expected, tok(code, dinit(CheckOptions, $.templateFullRebuild = true)));
6919+
}
6920+
{
6921+
// nested calls need multiple deduction rounds
6922+
const char code[] = "template<class T> T pass(T x) { return x; }\n"
6923+
"template<class T> void sink(T x) { (void)x; }\n"
6924+
"void use(long v) { sink(pass(v)); }";
6925+
const std::string expected = tok(code);
6926+
ASSERT(expected.find("sink<long>") != std::string::npos);
6927+
ASSERT_EQUALS(expected, tok(code, dinit(CheckOptions, $.templateFullRebuild = true)));
6928+
}
6929+
}
6930+
68746931
void simplifyTemplateArgs1() {
68756932
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < ( 2 ) >;"));
68766933
ASSERT_EQUALS("foo<2> = 2 ; foo<2> ;", tok("template<int N> foo = N; foo < 1 + 1 >;"));

0 commit comments

Comments
 (0)