1 //===- TemplateBase.cpp - Common template AST class implementation --------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements common classes used throughout C++ template
12 //===----------------------------------------------------------------------===//
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"
42 using namespace clang
;
44 /// Print a template integral argument value.
46 /// \param TemplArg the TemplateArgument instance to print.
48 /// \param Out the raw_ostream instance to use for printing.
50 /// \param Policy the printing policy for EnumConstantDecl printing.
52 /// \param IncludeType If set, ensure that the type of the expression printed
53 /// matches the type of the template argument.
54 static void printIntegral(const TemplateArgument
&TemplArg
, raw_ostream
&Out
,
55 const PrintingPolicy
&Policy
, bool IncludeType
) {
56 const Type
*T
= TemplArg
.getIntegralType().getTypePtr();
57 const llvm::APSInt
&Val
= TemplArg
.getAsIntegral();
59 if (Policy
.UseEnumerators
) {
60 if (const EnumType
*ET
= T
->getAs
<EnumType
>()) {
61 for (const EnumConstantDecl
*ECD
: ET
->getDecl()->enumerators()) {
62 // In Sema::CheckTemplateArugment, enum template arguments value are
63 // extended to the size of the integer underlying the enum type. This
64 // may create a size difference between the enum value and template
65 // argument value, requiring isSameValue here instead of operator==.
66 if (llvm::APSInt::isSameValue(ECD
->getInitVal(), Val
)) {
67 ECD
->printQualifiedName(Out
, Policy
);
74 if (Policy
.MSVCFormatting
)
77 if (T
->isBooleanType()) {
78 if (!Policy
.MSVCFormatting
)
79 Out
<< (Val
.getBoolValue() ? "true" : "false");
82 } else if (T
->isCharType()) {
84 if (T
->isSpecificBuiltinType(BuiltinType::SChar
))
85 Out
<< "(signed char)";
86 else if (T
->isSpecificBuiltinType(BuiltinType::UChar
))
87 Out
<< "(unsigned char)";
89 CharacterLiteral::print(Val
.getZExtValue(), CharacterLiteralKind::Ascii
,
91 } else if (T
->isAnyCharacterType() && !Policy
.MSVCFormatting
) {
92 CharacterLiteralKind Kind
;
93 if (T
->isWideCharType())
94 Kind
= CharacterLiteralKind::Wide
;
95 else if (T
->isChar8Type())
96 Kind
= CharacterLiteralKind::UTF8
;
97 else if (T
->isChar16Type())
98 Kind
= CharacterLiteralKind::UTF16
;
99 else if (T
->isChar32Type())
100 Kind
= CharacterLiteralKind::UTF32
;
102 Kind
= CharacterLiteralKind::Ascii
;
103 CharacterLiteral::print(Val
.getExtValue(), Kind
, Out
);
104 } else if (IncludeType
) {
105 if (const auto *BT
= T
->getAs
<BuiltinType
>()) {
106 switch (BT
->getKind()) {
107 case BuiltinType::ULongLong
:
110 case BuiltinType::LongLong
:
113 case BuiltinType::ULong
:
116 case BuiltinType::Long
:
119 case BuiltinType::UInt
:
122 case BuiltinType::Int
:
126 Out
<< "(" << T
->getCanonicalTypeInternal().getAsString(Policy
) << ")"
131 Out
<< "(" << T
->getCanonicalTypeInternal().getAsString(Policy
) << ")"
137 static unsigned getArrayDepth(QualType type
) {
139 while (const auto *arrayType
= type
->getAsArrayTypeUnsafe()) {
141 type
= arrayType
->getElementType();
146 static bool needsAmpersandOnTemplateArg(QualType paramType
, QualType argType
) {
147 // Generally, if the parameter type is a pointer, we must be taking the
148 // address of something and need a &. However, if the argument is an array,
149 // this could be implicit via array-to-pointer decay.
150 if (!paramType
->isPointerType())
151 return paramType
->isMemberPointerType();
152 if (argType
->isArrayType())
153 return getArrayDepth(argType
) == getArrayDepth(paramType
->getPointeeType());
157 //===----------------------------------------------------------------------===//
158 // TemplateArgument Implementation
159 //===----------------------------------------------------------------------===//
161 void TemplateArgument::initFromType(QualType T
, bool IsNullPtr
,
163 TypeOrValue
.Kind
= IsNullPtr
? NullPtr
: Type
;
164 TypeOrValue
.IsDefaulted
= IsDefaulted
;
165 TypeOrValue
.V
= reinterpret_cast<uintptr_t>(T
.getAsOpaquePtr());
168 void TemplateArgument::initFromDeclaration(ValueDecl
*D
, QualType QT
,
170 assert(D
&& "Expected decl");
171 DeclArg
.Kind
= Declaration
;
172 DeclArg
.IsDefaulted
= IsDefaulted
;
173 DeclArg
.QT
= QT
.getAsOpaquePtr();
177 void TemplateArgument::initFromIntegral(const ASTContext
&Ctx
,
178 const llvm::APSInt
&Value
,
179 QualType Type
, bool IsDefaulted
) {
180 Integer
.Kind
= Integral
;
181 Integer
.IsDefaulted
= IsDefaulted
;
182 // Copy the APSInt value into our decomposed form.
183 Integer
.BitWidth
= Value
.getBitWidth();
184 Integer
.IsUnsigned
= Value
.isUnsigned();
185 // If the value is large, we have to get additional memory from the ASTContext
186 unsigned NumWords
= Value
.getNumWords();
188 void *Mem
= Ctx
.Allocate(NumWords
* sizeof(uint64_t));
189 std::memcpy(Mem
, Value
.getRawData(), NumWords
* sizeof(uint64_t));
190 Integer
.pVal
= static_cast<uint64_t *>(Mem
);
192 Integer
.VAL
= Value
.getZExtValue();
195 Integer
.Type
= Type
.getAsOpaquePtr();
198 void TemplateArgument::initFromStructural(const ASTContext
&Ctx
, QualType Type
,
199 const APValue
&V
, bool IsDefaulted
) {
200 Value
.Kind
= StructuralValue
;
201 Value
.IsDefaulted
= IsDefaulted
;
202 Value
.Value
= new (Ctx
) APValue(V
);
203 Ctx
.addDestruction(Value
.Value
);
204 Value
.Type
= Type
.getAsOpaquePtr();
207 TemplateArgument::TemplateArgument(const ASTContext
&Ctx
,
208 const llvm::APSInt
&Value
, QualType Type
,
210 initFromIntegral(Ctx
, Value
, Type
, IsDefaulted
);
213 static const ValueDecl
*getAsSimpleValueDeclRef(const ASTContext
&Ctx
,
214 QualType T
, const APValue
&V
) {
215 // Pointers to members are relatively easy.
216 if (V
.isMemberPointer() && V
.getMemberPointerPath().empty())
217 return V
.getMemberPointerDecl();
219 // We model class non-type template parameters as their template parameter
220 // object declaration.
221 if (V
.isStruct() || V
.isUnion()) {
222 // Dependent types are not supposed to be described as
223 // TemplateParamObjectDecls.
224 if (T
->isDependentType() || T
->isInstantiationDependentType())
226 return Ctx
.getTemplateParamObjectDecl(T
, V
);
229 // Pointers and references with an empty path use the special 'Declaration'
231 if (V
.isLValue() && V
.hasLValuePath() && V
.getLValuePath().empty() &&
232 !V
.isLValueOnePastTheEnd())
233 return V
.getLValueBase().dyn_cast
<const ValueDecl
*>();
235 // Everything else uses the 'structural' representation.
239 TemplateArgument::TemplateArgument(const ASTContext
&Ctx
, QualType Type
,
240 const APValue
&V
, bool IsDefaulted
) {
241 if (Type
->isIntegralOrEnumerationType() && V
.isInt())
242 initFromIntegral(Ctx
, V
.getInt(), Type
, IsDefaulted
);
243 else if ((V
.isLValue() && V
.isNullPointer()) ||
244 (V
.isMemberPointer() && !V
.getMemberPointerDecl()))
245 initFromType(Type
, /*isNullPtr=*/true, IsDefaulted
);
246 else if (const ValueDecl
*VD
= getAsSimpleValueDeclRef(Ctx
, Type
, V
))
247 // FIXME: The Declaration form should expose a const ValueDecl*.
248 initFromDeclaration(const_cast<ValueDecl
*>(VD
), Type
, IsDefaulted
);
250 initFromStructural(Ctx
, Type
, V
, IsDefaulted
);
254 TemplateArgument::CreatePackCopy(ASTContext
&Context
,
255 ArrayRef
<TemplateArgument
> Args
) {
257 return getEmptyPack();
259 return TemplateArgument(Args
.copy(Context
));
262 TemplateArgumentDependence
TemplateArgument::getDependence() const {
263 auto Deps
= TemplateArgumentDependence::None
;
266 llvm_unreachable("Should not have a NULL template argument");
269 Deps
= toTemplateArgumentDependence(getAsType()->getDependence());
270 if (isa
<PackExpansionType
>(getAsType()))
271 Deps
|= TemplateArgumentDependence::Dependent
;
275 return toTemplateArgumentDependence(getAsTemplate().getDependence());
277 case TemplateExpansion
:
278 return TemplateArgumentDependence::Dependent
|
279 TemplateArgumentDependence::Instantiation
;
282 auto *DC
= dyn_cast
<DeclContext
>(getAsDecl());
284 DC
= getAsDecl()->getDeclContext();
285 if (DC
->isDependentContext())
286 Deps
= TemplateArgumentDependence::Dependent
|
287 TemplateArgumentDependence::Instantiation
;
293 case StructuralValue
:
294 return TemplateArgumentDependence::None
;
297 Deps
= toTemplateArgumentDependence(getAsExpr()->getDependence());
298 if (isa
<PackExpansionExpr
>(getAsExpr()))
299 Deps
|= TemplateArgumentDependence::Dependent
|
300 TemplateArgumentDependence::Instantiation
;
304 for (const auto &P
: pack_elements())
305 Deps
|= P
.getDependence();
308 llvm_unreachable("unhandled ArgKind");
311 bool TemplateArgument::isDependent() const {
312 return getDependence() & TemplateArgumentDependence::Dependent
;
315 bool TemplateArgument::isInstantiationDependent() const {
316 return getDependence() & TemplateArgumentDependence::Instantiation
;
319 bool TemplateArgument::isPackExpansion() const {
324 case StructuralValue
:
330 case TemplateExpansion
:
334 return isa
<PackExpansionType
>(getAsType());
337 return isa
<PackExpansionExpr
>(getAsExpr());
340 llvm_unreachable("Invalid TemplateArgument Kind!");
343 bool TemplateArgument::containsUnexpandedParameterPack() const {
344 return getDependence() & TemplateArgumentDependence::UnexpandedPack
;
347 std::optional
<unsigned> TemplateArgument::getNumTemplateExpansions() const {
348 assert(getKind() == TemplateExpansion
);
349 if (TemplateArg
.NumExpansions
)
350 return TemplateArg
.NumExpansions
- 1;
355 QualType
TemplateArgument::getNonTypeTemplateArgumentType() const {
357 case TemplateArgument::Null
:
358 case TemplateArgument::Type
:
359 case TemplateArgument::Template
:
360 case TemplateArgument::TemplateExpansion
:
361 case TemplateArgument::Pack
:
364 case TemplateArgument::Integral
:
365 return getIntegralType();
367 case TemplateArgument::Expression
:
368 return getAsExpr()->getType();
370 case TemplateArgument::Declaration
:
371 return getParamTypeForDecl();
373 case TemplateArgument::NullPtr
:
374 return getNullPtrType();
376 case TemplateArgument::StructuralValue
:
377 return getStructuralValueType();
380 llvm_unreachable("Invalid TemplateArgument Kind!");
383 void TemplateArgument::Profile(llvm::FoldingSetNodeID
&ID
,
384 const ASTContext
&Context
) const {
385 ID
.AddInteger(getKind());
391 getAsType().Profile(ID
);
395 getNullPtrType().Profile(ID
);
399 getParamTypeForDecl().Profile(ID
);
400 ID
.AddPointer(getAsDecl());
403 case TemplateExpansion
:
404 ID
.AddInteger(TemplateArg
.NumExpansions
);
407 ID
.AddPointer(TemplateArg
.Name
);
411 getIntegralType().Profile(ID
);
412 getAsIntegral().Profile(ID
);
415 case StructuralValue
:
416 getStructuralValueType().Profile(ID
);
417 getAsStructuralValue().Profile(ID
);
421 getAsExpr()->Profile(ID
, Context
, true);
425 ID
.AddInteger(Args
.NumArgs
);
426 for (unsigned I
= 0; I
!= Args
.NumArgs
; ++I
)
427 Args
.Args
[I
].Profile(ID
, Context
);
431 bool TemplateArgument::structurallyEquals(const TemplateArgument
&Other
) const {
432 if (getKind() != Other
.getKind()) return false;
439 return TypeOrValue
.V
== Other
.TypeOrValue
.V
;
442 case TemplateExpansion
:
443 return TemplateArg
.Name
== Other
.TemplateArg
.Name
&&
444 TemplateArg
.NumExpansions
== Other
.TemplateArg
.NumExpansions
;
447 return getAsDecl() == Other
.getAsDecl() &&
448 getParamTypeForDecl() == Other
.getParamTypeForDecl();
451 return getIntegralType() == Other
.getIntegralType() &&
452 getAsIntegral() == Other
.getAsIntegral();
454 case StructuralValue
: {
455 if (getStructuralValueType().getCanonicalType() !=
456 Other
.getStructuralValueType().getCanonicalType())
459 llvm::FoldingSetNodeID A
, B
;
460 getAsStructuralValue().Profile(A
);
461 Other
.getAsStructuralValue().Profile(B
);
466 if (Args
.NumArgs
!= Other
.Args
.NumArgs
) return false;
467 for (unsigned I
= 0, E
= Args
.NumArgs
; I
!= E
; ++I
)
468 if (!Args
.Args
[I
].structurallyEquals(Other
.Args
.Args
[I
]))
473 llvm_unreachable("Invalid TemplateArgument Kind!");
476 TemplateArgument
TemplateArgument::getPackExpansionPattern() const {
477 assert(isPackExpansion());
481 return getAsType()->castAs
<PackExpansionType
>()->getPattern();
484 return cast
<PackExpansionExpr
>(getAsExpr())->getPattern();
486 case TemplateExpansion
:
487 return TemplateArgument(getAsTemplateOrTemplatePattern());
491 case StructuralValue
:
496 return TemplateArgument();
499 llvm_unreachable("Invalid TemplateArgument Kind!");
502 void TemplateArgument::print(const PrintingPolicy
&Policy
, raw_ostream
&Out
,
503 bool IncludeType
) const {
511 PrintingPolicy
SubPolicy(Policy
);
512 SubPolicy
.SuppressStrongLifetime
= true;
513 getAsType().print(Out
, SubPolicy
);
518 NamedDecl
*ND
= getAsDecl();
519 if (getParamTypeForDecl()->isRecordType()) {
520 if (auto *TPO
= dyn_cast
<TemplateParamObjectDecl
>(ND
)) {
521 TPO
->getType().getUnqualifiedType().print(Out
, Policy
);
522 TPO
->printAsInit(Out
, Policy
);
526 if (auto *VD
= dyn_cast
<ValueDecl
>(ND
)) {
527 if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD
->getType()))
530 ND
->printQualifiedName(Out
);
534 case StructuralValue
:
535 getAsStructuralValue().printPretty(Out
, Policy
, getStructuralValueType());
539 // FIXME: Include the type if it's not obvious from the context.
544 getAsTemplate().print(Out
, Policy
);
548 case TemplateExpansion
:
549 getAsTemplateOrTemplatePattern().print(Out
, Policy
);
554 printIntegral(*this, Out
, Policy
, IncludeType
);
558 getAsExpr()->printPretty(Out
, nullptr, Policy
);
564 for (const auto &P
: pack_elements()) {
570 P
.print(Policy
, Out
, IncludeType
);
577 //===----------------------------------------------------------------------===//
578 // TemplateArgumentLoc Implementation
579 //===----------------------------------------------------------------------===//
581 SourceRange
TemplateArgumentLoc::getSourceRange() const {
582 switch (Argument
.getKind()) {
583 case TemplateArgument::Expression
:
584 return getSourceExpression()->getSourceRange();
586 case TemplateArgument::Declaration
:
587 return getSourceDeclExpression()->getSourceRange();
589 case TemplateArgument::NullPtr
:
590 return getSourceNullPtrExpression()->getSourceRange();
592 case TemplateArgument::Type
:
593 if (TypeSourceInfo
*TSI
= getTypeSourceInfo())
594 return TSI
->getTypeLoc().getSourceRange();
596 return SourceRange();
598 case TemplateArgument::Template
:
599 if (getTemplateQualifierLoc())
600 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
601 getTemplateNameLoc());
602 return SourceRange(getTemplateNameLoc());
604 case TemplateArgument::TemplateExpansion
:
605 if (getTemplateQualifierLoc())
606 return SourceRange(getTemplateQualifierLoc().getBeginLoc(),
607 getTemplateEllipsisLoc());
608 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc());
610 case TemplateArgument::Integral
:
611 return getSourceIntegralExpression()->getSourceRange();
613 case TemplateArgument::StructuralValue
:
614 return getSourceStructuralValueExpression()->getSourceRange();
616 case TemplateArgument::Pack
:
617 case TemplateArgument::Null
:
618 return SourceRange();
621 llvm_unreachable("Invalid TemplateArgument Kind!");
624 template <typename T
>
625 static const T
&DiagTemplateArg(const T
&DB
, const TemplateArgument
&Arg
) {
626 switch (Arg
.getKind()) {
627 case TemplateArgument::Null
:
628 // This is bad, but not as bad as crashing because of argument
630 return DB
<< "(null template argument)";
632 case TemplateArgument::Type
:
633 return DB
<< Arg
.getAsType();
635 case TemplateArgument::Declaration
:
636 return DB
<< Arg
.getAsDecl();
638 case TemplateArgument::NullPtr
:
639 return DB
<< "nullptr";
641 case TemplateArgument::Integral
:
642 return DB
<< toString(Arg
.getAsIntegral(), 10);
644 case TemplateArgument::StructuralValue
: {
645 // FIXME: We're guessing at LangOptions!
647 llvm::raw_svector_ostream
OS(Str
);
648 LangOptions LangOpts
;
649 LangOpts
.CPlusPlus
= true;
650 PrintingPolicy
Policy(LangOpts
);
651 Arg
.getAsStructuralValue().printPretty(OS
, Policy
,
652 Arg
.getStructuralValueType());
653 return DB
<< OS
.str();
656 case TemplateArgument::Template
:
657 return DB
<< Arg
.getAsTemplate();
659 case TemplateArgument::TemplateExpansion
:
660 return DB
<< Arg
.getAsTemplateOrTemplatePattern() << "...";
662 case TemplateArgument::Expression
: {
663 // This shouldn't actually ever happen, so it's okay that we're
664 // regurgitating an expression here.
665 // FIXME: We're guessing at LangOptions!
667 llvm::raw_svector_ostream
OS(Str
);
668 LangOptions LangOpts
;
669 LangOpts
.CPlusPlus
= true;
670 PrintingPolicy
Policy(LangOpts
);
671 Arg
.getAsExpr()->printPretty(OS
, nullptr, Policy
);
672 return DB
<< OS
.str();
675 case TemplateArgument::Pack
: {
676 // FIXME: We're guessing at LangOptions!
678 llvm::raw_svector_ostream
OS(Str
);
679 LangOptions LangOpts
;
680 LangOpts
.CPlusPlus
= true;
681 PrintingPolicy
Policy(LangOpts
);
682 Arg
.print(Policy
, OS
, /*IncludeType*/ true);
683 return DB
<< OS
.str();
687 llvm_unreachable("Invalid TemplateArgument Kind!");
690 const StreamingDiagnostic
&clang::operator<<(const StreamingDiagnostic
&DB
,
691 const TemplateArgument
&Arg
) {
692 return DiagTemplateArg(DB
, Arg
);
695 clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo(
696 ASTContext
&Ctx
, NestedNameSpecifierLoc QualifierLoc
,
697 SourceLocation TemplateNameLoc
, SourceLocation EllipsisLoc
) {
698 TemplateTemplateArgLocInfo
*Template
= new (Ctx
) TemplateTemplateArgLocInfo
;
699 Template
->Qualifier
= QualifierLoc
.getNestedNameSpecifier();
700 Template
->QualifierLocData
= QualifierLoc
.getOpaqueData();
701 Template
->TemplateNameLoc
= TemplateNameLoc
;
702 Template
->EllipsisLoc
= EllipsisLoc
;
706 const ASTTemplateArgumentListInfo
*
707 ASTTemplateArgumentListInfo::Create(const ASTContext
&C
,
708 const TemplateArgumentListInfo
&List
) {
709 std::size_t size
= totalSizeToAlloc
<TemplateArgumentLoc
>(List
.size());
710 void *Mem
= C
.Allocate(size
, alignof(ASTTemplateArgumentListInfo
));
711 return new (Mem
) ASTTemplateArgumentListInfo(List
);
714 const ASTTemplateArgumentListInfo
*
715 ASTTemplateArgumentListInfo::Create(const ASTContext
&C
,
716 const ASTTemplateArgumentListInfo
*List
) {
720 totalSizeToAlloc
<TemplateArgumentLoc
>(List
->getNumTemplateArgs());
721 void *Mem
= C
.Allocate(size
, alignof(ASTTemplateArgumentListInfo
));
722 return new (Mem
) ASTTemplateArgumentListInfo(List
);
725 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
726 const TemplateArgumentListInfo
&Info
) {
727 LAngleLoc
= Info
.getLAngleLoc();
728 RAngleLoc
= Info
.getRAngleLoc();
729 NumTemplateArgs
= Info
.size();
731 TemplateArgumentLoc
*ArgBuffer
= getTrailingObjects
<TemplateArgumentLoc
>();
732 for (unsigned i
= 0; i
!= NumTemplateArgs
; ++i
)
733 new (&ArgBuffer
[i
]) TemplateArgumentLoc(Info
[i
]);
736 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo(
737 const ASTTemplateArgumentListInfo
*Info
) {
738 LAngleLoc
= Info
->getLAngleLoc();
739 RAngleLoc
= Info
->getRAngleLoc();
740 NumTemplateArgs
= Info
->getNumTemplateArgs();
742 TemplateArgumentLoc
*ArgBuffer
= getTrailingObjects
<TemplateArgumentLoc
>();
743 for (unsigned i
= 0; i
!= NumTemplateArgs
; ++i
)
744 new (&ArgBuffer
[i
]) TemplateArgumentLoc((*Info
)[i
]);
747 void ASTTemplateKWAndArgsInfo::initializeFrom(
748 SourceLocation TemplateKWLoc
, const TemplateArgumentListInfo
&Info
,
749 TemplateArgumentLoc
*OutArgArray
) {
750 this->TemplateKWLoc
= TemplateKWLoc
;
751 LAngleLoc
= Info
.getLAngleLoc();
752 RAngleLoc
= Info
.getRAngleLoc();
753 NumTemplateArgs
= Info
.size();
755 for (unsigned i
= 0; i
!= NumTemplateArgs
; ++i
)
756 new (&OutArgArray
[i
]) TemplateArgumentLoc(Info
[i
]);
759 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc
) {
760 assert(TemplateKWLoc
.isValid());
761 LAngleLoc
= SourceLocation();
762 RAngleLoc
= SourceLocation();
763 this->TemplateKWLoc
= TemplateKWLoc
;
767 void ASTTemplateKWAndArgsInfo::initializeFrom(
768 SourceLocation TemplateKWLoc
, const TemplateArgumentListInfo
&Info
,
769 TemplateArgumentLoc
*OutArgArray
, TemplateArgumentDependence
&Deps
) {
770 this->TemplateKWLoc
= TemplateKWLoc
;
771 LAngleLoc
= Info
.getLAngleLoc();
772 RAngleLoc
= Info
.getRAngleLoc();
773 NumTemplateArgs
= Info
.size();
775 for (unsigned i
= 0; i
!= NumTemplateArgs
; ++i
) {
776 Deps
|= Info
[i
].getArgument().getDependence();
778 new (&OutArgArray
[i
]) TemplateArgumentLoc(Info
[i
]);
782 void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc
*ArgArray
,
783 TemplateArgumentListInfo
&Info
) const {
784 Info
.setLAngleLoc(LAngleLoc
);
785 Info
.setRAngleLoc(RAngleLoc
);
786 for (unsigned I
= 0; I
!= NumTemplateArgs
; ++I
)
787 Info
.addArgument(ArgArray
[I
]);