blob: 40a8736ae1afd54e4505db8d08be5dd261b95728 [file] [log] [blame]
Eugene Zelenko21fadad2017-11-21 23:26:08 +00001//===- TemplateName.cpp - C++ Template Name Representation ----------------===//
Douglas Gregordc572a32009-03-30 22:58:21 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Douglas Gregordc572a32009-03-30 22:58:21 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the TemplateName interface and subclasses.
10//
11//===----------------------------------------------------------------------===//
Chris Lattner098d94a2009-04-02 06:07:12 +000012
Douglas Gregordc572a32009-03-30 22:58:21 +000013#include "clang/AST/TemplateName.h"
Ilya Biryukovec3060c2020-03-02 16:07:09 +010014#include "clang/AST/Decl.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000015#include "clang/AST/DeclBase.h"
Douglas Gregordc572a32009-03-30 22:58:21 +000016#include "clang/AST/DeclTemplate.h"
Haojian Wu67d25912020-03-16 13:43:40 +010017#include "clang/AST/DependenceFlags.h"
Douglas Gregordc572a32009-03-30 22:58:21 +000018#include "clang/AST/NestedNameSpecifier.h"
Douglas Gregor7de59662009-05-29 20:38:28 +000019#include "clang/AST/PrettyPrinter.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000020#include "clang/AST/TemplateBase.h"
Jeffrey Yasskin823015d2010-04-08 00:03:06 +000021#include "clang/Basic/Diagnostic.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000022#include "clang/Basic/LLVM.h"
Chris Lattnerc61089a2009-06-30 01:26:17 +000023#include "clang/Basic/LangOptions.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000024#include "clang/Basic/OperatorKinds.h"
25#include "llvm/ADT/ArrayRef.h"
26#include "llvm/ADT/FoldingSet.h"
27#include "llvm/Support/Casting.h"
28#include "llvm/Support/Compiler.h"
Douglas Gregordc572a32009-03-30 22:58:21 +000029#include "llvm/Support/raw_ostream.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000030#include <cassert>
31#include <string>
32
Douglas Gregordc572a32009-03-30 22:58:21 +000033using namespace clang;
34
Fangrui Song6907ce22018-07-30 19:24:48 +000035TemplateArgument
Douglas Gregor5590be02011-01-15 06:45:20 +000036SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
Benjamin Kramercce63472015-08-05 09:40:22 +000037 return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
Douglas Gregor5590be02011-01-15 06:45:20 +000038}
39
John McCalld9dfe3a2011-06-30 08:33:18 +000040void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
41 Profile(ID, Parameter, Replacement);
42}
43
Fangrui Song6907ce22018-07-30 19:24:48 +000044void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
John McCalld9dfe3a2011-06-30 08:33:18 +000045 TemplateTemplateParmDecl *parameter,
46 TemplateName replacement) {
47 ID.AddPointer(parameter);
48 ID.AddPointer(replacement.getAsVoidPointer());
49}
50
51void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
52 ASTContext &Context) {
Benjamin Kramercce63472015-08-05 09:40:22 +000053 Profile(ID, Context, Parameter, getArgumentPack());
Douglas Gregor5590be02011-01-15 06:45:20 +000054}
55
Fangrui Song6907ce22018-07-30 19:24:48 +000056void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
Douglas Gregor5590be02011-01-15 06:45:20 +000057 ASTContext &Context,
58 TemplateTemplateParmDecl *Parameter,
59 const TemplateArgument &ArgPack) {
60 ID.AddPointer(Parameter);
61 ArgPack.Profile(ID, Context);
62}
63
Chandler Carruthbd452fb2015-12-30 06:21:02 +000064TemplateName::TemplateName(void *Ptr) {
65 Storage = StorageType::getFromOpaqueValue(Ptr);
66}
67
Chandler Carruth21c90602015-12-30 03:24:14 +000068TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
69TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
70 : Storage(Storage) {}
Richard Smithb23c5e82019-05-09 03:31:27 +000071TemplateName::TemplateName(AssumedTemplateStorage *Storage)
72 : Storage(Storage) {}
Chandler Carruth21c90602015-12-30 03:24:14 +000073TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
74 : Storage(Storage) {}
75TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
76 : Storage(Storage) {}
77TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
78TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
79
80bool TemplateName::isNull() const { return Storage.isNull(); }
81
Argyrios Kyrtzidis106caf922010-06-19 19:28:53 +000082TemplateName::NameKind TemplateName::getKind() const {
83 if (Storage.is<TemplateDecl *>())
84 return Template;
Douglas Gregor5590be02011-01-15 06:45:20 +000085 if (Storage.is<DependentTemplateName *>())
86 return DependentTemplate;
Argyrios Kyrtzidis106caf922010-06-19 19:28:53 +000087 if (Storage.is<QualifiedTemplateName *>())
88 return QualifiedTemplate;
John McCalld9dfe3a2011-06-30 08:33:18 +000089
90 UncommonTemplateNameStorage *uncommon
91 = Storage.get<UncommonTemplateNameStorage*>();
92 if (uncommon->getAsOverloadedStorage())
93 return OverloadedTemplate;
Richard Smithb23c5e82019-05-09 03:31:27 +000094 if (uncommon->getAsAssumedTemplateName())
95 return AssumedTemplate;
John McCalld9dfe3a2011-06-30 08:33:18 +000096 if (uncommon->getAsSubstTemplateTemplateParm())
97 return SubstTemplateTemplateParm;
98 return SubstTemplateTemplateParmPack;
Argyrios Kyrtzidis106caf922010-06-19 19:28:53 +000099}
100
Douglas Gregordc572a32009-03-30 22:58:21 +0000101TemplateDecl *TemplateName::getAsTemplateDecl() const {
102 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
103 return Template;
Mike Stump11289f42009-09-09 15:08:12 +0000104
Douglas Gregordc572a32009-03-30 22:58:21 +0000105 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
106 return QTN->getTemplateDecl();
107
John McCalld9dfe3a2011-06-30 08:33:18 +0000108 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
109 return sub->getReplacement().getAsTemplateDecl();
110
Craig Topper36250ad2014-05-12 05:36:57 +0000111 return nullptr;
Douglas Gregordc572a32009-03-30 22:58:21 +0000112}
113
Chandler Carruth21c90602015-12-30 03:24:14 +0000114OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
115 if (UncommonTemplateNameStorage *Uncommon =
116 Storage.dyn_cast<UncommonTemplateNameStorage *>())
117 return Uncommon->getAsOverloadedStorage();
118
119 return nullptr;
120}
121
Richard Smithb23c5e82019-05-09 03:31:27 +0000122AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
123 if (UncommonTemplateNameStorage *Uncommon =
124 Storage.dyn_cast<UncommonTemplateNameStorage *>())
125 return Uncommon->getAsAssumedTemplateName();
126
127 return nullptr;
128}
129
Chandler Carruth21c90602015-12-30 03:24:14 +0000130SubstTemplateTemplateParmStorage *
131TemplateName::getAsSubstTemplateTemplateParm() const {
132 if (UncommonTemplateNameStorage *uncommon =
133 Storage.dyn_cast<UncommonTemplateNameStorage *>())
134 return uncommon->getAsSubstTemplateTemplateParm();
135
136 return nullptr;
137}
138
139SubstTemplateTemplateParmPackStorage *
140TemplateName::getAsSubstTemplateTemplateParmPack() const {
141 if (UncommonTemplateNameStorage *Uncommon =
142 Storage.dyn_cast<UncommonTemplateNameStorage *>())
143 return Uncommon->getAsSubstTemplateTemplateParmPack();
144
145 return nullptr;
146}
147
148QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
149 return Storage.dyn_cast<QualifiedTemplateName *>();
150}
151
152DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
153 return Storage.dyn_cast<DependentTemplateName *>();
154}
155
Richard Smith1abacfc2017-08-29 22:14:43 +0000156TemplateName TemplateName::getNameToSubstitute() const {
157 TemplateDecl *Decl = getAsTemplateDecl();
158
159 // Substituting a dependent template name: preserve it as written.
160 if (!Decl)
161 return *this;
162
163 // If we have a template declaration, use the most recent non-friend
164 // declaration of that template.
165 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
166 while (Decl->getFriendObjectKind()) {
167 Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
168 assert(Decl && "all declarations of template are friends");
169 }
170 return TemplateName(Decl);
171}
172
Ilya Biryukovec3060c2020-03-02 16:07:09 +0100173TemplateNameDependence TemplateName::getDependence() const {
174 auto D = TemplateNameDependence::None;
175 switch (getKind()) {
176 case TemplateName::NameKind::QualifiedTemplate:
177 D |= toTemplateNameDependence(
178 getAsQualifiedTemplateName()->getQualifier()->getDependence());
179 break;
180 case TemplateName::NameKind::DependentTemplate:
181 D |= toTemplateNameDependence(
182 getAsDependentTemplateName()->getQualifier()->getDependence());
183 break;
184 case TemplateName::NameKind::SubstTemplateTemplateParmPack:
185 D |= TemplateNameDependence::UnexpandedPack;
186 break;
187 case TemplateName::NameKind::OverloadedTemplate:
Mikael Holmencd1dc7f2020-03-05 09:29:55 +0100188 llvm_unreachable("overloaded templates shouldn't survive to here.");
Ilya Biryukovec3060c2020-03-02 16:07:09 +0100189 default:
190 break;
191 }
Douglas Gregordc572a32009-03-30 22:58:21 +0000192 if (TemplateDecl *Template = getAsTemplateDecl()) {
Ilya Biryukovec3060c2020-03-02 16:07:09 +0100193 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
194 D |= TemplateNameDependence::DependentInstantiation;
195 if (TTP->isParameterPack())
196 D |= TemplateNameDependence::UnexpandedPack;
197 }
Argyrios Kyrtzidisf4bc0d82010-09-08 19:31:22 +0000198 // FIXME: Hack, getDeclContext() can be null if Template is still
199 // initializing due to PCH reading, so we check it before using it.
200 // Should probably modify TemplateSpecializationType to allow constructing
201 // it without the isDependent() checking.
Ilya Biryukovec3060c2020-03-02 16:07:09 +0100202 if (Template->getDeclContext() &&
203 Template->getDeclContext()->isDependentContext())
204 D |= TemplateNameDependence::DependentInstantiation;
205 } else {
206 D |= TemplateNameDependence::DependentInstantiation;
Douglas Gregordc572a32009-03-30 22:58:21 +0000207 }
Ilya Biryukovec3060c2020-03-02 16:07:09 +0100208 return D;
209}
Douglas Gregordc572a32009-03-30 22:58:21 +0000210
Ilya Biryukovec3060c2020-03-02 16:07:09 +0100211bool TemplateName::isDependent() const {
212 return getDependence() & TemplateNameDependence::Dependent;
Douglas Gregordc572a32009-03-30 22:58:21 +0000213}
214
Douglas Gregor678d76c2011-07-01 01:22:09 +0000215bool TemplateName::isInstantiationDependent() const {
Ilya Biryukovec3060c2020-03-02 16:07:09 +0100216 return getDependence() & TemplateNameDependence::Instantiation;
Douglas Gregor678d76c2011-07-01 01:22:09 +0000217}
218
Douglas Gregor506bd562010-12-13 22:49:22 +0000219bool TemplateName::containsUnexpandedParameterPack() const {
Ilya Biryukovec3060c2020-03-02 16:07:09 +0100220 return getDependence() & TemplateNameDependence::UnexpandedPack;
Douglas Gregor506bd562010-12-13 22:49:22 +0000221}
222
Mike Stump11289f42009-09-09 15:08:12 +0000223void
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000224TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Douglas Gregor7de59662009-05-29 20:38:28 +0000225 bool SuppressNNS) const {
Douglas Gregordc572a32009-03-30 22:58:21 +0000226 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
Benjamin Kramerb89514a2011-10-14 18:45:37 +0000227 OS << *Template;
Douglas Gregordc572a32009-03-30 22:58:21 +0000228 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
Douglas Gregordce2b622009-04-01 00:28:59 +0000229 if (!SuppressNNS)
Douglas Gregor7de59662009-05-29 20:38:28 +0000230 QTN->getQualifier()->print(OS, Policy);
Douglas Gregordc572a32009-03-30 22:58:21 +0000231 if (QTN->hasTemplateKeyword())
232 OS << "template ";
Benjamin Kramerb89514a2011-10-14 18:45:37 +0000233 OS << *QTN->getDecl();
Douglas Gregordc572a32009-03-30 22:58:21 +0000234 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
Douglas Gregor308047d2009-09-09 00:23:06 +0000235 if (!SuppressNNS && DTN->getQualifier())
Douglas Gregor7de59662009-05-29 20:38:28 +0000236 DTN->getQualifier()->print(OS, Policy);
Douglas Gregordc572a32009-03-30 22:58:21 +0000237 OS << "template ";
Fangrui Song6907ce22018-07-30 19:24:48 +0000238
Douglas Gregor71395fa2009-11-04 00:56:37 +0000239 if (DTN->isIdentifier())
240 OS << DTN->getIdentifier()->getName();
241 else
242 OS << "operator " << getOperatorSpelling(DTN->getOperator());
John McCalld9dfe3a2011-06-30 08:33:18 +0000243 } else if (SubstTemplateTemplateParmStorage *subst
244 = getAsSubstTemplateTemplateParm()) {
245 subst->getReplacement().print(OS, Policy, SuppressNNS);
Douglas Gregor5590be02011-01-15 06:45:20 +0000246 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
247 = getAsSubstTemplateTemplateParmPack())
Benjamin Kramerdb0fc512012-02-07 11:57:57 +0000248 OS << *SubstPack->getParameterPack();
Richard Smithb23c5e82019-05-09 03:31:27 +0000249 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
250 Assumed->getDeclName().print(OS, Policy);
251 } else {
Douglas Gregor8b6070b2011-03-04 21:37:14 +0000252 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
253 (*OTS->begin())->printName(OS);
254 }
Douglas Gregordc572a32009-03-30 22:58:21 +0000255}
Douglas Gregoraa594892009-03-31 18:38:02 +0000256
Jeffrey Yasskin823015d2010-04-08 00:03:06 +0000257const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
258 TemplateName N) {
259 std::string NameStr;
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000260 llvm::raw_string_ostream OS(NameStr);
Jeffrey Yasskin823015d2010-04-08 00:03:06 +0000261 LangOptions LO;
262 LO.CPlusPlus = true;
263 LO.Bool = true;
David Blaikiee7504912013-03-05 06:21:38 +0000264 OS << '\'';
Jeffrey Yasskin823015d2010-04-08 00:03:06 +0000265 N.print(OS, PrintingPolicy(LO));
David Blaikiee7504912013-03-05 06:21:38 +0000266 OS << '\'';
Jeffrey Yasskin823015d2010-04-08 00:03:06 +0000267 OS.flush();
268 return DB << NameStr;
269}
270
David Blaikie5e328052019-05-03 00:44:50 +0000271const PartialDiagnostic&clang::operator<<(const PartialDiagnostic &PD,
272 TemplateName N) {
273 std::string NameStr;
274 llvm::raw_string_ostream OS(NameStr);
275 LangOptions LO;
276 LO.CPlusPlus = true;
277 LO.Bool = true;
278 OS << '\'';
279 N.print(OS, PrintingPolicy(LO));
280 OS << '\'';
281 OS.flush();
282 return PD << NameStr;
283}
284
Alexander Kornienko90ff6072012-12-20 02:09:13 +0000285void TemplateName::dump(raw_ostream &OS) const {
Chris Lattnerc61089a2009-06-30 01:26:17 +0000286 LangOptions LO; // FIXME!
287 LO.CPlusPlus = true;
288 LO.Bool = true;
Alexander Kornienko90ff6072012-12-20 02:09:13 +0000289 print(OS, PrintingPolicy(LO));
290}
291
Yaron Kerencdae9412016-01-29 19:38:18 +0000292LLVM_DUMP_METHOD void TemplateName::dump() const {
Alexander Kornienko90ff6072012-12-20 02:09:13 +0000293 dump(llvm::errs());
Douglas Gregoraa594892009-03-31 18:38:02 +0000294}