[NFC, Refactor] Modernize TemplateIdAnnotation using TrailingObjects

A refactoring of TemplateIdAnnotation that uses TrailingObjects to create a variably-sized object on the heap.

https://reviews.llvm.org/D31414

Thanks to Aaron B for the review!

llvm-svn: 303594
This commit is contained in:
Faisal Vali 2017-05-23 01:07:12 +00:00
parent acf4b09fee
commit 43caf6785f
4 changed files with 82 additions and 66 deletions

View File

@ -26,13 +26,21 @@ enum TemplateNameKind {
TNK_Function_template,
/// The name refers to a template whose specialization produces a
/// type. The template itself could be a class template, template
/// template parameter, or C++0x template alias.
/// template parameter, or template alias.
TNK_Type_template,
/// The name refers to a variable template whose specialization produces a
/// variable.
TNK_Var_template,
/// The name refers to a dependent template name. Whether the
/// template name is assumed to refer to a type template or a
/// The name refers to a dependent template name:
/// \code
/// template<typename MetaFun, typename T1, typename T2> struct apply2 {
/// typedef typename MetaFun::template apply<T1, T2>::type type;
/// };
/// \endcode
///
/// Here, "apply" is a dependent template name within the typename
/// specifier in the typedef. "apply" is a nested template, and
/// whether the template name is assumed to refer to a type template or a
/// function template depends on the context in which the template
/// name occurs.
TNK_Dependent_template_name

View File

@ -145,12 +145,15 @@ namespace clang {
/// expressions, or template names, and the source locations for important
/// tokens. All of the information about template arguments is allocated
/// directly after this structure.
struct TemplateIdAnnotation {
struct TemplateIdAnnotation final
: private llvm::TrailingObjects<TemplateIdAnnotation,
ParsedTemplateArgument> {
friend TrailingObjects;
/// \brief The nested-name-specifier that precedes the template name.
CXXScopeSpec SS;
/// TemplateKWLoc - The location of the template keyword within the
/// source.
/// TemplateKWLoc - The location of the template keyword.
/// For e.g. typename T::template Y<U>
SourceLocation TemplateKWLoc;
/// TemplateNameLoc - The location of the template name within the
@ -183,34 +186,56 @@ namespace clang {
/// \brief Retrieves a pointer to the template arguments
ParsedTemplateArgument *getTemplateArgs() {
return reinterpret_cast<ParsedTemplateArgument *>(this + 1);
return getTrailingObjects<ParsedTemplateArgument>();
}
/// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and
/// appends it to List.
static TemplateIdAnnotation *
Allocate(unsigned NumArgs, SmallVectorImpl<TemplateIdAnnotation*> &List) {
TemplateIdAnnotation *TemplateId
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
sizeof(ParsedTemplateArgument) * NumArgs);
TemplateId->NumArgs = NumArgs;
// Default-construct nested-name-specifier.
new (&TemplateId->SS) CXXScopeSpec();
// Default-construct parsed template arguments.
ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs();
for (unsigned I = 0; I != NumArgs; ++I)
new (TemplateArgs + I) ParsedTemplateArgument();
List.push_back(TemplateId);
Create(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
SourceLocation TemplateNameLoc, IdentifierInfo *Name,
OverloadedOperatorKind OperatorKind,
ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
SourceLocation LAngleLoc, SourceLocation RAngleLoc,
ArrayRef<ParsedTemplateArgument> TemplateArgs,
SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
TemplateIdAnnotation *TemplateId = new (std::malloc(
totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
TemplateIdAnnotation(SS, TemplateKWLoc, TemplateNameLoc, Name,
OperatorKind, OpaqueTemplateName, TemplateKind,
LAngleLoc, RAngleLoc, TemplateArgs);
CleanupList.push_back(TemplateId);
return TemplateId;
}
void Destroy() {
SS.~CXXScopeSpec();
void Destroy() {
std::for_each(
getTemplateArgs(), getTemplateArgs() + NumArgs,
[](ParsedTemplateArgument &A) { A.~ParsedTemplateArgument(); });
this->~TemplateIdAnnotation();
free(this);
}
private:
TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
TemplateIdAnnotation(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
SourceLocation TemplateNameLoc, IdentifierInfo *Name,
OverloadedOperatorKind OperatorKind,
ParsedTemplateTy OpaqueTemplateName,
TemplateNameKind TemplateKind,
SourceLocation LAngleLoc, SourceLocation RAngleLoc,
ArrayRef<ParsedTemplateArgument> TemplateArgs) noexcept
: SS(SS), TemplateKWLoc(TemplateKWLoc),
TemplateNameLoc(TemplateNameLoc), Name(Name), Operator(OperatorKind),
Template(OpaqueTemplateName), Kind(TemplateKind),
LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
NumArgs(TemplateArgs.size()) {
std::uninitialized_copy(TemplateArgs.begin(), TemplateArgs.end(),
getTemplateArgs());
}
~TemplateIdAnnotation() = default;
};
/// Retrieves the range of the given template parameter lists.

View File

@ -2120,31 +2120,18 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
// Form a parsed representation of the template-id to be stored in the
// UnqualifiedId.
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
// FIXME: Store name for literal operator too.
if (Id.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = Id.Identifier;
TemplateId->Operator = OO_None;
TemplateId->TemplateNameLoc = Id.StartLocation;
} else {
TemplateId->Name = nullptr;
TemplateId->Operator = Id.OperatorFunctionId.Operator;
TemplateId->TemplateNameLoc = Id.StartLocation;
}
IdentifierInfo *TemplateII =
Id.getKind() == UnqualifiedId::IK_Identifier ? Id.Identifier : nullptr;
OverloadedOperatorKind OpKind = Id.getKind() == UnqualifiedId::IK_Identifier
? OO_None
: Id.OperatorFunctionId.Operator;
TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
SS, TemplateKWLoc, Id.StartLocation, TemplateII, OpKind, Template, TNK,
LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
TemplateId->SS = SS;
TemplateId->TemplateKWLoc = TemplateKWLoc;
TemplateId->Template = Template;
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
Arg != ArgEnd; ++Arg)
Args[Arg] = TemplateArgs[Arg];
Id.setTemplateId(TemplateId);
return false;
}

View File

@ -1011,25 +1011,21 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
// Build a template-id annotation token that can be processed
// later.
Tok.setKind(tok::annot_template_id);
TemplateIdAnnotation *TemplateId
= TemplateIdAnnotation::Allocate(TemplateArgs.size(), TemplateIds);
TemplateId->TemplateNameLoc = TemplateNameLoc;
if (TemplateName.getKind() == UnqualifiedId::IK_Identifier) {
TemplateId->Name = TemplateName.Identifier;
TemplateId->Operator = OO_None;
} else {
TemplateId->Name = nullptr;
TemplateId->Operator = TemplateName.OperatorFunctionId.Operator;
}
TemplateId->SS = SS;
TemplateId->TemplateKWLoc = TemplateKWLoc;
TemplateId->Template = Template;
TemplateId->Kind = TNK;
TemplateId->LAngleLoc = LAngleLoc;
TemplateId->RAngleLoc = RAngleLoc;
ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); Arg != ArgEnd; ++Arg)
Args[Arg] = ParsedTemplateArgument(TemplateArgs[Arg]);
IdentifierInfo *TemplateII =
TemplateName.getKind() == UnqualifiedId::IK_Identifier
? TemplateName.Identifier
: nullptr;
OverloadedOperatorKind OpKind =
TemplateName.getKind() == UnqualifiedId::IK_Identifier
? OO_None
: TemplateName.OperatorFunctionId.Operator;
TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create(
SS, TemplateKWLoc, TemplateNameLoc, TemplateII, OpKind, Template, TNK,
LAngleLoc, RAngleLoc, TemplateArgs, TemplateIds);
Tok.setAnnotationValue(TemplateId);
if (TemplateKWLoc.isValid())
Tok.setLocation(TemplateKWLoc);