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