Skip to content

Commit 463c805

Browse files
authored
fixed #10989 - the enforced language was not applied to the preprocessor (danmar#7492)
1 parent 7303e80 commit 463c805

File tree

8 files changed

+86
-33
lines changed

8 files changed

+86
-33
lines changed

lib/cppcheck.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -917,7 +917,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
917917
std::vector<std::string> files;
918918
simplecpp::TokenList tokens(*fileStream, files, file.spath());
919919
if (analyzerInformation) {
920-
const Preprocessor preprocessor(mSettings, mErrorLogger);
920+
const Preprocessor preprocessor(mSettings, mErrorLogger, Standards::Language::C);
921921
hash = calculateHash(preprocessor, tokens, mSettings, mSuppressions);
922922
}
923923
tokenlist.createTokens(std::move(tokens));
@@ -926,7 +926,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
926926
std::vector<std::string> files;
927927
simplecpp::TokenList tokens(file.spath(), files);
928928
if (analyzerInformation) {
929-
const Preprocessor preprocessor(mSettings, mErrorLogger);
929+
const Preprocessor preprocessor(mSettings, mErrorLogger, file.lang());
930930
hash = calculateHash(preprocessor, tokens, mSettings, mSuppressions);
931931
}
932932
tokenlist.createTokens(std::move(tokens));
@@ -973,7 +973,7 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
973973
return mLogger->exitcode();
974974
}
975975

976-
Preprocessor preprocessor(mSettings, mErrorLogger);
976+
Preprocessor preprocessor(mSettings, mErrorLogger, file.lang());
977977

978978
if (!preprocessor.loadFiles(tokens1, files))
979979
return mLogger->exitcode();

lib/preprocessor.cpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include <algorithm>
3333
#include <array>
34+
#include <cassert>
3435
#include <cstddef>
3536
#include <iterator>
3637
#include <sstream>
@@ -63,8 +64,13 @@ Directive::DirectiveToken::DirectiveToken(const simplecpp::Token & _tok) :
6364

6465
char Preprocessor::macroChar = char(1);
6566

66-
Preprocessor::Preprocessor(const Settings& settings, ErrorLogger &errorLogger) : mSettings(settings), mErrorLogger(errorLogger)
67-
{}
67+
Preprocessor::Preprocessor(const Settings& settings, ErrorLogger &errorLogger, Standards::Language lang)
68+
: mSettings(settings)
69+
, mErrorLogger(errorLogger)
70+
, mLang(lang)
71+
{
72+
assert(mLang != Standards::Language::None);
73+
}
6874

6975
Preprocessor::~Preprocessor()
7076
{
@@ -688,7 +694,7 @@ static void splitcfg(const std::string &cfg, std::list<std::string> &defines, co
688694
}
689695
}
690696

