1 //===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements a diagnostic formatting hook for AST elements. 11 // 12 //===----------------------------------------------------------------------===// 13 #include "clang/AST/ASTDiagnostic.h" 14 #include "clang/AST/ASTContext.h" 15 #include "clang/AST/ASTLambda.h" 16 #include "clang/AST/Attr.h" 17 #include "clang/AST/DeclObjC.h" 18 #include "clang/AST/DeclTemplate.h" 19 #include "clang/AST/ExprCXX.h" 20 #include "clang/AST/TemplateBase.h" 21 #include "clang/AST/Type.h" 22 #include "llvm/ADT/SmallString.h" 23 #include "llvm/Support/raw_ostream.h" 24 25 using namespace clang; 26 27 // Returns a desugared version of the QualType, and marks ShouldAKA as true 28 // whenever we remove significant sugar from the type. 29 static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { 30 QualifierCollector QC; 31 32 while (true) { 33 const Type *Ty = QC.strip(QT); 34 35 // Don't aka just because we saw an elaborated type... 36 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) { 37 QT = ET->desugar(); 38 continue; 39 } 40 // ... or a paren type ... 41 if (const ParenType *PT = dyn_cast<ParenType>(Ty)) { 42 QT = PT->desugar(); 43 continue; 44 } 45 // ...or a substituted template type parameter ... 46 if (const SubstTemplateTypeParmType *ST = 47 dyn_cast<SubstTemplateTypeParmType>(Ty)) { 48 QT = ST->desugar(); 49 continue; 50 } 51 // ...or an attributed type... 52 if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) { 53 QT = AT->desugar(); 54 continue; 55 } 56 // ...or an adjusted type... 57 if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) { 58 QT = AT->desugar(); 59 continue; 60 } 61 // ... or an auto type. 62 if (const AutoType *AT = dyn_cast<AutoType>(Ty)) { 63 if (!AT->isSugared()) 64 break; 65 QT = AT->desugar(); 66 continue; 67 } 68 69 // Don't desugar template specializations, unless it's an alias template. 70 if (const TemplateSpecializationType *TST 71 = dyn_cast<TemplateSpecializationType>(Ty)) 72 if (!TST->isTypeAlias()) 73 break; 74 75 // Don't desugar magic Objective-C types. 76 if (QualType(Ty,0) == Context.getObjCIdType() || 77 QualType(Ty,0) == Context.getObjCClassType() || 78 QualType(Ty,0) == Context.getObjCSelType() || 79 QualType(Ty,0) == Context.getObjCProtoType()) 80 break; 81 82 // Don't desugar va_list. 83 if (QualType(Ty,0) == Context.getBuiltinVaListType()) 84 break; 85 86 // Otherwise, do a single-step desugar. 87 QualType Underlying; 88 bool IsSugar = false; 89 switch (Ty->getTypeClass()) { 90 #define ABSTRACT_TYPE(Class, Base) 91 #define TYPE(Class, Base) \ 92 case Type::Class: { \ 93 const Class##Type *CTy = cast<Class##Type>(Ty); \ 94 if (CTy->isSugared()) { \ 95 IsSugar = true; \ 96 Underlying = CTy->desugar(); \ 97 } \ 98 break; \ 99 } 100 #include "clang/AST/TypeNodes.def" 101 } 102 103 // If it wasn't sugared, we're done. 104 if (!IsSugar) 105 break; 106 107 // If the desugared type is a vector type, we don't want to expand 108 // it, it will turn into an attribute mess. People want their "vec4". 109 if (isa<VectorType>(Underlying)) 110 break; 111 112 // Don't desugar through the primary typedef of an anonymous type. 113 if (const TagType *UTT = Underlying->getAs<TagType>()) 114 if (const TypedefType *QTT = dyn_cast<TypedefType>(QT)) 115 if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl()) 116 break; 117 118 // Record that we actually looked through an opaque type here. 119 ShouldAKA = true; 120 QT = Underlying; 121 } 122 123 // If we have a pointer-like type, desugar the pointee as well. 124 // FIXME: Handle other pointer-like types. 125 if (const PointerType *Ty = QT->getAs<PointerType>()) { 126 QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(), 127 ShouldAKA)); 128 } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) { 129 QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(), 130 ShouldAKA)); 131 } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) { 132 QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(), 133 ShouldAKA)); 134 } 135 136 return QC.apply(Context, QT); 137 } 138 139 /// \brief Convert the given type to a string suitable for printing as part of 140 /// a diagnostic. 141 /// 142 /// There are four main criteria when determining whether we should have an 143 /// a.k.a. clause when pretty-printing a type: 144 /// 145 /// 1) Some types provide very minimal sugar that doesn't impede the 146 /// user's understanding --- for example, elaborated type 147 /// specifiers. If this is all the sugar we see, we don't want an 148 /// a.k.a. clause. 149 /// 2) Some types are technically sugared but are much more familiar 150 /// when seen in their sugared form --- for example, va_list, 151 /// vector types, and the magic Objective C types. We don't 152 /// want to desugar these, even if we do produce an a.k.a. clause. 153 /// 3) Some types may have already been desugared previously in this diagnostic. 154 /// if this is the case, doing another "aka" would just be clutter. 155 /// 4) Two different types within the same diagnostic have the same output 156 /// string. In this case, force an a.k.a with the desugared type when 157 /// doing so will provide additional information. 158 /// 159 /// \param Context the context in which the type was allocated 160 /// \param Ty the type to print 161 /// \param QualTypeVals pointer values to QualTypes which are used in the 162 /// diagnostic message 163 static std::string 164 ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, 165 ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, 166 ArrayRef<intptr_t> QualTypeVals) { 167 // FIXME: Playing with std::string is really slow. 168 bool ForceAKA = false; 169 QualType CanTy = Ty.getCanonicalType(); 170 std::string S = Ty.getAsString(Context.getPrintingPolicy()); 171 std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); 172 173 for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) { 174 QualType CompareTy = 175 QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I])); 176 if (CompareTy.isNull()) 177 continue; 178 if (CompareTy == Ty) 179 continue; // Same types 180 QualType CompareCanTy = CompareTy.getCanonicalType(); 181 if (CompareCanTy == CanTy) 182 continue; // Same canonical types 183 std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy()); 184 bool aka; 185 QualType CompareDesugar = Desugar(Context, CompareTy, aka); 186 std::string CompareDesugarStr = 187 CompareDesugar.getAsString(Context.getPrintingPolicy()); 188 if (CompareS != S && CompareDesugarStr != S) 189 continue; // The type string is different than the comparison string 190 // and the desugared comparison string. 191 std::string CompareCanS = 192 CompareCanTy.getAsString(Context.getPrintingPolicy()); 193 194 if (CompareCanS == CanS) 195 continue; // No new info from canonical type 196 197 ForceAKA = true; 198 break; 199 } 200 201 // Check to see if we already desugared this type in this 202 // diagnostic. If so, don't do it again. 203 bool Repeated = false; 204 for (unsigned i = 0, e = PrevArgs.size(); i != e; ++i) { 205 // TODO: Handle ak_declcontext case. 206 if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { 207 void *Ptr = (void*)PrevArgs[i].second; 208 QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); 209 if (PrevTy == Ty) { 210 Repeated = true; 211 break; 212 } 213 } 214 } 215 216 // Consider producing an a.k.a. clause if removing all the direct 217 // sugar gives us something "significantly different". 218 if (!Repeated) { 219 bool ShouldAKA = false; 220 QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA); 221 if (ShouldAKA || ForceAKA) { 222 if (DesugaredTy == Ty) { 223 DesugaredTy = Ty.getCanonicalType(); 224 } 225 std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy()); 226 if (akaStr != S) { 227 S = "'" + S + "' (aka '" + akaStr + "')"; 228 return S; 229 } 230 } 231 232 // Give some additional info on vector types. These are either not desugared 233 // or displaying complex __attribute__ expressions so add details of the 234 // type and element count. 235 if (Ty->isVectorType()) { 236 const VectorType *VTy = Ty->getAs<VectorType>(); 237 std::string DecoratedString; 238 llvm::raw_string_ostream OS(DecoratedString); 239 const char *Values = VTy->getNumElements() > 1 ? "values" : "value"; 240 OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '" 241 << VTy->getElementType().getAsString(Context.getPrintingPolicy()) 242 << "' " << Values << ")"; 243 return OS.str(); 244 } 245 } 246 247 S = "'" + S + "'"; 248 return S; 249 } 250 251 static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, 252 QualType ToType, bool PrintTree, 253 bool PrintFromType, bool ElideType, 254 bool ShowColors, raw_ostream &OS); 255 256 void clang::FormatASTNodeDiagnosticArgument( 257 DiagnosticsEngine::ArgumentKind Kind, 258 intptr_t Val, 259 StringRef Modifier, 260 StringRef Argument, 261 ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, 262 SmallVectorImpl<char> &Output, 263 void *Cookie, 264 ArrayRef<intptr_t> QualTypeVals) { 265 ASTContext &Context = *static_cast<ASTContext*>(Cookie); 266 267 size_t OldEnd = Output.size(); 268 llvm::raw_svector_ostream OS(Output); 269 bool NeedQuotes = true; 270 271 switch (Kind) { 272 default: llvm_unreachable("unknown ArgumentKind"); 273 case DiagnosticsEngine::ak_qualtype_pair: { 274 TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val); 275 QualType FromType = 276 QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType)); 277 QualType ToType = 278 QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType)); 279 280 if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree, 281 TDT.PrintFromType, TDT.ElideType, 282 TDT.ShowColors, OS)) { 283 NeedQuotes = !TDT.PrintTree; 284 TDT.TemplateDiffUsed = true; 285 break; 286 } 287 288 // Don't fall-back during tree printing. The caller will handle 289 // this case. 290 if (TDT.PrintTree) 291 return; 292 293 // Attempting to do a template diff on non-templates. Set the variables 294 // and continue with regular type printing of the appropriate type. 295 Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType; 296 Modifier = StringRef(); 297 Argument = StringRef(); 298 // Fall through 299 } 300 case DiagnosticsEngine::ak_qualtype: { 301 assert(Modifier.empty() && Argument.empty() && 302 "Invalid modifier for QualType argument"); 303 304 QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); 305 OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals); 306 NeedQuotes = false; 307 break; 308 } 309 case DiagnosticsEngine::ak_declarationname: { 310 if (Modifier == "objcclass" && Argument.empty()) 311 OS << '+'; 312 else if (Modifier == "objcinstance" && Argument.empty()) 313 OS << '-'; 314 else 315 assert(Modifier.empty() && Argument.empty() && 316 "Invalid modifier for DeclarationName argument"); 317 318 OS << DeclarationName::getFromOpaqueInteger(Val); 319 break; 320 } 321 case DiagnosticsEngine::ak_nameddecl: { 322 bool Qualified; 323 if (Modifier == "q" && Argument.empty()) 324 Qualified = true; 325 else { 326 assert(Modifier.empty() && Argument.empty() && 327 "Invalid modifier for NamedDecl* argument"); 328 Qualified = false; 329 } 330 const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val); 331 ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified); 332 break; 333 } 334 case DiagnosticsEngine::ak_nestednamespec: { 335 NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val); 336 NNS->print(OS, Context.getPrintingPolicy()); 337 NeedQuotes = false; 338 break; 339 } 340 case DiagnosticsEngine::ak_declcontext: { 341 DeclContext *DC = reinterpret_cast<DeclContext *> (Val); 342 assert(DC && "Should never have a null declaration context"); 343 NeedQuotes = false; 344 345 // FIXME: Get the strings for DeclContext from some localized place 346 if (DC->isTranslationUnit()) { 347 if (Context.getLangOpts().CPlusPlus) 348 OS << "the global namespace"; 349 else 350 OS << "the global scope"; 351 } else if (DC->isClosure()) { 352 OS << "block literal"; 353 } else if (isLambdaCallOperator(DC)) { 354 OS << "lambda expression"; 355 } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { 356 OS << ConvertTypeToDiagnosticString(Context, 357 Context.getTypeDeclType(Type), 358 PrevArgs, QualTypeVals); 359 } else { 360 assert(isa<NamedDecl>(DC) && "Expected a NamedDecl"); 361 NamedDecl *ND = cast<NamedDecl>(DC); 362 if (isa<NamespaceDecl>(ND)) 363 OS << "namespace "; 364 else if (isa<ObjCMethodDecl>(ND)) 365 OS << "method "; 366 else if (isa<FunctionDecl>(ND)) 367 OS << "function "; 368 369 OS << '\''; 370 ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); 371 OS << '\''; 372 } 373 break; 374 } 375 case DiagnosticsEngine::ak_attr: { 376 const Attr *At = reinterpret_cast<Attr *>(Val); 377 assert(At && "Received null Attr object!"); 378 OS << '\'' << At->getSpelling() << '\''; 379 NeedQuotes = false; 380 break; 381 } 382 383 } 384 385 OS.flush(); 386 387 if (NeedQuotes) { 388 Output.insert(Output.begin()+OldEnd, '\''); 389 Output.push_back('\''); 390 } 391 } 392 393 /// TemplateDiff - A class that constructs a pretty string for a pair of 394 /// QualTypes. For the pair of types, a diff tree will be created containing 395 /// all the information about the templates and template arguments. Afterwards, 396 /// the tree is transformed to a string according to the options passed in. 397 namespace { 398 class TemplateDiff { 399 /// Context - The ASTContext which is used for comparing template arguments. 400 ASTContext &Context; 401 402 /// Policy - Used during expression printing. 403 PrintingPolicy Policy; 404 405 /// ElideType - Option to elide identical types. 406 bool ElideType; 407 408 /// PrintTree - Format output string as a tree. 409 bool PrintTree; 410 411 /// ShowColor - Diagnostics support color, so bolding will be used. 412 bool ShowColor; 413 414 /// FromType - When single type printing is selected, this is the type to be 415 /// be printed. When tree printing is selected, this type will show up first 416 /// in the tree. 417 QualType FromType; 418 419 /// ToType - The type that FromType is compared to. Only in tree printing 420 /// will this type be outputed. 421 QualType ToType; 422 423 /// OS - The stream used to construct the output strings. 424 raw_ostream &OS; 425 426 /// IsBold - Keeps track of the bold formatting for the output string. 427 bool IsBold; 428 429 /// DiffTree - A tree representation the differences between two types. 430 class DiffTree { 431 public: 432 /// DiffKind - The difference in a DiffNode and which fields are used. 433 enum DiffKind { 434 /// Incomplete or invalid node. 435 Invalid, 436 /// Another level of templates, uses TemplateDecl and Qualifiers 437 Template, 438 /// Type difference, uses QualType 439 Type, 440 /// Expression difference, uses Expr 441 Expression, 442 /// Template argument difference, uses TemplateDecl 443 TemplateTemplate, 444 /// Integer difference, uses APSInt and Expr 445 Integer, 446 /// Declaration difference, uses ValueDecl 447 Declaration 448 }; 449 private: 450 /// DiffNode - The root node stores the original type. Each child node 451 /// stores template arguments of their parents. For templated types, the 452 /// template decl is also stored. 453 struct DiffNode { 454 DiffKind Kind; 455 456 /// NextNode - The index of the next sibling node or 0. 457 unsigned NextNode; 458 459 /// ChildNode - The index of the first child node or 0. 460 unsigned ChildNode; 461 462 /// ParentNode - The index of the parent node. 463 unsigned ParentNode; 464 465 /// FromType, ToType - The type arguments. 466 QualType FromType, ToType; 467 468 /// FromExpr, ToExpr - The expression arguments. 469 Expr *FromExpr, *ToExpr; 470 471 /// FromNullPtr, ToNullPtr - If the template argument is a nullptr 472 bool FromNullPtr, ToNullPtr; 473 474 /// FromTD, ToTD - The template decl for template template 475 /// arguments or the type arguments that are templates. 476 TemplateDecl *FromTD, *ToTD; 477 478 /// FromQual, ToQual - Qualifiers for template types. 479 Qualifiers FromQual, ToQual; 480 481 /// FromInt, ToInt - APSInt's for integral arguments. 482 llvm::APSInt FromInt, ToInt; 483 484 /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid. 485 bool IsValidFromInt, IsValidToInt; 486 487 /// FromValueDecl, ToValueDecl - Whether the argument is a decl. 488 ValueDecl *FromValueDecl, *ToValueDecl; 489 490 /// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of 491 /// operator before it. 492 bool FromAddressOf, ToAddressOf; 493 494 /// FromDefault, ToDefault - Whether the argument is a default argument. 495 bool FromDefault, ToDefault; 496 497 /// Same - Whether the two arguments evaluate to the same value. 498 bool Same; 499 500 DiffNode(unsigned ParentNode = 0) 501 : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), 502 FromType(), ToType(), FromExpr(nullptr), ToExpr(nullptr), 503 FromNullPtr(false), ToNullPtr(false), 504 FromTD(nullptr), ToTD(nullptr), IsValidFromInt(false), 505 IsValidToInt(false), FromValueDecl(nullptr), ToValueDecl(nullptr), 506 FromAddressOf(false), ToAddressOf(false), FromDefault(false), 507 ToDefault(false), Same(false) {} 508 }; 509 510 /// FlatTree - A flattened tree used to store the DiffNodes. 511 SmallVector<DiffNode, 16> FlatTree; 512 513 /// CurrentNode - The index of the current node being used. 514 unsigned CurrentNode; 515 516 /// NextFreeNode - The index of the next unused node. Used when creating 517 /// child nodes. 518 unsigned NextFreeNode; 519 520 /// ReadNode - The index of the current node being read. 521 unsigned ReadNode; 522 523 public: 524 DiffTree() : 525 CurrentNode(0), NextFreeNode(1) { 526 FlatTree.push_back(DiffNode()); 527 } 528 529 // Node writing functions. 530 /// SetNode - Sets FromTD and ToTD of the current node. 531 void SetNode(TemplateDecl *FromTD, TemplateDecl *ToTD) { 532 FlatTree[CurrentNode].FromTD = FromTD; 533 FlatTree[CurrentNode].ToTD = ToTD; 534 } 535 536 /// SetNode - Sets FromType and ToType of the current node. 537 void SetNode(QualType FromType, QualType ToType) { 538 FlatTree[CurrentNode].FromType = FromType; 539 FlatTree[CurrentNode].ToType = ToType; 540 } 541 542 /// SetNode - Set FromExpr and ToExpr of the current node. 543 void SetNode(Expr *FromExpr, Expr *ToExpr) { 544 FlatTree[CurrentNode].FromExpr = FromExpr; 545 FlatTree[CurrentNode].ToExpr = ToExpr; 546 } 547 548 /// SetNode - Set FromInt and ToInt of the current node. 549 void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt, 550 bool IsValidFromInt, bool IsValidToInt) { 551 FlatTree[CurrentNode].FromInt = FromInt; 552 FlatTree[CurrentNode].ToInt = ToInt; 553 FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt; 554 FlatTree[CurrentNode].IsValidToInt = IsValidToInt; 555 } 556 557 /// SetNode - Set FromQual and ToQual of the current node. 558 void SetNode(Qualifiers FromQual, Qualifiers ToQual) { 559 FlatTree[CurrentNode].FromQual = FromQual; 560 FlatTree[CurrentNode].ToQual = ToQual; 561 } 562 563 /// SetNode - Set FromValueDecl and ToValueDecl of the current node. 564 void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, 565 bool FromAddressOf, bool ToAddressOf) { 566 FlatTree[CurrentNode].FromValueDecl = FromValueDecl; 567 FlatTree[CurrentNode].ToValueDecl = ToValueDecl; 568 FlatTree[CurrentNode].FromAddressOf = FromAddressOf; 569 FlatTree[CurrentNode].ToAddressOf = ToAddressOf; 570 } 571 572 /// SetSame - Sets the same flag of the current node. 573 void SetSame(bool Same) { 574 FlatTree[CurrentNode].Same = Same; 575 } 576 577 /// SetNullPtr - Sets the NullPtr flags of the current node. 578 void SetNullPtr(bool FromNullPtr, bool ToNullPtr) { 579 FlatTree[CurrentNode].FromNullPtr = FromNullPtr; 580 FlatTree[CurrentNode].ToNullPtr = ToNullPtr; 581 } 582 583 /// SetDefault - Sets FromDefault and ToDefault flags of the current node. 584 void SetDefault(bool FromDefault, bool ToDefault) { 585 FlatTree[CurrentNode].FromDefault = FromDefault; 586 FlatTree[CurrentNode].ToDefault = ToDefault; 587 } 588 589 /// SetKind - Sets the current node's type. 590 void SetKind(DiffKind Kind) { 591 FlatTree[CurrentNode].Kind = Kind; 592 } 593 594 /// Up - Changes the node to the parent of the current node. 595 void Up() { 596 CurrentNode = FlatTree[CurrentNode].ParentNode; 597 } 598 599 /// AddNode - Adds a child node to the current node, then sets that node 600 /// node as the current node. 601 void AddNode() { 602 FlatTree.push_back(DiffNode(CurrentNode)); 603 DiffNode &Node = FlatTree[CurrentNode]; 604 if (Node.ChildNode == 0) { 605 // If a child node doesn't exist, add one. 606 Node.ChildNode = NextFreeNode; 607 } else { 608 // If a child node exists, find the last child node and add a 609 // next node to it. 610 unsigned i; 611 for (i = Node.ChildNode; FlatTree[i].NextNode != 0; 612 i = FlatTree[i].NextNode) { 613 } 614 FlatTree[i].NextNode = NextFreeNode; 615 } 616 CurrentNode = NextFreeNode; 617 ++NextFreeNode; 618 } 619 620 // Node reading functions. 621 /// StartTraverse - Prepares the tree for recursive traversal. 622 void StartTraverse() { 623 ReadNode = 0; 624 CurrentNode = NextFreeNode; 625 NextFreeNode = 0; 626 } 627 628 /// Parent - Move the current read node to its parent. 629 void Parent() { 630 ReadNode = FlatTree[ReadNode].ParentNode; 631 } 632 633 /// GetNode - Gets the FromType and ToType. 634 void GetNode(QualType &FromType, QualType &ToType) { 635 FromType = FlatTree[ReadNode].FromType; 636 ToType = FlatTree[ReadNode].ToType; 637 } 638 639 /// GetNode - Gets the FromExpr and ToExpr. 640 void GetNode(Expr *&FromExpr, Expr *&ToExpr) { 641 FromExpr = FlatTree[ReadNode].FromExpr; 642 ToExpr = FlatTree[ReadNode].ToExpr; 643 } 644 645 /// GetNode - Gets the FromTD and ToTD. 646 void GetNode(TemplateDecl *&FromTD, TemplateDecl *&ToTD) { 647 FromTD = FlatTree[ReadNode].FromTD; 648 ToTD = FlatTree[ReadNode].ToTD; 649 } 650 651 /// GetNode - Gets the FromInt and ToInt. 652 void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt, 653 bool &IsValidFromInt, bool &IsValidToInt) { 654 FromInt = FlatTree[ReadNode].FromInt; 655 ToInt = FlatTree[ReadNode].ToInt; 656 IsValidFromInt = FlatTree[ReadNode].IsValidFromInt; 657 IsValidToInt = FlatTree[ReadNode].IsValidToInt; 658 } 659 660 /// GetNode - Gets the FromQual and ToQual. 661 void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) { 662 FromQual = FlatTree[ReadNode].FromQual; 663 ToQual = FlatTree[ReadNode].ToQual; 664 } 665 666 /// GetNode - Gets the FromValueDecl and ToValueDecl. 667 void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl, 668 bool &FromAddressOf, bool &ToAddressOf) { 669 FromValueDecl = FlatTree[ReadNode].FromValueDecl; 670 ToValueDecl = FlatTree[ReadNode].ToValueDecl; 671 FromAddressOf = FlatTree[ReadNode].FromAddressOf; 672 ToAddressOf = FlatTree[ReadNode].ToAddressOf; 673 } 674 675 /// NodeIsSame - Returns true the arguments are the same. 676 bool NodeIsSame() { 677 return FlatTree[ReadNode].Same; 678 } 679 680 /// HasChildrend - Returns true if the node has children. 681 bool HasChildren() { 682 return FlatTree[ReadNode].ChildNode != 0; 683 } 684 685 /// MoveToChild - Moves from the current node to its child. 686 void MoveToChild() { 687 ReadNode = FlatTree[ReadNode].ChildNode; 688 } 689 690 /// AdvanceSibling - If there is a next sibling, advance to it and return 691 /// true. Otherwise, return false. 692 bool AdvanceSibling() { 693 if (FlatTree[ReadNode].NextNode == 0) 694 return false; 695 696 ReadNode = FlatTree[ReadNode].NextNode; 697 return true; 698 } 699 700 /// HasNextSibling - Return true if the node has a next sibling. 701 bool HasNextSibling() { 702 return FlatTree[ReadNode].NextNode != 0; 703 } 704 705 /// FromNullPtr - Returns true if the from argument is null. 706 bool FromNullPtr() { 707 return FlatTree[ReadNode].FromNullPtr; 708 } 709 710 /// ToNullPtr - Returns true if the to argument is null. 711 bool ToNullPtr() { 712 return FlatTree[ReadNode].ToNullPtr; 713 } 714 715 /// FromDefault - Return true if the from argument is the default. 716 bool FromDefault() { 717 return FlatTree[ReadNode].FromDefault; 718 } 719 720 /// ToDefault - Return true if the to argument is the default. 721 bool ToDefault() { 722 return FlatTree[ReadNode].ToDefault; 723 } 724 725 /// Empty - Returns true if the tree has no information. 726 bool Empty() { 727 return GetKind() == Invalid; 728 } 729 730 /// GetKind - Returns the current node's type. 731 DiffKind GetKind() { 732 return FlatTree[ReadNode].Kind; 733 } 734 }; 735 736 DiffTree Tree; 737 738 /// TSTiterator - an iterator that is used to enter a 739 /// TemplateSpecializationType and read TemplateArguments inside template 740 /// parameter packs in order with the rest of the TemplateArguments. 741 struct TSTiterator { 742 typedef const TemplateArgument& reference; 743 typedef const TemplateArgument* pointer; 744 745 /// TST - the template specialization whose arguments this iterator 746 /// traverse over. 747 const TemplateSpecializationType *TST; 748 749 /// DesugarTST - desugared template specialization used to extract 750 /// default argument information 751 const TemplateSpecializationType *DesugarTST; 752 753 /// Index - the index of the template argument in TST. 754 unsigned Index; 755 756 /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA 757 /// points to a TemplateArgument within a parameter pack. 758 TemplateArgument::pack_iterator CurrentTA; 759 760 /// EndTA - the end iterator of a parameter pack 761 TemplateArgument::pack_iterator EndTA; 762 763 /// TSTiterator - Constructs an iterator and sets it to the first template 764 /// argument. 765 TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) 766 : TST(TST), 767 DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())), 768 Index(0), CurrentTA(nullptr), EndTA(nullptr) { 769 if (isEnd()) return; 770 771 // Set to first template argument. If not a parameter pack, done. 772 TemplateArgument TA = TST->getArg(0); 773 if (TA.getKind() != TemplateArgument::Pack) return; 774 775 // Start looking into the parameter pack. 776 CurrentTA = TA.pack_begin(); 777 EndTA = TA.pack_end(); 778 779 // Found a valid template argument. 780 if (CurrentTA != EndTA) return; 781 782 // Parameter pack is empty, use the increment to get to a valid 783 // template argument. 784 ++(*this); 785 } 786 787 /// isEnd - Returns true if the iterator is one past the end. 788 bool isEnd() const { 789 return Index >= TST->getNumArgs(); 790 } 791 792 /// &operator++ - Increment the iterator to the next template argument. 793 TSTiterator &operator++() { 794 // After the end, Index should be the default argument position in 795 // DesugarTST, if it exists. 796 if (isEnd()) { 797 ++Index; 798 return *this; 799 } 800 801 // If in a parameter pack, advance in the parameter pack. 802 if (CurrentTA != EndTA) { 803 ++CurrentTA; 804 if (CurrentTA != EndTA) 805 return *this; 806 } 807 808 // Loop until a template argument is found, or the end is reached. 809 while (true) { 810 // Advance to the next template argument. Break if reached the end. 811 if (++Index == TST->getNumArgs()) break; 812 813 // If the TemplateArgument is not a parameter pack, done. 814 TemplateArgument TA = TST->getArg(Index); 815 if (TA.getKind() != TemplateArgument::Pack) break; 816 817 // Handle parameter packs. 818 CurrentTA = TA.pack_begin(); 819 EndTA = TA.pack_end(); 820 821 // If the parameter pack is empty, try to advance again. 822 if (CurrentTA != EndTA) break; 823 } 824 return *this; 825 } 826 827 /// operator* - Returns the appropriate TemplateArgument. 828 reference operator*() const { 829 assert(!isEnd() && "Index exceeds number of arguments."); 830 if (CurrentTA == EndTA) 831 return TST->getArg(Index); 832 else 833 return *CurrentTA; 834 } 835 836 /// operator-> - Allow access to the underlying TemplateArgument. 837 pointer operator->() const { 838 return &operator*(); 839 } 840 841 /// getDesugar - Returns the deduced template argument from DesguarTST 842 reference getDesugar() const { 843 return DesugarTST->getArg(Index); 844 } 845 }; 846 847 // These functions build up the template diff tree, including functions to 848 // retrieve and compare template arguments. 849 850 static const TemplateSpecializationType * GetTemplateSpecializationType( 851 ASTContext &Context, QualType Ty) { 852 if (const TemplateSpecializationType *TST = 853 Ty->getAs<TemplateSpecializationType>()) 854 return TST; 855 856 const RecordType *RT = Ty->getAs<RecordType>(); 857 858 if (!RT) 859 return nullptr; 860 861 const ClassTemplateSpecializationDecl *CTSD = 862 dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); 863 864 if (!CTSD) 865 return nullptr; 866 867 Ty = Context.getTemplateSpecializationType( 868 TemplateName(CTSD->getSpecializedTemplate()), 869 CTSD->getTemplateArgs().data(), 870 CTSD->getTemplateArgs().size(), 871 Ty.getLocalUnqualifiedType().getCanonicalType()); 872 873 return Ty->getAs<TemplateSpecializationType>(); 874 } 875 876 /// DiffTypes - Fills a DiffNode with information about a type difference. 877 void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter, 878 TemplateTypeParmDecl *FromDefaultTypeDecl, 879 TemplateTypeParmDecl *ToDefaultTypeDecl) { 880 QualType FromType = GetType(FromIter, FromDefaultTypeDecl); 881 QualType ToType = GetType(ToIter, ToDefaultTypeDecl); 882 883 Tree.SetNode(FromType, ToType); 884 Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), 885 ToIter.isEnd() && !ToType.isNull()); 886 Tree.SetKind(DiffTree::Type); 887 if (FromType.isNull() || ToType.isNull()) 888 return; 889 890 if (Context.hasSameType(FromType, ToType)) { 891 Tree.SetSame(true); 892 return; 893 } 894 895 const TemplateSpecializationType *FromArgTST = 896 GetTemplateSpecializationType(Context, FromType); 897 if (!FromArgTST) 898 return; 899 900 const TemplateSpecializationType *ToArgTST = 901 GetTemplateSpecializationType(Context, ToType); 902 if (!ToArgTST) 903 return; 904 905 if (!hasSameTemplate(FromArgTST, ToArgTST)) 906 return; 907 908 Qualifiers FromQual = FromType.getQualifiers(), 909 ToQual = ToType.getQualifiers(); 910 FromQual -= QualType(FromArgTST, 0).getQualifiers(); 911 ToQual -= QualType(ToArgTST, 0).getQualifiers(); 912 Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(), 913 ToArgTST->getTemplateName().getAsTemplateDecl()); 914 Tree.SetNode(FromQual, ToQual); 915 Tree.SetKind(DiffTree::Template); 916 DiffTemplate(FromArgTST, ToArgTST); 917 } 918 919 /// DiffTemplateTemplates - Fills a DiffNode with information about a 920 /// template template difference. 921 void DiffTemplateTemplates(const TSTiterator &FromIter, 922 const TSTiterator &ToIter, 923 TemplateTemplateParmDecl *FromDefaultTemplateDecl, 924 TemplateTemplateParmDecl *ToDefaultTemplateDecl) { 925 TemplateDecl *FromDecl = GetTemplateDecl(FromIter, FromDefaultTemplateDecl); 926 TemplateDecl *ToDecl = GetTemplateDecl(ToIter, ToDefaultTemplateDecl); 927 Tree.SetNode(FromDecl, ToDecl); 928 Tree.SetSame(FromDecl && ToDecl && 929 FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); 930 Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl); 931 Tree.SetKind(DiffTree::TemplateTemplate); 932 } 933 934 /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes 935 static void InitializeNonTypeDiffVariables( 936 ASTContext &Context, const TSTiterator &Iter, 937 NonTypeTemplateParmDecl *Default, bool &HasInt, bool &HasValueDecl, 938 bool &IsNullPtr, Expr *&E, llvm::APSInt &Value, ValueDecl *&VD) { 939 HasInt = !Iter.isEnd() && Iter->getKind() == TemplateArgument::Integral; 940 941 HasValueDecl = 942 !Iter.isEnd() && Iter->getKind() == TemplateArgument::Declaration; 943 944 IsNullPtr = !Iter.isEnd() && Iter->getKind() == TemplateArgument::NullPtr; 945 946 if (HasInt) 947 Value = Iter->getAsIntegral(); 948 else if (HasValueDecl) 949 VD = Iter->getAsDecl(); 950 else if (!IsNullPtr) 951 E = GetExpr(Iter, Default); 952 953 if (E && Default->getType()->isPointerType()) 954 IsNullPtr = CheckForNullPtr(Context, E); 955 } 956 957 /// NeedsAddressOf - Helper function for DiffNonTypes. Returns true if the 958 /// ValueDecl needs a '&' when printed. 959 static bool NeedsAddressOf(ValueDecl *VD, Expr *E, 960 NonTypeTemplateParmDecl *Default) { 961 if (!VD) 962 return false; 963 964 if (E) { 965 if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParens())) { 966 if (UO->getOpcode() == UO_AddrOf) { 967 return true; 968 } 969 } 970 return false; 971 } 972 973 if (!Default->getType()->isReferenceType()) { 974 return true; 975 } 976 977 return false; 978 } 979 980 /// DiffNonTypes - Handles any template parameters not handled by DiffTypes 981 /// of DiffTemplatesTemplates, such as integer and declaration parameters. 982 void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter, 983 NonTypeTemplateParmDecl *FromDefaultNonTypeDecl, 984 NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) { 985 Expr *FromExpr = nullptr, *ToExpr = nullptr; 986 llvm::APSInt FromInt, ToInt; 987 ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr; 988 bool HasFromInt = false, HasToInt = false, HasFromValueDecl = false, 989 HasToValueDecl = false, FromNullPtr = false, ToNullPtr = false; 990 InitializeNonTypeDiffVariables(Context, FromIter, FromDefaultNonTypeDecl, 991 HasFromInt, HasFromValueDecl, FromNullPtr, 992 FromExpr, FromInt, FromValueDecl); 993 InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, 994 HasToInt, HasToValueDecl, ToNullPtr, 995 ToExpr, ToInt, ToValueDecl); 996 997 assert(((!HasFromInt && !HasToInt) || 998 (!HasFromValueDecl && !HasToValueDecl)) && 999 "Template argument cannot be both integer and declaration"); 1000 1001 if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { 1002 Tree.SetNode(FromExpr, ToExpr); 1003 Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr); 1004 if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType()) { 1005 if (FromExpr) 1006 HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt); 1007 if (ToExpr) 1008 HasToInt = GetInt(Context, ToIter, ToExpr, ToInt); 1009 } 1010 if (HasFromInt && HasToInt) { 1011 Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); 1012 Tree.SetSame(FromInt == ToInt); 1013 Tree.SetKind(DiffTree::Integer); 1014 } else if (HasFromInt || HasToInt) { 1015 Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); 1016 Tree.SetSame(false); 1017 Tree.SetKind(DiffTree::Integer); 1018 } else { 1019 Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr) || 1020 (FromNullPtr && ToNullPtr)); 1021 Tree.SetNullPtr(FromNullPtr, ToNullPtr); 1022 Tree.SetKind(DiffTree::Expression); 1023 } 1024 return; 1025 } 1026 1027 if (HasFromInt || HasToInt) { 1028 if (!HasFromInt && FromExpr) 1029 HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt); 1030 if (!HasToInt && ToExpr) 1031 HasToInt = GetInt(Context, ToIter, ToExpr, ToInt); 1032 Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); 1033 if (HasFromInt && HasToInt) { 1034 Tree.SetSame(FromInt == ToInt); 1035 } else { 1036 Tree.SetSame(false); 1037 } 1038 Tree.SetDefault(FromIter.isEnd() && HasFromInt, 1039 ToIter.isEnd() && HasToInt); 1040 Tree.SetKind(DiffTree::Integer); 1041 return; 1042 } 1043 1044 if (!HasFromValueDecl && FromExpr) 1045 FromValueDecl = GetValueDecl(FromIter, FromExpr); 1046 if (!HasToValueDecl && ToExpr) 1047 ToValueDecl = GetValueDecl(ToIter, ToExpr); 1048 1049 bool FromAddressOf = 1050 NeedsAddressOf(FromValueDecl, FromExpr, FromDefaultNonTypeDecl); 1051 bool ToAddressOf = 1052 NeedsAddressOf(ToValueDecl, ToExpr, ToDefaultNonTypeDecl); 1053 1054 Tree.SetNullPtr(FromNullPtr, ToNullPtr); 1055 Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); 1056 Tree.SetSame(FromValueDecl && ToValueDecl && 1057 FromValueDecl->getCanonicalDecl() == 1058 ToValueDecl->getCanonicalDecl()); 1059 Tree.SetDefault(FromIter.isEnd() && FromValueDecl, 1060 ToIter.isEnd() && ToValueDecl); 1061 Tree.SetKind(DiffTree::Declaration); 1062 } 1063 1064 /// DiffTemplate - recursively visits template arguments and stores the 1065 /// argument info into a tree. 1066 void DiffTemplate(const TemplateSpecializationType *FromTST, 1067 const TemplateSpecializationType *ToTST) { 1068 // Begin descent into diffing template tree. 1069 TemplateParameterList *ParamsFrom = 1070 FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); 1071 TemplateParameterList *ParamsTo = 1072 ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); 1073 unsigned TotalArgs = 0; 1074 for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST); 1075 !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) { 1076 Tree.AddNode(); 1077 1078 // Get the parameter at index TotalArgs. If index is larger 1079 // than the total number of parameters, then there is an 1080 // argument pack, so re-use the last parameter. 1081 unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1); 1082 unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1); 1083 NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex); 1084 NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex); 1085 1086 TemplateTypeParmDecl *FromDefaultTypeDecl = 1087 dyn_cast<TemplateTypeParmDecl>(FromParamND); 1088 TemplateTypeParmDecl *ToDefaultTypeDecl = 1089 dyn_cast<TemplateTypeParmDecl>(ToParamND); 1090 if (FromDefaultTypeDecl && ToDefaultTypeDecl) 1091 DiffTypes(FromIter, ToIter, FromDefaultTypeDecl, ToDefaultTypeDecl); 1092 1093 TemplateTemplateParmDecl *FromDefaultTemplateDecl = 1094 dyn_cast<TemplateTemplateParmDecl>(FromParamND); 1095 TemplateTemplateParmDecl *ToDefaultTemplateDecl = 1096 dyn_cast<TemplateTemplateParmDecl>(ToParamND); 1097 if (FromDefaultTemplateDecl && ToDefaultTemplateDecl) 1098 DiffTemplateTemplates(FromIter, ToIter, FromDefaultTemplateDecl, 1099 ToDefaultTemplateDecl); 1100 1101 NonTypeTemplateParmDecl *FromDefaultNonTypeDecl = 1102 dyn_cast<NonTypeTemplateParmDecl>(FromParamND); 1103 NonTypeTemplateParmDecl *ToDefaultNonTypeDecl = 1104 dyn_cast<NonTypeTemplateParmDecl>(ToParamND); 1105 if (FromDefaultNonTypeDecl && ToDefaultNonTypeDecl) 1106 DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl, 1107 ToDefaultNonTypeDecl); 1108 1109 ++FromIter; 1110 ++ToIter; 1111 Tree.Up(); 1112 } 1113 } 1114 1115 /// makeTemplateList - Dump every template alias into the vector. 1116 static void makeTemplateList( 1117 SmallVectorImpl<const TemplateSpecializationType *> &TemplateList, 1118 const TemplateSpecializationType *TST) { 1119 while (TST) { 1120 TemplateList.push_back(TST); 1121 if (!TST->isTypeAlias()) 1122 return; 1123 TST = TST->getAliasedType()->getAs<TemplateSpecializationType>(); 1124 } 1125 } 1126 1127 /// hasSameBaseTemplate - Returns true when the base templates are the same, 1128 /// even if the template arguments are not. 1129 static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST, 1130 const TemplateSpecializationType *ToTST) { 1131 return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() == 1132 ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl(); 1133 } 1134 1135 /// hasSameTemplate - Returns true if both types are specialized from the 1136 /// same template declaration. If they come from different template aliases, 1137 /// do a parallel ascension search to determine the highest template alias in 1138 /// common and set the arguments to them. 1139 static bool hasSameTemplate(const TemplateSpecializationType *&FromTST, 1140 const TemplateSpecializationType *&ToTST) { 1141 // Check the top templates if they are the same. 1142 if (hasSameBaseTemplate(FromTST, ToTST)) 1143 return true; 1144 1145 // Create vectors of template aliases. 1146 SmallVector<const TemplateSpecializationType*, 1> FromTemplateList, 1147 ToTemplateList; 1148 1149 makeTemplateList(FromTemplateList, FromTST); 1150 makeTemplateList(ToTemplateList, ToTST); 1151 1152 SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator 1153 FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(), 1154 ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend(); 1155 1156 // Check if the lowest template types are the same. If not, return. 1157 if (!hasSameBaseTemplate(*FromIter, *ToIter)) 1158 return false; 1159 1160 // Begin searching up the template aliases. The bottom most template 1161 // matches so move up until one pair does not match. Use the template 1162 // right before that one. 1163 for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) { 1164 if (!hasSameBaseTemplate(*FromIter, *ToIter)) 1165 break; 1166 } 1167 1168 FromTST = FromIter[-1]; 1169 ToTST = ToIter[-1]; 1170 1171 return true; 1172 } 1173 1174 /// GetType - Retrieves the template type arguments, including default 1175 /// arguments. 1176 static QualType GetType(const TSTiterator &Iter, 1177 TemplateTypeParmDecl *DefaultTTPD) { 1178 bool isVariadic = DefaultTTPD->isParameterPack(); 1179 1180 if (!Iter.isEnd()) 1181 return Iter->getAsType(); 1182 if (isVariadic) 1183 return QualType(); 1184 1185 QualType ArgType = DefaultTTPD->getDefaultArgument(); 1186 if (ArgType->isDependentType()) 1187 return Iter.getDesugar().getAsType(); 1188 1189 return ArgType; 1190 } 1191 1192 /// GetExpr - Retrieves the template expression argument, including default 1193 /// arguments. 1194 static Expr *GetExpr(const TSTiterator &Iter, 1195 NonTypeTemplateParmDecl *DefaultNTTPD) { 1196 Expr *ArgExpr = nullptr; 1197 bool isVariadic = DefaultNTTPD->isParameterPack(); 1198 1199 if (!Iter.isEnd()) 1200 ArgExpr = Iter->getAsExpr(); 1201 else if (!isVariadic) 1202 ArgExpr = DefaultNTTPD->getDefaultArgument(); 1203 1204 if (ArgExpr) 1205 while (SubstNonTypeTemplateParmExpr *SNTTPE = 1206 dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr)) 1207 ArgExpr = SNTTPE->getReplacement(); 1208 1209 return ArgExpr; 1210 } 1211 1212 /// GetInt - Retrieves the template integer argument, including evaluating 1213 /// default arguments. 1214 static bool GetInt(ASTContext &Context, const TSTiterator &Iter, 1215 Expr *ArgExpr, llvm::APSInt &Int) { 1216 // Default, value-depenedent expressions require fetching 1217 // from the desugared TemplateArgument, otherwise expression needs to 1218 // be evaluatable. 1219 if (Iter.isEnd() && ArgExpr->isValueDependent()) { 1220 switch (Iter.getDesugar().getKind()) { 1221 case TemplateArgument::Integral: 1222 Int = Iter.getDesugar().getAsIntegral(); 1223 return true; 1224 case TemplateArgument::Expression: 1225 ArgExpr = Iter.getDesugar().getAsExpr(); 1226 Int = ArgExpr->EvaluateKnownConstInt(Context); 1227 return true; 1228 default: 1229 llvm_unreachable("Unexpected template argument kind"); 1230 } 1231 } else if (ArgExpr->isEvaluatable(Context)) { 1232 Int = ArgExpr->EvaluateKnownConstInt(Context); 1233 return true; 1234 } 1235 1236 return false; 1237 } 1238 1239 /// GetValueDecl - Retrieves the template Decl argument, including 1240 /// default expression argument. 1241 static ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { 1242 // Default, value-depenedent expressions require fetching 1243 // from the desugared TemplateArgument 1244 if (Iter.isEnd() && ArgExpr->isValueDependent()) 1245 switch (Iter.getDesugar().getKind()) { 1246 case TemplateArgument::Declaration: 1247 return Iter.getDesugar().getAsDecl(); 1248 case TemplateArgument::Expression: 1249 ArgExpr = Iter.getDesugar().getAsExpr(); 1250 return cast<DeclRefExpr>(ArgExpr)->getDecl(); 1251 default: 1252 llvm_unreachable("Unexpected template argument kind"); 1253 } 1254 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr); 1255 if (!DRE) { 1256 UnaryOperator *UO = dyn_cast<UnaryOperator>(ArgExpr->IgnoreParens()); 1257 if (!UO) 1258 return nullptr; 1259 DRE = cast<DeclRefExpr>(UO->getSubExpr()); 1260 } 1261 1262 return DRE->getDecl(); 1263 } 1264 1265 /// CheckForNullPtr - returns true if the expression can be evaluated as 1266 /// a null pointer 1267 static bool CheckForNullPtr(ASTContext &Context, Expr *E) { 1268 assert(E && "Expected expression"); 1269 1270 E = E->IgnoreParenCasts(); 1271 if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) 1272 return true; 1273 1274 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); 1275 if (!DRE) 1276 return false; 1277 1278 VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); 1279 if (!VD || !VD->hasInit()) 1280 return false; 1281 1282 return VD->getInit()->IgnoreParenCasts()->isNullPointerConstant( 1283 Context, Expr::NPC_ValueDependentIsNull); 1284 } 1285 1286 /// GetTemplateDecl - Retrieves the template template arguments, including 1287 /// default arguments. 1288 static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, 1289 TemplateTemplateParmDecl *DefaultTTPD) { 1290 bool isVariadic = DefaultTTPD->isParameterPack(); 1291 1292 TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument(); 1293 TemplateDecl *DefaultTD = nullptr; 1294 if (TA.getKind() != TemplateArgument::Null) 1295 DefaultTD = TA.getAsTemplate().getAsTemplateDecl(); 1296 1297 if (!Iter.isEnd()) 1298 return Iter->getAsTemplate().getAsTemplateDecl(); 1299 if (!isVariadic) 1300 return DefaultTD; 1301 1302 return nullptr; 1303 } 1304 1305 /// IsEqualExpr - Returns true if the expressions evaluate to the same value. 1306 static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) { 1307 if (FromExpr == ToExpr) 1308 return true; 1309 1310 if (!FromExpr || !ToExpr) 1311 return false; 1312 1313 DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr->IgnoreParens()), 1314 *ToDRE = dyn_cast<DeclRefExpr>(ToExpr->IgnoreParens()); 1315 1316 if (FromDRE || ToDRE) { 1317 if (!FromDRE || !ToDRE) 1318 return false; 1319 return FromDRE->getDecl() == ToDRE->getDecl(); 1320 } 1321 1322 Expr::EvalResult FromResult, ToResult; 1323 if (!FromExpr->EvaluateAsRValue(FromResult, Context) || 1324 !ToExpr->EvaluateAsRValue(ToResult, Context)) { 1325 llvm::FoldingSetNodeID FromID, ToID; 1326 FromExpr->Profile(FromID, Context, true); 1327 ToExpr->Profile(ToID, Context, true); 1328 return FromID == ToID; 1329 } 1330 1331 APValue &FromVal = FromResult.Val; 1332 APValue &ToVal = ToResult.Val; 1333 1334 if (FromVal.getKind() != ToVal.getKind()) return false; 1335 1336 switch (FromVal.getKind()) { 1337 case APValue::Int: 1338 return FromVal.getInt() == ToVal.getInt(); 1339 case APValue::LValue: { 1340 APValue::LValueBase FromBase = FromVal.getLValueBase(); 1341 APValue::LValueBase ToBase = ToVal.getLValueBase(); 1342 if (FromBase.isNull() && ToBase.isNull()) 1343 return true; 1344 if (FromBase.isNull() || ToBase.isNull()) 1345 return false; 1346 return FromBase.get<const ValueDecl*>() == 1347 ToBase.get<const ValueDecl*>(); 1348 } 1349 case APValue::MemberPointer: 1350 return FromVal.getMemberPointerDecl() == ToVal.getMemberPointerDecl(); 1351 default: 1352 llvm_unreachable("Unknown template argument expression."); 1353 } 1354 } 1355 1356 // These functions converts the tree representation of the template 1357 // differences into the internal character vector. 1358 1359 /// TreeToString - Converts the Tree object into a character stream which 1360 /// will later be turned into the output string. 1361 void TreeToString(int Indent = 1) { 1362 if (PrintTree) { 1363 OS << '\n'; 1364 OS.indent(2 * Indent); 1365 ++Indent; 1366 } 1367 1368 // Handle cases where the difference is not templates with different 1369 // arguments. 1370 switch (Tree.GetKind()) { 1371 case DiffTree::Invalid: 1372 llvm_unreachable("Template diffing failed with bad DiffNode"); 1373 case DiffTree::Type: { 1374 QualType FromType, ToType; 1375 Tree.GetNode(FromType, ToType); 1376 PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(), 1377 Tree.NodeIsSame()); 1378 return; 1379 } 1380 case DiffTree::Expression: { 1381 Expr *FromExpr, *ToExpr; 1382 Tree.GetNode(FromExpr, ToExpr); 1383 PrintExpr(FromExpr, ToExpr, Tree.FromNullPtr(), Tree.ToNullPtr(), 1384 Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); 1385 return; 1386 } 1387 case DiffTree::TemplateTemplate: { 1388 TemplateDecl *FromTD, *ToTD; 1389 Tree.GetNode(FromTD, ToTD); 1390 PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(), 1391 Tree.ToDefault(), Tree.NodeIsSame()); 1392 return; 1393 } 1394 case DiffTree::Integer: { 1395 llvm::APSInt FromInt, ToInt; 1396 Expr *FromExpr, *ToExpr; 1397 bool IsValidFromInt, IsValidToInt; 1398 Tree.GetNode(FromExpr, ToExpr); 1399 Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt); 1400 PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, 1401 FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), 1402 Tree.NodeIsSame()); 1403 return; 1404 } 1405 case DiffTree::Declaration: { 1406 ValueDecl *FromValueDecl, *ToValueDecl; 1407 bool FromAddressOf, ToAddressOf; 1408 Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); 1409 PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf, 1410 Tree.FromNullPtr(), Tree.ToNullPtr(), Tree.FromDefault(), 1411 Tree.ToDefault(), Tree.NodeIsSame()); 1412 return; 1413 } 1414 case DiffTree::Template: { 1415 // Node is root of template. Recurse on children. 1416 TemplateDecl *FromTD, *ToTD; 1417 Tree.GetNode(FromTD, ToTD); 1418 1419 if (!Tree.HasChildren()) { 1420 // If we're dealing with a template specialization with zero 1421 // arguments, there are no children; special-case this. 1422 OS << FromTD->getNameAsString() << "<>"; 1423 return; 1424 } 1425 1426 Qualifiers FromQual, ToQual; 1427 Tree.GetNode(FromQual, ToQual); 1428 PrintQualifiers(FromQual, ToQual); 1429 1430 OS << FromTD->getNameAsString() << '<'; 1431 Tree.MoveToChild(); 1432 unsigned NumElideArgs = 0; 1433 do { 1434 if (ElideType) { 1435 if (Tree.NodeIsSame()) { 1436 ++NumElideArgs; 1437 continue; 1438 } 1439 if (NumElideArgs > 0) { 1440 PrintElideArgs(NumElideArgs, Indent); 1441 NumElideArgs = 0; 1442 OS << ", "; 1443 } 1444 } 1445 TreeToString(Indent); 1446 if (Tree.HasNextSibling()) 1447 OS << ", "; 1448 } while (Tree.AdvanceSibling()); 1449 if (NumElideArgs > 0) 1450 PrintElideArgs(NumElideArgs, Indent); 1451 1452 Tree.Parent(); 1453 OS << ">"; 1454 return; 1455 } 1456 } 1457 } 1458 1459 // To signal to the text printer that a certain text needs to be bolded, 1460 // a special character is injected into the character stream which the 1461 // text printer will later strip out. 1462 1463 /// Bold - Start bolding text. 1464 void Bold() { 1465 assert(!IsBold && "Attempting to bold text that is already bold."); 1466 IsBold = true; 1467 if (ShowColor) 1468 OS << ToggleHighlight; 1469 } 1470 1471 /// Unbold - Stop bolding text. 1472 void Unbold() { 1473 assert(IsBold && "Attempting to remove bold from unbold text."); 1474 IsBold = false; 1475 if (ShowColor) 1476 OS << ToggleHighlight; 1477 } 1478 1479 // Functions to print out the arguments and highlighting the difference. 1480 1481 /// PrintTypeNames - prints the typenames, bolding differences. Will detect 1482 /// typenames that are the same and attempt to disambiguate them by using 1483 /// canonical typenames. 1484 void PrintTypeNames(QualType FromType, QualType ToType, 1485 bool FromDefault, bool ToDefault, bool Same) { 1486 assert((!FromType.isNull() || !ToType.isNull()) && 1487 "Only one template argument may be missing."); 1488 1489 if (Same) { 1490 OS << FromType.getAsString(Policy); 1491 return; 1492 } 1493 1494 if (!FromType.isNull() && !ToType.isNull() && 1495 FromType.getLocalUnqualifiedType() == 1496 ToType.getLocalUnqualifiedType()) { 1497 Qualifiers FromQual = FromType.getLocalQualifiers(), 1498 ToQual = ToType.getLocalQualifiers(); 1499 PrintQualifiers(FromQual, ToQual); 1500 FromType.getLocalUnqualifiedType().print(OS, Policy); 1501 return; 1502 } 1503 1504 std::string FromTypeStr = FromType.isNull() ? "(no argument)" 1505 : FromType.getAsString(Policy); 1506 std::string ToTypeStr = ToType.isNull() ? "(no argument)" 1507 : ToType.getAsString(Policy); 1508 // Switch to canonical typename if it is better. 1509 // TODO: merge this with other aka printing above. 1510 if (FromTypeStr == ToTypeStr) { 1511 std::string FromCanTypeStr = 1512 FromType.getCanonicalType().getAsString(Policy); 1513 std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy); 1514 if (FromCanTypeStr != ToCanTypeStr) { 1515 FromTypeStr = FromCanTypeStr; 1516 ToTypeStr = ToCanTypeStr; 1517 } 1518 } 1519 1520 if (PrintTree) OS << '['; 1521 OS << (FromDefault ? "(default) " : ""); 1522 Bold(); 1523 OS << FromTypeStr; 1524 Unbold(); 1525 if (PrintTree) { 1526 OS << " != " << (ToDefault ? "(default) " : ""); 1527 Bold(); 1528 OS << ToTypeStr; 1529 Unbold(); 1530 OS << "]"; 1531 } 1532 return; 1533 } 1534 1535 /// PrintExpr - Prints out the expr template arguments, highlighting argument 1536 /// differences. 1537 void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromNullPtr, 1538 bool ToNullPtr, bool FromDefault, bool ToDefault, bool Same) { 1539 assert((FromExpr || ToExpr) && 1540 "Only one template argument may be missing."); 1541 if (Same) { 1542 PrintExpr(FromExpr, FromNullPtr); 1543 } else if (!PrintTree) { 1544 OS << (FromDefault ? "(default) " : ""); 1545 Bold(); 1546 PrintExpr(FromExpr, FromNullPtr); 1547 Unbold(); 1548 } else { 1549 OS << (FromDefault ? "[(default) " : "["); 1550 Bold(); 1551 PrintExpr(FromExpr, FromNullPtr); 1552 Unbold(); 1553 OS << " != " << (ToDefault ? "(default) " : ""); 1554 Bold(); 1555 PrintExpr(ToExpr, ToNullPtr); 1556 Unbold(); 1557 OS << ']'; 1558 } 1559 } 1560 1561 /// PrintExpr - Actual formatting and printing of expressions. 1562 void PrintExpr(const Expr *E, bool NullPtr = false) { 1563 if (E) { 1564 E->printPretty(OS, nullptr, Policy); 1565 return; 1566 } 1567 if (NullPtr) { 1568 OS << "nullptr"; 1569 return; 1570 } 1571 OS << "(no argument)"; 1572 } 1573 1574 /// PrintTemplateTemplate - Handles printing of template template arguments, 1575 /// highlighting argument differences. 1576 void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD, 1577 bool FromDefault, bool ToDefault, bool Same) { 1578 assert((FromTD || ToTD) && "Only one template argument may be missing."); 1579 1580 std::string FromName = FromTD ? FromTD->getName() : "(no argument)"; 1581 std::string ToName = ToTD ? ToTD->getName() : "(no argument)"; 1582 if (FromTD && ToTD && FromName == ToName) { 1583 FromName = FromTD->getQualifiedNameAsString(); 1584 ToName = ToTD->getQualifiedNameAsString(); 1585 } 1586 1587 if (Same) { 1588 OS << "template " << FromTD->getNameAsString(); 1589 } else if (!PrintTree) { 1590 OS << (FromDefault ? "(default) template " : "template "); 1591 Bold(); 1592 OS << FromName; 1593 Unbold(); 1594 } else { 1595 OS << (FromDefault ? "[(default) template " : "[template "); 1596 Bold(); 1597 OS << FromName; 1598 Unbold(); 1599 OS << " != " << (ToDefault ? "(default) template " : "template "); 1600 Bold(); 1601 OS << ToName; 1602 Unbold(); 1603 OS << ']'; 1604 } 1605 } 1606 1607 /// PrintAPSInt - Handles printing of integral arguments, highlighting 1608 /// argument differences. 1609 void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt, 1610 bool IsValidFromInt, bool IsValidToInt, Expr *FromExpr, 1611 Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) { 1612 assert((IsValidFromInt || IsValidToInt) && 1613 "Only one integral argument may be missing."); 1614 1615 if (Same) { 1616 OS << FromInt.toString(10); 1617 } else if (!PrintTree) { 1618 OS << (FromDefault ? "(default) " : ""); 1619 PrintAPSInt(FromInt, FromExpr, IsValidFromInt); 1620 } else { 1621 OS << (FromDefault ? "[(default) " : "["); 1622 PrintAPSInt(FromInt, FromExpr, IsValidFromInt); 1623 OS << " != " << (ToDefault ? "(default) " : ""); 1624 PrintAPSInt(ToInt, ToExpr, IsValidToInt); 1625 OS << ']'; 1626 } 1627 } 1628 1629 /// PrintAPSInt - If valid, print the APSInt. If the expression is 1630 /// gives more information, print it too. 1631 void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid) { 1632 Bold(); 1633 if (Valid) { 1634 if (HasExtraInfo(E)) { 1635 PrintExpr(E); 1636 Unbold(); 1637 OS << " aka "; 1638 Bold(); 1639 } 1640 OS << Val.toString(10); 1641 } else if (E) { 1642 PrintExpr(E); 1643 } else { 1644 OS << "(no argument)"; 1645 } 1646 Unbold(); 1647 } 1648 1649 /// HasExtraInfo - Returns true if E is not an integer literal or the 1650 /// negation of an integer literal 1651 bool HasExtraInfo(Expr *E) { 1652 if (!E) return false; 1653 1654 E = E->IgnoreImpCasts(); 1655 1656 if (isa<IntegerLiteral>(E)) return false; 1657 1658 if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) 1659 if (UO->getOpcode() == UO_Minus) 1660 if (isa<IntegerLiteral>(UO->getSubExpr())) 1661 return false; 1662 1663 return true; 1664 } 1665 1666 void PrintValueDecl(ValueDecl *VD, bool AddressOf, bool NullPtr) { 1667 if (VD) { 1668 if (AddressOf) 1669 OS << "&"; 1670 OS << VD->getName(); 1671 return; 1672 } 1673 1674 if (NullPtr) { 1675 OS << "nullptr"; 1676 return; 1677 } 1678 1679 OS << "(no argument)"; 1680 } 1681 1682 /// PrintDecl - Handles printing of Decl arguments, highlighting 1683 /// argument differences. 1684 void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, 1685 bool FromAddressOf, bool ToAddressOf, bool FromNullPtr, 1686 bool ToNullPtr, bool FromDefault, bool ToDefault, 1687 bool Same) { 1688 assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) && 1689 "Only one Decl argument may be NULL"); 1690 1691 if (Same) { 1692 PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); 1693 } else if (!PrintTree) { 1694 OS << (FromDefault ? "(default) " : ""); 1695 Bold(); 1696 PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); 1697 Unbold(); 1698 } else { 1699 OS << (FromDefault ? "[(default) " : "["); 1700 Bold(); 1701 PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); 1702 Unbold(); 1703 OS << " != " << (ToDefault ? "(default) " : ""); 1704 Bold(); 1705 PrintValueDecl(ToValueDecl, ToAddressOf, ToNullPtr); 1706 Unbold(); 1707 OS << ']'; 1708 } 1709 1710 } 1711 1712 // Prints the appropriate placeholder for elided template arguments. 1713 void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) { 1714 if (PrintTree) { 1715 OS << '\n'; 1716 for (unsigned i = 0; i < Indent; ++i) 1717 OS << " "; 1718 } 1719 if (NumElideArgs == 0) return; 1720 if (NumElideArgs == 1) 1721 OS << "[...]"; 1722 else 1723 OS << "[" << NumElideArgs << " * ...]"; 1724 } 1725 1726 // Prints and highlights differences in Qualifiers. 1727 void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) { 1728 // Both types have no qualifiers 1729 if (FromQual.empty() && ToQual.empty()) 1730 return; 1731 1732 // Both types have same qualifiers 1733 if (FromQual == ToQual) { 1734 PrintQualifier(FromQual, /*ApplyBold*/false); 1735 return; 1736 } 1737 1738 // Find common qualifiers and strip them from FromQual and ToQual. 1739 Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual, 1740 ToQual); 1741 1742 // The qualifiers are printed before the template name. 1743 // Inline printing: 1744 // The common qualifiers are printed. Then, qualifiers only in this type 1745 // are printed and highlighted. Finally, qualifiers only in the other 1746 // type are printed and highlighted inside parentheses after "missing". 1747 // Tree printing: 1748 // Qualifiers are printed next to each other, inside brackets, and 1749 // separated by "!=". The printing order is: 1750 // common qualifiers, highlighted from qualifiers, "!=", 1751 // common qualifiers, highlighted to qualifiers 1752 if (PrintTree) { 1753 OS << "["; 1754 if (CommonQual.empty() && FromQual.empty()) { 1755 Bold(); 1756 OS << "(no qualifiers) "; 1757 Unbold(); 1758 } else { 1759 PrintQualifier(CommonQual, /*ApplyBold*/false); 1760 PrintQualifier(FromQual, /*ApplyBold*/true); 1761 } 1762 OS << "!= "; 1763 if (CommonQual.empty() && ToQual.empty()) { 1764 Bold(); 1765 OS << "(no qualifiers)"; 1766 Unbold(); 1767 } else { 1768 PrintQualifier(CommonQual, /*ApplyBold*/false, 1769 /*appendSpaceIfNonEmpty*/!ToQual.empty()); 1770 PrintQualifier(ToQual, /*ApplyBold*/true, 1771 /*appendSpaceIfNonEmpty*/false); 1772 } 1773 OS << "] "; 1774 } else { 1775 PrintQualifier(CommonQual, /*ApplyBold*/false); 1776 PrintQualifier(FromQual, /*ApplyBold*/true); 1777 } 1778 } 1779 1780 void PrintQualifier(Qualifiers Q, bool ApplyBold, 1781 bool AppendSpaceIfNonEmpty = true) { 1782 if (Q.empty()) return; 1783 if (ApplyBold) Bold(); 1784 Q.print(OS, Policy, AppendSpaceIfNonEmpty); 1785 if (ApplyBold) Unbold(); 1786 } 1787 1788 public: 1789 1790 TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType, 1791 QualType ToType, bool PrintTree, bool PrintFromType, 1792 bool ElideType, bool ShowColor) 1793 : Context(Context), 1794 Policy(Context.getLangOpts()), 1795 ElideType(ElideType), 1796 PrintTree(PrintTree), 1797 ShowColor(ShowColor), 1798 // When printing a single type, the FromType is the one printed. 1799 FromType(PrintFromType ? FromType : ToType), 1800 ToType(PrintFromType ? ToType : FromType), 1801 OS(OS), 1802 IsBold(false) { 1803 } 1804 1805 /// DiffTemplate - Start the template type diffing. 1806 void DiffTemplate() { 1807 Qualifiers FromQual = FromType.getQualifiers(), 1808 ToQual = ToType.getQualifiers(); 1809 1810 const TemplateSpecializationType *FromOrigTST = 1811 GetTemplateSpecializationType(Context, FromType); 1812 const TemplateSpecializationType *ToOrigTST = 1813 GetTemplateSpecializationType(Context, ToType); 1814 1815 // Only checking templates. 1816 if (!FromOrigTST || !ToOrigTST) 1817 return; 1818 1819 // Different base templates. 1820 if (!hasSameTemplate(FromOrigTST, ToOrigTST)) { 1821 return; 1822 } 1823 1824 FromQual -= QualType(FromOrigTST, 0).getQualifiers(); 1825 ToQual -= QualType(ToOrigTST, 0).getQualifiers(); 1826 Tree.SetNode(FromType, ToType); 1827 Tree.SetNode(FromQual, ToQual); 1828 Tree.SetKind(DiffTree::Template); 1829 1830 // Same base template, but different arguments. 1831 Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(), 1832 ToOrigTST->getTemplateName().getAsTemplateDecl()); 1833 1834 DiffTemplate(FromOrigTST, ToOrigTST); 1835 } 1836 1837 /// Emit - When the two types given are templated types with the same 1838 /// base template, a string representation of the type difference will be 1839 /// emitted to the stream and return true. Otherwise, return false. 1840 bool Emit() { 1841 Tree.StartTraverse(); 1842 if (Tree.Empty()) 1843 return false; 1844 1845 TreeToString(); 1846 assert(!IsBold && "Bold is applied to end of string."); 1847 return true; 1848 } 1849 }; // end class TemplateDiff 1850 } // end namespace 1851 1852 /// FormatTemplateTypeDiff - A helper static function to start the template 1853 /// diff and return the properly formatted string. Returns true if the diff 1854 /// is successful. 1855 static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, 1856 QualType ToType, bool PrintTree, 1857 bool PrintFromType, bool ElideType, 1858 bool ShowColors, raw_ostream &OS) { 1859 if (PrintTree) 1860 PrintFromType = true; 1861 TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType, 1862 ElideType, ShowColors); 1863 TD.DiffTemplate(); 1864 return TD.Emit(); 1865 } 1866