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