1203955Srdivacky//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===// 2203955Srdivacky// 3203955Srdivacky// The LLVM Compiler Infrastructure 4203955Srdivacky// 5203955Srdivacky// This file is distributed under the University of Illinois Open Source 6203955Srdivacky// License. See LICENSE.TXT for details. 7203955Srdivacky// 8203955Srdivacky//===----------------------------------------------------------------------===// 9203955Srdivacky// 10203955Srdivacky// This file implements a diagnostic formatting hook for AST elements. 11203955Srdivacky// 12203955Srdivacky//===----------------------------------------------------------------------===// 13203955Srdivacky#include "clang/AST/ASTDiagnostic.h" 14203955Srdivacky#include "clang/AST/ASTContext.h" 15203955Srdivacky#include "clang/AST/DeclObjC.h" 16252723Sdim#include "clang/AST/DeclTemplate.h" 17252723Sdim#include "clang/AST/ExprCXX.h" 18245431Sdim#include "clang/AST/TemplateBase.h" 19203955Srdivacky#include "clang/AST/Type.h" 20245431Sdim#include "llvm/ADT/SmallString.h" 21203955Srdivacky#include "llvm/Support/raw_ostream.h" 22203955Srdivacky 23203955Srdivackyusing namespace clang; 24203955Srdivacky 25208600Srdivacky// Returns a desugared version of the QualType, and marks ShouldAKA as true 26208600Srdivacky// whenever we remove significant sugar from the type. 27208600Srdivackystatic QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { 28208600Srdivacky QualifierCollector QC; 29208600Srdivacky 30203955Srdivacky while (true) { 31208600Srdivacky const Type *Ty = QC.strip(QT); 32208600Srdivacky 33203955Srdivacky // Don't aka just because we saw an elaborated type... 34218893Sdim if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) { 35218893Sdim QT = ET->desugar(); 36203955Srdivacky continue; 37203955Srdivacky } 38218893Sdim // ... or a paren type ... 39218893Sdim if (const ParenType *PT = dyn_cast<ParenType>(Ty)) { 40218893Sdim QT = PT->desugar(); 41203955Srdivacky continue; 42203955Srdivacky } 43218893Sdim // ...or a substituted template type parameter ... 44218893Sdim if (const SubstTemplateTypeParmType *ST = 45218893Sdim dyn_cast<SubstTemplateTypeParmType>(Ty)) { 46218893Sdim QT = ST->desugar(); 47218893Sdim continue; 48218893Sdim } 49221345Sdim // ...or an attributed type... 50221345Sdim if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) { 51221345Sdim QT = AT->desugar(); 52221345Sdim continue; 53221345Sdim } 54218893Sdim // ... or an auto type. 55218893Sdim if (const AutoType *AT = dyn_cast<AutoType>(Ty)) { 56218893Sdim if (!AT->isSugared()) 57218893Sdim break; 58218893Sdim QT = AT->desugar(); 59218893Sdim continue; 60218893Sdim } 61208600Srdivacky 62223017Sdim // Don't desugar template specializations, unless it's an alias template. 63223017Sdim if (const TemplateSpecializationType *TST 64223017Sdim = dyn_cast<TemplateSpecializationType>(Ty)) 65223017Sdim if (!TST->isTypeAlias()) 66223017Sdim break; 67208600Srdivacky 68203955Srdivacky // Don't desugar magic Objective-C types. 69203955Srdivacky if (QualType(Ty,0) == Context.getObjCIdType() || 70203955Srdivacky QualType(Ty,0) == Context.getObjCClassType() || 71203955Srdivacky QualType(Ty,0) == Context.getObjCSelType() || 72203955Srdivacky QualType(Ty,0) == Context.getObjCProtoType()) 73203955Srdivacky break; 74208600Srdivacky 75203955Srdivacky // Don't desugar va_list. 76203955Srdivacky if (QualType(Ty,0) == Context.getBuiltinVaListType()) 77203955Srdivacky break; 78208600Srdivacky 79203955Srdivacky // Otherwise, do a single-step desugar. 80203955Srdivacky QualType Underlying; 81203955Srdivacky bool IsSugar = false; 82203955Srdivacky switch (Ty->getTypeClass()) { 83203955Srdivacky#define ABSTRACT_TYPE(Class, Base) 84203955Srdivacky#define TYPE(Class, Base) \ 85203955Srdivackycase Type::Class: { \ 86203955Srdivackyconst Class##Type *CTy = cast<Class##Type>(Ty); \ 87203955Srdivackyif (CTy->isSugared()) { \ 88203955SrdivackyIsSugar = true; \ 89203955SrdivackyUnderlying = CTy->desugar(); \ 90203955Srdivacky} \ 91203955Srdivackybreak; \ 92203955Srdivacky} 93203955Srdivacky#include "clang/AST/TypeNodes.def" 94203955Srdivacky } 95208600Srdivacky 96203955Srdivacky // If it wasn't sugared, we're done. 97203955Srdivacky if (!IsSugar) 98203955Srdivacky break; 99208600Srdivacky 100203955Srdivacky // If the desugared type is a vector type, we don't want to expand 101203955Srdivacky // it, it will turn into an attribute mess. People want their "vec4". 102203955Srdivacky if (isa<VectorType>(Underlying)) 103203955Srdivacky break; 104208600Srdivacky 105203955Srdivacky // Don't desugar through the primary typedef of an anonymous type. 106218893Sdim if (const TagType *UTT = Underlying->getAs<TagType>()) 107218893Sdim if (const TypedefType *QTT = dyn_cast<TypedefType>(QT)) 108221345Sdim if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl()) 109218893Sdim break; 110208600Srdivacky 111208600Srdivacky // Record that we actually looked through an opaque type here. 112208600Srdivacky ShouldAKA = true; 113203955Srdivacky QT = Underlying; 114203955Srdivacky } 115208600Srdivacky 116208600Srdivacky // If we have a pointer-like type, desugar the pointee as well. 117208600Srdivacky // FIXME: Handle other pointer-like types. 118208600Srdivacky if (const PointerType *Ty = QT->getAs<PointerType>()) { 119218893Sdim QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(), 120218893Sdim ShouldAKA)); 121208600Srdivacky } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) { 122218893Sdim QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(), 123218893Sdim ShouldAKA)); 124218893Sdim } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) { 125218893Sdim QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(), 126218893Sdim ShouldAKA)); 127203955Srdivacky } 128208600Srdivacky 129218893Sdim return QC.apply(Context, QT); 130203955Srdivacky} 131203955Srdivacky 132203955Srdivacky/// \brief Convert the given type to a string suitable for printing as part of 133208600Srdivacky/// a diagnostic. 134203955Srdivacky/// 135224145Sdim/// There are four main criteria when determining whether we should have an 136208600Srdivacky/// a.k.a. clause when pretty-printing a type: 137208600Srdivacky/// 138208600Srdivacky/// 1) Some types provide very minimal sugar that doesn't impede the 139208600Srdivacky/// user's understanding --- for example, elaborated type 140208600Srdivacky/// specifiers. If this is all the sugar we see, we don't want an 141208600Srdivacky/// a.k.a. clause. 142208600Srdivacky/// 2) Some types are technically sugared but are much more familiar 143208600Srdivacky/// when seen in their sugared form --- for example, va_list, 144208600Srdivacky/// vector types, and the magic Objective C types. We don't 145208600Srdivacky/// want to desugar these, even if we do produce an a.k.a. clause. 146208600Srdivacky/// 3) Some types may have already been desugared previously in this diagnostic. 147208600Srdivacky/// if this is the case, doing another "aka" would just be clutter. 148224145Sdim/// 4) Two different types within the same diagnostic have the same output 149224145Sdim/// string. In this case, force an a.k.a with the desugared type when 150224145Sdim/// doing so will provide additional information. 151208600Srdivacky/// 152203955Srdivacky/// \param Context the context in which the type was allocated 153203955Srdivacky/// \param Ty the type to print 154224145Sdim/// \param QualTypeVals pointer values to QualTypes which are used in the 155224145Sdim/// diagnostic message 156203955Srdivackystatic std::string 157203955SrdivackyConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, 158226890Sdim const DiagnosticsEngine::ArgumentValue *PrevArgs, 159224145Sdim unsigned NumPrevArgs, 160235633Sdim ArrayRef<intptr_t> QualTypeVals) { 161203955Srdivacky // FIXME: Playing with std::string is really slow. 162224145Sdim bool ForceAKA = false; 163224145Sdim QualType CanTy = Ty.getCanonicalType(); 164226890Sdim std::string S = Ty.getAsString(Context.getPrintingPolicy()); 165226890Sdim std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); 166208600Srdivacky 167235633Sdim for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) { 168224145Sdim QualType CompareTy = 169235633Sdim QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I])); 170235633Sdim if (CompareTy.isNull()) 171235633Sdim continue; 172224145Sdim if (CompareTy == Ty) 173224145Sdim continue; // Same types 174224145Sdim QualType CompareCanTy = CompareTy.getCanonicalType(); 175224145Sdim if (CompareCanTy == CanTy) 176224145Sdim continue; // Same canonical types 177226890Sdim std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy()); 178235633Sdim bool aka; 179235633Sdim QualType CompareDesugar = Desugar(Context, CompareTy, aka); 180235633Sdim std::string CompareDesugarStr = 181235633Sdim CompareDesugar.getAsString(Context.getPrintingPolicy()); 182235633Sdim if (CompareS != S && CompareDesugarStr != S) 183235633Sdim continue; // The type string is different than the comparison string 184235633Sdim // and the desugared comparison string. 185235633Sdim std::string CompareCanS = 186235633Sdim CompareCanTy.getAsString(Context.getPrintingPolicy()); 187235633Sdim 188224145Sdim if (CompareCanS == CanS) 189224145Sdim continue; // No new info from canonical type 190224145Sdim 191224145Sdim ForceAKA = true; 192224145Sdim break; 193224145Sdim } 194224145Sdim 195208600Srdivacky // Check to see if we already desugared this type in this 196208600Srdivacky // diagnostic. If so, don't do it again. 197208600Srdivacky bool Repeated = false; 198208600Srdivacky for (unsigned i = 0; i != NumPrevArgs; ++i) { 199208600Srdivacky // TODO: Handle ak_declcontext case. 200226890Sdim if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { 201208600Srdivacky void *Ptr = (void*)PrevArgs[i].second; 202208600Srdivacky QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); 203208600Srdivacky if (PrevTy == Ty) { 204208600Srdivacky Repeated = true; 205208600Srdivacky break; 206208600Srdivacky } 207208600Srdivacky } 208208600Srdivacky } 209208600Srdivacky 210203955Srdivacky // Consider producing an a.k.a. clause if removing all the direct 211203955Srdivacky // sugar gives us something "significantly different". 212208600Srdivacky if (!Repeated) { 213208600Srdivacky bool ShouldAKA = false; 214208600Srdivacky QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA); 215224145Sdim if (ShouldAKA || ForceAKA) { 216224145Sdim if (DesugaredTy == Ty) { 217224145Sdim DesugaredTy = Ty.getCanonicalType(); 218224145Sdim } 219226890Sdim std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy()); 220224145Sdim if (akaStr != S) { 221224145Sdim S = "'" + S + "' (aka '" + akaStr + "')"; 222224145Sdim return S; 223224145Sdim } 224208600Srdivacky } 225203955Srdivacky } 226208600Srdivacky 227203955Srdivacky S = "'" + S + "'"; 228203955Srdivacky return S; 229203955Srdivacky} 230203955Srdivacky 231245431Sdimstatic bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, 232245431Sdim QualType ToType, bool PrintTree, 233245431Sdim bool PrintFromType, bool ElideType, 234252723Sdim bool ShowColors, raw_ostream &OS); 235245431Sdim 236224145Sdimvoid clang::FormatASTNodeDiagnosticArgument( 237226890Sdim DiagnosticsEngine::ArgumentKind Kind, 238224145Sdim intptr_t Val, 239224145Sdim const char *Modifier, 240224145Sdim unsigned ModLen, 241224145Sdim const char *Argument, 242224145Sdim unsigned ArgLen, 243226890Sdim const DiagnosticsEngine::ArgumentValue *PrevArgs, 244224145Sdim unsigned NumPrevArgs, 245226890Sdim SmallVectorImpl<char> &Output, 246224145Sdim void *Cookie, 247235633Sdim ArrayRef<intptr_t> QualTypeVals) { 248203955Srdivacky ASTContext &Context = *static_cast<ASTContext*>(Cookie); 249203955Srdivacky 250252723Sdim size_t OldEnd = Output.size(); 251252723Sdim llvm::raw_svector_ostream OS(Output); 252203955Srdivacky bool NeedQuotes = true; 253203955Srdivacky 254203955Srdivacky switch (Kind) { 255226890Sdim default: llvm_unreachable("unknown ArgumentKind"); 256245431Sdim case DiagnosticsEngine::ak_qualtype_pair: { 257245431Sdim TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val); 258245431Sdim QualType FromType = 259245431Sdim QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType)); 260245431Sdim QualType ToType = 261245431Sdim QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType)); 262245431Sdim 263245431Sdim if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree, 264245431Sdim TDT.PrintFromType, TDT.ElideType, 265252723Sdim TDT.ShowColors, OS)) { 266245431Sdim NeedQuotes = !TDT.PrintTree; 267245431Sdim TDT.TemplateDiffUsed = true; 268245431Sdim break; 269245431Sdim } 270245431Sdim 271245431Sdim // Don't fall-back during tree printing. The caller will handle 272245431Sdim // this case. 273245431Sdim if (TDT.PrintTree) 274245431Sdim return; 275245431Sdim 276252723Sdim // Attempting to do a template diff on non-templates. Set the variables 277245431Sdim // and continue with regular type printing of the appropriate type. 278245431Sdim Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType; 279245431Sdim ModLen = 0; 280245431Sdim ArgLen = 0; 281245431Sdim // Fall through 282245431Sdim } 283226890Sdim case DiagnosticsEngine::ak_qualtype: { 284203955Srdivacky assert(ModLen == 0 && ArgLen == 0 && 285203955Srdivacky "Invalid modifier for QualType argument"); 286203955Srdivacky 287203955Srdivacky QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); 288252723Sdim OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, 289252723Sdim QualTypeVals); 290203955Srdivacky NeedQuotes = false; 291203955Srdivacky break; 292203955Srdivacky } 293226890Sdim case DiagnosticsEngine::ak_declarationname: { 294203955Srdivacky if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) 295252723Sdim OS << '+'; 296203955Srdivacky else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) 297203955Srdivacky && ArgLen==0) 298252723Sdim OS << '-'; 299203955Srdivacky else 300203955Srdivacky assert(ModLen == 0 && ArgLen == 0 && 301203955Srdivacky "Invalid modifier for DeclarationName argument"); 302252723Sdim 303263509Sdim OS << DeclarationName::getFromOpaqueInteger(Val); 304203955Srdivacky break; 305203955Srdivacky } 306226890Sdim case DiagnosticsEngine::ak_nameddecl: { 307203955Srdivacky bool Qualified; 308203955Srdivacky if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) 309203955Srdivacky Qualified = true; 310203955Srdivacky else { 311203955Srdivacky assert(ModLen == 0 && ArgLen == 0 && 312203955Srdivacky "Invalid modifier for NamedDecl* argument"); 313203955Srdivacky Qualified = false; 314203955Srdivacky } 315226890Sdim const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val); 316252723Sdim ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified); 317203955Srdivacky break; 318203955Srdivacky } 319226890Sdim case DiagnosticsEngine::ak_nestednamespec: { 320252723Sdim NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val); 321252723Sdim NNS->print(OS, Context.getPrintingPolicy()); 322203955Srdivacky NeedQuotes = false; 323203955Srdivacky break; 324203955Srdivacky } 325226890Sdim case DiagnosticsEngine::ak_declcontext: { 326203955Srdivacky DeclContext *DC = reinterpret_cast<DeclContext *> (Val); 327203955Srdivacky assert(DC && "Should never have a null declaration context"); 328203955Srdivacky 329203955Srdivacky if (DC->isTranslationUnit()) { 330203955Srdivacky // FIXME: Get these strings from some localized place 331235633Sdim if (Context.getLangOpts().CPlusPlus) 332252723Sdim OS << "the global namespace"; 333203955Srdivacky else 334252723Sdim OS << "the global scope"; 335203955Srdivacky } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { 336252723Sdim OS << ConvertTypeToDiagnosticString(Context, 337252723Sdim Context.getTypeDeclType(Type), 338252723Sdim PrevArgs, NumPrevArgs, 339252723Sdim QualTypeVals); 340203955Srdivacky } else { 341203955Srdivacky // FIXME: Get these strings from some localized place 342203955Srdivacky NamedDecl *ND = cast<NamedDecl>(DC); 343203955Srdivacky if (isa<NamespaceDecl>(ND)) 344252723Sdim OS << "namespace "; 345203955Srdivacky else if (isa<ObjCMethodDecl>(ND)) 346252723Sdim OS << "method "; 347203955Srdivacky else if (isa<FunctionDecl>(ND)) 348252723Sdim OS << "function "; 349252723Sdim 350252723Sdim OS << '\''; 351252723Sdim ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); 352252723Sdim OS << '\''; 353203955Srdivacky } 354203955Srdivacky NeedQuotes = false; 355203955Srdivacky break; 356203955Srdivacky } 357203955Srdivacky } 358252723Sdim 359252723Sdim OS.flush(); 360252723Sdim 361252723Sdim if (NeedQuotes) { 362252723Sdim Output.insert(Output.begin()+OldEnd, '\''); 363203955Srdivacky Output.push_back('\''); 364252723Sdim } 365203955Srdivacky} 366245431Sdim 367245431Sdim/// TemplateDiff - A class that constructs a pretty string for a pair of 368245431Sdim/// QualTypes. For the pair of types, a diff tree will be created containing 369245431Sdim/// all the information about the templates and template arguments. Afterwards, 370245431Sdim/// the tree is transformed to a string according to the options passed in. 371245431Sdimnamespace { 372245431Sdimclass TemplateDiff { 373245431Sdim /// Context - The ASTContext which is used for comparing template arguments. 374245431Sdim ASTContext &Context; 375245431Sdim 376245431Sdim /// Policy - Used during expression printing. 377245431Sdim PrintingPolicy Policy; 378245431Sdim 379245431Sdim /// ElideType - Option to elide identical types. 380245431Sdim bool ElideType; 381245431Sdim 382245431Sdim /// PrintTree - Format output string as a tree. 383245431Sdim bool PrintTree; 384245431Sdim 385245431Sdim /// ShowColor - Diagnostics support color, so bolding will be used. 386245431Sdim bool ShowColor; 387245431Sdim 388245431Sdim /// FromType - When single type printing is selected, this is the type to be 389245431Sdim /// be printed. When tree printing is selected, this type will show up first 390245431Sdim /// in the tree. 391245431Sdim QualType FromType; 392245431Sdim 393245431Sdim /// ToType - The type that FromType is compared to. Only in tree printing 394245431Sdim /// will this type be outputed. 395245431Sdim QualType ToType; 396245431Sdim 397245431Sdim /// OS - The stream used to construct the output strings. 398252723Sdim raw_ostream &OS; 399245431Sdim 400245431Sdim /// IsBold - Keeps track of the bold formatting for the output string. 401245431Sdim bool IsBold; 402245431Sdim 403245431Sdim /// DiffTree - A tree representation the differences between two types. 404245431Sdim class DiffTree { 405252723Sdim public: 406252723Sdim /// DiffKind - The difference in a DiffNode and which fields are used. 407252723Sdim enum DiffKind { 408252723Sdim /// Incomplete or invalid node. 409252723Sdim Invalid, 410252723Sdim /// Another level of templates, uses TemplateDecl and Qualifiers 411252723Sdim Template, 412252723Sdim /// Type difference, uses QualType 413252723Sdim Type, 414252723Sdim /// Expression difference, uses Expr 415252723Sdim Expression, 416252723Sdim /// Template argument difference, uses TemplateDecl 417252723Sdim TemplateTemplate, 418252723Sdim /// Integer difference, uses APSInt and Expr 419252723Sdim Integer, 420252723Sdim /// Declaration difference, uses ValueDecl 421252723Sdim Declaration 422252723Sdim }; 423252723Sdim private: 424245431Sdim /// DiffNode - The root node stores the original type. Each child node 425245431Sdim /// stores template arguments of their parents. For templated types, the 426245431Sdim /// template decl is also stored. 427245431Sdim struct DiffNode { 428252723Sdim DiffKind Kind; 429252723Sdim 430245431Sdim /// NextNode - The index of the next sibling node or 0. 431245431Sdim unsigned NextNode; 432245431Sdim 433245431Sdim /// ChildNode - The index of the first child node or 0. 434245431Sdim unsigned ChildNode; 435245431Sdim 436245431Sdim /// ParentNode - The index of the parent node. 437245431Sdim unsigned ParentNode; 438245431Sdim 439245431Sdim /// FromType, ToType - The type arguments. 440245431Sdim QualType FromType, ToType; 441245431Sdim 442245431Sdim /// FromExpr, ToExpr - The expression arguments. 443245431Sdim Expr *FromExpr, *ToExpr; 444245431Sdim 445245431Sdim /// FromTD, ToTD - The template decl for template template 446245431Sdim /// arguments or the type arguments that are templates. 447245431Sdim TemplateDecl *FromTD, *ToTD; 448245431Sdim 449245431Sdim /// FromQual, ToQual - Qualifiers for template types. 450245431Sdim Qualifiers FromQual, ToQual; 451245431Sdim 452245431Sdim /// FromInt, ToInt - APSInt's for integral arguments. 453245431Sdim llvm::APSInt FromInt, ToInt; 454245431Sdim 455245431Sdim /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid. 456245431Sdim bool IsValidFromInt, IsValidToInt; 457245431Sdim 458252723Sdim /// FromValueDecl, ToValueDecl - Whether the argument is a decl. 459252723Sdim ValueDecl *FromValueDecl, *ToValueDecl; 460252723Sdim 461263509Sdim /// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of 462263509Sdim /// operator before it. 463263509Sdim bool FromAddressOf, ToAddressOf; 464263509Sdim 465245431Sdim /// FromDefault, ToDefault - Whether the argument is a default argument. 466245431Sdim bool FromDefault, ToDefault; 467245431Sdim 468245431Sdim /// Same - Whether the two arguments evaluate to the same value. 469245431Sdim bool Same; 470245431Sdim 471245431Sdim DiffNode(unsigned ParentNode = 0) 472252723Sdim : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), 473245431Sdim FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0), 474252723Sdim IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0), 475263509Sdim ToValueDecl(0), FromAddressOf(false), ToAddressOf(false), 476263509Sdim FromDefault(false), ToDefault(false), Same(false) { } 477245431Sdim }; 478245431Sdim 479245431Sdim /// FlatTree - A flattened tree used to store the DiffNodes. 480252723Sdim SmallVector<DiffNode, 16> FlatTree; 481245431Sdim 482245431Sdim /// CurrentNode - The index of the current node being used. 483245431Sdim unsigned CurrentNode; 484245431Sdim 485245431Sdim /// NextFreeNode - The index of the next unused node. Used when creating 486245431Sdim /// child nodes. 487245431Sdim unsigned NextFreeNode; 488245431Sdim 489245431Sdim /// ReadNode - The index of the current node being read. 490245431Sdim unsigned ReadNode; 491245431Sdim 492245431Sdim public: 493245431Sdim DiffTree() : 494245431Sdim CurrentNode(0), NextFreeNode(1) { 495245431Sdim FlatTree.push_back(DiffNode()); 496245431Sdim } 497245431Sdim 498245431Sdim // Node writing functions. 499245431Sdim /// SetNode - Sets FromTD and ToTD of the current node. 500245431Sdim void SetNode(TemplateDecl *FromTD, TemplateDecl *ToTD) { 501245431Sdim FlatTree[CurrentNode].FromTD = FromTD; 502245431Sdim FlatTree[CurrentNode].ToTD = ToTD; 503245431Sdim } 504245431Sdim 505245431Sdim /// SetNode - Sets FromType and ToType of the current node. 506245431Sdim void SetNode(QualType FromType, QualType ToType) { 507245431Sdim FlatTree[CurrentNode].FromType = FromType; 508245431Sdim FlatTree[CurrentNode].ToType = ToType; 509245431Sdim } 510245431Sdim 511245431Sdim /// SetNode - Set FromExpr and ToExpr of the current node. 512245431Sdim void SetNode(Expr *FromExpr, Expr *ToExpr) { 513245431Sdim FlatTree[CurrentNode].FromExpr = FromExpr; 514245431Sdim FlatTree[CurrentNode].ToExpr = ToExpr; 515245431Sdim } 516245431Sdim 517245431Sdim /// SetNode - Set FromInt and ToInt of the current node. 518245431Sdim void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt, 519245431Sdim bool IsValidFromInt, bool IsValidToInt) { 520245431Sdim FlatTree[CurrentNode].FromInt = FromInt; 521245431Sdim FlatTree[CurrentNode].ToInt = ToInt; 522245431Sdim FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt; 523245431Sdim FlatTree[CurrentNode].IsValidToInt = IsValidToInt; 524245431Sdim } 525245431Sdim 526245431Sdim /// SetNode - Set FromQual and ToQual of the current node. 527245431Sdim void SetNode(Qualifiers FromQual, Qualifiers ToQual) { 528245431Sdim FlatTree[CurrentNode].FromQual = FromQual; 529245431Sdim FlatTree[CurrentNode].ToQual = ToQual; 530245431Sdim } 531245431Sdim 532252723Sdim /// SetNode - Set FromValueDecl and ToValueDecl of the current node. 533263509Sdim void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, 534263509Sdim bool FromAddressOf, bool ToAddressOf) { 535252723Sdim FlatTree[CurrentNode].FromValueDecl = FromValueDecl; 536252723Sdim FlatTree[CurrentNode].ToValueDecl = ToValueDecl; 537263509Sdim FlatTree[CurrentNode].FromAddressOf = FromAddressOf; 538263509Sdim FlatTree[CurrentNode].ToAddressOf = ToAddressOf; 539252723Sdim } 540252723Sdim 541245431Sdim /// SetSame - Sets the same flag of the current node. 542245431Sdim void SetSame(bool Same) { 543245431Sdim FlatTree[CurrentNode].Same = Same; 544245431Sdim } 545245431Sdim 546245431Sdim /// SetDefault - Sets FromDefault and ToDefault flags of the current node. 547245431Sdim void SetDefault(bool FromDefault, bool ToDefault) { 548245431Sdim FlatTree[CurrentNode].FromDefault = FromDefault; 549245431Sdim FlatTree[CurrentNode].ToDefault = ToDefault; 550245431Sdim } 551245431Sdim 552252723Sdim /// SetKind - Sets the current node's type. 553252723Sdim void SetKind(DiffKind Kind) { 554252723Sdim FlatTree[CurrentNode].Kind = Kind; 555252723Sdim } 556252723Sdim 557245431Sdim /// Up - Changes the node to the parent of the current node. 558245431Sdim void Up() { 559245431Sdim CurrentNode = FlatTree[CurrentNode].ParentNode; 560245431Sdim } 561245431Sdim 562245431Sdim /// AddNode - Adds a child node to the current node, then sets that node 563245431Sdim /// node as the current node. 564245431Sdim void AddNode() { 565245431Sdim FlatTree.push_back(DiffNode(CurrentNode)); 566245431Sdim DiffNode &Node = FlatTree[CurrentNode]; 567245431Sdim if (Node.ChildNode == 0) { 568245431Sdim // If a child node doesn't exist, add one. 569245431Sdim Node.ChildNode = NextFreeNode; 570245431Sdim } else { 571245431Sdim // If a child node exists, find the last child node and add a 572245431Sdim // next node to it. 573245431Sdim unsigned i; 574245431Sdim for (i = Node.ChildNode; FlatTree[i].NextNode != 0; 575245431Sdim i = FlatTree[i].NextNode) { 576245431Sdim } 577245431Sdim FlatTree[i].NextNode = NextFreeNode; 578245431Sdim } 579245431Sdim CurrentNode = NextFreeNode; 580245431Sdim ++NextFreeNode; 581245431Sdim } 582245431Sdim 583245431Sdim // Node reading functions. 584245431Sdim /// StartTraverse - Prepares the tree for recursive traversal. 585245431Sdim void StartTraverse() { 586245431Sdim ReadNode = 0; 587245431Sdim CurrentNode = NextFreeNode; 588245431Sdim NextFreeNode = 0; 589245431Sdim } 590245431Sdim 591245431Sdim /// Parent - Move the current read node to its parent. 592245431Sdim void Parent() { 593245431Sdim ReadNode = FlatTree[ReadNode].ParentNode; 594245431Sdim } 595245431Sdim 596245431Sdim /// GetNode - Gets the FromType and ToType. 597245431Sdim void GetNode(QualType &FromType, QualType &ToType) { 598245431Sdim FromType = FlatTree[ReadNode].FromType; 599245431Sdim ToType = FlatTree[ReadNode].ToType; 600245431Sdim } 601245431Sdim 602245431Sdim /// GetNode - Gets the FromExpr and ToExpr. 603245431Sdim void GetNode(Expr *&FromExpr, Expr *&ToExpr) { 604245431Sdim FromExpr = FlatTree[ReadNode].FromExpr; 605245431Sdim ToExpr = FlatTree[ReadNode].ToExpr; 606245431Sdim } 607245431Sdim 608245431Sdim /// GetNode - Gets the FromTD and ToTD. 609245431Sdim void GetNode(TemplateDecl *&FromTD, TemplateDecl *&ToTD) { 610245431Sdim FromTD = FlatTree[ReadNode].FromTD; 611245431Sdim ToTD = FlatTree[ReadNode].ToTD; 612245431Sdim } 613245431Sdim 614245431Sdim /// GetNode - Gets the FromInt and ToInt. 615245431Sdim void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt, 616245431Sdim bool &IsValidFromInt, bool &IsValidToInt) { 617245431Sdim FromInt = FlatTree[ReadNode].FromInt; 618245431Sdim ToInt = FlatTree[ReadNode].ToInt; 619245431Sdim IsValidFromInt = FlatTree[ReadNode].IsValidFromInt; 620245431Sdim IsValidToInt = FlatTree[ReadNode].IsValidToInt; 621245431Sdim } 622245431Sdim 623245431Sdim /// GetNode - Gets the FromQual and ToQual. 624245431Sdim void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) { 625245431Sdim FromQual = FlatTree[ReadNode].FromQual; 626245431Sdim ToQual = FlatTree[ReadNode].ToQual; 627245431Sdim } 628245431Sdim 629252723Sdim /// GetNode - Gets the FromValueDecl and ToValueDecl. 630263509Sdim void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl, 631263509Sdim bool &FromAddressOf, bool &ToAddressOf) { 632252723Sdim FromValueDecl = FlatTree[ReadNode].FromValueDecl; 633252723Sdim ToValueDecl = FlatTree[ReadNode].ToValueDecl; 634263509Sdim FromAddressOf = FlatTree[ReadNode].FromAddressOf; 635263509Sdim ToAddressOf = FlatTree[ReadNode].ToAddressOf; 636252723Sdim } 637252723Sdim 638245431Sdim /// NodeIsSame - Returns true the arguments are the same. 639245431Sdim bool NodeIsSame() { 640245431Sdim return FlatTree[ReadNode].Same; 641245431Sdim } 642245431Sdim 643245431Sdim /// HasChildrend - Returns true if the node has children. 644245431Sdim bool HasChildren() { 645245431Sdim return FlatTree[ReadNode].ChildNode != 0; 646245431Sdim } 647245431Sdim 648245431Sdim /// MoveToChild - Moves from the current node to its child. 649245431Sdim void MoveToChild() { 650245431Sdim ReadNode = FlatTree[ReadNode].ChildNode; 651245431Sdim } 652245431Sdim 653245431Sdim /// AdvanceSibling - If there is a next sibling, advance to it and return 654245431Sdim /// true. Otherwise, return false. 655245431Sdim bool AdvanceSibling() { 656245431Sdim if (FlatTree[ReadNode].NextNode == 0) 657245431Sdim return false; 658245431Sdim 659245431Sdim ReadNode = FlatTree[ReadNode].NextNode; 660245431Sdim return true; 661245431Sdim } 662245431Sdim 663245431Sdim /// HasNextSibling - Return true if the node has a next sibling. 664245431Sdim bool HasNextSibling() { 665245431Sdim return FlatTree[ReadNode].NextNode != 0; 666245431Sdim } 667245431Sdim 668245431Sdim /// FromDefault - Return true if the from argument is the default. 669245431Sdim bool FromDefault() { 670245431Sdim return FlatTree[ReadNode].FromDefault; 671245431Sdim } 672245431Sdim 673245431Sdim /// ToDefault - Return true if the to argument is the default. 674245431Sdim bool ToDefault() { 675245431Sdim return FlatTree[ReadNode].ToDefault; 676245431Sdim } 677245431Sdim 678245431Sdim /// Empty - Returns true if the tree has no information. 679245431Sdim bool Empty() { 680252723Sdim return GetKind() == Invalid; 681245431Sdim } 682252723Sdim 683252723Sdim /// GetKind - Returns the current node's type. 684252723Sdim DiffKind GetKind() { 685252723Sdim return FlatTree[ReadNode].Kind; 686252723Sdim } 687245431Sdim }; 688245431Sdim 689245431Sdim DiffTree Tree; 690245431Sdim 691245431Sdim /// TSTiterator - an iterator that is used to enter a 692245431Sdim /// TemplateSpecializationType and read TemplateArguments inside template 693245431Sdim /// parameter packs in order with the rest of the TemplateArguments. 694245431Sdim struct TSTiterator { 695245431Sdim typedef const TemplateArgument& reference; 696245431Sdim typedef const TemplateArgument* pointer; 697245431Sdim 698245431Sdim /// TST - the template specialization whose arguments this iterator 699245431Sdim /// traverse over. 700245431Sdim const TemplateSpecializationType *TST; 701245431Sdim 702252723Sdim /// DesugarTST - desugared template specialization used to extract 703252723Sdim /// default argument information 704252723Sdim const TemplateSpecializationType *DesugarTST; 705252723Sdim 706245431Sdim /// Index - the index of the template argument in TST. 707245431Sdim unsigned Index; 708245431Sdim 709245431Sdim /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA 710245431Sdim /// points to a TemplateArgument within a parameter pack. 711245431Sdim TemplateArgument::pack_iterator CurrentTA; 712245431Sdim 713245431Sdim /// EndTA - the end iterator of a parameter pack 714245431Sdim TemplateArgument::pack_iterator EndTA; 715245431Sdim 716245431Sdim /// TSTiterator - Constructs an iterator and sets it to the first template 717245431Sdim /// argument. 718252723Sdim TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) 719252723Sdim : TST(TST), 720252723Sdim DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())), 721252723Sdim Index(0), CurrentTA(0), EndTA(0) { 722245431Sdim if (isEnd()) return; 723245431Sdim 724245431Sdim // Set to first template argument. If not a parameter pack, done. 725245431Sdim TemplateArgument TA = TST->getArg(0); 726245431Sdim if (TA.getKind() != TemplateArgument::Pack) return; 727245431Sdim 728245431Sdim // Start looking into the parameter pack. 729245431Sdim CurrentTA = TA.pack_begin(); 730245431Sdim EndTA = TA.pack_end(); 731245431Sdim 732245431Sdim // Found a valid template argument. 733245431Sdim if (CurrentTA != EndTA) return; 734245431Sdim 735245431Sdim // Parameter pack is empty, use the increment to get to a valid 736245431Sdim // template argument. 737245431Sdim ++(*this); 738245431Sdim } 739245431Sdim 740245431Sdim /// isEnd - Returns true if the iterator is one past the end. 741245431Sdim bool isEnd() const { 742252723Sdim return Index >= TST->getNumArgs(); 743245431Sdim } 744245431Sdim 745245431Sdim /// &operator++ - Increment the iterator to the next template argument. 746245431Sdim TSTiterator &operator++() { 747252723Sdim // After the end, Index should be the default argument position in 748252723Sdim // DesugarTST, if it exists. 749252723Sdim if (isEnd()) { 750252723Sdim ++Index; 751252723Sdim return *this; 752252723Sdim } 753245431Sdim 754245431Sdim // If in a parameter pack, advance in the parameter pack. 755245431Sdim if (CurrentTA != EndTA) { 756245431Sdim ++CurrentTA; 757245431Sdim if (CurrentTA != EndTA) 758245431Sdim return *this; 759245431Sdim } 760245431Sdim 761245431Sdim // Loop until a template argument is found, or the end is reached. 762245431Sdim while (true) { 763245431Sdim // Advance to the next template argument. Break if reached the end. 764245431Sdim if (++Index == TST->getNumArgs()) break; 765245431Sdim 766245431Sdim // If the TemplateArgument is not a parameter pack, done. 767245431Sdim TemplateArgument TA = TST->getArg(Index); 768245431Sdim if (TA.getKind() != TemplateArgument::Pack) break; 769245431Sdim 770245431Sdim // Handle parameter packs. 771245431Sdim CurrentTA = TA.pack_begin(); 772245431Sdim EndTA = TA.pack_end(); 773245431Sdim 774245431Sdim // If the parameter pack is empty, try to advance again. 775245431Sdim if (CurrentTA != EndTA) break; 776245431Sdim } 777245431Sdim return *this; 778245431Sdim } 779245431Sdim 780245431Sdim /// operator* - Returns the appropriate TemplateArgument. 781245431Sdim reference operator*() const { 782245431Sdim assert(!isEnd() && "Index exceeds number of arguments."); 783245431Sdim if (CurrentTA == EndTA) 784245431Sdim return TST->getArg(Index); 785245431Sdim else 786245431Sdim return *CurrentTA; 787245431Sdim } 788245431Sdim 789245431Sdim /// operator-> - Allow access to the underlying TemplateArgument. 790245431Sdim pointer operator->() const { 791245431Sdim return &operator*(); 792245431Sdim } 793252723Sdim 794252723Sdim /// getDesugar - Returns the deduced template argument from DesguarTST 795252723Sdim reference getDesugar() const { 796252723Sdim return DesugarTST->getArg(Index); 797252723Sdim } 798245431Sdim }; 799245431Sdim 800245431Sdim // These functions build up the template diff tree, including functions to 801245431Sdim // retrieve and compare template arguments. 802245431Sdim 803245431Sdim static const TemplateSpecializationType * GetTemplateSpecializationType( 804245431Sdim ASTContext &Context, QualType Ty) { 805245431Sdim if (const TemplateSpecializationType *TST = 806245431Sdim Ty->getAs<TemplateSpecializationType>()) 807245431Sdim return TST; 808245431Sdim 809245431Sdim const RecordType *RT = Ty->getAs<RecordType>(); 810245431Sdim 811245431Sdim if (!RT) 812245431Sdim return 0; 813245431Sdim 814245431Sdim const ClassTemplateSpecializationDecl *CTSD = 815245431Sdim dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); 816245431Sdim 817245431Sdim if (!CTSD) 818245431Sdim return 0; 819245431Sdim 820245431Sdim Ty = Context.getTemplateSpecializationType( 821245431Sdim TemplateName(CTSD->getSpecializedTemplate()), 822245431Sdim CTSD->getTemplateArgs().data(), 823245431Sdim CTSD->getTemplateArgs().size(), 824252723Sdim Ty.getLocalUnqualifiedType().getCanonicalType()); 825245431Sdim 826245431Sdim return Ty->getAs<TemplateSpecializationType>(); 827245431Sdim } 828245431Sdim 829245431Sdim /// DiffTemplate - recursively visits template arguments and stores the 830245431Sdim /// argument info into a tree. 831245431Sdim void DiffTemplate(const TemplateSpecializationType *FromTST, 832245431Sdim const TemplateSpecializationType *ToTST) { 833245431Sdim // Begin descent into diffing template tree. 834263509Sdim TemplateParameterList *ParamsFrom = 835245431Sdim FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); 836263509Sdim TemplateParameterList *ParamsTo = 837263509Sdim ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); 838245431Sdim unsigned TotalArgs = 0; 839252723Sdim for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST); 840245431Sdim !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) { 841245431Sdim Tree.AddNode(); 842245431Sdim 843245431Sdim // Get the parameter at index TotalArgs. If index is larger 844245431Sdim // than the total number of parameters, then there is an 845245431Sdim // argument pack, so re-use the last parameter. 846263509Sdim unsigned ParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1); 847263509Sdim NamedDecl *ParamND = ParamsFrom->getParam(ParamIndex); 848263509Sdim 849245431Sdim // Handle Types 850245431Sdim if (TemplateTypeParmDecl *DefaultTTPD = 851245431Sdim dyn_cast<TemplateTypeParmDecl>(ParamND)) { 852245431Sdim QualType FromType, ToType; 853252723Sdim FromType = GetType(FromIter, DefaultTTPD); 854263509Sdim // A forward declaration can have no default arg but the actual class 855263509Sdim // can, don't mix up iterators and get the original parameter. 856263509Sdim ToType = GetType( 857263509Sdim ToIter, cast<TemplateTypeParmDecl>(ParamsTo->getParam(ParamIndex))); 858245431Sdim Tree.SetNode(FromType, ToType); 859245431Sdim Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(), 860245431Sdim ToIter.isEnd() && !ToType.isNull()); 861252723Sdim Tree.SetKind(DiffTree::Type); 862245431Sdim if (!FromType.isNull() && !ToType.isNull()) { 863245431Sdim if (Context.hasSameType(FromType, ToType)) { 864245431Sdim Tree.SetSame(true); 865245431Sdim } else { 866245431Sdim Qualifiers FromQual = FromType.getQualifiers(), 867245431Sdim ToQual = ToType.getQualifiers(); 868245431Sdim const TemplateSpecializationType *FromArgTST = 869245431Sdim GetTemplateSpecializationType(Context, FromType); 870245431Sdim const TemplateSpecializationType *ToArgTST = 871245431Sdim GetTemplateSpecializationType(Context, ToType); 872245431Sdim 873245431Sdim if (FromArgTST && ToArgTST && 874245431Sdim hasSameTemplate(FromArgTST, ToArgTST)) { 875245431Sdim FromQual -= QualType(FromArgTST, 0).getQualifiers(); 876245431Sdim ToQual -= QualType(ToArgTST, 0).getQualifiers(); 877245431Sdim Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(), 878245431Sdim ToArgTST->getTemplateName().getAsTemplateDecl()); 879245431Sdim Tree.SetNode(FromQual, ToQual); 880252723Sdim Tree.SetKind(DiffTree::Template); 881245431Sdim DiffTemplate(FromArgTST, ToArgTST); 882245431Sdim } 883245431Sdim } 884245431Sdim } 885245431Sdim } 886245431Sdim 887245431Sdim // Handle Expressions 888245431Sdim if (NonTypeTemplateParmDecl *DefaultNTTPD = 889245431Sdim dyn_cast<NonTypeTemplateParmDecl>(ParamND)) { 890252723Sdim Expr *FromExpr = 0, *ToExpr = 0; 891245431Sdim llvm::APSInt FromInt, ToInt; 892252723Sdim ValueDecl *FromValueDecl = 0, *ToValueDecl = 0; 893252723Sdim unsigned ParamWidth = 128; // Safe default 894252723Sdim if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) 895252723Sdim ParamWidth = Context.getIntWidth(DefaultNTTPD->getType()); 896245431Sdim bool HasFromInt = !FromIter.isEnd() && 897245431Sdim FromIter->getKind() == TemplateArgument::Integral; 898245431Sdim bool HasToInt = !ToIter.isEnd() && 899245431Sdim ToIter->getKind() == TemplateArgument::Integral; 900252723Sdim bool HasFromValueDecl = 901252723Sdim !FromIter.isEnd() && 902252723Sdim FromIter->getKind() == TemplateArgument::Declaration; 903252723Sdim bool HasToValueDecl = 904252723Sdim !ToIter.isEnd() && 905252723Sdim ToIter->getKind() == TemplateArgument::Declaration; 906252723Sdim 907252723Sdim assert(((!HasFromInt && !HasToInt) || 908252723Sdim (!HasFromValueDecl && !HasToValueDecl)) && 909252723Sdim "Template argument cannot be both integer and declaration"); 910252723Sdim 911245431Sdim if (HasFromInt) 912245431Sdim FromInt = FromIter->getAsIntegral(); 913252723Sdim else if (HasFromValueDecl) 914252723Sdim FromValueDecl = FromIter->getAsDecl(); 915245431Sdim else 916252723Sdim FromExpr = GetExpr(FromIter, DefaultNTTPD); 917245431Sdim 918245431Sdim if (HasToInt) 919245431Sdim ToInt = ToIter->getAsIntegral(); 920252723Sdim else if (HasToValueDecl) 921252723Sdim ToValueDecl = ToIter->getAsDecl(); 922245431Sdim else 923252723Sdim ToExpr = GetExpr(ToIter, DefaultNTTPD); 924245431Sdim 925252723Sdim if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { 926245431Sdim Tree.SetNode(FromExpr, ToExpr); 927245431Sdim Tree.SetDefault(FromIter.isEnd() && FromExpr, 928245431Sdim ToIter.isEnd() && ToExpr); 929252723Sdim if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) { 930252723Sdim if (FromExpr) 931252723Sdim FromInt = GetInt(FromIter, FromExpr); 932252723Sdim if (ToExpr) 933252723Sdim ToInt = GetInt(ToIter, ToExpr); 934252723Sdim Tree.SetNode(FromInt, ToInt, FromExpr, ToExpr); 935252723Sdim Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); 936252723Sdim Tree.SetKind(DiffTree::Integer); 937252723Sdim } else { 938252723Sdim Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr)); 939252723Sdim Tree.SetKind(DiffTree::Expression); 940252723Sdim } 941252723Sdim } else if (HasFromInt || HasToInt) { 942245431Sdim if (!HasFromInt && FromExpr) { 943252723Sdim FromInt = GetInt(FromIter, FromExpr); 944245431Sdim HasFromInt = true; 945245431Sdim } 946245431Sdim if (!HasToInt && ToExpr) { 947252723Sdim ToInt = GetInt(ToIter, ToExpr); 948245431Sdim HasToInt = true; 949245431Sdim } 950245431Sdim Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); 951252723Sdim Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); 952245431Sdim Tree.SetDefault(FromIter.isEnd() && HasFromInt, 953245431Sdim ToIter.isEnd() && HasToInt); 954252723Sdim Tree.SetKind(DiffTree::Integer); 955252723Sdim } else { 956252723Sdim if (!HasFromValueDecl && FromExpr) 957252723Sdim FromValueDecl = GetValueDecl(FromIter, FromExpr); 958252723Sdim if (!HasToValueDecl && ToExpr) 959252723Sdim ToValueDecl = GetValueDecl(ToIter, ToExpr); 960263509Sdim QualType ArgumentType = DefaultNTTPD->getType(); 961263509Sdim bool FromAddressOf = FromValueDecl && 962263509Sdim !ArgumentType->isReferenceType() && 963263509Sdim !FromValueDecl->getType()->isArrayType(); 964263509Sdim bool ToAddressOf = ToValueDecl && 965263509Sdim !ArgumentType->isReferenceType() && 966263509Sdim !ToValueDecl->getType()->isArrayType(); 967263509Sdim Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); 968252723Sdim Tree.SetSame(FromValueDecl && ToValueDecl && 969252723Sdim FromValueDecl->getCanonicalDecl() == 970252723Sdim ToValueDecl->getCanonicalDecl()); 971252723Sdim Tree.SetDefault(FromIter.isEnd() && FromValueDecl, 972252723Sdim ToIter.isEnd() && ToValueDecl); 973252723Sdim Tree.SetKind(DiffTree::Declaration); 974245431Sdim } 975245431Sdim } 976245431Sdim 977245431Sdim // Handle Templates 978245431Sdim if (TemplateTemplateParmDecl *DefaultTTPD = 979245431Sdim dyn_cast<TemplateTemplateParmDecl>(ParamND)) { 980245431Sdim TemplateDecl *FromDecl, *ToDecl; 981252723Sdim FromDecl = GetTemplateDecl(FromIter, DefaultTTPD); 982252723Sdim ToDecl = GetTemplateDecl(ToIter, DefaultTTPD); 983245431Sdim Tree.SetNode(FromDecl, ToDecl); 984252723Sdim Tree.SetSame( 985252723Sdim FromDecl && ToDecl && 986252723Sdim FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); 987252723Sdim Tree.SetKind(DiffTree::TemplateTemplate); 988245431Sdim } 989245431Sdim 990252723Sdim ++FromIter; 991252723Sdim ++ToIter; 992245431Sdim Tree.Up(); 993245431Sdim } 994245431Sdim } 995245431Sdim 996245431Sdim /// makeTemplateList - Dump every template alias into the vector. 997245431Sdim static void makeTemplateList( 998263509Sdim SmallVectorImpl<const TemplateSpecializationType *> &TemplateList, 999245431Sdim const TemplateSpecializationType *TST) { 1000245431Sdim while (TST) { 1001245431Sdim TemplateList.push_back(TST); 1002245431Sdim if (!TST->isTypeAlias()) 1003245431Sdim return; 1004245431Sdim TST = TST->getAliasedType()->getAs<TemplateSpecializationType>(); 1005245431Sdim } 1006245431Sdim } 1007245431Sdim 1008245431Sdim /// hasSameBaseTemplate - Returns true when the base templates are the same, 1009245431Sdim /// even if the template arguments are not. 1010245431Sdim static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST, 1011245431Sdim const TemplateSpecializationType *ToTST) { 1012252723Sdim return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() == 1013252723Sdim ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl(); 1014245431Sdim } 1015245431Sdim 1016245431Sdim /// hasSameTemplate - Returns true if both types are specialized from the 1017245431Sdim /// same template declaration. If they come from different template aliases, 1018245431Sdim /// do a parallel ascension search to determine the highest template alias in 1019245431Sdim /// common and set the arguments to them. 1020245431Sdim static bool hasSameTemplate(const TemplateSpecializationType *&FromTST, 1021245431Sdim const TemplateSpecializationType *&ToTST) { 1022245431Sdim // Check the top templates if they are the same. 1023245431Sdim if (hasSameBaseTemplate(FromTST, ToTST)) 1024245431Sdim return true; 1025245431Sdim 1026245431Sdim // Create vectors of template aliases. 1027245431Sdim SmallVector<const TemplateSpecializationType*, 1> FromTemplateList, 1028245431Sdim ToTemplateList; 1029245431Sdim 1030245431Sdim makeTemplateList(FromTemplateList, FromTST); 1031245431Sdim makeTemplateList(ToTemplateList, ToTST); 1032245431Sdim 1033263509Sdim SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator 1034245431Sdim FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(), 1035245431Sdim ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend(); 1036245431Sdim 1037245431Sdim // Check if the lowest template types are the same. If not, return. 1038245431Sdim if (!hasSameBaseTemplate(*FromIter, *ToIter)) 1039245431Sdim return false; 1040245431Sdim 1041245431Sdim // Begin searching up the template aliases. The bottom most template 1042245431Sdim // matches so move up until one pair does not match. Use the template 1043245431Sdim // right before that one. 1044245431Sdim for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) { 1045245431Sdim if (!hasSameBaseTemplate(*FromIter, *ToIter)) 1046245431Sdim break; 1047245431Sdim } 1048245431Sdim 1049245431Sdim FromTST = FromIter[-1]; 1050245431Sdim ToTST = ToIter[-1]; 1051245431Sdim 1052245431Sdim return true; 1053245431Sdim } 1054245431Sdim 1055245431Sdim /// GetType - Retrieves the template type arguments, including default 1056245431Sdim /// arguments. 1057252723Sdim QualType GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD) { 1058245431Sdim bool isVariadic = DefaultTTPD->isParameterPack(); 1059245431Sdim 1060245431Sdim if (!Iter.isEnd()) 1061252723Sdim return Iter->getAsType(); 1062263509Sdim if (isVariadic) 1063263509Sdim return QualType(); 1064252723Sdim 1065263509Sdim QualType ArgType = DefaultTTPD->getDefaultArgument(); 1066263509Sdim if (ArgType->isDependentType()) 1067263509Sdim return Iter.getDesugar().getAsType(); 1068263509Sdim 1069263509Sdim return ArgType; 1070245431Sdim } 1071245431Sdim 1072245431Sdim /// GetExpr - Retrieves the template expression argument, including default 1073245431Sdim /// arguments. 1074252723Sdim Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) { 1075252723Sdim Expr *ArgExpr = 0; 1076245431Sdim bool isVariadic = DefaultNTTPD->isParameterPack(); 1077245431Sdim 1078245431Sdim if (!Iter.isEnd()) 1079245431Sdim ArgExpr = Iter->getAsExpr(); 1080245431Sdim else if (!isVariadic) 1081245431Sdim ArgExpr = DefaultNTTPD->getDefaultArgument(); 1082245431Sdim 1083245431Sdim if (ArgExpr) 1084245431Sdim while (SubstNonTypeTemplateParmExpr *SNTTPE = 1085245431Sdim dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr)) 1086245431Sdim ArgExpr = SNTTPE->getReplacement(); 1087252723Sdim 1088252723Sdim return ArgExpr; 1089245431Sdim } 1090245431Sdim 1091252723Sdim /// GetInt - Retrieves the template integer argument, including evaluating 1092252723Sdim /// default arguments. 1093252723Sdim llvm::APInt GetInt(const TSTiterator &Iter, Expr *ArgExpr) { 1094252723Sdim // Default, value-depenedent expressions require fetching 1095252723Sdim // from the desugared TemplateArgument 1096252723Sdim if (Iter.isEnd() && ArgExpr->isValueDependent()) 1097252723Sdim switch (Iter.getDesugar().getKind()) { 1098252723Sdim case TemplateArgument::Integral: 1099252723Sdim return Iter.getDesugar().getAsIntegral(); 1100252723Sdim case TemplateArgument::Expression: 1101252723Sdim ArgExpr = Iter.getDesugar().getAsExpr(); 1102252723Sdim return ArgExpr->EvaluateKnownConstInt(Context); 1103252723Sdim default: 1104252723Sdim assert(0 && "Unexpected template argument kind"); 1105252723Sdim } 1106252723Sdim return ArgExpr->EvaluateKnownConstInt(Context); 1107252723Sdim } 1108252723Sdim 1109263509Sdim /// GetValueDecl - Retrieves the template Decl argument, including 1110252723Sdim /// default expression argument. 1111252723Sdim ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) { 1112252723Sdim // Default, value-depenedent expressions require fetching 1113252723Sdim // from the desugared TemplateArgument 1114252723Sdim if (Iter.isEnd() && ArgExpr->isValueDependent()) 1115252723Sdim switch (Iter.getDesugar().getKind()) { 1116252723Sdim case TemplateArgument::Declaration: 1117252723Sdim return Iter.getDesugar().getAsDecl(); 1118252723Sdim case TemplateArgument::Expression: 1119252723Sdim ArgExpr = Iter.getDesugar().getAsExpr(); 1120252723Sdim return cast<DeclRefExpr>(ArgExpr)->getDecl(); 1121252723Sdim default: 1122252723Sdim assert(0 && "Unexpected template argument kind"); 1123252723Sdim } 1124263509Sdim DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr); 1125263509Sdim if (!DRE) { 1126263509Sdim DRE = cast<DeclRefExpr>(cast<UnaryOperator>(ArgExpr)->getSubExpr()); 1127263509Sdim } 1128263509Sdim 1129263509Sdim return DRE->getDecl(); 1130252723Sdim } 1131252723Sdim 1132245431Sdim /// GetTemplateDecl - Retrieves the template template arguments, including 1133245431Sdim /// default arguments. 1134252723Sdim TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, 1135252723Sdim TemplateTemplateParmDecl *DefaultTTPD) { 1136245431Sdim bool isVariadic = DefaultTTPD->isParameterPack(); 1137245431Sdim 1138245431Sdim TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument(); 1139245431Sdim TemplateDecl *DefaultTD = 0; 1140245431Sdim if (TA.getKind() != TemplateArgument::Null) 1141245431Sdim DefaultTD = TA.getAsTemplate().getAsTemplateDecl(); 1142245431Sdim 1143245431Sdim if (!Iter.isEnd()) 1144252723Sdim return Iter->getAsTemplate().getAsTemplateDecl(); 1145252723Sdim if (!isVariadic) 1146252723Sdim return DefaultTD; 1147252723Sdim 1148252723Sdim return 0; 1149245431Sdim } 1150245431Sdim 1151252723Sdim /// IsSameConvertedInt - Returns true if both integers are equal when 1152252723Sdim /// converted to an integer type with the given width. 1153252723Sdim static bool IsSameConvertedInt(unsigned Width, const llvm::APSInt &X, 1154252723Sdim const llvm::APSInt &Y) { 1155252723Sdim llvm::APInt ConvertedX = X.extOrTrunc(Width); 1156252723Sdim llvm::APInt ConvertedY = Y.extOrTrunc(Width); 1157252723Sdim return ConvertedX == ConvertedY; 1158252723Sdim } 1159252723Sdim 1160245431Sdim /// IsEqualExpr - Returns true if the expressions evaluate to the same value. 1161252723Sdim static bool IsEqualExpr(ASTContext &Context, unsigned ParamWidth, 1162252723Sdim Expr *FromExpr, Expr *ToExpr) { 1163245431Sdim if (FromExpr == ToExpr) 1164245431Sdim return true; 1165245431Sdim 1166245431Sdim if (!FromExpr || !ToExpr) 1167245431Sdim return false; 1168245431Sdim 1169245431Sdim FromExpr = FromExpr->IgnoreParens(); 1170245431Sdim ToExpr = ToExpr->IgnoreParens(); 1171245431Sdim 1172245431Sdim DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr), 1173245431Sdim *ToDRE = dyn_cast<DeclRefExpr>(ToExpr); 1174245431Sdim 1175245431Sdim if (FromDRE || ToDRE) { 1176245431Sdim if (!FromDRE || !ToDRE) 1177245431Sdim return false; 1178245431Sdim return FromDRE->getDecl() == ToDRE->getDecl(); 1179245431Sdim } 1180245431Sdim 1181245431Sdim Expr::EvalResult FromResult, ToResult; 1182245431Sdim if (!FromExpr->EvaluateAsRValue(FromResult, Context) || 1183245431Sdim !ToExpr->EvaluateAsRValue(ToResult, Context)) 1184252723Sdim return false; 1185245431Sdim 1186245431Sdim APValue &FromVal = FromResult.Val; 1187245431Sdim APValue &ToVal = ToResult.Val; 1188245431Sdim 1189245431Sdim if (FromVal.getKind() != ToVal.getKind()) return false; 1190245431Sdim 1191245431Sdim switch (FromVal.getKind()) { 1192245431Sdim case APValue::Int: 1193252723Sdim return IsSameConvertedInt(ParamWidth, FromVal.getInt(), ToVal.getInt()); 1194245431Sdim case APValue::LValue: { 1195245431Sdim APValue::LValueBase FromBase = FromVal.getLValueBase(); 1196245431Sdim APValue::LValueBase ToBase = ToVal.getLValueBase(); 1197245431Sdim if (FromBase.isNull() && ToBase.isNull()) 1198245431Sdim return true; 1199245431Sdim if (FromBase.isNull() || ToBase.isNull()) 1200245431Sdim return false; 1201245431Sdim return FromBase.get<const ValueDecl*>() == 1202245431Sdim ToBase.get<const ValueDecl*>(); 1203245431Sdim } 1204245431Sdim case APValue::MemberPointer: 1205245431Sdim return FromVal.getMemberPointerDecl() == ToVal.getMemberPointerDecl(); 1206245431Sdim default: 1207245431Sdim llvm_unreachable("Unknown template argument expression."); 1208245431Sdim } 1209245431Sdim } 1210245431Sdim 1211245431Sdim // These functions converts the tree representation of the template 1212245431Sdim // differences into the internal character vector. 1213245431Sdim 1214245431Sdim /// TreeToString - Converts the Tree object into a character stream which 1215245431Sdim /// will later be turned into the output string. 1216245431Sdim void TreeToString(int Indent = 1) { 1217245431Sdim if (PrintTree) { 1218245431Sdim OS << '\n'; 1219252723Sdim OS.indent(2 * Indent); 1220245431Sdim ++Indent; 1221245431Sdim } 1222245431Sdim 1223245431Sdim // Handle cases where the difference is not templates with different 1224245431Sdim // arguments. 1225252723Sdim switch (Tree.GetKind()) { 1226252723Sdim case DiffTree::Invalid: 1227252723Sdim llvm_unreachable("Template diffing failed with bad DiffNode"); 1228252723Sdim case DiffTree::Type: { 1229245431Sdim QualType FromType, ToType; 1230245431Sdim Tree.GetNode(FromType, ToType); 1231245431Sdim PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(), 1232245431Sdim Tree.NodeIsSame()); 1233245431Sdim return; 1234245431Sdim } 1235252723Sdim case DiffTree::Expression: { 1236245431Sdim Expr *FromExpr, *ToExpr; 1237245431Sdim Tree.GetNode(FromExpr, ToExpr); 1238245431Sdim PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), 1239245431Sdim Tree.NodeIsSame()); 1240245431Sdim return; 1241245431Sdim } 1242252723Sdim case DiffTree::TemplateTemplate: { 1243245431Sdim TemplateDecl *FromTD, *ToTD; 1244245431Sdim Tree.GetNode(FromTD, ToTD); 1245245431Sdim PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(), 1246245431Sdim Tree.ToDefault(), Tree.NodeIsSame()); 1247245431Sdim return; 1248245431Sdim } 1249252723Sdim case DiffTree::Integer: { 1250245431Sdim llvm::APSInt FromInt, ToInt; 1251252723Sdim Expr *FromExpr, *ToExpr; 1252245431Sdim bool IsValidFromInt, IsValidToInt; 1253252723Sdim Tree.GetNode(FromExpr, ToExpr); 1254245431Sdim Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt); 1255245431Sdim PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, 1256252723Sdim FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), 1257252723Sdim Tree.NodeIsSame()); 1258245431Sdim return; 1259245431Sdim } 1260252723Sdim case DiffTree::Declaration: { 1261252723Sdim ValueDecl *FromValueDecl, *ToValueDecl; 1262263509Sdim bool FromAddressOf, ToAddressOf; 1263263509Sdim Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); 1264263509Sdim PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf, 1265263509Sdim Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); 1266252723Sdim return; 1267252723Sdim } 1268252723Sdim case DiffTree::Template: { 1269252723Sdim // Node is root of template. Recurse on children. 1270252723Sdim TemplateDecl *FromTD, *ToTD; 1271252723Sdim Tree.GetNode(FromTD, ToTD); 1272245431Sdim 1273252723Sdim if (!Tree.HasChildren()) { 1274252723Sdim // If we're dealing with a template specialization with zero 1275252723Sdim // arguments, there are no children; special-case this. 1276252723Sdim OS << FromTD->getNameAsString() << "<>"; 1277252723Sdim return; 1278252723Sdim } 1279245431Sdim 1280252723Sdim Qualifiers FromQual, ToQual; 1281252723Sdim Tree.GetNode(FromQual, ToQual); 1282252723Sdim PrintQualifiers(FromQual, ToQual); 1283245431Sdim 1284252723Sdim OS << FromTD->getNameAsString() << '<'; 1285252723Sdim Tree.MoveToChild(); 1286252723Sdim unsigned NumElideArgs = 0; 1287252723Sdim do { 1288252723Sdim if (ElideType) { 1289252723Sdim if (Tree.NodeIsSame()) { 1290252723Sdim ++NumElideArgs; 1291252723Sdim continue; 1292252723Sdim } 1293252723Sdim if (NumElideArgs > 0) { 1294252723Sdim PrintElideArgs(NumElideArgs, Indent); 1295252723Sdim NumElideArgs = 0; 1296252723Sdim OS << ", "; 1297252723Sdim } 1298252723Sdim } 1299252723Sdim TreeToString(Indent); 1300252723Sdim if (Tree.HasNextSibling()) 1301252723Sdim OS << ", "; 1302252723Sdim } while (Tree.AdvanceSibling()); 1303252723Sdim if (NumElideArgs > 0) 1304252723Sdim PrintElideArgs(NumElideArgs, Indent); 1305245431Sdim 1306252723Sdim Tree.Parent(); 1307252723Sdim OS << ">"; 1308252723Sdim return; 1309245431Sdim } 1310252723Sdim } 1311245431Sdim } 1312245431Sdim 1313245431Sdim // To signal to the text printer that a certain text needs to be bolded, 1314245431Sdim // a special character is injected into the character stream which the 1315245431Sdim // text printer will later strip out. 1316245431Sdim 1317245431Sdim /// Bold - Start bolding text. 1318245431Sdim void Bold() { 1319245431Sdim assert(!IsBold && "Attempting to bold text that is already bold."); 1320245431Sdim IsBold = true; 1321245431Sdim if (ShowColor) 1322245431Sdim OS << ToggleHighlight; 1323245431Sdim } 1324245431Sdim 1325245431Sdim /// Unbold - Stop bolding text. 1326245431Sdim void Unbold() { 1327245431Sdim assert(IsBold && "Attempting to remove bold from unbold text."); 1328245431Sdim IsBold = false; 1329245431Sdim if (ShowColor) 1330245431Sdim OS << ToggleHighlight; 1331245431Sdim } 1332245431Sdim 1333245431Sdim // Functions to print out the arguments and highlighting the difference. 1334245431Sdim 1335245431Sdim /// PrintTypeNames - prints the typenames, bolding differences. Will detect 1336245431Sdim /// typenames that are the same and attempt to disambiguate them by using 1337245431Sdim /// canonical typenames. 1338245431Sdim void PrintTypeNames(QualType FromType, QualType ToType, 1339245431Sdim bool FromDefault, bool ToDefault, bool Same) { 1340245431Sdim assert((!FromType.isNull() || !ToType.isNull()) && 1341245431Sdim "Only one template argument may be missing."); 1342245431Sdim 1343245431Sdim if (Same) { 1344245431Sdim OS << FromType.getAsString(); 1345245431Sdim return; 1346245431Sdim } 1347245431Sdim 1348245431Sdim if (!FromType.isNull() && !ToType.isNull() && 1349245431Sdim FromType.getLocalUnqualifiedType() == 1350245431Sdim ToType.getLocalUnqualifiedType()) { 1351245431Sdim Qualifiers FromQual = FromType.getLocalQualifiers(), 1352245431Sdim ToQual = ToType.getLocalQualifiers(), 1353245431Sdim CommonQual; 1354245431Sdim PrintQualifiers(FromQual, ToQual); 1355245431Sdim FromType.getLocalUnqualifiedType().print(OS, Policy); 1356245431Sdim return; 1357245431Sdim } 1358245431Sdim 1359245431Sdim std::string FromTypeStr = FromType.isNull() ? "(no argument)" 1360245431Sdim : FromType.getAsString(); 1361245431Sdim std::string ToTypeStr = ToType.isNull() ? "(no argument)" 1362245431Sdim : ToType.getAsString(); 1363245431Sdim // Switch to canonical typename if it is better. 1364245431Sdim // TODO: merge this with other aka printing above. 1365245431Sdim if (FromTypeStr == ToTypeStr) { 1366245431Sdim std::string FromCanTypeStr = FromType.getCanonicalType().getAsString(); 1367245431Sdim std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(); 1368245431Sdim if (FromCanTypeStr != ToCanTypeStr) { 1369245431Sdim FromTypeStr = FromCanTypeStr; 1370245431Sdim ToTypeStr = ToCanTypeStr; 1371245431Sdim } 1372245431Sdim } 1373245431Sdim 1374245431Sdim if (PrintTree) OS << '['; 1375245431Sdim OS << (FromDefault ? "(default) " : ""); 1376245431Sdim Bold(); 1377245431Sdim OS << FromTypeStr; 1378245431Sdim Unbold(); 1379245431Sdim if (PrintTree) { 1380245431Sdim OS << " != " << (ToDefault ? "(default) " : ""); 1381245431Sdim Bold(); 1382245431Sdim OS << ToTypeStr; 1383245431Sdim Unbold(); 1384245431Sdim OS << "]"; 1385245431Sdim } 1386245431Sdim return; 1387245431Sdim } 1388245431Sdim 1389245431Sdim /// PrintExpr - Prints out the expr template arguments, highlighting argument 1390245431Sdim /// differences. 1391245431Sdim void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, 1392245431Sdim bool FromDefault, bool ToDefault, bool Same) { 1393245431Sdim assert((FromExpr || ToExpr) && 1394245431Sdim "Only one template argument may be missing."); 1395245431Sdim if (Same) { 1396245431Sdim PrintExpr(FromExpr); 1397245431Sdim } else if (!PrintTree) { 1398245431Sdim OS << (FromDefault ? "(default) " : ""); 1399245431Sdim Bold(); 1400245431Sdim PrintExpr(FromExpr); 1401245431Sdim Unbold(); 1402245431Sdim } else { 1403245431Sdim OS << (FromDefault ? "[(default) " : "["); 1404245431Sdim Bold(); 1405245431Sdim PrintExpr(FromExpr); 1406245431Sdim Unbold(); 1407245431Sdim OS << " != " << (ToDefault ? "(default) " : ""); 1408245431Sdim Bold(); 1409245431Sdim PrintExpr(ToExpr); 1410245431Sdim Unbold(); 1411245431Sdim OS << ']'; 1412245431Sdim } 1413245431Sdim } 1414245431Sdim 1415245431Sdim /// PrintExpr - Actual formatting and printing of expressions. 1416245431Sdim void PrintExpr(const Expr *E) { 1417245431Sdim if (!E) 1418245431Sdim OS << "(no argument)"; 1419245431Sdim else 1420245431Sdim E->printPretty(OS, 0, Policy); return; 1421245431Sdim } 1422245431Sdim 1423245431Sdim /// PrintTemplateTemplate - Handles printing of template template arguments, 1424245431Sdim /// highlighting argument differences. 1425245431Sdim void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD, 1426245431Sdim bool FromDefault, bool ToDefault, bool Same) { 1427245431Sdim assert((FromTD || ToTD) && "Only one template argument may be missing."); 1428252723Sdim 1429252723Sdim std::string FromName = FromTD ? FromTD->getName() : "(no argument)"; 1430252723Sdim std::string ToName = ToTD ? ToTD->getName() : "(no argument)"; 1431252723Sdim if (FromTD && ToTD && FromName == ToName) { 1432252723Sdim FromName = FromTD->getQualifiedNameAsString(); 1433252723Sdim ToName = ToTD->getQualifiedNameAsString(); 1434252723Sdim } 1435252723Sdim 1436245431Sdim if (Same) { 1437245431Sdim OS << "template " << FromTD->getNameAsString(); 1438245431Sdim } else if (!PrintTree) { 1439245431Sdim OS << (FromDefault ? "(default) template " : "template "); 1440245431Sdim Bold(); 1441252723Sdim OS << FromName; 1442245431Sdim Unbold(); 1443245431Sdim } else { 1444245431Sdim OS << (FromDefault ? "[(default) template " : "[template "); 1445245431Sdim Bold(); 1446252723Sdim OS << FromName; 1447245431Sdim Unbold(); 1448245431Sdim OS << " != " << (ToDefault ? "(default) template " : "template "); 1449245431Sdim Bold(); 1450252723Sdim OS << ToName; 1451245431Sdim Unbold(); 1452245431Sdim OS << ']'; 1453245431Sdim } 1454245431Sdim } 1455245431Sdim 1456245431Sdim /// PrintAPSInt - Handles printing of integral arguments, highlighting 1457245431Sdim /// argument differences. 1458245431Sdim void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt, 1459252723Sdim bool IsValidFromInt, bool IsValidToInt, Expr *FromExpr, 1460252723Sdim Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) { 1461245431Sdim assert((IsValidFromInt || IsValidToInt) && 1462245431Sdim "Only one integral argument may be missing."); 1463245431Sdim 1464245431Sdim if (Same) { 1465245431Sdim OS << FromInt.toString(10); 1466245431Sdim } else if (!PrintTree) { 1467245431Sdim OS << (FromDefault ? "(default) " : ""); 1468252723Sdim PrintAPSInt(FromInt, FromExpr, IsValidFromInt); 1469252723Sdim } else { 1470252723Sdim OS << (FromDefault ? "[(default) " : "["); 1471252723Sdim PrintAPSInt(FromInt, FromExpr, IsValidFromInt); 1472252723Sdim OS << " != " << (ToDefault ? "(default) " : ""); 1473252723Sdim PrintAPSInt(ToInt, ToExpr, IsValidToInt); 1474252723Sdim OS << ']'; 1475252723Sdim } 1476252723Sdim } 1477252723Sdim 1478252723Sdim /// PrintAPSInt - If valid, print the APSInt. If the expression is 1479252723Sdim /// gives more information, print it too. 1480252723Sdim void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid) { 1481252723Sdim Bold(); 1482252723Sdim if (Valid) { 1483252723Sdim if (HasExtraInfo(E)) { 1484252723Sdim PrintExpr(E); 1485252723Sdim Unbold(); 1486252723Sdim OS << " aka "; 1487252723Sdim Bold(); 1488252723Sdim } 1489252723Sdim OS << Val.toString(10); 1490252723Sdim } else { 1491252723Sdim OS << "(no argument)"; 1492252723Sdim } 1493252723Sdim Unbold(); 1494252723Sdim } 1495252723Sdim 1496252723Sdim /// HasExtraInfo - Returns true if E is not an integer literal or the 1497252723Sdim /// negation of an integer literal 1498252723Sdim bool HasExtraInfo(Expr *E) { 1499252723Sdim if (!E) return false; 1500252723Sdim if (isa<IntegerLiteral>(E)) return false; 1501252723Sdim 1502252723Sdim if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) 1503252723Sdim if (UO->getOpcode() == UO_Minus) 1504252723Sdim if (isa<IntegerLiteral>(UO->getSubExpr())) 1505252723Sdim return false; 1506252723Sdim 1507252723Sdim return true; 1508252723Sdim } 1509252723Sdim 1510252723Sdim /// PrintDecl - Handles printing of Decl arguments, highlighting 1511252723Sdim /// argument differences. 1512252723Sdim void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, 1513263509Sdim bool FromAddressOf, bool ToAddressOf, bool FromDefault, 1514263509Sdim bool ToDefault, bool Same) { 1515252723Sdim assert((FromValueDecl || ToValueDecl) && 1516252723Sdim "Only one Decl argument may be NULL"); 1517252723Sdim 1518252723Sdim if (Same) { 1519252723Sdim OS << FromValueDecl->getName(); 1520252723Sdim } else if (!PrintTree) { 1521252723Sdim OS << (FromDefault ? "(default) " : ""); 1522245431Sdim Bold(); 1523263509Sdim if (FromAddressOf) 1524263509Sdim OS << "&"; 1525252723Sdim OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); 1526245431Sdim Unbold(); 1527245431Sdim } else { 1528245431Sdim OS << (FromDefault ? "[(default) " : "["); 1529245431Sdim Bold(); 1530263509Sdim if (FromAddressOf) 1531263509Sdim OS << "&"; 1532252723Sdim OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); 1533245431Sdim Unbold(); 1534245431Sdim OS << " != " << (ToDefault ? "(default) " : ""); 1535245431Sdim Bold(); 1536263509Sdim if (ToAddressOf) 1537263509Sdim OS << "&"; 1538252723Sdim OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)"); 1539245431Sdim Unbold(); 1540245431Sdim OS << ']'; 1541245431Sdim } 1542252723Sdim 1543245431Sdim } 1544245431Sdim 1545245431Sdim // Prints the appropriate placeholder for elided template arguments. 1546245431Sdim void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) { 1547245431Sdim if (PrintTree) { 1548245431Sdim OS << '\n'; 1549245431Sdim for (unsigned i = 0; i < Indent; ++i) 1550245431Sdim OS << " "; 1551245431Sdim } 1552245431Sdim if (NumElideArgs == 0) return; 1553245431Sdim if (NumElideArgs == 1) 1554245431Sdim OS << "[...]"; 1555245431Sdim else 1556245431Sdim OS << "[" << NumElideArgs << " * ...]"; 1557245431Sdim } 1558245431Sdim 1559245431Sdim // Prints and highlights differences in Qualifiers. 1560245431Sdim void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) { 1561245431Sdim // Both types have no qualifiers 1562245431Sdim if (FromQual.empty() && ToQual.empty()) 1563245431Sdim return; 1564245431Sdim 1565245431Sdim // Both types have same qualifiers 1566245431Sdim if (FromQual == ToQual) { 1567245431Sdim PrintQualifier(FromQual, /*ApplyBold*/false); 1568245431Sdim return; 1569245431Sdim } 1570245431Sdim 1571245431Sdim // Find common qualifiers and strip them from FromQual and ToQual. 1572245431Sdim Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual, 1573245431Sdim ToQual); 1574245431Sdim 1575245431Sdim // The qualifiers are printed before the template name. 1576245431Sdim // Inline printing: 1577245431Sdim // The common qualifiers are printed. Then, qualifiers only in this type 1578245431Sdim // are printed and highlighted. Finally, qualifiers only in the other 1579245431Sdim // type are printed and highlighted inside parentheses after "missing". 1580245431Sdim // Tree printing: 1581245431Sdim // Qualifiers are printed next to each other, inside brackets, and 1582245431Sdim // separated by "!=". The printing order is: 1583245431Sdim // common qualifiers, highlighted from qualifiers, "!=", 1584245431Sdim // common qualifiers, highlighted to qualifiers 1585245431Sdim if (PrintTree) { 1586245431Sdim OS << "["; 1587245431Sdim if (CommonQual.empty() && FromQual.empty()) { 1588245431Sdim Bold(); 1589245431Sdim OS << "(no qualifiers) "; 1590245431Sdim Unbold(); 1591245431Sdim } else { 1592245431Sdim PrintQualifier(CommonQual, /*ApplyBold*/false); 1593245431Sdim PrintQualifier(FromQual, /*ApplyBold*/true); 1594245431Sdim } 1595245431Sdim OS << "!= "; 1596245431Sdim if (CommonQual.empty() && ToQual.empty()) { 1597245431Sdim Bold(); 1598245431Sdim OS << "(no qualifiers)"; 1599245431Sdim Unbold(); 1600245431Sdim } else { 1601245431Sdim PrintQualifier(CommonQual, /*ApplyBold*/false, 1602245431Sdim /*appendSpaceIfNonEmpty*/!ToQual.empty()); 1603245431Sdim PrintQualifier(ToQual, /*ApplyBold*/true, 1604245431Sdim /*appendSpaceIfNonEmpty*/false); 1605245431Sdim } 1606245431Sdim OS << "] "; 1607245431Sdim } else { 1608245431Sdim PrintQualifier(CommonQual, /*ApplyBold*/false); 1609245431Sdim PrintQualifier(FromQual, /*ApplyBold*/true); 1610245431Sdim } 1611245431Sdim } 1612245431Sdim 1613245431Sdim void PrintQualifier(Qualifiers Q, bool ApplyBold, 1614245431Sdim bool AppendSpaceIfNonEmpty = true) { 1615245431Sdim if (Q.empty()) return; 1616245431Sdim if (ApplyBold) Bold(); 1617245431Sdim Q.print(OS, Policy, AppendSpaceIfNonEmpty); 1618245431Sdim if (ApplyBold) Unbold(); 1619245431Sdim } 1620245431Sdim 1621245431Sdimpublic: 1622245431Sdim 1623252723Sdim TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType, 1624252723Sdim QualType ToType, bool PrintTree, bool PrintFromType, 1625252723Sdim bool ElideType, bool ShowColor) 1626245431Sdim : Context(Context), 1627245431Sdim Policy(Context.getLangOpts()), 1628245431Sdim ElideType(ElideType), 1629245431Sdim PrintTree(PrintTree), 1630245431Sdim ShowColor(ShowColor), 1631245431Sdim // When printing a single type, the FromType is the one printed. 1632245431Sdim FromType(PrintFromType ? FromType : ToType), 1633245431Sdim ToType(PrintFromType ? ToType : FromType), 1634252723Sdim OS(OS), 1635245431Sdim IsBold(false) { 1636245431Sdim } 1637245431Sdim 1638245431Sdim /// DiffTemplate - Start the template type diffing. 1639245431Sdim void DiffTemplate() { 1640245431Sdim Qualifiers FromQual = FromType.getQualifiers(), 1641245431Sdim ToQual = ToType.getQualifiers(); 1642245431Sdim 1643245431Sdim const TemplateSpecializationType *FromOrigTST = 1644245431Sdim GetTemplateSpecializationType(Context, FromType); 1645245431Sdim const TemplateSpecializationType *ToOrigTST = 1646245431Sdim GetTemplateSpecializationType(Context, ToType); 1647245431Sdim 1648245431Sdim // Only checking templates. 1649245431Sdim if (!FromOrigTST || !ToOrigTST) 1650245431Sdim return; 1651245431Sdim 1652245431Sdim // Different base templates. 1653245431Sdim if (!hasSameTemplate(FromOrigTST, ToOrigTST)) { 1654245431Sdim return; 1655245431Sdim } 1656245431Sdim 1657245431Sdim FromQual -= QualType(FromOrigTST, 0).getQualifiers(); 1658245431Sdim ToQual -= QualType(ToOrigTST, 0).getQualifiers(); 1659245431Sdim Tree.SetNode(FromType, ToType); 1660245431Sdim Tree.SetNode(FromQual, ToQual); 1661252723Sdim Tree.SetKind(DiffTree::Template); 1662245431Sdim 1663245431Sdim // Same base template, but different arguments. 1664245431Sdim Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(), 1665245431Sdim ToOrigTST->getTemplateName().getAsTemplateDecl()); 1666245431Sdim 1667245431Sdim DiffTemplate(FromOrigTST, ToOrigTST); 1668245431Sdim } 1669245431Sdim 1670252723Sdim /// Emit - When the two types given are templated types with the same 1671245431Sdim /// base template, a string representation of the type difference will be 1672252723Sdim /// emitted to the stream and return true. Otherwise, return false. 1673252723Sdim bool Emit() { 1674245431Sdim Tree.StartTraverse(); 1675245431Sdim if (Tree.Empty()) 1676245431Sdim return false; 1677245431Sdim 1678245431Sdim TreeToString(); 1679245431Sdim assert(!IsBold && "Bold is applied to end of string."); 1680245431Sdim return true; 1681245431Sdim } 1682245431Sdim}; // end class TemplateDiff 1683245431Sdim} // end namespace 1684245431Sdim 1685245431Sdim/// FormatTemplateTypeDiff - A helper static function to start the template 1686245431Sdim/// diff and return the properly formatted string. Returns true if the diff 1687245431Sdim/// is successful. 1688245431Sdimstatic bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, 1689245431Sdim QualType ToType, bool PrintTree, 1690245431Sdim bool PrintFromType, bool ElideType, 1691252723Sdim bool ShowColors, raw_ostream &OS) { 1692245431Sdim if (PrintTree) 1693245431Sdim PrintFromType = true; 1694252723Sdim TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType, 1695245431Sdim ElideType, ShowColors); 1696245431Sdim TD.DiffTemplate(); 1697252723Sdim return TD.Emit(); 1698245431Sdim} 1699