Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 1 | //===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===// |
| 2 | // |
||
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
||
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
| 6 | //===----------------------------------------------------------------------===// |
||
| 7 | // |
||
| 8 | // This file provides types used in the semantic analysis of C++ templates. |
||
| 9 | // |
||
| 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 "clang/AST/DeclVisitor.h" |
||
| 17 | #include "clang/AST/TemplateBase.h" |
||
| 18 | #include "clang/AST/Type.h" |
||
| 19 | #include "clang/Basic/LLVM.h" |
||
| 20 | #include "clang/Sema/Sema.h" |
||
| 21 | #include "llvm/ADT/ArrayRef.h" |
||
| 22 | #include "llvm/ADT/DenseMap.h" |
||
| 23 | #include "llvm/ADT/PointerUnion.h" |
||
| 24 | #include "llvm/ADT/SmallVector.h" |
||
| 25 | #include <cassert> |
||
| 26 | #include <optional> |
||
| 27 | #include <utility> |
||
| 28 | |||
| 29 | namespace clang { |
||
| 30 | |||
| 31 | class ASTContext; |
||
| 32 | class BindingDecl; |
||
| 33 | class CXXMethodDecl; |
||
| 34 | class Decl; |
||
| 35 | class DeclaratorDecl; |
||
| 36 | class DeclContext; |
||
| 37 | class EnumDecl; |
||
| 38 | class FunctionDecl; |
||
| 39 | class NamedDecl; |
||
| 40 | class ParmVarDecl; |
||
| 41 | class TagDecl; |
||
| 42 | class TypedefNameDecl; |
||
| 43 | class TypeSourceInfo; |
||
| 44 | class VarDecl; |
||
| 45 | |||
| 46 | /// The kind of template substitution being performed. |
||
| 47 | enum class TemplateSubstitutionKind : char { |
||
| 48 | /// We are substituting template parameters for template arguments in order |
||
| 49 | /// to form a template specialization. |
||
| 50 | Specialization, |
||
| 51 | /// We are substituting template parameters for (typically) other template |
||
| 52 | /// parameters in order to rewrite a declaration as a different declaration |
||
| 53 | /// (for example, when forming a deduction guide from a constructor). |
||
| 54 | Rewrite, |
||
| 55 | }; |
||
| 56 | |||
| 57 | /// Data structure that captures multiple levels of template argument |
||
| 58 | /// lists for use in template instantiation. |
||
| 59 | /// |
||
| 60 | /// Multiple levels of template arguments occur when instantiating the |
||
| 61 | /// definitions of member templates. For example: |
||
| 62 | /// |
||
| 63 | /// \code |
||
| 64 | /// template<typename T> |
||
| 65 | /// struct X { |
||
| 66 | /// template<T Value> |
||
| 67 | /// struct Y { |
||
| 68 | /// void f(); |
||
| 69 | /// }; |
||
| 70 | /// }; |
||
| 71 | /// \endcode |
||
| 72 | /// |
||
| 73 | /// When instantiating X<int>::Y<17>::f, the multi-level template argument |
||
| 74 | /// list will contain a template argument list (int) at depth 0 and a |
||
| 75 | /// template argument list (17) at depth 1. |
||
| 76 | class MultiLevelTemplateArgumentList { |
||
| 77 | /// The template argument list at a certain template depth |
||
| 78 | |||
| 79 | using ArgList = ArrayRef<TemplateArgument>; |
||
| 80 | struct ArgumentListLevel { |
||
| 81 | llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal; |
||
| 82 | ArgList Args; |
||
| 83 | }; |
||
| 84 | using ContainerType = SmallVector<ArgumentListLevel, 4>; |
||
| 85 | |||
| 86 | using ArgListsIterator = ContainerType::iterator; |
||
| 87 | using ConstArgListsIterator = ContainerType::const_iterator; |
||
| 88 | |||
| 89 | /// The template argument lists, stored from the innermost template |
||
| 90 | /// argument list (first) to the outermost template argument list (last). |
||
| 91 | ContainerType TemplateArgumentLists; |
||
| 92 | |||
| 93 | /// The number of outer levels of template arguments that are not |
||
| 94 | /// being substituted. |
||
| 95 | unsigned NumRetainedOuterLevels = 0; |
||
| 96 | |||
| 97 | /// The kind of substitution described by this argument list. |
||
| 98 | TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization; |
||
| 99 | |||
| 100 | public: |
||
| 101 | /// Construct an empty set of template argument lists. |
||
| 102 | MultiLevelTemplateArgumentList() = default; |
||
| 103 | |||
| 104 | /// Construct a single-level template argument list. |
||
| 105 | MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final) { |
||
| 106 | addOuterTemplateArguments(D, Args, Final); |
||
| 107 | } |
||
| 108 | |||
| 109 | void setKind(TemplateSubstitutionKind K) { Kind = K; } |
||
| 110 | |||
| 111 | /// Determine the kind of template substitution being performed. |
||
| 112 | TemplateSubstitutionKind getKind() const { return Kind; } |
||
| 113 | |||
| 114 | /// Determine whether we are rewriting template parameters rather than |
||
| 115 | /// substituting for them. If so, we should not leave references to the |
||
| 116 | /// original template parameters behind. |
||
| 117 | bool isRewrite() const { |
||
| 118 | return Kind == TemplateSubstitutionKind::Rewrite; |
||
| 119 | } |
||
| 120 | |||
| 121 | /// Determine the number of levels in this template argument |
||
| 122 | /// list. |
||
| 123 | unsigned getNumLevels() const { |
||
| 124 | return TemplateArgumentLists.size() + NumRetainedOuterLevels; |
||
| 125 | } |
||
| 126 | |||
| 127 | /// Determine the number of substituted levels in this template |
||
| 128 | /// argument list. |
||
| 129 | unsigned getNumSubstitutedLevels() const { |
||
| 130 | return TemplateArgumentLists.size(); |
||
| 131 | } |
||
| 132 | |||
| 133 | // Determine the number of substituted args at 'Depth'. |
||
| 134 | unsigned getNumSubsitutedArgs(unsigned Depth) const { |
||
| 135 | assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); |
||
| 136 | return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size(); |
||
| 137 | } |
||
| 138 | |||
| 139 | unsigned getNumRetainedOuterLevels() const { |
||
| 140 | return NumRetainedOuterLevels; |
||
| 141 | } |
||
| 142 | |||
| 143 | /// Determine how many of the \p OldDepth outermost template parameter |
||
| 144 | /// lists would be removed by substituting these arguments. |
||
| 145 | unsigned getNewDepth(unsigned OldDepth) const { |
||
| 146 | if (OldDepth < NumRetainedOuterLevels) |
||
| 147 | return OldDepth; |
||
| 148 | if (OldDepth < getNumLevels()) |
||
| 149 | return NumRetainedOuterLevels; |
||
| 150 | return OldDepth - TemplateArgumentLists.size(); |
||
| 151 | } |
||
| 152 | |||
| 153 | /// Retrieve the template argument at a given depth and index. |
||
| 154 | const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { |
||
| 155 | assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); |
||
| 156 | assert(Index < |
||
| 157 | TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()); |
||
| 158 | return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]; |
||
| 159 | } |
||
| 160 | |||
| 161 | /// A template-like entity which owns the whole pattern being substituted. |
||
| 162 | /// This will usually own a set of template parameters, or in some |
||
| 163 | /// cases might even be a template parameter itself. |
||
| 164 | std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const { |
||
| 165 | assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); |
||
| 166 | auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1] |
||
| 167 | .AssociatedDeclAndFinal; |
||
| 168 | return {AD.getPointer(), AD.getInt()}; |
||
| 169 | } |
||
| 170 | |||
| 171 | /// Determine whether there is a non-NULL template argument at the |
||
| 172 | /// given depth and index. |
||
| 173 | /// |
||
| 174 | /// There must exist a template argument list at the given depth. |
||
| 175 | bool hasTemplateArgument(unsigned Depth, unsigned Index) const { |
||
| 176 | assert(Depth < getNumLevels()); |
||
| 177 | |||
| 178 | if (Depth < NumRetainedOuterLevels) |
||
| 179 | return false; |
||
| 180 | |||
| 181 | if (Index >= |
||
| 182 | TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()) |
||
| 183 | return false; |
||
| 184 | |||
| 185 | return !(*this)(Depth, Index).isNull(); |
||
| 186 | } |
||
| 187 | |||
| 188 | bool isAnyArgInstantiationDependent() const { |
||
| 189 | for (ArgumentListLevel ListLevel : TemplateArgumentLists) |
||
| 190 | for (const TemplateArgument &TA : ListLevel.Args) |
||
| 191 | if (TA.isInstantiationDependent()) |
||
| 192 | return true; |
||
| 193 | return false; |
||
| 194 | } |
||
| 195 | |||
| 196 | /// Clear out a specific template argument. |
||
| 197 | void setArgument(unsigned Depth, unsigned Index, |
||
| 198 | TemplateArgument Arg) { |
||
| 199 | assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); |
||
| 200 | assert(Index < |
||
| 201 | TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()); |
||
| 202 | const_cast<TemplateArgument &>( |
||
| 203 | TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg; |
||
| 204 | } |
||
| 205 | |||
| 206 | /// Add a new outmost level to the multi-level template argument |
||
| 207 | /// list. |
||
| 208 | /// A 'Final' substitution means that Subst* nodes won't be built |
||
| 209 | /// for the replacements. |
||
| 210 | void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, |
||
| 211 | bool Final) { |
||
| 212 | assert(!NumRetainedOuterLevels && |
||
| 213 | "substituted args outside retained args?"); |
||
| 214 | assert(getKind() == TemplateSubstitutionKind::Specialization); |
||
| 215 | TemplateArgumentLists.push_back( |
||
| 216 | {{AssociatedDecl->getCanonicalDecl(), Final}, Args}); |
||
| 217 | } |
||
| 218 | |||
| 219 | void addOuterTemplateArguments(ArgList Args) { |
||
| 220 | assert(!NumRetainedOuterLevels && |
||
| 221 | "substituted args outside retained args?"); |
||
| 222 | assert(getKind() == TemplateSubstitutionKind::Rewrite); |
||
| 223 | TemplateArgumentLists.push_back({{}, Args}); |
||
| 224 | } |
||
| 225 | |||
| 226 | void addOuterTemplateArguments(std::nullopt_t) { |
||
| 227 | assert(!NumRetainedOuterLevels && |
||
| 228 | "substituted args outside retained args?"); |
||
| 229 | TemplateArgumentLists.push_back({}); |
||
| 230 | } |
||
| 231 | |||
| 232 | /// Replaces the current 'innermost' level with the provided argument list. |
||
| 233 | /// This is useful for type deduction cases where we need to get the entire |
||
| 234 | /// list from the AST, but then add the deduced innermost list. |
||
| 235 | void replaceInnermostTemplateArguments(ArgList Args) { |
||
| 236 | assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?"); |
||
| 237 | TemplateArgumentLists[0].Args = Args; |
||
| 238 | } |
||
| 239 | |||
| 240 | /// Add an outermost level that we are not substituting. We have no |
||
| 241 | /// arguments at this level, and do not remove it from the depth of inner |
||
| 242 | /// template parameters that we instantiate. |
||
| 243 | void addOuterRetainedLevel() { |
||
| 244 | ++NumRetainedOuterLevels; |
||
| 245 | } |
||
| 246 | void addOuterRetainedLevels(unsigned Num) { |
||
| 247 | NumRetainedOuterLevels += Num; |
||
| 248 | } |
||
| 249 | |||
| 250 | /// Retrieve the innermost template argument list. |
||
| 251 | const ArgList &getInnermost() const { |
||
| 252 | return TemplateArgumentLists.front().Args; |
||
| 253 | } |
||
| 254 | /// Retrieve the outermost template argument list. |
||
| 255 | const ArgList &getOutermost() const { |
||
| 256 | return TemplateArgumentLists.back().Args; |
||
| 257 | } |
||
| 258 | ArgListsIterator begin() { return TemplateArgumentLists.begin(); } |
||
| 259 | ConstArgListsIterator begin() const { |
||
| 260 | return TemplateArgumentLists.begin(); |
||
| 261 | } |
||
| 262 | ArgListsIterator end() { return TemplateArgumentLists.end(); } |
||
| 263 | ConstArgListsIterator end() const { return TemplateArgumentLists.end(); } |
||
| 264 | }; |
||
| 265 | |||
| 266 | /// The context in which partial ordering of function templates occurs. |
||
| 267 | enum TPOC { |
||
| 268 | /// Partial ordering of function templates for a function call. |
||
| 269 | TPOC_Call, |
||
| 270 | |||
| 271 | /// Partial ordering of function templates for a call to a |
||
| 272 | /// conversion function. |
||
| 273 | TPOC_Conversion, |
||
| 274 | |||
| 275 | /// Partial ordering of function templates in other contexts, e.g., |
||
| 276 | /// taking the address of a function template or matching a function |
||
| 277 | /// template specialization to a function template. |
||
| 278 | TPOC_Other |
||
| 279 | }; |
||
| 280 | |||
| 281 | // This is lame but unavoidable in a world without forward |
||
| 282 | // declarations of enums. The alternatives are to either pollute |
||
| 283 | // Sema.h (by including this file) or sacrifice type safety (by |
||
| 284 | // making Sema.h declare things as enums). |
||
| 285 | class TemplatePartialOrderingContext { |
||
| 286 | TPOC Value; |
||
| 287 | |||
| 288 | public: |
||
| 289 | TemplatePartialOrderingContext(TPOC Value) : Value(Value) {} |
||
| 290 | |||
| 291 | operator TPOC() const { return Value; } |
||
| 292 | }; |
||
| 293 | |||
| 294 | /// Captures a template argument whose value has been deduced |
||
| 295 | /// via c++ template argument deduction. |
||
| 296 | class DeducedTemplateArgument : public TemplateArgument { |
||
| 297 | /// For a non-type template argument, whether the value was |
||
| 298 | /// deduced from an array bound. |
||
| 299 | bool DeducedFromArrayBound = false; |
||
| 300 | |||
| 301 | public: |
||
| 302 | DeducedTemplateArgument() = default; |
||
| 303 | |||
| 304 | DeducedTemplateArgument(const TemplateArgument &Arg, |
||
| 305 | bool DeducedFromArrayBound = false) |
||
| 306 | : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {} |
||
| 307 | |||
| 308 | /// Construct an integral non-type template argument that |
||
| 309 | /// has been deduced, possibly from an array bound. |
||
| 310 | DeducedTemplateArgument(ASTContext &Ctx, |
||
| 311 | const llvm::APSInt &Value, |
||
| 312 | QualType ValueType, |
||
| 313 | bool DeducedFromArrayBound) |
||
| 314 | : TemplateArgument(Ctx, Value, ValueType), |
||
| 315 | DeducedFromArrayBound(DeducedFromArrayBound) {} |
||
| 316 | |||
| 317 | /// For a non-type template argument, determine whether the |
||
| 318 | /// template argument was deduced from an array bound. |
||
| 319 | bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } |
||
| 320 | |||
| 321 | /// Specify whether the given non-type template argument |
||
| 322 | /// was deduced from an array bound. |
||
| 323 | void setDeducedFromArrayBound(bool Deduced) { |
||
| 324 | DeducedFromArrayBound = Deduced; |
||
| 325 | } |
||
| 326 | }; |
||
| 327 | |||
| 328 | /// A stack-allocated class that identifies which local |
||
| 329 | /// variable declaration instantiations are present in this scope. |
||
| 330 | /// |
||
| 331 | /// A new instance of this class type will be created whenever we |
||
| 332 | /// instantiate a new function declaration, which will have its own |
||
| 333 | /// set of parameter declarations. |
||
| 334 | class LocalInstantiationScope { |
||
| 335 | public: |
||
| 336 | /// A set of declarations. |
||
| 337 | using DeclArgumentPack = SmallVector<VarDecl *, 4>; |
||
| 338 | |||
| 339 | private: |
||
| 340 | /// Reference to the semantic analysis that is performing |
||
| 341 | /// this template instantiation. |
||
| 342 | Sema &SemaRef; |
||
| 343 | |||
| 344 | using LocalDeclsMap = |
||
| 345 | llvm::SmallDenseMap<const Decl *, |
||
| 346 | llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>; |
||
| 347 | |||
| 348 | /// A mapping from local declarations that occur |
||
| 349 | /// within a template to their instantiations. |
||
| 350 | /// |
||
| 351 | /// This mapping is used during instantiation to keep track of, |
||
| 352 | /// e.g., function parameter and variable declarations. For example, |
||
| 353 | /// given: |
||
| 354 | /// |
||
| 355 | /// \code |
||
| 356 | /// template<typename T> T add(T x, T y) { return x + y; } |
||
| 357 | /// \endcode |
||
| 358 | /// |
||
| 359 | /// when we instantiate add<int>, we will introduce a mapping from |
||
| 360 | /// the ParmVarDecl for 'x' that occurs in the template to the |
||
| 361 | /// instantiated ParmVarDecl for 'x'. |
||
| 362 | /// |
||
| 363 | /// For a parameter pack, the local instantiation scope may contain a |
||
| 364 | /// set of instantiated parameters. This is stored as a DeclArgumentPack |
||
| 365 | /// pointer. |
||
| 366 | LocalDeclsMap LocalDecls; |
||
| 367 | |||
| 368 | /// The set of argument packs we've allocated. |
||
| 369 | SmallVector<DeclArgumentPack *, 1> ArgumentPacks; |
||
| 370 | |||
| 371 | /// The outer scope, which contains local variable |
||
| 372 | /// definitions from some other instantiation (that may not be |
||
| 373 | /// relevant to this particular scope). |
||
| 374 | LocalInstantiationScope *Outer; |
||
| 375 | |||
| 376 | /// Whether we have already exited this scope. |
||
| 377 | bool Exited = false; |
||
| 378 | |||
| 379 | /// Whether to combine this scope with the outer scope, such that |
||
| 380 | /// lookup will search our outer scope. |
||
| 381 | bool CombineWithOuterScope; |
||
| 382 | |||
| 383 | /// If non-NULL, the template parameter pack that has been |
||
| 384 | /// partially substituted per C++0x [temp.arg.explicit]p9. |
||
| 385 | NamedDecl *PartiallySubstitutedPack = nullptr; |
||
| 386 | |||
| 387 | /// If \c PartiallySubstitutedPack is non-null, the set of |
||
| 388 | /// explicitly-specified template arguments in that pack. |
||
| 389 | const TemplateArgument *ArgsInPartiallySubstitutedPack; |
||
| 390 | |||
| 391 | /// If \c PartiallySubstitutedPack, the number of |
||
| 392 | /// explicitly-specified template arguments in |
||
| 393 | /// ArgsInPartiallySubstitutedPack. |
||
| 394 | unsigned NumArgsInPartiallySubstitutedPack; |
||
| 395 | |||
| 396 | public: |
||
| 397 | LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) |
||
| 398 | : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), |
||
| 399 | CombineWithOuterScope(CombineWithOuterScope) { |
||
| 400 | SemaRef.CurrentInstantiationScope = this; |
||
| 401 | } |
||
| 402 | |||
| 403 | LocalInstantiationScope(const LocalInstantiationScope &) = delete; |
||
| 404 | LocalInstantiationScope & |
||
| 405 | operator=(const LocalInstantiationScope &) = delete; |
||
| 406 | |||
| 407 | ~LocalInstantiationScope() { |
||
| 408 | Exit(); |
||
| 409 | } |
||
| 410 | |||
| 411 | const Sema &getSema() const { return SemaRef; } |
||
| 412 | |||
| 413 | /// Exit this local instantiation scope early. |
||
| 414 | void Exit() { |
||
| 415 | if (Exited) |
||
| 416 | return; |
||
| 417 | |||
| 418 | for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I) |
||
| 419 | delete ArgumentPacks[I]; |
||
| 420 | |||
| 421 | SemaRef.CurrentInstantiationScope = Outer; |
||
| 422 | Exited = true; |
||
| 423 | } |
||
| 424 | |||
| 425 | /// Clone this scope, and all outer scopes, down to the given |
||
| 426 | /// outermost scope. |
||
| 427 | LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) { |
||
| 428 | if (this == Outermost) return this; |
||
| 429 | |||
| 430 | // Save the current scope from SemaRef since the LocalInstantiationScope |
||
| 431 | // will overwrite it on construction |
||
| 432 | LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope; |
||
| 433 | |||
| 434 | LocalInstantiationScope *newScope = |
||
| 435 | new LocalInstantiationScope(SemaRef, CombineWithOuterScope); |
||
| 436 | |||
| 437 | newScope->Outer = nullptr; |
||
| 438 | if (Outer) |
||
| 439 | newScope->Outer = Outer->cloneScopes(Outermost); |
||
| 440 | |||
| 441 | newScope->PartiallySubstitutedPack = PartiallySubstitutedPack; |
||
| 442 | newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack; |
||
| 443 | newScope->NumArgsInPartiallySubstitutedPack = |
||
| 444 | NumArgsInPartiallySubstitutedPack; |
||
| 445 | |||
| 446 | for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end(); |
||
| 447 | I != E; ++I) { |
||
| 448 | const Decl *D = I->first; |
||
| 449 | llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = |
||
| 450 | newScope->LocalDecls[D]; |
||
| 451 | if (I->second.is<Decl *>()) { |
||
| 452 | Stored = I->second.get<Decl *>(); |
||
| 453 | } else { |
||
| 454 | DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>(); |
||
| 455 | DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack); |
||
| 456 | Stored = NewPack; |
||
| 457 | newScope->ArgumentPacks.push_back(NewPack); |
||
| 458 | } |
||
| 459 | } |
||
| 460 | // Restore the saved scope to SemaRef |
||
| 461 | SemaRef.CurrentInstantiationScope = oldScope; |
||
| 462 | return newScope; |
||
| 463 | } |
||
| 464 | |||
| 465 | /// deletes the given scope, and all outer scopes, down to the |
||
| 466 | /// given outermost scope. |
||
| 467 | static void deleteScopes(LocalInstantiationScope *Scope, |
||
| 468 | LocalInstantiationScope *Outermost) { |
||
| 469 | while (Scope && Scope != Outermost) { |
||
| 470 | LocalInstantiationScope *Out = Scope->Outer; |
||
| 471 | delete Scope; |
||
| 472 | Scope = Out; |
||
| 473 | } |
||
| 474 | } |
||
| 475 | |||
| 476 | /// Find the instantiation of the declaration D within the current |
||
| 477 | /// instantiation scope. |
||
| 478 | /// |
||
| 479 | /// \param D The declaration whose instantiation we are searching for. |
||
| 480 | /// |
||
| 481 | /// \returns A pointer to the declaration or argument pack of declarations |
||
| 482 | /// to which the declaration \c D is instantiated, if found. Otherwise, |
||
| 483 | /// returns NULL. |
||
| 484 | llvm::PointerUnion<Decl *, DeclArgumentPack *> * |
||
| 485 | findInstantiationOf(const Decl *D); |
||
| 486 | |||
| 487 | void InstantiatedLocal(const Decl *D, Decl *Inst); |
||
| 488 | void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst); |
||
| 489 | void MakeInstantiatedLocalArgPack(const Decl *D); |
||
| 490 | |||
| 491 | /// Note that the given parameter pack has been partially substituted |
||
| 492 | /// via explicit specification of template arguments |
||
| 493 | /// (C++0x [temp.arg.explicit]p9). |
||
| 494 | /// |
||
| 495 | /// \param Pack The parameter pack, which will always be a template |
||
| 496 | /// parameter pack. |
||
| 497 | /// |
||
| 498 | /// \param ExplicitArgs The explicitly-specified template arguments provided |
||
| 499 | /// for this parameter pack. |
||
| 500 | /// |
||
| 501 | /// \param NumExplicitArgs The number of explicitly-specified template |
||
| 502 | /// arguments provided for this parameter pack. |
||
| 503 | void SetPartiallySubstitutedPack(NamedDecl *Pack, |
||
| 504 | const TemplateArgument *ExplicitArgs, |
||
| 505 | unsigned NumExplicitArgs); |
||
| 506 | |||
| 507 | /// Reset the partially-substituted pack when it is no longer of |
||
| 508 | /// interest. |
||
| 509 | void ResetPartiallySubstitutedPack() { |
||
| 510 | assert(PartiallySubstitutedPack && "No partially-substituted pack"); |
||
| 511 | PartiallySubstitutedPack = nullptr; |
||
| 512 | ArgsInPartiallySubstitutedPack = nullptr; |
||
| 513 | NumArgsInPartiallySubstitutedPack = 0; |
||
| 514 | } |
||
| 515 | |||
| 516 | /// Retrieve the partially-substitued template parameter pack. |
||
| 517 | /// |
||
| 518 | /// If there is no partially-substituted parameter pack, returns NULL. |
||
| 519 | NamedDecl * |
||
| 520 | getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr, |
||
| 521 | unsigned *NumExplicitArgs = nullptr) const; |
||
| 522 | |||
| 523 | /// Determine whether D is a pack expansion created in this scope. |
||
| 524 | bool isLocalPackExpansion(const Decl *D); |
||
| 525 | }; |
||
| 526 | |||
| 527 | class TemplateDeclInstantiator |
||
| 528 | : public DeclVisitor<TemplateDeclInstantiator, Decl *> |
||
| 529 | { |
||
| 530 | Sema &SemaRef; |
||
| 531 | Sema::ArgumentPackSubstitutionIndexRAII SubstIndex; |
||
| 532 | DeclContext *Owner; |
||
| 533 | const MultiLevelTemplateArgumentList &TemplateArgs; |
||
| 534 | Sema::LateInstantiatedAttrVec* LateAttrs = nullptr; |
||
| 535 | LocalInstantiationScope *StartingScope = nullptr; |
||
| 536 | bool EvaluateConstraints = true; |
||
| 537 | |||
| 538 | /// A list of out-of-line class template partial |
||
| 539 | /// specializations that will need to be instantiated after the |
||
| 540 | /// enclosing class's instantiation is complete. |
||
| 541 | SmallVector<std::pair<ClassTemplateDecl *, |
||
| 542 | ClassTemplatePartialSpecializationDecl *>, 4> |
||
| 543 | OutOfLinePartialSpecs; |
||
| 544 | |||
| 545 | /// A list of out-of-line variable template partial |
||
| 546 | /// specializations that will need to be instantiated after the |
||
| 547 | /// enclosing variable's instantiation is complete. |
||
| 548 | /// FIXME: Verify that this is needed. |
||
| 549 | SmallVector< |
||
| 550 | std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4> |
||
| 551 | OutOfLineVarPartialSpecs; |
||
| 552 | |||
| 553 | public: |
||
| 554 | TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, |
||
| 555 | const MultiLevelTemplateArgumentList &TemplateArgs) |
||
| 556 | : SemaRef(SemaRef), |
||
| 557 | SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), |
||
| 558 | Owner(Owner), TemplateArgs(TemplateArgs) {} |
||
| 559 | |||
| 560 | void setEvaluateConstraints(bool B) { |
||
| 561 | EvaluateConstraints = B; |
||
| 562 | } |
||
| 563 | bool getEvaluateConstraints() { |
||
| 564 | return EvaluateConstraints; |
||
| 565 | } |
||
| 566 | |||
| 567 | // Define all the decl visitors using DeclNodes.inc |
||
| 568 | #define DECL(DERIVED, BASE) \ |
||
| 569 | Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D); |
||
| 570 | #define ABSTRACT_DECL(DECL) |
||
| 571 | |||
| 572 | // Decls which never appear inside a class or function. |
||
| 573 | #define OBJCCONTAINER(DERIVED, BASE) |
||
| 574 | #define FILESCOPEASM(DERIVED, BASE) |
||
| 575 | #define TOPLEVELSTMT(DERIVED, BASE) |
||
| 576 | #define IMPORT(DERIVED, BASE) |
||
| 577 | #define EXPORT(DERIVED, BASE) |
||
| 578 | #define LINKAGESPEC(DERIVED, BASE) |
||
| 579 | #define OBJCCOMPATIBLEALIAS(DERIVED, BASE) |
||
| 580 | #define OBJCMETHOD(DERIVED, BASE) |
||
| 581 | #define OBJCTYPEPARAM(DERIVED, BASE) |
||
| 582 | #define OBJCIVAR(DERIVED, BASE) |
||
| 583 | #define OBJCPROPERTY(DERIVED, BASE) |
||
| 584 | #define OBJCPROPERTYIMPL(DERIVED, BASE) |
||
| 585 | #define EMPTY(DERIVED, BASE) |
||
| 586 | #define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE) |
||
| 587 | |||
| 588 | // Decls which use special-case instantiation code. |
||
| 589 | #define BLOCK(DERIVED, BASE) |
||
| 590 | #define CAPTURED(DERIVED, BASE) |
||
| 591 | #define IMPLICITPARAM(DERIVED, BASE) |
||
| 592 | |||
| 593 | #include "clang/AST/DeclNodes.inc" |
||
| 594 | |||
| 595 | enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual }; |
||
| 596 | |||
| 597 | void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T, |
||
| 598 | TypeSourceInfo *&TInfo, |
||
| 599 | DeclarationNameInfo &NameInfo); |
||
| 600 | |||
| 601 | // A few supplemental visitor functions. |
||
| 602 | Decl *VisitCXXMethodDecl(CXXMethodDecl *D, |
||
| 603 | TemplateParameterList *TemplateParams, |
||
| 604 | std::optional<const ASTTemplateArgumentListInfo *> |
||
| 605 | ClassScopeSpecializationArgs = std::nullopt, |
||
| 606 | RewriteKind RK = RewriteKind::None); |
||
| 607 | Decl *VisitFunctionDecl(FunctionDecl *D, |
||
| 608 | TemplateParameterList *TemplateParams, |
||
| 609 | RewriteKind RK = RewriteKind::None); |
||
| 610 | Decl *VisitDecl(Decl *D); |
||
| 611 | Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate, |
||
| 612 | ArrayRef<BindingDecl *> *Bindings = nullptr); |
||
| 613 | Decl *VisitBaseUsingDecls(BaseUsingDecl *D, BaseUsingDecl *Inst, |
||
| 614 | LookupResult *Lookup); |
||
| 615 | |||
| 616 | // Enable late instantiation of attributes. Late instantiated attributes |
||
| 617 | // will be stored in LA. |
||
| 618 | void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) { |
||
| 619 | LateAttrs = LA; |
||
| 620 | StartingScope = SemaRef.CurrentInstantiationScope; |
||
| 621 | } |
||
| 622 | |||
| 623 | // Disable late instantiation of attributes. |
||
| 624 | void disableLateAttributeInstantiation() { |
||
| 625 | LateAttrs = nullptr; |
||
| 626 | StartingScope = nullptr; |
||
| 627 | } |
||
| 628 | |||
| 629 | LocalInstantiationScope *getStartingScope() const { return StartingScope; } |
||
| 630 | |||
| 631 | using delayed_partial_spec_iterator = SmallVectorImpl<std::pair< |
||
| 632 | ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator; |
||
| 633 | |||
| 634 | using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair< |
||
| 635 | VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator; |
||
| 636 | |||
| 637 | /// Return an iterator to the beginning of the set of |
||
| 638 | /// "delayed" partial specializations, which must be passed to |
||
| 639 | /// InstantiateClassTemplatePartialSpecialization once the class |
||
| 640 | /// definition has been completed. |
||
| 641 | delayed_partial_spec_iterator delayed_partial_spec_begin() { |
||
| 642 | return OutOfLinePartialSpecs.begin(); |
||
| 643 | } |
||
| 644 | |||
| 645 | delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() { |
||
| 646 | return OutOfLineVarPartialSpecs.begin(); |
||
| 647 | } |
||
| 648 | |||
| 649 | /// Return an iterator to the end of the set of |
||
| 650 | /// "delayed" partial specializations, which must be passed to |
||
| 651 | /// InstantiateClassTemplatePartialSpecialization once the class |
||
| 652 | /// definition has been completed. |
||
| 653 | delayed_partial_spec_iterator delayed_partial_spec_end() { |
||
| 654 | return OutOfLinePartialSpecs.end(); |
||
| 655 | } |
||
| 656 | |||
| 657 | delayed_var_partial_spec_iterator delayed_var_partial_spec_end() { |
||
| 658 | return OutOfLineVarPartialSpecs.end(); |
||
| 659 | } |
||
| 660 | |||
| 661 | // Helper functions for instantiating methods. |
||
| 662 | TypeSourceInfo *SubstFunctionType(FunctionDecl *D, |
||
| 663 | SmallVectorImpl<ParmVarDecl *> &Params); |
||
| 664 | bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl); |
||
| 665 | bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl); |
||
| 666 | |||
| 667 | bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl); |
||
| 668 | |||
| 669 | TemplateParameterList * |
||
| 670 | SubstTemplateParams(TemplateParameterList *List); |
||
| 671 | |||
| 672 | bool SubstQualifier(const DeclaratorDecl *OldDecl, |
||
| 673 | DeclaratorDecl *NewDecl); |
||
| 674 | bool SubstQualifier(const TagDecl *OldDecl, |
||
| 675 | TagDecl *NewDecl); |
||
| 676 | |||
| 677 | Decl *VisitVarTemplateSpecializationDecl( |
||
| 678 | VarTemplateDecl *VarTemplate, VarDecl *FromVar, |
||
| 679 | const TemplateArgumentListInfo &TemplateArgsInfo, |
||
| 680 | ArrayRef<TemplateArgument> Converted, |
||
| 681 | VarTemplateSpecializationDecl *PrevDecl = nullptr); |
||
| 682 | |||
| 683 | Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); |
||
| 684 | ClassTemplatePartialSpecializationDecl * |
||
| 685 | InstantiateClassTemplatePartialSpecialization( |
||
| 686 | ClassTemplateDecl *ClassTemplate, |
||
| 687 | ClassTemplatePartialSpecializationDecl *PartialSpec); |
||
| 688 | VarTemplatePartialSpecializationDecl * |
||
| 689 | InstantiateVarTemplatePartialSpecialization( |
||
| 690 | VarTemplateDecl *VarTemplate, |
||
| 691 | VarTemplatePartialSpecializationDecl *PartialSpec); |
||
| 692 | void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern); |
||
| 693 | |||
| 694 | private: |
||
| 695 | template<typename T> |
||
| 696 | Decl *instantiateUnresolvedUsingDecl(T *D, |
||
| 697 | bool InstantiatingPackElement = false); |
||
| 698 | }; |
||
| 699 | |||
| 700 | } // namespace clang |
||
| 701 | |||
| 702 | #endif // LLVM_CLANG_SEMA_TEMPLATE_H |