Files
qt-creator/src/libs/3rdparty/cplusplus/TranslationUnit.cpp

601 lines
19 KiB
C++
Raw Normal View History

2008-12-02 12:01:29 +01:00
// Copyright (c) 2008 Roberto Raggi <roberto.raggi@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "TranslationUnit.h"
#include "Control.h"
#include "Parser.h"
#include "Lexer.h"
#include "MemoryPool.h"
#include "AST.h"
#include "Literals.h"
#include "DiagnosticClient.h"
#include <stack>
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
#include <vector>
2008-12-02 12:01:29 +01:00
#include <cstdarg>
#include <algorithm>
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
#include <utility>
2008-12-02 12:01:29 +01:00
2010-08-11 16:10:21 +02:00
#ifdef _MSC_VER
2010-08-11 16:08:13 +02:00
# define va_copy(dst, src) ((dst) = (src))
#elif defined(__INTEL_COMPILER) && !defined(va_copy)
# define va_copy __va_copy
2010-08-11 16:08:13 +02:00
#endif
using namespace CPlusPlus;
2008-12-02 12:01:29 +01:00
2009-12-01 11:33:13 +01:00
TranslationUnit::TranslationUnit(Control *control, const StringLiteral *fileId)
2008-12-02 12:01:29 +01:00
: _control(control),
_fileId(fileId),
_firstSourceChar(0),
_lastSourceChar(0),
_pool(0),
_ast(0),
_flags(0)
{
_tokens = new std::vector<Token>();
_comments = new std::vector<Token>();
2008-12-02 12:01:29 +01:00
_previousTranslationUnit = control->switchTranslationUnit(this);
_pool = new MemoryPool();
}
TranslationUnit::~TranslationUnit()
{
(void) _control->switchTranslationUnit(_previousTranslationUnit);
delete _tokens;
delete _comments;
2008-12-02 12:01:29 +01:00
delete _pool;
}
bool TranslationUnit::qtMocRunEnabled() const
{ return f._qtMocRunEnabled; }
2008-12-02 12:01:29 +01:00
void TranslationUnit::setQtMocRunEnabled(bool onoff)
{ f._qtMocRunEnabled = onoff; }
2008-12-02 12:01:29 +01:00
2010-03-24 12:54:25 +01:00
bool TranslationUnit::cxx0xEnabled() const
{ return f._cxx0xEnabled; }
void TranslationUnit::setCxxOxEnabled(bool onoff)
{ f._cxx0xEnabled = onoff; }
2009-01-09 16:55:25 +01:00
bool TranslationUnit::objCEnabled() const
{ return f._objCEnabled; }
2009-01-09 16:55:25 +01:00
void TranslationUnit::setObjCEnabled(bool onoff)
{ f._objCEnabled = onoff; }
2009-01-09 16:55:25 +01:00
2008-12-02 12:01:29 +01:00
Control *TranslationUnit::control() const
{ return _control; }
2009-12-01 11:33:13 +01:00
const StringLiteral *TranslationUnit::fileId() const
2008-12-02 12:01:29 +01:00
{ return _fileId; }
const char *TranslationUnit::fileName() const
{ return _fileId->chars(); }
unsigned TranslationUnit::fileNameLength() const
{ return _fileId->size(); }
const char *TranslationUnit::firstSourceChar() const
{ return _firstSourceChar; }
const char *TranslationUnit::lastSourceChar() const
{ return _lastSourceChar; }
unsigned TranslationUnit::sourceLength() const
{ return _lastSourceChar - _firstSourceChar; }
void TranslationUnit::setSource(const char *source, unsigned size)
{
_firstSourceChar = source;
_lastSourceChar = source + size;
}
const char *TranslationUnit::spell(unsigned index) const
{
if (! index)
return 0;
return _tokens->at(index).spell();
}
unsigned TranslationUnit::commentCount() const
{ return unsigned(_comments->size()); }
const Token &TranslationUnit::commentAt(unsigned index) const
{ return _comments->at(index); }
2009-12-01 11:33:13 +01:00
const Identifier *TranslationUnit::identifier(unsigned index) const
2008-12-02 12:01:29 +01:00
{ return _tokens->at(index).identifier; }
2009-12-01 11:33:13 +01:00
const Literal *TranslationUnit::literal(unsigned index) const
2008-12-02 12:01:29 +01:00
{ return _tokens->at(index).literal; }
2009-12-01 11:33:13 +01:00
const StringLiteral *TranslationUnit::stringLiteral(unsigned index) const
2008-12-02 12:01:29 +01:00
{ return _tokens->at(index).string; }
2009-12-01 11:33:13 +01:00
const NumericLiteral *TranslationUnit::numericLiteral(unsigned index) const
2008-12-02 12:01:29 +01:00
{ return _tokens->at(index).number; }
unsigned TranslationUnit::matchingBrace(unsigned index) const
{ return _tokens->at(index).close_brace; }
MemoryPool *TranslationUnit::memoryPool() const
{ return _pool; }
AST *TranslationUnit::ast() const
2008-12-02 12:01:29 +01:00
{ return _ast; }
bool TranslationUnit::isTokenized() const
{ return f._tokenized; }
2008-12-02 12:01:29 +01:00
bool TranslationUnit::isParsed() const
{ return f._parsed; }
2008-12-02 12:01:29 +01:00
void TranslationUnit::tokenize()
{
if (isTokenized())
return;
f._tokenized = true;
2008-12-02 12:01:29 +01:00
Lexer lex(this);
lex.setQtMocRunEnabled(f._qtMocRunEnabled);
2010-03-24 12:54:25 +01:00
lex.setCxxOxEnabled(f._cxx0xEnabled);
lex.setObjCEnabled(f._objCEnabled);
lex.setScanCommentTokens(true);
2008-12-02 12:01:29 +01:00
std::stack<unsigned> braces;
_tokens->push_back(Token()); // the first token needs to be invalid!
pushLineOffset(0);
pushPreprocessorLine(0, 1, fileId());
const Identifier *lineId = control()->identifier("line");
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
const Identifier *expansionId = control()->identifier("expansion");
const Identifier *beginId = control()->identifier("begin");
const Identifier *endId = control()->identifier("end");
// We need to track information about the expanded tokens. A vector with an addition
// explicit index control is used instead of queue mainly for performance reasons.
std::vector<std::pair<unsigned, unsigned> > lineColumn;
unsigned lineColumnIdx = 0;
2008-12-02 12:01:29 +01:00
Token tk;
do {
lex(&tk);
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
_Lrecognize:
if (tk.is(T_POUND) && tk.newline()) {
2008-12-02 12:01:29 +01:00
unsigned offset = tk.offset;
lex(&tk);
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
if (! tk.f.newline && tk.is(T_IDENTIFIER) && tk.identifier == expansionId) {
// It's an expansion mark.
2008-12-02 12:01:29 +01:00
lex(&tk);
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
if (!tk.f.newline && tk.is(T_IDENTIFIER)) {
if (tk.identifier == beginId) {
// Start of a macro expansion section.
lex(&tk);
// Gather where the expansion happens and its length.
//unsigned macroOffset = static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
lex(&tk);
lex(&tk); // Skip the separating comma
//unsigned macroLength = static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
lex(&tk);
// NOTE: We are currently not using the macro offset and length. They
// are kept here for now because of future use.
//Q_UNUSED(macroOffset)
//Q_UNUSED(macroLength)
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
// Now we need to gather the real line and columns from the upcoming
// tokens. But notice this is only relevant for tokens which are expanded
// but not generated.
while (tk.isNot(T_EOF_SYMBOL) && !tk.f.newline) {
// When we get a ~ it means there's a number of generated tokens
// following. Otherwise, we have actual data.
if (tk.is(T_TILDE)) {
lex(&tk);
// Get the total number of generated tokens and specifiy "null"
// information for them.
unsigned totalGenerated =
static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
const std::size_t previousSize = lineColumn.size();
lineColumn.resize(previousSize + totalGenerated);
std::fill(lineColumn.begin() + previousSize,
lineColumn.end(),
std::make_pair(0, 0));
lex(&tk);
} else if (tk.is(T_NUMERIC_LITERAL)) {
unsigned line = static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
lex(&tk);
lex(&tk); // Skip the separating colon
unsigned column = static_cast<unsigned>(strtoul(tk.spell(), 0, 0));
// Store line and column for this non-generated token.
lineColumn.push_back(std::make_pair(line, column));
lex(&tk);
}
}
} else if (tk.identifier == endId) {
// End of a macro expansion.
lineColumn.clear();
lineColumnIdx = 0;
lex(&tk);
}
}
} else {
if (! tk.f.newline && tk.is(T_IDENTIFIER) && tk.identifier == lineId)
lex(&tk);
if (! tk.f.newline && tk.is(T_NUMERIC_LITERAL)) {
unsigned line = (unsigned) strtoul(tk.spell(), 0, 0);
2008-12-02 12:01:29 +01:00
lex(&tk);
if (! tk.f.newline && tk.is(T_STRING_LITERAL)) {
const StringLiteral *fileName =
control()->stringLiteral(tk.string->chars(), tk.string->size());
pushPreprocessorLine(offset, line, fileName);
lex(&tk);
}
2008-12-02 12:01:29 +01:00
}
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
while (tk.isNot(T_EOF_SYMBOL) && ! tk.f.newline)
lex(&tk);
2008-12-02 12:01:29 +01:00
}
goto _Lrecognize;
} else if (tk.f.kind == T_LBRACE) {
braces.push(unsigned(_tokens->size()));
} else if (tk.f.kind == T_RBRACE && ! braces.empty()) {
2008-12-02 12:01:29 +01:00
const unsigned open_brace_index = braces.top();
braces.pop();
(*_tokens)[open_brace_index].close_brace = unsigned(_tokens->size());
} else if (tk.isComment()) {
_comments->push_back(tk);
continue; // comments are not in the regular token stream
2008-12-02 12:01:29 +01:00
}
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
bool currentExpanded = false;
bool currentGenerated = false;
if (!lineColumn.empty() && lineColumnIdx < lineColumn.size()) {
currentExpanded = true;
const std::pair<unsigned, unsigned> &p = lineColumn[lineColumnIdx];
if (p.first)
_expandedLineColumn.insert(std::make_pair(tk.offset, p));
else
currentGenerated = true;
++lineColumnIdx;
}
tk.f.expanded = currentExpanded;
tk.f.generated = currentGenerated;
2008-12-02 12:01:29 +01:00
_tokens->push_back(tk);
} while (tk.f.kind);
2008-12-02 12:01:29 +01:00
for (; ! braces.empty(); braces.pop()) {
unsigned open_brace_index = braces.top();
(*_tokens)[open_brace_index].close_brace = unsigned(_tokens->size());
2008-12-02 12:01:29 +01:00
}
}
bool TranslationUnit::skipFunctionBody() const
{ return f._skipFunctionBody; }
2008-12-02 12:01:29 +01:00
void TranslationUnit::setSkipFunctionBody(bool skipFunctionBody)
{ f._skipFunctionBody = skipFunctionBody; }
2008-12-02 12:01:29 +01:00
bool TranslationUnit::parse(ParseMode mode)
2008-12-02 12:01:29 +01:00
{
if (isParsed())
return false;
2008-12-02 12:01:29 +01:00
if (! isTokenized())
tokenize();
2009-09-30 16:13:43 +02:00
f._parsed = true;
2008-12-02 12:01:29 +01:00
Parser parser(this);
parser.setQtMocRunEnabled(f._qtMocRunEnabled);
2010-03-24 12:54:25 +01:00
parser.setCxxOxEnabled(f._cxx0xEnabled);
parser.setObjCEnabled(f._objCEnabled);
bool parsed = false;
switch (mode) {
case ParseTranlationUnit: {
TranslationUnitAST *node = 0;
parsed = parser.parseTranslationUnit(node);
_ast = node;
} break;
case ParseDeclaration: {
DeclarationAST *node = 0;
parsed = parser.parseDeclaration(node);
_ast = node;
} break;
case ParseExpression: {
ExpressionAST *node = 0;
parsed = parser.parseExpression(node);
_ast = node;
} break;
2009-03-30 15:07:30 +02:00
case ParseDeclarator: {
DeclaratorAST *node = 0;
parsed = parser.parseDeclarator(node, /*decl_specifier_list =*/ 0);
2009-03-30 15:07:30 +02:00
_ast = node;
} break;
case ParseStatement: {
StatementAST *node = 0;
parsed = parser.parseStatement(node);
_ast = node;
} break;
default:
break;
} // switch
return parsed;
2008-12-02 12:01:29 +01:00
}
void TranslationUnit::pushLineOffset(unsigned offset)
{ _lineOffsets.push_back(offset); }
void TranslationUnit::pushPreprocessorLine(unsigned offset,
unsigned line,
2009-12-01 11:33:13 +01:00
const StringLiteral *fileName)
2008-12-02 12:01:29 +01:00
{ _ppLines.push_back(PPLine(offset, line, fileName)); }
unsigned TranslationUnit::findLineNumber(unsigned offset) const
{
std::vector<unsigned>::const_iterator it =
std::lower_bound(_lineOffsets.begin(), _lineOffsets.end(), offset);
if (it != _lineOffsets.begin())
--it;
return it - _lineOffsets.begin();
}
TranslationUnit::PPLine TranslationUnit::findPreprocessorLine(unsigned offset) const
{
std::vector<PPLine>::const_iterator it =
std::lower_bound(_ppLines.begin(), _ppLines.end(), PPLine(offset));
if (it != _ppLines.begin())
--it;
return *it;
}
unsigned TranslationUnit::findColumnNumber(unsigned offset, unsigned lineNumber) const
{
if (! offset)
return 0;
return offset - _lineOffsets[lineNumber];
}
void TranslationUnit::getTokenPosition(unsigned index,
unsigned *line,
unsigned *column,
2009-12-01 11:33:13 +01:00
const StringLiteral **fileName) const
2008-12-02 12:01:29 +01:00
{ return getPosition(tokenAt(index).offset, line, column, fileName); }
2009-06-24 16:40:30 +02:00
void TranslationUnit::getTokenStartPosition(unsigned index, unsigned *line,
unsigned *column,
2009-12-01 11:33:13 +01:00
const StringLiteral **fileName) const
2009-06-24 16:40:30 +02:00
{ return getPosition(tokenAt(index).begin(), line, column, fileName); }
void TranslationUnit::getTokenEndPosition(unsigned index, unsigned *line,
unsigned *column,
2009-12-01 11:33:13 +01:00
const StringLiteral **fileName) const
2009-06-24 16:40:30 +02:00
{ return getPosition(tokenAt(index).end(), line, column, fileName); }
2008-12-02 12:01:29 +01:00
void TranslationUnit::getPosition(unsigned tokenOffset,
unsigned *line,
unsigned *column,
2009-12-01 11:33:13 +01:00
const StringLiteral **fileName) const
2008-12-02 12:01:29 +01:00
{
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
unsigned lineNumber = 0;
unsigned columnNumber = 0;
const StringLiteral *file = 0;
// If this token is expanded we already have the information directly from the expansion
// section header. Otherwise, we need to calculate it.
TokenLineColumn::const_iterator it = _expandedLineColumn.find(tokenOffset);
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
if (it != _expandedLineColumn.end()) {
lineNumber = it->second.first;
columnNumber = it->second.second + 1;
file = _fileId;
} else {
// Identify line within the entire translation unit.
lineNumber = findLineNumber(tokenOffset);
// Identify column.
columnNumber = findColumnNumber(tokenOffset, lineNumber);
2008-12-02 12:01:29 +01:00
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
// Adjust the line in regards to the preprocessing markers.
const PPLine ppLine = findPreprocessorLine(tokenOffset);
lineNumber -= findLineNumber(ppLine.offset) + 1;
lineNumber += ppLine.line;
file = ppLine.fileName;
}
2008-12-02 12:01:29 +01:00
if (line)
*line = lineNumber;
if (column)
*column = columnNumber;
if (fileName)
C++: Core changes in preprocessing Summary of most relevant items: - Preprocessor output format change. No more gen true/false. Instead a more intuitive and natural expansion (like from a real compiler) is performed directly corresponding to the macro invocation. Notice that information about the generated tokens is not lost, because it's now embedded in the expansion section header (in terms of lines and columns as explained in the code). In addition the location on where the macro expansion happens is also documented for future use. - Fix line control directives and associated token line numbers. This was not detected in tests cases because some of them were actually wrong: Within expansions the line information was being considered as originally computed in the macro definition, while the desired and expected for Creator's reporting mechanism (just like regular compilers) is the line from the expanded version of the tokens. - Do not allow for eager expansion. This was previously being done inside define directives. However, it's not allowed and might lead to incorrect results, since the argument substitution should only happen upon the macro invocation (and following nested ones). At least GCC and clang are consistent with that. See test case tst_Preprocessor:dont_eagerly_expand for a detailed explanation. - Revive the 'expanded' token flag. This is used to mark every token that originates from a macro expansion. Notice, however, that expanded tokens are not necessarily generated tokens (although every generated token is a expanded token). Expanded tokens that are not generated are those which are still considered by our code model features, since they are visible on the editor. The translation unit is smart enough to calculate line/column position for such tokens based on the information from the expansion section header. - How expansions are tracked has also changed. Now, we simply add two surrounding marker tokens to each "top-level" expansion sequence. There is an enumeration that control expansion states. Also, no "previous" token is kept around. - Preprocessor client methods suffered a change in signature so they now receive the line number of the action in question as a paramater. Previously such line could be retrieved by the client implementation by accessing the environment line. However, this is not reliable because we try to avoid synchronization of the output/environment lines in order to avoid unnecessary output, while expanding macros or handling preprocessor directives. - Although macros are not expanded during define directives (as mentioned above) the preprocessor client is now "notified" when it sees a macro. This is to allow usage tracking. - Other small stuff. This is all in one patch because the fixes are a consequence of the change in preprocessing control. Change-Id: I8f4c6e6366f37756ec65d0a93b79f72a3ac4ed50 Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
2012-06-20 15:22:02 +02:00
*fileName = file;
2008-12-02 12:01:29 +01:00
}
2010-08-10 17:30:20 +02:00
void TranslationUnit::message(DiagnosticClient::Level level, unsigned index, const char *format, va_list args)
2008-12-02 12:01:29 +01:00
{
if (f._blockErrors)
2008-12-02 12:01:29 +01:00
return;
index = std::min(index, tokenCount() - 1);
unsigned line = 0, column = 0;
2009-12-01 11:33:13 +01:00
const StringLiteral *fileName = 0;
2008-12-02 12:01:29 +01:00
getTokenPosition(index, &line, &column, &fileName);
if (DiagnosticClient *client = control()->diagnosticClient()) {
2010-08-10 17:30:20 +02:00
client->report(level, fileName, line, column, format, args);
2008-12-02 12:01:29 +01:00
} else {
fprintf(stderr, "%s:%d: ", fileName->chars(), line);
2010-08-10 17:30:20 +02:00
const char *l = "error";
if (level == DiagnosticClient::Warning)
l = "warning";
else if (level == DiagnosticClient::Fatal)
l = "fatal";
fprintf(stderr, "%s: ", l);
2008-12-02 12:01:29 +01:00
vfprintf(stderr, format, args);
fputc('\n', stderr);
showErrorLine(index, column, stderr);
}
2010-08-10 17:30:20 +02:00
if (level == DiagnosticClient::Fatal)
exit(EXIT_FAILURE);
2008-12-02 12:01:29 +01:00
}
2010-08-10 17:30:20 +02:00
void TranslationUnit::warning(unsigned index, const char *format, ...)
2008-12-02 12:01:29 +01:00
{
if (f._blockErrors)
2008-12-02 12:01:29 +01:00
return;
2010-08-10 17:30:20 +02:00
va_list args, ap;
va_start(args, format);
va_copy(ap, args);
message(DiagnosticClient::Warning, index, format, args);
2010-08-10 17:30:20 +02:00
va_end(ap);
va_end(args);
}
2008-12-02 12:01:29 +01:00
2010-08-10 17:30:20 +02:00
void TranslationUnit::error(unsigned index, const char *format, ...)
{
if (f._blockErrors)
return;
2008-12-02 12:01:29 +01:00
2010-08-10 17:30:20 +02:00
va_list args, ap;
va_start(args, format);
va_copy(ap, args);
message(DiagnosticClient::Error, index, format, args);
va_end(ap);
va_end(args);
2008-12-02 12:01:29 +01:00
}
void TranslationUnit::fatal(unsigned index, const char *format, ...)
{
if (f._blockErrors)
2008-12-02 12:01:29 +01:00
return;
2010-08-10 17:30:20 +02:00
va_list args, ap;
va_start(args, format);
va_copy(ap, args);
message(DiagnosticClient::Fatal, index, format, args);
va_end(ap);
va_end(args);
2008-12-02 12:01:29 +01:00
}
2009-06-02 14:56:03 +02:00
unsigned TranslationUnit::findPreviousLineOffset(unsigned tokenIndex) const
{
unsigned lineOffset = _lineOffsets[findLineNumber(_tokens->at(tokenIndex).offset)];
return lineOffset;
}
bool TranslationUnit::maybeSplitGreaterGreaterToken(unsigned tokenIndex)
{
Token &tok = _tokens->at(tokenIndex);
if (tok.kind() != T_GREATER_GREATER)
return false;
tok.f.kind = T_GREATER;
tok.f.length = 1;
Token newGreater;
newGreater.f.kind = T_GREATER;
newGreater.f.expanded = tok.f.expanded;
newGreater.f.generated = tok.f.generated;
newGreater.f.length = 1;
newGreater.offset = tok.offset + 1;
_tokens->insert(_tokens->begin() + tokenIndex + 1, newGreater);
TokenLineColumn::const_iterator it = _expandedLineColumn.find(tok.offset);
if (it != _expandedLineColumn.end()) {
const std::pair<unsigned, unsigned> newPosition(it->second.first, it->second.second + 1);
_expandedLineColumn.insert(std::make_pair(newGreater.offset, newPosition));
}
return true;
}
2008-12-02 12:01:29 +01:00
void TranslationUnit::showErrorLine(unsigned index, unsigned column, FILE *out)
{
unsigned lineOffset = _lineOffsets[findLineNumber(_tokens->at(index).offset)];
for (const char *cp = _firstSourceChar + lineOffset + 1; *cp && *cp != '\n'; ++cp) {
fputc(*cp, out);
}
fputc('\n', out);
const char *end = _firstSourceChar + lineOffset + 1 + column - 1;
for (const char *cp = _firstSourceChar + lineOffset + 1; cp != end; ++cp) {
if (*cp != '\t')
fputc(' ', out);
else
fputc('\t', out);
}
fputc('^', out);
fputc('\n', out);
}
void TranslationUnit::resetAST()
{
delete _pool;
_pool = 0;
2009-12-18 12:24:21 +01:00
_ast = 0;
2008-12-02 12:01:29 +01:00
}
void TranslationUnit::release()
{
resetAST();
delete _tokens;
_tokens = 0;
delete _comments;
_comments = 0;
2008-12-02 12:01:29 +01:00
}