blob: 03de9ff6ae44fb2bfe43c4bd7dfb1f96318431bf [file] [log] [blame]
//===--- ParsedTemplate.h - Template Parsing Data Types ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides data structures that store the parsed representation of
// templates.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Ownership.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <cstdlib>
#include <new>
namespace clang {
/// \brief Represents the parsed form of a C++ template argument.
class ParsedTemplateArgument {
public:
/// \brief Describes the kind of template argument that was parsed.
enum KindType {
/// \brief A template type parameter, stored as a type.
Type,
/// \brief A non-type template parameter, stored as an expression.
NonType,
/// \brief A template template argument, stored as a template name.
Template
};
/// \brief Build an empty template argument.
///
/// This template argument is invalid.
ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { }
/// \brief Create a template type argument or non-type template argument.
///
/// \param Arg the template type argument or non-type template argument.
/// \param Loc the location of the type.
ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc)
: Kind(Kind), Arg(Arg), Loc(Loc) { }
/// \brief Create a template template argument.
///
/// \param SS the C++ scope specifier that precedes the template name, if
/// any.
///
/// \param Template the template to which this template template
/// argument refers.
///
/// \param TemplateLoc the location of the template name.
ParsedTemplateArgument(const CXXScopeSpec &SS,
ParsedTemplateTy Template,
SourceLocation TemplateLoc)
: Kind(ParsedTemplateArgument::Template),
Arg(Template.getAsOpaquePtr()),
SS(SS), Loc(TemplateLoc), EllipsisLoc() { }
/// \brief Determine whether the given template argument is invalid.
bool isInvalid() const { return Arg == nullptr; }
/// \brief Determine what kind of template argument we have.
KindType getKind() const { return Kind; }
/// \brief Retrieve the template type argument's type.
ParsedType getAsType() const {
assert(Kind == Type && "Not a template type argument");
return ParsedType::getFromOpaquePtr(Arg);
}
/// \brief Retrieve the non-type template argument's expression.
Expr *getAsExpr() const {
assert(Kind == NonType && "Not a non-type template argument");
return static_cast<Expr*>(Arg);
}
/// \brief Retrieve the template template argument's template name.
ParsedTemplateTy getAsTemplate() const {
assert(Kind == Template && "Not a template template argument");
return ParsedTemplateTy::getFromOpaquePtr(Arg);
}
/// \brief Retrieve the location of the template argument.
SourceLocation getLocation() const { return Loc; }
/// \brief Retrieve the nested-name-specifier that precedes the template
/// name in a template template argument.
const CXXScopeSpec &getScopeSpec() const {
assert(Kind == Template &&
"Only template template arguments can have a scope specifier");
return SS;
}
/// \brief Retrieve the location of the ellipsis that makes a template
/// template argument into a pack expansion.
SourceLocation getEllipsisLoc() const {
assert(Kind == Template &&
"Only template template arguments can have an ellipsis");
return EllipsisLoc;
}
/// \brief Retrieve a pack expansion of the given template template
/// argument.
///
/// \param EllipsisLoc The location of the ellipsis.
ParsedTemplateArgument getTemplatePackExpansion(
SourceLocation EllipsisLoc) const;
private:
KindType Kind;
/// \brief The actual template argument representation, which may be
/// an \c Sema::TypeTy* (for a type), an Expr* (for an
/// expression), or an Sema::TemplateTy (for a template).
void *Arg;
/// \brief The nested-name-specifier that can accompany a template template
/// argument.
CXXScopeSpec SS;
/// \brief the location of the template argument.
SourceLocation Loc;
/// \brief The ellipsis location that can accompany a template template
/// argument (turning it into a template template argument expansion).
SourceLocation EllipsisLoc;
};
/// \brief Information about a template-id annotation
/// token.
///
/// A template-id annotation token contains the template declaration,
/// template arguments, whether those template arguments were types,
/// 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 {
/// \brief The nested-name-specifier that precedes the template name.
CXXScopeSpec SS;
/// TemplateKWLoc - The location of the template keyword within the
/// source.
SourceLocation TemplateKWLoc;
/// TemplateNameLoc - The location of the template name within the
/// source.
SourceLocation TemplateNameLoc;
/// FIXME: Temporarily stores the name of a specialization
IdentifierInfo *Name;
/// FIXME: Temporarily stores the overloaded operator kind.
OverloadedOperatorKind Operator;
/// The declaration of the template corresponding to the
/// template-name.
ParsedTemplateTy Template;
/// The kind of template that Template refers to.
TemplateNameKind Kind;
/// The location of the '<' before the template argument
/// list.
SourceLocation LAngleLoc;
/// The location of the '>' after the template argument
/// list.
SourceLocation RAngleLoc;
/// NumArgs - The number of template arguments.
unsigned NumArgs;
/// \brief Retrieves a pointer to the template arguments
ParsedTemplateArgument *getTemplateArgs() {
return reinterpret_cast<ParsedTemplateArgument *>(this + 1);
}
/// \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);
return TemplateId;
}
void Destroy() {
SS.~CXXScopeSpec();
free(this);
}
};
/// Retrieves the range of the given template parameter lists.
SourceRange getTemplateParamsRange(TemplateParameterList const *const *Params,
unsigned NumParams);
} // end namespace clang
#endif // LLVM_CLANG_SEMA_PARSEDTEMPLATE_H