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