diff options
Diffstat (limited to 'include/clang/Sema/Template.h')
| -rw-r--r-- | include/clang/Sema/Template.h | 244 | 
1 files changed, 244 insertions, 0 deletions
diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h new file mode 100644 index 000000000000..a7b3b8461854 --- /dev/null +++ b/include/clang/Sema/Template.h @@ -0,0 +1,244 @@ +//===------- 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  | 
