Clang Project

clang_source_code/lib/AST/TemplateName.cpp
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
13#include "clang/AST/TemplateName.h"
14#include "clang/AST/DeclBase.h"
15#include "clang/AST/DeclTemplate.h"
16#include "clang/AST/NestedNameSpecifier.h"
17#include "clang/AST/PrettyPrinter.h"
18#include "clang/AST/TemplateBase.h"
19#include "clang/Basic/Diagnostic.h"
20#include "clang/Basic/LLVM.h"
21#include "clang/Basic/LangOptions.h"
22#include "clang/Basic/OperatorKinds.h"
23#include "llvm/ADT/ArrayRef.h"
24#include "llvm/ADT/FoldingSet.h"
25#include "llvm/Support/Casting.h"
26#include "llvm/Support/Compiler.h"
27#include "llvm/Support/raw_ostream.h"
28#include <cassert>
29#include <string>
30
31using namespace clang;
32
33TemplateArgument
34SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
35  return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
36}
37
38void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
39  Profile(ID, Parameter, Replacement);
40}
41
42void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
43                                           TemplateTemplateParmDecl *parameter,
44                                               TemplateName replacement) {
45  ID.AddPointer(parameter);
46  ID.AddPointer(replacement.getAsVoidPointer());
47}
48
49void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
50                                                   ASTContext &Context) {
51  Profile(ID, Context, Parameter, getArgumentPack());
52}
53
54void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
55                                                   ASTContext &Context,
56                                           TemplateTemplateParmDecl *Parameter,
57                                             const TemplateArgument &ArgPack) {
58  ID.AddPointer(Parameter);
59  ArgPack.Profile(IDContext);
60}
61
62TemplateName::TemplateName(void *Ptr) {
63  Storage = StorageType::getFromOpaqueValue(Ptr);
64}
65
66TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
67TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
68    : Storage(Storage) {}
69TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
70    : Storage(Storage) {}
71TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
72    : Storage(Storage) {}
73TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
74TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
75
76bool TemplateName::isNull() const { return Storage.isNull(); }
77
78TemplateName::NameKind TemplateName::getKind() const {
79  if (Storage.is<TemplateDecl *>())
80    return Template;
81  if (Storage.is<DependentTemplateName *>())
82    return DependentTemplate;
83  if (Storage.is<QualifiedTemplateName *>())
84    return QualifiedTemplate;
85
86  UncommonTemplateNameStorage *uncommon
87    = Storage.get<UncommonTemplateNameStorage*>();
88  if (uncommon->getAsOverloadedStorage())
89    return OverloadedTemplate;
90  if (uncommon->getAsSubstTemplateTemplateParm())
91    return SubstTemplateTemplateParm;
92  return SubstTemplateTemplateParmPack;
93}
94
95TemplateDecl *TemplateName::getAsTemplateDecl() const {
96  if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
97    return Template;
98
99  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
100    return QTN->getTemplateDecl();
101
102  if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
103    return sub->getReplacement().getAsTemplateDecl();
104
105  return nullptr;
106}
107
108OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
109  if (UncommonTemplateNameStorage *Uncommon =
110          Storage.dyn_cast<UncommonTemplateNameStorage *>())
111    return Uncommon->getAsOverloadedStorage();
112
113  return nullptr;
114}
115
116SubstTemplateTemplateParmStorage *
117TemplateName::getAsSubstTemplateTemplateParm() const {
118  if (UncommonTemplateNameStorage *uncommon =
119          Storage.dyn_cast<UncommonTemplateNameStorage *>())
120    return uncommon->getAsSubstTemplateTemplateParm();
121
122  return nullptr;
123}
124
125SubstTemplateTemplateParmPackStorage *
126TemplateName::getAsSubstTemplateTemplateParmPack() const {
127  if (UncommonTemplateNameStorage *Uncommon =
128          Storage.dyn_cast<UncommonTemplateNameStorage *>())
129    return Uncommon->getAsSubstTemplateTemplateParmPack();
130
131  return nullptr;
132}
133
134QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
135  return Storage.dyn_cast<QualifiedTemplateName *>();
136}
137
138DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
139  return Storage.dyn_cast<DependentTemplateName *>();
140}
141
142TemplateName TemplateName::getNameToSubstitute() const {
143  TemplateDecl *Decl = getAsTemplateDecl();
144
145  // Substituting a dependent template name: preserve it as written.
146  if (!Decl)
147    return *this;
148
149  // If we have a template declaration, use the most recent non-friend
150  // declaration of that template.
151  Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
152  while (Decl->getFriendObjectKind()) {
153    Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
154     (0) . __assert_fail ("Decl && \"all declarations of template are friends\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/TemplateName.cpp", 154, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Decl && "all declarations of template are friends");
155  }
156  return TemplateName(Decl);
157}
158
159bool TemplateName::isDependent() const {
160  if (TemplateDecl *Template = getAsTemplateDecl()) {
161    if (isa<TemplateTemplateParmDecl>(Template))
162      return true;
163    // FIXME: Hack, getDeclContext() can be null if Template is still
164    // initializing due to PCH reading, so we check it before using it.
165    // Should probably modify TemplateSpecializationType to allow constructing
166    // it without the isDependent() checking.
167    return Template->getDeclContext() &&
168           Template->getDeclContext()->isDependentContext();
169  }
170
171   (0) . __assert_fail ("!getAsOverloadedTemplate() && \"overloaded templates shouldn't survive to here\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/TemplateName.cpp", 172, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!getAsOverloadedTemplate() &&
172 (0) . __assert_fail ("!getAsOverloadedTemplate() && \"overloaded templates shouldn't survive to here\"", "/home/seafit/code_projects/clang_source/clang/lib/AST/TemplateName.cpp", 172, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">         "overloaded templates shouldn't survive to here");
173
174  return true;
175}
176
177bool TemplateName::isInstantiationDependent() const {
178  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
179    if (QTN->getQualifier()->isInstantiationDependent())
180      return true;
181  }
182
183  return isDependent();
184}
185
186bool TemplateName::containsUnexpandedParameterPack() const {
187  if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
188    if (QTN->getQualifier()->containsUnexpandedParameterPack())
189      return true;
190  }
191
192  if (TemplateDecl *Template = getAsTemplateDecl()) {
193    if (TemplateTemplateParmDecl *TTP
194                                  = dyn_cast<TemplateTemplateParmDecl>(Template))
195      return TTP->isParameterPack();
196
197    return false;
198  }
199
200  if (DependentTemplateName *DTN = getAsDependentTemplateName())
201    return DTN->getQualifier() &&
202      DTN->getQualifier()->containsUnexpandedParameterPack();
203
204  return getAsSubstTemplateTemplateParmPack() != nullptr;
205}
206
207void
208TemplateName::print(raw_ostream &OSconst PrintingPolicy &Policy,
209                    bool SuppressNNSconst {
210  if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
211    OS << *Template;
212  else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
213    if (!SuppressNNS)
214      QTN->getQualifier()->print(OSPolicy);
215    if (QTN->hasTemplateKeyword())
216      OS << "template ";
217    OS << *QTN->getDecl();
218  } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
219    if (!SuppressNNS && DTN->getQualifier())
220      DTN->getQualifier()->print(OSPolicy);
221    OS << "template ";
222
223    if (DTN->isIdentifier())
224      OS << DTN->getIdentifier()->getName();
225    else
226      OS << "operator " << getOperatorSpelling(DTN->getOperator());
227  } else if (SubstTemplateTemplateParmStorage *subst
228               = getAsSubstTemplateTemplateParm()) {
229    subst->getReplacement().print(OSPolicySuppressNNS);
230  } else if (SubstTemplateTemplateParmPackStorage *SubstPack
231                                        = getAsSubstTemplateTemplateParmPack())
232    OS << *SubstPack->getParameterPack();
233  else {
234    OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
235    (*OTS->begin())->printName(OS);
236  }
237}
238
239const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
240                                           TemplateName N) {
241  std::string NameStr;
242  llvm::raw_string_ostream OS(NameStr);
243  LangOptions LO;
244  LO.CPlusPlus = true;
245  LO.Bool = true;
246  OS << '\'';
247  N.print(OS, PrintingPolicy(LO));
248  OS << '\'';
249  OS.flush();
250  return DB << NameStr;
251}
252
253void TemplateName::dump(raw_ostream &OSconst {
254  LangOptions LO;  // FIXME!
255  LO.CPlusPlus = true;
256  LO.Bool = true;
257  print(OSPrintingPolicy(LO));
258}
259
260LLVM_DUMP_METHOD void TemplateName::dump() const {
261  dump(llvm::errs());
262}
263
clang::SubstTemplateTemplateParmPackStorage::getArgumentPack
clang::SubstTemplateTemplateParmStorage::Profile
clang::SubstTemplateTemplateParmStorage::Profile
clang::SubstTemplateTemplateParmPackStorage::Profile
clang::SubstTemplateTemplateParmPackStorage::Profile
clang::TemplateName::isNull
clang::TemplateName::getKind
clang::TemplateName::getAsTemplateDecl
clang::TemplateName::getAsOverloadedTemplate
clang::TemplateName::getAsSubstTemplateTemplateParm
clang::TemplateName::getAsSubstTemplateTemplateParmPack
clang::TemplateName::getAsQualifiedTemplateName
clang::TemplateName::getAsDependentTemplateName
clang::TemplateName::getNameToSubstitute
clang::TemplateName::isDependent
clang::TemplateName::isInstantiationDependent
clang::TemplateName::containsUnexpandedParameterPack
clang::TemplateName::print
clang::TemplateName::dump
clang::TemplateName::dump