1203955Srdivacky//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//
2203955Srdivacky//
3203955Srdivacky//                     The LLVM Compiler Infrastructure
4203955Srdivacky//
5203955Srdivacky// This file is distributed under the University of Illinois Open Source
6203955Srdivacky// License. See LICENSE.TXT for details.
7203955Srdivacky//
8203955Srdivacky//===----------------------------------------------------------------------===//
9203955Srdivacky//
10203955Srdivacky// This file implements a diagnostic formatting hook for AST elements.
11203955Srdivacky//
12203955Srdivacky//===----------------------------------------------------------------------===//
13203955Srdivacky#include "clang/AST/ASTDiagnostic.h"
14203955Srdivacky#include "clang/AST/ASTContext.h"
15203955Srdivacky#include "clang/AST/DeclObjC.h"
16252723Sdim#include "clang/AST/DeclTemplate.h"
17252723Sdim#include "clang/AST/ExprCXX.h"
18245431Sdim#include "clang/AST/TemplateBase.h"
19203955Srdivacky#include "clang/AST/Type.h"
20245431Sdim#include "llvm/ADT/SmallString.h"
21203955Srdivacky#include "llvm/Support/raw_ostream.h"
22203955Srdivacky
23203955Srdivackyusing namespace clang;
24203955Srdivacky
25208600Srdivacky// Returns a desugared version of the QualType, and marks ShouldAKA as true
26208600Srdivacky// whenever we remove significant sugar from the type.
27208600Srdivackystatic QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
28208600Srdivacky  QualifierCollector QC;
29208600Srdivacky
30203955Srdivacky  while (true) {
31208600Srdivacky    const Type *Ty = QC.strip(QT);
32208600Srdivacky
33203955Srdivacky    // Don't aka just because we saw an elaborated type...
34218893Sdim    if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) {
35218893Sdim      QT = ET->desugar();
36203955Srdivacky      continue;
37203955Srdivacky    }
38218893Sdim    // ... or a paren type ...
39218893Sdim    if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
40218893Sdim      QT = PT->desugar();
41203955Srdivacky      continue;
42203955Srdivacky    }
43218893Sdim    // ...or a substituted template type parameter ...
44218893Sdim    if (const SubstTemplateTypeParmType *ST =
45218893Sdim          dyn_cast<SubstTemplateTypeParmType>(Ty)) {
46218893Sdim      QT = ST->desugar();
47218893Sdim      continue;
48218893Sdim    }
49221345Sdim    // ...or an attributed type...
50221345Sdim    if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) {
51221345Sdim      QT = AT->desugar();
52221345Sdim      continue;
53221345Sdim    }
54218893Sdim    // ... or an auto type.
55218893Sdim    if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
56218893Sdim      if (!AT->isSugared())
57218893Sdim        break;
58218893Sdim      QT = AT->desugar();
59218893Sdim      continue;
60218893Sdim    }
61208600Srdivacky
62223017Sdim    // Don't desugar template specializations, unless it's an alias template.
63223017Sdim    if (const TemplateSpecializationType *TST
64223017Sdim          = dyn_cast<TemplateSpecializationType>(Ty))
65223017Sdim      if (!TST->isTypeAlias())
66223017Sdim        break;
67208600Srdivacky
68203955Srdivacky    // Don't desugar magic Objective-C types.
69203955Srdivacky    if (QualType(Ty,0) == Context.getObjCIdType() ||
70203955Srdivacky        QualType(Ty,0) == Context.getObjCClassType() ||
71203955Srdivacky        QualType(Ty,0) == Context.getObjCSelType() ||
72203955Srdivacky        QualType(Ty,0) == Context.getObjCProtoType())
73203955Srdivacky      break;
74208600Srdivacky
75203955Srdivacky    // Don't desugar va_list.
76203955Srdivacky    if (QualType(Ty,0) == Context.getBuiltinVaListType())
77203955Srdivacky      break;
78208600Srdivacky
79203955Srdivacky    // Otherwise, do a single-step desugar.
80203955Srdivacky    QualType Underlying;
81203955Srdivacky    bool IsSugar = false;
82203955Srdivacky    switch (Ty->getTypeClass()) {
83203955Srdivacky#define ABSTRACT_TYPE(Class, Base)
84203955Srdivacky#define TYPE(Class, Base) \
85203955Srdivackycase Type::Class: { \
86203955Srdivackyconst Class##Type *CTy = cast<Class##Type>(Ty); \
87203955Srdivackyif (CTy->isSugared()) { \
88203955SrdivackyIsSugar = true; \
89203955SrdivackyUnderlying = CTy->desugar(); \
90203955Srdivacky} \
91203955Srdivackybreak; \
92203955Srdivacky}
93203955Srdivacky#include "clang/AST/TypeNodes.def"
94203955Srdivacky    }
95208600Srdivacky
96203955Srdivacky    // If it wasn't sugared, we're done.
97203955Srdivacky    if (!IsSugar)
98203955Srdivacky      break;
99208600Srdivacky
100203955Srdivacky    // If the desugared type is a vector type, we don't want to expand
101203955Srdivacky    // it, it will turn into an attribute mess. People want their "vec4".
102203955Srdivacky    if (isa<VectorType>(Underlying))
103203955Srdivacky      break;
104208600Srdivacky
105203955Srdivacky    // Don't desugar through the primary typedef of an anonymous type.
106218893Sdim    if (const TagType *UTT = Underlying->getAs<TagType>())
107218893Sdim      if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))
108221345Sdim        if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
109218893Sdim          break;
110208600Srdivacky
111208600Srdivacky    // Record that we actually looked through an opaque type here.
112208600Srdivacky    ShouldAKA = true;
113203955Srdivacky    QT = Underlying;
114203955Srdivacky  }
115208600Srdivacky
116208600Srdivacky  // If we have a pointer-like type, desugar the pointee as well.
117208600Srdivacky  // FIXME: Handle other pointer-like types.
118208600Srdivacky  if (const PointerType *Ty = QT->getAs<PointerType>()) {
119218893Sdim    QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(),
120218893Sdim                                        ShouldAKA));
121208600Srdivacky  } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
122218893Sdim    QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(),
123218893Sdim                                                ShouldAKA));
124218893Sdim  } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
125218893Sdim    QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(),
126218893Sdim                                                ShouldAKA));
127203955Srdivacky  }
128208600Srdivacky
129218893Sdim  return QC.apply(Context, QT);
130203955Srdivacky}
131203955Srdivacky
132203955Srdivacky/// \brief Convert the given type to a string suitable for printing as part of
133208600Srdivacky/// a diagnostic.
134203955Srdivacky///
135224145Sdim/// There are four main criteria when determining whether we should have an
136208600Srdivacky/// a.k.a. clause when pretty-printing a type:
137208600Srdivacky///
138208600Srdivacky/// 1) Some types provide very minimal sugar that doesn't impede the
139208600Srdivacky///    user's understanding --- for example, elaborated type
140208600Srdivacky///    specifiers.  If this is all the sugar we see, we don't want an
141208600Srdivacky///    a.k.a. clause.
142208600Srdivacky/// 2) Some types are technically sugared but are much more familiar
143208600Srdivacky///    when seen in their sugared form --- for example, va_list,
144208600Srdivacky///    vector types, and the magic Objective C types.  We don't
145208600Srdivacky///    want to desugar these, even if we do produce an a.k.a. clause.
146208600Srdivacky/// 3) Some types may have already been desugared previously in this diagnostic.
147208600Srdivacky///    if this is the case, doing another "aka" would just be clutter.
148224145Sdim/// 4) Two different types within the same diagnostic have the same output
149224145Sdim///    string.  In this case, force an a.k.a with the desugared type when
150224145Sdim///    doing so will provide additional information.
151208600Srdivacky///
152203955Srdivacky/// \param Context the context in which the type was allocated
153203955Srdivacky/// \param Ty the type to print
154224145Sdim/// \param QualTypeVals pointer values to QualTypes which are used in the
155224145Sdim/// diagnostic message
156203955Srdivackystatic std::string
157203955SrdivackyConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
158226890Sdim                              const DiagnosticsEngine::ArgumentValue *PrevArgs,
159224145Sdim                              unsigned NumPrevArgs,
160235633Sdim                              ArrayRef<intptr_t> QualTypeVals) {
161203955Srdivacky  // FIXME: Playing with std::string is really slow.
162224145Sdim  bool ForceAKA = false;
163224145Sdim  QualType CanTy = Ty.getCanonicalType();
164226890Sdim  std::string S = Ty.getAsString(Context.getPrintingPolicy());
165226890Sdim  std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());
166208600Srdivacky
167235633Sdim  for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) {
168224145Sdim    QualType CompareTy =
169235633Sdim        QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I]));
170235633Sdim    if (CompareTy.isNull())
171235633Sdim      continue;
172224145Sdim    if (CompareTy == Ty)
173224145Sdim      continue;  // Same types
174224145Sdim    QualType CompareCanTy = CompareTy.getCanonicalType();
175224145Sdim    if (CompareCanTy == CanTy)
176224145Sdim      continue;  // Same canonical types
177226890Sdim    std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
178235633Sdim    bool aka;
179235633Sdim    QualType CompareDesugar = Desugar(Context, CompareTy, aka);
180235633Sdim    std::string CompareDesugarStr =
181235633Sdim        CompareDesugar.getAsString(Context.getPrintingPolicy());
182235633Sdim    if (CompareS != S && CompareDesugarStr != S)
183235633Sdim      continue;  // The type string is different than the comparison string
184235633Sdim                 // and the desugared comparison string.
185235633Sdim    std::string CompareCanS =
186235633Sdim        CompareCanTy.getAsString(Context.getPrintingPolicy());
187235633Sdim
188224145Sdim    if (CompareCanS == CanS)
189224145Sdim      continue;  // No new info from canonical type
190224145Sdim
191224145Sdim    ForceAKA = true;
192224145Sdim    break;
193224145Sdim  }
194224145Sdim
195208600Srdivacky  // Check to see if we already desugared this type in this
196208600Srdivacky  // diagnostic.  If so, don't do it again.
197208600Srdivacky  bool Repeated = false;
198208600Srdivacky  for (unsigned i = 0; i != NumPrevArgs; ++i) {
199208600Srdivacky    // TODO: Handle ak_declcontext case.
200226890Sdim    if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) {
201208600Srdivacky      void *Ptr = (void*)PrevArgs[i].second;
202208600Srdivacky      QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
203208600Srdivacky      if (PrevTy == Ty) {
204208600Srdivacky        Repeated = true;
205208600Srdivacky        break;
206208600Srdivacky      }
207208600Srdivacky    }
208208600Srdivacky  }
209208600Srdivacky
210203955Srdivacky  // Consider producing an a.k.a. clause if removing all the direct
211203955Srdivacky  // sugar gives us something "significantly different".
212208600Srdivacky  if (!Repeated) {
213208600Srdivacky    bool ShouldAKA = false;
214208600Srdivacky    QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA);
215224145Sdim    if (ShouldAKA || ForceAKA) {
216224145Sdim      if (DesugaredTy == Ty) {
217224145Sdim        DesugaredTy = Ty.getCanonicalType();
218224145Sdim      }
219226890Sdim      std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy());
220224145Sdim      if (akaStr != S) {
221224145Sdim        S = "'" + S + "' (aka '" + akaStr + "')";
222224145Sdim        return S;
223224145Sdim      }
224208600Srdivacky    }
225203955Srdivacky  }
226208600Srdivacky
227203955Srdivacky  S = "'" + S + "'";
228203955Srdivacky  return S;
229203955Srdivacky}
230203955Srdivacky
231245431Sdimstatic bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
232245431Sdim                                   QualType ToType, bool PrintTree,
233245431Sdim                                   bool PrintFromType, bool ElideType,
234252723Sdim                                   bool ShowColors, raw_ostream &OS);
235245431Sdim
236224145Sdimvoid clang::FormatASTNodeDiagnosticArgument(
237226890Sdim    DiagnosticsEngine::ArgumentKind Kind,
238224145Sdim    intptr_t Val,
239224145Sdim    const char *Modifier,
240224145Sdim    unsigned ModLen,
241224145Sdim    const char *Argument,
242224145Sdim    unsigned ArgLen,
243226890Sdim    const DiagnosticsEngine::ArgumentValue *PrevArgs,
244224145Sdim    unsigned NumPrevArgs,
245226890Sdim    SmallVectorImpl<char> &Output,
246224145Sdim    void *Cookie,
247235633Sdim    ArrayRef<intptr_t> QualTypeVals) {
248203955Srdivacky  ASTContext &Context = *static_cast<ASTContext*>(Cookie);
249203955Srdivacky
250252723Sdim  size_t OldEnd = Output.size();
251252723Sdim  llvm::raw_svector_ostream OS(Output);
252203955Srdivacky  bool NeedQuotes = true;
253203955Srdivacky
254203955Srdivacky  switch (Kind) {
255226890Sdim    default: llvm_unreachable("unknown ArgumentKind");
256245431Sdim    case DiagnosticsEngine::ak_qualtype_pair: {
257245431Sdim      TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val);
258245431Sdim      QualType FromType =
259245431Sdim          QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType));
260245431Sdim      QualType ToType =
261245431Sdim          QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType));
262245431Sdim
263245431Sdim      if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree,
264245431Sdim                                 TDT.PrintFromType, TDT.ElideType,
265252723Sdim                                 TDT.ShowColors, OS)) {
266245431Sdim        NeedQuotes = !TDT.PrintTree;
267245431Sdim        TDT.TemplateDiffUsed = true;
268245431Sdim        break;
269245431Sdim      }
270245431Sdim
271245431Sdim      // Don't fall-back during tree printing.  The caller will handle
272245431Sdim      // this case.
273245431Sdim      if (TDT.PrintTree)
274245431Sdim        return;
275245431Sdim
276252723Sdim      // Attempting to do a template diff on non-templates.  Set the variables
277245431Sdim      // and continue with regular type printing of the appropriate type.
278245431Sdim      Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType;
279245431Sdim      ModLen = 0;
280245431Sdim      ArgLen = 0;
281245431Sdim      // Fall through
282245431Sdim    }
283226890Sdim    case DiagnosticsEngine::ak_qualtype: {
284203955Srdivacky      assert(ModLen == 0 && ArgLen == 0 &&
285203955Srdivacky             "Invalid modifier for QualType argument");
286203955Srdivacky
287203955Srdivacky      QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
288252723Sdim      OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs,
289252723Sdim                                          QualTypeVals);
290203955Srdivacky      NeedQuotes = false;
291203955Srdivacky      break;
292203955Srdivacky    }
293226890Sdim    case DiagnosticsEngine::ak_declarationname: {
294203955Srdivacky      if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0)
295252723Sdim        OS << '+';
296203955Srdivacky      else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12)
297203955Srdivacky                && ArgLen==0)
298252723Sdim        OS << '-';
299203955Srdivacky      else
300203955Srdivacky        assert(ModLen == 0 && ArgLen == 0 &&
301203955Srdivacky               "Invalid modifier for DeclarationName argument");
302252723Sdim
303263509Sdim      OS << DeclarationName::getFromOpaqueInteger(Val);
304203955Srdivacky      break;
305203955Srdivacky    }
306226890Sdim    case DiagnosticsEngine::ak_nameddecl: {
307203955Srdivacky      bool Qualified;
308203955Srdivacky      if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)
309203955Srdivacky        Qualified = true;
310203955Srdivacky      else {
311203955Srdivacky        assert(ModLen == 0 && ArgLen == 0 &&
312203955Srdivacky               "Invalid modifier for NamedDecl* argument");
313203955Srdivacky        Qualified = false;
314203955Srdivacky      }
315226890Sdim      const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val);
316252723Sdim      ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified);
317203955Srdivacky      break;
318203955Srdivacky    }
319226890Sdim    case DiagnosticsEngine::ak_nestednamespec: {
320252723Sdim      NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val);
321252723Sdim      NNS->print(OS, Context.getPrintingPolicy());
322203955Srdivacky      NeedQuotes = false;
323203955Srdivacky      break;
324203955Srdivacky    }
325226890Sdim    case DiagnosticsEngine::ak_declcontext: {
326203955Srdivacky      DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
327203955Srdivacky      assert(DC && "Should never have a null declaration context");
328203955Srdivacky
329203955Srdivacky      if (DC->isTranslationUnit()) {
330203955Srdivacky        // FIXME: Get these strings from some localized place
331235633Sdim        if (Context.getLangOpts().CPlusPlus)
332252723Sdim          OS << "the global namespace";
333203955Srdivacky        else
334252723Sdim          OS << "the global scope";
335203955Srdivacky      } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
336252723Sdim        OS << ConvertTypeToDiagnosticString(Context,
337252723Sdim                                            Context.getTypeDeclType(Type),
338252723Sdim                                            PrevArgs, NumPrevArgs,
339252723Sdim                                            QualTypeVals);
340203955Srdivacky      } else {
341203955Srdivacky        // FIXME: Get these strings from some localized place
342203955Srdivacky        NamedDecl *ND = cast<NamedDecl>(DC);
343203955Srdivacky        if (isa<NamespaceDecl>(ND))
344252723Sdim          OS << "namespace ";
345203955Srdivacky        else if (isa<ObjCMethodDecl>(ND))
346252723Sdim          OS << "method ";
347203955Srdivacky        else if (isa<FunctionDecl>(ND))
348252723Sdim          OS << "function ";
349252723Sdim
350252723Sdim        OS << '\'';
351252723Sdim        ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
352252723Sdim        OS << '\'';
353203955Srdivacky      }
354203955Srdivacky      NeedQuotes = false;
355203955Srdivacky      break;
356203955Srdivacky    }
357203955Srdivacky  }
358252723Sdim
359252723Sdim  OS.flush();
360252723Sdim
361252723Sdim  if (NeedQuotes) {
362252723Sdim    Output.insert(Output.begin()+OldEnd, '\'');
363203955Srdivacky    Output.push_back('\'');
364252723Sdim  }
365203955Srdivacky}
366245431Sdim
367245431Sdim/// TemplateDiff - A class that constructs a pretty string for a pair of
368245431Sdim/// QualTypes.  For the pair of types, a diff tree will be created containing
369245431Sdim/// all the information about the templates and template arguments.  Afterwards,
370245431Sdim/// the tree is transformed to a string according to the options passed in.
371245431Sdimnamespace {
372245431Sdimclass TemplateDiff {
373245431Sdim  /// Context - The ASTContext which is used for comparing template arguments.
374245431Sdim  ASTContext &Context;
375245431Sdim
376245431Sdim  /// Policy - Used during expression printing.
377245431Sdim  PrintingPolicy Policy;
378245431Sdim
379245431Sdim  /// ElideType - Option to elide identical types.
380245431Sdim  bool ElideType;
381245431Sdim
382245431Sdim  /// PrintTree - Format output string as a tree.
383245431Sdim  bool PrintTree;
384245431Sdim
385245431Sdim  /// ShowColor - Diagnostics support color, so bolding will be used.
386245431Sdim  bool ShowColor;
387245431Sdim
388245431Sdim  /// FromType - When single type printing is selected, this is the type to be
389245431Sdim  /// be printed.  When tree printing is selected, this type will show up first
390245431Sdim  /// in the tree.
391245431Sdim  QualType FromType;
392245431Sdim
393245431Sdim  /// ToType - The type that FromType is compared to.  Only in tree printing
394245431Sdim  /// will this type be outputed.
395245431Sdim  QualType ToType;
396245431Sdim
397245431Sdim  /// OS - The stream used to construct the output strings.
398252723Sdim  raw_ostream &OS;
399245431Sdim
400245431Sdim  /// IsBold - Keeps track of the bold formatting for the output string.
401245431Sdim  bool IsBold;
402245431Sdim
403245431Sdim  /// DiffTree - A tree representation the differences between two types.
404245431Sdim  class DiffTree {
405252723Sdim  public:
406252723Sdim    /// DiffKind - The difference in a DiffNode and which fields are used.
407252723Sdim    enum DiffKind {
408252723Sdim      /// Incomplete or invalid node.
409252723Sdim      Invalid,
410252723Sdim      /// Another level of templates, uses TemplateDecl and Qualifiers
411252723Sdim      Template,
412252723Sdim      /// Type difference, uses QualType
413252723Sdim      Type,
414252723Sdim      /// Expression difference, uses Expr
415252723Sdim      Expression,
416252723Sdim      /// Template argument difference, uses TemplateDecl
417252723Sdim      TemplateTemplate,
418252723Sdim      /// Integer difference, uses APSInt and Expr
419252723Sdim      Integer,
420252723Sdim      /// Declaration difference, uses ValueDecl
421252723Sdim      Declaration
422252723Sdim    };
423252723Sdim  private:
424245431Sdim    /// DiffNode - The root node stores the original type.  Each child node
425245431Sdim    /// stores template arguments of their parents.  For templated types, the
426245431Sdim    /// template decl is also stored.
427245431Sdim    struct DiffNode {
428252723Sdim      DiffKind Kind;
429252723Sdim
430245431Sdim      /// NextNode - The index of the next sibling node or 0.
431245431Sdim      unsigned NextNode;
432245431Sdim
433245431Sdim      /// ChildNode - The index of the first child node or 0.
434245431Sdim      unsigned ChildNode;
435245431Sdim
436245431Sdim      /// ParentNode - The index of the parent node.
437245431Sdim      unsigned ParentNode;
438245431Sdim
439245431Sdim      /// FromType, ToType - The type arguments.
440245431Sdim      QualType FromType, ToType;
441245431Sdim
442245431Sdim      /// FromExpr, ToExpr - The expression arguments.
443245431Sdim      Expr *FromExpr, *ToExpr;
444245431Sdim
445245431Sdim      /// FromTD, ToTD - The template decl for template template
446245431Sdim      /// arguments or the type arguments that are templates.
447245431Sdim      TemplateDecl *FromTD, *ToTD;
448245431Sdim
449245431Sdim      /// FromQual, ToQual - Qualifiers for template types.
450245431Sdim      Qualifiers FromQual, ToQual;
451245431Sdim
452245431Sdim      /// FromInt, ToInt - APSInt's for integral arguments.
453245431Sdim      llvm::APSInt FromInt, ToInt;
454245431Sdim
455245431Sdim      /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid.
456245431Sdim      bool IsValidFromInt, IsValidToInt;
457245431Sdim
458252723Sdim      /// FromValueDecl, ToValueDecl - Whether the argument is a decl.
459252723Sdim      ValueDecl *FromValueDecl, *ToValueDecl;
460252723Sdim
461263509Sdim      /// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of
462263509Sdim      /// operator before it.
463263509Sdim      bool FromAddressOf, ToAddressOf;
464263509Sdim
465245431Sdim      /// FromDefault, ToDefault - Whether the argument is a default argument.
466245431Sdim      bool FromDefault, ToDefault;
467245431Sdim
468245431Sdim      /// Same - Whether the two arguments evaluate to the same value.
469245431Sdim      bool Same;
470245431Sdim
471245431Sdim      DiffNode(unsigned ParentNode = 0)
472252723Sdim        : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode),
473245431Sdim          FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0),
474252723Sdim          IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0),
475263509Sdim          ToValueDecl(0), FromAddressOf(false), ToAddressOf(false),
476263509Sdim          FromDefault(false), ToDefault(false), Same(false) { }
477245431Sdim    };
478245431Sdim
479245431Sdim    /// FlatTree - A flattened tree used to store the DiffNodes.
480252723Sdim    SmallVector<DiffNode, 16> FlatTree;
481245431Sdim
482245431Sdim    /// CurrentNode - The index of the current node being used.
483245431Sdim    unsigned CurrentNode;
484245431Sdim
485245431Sdim    /// NextFreeNode - The index of the next unused node.  Used when creating
486245431Sdim    /// child nodes.
487245431Sdim    unsigned NextFreeNode;
488245431Sdim
489245431Sdim    /// ReadNode - The index of the current node being read.
490245431Sdim    unsigned ReadNode;
491245431Sdim
492245431Sdim  public:
493245431Sdim    DiffTree() :
494245431Sdim        CurrentNode(0), NextFreeNode(1) {
495245431Sdim      FlatTree.push_back(DiffNode());
496245431Sdim    }
497245431Sdim
498245431Sdim    // Node writing functions.
499245431Sdim    /// SetNode - Sets FromTD and ToTD of the current node.
500245431Sdim    void SetNode(TemplateDecl *FromTD, TemplateDecl *ToTD) {
501245431Sdim      FlatTree[CurrentNode].FromTD = FromTD;
502245431Sdim      FlatTree[CurrentNode].ToTD = ToTD;
503245431Sdim    }
504245431Sdim
505245431Sdim    /// SetNode - Sets FromType and ToType of the current node.
506245431Sdim    void SetNode(QualType FromType, QualType ToType) {
507245431Sdim      FlatTree[CurrentNode].FromType = FromType;
508245431Sdim      FlatTree[CurrentNode].ToType = ToType;
509245431Sdim    }
510245431Sdim
511245431Sdim    /// SetNode - Set FromExpr and ToExpr of the current node.
512245431Sdim    void SetNode(Expr *FromExpr, Expr *ToExpr) {
513245431Sdim      FlatTree[CurrentNode].FromExpr = FromExpr;
514245431Sdim      FlatTree[CurrentNode].ToExpr = ToExpr;
515245431Sdim    }
516245431Sdim
517245431Sdim    /// SetNode - Set FromInt and ToInt of the current node.
518245431Sdim    void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt,
519245431Sdim                 bool IsValidFromInt, bool IsValidToInt) {
520245431Sdim      FlatTree[CurrentNode].FromInt = FromInt;
521245431Sdim      FlatTree[CurrentNode].ToInt = ToInt;
522245431Sdim      FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt;
523245431Sdim      FlatTree[CurrentNode].IsValidToInt = IsValidToInt;
524245431Sdim    }
525245431Sdim
526245431Sdim    /// SetNode - Set FromQual and ToQual of the current node.
527245431Sdim    void SetNode(Qualifiers FromQual, Qualifiers ToQual) {
528245431Sdim      FlatTree[CurrentNode].FromQual = FromQual;
529245431Sdim      FlatTree[CurrentNode].ToQual = ToQual;
530245431Sdim    }
531245431Sdim
532252723Sdim    /// SetNode - Set FromValueDecl and ToValueDecl of the current node.
533263509Sdim    void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
534263509Sdim                 bool FromAddressOf, bool ToAddressOf) {
535252723Sdim      FlatTree[CurrentNode].FromValueDecl = FromValueDecl;
536252723Sdim      FlatTree[CurrentNode].ToValueDecl = ToValueDecl;
537263509Sdim      FlatTree[CurrentNode].FromAddressOf = FromAddressOf;
538263509Sdim      FlatTree[CurrentNode].ToAddressOf = ToAddressOf;
539252723Sdim    }
540252723Sdim
541245431Sdim    /// SetSame - Sets the same flag of the current node.
542245431Sdim    void SetSame(bool Same) {
543245431Sdim      FlatTree[CurrentNode].Same = Same;
544245431Sdim    }
545245431Sdim
546245431Sdim    /// SetDefault - Sets FromDefault and ToDefault flags of the current node.
547245431Sdim    void SetDefault(bool FromDefault, bool ToDefault) {
548245431Sdim      FlatTree[CurrentNode].FromDefault = FromDefault;
549245431Sdim      FlatTree[CurrentNode].ToDefault = ToDefault;
550245431Sdim    }
551245431Sdim
552252723Sdim    /// SetKind - Sets the current node's type.
553252723Sdim    void SetKind(DiffKind Kind) {
554252723Sdim      FlatTree[CurrentNode].Kind = Kind;
555252723Sdim    }
556252723Sdim
557245431Sdim    /// Up - Changes the node to the parent of the current node.
558245431Sdim    void Up() {
559245431Sdim      CurrentNode = FlatTree[CurrentNode].ParentNode;
560245431Sdim    }
561245431Sdim
562245431Sdim    /// AddNode - Adds a child node to the current node, then sets that node
563245431Sdim    /// node as the current node.
564245431Sdim    void AddNode() {
565245431Sdim      FlatTree.push_back(DiffNode(CurrentNode));
566245431Sdim      DiffNode &Node = FlatTree[CurrentNode];
567245431Sdim      if (Node.ChildNode == 0) {
568245431Sdim        // If a child node doesn't exist, add one.
569245431Sdim        Node.ChildNode = NextFreeNode;
570245431Sdim      } else {
571245431Sdim        // If a child node exists, find the last child node and add a
572245431Sdim        // next node to it.
573245431Sdim        unsigned i;
574245431Sdim        for (i = Node.ChildNode; FlatTree[i].NextNode != 0;
575245431Sdim             i = FlatTree[i].NextNode) {
576245431Sdim        }
577245431Sdim        FlatTree[i].NextNode = NextFreeNode;
578245431Sdim      }
579245431Sdim      CurrentNode = NextFreeNode;
580245431Sdim      ++NextFreeNode;
581245431Sdim    }
582245431Sdim
583245431Sdim    // Node reading functions.
584245431Sdim    /// StartTraverse - Prepares the tree for recursive traversal.
585245431Sdim    void StartTraverse() {
586245431Sdim      ReadNode = 0;
587245431Sdim      CurrentNode = NextFreeNode;
588245431Sdim      NextFreeNode = 0;
589245431Sdim    }
590245431Sdim
591245431Sdim    /// Parent - Move the current read node to its parent.
592245431Sdim    void Parent() {
593245431Sdim      ReadNode = FlatTree[ReadNode].ParentNode;
594245431Sdim    }
595245431Sdim
596245431Sdim    /// GetNode - Gets the FromType and ToType.
597245431Sdim    void GetNode(QualType &FromType, QualType &ToType) {
598245431Sdim      FromType = FlatTree[ReadNode].FromType;
599245431Sdim      ToType = FlatTree[ReadNode].ToType;
600245431Sdim    }
601245431Sdim
602245431Sdim    /// GetNode - Gets the FromExpr and ToExpr.
603245431Sdim    void GetNode(Expr *&FromExpr, Expr *&ToExpr) {
604245431Sdim      FromExpr = FlatTree[ReadNode].FromExpr;
605245431Sdim      ToExpr = FlatTree[ReadNode].ToExpr;
606245431Sdim    }
607245431Sdim
608245431Sdim    /// GetNode - Gets the FromTD and ToTD.
609245431Sdim    void GetNode(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {
610245431Sdim      FromTD = FlatTree[ReadNode].FromTD;
611245431Sdim      ToTD = FlatTree[ReadNode].ToTD;
612245431Sdim    }
613245431Sdim
614245431Sdim    /// GetNode - Gets the FromInt and ToInt.
615245431Sdim    void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
616245431Sdim                 bool &IsValidFromInt, bool &IsValidToInt) {
617245431Sdim      FromInt = FlatTree[ReadNode].FromInt;
618245431Sdim      ToInt = FlatTree[ReadNode].ToInt;
619245431Sdim      IsValidFromInt = FlatTree[ReadNode].IsValidFromInt;
620245431Sdim      IsValidToInt = FlatTree[ReadNode].IsValidToInt;
621245431Sdim    }
622245431Sdim
623245431Sdim    /// GetNode - Gets the FromQual and ToQual.
624245431Sdim    void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) {
625245431Sdim      FromQual = FlatTree[ReadNode].FromQual;
626245431Sdim      ToQual = FlatTree[ReadNode].ToQual;
627245431Sdim    }
628245431Sdim
629252723Sdim    /// GetNode - Gets the FromValueDecl and ToValueDecl.
630263509Sdim    void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
631263509Sdim                 bool &FromAddressOf, bool &ToAddressOf) {
632252723Sdim      FromValueDecl = FlatTree[ReadNode].FromValueDecl;
633252723Sdim      ToValueDecl = FlatTree[ReadNode].ToValueDecl;
634263509Sdim      FromAddressOf = FlatTree[ReadNode].FromAddressOf;
635263509Sdim      ToAddressOf = FlatTree[ReadNode].ToAddressOf;
636252723Sdim    }
637252723Sdim
638245431Sdim    /// NodeIsSame - Returns true the arguments are the same.
639245431Sdim    bool NodeIsSame() {
640245431Sdim      return FlatTree[ReadNode].Same;
641245431Sdim    }
642245431Sdim
643245431Sdim    /// HasChildrend - Returns true if the node has children.
644245431Sdim    bool HasChildren() {
645245431Sdim      return FlatTree[ReadNode].ChildNode != 0;
646245431Sdim    }
647245431Sdim
648245431Sdim    /// MoveToChild - Moves from the current node to its child.
649245431Sdim    void MoveToChild() {
650245431Sdim      ReadNode = FlatTree[ReadNode].ChildNode;
651245431Sdim    }
652245431Sdim
653245431Sdim    /// AdvanceSibling - If there is a next sibling, advance to it and return
654245431Sdim    /// true.  Otherwise, return false.
655245431Sdim    bool AdvanceSibling() {
656245431Sdim      if (FlatTree[ReadNode].NextNode == 0)
657245431Sdim        return false;
658245431Sdim
659245431Sdim      ReadNode = FlatTree[ReadNode].NextNode;
660245431Sdim      return true;
661245431Sdim    }
662245431Sdim
663245431Sdim    /// HasNextSibling - Return true if the node has a next sibling.
664245431Sdim    bool HasNextSibling() {
665245431Sdim      return FlatTree[ReadNode].NextNode != 0;
666245431Sdim    }
667245431Sdim
668245431Sdim    /// FromDefault - Return true if the from argument is the default.
669245431Sdim    bool FromDefault() {
670245431Sdim      return FlatTree[ReadNode].FromDefault;
671245431Sdim    }
672245431Sdim
673245431Sdim    /// ToDefault - Return true if the to argument is the default.
674245431Sdim    bool ToDefault() {
675245431Sdim      return FlatTree[ReadNode].ToDefault;
676245431Sdim    }
677245431Sdim
678245431Sdim    /// Empty - Returns true if the tree has no information.
679245431Sdim    bool Empty() {
680252723Sdim      return GetKind() == Invalid;
681245431Sdim    }
682252723Sdim
683252723Sdim    /// GetKind - Returns the current node's type.
684252723Sdim    DiffKind GetKind() {
685252723Sdim      return FlatTree[ReadNode].Kind;
686252723Sdim    }
687245431Sdim  };
688245431Sdim
689245431Sdim  DiffTree Tree;
690245431Sdim
691245431Sdim  /// TSTiterator - an iterator that is used to enter a
692245431Sdim  /// TemplateSpecializationType and read TemplateArguments inside template
693245431Sdim  /// parameter packs in order with the rest of the TemplateArguments.
694245431Sdim  struct TSTiterator {
695245431Sdim    typedef const TemplateArgument& reference;
696245431Sdim    typedef const TemplateArgument* pointer;
697245431Sdim
698245431Sdim    /// TST - the template specialization whose arguments this iterator
699245431Sdim    /// traverse over.
700245431Sdim    const TemplateSpecializationType *TST;
701245431Sdim
702252723Sdim    /// DesugarTST - desugared template specialization used to extract
703252723Sdim    /// default argument information
704252723Sdim    const TemplateSpecializationType *DesugarTST;
705252723Sdim
706245431Sdim    /// Index - the index of the template argument in TST.
707245431Sdim    unsigned Index;
708245431Sdim
709245431Sdim    /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA
710245431Sdim    /// points to a TemplateArgument within a parameter pack.
711245431Sdim    TemplateArgument::pack_iterator CurrentTA;
712245431Sdim
713245431Sdim    /// EndTA - the end iterator of a parameter pack
714245431Sdim    TemplateArgument::pack_iterator EndTA;
715245431Sdim
716245431Sdim    /// TSTiterator - Constructs an iterator and sets it to the first template
717245431Sdim    /// argument.
718252723Sdim    TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
719252723Sdim        : TST(TST),
720252723Sdim          DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())),
721252723Sdim          Index(0), CurrentTA(0), EndTA(0) {
722245431Sdim      if (isEnd()) return;
723245431Sdim
724245431Sdim      // Set to first template argument.  If not a parameter pack, done.
725245431Sdim      TemplateArgument TA = TST->getArg(0);
726245431Sdim      if (TA.getKind() != TemplateArgument::Pack) return;
727245431Sdim
728245431Sdim      // Start looking into the parameter pack.
729245431Sdim      CurrentTA = TA.pack_begin();
730245431Sdim      EndTA = TA.pack_end();
731245431Sdim
732245431Sdim      // Found a valid template argument.
733245431Sdim      if (CurrentTA != EndTA) return;
734245431Sdim
735245431Sdim      // Parameter pack is empty, use the increment to get to a valid
736245431Sdim      // template argument.
737245431Sdim      ++(*this);
738245431Sdim    }
739245431Sdim
740245431Sdim    /// isEnd - Returns true if the iterator is one past the end.
741245431Sdim    bool isEnd() const {
742252723Sdim      return Index >= TST->getNumArgs();
743245431Sdim    }
744245431Sdim
745245431Sdim    /// &operator++ - Increment the iterator to the next template argument.
746245431Sdim    TSTiterator &operator++() {
747252723Sdim      // After the end, Index should be the default argument position in
748252723Sdim      // DesugarTST, if it exists.
749252723Sdim      if (isEnd()) {
750252723Sdim        ++Index;
751252723Sdim        return *this;
752252723Sdim      }
753245431Sdim
754245431Sdim      // If in a parameter pack, advance in the parameter pack.
755245431Sdim      if (CurrentTA != EndTA) {
756245431Sdim        ++CurrentTA;
757245431Sdim        if (CurrentTA != EndTA)
758245431Sdim          return *this;
759245431Sdim      }
760245431Sdim
761245431Sdim      // Loop until a template argument is found, or the end is reached.
762245431Sdim      while (true) {
763245431Sdim        // Advance to the next template argument.  Break if reached the end.
764245431Sdim        if (++Index == TST->getNumArgs()) break;
765245431Sdim
766245431Sdim        // If the TemplateArgument is not a parameter pack, done.
767245431Sdim        TemplateArgument TA = TST->getArg(Index);
768245431Sdim        if (TA.getKind() != TemplateArgument::Pack) break;
769245431Sdim
770245431Sdim        // Handle parameter packs.
771245431Sdim        CurrentTA = TA.pack_begin();
772245431Sdim        EndTA = TA.pack_end();
773245431Sdim
774245431Sdim        // If the parameter pack is empty, try to advance again.
775245431Sdim        if (CurrentTA != EndTA) break;
776245431Sdim      }
777245431Sdim      return *this;
778245431Sdim    }
779245431Sdim
780245431Sdim    /// operator* - Returns the appropriate TemplateArgument.
781245431Sdim    reference operator*() const {
782245431Sdim      assert(!isEnd() && "Index exceeds number of arguments.");
783245431Sdim      if (CurrentTA == EndTA)
784245431Sdim        return TST->getArg(Index);
785245431Sdim      else
786245431Sdim        return *CurrentTA;
787245431Sdim    }
788245431Sdim
789245431Sdim    /// operator-> - Allow access to the underlying TemplateArgument.
790245431Sdim    pointer operator->() const {
791245431Sdim      return &operator*();
792245431Sdim    }
793252723Sdim
794252723Sdim    /// getDesugar - Returns the deduced template argument from DesguarTST
795252723Sdim    reference getDesugar() const {
796252723Sdim      return DesugarTST->getArg(Index);
797252723Sdim    }
798245431Sdim  };
799245431Sdim
800245431Sdim  // These functions build up the template diff tree, including functions to
801245431Sdim  // retrieve and compare template arguments.
802245431Sdim
803245431Sdim  static const TemplateSpecializationType * GetTemplateSpecializationType(
804245431Sdim      ASTContext &Context, QualType Ty) {
805245431Sdim    if (const TemplateSpecializationType *TST =
806245431Sdim            Ty->getAs<TemplateSpecializationType>())
807245431Sdim      return TST;
808245431Sdim
809245431Sdim    const RecordType *RT = Ty->getAs<RecordType>();
810245431Sdim
811245431Sdim    if (!RT)
812245431Sdim      return 0;
813245431Sdim
814245431Sdim    const ClassTemplateSpecializationDecl *CTSD =
815245431Sdim        dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
816245431Sdim
817245431Sdim    if (!CTSD)
818245431Sdim      return 0;
819245431Sdim
820245431Sdim    Ty = Context.getTemplateSpecializationType(
821245431Sdim             TemplateName(CTSD->getSpecializedTemplate()),
822245431Sdim             CTSD->getTemplateArgs().data(),
823245431Sdim             CTSD->getTemplateArgs().size(),
824252723Sdim             Ty.getLocalUnqualifiedType().getCanonicalType());
825245431Sdim
826245431Sdim    return Ty->getAs<TemplateSpecializationType>();
827245431Sdim  }
828245431Sdim
829245431Sdim  /// DiffTemplate - recursively visits template arguments and stores the
830245431Sdim  /// argument info into a tree.
831245431Sdim  void DiffTemplate(const TemplateSpecializationType *FromTST,
832245431Sdim                    const TemplateSpecializationType *ToTST) {
833245431Sdim    // Begin descent into diffing template tree.
834263509Sdim    TemplateParameterList *ParamsFrom =
835245431Sdim        FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
836263509Sdim    TemplateParameterList *ParamsTo =
837263509Sdim        ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
838245431Sdim    unsigned TotalArgs = 0;
839252723Sdim    for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST);
840245431Sdim         !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {
841245431Sdim      Tree.AddNode();
842245431Sdim
843245431Sdim      // Get the parameter at index TotalArgs.  If index is larger
844245431Sdim      // than the total number of parameters, then there is an
845245431Sdim      // argument pack, so re-use the last parameter.
846263509Sdim      unsigned ParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);
847263509Sdim      NamedDecl *ParamND = ParamsFrom->getParam(ParamIndex);
848263509Sdim
849245431Sdim      // Handle Types
850245431Sdim      if (TemplateTypeParmDecl *DefaultTTPD =
851245431Sdim              dyn_cast<TemplateTypeParmDecl>(ParamND)) {
852245431Sdim        QualType FromType, ToType;
853252723Sdim        FromType = GetType(FromIter, DefaultTTPD);
854263509Sdim        // A forward declaration can have no default arg but the actual class
855263509Sdim        // can, don't mix up iterators and get the original parameter.
856263509Sdim        ToType = GetType(
857263509Sdim            ToIter, cast<TemplateTypeParmDecl>(ParamsTo->getParam(ParamIndex)));
858245431Sdim        Tree.SetNode(FromType, ToType);
859245431Sdim        Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(),
860245431Sdim                        ToIter.isEnd() && !ToType.isNull());
861252723Sdim        Tree.SetKind(DiffTree::Type);
862245431Sdim        if (!FromType.isNull() && !ToType.isNull()) {
863245431Sdim          if (Context.hasSameType(FromType, ToType)) {
864245431Sdim            Tree.SetSame(true);
865245431Sdim          } else {
866245431Sdim            Qualifiers FromQual = FromType.getQualifiers(),
867245431Sdim                       ToQual = ToType.getQualifiers();
868245431Sdim            const TemplateSpecializationType *FromArgTST =
869245431Sdim                GetTemplateSpecializationType(Context, FromType);
870245431Sdim            const TemplateSpecializationType *ToArgTST =
871245431Sdim                GetTemplateSpecializationType(Context, ToType);
872245431Sdim
873245431Sdim            if (FromArgTST && ToArgTST &&
874245431Sdim                hasSameTemplate(FromArgTST, ToArgTST)) {
875245431Sdim              FromQual -= QualType(FromArgTST, 0).getQualifiers();
876245431Sdim              ToQual -= QualType(ToArgTST, 0).getQualifiers();
877245431Sdim              Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),
878245431Sdim                           ToArgTST->getTemplateName().getAsTemplateDecl());
879245431Sdim              Tree.SetNode(FromQual, ToQual);
880252723Sdim              Tree.SetKind(DiffTree::Template);
881245431Sdim              DiffTemplate(FromArgTST, ToArgTST);
882245431Sdim            }
883245431Sdim          }
884245431Sdim        }
885245431Sdim      }
886245431Sdim
887245431Sdim      // Handle Expressions
888245431Sdim      if (NonTypeTemplateParmDecl *DefaultNTTPD =
889245431Sdim              dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {
890252723Sdim        Expr *FromExpr = 0, *ToExpr = 0;
891245431Sdim        llvm::APSInt FromInt, ToInt;
892252723Sdim        ValueDecl *FromValueDecl = 0, *ToValueDecl = 0;
893252723Sdim        unsigned ParamWidth = 128; // Safe default
894252723Sdim        if (DefaultNTTPD->getType()->isIntegralOrEnumerationType())
895252723Sdim          ParamWidth = Context.getIntWidth(DefaultNTTPD->getType());
896245431Sdim        bool HasFromInt = !FromIter.isEnd() &&
897245431Sdim                          FromIter->getKind() == TemplateArgument::Integral;
898245431Sdim        bool HasToInt = !ToIter.isEnd() &&
899245431Sdim                        ToIter->getKind() == TemplateArgument::Integral;
900252723Sdim        bool HasFromValueDecl =
901252723Sdim            !FromIter.isEnd() &&
902252723Sdim            FromIter->getKind() == TemplateArgument::Declaration;
903252723Sdim        bool HasToValueDecl =
904252723Sdim            !ToIter.isEnd() &&
905252723Sdim            ToIter->getKind() == TemplateArgument::Declaration;
906252723Sdim
907252723Sdim        assert(((!HasFromInt && !HasToInt) ||
908252723Sdim                (!HasFromValueDecl && !HasToValueDecl)) &&
909252723Sdim               "Template argument cannot be both integer and declaration");
910252723Sdim
911245431Sdim        if (HasFromInt)
912245431Sdim          FromInt = FromIter->getAsIntegral();
913252723Sdim        else if (HasFromValueDecl)
914252723Sdim          FromValueDecl = FromIter->getAsDecl();
915245431Sdim        else
916252723Sdim          FromExpr = GetExpr(FromIter, DefaultNTTPD);
917245431Sdim
918245431Sdim        if (HasToInt)
919245431Sdim          ToInt = ToIter->getAsIntegral();
920252723Sdim        else if (HasToValueDecl)
921252723Sdim          ToValueDecl = ToIter->getAsDecl();
922245431Sdim        else
923252723Sdim          ToExpr = GetExpr(ToIter, DefaultNTTPD);
924245431Sdim
925252723Sdim        if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) {
926245431Sdim          Tree.SetNode(FromExpr, ToExpr);
927245431Sdim          Tree.SetDefault(FromIter.isEnd() && FromExpr,
928245431Sdim                          ToIter.isEnd() && ToExpr);
929252723Sdim          if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) {
930252723Sdim            if (FromExpr)
931252723Sdim              FromInt = GetInt(FromIter, FromExpr);
932252723Sdim            if (ToExpr)
933252723Sdim              ToInt = GetInt(ToIter, ToExpr);
934252723Sdim            Tree.SetNode(FromInt, ToInt, FromExpr, ToExpr);
935252723Sdim            Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
936252723Sdim            Tree.SetKind(DiffTree::Integer);
937252723Sdim          } else {
938252723Sdim            Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr));
939252723Sdim            Tree.SetKind(DiffTree::Expression);
940252723Sdim          }
941252723Sdim        } else if (HasFromInt || HasToInt) {
942245431Sdim          if (!HasFromInt && FromExpr) {
943252723Sdim            FromInt = GetInt(FromIter, FromExpr);
944245431Sdim            HasFromInt = true;
945245431Sdim          }
946245431Sdim          if (!HasToInt && ToExpr) {
947252723Sdim            ToInt = GetInt(ToIter, ToExpr);
948245431Sdim            HasToInt = true;
949245431Sdim          }
950245431Sdim          Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
951252723Sdim          Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
952245431Sdim          Tree.SetDefault(FromIter.isEnd() && HasFromInt,
953245431Sdim                          ToIter.isEnd() && HasToInt);
954252723Sdim          Tree.SetKind(DiffTree::Integer);
955252723Sdim        } else {
956252723Sdim          if (!HasFromValueDecl && FromExpr)
957252723Sdim            FromValueDecl = GetValueDecl(FromIter, FromExpr);
958252723Sdim          if (!HasToValueDecl && ToExpr)
959252723Sdim            ToValueDecl = GetValueDecl(ToIter, ToExpr);
960263509Sdim          QualType ArgumentType = DefaultNTTPD->getType();
961263509Sdim          bool FromAddressOf = FromValueDecl &&
962263509Sdim                               !ArgumentType->isReferenceType() &&
963263509Sdim                               !FromValueDecl->getType()->isArrayType();
964263509Sdim          bool ToAddressOf = ToValueDecl &&
965263509Sdim                             !ArgumentType->isReferenceType() &&
966263509Sdim                             !ToValueDecl->getType()->isArrayType();
967263509Sdim          Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
968252723Sdim          Tree.SetSame(FromValueDecl && ToValueDecl &&
969252723Sdim                       FromValueDecl->getCanonicalDecl() ==
970252723Sdim                       ToValueDecl->getCanonicalDecl());
971252723Sdim          Tree.SetDefault(FromIter.isEnd() && FromValueDecl,
972252723Sdim                          ToIter.isEnd() && ToValueDecl);
973252723Sdim          Tree.SetKind(DiffTree::Declaration);
974245431Sdim        }
975245431Sdim      }
976245431Sdim
977245431Sdim      // Handle Templates
978245431Sdim      if (TemplateTemplateParmDecl *DefaultTTPD =
979245431Sdim              dyn_cast<TemplateTemplateParmDecl>(ParamND)) {
980245431Sdim        TemplateDecl *FromDecl, *ToDecl;
981252723Sdim        FromDecl = GetTemplateDecl(FromIter, DefaultTTPD);
982252723Sdim        ToDecl = GetTemplateDecl(ToIter, DefaultTTPD);
983245431Sdim        Tree.SetNode(FromDecl, ToDecl);
984252723Sdim        Tree.SetSame(
985252723Sdim            FromDecl && ToDecl &&
986252723Sdim            FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());
987252723Sdim        Tree.SetKind(DiffTree::TemplateTemplate);
988245431Sdim      }
989245431Sdim
990252723Sdim      ++FromIter;
991252723Sdim      ++ToIter;
992245431Sdim      Tree.Up();
993245431Sdim    }
994245431Sdim  }
995245431Sdim
996245431Sdim  /// makeTemplateList - Dump every template alias into the vector.
997245431Sdim  static void makeTemplateList(
998263509Sdim      SmallVectorImpl<const TemplateSpecializationType *> &TemplateList,
999245431Sdim      const TemplateSpecializationType *TST) {
1000245431Sdim    while (TST) {
1001245431Sdim      TemplateList.push_back(TST);
1002245431Sdim      if (!TST->isTypeAlias())
1003245431Sdim        return;
1004245431Sdim      TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
1005245431Sdim    }
1006245431Sdim  }
1007245431Sdim
1008245431Sdim  /// hasSameBaseTemplate - Returns true when the base templates are the same,
1009245431Sdim  /// even if the template arguments are not.
1010245431Sdim  static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST,
1011245431Sdim                                  const TemplateSpecializationType *ToTST) {
1012252723Sdim    return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() ==
1013252723Sdim           ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl();
1014245431Sdim  }
1015245431Sdim
1016245431Sdim  /// hasSameTemplate - Returns true if both types are specialized from the
1017245431Sdim  /// same template declaration.  If they come from different template aliases,
1018245431Sdim  /// do a parallel ascension search to determine the highest template alias in
1019245431Sdim  /// common and set the arguments to them.
1020245431Sdim  static bool hasSameTemplate(const TemplateSpecializationType *&FromTST,
1021245431Sdim                              const TemplateSpecializationType *&ToTST) {
1022245431Sdim    // Check the top templates if they are the same.
1023245431Sdim    if (hasSameBaseTemplate(FromTST, ToTST))
1024245431Sdim      return true;
1025245431Sdim
1026245431Sdim    // Create vectors of template aliases.
1027245431Sdim    SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,
1028245431Sdim                                                      ToTemplateList;
1029245431Sdim
1030245431Sdim    makeTemplateList(FromTemplateList, FromTST);
1031245431Sdim    makeTemplateList(ToTemplateList, ToTST);
1032245431Sdim
1033263509Sdim    SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator
1034245431Sdim        FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),
1035245431Sdim        ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();
1036245431Sdim
1037245431Sdim    // Check if the lowest template types are the same.  If not, return.
1038245431Sdim    if (!hasSameBaseTemplate(*FromIter, *ToIter))
1039245431Sdim      return false;
1040245431Sdim
1041245431Sdim    // Begin searching up the template aliases.  The bottom most template
1042245431Sdim    // matches so move up until one pair does not match.  Use the template
1043245431Sdim    // right before that one.
1044245431Sdim    for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {
1045245431Sdim      if (!hasSameBaseTemplate(*FromIter, *ToIter))
1046245431Sdim        break;
1047245431Sdim    }
1048245431Sdim
1049245431Sdim    FromTST = FromIter[-1];
1050245431Sdim    ToTST = ToIter[-1];
1051245431Sdim
1052245431Sdim    return true;
1053245431Sdim  }
1054245431Sdim
1055245431Sdim  /// GetType - Retrieves the template type arguments, including default
1056245431Sdim  /// arguments.
1057252723Sdim  QualType GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD) {
1058245431Sdim    bool isVariadic = DefaultTTPD->isParameterPack();
1059245431Sdim
1060245431Sdim    if (!Iter.isEnd())
1061252723Sdim      return Iter->getAsType();
1062263509Sdim    if (isVariadic)
1063263509Sdim      return QualType();
1064252723Sdim
1065263509Sdim    QualType ArgType = DefaultTTPD->getDefaultArgument();
1066263509Sdim    if (ArgType->isDependentType())
1067263509Sdim      return Iter.getDesugar().getAsType();
1068263509Sdim
1069263509Sdim    return ArgType;
1070245431Sdim  }
1071245431Sdim
1072245431Sdim  /// GetExpr - Retrieves the template expression argument, including default
1073245431Sdim  /// arguments.
1074252723Sdim  Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) {
1075252723Sdim    Expr *ArgExpr = 0;
1076245431Sdim    bool isVariadic = DefaultNTTPD->isParameterPack();
1077245431Sdim
1078245431Sdim    if (!Iter.isEnd())
1079245431Sdim      ArgExpr = Iter->getAsExpr();
1080245431Sdim    else if (!isVariadic)
1081245431Sdim      ArgExpr = DefaultNTTPD->getDefaultArgument();
1082245431Sdim
1083245431Sdim    if (ArgExpr)
1084245431Sdim      while (SubstNonTypeTemplateParmExpr *SNTTPE =
1085245431Sdim                 dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr))
1086245431Sdim        ArgExpr = SNTTPE->getReplacement();
1087252723Sdim
1088252723Sdim    return ArgExpr;
1089245431Sdim  }
1090245431Sdim
1091252723Sdim  /// GetInt - Retrieves the template integer argument, including evaluating
1092252723Sdim  /// default arguments.
1093252723Sdim  llvm::APInt GetInt(const TSTiterator &Iter, Expr *ArgExpr) {
1094252723Sdim    // Default, value-depenedent expressions require fetching
1095252723Sdim    // from the desugared TemplateArgument
1096252723Sdim    if (Iter.isEnd() && ArgExpr->isValueDependent())
1097252723Sdim      switch (Iter.getDesugar().getKind()) {
1098252723Sdim        case TemplateArgument::Integral:
1099252723Sdim          return Iter.getDesugar().getAsIntegral();
1100252723Sdim        case TemplateArgument::Expression:
1101252723Sdim          ArgExpr = Iter.getDesugar().getAsExpr();
1102252723Sdim          return ArgExpr->EvaluateKnownConstInt(Context);
1103252723Sdim        default:
1104252723Sdim          assert(0 && "Unexpected template argument kind");
1105252723Sdim      }
1106252723Sdim    return ArgExpr->EvaluateKnownConstInt(Context);
1107252723Sdim  }
1108252723Sdim
1109263509Sdim  /// GetValueDecl - Retrieves the template Decl argument, including
1110252723Sdim  /// default expression argument.
1111252723Sdim  ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
1112252723Sdim    // Default, value-depenedent expressions require fetching
1113252723Sdim    // from the desugared TemplateArgument
1114252723Sdim    if (Iter.isEnd() && ArgExpr->isValueDependent())
1115252723Sdim      switch (Iter.getDesugar().getKind()) {
1116252723Sdim        case TemplateArgument::Declaration:
1117252723Sdim          return Iter.getDesugar().getAsDecl();
1118252723Sdim        case TemplateArgument::Expression:
1119252723Sdim          ArgExpr = Iter.getDesugar().getAsExpr();
1120252723Sdim          return cast<DeclRefExpr>(ArgExpr)->getDecl();
1121252723Sdim        default:
1122252723Sdim          assert(0 && "Unexpected template argument kind");
1123252723Sdim      }
1124263509Sdim    DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr);
1125263509Sdim    if (!DRE) {
1126263509Sdim      DRE = cast<DeclRefExpr>(cast<UnaryOperator>(ArgExpr)->getSubExpr());
1127263509Sdim    }
1128263509Sdim
1129263509Sdim    return DRE->getDecl();
1130252723Sdim  }
1131252723Sdim
1132245431Sdim  /// GetTemplateDecl - Retrieves the template template arguments, including
1133245431Sdim  /// default arguments.
1134252723Sdim  TemplateDecl *GetTemplateDecl(const TSTiterator &Iter,
1135252723Sdim                                TemplateTemplateParmDecl *DefaultTTPD) {
1136245431Sdim    bool isVariadic = DefaultTTPD->isParameterPack();
1137245431Sdim
1138245431Sdim    TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument();
1139245431Sdim    TemplateDecl *DefaultTD = 0;
1140245431Sdim    if (TA.getKind() != TemplateArgument::Null)
1141245431Sdim      DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
1142245431Sdim
1143245431Sdim    if (!Iter.isEnd())
1144252723Sdim      return Iter->getAsTemplate().getAsTemplateDecl();
1145252723Sdim    if (!isVariadic)
1146252723Sdim      return DefaultTD;
1147252723Sdim
1148252723Sdim    return 0;
1149245431Sdim  }
1150245431Sdim
1151252723Sdim  /// IsSameConvertedInt - Returns true if both integers are equal when
1152252723Sdim  /// converted to an integer type with the given width.
1153252723Sdim  static bool IsSameConvertedInt(unsigned Width, const llvm::APSInt &X,
1154252723Sdim                                 const llvm::APSInt &Y) {
1155252723Sdim    llvm::APInt ConvertedX = X.extOrTrunc(Width);
1156252723Sdim    llvm::APInt ConvertedY = Y.extOrTrunc(Width);
1157252723Sdim    return ConvertedX == ConvertedY;
1158252723Sdim  }
1159252723Sdim
1160245431Sdim  /// IsEqualExpr - Returns true if the expressions evaluate to the same value.
1161252723Sdim  static bool IsEqualExpr(ASTContext &Context, unsigned ParamWidth,
1162252723Sdim                          Expr *FromExpr, Expr *ToExpr) {
1163245431Sdim    if (FromExpr == ToExpr)
1164245431Sdim      return true;
1165245431Sdim
1166245431Sdim    if (!FromExpr || !ToExpr)
1167245431Sdim      return false;
1168245431Sdim
1169245431Sdim    FromExpr = FromExpr->IgnoreParens();
1170245431Sdim    ToExpr = ToExpr->IgnoreParens();
1171245431Sdim
1172245431Sdim    DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr),
1173245431Sdim                *ToDRE = dyn_cast<DeclRefExpr>(ToExpr);
1174245431Sdim
1175245431Sdim    if (FromDRE || ToDRE) {
1176245431Sdim      if (!FromDRE || !ToDRE)
1177245431Sdim        return false;
1178245431Sdim      return FromDRE->getDecl() == ToDRE->getDecl();
1179245431Sdim    }
1180245431Sdim
1181245431Sdim    Expr::EvalResult FromResult, ToResult;
1182245431Sdim    if (!FromExpr->EvaluateAsRValue(FromResult, Context) ||
1183245431Sdim        !ToExpr->EvaluateAsRValue(ToResult, Context))
1184252723Sdim      return false;
1185245431Sdim
1186245431Sdim    APValue &FromVal = FromResult.Val;
1187245431Sdim    APValue &ToVal = ToResult.Val;
1188245431Sdim
1189245431Sdim    if (FromVal.getKind() != ToVal.getKind()) return false;
1190245431Sdim
1191245431Sdim    switch (FromVal.getKind()) {
1192245431Sdim      case APValue::Int:
1193252723Sdim        return IsSameConvertedInt(ParamWidth, FromVal.getInt(), ToVal.getInt());
1194245431Sdim      case APValue::LValue: {
1195245431Sdim        APValue::LValueBase FromBase = FromVal.getLValueBase();
1196245431Sdim        APValue::LValueBase ToBase = ToVal.getLValueBase();
1197245431Sdim        if (FromBase.isNull() && ToBase.isNull())
1198245431Sdim          return true;
1199245431Sdim        if (FromBase.isNull() || ToBase.isNull())
1200245431Sdim          return false;
1201245431Sdim        return FromBase.get<const ValueDecl*>() ==
1202245431Sdim               ToBase.get<const ValueDecl*>();
1203245431Sdim      }
1204245431Sdim      case APValue::MemberPointer:
1205245431Sdim        return FromVal.getMemberPointerDecl() == ToVal.getMemberPointerDecl();
1206245431Sdim      default:
1207245431Sdim        llvm_unreachable("Unknown template argument expression.");
1208245431Sdim    }
1209245431Sdim  }
1210245431Sdim
1211245431Sdim  // These functions converts the tree representation of the template
1212245431Sdim  // differences into the internal character vector.
1213245431Sdim
1214245431Sdim  /// TreeToString - Converts the Tree object into a character stream which
1215245431Sdim  /// will later be turned into the output string.
1216245431Sdim  void TreeToString(int Indent = 1) {
1217245431Sdim    if (PrintTree) {
1218245431Sdim      OS << '\n';
1219252723Sdim      OS.indent(2 * Indent);
1220245431Sdim      ++Indent;
1221245431Sdim    }
1222245431Sdim
1223245431Sdim    // Handle cases where the difference is not templates with different
1224245431Sdim    // arguments.
1225252723Sdim    switch (Tree.GetKind()) {
1226252723Sdim      case DiffTree::Invalid:
1227252723Sdim        llvm_unreachable("Template diffing failed with bad DiffNode");
1228252723Sdim      case DiffTree::Type: {
1229245431Sdim        QualType FromType, ToType;
1230245431Sdim        Tree.GetNode(FromType, ToType);
1231245431Sdim        PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),
1232245431Sdim                       Tree.NodeIsSame());
1233245431Sdim        return;
1234245431Sdim      }
1235252723Sdim      case DiffTree::Expression: {
1236245431Sdim        Expr *FromExpr, *ToExpr;
1237245431Sdim        Tree.GetNode(FromExpr, ToExpr);
1238245431Sdim        PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
1239245431Sdim                  Tree.NodeIsSame());
1240245431Sdim        return;
1241245431Sdim      }
1242252723Sdim      case DiffTree::TemplateTemplate: {
1243245431Sdim        TemplateDecl *FromTD, *ToTD;
1244245431Sdim        Tree.GetNode(FromTD, ToTD);
1245245431Sdim        PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),
1246245431Sdim                              Tree.ToDefault(), Tree.NodeIsSame());
1247245431Sdim        return;
1248245431Sdim      }
1249252723Sdim      case DiffTree::Integer: {
1250245431Sdim        llvm::APSInt FromInt, ToInt;
1251252723Sdim        Expr *FromExpr, *ToExpr;
1252245431Sdim        bool IsValidFromInt, IsValidToInt;
1253252723Sdim        Tree.GetNode(FromExpr, ToExpr);
1254245431Sdim        Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt);
1255245431Sdim        PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt,
1256252723Sdim                    FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
1257252723Sdim                    Tree.NodeIsSame());
1258245431Sdim        return;
1259245431Sdim      }
1260252723Sdim      case DiffTree::Declaration: {
1261252723Sdim        ValueDecl *FromValueDecl, *ToValueDecl;
1262263509Sdim        bool FromAddressOf, ToAddressOf;
1263263509Sdim        Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
1264263509Sdim        PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
1265263509Sdim                       Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
1266252723Sdim        return;
1267252723Sdim      }
1268252723Sdim      case DiffTree::Template: {
1269252723Sdim        // Node is root of template.  Recurse on children.
1270252723Sdim        TemplateDecl *FromTD, *ToTD;
1271252723Sdim        Tree.GetNode(FromTD, ToTD);
1272245431Sdim
1273252723Sdim        if (!Tree.HasChildren()) {
1274252723Sdim          // If we're dealing with a template specialization with zero
1275252723Sdim          // arguments, there are no children; special-case this.
1276252723Sdim          OS << FromTD->getNameAsString() << "<>";
1277252723Sdim          return;
1278252723Sdim        }
1279245431Sdim
1280252723Sdim        Qualifiers FromQual, ToQual;
1281252723Sdim        Tree.GetNode(FromQual, ToQual);
1282252723Sdim        PrintQualifiers(FromQual, ToQual);
1283245431Sdim
1284252723Sdim        OS << FromTD->getNameAsString() << '<';
1285252723Sdim        Tree.MoveToChild();
1286252723Sdim        unsigned NumElideArgs = 0;
1287252723Sdim        do {
1288252723Sdim          if (ElideType) {
1289252723Sdim            if (Tree.NodeIsSame()) {
1290252723Sdim              ++NumElideArgs;
1291252723Sdim              continue;
1292252723Sdim            }
1293252723Sdim            if (NumElideArgs > 0) {
1294252723Sdim              PrintElideArgs(NumElideArgs, Indent);
1295252723Sdim              NumElideArgs = 0;
1296252723Sdim              OS << ", ";
1297252723Sdim            }
1298252723Sdim          }
1299252723Sdim          TreeToString(Indent);
1300252723Sdim          if (Tree.HasNextSibling())
1301252723Sdim            OS << ", ";
1302252723Sdim        } while (Tree.AdvanceSibling());
1303252723Sdim        if (NumElideArgs > 0)
1304252723Sdim          PrintElideArgs(NumElideArgs, Indent);
1305245431Sdim
1306252723Sdim        Tree.Parent();
1307252723Sdim        OS << ">";
1308252723Sdim        return;
1309245431Sdim      }
1310252723Sdim    }
1311245431Sdim  }
1312245431Sdim
1313245431Sdim  // To signal to the text printer that a certain text needs to be bolded,
1314245431Sdim  // a special character is injected into the character stream which the
1315245431Sdim  // text printer will later strip out.
1316245431Sdim
1317245431Sdim  /// Bold - Start bolding text.
1318245431Sdim  void Bold() {
1319245431Sdim    assert(!IsBold && "Attempting to bold text that is already bold.");
1320245431Sdim    IsBold = true;
1321245431Sdim    if (ShowColor)
1322245431Sdim      OS << ToggleHighlight;
1323245431Sdim  }
1324245431Sdim
1325245431Sdim  /// Unbold - Stop bolding text.
1326245431Sdim  void Unbold() {
1327245431Sdim    assert(IsBold && "Attempting to remove bold from unbold text.");
1328245431Sdim    IsBold = false;
1329245431Sdim    if (ShowColor)
1330245431Sdim      OS << ToggleHighlight;
1331245431Sdim  }
1332245431Sdim
1333245431Sdim  // Functions to print out the arguments and highlighting the difference.
1334245431Sdim
1335245431Sdim  /// PrintTypeNames - prints the typenames, bolding differences.  Will detect
1336245431Sdim  /// typenames that are the same and attempt to disambiguate them by using
1337245431Sdim  /// canonical typenames.
1338245431Sdim  void PrintTypeNames(QualType FromType, QualType ToType,
1339245431Sdim                      bool FromDefault, bool ToDefault, bool Same) {
1340245431Sdim    assert((!FromType.isNull() || !ToType.isNull()) &&
1341245431Sdim           "Only one template argument may be missing.");
1342245431Sdim
1343245431Sdim    if (Same) {
1344245431Sdim      OS << FromType.getAsString();
1345245431Sdim      return;
1346245431Sdim    }
1347245431Sdim
1348245431Sdim    if (!FromType.isNull() && !ToType.isNull() &&
1349245431Sdim        FromType.getLocalUnqualifiedType() ==
1350245431Sdim        ToType.getLocalUnqualifiedType()) {
1351245431Sdim      Qualifiers FromQual = FromType.getLocalQualifiers(),
1352245431Sdim                 ToQual = ToType.getLocalQualifiers(),
1353245431Sdim                 CommonQual;
1354245431Sdim      PrintQualifiers(FromQual, ToQual);
1355245431Sdim      FromType.getLocalUnqualifiedType().print(OS, Policy);
1356245431Sdim      return;
1357245431Sdim    }
1358245431Sdim
1359245431Sdim    std::string FromTypeStr = FromType.isNull() ? "(no argument)"
1360245431Sdim                                                : FromType.getAsString();
1361245431Sdim    std::string ToTypeStr = ToType.isNull() ? "(no argument)"
1362245431Sdim                                            : ToType.getAsString();
1363245431Sdim    // Switch to canonical typename if it is better.
1364245431Sdim    // TODO: merge this with other aka printing above.
1365245431Sdim    if (FromTypeStr == ToTypeStr) {
1366245431Sdim      std::string FromCanTypeStr = FromType.getCanonicalType().getAsString();
1367245431Sdim      std::string ToCanTypeStr = ToType.getCanonicalType().getAsString();
1368245431Sdim      if (FromCanTypeStr != ToCanTypeStr) {
1369245431Sdim        FromTypeStr = FromCanTypeStr;
1370245431Sdim        ToTypeStr = ToCanTypeStr;
1371245431Sdim      }
1372245431Sdim    }
1373245431Sdim
1374245431Sdim    if (PrintTree) OS << '[';
1375245431Sdim    OS << (FromDefault ? "(default) " : "");
1376245431Sdim    Bold();
1377245431Sdim    OS << FromTypeStr;
1378245431Sdim    Unbold();
1379245431Sdim    if (PrintTree) {
1380245431Sdim      OS << " != " << (ToDefault ? "(default) " : "");
1381245431Sdim      Bold();
1382245431Sdim      OS << ToTypeStr;
1383245431Sdim      Unbold();
1384245431Sdim      OS << "]";
1385245431Sdim    }
1386245431Sdim    return;
1387245431Sdim  }
1388245431Sdim
1389245431Sdim  /// PrintExpr - Prints out the expr template arguments, highlighting argument
1390245431Sdim  /// differences.
1391245431Sdim  void PrintExpr(const Expr *FromExpr, const Expr *ToExpr,
1392245431Sdim                 bool FromDefault, bool ToDefault, bool Same) {
1393245431Sdim    assert((FromExpr || ToExpr) &&
1394245431Sdim            "Only one template argument may be missing.");
1395245431Sdim    if (Same) {
1396245431Sdim      PrintExpr(FromExpr);
1397245431Sdim    } else if (!PrintTree) {
1398245431Sdim      OS << (FromDefault ? "(default) " : "");
1399245431Sdim      Bold();
1400245431Sdim      PrintExpr(FromExpr);
1401245431Sdim      Unbold();
1402245431Sdim    } else {
1403245431Sdim      OS << (FromDefault ? "[(default) " : "[");
1404245431Sdim      Bold();
1405245431Sdim      PrintExpr(FromExpr);
1406245431Sdim      Unbold();
1407245431Sdim      OS << " != " << (ToDefault ? "(default) " : "");
1408245431Sdim      Bold();
1409245431Sdim      PrintExpr(ToExpr);
1410245431Sdim      Unbold();
1411245431Sdim      OS << ']';
1412245431Sdim    }
1413245431Sdim  }
1414245431Sdim
1415245431Sdim  /// PrintExpr - Actual formatting and printing of expressions.
1416245431Sdim  void PrintExpr(const Expr *E) {
1417245431Sdim    if (!E)
1418245431Sdim      OS << "(no argument)";
1419245431Sdim    else
1420245431Sdim      E->printPretty(OS, 0, Policy); return;
1421245431Sdim  }
1422245431Sdim
1423245431Sdim  /// PrintTemplateTemplate - Handles printing of template template arguments,
1424245431Sdim  /// highlighting argument differences.
1425245431Sdim  void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,
1426245431Sdim                             bool FromDefault, bool ToDefault, bool Same) {
1427245431Sdim    assert((FromTD || ToTD) && "Only one template argument may be missing.");
1428252723Sdim
1429252723Sdim    std::string FromName = FromTD ? FromTD->getName() : "(no argument)";
1430252723Sdim    std::string ToName = ToTD ? ToTD->getName() : "(no argument)";
1431252723Sdim    if (FromTD && ToTD && FromName == ToName) {
1432252723Sdim      FromName = FromTD->getQualifiedNameAsString();
1433252723Sdim      ToName = ToTD->getQualifiedNameAsString();
1434252723Sdim    }
1435252723Sdim
1436245431Sdim    if (Same) {
1437245431Sdim      OS << "template " << FromTD->getNameAsString();
1438245431Sdim    } else if (!PrintTree) {
1439245431Sdim      OS << (FromDefault ? "(default) template " : "template ");
1440245431Sdim      Bold();
1441252723Sdim      OS << FromName;
1442245431Sdim      Unbold();
1443245431Sdim    } else {
1444245431Sdim      OS << (FromDefault ? "[(default) template " : "[template ");
1445245431Sdim      Bold();
1446252723Sdim      OS << FromName;
1447245431Sdim      Unbold();
1448245431Sdim      OS << " != " << (ToDefault ? "(default) template " : "template ");
1449245431Sdim      Bold();
1450252723Sdim      OS << ToName;
1451245431Sdim      Unbold();
1452245431Sdim      OS << ']';
1453245431Sdim    }
1454245431Sdim  }
1455245431Sdim
1456245431Sdim  /// PrintAPSInt - Handles printing of integral arguments, highlighting
1457245431Sdim  /// argument differences.
1458245431Sdim  void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt,
1459252723Sdim                   bool IsValidFromInt, bool IsValidToInt, Expr *FromExpr,
1460252723Sdim                   Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) {
1461245431Sdim    assert((IsValidFromInt || IsValidToInt) &&
1462245431Sdim           "Only one integral argument may be missing.");
1463245431Sdim
1464245431Sdim    if (Same) {
1465245431Sdim      OS << FromInt.toString(10);
1466245431Sdim    } else if (!PrintTree) {
1467245431Sdim      OS << (FromDefault ? "(default) " : "");
1468252723Sdim      PrintAPSInt(FromInt, FromExpr, IsValidFromInt);
1469252723Sdim    } else {
1470252723Sdim      OS << (FromDefault ? "[(default) " : "[");
1471252723Sdim      PrintAPSInt(FromInt, FromExpr, IsValidFromInt);
1472252723Sdim      OS << " != " << (ToDefault ? "(default) " : "");
1473252723Sdim      PrintAPSInt(ToInt, ToExpr, IsValidToInt);
1474252723Sdim      OS << ']';
1475252723Sdim    }
1476252723Sdim  }
1477252723Sdim
1478252723Sdim  /// PrintAPSInt - If valid, print the APSInt.  If the expression is
1479252723Sdim  /// gives more information, print it too.
1480252723Sdim  void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid) {
1481252723Sdim    Bold();
1482252723Sdim    if (Valid) {
1483252723Sdim      if (HasExtraInfo(E)) {
1484252723Sdim        PrintExpr(E);
1485252723Sdim        Unbold();
1486252723Sdim        OS << " aka ";
1487252723Sdim        Bold();
1488252723Sdim      }
1489252723Sdim      OS << Val.toString(10);
1490252723Sdim    } else {
1491252723Sdim      OS << "(no argument)";
1492252723Sdim    }
1493252723Sdim    Unbold();
1494252723Sdim  }
1495252723Sdim
1496252723Sdim  /// HasExtraInfo - Returns true if E is not an integer literal or the
1497252723Sdim  /// negation of an integer literal
1498252723Sdim  bool HasExtraInfo(Expr *E) {
1499252723Sdim    if (!E) return false;
1500252723Sdim    if (isa<IntegerLiteral>(E)) return false;
1501252723Sdim
1502252723Sdim    if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))
1503252723Sdim      if (UO->getOpcode() == UO_Minus)
1504252723Sdim        if (isa<IntegerLiteral>(UO->getSubExpr()))
1505252723Sdim          return false;
1506252723Sdim
1507252723Sdim    return true;
1508252723Sdim  }
1509252723Sdim
1510252723Sdim  /// PrintDecl - Handles printing of Decl arguments, highlighting
1511252723Sdim  /// argument differences.
1512252723Sdim  void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
1513263509Sdim                      bool FromAddressOf, bool ToAddressOf, bool FromDefault,
1514263509Sdim                      bool ToDefault, bool Same) {
1515252723Sdim    assert((FromValueDecl || ToValueDecl) &&
1516252723Sdim           "Only one Decl argument may be NULL");
1517252723Sdim
1518252723Sdim    if (Same) {
1519252723Sdim      OS << FromValueDecl->getName();
1520252723Sdim    } else if (!PrintTree) {
1521252723Sdim      OS << (FromDefault ? "(default) " : "");
1522245431Sdim      Bold();
1523263509Sdim      if (FromAddressOf)
1524263509Sdim        OS << "&";
1525252723Sdim      OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
1526245431Sdim      Unbold();
1527245431Sdim    } else {
1528245431Sdim      OS << (FromDefault ? "[(default) " : "[");
1529245431Sdim      Bold();
1530263509Sdim      if (FromAddressOf)
1531263509Sdim        OS << "&";
1532252723Sdim      OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
1533245431Sdim      Unbold();
1534245431Sdim      OS << " != " << (ToDefault ? "(default) " : "");
1535245431Sdim      Bold();
1536263509Sdim      if (ToAddressOf)
1537263509Sdim        OS << "&";
1538252723Sdim      OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)");
1539245431Sdim      Unbold();
1540245431Sdim      OS << ']';
1541245431Sdim    }
1542252723Sdim
1543245431Sdim  }
1544245431Sdim
1545245431Sdim  // Prints the appropriate placeholder for elided template arguments.
1546245431Sdim  void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
1547245431Sdim    if (PrintTree) {
1548245431Sdim      OS << '\n';
1549245431Sdim      for (unsigned i = 0; i < Indent; ++i)
1550245431Sdim        OS << "  ";
1551245431Sdim    }
1552245431Sdim    if (NumElideArgs == 0) return;
1553245431Sdim    if (NumElideArgs == 1)
1554245431Sdim      OS << "[...]";
1555245431Sdim    else
1556245431Sdim      OS << "[" << NumElideArgs << " * ...]";
1557245431Sdim  }
1558245431Sdim
1559245431Sdim  // Prints and highlights differences in Qualifiers.
1560245431Sdim  void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {
1561245431Sdim    // Both types have no qualifiers
1562245431Sdim    if (FromQual.empty() && ToQual.empty())
1563245431Sdim      return;
1564245431Sdim
1565245431Sdim    // Both types have same qualifiers
1566245431Sdim    if (FromQual == ToQual) {
1567245431Sdim      PrintQualifier(FromQual, /*ApplyBold*/false);
1568245431Sdim      return;
1569245431Sdim    }
1570245431Sdim
1571245431Sdim    // Find common qualifiers and strip them from FromQual and ToQual.
1572245431Sdim    Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual,
1573245431Sdim                                                               ToQual);
1574245431Sdim
1575245431Sdim    // The qualifiers are printed before the template name.
1576245431Sdim    // Inline printing:
1577245431Sdim    // The common qualifiers are printed.  Then, qualifiers only in this type
1578245431Sdim    // are printed and highlighted.  Finally, qualifiers only in the other
1579245431Sdim    // type are printed and highlighted inside parentheses after "missing".
1580245431Sdim    // Tree printing:
1581245431Sdim    // Qualifiers are printed next to each other, inside brackets, and
1582245431Sdim    // separated by "!=".  The printing order is:
1583245431Sdim    // common qualifiers, highlighted from qualifiers, "!=",
1584245431Sdim    // common qualifiers, highlighted to qualifiers
1585245431Sdim    if (PrintTree) {
1586245431Sdim      OS << "[";
1587245431Sdim      if (CommonQual.empty() && FromQual.empty()) {
1588245431Sdim        Bold();
1589245431Sdim        OS << "(no qualifiers) ";
1590245431Sdim        Unbold();
1591245431Sdim      } else {
1592245431Sdim        PrintQualifier(CommonQual, /*ApplyBold*/false);
1593245431Sdim        PrintQualifier(FromQual, /*ApplyBold*/true);
1594245431Sdim      }
1595245431Sdim      OS << "!= ";
1596245431Sdim      if (CommonQual.empty() && ToQual.empty()) {
1597245431Sdim        Bold();
1598245431Sdim        OS << "(no qualifiers)";
1599245431Sdim        Unbold();
1600245431Sdim      } else {
1601245431Sdim        PrintQualifier(CommonQual, /*ApplyBold*/false,
1602245431Sdim                       /*appendSpaceIfNonEmpty*/!ToQual.empty());
1603245431Sdim        PrintQualifier(ToQual, /*ApplyBold*/true,
1604245431Sdim                       /*appendSpaceIfNonEmpty*/false);
1605245431Sdim      }
1606245431Sdim      OS << "] ";
1607245431Sdim    } else {
1608245431Sdim      PrintQualifier(CommonQual, /*ApplyBold*/false);
1609245431Sdim      PrintQualifier(FromQual, /*ApplyBold*/true);
1610245431Sdim    }
1611245431Sdim  }
1612245431Sdim
1613245431Sdim  void PrintQualifier(Qualifiers Q, bool ApplyBold,
1614245431Sdim                      bool AppendSpaceIfNonEmpty = true) {
1615245431Sdim    if (Q.empty()) return;
1616245431Sdim    if (ApplyBold) Bold();
1617245431Sdim    Q.print(OS, Policy, AppendSpaceIfNonEmpty);
1618245431Sdim    if (ApplyBold) Unbold();
1619245431Sdim  }
1620245431Sdim
1621245431Sdimpublic:
1622245431Sdim
1623252723Sdim  TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType,
1624252723Sdim               QualType ToType, bool PrintTree, bool PrintFromType,
1625252723Sdim               bool ElideType, bool ShowColor)
1626245431Sdim    : Context(Context),
1627245431Sdim      Policy(Context.getLangOpts()),
1628245431Sdim      ElideType(ElideType),
1629245431Sdim      PrintTree(PrintTree),
1630245431Sdim      ShowColor(ShowColor),
1631245431Sdim      // When printing a single type, the FromType is the one printed.
1632245431Sdim      FromType(PrintFromType ? FromType : ToType),
1633245431Sdim      ToType(PrintFromType ? ToType : FromType),
1634252723Sdim      OS(OS),
1635245431Sdim      IsBold(false) {
1636245431Sdim  }
1637245431Sdim
1638245431Sdim  /// DiffTemplate - Start the template type diffing.
1639245431Sdim  void DiffTemplate() {
1640245431Sdim    Qualifiers FromQual = FromType.getQualifiers(),
1641245431Sdim               ToQual = ToType.getQualifiers();
1642245431Sdim
1643245431Sdim    const TemplateSpecializationType *FromOrigTST =
1644245431Sdim        GetTemplateSpecializationType(Context, FromType);
1645245431Sdim    const TemplateSpecializationType *ToOrigTST =
1646245431Sdim        GetTemplateSpecializationType(Context, ToType);
1647245431Sdim
1648245431Sdim    // Only checking templates.
1649245431Sdim    if (!FromOrigTST || !ToOrigTST)
1650245431Sdim      return;
1651245431Sdim
1652245431Sdim    // Different base templates.
1653245431Sdim    if (!hasSameTemplate(FromOrigTST, ToOrigTST)) {
1654245431Sdim      return;
1655245431Sdim    }
1656245431Sdim
1657245431Sdim    FromQual -= QualType(FromOrigTST, 0).getQualifiers();
1658245431Sdim    ToQual -= QualType(ToOrigTST, 0).getQualifiers();
1659245431Sdim    Tree.SetNode(FromType, ToType);
1660245431Sdim    Tree.SetNode(FromQual, ToQual);
1661252723Sdim    Tree.SetKind(DiffTree::Template);
1662245431Sdim
1663245431Sdim    // Same base template, but different arguments.
1664245431Sdim    Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(),
1665245431Sdim                 ToOrigTST->getTemplateName().getAsTemplateDecl());
1666245431Sdim
1667245431Sdim    DiffTemplate(FromOrigTST, ToOrigTST);
1668245431Sdim  }
1669245431Sdim
1670252723Sdim  /// Emit - When the two types given are templated types with the same
1671245431Sdim  /// base template, a string representation of the type difference will be
1672252723Sdim  /// emitted to the stream and return true.  Otherwise, return false.
1673252723Sdim  bool Emit() {
1674245431Sdim    Tree.StartTraverse();
1675245431Sdim    if (Tree.Empty())
1676245431Sdim      return false;
1677245431Sdim
1678245431Sdim    TreeToString();
1679245431Sdim    assert(!IsBold && "Bold is applied to end of string.");
1680245431Sdim    return true;
1681245431Sdim  }
1682245431Sdim}; // end class TemplateDiff
1683245431Sdim}  // end namespace
1684245431Sdim
1685245431Sdim/// FormatTemplateTypeDiff - A helper static function to start the template
1686245431Sdim/// diff and return the properly formatted string.  Returns true if the diff
1687245431Sdim/// is successful.
1688245431Sdimstatic bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
1689245431Sdim                                   QualType ToType, bool PrintTree,
1690245431Sdim                                   bool PrintFromType, bool ElideType,
1691252723Sdim                                   bool ShowColors, raw_ostream &OS) {
1692245431Sdim  if (PrintTree)
1693245431Sdim    PrintFromType = true;
1694252723Sdim  TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType,
1695245431Sdim                  ElideType, ShowColors);
1696245431Sdim  TD.DiffTemplate();
1697252723Sdim  return TD.Emit();
1698245431Sdim}
1699