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