diff options
Diffstat (limited to 'lib/Lex/MacroArgs.cpp')
-rw-r--r-- | lib/Lex/MacroArgs.cpp | 63 |
1 files changed, 40 insertions, 23 deletions
diff --git a/lib/Lex/MacroArgs.cpp b/lib/Lex/MacroArgs.cpp index 1c1979d8e8..5c0f0623c3 100644 --- a/lib/Lex/MacroArgs.cpp +++ b/lib/Lex/MacroArgs.cpp @@ -33,7 +33,7 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI, // See if we have an entry with a big enough argument list to reuse on the // free list. If so, reuse it. for (MacroArgs **Entry = &PP.MacroArgCache; *Entry; - Entry = &(*Entry)->ArgCache) + Entry = &(*Entry)->ArgCache) { if ((*Entry)->NumUnexpArgTokens >= UnexpArgTokens.size() && (*Entry)->NumUnexpArgTokens < ClosestMatch) { ResultEnt = Entry; @@ -44,26 +44,31 @@ MacroArgs *MacroArgs::create(const MacroInfo *MI, // Otherwise, use the best fit. ClosestMatch = (*Entry)->NumUnexpArgTokens; } - + } MacroArgs *Result; if (!ResultEnt) { - // Allocate memory for a MacroArgs object with the lexer tokens at the end. - Result = (MacroArgs*)malloc(sizeof(MacroArgs) + - UnexpArgTokens.size() * sizeof(Token)); - // Construct the MacroArgs object. - new (Result) MacroArgs(UnexpArgTokens.size(), VarargsElided); + // Allocate memory for a MacroArgs object with the lexer tokens at the end, + // and construct the MacroArgs object. + Result = new (std::malloc(totalSizeToAlloc<Token>(UnexpArgTokens.size()))) + MacroArgs(UnexpArgTokens.size(), VarargsElided, MI->getNumParams()); } else { Result = *ResultEnt; // Unlink this node from the preprocessors singly linked list. *ResultEnt = Result->ArgCache; Result->NumUnexpArgTokens = UnexpArgTokens.size(); Result->VarargsElided = VarargsElided; + Result->NumMacroArgs = MI->getNumParams(); } // Copy the actual unexpanded tokens to immediately after the result ptr. - if (!UnexpArgTokens.empty()) - std::copy(UnexpArgTokens.begin(), UnexpArgTokens.end(), - const_cast<Token*>(Result->getUnexpArgument(0))); + if (!UnexpArgTokens.empty()) { + static_assert(std::is_trivial<Token>::value, + "assume trivial copyability if copying into the " + "uninitialized array (as opposed to reusing a cached " + "MacroArgs)"); + std::copy(UnexpArgTokens.begin(), UnexpArgTokens.end(), + Result->getTrailingObjects<Token>()); + } return Result; } @@ -91,6 +96,8 @@ MacroArgs *MacroArgs::deallocate() { // Run the dtor to deallocate the vectors. this->~MacroArgs(); // Release the memory for the object. + static_assert(std::is_trivially_destructible<Token>::value, + "assume trivially destructible and forego destructors"); free(this); return Next; @@ -111,10 +118,13 @@ unsigned MacroArgs::getArgLength(const Token *ArgPtr) { /// getUnexpArgument - Return the unexpanded tokens for the specified formal. /// const Token *MacroArgs::getUnexpArgument(unsigned Arg) const { + + assert(Arg < getNumMacroArguments() && "Invalid arg #"); // The unexpanded argument tokens start immediately after the MacroArgs object // in memory. - const Token *Start = (const Token *)(this+1); + const Token *Start = getTrailingObjects<Token>(); const Token *Result = Start; + // Scan to find Arg. for (; Arg; ++Result) { assert(Result < Start+NumUnexpArgTokens && "Invalid arg #"); @@ -125,6 +135,16 @@ const Token *MacroArgs::getUnexpArgument(unsigned Arg) const { return Result; } +// This function assumes that the variadic arguments are the tokens +// corresponding to the last parameter (ellipsis) - and since tokens are +// separated by the 'eof' token, if that is the only token corresponding to that +// last parameter, we know no variadic arguments were supplied. +bool MacroArgs::invokedWithVariadicArgument(const MacroInfo *const MI) const { + if (!MI->isVariadic()) + return false; + const int VariadicArgIndex = getNumMacroArguments() - 1; + return getUnexpArgument(VariadicArgIndex)->isNot(tok::eof); +} /// ArgNeedsPreexpansion - If we can prove that the argument won't be affected /// by pre-expansion, return false. Otherwise, conservatively return true. @@ -143,14 +163,13 @@ bool MacroArgs::ArgNeedsPreexpansion(const Token *ArgTok, /// getPreExpArgument - Return the pre-expanded form of the specified /// argument. -const std::vector<Token> & -MacroArgs::getPreExpArgument(unsigned Arg, const MacroInfo *MI, - Preprocessor &PP) { - assert(Arg < MI->getNumArgs() && "Invalid argument number!"); +const std::vector<Token> &MacroArgs::getPreExpArgument(unsigned Arg, + Preprocessor &PP) { + assert(Arg < getNumMacroArguments() && "Invalid argument number!"); // If we have already computed this, return it. - if (PreExpArgTokens.size() < MI->getNumArgs()) - PreExpArgTokens.resize(MI->getNumArgs()); + if (PreExpArgTokens.size() < getNumMacroArguments()) + PreExpArgTokens.resize(getNumMacroArguments()); std::vector<Token> &Result = PreExpArgTokens[Arg]; if (!Result.empty()) return Result; @@ -298,12 +317,10 @@ const Token &MacroArgs::getStringifiedArgument(unsigned ArgNo, Preprocessor &PP, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd) { - assert(ArgNo < NumUnexpArgTokens && "Invalid argument number!"); - if (StringifiedArgs.empty()) { - StringifiedArgs.resize(getNumArguments()); - memset((void*)&StringifiedArgs[0], 0, - sizeof(StringifiedArgs[0])*getNumArguments()); - } + assert(ArgNo < getNumMacroArguments() && "Invalid argument number!"); + if (StringifiedArgs.empty()) + StringifiedArgs.resize(getNumMacroArguments(), {}); + if (StringifiedArgs[ArgNo].isNot(tok::string_literal)) StringifiedArgs[ArgNo] = StringifyArgument(getUnexpArgument(ArgNo), PP, /*Charify=*/false, |