Skip to content

Commit 2e4ea69

Browse files
committed
test
1 parent 5ac33c8 commit 2e4ea69

File tree

7 files changed

+189
-4
lines changed

7 files changed

+189
-4
lines changed

cli/cmdlineparser.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
11021102
mSettings.plistOutput = std::move(path);
11031103
}
11041104

1105+
else if (std::strcmp(argv[i], "-pch") == 0)
1106+
mSettings.precompileHeader = true;
1107+
11051108
// Special Cppcheck Premium options
11061109
else if ((std::strncmp(argv[i], "--premium=", 10) == 0 || std::strncmp(argv[i], "--premium-", 10) == 0) && isCppcheckPremium()) {
11071110
// valid options --premium=..

externals/simplecpp/simplecpp.cpp

+161-3
Original file line numberDiff line numberDiff line change
@@ -1681,6 +1681,13 @@ namespace simplecpp {
16811681
return invalidHashHash(loc, macroName, "Combining '\\"+ tokenA->str()+ "' and '"+ strAB.substr(tokenA->str().size()) + "' yields universal character '\\" + strAB + "'. This is undefined behavior according to C standard chapter 5.1.1.2, paragraph 4.");
16821682
}
16831683
};
1684+
1685+
std::string dump() const {
1686+
std::string ret;
1687+
for (const Token *tok = nameTokDef; sameline(nameTokDef,tok); tok = tok->next)
1688+
ret += "\n" + toString(tok->location.col) + ":" + tok->str();
1689+
return ret.substr(1);
1690+
}
16841691
private:
16851692
/** Create new token where Token::macro is set for replaced tokens */
16861693
Token *newMacroToken(const TokenString &str, const Location &loc, bool replaced, const Token *expandedFromToken=nullptr) const {
@@ -3245,7 +3252,18 @@ std::map<std::string, simplecpp::TokenList*> simplecpp::load(const simplecpp::To
32453252
continue;
32463253

32473254
std::ifstream f;
3248-
const std::string header2 = openHeader(f,dui,sourcefile,header,systemheader);
3255+
std::string header2;
3256+
if (filenames.size() == 1) {
3257+
header2 = openHeader(f,dui,sourcefile,header + ".pch",systemheader);
3258+
if (f.is_open()) {
3259+
const std::string header2WithoutPch = header2.substr(0, header2.size() - 4);
3260+
TokenList *tokens = new TokenList(header2WithoutPch, filenames, outputList);
3261+
ret[header2WithoutPch] = tokens;
3262+
continue;
3263+
}
3264+
}
3265+
if (!f.is_open())
3266+
header2 = openHeader(f,dui,sourcefile,header,systemheader);
32493267
if (!f.is_open())
32503268
continue;
32513269
f.close();
@@ -3314,8 +3332,82 @@ static std::string getTimeDefine(const struct tm *timep)
33143332
return std::string("\"").append(buf).append("\"");
33153333
}
33163334

3317-
void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector<std::string> &files, std::map<std::string, simplecpp::TokenList *> &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list<simplecpp::MacroUsage> *macroUsage, std::list<simplecpp::IfCond> *ifCond)
3335+
static void loadPrecompiledHeader(simplecpp::TokenList& output,
3336+
const std::string& pch,
3337+
std::istream& f,
3338+
std::vector<std::string>& files,
3339+
std::map<std::string, simplecpp::TokenList *> &filedata,
3340+
simplecpp::MacroMap& macros)
3341+
{
3342+
simplecpp::TokenList * const macroTokens = new simplecpp::TokenList(files);
3343+
filedata[pch] = macroTokens;
3344+
enum { FILES, TOKENS, MACROS } section = FILES;
3345+
simplecpp::Location loc(files);
3346+
std::string line;
3347+
while (std::getline(f,line)) {
3348+
if (line == "files") {
3349+
section = FILES;
3350+
continue;
3351+
}
3352+
if (line == "tokens") {
3353+
section = TOKENS;
3354+
continue;
3355+
}
3356+
if (line == "[MACRO]") {
3357+
section = MACROS;
3358+
loc.fileIndex = 1;
3359+
loc.line = 1;
3360+
if (macroTokens->cback())
3361+
loc.line = macroTokens->cback()->location.line + 1;
3362+
loc.col = 1;
3363+
macroTokens->push_back(new simplecpp::Token("#", loc));
3364+
loc.col = 2;
3365+
macroTokens->push_back(new simplecpp::Token("define", loc));
3366+
continue;
3367+
}
3368+
if (section == FILES) {
3369+
std::string::size_type pos = line.find(':');
3370+
if (pos >= 1 && pos < line.size())
3371+
files.push_back(line.substr(pos+1));
3372+
continue;
3373+
}
3374+
if (section == TOKENS) {
3375+
std::string::size_type pos = 0;
3376+
while (pos < line.size() && line[pos] != ':') {
3377+
char c = line[pos++];
3378+
int value = 0;
3379+
while (pos < line.size() && std::isdigit(line[pos]))
3380+
value = value * 10 + line[pos++] - '0';
3381+
if (c == 'f')
3382+
loc.fileIndex = value;
3383+
else if (c == 'l')
3384+
loc.line = value;
3385+
else if (c == 'c')
3386+
loc.col = value;
3387+
}
3388+
if (pos + 1 < line.size() && line[pos] == ':')
3389+
output.push_back(new simplecpp::Token(line.substr(pos + 1), loc));
3390+
continue;
3391+
}
3392+
if (section == MACROS) {
3393+
const std::string::size_type pos = line.find(':');
3394+
loc.col = std::atoi(line.substr(0, pos).c_str());
3395+
macroTokens->push_back(new simplecpp::Token(line.substr(pos + 1), loc));
3396+
}
3397+
}
3398+
for (const simplecpp::Token* tok = macroTokens->cfront(); tok; tok = tok->next) {
3399+
if (tok->op == '#' && tok->next && tok->next->str() == DEFINE) {
3400+
simplecpp::Macro macro(tok, files);
3401+
if (macro.name() != "__DATE__" && macro.name() != "__TIME__")
3402+
macros.insert(std::pair<simplecpp::TokenString,simplecpp::Macro>(macro.name(), macro));
3403+
}
3404+
}
3405+
}
3406+
3407+
static void simplecppPreprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector<std::string> &files, std::map<std::string, simplecpp::TokenList *> &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list<simplecpp::MacroUsage> *macroUsage, std::list<simplecpp::IfCond> *ifCond, simplecpp::MacroMap& macros)
33183408
{
3409+
using namespace simplecpp;
3410+
33193411
#ifdef SIMPLECPP_WINDOWS
33203412
if (dui.clearIncludeCache)
33213413
nonExistingFilesCache.clear();
@@ -3347,7 +3439,6 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
33473439
std::vector<std::string> dummy;
33483440

33493441
const bool hasInclude = isCpp17OrLater(dui);
3350-
MacroMap macros;
33513442
for (std::list<std::string>::const_iterator it = dui.defines.begin(); it != dui.defines.end(); ++it) {
33523443
const std::string &macrostr = *it;
33533444
const std::string::size_type eq = macrostr.find('=');
@@ -3534,6 +3625,13 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
35343625
if (header2.empty()) {
35353626
// try to load file..
35363627
std::ifstream f;
3628+
if (output.empty()) {
3629+
header2 = openHeader(f, dui, rawtok->location.file(), header + ".pch", systemheader);
3630+
if (f.is_open()) {
3631+
loadPrecompiledHeader(output, header + ".pch", f, files, filedata, macros);
3632+
continue;
3633+
}
3634+
}
35373635
header2 = openHeader(f, dui, rawtok->location.file(), header, systemheader);
35383636
if (f.is_open()) {
35393637
f.close();
@@ -3792,6 +3890,66 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
37923890
}
37933891
}
37943892

3893+
void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector<std::string> &files, std::map<std::string, simplecpp::TokenList *> &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list<simplecpp::MacroUsage> *macroUsage, std::list<simplecpp::IfCond> *ifCond)
3894+
{
3895+
MacroMap macroMap;
3896+
simplecppPreprocess(output,
3897+
rawtokens,
3898+
files,
3899+
filedata,
3900+
dui,
3901+
outputList,
3902+
macroUsage,
3903+
ifCond,
3904+
macroMap);
3905+
}
3906+
3907+
3908+
std::string simplecpp::precompileHeader(const TokenList &rawtokens, std::vector<std::string> &files, const DUI &dui, OutputList *outputList)
3909+
{
3910+
std::map<std::string, TokenList*> filedata;
3911+
simplecpp::TokenList output(files);
3912+
std::list<simplecpp::MacroUsage> macroUsage;
3913+
std::list<simplecpp::IfCond> ifCond;
3914+
simplecpp::MacroMap macroMap;
3915+
simplecppPreprocess(output,
3916+
rawtokens,
3917+
files,
3918+
filedata,
3919+
dui,
3920+
outputList,
3921+
&macroUsage,
3922+
&ifCond,
3923+
macroMap);
3924+
3925+
std::string ret;
3926+
ret = "files\n";
3927+
for (size_t i = 0; i < files.size(); ++i)
3928+
ret += toString(i) + ":" + files[i] + "\n";
3929+
ret += "tokens\n";
3930+
unsigned int fileIndex = 0;
3931+
unsigned int line = 0;
3932+
unsigned int col = 0;
3933+
for (const simplecpp::Token *tok = output.cfront(); tok; tok = tok->next) {
3934+
if (tok->location.fileIndex != fileIndex) {
3935+
fileIndex = tok->location.fileIndex;
3936+
ret += "f" + toString(fileIndex);
3937+
}
3938+
if (tok->location.line != line) {
3939+
line = tok->location.line;
3940+
ret += "l" + toString(line);
3941+
}
3942+
if (tok->location.col != col) {
3943+
col = tok->location.col;
3944+
ret += "c" + toString(col);
3945+
}
3946+
ret += ":" + tok->str() + "\n";
3947+
}
3948+
for (simplecpp::MacroMap::const_iterator it = macroMap.begin(); it != macroMap.end(); ++it)
3949+
ret += "[MACRO]\n" + it->second.dump() + "\n";
3950+
return ret;
3951+
}
3952+
37953953
void simplecpp::cleanup(std::map<std::string, TokenList*> &filedata)
37963954
{
37973955
for (std::map<std::string, TokenList*>::iterator it = filedata.begin(); it != filedata.end(); ++it)

externals/simplecpp/simplecpp.h

+10
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,16 @@ namespace simplecpp {
365365
*/
366366
SIMPLECPP_LIB void preprocess(TokenList &output, const TokenList &rawtokens, std::vector<std::string> &files, std::map<std::string, TokenList*> &filedata, const DUI &dui, OutputList *outputList = nullptr, std::list<MacroUsage> *macroUsage = nullptr, std::list<IfCond> *ifCond = nullptr);
367367

368+
/**
369+
* Precompile header
370+
* @param rawtokens Raw tokenlist for top sourcefile
371+
* @param files internal data of simplecpp
372+
* @param dui defines, undefs, and include paths
373+
* @param outputList output: list that will receive output messages
374+
* @return precompiled header data
375+
*/
376+
SIMPLECPP_LIB std::string precompileHeader(const TokenList &rawtokens, std::vector<std::string> &files, const DUI &dui, OutputList *outputList = nullptr);
377+
368378
/**
369379
* Deallocate data
370380
*/

lib/cppcheck.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,15 @@ unsigned int CppCheck::checkFile(const FileWithDetails& file, const std::string
957957
return mLogger->exitcode();
958958
}
959959

960+
if (mSettings.precompileHeader) {
961+
std::ofstream fout(file.spath() + ".pch");
962+
if (fout.is_open()) {
963+
const simplecpp::DUI& dui = Preprocessor::createDUI(mSettings, "", file.spath());
964+
fout << simplecpp::precompileHeader(tokens1, files, dui, &outputList);
965+
return mLogger->exitcode();
966+
}
967+
}
968+
960969
Preprocessor preprocessor(mSettings, mErrorLogger);
961970

962971
if (!preprocessor.loadFiles(tokens1, files))

lib/preprocessor.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ static void splitcfg(const std::string &cfg, std::list<std::string> &defines, co
688688
}
689689
}
690690

691-
static simplecpp::DUI createDUI(const Settings &mSettings, const std::string &cfg, const std::string &filename)
691+
simplecpp::DUI Preprocessor::createDUI(const Settings &mSettings, const std::string &cfg, const std::string &filename)
692692
{
693693
// TODO: make it possible to specify platform-dependent sizes
694694
simplecpp::DUI dui;

lib/preprocessor.h

+2
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ class CPPCHECKLIB WARN_UNUSED Preprocessor {
125125

126126
static void setPlatformInfo(simplecpp::TokenList &tokens, const Settings& settings);
127127

128+
static simplecpp::DUI createDUI(const Settings &mSettings, const std::string &cfg, const std::string &filename);
129+
128130
simplecpp::TokenList preprocess(const simplecpp::TokenList &tokens1, const std::string &cfg, std::vector<std::string> &files, bool throwError = false);
129131

130132
std::string getcode(const simplecpp::TokenList &tokens1, const std::string &cfg, std::vector<std::string> &files, bool writeLocations);

lib/settings.h

+3
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ class CPPCHECKLIB WARN_UNUSED Settings {
307307
/** Is checker id enabled by premiumArgs */
308308
bool isPremiumEnabled(const char id[]) const;
309309

310+
/** @brief Precompile a header file into a .pch file */
311+
bool precompileHeader{};
312+
310313
/** @brief Using -E for debugging purposes */
311314
bool preprocessOnly{};
312315

0 commit comments

Comments
 (0)