#include "clang/Basic/LLVM.h"
#include "clang/Lex/Token.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/TrailingObjects.h"
#include <vector>
namespace clang {
/// MacroArgs - An instance of this class captures information about
/// the formal arguments specified to a function-like macro invocation.
-class MacroArgs {
+class MacroArgs final
+ : private llvm::TrailingObjects<MacroArgs, Token> {
+
+ friend TrailingObjects;
/// 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
// 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;
// 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)
+ // 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;
}
// Copy the actual unexpanded tokens to immediately after the result ptr.
- if (!UnexpArgTokens.empty())
+ if (!UnexpArgTokens.empty()) {
+ static_assert(std::is_trivially_copyable_v<Token>,
+ "assume trivial copyability if copying into the "
+ "uninitialized array (as opposed to reusing a cached "
+ "MacroArgs)");
std::copy(UnexpArgTokens.begin(), UnexpArgTokens.end(),
- const_cast<Token*>(Result->getUnexpArgument(0)));
+ Result->getTrailingObjects<Token>());
+ }
return Result;
}
// Run the dtor to deallocate the vectors.
this->~MacroArgs();
// Release the memory for the object.
+ static_assert(std::is_trivially_destructible_v<Token>,
+ "assume trivially destructible and forego destructors");
free(this);
return Next;
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 *Start = getTrailingObjects<Token>();
const Token *Result = Start;
// Scan to find Arg.
for (; Arg; ++Result) {