blob: 548468ed17cdcc5ee7e77920976f75b777054808 [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//
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//
10// This file defines the TemplateName interface and subclasses.
11//
12//===----------------------------------------------------------------------===//
Chris Lattner098d94a2009-04-02 06:07:12 +000013
Douglas Gregordc572a32009-03-30 22:58:21 +000014#include "clang/AST/TemplateName.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"
17#include "clang/AST/NestedNameSpecifier.h"
Douglas Gregor7de59662009-05-29 20:38:28 +000018#include "clang/AST/PrettyPrinter.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000019#include "clang/AST/TemplateBase.h"
Jeffrey Yasskin823015d2010-04-08 00:03:06 +000020#include "clang/Basic/Diagnostic.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000021#include "clang/Basic/LLVM.h"
Chris Lattnerc61089a2009-06-30 01:26:17 +000022#include "clang/Basic/LangOptions.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000023#include "clang/Basic/OperatorKinds.h"
24#include "llvm/ADT/ArrayRef.h"
25#include "llvm/ADT/FoldingSet.h"
26#include "llvm/Support/Casting.h"
27#include "llvm/Support/Compiler.h"
Douglas Gregordc572a32009-03-30 22:58:21 +000028#include "llvm/Support/raw_ostream.h"
Eugene Zelenko21fadad2017-11-21 23:26:08 +000029#include <cassert>
30#include <string>
31
Douglas Gregordc572a32009-03-30 22:58:21 +000032using namespace clang;
33
Douglas Gregor5590be02011-01-15 06:45:20 +000034TemplateArgument
35SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
Benjamin Kramercce63472015-08-05 09:40:22 +000036 return TemplateArgument(llvm::makeArrayRef(Arguments, size()));
Douglas Gregor5590be02011-01-15 06:45:20 +000037}
38
John McCalld9dfe3a2011-06-30 08:33:18 +000039void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
40 Profile(ID, Parameter, Replacement);
41}
42
43void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID,
44 TemplateTemplateParmDecl *parameter,
45 TemplateName replacement) {
46 ID.AddPointer(parameter);
47 ID.AddPointer(replacement.getAsVoidPointer());
48}
49
50void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
51 ASTContext &Context) {
Benjamin Kramercce63472015-08-05 09:40:22 +000052 Profile(ID, Context, Parameter, getArgumentPack());
Douglas Gregor5590be02011-01-15 06:45:20 +000053}
54
55void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
56 ASTContext &Context,
57 TemplateTemplateParmDecl *Parameter,
58 const TemplateArgument &ArgPack) {
59 ID.AddPointer(Parameter);
60 ArgPack.Profile(ID, Context);
61}
62
Chandler Carruthbd452fb2015-12-30 06:21:02 +000063TemplateName::TemplateName(void *Ptr) {
64 Storage = StorageType::getFromOpaqueValue(Ptr);
65}
66
Chandler Carruth21c90602015-12-30 03:24:14 +000067TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
68TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
69 : Storage(Storage) {}
70TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
71 : Storage(Storage) {}
72TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
73 : Storage(Storage) {}
74TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
75TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
76
77bool TemplateName::isNull() const { return Storage.isNull(); }
78
Argyrios Kyrtzidis106caf922010-06-19 19:28:53 +000079TemplateName::NameKind TemplateName::getKind() const {
80 if (Storage.is<TemplateDecl *>())
81 return Template;
Douglas Gregor5590be02011-01-15 06:45:20 +000082 if (Storage.is<DependentTemplateName *>())
83 return DependentTemplate;
Argyrios Kyrtzidis106caf922010-06-19 19:28:53 +000084 if (Storage.is<QualifiedTemplateName *>())
85 return QualifiedTemplate;
John McCalld9dfe3a2011-06-30 08:33:18 +000086
87 UncommonTemplateNameStorage *uncommon
88 = Storage.get<UncommonTemplateNameStorage*>();
89 if (uncommon->getAsOverloadedStorage())
90 return OverloadedTemplate;
91 if (uncommon->getAsSubstTemplateTemplateParm())
92 return SubstTemplateTemplateParm;
93 return SubstTemplateTemplateParmPack;
Argyrios Kyrtzidis106caf922010-06-19 19:28:53 +000094}
95
Douglas Gregordc572a32009-03-30 22:58:21 +000096TemplateDecl *TemplateName::getAsTemplateDecl() const {
97 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
98 return Template;
Mike Stump11289f42009-09-09 15:08:12 +000099
Douglas Gregordc572a32009-03-30 22:58:21 +0000100 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
101 return QTN->getTemplateDecl();
102
John McCalld9dfe3a2011-06-30 08:33:18 +0000103 if (SubstTemplateTemplateParmStorage *sub = getAsSubstTemplateTemplateParm())
104 return sub->getReplacement().getAsTemplateDecl();
105
Craig Topper36250ad2014-05-12 05:36:57 +0000106 return nullptr;
Douglas Gregordc572a32009-03-30 22:58:21 +0000107}
108
Chandler Carruth21c90602015-12-30 03:24:14 +0000109OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
110 if (UncommonTemplateNameStorage *Uncommon =
111 Storage.dyn_cast<UncommonTemplateNameStorage *>())
112 return Uncommon->getAsOverloadedStorage();
113
114 return nullptr;
115}
116
117SubstTemplateTemplateParmStorage *
118TemplateName::getAsSubstTemplateTemplateParm() const {
119 if (UncommonTemplateNameStorage *uncommon =
120 Storage.dyn_cast<UncommonTemplateNameStorage *>())
121 return uncommon->getAsSubstTemplateTemplateParm();
122
123 return nullptr;
124}
125
126SubstTemplateTemplateParmPackStorage *
127TemplateName::getAsSubstTemplateTemplateParmPack() const {
128 if (UncommonTemplateNameStorage *Uncommon =
129 Storage.dyn_cast<UncommonTemplateNameStorage *>())
130 return Uncommon->getAsSubstTemplateTemplateParmPack();
131
132 return nullptr;
133}
134
135QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
136 return Storage.dyn_cast<QualifiedTemplateName *>();
137}
138
139DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
140 return Storage.dyn_cast<DependentTemplateName *>();
141}
142
Richard Smith1abacfc2017-08-29 22:14:43 +0000143TemplateName TemplateName::getNameToSubstitute() const {
144 TemplateDecl *Decl = getAsTemplateDecl();
145
146 // Substituting a dependent template name: preserve it as written.
147 if (!Decl)
148 return *this;
149
150 // If we have a template declaration, use the most recent non-friend
151 // declaration of that template.
152 Decl = cast<TemplateDecl>(Decl->getMostRecentDecl());
153 while (Decl->getFriendObjectKind()) {
154 Decl = cast<TemplateDecl>(Decl->getPreviousDecl());
155 assert(Decl && "all declarations of template are friends");
156 }
157 return TemplateName(Decl);
158}
159
Douglas Gregordc572a32009-03-30 22:58:21 +0000160bool TemplateName::isDependent() const {
161 if (TemplateDecl *Template = getAsTemplateDecl()) {
Argyrios Kyrtzidisf4bc0d82010-09-08 19:31:22 +0000162 if (isa<TemplateTemplateParmDecl>(Template))
163 return true;
164 // FIXME: Hack, getDeclContext() can be null if Template is still
165 // initializing due to PCH reading, so we check it before using it.
166 // Should probably modify TemplateSpecializationType to allow constructing
167 // it without the isDependent() checking.
168 return Template->getDeclContext() &&
169 Template->getDeclContext()->isDependentContext();
Douglas Gregordc572a32009-03-30 22:58:21 +0000170 }
171
John McCalld28ae272009-12-02 08:04:21 +0000172 assert(!getAsOverloadedTemplate() &&
173 "overloaded templates shouldn't survive to here");
Mike Stump11289f42009-09-09 15:08:12 +0000174
Douglas Gregordc572a32009-03-30 22:58:21 +0000175 return true;
176}
177
Douglas Gregor678d76c2011-07-01 01:22:09 +0000178bool TemplateName::isInstantiationDependent() const {
179 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
180 if (QTN->getQualifier()->isInstantiationDependent())
181 return true;
182 }
183
184 return isDependent();
185}
186
Douglas Gregor506bd562010-12-13 22:49:22 +0000187bool TemplateName::containsUnexpandedParameterPack() const {
Richard Smith77a9c602018-02-28 03:02:23 +0000188 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
189 if (QTN->getQualifier()->containsUnexpandedParameterPack())
190 return true;
191 }
192
Douglas Gregor506bd562010-12-13 22:49:22 +0000193 if (TemplateDecl *Template = getAsTemplateDecl()) {
194 if (TemplateTemplateParmDecl *TTP
195 = dyn_cast<TemplateTemplateParmDecl>(Template))
196 return TTP->isParameterPack();
197
198 return false;
199 }
200
201 if (DependentTemplateName *DTN = getAsDependentTemplateName())
202 return DTN->getQualifier() &&
203 DTN->getQualifier()->containsUnexpandedParameterPack();
204
Craig Topper36250ad2014-05-12 05:36:57 +0000205 return getAsSubstTemplateTemplateParmPack() != nullptr;
Douglas Gregor506bd562010-12-13 22:49:22 +0000206}
207
Mike Stump11289f42009-09-09 15:08:12 +0000208void
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000209TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Douglas Gregor7de59662009-05-29 20:38:28 +0000210 bool SuppressNNS) const {
Douglas Gregordc572a32009-03-30 22:58:21 +0000211 if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
Benjamin Kramerb89514a2011-10-14 18:45:37 +0000212 OS << *Template;
Douglas Gregordc572a32009-03-30 22:58:21 +0000213 else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
Douglas Gregordce2b622009-04-01 00:28:59 +0000214 if (!SuppressNNS)
Douglas Gregor7de59662009-05-29 20:38:28 +0000215 QTN->getQualifier()->print(OS, Policy);
Douglas Gregordc572a32009-03-30 22:58:21 +0000216 if (QTN->hasTemplateKeyword())
217 OS << "template ";
Benjamin Kramerb89514a2011-10-14 18:45:37 +0000218 OS << *QTN->getDecl();
Douglas Gregordc572a32009-03-30 22:58:21 +0000219 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
Douglas Gregor308047d2009-09-09 00:23:06 +0000220 if (!SuppressNNS && DTN->getQualifier())
Douglas Gregor7de59662009-05-29 20:38:28 +0000221 DTN->getQualifier()->print(OS, Policy);
Douglas Gregordc572a32009-03-30 22:58:21 +0000222 OS << "template ";
Douglas Gregor71395fa2009-11-04 00:56:37 +0000223
224 if (DTN->isIdentifier())
225 OS << DTN->getIdentifier()->getName();
226 else
227 OS << "operator " << getOperatorSpelling(DTN->getOperator());
John McCalld9dfe3a2011-06-30 08:33:18 +0000228 } else if (SubstTemplateTemplateParmStorage *subst
229 = getAsSubstTemplateTemplateParm()) {
230 subst->getReplacement().print(OS, Policy, SuppressNNS);
Douglas Gregor5590be02011-01-15 06:45:20 +0000231 } else if (SubstTemplateTemplateParmPackStorage *SubstPack
232 = getAsSubstTemplateTemplateParmPack())
Benjamin Kramerdb0fc512012-02-07 11:57:57 +0000233 OS << *SubstPack->getParameterPack();
Douglas Gregor8b6070b2011-03-04 21:37:14 +0000234 else {
235 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
236 (*OTS->begin())->printName(OS);
237 }
Douglas Gregordc572a32009-03-30 22:58:21 +0000238}
Douglas Gregoraa594892009-03-31 18:38:02 +0000239
Jeffrey Yasskin823015d2010-04-08 00:03:06 +0000240const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
241 TemplateName N) {
242 std::string NameStr;
Eugene Zelenko21fadad2017-11-21 23:26:08 +0000243 llvm::raw_string_ostream OS(NameStr);
Jeffrey Yasskin823015d2010-04-08 00:03:06 +0000244 LangOptions LO;
245 LO.CPlusPlus = true;
246 LO.Bool = true;
David Blaikiee7504912013-03-05 06:21:38 +0000247 OS << '\'';
Jeffrey Yasskin823015d2010-04-08 00:03:06 +0000248 N.print(OS, PrintingPolicy(LO));
David Blaikiee7504912013-03-05 06:21:38 +0000249 OS << '\'';
Jeffrey Yasskin823015d2010-04-08 00:03:06 +0000250 OS.flush();
251 return DB << NameStr;
252}
253
Alexander Kornienko90ff6072012-12-20 02:09:13 +0000254void TemplateName::dump(raw_ostream &OS) const {
Chris Lattnerc61089a2009-06-30 01:26:17 +0000255 LangOptions LO; // FIXME!
256 LO.CPlusPlus = true;
257 LO.Bool = true;
Alexander Kornienko90ff6072012-12-20 02:09:13 +0000258 print(OS, PrintingPolicy(LO));
259}
260
Yaron Kerencdae9412016-01-29 19:38:18 +0000261LLVM_DUMP_METHOD void TemplateName::dump() const {
Alexander Kornienko90ff6072012-12-20 02:09:13 +0000262 dump(llvm::errs());
Douglas Gregoraa594892009-03-31 18:38:02 +0000263}