summaryrefslogtreecommitdiffstats
path: root/lib/Lex/MacroArgs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lex/MacroArgs.cpp')
-rw-r--r--lib/Lex/MacroArgs.cpp63
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,