Skip to content

Commit d05b68d

Browse files
authored
bumped simplecpp to 1.1.5 / improved testing (and output) / added TODOs (#6767)
1 parent 7fa2eb5 commit d05b68d

File tree

8 files changed

+228
-43
lines changed

8 files changed

+228
-43
lines changed

.github/workflows/CI-unixish.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ jobs:
462462
# TODO: move to scriptcheck.yml so these are tested with all Python versions?
463463
- name: Test addons
464464
run: |
465+
set -x
465466
./cppcheck --error-exitcode=1 --inline-suppr --addon=threadsafety addons/test/threadsafety
466467
./cppcheck --error-exitcode=1 --inline-suppr --addon=threadsafety --std=c++03 addons/test/threadsafety
467468
./cppcheck --error-exitcode=1 --inline-suppr --addon=misra addons/test/misra/crash*.c

.github/workflows/CI-windows.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ jobs:
194194
- name: Test addons
195195
if: matrix.config == 'release'
196196
run: |
197+
echo on
197198
.\cppcheck --addon=threadsafety addons\test\threadsafety || exit /b !errorlevel!
198199
.\cppcheck --addon=threadsafety --std=c++03 addons\test\threadsafety || exit /b !errorlevel!
199200
.\cppcheck --addon=misra --enable=style --inline-suppr --enable=information --error-exitcode=1 addons\test\misra\misra-ctu-*-test.c || exit /b !errorlevel!

externals/simplecpp/simplecpp.cpp

Lines changed: 153 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <exception>
2323
#include <fstream>
2424
#include <iostream>
25+
#include <istream>
2526
#include <limits>
2627
#include <list>
2728
#include <map>
@@ -377,6 +378,42 @@ class StdIStream : public simplecpp::TokenList::Stream {
377378
std::istream &istr;
378379
};
379380

381+
class StdCharBufStream : public simplecpp::TokenList::Stream {
382+
public:
383+
// cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members
384+
StdCharBufStream(const unsigned char* str, std::size_t size)
385+
: str(str)
386+
, size(size)
387+
, pos(0)
388+
, lastStatus(0)
389+
{
390+
init();
391+
}
392+
393+
virtual int get() OVERRIDE {
394+
if (pos >= size)
395+
return lastStatus = EOF;
396+
return str[pos++];
397+
}
398+
virtual int peek() OVERRIDE {
399+
if (pos >= size)
400+
return lastStatus = EOF;
401+
return str[pos];
402+
}
403+
virtual void unget() OVERRIDE {
404+
--pos;
405+
}
406+
virtual bool good() OVERRIDE {
407+
return lastStatus != EOF;
408+
}
409+
410+
private:
411+
const unsigned char *str;
412+
const std::size_t size;
413+
std::size_t pos;
414+
int lastStatus;
415+
};
416+
380417
class FileStream : public simplecpp::TokenList::Stream {
381418
public:
382419
// cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members
@@ -442,6 +479,20 @@ simplecpp::TokenList::TokenList(std::istream &istr, std::vector<std::string> &fi
442479
readfile(stream,filename,outputList);
443480
}
444481

482+
simplecpp::TokenList::TokenList(const unsigned char* data, std::size_t size, std::vector<std::string> &filenames, const std::string &filename, OutputList *outputList)
483+
: frontToken(nullptr), backToken(nullptr), files(filenames)
484+
{
485+
StdCharBufStream stream(data, size);
486+
readfile(stream,filename,outputList);
487+
}
488+
489+
simplecpp::TokenList::TokenList(const char* data, std::size_t size, std::vector<std::string> &filenames, const std::string &filename, OutputList *outputList)
490+
: frontToken(nullptr), backToken(nullptr), files(filenames)
491+
{
492+
StdCharBufStream stream(reinterpret_cast<const unsigned char*>(data), size);
493+
readfile(stream,filename,outputList);
494+
}
495+
445496
simplecpp::TokenList::TokenList(const std::string &filename, std::vector<std::string> &filenames, OutputList *outputList)
446497
: frontToken(nullptr), backToken(nullptr), files(filenames)
447498
{
@@ -1447,8 +1498,7 @@ namespace simplecpp {
14471498

14481499
Macro(const std::string &name, const std::string &value, std::vector<std::string> &f) : nameTokDef(nullptr), files(f), tokenListDefine(f), valueDefinedInCode_(false) {
14491500
const std::string def(name + ' ' + value);
1450-
std::istringstream istr(def);
1451-
StdIStream stream(istr);
1501+
StdCharBufStream stream(reinterpret_cast<const unsigned char*>(def.data()), def.size());
14521502
tokenListDefine.readfile(stream);
14531503
if (!parseDefine(tokenListDefine.cfront()))
14541504
throw std::runtime_error("bad macro syntax. macroname=" + name + " value=" + value);
@@ -3310,11 +3360,24 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
33103360
macros.insert(std::make_pair("__TIME__", Macro("__TIME__", getTimeDefine(&ltime), dummy)));
33113361

33123362
if (!dui.std.empty()) {
3313-
std::string std_def = simplecpp::getCStdString(dui.std);
3314-
if (!std_def.empty()) {
3315-
macros.insert(std::make_pair("__STDC_VERSION__", Macro("__STDC_VERSION__", std_def, dummy)));
3363+
const cstd_t c_std = simplecpp::getCStd(dui.std);
3364+
if (c_std != CUnknown) {
3365+
const std::string std_def = simplecpp::getCStdString(c_std);
3366+
if (!std_def.empty())
3367+
macros.insert(std::make_pair("__STDC_VERSION__", Macro("__STDC_VERSION__", std_def, dummy)));
33163368
} else {
3317-
std_def = simplecpp::getCppStdString(dui.std);
3369+
const cppstd_t cpp_std = simplecpp::getCppStd(dui.std);
3370+
if (cpp_std == CPPUnknown) {
3371+
if (outputList) {
3372+
simplecpp::Output err(files);
3373+
err.type = Output::DUI_ERROR;
3374+
err.msg = "unknown standard specified: '" + dui.std + "'";
3375+
outputList->push_back(err);
3376+
}
3377+
output.clear();
3378+
return;
3379+
}
3380+
const std::string std_def = simplecpp::getCppStdString(cpp_std);
33183381
if (!std_def.empty())
33193382
macros.insert(std::make_pair("__cplusplus", Macro("__cplusplus", std_def, dummy)));
33203383
}
@@ -3463,7 +3526,8 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
34633526
std::ifstream f;
34643527
header2 = openHeader(f, dui, rawtok->location.file(), header, systemheader);
34653528
if (f.is_open()) {
3466-
TokenList * const tokens = new TokenList(f, files, header2, outputList);
3529+
f.close();
3530+
TokenList * const tokens = new TokenList(header2, files, outputList);
34673531
if (dui.removeComments)
34683532
tokens->removeComments();
34693533
filedata[header2] = tokens;
@@ -3726,56 +3790,105 @@ void simplecpp::cleanup(std::map<std::string, TokenList*> &filedata)
37263790
filedata.clear();
37273791
}
37283792

3729-
std::string simplecpp::getCStdString(const std::string &std)
3793+
simplecpp::cstd_t simplecpp::getCStd(const std::string &std)
37303794
{
3731-
if (std == "c90" || std == "c89" || std == "iso9899:1990" || std == "iso9899:199409" || std == "gnu90" || std == "gnu89") {
3732-
// __STDC_VERSION__ is not set for C90 although the macro was added in the 1994 amendments
3733-
return "";
3734-
}
3795+
if (std == "c90" || std == "c89" || std == "iso9899:1990" || std == "iso9899:199409" || std == "gnu90" || std == "gnu89")
3796+
return C89;
37353797
if (std == "c99" || std == "c9x" || std == "iso9899:1999" || std == "iso9899:199x" || std == "gnu99"|| std == "gnu9x")
3736-
return "199901L";
3798+
return C99;
37373799
if (std == "c11" || std == "c1x" || std == "iso9899:2011" || std == "gnu11" || std == "gnu1x")
3738-
return "201112L";
3800+
return C11;
37393801
if (std == "c17" || std == "c18" || std == "iso9899:2017" || std == "iso9899:2018" || std == "gnu17"|| std == "gnu18")
3740-
return "201710L";
3741-
if (std == "c23" || std == "gnu23" || std == "c2x" || std == "gnu2x") {
3742-
// supported by GCC 9+ and Clang 9+
3743-
// Clang 9, 10, 11, 12, 13 return "201710L"
3744-
// Clang 14, 15, 16, 17 return "202000L"
3745-
// Clang 9, 10, 11, 12, 13, 14, 15, 16, 17 do not support "c23" and "gnu23"
3746-
return "202311L";
3802+
return C17;
3803+
if (std == "c23" || std == "gnu23" || std == "c2x" || std == "gnu2x")
3804+
return C23;
3805+
return CUnknown;
3806+
}
3807+
3808+
std::string simplecpp::getCStdString(cstd_t std)
3809+
{
3810+
switch (std)
3811+
{
3812+
case C89:
3813+
// __STDC_VERSION__ is not set for C90 although the macro was added in the 1994 amendments
3814+
return "";
3815+
case C99:
3816+
return "199901L";
3817+
case C11:
3818+
return "201112L";
3819+
case C17:
3820+
return "201710L";
3821+
case C23:
3822+
// supported by GCC 9+ and Clang 9+
3823+
// Clang 9, 10, 11, 12, 13 return "201710L"
3824+
// Clang 14, 15, 16, 17 return "202000L"
3825+
// Clang 9, 10, 11, 12, 13, 14, 15, 16, 17 do not support "c23" and "gnu23"
3826+
return "202311L";
3827+
case CUnknown:
3828+
return "";
37473829
}
37483830
return "";
37493831
}
37503832

3751-
std::string simplecpp::getCppStdString(const std::string &std)
3833+
std::string simplecpp::getCStdString(const std::string &std)
3834+
{
3835+
return getCStdString(getCStd(std));
3836+
}
3837+
3838+
simplecpp::cppstd_t simplecpp::getCppStd(const std::string &std)
37523839
{
37533840
if (std == "c++98" || std == "c++03" || std == "gnu++98" || std == "gnu++03")
3754-
return "199711L";
3841+
return CPP03;
37553842
if (std == "c++11" || std == "gnu++11" || std == "c++0x" || std == "gnu++0x")
3756-
return "201103L";
3843+
return CPP11;
37573844
if (std == "c++14" || std == "c++1y" || std == "gnu++14" || std == "gnu++1y")
3758-
return "201402L";
3845+
return CPP14;
37593846
if (std == "c++17" || std == "c++1z" || std == "gnu++17" || std == "gnu++1z")
3760-
return "201703L";
3761-
if (std == "c++20" || std == "c++2a" || std == "gnu++20" || std == "gnu++2a") {
3762-
// GCC 10 returns "201703L" - correct in 11+
3763-
return "202002L";
3764-
}
3765-
if (std == "c++23" || std == "c++2b" || std == "gnu++23" || std == "gnu++2b") {
3766-
// supported by GCC 11+ and Clang 12+
3767-
// GCC 11, 12, 13 return "202100L"
3768-
// Clang 12, 13, 14, 15, 16 do not support "c++23" and "gnu++23" and return "202101L"
3769-
// Clang 17, 18 return "202302L"
3770-
return "202302L";
3771-
}
3772-
if (std == "c++26" || std == "c++2c" || std == "gnu++26" || std == "gnu++2c") {
3773-
// supported by Clang 17+
3774-
return "202400L";
3847+
return CPP17;
3848+
if (std == "c++20" || std == "c++2a" || std == "gnu++20" || std == "gnu++2a")
3849+
return CPP20;
3850+
if (std == "c++23" || std == "c++2b" || std == "gnu++23" || std == "gnu++2b")
3851+
return CPP23;
3852+
if (std == "c++26" || std == "c++2c" || std == "gnu++26" || std == "gnu++2c")
3853+
return CPP26;
3854+
return CPPUnknown;
3855+
}
3856+
3857+
std::string simplecpp::getCppStdString(cppstd_t std)
3858+
{
3859+
switch (std)
3860+
{
3861+
case CPP03:
3862+
return "199711L";
3863+
case CPP11:
3864+
return "201103L";
3865+
case CPP14:
3866+
return "201402L";
3867+
case CPP17:
3868+
return "201703L";
3869+
case CPP20:
3870+
// GCC 10 returns "201703L" - correct in 11+
3871+
return "202002L";
3872+
case CPP23:
3873+
// supported by GCC 11+ and Clang 12+
3874+
// GCC 11, 12, 13 return "202100L"
3875+
// Clang 12, 13, 14, 15, 16 do not support "c++23" and "gnu++23" and return "202101L"
3876+
// Clang 17, 18 return "202302L"
3877+
return "202302L";
3878+
case CPP26:
3879+
// supported by Clang 17+
3880+
return "202400L";
3881+
case CPPUnknown:
3882+
return "";
37753883
}
37763884
return "";
37773885
}
37783886

3887+
std::string simplecpp::getCppStdString(const std::string &std)
3888+
{
3889+
return getCppStdString(getCppStd(std));
3890+
}
3891+
37793892
#if (__cplusplus < 201103L) && !defined(__APPLE__)
37803893
#undef nullptr
37813894
#endif

externals/simplecpp/simplecpp.h

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*
1+
/* -*- C++ -*-
22
* simplecpp - A simple and high-fidelity C/C++ preprocessor library
33
* Copyright (C) 2016-2023 simplecpp team
44
*/
@@ -8,7 +8,7 @@
88

99
#include <cctype>
1010
#include <cstring>
11-
#include <istream>
11+
#include <iosfwd>
1212
#include <list>
1313
#include <map>
1414
#include <set>
@@ -39,6 +39,11 @@
3939
#endif
4040

4141
namespace simplecpp {
42+
/** C code standard */
43+
enum cstd_t { CUnknown=-1, C89, C99, C11, C17, C23 };
44+
45+
/** C++ code standard */
46+
enum cppstd_t { CPPUnknown=-1, CPP03, CPP11, CPP14, CPP17, CPP20, CPP23, CPP26 };
4247

4348
typedef std::string TokenString;
4449
class Macro;
@@ -181,7 +186,8 @@ namespace simplecpp {
181186
PORTABILITY_BACKSLASH,
182187
UNHANDLED_CHAR_ERROR,
183188
EXPLICIT_INCLUDE_NOT_FOUND,
184-
FILE_NOT_FOUND
189+
FILE_NOT_FOUND,
190+
DUI_ERROR
185191
} type;
186192
explicit Output(const std::vector<std::string>& files, Type type, const std::string& msg) : type(type), location(files), msg(msg) {}
187193
Location location;
@@ -198,6 +204,10 @@ namespace simplecpp {
198204
explicit TokenList(std::vector<std::string> &filenames);
199205
/** generates a token list from the given std::istream parameter */
200206
TokenList(std::istream &istr, std::vector<std::string> &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr);
207+
/** generates a token list from the given buffer */
208+
TokenList(const unsigned char* data, std::size_t size, std::vector<std::string> &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr);
209+
/** generates a token list from the given buffer */
210+
TokenList(const char* data, std::size_t size, std::vector<std::string> &filenames, const std::string &filename=std::string(), OutputList *outputList = nullptr);
201211
/** generates a token list from the given filename parameter */
202212
TokenList(const std::string &filename, std::vector<std::string> &filenames, OutputList *outputList = nullptr);
203213
TokenList(const TokenList &other);
@@ -363,11 +373,19 @@ namespace simplecpp {
363373
/** Convert Cygwin path to Windows path */
364374
SIMPLECPP_LIB std::string convertCygwinToWindowsPath(const std::string &cygwinPath);
365375

376+
/** Returns the C version a given standard */
377+
SIMPLECPP_LIB cstd_t getCStd(const std::string &std);
378+
379+
/** Returns the C++ version a given standard */
380+
SIMPLECPP_LIB cppstd_t getCppStd(const std::string &std);
381+
366382
/** Returns the __STDC_VERSION__ value for a given standard */
367383
SIMPLECPP_LIB std::string getCStdString(const std::string &std);
384+
SIMPLECPP_LIB std::string getCStdString(cstd_t std);
368385

369386
/** Returns the __cplusplus value for a given standard */
370387
SIMPLECPP_LIB std::string getCppStdString(const std::string &std);
388+
SIMPLECPP_LIB std::string getCppStdString(cppstd_t std);
371389
}
372390

373391
#if defined(_MSC_VER)

lib/preprocessor.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ bool Preprocessor::hasErrors(const simplecpp::Output &output)
735735
case simplecpp::Output::UNHANDLED_CHAR_ERROR:
736736
case simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND:
737737
case simplecpp::Output::FILE_NOT_FOUND:
738+
case simplecpp::Output::DUI_ERROR:
738739
return true;
739740
case simplecpp::Output::WARNING:
740741
case simplecpp::Output::MISSING_HEADER:
@@ -875,6 +876,7 @@ void Preprocessor::reportOutput(const simplecpp::OutputList &outputList, bool sh
875876
break;
876877
case simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND:
877878
case simplecpp::Output::FILE_NOT_FOUND:
879+
case simplecpp::Output::DUI_ERROR:
878880
error(emptyString, 0, out.msg);
879881
break;
880882
}

lib/tokenlist.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,8 @@ bool TokenList::createTokensInternal(std::istream &code, const std::string& file
375375
// NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
376376
void TokenList::createTokens(simplecpp::TokenList&& tokenList)
377377
{
378+
// TODO: what to do if the list has been filled already? clear mTokensFrontBack?
379+
378380
// tokenList.cfront() might be NULL if the file contained nothing to tokenize so we need to check the files instead
379381
if (!tokenList.getFiles().empty()) {
380382
// this is a copy

test/helpers.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,12 +170,15 @@ void PreprocessorHelper::preprocess(const char code[], std::vector<std::string>
170170

171171
void PreprocessorHelper::preprocess(const char code[], std::vector<std::string> &files, Tokenizer& tokenizer, ErrorLogger& errorlogger, const simplecpp::DUI& dui)
172172
{
173+
// TODO: make sure the given Tokenizer has not been used yet
174+
173175
std::istringstream istr(code);
174176
const simplecpp::TokenList tokens1(istr, files, files[0]);
175177

176178
// Preprocess..
177179
simplecpp::TokenList tokens2(files);
178180
std::map<std::string, simplecpp::TokenList*> filedata;
181+
// TODO: provide and handle outputList
179182
simplecpp::preprocess(tokens2, tokens1, files, filedata, dui);
180183

181184
// Tokenizer..

0 commit comments

Comments
 (0)