Template.h revision 2a7fb27913999d132cf9e10e03dc5271faa2e9d3
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 19namespace 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 class MultiLevelTemplateArgumentList { 40 public: 41 typedef std::pair<const TemplateArgument *, unsigned> ArgList; 42 43 private: 44 /// \brief The template argument lists, stored from the innermost template 45 /// argument list (first) to the outermost template argument list (last). 46 llvm::SmallVector<ArgList, 4> TemplateArgumentLists; 47 48 public: 49 /// \brief Construct an empty set of template argument lists. 50 MultiLevelTemplateArgumentList() { } 51 52 /// \brief Construct a single-level template argument list. 53 explicit 54 MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) { 55 addOuterTemplateArguments(&TemplateArgs); 56 } 57 58 /// \brief Determine the number of levels in this template argument 59 /// list. 60 unsigned getNumLevels() const { return TemplateArgumentLists.size(); } 61 62 /// \brief Retrieve the template argument at a given depth and index. 63 const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { 64 assert(Depth < TemplateArgumentLists.size()); 65 assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].second); 66 return TemplateArgumentLists[getNumLevels() - Depth - 1].first[Index]; 67 } 68 69 /// \brief Determine whether there is a non-NULL template argument at the 70 /// given depth and index. 71 /// 72 /// There must exist a template argument list at the given depth. 73 bool hasTemplateArgument(unsigned Depth, unsigned Index) const { 74 assert(Depth < TemplateArgumentLists.size()); 75 76 if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].second) 77 return false; 78 79 return !(*this)(Depth, Index).isNull(); 80 } 81 82 /// \brief Add a new outermost level to the multi-level template argument 83 /// list. 84 void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) { 85 TemplateArgumentLists.push_back( 86 ArgList(TemplateArgs->getFlatArgumentList(), 87 TemplateArgs->flat_size())); 88 } 89 90 /// \brief Add a new outmost level to the multi-level template argument 91 /// list. 92 void addOuterTemplateArguments(const TemplateArgument *Args, 93 unsigned NumArgs) { 94 TemplateArgumentLists.push_back(ArgList(Args, NumArgs)); 95 } 96 97 /// \brief Retrieve the innermost template argument list. 98 const ArgList &getInnermost() const { 99 return TemplateArgumentLists.front(); 100 } 101 }; 102 103 /// \brief The context in which partial ordering of function templates occurs. 104 enum TPOC { 105 /// \brief Partial ordering of function templates for a function call. 106 TPOC_Call, 107 /// \brief Partial ordering of function templates for a call to a 108 /// conversion function. 109 TPOC_Conversion, 110 /// \brief Partial ordering of function templates in other contexts, e.g., 111 /// taking the address of a function template or matching a function 112 /// template specialization to a function template. 113 TPOC_Other 114 }; 115 116 // This is lame but unavoidable in a world without forward 117 // declarations of enums. The alternatives are to either pollute 118 // Sema.h (by including this file) or sacrifice type safety (by 119 // making Sema.h declare things as enums). 120 class TemplatePartialOrderingContext { 121 TPOC Value; 122 public: 123 TemplatePartialOrderingContext(TPOC Value) : Value(Value) {} 124 operator TPOC() const { return Value; } 125 }; 126 127 /// \brief Captures a template argument whose value has been deduced 128 /// via c++ template argument deduction. 129 class DeducedTemplateArgument : public TemplateArgument { 130 /// \brief For a non-type template argument, whether the value was 131 /// deduced from an array bound. 132 bool DeducedFromArrayBound; 133 134 public: 135 DeducedTemplateArgument() 136 : TemplateArgument(), DeducedFromArrayBound(false) { } 137 138 DeducedTemplateArgument(const TemplateArgument &Arg, 139 bool DeducedFromArrayBound = false) 140 : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { } 141 142 /// \brief Construct an integral non-type template argument that 143 /// has been deduced, possible from an array bound. 144 DeducedTemplateArgument(const llvm::APSInt &Value, 145 QualType ValueType, 146 bool DeducedFromArrayBound) 147 : TemplateArgument(Value, ValueType), 148 DeducedFromArrayBound(DeducedFromArrayBound) { } 149 150 /// \brief For a non-type template argument, determine whether the 151 /// template argument was deduced from an array bound. 152 bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } 153 154 /// \brief Specify whether the given non-type template argument 155 /// was deduced from an array bound. 156 void setDeducedFromArrayBound(bool Deduced) { 157 DeducedFromArrayBound = Deduced; 158 } 159 }; 160 161 /// \brief A stack-allocated class that identifies which local 162 /// variable declaration instantiations are present in this scope. 163 /// 164 /// A new instance of this class type will be created whenever we 165 /// instantiate a new function declaration, which will have its own 166 /// set of parameter declarations. 167 class LocalInstantiationScope { 168 /// \brief Reference to the semantic analysis that is performing 169 /// this template instantiation. 170 Sema &SemaRef; 171 172 /// \brief A mapping from local declarations that occur 173 /// within a template to their instantiations. 174 /// 175 /// This mapping is used during instantiation to keep track of, 176 /// e.g., function parameter and variable declarations. For example, 177 /// given: 178 /// 179 /// \code 180 /// template<typename T> T add(T x, T y) { return x + y; } 181 /// \endcode 182 /// 183 /// when we instantiate add<int>, we will introduce a mapping from 184 /// the ParmVarDecl for 'x' that occurs in the template to the 185 /// instantiated ParmVarDecl for 'x'. 186 llvm::DenseMap<const Decl *, Decl *> LocalDecls; 187 188 /// \brief The outer scope, which contains local variable 189 /// definitions from some other instantiation (that may not be 190 /// relevant to this particular scope). 191 LocalInstantiationScope *Outer; 192 193 /// \brief Whether we have already exited this scope. 194 bool Exited; 195 196 /// \brief Whether to combine this scope with the outer scope, such that 197 /// lookup will search our outer scope. 198 bool CombineWithOuterScope; 199 200 // This class is non-copyable 201 LocalInstantiationScope(const LocalInstantiationScope &); 202 LocalInstantiationScope &operator=(const LocalInstantiationScope &); 203 204 public: 205 LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) 206 : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), 207 Exited(false), CombineWithOuterScope(CombineWithOuterScope) 208 { 209 SemaRef.CurrentInstantiationScope = this; 210 } 211 212 ~LocalInstantiationScope() { 213 Exit(); 214 } 215 216 /// \brief Exit this local instantiation scope early. 217 void Exit() { 218 if (Exited) 219 return; 220 221 SemaRef.CurrentInstantiationScope = Outer; 222 Exited = true; 223 } 224 225 Decl *getInstantiationOf(const Decl *D); 226 227 VarDecl *getInstantiationOf(const VarDecl *Var) { 228 return cast<VarDecl>(getInstantiationOf(cast<Decl>(Var))); 229 } 230 231 ParmVarDecl *getInstantiationOf(const ParmVarDecl *Var) { 232 return cast<ParmVarDecl>(getInstantiationOf(cast<Decl>(Var))); 233 } 234 235 NonTypeTemplateParmDecl *getInstantiationOf( 236 const NonTypeTemplateParmDecl *Var) { 237 return cast<NonTypeTemplateParmDecl>(getInstantiationOf(cast<Decl>(Var))); 238 } 239 240 void InstantiatedLocal(const Decl *D, Decl *Inst); 241 }; 242} 243 244#endif // LLVM_CLANG_SEMA_TEMPLATE_H 245