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