aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp61
1 files changed, 39 insertions, 22 deletions
diff --git a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
index 07753c7d7c36..0213afcee921 100644
--- a/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
+++ b/contrib/llvm/tools/clang/lib/Lex/TokenLexer.cpp
@@ -121,7 +121,7 @@ void TokenLexer::destroy() {
/// Remove comma ahead of __VA_ARGS__, if present, according to compiler dialect
/// settings. Returns true if the comma is removed.
-static bool MaybeRemoveCommaBeforeVaArgs(SmallVector<Token, 128> &ResultToks,
+static bool MaybeRemoveCommaBeforeVaArgs(SmallVectorImpl<Token> &ResultToks,
bool &NextTokGetsSpace,
bool HasPasteOperator,
MacroInfo *Macro, unsigned MacroArgNo,
@@ -244,9 +244,11 @@ void TokenLexer::ExpandFunctionArguments() {
// Otherwise, this is a use of the argument. Find out if there is a paste
// (##) operator before or after the argument.
- bool PasteBefore =
+ bool NonEmptyPasteBefore =
!ResultToks.empty() && ResultToks.back().is(tok::hashhash);
+ bool PasteBefore = i != 0 && Tokens[i-1].is(tok::hashhash);
bool PasteAfter = i+1 != e && Tokens[i+1].is(tok::hashhash);
+ assert(!NonEmptyPasteBefore || PasteBefore);
// In Microsoft mode, remove the comma before __VA_ARGS__ to ensure there
// are no trailing commas if __VA_ARGS__ is empty.
@@ -276,6 +278,14 @@ void TokenLexer::ExpandFunctionArguments() {
unsigned NumToks = MacroArgs::getArgLength(ResultArgToks);
ResultToks.append(ResultArgToks, ResultArgToks+NumToks);
+ // In Microsoft-compatibility mode, we follow MSVC's preprocessing
+ // behavior by not considering single commas from nested macro
+ // expansions as argument separators. Set a flag on the token so we can
+ // test for this later when the macro expansion is processed.
+ if (PP.getLangOpts().MicrosoftMode && NumToks == 1 &&
+ ResultToks.back().is(tok::comma))
+ ResultToks.back().setFlag(Token::IgnoredComma);
+
// If the '##' came from expanding an argument, turn it into 'unknown'
// to avoid pasting.
for (unsigned i = FirstResult, e = ResultToks.size(); i != e; ++i) {
@@ -314,13 +324,12 @@ void TokenLexer::ExpandFunctionArguments() {
// that __VA_ARGS__ expands to multiple tokens, avoid a pasting error when
// the expander trys to paste ',' with the first token of the __VA_ARGS__
// expansion.
- if (PasteBefore && ResultToks.size() >= 2 &&
+ if (NonEmptyPasteBefore && ResultToks.size() >= 2 &&
ResultToks[ResultToks.size()-2].is(tok::comma) &&
(unsigned)ArgNo == Macro->getNumArgs()-1 &&
Macro->isVariadic()) {
// Remove the paste operator, report use of the extension.
- PP.Diag(ResultToks.back().getLocation(), diag::ext_paste_comma);
- ResultToks.pop_back();
+ PP.Diag(ResultToks.pop_back_val().getLocation(), diag::ext_paste_comma);
}
ResultToks.append(ArgToks, ArgToks+NumToks);
@@ -350,7 +359,7 @@ void TokenLexer::ExpandFunctionArguments() {
// case, we do not want the extra whitespace to be added. For example,
// we want ". ## foo" -> ".foo" not ". foo".
if ((CurTok.hasLeadingSpace() || NextTokGetsSpace) &&
- !PasteBefore)
+ !NonEmptyPasteBefore)
ResultToks[ResultToks.size()-NumToks].setFlag(Token::LeadingSpace);
NextTokGetsSpace = false;
@@ -371,10 +380,13 @@ void TokenLexer::ExpandFunctionArguments() {
}
// If this is on the RHS of a paste operator, we've already copied the
- // paste operator to the ResultToks list. Remove it.
- assert(PasteBefore && ResultToks.back().is(tok::hashhash));
- NextTokGetsSpace |= ResultToks.back().hasLeadingSpace();
- ResultToks.pop_back();
+ // paste operator to the ResultToks list, unless the LHS was empty too.
+ // Remove it.
+ assert(PasteBefore);
+ if (NonEmptyPasteBefore) {
+ assert(ResultToks.back().is(tok::hashhash));
+ NextTokGetsSpace |= ResultToks.pop_back_val().hasLeadingSpace();
+ }
// If this is the __VA_ARGS__ token, and if the argument wasn't provided,
// and if the macro had at least one real argument, and if the token before
@@ -404,22 +416,19 @@ void TokenLexer::ExpandFunctionArguments() {
/// Lex - Lex and return a token from this macro stream.
///
-void TokenLexer::Lex(Token &Tok) {
+bool TokenLexer::Lex(Token &Tok) {
// Lexing off the end of the macro, pop this macro off the expansion stack.
if (isAtEnd()) {
// If this is a macro (not a token stream), mark the macro enabled now
// that it is no longer being expanded.
if (Macro) Macro->EnableMacro();
- // Pop this context off the preprocessors lexer stack and get the next
- // token. This will delete "this" so remember the PP instance var.
- Preprocessor &PPCache = PP;
- if (PP.HandleEndOfTokenLexer(Tok))
- return;
-
- // HandleEndOfTokenLexer may not return a token. If it doesn't, lex
- // whatever is next.
- return PPCache.Lex(Tok);
+ Tok.startToken();
+ Tok.setFlagValue(Token::StartOfLine , AtStartOfLine);
+ Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
+ if (CurToken == 0)
+ Tok.setFlag(Token::LeadingEmptyMacro);
+ return PP.HandleEndOfTokenLexer(Tok);
}
SourceManager &SM = PP.getSourceManager();
@@ -439,7 +448,7 @@ void TokenLexer::Lex(Token &Tok) {
// When handling the microsoft /##/ extension, the final token is
// returned by PasteTokens, not the pasted token.
if (PasteTokens(Tok))
- return;
+ return true;
TokenIsFromPaste = true;
}
@@ -470,6 +479,8 @@ void TokenLexer::Lex(Token &Tok) {
if (isFirstToken) {
Tok.setFlagValue(Token::StartOfLine , AtStartOfLine);
Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
+ AtStartOfLine = false;
+ HasLeadingSpace = false;
}
// Handle recursive expansion!
@@ -487,10 +498,11 @@ void TokenLexer::Lex(Token &Tok) {
}
if (!DisableMacroExpansion && II->isHandleIdentifierCase())
- PP.HandleIdentifier(Tok);
+ return PP.HandleIdentifier(Tok);
}
// Otherwise, return a normal token.
+ return true;
}
/// PasteTokens - Tok is the LHS of a ## operator, and CurToken is the ##
@@ -812,3 +824,8 @@ void TokenLexer::updateLocForMacroArgTokens(SourceLocation ArgIdSpellLoc,
updateConsecutiveMacroArgTokens(SM, InstLoc, begin_tokens, end_tokens);
}
}
+
+void TokenLexer::PropagateLineStartLeadingSpaceInfo(Token &Result) {
+ AtStartOfLine = Result.isAtStartOfLine();
+ HasLeadingSpace = Result.hasLeadingSpace();
+}