mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-26 11:25:27 +00:00
Read, remember, and validate the arguments provided the a function-style
macro invocation. llvm-svn: 38685
This commit is contained in:
parent
8eede3e6c0
commit
7818605f83
@ -18,8 +18,29 @@
|
||||
using namespace llvm;
|
||||
using namespace clang;
|
||||
|
||||
MacroExpander::MacroExpander(LexerToken &Tok, Preprocessor &pp)
|
||||
: Macro(*Tok.getIdentifierInfo()->getMacroInfo()), PP(pp), CurToken(0),
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MacroFormalArgs Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
MacroFormalArgs::MacroFormalArgs(const MacroInfo *MI) {
|
||||
assert(MI->isFunctionLike() &&
|
||||
"Can't have formal args for an object-like macro!");
|
||||
// Reserve space for arguments to avoid reallocation.
|
||||
unsigned NumArgs = MI->getNumArgs();
|
||||
if (MI->isC99Varargs() || MI->isGNUVarargs())
|
||||
NumArgs += 3; // Varargs can have more than this, just some guess.
|
||||
|
||||
ArgTokens.reserve(NumArgs);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// MacroExpander Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
MacroExpander::MacroExpander(LexerToken &Tok, MacroFormalArgs *Formals,
|
||||
Preprocessor &pp)
|
||||
: Macro(*Tok.getIdentifierInfo()->getMacroInfo()), FormalArgs(Formals),
|
||||
PP(pp), CurToken(0),
|
||||
InstantiateLoc(Tok.getLocation()),
|
||||
AtStartOfLine(Tok.isAtStartOfLine()),
|
||||
HasLeadingSpace(Tok.hasLeadingSpace()) {
|
||||
|
@ -11,10 +11,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// TODO: GCC Diagnostics emitted by the lexer:
|
||||
//
|
||||
// ERROR : __VA_ARGS__ can only appear in the expansion of a C99 variadic macro
|
||||
//
|
||||
// Options to support:
|
||||
// -H - Print the name of each header file used.
|
||||
// -C -CC - Do not discard comments for cpp.
|
||||
@ -28,8 +24,6 @@
|
||||
// Messages to emit:
|
||||
// "Multiple include guards may be useful for:\n"
|
||||
//
|
||||
// TODO: Implement the include guard optimization.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
@ -55,13 +49,16 @@ Preprocessor::Preprocessor(Diagnostic &diags, const LangOptions &opts,
|
||||
// Clear stats.
|
||||
NumDirectives = NumIncluded = NumDefined = NumUndefined = NumPragma = 0;
|
||||
NumIf = NumElse = NumEndif = 0;
|
||||
NumEnteredSourceFiles = NumMacroExpanded = NumFastMacroExpanded = 0;
|
||||
NumEnteredSourceFiles = 0;
|
||||
NumMacroExpanded = NumFnMacroExpanded = NumBuiltinMacroExpanded = 0;
|
||||
NumFastMacroExpanded = 0;
|
||||
MaxIncludeStackDepth = 0; NumMultiIncludeFileOptzn = 0;
|
||||
NumSkipped = 0;
|
||||
|
||||
// Macro expansion is enabled.
|
||||
DisableMacroExpansion = false;
|
||||
SkippingContents = false;
|
||||
InMacroFormalArgs = false;
|
||||
|
||||
// There is no file-change handler yet.
|
||||
FileChangeHandler = 0;
|
||||
@ -199,7 +196,8 @@ void Preprocessor::PrintStats() {
|
||||
std::cerr << " " << NumPragma << " #pragma.\n";
|
||||
std::cerr << NumSkipped << " #if/#ifndef#ifdef regions skipped\n";
|
||||
|
||||
std::cerr << NumMacroExpanded << " macros expanded, "
|
||||
std::cerr << NumMacroExpanded << "/" << NumFnMacroExpanded << "/"
|
||||
<< NumBuiltinMacroExpanded << " obj/fn/builtin macros expanded, "
|
||||
<< NumFastMacroExpanded << " on the fast path.\n";
|
||||
}
|
||||
|
||||
@ -433,7 +431,7 @@ void Preprocessor::EnterSourceFileWithLexer(Lexer *TheLexer,
|
||||
|
||||
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
|
||||
/// tokens from it instead of the current buffer.
|
||||
void Preprocessor::EnterMacro(LexerToken &Tok) {
|
||||
void Preprocessor::EnterMacro(LexerToken &Tok, MacroFormalArgs *Formals) {
|
||||
IdentifierInfo *Identifier = Tok.getIdentifierInfo();
|
||||
MacroInfo &MI = *Identifier->getMacroInfo();
|
||||
IncludeMacroStack.push_back(IncludeStackInfo(CurLexer, CurDirLookup,
|
||||
@ -441,12 +439,10 @@ void Preprocessor::EnterMacro(LexerToken &Tok) {
|
||||
CurLexer = 0;
|
||||
CurDirLookup = 0;
|
||||
|
||||
// TODO: Figure out arguments.
|
||||
|
||||
// Mark the macro as currently disabled, so that it is not recursively
|
||||
// expanded.
|
||||
MI.DisableMacro();
|
||||
CurMacroExpander = new MacroExpander(Tok, *this);
|
||||
CurMacroExpander = new MacroExpander(Tok, Formals, *this);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -485,24 +481,63 @@ void Preprocessor::RegisterBuiltinMacros() {
|
||||
|
||||
/// HandleMacroExpandedIdentifier - If an identifier token is read that is to be
|
||||
/// expanded as a macro, handle it and return the next token as 'Identifier'.
|
||||
void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
|
||||
bool Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
|
||||
MacroInfo *MI) {
|
||||
++NumMacroExpanded;
|
||||
|
||||
// If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
|
||||
if (MI->isBuiltinMacro()) {
|
||||
ExpandBuiltinMacro(Identifier);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// FormalArgs - If this is a function-like macro expansion, this contains,
|
||||
/// for each macro argument, the list of tokens that were provided to the
|
||||
/// invocation.
|
||||
MacroFormalArgs *FormalArgs = 0;
|
||||
|
||||
// If this is a function-like macro, read the arguments.
|
||||
if (MI->isFunctionLike()) {
|
||||
// FIXME: We need to query to see if the ( exists without reading it.
|
||||
|
||||
// C99 6.10.3p10: If the preprocessing token immediately after the the macro
|
||||
// name isn't a '(', this macro should not be expanded.
|
||||
bool isFunctionInvocation = true;
|
||||
if (!isFunctionInvocation)
|
||||
return true;
|
||||
|
||||
LexerToken Tok;
|
||||
LexUnexpandedToken(Tok);
|
||||
assert(Tok.getKind() == tok::l_paren &&
|
||||
"not a function-like macro invocation!");
|
||||
|
||||
// Remember that we are now parsing the arguments to a macro invocation.
|
||||
// Preprocessor directives used inside macro arguments are not portable, and
|
||||
// this enables the warning.
|
||||
InMacroFormalArgs = true;
|
||||
FormalArgs = ReadFunctionLikeMacroFormalArgs(Identifier, MI);
|
||||
|
||||
// Finished parsing args.
|
||||
InMacroFormalArgs = false;
|
||||
|
||||
// If there was an error parsing the arguments, bail out.
|
||||
if (FormalArgs == 0) return false;
|
||||
|
||||
++NumFnMacroExpanded;
|
||||
} else {
|
||||
++NumMacroExpanded;
|
||||
}
|
||||
|
||||
// Notice that this macro has been used.
|
||||
MI->setIsUsed(true);
|
||||
|
||||
// If this is a builtin macro, like __LINE__ or _Pragma, handle it specially.
|
||||
if (MI->isBuiltinMacro())
|
||||
return ExpandBuiltinMacro(Identifier);
|
||||
|
||||
// If we started lexing a macro, enter the macro expansion body.
|
||||
// FIXME: Fn-Like Macros: Read/Validate the argument list here!
|
||||
|
||||
|
||||
// If this macro expands to no tokens, don't bother to push it onto the
|
||||
// expansion stack, only to take it right back off.
|
||||
if (MI->getNumTokens() == 0) {
|
||||
// No need for formal arg info.
|
||||
delete FormalArgs;
|
||||
|
||||
// Ignore this macro use, just return the next token in the current
|
||||
// buffer.
|
||||
bool HadLeadingSpace = Identifier.hasLeadingSpace();
|
||||
@ -519,13 +554,14 @@ void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
|
||||
if (HadLeadingSpace) Identifier.SetFlag(LexerToken::LeadingSpace);
|
||||
}
|
||||
++NumFastMacroExpanded;
|
||||
return;
|
||||
return false;
|
||||
|
||||
} else if (MI->getNumTokens() == 1 &&
|
||||
// FIXME: Fn-Like Macros: Fast if arg not used.
|
||||
FormalArgs == 0 &&
|
||||
// Don't handle identifiers if they need recursive expansion.
|
||||
(MI->getReplacementToken(0).getIdentifierInfo() == 0 ||
|
||||
!MI->getReplacementToken(0).getIdentifierInfo()->getMacroInfo())){
|
||||
// FIXME: Fn-Like Macros: Function-style macros only if no arguments?
|
||||
|
||||
// Otherwise, if this macro expands into a single trivially-expanded
|
||||
// token: expand it now. This handles common cases like
|
||||
@ -555,15 +591,115 @@ void Preprocessor::HandleMacroExpandedIdentifier(LexerToken &Identifier,
|
||||
// Since this is not an identifier token, it can't be macro expanded, so
|
||||
// we're done.
|
||||
++NumFastMacroExpanded;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start expanding the macro (FIXME: Fn-Like Macros: pass arguments).
|
||||
EnterMacro(Identifier);
|
||||
// Start expanding the macro.
|
||||
EnterMacro(Identifier, FormalArgs);
|
||||
|
||||
// Now that the macro is at the top of the include stack, ask the
|
||||
// preprocessor to read the next token from it.
|
||||
return Lex(Identifier);
|
||||
Lex(Identifier);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ReadFunctionLikeMacroFormalArgs - After reading "MACRO(", this method is
|
||||
/// invoked to read all of the formal arguments specified for the macro
|
||||
/// invocation. This returns null on error.
|
||||
MacroFormalArgs *Preprocessor::
|
||||
ReadFunctionLikeMacroFormalArgs(LexerToken &MacroName, MacroInfo *MI) {
|
||||
// Use an auto_ptr here so that the MacroFormalArgs object is deleted on
|
||||
// all error paths.
|
||||
std::auto_ptr<MacroFormalArgs> Args(new MacroFormalArgs(MI));
|
||||
|
||||
// The number of fixed arguments to parse.
|
||||
unsigned NumFixedArgsLeft = MI->getNumArgs();
|
||||
bool isVariadic = MI->isVariadic();
|
||||
|
||||
// If this is a C99-style varargs macro invocation, add an extra expected
|
||||
// argument, which will catch all of the varargs formals in one argument.
|
||||
if (MI->isC99Varargs())
|
||||
++NumFixedArgsLeft;
|
||||
|
||||
// Outer loop, while there are more arguments, keep reading them.
|
||||
LexerToken Tok;
|
||||
Tok.SetKind(tok::comma);
|
||||
--NumFixedArgsLeft; // Start reading the first arg.
|
||||
|
||||
while (Tok.getKind() == tok::comma) {
|
||||
// ArgTokens - Build up a list of tokens that make up this argument.
|
||||
std::vector<LexerToken> ArgTokens;
|
||||
// C99 6.10.3p11: Keep track of the number of l_parens we have seen.
|
||||
unsigned NumParens = 0;
|
||||
|
||||
while (1) {
|
||||
LexUnexpandedToken(Tok);
|
||||
|
||||
if (Tok.getKind() == tok::eof) {
|
||||
Diag(MacroName, diag::err_unterm_macro_invoc);
|
||||
// Do not lose the EOF. Return it to the client.
|
||||
MacroName = Tok;
|
||||
return 0;
|
||||
} else if (Tok.getKind() == tok::r_paren) {
|
||||
// If we found the ) token, the macro arg list is done.
|
||||
if (NumParens-- == 0)
|
||||
break;
|
||||
} else if (Tok.getKind() == tok::l_paren) {
|
||||
++NumParens;
|
||||
} else if (Tok.getKind() == tok::comma && NumParens == 0) {
|
||||
// Comma ends this argument if there are more fixed arguments expected.
|
||||
if (NumFixedArgsLeft)
|
||||
break;
|
||||
|
||||
// If this is not a variadic macro, too many formals were specified.
|
||||
if (!isVariadic) {
|
||||
// Emit the diagnostic at the macro name in case there is a missing ).
|
||||
// Emitting it at the , could be far away from the macro name.
|
||||
Diag(MacroName, diag::err_too_many_formals_in_macro_invoc);
|
||||
return 0;
|
||||
}
|
||||
// Otherwise, continue to add the tokens to this variable argument.
|
||||
}
|
||||
|
||||
ArgTokens.push_back(Tok);
|
||||
}
|
||||
|
||||
// Remember the tokens that make up this argument. This destroys ArgTokens.
|
||||
Args->addArgument(ArgTokens);
|
||||
--NumFixedArgsLeft;
|
||||
};
|
||||
|
||||
// Okay, we either found the r_paren. Check to see if we parsed too few
|
||||
// arguments.
|
||||
unsigned NumFormals = Args->getNumArguments();
|
||||
unsigned MinArgsExpected = MI->getNumArgs();
|
||||
|
||||
// C99 expects us to pass at least one vararg arg (but as an extension, we
|
||||
// don't require this).
|
||||
if (MI->isC99Varargs())
|
||||
++MinArgsExpected;
|
||||
|
||||
if (NumFormals < MinArgsExpected) {
|
||||
// There are several cases where too few arguments is ok, handle them now.
|
||||
if (NumFormals+1 == MinArgsExpected && MI->isVariadic()) {
|
||||
// Varargs where the named vararg parameter is missing: ok as extension.
|
||||
// #define A(x, ...)
|
||||
// A("blah")
|
||||
Diag(Tok, diag::ext_missing_varargs_arg);
|
||||
} else if (MI->getNumArgs() == 1) {
|
||||
// #define A(x)
|
||||
// A()
|
||||
// is ok. Add an empty argument.
|
||||
std::vector<LexerToken> ArgTokens;
|
||||
Args->addArgument(ArgTokens);
|
||||
} else {
|
||||
// Otherwise, emit the error.
|
||||
Diag(Tok, diag::err_too_few_formals_in_macro_invoc);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return Args.release();
|
||||
}
|
||||
|
||||
/// ComputeDATE_TIME - Compute the current time, enter it into the specified
|
||||
@ -599,6 +735,8 @@ void Preprocessor::ExpandBuiltinMacro(LexerToken &Tok) {
|
||||
if (II == Ident_Pragma)
|
||||
return Handle_Pragma(Tok);
|
||||
|
||||
++NumBuiltinMacroExpanded;
|
||||
|
||||
char TmpBuffer[100];
|
||||
|
||||
// Set up the return result.
|
||||
@ -750,9 +888,11 @@ void Preprocessor::HandleIdentifier(LexerToken &Identifier) {
|
||||
Diag(Identifier, diag::ext_pp_bad_vaargs_use);
|
||||
}
|
||||
|
||||
// If this is a macro to be expanded, do it.
|
||||
if (MacroInfo *MI = II.getMacroInfo())
|
||||
if (MI->isEnabled() && !DisableMacroExpansion)
|
||||
return HandleMacroExpandedIdentifier(Identifier, MI);
|
||||
if (!HandleMacroExpandedIdentifier(Identifier, MI))
|
||||
return;
|
||||
|
||||
// Change the kind of this identifier to the appropriate token kind, e.g.
|
||||
// turning "for" into a keyword.
|
||||
@ -1101,7 +1241,7 @@ void Preprocessor::HandleDirective(LexerToken &Result) {
|
||||
|
||||
// We just parsed a # character at the start of a line, so we're in directive
|
||||
// mode. Tell the lexer this so any newlines we see will be converted into an
|
||||
// EOM token (this terminates the macro).
|
||||
// EOM token (which terminates the directive).
|
||||
CurLexer->ParsingPreprocessorDirective = true;
|
||||
|
||||
++NumDirectives;
|
||||
@ -1111,9 +1251,19 @@ void Preprocessor::HandleDirective(LexerToken &Result) {
|
||||
// pp-directive.
|
||||
bool ReadAnyTokensBeforeDirective = CurLexer->MIOpt.getHasReadAnyTokensVal();
|
||||
|
||||
// Read the next token, the directive flavor.
|
||||
// Read the next token, the directive flavor. This isn't expanded due to
|
||||
// C99 6.10.3p8.
|
||||
LexUnexpandedToken(Result);
|
||||
|
||||
// C99 6.10.3p11: Is this preprocessor directive in macro invocation? e.g.:
|
||||
// #define A(x) #x
|
||||
// A(abc
|
||||
// #warning blah
|
||||
// def)
|
||||
// If so, the user is relying on non-portable behavior, emit a diagnostic.
|
||||
if (InMacroFormalArgs)
|
||||
Diag(Result, diag::ext_embedded_directive);
|
||||
|
||||
switch (Result.getKind()) {
|
||||
default: break;
|
||||
case tok::eom:
|
||||
@ -1436,6 +1586,8 @@ void Preprocessor::HandleDefineDirective(LexerToken &DefineTok) {
|
||||
LexerToken Tok;
|
||||
LexUnexpandedToken(Tok);
|
||||
|
||||
// FIXME: Enable __VA_ARGS__.
|
||||
|
||||
// If this is a function-like macro definition, parse the argument list,
|
||||
// marking each of the identifiers as being used as macro arguments. Also,
|
||||
// check other constraints on the first token of the macro body.
|
||||
@ -1503,22 +1655,20 @@ void Preprocessor::HandleDefineDirective(LexerToken &DefineTok) {
|
||||
LexUnexpandedToken(Tok);
|
||||
}
|
||||
|
||||
unsigned NumTokens = MI->getNumTokens();
|
||||
|
||||
// Clear the "isMacroArg" flags from all the macro arguments.
|
||||
MI->SetIdentifierIsMacroArgFlags(false);
|
||||
|
||||
// Check that there is no paste (##) operator at the begining or end of the
|
||||
// replacement list.
|
||||
unsigned NumTokens = MI->getNumTokens();
|
||||
if (NumTokens != 0) {
|
||||
if (MI->getReplacementToken(0).getKind() == tok::hashhash) {
|
||||
Diag(MI->getReplacementToken(0), diag::err_paste_at_start);
|
||||
// Clear the "isMacroArg" flags from all the macro arguments.
|
||||
MI->SetIdentifierIsMacroArgFlags(false);
|
||||
delete MI;
|
||||
return;
|
||||
}
|
||||
if (MI->getReplacementToken(NumTokens-1).getKind() == tok::hashhash) {
|
||||
Diag(MI->getReplacementToken(NumTokens-1), diag::err_paste_at_end);
|
||||
// Clear the "isMacroArg" flags from all the macro arguments.
|
||||
MI->SetIdentifierIsMacroArgFlags(false);
|
||||
delete MI;
|
||||
return;
|
||||
}
|
||||
@ -1546,9 +1696,6 @@ void Preprocessor::HandleDefineDirective(LexerToken &DefineTok) {
|
||||
}
|
||||
|
||||
MacroNameTok.getIdentifierInfo()->setMacroInfo(MI);
|
||||
|
||||
// Clear the "isMacroArg" flags from all the macro arguments.
|
||||
MI->SetIdentifierIsMacroArgFlags(false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -123,6 +123,10 @@ DIAG(ext_variadic_macro, EXTENSION,
|
||||
"variadic macros were introduced in C99")
|
||||
DIAG(ext_named_variadic_macro, EXTENSION,
|
||||
"named variadic macros are a GNU extension")
|
||||
DIAG(ext_embedded_directive, EXTENSION,
|
||||
"embedding a directive within macro arguments is not portable")
|
||||
DIAG(ext_missing_varargs_arg, EXTENSION,
|
||||
"varargs argument missing, but tolerated as an extension")
|
||||
|
||||
DIAG(ext_pp_base_file, EXTENSION,
|
||||
"__BASE_FILE__ is a language extension")
|
||||
@ -207,6 +211,13 @@ DIAG(err_paste_at_start, ERROR,
|
||||
"\"##\" cannot appear at start of macro expansion")
|
||||
DIAG(err_paste_at_end, ERROR,
|
||||
"\"##\" cannot appear at end of macro expansion")
|
||||
DIAG(err_unterm_macro_invoc, ERROR,
|
||||
"unterminated function-like macro invocation")
|
||||
DIAG(err_too_many_formals_in_macro_invoc, ERROR,
|
||||
"too many arguments provided to function-like macro invocation")
|
||||
DIAG(err_too_few_formals_in_macro_invoc, ERROR,
|
||||
"too few arguments provided to function-like macro invocation")
|
||||
|
||||
|
||||
// Should be a sorry?
|
||||
DIAG(err_pp_I_dash_not_supported, ERROR,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define LLVM_CLANG_MACROEXPANDER_H
|
||||
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
namespace clang {
|
||||
@ -22,6 +23,26 @@ namespace clang {
|
||||
class Preprocessor;
|
||||
class LexerToken;
|
||||
|
||||
/// MacroFormalArgs - An instance of this class captures information about
|
||||
/// the formal arguments specified to a function-like macro invocation.
|
||||
class MacroFormalArgs {
|
||||
std::vector<std::vector<LexerToken> > ArgTokens;
|
||||
public:
|
||||
MacroFormalArgs(const MacroInfo *MI);
|
||||
|
||||
/// addArgument - Add an argument for this invocation. This method destroys
|
||||
/// the vector passed in to avoid extraneous memory copies.
|
||||
void addArgument(std::vector<LexerToken> &ArgToks) {
|
||||
ArgTokens.push_back(std::vector<LexerToken>());
|
||||
ArgTokens.back().swap(ArgToks);
|
||||
}
|
||||
|
||||
/// getNumArguments - Return the number of arguments passed into this macro
|
||||
/// invocation.
|
||||
unsigned getNumArguments() const { return ArgTokens.size(); }
|
||||
};
|
||||
|
||||
|
||||
/// MacroExpander - This implements a lexer that returns token from a macro body
|
||||
/// instead of lexing from a character buffer.
|
||||
///
|
||||
@ -29,6 +50,10 @@ class MacroExpander {
|
||||
/// 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;
|
||||
|
||||
/// PP - The current preprocessor object we are expanding for.
|
||||
///
|
||||
@ -45,15 +70,24 @@ class MacroExpander {
|
||||
/// that the macro expanded from had these properties.
|
||||
bool AtStartOfLine, HasLeadingSpace;
|
||||
|
||||
MacroExpander(const MacroExpander&); // DO NOT IMPLEMENT
|
||||
void operator=(const MacroExpander&); // DO NOT IMPLEMENT
|
||||
public:
|
||||
MacroExpander(LexerToken &Tok, Preprocessor &pp);
|
||||
/// Create a macro expander of the specified macro with the specified formal
|
||||
/// 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;
|
||||
}
|
||||
|
||||
MacroInfo &getMacro() const { return Macro; }
|
||||
|
||||
/// Lex - Lex and return a token from this macro stream.
|
||||
void Lex(LexerToken &Tok);
|
||||
};
|
||||
|
||||
|
||||
} // end namespace llvm
|
||||
} // end namespace clang
|
||||
|
||||
|
@ -104,7 +104,7 @@ public:
|
||||
typedef std::vector<IdentifierInfo*>::const_iterator arg_iterator;
|
||||
arg_iterator arg_begin() const { return Arguments.begin(); }
|
||||
arg_iterator arg_end() const { return Arguments.end(); }
|
||||
|
||||
unsigned getNumArgs() const { return Arguments.size(); }
|
||||
|
||||
/// Function/Object-likeness. Keep track of whether this macro has formal
|
||||
/// parameters.
|
||||
@ -117,6 +117,7 @@ public:
|
||||
void setIsGNUVarargs() { IsGNUVarargs = true; }
|
||||
bool isC99Varargs() const { return IsC99Varargs; }
|
||||
bool isGNUVarargs() const { return IsGNUVarargs; }
|
||||
bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; }
|
||||
|
||||
/// isBuiltinMacro - Return true if this macro is a builtin macro, such as
|
||||
/// __LINE__, which requires processing before expansion.
|
||||
|
@ -130,6 +130,7 @@ private:
|
||||
// State that changes while the preprocessor runs:
|
||||
bool DisableMacroExpansion; // True if macro expansion is disabled.
|
||||
bool SkippingContents; // True if in a #if 0 block.
|
||||
bool InMacroFormalArgs; // True if parsing fn macro invocation args.
|
||||
|
||||
/// Identifiers - This is mapping/lookup information for all identifiers in
|
||||
/// the program, including program keywords.
|
||||
@ -199,7 +200,8 @@ private:
|
||||
unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma;
|
||||
unsigned NumIf, NumElse, NumEndif;
|
||||
unsigned NumEnteredSourceFiles, MaxIncludeStackDepth,NumMultiIncludeFileOptzn;
|
||||
unsigned NumMacroExpanded, NumFastMacroExpanded;
|
||||
unsigned NumMacroExpanded, NumFnMacroExpanded, NumBuiltinMacroExpanded;
|
||||
unsigned NumFastMacroExpanded;
|
||||
unsigned NumSkipped;
|
||||
public:
|
||||
Preprocessor(Diagnostic &diags, const LangOptions &opts, FileManager &FM,
|
||||
@ -320,8 +322,9 @@ public:
|
||||
bool isMainFile = false);
|
||||
|
||||
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
|
||||
/// tokens from it instead of the current buffer.
|
||||
void EnterMacro(LexerToken &Identifier);
|
||||
/// tokens from it instead of the current buffer. Formals specifies the
|
||||
/// tokens input to a function-like macro.
|
||||
void EnterMacro(LexerToken &Identifier, MacroFormalArgs *Formals);
|
||||
|
||||
|
||||
/// Lex - To lex a token from the preprocessor, just pull a token from the
|
||||
@ -460,8 +463,15 @@ private:
|
||||
IdentifierInfo *RegisterBuiltinMacro(const char *Name);
|
||||
|
||||
/// HandleMacroExpandedIdentifier - If an identifier token is read that is to
|
||||
/// be expanded as a macro, handle it and return the next token as 'Tok'.
|
||||
void HandleMacroExpandedIdentifier(LexerToken &Tok, MacroInfo *MI);
|
||||
/// be expanded as a macro, handle it and return the next token as 'Tok'. If
|
||||
/// the macro should not be expanded return true, otherwise return false.
|
||||
bool HandleMacroExpandedIdentifier(LexerToken &Tok, MacroInfo *MI);
|
||||
|
||||
/// ReadFunctionLikeMacroFormalArgs - After reading "MACRO(", this method is
|
||||
/// invoked to read all of the formal arguments specified for the macro
|
||||
/// invocation. This returns null on error.
|
||||
MacroFormalArgs *ReadFunctionLikeMacroFormalArgs(LexerToken &MacroName,
|
||||
MacroInfo *MI);
|
||||
|
||||
/// ExpandBuiltinMacro - If an identifier token is read that is to be expanded
|
||||
/// as a builtin macro, handle it and return the next token as 'Tok'.
|
||||
|
Loading…
x
Reference in New Issue
Block a user