691-
static simplecpp::DUI createDUI(const Settings &mSettings, const std::string &cfg, const std::string &filename)
697+
static simplecpp::DUI createDUI(const Settings &mSettings, const std::string &cfg, Standards::Language lang)
692698
{
693699
// TODO: make it possible to specify platform-dependent sizes
694700
simplecpp::DUI dui;
@@ -716,8 +722,6 @@ static simplecpp::DUI createDUI(const Settings &mSettings, const std::string &cf
716722
dui.includePaths = mSettings.includePaths; // -I
717723
dui.includes = mSettings.userIncludes; // --include
718724
// TODO: use mSettings.standards.stdValue instead
719-
// TODO: error out on unknown language?
720-
const Standards::Language lang = Path::identify(filename, mSettings.cppHeaderProbe);
721725
if (lang == Standards::Language::CPP) {
722726
dui.std = mSettings.standards.getCPP();
723727
splitcfg(mSettings.platform.getLimitsDefines(Standards::getCPP(dui.std)), dui.defines, "");
@@ -773,7 +777,7 @@ void Preprocessor::handleErrors(const simplecpp::OutputList& outputList, bool th
773777

774778
bool Preprocessor::loadFiles(const simplecpp::TokenList &rawtokens, std::vector<std::string> &files)
775779
{
776-
const simplecpp::DUI dui = createDUI(mSettings, "", files[0]);
780+
const simplecpp::DUI dui = createDUI(mSettings, "", mLang);
777781

778782
simplecpp::OutputList outputList;
779783
mTokenLists = simplecpp::load(rawtokens, files, dui, &outputList);
@@ -812,7 +816,7 @@ void Preprocessor::setPlatformInfo(simplecpp::TokenList &tokens, const Settings&
812816

813817
simplecpp::TokenList Preprocessor::preprocess(const simplecpp::TokenList &tokens1, const std::string &cfg, std::vector<std::string> &files, bool throwError)
814818
{
815-
const simplecpp::DUI dui = createDUI(mSettings, cfg, files[0]);
819+
const simplecpp::DUI dui = createDUI(mSettings, cfg, mLang);
816820

817821
simplecpp::OutputList outputList;
818822
std::list<simplecpp::MacroUsage> macroUsage;
@@ -927,7 +931,7 @@ void Preprocessor::missingInclude(const std::string &filename, unsigned int line
927931

928932
void Preprocessor::getErrorMessages(ErrorLogger &errorLogger, const Settings &settings)
929933
{
930-
Preprocessor preprocessor(settings, errorLogger);
934+
Preprocessor preprocessor(settings, errorLogger, Standards::Language::CPP);
931935
preprocessor.missingInclude("", 1, "", UserHeader);
932936
preprocessor.missingInclude("", 1, "", SystemHeader);
933937
preprocessor.error("", 1, "#error message"); // #error ..

lib/preprocessor.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
//---------------------------------------------------------------------------
2323

2424
#include "config.h"
25+
#include "standards.h"
2526

2627
#include <cstddef>
2728
#include <cstdint>
@@ -108,7 +109,7 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
108109
/** character that is inserted in expanded macros */
109110
static char macroChar;
110111

111-
explicit Preprocessor(const Settings& settings, ErrorLogger &errorLogger);
112+
explicit Preprocessor(const Settings& settings, ErrorLogger &errorLogger, Standards::Language lang);
112113
virtual ~Preprocessor();
113114

114115
void inlineSuppressions(const simplecpp::TokenList &tokens, SuppressionList &suppressions);
@@ -180,6 +181,7 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
180181

181182
/** filename for cpp/c file - useful when reporting errors */
182183
std::string mFile0;
184+
Standards::Language mLang{Standards::Language::None};
183185

184186
/** simplecpp tracking info */
185187
std::list<simplecpp::MacroUsage> mMacroUsage;

test/cli/other_test.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3563,4 +3563,48 @@ def test_suppress_unmatched_wildcard_unchecked(tmp_path):
35633563
'tes?.c:-1:0: information: Unmatched suppression: id [unmatchedSuppression]',
35643564
'*:-1:0: information: Unmatched suppression: id2 [unmatchedSuppression]',
35653565
'test*.c:-1:0: information: Unmatched suppression: * [unmatchedSuppression]'
3566-
]
3566+
]
3567+
3568+
3569+
def test_preprocess_enforced_c(tmp_path): # #10989
3570+
test_file = tmp_path / 'test.cpp'
3571+
with open(test_file, 'wt') as f:
3572+
f.write(
3573+
"""#ifdef __cplusplus
3574+
#error "err"
3575+
#endif""")
3576+
3577+
args = [
3578+
'-q',
3579+
'--template=simple',
3580+
'--language=c',
3581+
str(test_file)
3582+
]
3583+
3584+
exitcode, stdout, stderr = cppcheck(args)
3585+
assert exitcode == 0, stdout if stdout else stderr
3586+
assert stdout.splitlines() == []
3587+
assert stderr.splitlines() == []
3588+
3589+
3590+
def test_preprocess_enforced_cpp(tmp_path): # #10989
3591+
test_file = tmp_path / 'test.c'
3592+
with open(test_file, 'wt') as f:
3593+
f.write(
3594+
"""#ifdef __cplusplus
3595+
#error "err"
3596+
#endif""")
3597+
3598+
args = [
3599+
'-q',
3600+
'--template=simple',
3601+
'--language=c++',
3602+
str(test_file)
3603+
]
3604+
3605+
exitcode, stdout, stderr = cppcheck(args)
3606+
assert exitcode == 0, stdout if stdout else stderr
3607+
assert stdout.splitlines() == []
3608+
assert stderr.splitlines() == [
3609+
'{}:2:2: error: #error "err" [preprocessorErrorDirective]'.format(test_file)
3610+
]

test/helpers.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ std::map<std::string, std::string> PreprocessorHelper::getcode(const Settings& s
136136

137137
std::istringstream istr(code);
138138
simplecpp::TokenList tokens(istr, files, Path::simplifyPath(filename), &outputList);
139-
Preprocessor preprocessor(settings, errorlogger);
139+
Preprocessor preprocessor(settings, errorlogger, Path::identify(tokens.getFiles()[0], false));
140140
if (inlineSuppression)
141141
preprocessor.inlineSuppressions(tokens, *inlineSuppression);
142142
preprocessor.removeComments(tokens);
@@ -168,7 +168,7 @@ void SimpleTokenizer2::preprocess(const char code[], std::vector<std::string> &f
168168
std::istringstream istr(code);
169169
const simplecpp::TokenList tokens1(istr, files, file0);
170170

171-
Preprocessor preprocessor(tokenizer.getSettings(), errorlogger);
171+
Preprocessor preprocessor(tokenizer.getSettings(), errorlogger, Path::identify(tokens1.getFiles()[0], false));
172172
simplecpp::TokenList tokens2 = preprocessor.preprocess(tokens1, "", files, true);
173173

174174
// Tokenizer..

test/testpreprocessor.cpp

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "platform.h"
2626
#include "preprocessor.h"
2727
#include "settings.h"
28+
#include "standards.h"
2829
#include "suppressions.h"
2930
#include "tokenlist.h"
3031
#include "fixture.h"
@@ -54,7 +55,7 @@ class TestPreprocessor : public TestFixture {
5455
simplecpp::OutputList outputList;
5556
std::vector<std::string> files;
5657
const simplecpp::TokenList tokens1 = simplecpp::TokenList(istr, files, "file.cpp", &outputList);
57-
Preprocessor p(settingsDefault, errorLogger);
58+
Preprocessor p(settingsDefault, errorLogger, Path::identify(tokens1.getFiles()[0], false));
5859
simplecpp::TokenList tokens2 = p.preprocess(tokens1, "", files, true);
5960
p.reportOutput(outputList, true);
6061
return tokens2.stringify();
@@ -87,7 +88,7 @@ class TestPreprocessor : public TestFixture {
8788
std::istringstream istr(code);
8889
const simplecpp::TokenList tokens1(istr, files, "test.cpp");
8990

90-
const Preprocessor preprocessor(settingsDefault, errorLogger);
91+
const Preprocessor preprocessor(settingsDefault, errorLogger, Path::identify(tokens1.getFiles()[0], false));
9192
return preprocessor.getRemarkComments(tokens1);
9293
}
9394

@@ -301,11 +302,12 @@ class TestPreprocessor : public TestFixture {
301302
settings.userDefines = arg + 2;
302303
if (arg && std::strncmp(arg,"-U",2)==0)
303304
settings.userUndefs.insert(arg+2);
304-
Preprocessor preprocessor(settings, *this);
305305
std::vector<std::string> files;
306306
std::istringstream istr(filedata);
307+
// TODO: this adds an empty filename
307308
simplecpp::TokenList tokens(istr,files);
308309
tokens.removeComments();
310+
Preprocessor preprocessor(settings, *this, Standards::Language::C); // TODO: do we need to consider #file?
309311
const std::set<std::string> configs = preprocessor.getConfigs(tokens);
310312
std::string ret;
311313
for (const std::string & config : configs)
@@ -314,11 +316,12 @@ class TestPreprocessor : public TestFixture {
314316
}
315317

316318
std::size_t getHash(const char filedata[]) {
317-
Preprocessor preprocessor(settingsDefault, *this);
318319
std::vector<std::string> files;
319320
std::istringstream istr(filedata);
321+
// TODO: this adds an empty filename
320322
simplecpp::TokenList tokens(istr,files);
321323
tokens.removeComments();
324+
Preprocessor preprocessor(settingsDefault, *this, Standards::Language::C); // TODO: do we need to consider #file?
322325
return preprocessor.calculateHash(tokens, "");
323326
}
324327

@@ -478,15 +481,15 @@ class TestPreprocessor : public TestFixture {
478481
{
479482
const Settings settings = settingsBuilder().platform(Platform::Type::Unix32).build();
480483
Preprocessor::setPlatformInfo(tokens, settings);
481-
Preprocessor preprocessor(settings, *this);
484+
Preprocessor preprocessor(settings, *this, Path::identify(tokens.getFiles()[0], false));
482485
ASSERT_EQUALS("\n1", preprocessor.getcode(tokens, "", files, false));
483486
}
484487

485488
// preprocess code with unix64 platform..
486489
{
487490
const Settings settings = settingsBuilder().platform(Platform::Type::Unix64).build();
488491
Preprocessor::setPlatformInfo(tokens, settings);
489-
Preprocessor preprocessor(settings, *this);
492+
Preprocessor preprocessor(settings, *this, Path::identify(tokens.getFiles()[0], false));
490493
ASSERT_EQUALS("\n\n\n2", preprocessor.getcode(tokens, "", files, false));
491494
}
492495
}
@@ -1211,7 +1214,7 @@ class TestPreprocessor : public TestFixture {
12111214
"#undef z\n"
12121215
"int z;\n"
12131216
"z = 0;\n";
1214-
ASSERT_EQUALS("\n\nint z ;\nz = 0 ;", PreprocessorHelper::getcode(settings0, *this, filedata, "", ""));
1217+
ASSERT_EQUALS("\n\nint z ;\nz = 0 ;", PreprocessorHelper::getcode(settings0, *this, filedata, "", "test.c"));
12151218
}
12161219
}
12171220

@@ -1629,14 +1632,14 @@ class TestPreprocessor : public TestFixture {
16291632
"#if A\n"
16301633
"FOO\n"
16311634
"#endif";
1632-
ASSERT_EQUALS("", PreprocessorHelper::getcode(settings0, *this, filedata,"",""));
1635+
ASSERT_EQUALS("", PreprocessorHelper::getcode(settings0, *this, filedata,"","test.c"));
16331636
}
16341637
{
16351638
const char filedata[] = "#define A 1\n"
16361639
"#if A==1\n"
16371640
"FOO\n"
16381641
"#endif";
1639-
ASSERT_EQUALS("\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"",""));
1642+
ASSERT_EQUALS("\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"","test.c"));
16401643
}
16411644
}
16421645

@@ -1646,23 +1649,23 @@ class TestPreprocessor : public TestFixture {
16461649
"#if (B==A) || (B==C)\n"
16471650
"FOO\n"
16481651
"#endif";
1649-
ASSERT_EQUALS("\n\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"",""));
1652+
ASSERT_EQUALS("\n\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"","test.c"));
16501653
}
16511654

16521655
void define_if3() {
16531656
const char filedata[] = "#define A 0\n"
16541657
"#if (A==0)\n"
16551658
"FOO\n"
16561659
"#endif";
1657-
ASSERT_EQUALS("\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"",""));
1660+
ASSERT_EQUALS("\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"","test.c"));
16581661
}
16591662

16601663
void define_if4() {
16611664
const char filedata[] = "#define X +123\n"
16621665
"#if X==123\n"
16631666
"FOO\n"
16641667
"#endif";
1665-
ASSERT_EQUALS("\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"",""));
1668+
ASSERT_EQUALS("\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"","test.c"));
16661669
}
16671670

16681671
void define_if5() { // #4516 - #define B (A & 0x00f0)
@@ -1672,7 +1675,7 @@ class TestPreprocessor : public TestFixture {
16721675
"#if B==0x0010\n"
16731676
"FOO\n"
16741677
"#endif";
1675-
ASSERT_EQUALS("\n\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"",""));
1678+
ASSERT_EQUALS("\n\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"","test.c"));
16761679
}
16771680
{
16781681
const char filedata[] = "#define A 0x00f0\n"
@@ -1681,14 +1684,14 @@ class TestPreprocessor : public TestFixture {
16811684
"#if C==0x0010\n"
16821685
"FOO\n"
16831686
"#endif";
1684-
ASSERT_EQUALS("\n\n\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"",""));
1687+
ASSERT_EQUALS("\n\n\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"","test.c"));
16851688
}
16861689
{
16871690
const char filedata[] = "#define A (1+A)\n" // don't hang for recursive macros
16881691
"#if A==1\n"
16891692
"FOO\n"
16901693
"#endif";
1691-
ASSERT_EQUALS("\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"",""));
1694+
ASSERT_EQUALS("\n\nFOO", PreprocessorHelper::getcode(settings0, *this, filedata,"","test.c"));
16921695
}
16931696
}
16941697

test/testtokenize.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,11 @@ class TestTokenizer : public TestFixture {
550550
}
551551

552552
void directiveDump(const char filedata[], const char filename[], const Settings& settings, std::ostream& ostr) {
553-
Preprocessor preprocessor(settings, *this);
554553
std::istringstream istr(filedata);
555554
simplecpp::OutputList outputList;
556555
std::vector<std::string> files;
557556
const simplecpp::TokenList tokens1(istr, files, filename, &outputList);
557+
Preprocessor preprocessor(settings, *this, Path::identify(tokens1.getFiles()[0], false));
558558
std::list<Directive> directives = preprocessor.createDirectives(tokens1);
559559

560560
TokenList tokenlist{&settings};
@@ -8573,7 +8573,7 @@ class TestTokenizerCompileLimits : public TestFixture
85738573
std::vector<std::string> files;
85748574
const simplecpp::TokenList tokens1(fin, files, "", &outputList);
85758575
const std::string filedata = tokens1.stringify();
8576-
const std::string code = PreprocessorHelper::getcode(settingsDefault, *this, filedata, "", "");
8576+
const std::string code = PreprocessorHelper::getcode(settingsDefault, *this, filedata, "", "test.c");
85778577

85788578
ASSERT_THROW_INTERNAL_EQUALS(tokenizeAndStringify(code), AST, "maximum AST depth exceeded");
85798579
}

test/testtokenlist.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class TestTokenList : public TestFixture {
165165
std::istringstream istr(code);
166166
std::vector<std::string> files;
167167
simplecpp::TokenList tokens1(istr, files, "poll.h", nullptr);
168-
Preprocessor preprocessor(settingsDefault, *this);
168+
Preprocessor preprocessor(settingsDefault, *this, Path::identify(tokens1.getFiles()[0], false));
169169
simplecpp::TokenList tokensP = preprocessor.preprocess(tokens1, "", files, true);
170170
TokenList tokenlist(&settingsDefault);
171171
tokenlist.createTokens(std::move(tokensP)); // do not assert

0 commit comments

Comments
 (0)