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/Decl.h"
15 #include "clang/AST/DeclBase.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/DeclTemplate.h"
18 #include "clang/AST/DependenceFlags.h"
19 #include "clang/AST/NestedNameSpecifier.h"
20 #include "clang/AST/PrettyPrinter.h"
21 #include "clang/AST/TemplateBase.h"
22 #include "clang/Basic/Diagnostic.h"
23 #include "clang/Basic/LLVM.h"
24 #include "clang/Basic/LangOptions.h"
25 #include "clang/Basic/OperatorKinds.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
34 using namespace clang;
35
DeducedTemplateStorage(TemplateName Underlying,const DefaultArguments & DefArgs)36 DeducedTemplateStorage::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
Profile(llvm::FoldingSetNodeID & ID,const ASTContext & Context) const44 void DeducedTemplateStorage::Profile(llvm::FoldingSetNodeID &ID,
45 const ASTContext &Context) const {
46 Profile(ID, Context, Underlying, getDefaultArguments());
47 }
48
Profile(llvm::FoldingSetNodeID & ID,const ASTContext & Context,TemplateName Underlying,const DefaultArguments & DefArgs)49 void 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
60 TemplateArgument
getArgumentPack() const61 SubstTemplateTemplateParmPackStorage::getArgumentPack() const {
62 return TemplateArgument(ArrayRef(Arguments, Bits.Data));
63 }
64
65 TemplateTemplateParmDecl *
getParameterPack() const66 SubstTemplateTemplateParmPackStorage::getParameterPack() const {
67 return cast<TemplateTemplateParmDecl>(
68 getReplacedTemplateParameterList(getAssociatedDecl())
69 ->asArray()[Bits.Index]);
70 }
71
72 TemplateTemplateParmDecl *
getParameter() const73 SubstTemplateTemplateParmStorage::getParameter() const {
74 return cast<TemplateTemplateParmDecl>(
75 getReplacedTemplateParameterList(getAssociatedDecl())
76 ->asArray()[Bits.Index]);
77 }
78
Profile(llvm::FoldingSetNodeID & ID)79 void SubstTemplateTemplateParmStorage::Profile(llvm::FoldingSetNodeID &ID) {
80 Profile(ID, Replacement, getAssociatedDecl(), getIndex(), getPackIndex(),
81 getFinal());
82 }
83
Profile(llvm::FoldingSetNodeID & ID,TemplateName Replacement,Decl * AssociatedDecl,unsigned Index,UnsignedOrNone PackIndex,bool Final)84 void SubstTemplateTemplateParmStorage::Profile(
85 llvm::FoldingSetNodeID &ID, TemplateName Replacement, Decl *AssociatedDecl,
86 unsigned Index, UnsignedOrNone PackIndex, bool Final) {
87 Replacement.Profile(ID);
88 ID.AddPointer(AssociatedDecl);
89 ID.AddInteger(Index);
90 ID.AddInteger(PackIndex.toInternalRepresentation());
91 ID.AddBoolean(Final);
92 }
93
SubstTemplateTemplateParmPackStorage(ArrayRef<TemplateArgument> ArgPack,Decl * AssociatedDecl,unsigned Index,bool Final)94 SubstTemplateTemplateParmPackStorage::SubstTemplateTemplateParmPackStorage(
95 ArrayRef<TemplateArgument> ArgPack, Decl *AssociatedDecl, unsigned Index,
96 bool Final)
97 : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Index,
98 ArgPack.size()),
99 Arguments(ArgPack.data()), AssociatedDeclAndFinal(AssociatedDecl, Final) {
100 assert(AssociatedDecl != nullptr);
101 }
102
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context)103 void SubstTemplateTemplateParmPackStorage::Profile(llvm::FoldingSetNodeID &ID,
104 ASTContext &Context) {
105 Profile(ID, Context, getArgumentPack(), getAssociatedDecl(), getIndex(),
106 getFinal());
107 }
108
getAssociatedDecl() const109 Decl *SubstTemplateTemplateParmPackStorage::getAssociatedDecl() const {
110 return AssociatedDeclAndFinal.getPointer();
111 }
112
getFinal() const113 bool SubstTemplateTemplateParmPackStorage::getFinal() const {
114 return AssociatedDeclAndFinal.getInt();
115 }
116
Profile(llvm::FoldingSetNodeID & ID,ASTContext & Context,const TemplateArgument & ArgPack,Decl * AssociatedDecl,unsigned Index,bool Final)117 void SubstTemplateTemplateParmPackStorage::Profile(
118 llvm::FoldingSetNodeID &ID, ASTContext &Context,
119 const TemplateArgument &ArgPack, Decl *AssociatedDecl, unsigned Index,
120 bool Final) {
121 ArgPack.Profile(ID, Context);
122 ID.AddPointer(AssociatedDecl);
123 ID.AddInteger(Index);
124 ID.AddBoolean(Final);
125 }
126
IdentifierOrOverloadedOperator(const IdentifierInfo * II)127 IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(
128 const IdentifierInfo *II)
129 : PtrOrOp(reinterpret_cast<uintptr_t>(II)) {
130 static_assert(NUM_OVERLOADED_OPERATORS <= 4096,
131 "NUM_OVERLOADED_OPERATORS is too large");
132 assert(II);
133 assert(getIdentifier() == II);
134 }
IdentifierOrOverloadedOperator(OverloadedOperatorKind OOK)135 IdentifierOrOverloadedOperator::IdentifierOrOverloadedOperator(
136 OverloadedOperatorKind OOK)
137 : PtrOrOp(-uintptr_t(OOK)) {
138 assert(OOK != OO_None);
139 assert(getOperator() == OOK);
140 }
141
Profile(llvm::FoldingSetNodeID & ID) const142 void IdentifierOrOverloadedOperator::Profile(llvm::FoldingSetNodeID &ID) const {
143 if (auto *Identifier = getIdentifier()) {
144 ID.AddBoolean(false);
145 ID.AddPointer(Identifier);
146 } else {
147 ID.AddBoolean(true);
148 ID.AddInteger(getOperator());
149 }
150 }
151
TemplateName(void * Ptr)152 TemplateName::TemplateName(void *Ptr) {
153 Storage = StorageType::getFromOpaqueValue(Ptr);
154 }
155
TemplateName(TemplateDecl * Template)156 TemplateName::TemplateName(TemplateDecl *Template) : Storage(Template) {}
TemplateName(OverloadedTemplateStorage * Storage)157 TemplateName::TemplateName(OverloadedTemplateStorage *Storage)
158 : Storage(Storage) {}
TemplateName(AssumedTemplateStorage * Storage)159 TemplateName::TemplateName(AssumedTemplateStorage *Storage)
160 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmStorage * Storage)161 TemplateName::TemplateName(SubstTemplateTemplateParmStorage *Storage)
162 : Storage(Storage) {}
TemplateName(SubstTemplateTemplateParmPackStorage * Storage)163 TemplateName::TemplateName(SubstTemplateTemplateParmPackStorage *Storage)
164 : Storage(Storage) {}
TemplateName(QualifiedTemplateName * Qual)165 TemplateName::TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) {}
TemplateName(DependentTemplateName * Dep)166 TemplateName::TemplateName(DependentTemplateName *Dep) : Storage(Dep) {}
TemplateName(UsingShadowDecl * Using)167 TemplateName::TemplateName(UsingShadowDecl *Using) : Storage(Using) {}
TemplateName(DeducedTemplateStorage * Deduced)168 TemplateName::TemplateName(DeducedTemplateStorage *Deduced)
169 : Storage(Deduced) {}
170
isNull() const171 bool TemplateName::isNull() const { return Storage.isNull(); }
172
getKind() const173 TemplateName::NameKind TemplateName::getKind() const {
174 if (auto *ND = dyn_cast<Decl *>(Storage)) {
175 if (isa<UsingShadowDecl>(ND))
176 return UsingTemplate;
177 assert(isa<TemplateDecl>(ND));
178 return Template;
179 }
180
181 if (isa<DependentTemplateName *>(Storage))
182 return DependentTemplate;
183 if (isa<QualifiedTemplateName *>(Storage))
184 return QualifiedTemplate;
185
186 UncommonTemplateNameStorage *uncommon =
187 cast<UncommonTemplateNameStorage *>(Storage);
188 if (uncommon->getAsOverloadedStorage())
189 return OverloadedTemplate;
190 if (uncommon->getAsAssumedTemplateName())
191 return AssumedTemplate;
192 if (uncommon->getAsSubstTemplateTemplateParm())
193 return SubstTemplateTemplateParm;
194 if (uncommon->getAsDeducedTemplateName())
195 return DeducedTemplate;
196
197 assert(uncommon->getAsSubstTemplateTemplateParmPack() != nullptr);
198 return SubstTemplateTemplateParmPack;
199 }
200
getAsTemplateDecl(bool IgnoreDeduced) const201 TemplateDecl *TemplateName::getAsTemplateDecl(bool IgnoreDeduced) const {
202 TemplateName Name = *this;
203 while (std::optional<TemplateName> UnderlyingOrNone =
204 Name.desugar(IgnoreDeduced))
205 Name = *UnderlyingOrNone;
206
207 if (!IgnoreDeduced)
208 assert(Name.getAsDeducedTemplateName() == nullptr &&
209 "Unexpected canonical DeducedTemplateName; Did you mean to use "
210 "getTemplateDeclAndDefaultArgs instead?");
211
212 return cast_if_present<TemplateDecl>(
213 dyn_cast_if_present<Decl *>(Name.Storage));
214 }
215
216 std::pair<TemplateDecl *, DefaultArguments>
getTemplateDeclAndDefaultArgs() const217 TemplateName::getTemplateDeclAndDefaultArgs() const {
218 for (TemplateName Name = *this; /**/; /**/) {
219 if (Name.getKind() == TemplateName::DeducedTemplate) {
220 DeducedTemplateStorage *DTS = Name.getAsDeducedTemplateName();
221 TemplateDecl *TD =
222 DTS->getUnderlying().getAsTemplateDecl(/*IgnoreDeduced=*/true);
223 DefaultArguments DefArgs = DTS->getDefaultArguments();
224 if (TD && DefArgs)
225 assert(DefArgs.StartPos + DefArgs.Args.size() <=
226 TD->getTemplateParameters()->size());
227 return {TD, DTS->getDefaultArguments()};
228 }
229 if (std::optional<TemplateName> UnderlyingOrNone =
230 Name.desugar(/*IgnoreDeduced=*/false)) {
231 Name = *UnderlyingOrNone;
232 continue;
233 }
234 return {cast_if_present<TemplateDecl>(Name.Storage.dyn_cast<Decl *>()), {}};
235 }
236 }
237
desugar(bool IgnoreDeduced) const238 std::optional<TemplateName> TemplateName::desugar(bool IgnoreDeduced) const {
239 if (Decl *D = dyn_cast_if_present<Decl *>(Storage)) {
240 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
241 return TemplateName(USD->getTargetDecl());
242 return std::nullopt;
243 }
244 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
245 return QTN->getUnderlyingTemplate();
246 if (SubstTemplateTemplateParmStorage *S = getAsSubstTemplateTemplateParm())
247 return S->getReplacement();
248 if (IgnoreDeduced)
249 if (DeducedTemplateStorage *S = getAsDeducedTemplateName())
250 return S->getUnderlying();
251 return std::nullopt;
252 }
253
getAsOverloadedTemplate() const254 OverloadedTemplateStorage *TemplateName::getAsOverloadedTemplate() const {
255 if (UncommonTemplateNameStorage *Uncommon =
256 Storage.dyn_cast<UncommonTemplateNameStorage *>())
257 return Uncommon->getAsOverloadedStorage();
258
259 return nullptr;
260 }
261
getAsAssumedTemplateName() const262 AssumedTemplateStorage *TemplateName::getAsAssumedTemplateName() const {
263 if (UncommonTemplateNameStorage *Uncommon =
264 Storage.dyn_cast<UncommonTemplateNameStorage *>())
265 return Uncommon->getAsAssumedTemplateName();
266
267 return nullptr;
268 }
269
270 SubstTemplateTemplateParmStorage *
getAsSubstTemplateTemplateParm() const271 TemplateName::getAsSubstTemplateTemplateParm() const {
272 if (UncommonTemplateNameStorage *uncommon =
273 dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
274 return uncommon->getAsSubstTemplateTemplateParm();
275
276 return nullptr;
277 }
278
279 SubstTemplateTemplateParmPackStorage *
getAsSubstTemplateTemplateParmPack() const280 TemplateName::getAsSubstTemplateTemplateParmPack() const {
281 if (UncommonTemplateNameStorage *Uncommon =
282 Storage.dyn_cast<UncommonTemplateNameStorage *>())
283 return Uncommon->getAsSubstTemplateTemplateParmPack();
284
285 return nullptr;
286 }
287
getAsQualifiedTemplateName() const288 QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
289 return dyn_cast_if_present<QualifiedTemplateName *>(Storage);
290 }
291
getAsDependentTemplateName() const292 DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
293 return Storage.dyn_cast<DependentTemplateName *>();
294 }
295
getAsUsingShadowDecl() const296 UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
297 if (Decl *D = Storage.dyn_cast<Decl *>())
298 if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
299 return USD;
300 if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
301 return QTN->getUnderlyingTemplate().getAsUsingShadowDecl();
302 return nullptr;
303 }
304
DependentTemplateStorage(NestedNameSpecifier * Qualifier,IdentifierOrOverloadedOperator Name,bool HasTemplateKeyword)305 DependentTemplateStorage::DependentTemplateStorage(
306 NestedNameSpecifier *Qualifier, IdentifierOrOverloadedOperator Name,
307 bool HasTemplateKeyword)
308 : Qualifier(Qualifier, HasTemplateKeyword), Name(Name) {
309 assert((!Qualifier || Qualifier->isDependent()) &&
310 "Qualifier must be dependent");
311 }
312
getDependence() const313 TemplateNameDependence DependentTemplateStorage::getDependence() const {
314 auto D = TemplateNameDependence::DependentInstantiation;
315 if (NestedNameSpecifier *Qualifier = getQualifier())
316 D |= toTemplateNameDependence(Qualifier->getDependence());
317 return D;
318 }
319
print(raw_ostream & OS,const PrintingPolicy & Policy) const320 void DependentTemplateStorage::print(raw_ostream &OS,
321 const PrintingPolicy &Policy) const {
322 if (NestedNameSpecifier *NNS = getQualifier())
323 NNS->print(OS, Policy);
324
325 if (hasTemplateKeyword())
326 OS << "template ";
327
328 IdentifierOrOverloadedOperator Name = getName();
329 if (const IdentifierInfo *II = Name.getIdentifier())
330 OS << II->getName();
331 else
332 OS << "operator " << getOperatorSpelling(Name.getOperator());
333 }
334
getAsDeducedTemplateName() const335 DeducedTemplateStorage *TemplateName::getAsDeducedTemplateName() const {
336 if (UncommonTemplateNameStorage *Uncommon =
337 dyn_cast_if_present<UncommonTemplateNameStorage *>(Storage))
338 return Uncommon->getAsDeducedTemplateName();
339
340 return nullptr;
341 }
342
getDependence() const343 TemplateNameDependence TemplateName::getDependence() const {
344 switch (getKind()) {
345 case NameKind::Template:
346 case NameKind::UsingTemplate: {
347 TemplateDecl *Template = getAsTemplateDecl();
348 auto D = TemplateNameDependence::None;
349 if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) {
350 D |= TemplateNameDependence::DependentInstantiation;
351 if (TTP->isParameterPack())
352 D |= TemplateNameDependence::UnexpandedPack;
353 }
354 // FIXME: Hack, getDeclContext() can be null if Template is still
355 // initializing due to PCH reading, so we check it before using it.
356 // Should probably modify TemplateSpecializationType to allow constructing
357 // it without the isDependent() checking.
358 if (Template->getDeclContext() &&
359 Template->getDeclContext()->isDependentContext())
360 D |= TemplateNameDependence::DependentInstantiation;
361 return D;
362 }
363 case NameKind::QualifiedTemplate: {
364 QualifiedTemplateName *S = getAsQualifiedTemplateName();
365 TemplateNameDependence D = S->getUnderlyingTemplate().getDependence();
366 if (NestedNameSpecifier *NNS = S->getQualifier())
367 D |= toTemplateNameDependence(NNS->getDependence());
368 return D;
369 }
370 case NameKind::DependentTemplate: {
371 DependentTemplateName *S = getAsDependentTemplateName();
372 auto D = TemplateNameDependence::DependentInstantiation;
373 if (NestedNameSpecifier *Qualifier = S->getQualifier())
374 D |= toTemplateNameDependence(Qualifier->getDependence());
375 return D;
376 }
377 case NameKind::SubstTemplateTemplateParm: {
378 auto *S = getAsSubstTemplateTemplateParm();
379 return S->getReplacement().getDependence();
380 }
381 case NameKind::SubstTemplateTemplateParmPack:
382 return TemplateNameDependence::UnexpandedPack |
383 TemplateNameDependence::DependentInstantiation;
384 case NameKind::DeducedTemplate: {
385 DeducedTemplateStorage *DTS = getAsDeducedTemplateName();
386 TemplateNameDependence D = DTS->getUnderlying().getDependence();
387 for (const TemplateArgument &Arg : DTS->getDefaultArguments().Args)
388 D |= toTemplateNameDependence(Arg.getDependence());
389 return D;
390 }
391 case NameKind::AssumedTemplate:
392 return TemplateNameDependence::DependentInstantiation;
393 case NameKind::OverloadedTemplate:
394 llvm_unreachable("overloaded templates shouldn't survive to here.");
395 }
396 llvm_unreachable("Unknown TemplateName kind");
397 }
398
isDependent() const399 bool TemplateName::isDependent() const {
400 return getDependence() & TemplateNameDependence::Dependent;
401 }
402
isInstantiationDependent() const403 bool TemplateName::isInstantiationDependent() const {
404 return getDependence() & TemplateNameDependence::Instantiation;
405 }
406
containsUnexpandedParameterPack() const407 bool TemplateName::containsUnexpandedParameterPack() const {
408 return getDependence() & TemplateNameDependence::UnexpandedPack;
409 }
410
print(raw_ostream & OS,const PrintingPolicy & Policy,Qualified Qual) const411 void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
412 Qualified Qual) const {
413 auto handleAnonymousTTP = [&](TemplateDecl *TD, raw_ostream &OS) {
414 if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);
415 TTP && (Policy.PrintAsCanonical || TTP->getIdentifier() == nullptr)) {
416 OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
417 return true;
418 }
419 return false;
420 };
421 if (NameKind Kind = getKind();
422 Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
423 // After `namespace ns { using std::vector }`, what is the fully-qualified
424 // name of the UsingTemplateName `vector` within ns?
425 //
426 // - ns::vector (the qualified name of the using-shadow decl)
427 // - std::vector (the qualified name of the underlying template decl)
428 //
429 // Similar to the UsingType behavior, using declarations are used to import
430 // names more often than to export them, thus using the original name is
431 // most useful in this case.
432 TemplateDecl *Template = getAsTemplateDecl();
433 if (Policy.PrintAsCanonical)
434 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
435 if (handleAnonymousTTP(Template, OS))
436 return;
437 if (Qual == Qualified::None)
438 OS << *Template;
439 else
440 Template->printQualifiedName(OS, Policy);
441 } else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
442 if (Policy.PrintAsCanonical) {
443 QTN->getUnderlyingTemplate().print(OS, Policy, Qual);
444 return;
445 }
446 if (NestedNameSpecifier *NNS = QTN->getQualifier();
447 Qual != Qualified::None && NNS)
448 NNS->print(OS, Policy);
449 if (QTN->hasTemplateKeyword())
450 OS << "template ";
451
452 TemplateName Underlying = QTN->getUnderlyingTemplate();
453 assert(Underlying.getKind() == TemplateName::Template ||
454 Underlying.getKind() == TemplateName::UsingTemplate);
455
456 TemplateDecl *UTD = Underlying.getAsTemplateDecl();
457
458 if (handleAnonymousTTP(UTD, OS))
459 return;
460
461 if (IdentifierInfo *II = UTD->getIdentifier();
462 Policy.CleanUglifiedParameters && II &&
463 isa<TemplateTemplateParmDecl>(UTD))
464 OS << II->deuglifiedName();
465 else
466 OS << *UTD;
467 } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
468 DTN->print(OS, Policy);
469 } else if (SubstTemplateTemplateParmStorage *subst =
470 getAsSubstTemplateTemplateParm()) {
471 subst->getReplacement().print(OS, Policy, Qual);
472 } else if (SubstTemplateTemplateParmPackStorage *SubstPack =
473 getAsSubstTemplateTemplateParmPack())
474 OS << *SubstPack->getParameterPack();
475 else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
476 Assumed->getDeclName().print(OS, Policy);
477 } else if (DeducedTemplateStorage *Deduced = getAsDeducedTemplateName()) {
478 Deduced->getUnderlying().print(OS, Policy);
479 DefaultArguments DefArgs = Deduced->getDefaultArguments();
480 OS << ":" << DefArgs.StartPos;
481 printTemplateArgumentList(OS, DefArgs.Args, Policy);
482 } else {
483 assert(getKind() == TemplateName::OverloadedTemplate);
484 OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
485 (*OTS->begin())->printName(OS, Policy);
486 }
487 }
488
operator <<(const StreamingDiagnostic & DB,TemplateName N)489 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
490 TemplateName N) {
491 std::string NameStr;
492 llvm::raw_string_ostream OS(NameStr);
493 LangOptions LO;
494 LO.CPlusPlus = true;
495 LO.Bool = true;
496 OS << '\'';
497 N.print(OS, PrintingPolicy(LO));
498 OS << '\'';
499 return DB << NameStr;
500 }
501