[cfe-commits] r38707 - in /cfe/cfe/trunk: Lex/MacroExpander.cpp include/clang/Lex/MacroExpander.h include/clang/Lex/MacroInfo.h
sabre at cs.uiuc.edu
sabre at cs.uiuc.edu
Wed Jul 11 09:23:59 PDT 2007
Author: sabre
Date: Wed Jul 11 11:23:59 2007
New Revision: 38707
URL: http://llvm.org/viewvc/llvm-project?rev=38707&view=rev
Log:
Set up infrastructure for function-like macro expansion with preexpansion
stringizing, etc.
Modified:
cfe/cfe/trunk/Lex/MacroExpander.cpp
cfe/cfe/trunk/include/clang/Lex/MacroExpander.h
cfe/cfe/trunk/include/clang/Lex/MacroInfo.h
Modified: cfe/cfe/trunk/Lex/MacroExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Lex/MacroExpander.cpp?rev=38707&r1=38706&r2=38707&view=diff
==============================================================================
--- cfe/cfe/trunk/Lex/MacroExpander.cpp (original)
+++ cfe/cfe/trunk/Lex/MacroExpander.cpp Wed Jul 11 11:23:59 2007
@@ -33,29 +33,112 @@
ArgTokens.reserve(NumArgs);
}
+/// StringifyArgument - Implement C99 6.10.3.2p2.
+static LexerToken StringifyArgument(const std::vector<LexerToken> &Toks,
+ Preprocessor &PP) {
+ LexerToken Tok;
+ Tok.StartToken();
+ Tok.SetKind(tok::string_literal);
+
+ std::string Val = "\"XXYZLAKSDFJAS\"";
+ Tok.SetLength(Val.size());
+ Tok.SetLocation(PP.CreateString(&Val[0], Val.size()));
+ return Tok;
+}
+
+/// getStringifiedArgument - Compute, cache, and return the specified argument
+/// that has been 'stringified' as required by the # operator.
+const LexerToken &MacroFormalArgs::getStringifiedArgument(unsigned ArgNo,
+ Preprocessor &PP) {
+ assert(ArgNo < ArgTokens.size() && "Invalid argument number!");
+ if (StringifiedArgs.empty()) {
+ StringifiedArgs.resize(ArgTokens.size());
+ memset(&StringifiedArgs[0], 0, sizeof(StringifiedArgs[0])*ArgTokens.size());
+ }
+ if (StringifiedArgs[ArgNo].getKind() != tok::string_literal)
+ StringifiedArgs[ArgNo] = StringifyArgument(ArgTokens[ArgNo], PP);
+ return StringifiedArgs[ArgNo];
+}
+
//===----------------------------------------------------------------------===//
// MacroExpander Implementation
//===----------------------------------------------------------------------===//
MacroExpander::MacroExpander(LexerToken &Tok, MacroFormalArgs *Formals,
Preprocessor &pp)
- : Macro(*Tok.getIdentifierInfo()->getMacroInfo()), FormalArgs(Formals),
- PP(pp), CurToken(0),
+ : Macro(*Tok.getIdentifierInfo()->getMacroInfo()),
+ FormalArgs(Formals), PP(pp), CurToken(0),
InstantiateLoc(Tok.getLocation()),
AtStartOfLine(Tok.isAtStartOfLine()),
HasLeadingSpace(Tok.hasLeadingSpace()) {
+ MacroTokens = &Macro.getReplacementTokens();
+
+ // If this is a function-like macro, expand the arguments and change
+ // MacroTokens to point to the expanded tokens.
+ if (Macro.isFunctionLike() && Macro.getNumArgs())
+ ExpandFunctionArguments();
+}
+
+MacroExpander::~MacroExpander() {
+ // If this was a function-like macro that actually uses its arguments, delete
+ // the expanded tokens.
+ if (MacroTokens != &Macro.getReplacementTokens())
+ delete MacroTokens;
+
+ // MacroExpander owns its formal arguments.
+ delete FormalArgs;
}
+/// Expand the arguments of a function-like macro so that we can quickly
+/// return preexpanded tokens from MacroTokens.
+void MacroExpander::ExpandFunctionArguments() {
+ std::vector<LexerToken> ResultToks;
+
+ // Loop through the MacroTokens tokens, expanding them into ResultToks. Keep
+ // track of whether we change anything. If not, no need to keep them. If so,
+ // we install the newly expanded sequence as MacroTokens.
+ bool MadeChange = false;
+ for (unsigned i = 0, e = MacroTokens->size(); i != e; ++i) {
+ // If we found the stringify operator, get the argument stringified. The
+ // preprocessor already verified that the following token is a macro name
+ // when the #define was parsed.
+ const LexerToken &CurTok = (*MacroTokens)[i];
+ if (CurTok.getKind() == tok::hash) {
+ int ArgNo = Macro.getArgumentNum((*MacroTokens)[i+1].getIdentifierInfo());
+ assert(ArgNo != -1 && "Token following # is not an argument?");
+
+ ResultToks.push_back(FormalArgs->getStringifiedArgument(ArgNo, PP));
+
+ // FIXME: Should the stringified string leading space flag get set to
+ // match the # or the identifier?
+
+ MadeChange = true;
+ ++i; // Skip arg name.
+ } else {
+ // FIXME: handle microsoft charize extension.
+
+ ResultToks.push_back(CurTok);
+ }
+ }
+
+ // If anything changed, install this as the new MacroTokens list.
+ if (MadeChange) {
+ // This is deleted in the dtor.
+ std::vector<LexerToken> *Res = new std::vector<LexerToken>();
+ Res->swap(ResultToks);
+ MacroTokens = Res;
+ }
+}
/// Lex - Lex and return a token from this macro stream.
///
void MacroExpander::Lex(LexerToken &Tok) {
// Lexing off the end of the macro, pop this macro off the expansion stack.
- if (CurToken == Macro.getNumTokens())
+ if (isAtEnd())
return PP.HandleEndOfMacro(Tok);
// Get the next token to return.
- Tok = Macro.getReplacementToken(CurToken++);
+ Tok = (*MacroTokens)[CurToken++];
// The token's current location indicate where the token was lexed from. We
// need this information to compute the spelling of the token, but any
@@ -84,8 +167,7 @@
/// 1, otherwise return 0.
unsigned MacroExpander::isNextTokenLParen() const {
// Out of tokens?
- if (CurToken == Macro.getNumTokens())
+ if (isAtEnd())
return 2;
-
- return Macro.getReplacementToken(CurToken).getKind() == tok::l_paren;
+ return (*MacroTokens)[CurToken].getKind() == tok::l_paren;
}
Modified: cfe/cfe/trunk/include/clang/Lex/MacroExpander.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/MacroExpander.h?rev=38707&r1=38706&r2=38707&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroExpander.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroExpander.h Wed Jul 11 11:23:59 2007
@@ -27,6 +27,10 @@
/// the formal arguments specified to a function-like macro invocation.
class MacroFormalArgs {
std::vector<std::vector<LexerToken> > ArgTokens;
+
+ /// StringifiedArgs - This contains arguments in 'stringified' form. If the
+ /// stringified form of an argument has not yet been computed, this is empty.
+ std::vector<LexerToken> StringifiedArgs;
public:
MacroFormalArgs(const MacroInfo *MI);
@@ -37,6 +41,10 @@
ArgTokens.back().swap(ArgToks);
}
+ /// getStringifiedArgument - Compute, cache, and return the specified argument
+ /// that has been 'stringified' as required by the # operator.
+ const LexerToken &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP);
+
/// getNumArguments - Return the number of arguments passed into this macro
/// invocation.
unsigned getNumArguments() const { return ArgTokens.size(); }
@@ -50,7 +58,7 @@
/// Macro - The macro we are expanding from.
///
MacroInfo &Macro;
-
+
/// FormalArgs - The formal arguments specified for a function-like macro, or
/// null. The MacroExpander owns the pointed-to object.
MacroFormalArgs *FormalArgs;
@@ -58,8 +66,13 @@
/// PP - The current preprocessor object we are expanding for.
///
Preprocessor &PP;
+
+ /// MacroTokens - This is the pointer to the list of tokens that the macro is
+ /// defined to, with arguments expanded for function-like macros.
+ const std::vector<LexerToken> *MacroTokens;
/// CurToken - This is the next token that Lex will return.
+ ///
unsigned CurToken;
/// InstantiateLoc - The source location where this macro was instantiated.
@@ -77,10 +90,7 @@
/// arguments. Note that this ctor takes ownership of the FormalArgs pointer.
MacroExpander(LexerToken &Tok, MacroFormalArgs *FormalArgs,
Preprocessor &pp);
- ~MacroExpander() {
- // MacroExpander owns its formal arguments.
- delete FormalArgs;
- }
+ ~MacroExpander();
/// isNextTokenLParen - If the next token lexed will pop this macro off the
/// expansion stack, return 2. If the next unexpanded token is a '(', return
@@ -91,6 +101,17 @@
/// Lex - Lex and return a token from this macro stream.
void Lex(LexerToken &Tok);
+
+private:
+ /// isAtEnd - Return true if the next lex call will pop this macro off the
+ /// include stack.
+ bool isAtEnd() const {
+ return CurToken == MacroTokens->size();
+ }
+
+ /// Expand the arguments of a function-like macro so that we can quickly
+ /// return preexpanded tokens from MacroTokens.
+ void ExpandFunctionArguments();
};
} // end namespace llvm
Modified: cfe/cfe/trunk/include/clang/Lex/MacroInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Lex/MacroInfo.h?rev=38707&r1=38706&r2=38707&view=diff
==============================================================================
--- cfe/cfe/trunk/include/clang/Lex/MacroInfo.h (original)
+++ cfe/cfe/trunk/include/clang/Lex/MacroInfo.h Wed Jul 11 11:23:59 2007
@@ -98,6 +98,14 @@
void addArgument(IdentifierInfo *Arg) {
Arguments.push_back(Arg);
}
+
+ /// getArgumentNum - Return the argument number of the specified identifier,
+ /// or -1 if the identifier is not a formal argument identifier.
+ int getArgumentNum(IdentifierInfo *Arg) {
+ for (unsigned i = 0, e = Arguments.size(); i != e; ++i)
+ if (Arguments[i] == Arg) return i;
+ return -1;
+ }
/// Arguments - The list of arguments for a function-like macro. This can be
/// empty, for, e.g. "#define X()".
@@ -137,6 +145,10 @@
assert(Tok < ReplacementTokens.size() && "Invalid token #");
return ReplacementTokens[Tok];
}
+
+ const std::vector<LexerToken> &getReplacementTokens() const {
+ return ReplacementTokens;
+ }
/// AddTokenToBody - Add the specified token to the replacement text for the
/// macro.
More information about the cfe-commits
mailing list