]> granicus.if.org Git - clang/blob - lib/AST/TemplateBase.cpp
NFC: Minor formatting fix
[clang] / lib / AST / TemplateBase.cpp
1 //===--- TemplateBase.cpp - Common template AST class implementation ------===//
2 //
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 implements common classes used throughout C++ template
11 // representations.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "clang/AST/TemplateBase.h"
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/DeclBase.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/ExprCXX.h"
21 #include "clang/AST/Type.h"
22 #include "clang/AST/TypeLoc.h"
23 #include "clang/Basic/Diagnostic.h"
24 #include "llvm/ADT/FoldingSet.h"
25 #include "llvm/ADT/SmallString.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include <algorithm>
28
29 using namespace clang;
30
31 /// \brief Print a template integral argument value.
32 ///
33 /// \param TemplArg the TemplateArgument instance to print.
34 ///
35 /// \param Out the raw_ostream instance to use for printing.
36 ///
37 /// \param Policy the printing policy for EnumConstantDecl printing.
38 static void printIntegral(const TemplateArgument &TemplArg,
39                           raw_ostream &Out, const PrintingPolicy& Policy) {
40   const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr();
41   const llvm::APSInt &Val = TemplArg.getAsIntegral();
42
43   if (const EnumType *ET = T->getAs<EnumType>()) {
44     for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) {
45       if (ECD->getInitVal() == Val) {
46         ECD->printQualifiedName(Out, Policy);
47         return;
48       }
49     }
50   }
51
52   if (T->isBooleanType()) {
53     Out << (Val.getBoolValue() ? "true" : "false");
54   } else if (T->isCharType()) {
55     const char Ch = Val.getZExtValue();
56     Out << ((Ch == '\'') ? "'\\" : "'");
57     Out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true);
58     Out << "'";
59   } else {
60     Out << Val;
61   }
62 }
63
64 //===----------------------------------------------------------------------===//
65 // TemplateArgument Implementation
66 //===----------------------------------------------------------------------===//
67
68 TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
69                                    QualType Type) {
70   Integer.Kind = Integral;
71   // Copy the APSInt value into our decomposed form.
72   Integer.BitWidth = Value.getBitWidth();
73   Integer.IsUnsigned = Value.isUnsigned();
74   // If the value is large, we have to get additional memory from the ASTContext
75   unsigned NumWords = Value.getNumWords();
76   if (NumWords > 1) {
77     void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t));
78     std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t));
79     Integer.pVal = static_cast<uint64_t *>(Mem);
80   } else {
81     Integer.VAL = Value.getZExtValue();
82   }
83
84   Integer.Type = Type.getAsOpaquePtr();
85 }
86
87 TemplateArgument TemplateArgument::CreatePackCopy(ASTContext &Context,
88                                                   const TemplateArgument *Args,
89                                                   unsigned NumArgs) {
90   if (NumArgs == 0)
91     return getEmptyPack();
92   
93   TemplateArgument *Storage = new (Context) TemplateArgument [NumArgs];
94   std::copy(Args, Args + NumArgs, Storage);
95   return TemplateArgument(Storage, NumArgs);
96 }
97
98 bool TemplateArgument::isDependent() const {
99   switch (getKind()) {
100   case Null:
101     llvm_unreachable("Should not have a NULL template argument");
102
103   case Type:
104     return getAsType()->isDependentType() ||
105            isa<PackExpansionType>(getAsType());
106
107   case Template:
108     return getAsTemplate().isDependent();
109
110   case TemplateExpansion:
111     return true;
112
113   case Declaration:
114     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
115       return DC->isDependentContext();
116     return getAsDecl()->getDeclContext()->isDependentContext();
117
118   case NullPtr:
119     return false;
120
121   case Integral:
122     // Never dependent
123     return false;
124
125   case Expression:
126     return (getAsExpr()->isTypeDependent() || getAsExpr()->isValueDependent() ||
127             isa<PackExpansionExpr>(getAsExpr()));
128
129   case Pack:
130     for (const auto &P : pack_elements())
131       if (P.isDependent())
132         return true;
133     return false;
134   }
135
136   llvm_unreachable("Invalid TemplateArgument Kind!");
137 }
138
139 bool TemplateArgument::isInstantiationDependent() const {
140   switch (getKind()) {
141   case Null:
142     llvm_unreachable("Should not have a NULL template argument");
143     
144   case Type:
145     return getAsType()->isInstantiationDependentType();
146     
147   case Template:
148     return getAsTemplate().isInstantiationDependent();
149     
150   case TemplateExpansion:
151     return true;
152     
153   case Declaration:
154     if (DeclContext *DC = dyn_cast<DeclContext>(getAsDecl()))
155       return DC->isDependentContext();
156     return getAsDecl()->getDeclContext()->isDependentContext();
157
158   case NullPtr:
159     return false;
160       
161   case Integral:
162     // Never dependent
163     return false;
164     
165   case Expression:
166     return getAsExpr()->isInstantiationDependent();
167     
168   case Pack:
169     for (const auto &P : pack_elements())
170       if (P.isInstantiationDependent())
171         return true;
172     return false;
173   }
174
175   llvm_unreachable("Invalid TemplateArgument Kind!");
176 }
177
178 bool TemplateArgument::isPackExpansion() const {
179   switch (getKind()) {
180   case Null:
181   case Declaration:
182   case Integral:
183   case Pack:    
184   case Template:
185   case NullPtr:
186     return false;
187       
188   case TemplateExpansion:
189     return true;
190       
191   case Type:
192     return isa<PackExpansionType>(getAsType());
193           
194   case Expression:
195     return isa<PackExpansionExpr>(getAsExpr());
196   }
197
198   llvm_unreachable("Invalid TemplateArgument Kind!");
199 }
200
201 bool TemplateArgument::containsUnexpandedParameterPack() const {
202   switch (getKind()) {
203   case Null:
204   case Declaration:
205   case Integral:
206   case TemplateExpansion:
207   case NullPtr:
208     break;
209
210   case Type:
211     if (getAsType()->containsUnexpandedParameterPack())
212       return true;
213     break;
214
215   case Template:
216     if (getAsTemplate().containsUnexpandedParameterPack())
217       return true;
218     break;
219         
220   case Expression:
221     if (getAsExpr()->containsUnexpandedParameterPack())
222       return true;
223     break;
224
225   case Pack:
226     for (const auto &P : pack_elements())
227       if (P.containsUnexpandedParameterPack())
228         return true;
229
230     break;
231   }
232
233   return false;
234 }
235
236 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
237   assert(getKind() == TemplateExpansion);
238   if (TemplateArg.NumExpansions)
239     return TemplateArg.NumExpansions - 1;
240   
241   return None; 
242 }
243
244 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
245                                const ASTContext &Context) const {
246   ID.AddInteger(getKind());
247   switch (getKind()) {
248   case Null:
249     break;
250
251   case Type:
252     getAsType().Profile(ID);
253     break;
254
255   case NullPtr:
256     getNullPtrType().Profile(ID);
257     break;
258
259   case Declaration:
260     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
261     break;
262
263   case Template:
264   case TemplateExpansion: {
265     TemplateName Template = getAsTemplateOrTemplatePattern();
266     if (TemplateTemplateParmDecl *TTP
267           = dyn_cast_or_null<TemplateTemplateParmDecl>(
268                                                 Template.getAsTemplateDecl())) {
269       ID.AddBoolean(true);
270       ID.AddInteger(TTP->getDepth());
271       ID.AddInteger(TTP->getPosition());
272       ID.AddBoolean(TTP->isParameterPack());
273     } else {
274       ID.AddBoolean(false);
275       ID.AddPointer(Context.getCanonicalTemplateName(Template)
276                                                           .getAsVoidPointer());
277     }
278     break;
279   }
280       
281   case Integral:
282     getAsIntegral().Profile(ID);
283     getIntegralType().Profile(ID);
284     break;
285
286   case Expression:
287     getAsExpr()->Profile(ID, Context, true);
288     break;
289
290   case Pack:
291     ID.AddInteger(Args.NumArgs);
292     for (unsigned I = 0; I != Args.NumArgs; ++I)
293       Args.Args[I].Profile(ID, Context);
294   }
295 }
296
297 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
298   if (getKind() != Other.getKind()) return false;
299
300   switch (getKind()) {
301   case Null:
302   case Type:
303   case Expression:      
304   case Template:
305   case TemplateExpansion:
306   case NullPtr:
307     return TypeOrValue.V == Other.TypeOrValue.V;
308
309   case Declaration:
310     return getAsDecl() == Other.getAsDecl();
311
312   case Integral:
313     return getIntegralType() == Other.getIntegralType() &&
314            getAsIntegral() == Other.getAsIntegral();
315
316   case Pack:
317     if (Args.NumArgs != Other.Args.NumArgs) return false;
318     for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
319       if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
320         return false;
321     return true;
322   }
323
324   llvm_unreachable("Invalid TemplateArgument Kind!");
325 }
326
327 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
328   assert(isPackExpansion());
329   
330   switch (getKind()) {
331   case Type:
332     return getAsType()->getAs<PackExpansionType>()->getPattern();
333     
334   case Expression:
335     return cast<PackExpansionExpr>(getAsExpr())->getPattern();
336     
337   case TemplateExpansion:
338     return TemplateArgument(getAsTemplateOrTemplatePattern());
339
340   case Declaration:
341   case Integral:
342   case Pack:
343   case Null:
344   case Template:
345   case NullPtr:
346     return TemplateArgument();
347   }
348
349   llvm_unreachable("Invalid TemplateArgument Kind!");
350 }
351
352 void TemplateArgument::print(const PrintingPolicy &Policy, 
353                              raw_ostream &Out) const {
354   switch (getKind()) {
355   case Null:
356     Out << "(no value)";
357     break;
358     
359   case Type: {
360     PrintingPolicy SubPolicy(Policy);
361     SubPolicy.SuppressStrongLifetime = true;
362     getAsType().print(Out, SubPolicy);
363     break;
364   }
365     
366   case Declaration: {
367     NamedDecl *ND = cast<NamedDecl>(getAsDecl());
368     Out << '&';
369     if (ND->getDeclName()) {
370       // FIXME: distinguish between pointer and reference args?
371       ND->printQualifiedName(Out);
372     } else {
373       Out << "(anonymous)";
374     }
375     break;
376   }
377
378   case NullPtr:
379     Out << "nullptr";
380     break;
381
382   case Template:
383     getAsTemplate().print(Out, Policy);
384     break;
385
386   case TemplateExpansion:
387     getAsTemplateOrTemplatePattern().print(Out, Policy);
388     Out << "...";
389     break;
390       
391   case Integral: {
392     printIntegral(*this, Out, Policy);
393     break;
394   }
395     
396   case Expression:
397     getAsExpr()->printPretty(Out, nullptr, Policy);
398     break;
399     
400   case Pack:
401     Out << "<";
402     bool First = true;
403     for (const auto &P : pack_elements()) {
404       if (First)
405         First = false;
406       else
407         Out << ", ";
408       
409       P.print(Policy, Out);
410     }
411     Out << ">";
412     break;        
413   }
414 }
415
416 //===----------------------------------------------------------------------===//
417 // TemplateArgumentLoc Implementation
418 //===----------------------------------------------------------------------===//
419
420 TemplateArgumentLocInfo::TemplateArgumentLocInfo() {
421   memset((void*)this, 0, sizeof(TemplateArgumentLocInfo));
422 }
423
424 SourceRange TemplateArgumentLoc::getSourceRange() const {
425   switch (Argument.getKind()) {
426   case TemplateArgument::Expression:
427     return getSourceExpression()->getSourceRange();
428
429   case TemplateArgument::Declaration:
430     return getSourceDeclExpression()->getSourceRange();
431
432   case TemplateArgument::NullPtr:
433     return getSourceNullPtrExpression()->getSourceRange();
434
435   case TemplateArgument::Type:
436     if (TypeSourceInfo *TSI = getTypeSourceInfo())
437       return TSI->getTypeLoc().getSourceRange();
438     else
439       return SourceRange();
440
441   case TemplateArgument::Template:
442     if (getTemplateQualifierLoc())
443       return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 
444                          getTemplateNameLoc());
445     return SourceRange(getTemplateNameLoc());
446
447   case TemplateArgument::TemplateExpansion:
448     if (getTemplateQualifierLoc())
449       return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 
450                          getTemplateEllipsisLoc());
451     return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
452
453   case TemplateArgument::Integral:
454     return getSourceIntegralExpression()->getSourceRange();
455
456   case TemplateArgument::Pack:
457   case TemplateArgument::Null:
458     return SourceRange();
459   }
460
461   llvm_unreachable("Invalid TemplateArgument Kind!");
462 }
463
464 const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB,
465                                            const TemplateArgument &Arg) {
466   switch (Arg.getKind()) {
467   case TemplateArgument::Null:
468     // This is bad, but not as bad as crashing because of argument
469     // count mismatches.
470     return DB << "(null template argument)";
471       
472   case TemplateArgument::Type:
473     return DB << Arg.getAsType();
474       
475   case TemplateArgument::Declaration:
476     return DB << Arg.getAsDecl();
477
478   case TemplateArgument::NullPtr:
479     return DB << "nullptr";
480       
481   case TemplateArgument::Integral:
482     return DB << Arg.getAsIntegral().toString(10);
483       
484   case TemplateArgument::Template:
485     return DB << Arg.getAsTemplate();
486
487   case TemplateArgument::TemplateExpansion:
488     return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
489
490   case TemplateArgument::Expression: {
491     // This shouldn't actually ever happen, so it's okay that we're
492     // regurgitating an expression here.
493     // FIXME: We're guessing at LangOptions!
494     SmallString<32> Str;
495     llvm::raw_svector_ostream OS(Str);
496     LangOptions LangOpts;
497     LangOpts.CPlusPlus = true;
498     PrintingPolicy Policy(LangOpts);
499     Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
500     return DB << OS.str();
501   }
502       
503   case TemplateArgument::Pack: {
504     // FIXME: We're guessing at LangOptions!
505     SmallString<32> Str;
506     llvm::raw_svector_ostream OS(Str);
507     LangOptions LangOpts;
508     LangOpts.CPlusPlus = true;
509     PrintingPolicy Policy(LangOpts);
510     Arg.print(Policy, OS);
511     return DB << OS.str();
512   }
513   }
514
515   llvm_unreachable("Invalid TemplateArgument Kind!");
516 }
517
518 const ASTTemplateArgumentListInfo *
519 ASTTemplateArgumentListInfo::Create(ASTContext &C,
520                                     const TemplateArgumentListInfo &List) {
521   assert(llvm::alignOf<ASTTemplateArgumentListInfo>() >=
522          llvm::alignOf<TemplateArgumentLoc>());
523   std::size_t size = ASTTemplateArgumentListInfo::sizeFor(List.size());
524   void *Mem = C.Allocate(size, llvm::alignOf<ASTTemplateArgumentListInfo>());
525   ASTTemplateArgumentListInfo *TAI = new (Mem) ASTTemplateArgumentListInfo();
526   TAI->initializeFrom(List);
527   return TAI;
528 }
529
530 void ASTTemplateArgumentListInfo::initializeFrom(
531                                       const TemplateArgumentListInfo &Info) {
532   LAngleLoc = Info.getLAngleLoc();
533   RAngleLoc = Info.getRAngleLoc();
534   NumTemplateArgs = Info.size();
535
536   TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
537   for (unsigned i = 0; i != NumTemplateArgs; ++i)
538     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
539 }
540
541 void ASTTemplateArgumentListInfo::initializeFrom(
542                                           const TemplateArgumentListInfo &Info,
543                                                   bool &Dependent, 
544                                                   bool &InstantiationDependent,
545                                        bool &ContainsUnexpandedParameterPack) {
546   LAngleLoc = Info.getLAngleLoc();
547   RAngleLoc = Info.getRAngleLoc();
548   NumTemplateArgs = Info.size();
549
550   TemplateArgumentLoc *ArgBuffer = getTemplateArgs();
551   for (unsigned i = 0; i != NumTemplateArgs; ++i) {
552     Dependent = Dependent || Info[i].getArgument().isDependent();
553     InstantiationDependent = InstantiationDependent || 
554                              Info[i].getArgument().isInstantiationDependent();
555     ContainsUnexpandedParameterPack 
556       = ContainsUnexpandedParameterPack || 
557         Info[i].getArgument().containsUnexpandedParameterPack();
558
559     new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
560   }
561 }
562
563 void ASTTemplateArgumentListInfo::copyInto(
564                                       TemplateArgumentListInfo &Info) const {
565   Info.setLAngleLoc(LAngleLoc);
566   Info.setRAngleLoc(RAngleLoc);
567   for (unsigned I = 0; I != NumTemplateArgs; ++I)
568     Info.addArgument(getTemplateArgs()[I]);
569 }
570
571 std::size_t ASTTemplateArgumentListInfo::sizeFor(unsigned NumTemplateArgs) {
572   return sizeof(ASTTemplateArgumentListInfo) +
573          sizeof(TemplateArgumentLoc) * NumTemplateArgs;
574 }
575
576 void
577 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc,
578                                          const TemplateArgumentListInfo &Info) {
579   Base::initializeFrom(Info);
580   setTemplateKeywordLoc(TemplateKWLoc);
581 }
582
583 void
584 ASTTemplateKWAndArgsInfo
585 ::initializeFrom(SourceLocation TemplateKWLoc,
586                  const TemplateArgumentListInfo &Info,
587                  bool &Dependent,
588                  bool &InstantiationDependent,
589                  bool &ContainsUnexpandedParameterPack) {
590   Base::initializeFrom(Info, Dependent, InstantiationDependent,
591                        ContainsUnexpandedParameterPack);
592   setTemplateKeywordLoc(TemplateKWLoc);
593 }
594
595 void
596 ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
597   // No explicit template arguments, but template keyword loc is valid.
598   assert(TemplateKWLoc.isValid());
599   LAngleLoc = SourceLocation();
600   RAngleLoc = SourceLocation();
601   NumTemplateArgs = 0;
602   setTemplateKeywordLoc(TemplateKWLoc);
603 }
604
605 std::size_t
606 ASTTemplateKWAndArgsInfo::sizeFor(unsigned NumTemplateArgs) {
607   // Add space for the template keyword location.
608   // FIXME: There's room for this in the padding before the template args in
609   //        64-bit builds.
610   return Base::sizeFor(NumTemplateArgs) + sizeof(SourceLocation);
611 }