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