diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index 84d443f3bc29ce7c13b505dcd07250b75c84933b..8be7be2572de0ca8aaffc2817c27b7e689c4ac3c 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -138,7 +138,7 @@ QString TypeOfExpression::preprocessedExpression(const QString &expression, processEnvironment(documents, thisDocument, &env, &processed); const QByteArray code = expression.toUtf8(); - Preprocessor preproc(0, env); + Preprocessor preproc(0, &env); const QByteArray preprocessedCode = preproc("<expression>", code); return QString::fromUtf8(preprocessedCode.constData(), preprocessedCode.size()); } diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index dfe4a487a2a5a749d713b53fd03213637ab49391..1f3750b1c2bea362e0037ce654f3743d64edc7e5 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -55,8 +55,84 @@ #include <QtDebug> #include <algorithm> +namespace CPlusPlus { + +struct Value +{ + enum Kind { + Kind_Long, + Kind_ULong, + }; + + Kind kind; + + union { + long l; + unsigned long ul; + }; + + + Value() + : kind(Kind_Long), l(0) + { } + + inline bool is_ulong () const + { return kind == Kind_ULong; } + + inline void set_ulong (unsigned long v) + { + ul = v; + kind = Kind_ULong; + } + + inline void set_long (long v) + { + l = v; + kind = Kind_Long; + } + + inline bool is_zero () const + { return l == 0; } + +#define PP_DEFINE_BIN_OP(name, op) \ + inline Value operator op(const Value &other) const \ + { \ + Value v = *this; \ + if (v.is_ulong () || other.is_ulong ()) \ + v.set_ulong (v.ul op other.ul); \ + else \ + v.set_long (v.l op other.l); \ + return v; \ + } + + PP_DEFINE_BIN_OP(op_add, +) + PP_DEFINE_BIN_OP(op_sub, -) + PP_DEFINE_BIN_OP(op_mult, *) + PP_DEFINE_BIN_OP(op_div, /) + PP_DEFINE_BIN_OP(op_mod, %) + PP_DEFINE_BIN_OP(op_lhs, <<) + PP_DEFINE_BIN_OP(op_rhs, >>) + PP_DEFINE_BIN_OP(op_lt, <) + PP_DEFINE_BIN_OP(op_gt, >) + PP_DEFINE_BIN_OP(op_le, <=) + PP_DEFINE_BIN_OP(op_ge, >=) + PP_DEFINE_BIN_OP(op_eq, ==) + PP_DEFINE_BIN_OP(op_ne, !=) + PP_DEFINE_BIN_OP(op_bit_and, &) + PP_DEFINE_BIN_OP(op_bit_or, |) + PP_DEFINE_BIN_OP(op_bit_xor, ^) + PP_DEFINE_BIN_OP(op_and, &&) + PP_DEFINE_BIN_OP(op_or, ||) + +#undef PP_DEFINE_BIN_OP +}; + +} // end of namespace CPlusPlus + + using namespace CPlusPlus; + namespace { class RangeLexer @@ -449,7 +525,7 @@ private: } // end of anonymous namespace -Preprocessor::Preprocessor(Client *client, Environment &env) +Preprocessor::Preprocessor(Client *client, Environment *env) : client(client), env(env), _expand(env), @@ -528,23 +604,23 @@ Preprocessor::State Preprocessor::createStateFromSource(const QByteArray &source void Preprocessor::processNewline() { - if (env.currentLine == _dot->lineno) + if (env->currentLine == _dot->lineno) return; - if (env.currentLine > _dot->lineno) { + if (env->currentLine > _dot->lineno) { _result->append("\n# "); _result->append(QByteArray::number(_dot->lineno)); _result->append(' '); _result->append('"'); - _result->append(env.currentFile); + _result->append(env->currentFile); _result->append('"'); _result->append('\n'); } else { - for (unsigned i = env.currentLine; i < _dot->lineno; ++i) + for (unsigned i = env->currentLine; i < _dot->lineno; ++i) _result->append('\n'); } - env.currentLine = _dot->lineno; + env->currentLine = _dot->lineno; } void Preprocessor::processSkippingBlocks(bool skippingBlocks, @@ -579,11 +655,11 @@ void Preprocessor::preprocess(const QByteArray &fileName, const QByteArray &sour pushState(createStateFromSource(source)); - const QByteArray previousFileName = env.currentFile; - env.currentFile = fileName; + const QByteArray previousFileName = env->currentFile; + env->currentFile = fileName; - const unsigned previousCurrentLine = env.currentLine; - env.currentLine = 0; + const unsigned previousCurrentLine = env->currentLine; + env->currentLine = 0; while (true) { processNewline(); @@ -628,7 +704,8 @@ void Preprocessor::preprocess(const QByteArray &fileName, const QByteArray &sour ++_dot; // skip T_IDENTIFIER const QByteArray spell = tokenSpell(*identifierToken); - if (env.isBuiltinMacro(spell)) { + + if (env->isBuiltinMacro(spell)) { const Macro trivial; if (client) @@ -643,7 +720,7 @@ void Preprocessor::preprocess(const QByteArray &fileName, const QByteArray &sour continue; } - Macro *m = env.resolve(spell); + Macro *m = env->resolve(spell); if (! m) _result->append(spell); @@ -675,7 +752,7 @@ void Preprocessor::preprocess(const QByteArray &fileName, const QByteArray &sour if (_dot->is(T_IDENTIFIER)) { const QByteArray id = tokenSpell(*_dot); - if (Macro *macro = env.resolve(id)) { + if (Macro *macro = env->resolve(id)) { if (macro->isFunctionLike()) m = macro; } @@ -690,6 +767,8 @@ void Preprocessor::preprocess(const QByteArray &fileName, const QByteArray &sour } } + // `m' is function-like macro. + // collect the actual arguments if (_dot->isNot(T_LPAREN)) { // ### warnng expected T_LPAREN @@ -709,6 +788,7 @@ void Preprocessor::preprocess(const QByteArray &fileName, const QByteArray &sour ++_dot; } + if (_dot->isNot(T_RPAREN)) { // ### warning expected T_RPAREN @@ -738,8 +818,8 @@ void Preprocessor::preprocess(const QByteArray &fileName, const QByteArray &sour popState(); - env.currentFile = previousFileName; - env.currentLine = previousCurrentLine; + env->currentFile = previousFileName; + env->currentLine = previousCurrentLine; _result = previousResult; } @@ -899,8 +979,8 @@ void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastTok } Macro macro; - macro.setFileName(env.currentFile); - macro.setLine(env.currentLine); + macro.setFileName(env->currentFile); + macro.setLine(env->currentLine); macro.setName(tokenText(*tk)); ++tk; // skip T_IDENTIFIER @@ -961,7 +1041,7 @@ void Preprocessor::processDefine(TokenIterator firstToken, TokenIterator lastTok macro.setDefinition(definition.trimmed()); } - env.bind(macro); + env->bind(macro); if (client) client->macroAdded(macro); @@ -1063,7 +1143,7 @@ void Preprocessor::processIfdef(bool checkUndefined, if (testIfLevel()) { if (tk->is(T_IDENTIFIER)) { const QByteArray macroName = tokenSpell(*tk); - bool value = env.resolve(macroName) != 0 || env.isBuiltinMacro(macroName); + bool value = env->resolve(macroName) != 0 || env->isBuiltinMacro(macroName); if (checkUndefined) value = ! value; @@ -1083,7 +1163,7 @@ void Preprocessor::processUndef(TokenIterator firstToken, TokenIterator lastToke if (tk->is(T_IDENTIFIER)) { const QByteArray macroName = tokenText(*tk); - const Macro *macro = env.remove(macroName); + const Macro *macro = env->remove(macroName); if (client && macro) client->macroAdded(*macro); @@ -1162,7 +1242,7 @@ int Preprocessor::skipping() const Value Preprocessor::evalExpression(TokenIterator firstToken, TokenIterator lastToken, const QByteArray &source) const { - ExpressionEvaluator eval(&env); + ExpressionEvaluator eval(env); const Value result = eval(firstToken, lastToken, source); return result; } diff --git a/src/libs/cplusplus/pp-engine.h b/src/libs/cplusplus/pp-engine.h index 1b51c88d34771769acd6425393e08d10005f32e6..cd5129a9096de4c738c9a5719e22514c9d665c9a 100644 --- a/src/libs/cplusplus/pp-engine.h +++ b/src/libs/cplusplus/pp-engine.h @@ -60,80 +60,12 @@ namespace CPlusPlus { namespace CPlusPlus { -struct Value -{ - enum Kind { - Kind_Long, - Kind_ULong, - }; - - Kind kind; - - union { - long l; - unsigned long ul; - }; - - - Value() - : kind(Kind_Long), l(0) - { } - - inline bool is_ulong () const - { return kind == Kind_ULong; } - - inline void set_ulong (unsigned long v) - { - ul = v; - kind = Kind_ULong; - } - - inline void set_long (long v) - { - l = v; - kind = Kind_Long; - } - - inline bool is_zero () const - { return l == 0; } - -#define PP_DEFINE_BIN_OP(name, op) \ - inline Value operator op(const Value &other) const \ - { \ - Value v = *this; \ - if (v.is_ulong () || other.is_ulong ()) \ - v.set_ulong (v.ul op other.ul); \ - else \ - v.set_long (v.l op other.l); \ - return v; \ - } - - PP_DEFINE_BIN_OP(op_add, +) - PP_DEFINE_BIN_OP(op_sub, -) - PP_DEFINE_BIN_OP(op_mult, *) - PP_DEFINE_BIN_OP(op_div, /) - PP_DEFINE_BIN_OP(op_mod, %) - PP_DEFINE_BIN_OP(op_lhs, <<) - PP_DEFINE_BIN_OP(op_rhs, >>) - PP_DEFINE_BIN_OP(op_lt, <) - PP_DEFINE_BIN_OP(op_gt, >) - PP_DEFINE_BIN_OP(op_le, <=) - PP_DEFINE_BIN_OP(op_ge, >=) - PP_DEFINE_BIN_OP(op_eq, ==) - PP_DEFINE_BIN_OP(op_ne, !=) - PP_DEFINE_BIN_OP(op_bit_and, &) - PP_DEFINE_BIN_OP(op_bit_or, |) - PP_DEFINE_BIN_OP(op_bit_xor, ^) - PP_DEFINE_BIN_OP(op_and, &&) - PP_DEFINE_BIN_OP(op_or, ||) - -#undef PP_DEFINE_BIN_OP -}; +struct Value; class CPLUSPLUS_EXPORT Preprocessor { public: - Preprocessor(Client *client, Environment &env); + Preprocessor(Client *client, Environment *env); QByteArray operator()(const QByteArray &filename, const QByteArray &source); @@ -218,7 +150,7 @@ private: private: Client *client; - Environment &env; + Environment *env; MacroExpander _expand; bool _skipping[MAX_LEVEL]; // ### move in state diff --git a/src/libs/cplusplus/pp-macro-expander.cpp b/src/libs/cplusplus/pp-macro-expander.cpp index 0502aef4a4d9847afdd9f570be61ca053d701987..a9f4ced4010efa714fff2c14862190e9a75c16a5 100644 --- a/src/libs/cplusplus/pp-macro-expander.cpp +++ b/src/libs/cplusplus/pp-macro-expander.cpp @@ -32,6 +32,24 @@ #include "pp-macro-expander.h" #include <QDateTime> +namespace CPlusPlus { + + + +struct pp_frame +{ + Macro *expanding_macro; + const QVector<QByteArray> actuals; + + pp_frame(Macro *expanding_macro, const QVector<QByteArray> &actuals) + : expanding_macro (expanding_macro), + actuals (actuals) + { } +}; + + +} // end of namespace CPlusPlus + using namespace CPlusPlus; inline static bool comment_p (const char *__first, const char *__last) @@ -48,7 +66,7 @@ inline static bool comment_p (const char *__first, const char *__last) return (*__first == '/' || *__first == '*'); } -MacroExpander::MacroExpander (Environment &env, pp_frame *frame) +MacroExpander::MacroExpander(Environment *env, pp_frame *frame) : env(env), frame(frame), lines(0), generated_lines(0) { } @@ -87,10 +105,10 @@ const char *MacroExpander::expand(const char *__first, const char *__last, if (*__first == '\n') { __result->append("\n# "); - __result->append(QByteArray::number(env.currentLine)); + __result->append(QByteArray::number(env->currentLine)); __result->append(' '); __result->append('"'); - __result->append(env.currentFile); + __result->append(env->currentFile); __result->append('"'); __result->append('\n'); ++lines; @@ -214,20 +232,20 @@ const char *MacroExpander::expand(const char *__first, const char *__last, continue; } - Macro *macro = env.resolve (fast_name); - if (! macro || macro->isHidden() || env.hideNext) + Macro *macro = env->resolve (fast_name); + if (! macro || macro->isHidden() || env->hideNext) { if (fast_name.size () == 7 && fast_name [0] == 'd' && fast_name == "defined") - env.hideNext = true; + env->hideNext = true; else - env.hideNext = false; + env->hideNext = false; if (fast_name.size () == 8 && fast_name [0] == '_' && fast_name [1] == '_') { if (fast_name == "__LINE__") { char buf [16]; - const size_t count = qsnprintf (buf, 16, "%d", env.currentLine + lines); + const size_t count = qsnprintf (buf, 16, "%d", env->currentLine + lines); __result->append(buf, count); continue; } @@ -235,7 +253,7 @@ const char *MacroExpander::expand(const char *__first, const char *__last, else if (fast_name == "__FILE__") { __result->append('"'); - __result->append(env.currentFile); + __result->append(env->currentFile); __result->append('"'); continue; } @@ -287,7 +305,7 @@ const char *MacroExpander::expand(const char *__first, const char *__last, if (__end_id == __tmp_end) { const QByteArray __id (__begin_id, __end_id - __begin_id); - m = env.resolve (__id); + m = env->resolve (__id); } if (! m) diff --git a/src/libs/cplusplus/pp-macro-expander.h b/src/libs/cplusplus/pp-macro-expander.h index 25d22aef7b19ddcc20c34f9f194036aed831c6f6..c1c9f24d712e17f702b0a1db95ec385320f70d1e 100644 --- a/src/libs/cplusplus/pp-macro-expander.h +++ b/src/libs/cplusplus/pp-macro-expander.h @@ -49,56 +49,53 @@ #ifndef PP_MACRO_EXPANDER_H #define PP_MACRO_EXPANDER_H +#include "pp-scanner.h" +#include <QVector> +#include <QByteArray> + namespace CPlusPlus { - struct pp_frame - { - Macro *expanding_macro; - const QVector<QByteArray> actuals; - - pp_frame (Macro *expanding_macro, const QVector<QByteArray> &actuals) - : expanding_macro (expanding_macro), - actuals (actuals) - { } - }; - - class MacroExpander - { - Environment &env; - pp_frame *frame; - - pp_skip_number skip_number; - pp_skip_identifier skip_identifier; - pp_skip_string_literal skip_string_literal; - pp_skip_char_literal skip_char_literal; - pp_skip_argument skip_argument; - pp_skip_comment_or_divop skip_comment_or_divop; - pp_skip_blanks skip_blanks; - pp_skip_whitespaces skip_whitespaces; - - const QByteArray *resolve_formal (const QByteArray &name); - - public: - MacroExpander (Environment &env, pp_frame *frame = 0); - - const char *operator () (const char *first, const char *last, - QByteArray *result); - - const char *operator () (const QByteArray &source, - QByteArray *result) - { return operator()(source.constBegin(), source.constEnd(), result); } - - const char *expand(const char *first, const char *last, - QByteArray *result); - - const char *skip_argument_variadics (const QVector<QByteArray> &actuals, - Macro *macro, - const char *first, const char *last); - - public: // attributes - int lines; - int generated_lines; - }; +class Environment; + +struct pp_frame; + +class MacroExpander +{ + Environment *env; + pp_frame *frame; + + pp_skip_number skip_number; + pp_skip_identifier skip_identifier; + pp_skip_string_literal skip_string_literal; + pp_skip_char_literal skip_char_literal; + pp_skip_argument skip_argument; + pp_skip_comment_or_divop skip_comment_or_divop; + pp_skip_blanks skip_blanks; + pp_skip_whitespaces skip_whitespaces; + + const QByteArray *resolve_formal(const QByteArray &name); + +public: + MacroExpander(Environment *env, pp_frame *frame = 0); + + const char *operator()(const char *first, const char *last, + QByteArray *result); + + const char *operator()(const QByteArray &source, + QByteArray *result) + { return operator()(source.constBegin(), source.constEnd(), result); } + + const char *expand(const char *first, const char *last, + QByteArray *result); + + const char *skip_argument_variadics(const QVector<QByteArray> &actuals, + Macro *macro, + const char *first, const char *last); + +public: // attributes + int lines; + int generated_lines; +}; } // namespace CPlusPlus diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 6dc59f0d4d2cf920a8020cc4e7c3f46f594da878..b4db1925358de746572fec4e1ff75b409cf7b9c5 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -220,7 +220,7 @@ private: CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager) : snapshot(modelManager->snapshot()), m_modelManager(modelManager), - preprocess(this, env) + preprocess(this, &env) { } void CppPreprocessor::setWorkingCopy(const QMap<QString, QByteArray> &workingCopy)