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