Template.h revision 212795
1212795Sdim//===------- SemaTemplate.h - C++ Templates ---------------------*- C++ -*-===/
2212795Sdim//
3212795Sdim//                     The LLVM Compiler Infrastructure
4212795Sdim//
5212795Sdim// This file is distributed under the University of Illinois Open Source
6212795Sdim// License. See LICENSE.TXT for details.
7212795Sdim//===----------------------------------------------------------------------===/
8212795Sdim//
9212795Sdim//  This file provides types used in the semantic analysis of C++ templates.
10212795Sdim//
11212795Sdim//===----------------------------------------------------------------------===/
12212795Sdim#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
13212795Sdim#define LLVM_CLANG_SEMA_TEMPLATE_H
14212795Sdim
15212795Sdim#include "clang/AST/DeclTemplate.h"
16212795Sdim#include "llvm/ADT/SmallVector.h"
17212795Sdim#include <cassert>
18212795Sdim
19212795Sdimnamespace clang {
20212795Sdim  /// \brief Data structure that captures multiple levels of template argument
21212795Sdim  /// lists for use in template instantiation.
22212795Sdim  ///
23212795Sdim  /// Multiple levels of template arguments occur when instantiating the
24212795Sdim  /// definitions of member templates. For example:
25212795Sdim  ///
26212795Sdim  /// \code
27212795Sdim  /// template<typename T>
28212795Sdim  /// struct X {
29212795Sdim  ///   template<T Value>
30212795Sdim  ///   struct Y {
31212795Sdim  ///     void f();
32212795Sdim  ///   };
33212795Sdim  /// };
34212795Sdim  /// \endcode
35212795Sdim  ///
36212795Sdim  /// When instantiating X<int>::Y<17>::f, the multi-level template argument
37212795Sdim  /// list will contain a template argument list (int) at depth 0 and a
38212795Sdim  /// template argument list (17) at depth 1.
39212795Sdim  class MultiLevelTemplateArgumentList {
40212795Sdim  public:
41212795Sdim    typedef std::pair<const TemplateArgument *, unsigned> ArgList;
42212795Sdim
43212795Sdim  private:
44212795Sdim    /// \brief The template argument lists, stored from the innermost template
45212795Sdim    /// argument list (first) to the outermost template argument list (last).
46212795Sdim    llvm::SmallVector<ArgList, 4> TemplateArgumentLists;
47212795Sdim
48212795Sdim  public:
49212795Sdim    /// \brief Construct an empty set of template argument lists.
50212795Sdim    MultiLevelTemplateArgumentList() { }
51212795Sdim
52212795Sdim    /// \brief Construct a single-level template argument list.
53212795Sdim    explicit
54212795Sdim    MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
55212795Sdim      addOuterTemplateArguments(&TemplateArgs);
56212795Sdim    }
57212795Sdim
58212795Sdim    /// \brief Determine the number of levels in this template argument
59212795Sdim    /// list.
60212795Sdim    unsigned getNumLevels() const { return TemplateArgumentLists.size(); }
61212795Sdim
62212795Sdim    /// \brief Retrieve the template argument at a given depth and index.
63212795Sdim    const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
64212795Sdim      assert(Depth < TemplateArgumentLists.size());
65212795Sdim      assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second);
66212795Sdim      return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index];
67212795Sdim    }
68212795Sdim
69212795Sdim    /// \brief Determine whether there is a non-NULL template argument at the
70212795Sdim    /// given depth and index.
71212795Sdim    ///
72212795Sdim    /// There must exist a template argument list at the given depth.
73212795Sdim    bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
74212795Sdim      assert(Depth < TemplateArgumentLists.size());
75212795Sdim
76212795Sdim      if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second)
77212795Sdim        return false;
78212795Sdim
79212795Sdim      return !(*this)(Depth, Index).isNull();
80212795Sdim    }
81212795Sdim
82212795Sdim    /// \brief Add a new outermost level to the multi-level template argument
83212795Sdim    /// list.
84212795Sdim    void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
85212795Sdim      TemplateArgumentLists.push_back(
86212795Sdim                                    ArgList(TemplateArgs->getFlatArgumentList(),
87212795Sdim                                            TemplateArgs->flat_size()));
88212795Sdim    }
89212795Sdim
90212795Sdim    /// \brief Add a new outmost level to the multi-level template argument
91212795Sdim    /// list.
92212795Sdim    void addOuterTemplateArguments(const TemplateArgument *Args,
93212795Sdim                                   unsigned NumArgs) {
94212795Sdim      TemplateArgumentLists.push_back(ArgList(Args, NumArgs));
95212795Sdim    }
96212795Sdim
97212795Sdim    /// \brief Retrieve the innermost template argument list.
98212795Sdim    const ArgList &getInnermost() const {
99212795Sdim      return TemplateArgumentLists.front();
100212795Sdim    }
101212795Sdim  };
102212795Sdim
103212795Sdim  /// \brief The context in which partial ordering of function templates occurs.
104212795Sdim  enum TPOC {
105212795Sdim    /// \brief Partial ordering of function templates for a function call.
106212795Sdim    TPOC_Call,
107212795Sdim    /// \brief Partial ordering of function templates for a call to a
108212795Sdim    /// conversion function.
109212795Sdim    TPOC_Conversion,
110212795Sdim    /// \brief Partial ordering of function templates in other contexts, e.g.,
111212795Sdim    /// taking the address of a function template or matching a function
112212795Sdim    /// template specialization to a function template.
113212795Sdim    TPOC_Other
114212795Sdim  };
115212795Sdim
116212795Sdim  // This is lame but unavoidable in a world without forward
117212795Sdim  // declarations of enums.  The alternatives are to either pollute
118212795Sdim  // Sema.h (by including this file) or sacrifice type safety (by
119212795Sdim  // making Sema.h declare things as enums).
120212795Sdim  class TemplatePartialOrderingContext {
121212795Sdim    TPOC Value;
122212795Sdim  public:
123212795Sdim    TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
124212795Sdim    operator TPOC() const { return Value; }
125212795Sdim  };
126212795Sdim
127212795Sdim  /// \brief Captures a template argument whose value has been deduced
128212795Sdim  /// via c++ template argument deduction.
129212795Sdim  class DeducedTemplateArgument : public TemplateArgument {
130212795Sdim    /// \brief For a non-type template argument, whether the value was
131212795Sdim    /// deduced from an array bound.
132212795Sdim    bool DeducedFromArrayBound;
133212795Sdim
134212795Sdim  public:
135212795Sdim    DeducedTemplateArgument()
136212795Sdim      : TemplateArgument(), DeducedFromArrayBound(false) { }
137212795Sdim
138212795Sdim    DeducedTemplateArgument(const TemplateArgument &Arg,
139212795Sdim                            bool DeducedFromArrayBound = false)
140212795Sdim      : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { }
141212795Sdim
142212795Sdim    /// \brief Construct an integral non-type template argument that
143212795Sdim    /// has been deduced, possible from an array bound.
144212795Sdim    DeducedTemplateArgument(const llvm::APSInt &Value,
145212795Sdim                            QualType ValueType,
146212795Sdim                            bool DeducedFromArrayBound)
147212795Sdim      : TemplateArgument(Value, ValueType),
148212795Sdim        DeducedFromArrayBound(DeducedFromArrayBound) { }
149212795Sdim
150212795Sdim    /// \brief For a non-type template argument, determine whether the
151212795Sdim    /// template argument was deduced from an array bound.
152212795Sdim    bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
153212795Sdim
154212795Sdim    /// \brief Specify whether the given non-type template argument
155212795Sdim    /// was deduced from an array bound.
156212795Sdim    void setDeducedFromArrayBound(bool Deduced) {
157212795Sdim      DeducedFromArrayBound = Deduced;
158212795Sdim    }
159212795Sdim  };
160212795Sdim
161212795Sdim  /// \brief A stack-allocated class that identifies which local
162212795Sdim  /// variable declaration instantiations are present in this scope.
163212795Sdim  ///
164212795Sdim  /// A new instance of this class type will be created whenever we
165212795Sdim  /// instantiate a new function declaration, which will have its own
166212795Sdim  /// set of parameter declarations.
167212795Sdim  class LocalInstantiationScope {
168212795Sdim    /// \brief Reference to the semantic analysis that is performing
169212795Sdim    /// this template instantiation.
170212795Sdim    Sema &SemaRef;
171212795Sdim
172212795Sdim    /// \brief A mapping from local declarations that occur
173212795Sdim    /// within a template to their instantiations.
174212795Sdim    ///
175212795Sdim    /// This mapping is used during instantiation to keep track of,
176212795Sdim    /// e.g., function parameter and variable declarations. For example,
177212795Sdim    /// given:
178212795Sdim    ///
179212795Sdim    /// \code
180212795Sdim    ///   template<typename T> T add(T x, T y) { return x + y; }
181212795Sdim    /// \endcode
182212795Sdim    ///
183212795Sdim    /// when we instantiate add<int>, we will introduce a mapping from
184212795Sdim    /// the ParmVarDecl for 'x' that occurs in the template to the
185212795Sdim    /// instantiated ParmVarDecl for 'x'.
186212795Sdim    llvm::DenseMap<const Decl *, Decl *> LocalDecls;
187212795Sdim
188212795Sdim    /// \brief The outer scope, which contains local variable
189212795Sdim    /// definitions from some other instantiation (that may not be
190212795Sdim    /// relevant to this particular scope).
191212795Sdim    LocalInstantiationScope *Outer;
192212795Sdim
193212795Sdim    /// \brief Whether we have already exited this scope.
194212795Sdim    bool Exited;
195212795Sdim
196212795Sdim    /// \brief Whether to combine this scope with the outer scope, such that
197212795Sdim    /// lookup will search our outer scope.
198212795Sdim    bool CombineWithOuterScope;
199212795Sdim
200212795Sdim    // This class is non-copyable
201212795Sdim    LocalInstantiationScope(const LocalInstantiationScope &);
202212795Sdim    LocalInstantiationScope &operator=(const LocalInstantiationScope &);
203212795Sdim
204212795Sdim  public:
205212795Sdim    LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
206212795Sdim      : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
207212795Sdim        Exited(false), CombineWithOuterScope(CombineWithOuterScope)
208212795Sdim    {
209212795Sdim      SemaRef.CurrentInstantiationScope = this;
210212795Sdim    }
211212795Sdim
212212795Sdim    ~LocalInstantiationScope() {
213212795Sdim      Exit();
214212795Sdim    }
215212795Sdim
216212795Sdim    /// \brief Exit this local instantiation scope early.
217212795Sdim    void Exit() {
218212795Sdim      if (Exited)
219212795Sdim        return;
220212795Sdim
221212795Sdim      SemaRef.CurrentInstantiationScope = Outer;
222212795Sdim      Exited = true;
223212795Sdim    }
224212795Sdim
225212795Sdim    Decl *getInstantiationOf(const Decl *D);
226212795Sdim
227212795Sdim    VarDecl *getInstantiationOf(const VarDecl *Var) {
228212795Sdim      return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var)));
229212795Sdim    }
230212795Sdim
231212795Sdim    ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) {
232212795Sdim      return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var)));
233212795Sdim    }
234212795Sdim
235212795Sdim    NonTypeTemplateParmDecl *getInstantiationOf(
236212795Sdim                                          const NonTypeTemplateParmDecl *Var) {
237212795Sdim      return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var)));
238212795Sdim    }
239212795Sdim
240212795Sdim    void InstantiatedLocal(const Decl *D, Decl *Inst);
241212795Sdim  };
242212795Sdim}
243212795Sdim
244212795Sdim#endif // LLVM_CLANG_SEMA_TEMPLATE_H
245