diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 35ffc1068..a5e97b205 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -123,10 +123,18 @@ static std::string unify(const std::string &s, char separator) } +bool Preprocessor::cplusplus(const Settings *settings, const std::string &filename) +{ + const bool undef = settings && settings->userUndefs.find("__cplusplus") != settings->userUndefs.end(); + const bool cpplang = settings && settings->enforcedLang == Settings::CPP; + const bool cppfile = (!settings || settings->enforcedLang == Settings::None) && Path::isCPP(filename); + return (!undef && (cpplang || cppfile)); +} + /** * Get cfgmap - a map of macro names and values */ -static std::map getcfgmap(const std::string &cfg) +static std::map getcfgmap(const std::string &cfg, const Settings *settings, const std::string &filename) { std::map cfgmap; @@ -154,6 +162,9 @@ static std::map getcfgmap(const std::string &cfg) } } + if (cfgmap.find("__cplusplus") == cfgmap.end() && Preprocessor::cplusplus(settings,filename)) + cfgmap["__cplusplus"] = "1"; + return cfgmap; } @@ -1023,7 +1034,7 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe processedFile = ostr.str(); } - std::map defs(getcfgmap(_settings ? _settings->userDefines : std::string(""))); + std::map defs(getcfgmap(_settings ? _settings->userDefines : std::string(""), _settings, filename)); if (_settings && _settings->_maxConfigs == 1U) { std::set pragmaOnce; @@ -1735,9 +1746,7 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string std::list matched_ifdef; // Create a map for the cfg for faster access to defines - std::map cfgmap(getcfgmap(cfg)); - if (((_settings && _settings->enforcedLang == Settings::CPP) || ((!_settings || _settings->enforcedLang == Settings::None) && Path::isCPP(filename))) && cfgmap.find("__cplusplus") == cfgmap.end()) - cfgmap["__cplusplus"] = "1"; + std::map cfgmap(getcfgmap(cfg, _settings, filename)); std::stack filenames; filenames.push(filename); @@ -2895,7 +2904,7 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file { // fill up "macros" with user defined macros - const std::map cfgmap(getcfgmap(cfg)); + const std::map cfgmap(getcfgmap(cfg,NULL,"")); std::map::const_iterator it; for (it = cfgmap.begin(); it != cfgmap.end(); ++it) { std::string s = it->first; diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 8d944ce52..6c421a488 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -96,6 +96,9 @@ public: /** read preprocessor statements into a string. */ std::string readpreprocessor(std::istream &istr, const unsigned int bom) const; + /** should __cplusplus be defined? */ + static bool cplusplus(const Settings *settings, const std::string &filename); + /** * Get preprocessed code for a given configuration * @param filedata file data including preprocessing 'if', 'define', etc diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index bb50bc381..f68863f90 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -3272,11 +3272,21 @@ private: ASSERT_EQUALS("char buf[$123];\n", actual); } - void predefine5() { // #3737 - automatically define __cplusplus + void predefine5() { // #3737, #5119 - automatically define __cplusplus + // #3737... const char code[] = "#ifdef __cplusplus\n123\n#endif"; Preprocessor preprocessor(NULL,this); ASSERT_EQUALS("\n\n\n", preprocessor.getcode(code, "X=123", "test.c")); ASSERT_EQUALS("\n123\n\n", preprocessor.getcode(code, "X=123", "test.cpp")); + + // #5119... + ASSERT_EQUALS(false, Preprocessor::cplusplus(NULL,"test.c")); + ASSERT_EQUALS(true, Preprocessor::cplusplus(NULL,"test.cpp")); + + Settings settings; + ASSERT_EQUALS(true, Preprocessor::cplusplus(&settings,"test.cpp")); + settings.userUndefs.insert("__cplusplus"); + ASSERT_EQUALS(false, Preprocessor::cplusplus(&settings,"test.cpp")); } void predefine6() { // #3737 - using -D and -f => check all matching configurations