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/StringExtras.h"
33#include "llvm/Support/Compiler.h"
34#include "llvm/Support/ErrorHandling.h"
35#include "llvm/Support/raw_ostream.h"
36#include <cassert>
37#include <cstddef>
38#include <cstdint>
39#include <cstring>
40
41using namespace clang;
42
43/// Print a template integral argument value.
44///
45/// \param TemplArg the TemplateArgument instance to print.
46///
47/// \param Out the raw_ostream instance to use for printing.
48///
49/// \param Policy the printing policy for EnumConstantDecl printing.
50///
51/// \param IncludeType If set, ensure that the type of the expression printed
52/// matches the type of the template argument.
53static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out,
54 const PrintingPolicy &Policy, bool IncludeType) {
55 const Type *T = TemplArg.getIntegralType().getTypePtr();
56 const llvm::APSInt &Val = TemplArg.getAsIntegral();
57
58 if (Policy.UseEnumerators) {
59 if (const EnumType *ET = T->getAs<EnumType>()) {
60 for (const EnumConstantDecl *ECD : ET->getDecl()->enumerators()) {
61 // In Sema::CheckTemplateArugment, enum template arguments value are
62 // extended to the size of the integer underlying the enum type. This
63 // may create a size difference between the enum value and template
64 // argument value, requiring isSameValue here instead of operator==.
65 if (llvm::APSInt::isSameValue(I1: ECD->getInitVal(), I2: Val)) {
66 ECD->printQualifiedName(Out, Policy);
67 return;
68 }
69 }
70 }
71 }
72
73 if (Policy.MSVCFormatting)
74 IncludeType = false;
75
76 if (T->isBooleanType()) {
77 if (!Policy.MSVCFormatting)
78 Out << (Val.getBoolValue() ? "true" : "false");
79 else
80 Out << Val;
81 } else if (T->isCharType()) {
82 if (IncludeType) {
83 if (T->isSpecificBuiltinType(K: BuiltinType::SChar))
84 Out << "(signed char)";
85 else if (T->isSpecificBuiltinType(K: BuiltinType::UChar))
86 Out << "(unsigned char)";
87 }
88 CharacterLiteral::print(val: Val.getZExtValue(), Kind: CharacterLiteralKind::Ascii,
89 OS&: Out);
90 } else if (T->isAnyCharacterType() && !Policy.MSVCFormatting) {
91 CharacterLiteralKind Kind;
92 if (T->isWideCharType())
93 Kind = CharacterLiteralKind::Wide;
94 else if (T->isChar8Type())
95 Kind = CharacterLiteralKind::UTF8;
96 else if (T->isChar16Type())
97 Kind = CharacterLiteralKind::UTF16;
98 else if (T->isChar32Type())
99 Kind = CharacterLiteralKind::UTF32;
100 else
101 Kind = CharacterLiteralKind::Ascii;
102 CharacterLiteral::print(val: Val.getExtValue(), Kind, OS&: 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
136static 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
145static 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(type: argType) == getArrayDepth(type: paramType->getPointeeType());
153 return true;
154}
155
156//===----------------------------------------------------------------------===//
157// TemplateArgument Implementation
158//===----------------------------------------------------------------------===//
159
160void TemplateArgument::initFromType(QualType T, bool IsNullPtr,
161 bool IsDefaulted) {
162 TypeOrValue.Kind = IsNullPtr ? NullPtr : Type;
163 TypeOrValue.IsDefaulted = IsDefaulted;
164 TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
165}
166
167void TemplateArgument::initFromDeclaration(ValueDecl *D, QualType QT,
168 bool IsDefaulted) {
169 assert(D && "Expected decl");
170 DeclArg.Kind = Declaration;
171 DeclArg.IsDefaulted = IsDefaulted;
172 DeclArg.QT = QT.getAsOpaquePtr();
173 DeclArg.D = D;
174}
175
176void TemplateArgument::initFromIntegral(const ASTContext &Ctx,
177 const llvm::APSInt &Value,
178 QualType Type, bool IsDefaulted) {
179 Integer.Kind = Integral;
180 Integer.IsDefaulted = IsDefaulted;
181 // Copy the APSInt value into our decomposed form.
182 Integer.BitWidth = Value.getBitWidth();
183 Integer.IsUnsigned = Value.isUnsigned();
184 // If the value is large, we have to get additional memory from the ASTContext
185 unsigned NumWords = Value.getNumWords();
186 if (NumWords > 1) {
187 void *Mem = Ctx.Allocate(Size: NumWords * sizeof(uint64_t));
188 std::memcpy(dest: Mem, src: Value.getRawData(), n: NumWords * sizeof(uint64_t));
189 Integer.pVal = static_cast<uint64_t *>(Mem);
190 } else {
191 Integer.VAL = Value.getZExtValue();
192 }
193
194 Integer.Type = Type.getAsOpaquePtr();
195}
196
197void TemplateArgument::initFromStructural(const ASTContext &Ctx, QualType Type,
198 const APValue &V, bool IsDefaulted) {
199 Value.Kind = StructuralValue;
200 Value.IsDefaulted = IsDefaulted;
201 Value.Value = new (Ctx) APValue(V);
202 Ctx.addDestruction(Ptr: Value.Value);
203 Value.Type = Type.getAsOpaquePtr();
204}
205
206TemplateArgument::TemplateArgument(const ASTContext &Ctx,
207 const llvm::APSInt &Value, QualType Type,
208 bool IsDefaulted) {
209 initFromIntegral(Ctx, Value, Type, IsDefaulted);
210}
211
212static const ValueDecl *getAsSimpleValueDeclRef(const ASTContext &Ctx,
213 QualType T, const APValue &V) {
214 // Pointers to members are relatively easy.
215 if (V.isMemberPointer() && V.getMemberPointerPath().empty())
216 return V.getMemberPointerDecl();
217
218 // We model class non-type template parameters as their template parameter
219 // object declaration.
220 if (V.isStruct() || V.isUnion()) {
221 // Dependent types are not supposed to be described as
222 // TemplateParamObjectDecls.
223 if (T->isDependentType() || T->isInstantiationDependentType())
224 return nullptr;
225 return Ctx.getTemplateParamObjectDecl(T, V);
226 }
227
228 // Pointers and references with an empty path use the special 'Declaration'
229 // representation.
230 if (V.isLValue() && V.hasLValuePath() && V.getLValuePath().empty() &&
231 !V.isLValueOnePastTheEnd())
232 return V.getLValueBase().dyn_cast<const ValueDecl *>();
233
234 // Everything else uses the 'structural' representation.
235 return nullptr;
236}
237
238TemplateArgument::TemplateArgument(const ASTContext &Ctx, QualType Type,
239 const APValue &V, bool IsDefaulted) {
240 if (Type->isIntegralOrEnumerationType() && V.isInt())
241 initFromIntegral(Ctx, Value: V.getInt(), Type, IsDefaulted);
242 else if ((V.isLValue() && V.isNullPointer()) ||
243 (V.isMemberPointer() && !V.getMemberPointerDecl()))
244 initFromType(T: Type, /*isNullPtr=*/IsNullPtr: true, IsDefaulted);
245 else if (const ValueDecl *VD = getAsSimpleValueDeclRef(Ctx, T: Type, V))
246 // FIXME: The Declaration form should expose a const ValueDecl*.
247 initFromDeclaration(D: const_cast<ValueDecl *>(VD), QT: Type, IsDefaulted);
248 else
249 initFromStructural(Ctx, Type, V, IsDefaulted);
250}
251
252TemplateArgument
253TemplateArgument::CreatePackCopy(ASTContext &Context,
254 ArrayRef<TemplateArgument> Args) {
255 if (Args.empty())
256 return getEmptyPack();
257
258 return TemplateArgument(Args.copy(A&: Context));
259}
260
261TemplateArgumentDependence TemplateArgument::getDependence() const {
262 auto Deps = TemplateArgumentDependence::None;
263 switch (getKind()) {
264 case Null:
265 llvm_unreachable("Should not have a NULL template argument");
266
267 case Type:
268 Deps = toTemplateArgumentDependence(D: getAsType()->getDependence());
269 if (isa<PackExpansionType>(Val: getAsType()))
270 Deps |= TemplateArgumentDependence::Dependent;
271 return Deps;
272
273 case Template:
274 return toTemplateArgumentDependence(D: getAsTemplate().getDependence());
275
276 case TemplateExpansion:
277 return TemplateArgumentDependence::Dependent |
278 TemplateArgumentDependence::Instantiation;
279
280 case Declaration: {
281 auto *DC = dyn_cast<DeclContext>(Val: getAsDecl());
282 if (!DC)
283 DC = getAsDecl()->getDeclContext();
284 if (DC->isDependentContext())
285 Deps = TemplateArgumentDependence::Dependent |
286 TemplateArgumentDependence::Instantiation;
287 return Deps;
288 }
289
290 case NullPtr:
291 case Integral:
292 case StructuralValue:
293 return TemplateArgumentDependence::None;
294
295 case Expression:
296 Deps = toTemplateArgumentDependence(D: getAsExpr()->getDependence());
297 if (isa<PackExpansionExpr>(Val: getAsExpr()))
298 Deps |= TemplateArgumentDependence::Dependent |
299 TemplateArgumentDependence::Instantiation;
300 return Deps;
301
302 case Pack:
303 for (const auto &P : pack_elements())
304 Deps |= P.getDependence();
305 return Deps;
306 }
307 llvm_unreachable("unhandled ArgKind");
308}
309
310bool TemplateArgument::isDependent() const {
311 return getDependence() & TemplateArgumentDependence::Dependent;
312}
313
314bool TemplateArgument::isInstantiationDependent() const {
315 return getDependence() & TemplateArgumentDependence::Instantiation;
316}
317
318bool TemplateArgument::isPackExpansion() const {
319 switch (getKind()) {
320 case Null:
321 case Declaration:
322 case Integral:
323 case StructuralValue:
324 case Pack:
325 case Template:
326 case NullPtr:
327 return false;
328
329 case TemplateExpansion:
330 return true;
331
332 case Type:
333 return isa<PackExpansionType>(Val: getAsType());
334
335 case Expression:
336 return isa<PackExpansionExpr>(Val: getAsExpr());
337 }
338
339 llvm_unreachable("Invalid TemplateArgument Kind!");
340}
341
342bool TemplateArgument::containsUnexpandedParameterPack() const {
343 return getDependence() & TemplateArgumentDependence::UnexpandedPack;
344}
345
346UnsignedOrNone TemplateArgument::getNumTemplateExpansions() const {
347 assert(getKind() == TemplateExpansion);
348 return TemplateArg.NumExpansions;
349}
350
351QualType TemplateArgument::getNonTypeTemplateArgumentType() const {
352 switch (getKind()) {
353 case TemplateArgument::Null:
354 case TemplateArgument::Type:
355 case TemplateArgument::Template:
356 case TemplateArgument::TemplateExpansion:
357 case TemplateArgument::Pack:
358 return QualType();
359
360 case TemplateArgument::Integral:
361 return getIntegralType();
362
363 case TemplateArgument::Expression:
364 return getAsExpr()->getType();
365
366 case TemplateArgument::Declaration:
367 return getParamTypeForDecl();
368
369 case TemplateArgument::NullPtr:
370 return getNullPtrType();
371
372 case TemplateArgument::StructuralValue:
373 return getStructuralValueType();
374 }
375
376 llvm_unreachable("Invalid TemplateArgument Kind!");
377}
378
379void TemplateArgument::Profile(llvm::FoldingSetNodeID &ID,
380 const ASTContext &Context) const {
381 ID.AddInteger(I: getKind());
382 switch (getKind()) {
383 case Null:
384 break;
385
386 case Type:
387 getAsType().Profile(ID);
388 break;
389
390 case NullPtr:
391 getNullPtrType().Profile(ID);
392 break;
393
394 case Declaration:
395 getParamTypeForDecl().Profile(ID);
396 ID.AddPointer(Ptr: getAsDecl());
397 break;
398
399 case TemplateExpansion:
400 ID.AddInteger(I: TemplateArg.NumExpansions.toInternalRepresentation());
401 [[fallthrough]];
402 case Template:
403 ID.AddPointer(Ptr: TemplateArg.Name);
404 break;
405
406 case Integral:
407 getIntegralType().Profile(ID);
408 getAsIntegral().Profile(ID);
409 break;
410
411 case StructuralValue:
412 getStructuralValueType().Profile(ID);
413 getAsStructuralValue().Profile(ID);
414 break;
415
416 case Expression: {
417 const Expr *E = getAsExpr();
418 bool IsCanonical = isCanonicalExpr();
419 ID.AddBoolean(B: IsCanonical);
420 if (IsCanonical)
421 E->Profile(ID, Context, true);
422 else
423 ID.AddPointer(Ptr: E);
424 break;
425 }
426
427 case Pack:
428 ID.AddInteger(I: Args.NumArgs);
429 for (unsigned I = 0; I != Args.NumArgs; ++I)
430 Args.Args[I].Profile(ID, Context);
431 }
432}
433
434bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
435 if (getKind() != Other.getKind()) return false;
436
437 switch (getKind()) {
438 case Null:
439 case Type:
440 case NullPtr:
441 return TypeOrValue.V == Other.TypeOrValue.V;
442 case Expression:
443 return TypeOrValue.V == Other.TypeOrValue.V &&
444 TypeOrValue.IsCanonicalExpr == Other.TypeOrValue.IsCanonicalExpr;
445
446 case Template:
447 case TemplateExpansion:
448 return TemplateArg.Name == Other.TemplateArg.Name &&
449 TemplateArg.NumExpansions == Other.TemplateArg.NumExpansions;
450
451 case Declaration:
452 return getAsDecl() == Other.getAsDecl() &&
453 getParamTypeForDecl() == Other.getParamTypeForDecl();
454
455 case Integral:
456 return getIntegralType() == Other.getIntegralType() &&
457 getAsIntegral() == Other.getAsIntegral();
458
459 case StructuralValue: {
460 if (getStructuralValueType().getCanonicalType() !=
461 Other.getStructuralValueType().getCanonicalType())
462 return false;
463
464 llvm::FoldingSetNodeID A, B;
465 getAsStructuralValue().Profile(ID&: A);
466 Other.getAsStructuralValue().Profile(ID&: B);
467 return A == B;
468 }
469
470 case Pack:
471 if (Args.NumArgs != Other.Args.NumArgs) return false;
472 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I)
473 if (!Args.Args[I].structurallyEquals(Other: Other.Args.Args[I]))
474 return false;
475 return true;
476 }
477
478 llvm_unreachable("Invalid TemplateArgument Kind!");
479}
480
481TemplateArgument TemplateArgument::getPackExpansionPattern() const {
482 assert(isPackExpansion());
483
484 switch (getKind()) {
485 case Type:
486 return getAsType()->castAs<PackExpansionType>()->getPattern();
487
488 case Expression:
489 return TemplateArgument(cast<PackExpansionExpr>(Val: getAsExpr())->getPattern(),
490 isCanonicalExpr());
491
492 case TemplateExpansion:
493 return TemplateArgument(getAsTemplateOrTemplatePattern());
494
495 case Declaration:
496 case Integral:
497 case StructuralValue:
498 case Pack:
499 case Null:
500 case Template:
501 case NullPtr:
502 return TemplateArgument();
503 }
504
505 llvm_unreachable("Invalid TemplateArgument Kind!");
506}
507
508void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
509 bool IncludeType) const {
510
511 switch (getKind()) {
512 case Null:
513 Out << "(no value)";
514 break;
515
516 case Type: {
517 PrintingPolicy SubPolicy(Policy);
518 SubPolicy.SuppressStrongLifetime = true;
519 getAsType().print(OS&: Out, Policy: SubPolicy);
520 break;
521 }
522
523 case Declaration: {
524 ValueDecl *VD = getAsDecl();
525 if (getParamTypeForDecl()->isRecordType()) {
526 if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(Val: VD)) {
527 TPO->getType().getUnqualifiedType().print(Out, Policy);
528 TPO->printAsInit(OS&: Out, Policy);
529 break;
530 }
531 }
532 if (needsAmpersandOnTemplateArg(paramType: getParamTypeForDecl(), argType: VD->getType()))
533 Out << "&";
534 VD->printQualifiedName(Out);
535 break;
536 }
537
538 case StructuralValue:
539 getAsStructuralValue().printPretty(OS&: Out, Policy, Ty: getStructuralValueType());
540 break;
541
542 case NullPtr:
543 // FIXME: Include the type if it's not obvious from the context.
544 Out << "nullptr";
545 break;
546
547 case Template: {
548 getAsTemplate().print(OS&: Out, Policy);
549 break;
550 }
551
552 case TemplateExpansion:
553 getAsTemplateOrTemplatePattern().print(OS&: Out, Policy);
554 Out << "...";
555 break;
556
557 case Integral:
558 printIntegral(TemplArg: *this, Out, Policy, IncludeType);
559 break;
560
561 case Expression: {
562 PrintingPolicy ExprPolicy = Policy;
563 ExprPolicy.PrintAsCanonical = isCanonicalExpr();
564 getAsExpr()->printPretty(Out, nullptr, ExprPolicy);
565 break;
566 }
567
568 case Pack:
569 Out << "<";
570 bool First = true;
571 for (const auto &P : pack_elements()) {
572 if (First)
573 First = false;
574 else
575 Out << ", ";
576
577 P.print(Policy, Out, IncludeType);
578 }
579 Out << ">";
580 break;
581 }
582}
583
584//===----------------------------------------------------------------------===//
585// TemplateArgumentLoc Implementation
586//===----------------------------------------------------------------------===//
587
588SourceRange TemplateArgumentLoc::getSourceRange() const {
589 switch (Argument.getKind()) {
590 case TemplateArgument::Expression:
591 return getSourceExpression()->getSourceRange();
592
593 case TemplateArgument::Declaration:
594 return getSourceDeclExpression()->getSourceRange();
595
596 case TemplateArgument::NullPtr:
597 return getSourceNullPtrExpression()->getSourceRange();
598
599 case TemplateArgument::Type:
600 if (TypeSourceInfo *TSI = getTypeSourceInfo())
601 return TSI->getTypeLoc().getSourceRange();
602 else
603 return SourceRange();
604
605 case TemplateArgument::Template:
606 if (getTemplateQualifierLoc())
607 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
608 getTemplateNameLoc());
609 return SourceRange(getTemplateNameLoc());
610
611 case TemplateArgument::TemplateExpansion:
612 if (getTemplateQualifierLoc())
613 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
614 getTemplateEllipsisLoc());
615 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
616
617 case TemplateArgument::Integral:
618 return getSourceIntegralExpression()->getSourceRange();
619
620 case TemplateArgument::StructuralValue:
621 return getSourceStructuralValueExpression()->getSourceRange();
622
623 case TemplateArgument::Pack:
624 case TemplateArgument::Null:
625 return SourceRange();
626 }
627
628 llvm_unreachable("Invalid TemplateArgument Kind!");
629}
630
631template <typename T>
632static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) {
633 switch (Arg.getKind()) {
634 case TemplateArgument::Null:
635 // This is bad, but not as bad as crashing because of argument
636 // count mismatches.
637 return DB << "(null template argument)";
638
639 case TemplateArgument::Type:
640 return DB << Arg.getAsType();
641
642 case TemplateArgument::Declaration:
643 return DB << Arg.getAsDecl();
644
645 case TemplateArgument::NullPtr:
646 return DB << "nullptr";
647
648 case TemplateArgument::Integral:
649 return DB << toString(I: Arg.getAsIntegral(), Radix: 10);
650
651 case TemplateArgument::StructuralValue: {
652 // FIXME: We're guessing at LangOptions!
653 SmallString<32> Str;
654 llvm::raw_svector_ostream OS(Str);
655 LangOptions LangOpts;
656 LangOpts.CPlusPlus = true;
657 PrintingPolicy Policy(LangOpts);
658 Arg.getAsStructuralValue().printPretty(OS, Policy,
659 Ty: Arg.getStructuralValueType());
660 return DB << OS.str();
661 }
662
663 case TemplateArgument::Template:
664 return DB << Arg.getAsTemplate();
665
666 case TemplateArgument::TemplateExpansion:
667 return DB << Arg.getAsTemplateOrTemplatePattern() << "...";
668
669 case TemplateArgument::Expression:
670 // FIXME: Support printing expressions as canonical
671 return DB << Arg.getAsExpr();
672
673 case TemplateArgument::Pack: {
674 // FIXME: We're guessing at LangOptions!
675 SmallString<32> Str;
676 llvm::raw_svector_ostream OS(Str);
677 LangOptions LangOpts;
678 LangOpts.CPlusPlus = true;
679 PrintingPolicy Policy(LangOpts);
680 Arg.print(Policy, Out&: OS, /*IncludeType*/ true);
681 return DB << OS.str();
682 }
683 }
684
685 llvm_unreachable("Invalid TemplateArgument Kind!");
686}
687
688const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
689 const TemplateArgument &Arg) {
690 return DiagTemplateArg(DB, Arg);
691}
692
693clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo(
694 ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc,
695 SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) {
696 TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo;
697 Template->Qualifier = QualifierLoc.getNestedNameSpecifier();
698 Template->QualifierLocData = QualifierLoc.getOpaqueData();
699 Template->TemplateNameLoc = TemplateNameLoc;
700 Template->EllipsisLoc = EllipsisLoc;
701 Pointer = Template;
702}
703
704const ASTTemplateArgumentListInfo *
705ASTTemplateArgumentListInfo::Create(const ASTContext &C,
706 const TemplateArgumentListInfo &List) {
707 std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(Counts: List.size());
708 void *Mem = C.Allocate(Size: size, Align: alignof(ASTTemplateArgumentListInfo));
709 return new (Mem) ASTTemplateArgumentListInfo(List);
710}
711
712const ASTTemplateArgumentListInfo *
713ASTTemplateArgumentListInfo::Create(const ASTContext &C,
714 const ASTTemplateArgumentListInfo *List) {
715 if (!List)
716 return nullptr;
717 std::size_t size =
718 totalSizeToAlloc<TemplateArgumentLoc>(Counts: List->getNumTemplateArgs());
719 void *Mem = C.Allocate(Size: size, Align: alignof(ASTTemplateArgumentListInfo));
720 return new (Mem) ASTTemplateArgumentListInfo(List);
721}
722
723ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
724 const TemplateArgumentListInfo &Info) {
725 LAngleLoc = Info.getLAngleLoc();
726 RAngleLoc = Info.getRAngleLoc();
727 NumTemplateArgs = Info.size();
728
729 TemplateArgumentLoc *ArgBuffer = getTrailingObjects();
730 for (unsigned i = 0; i != NumTemplateArgs; ++i)
731 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]);
732}
733
734ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
735 const ASTTemplateArgumentListInfo *Info) {
736 LAngleLoc = Info->getLAngleLoc();
737 RAngleLoc = Info->getRAngleLoc();
738 NumTemplateArgs = Info->getNumTemplateArgs();
739
740 TemplateArgumentLoc *ArgBuffer = getTrailingObjects();
741 for (unsigned i = 0; i != NumTemplateArgs; ++i)
742 new (&ArgBuffer[i]) TemplateArgumentLoc((*Info)[i]);
743}
744
745void ASTTemplateKWAndArgsInfo::initializeFrom(
746 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
747 TemplateArgumentLoc *OutArgArray) {
748 this->TemplateKWLoc = TemplateKWLoc;
749 LAngleLoc = Info.getLAngleLoc();
750 RAngleLoc = Info.getRAngleLoc();
751 NumTemplateArgs = Info.size();
752
753 for (unsigned i = 0; i != NumTemplateArgs; ++i)
754 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
755}
756
757void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) {
758 assert(TemplateKWLoc.isValid());
759 LAngleLoc = SourceLocation();
760 RAngleLoc = SourceLocation();
761 this->TemplateKWLoc = TemplateKWLoc;
762 NumTemplateArgs = 0;
763}
764
765void ASTTemplateKWAndArgsInfo::initializeFrom(
766 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info,
767 TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) {
768 this->TemplateKWLoc = TemplateKWLoc;
769 LAngleLoc = Info.getLAngleLoc();
770 RAngleLoc = Info.getRAngleLoc();
771 NumTemplateArgs = Info.size();
772
773 for (unsigned i = 0; i != NumTemplateArgs; ++i) {
774 Deps |= Info[i].getArgument().getDependence();
775
776 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]);
777 }
778}
779
780void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray,
781 TemplateArgumentListInfo &Info) const {
782 Info.setLAngleLoc(LAngleLoc);
783 Info.setRAngleLoc(RAngleLoc);
784 for (unsigned I = 0; I != NumTemplateArgs; ++I)
785 Info.addArgument(Loc: ArgArray[I]);
786}
787

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/lib/AST/TemplateBase.cpp