forked from OSchip/llvm-project
split the MacroArgs class out of TokenLexer.cpp/h into
MacroArgs.cpp/h llvm-svn: 48075
This commit is contained in:
parent
d5917cef95
commit
7ff66fb91e
|
@ -0,0 +1,224 @@
|
|||
//===--- TokenLexer.cpp - Lex from a token stream -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the TokenLexer interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MacroArgs.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
using namespace clang;
|
||||
|
||||
/// MacroArgs ctor function - This destroys the vector passed in.
|
||||
MacroArgs *MacroArgs::create(const MacroInfo *MI,
|
||||
const Token *UnexpArgTokens,
|
||||
unsigned NumToks, bool VarargsElided) {
|
||||
assert(MI->isFunctionLike() &&
|
||||
"Can't have args for an object-like macro!");
|
||||
|
||||
// Allocate memory for the MacroArgs object with the lexer tokens at the end.
|
||||
MacroArgs *Result = (MacroArgs*)malloc(sizeof(MacroArgs) +
|
||||
NumToks*sizeof(Token));
|
||||
// Construct the macroargs object.
|
||||
new (Result) MacroArgs(NumToks, VarargsElided);
|
||||
|
||||
// Copy the actual unexpanded tokens to immediately after the result ptr.
|
||||
if (NumToks)
|
||||
memcpy(const_cast<Token*>(Result->getUnexpArgument(0)),
|
||||
UnexpArgTokens, NumToks*sizeof(Token));
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// destroy - Destroy and deallocate the memory for this object.
|
||||
///
|
||||
void MacroArgs::destroy() {
|
||||
// Run the dtor to deallocate the vectors.
|
||||
this->~MacroArgs();
|
||||
// Release the memory for the object.
|
||||
free(this);
|
||||
}
|
||||
|
||||
|
||||
/// getArgLength - Given a pointer to an expanded or unexpanded argument,
|
||||
/// return the number of tokens, not counting the EOF, that make up the
|
||||
/// argument.
|
||||
unsigned MacroArgs::getArgLength(const Token *ArgPtr) {
|
||||
unsigned NumArgTokens = 0;
|
||||
for (; ArgPtr->isNot(tok::eof); ++ArgPtr)
|
||||
++NumArgTokens;
|
||||
return NumArgTokens;
|
||||
}
|
||||
|
||||
|
||||
/// getUnexpArgument - Return the unexpanded tokens for the specified formal.
|
||||
///
|
||||
const Token *MacroArgs::getUnexpArgument(unsigned Arg) const {
|
||||
// The unexpanded argument tokens start immediately after the MacroArgs object
|
||||
// in memory.
|
||||
const Token *Start = (const Token *)(this+1);
|
||||
const Token *Result = Start;
|
||||
// Scan to find Arg.
|
||||
for (; Arg; ++Result) {
|
||||
assert(Result < Start+NumUnexpArgTokens && "Invalid arg #");
|
||||
if (Result->is(tok::eof))
|
||||
--Arg;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
|
||||
/// by pre-expansion, return false. Otherwise, conservatively return true.
|
||||
bool MacroArgs::ArgNeedsPreexpansion(const Token *ArgTok,
|
||||
Preprocessor &PP) const {
|
||||
// If there are no identifiers in the argument list, or if the identifiers are
|
||||
// known to not be macros, pre-expansion won't modify it.
|
||||
for (; ArgTok->isNot(tok::eof); ++ArgTok)
|
||||
if (IdentifierInfo *II = ArgTok->getIdentifierInfo()) {
|
||||
if (II->hasMacroDefinition() && PP.getMacroInfo(II)->isEnabled())
|
||||
// Return true even though the macro could be a function-like macro
|
||||
// without a following '(' token.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getPreExpArgument - Return the pre-expanded form of the specified
|
||||
/// argument.
|
||||
const std::vector<Token> &
|
||||
MacroArgs::getPreExpArgument(unsigned Arg, Preprocessor &PP) {
|
||||
assert(Arg < NumUnexpArgTokens && "Invalid argument number!");
|
||||
|
||||
// If we have already computed this, return it.
|
||||
if (PreExpArgTokens.empty())
|
||||
PreExpArgTokens.resize(NumUnexpArgTokens);
|
||||
|
||||
std::vector<Token> &Result = PreExpArgTokens[Arg];
|
||||
if (!Result.empty()) return Result;
|
||||
|
||||
const Token *AT = getUnexpArgument(Arg);
|
||||
unsigned NumToks = getArgLength(AT)+1; // Include the EOF.
|
||||
|
||||
// Otherwise, we have to pre-expand this argument, populating Result. To do
|
||||
// this, we set up a fake TokenLexer to lex from the unexpanded argument
|
||||
// list. With this installed, we lex expanded tokens until we hit the EOF
|
||||
// token at the end of the unexp list.
|
||||
PP.EnterTokenStream(AT, NumToks);
|
||||
|
||||
// Lex all of the macro-expanded tokens into Result.
|
||||
do {
|
||||
Result.push_back(Token());
|
||||
PP.Lex(Result.back());
|
||||
} while (Result.back().isNot(tok::eof));
|
||||
|
||||
// Pop the token stream off the top of the stack. We know that the internal
|
||||
// pointer inside of it is to the "end" of the token stream, but the stack
|
||||
// will not otherwise be popped until the next token is lexed. The problem is
|
||||
// that the token may be lexed sometime after the vector of tokens itself is
|
||||
// destroyed, which would be badness.
|
||||
PP.RemoveTopOfLexerStack();
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
|
||||
/// tokens into the literal string token that should be produced by the C #
|
||||
/// preprocessor operator. If Charify is true, then it should be turned into
|
||||
/// a character literal for the Microsoft charize (#@) extension.
|
||||
///
|
||||
Token MacroArgs::StringifyArgument(const Token *ArgToks,
|
||||
Preprocessor &PP, bool Charify) {
|
||||
Token Tok;
|
||||
Tok.startToken();
|
||||
Tok.setKind(tok::string_literal);
|
||||
|
||||
const Token *ArgTokStart = ArgToks;
|
||||
|
||||
// Stringify all the tokens.
|
||||
std::string Result = "\"";
|
||||
// FIXME: Optimize this loop to not use std::strings.
|
||||
bool isFirst = true;
|
||||
for (; ArgToks->isNot(tok::eof); ++ArgToks) {
|
||||
const Token &Tok = *ArgToks;
|
||||
if (!isFirst && (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()))
|
||||
Result += ' ';
|
||||
isFirst = false;
|
||||
|
||||
// If this is a string or character constant, escape the token as specified
|
||||
// by 6.10.3.2p2.
|
||||
if (Tok.is(tok::string_literal) || // "foo"
|
||||
Tok.is(tok::wide_string_literal) || // L"foo"
|
||||
Tok.is(tok::char_constant)) { // 'x' and L'x'.
|
||||
Result += Lexer::Stringify(PP.getSpelling(Tok));
|
||||
} else {
|
||||
// Otherwise, just append the token.
|
||||
Result += PP.getSpelling(Tok);
|
||||
}
|
||||
}
|
||||
|
||||
// If the last character of the string is a \, and if it isn't escaped, this
|
||||
// is an invalid string literal, diagnose it as specified in C99.
|
||||
if (Result[Result.size()-1] == '\\') {
|
||||
// Count the number of consequtive \ characters. If even, then they are
|
||||
// just escaped backslashes, otherwise it's an error.
|
||||
unsigned FirstNonSlash = Result.size()-2;
|
||||
// Guaranteed to find the starting " if nothing else.
|
||||
while (Result[FirstNonSlash] == '\\')
|
||||
--FirstNonSlash;
|
||||
if ((Result.size()-1-FirstNonSlash) & 1) {
|
||||
// Diagnose errors for things like: #define F(X) #X / F(\)
|
||||
PP.Diag(ArgToks[-1], diag::pp_invalid_string_literal);
|
||||
Result.erase(Result.end()-1); // remove one of the \'s.
|
||||
}
|
||||
}
|
||||
Result += '"';
|
||||
|
||||
// If this is the charify operation and the result is not a legal character
|
||||
// constant, diagnose it.
|
||||
if (Charify) {
|
||||
// First step, turn double quotes into single quotes:
|
||||
Result[0] = '\'';
|
||||
Result[Result.size()-1] = '\'';
|
||||
|
||||
// Check for bogus character.
|
||||
bool isBad = false;
|
||||
if (Result.size() == 3) {
|
||||
isBad = Result[1] == '\''; // ''' is not legal. '\' already fixed above.
|
||||
} else {
|
||||
isBad = (Result.size() != 4 || Result[1] != '\\'); // Not '\x'
|
||||
}
|
||||
|
||||
if (isBad) {
|
||||
PP.Diag(ArgTokStart[0], diag::err_invalid_character_to_charify);
|
||||
Result = "' '"; // Use something arbitrary, but legal.
|
||||
}
|
||||
}
|
||||
|
||||
Tok.setLength(Result.size());
|
||||
Tok.setLocation(PP.CreateString(&Result[0], Result.size()));
|
||||
return Tok;
|
||||
}
|
||||
|
||||
/// getStringifiedArgument - Compute, cache, and return the specified argument
|
||||
/// that has been 'stringified' as required by the # operator.
|
||||
const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo,
|
||||
Preprocessor &PP) {
|
||||
assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!");
|
||||
if (StringifiedArgs.empty()) {
|
||||
StringifiedArgs.resize(getNumArguments());
|
||||
memset(&StringifiedArgs[0], 0,
|
||||
sizeof(StringifiedArgs[0])*getNumArguments());
|
||||
}
|
||||
if (StringifiedArgs[ArgNo].isNot(tok::string_literal))
|
||||
StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP);
|
||||
return StringifiedArgs[ArgNo];
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
//===--- MacroArgs.h - Formal argument info for Macros ----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the MacroArgs interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_MACROARGS_H
|
||||
#define LLVM_CLANG_MACROARGS_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
class MacroInfo;
|
||||
class Preprocessor;
|
||||
class Token;
|
||||
|
||||
/// MacroArgs - An instance of this class captures information about
|
||||
/// the formal arguments specified to a function-like macro invocation.
|
||||
class MacroArgs {
|
||||
/// NumUnexpArgTokens - The number of raw, unexpanded tokens for the
|
||||
/// arguments. All of the actual argument tokens are allocated immediately
|
||||
/// after the MacroArgs object in memory. This is all of the arguments
|
||||
/// concatenated together, with 'EOF' markers at the end of each argument.
|
||||
unsigned NumUnexpArgTokens;
|
||||
|
||||
/// PreExpArgTokens - Pre-expanded tokens for arguments that need them. Empty
|
||||
/// if not yet computed. This includes the EOF marker at the end of the
|
||||
/// stream.
|
||||
std::vector<std::vector<Token> > PreExpArgTokens;
|
||||
|
||||
/// StringifiedArgs - This contains arguments in 'stringified' form. If the
|
||||
/// stringified form of an argument has not yet been computed, this is empty.
|
||||
std::vector<Token> StringifiedArgs;
|
||||
|
||||
/// VarargsElided - True if this is a C99 style varargs macro invocation and
|
||||
/// there was no argument specified for the "..." argument. If the argument
|
||||
/// was specified (even empty) or this isn't a C99 style varargs function, or
|
||||
/// if in strict mode and the C99 varargs macro had only a ... argument, this
|
||||
/// is false.
|
||||
bool VarargsElided;
|
||||
|
||||
MacroArgs(unsigned NumToks, bool varargsElided)
|
||||
: NumUnexpArgTokens(NumToks), VarargsElided(varargsElided) {}
|
||||
~MacroArgs() {}
|
||||
public:
|
||||
/// MacroArgs ctor function - Create a new MacroArgs object with the specified
|
||||
/// macro and argument info.
|
||||
static MacroArgs *create(const MacroInfo *MI,
|
||||
const Token *UnexpArgTokens,
|
||||
unsigned NumArgTokens, bool VarargsElided);
|
||||
|
||||
/// destroy - Destroy and deallocate the memory for this object.
|
||||
///
|
||||
void destroy();
|
||||
|
||||
/// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
|
||||
/// by pre-expansion, return false. Otherwise, conservatively return true.
|
||||
bool ArgNeedsPreexpansion(const Token *ArgTok, Preprocessor &PP) const;
|
||||
|
||||
/// getUnexpArgument - Return a pointer to the first token of the unexpanded
|
||||
/// token list for the specified formal.
|
||||
///
|
||||
const Token *getUnexpArgument(unsigned Arg) const;
|
||||
|
||||
/// getArgLength - Given a pointer to an expanded or unexpanded argument,
|
||||
/// return the number of tokens, not counting the EOF, that make up the
|
||||
/// argument.
|
||||
static unsigned getArgLength(const Token *ArgPtr);
|
||||
|
||||
/// getPreExpArgument - Return the pre-expanded form of the specified
|
||||
/// argument.
|
||||
const std::vector<Token> &
|
||||
getPreExpArgument(unsigned Arg, Preprocessor &PP);
|
||||
|
||||
/// getStringifiedArgument - Compute, cache, and return the specified argument
|
||||
/// that has been 'stringified' as required by the # operator.
|
||||
const Token &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP);
|
||||
|
||||
/// getNumArguments - Return the number of arguments passed into this macro
|
||||
/// invocation.
|
||||
unsigned getNumArguments() const { return NumUnexpArgTokens; }
|
||||
|
||||
|
||||
/// isVarargsElidedUse - Return true if this is a C99 style varargs macro
|
||||
/// invocation and there was no argument specified for the "..." argument. If
|
||||
/// the argument was specified (even empty) or this isn't a C99 style varargs
|
||||
/// function, or if in strict mode and the C99 varargs macro had only a ...
|
||||
/// argument, this returns false.
|
||||
bool isVarargsElidedUse() const { return VarargsElided; }
|
||||
|
||||
/// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
|
||||
/// tokens into the literal string token that should be produced by the C #
|
||||
/// preprocessor operator. If Charify is true, then it should be turned into
|
||||
/// a character literal for the Microsoft charize (#@) extension.
|
||||
///
|
||||
static Token StringifyArgument(const Token *ArgToks,
|
||||
Preprocessor &PP, bool Charify = false);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
|
@ -26,6 +26,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "MacroArgs.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/PPCallbacks.h"
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Lex/TokenLexer.h"
|
||||
#include "MacroArgs.h"
|
||||
#include "clang/Lex/MacroInfo.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
|
@ -19,218 +20,6 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
using namespace clang;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MacroArgs Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// MacroArgs ctor function - This destroys the vector passed in.
|
||||
MacroArgs *MacroArgs::create(const MacroInfo *MI,
|
||||
const Token *UnexpArgTokens,
|
||||
unsigned NumToks, bool VarargsElided) {
|
||||
assert(MI->isFunctionLike() &&
|
||||
"Can't have args for an object-like macro!");
|
||||
|
||||
// Allocate memory for the MacroArgs object with the lexer tokens at the end.
|
||||
MacroArgs *Result = (MacroArgs*)malloc(sizeof(MacroArgs) +
|
||||
NumToks*sizeof(Token));
|
||||
// Construct the macroargs object.
|
||||
new (Result) MacroArgs(NumToks, VarargsElided);
|
||||
|
||||
// Copy the actual unexpanded tokens to immediately after the result ptr.
|
||||
if (NumToks)
|
||||
memcpy(const_cast<Token*>(Result->getUnexpArgument(0)),
|
||||
UnexpArgTokens, NumToks*sizeof(Token));
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// destroy - Destroy and deallocate the memory for this object.
|
||||
///
|
||||
void MacroArgs::destroy() {
|
||||
// Run the dtor to deallocate the vectors.
|
||||
this->~MacroArgs();
|
||||
// Release the memory for the object.
|
||||
free(this);
|
||||
}
|
||||
|
||||
|
||||
/// getArgLength - Given a pointer to an expanded or unexpanded argument,
|
||||
/// return the number of tokens, not counting the EOF, that make up the
|
||||
/// argument.
|
||||
unsigned MacroArgs::getArgLength(const Token *ArgPtr) {
|
||||
unsigned NumArgTokens = 0;
|
||||
for (; ArgPtr->isNot(tok::eof); ++ArgPtr)
|
||||
++NumArgTokens;
|
||||
return NumArgTokens;
|
||||
}
|
||||
|
||||
|
||||
/// getUnexpArgument - Return the unexpanded tokens for the specified formal.
|
||||
///
|
||||
const Token *MacroArgs::getUnexpArgument(unsigned Arg) const {
|
||||
// The unexpanded argument tokens start immediately after the MacroArgs object
|
||||
// in memory.
|
||||
const Token *Start = (const Token *)(this+1);
|
||||
const Token *Result = Start;
|
||||
// Scan to find Arg.
|
||||
for (; Arg; ++Result) {
|
||||
assert(Result < Start+NumUnexpArgTokens && "Invalid arg #");
|
||||
if (Result->is(tok::eof))
|
||||
--Arg;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
|
||||
/// by pre-expansion, return false. Otherwise, conservatively return true.
|
||||
bool MacroArgs::ArgNeedsPreexpansion(const Token *ArgTok,
|
||||
Preprocessor &PP) const {
|
||||
// If there are no identifiers in the argument list, or if the identifiers are
|
||||
// known to not be macros, pre-expansion won't modify it.
|
||||
for (; ArgTok->isNot(tok::eof); ++ArgTok)
|
||||
if (IdentifierInfo *II = ArgTok->getIdentifierInfo()) {
|
||||
if (II->hasMacroDefinition() && PP.getMacroInfo(II)->isEnabled())
|
||||
// Return true even though the macro could be a function-like macro
|
||||
// without a following '(' token.
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getPreExpArgument - Return the pre-expanded form of the specified
|
||||
/// argument.
|
||||
const std::vector<Token> &
|
||||
MacroArgs::getPreExpArgument(unsigned Arg, Preprocessor &PP) {
|
||||
assert(Arg < NumUnexpArgTokens && "Invalid argument number!");
|
||||
|
||||
// If we have already computed this, return it.
|
||||
if (PreExpArgTokens.empty())
|
||||
PreExpArgTokens.resize(NumUnexpArgTokens);
|
||||
|
||||
std::vector<Token> &Result = PreExpArgTokens[Arg];
|
||||
if (!Result.empty()) return Result;
|
||||
|
||||
const Token *AT = getUnexpArgument(Arg);
|
||||
unsigned NumToks = getArgLength(AT)+1; // Include the EOF.
|
||||
|
||||
// Otherwise, we have to pre-expand this argument, populating Result. To do
|
||||
// this, we set up a fake TokenLexer to lex from the unexpanded argument
|
||||
// list. With this installed, we lex expanded tokens until we hit the EOF
|
||||
// token at the end of the unexp list.
|
||||
PP.EnterTokenStream(AT, NumToks);
|
||||
|
||||
// Lex all of the macro-expanded tokens into Result.
|
||||
do {
|
||||
Result.push_back(Token());
|
||||
PP.Lex(Result.back());
|
||||
} while (Result.back().isNot(tok::eof));
|
||||
|
||||
// Pop the token stream off the top of the stack. We know that the internal
|
||||
// pointer inside of it is to the "end" of the token stream, but the stack
|
||||
// will not otherwise be popped until the next token is lexed. The problem is
|
||||
// that the token may be lexed sometime after the vector of tokens itself is
|
||||
// destroyed, which would be badness.
|
||||
PP.RemoveTopOfLexerStack();
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
/// StringifyArgument - Implement C99 6.10.3.2p2, converting a sequence of
|
||||
/// tokens into the literal string token that should be produced by the C #
|
||||
/// preprocessor operator.
|
||||
///
|
||||
static Token StringifyArgument(const Token *ArgToks,
|
||||
Preprocessor &PP, bool Charify = false) {
|
||||
Token Tok;
|
||||
Tok.startToken();
|
||||
Tok.setKind(tok::string_literal);
|
||||
|
||||
const Token *ArgTokStart = ArgToks;
|
||||
|
||||
// Stringify all the tokens.
|
||||
std::string Result = "\"";
|
||||
// FIXME: Optimize this loop to not use std::strings.
|
||||
bool isFirst = true;
|
||||
for (; ArgToks->isNot(tok::eof); ++ArgToks) {
|
||||
const Token &Tok = *ArgToks;
|
||||
if (!isFirst && (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()))
|
||||
Result += ' ';
|
||||
isFirst = false;
|
||||
|
||||
// If this is a string or character constant, escape the token as specified
|
||||
// by 6.10.3.2p2.
|
||||
if (Tok.is(tok::string_literal) || // "foo"
|
||||
Tok.is(tok::wide_string_literal) || // L"foo"
|
||||
Tok.is(tok::char_constant)) { // 'x' and L'x'.
|
||||
Result += Lexer::Stringify(PP.getSpelling(Tok));
|
||||
} else {
|
||||
// Otherwise, just append the token.
|
||||
Result += PP.getSpelling(Tok);
|
||||
}
|
||||
}
|
||||
|
||||
// If the last character of the string is a \, and if it isn't escaped, this
|
||||
// is an invalid string literal, diagnose it as specified in C99.
|
||||
if (Result[Result.size()-1] == '\\') {
|
||||
// Count the number of consequtive \ characters. If even, then they are
|
||||
// just escaped backslashes, otherwise it's an error.
|
||||
unsigned FirstNonSlash = Result.size()-2;
|
||||
// Guaranteed to find the starting " if nothing else.
|
||||
while (Result[FirstNonSlash] == '\\')
|
||||
--FirstNonSlash;
|
||||
if ((Result.size()-1-FirstNonSlash) & 1) {
|
||||
// Diagnose errors for things like: #define F(X) #X / F(\)
|
||||
PP.Diag(ArgToks[-1], diag::pp_invalid_string_literal);
|
||||
Result.erase(Result.end()-1); // remove one of the \'s.
|
||||
}
|
||||
}
|
||||
Result += '"';
|
||||
|
||||
// If this is the charify operation and the result is not a legal character
|
||||
// constant, diagnose it.
|
||||
if (Charify) {
|
||||
// First step, turn double quotes into single quotes:
|
||||
Result[0] = '\'';
|
||||
Result[Result.size()-1] = '\'';
|
||||
|
||||
// Check for bogus character.
|
||||
bool isBad = false;
|
||||
if (Result.size() == 3) {
|
||||
isBad = Result[1] == '\''; // ''' is not legal. '\' already fixed above.
|
||||
} else {
|
||||
isBad = (Result.size() != 4 || Result[1] != '\\'); // Not '\x'
|
||||
}
|
||||
|
||||
if (isBad) {
|
||||
PP.Diag(ArgTokStart[0], diag::err_invalid_character_to_charify);
|
||||
Result = "' '"; // Use something arbitrary, but legal.
|
||||
}
|
||||
}
|
||||
|
||||
Tok.setLength(Result.size());
|
||||
Tok.setLocation(PP.CreateString(&Result[0], Result.size()));
|
||||
return Tok;
|
||||
}
|
||||
|
||||
/// getStringifiedArgument - Compute, cache, and return the specified argument
|
||||
/// that has been 'stringified' as required by the # operator.
|
||||
const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo,
|
||||
Preprocessor &PP) {
|
||||
assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!");
|
||||
if (StringifiedArgs.empty()) {
|
||||
StringifiedArgs.resize(getNumArguments());
|
||||
memset(&StringifiedArgs[0], 0,
|
||||
sizeof(StringifiedArgs[0])*getNumArguments());
|
||||
}
|
||||
if (StringifiedArgs[ArgNo].isNot(tok::string_literal))
|
||||
StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP);
|
||||
return StringifiedArgs[ArgNo];
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TokenLexer Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// Create a TokenLexer for the specified macro with the specified actual
|
||||
/// arguments. Note that this ctor takes ownership of the ActualArgs pointer.
|
||||
|
@ -329,7 +118,8 @@ void TokenLexer::ExpandFunctionArguments() {
|
|||
Res = ActualArgs->getStringifiedArgument(ArgNo, PP);
|
||||
else {
|
||||
// 'charify': don't bother caching these.
|
||||
Res = StringifyArgument(ActualArgs->getUnexpArgument(ArgNo), PP, true);
|
||||
Res = MacroArgs::StringifyArgument(ActualArgs->getUnexpArgument(ArgNo),
|
||||
PP, true);
|
||||
}
|
||||
|
||||
// The stringified/charified string leading space flag gets set to match
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
DE75EDF10B06880E0020CF81 /* Type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE75EDF00B06880E0020CF81 /* Type.cpp */; };
|
||||
DE85CD4B0D8378320070E26E /* Directives.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE85CD4A0D8378320070E26E /* Directives.cpp */; };
|
||||
DE85CD810D8380B10070E26E /* TokenLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE85CD800D8380B10070E26E /* TokenLexer.cpp */; };
|
||||
DE85CDA30D8383B20070E26E /* MacroArgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE85CDA20D8383B20070E26E /* MacroArgs.cpp */; };
|
||||
DE928B130C05659200231DA4 /* ModuleBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE928B120C05659200231DA4 /* ModuleBuilder.cpp */; };
|
||||
DE928B200C0565B000231DA4 /* ModuleBuilder.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE928B1F0C0565B000231DA4 /* ModuleBuilder.h */; };
|
||||
DE928B7D0C0A615100231DA4 /* CodeGenModule.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE928B7C0C0A615100231DA4 /* CodeGenModule.h */; };
|
||||
|
@ -365,6 +366,8 @@
|
|||
DE85CD4A0D8378320070E26E /* Directives.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Directives.cpp; sourceTree = "<group>"; };
|
||||
DE85CD800D8380B10070E26E /* TokenLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TokenLexer.cpp; sourceTree = "<group>"; };
|
||||
DE85CD840D8380F20070E26E /* TokenLexer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TokenLexer.h; sourceTree = "<group>"; };
|
||||
DE85CD9E0D8382DD0070E26E /* MacroArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroArgs.h; sourceTree = "<group>"; };
|
||||
DE85CDA20D8383B20070E26E /* MacroArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MacroArgs.cpp; sourceTree = "<group>"; };
|
||||
DE928B120C05659200231DA4 /* ModuleBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleBuilder.cpp; path = CodeGen/ModuleBuilder.cpp; sourceTree = "<group>"; };
|
||||
DE928B1F0C0565B000231DA4 /* ModuleBuilder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ModuleBuilder.h; path = clang/CodeGen/ModuleBuilder.h; sourceTree = "<group>"; };
|
||||
DE928B7C0C0A615100231DA4 /* CodeGenModule.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = CodeGenModule.h; path = CodeGen/CodeGenModule.h; sourceTree = "<group>"; };
|
||||
|
@ -816,6 +819,8 @@
|
|||
DE344B530AE5E46C00DBC861 /* HeaderSearch.cpp */,
|
||||
DED7D79E0A5242E6003AD0FB /* Lexer.cpp */,
|
||||
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */,
|
||||
DE85CD9E0D8382DD0070E26E /* MacroArgs.h */,
|
||||
DE85CDA20D8383B20070E26E /* MacroArgs.cpp */,
|
||||
DED7D7A00A5242E6003AD0FB /* MacroInfo.cpp */,
|
||||
DED7D7A20A5242E6003AD0FB /* PPExpressions.cpp */,
|
||||
DED7D7A30A5242E6003AD0FB /* Pragma.cpp */,
|
||||
|
@ -983,6 +988,7 @@
|
|||
35D55B280D81D8C60092E734 /* CFRefCount.cpp in Sources */,
|
||||
DE85CD4B0D8378320070E26E /* Directives.cpp in Sources */,
|
||||
DE85CD810D8380B10070E26E /* TokenLexer.cpp in Sources */,
|
||||
DE85CDA30D8383B20070E26E /* MacroArgs.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the TokenLexer and MacroArgs interfaces.
|
||||
// This file defines the TokenLexer interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -15,88 +15,12 @@
|
|||
#define LLVM_CLANG_TOKENLEXER_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
class MacroInfo;
|
||||
class Preprocessor;
|
||||
class Token;
|
||||
|
||||
/// MacroArgs - An instance of this class captures information about
|
||||
/// the formal arguments specified to a function-like macro invocation.
|
||||
class MacroArgs {
|
||||
/// NumUnexpArgTokens - The number of raw, unexpanded tokens for the
|
||||
/// arguments. All of the actual argument tokens are allocated immediately
|
||||
/// after the MacroArgs object in memory. This is all of the arguments
|
||||
/// concatenated together, with 'EOF' markers at the end of each argument.
|
||||
unsigned NumUnexpArgTokens;
|
||||
|
||||
/// PreExpArgTokens - Pre-expanded tokens for arguments that need them. Empty
|
||||
/// if not yet computed. This includes the EOF marker at the end of the
|
||||
/// stream.
|
||||
std::vector<std::vector<Token> > PreExpArgTokens;
|
||||
|
||||
/// StringifiedArgs - This contains arguments in 'stringified' form. If the
|
||||
/// stringified form of an argument has not yet been computed, this is empty.
|
||||
std::vector<Token> StringifiedArgs;
|
||||
|
||||
/// VarargsElided - True if this is a C99 style varargs macro invocation and
|
||||
/// there was no argument specified for the "..." argument. If the argument
|
||||
/// was specified (even empty) or this isn't a C99 style varargs function, or
|
||||
/// if in strict mode and the C99 varargs macro had only a ... argument, this
|
||||
/// is false.
|
||||
bool VarargsElided;
|
||||
|
||||
MacroArgs(unsigned NumToks, bool varargsElided)
|
||||
: NumUnexpArgTokens(NumToks), VarargsElided(varargsElided) {}
|
||||
~MacroArgs() {}
|
||||
public:
|
||||
/// MacroArgs ctor function - Create a new MacroArgs object with the specified
|
||||
/// macro and argument info.
|
||||
static MacroArgs *create(const MacroInfo *MI,
|
||||
const Token *UnexpArgTokens,
|
||||
unsigned NumArgTokens, bool VarargsElided);
|
||||
|
||||
/// destroy - Destroy and deallocate the memory for this object.
|
||||
///
|
||||
void destroy();
|
||||
|
||||
/// ArgNeedsPreexpansion - If we can prove that the argument won't be affected
|
||||
/// by pre-expansion, return false. Otherwise, conservatively return true.
|
||||
bool ArgNeedsPreexpansion(const Token *ArgTok, Preprocessor &PP) const;
|
||||
|
||||
/// getUnexpArgument - Return a pointer to the first token of the unexpanded
|
||||
/// token list for the specified formal.
|
||||
///
|
||||
const Token *getUnexpArgument(unsigned Arg) const;
|
||||
|
||||
/// getArgLength - Given a pointer to an expanded or unexpanded argument,
|
||||
/// return the number of tokens, not counting the EOF, that make up the
|
||||
/// argument.
|
||||
static unsigned getArgLength(const Token *ArgPtr);
|
||||
|
||||
/// getPreExpArgument - Return the pre-expanded form of the specified
|
||||
/// argument.
|
||||
const std::vector<Token> &
|
||||
getPreExpArgument(unsigned Arg, Preprocessor &PP);
|
||||
|
||||
/// getStringifiedArgument - Compute, cache, and return the specified argument
|
||||
/// that has been 'stringified' as required by the # operator.
|
||||
const Token &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP);
|
||||
|
||||
/// getNumArguments - Return the number of arguments passed into this macro
|
||||
/// invocation.
|
||||
unsigned getNumArguments() const { return NumUnexpArgTokens; }
|
||||
|
||||
|
||||
/// isVarargsElidedUse - Return true if this is a C99 style varargs macro
|
||||
/// invocation and there was no argument specified for the "..." argument. If
|
||||
/// the argument was specified (even empty) or this isn't a C99 style varargs
|
||||
/// function, or if in strict mode and the C99 varargs macro had only a ...
|
||||
/// argument, this returns false.
|
||||
bool isVarargsElidedUse() const { return VarargsElided; }
|
||||
};
|
||||
|
||||
class MacroArgs;
|
||||
|
||||
/// TokenLexer - This implements a lexer that returns token from a macro body
|
||||
/// or token stream instead of lexing from a character buffer. This is used for
|
||||
|
|
Loading…
Reference in New Issue