1 //===- TemplateBase.cpp - Common template AST class implementation --------===//
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 implements common classes used throughout C++ template
10 // representations.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/AST/TemplateBase.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclBase.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/DependenceFlags.h"
20 #include "clang/AST/Expr.h"
21 #include "clang/AST/ExprCXX.h"
22 #include "clang/AST/PrettyPrinter.h"
23 #include "clang/AST/TemplateName.h"
24 #include "clang/AST/Type.h"
25 #include "clang/AST/TypeLoc.h"
26 #include "clang/Basic/Diagnostic.h"
27 #include "clang/Basic/LLVM.h"
28 #include "clang/Basic/LangOptions.h"
29 #include "clang/Basic/SourceLocation.h"
30 #include "llvm/ADT/APSInt.h"
31 #include "llvm/ADT/FoldingSet.h"
32 #include "llvm/ADT/None.h"
33 #include "llvm/ADT/SmallString.h"
34 #include "llvm/ADT/StringRef.h"
35 #include "llvm/Support/Casting.h"
36 #include "llvm/Support/Compiler.h"
37 #include "llvm/Support/ErrorHandling.h"
38 #include "llvm/Support/raw_ostream.h"
39 #include <cassert>
40 #include <cstddef>
41 #include <cstdint>
42 #include <cstring>
43
44 using namespace clang;
45
46 /// Print a template integral argument value.
47 ///
48 /// \param TemplArg the TemplateArgument instance to print.
49 ///
50 /// \param Out the raw_ostream instance to use for printing.
51 ///
52 /// \param Policy the printing policy for EnumConstantDecl printing.
53 ///
54 /// \param IncludeType If set, ensure that the type of the expression printed
55 /// matches the type of the template argument.
printIntegral(const TemplateArgument & TemplArg,raw_ostream & Out,const PrintingPolicy & Policy,bool IncludeType)56 static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out,
57 const PrintingPolicy &Policy, bool IncludeType) {
58 const Type *T = TemplArg.getIntegralType().getTypePtr();
59 const llvm::APSInt &Val = TemplArg.getAsIntegral();
60
61 if (const EnumType *ET = T->getAs<EnumType>()) {
62 for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) {
63 // In Sema::CheckTemplateArugment, enum template arguments value are
64 // extended to the size of the integer underlying the enum type. This
65 // may create a size difference between the enum value and template
66 // argument value, requiring isSameValue here instead of operator==.
67 if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) {
68 ECD->printQualifiedName(Out, Policy);
69 return;
70 }
71 }
72 }
73
74 if (Policy.MSVCFormatting)
75 IncludeType = false;
76
77 if (T->isBooleanType()) {
78 if (!Policy.MSVCFormatting)
79 Out << (Val.getBoolValue() ? "true" : "false");
80 else
81 Out << Val;
82 } else if (T->isCharType()) {
83 if (IncludeType) {
84 if (T->isSpecificBuiltinType(BuiltinType::SChar))
85 Out << "(signed char)";
86 else if (T->isSpecificBuiltinType(BuiltinType::UChar))
87 Out << "(unsigned char)";
88 }
89 CharacterLiteral::print(Val.getZExtValue(), CharacterLiteral::Ascii, Out);
90 } else if (T->isAnyCharacterType() && !Policy.MSVCFormatting) {
91 CharacterLiteral::CharacterKind Kind;
92 if (T->isWideCharType())
93 Kind = CharacterLiteral::Wide;
94 else if (T->isChar8Type())
95 Kind = CharacterLiteral::UTF8;
96 else if (T->isChar16Type())
97 Kind = CharacterLiteral::UTF16;
98 else if (T->isChar32Type())
99 Kind = CharacterLiteral::UTF32;
100 else
101 Kind = CharacterLiteral::Ascii;
102 CharacterLiteral::print(Val.getExtValue(), Kind, Out);
103 } else if (IncludeType) {
104 if (const auto *BT = T->getAs<BuiltinType>()) {
105 switch (BT->getKind()) {
106 case BuiltinType::ULongLong:
107 Out << Val << "ULL";
108 break;
109 case BuiltinType::LongLong:
110 Out << Val << "LL";
111 break;
112 case BuiltinType::ULong:
113 Out << Val << "UL";
114 break;
115 case BuiltinType::Long:
116 Out << Val << "L";
117 break;
118 case BuiltinType::UInt:
119 Out << Val << "U";
120 break;
121 case BuiltinType::Int:
122 Out << Val;
123 break;
124 default:
125 Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
126 << Val;
127 break;
128 }
129 } else
130 Out << "(" << T->getCanonicalTypeInternal().getAsString(Policy) << ")"
131 << Val;
132 } else
133 Out << Val;
134 }
135
getArrayDepth(QualType type)136 static unsigned getArrayDepth(QualType type) {
137 unsigned count = 0;
138 while (const auto *arrayType = type->getAsArrayTypeUnsafe()) {
139 count++;
140 type = arrayType->getElementType();
141 }
142 return count;
143 }
144
needsAmpersandOnTemplateArg(QualType paramType,QualType argType)145 static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) {
146 // Generally, if the parameter type is a pointer, we must be taking the
147 // address of something and need a &. However, if the argument is an array,
148 // this could be implicit via array-to-pointer decay.
149 if (!paramType->isPointerType())
150 return paramType->isMemberPointerType();
151 if (argType->isArrayType())
152 return getArrayDepth(argType) == getArrayDepth(paramType->getPointeeType());
153 return true;
154 }
155
156 //===----------------------------------------------------------------------===//
157 // TemplateArgument Implementation
158 //===----------------------------------------------------------------------===//
159
TemplateArgument(ASTContext & Ctx,const llvm::APSInt & Value,QualType Type)160 TemplateArgument::TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value,
161 QualType Type) {
162 Integer.Kind = Integral;
163 // Copy the APSInt value into our decomposed form.
164 Integer.BitWidth = Value.getBitWidth();
165 Integer.IsUnsigned = Value.isUnsigned();
166 // If the value is large, we have to get additional memory from the ASTContext
167 unsigned NumWords = Value.getNumWords();
168 if (NumWords > 1) {
169 void *Mem = Ctx.Allocate(NumWords * sizeof(uint64_t));
170 std::memcpy(Mem, Value.getRawData(), NumWords * sizeof(uint64_t));
171 Integer.pVal = static_cast<uint64_t *>(Mem);
172 } else {
173 Integer.VAL = Value.getZExtValue();
174 }
175
176 Integer.Type = Type.getAsOpaquePtr();
177 }
178
179 TemplateArgument
CreatePackCopy(ASTContext & Context,ArrayRef<TemplateArgument> Args)180 TemplateArgument::CreatePackCopy(ASTContext &Context,
181 ArrayRef<TemplateArgument> Args) {
182 if (Args.empty())
183 return getEmptyPack();
184
185 return TemplateArgument(Args.copy(Context));
186 }
187
getDependence() const188 TemplateArgumentDependence TemplateArgument::getDependence() const {
189 auto Deps = TemplateArgumentDependence::None;
190 switch (getKind()) {
191 case Null:
192 llvm_unreachable("Should not have a NULL template argument");
193
194 case Type:
195 Deps = toTemplateArgumentDependence(getAsType()->getDependence());
196 if (isa<PackExpansionType>(getAsType()))
197 Deps |= TemplateArgumentDependence::Dependent;
198 return Deps;
199
200 case Template:
201 return toTemplateArgumentDependence(getAsTemplate().getDependence());
202
203 case TemplateExpansion:
204 return TemplateArgumentDependence::Dependent |
205 TemplateArgumentDependence::Instantiation;
206
207 case Declaration: {
208 auto *DC = dyn_cast<DeclContext>(getAsDecl());
209 if (!DC)
210 DC = getAsDecl()->getDeclContext();
211 if (DC->isDependentContext())
212 Deps = TemplateArgumentDependence::Dependent |
213 TemplateArgumentDependence::Instantiation;
214 return Deps;
215 }
216
217 case NullPtr:
218 case Integral:
219 return TemplateArgumentDependence::None;
220
221 case Expression:
222 Deps = toTemplateArgumentDependence(getAsExpr()->getDependence());
223 if (isa<PackExpansionExpr>(getAsExpr()))
224 Deps |= TemplateArgumentDependence::Dependent |
225 TemplateArgumentDependence::Instantiation;
226 return Deps;
227
228 case Pack:
229 for (const auto &P : pack_elements())
230 Deps |= P.getDependence();
231 return Deps;
232 }
233 llvm_unreachable("unhandled ArgKind");
234 }
235
isDependent() const236 bool TemplateArgument::isDependent() const {
237 return getDependence() & TemplateArgumentDependence::Dependent;
238 }
239
isInstantiationDependent() const240 bool TemplateArgument::isInstantiationDependent() const {
241 return getDependence() & TemplateArgumentDependence::Instantiation;
242 }
243
isPackExpansion() const244 bool TemplateArgument::isPackExpansion() const {
245 switch (getKind()) {
246 case Null:
247 case Declaration:
248 case Integral:
249 case Pack:
250 case Template:
251 case NullPtr:
252 return false;
253
254 case TemplateExpansion:
255 return true;
256
257 case Type:
258 return isa<PackExpansionType>(getAsType());
259
260 case Expression:
261 return isa<PackExpansionExpr>(getAsExpr());
262 }
263
264 llvm_unreachable("Invalid TemplateArgument Kind!");
265 }
266
containsUnexpandedParameterPack() const267 bool TemplateArgument::containsUnexpandedParameterPack() const {
268 return getDependence() & TemplateArgumentDependence::UnexpandedPack;
269 }
270
getNumTemplateExpansions() const271 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const {
272 assert(getKind() == TemplateExpansion);
273 if (TemplateArg.NumExpansions)
274 return TemplateArg.NumExpansions - 1;
275
276 return None;
277 }
278
getNonTypeTemplateArgumentType() const279 QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
280 switch (getKind()) {
281 case TemplateArgument::Null:
282 case TemplateArgument::Type:
283 case TemplateArgument::Template:
284 case TemplateArgument::TemplateExpansion:
285 case TemplateArgument::Pack:
286 return QualType();
287
288 case TemplateArgument::Integral:
289 return getIntegralType();
290
291 case TemplateArgument::Expression:
292 return getAsExpr()->getType();
293
294 case TemplateArgument::Declaration:
295 return getParamTypeForDecl();
296
297 case TemplateArgument::NullPtr:
298 return getNullPtrType();
299 }
300
301 llvm_unreachable("Invalid TemplateArgument Kind!");
302 }
303
Profile(llvm::FoldingSetNodeID & ID,const ASTContext & Context) const304 void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
305 const ASTContext &Context) const {
306 ID.AddInteger(getKind());
307 switch (getKind()) {
308 case Null:
309 break;
310
311 case Type:
312 getAsType().Profile(ID);
313 break;
314
315 case NullPtr:
316 getNullPtrType().Profile(ID);
317 break;
318
319 case Declaration:
320 getParamTypeForDecl().Profile(ID);
321 ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : nullptr);
322 break;
323
324 case Template:
325 case TemplateExpansion: {
326 TemplateName Template = getAsTemplateOrTemplatePattern();
327 if (TemplateTemplateParmDecl *TTP
328 = dyn_cast_or_null<TemplateTemplateParmDecl>(
329 Template.getAsTemplateDecl())) {
330 ID.AddBoolean(true);
331 ID.AddInteger(TTP->getDepth());
332 ID.AddInteger(TTP->getPosition());
333 ID.AddBoolean(TTP->isParameterPack());
334 } else {
335 ID.AddBoolean(false);
336 ID.AddPointer(Context.getCanonicalTemplateName(Template)
337 .getAsVoidPointer());
338 }
339 break;
340 }
341
342 case Integral:
343 getAsIntegral().Profile(ID);
344 getIntegralType().Profile(ID);
345 break;
346
347 case Expression:
348 getAsExpr()->Profile(ID, Context, true);
349 break;
350
351 case Pack:
352 ID.AddInteger(Args.NumArgs);
353 for (unsigned I = 0; I != Args.NumArgs; ++I)
354 Args.Args[I].Profile(ID, Context);
355 }
356 }
357
structurallyEquals(const TemplateArgument & Other) const358 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
359 if (getKind() != Other.getKind()) return false;
360
361 switch (getKind()) {
362 case Null:
363 case Type:
364 case Expression:
365 case NullPtr:
366 return TypeOrValue.V == Other.TypeOrValue.V;
367
368 case Template:
369 case TemplateExpansion:
370 return TemplateArg.Name == Other.TemplateArg.Name &&
371 TemplateArg.NumExpansions == Other.TemplateArg.NumExpansions;
372
373 case Declaration:
374 return getAsDecl() == Other.getAsDecl();
375
376 case Integral:
377 return getIntegralType() == Other.getIntegralType() &&
378 getAsIntegral() == Other.getAsIntegral();
379
380 case Pack:
381 if (Args.NumArgs != Other.Args.NumArgs) return false;
382 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
383 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I]))
384 return false;
385 return true;
386 }
387
388 llvm_unreachable("Invalid TemplateArgument Kind!");
389 }
390
getPackExpansionPattern() const391 TemplateArgument TemplateArgument::getPackExpansionPattern() const {
392 assert(isPackExpansion());
393
394 switch (getKind()) {
395 case Type:
396 return getAsType()->castAs<PackExpansionType>()->getPattern();
397
398 case Expression:
399 return cast<PackExpansionExpr>(getAsExpr())->getPattern();
400
401 case TemplateExpansion:
402 return TemplateArgument(getAsTemplateOrTemplatePattern());
403
404 case Declaration:
405 case Integral:
406 case Pack:
407 case Null:
408 case Template:
409 case NullPtr:
410 return TemplateArgument();
411 }
412
413 llvm_unreachable("Invalid TemplateArgument Kind!");
414 }
415
print(const PrintingPolicy & Policy,raw_ostream & Out,bool IncludeType) const416 void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
417 bool IncludeType) const {
418
419 switch (getKind()) {
420 case Null:
421 Out << "(no value)";
422 break;
423
424 case Type: {
425 PrintingPolicy SubPolicy(Policy);
426 SubPolicy.SuppressStrongLifetime = true;
427 getAsType().print(Out, SubPolicy);
428 break;
429 }
430
431 case Declaration: {
432 // FIXME: Include the type if it's not obvious from the context.
433 NamedDecl *ND = getAsDecl();
434 if (getParamTypeForDecl()->isRecordType()) {
435 if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) {
436 TPO->printAsInit(Out);
437 break;
438 }
439 }
440 if (auto *VD = dyn_cast<ValueDecl>(ND)) {
441 if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType()))
442 Out << "&";
443 }
444 ND->printQualifiedName(Out);
445 break;
446 }
447
448 case NullPtr:
449 // FIXME: Include the type if it's not obvious from the context.
450 Out << "nullptr";
451 break;
452
453 case Template:
454 getAsTemplate().print(Out, Policy);
455 break;
456
457 case TemplateExpansion:
458 getAsTemplateOrTemplatePattern().print(Out, Policy);
459 Out << "...";
460 break;
461
462 case Integral:
463 printIntegral(*this, Out, Policy, IncludeType);
464 break;
465
466 case Expression:
467 getAsExpr()->printPretty(Out, nullptr, Policy);
468 break;
469
470 case Pack:
471 Out << "<";
472 bool First = true;
473 for (const auto &P : pack_elements()) {
474 if (First)
475 First = false;
476 else
477 Out << ", ";
478
479 P.print(Policy, Out, IncludeType);
480 }
481 Out << ">";
482 break;
483 }
484 }
485
dump(raw_ostream & Out) const486 void TemplateArgument::dump(raw_ostream &Out) const {
487 LangOptions LO; // FIXME! see also TemplateName::dump().
488 LO.CPlusPlus = true;
489 LO.Bool = true;
490 print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
491 }
492
dump() const493 LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }
494
495 //===----------------------------------------------------------------------===//
496 // TemplateArgumentLoc Implementation
497 //===----------------------------------------------------------------------===//
498
getSourceRange() const499 SourceRange TemplateArgumentLoc::getSourceRange() const {
500 switch (Argument.getKind()) {
501 case TemplateArgument::Expression:
502 return getSourceExpression()->getSourceRange();
503
504 case TemplateArgument::Declaration:
505 return getSourceDeclExpression()->getSourceRange();
506
507 case TemplateArgument::NullPtr:
508 return getSourceNullPtrExpression()->getSourceRange();
509
510 case TemplateArgument::Type:
511 if (TypeSourceInfo *TSI = getTypeSourceInfo())
512 return TSI->getTypeLoc().getSourceRange();
513 else
514 return SourceRange();
515
516 case TemplateArgument::Template:
517 if (getTemplateQualifierLoc())
518 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
519 getTemplateNameLoc());
520 return SourceRange(getTemplateNameLoc());
521
522 case TemplateArgument::TemplateExpansion:
523 if (getTemplateQualifierLoc())
524 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
525 getTemplateEllipsisLoc());
526 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
527
528 case TemplateArgument::Integral:
529 return getSourceIntegralExpression()->getSourceRange();
530
531 case TemplateArgument::Pack:
532 case TemplateArgument::Null:
533 return SourceRange();
534 }
535
536 llvm_unreachable("Invalid TemplateArgument Kind!");
537 }
538
539 template <typename T>
DiagTemplateArg(const T & DB,const TemplateArgument & Arg)540 static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
541 switch (Arg.getKind()) {
542 case TemplateArgument::Null:
543 // This is bad, but not as bad as crashing because of argument
544 // count mismatches.
545 return DB << "(null template argument)";
546
547 case TemplateArgument::Type:
548 return DB << Arg.getAsType();
549
550 case TemplateArgument::Declaration:
551 return DB << Arg.getAsDecl();
552
553 case TemplateArgument::NullPtr:
554 return DB << "nullptr";
555
556 case TemplateArgument::Integral:
557 return DB << Arg.getAsIntegral().toString(10);
558
559 case TemplateArgument::Template:
560 return DB << Arg.getAsTemplate();
561
562 case TemplateArgument::TemplateExpansion:
563 return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
564
565 case TemplateArgument::Expression: {
566 // This shouldn't actually ever happen, so it's okay that we're
567 // regurgitating an expression here.
568 // FIXME: We're guessing at LangOptions!
569 SmallString<32> Str;
570 llvm::raw_svector_ostream OS(Str);
571 LangOptions LangOpts;
572 LangOpts.CPlusPlus = true;
573 PrintingPolicy Policy(LangOpts);
574 Arg.getAsExpr()->printPretty(OS, nullptr, Policy);
575 return DB << OS.str();
576 }
577
578 case TemplateArgument::Pack: {
579 // FIXME: We're guessing at LangOptions!
580 SmallString<32> Str;
581 llvm::raw_svector_ostream OS(Str);
582 LangOptions LangOpts;
583 LangOpts.CPlusPlus = true;
584 PrintingPolicy Policy(LangOpts);
585 Arg.print(Policy, OS, /*IncludeType*/ true);
586 return DB << OS.str();
587 }
588 }
589
590 llvm_unreachable("Invalid TemplateArgument Kind!");
591 }
592
operator <<(const StreamingDiagnostic & DB,const TemplateArgument & Arg)593 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
594 const TemplateArgument &Arg) {
595 return DiagTemplateArg(DB, Arg);
596 }
597
TemplateArgumentLocInfo(ASTContext & Ctx,NestedNameSpecifierLoc QualifierLoc,SourceLocation TemplateNameLoc,SourceLocation EllipsisLoc)598 clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo(
599 ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
600 SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) {
601 TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo;
602 Template->Qualifier = QualifierLoc.getNestedNameSpecifier();
603 Template->QualifierLocData = QualifierLoc.getOpaqueData();
604 Template->TemplateNameLoc = TemplateNameLoc;
605 Template->EllipsisLoc = EllipsisLoc;
606 Pointer = Template;
607 }
608
609 const ASTTemplateArgumentListInfo *
Create(const ASTContext & C,const TemplateArgumentListInfo & List)610 ASTTemplateArgumentListInfo::Create(const ASTContext &C,
611 const TemplateArgumentListInfo &List) {
612 std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size());
613 void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo));
614 return new (Mem) ASTTemplateArgumentListInfo(List);
615 }
616
ASTTemplateArgumentListInfo(const TemplateArgumentListInfo & Info)617 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
618 const TemplateArgumentListInfo &Info) {
619 LAngleLoc = Info.getLAngleLoc();
620 RAngleLoc = Info.getRAngleLoc();
621 NumTemplateArgs = Info.size();
622
623 TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>();
624 for (unsigned i = 0; i != NumTemplateArgs; ++i)
625 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
626 }
627
initializeFrom(SourceLocation TemplateKWLoc,const TemplateArgumentListInfo & Info,TemplateArgumentLoc * OutArgArray)628 void ASTTemplateKWAndArgsInfo::initializeFrom(
629 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
630 TemplateArgumentLoc *OutArgArray) {
631 this->TemplateKWLoc = TemplateKWLoc;
632 LAngleLoc = Info.getLAngleLoc();
633 RAngleLoc = Info.getRAngleLoc();
634 NumTemplateArgs = Info.size();
635
636 for (unsigned i = 0; i != NumTemplateArgs; ++i)
637 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
638 }
639
initializeFrom(SourceLocation TemplateKWLoc)640 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
641 assert(TemplateKWLoc.isValid());
642 LAngleLoc = SourceLocation();
643 RAngleLoc = SourceLocation();
644 this->TemplateKWLoc = TemplateKWLoc;
645 NumTemplateArgs = 0;
646 }
647
initializeFrom(SourceLocation TemplateKWLoc,const TemplateArgumentListInfo & Info,TemplateArgumentLoc * OutArgArray,TemplateArgumentDependence & Deps)648 void ASTTemplateKWAndArgsInfo::initializeFrom(
649 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
650 TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) {
651 this->TemplateKWLoc = TemplateKWLoc;
652 LAngleLoc = Info.getLAngleLoc();
653 RAngleLoc = Info.getRAngleLoc();
654 NumTemplateArgs = Info.size();
655
656 for (unsigned i = 0; i != NumTemplateArgs; ++i) {
657 Deps |= Info[i].getArgument().getDependence();
658
659 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
660 }
661 }
662
copyInto(const TemplateArgumentLoc * ArgArray,TemplateArgumentListInfo & Info) const663 void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
664 TemplateArgumentListInfo &Info) const {
665 Info.setLAngleLoc(LAngleLoc);
666 Info.setRAngleLoc(RAngleLoc);
667 for (unsigned I = 0; I != NumTemplateArgs; ++I)
668 Info.addArgument(ArgArray[I]);
669 }
670