clang 20.0.0git
TemplateName.cpp
Go to the documentation of this file.
1//===- TemplateName.cpp - C++ Template Name Representation ----------------===//
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//
9// This file defines the TemplateName interface and subclasses.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/Decl.h"
15#include "clang/AST/DeclBase.h"
16#include "clang/AST/DeclCXX.h"
23#include "clang/Basic/LLVM.h"
26#include "llvm/ADT/ArrayRef.h"
27#include "llvm/ADT/FoldingSet.h"
28#include "llvm/Support/Compiler.h"
29#include "llvm/Support/raw_ostream.h"
30#include <cassert>
31#include <optional>
32#include <string>
33
34using namespace clang;
35
36DeducedTemplateStorage::DeducedTemplateStorage(TemplateName Underlying,
37 const DefaultArguments &DefArgs)
38 : UncommonTemplateNameStorage(Deduced, /*Index=*/DefArgs.StartPos,
39 DefArgs.Args.size()),
40 Underlying(Underlying) {
41 llvm::copy(DefArgs.Args, reinterpret_cast<TemplateArgument *>(this + 1));
42}
43
44void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
45 const ASTContext &Context) const {
46 Profile(ID, Context, Underlying, getDefaultArguments());
47}
48
49void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
50 const ASTContext &Context,
51 TemplateName Underlying,
52 const DefaultArguments &DefArgs) {
53 Underlying.Profile(ID);
54 ID.AddInteger(DefArgs.StartPos);
55 ID.AddInteger(DefArgs.Args.size());
56 for (const TemplateArgument &Arg : DefArgs.Args)
57 Arg.Profile(ID, Context);
58}
59
62 return TemplateArgument(llvm::ArrayRef(Arguments, Bits.Data));
63}
64
67 return cast<TemplateTemplateParmDecl>(
69 ->asArray()[Bits.Index]);
70}
71
74 return cast<TemplateTemplateParmDecl>(
76 ->asArray()[Bits.Index]);
77}
78
79void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
80 Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex());
81}
82
84 llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
85 unsigned Index, std::optional<unsigned> PackIndex) {
86 Replacement.Profile(ID);
87 ID.AddPointer(AssociatedDecl);
88 ID.AddInteger(Index);
89 ID.AddInteger(PackIndex ? *PackIndex + 1 : 0);
90}
91
93 ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
94 bool Final)
95 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
96 ArgPack.size()),
97 Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
98 assert(AssociatedDecl != nullptr);
99}
100
101void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
102 ASTContext &Context) {
104 getFinal());
105}
106
108 return AssociatedDeclAndFinal.getPointer();
109}
110
112 return AssociatedDeclAndFinal.getInt();
113}
114
116 llvm::FoldingSetNodeID &ID, ASTContext &Context,
117 const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
118 bool Final) {
119 ArgPack.Profile(ID, Context);
120 ID.AddPointer(AssociatedDecl);
121 ID.AddInteger(Index);
122 ID.AddBoolean(Final);
123}
124
126 Storage = StorageType::getFromOpaqueValue(Ptr);
127}
128
129TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
131 : Storage(Storage) {}
133 : Storage(Storage) {}
135 : Storage(Storage) {}
137 : Storage(Storage) {}
142 : Storage(Deduced) {}
143
144bool TemplateName::isNull() const { return Storage.isNull(); }
145
147 if (auto *ND = Storage.dyn_cast<Decl *>()) {
148 if (isa<UsingShadowDecl>(ND))
149 return UsingTemplate;
150 assert(isa<TemplateDecl>(ND));
151 return Template;
152 }
153
154 if (isa<DependentTemplateName *>(Storage))
155 return DependentTemplate;
156 if (isa<QualifiedTemplateName *>(Storage))
157 return QualifiedTemplate;
158
160 cast<UncommonTemplateNameStorage *>(Storage);
161 if (uncommon->getAsOverloadedStorage())
162 return OverloadedTemplate;
163 if (uncommon->getAsAssumedTemplateName())
164 return AssumedTemplate;
165 if (uncommon->getAsSubstTemplateTemplateParm())
167 if (uncommon->getAsDeducedTemplateName())
168 return DeducedTemplate;
169
170 assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr);
172}
173
175 TemplateName Name = *this;
176 while (std::optional<TemplateName> UnderlyingOrNone =
177 Name.desugar(IgnoreDeduced))
178 Name = *UnderlyingOrNone;
179
180 if (!IgnoreDeduced)
181 assert(Name.getAsDeducedTemplateName() == nullptr &&
182 "Unexpected canonical DeducedTemplateName; Did you mean to use "
183 "getTemplateDeclAndDefaultArgs instead?");
184
185 return cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>());
186}
187
188std::pair<TemplateDecl *, DefaultArguments>
190 for (TemplateName Name = *this; /**/; /**/) {
191 if (Name.getKind() == TemplateName::DeducedTemplate) {
192 DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName();
193 TemplateDecl *TD =
194 DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true);
195 DefaultArguments DefArgs = DTS->getDefaultArguments();
196 if (TD && DefArgs)
197 assert(DefArgs.StartPos + DefArgs.Args.size() <=