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/None.h" 33 #include "llvm/ADT/SmallString.h" 34 #include "llvm/ADT/StringExtras.h" 35 #include "llvm/ADT/StringRef.h" 36 #include "llvm/Support/Casting.h" 37 #include "llvm/Support/Compiler.h" 38 #include "llvm/Support/ErrorHandling.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <cassert> 41 #include <cstddef> 42 #include <cstdint> 43 #include <cstring> 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 Optional<unsigned> TemplateArgument::getNumTemplateExpansions() const { 275 assert(getKind() == TemplateExpansion); 276 if (TemplateArg.NumExpansions) 277 return TemplateArg.NumExpansions - 1; 278 279 return None; 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()? getAsDecl()->getCanonicalDecl() : nullptr); 325 break; 326 327 case Template: 328 case TemplateExpansion: { 329 TemplateName Template = getAsTemplateOrTemplatePattern(); 330 if (TemplateTemplateParmDecl *TTP 331 = dyn_cast_or_null<TemplateTemplateParmDecl>( 332 Template.getAsTemplateDecl())) { 333 ID.AddBoolean(true); 334 ID.AddInteger(TTP->getDepth()); 335 ID.AddInteger(TTP->getPosition()); 336 ID.AddBoolean(TTP->isParameterPack()); 337 } else { 338 ID.AddBoolean(false); 339 ID.AddPointer(Context.getCanonicalTemplateName(Template) 340 .getAsVoidPointer()); 341 } 342 break; 343 } 344 345 case Integral: 346 getAsIntegral().Profile(ID); 347 getIntegralType().Profile(ID); 348 break; 349 350 case Expression: 351 getAsExpr()->Profile(ID, Context, true); 352 break; 353 354 case Pack: 355 ID.AddInteger(Args.NumArgs); 356 for (unsigned I = 0; I != Args.NumArgs; ++I) 357 Args.Args[I].Profile(ID, Context); 358 } 359 } 360 361 bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const { 362 if (getKind() != Other.getKind()) return false; 363 364 switch (getKind()) { 365 case Null: 366 case Type: 367 case Expression: 368 case NullPtr: 369 return TypeOrValue.V == Other.TypeOrValue.V; 370 371 case Template: 372 case TemplateExpansion: 373 return TemplateArg.Name == Other.TemplateArg.Name && 374 TemplateArg.NumExpansions == Other.TemplateArg.NumExpansions; 375 376 case Declaration: 377 return getAsDecl() == Other.getAsDecl(); 378 379 case Integral: 380 return getIntegralType() == Other.getIntegralType() && 381 getAsIntegral() == Other.getAsIntegral(); 382 383 case Pack: 384 if (Args.NumArgs != Other.Args.NumArgs) return false; 385 for (unsigned I = 0, E = Args.NumArgs; I != E; ++I) 386 if (!Args.Args[I].structurallyEquals(Other.Args.Args[I])) 387 return false; 388 return true; 389 } 390 391 llvm_unreachable("Invalid TemplateArgument Kind!"); 392 } 393 394 TemplateArgument TemplateArgument::getPackExpansionPattern() const { 395 assert(isPackExpansion()); 396 397 switch (getKind()) { 398 case Type: 399 return getAsType()->castAs<PackExpansionType>()->getPattern(); 400 401 case Expression: 402 return cast<PackExpansionExpr>(getAsExpr())->getPattern(); 403 404 case TemplateExpansion: 405 return TemplateArgument(getAsTemplateOrTemplatePattern()); 406 407 case Declaration: 408 case Integral: 409 case Pack: 410 case Null: 411 case Template: 412 case NullPtr: 413 return TemplateArgument(); 414 } 415 416 llvm_unreachable("Invalid TemplateArgument Kind!"); 417 } 418 419 void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out, 420 bool IncludeType) const { 421 422 switch (getKind()) { 423 case Null: 424 Out << "(no value)"; 425 break; 426 427 case Type: { 428 PrintingPolicy SubPolicy(Policy); 429 SubPolicy.SuppressStrongLifetime = true; 430 getAsType().print(Out, SubPolicy); 431 break; 432 } 433 434 case Declaration: { 435 // FIXME: Include the type if it's not obvious from the context. 436 NamedDecl *ND = getAsDecl(); 437 if (getParamTypeForDecl()->isRecordType()) { 438 if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(ND)) { 439 TPO->printAsInit(Out, Policy); 440 break; 441 } 442 } 443 if (auto *VD = dyn_cast<ValueDecl>(ND)) { 444 if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType())) 445 Out << "&"; 446 } 447 ND->printQualifiedName(Out); 448 break; 449 } 450 451 case NullPtr: 452 // FIXME: Include the type if it's not obvious from the context. 453 Out << "nullptr"; 454 break; 455 456 case Template: 457 getAsTemplate().print(Out, Policy, TemplateName::Qualified::Fully); 458 break; 459 460 case TemplateExpansion: 461 getAsTemplateOrTemplatePattern().print(Out, Policy); 462 Out << "..."; 463 break; 464 465 case Integral: 466 printIntegral(*this, Out, Policy, IncludeType); 467 break; 468 469 case Expression: 470 getAsExpr()->printPretty(Out, nullptr, Policy); 471 break; 472 473 case Pack: 474 Out << "<"; 475 bool First = true; 476 for (const auto &P : pack_elements()) { 477 if (First) 478 First = false; 479 else 480 Out << ", "; 481 482 P.print(Policy, Out, IncludeType); 483 } 484 Out << ">"; 485 break; 486 } 487 } 488 489 void TemplateArgument::dump(raw_ostream &Out) const { 490 LangOptions LO; // FIXME! see also TemplateName::dump(). 491 LO.CPlusPlus = true; 492 LO.Bool = true; 493 print(PrintingPolicy(LO), Out, /*IncludeType*/ true); 494 } 495 496 LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); } 497 498 //===----------------------------------------------------------------------===// 499 // TemplateArgumentLoc Implementation 500 //===----------------------------------------------------------------------===// 501 502 SourceRange TemplateArgumentLoc::getSourceRange() const { 503 switch (Argument.getKind()) { 504 case TemplateArgument::Expression: 505 return getSourceExpression()->getSourceRange(); 506 507 case TemplateArgument::Declaration: 508 return getSourceDeclExpression()->getSourceRange(); 509 510 case TemplateArgument::NullPtr: 511 return getSourceNullPtrExpression()->getSourceRange(); 512 513 case TemplateArgument::Type: 514 if (TypeSourceInfo *TSI = getTypeSourceInfo()) 515 return TSI->getTypeLoc().getSourceRange(); 516 else 517 return SourceRange(); 518 519 case TemplateArgument::Template: 520 if (getTemplateQualifierLoc()) 521 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 522 getTemplateNameLoc()); 523 return SourceRange(getTemplateNameLoc()); 524 525 case TemplateArgument::TemplateExpansion: 526 if (getTemplateQualifierLoc()) 527 return SourceRange(getTemplateQualifierLoc().getBeginLoc(), 528 getTemplateEllipsisLoc()); 529 return SourceRange(getTemplateNameLoc(), getTemplateEllipsisLoc()); 530 531 case TemplateArgument::Integral: 532 return getSourceIntegralExpression()->getSourceRange(); 533 534 case TemplateArgument::Pack: 535 case TemplateArgument::Null: 536 return SourceRange(); 537 } 538 539 llvm_unreachable("Invalid TemplateArgument Kind!"); 540 } 541 542 template <typename T> 543 static const T &DiagTemplateArg(const T &DB, const TemplateArgument &Arg) { 544 switch (Arg.getKind()) { 545 case TemplateArgument::Null: 546 // This is bad, but not as bad as crashing because of argument 547 // count mismatches. 548 return DB << "(null template argument)"; 549 550 case TemplateArgument::Type: 551 return DB << Arg.getAsType(); 552 553 case TemplateArgument::Declaration: 554 return DB << Arg.getAsDecl(); 555 556 case TemplateArgument::NullPtr: 557 return DB << "nullptr"; 558 559 case TemplateArgument::Integral: 560 return DB << toString(Arg.getAsIntegral(), 10); 561 562 case TemplateArgument::Template: 563 return DB << Arg.getAsTemplate(); 564 565 case TemplateArgument::TemplateExpansion: 566 return DB << Arg.getAsTemplateOrTemplatePattern() << "..."; 567 568 case TemplateArgument::Expression: { 569 // This shouldn't actually ever happen, so it's okay that we're 570 // regurgitating an expression here. 571 // FIXME: We're guessing at LangOptions! 572 SmallString<32> Str; 573 llvm::raw_svector_ostream OS(Str); 574 LangOptions LangOpts; 575 LangOpts.CPlusPlus = true; 576 PrintingPolicy Policy(LangOpts); 577 Arg.getAsExpr()->printPretty(OS, nullptr, Policy); 578 return DB << OS.str(); 579 } 580 581 case TemplateArgument::Pack: { 582 // FIXME: We're guessing at LangOptions! 583 SmallString<32> Str; 584 llvm::raw_svector_ostream OS(Str); 585 LangOptions LangOpts; 586 LangOpts.CPlusPlus = true; 587 PrintingPolicy Policy(LangOpts); 588 Arg.print(Policy, OS, /*IncludeType*/ true); 589 return DB << OS.str(); 590 } 591 } 592 593 llvm_unreachable("Invalid TemplateArgument Kind!"); 594 } 595 596 const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB, 597 const TemplateArgument &Arg) { 598 return DiagTemplateArg(DB, Arg); 599 } 600 601 clang::TemplateArgumentLocInfo::TemplateArgumentLocInfo( 602 ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, 603 SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) { 604 TemplateTemplateArgLocInfo *Template = new (Ctx) TemplateTemplateArgLocInfo; 605 Template->Qualifier = QualifierLoc.getNestedNameSpecifier(); 606 Template->QualifierLocData = QualifierLoc.getOpaqueData(); 607 Template->TemplateNameLoc = TemplateNameLoc; 608 Template->EllipsisLoc = EllipsisLoc; 609 Pointer = Template; 610 } 611 612 const ASTTemplateArgumentListInfo * 613 ASTTemplateArgumentListInfo::Create(const ASTContext &C, 614 const TemplateArgumentListInfo &List) { 615 std::size_t size = totalSizeToAlloc<TemplateArgumentLoc>(List.size()); 616 void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo)); 617 return new (Mem) ASTTemplateArgumentListInfo(List); 618 } 619 620 const ASTTemplateArgumentListInfo * 621 ASTTemplateArgumentListInfo::Create(const ASTContext &C, 622 const ASTTemplateArgumentListInfo *List) { 623 if (!List) 624 return nullptr; 625 std::size_t size = 626 totalSizeToAlloc<TemplateArgumentLoc>(List->getNumTemplateArgs()); 627 void *Mem = C.Allocate(size, alignof(ASTTemplateArgumentListInfo)); 628 return new (Mem) ASTTemplateArgumentListInfo(List); 629 } 630 631 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( 632 const TemplateArgumentListInfo &Info) { 633 LAngleLoc = Info.getLAngleLoc(); 634 RAngleLoc = Info.getRAngleLoc(); 635 NumTemplateArgs = Info.size(); 636 637 TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>(); 638 for (unsigned i = 0; i != NumTemplateArgs; ++i) 639 new (&ArgBuffer[i]) TemplateArgumentLoc(Info[i]); 640 } 641 642 ASTTemplateArgumentListInfo::ASTTemplateArgumentListInfo( 643 const ASTTemplateArgumentListInfo *Info) { 644 LAngleLoc = Info->getLAngleLoc(); 645 RAngleLoc = Info->getRAngleLoc(); 646 NumTemplateArgs = Info->getNumTemplateArgs(); 647 648 TemplateArgumentLoc *ArgBuffer = getTrailingObjects<TemplateArgumentLoc>(); 649 for (unsigned i = 0; i != NumTemplateArgs; ++i) 650 new (&ArgBuffer[i]) TemplateArgumentLoc((*Info)[i]); 651 } 652 653 void ASTTemplateKWAndArgsInfo::initializeFrom( 654 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, 655 TemplateArgumentLoc *OutArgArray) { 656 this->TemplateKWLoc = TemplateKWLoc; 657 LAngleLoc = Info.getLAngleLoc(); 658 RAngleLoc = Info.getRAngleLoc(); 659 NumTemplateArgs = Info.size(); 660 661 for (unsigned i = 0; i != NumTemplateArgs; ++i) 662 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); 663 } 664 665 void ASTTemplateKWAndArgsInfo::initializeFrom(SourceLocation TemplateKWLoc) { 666 assert(TemplateKWLoc.isValid()); 667 LAngleLoc = SourceLocation(); 668 RAngleLoc = SourceLocation(); 669 this->TemplateKWLoc = TemplateKWLoc; 670 NumTemplateArgs = 0; 671 } 672 673 void ASTTemplateKWAndArgsInfo::initializeFrom( 674 SourceLocation TemplateKWLoc, const TemplateArgumentListInfo &Info, 675 TemplateArgumentLoc *OutArgArray, TemplateArgumentDependence &Deps) { 676 this->TemplateKWLoc = TemplateKWLoc; 677 LAngleLoc = Info.getLAngleLoc(); 678 RAngleLoc = Info.getRAngleLoc(); 679 NumTemplateArgs = Info.size(); 680 681 for (unsigned i = 0; i != NumTemplateArgs; ++i) { 682 Deps |= Info[i].getArgument().getDependence(); 683 684 new (&OutArgArray[i]) TemplateArgumentLoc(Info[i]); 685 } 686 } 687 688 void ASTTemplateKWAndArgsInfo::copyInto(const TemplateArgumentLoc *ArgArray, 689 TemplateArgumentListInfo &Info) const { 690 Info.setLAngleLoc(LAngleLoc); 691 Info.setRAngleLoc(RAngleLoc); 692 for (unsigned I = 0; I != NumTemplateArgs; ++I) 693 Info.addArgument(ArgArray[I]); 694 } 695