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