Douglas Gregor | d110243 | 2009-08-28 17:37:35 +0000 | [diff] [blame] | 1 | //===------- SemaTemplate.h - C++ Templates ---------------------*- C++ -*-===/ |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | //===----------------------------------------------------------------------===/ |
| 8 | // |
| 9 | // This file provides types used in the semantic analysis of C++ templates. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===/ |
| 12 | #ifndef LLVM_CLANG_SEMA_TEMPLATE_H |
| 13 | #define LLVM_CLANG_SEMA_TEMPLATE_H |
| 14 | |
| 15 | #include "clang/AST/DeclTemplate.h" |
| 16 | #include "llvm/ADT/SmallVector.h" |
| 17 | #include <cassert> |
| 18 | |
| 19 | namespace clang { |
| 20 | /// \brief Data structure that captures multiple levels of template argument |
| 21 | /// lists for use in template instantiation. |
| 22 | /// |
| 23 | /// Multiple levels of template arguments occur when instantiating the |
| 24 | /// definitions of member templates. For example: |
| 25 | /// |
| 26 | /// \code |
| 27 | /// template<typename T> |
| 28 | /// struct X { |
| 29 | /// template<T Value> |
| 30 | /// struct Y { |
| 31 | /// void f(); |
| 32 | /// }; |
| 33 | /// }; |
| 34 | /// \endcode |
| 35 | /// |
| 36 | /// When instantiating X<int>::Y<17>::f, the multi-level template argument |
| 37 | /// list will contain a template argument list (int) at depth 0 and a |
| 38 | /// template argument list (17) at depth 1. |
| 39 | struct MultiLevelTemplateArgumentList { |
| 40 | /// \brief The template argument lists, stored from the innermost template |
Douglas Gregor | 357bbd0 | 2009-08-28 20:50:45 +0000 | [diff] [blame] | 41 | /// argument list (first) to the outermost template argument list (last). |
Douglas Gregor | d110243 | 2009-08-28 17:37:35 +0000 | [diff] [blame] | 42 | llvm::SmallVector<const TemplateArgumentList *, 4> TemplateArgumentLists; |
| 43 | |
| 44 | public: |
| 45 | /// \brief Construct an empty set of template argument lists. |
| 46 | MultiLevelTemplateArgumentList() { } |
| 47 | |
| 48 | /// \brief Construct a single-level template argument list. |
Douglas Gregor | 357bbd0 | 2009-08-28 20:50:45 +0000 | [diff] [blame] | 49 | explicit |
Douglas Gregor | d6350ae | 2009-08-28 20:31:08 +0000 | [diff] [blame] | 50 | MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) { |
| 51 | TemplateArgumentLists.push_back(&TemplateArgs); |
Douglas Gregor | d110243 | 2009-08-28 17:37:35 +0000 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | /// \brief Determine the number of levels in this template argument |
| 55 | /// list. |
| 56 | unsigned getNumLevels() const { return TemplateArgumentLists.size(); } |
| 57 | |
| 58 | /// \brief Retrieve the template argument at a given depth and index. |
| 59 | const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { |
| 60 | assert(Depth < TemplateArgumentLists.size()); |
Douglas Gregor | d6350ae | 2009-08-28 20:31:08 +0000 | [diff] [blame] | 61 | assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1]->size()); |
| 62 | return TemplateArgumentLists[getNumLevels() - Depth - 1]->get(Index); |
| 63 | } |
| 64 | |
| 65 | /// \brief Determine whether there is a non-NULL template argument at the |
| 66 | /// given depth and index. |
| 67 | /// |
| 68 | /// There must exist a template argument list at the given depth. |
| 69 | bool hasTemplateArgument(unsigned Depth, unsigned Index) const { |
| 70 | assert(Depth < TemplateArgumentLists.size()); |
| 71 | |
| 72 | if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1]->size()) |
| 73 | return false; |
| 74 | |
| 75 | return !(*this)(Depth, Index).isNull(); |
Douglas Gregor | d110243 | 2009-08-28 17:37:35 +0000 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | /// \brief Add a new outermost level to the multi-level template argument |
| 79 | /// list. |
| 80 | void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) { |
| 81 | TemplateArgumentLists.push_back(TemplateArgs); |
| 82 | } |
| 83 | |
Douglas Gregor | d6350ae | 2009-08-28 20:31:08 +0000 | [diff] [blame] | 84 | /// \brief Retrieve the innermost template argument list. |
| 85 | const TemplateArgumentList &getInnermost() const { |
| 86 | return *TemplateArgumentLists.front(); |
| 87 | } |
Douglas Gregor | d110243 | 2009-08-28 17:37:35 +0000 | [diff] [blame] | 88 | }; |
Douglas Gregor | 8a51491 | 2009-09-14 18:39:43 +0000 | [diff] [blame] | 89 | |
| 90 | /// \brief The context in which partial ordering of function templates occurs. |
| 91 | enum TemplatePartialOrderingContext { |
| 92 | /// \brief Partial ordering of function templates for a function call. |
| 93 | TPOC_Call, |
| 94 | /// \brief Partial ordering of function templates for a call to a |
| 95 | /// conversion function. |
| 96 | TPOC_Conversion, |
| 97 | /// \brief Partial ordering of function templates in other contexts, e.g., |
| 98 | /// taking the address of a function template or matching a function |
| 99 | /// template specialization to a function template. |
| 100 | TPOC_Other |
| 101 | }; |
Douglas Gregor | 02024a9 | 2010-03-28 02:42:43 +0000 | [diff] [blame] | 102 | |
| 103 | /// \brief Captures a template argument whose value has been deduced |
| 104 | /// via c++ template argument deduction. |
| 105 | class DeducedTemplateArgument : public TemplateArgument { |
| 106 | /// \brief For a non-type template argument, whether the value was |
| 107 | /// deduced from an array bound. |
| 108 | bool DeducedFromArrayBound; |
| 109 | |
| 110 | public: |
| 111 | DeducedTemplateArgument() |
| 112 | : TemplateArgument(), DeducedFromArrayBound(false) { } |
| 113 | |
| 114 | DeducedTemplateArgument(const TemplateArgument &Arg, |
| 115 | bool DeducedFromArrayBound = false) |
| 116 | : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { } |
| 117 | |
| 118 | /// \brief Construct an integral non-type template argument that |
| 119 | /// has been deduced, possible from an array bound. |
| 120 | DeducedTemplateArgument(const llvm::APSInt &Value, |
| 121 | QualType ValueType, |
| 122 | bool DeducedFromArrayBound) |
| 123 | : TemplateArgument(Value, ValueType), |
| 124 | DeducedFromArrayBound(DeducedFromArrayBound) { } |
| 125 | |
| 126 | /// \brief For a non-type template argument, determine whether the |
| 127 | /// template argument was deduced from an array bound. |
| 128 | bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } |
| 129 | |
| 130 | /// \brief Specify whether the given non-type template argument |
| 131 | /// was deduced from an array bound. |
| 132 | void setDeducedFromArrayBound(bool Deduced) { |
| 133 | DeducedFromArrayBound = Deduced; |
| 134 | } |
| 135 | }; |
Douglas Gregor | d110243 | 2009-08-28 17:37:35 +0000 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | #endif // LLVM_CLANG_SEMA_TEMPLATE_H |