blob: a7b3b8461854d1dad2d000e064f5e456f50e86bd [file] [log] [blame]
//===------- SemaTemplate.h - C++ Templates ---------------------*- 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 types used in the semantic analysis of C++ templates.
//
//===----------------------------------------------------------------------===/
#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
#define LLVM_CLANG_SEMA_TEMPLATE_H
#include "clang/AST/DeclTemplate.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
namespace clang {
/// \brief Data structure that captures multiple levels of template argument
/// lists for use in template instantiation.
///
/// Multiple levels of template arguments occur when instantiating the
/// definitions of member templates. For example:
///
/// \code
/// template<typename T>
/// struct X {
/// template<T Value>
/// struct Y {
/// void f();
/// };
/// };
/// \endcode
///
/// When instantiating X<int>::Y<17>::f, the multi-level template argument
/// list will contain a template argument list (int) at depth 0 and a
/// template argument list (17) at depth 1.
class MultiLevelTemplateArgumentList {
public:
typedef std::pair<const TemplateArgument *, unsigned> ArgList;
private:
/// \brief The template argument lists, stored from the innermost template
/// argument list (first) to the outermost template argument list (last).
llvm::SmallVector<ArgList, 4> TemplateArgumentLists;
public:
/// \brief Construct an empty set of template argument lists.
MultiLevelTemplateArgumentList() { }
/// \brief Construct a single-level template argument list.
explicit
MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
addOuterTemplateArguments(&TemplateArgs);
}
/// \brief Determine the number of levels in this template argument
/// list.
unsigned getNumLevels() const { return TemplateArgumentLists.size(); }
/// \brief Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(Depth < TemplateArgumentLists.size());
assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index];
}
/// \brief Determine whether there is a non-NULL template argument at the
/// given depth and index.
///
/// There must exist a template argument list at the given depth.
bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
assert(Depth < TemplateArgumentLists.size());
if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second)
return false;
return !(*this)(Depth, Index).isNull();
}
/// \brief Add a new outermost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
TemplateArgumentLists.push_back(
ArgList(TemplateArgs->getFlatArgumentList(),
TemplateArgs->flat_size()));
}
/// \brief Add a new outmost level to the multi-level template argument
/// list.
void addOuterTemplateArguments(const TemplateArgument *Args,
unsigned NumArgs) {
TemplateArgumentLists.push_back(ArgList(Args, NumArgs));
}
/// \brief Retrieve the innermost template argument list.
const ArgList &getInnermost() const {
return TemplateArgumentLists.front();
}
};
/// \brief The context in which partial ordering of function templates occurs.
enum TPOC {
/// \brief Partial ordering of function templates for a function call.
TPOC_Call,
/// \brief Partial ordering of function templates for a call to a
/// conversion function.
TPOC_Conversion,
/// \brief Partial ordering of function templates in other contexts, e.g.,
/// taking the address of a function template or matching a function
/// template specialization to a function template.
TPOC_Other
};
// This is lame but unavoidable in a world without forward
// declarations of enums. The alternatives are to either pollute
// Sema.h (by including this file) or sacrifice type safety (by
// making Sema.h declare things as enums).
class TemplatePartialOrderingContext {
TPOC Value;
public:
TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
operator TPOC() const { return Value; }
};
/// \brief Captures a template argument whose value has been deduced
/// via c++ template argument deduction.
class DeducedTemplateArgument : public TemplateArgument {
/// \brief For a non-type template argument, whether the value was
/// deduced from an array bound.
bool DeducedFromArrayBound;
public:
DeducedTemplateArgument()
: TemplateArgument(), DeducedFromArrayBound(false) { }
DeducedTemplateArgument(const TemplateArgument &Arg,
bool DeducedFromArrayBound = false)
: TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { }
/// \brief Construct an integral non-type template argument that
/// has been deduced, possible from an array bound.
DeducedTemplateArgument(const llvm::APSInt &Value,
QualType ValueType,
bool DeducedFromArrayBound)
: TemplateArgument(Value, ValueType),
DeducedFromArrayBound(DeducedFromArrayBound) { }
/// \brief For a non-type template argument, determine whether the
/// template argument was deduced from an array bound.
bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
/// \brief Specify whether the given non-type template argument
/// was deduced from an array bound.
void setDeducedFromArrayBound(bool Deduced) {
DeducedFromArrayBound = Deduced;
}
};
/// \brief A stack-allocated class that identifies which local
/// variable declaration instantiations are present in this scope.
///
/// A new instance of this class type will be created whenever we
/// instantiate a new function declaration, which will have its own
/// set of parameter declarations.
class LocalInstantiationScope {
/// \brief Reference to the semantic analysis that is performing
/// this template instantiation.
Sema &SemaRef;
/// \brief A mapping from local declarations that occur
/// within a template to their instantiations.
///
/// This mapping is used during instantiation to keep track of,
/// e.g., function parameter and variable declarations. For example,
/// given:
///
/// \code
/// template<typename T> T add(T x, T y) { return x + y; }
/// \endcode
///
/// when we instantiate add<int>, we will introduce a mapping from
/// the ParmVarDecl for 'x' that occurs in the template to the
/// instantiated ParmVarDecl for 'x'.
llvm::DenseMap<const Decl *, Decl *> LocalDecls;
/// \brief The outer scope, which contains local variable
/// definitions from some other instantiation (that may not be
/// relevant to this particular scope).
LocalInstantiationScope *Outer;
/// \brief Whether we have already exited this scope.
bool Exited;
/// \brief Whether to combine this scope with the outer scope, such that
/// lookup will search our outer scope.
bool CombineWithOuterScope;
// This class is non-copyable
LocalInstantiationScope(const LocalInstantiationScope &);
LocalInstantiationScope &operator=(const LocalInstantiationScope &);
public:
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
Exited(false), CombineWithOuterScope(CombineWithOuterScope)
{
SemaRef.CurrentInstantiationScope = this;
}
~LocalInstantiationScope() {
Exit();
}
/// \brief Exit this local instantiation scope early.
void Exit() {
if (Exited)
return;
SemaRef.CurrentInstantiationScope = Outer;
Exited = true;
}
Decl *getInstantiationOf(const Decl *D);
VarDecl *getInstantiationOf(const VarDecl *Var) {
return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
}
ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
}
NonTypeTemplateParmDecl *getInstantiationOf(
const NonTypeTemplateParmDecl *Var) {
return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
}
void InstantiatedLocal(const Decl *D, Decl *Inst);
};
}
#endif // LLVM_CLANG_SEMA_TEMPLATE_H