blob: 1f8ccfbf05c65b64d1fed07397c4b6f6b15f4555 [file] [log] [blame]
//===--- Template.h - Template Parsing Data Types -------------------------===//
//
// 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_PARSE_TEMPLATE_H
#define LLVM_CLANG_PARSE_TEMPLATE_H
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Ownership.h"
#include <cassert>
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
ParsedTemplateArgument() : Kind(Type), Arg(0) { }
/// \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,
ActionBase::TemplateTy Template,
SourceLocation TemplateLoc)
: Kind(ParsedTemplateArgument::Template), Arg(Template.get()),
Loc(TemplateLoc), SS(SS) { }
/// \brief Determine whether the given template argument is invalid.
bool isInvalid() { return Arg == 0; }
/// \brief Determine what kind of template argument we have.
KindType getKind() const { return Kind; }
/// \brief Retrieve the template type argument's type.
ActionBase::TypeTy *getAsType() const {
assert(Kind == Type && "Not a template type argument");
return Arg;
}
/// \brief Retrieve the non-type template argument's expression.
ActionBase::ExprTy *getAsExpr() const {
assert(Kind == NonType && "Not a non-type template argument");
return Arg;
}
/// \brief Retrieve the template template argument's template name.
ActionBase::TemplateTy getAsTemplate() const {
assert(Kind == Template && "Not a template template argument");
return ActionBase::TemplateTy::make(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;
}
private:
KindType Kind;
/// \brief The actual template argument representation, which may be
/// an \c ActionBase::TypeTy* (for a type), an ActionBase::ExprTy* (for an
/// expression), or an ActionBase::TemplateTy (for a template).
void *Arg;
/// \brief the location of the template argument.
SourceLocation Loc;
/// \brief The nested-name-specifier that can accompany a template template
/// argument.
CXXScopeSpec SS;
};
/// \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 {
/// 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. This is an Action::TemplateTy.
void *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);
}
static TemplateIdAnnotation* Allocate(unsigned NumArgs) {
TemplateIdAnnotation *TemplateId
= (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) +
sizeof(ParsedTemplateArgument) * NumArgs);
TemplateId->NumArgs = NumArgs;
return TemplateId;
}
void Destroy() { free(this); }
};
#if !defined(DISABLE_SMART_POINTERS)
inline void ASTTemplateArgsPtr::destroy() {
if (!Count)
return;
for (unsigned I = 0; I != Count; ++I)
if (Args[I].getKind() == ParsedTemplateArgument::NonType)
Actions.DeleteExpr(Args[I].getAsExpr());
Count = 0;
}
#endif
inline const ParsedTemplateArgument &
ASTTemplateArgsPtr::operator[](unsigned Arg) const {
return Args[Arg];
}
}
#endif