diff --git a/externals/simplecpp/simplecpp.cpp b/externals/simplecpp/simplecpp.cpp index 81b5e7317..772aed07d 100644 --- a/externals/simplecpp/simplecpp.cpp +++ b/externals/simplecpp/simplecpp.cpp @@ -1110,9 +1110,9 @@ unsigned int simplecpp::TokenList::fileIndex(const std::string &filename) namespace simplecpp { class Macro { public: - explicit Macro(std::vector &f) : nameTokDef(NULL), variadic(false), valueToken(NULL), endToken(NULL), files(f), tokenListDefine(f) {} + explicit Macro(std::vector &f) : nameTokDef(NULL), variadic(false), valueToken(NULL), endToken(NULL), files(f), tokenListDefine(f), valueDefinedInCode_(false) {} - Macro(const Token *tok, std::vector &f) : nameTokDef(NULL), files(f), tokenListDefine(f) { + Macro(const Token *tok, std::vector &f) : nameTokDef(NULL), files(f), tokenListDefine(f), valueDefinedInCode_(true) { if (sameline(tok->previous, tok)) throw std::runtime_error("bad macro syntax"); if (tok->op != '#') @@ -1128,7 +1128,7 @@ namespace simplecpp { throw std::runtime_error("bad macro syntax"); } - Macro(const std::string &name, const std::string &value, std::vector &f) : nameTokDef(NULL), files(f), tokenListDefine(f) { + Macro(const std::string &name, const std::string &value, std::vector &f) : nameTokDef(NULL), files(f), tokenListDefine(f), valueDefinedInCode_(false) { const std::string def(name + ' ' + value); std::istringstream istr(def); tokenListDefine.readfile(istr); @@ -1136,12 +1136,13 @@ namespace simplecpp { throw std::runtime_error("bad macro syntax"); } - Macro(const Macro ¯o) : nameTokDef(NULL), files(macro.files), tokenListDefine(macro.files) { + Macro(const Macro ¯o) : nameTokDef(NULL), files(macro.files), tokenListDefine(macro.files), valueDefinedInCode_(macro.valueDefinedInCode_) { *this = macro; } void operator=(const Macro ¯o) { if (this != ¯o) { + valueDefinedInCode_ = macro.valueDefinedInCode_; if (macro.tokenListDefine.empty()) parseDefine(macro.nameTokDef); else { @@ -1151,6 +1152,10 @@ namespace simplecpp { } } + bool valueDefinedInCode() const { + return valueDefinedInCode_; + } + /** * Expand macro. This will recursively expand inner macros. * @param output destination tokenlist @@ -1821,6 +1826,9 @@ namespace simplecpp { /** usage of this macro */ mutable std::list usageList; + + /** was the value of this macro actually defined in the code? */ + bool valueDefinedInCode_; }; } @@ -2612,7 +2620,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL const Macro ¯o = macroIt->second; const std::list &usage = macro.usage(); for (std::list::const_iterator usageIt = usage.begin(); usageIt != usage.end(); ++usageIt) { - MacroUsage mu(usageIt->files); + MacroUsage mu(usageIt->files, macro.valueDefinedInCode()); mu.macroName = macro.name(); mu.macroLocation = macro.defineLocation(); mu.useLocation = *usageIt; diff --git a/externals/simplecpp/simplecpp.h b/externals/simplecpp/simplecpp.h index 62f7a5866..df1d4d2fe 100644 --- a/externals/simplecpp/simplecpp.h +++ b/externals/simplecpp/simplecpp.h @@ -269,10 +269,11 @@ namespace simplecpp { /** Tracking how macros are used */ struct SIMPLECPP_LIB MacroUsage { - explicit MacroUsage(const std::vector &f) : macroLocation(f), useLocation(f) {} + explicit MacroUsage(const std::vector &f, bool macroValueKnown_) : macroLocation(f), useLocation(f), macroValueKnown(macroValueKnown_) {} std::string macroName; Location macroLocation; Location useLocation; + bool macroValueKnown; }; /** diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 88831ea6c..681d7a85d 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -786,6 +786,8 @@ bool Preprocessor::validateCfg(const std::string &cfg, const std::list files(1, "test.c"); - simplecpp::MacroUsage macroUsage(files); + simplecpp::MacroUsage macroUsage(files, false); macroUsage.useLocation.fileIndex = 0; macroUsage.useLocation.line = 1; macroUsage.macroName = "X"; @@ -2224,6 +2226,19 @@ private: ASSERT_EQUALS(false, preprocessor.validateCfg("A=42;X", macroUsageList)); ASSERT_EQUALS(true, preprocessor.validateCfg("X=1", macroUsageList)); ASSERT_EQUALS(true, preprocessor.validateCfg("Y", macroUsageList)); + + macroUsageList.front().macroValueKnown = true; // #8404 + ASSERT_EQUALS(true, preprocessor.validateCfg("X", macroUsageList)); + } + + void validateCfg2() { + const char filedata[] = "#ifdef ABC\n" + "#endif\n" + "int i = ABC;"; + + std::map actual; + preprocess(filedata, actual, "file.cpp"); + ASSERT_EQUALS("[file.cpp:3]: (information) Skipping configuration 'ABC' since the value of 'ABC' is unknown. Use -D if you want to check it. You can use -U to skip it explicitly.\n", errout.str()); } void if_sizeof() { // #4071