<div style="font-family: arial, helvetica, sans-serif"><font size="2">I know we chatted about this already, but wanted to mention:<div><br></div><div>1) Release notes</div><div>2) Documentation updates</div><div><br></div>
<div><br></div><div>Thanks again, I'm really excited to have this. :: goes and builds a new Clang ::</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Jun 26, 2012 at 11:18 AM, Richard Trieu <span dir="ltr"><<a href="mailto:rtrieu@google.com" target="_blank">rtrieu@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rtrieu<br>
Date: Tue Jun 26 13:18:47 2012<br>
New Revision: 159216<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=159216&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=159216&view=rev</a><br>
Log:<br>
Add template type diffing to Clang.  This feature will provide a better<br>
comparison between two templated types when they both appear in a diagnostic.<br>
Type elision will remove indentical template arguments, which can be disabled<br>
with -fno-elide-type.  Cyan highlighting is applied to the differing types.<br>
<br>
For more formatting, -fdiagnostic-show-template-tree will output the template<br>
type as an indented text tree, with differences appearing inline. Template<br>
tree works with or without type elision.<br>
<br>
Added:<br>
    cfe/trunk/test/Misc/diag-template-diffing.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/Diagnostic.h<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/include/clang/Driver/Options.td<br>
    cfe/trunk/include/clang/Frontend/DiagnosticOptions.h<br>
    cfe/trunk/lib/AST/ASTDiagnostic.cpp<br>
    cfe/trunk/lib/Basic/Diagnostic.cpp<br>
    cfe/trunk/lib/Driver/Tools.cpp<br>
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp<br>
    cfe/trunk/lib/Frontend/TextDiagnostic.cpp<br>
    cfe/trunk/lib/Frontend/Warnings.cpp<br>
    cfe/trunk/test/Misc/diag-aka-types.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/Diagnostic.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)<br>
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Tue Jun 26 13:18:47 2012<br>
@@ -153,7 +153,8 @@<br>
     ak_declarationname, // DeclarationName<br>
     ak_nameddecl,       // NamedDecl *<br>
     ak_nestednamespec,  // NestedNameSpecifier *<br>
-    ak_declcontext      // DeclContext *<br>
+    ak_declcontext,     // DeclContext *<br>
+    ak_qualtype_pair    // pair<QualType, QualType><br>
   };<br>
<br>
   /// Specifies which overload candidates to display when overload resolution<br>
@@ -175,6 +176,9 @@<br>
   bool ErrorsAsFatal;            // Treat errors like fatal errors.<br>
   bool SuppressSystemWarnings;   // Suppress warnings in system headers.<br>
   bool SuppressAllDiagnostics;   // Suppress all diagnostics.<br>
+  bool ElideType;                // Elide common types of templates.<br>
+  bool PrintTemplateTree;        // Print a tree when comparing templates.<br>
+  bool ShowColors;               // Color printing is enabled.<br>
   OverloadsShown ShowOverloads;  // Which overload candidates to show.<br>
   unsigned ErrorLimit;           // Cap of # errors emitted, 0 -> no limit.<br>
   unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,<br>
@@ -438,7 +442,22 @@<br>
     SuppressAllDiagnostics = Val;<br>
   }<br>
   bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }<br>
-<br>
+<br>
+  /// \brief Set type eliding, to skip outputting same types occurring in<br>
+  /// template types.<br>
+  void setElideType(bool Val = true) { ElideType = Val; }<br>
+  bool getElideType() { return ElideType; }<br>
+<br>
+  /// \brief Set tree printing, to outputting the template difference in a<br>
+  /// tree format.<br>
+  void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }<br>
+  bool getPrintTemplateTree() { return PrintTemplateTree; }<br>
+<br>
+  /// \brief Set color printing, so the type diffing will inject color markers<br>
+  /// into the output.<br>
+  void setShowColors(bool Val = false) { ShowColors = Val; }<br>
+  bool getShowColors() { return ShowColors; }<br>
+<br>
   /// \brief Specify which overload candidates to show when overload resolution<br>
   /// fails.  By default, we show all candidates.<br>
   void setShowOverloads(OverloadsShown Val) {<br>
@@ -1058,7 +1077,6 @@<br>
     return DiagObj->DiagArgumentsVal[Idx];<br>
   }<br>
<br>
-<br>
   /// getNumRanges - Return the number of source ranges associated with this<br>
   /// diagnostic.<br>
   unsigned getNumRanges() const {<br>
@@ -1223,6 +1241,20 @@<br>
   }<br>
 };<br>
<br>
+// Struct used for sending info about how a type should be printed.<br>
+struct TemplateDiffTypes {<br>
+  intptr_t FromType;<br>
+  intptr_t ToType;<br>
+  unsigned PrintTree : 1;<br>
+  unsigned PrintFromType : 1;<br>
+  unsigned ElideType : 1;<br>
+  unsigned ShowColors : 1;<br>
+};<br>
+<br>
+/// Special character that the diagnostic printer will use to toggle the bold<br>
+/// attribute.  The character itself will be not be printed.<br>
+const char ToggleHighlight = 127;<br>
+<br>
 }  // end namespace clang<br>
<br>
 #endif<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Jun 26 13:18:47 2012<br>
@@ -2162,7 +2162,7 @@<br>
     "function (the implicit copy assignment operator)|"<br>
     "function (the implicit move assignment operator)|"<br>
     "constructor (inherited)}0%1"<br>
-    " not viable: no known conversion from %2 to %3 for "<br>
+    " not viable: no known conversion %diff{from | to | }2,3for "<br>
     "%select{%ordinal5 argument|object argument}4; "<br>
     "%select{|dereference the argument with *|"<br>
     "take the address of the argument with &|"<br>
<br>
Modified: cfe/trunk/include/clang/Driver/Options.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Driver/Options.td (original)<br>
+++ cfe/trunk/include/clang/Driver/Options.td Tue Jun 26 13:18:47 2012<br>
@@ -358,6 +358,9 @@<br>
     Group<f_Group>,  Flags<[CC1Option]>, HelpText<"Display include stacks for diagnostic notes">;<br>
 def fdiagnostics_format_EQ : Joined<"-fdiagnostics-format=">, Group<f_clang_Group>;<br>
 def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_clang_Group>;<br>
+def fdiagnostics_show_template_tree : Flag<"-fdiagnostics-show-template-tree">,<br>
+    Group<f_Group>, Flags<[CC1Option]>,<br>
+    HelpText<"Print a template comparison tree for differing templates">;<br>
 def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>,<br>
   HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>;<br>
 def fdwarf2_cfi_asm : Flag<"-fdwarf2-cfi-asm">, Group<f_Group>;<br>
@@ -365,6 +368,9 @@<br>
 def fdwarf_directory_asm : Flag<"-fdwarf-directory-asm">, Group<f_Group>;<br>
 def fno_dwarf_directory_asm : Flag<"-fno-dwarf-directory-asm">, Group<f_Group>, Flags<[CC1Option]>;<br>
 def felide_constructors : Flag<"-felide-constructors">, Group<f_Group>;<br>
+def fno_elide_type : Flag<"-fno-elide-type">, Group<f_Group>,<br>
+    Flags<[CC1Option]>,<br>
+    HelpText<"Do not elide types when printing diagnostics">;<br>
 def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>;<br>
 def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>, Flags<[CC1Option]>,<br>
   HelpText<"Emit all declarations, even if unused">;<br>
<br>
Modified: cfe/trunk/include/clang/Frontend/DiagnosticOptions.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DiagnosticOptions.h?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DiagnosticOptions.h?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Frontend/DiagnosticOptions.h (original)<br>
+++ cfe/trunk/include/clang/Frontend/DiagnosticOptions.h Tue Jun 26 13:18:47 2012<br>
@@ -47,6 +47,9 @@<br>
                                  /// diagnostics, indicated by markers in the<br>
                                  /// input source file.<br>
<br>
+  unsigned ElideType: 1;         /// Elide identical types in template diffing<br>
+  unsigned ShowTemplateTree: 1;  /// Print a template tree when diffing<br>
+<br>
   unsigned ErrorLimit;           /// Limit # errors emitted.<br>
   unsigned MacroBacktraceLimit;  /// Limit depth of macro expansion backtrace.<br>
   unsigned TemplateBacktraceLimit; /// Limit depth of instantiation backtrace.<br>
<br>
Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Tue Jun 26 13:18:47 2012<br>
@@ -14,7 +14,11 @@<br>
<br>
 #include "clang/AST/ASTContext.h"<br>
 #include "clang/AST/DeclObjC.h"<br>
+#include "clang/AST/TemplateBase.h"<br>
+#include "clang/AST/ExprCXX.h"<br>
+#include "clang/AST/DeclTemplate.h"<br>
 #include "clang/AST/Type.h"<br>
+#include "llvm/ADT/SmallString.h"<br>
 #include "llvm/Support/raw_ostream.h"<br>
<br>
 using namespace clang;<br>
@@ -225,6 +229,11 @@<br>
   return S;<br>
 }<br>
<br>
+static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,<br>
+                                   QualType ToType, bool PrintTree,<br>
+                                   bool PrintFromType, bool ElideType,<br>
+                                   bool ShowColors, std::string &S);<br>
+<br>
 void clang::FormatASTNodeDiagnosticArgument(<br>
     DiagnosticsEngine::ArgumentKind Kind,<br>
     intptr_t Val,<br>
@@ -244,6 +253,32 @@<br>
<br>
   switch (Kind) {<br>
     default: llvm_unreachable("unknown ArgumentKind");<br>
+    case DiagnosticsEngine::ak_qualtype_pair: {<br>
+      const TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val);<br>
+      QualType FromType =<br>
+          QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType));<br>
+      QualType ToType =<br>
+          QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType));<br>
+<br>
+      if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree,<br>
+                                 TDT.PrintFromType, TDT.ElideType,<br>
+                                 TDT.ShowColors, S)) {<br>
+        NeedQuotes = !TDT.PrintTree;<br>
+        break;<br>
+      }<br>
+<br>
+      // Don't fall-back during tree printing.  The caller will handle<br>
+      // this case.<br>
+      if (TDT.PrintTree)<br>
+        return;<br>
+<br>
+      // Attempting to do a templete diff on non-templates.  Set the variables<br>
+      // and continue with regular type printing of the appropriate type.<br>
+      Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType;<br>
+      ModLen = 0;<br>
+      ArgLen = 0;<br>
+      // Fall through<br>
+    }<br>
     case DiagnosticsEngine::ak_qualtype: {<br>
       assert(ModLen == 0 && ArgLen == 0 &&<br>
              "Invalid modifier for QualType argument");<br>
@@ -329,3 +364,901 @@<br>
   if (NeedQuotes)<br>
     Output.push_back('\'');<br>
 }<br>
+<br>
+/// TemplateDiff - A class that constructs a pretty string for a pair of<br>
+/// QualTypes.  For the pair of types, a diff tree will be created containing<br>
+/// all the information about the templates and template arguments.  Afterwards,<br>
+/// the tree is transformed to a string according to the options passed in.<br>
+namespace {<br>
+class TemplateDiff {<br>
+  /// Context - The ASTContext which is used for comparing template arguments.<br>
+  ASTContext &Context;<br>
+<br>
+  /// Policy - Used during expression printing.<br>
+  PrintingPolicy Policy;<br>
+<br>
+  /// ElideType - Option to elide identical types.<br>
+  bool ElideType;<br>
+<br>
+  /// PrintTree - Format output string as a tree.<br>
+  bool PrintTree;<br>
+<br>
+  /// ShowColor - Diagnostics support color, so bolding will be used.<br>
+  bool ShowColor;<br>
+<br>
+  /// FromType - When single type printing is selected, this is the type to be<br>
+  /// be printed.  When tree printing is selected, this type will show up first<br>
+  /// in the tree.<br>
+  QualType FromType;<br>
+<br>
+  /// ToType - The type that FromType is compared to.  Only in tree printing<br>
+  /// will this type be outputed.<br>
+  QualType ToType;<br>
+<br>
+  /// Str - Storage for the output stream.<br>
+  llvm::SmallString<128> Str;<br>
+<br>
+  /// OS - The stream used to construct the output strings.<br>
+  llvm::raw_svector_ostream OS;<br>
+<br>
+  /// IsBold - Keeps track of the bold formatting for the output string.<br>
+  bool IsBold;<br>
+<br>
+  /// DiffTree - A tree representation the differences between two types.<br>
+  class DiffTree {<br>
+    /// DiffNode - The root node stores the original type.  Each child node<br>
+    /// stores template arguments of their parents.  For templated types, the<br>
+    /// template decl is also stored.<br>
+    struct DiffNode {<br>
+      /// NextNode - The index of the next sibling node or 0.<br>
+      unsigned NextNode;<br>
+<br>
+      /// ChildNode - The index of the first child node or 0.<br>
+      unsigned ChildNode;<br>
+<br>
+      /// ParentNode - The index of the parent node.<br>
+      unsigned ParentNode;<br>
+<br>
+      /// FromType, ToType - The type arguments.<br>
+      QualType FromType, ToType;<br>
+<br>
+      /// FromExpr, ToExpr - The expression arguments.<br>
+      Expr *FromExpr, *ToExpr;<br>
+<br>
+      /// FromTD, ToTD - The template decl for template template<br>
+      /// arguments or the type arguments that are templates.<br>
+      TemplateDecl *FromTD, *ToTD;<br>
+<br>
+      /// FromDefault, ToDefault - Whether the argument is a default argument.<br>
+      bool FromDefault, ToDefault;<br>
+<br>
+      /// Same - Whether the two arguments evaluate to the same value.<br>
+      bool Same;<br>
+<br>
+      DiffNode(unsigned ParentNode = 0)<br>
+        : NextNode(0), ChildNode(0), ParentNode(ParentNode),<br>
+          FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0),<br>
+          FromDefault(false), ToDefault(false), Same(false) { }<br>
+    };<br>
+<br>
+    /// FlatTree - A flattened tree used to store the DiffNodes.<br>
+    llvm::SmallVector<DiffNode, 16> FlatTree;<br>
+<br>
+    /// CurrentNode - The index of the current node being used.<br>
+    unsigned CurrentNode;<br>
+<br>
+    /// NextFreeNode - The index of the next unused node.  Used when creating<br>
+    /// child nodes.<br>
+    unsigned NextFreeNode;<br>
+<br>
+    /// ReadNode - The index of the current node being read.<br>
+    unsigned ReadNode;<br>
+<br>
+  public:<br>
+    DiffTree() :<br>
+        CurrentNode(0), NextFreeNode(1) {<br>
+      FlatTree.push_back(DiffNode());<br>
+    }<br>
+<br>
+    // Node writing functions.<br>
+    /// SetNode - Sets FromTD and ToTD of the current node.<br>
+    void SetNode(TemplateDecl *FromTD, TemplateDecl *ToTD) {<br>
+      FlatTree[CurrentNode].FromTD = FromTD;<br>
+      FlatTree[CurrentNode].ToTD = ToTD;<br>
+    }<br>
+<br>
+    /// SetNode - Sets FromType and ToType of the current node.<br>
+    void SetNode(QualType FromType, QualType ToType) {<br>
+      FlatTree[CurrentNode].FromType = FromType;<br>
+      FlatTree[CurrentNode].ToType = ToType;<br>
+    }<br>
+<br>
+    /// SetNode - Set FromExpr and ToExpr of the current node.<br>
+    void SetNode(Expr *FromExpr, Expr *ToExpr) {<br>
+      FlatTree[CurrentNode].FromExpr = FromExpr;<br>
+      FlatTree[CurrentNode].ToExpr = ToExpr;<br>
+    }<br>
+<br>
+    /// SetSame - Sets the same flag of the current node.<br>
+    void SetSame(bool Same) {<br>
+      FlatTree[CurrentNode].Same = Same;<br>
+    }<br>
+<br>
+    /// SetDefault - Sets FromDefault and ToDefault flags of the current node.<br>
+    void SetDefault(bool FromDefault, bool ToDefault) {<br>
+      FlatTree[CurrentNode].FromDefault = FromDefault;<br>
+      FlatTree[CurrentNode].ToDefault = ToDefault;<br>
+    }<br>
+<br>
+    /// Up - Changes the node to the parent of the current node.<br>
+    void Up() {<br>
+      CurrentNode = FlatTree[CurrentNode].ParentNode;<br>
+    }<br>
+<br>
+    /// AddNode - Adds a child node to the current node, then sets that node<br>
+    /// node as the current node.<br>
+    void AddNode() {<br>
+      FlatTree.push_back(DiffNode(CurrentNode));<br>
+      DiffNode &Node = FlatTree[CurrentNode];<br>
+      if (Node.ChildNode == 0) {<br>
+        // If a child node doesn't exist, add one.<br>
+        Node.ChildNode = NextFreeNode;<br>
+      } else {<br>
+        // If a child node exists, find the last child node and add a<br>
+        // next node to it.<br>
+        unsigned i;<br>
+        for (i = Node.ChildNode; FlatTree[i].NextNode != 0;<br>
+             i = FlatTree[i].NextNode) {<br>
+        }<br>
+        FlatTree[i].NextNode = NextFreeNode;<br>
+      }<br>
+      CurrentNode = NextFreeNode;<br>
+      ++NextFreeNode;<br>
+    }<br>
+<br>
+    // Node reading functions.<br>
+    /// StartTraverse - Prepares the tree for recursive traversal.<br>
+    void StartTraverse() {<br>
+      ReadNode = 0;<br>
+      CurrentNode = NextFreeNode;<br>
+      NextFreeNode = 0;<br>
+    }<br>
+<br>
+    /// Parent - Move the current read node to its parent.<br>
+    void Parent() {<br>
+      ReadNode = FlatTree[ReadNode].ParentNode;<br>
+    }<br>
+<br>
+    /// NodeIsTemplate - Returns true if a template decl is set, and types are<br>
+    /// set.<br>
+    bool NodeIsTemplate() {<br>
+      return (FlatTree[ReadNode].FromTD &&<br>
+              !FlatTree[ReadNode].ToType.isNull()) ||<br>
+             (FlatTree[ReadNode].ToTD && !FlatTree[ReadNode].ToType.isNull());<br>
+    }<br>
+<br>
+    /// NodeIsQualType - Returns true if a Qualtype is set.<br>
+    bool NodeIsQualType() {<br>
+      return !FlatTree[ReadNode].FromType.isNull() ||<br>
+             !FlatTree[ReadNode].ToType.isNull();<br>
+    }<br>
+<br>
+    /// NodeIsExpr - Returns true if an expr is set.<br>
+    bool NodeIsExpr() {<br>
+      return FlatTree[ReadNode].FromExpr || FlatTree[ReadNode].ToExpr;<br>
+    }<br>
+<br>
+    /// NodeIsTemplateTemplate - Returns true if the argument is a template<br>
+    /// template type.<br>
+    bool NodeIsTemplateTemplate() {<br>
+      return FlatTree[ReadNode].FromType.isNull() &&<br>
+             FlatTree[ReadNode].ToType.isNull() &&<br>
+             (FlatTree[ReadNode].FromTD || FlatTree[ReadNode].ToTD);<br>
+    }<br>
+<br>
+    /// GetNode - Gets the FromType and ToType.<br>
+    void GetNode(QualType &FromType, QualType &ToType) {<br>
+      FromType = FlatTree[ReadNode].FromType;<br>
+      ToType = FlatTree[ReadNode].ToType;<br>
+    }<br>
+<br>
+    /// GetNode - Gets the FromExpr and ToExpr.<br>
+    void GetNode(Expr *&FromExpr, Expr *&ToExpr) {<br>
+      FromExpr = FlatTree[ReadNode].FromExpr;<br>
+      ToExpr = FlatTree[ReadNode].ToExpr;<br>
+    }<br>
+<br>
+    /// GetNode - Gets the FromTD and ToTD.<br>
+    void GetNode(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {<br>
+      FromTD = FlatTree[ReadNode].FromTD;<br>
+      ToTD = FlatTree[ReadNode].ToTD;<br>
+    }<br>
+<br>
+    /// NodeIsSame - Returns true the arguments are the same.<br>
+    bool NodeIsSame() {<br>
+      return FlatTree[ReadNode].Same;<br>
+    }<br>
+<br>
+    /// HasChildrend - Returns true if the node has children.<br>
+    bool HasChildren() {<br>
+      return FlatTree[ReadNode].ChildNode != 0;<br>
+    }<br>
+<br>
+    /// MoveToChild - Moves from the current node to its child.<br>
+    void MoveToChild() {<br>
+      ReadNode = FlatTree[ReadNode].ChildNode;<br>
+    }<br>
+<br>
+    /// AdvanceSibling - If there is a next sibling, advance to it and return<br>
+    /// true.  Otherwise, return false.<br>
+    bool AdvanceSibling() {<br>
+      if (FlatTree[ReadNode].NextNode == 0)<br>
+        return false;<br>
+<br>
+      ReadNode = FlatTree[ReadNode].NextNode;<br>
+      return true;<br>
+    }<br>
+<br>
+    /// HasNextSibling - Return true if the node has a next sibling.<br>
+    bool HasNextSibling() {<br>
+      return FlatTree[ReadNode].NextNode != 0;<br>
+    }<br>
+<br>
+    /// FromDefault - Return true if the from argument is the default.<br>
+    bool FromDefault() {<br>
+      return FlatTree[ReadNode].FromDefault;<br>
+    }<br>
+<br>
+    /// ToDefault - Return true if the to argument is the default.<br>
+    bool ToDefault() {<br>
+      return FlatTree[ReadNode].ToDefault;<br>
+    }<br>
+<br>
+    /// Empty - Returns true if the tree has no information.<br>
+    bool Empty() {<br>
+      return !FlatTree[0].FromTD && !FlatTree[0].ToTD &&<br>
+             !FlatTree[0].FromExpr && !FlatTree[0].ToExpr &&<br>
+             FlatTree[0].FromType.isNull() && FlatTree[0].ToType.isNull();<br>
+    }<br>
+  };<br>
+<br>
+  DiffTree Tree;<br>
+<br>
+  /// TSTiterator - an iterator that is used to enter a<br>
+  /// TemplateSpecializationType and read TemplateArguments inside template<br>
+  /// parameter packs in order with the rest of the TemplateArguments.<br>
+  struct TSTiterator {<br>
+    typedef const TemplateArgument& reference;<br>
+    typedef const TemplateArgument* pointer;<br>
+<br>
+    /// TST - the template specialization whose arguments this iterator<br>
+    /// traverse over.<br>
+    const TemplateSpecializationType *TST;<br>
+<br>
+    /// Index - the index of the template argument in TST.<br>
+    unsigned Index;<br>
+<br>
+    /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA<br>
+    /// points to a TemplateArgument within a parameter pack.<br>
+    TemplateArgument::pack_iterator CurrentTA;<br>
+<br>
+    /// EndTA - the end iterator of a parameter pack<br>
+    TemplateArgument::pack_iterator EndTA;<br>
+<br>
+    /// TSTiterator - Constructs an iterator and sets it to the first template<br>
+    /// argument.<br>
+    TSTiterator(const TemplateSpecializationType *TST)<br>
+        : TST(TST), Index(0), CurrentTA(0), EndTA(0) {<br>
+      if (isEnd()) return;<br>
+<br>
+      // Set to first template argument.  If not a parameter pack, done.<br>
+      TemplateArgument TA = TST->getArg(0);<br>
+      if (TA.getKind() != TemplateArgument::Pack) return;<br>
+<br>
+      // Start looking into the parameter pack.<br>
+      CurrentTA = TA.pack_begin();<br>
+      EndTA = TA.pack_end();<br>
+<br>
+      // Found a valid template argument.<br>
+      if (CurrentTA != EndTA) return;<br>
+<br>
+      // Parameter pack is empty, use the increment to get to a valid<br>
+      // template argument.<br>
+      ++(*this);<br>
+    }<br>
+<br>
+    /// isEnd - Returns true if the iterator is one past the end.<br>
+    bool isEnd() const {<br>
+      return Index == TST->getNumArgs();<br>
+    }<br>
+<br>
+    /// &operator++ - Increment the iterator to the next template argument.<br>
+    TSTiterator &operator++() {<br>
+      assert(!isEnd() && "Iterator incremented past end of arguments.");<br>
+<br>
+      // If in a parameter pack, advance in the parameter pack.<br>
+      if (CurrentTA != EndTA) {<br>
+        ++CurrentTA;<br>
+        if (CurrentTA != EndTA)<br>
+          return *this;<br>
+      }<br>
+<br>
+      // Loop until a template argument is found, or the end is reached.<br>
+      while (true) {<br>
+        // Advance to the next template argument.  Break if reached the end.<br>
+        if (++Index == TST->getNumArgs()) break;<br>
+<br>
+        // If the TemplateArgument is not a parameter pack, done.<br>
+        TemplateArgument TA = TST->getArg(Index);<br>
+        if (TA.getKind() != TemplateArgument::Pack) break;<br>
+<br>
+        // Handle parameter packs.<br>
+        CurrentTA = TA.pack_begin();<br>
+        EndTA = TA.pack_end();<br>
+<br>
+        // If the parameter pack is empty, try to advance again.<br>
+        if (CurrentTA != EndTA) break;<br>
+      }<br>
+      return *this;<br>
+    }<br>
+<br>
+    /// operator* - Returns the appropriate TemplateArgument.<br>
+    reference operator*() const {<br>
+      assert(!isEnd() && "Index exceeds number of arguments.");<br>
+      if (CurrentTA == EndTA)<br>
+        return TST->getArg(Index);<br>
+      else<br>
+        return *CurrentTA;<br>
+    }<br>
+<br>
+    /// operator-> - Allow access to the underlying TemplateArgument.<br>
+    pointer operator->() const {<br>
+      return &operator*();<br>
+    }<br>
+  };<br>
+<br>
+  // These functions build up the template diff tree, including functions to<br>
+  // retrieve and compare template arguments.<br>
+<br>
+  static const TemplateSpecializationType * GetTemplateSpecializationType(<br>
+      ASTContext &Context, QualType Ty) {<br>
+    if (const TemplateSpecializationType *TST =<br>
+            Ty->getAs<TemplateSpecializationType>())<br>
+      return TST;<br>
+<br>
+    const RecordType *RT = Ty->getAs<RecordType>();<br>
+<br>
+    if (!RT)<br>
+      return 0;<br>
+<br>
+    const ClassTemplateSpecializationDecl *CTSD =<br>
+        dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());<br>
+<br>
+    if (!CTSD)<br>
+      return 0;<br>
+<br>
+    Ty = Context.getTemplateSpecializationType(<br>
+             TemplateName(CTSD->getSpecializedTemplate()),<br>
+             CTSD->getTemplateArgs().data(),<br>
+             CTSD->getTemplateArgs().size(),<br>
+             Ty.getCanonicalType());<br>
+<br>
+    return Ty->getAs<TemplateSpecializationType>();<br>
+  }<br>
+<br>
+  /// DiffTemplate - recursively visits template arguments and stores the<br>
+  /// argument info into a tree.<br>
+  void DiffTemplate(const TemplateSpecializationType *FromTST,<br>
+                    const TemplateSpecializationType *ToTST) {<br>
+    // Begin descent into diffing template tree.<br>
+    TemplateParameterList *Params =<br>
+        FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();<br>
+    unsigned TotalArgs = 0;<br>
+    for (TSTiterator FromIter(FromTST), ToIter(ToTST);<br>
+         !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {<br>
+      Tree.AddNode();<br>
+<br>
+      // Get the parameter at index TotalArgs.  If index is larger<br>
+      // than the total number of parameters, then there is an<br>
+      // argument pack, so re-use the last parameter.<br>
+      NamedDecl *ParamND = Params->getParam(<br>
+          (TotalArgs < Params->size()) ? TotalArgs<br>
+                                       : Params->size() - 1);<br>
+      // Handle Types<br>
+      if (TemplateTypeParmDecl *DefaultTTPD =<br>
+              dyn_cast<TemplateTypeParmDecl>(ParamND)) {<br>
+        QualType FromType, ToType;<br>
+        GetType(FromIter, DefaultTTPD, FromType);<br>
+        GetType(ToIter, DefaultTTPD, ToType);<br>
+        Tree.SetNode(FromType, ToType);<br>
+        Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(),<br>
+                        ToIter.isEnd() && !ToType.isNull());<br>
+        if (!FromType.isNull() && !ToType.isNull()) {<br>
+          if (Context.hasSameType(FromType, ToType)) {<br>
+            Tree.SetSame(true);<br>
+          } else {<br>
+            const TemplateSpecializationType *FromArgTST =<br>
+                GetTemplateSpecializationType(Context, FromType);<br>
+            const TemplateSpecializationType *ToArgTST =<br>
+                GetTemplateSpecializationType(Context, ToType);<br>
+<br>
+            if (FromArgTST && ToArgTST) {<br>
+              bool SameTemplate = hasSameTemplate(FromArgTST, ToArgTST);<br>
+              if (SameTemplate) {<br>
+                Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),<br>
+                             ToArgTST->getTemplateName().getAsTemplateDecl());<br>
+                DiffTemplate(FromArgTST, ToArgTST);<br>
+              }<br>
+            }<br>
+          }<br>
+        }<br>
+      }<br>
+<br>
+      // Handle Expressions<br>
+      if (NonTypeTemplateParmDecl *DefaultNTTPD =<br>
+              dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {<br>
+        Expr *FromExpr, *ToExpr;<br>
+        GetExpr(FromIter, DefaultNTTPD, FromExpr);<br>
+        GetExpr(ToIter, DefaultNTTPD, ToExpr);<br>
+        Tree.SetNode(FromExpr, ToExpr);<br>
+        Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));<br>
+        Tree.SetDefault(FromIter.isEnd() && FromExpr,<br>
+                        ToIter.isEnd() && ToExpr);<br>
+      }<br>
+<br>
+      // Handle Templates<br>
+      if (TemplateTemplateParmDecl *DefaultTTPD =<br>
+              dyn_cast<TemplateTemplateParmDecl>(ParamND)) {<br>
+        TemplateDecl *FromDecl, *ToDecl;<br>
+        GetTemplateDecl(FromIter, DefaultTTPD, FromDecl);<br>
+        GetTemplateDecl(ToIter, DefaultTTPD, ToDecl);<br>
+        Tree.SetNode(FromDecl, ToDecl);<br>
+        Tree.SetSame(FromDecl && ToDecl &&<br>
+                     FromDecl->getIdentifier() == ToDecl->getIdentifier());<br>
+      }<br>
+<br>
+      if (!FromIter.isEnd()) ++FromIter;<br>
+      if (!ToIter.isEnd()) ++ToIter;<br>
+      Tree.Up();<br>
+    }<br>
+  }<br>
+<br>
+  /// hasSameTemplate - Returns true if both types are specialized from the<br>
+  /// same template declaration.  If they come from different template aliases,<br>
+  /// do a parallel ascension search to determine the highest template alias in<br>
+  /// common and set the arguments to them.<br>
+  static bool hasSameTemplate(const TemplateSpecializationType *&FromTST,<br>
+                              const TemplateSpecializationType *&ToTST) {<br>
+    // Check the top templates if they are the same.<br>
+    if (FromTST->getTemplateName().getAsTemplateDecl()->getIdentifier() ==<br>
+        ToTST->getTemplateName().getAsTemplateDecl()->getIdentifier())<br>
+      return true;<br>
+<br>
+    // Create vectors of template aliases.<br>
+    SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,<br>
+                                                      ToTemplateList;<br>
+<br>
+    const TemplateSpecializationType *TempToTST = ToTST, *TempFromTST = FromTST;<br>
+    FromTemplateList.push_back(FromTST);<br>
+    ToTemplateList.push_back(ToTST);<br>
+<br>
+    // Dump every template alias into the vectors.<br>
+    while (TempFromTST->isTypeAlias()) {<br>
+      TempFromTST =<br>
+          TempFromTST->getAliasedType()->getAs<TemplateSpecializationType>();<br>
+      if (!TempFromTST)<br>
+        break;<br>
+      FromTemplateList.push_back(TempFromTST);<br>
+    }<br>
+    while (TempToTST->isTypeAlias()) {<br>
+      TempToTST =<br>
+          TempToTST->getAliasedType()->getAs<TemplateSpecializationType>();<br>
+      if (!TempToTST)<br>
+        break;<br>
+      ToTemplateList.push_back(TempToTST);<br>
+    }<br>
+<br>
+    SmallVector<const TemplateSpecializationType*, 1>::reverse_iterator<br>
+        FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),<br>
+        ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();<br>
+<br>
+    // Check if the lowest template types are the same.  If not, return.<br>
+    if ((*FromIter)->getTemplateName().getAsTemplateDecl()->getIdentifier() !=<br>
+        (*ToIter)->getTemplateName().getAsTemplateDecl()->getIdentifier())<br>
+      return false;<br>
+<br>
+    // Begin searching up the template aliases.  The bottom most template<br>
+    // matches so move up until one pair does not match.  Use the template<br>
+    // right before that one.<br>
+    for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {<br>
+      if ((*FromIter)->getTemplateName().getAsTemplateDecl()->getIdentifier() !=<br>
+          (*ToIter)->getTemplateName().getAsTemplateDecl()->getIdentifier())<br>
+        break;<br>
+    }<br>
+<br>
+    FromTST = FromIter[-1];<br>
+    ToTST = ToIter[-1];<br>
+<br>
+    return true;<br>
+  }<br>
+<br>
+  /// GetType - Retrieves the template type arguments, including default<br>
+  /// arguments.<br>
+  void GetType(const TSTiterator &Iter, TemplateTypeParmDecl *DefaultTTPD,<br>
+               QualType &ArgType) {<br>
+    ArgType = QualType();<br>
+    bool isVariadic = DefaultTTPD->isParameterPack();<br>
+<br>
+    if (!Iter.isEnd())<br>
+      ArgType = Iter->getAsType();<br>
+    else if (!isVariadic)<br>
+      ArgType = DefaultTTPD->getDefaultArgument();<br>
+  };<br>
+<br>
+  /// GetExpr - Retrieves the template expression argument, including default<br>
+  /// arguments.<br>
+  void GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD,<br>
+               Expr *&ArgExpr) {<br>
+    ArgExpr = 0;<br>
+    bool isVariadic = DefaultNTTPD->isParameterPack();<br>
+<br>
+    if (!Iter.isEnd())<br>
+      ArgExpr = Iter->getAsExpr();<br>
+    else if (!isVariadic)<br>
+      ArgExpr = DefaultNTTPD->getDefaultArgument();<br>
+<br>
+    if (ArgExpr)<br>
+      while (SubstNonTypeTemplateParmExpr *SNTTPE =<br>
+                 dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr))<br>
+        ArgExpr = SNTTPE->getReplacement();<br>
+  }<br>
+<br>
+  /// GetTemplateDecl - Retrieves the template template arguments, including<br>
+  /// default arguments.<br>
+  void GetTemplateDecl(const TSTiterator &Iter,<br>
+                       TemplateTemplateParmDecl *DefaultTTPD,<br>
+                       TemplateDecl *&ArgDecl) {<br>
+    ArgDecl = 0;<br>
+    bool isVariadic = DefaultTTPD->isParameterPack();<br>
+<br>
+    TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument();<br>
+    TemplateDecl *DefaultTD = TA.getAsTemplate().getAsTemplateDecl();<br>
+<br>
+    if (!Iter.isEnd())<br>
+      ArgDecl = Iter->getAsTemplate().getAsTemplateDecl();<br>
+    else if (!isVariadic)<br>
+      ArgDecl = DefaultTD;<br>
+  }<br>
+<br>
+  /// IsEqualExpr - Returns true if the expressions evaluate to the same value.<br>
+  static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {<br>
+    if (FromExpr == ToExpr)<br>
+      return true;<br>
+<br>
+    if (!FromExpr || !ToExpr)<br>
+      return false;<br>
+<br>
+    FromExpr = FromExpr->IgnoreParens();<br>
+    ToExpr = ToExpr->IgnoreParens();<br>
+<br>
+    DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr),<br>
+                *ToDRE = dyn_cast<DeclRefExpr>(ToExpr);<br>
+<br>
+    if (FromDRE || ToDRE) {<br>
+      if (!FromDRE || !ToDRE)<br>
+        return false;<br>
+      return FromDRE->getDecl() == ToDRE->getDecl();<br>
+    }<br>
+<br>
+    Expr::EvalResult FromResult, ToResult;<br>
+    if (!FromExpr->EvaluateAsRValue(FromResult, Context) ||<br>
+        !ToExpr->EvaluateAsRValue(ToResult, Context))<br>
+      assert(0 && "Template arguments must be known at compile time.");<br>
+<br>
+    APValue &FromVal = FromResult.Val;<br>
+    APValue &ToVal = ToResult.Val;<br>
+<br>
+    if (FromVal.getKind() != ToVal.getKind()) return false;<br>
+<br>
+    switch (FromVal.getKind()) {<br>
+      case APValue::Int:<br>
+        return FromVal.getInt() == ToVal.getInt();<br>
+      case APValue::LValue: {<br>
+        APValue::LValueBase FromBase = FromVal.getLValueBase();<br>
+        APValue::LValueBase ToBase = ToVal.getLValueBase();<br>
+        if (FromBase.isNull() && ToBase.isNull())<br>
+          return true;<br>
+        if (FromBase.isNull() || ToBase.isNull())<br>
+          return false;<br>
+        return FromBase.get<const ValueDecl*>() ==<br>
+               ToBase.get<const ValueDecl*>();<br>
+      }<br>
+      case APValue::MemberPointer:<br>
+        return FromVal.getMemberPointerDecl() == ToVal.getMemberPointerDecl();<br>
+      default:<br>
+        llvm_unreachable("Unknown template argument expression.");<br>
+    }<br>
+  }<br>
+<br>
+  // These functions converts the tree representation of the template<br>
+  // differences into the internal character vector.<br>
+<br>
+  /// TreeToString - Converts the Tree object into a character stream which<br>
+  /// will later be turned into the output string.<br>
+  void TreeToString(int Indent = 1) {<br>
+    if (PrintTree) {<br>
+      OS << '\n';<br>
+      for (int i = 0; i < Indent; ++i)<br>
+        OS << "  ";<br>
+      ++Indent;<br>
+    }<br>
+<br>
+    // Handle cases where the difference is not templates with different<br>
+    // arguments.<br>
+    if (!Tree.NodeIsTemplate()) {<br>
+      if (Tree.NodeIsQualType()) {<br>
+        QualType FromType, ToType;<br>
+        Tree.GetNode(FromType, ToType);<br>
+        PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),<br>
+                       Tree.NodeIsSame());<br>
+        return;<br>
+      }<br>
+      if (Tree.NodeIsExpr()) {<br>
+        Expr *FromExpr, *ToExpr;<br>
+        Tree.GetNode(FromExpr, ToExpr);<br>
+        PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),<br>
+                  Tree.NodeIsSame());<br>
+        return;<br>
+      }<br>
+      if (Tree.NodeIsTemplateTemplate()) {<br>
+        TemplateDecl *FromTD, *ToTD;<br>
+        Tree.GetNode(FromTD, ToTD);<br>
+        PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),<br>
+                              Tree.ToDefault(), Tree.NodeIsSame());<br>
+        return;<br>
+      }<br>
+      llvm_unreachable("Unable to deduce template difference.");<br>
+    }<br>
+<br>
+    // Node is root of template.  Recurse on children.<br>
+    TemplateDecl *FromTD, *ToTD;<br>
+    Tree.GetNode(FromTD, ToTD);<br>
+<br>
+    assert(Tree.HasChildren() && "Template difference not found in diff tree.");<br>
+<br>
+    OS << FromTD->getNameAsString() << '<';<br>
+    Tree.MoveToChild();<br>
+    unsigned NumElideArgs = 0;<br>
+    do {<br>
+      if (ElideType) {<br>
+        if (Tree.NodeIsSame()) {<br>
+          ++NumElideArgs;<br>
+          continue;<br>
+        }<br>
+        if (NumElideArgs > 0) {<br>
+          PrintElideArgs(NumElideArgs, Indent);<br>
+          NumElideArgs = 0;<br>
+          OS << ", ";<br>
+        }<br>
+      }<br>
+      TreeToString(Indent);<br>
+      if (Tree.HasNextSibling())<br>
+        OS << ", ";<br>
+    } while (Tree.AdvanceSibling());<br>
+    if (NumElideArgs > 0)<br>
+      PrintElideArgs(NumElideArgs, Indent);<br>
+<br>
+    Tree.Parent();<br>
+    OS << ">";<br>
+  }<br>
+<br>
+  // To signal to the text printer that a certain text needs to be bolded,<br>
+  // a special character is injected into the character stream which the<br>
+  // text printer will later strip out.<br>
+<br>
+  /// Bold - Start bolding text.<br>
+  void Bold() {<br>
+    assert(!IsBold && "Attempting to bold text that is already bold.");<br>
+    IsBold = true;<br>
+    if (ShowColor)<br>
+      OS << ToggleHighlight;<br>
+  }<br>
+<br>
+  /// Unbold - Stop bolding text.<br>
+  void Unbold() {<br>
+    assert(IsBold && "Attempting to remove bold from unbold text.");<br>
+    IsBold = false;<br>
+    if (ShowColor)<br>
+      OS << ToggleHighlight;<br>
+  }<br>
+<br>
+  // Functions to print out the arguments and highlighting the difference.<br>
+<br>
+  /// PrintTypeNames - prints the typenames, bolding differences.  Will detect<br>
+  /// typenames that are the same and attempt to disambiguate them by using<br>
+  /// canonical typenames.<br>
+  void PrintTypeNames(QualType FromType, QualType ToType,<br>
+                      bool FromDefault, bool ToDefault, bool Same) {<br>
+    assert((!FromType.isNull() || !ToType.isNull()) &&<br>
+           "Only one template argument may be missing.");<br>
+<br>
+    if (Same) {<br>
+      OS << FromType.getAsString();<br>
+      return;<br>
+    }<br>
+<br>
+    std::string FromTypeStr = FromType.isNull() ? "(no argument)"<br>
+                                                : FromType.getAsString();<br>
+    std::string ToTypeStr = ToType.isNull() ? "(no argument)"<br>
+                                            : ToType.getAsString();<br>
+    // Switch to canonical typename if it is better.<br>
+    // TODO: merge this with other aka printing above.<br>
+    if (FromTypeStr == ToTypeStr) {<br>
+      std::string FromCanTypeStr = FromType.getCanonicalType().getAsString();<br>
+      std::string ToCanTypeStr = ToType.getCanonicalType().getAsString();<br>
+      if (FromCanTypeStr != ToCanTypeStr) {<br>
+        FromTypeStr = FromCanTypeStr;<br>
+        ToTypeStr = ToCanTypeStr;<br>
+      }<br>
+    }<br>
+<br>
+    if (PrintTree) OS << '[';<br>
+    OS << (FromDefault ? "(default) " : "");<br>
+    Bold();<br>
+    OS << FromTypeStr;<br>
+    Unbold();<br>
+    if (PrintTree) {<br>
+      OS << " != " << (ToDefault ? "(default) " : "");<br>
+      Bold();<br>
+      OS << ToTypeStr;<br>
+      Unbold();<br>
+      OS << "]";<br>
+    }<br>
+    return;<br>
+  }<br>
+<br>
+  /// PrintExpr - Prints out the expr template arguments, highlighting argument<br>
+  /// differences.<br>
+  void PrintExpr(const Expr *FromExpr, const Expr *ToExpr,<br>
+                 bool FromDefault, bool ToDefault, bool Same) {<br>
+    assert((FromExpr || ToExpr) &&<br>
+            "Only one template argument may be missing.");<br>
+    if (Same) {<br>
+      PrintExpr(FromExpr);<br>
+    } else if (!PrintTree) {<br>
+      OS << (FromDefault ? "(default) " : "");<br>
+      Bold();<br>
+      PrintExpr(FromExpr);<br>
+      Unbold();<br>
+    } else {<br>
+      OS << (FromDefault ? "[(default) " : "[");<br>
+      Bold();<br>
+      PrintExpr(FromExpr);<br>
+      Unbold();<br>
+      OS << " != " << (ToDefault ? "(default) " : "");<br>
+      Bold();<br>
+      PrintExpr(ToExpr);<br>
+      Unbold();<br>
+      OS << ']';<br>
+    }<br>
+  }<br>
+<br>
+  /// PrintExpr - Actual formatting and printing of expressions.<br>
+  void PrintExpr(const Expr *E) {<br>
+    if (!E)<br>
+      OS << "(no argument)";<br>
+    else<br>
+      E->printPretty(OS, Context, 0, Policy); return;<br>
+  }<br>
+<br>
+  /// PrintTemplateTemplate - Handles printing of template template arguments,<br>
+  /// highlighting argument differences.<br>
+  void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,<br>
+                             bool FromDefault, bool ToDefault, bool Same) {<br>
+    assert((FromTD || ToTD) && "Only one template argument may be missing.");<br>
+    if (Same) {<br>
+      OS << "template " << FromTD->getNameAsString();<br>
+    } else if (!PrintTree) {<br>
+      OS << (FromDefault ? "(default) template " : "template ");<br>
+      Bold();<br>
+      OS << (FromTD ? FromTD->getNameAsString() : "(no argument)");<br>
+      Unbold();<br>
+    } else {<br>
+      OS << (FromDefault ? "[(default) template " : "[template ");<br>
+      Bold();<br>
+      OS << (FromTD ? FromTD->getNameAsString() : "(no argument)");<br>
+      Unbold();<br>
+      OS << " != " << (ToDefault ? "(default) template " : "template ");<br>
+      Bold();<br>
+      OS << (ToTD ? ToTD->getNameAsString() : "(no argument)");<br>
+      Unbold();<br>
+      OS << ']';<br>
+    }<br>
+  }<br>
+<br>
+  // Prints the appropriate placeholder for elided template arguments.<br>
+  void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {<br>
+    if (PrintTree) {<br>
+      OS << '\n';<br>
+      for (unsigned i = 0; i < Indent; ++i)<br>
+        OS << "  ";<br>
+    }<br>
+    if (NumElideArgs == 0) return;<br>
+    if (NumElideArgs == 1)<br>
+      OS << "[...]";<br>
+    else<br>
+      OS << "[" << NumElideArgs << " * ...]";<br>
+  }<br>
+<br>
+public:<br>
+<br>
+  TemplateDiff(ASTContext &Context, QualType FromType, QualType ToType,<br>
+               bool PrintTree, bool PrintFromType, bool ElideType,<br>
+               bool ShowColor)<br>
+    : Context(Context),<br>
+      Policy(Context.getLangOpts()),<br>
+      ElideType(ElideType),<br>
+      PrintTree(PrintTree),<br>
+      ShowColor(ShowColor),<br>
+      // When printing a single type, the FromType is the one printed.<br>
+      FromType(PrintFromType ? FromType : ToType),<br>
+      ToType(PrintFromType ? ToType : FromType),<br>
+      OS(Str),<br>
+      IsBold(false) {<br>
+  }<br>
+<br>
+  /// DiffTemplate - Start the template type diffing.<br>
+  void DiffTemplate() {<br>
+    const TemplateSpecializationType *FromOrigTST =<br>
+        GetTemplateSpecializationType(Context, FromType);<br>
+    const TemplateSpecializationType *ToOrigTST =<br>
+        GetTemplateSpecializationType(Context, ToType);<br>
+<br>
+    // Only checking templates.<br>
+    if (!FromOrigTST || !ToOrigTST)<br>
+      return;<br>
+<br>
+    // Different base templates.<br>
+    if (!hasSameTemplate(FromOrigTST, ToOrigTST)) {<br>
+      return;<br>
+    }<br>
+<br>
+    Tree.SetNode(FromType, ToType);<br>
+<br>
+    // Same base template, but different arguments.<br>
+    Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(),<br>
+                 ToOrigTST->getTemplateName().getAsTemplateDecl());<br>
+<br>
+    DiffTemplate(FromOrigTST, ToOrigTST);<br>
+  };<br>
+<br>
+  /// MakeString - When the two types given are templated types with the same<br>
+  /// base template, a string representation of the type difference will be<br>
+  /// loaded into S and return true.  Otherwise, return false.<br>
+  bool MakeString(std::string &S) {<br>
+    Tree.StartTraverse();<br>
+    if (Tree.Empty())<br>
+      return false;<br>
+<br>
+    TreeToString();<br>
+    assert(!IsBold && "Bold is applied to end of string.");<br>
+    S = OS.str();<br>
+    return true;<br>
+  }<br>
+}; // end class TemplateDiff<br>
+}  // end namespace<br>
+<br>
+/// FormatTemplateTypeDiff - A helper static function to start the template<br>
+/// diff and return the properly formatted string.  Returns true if the diff<br>
+/// is successful.<br>
+static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,<br>
+                                   QualType ToType, bool PrintTree,<br>
+                                   bool PrintFromType, bool ElideType,<br>
+                                   bool ShowColors, std::string &S) {<br>
+  if (PrintTree)<br>
+    PrintFromType = true;<br>
+  TemplateDiff TD(Context, FromType, ToType, PrintTree, PrintFromType,<br>
+                  ElideType, ShowColors);<br>
+  TD.DiffTemplate();<br>
+  return TD.MakeString(S);<br>
+}<br>
<br>
Modified: cfe/trunk/lib/Basic/Diagnostic.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)<br>
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Tue Jun 26 13:18:47 2012<br>
@@ -48,6 +48,9 @@<br>
   ErrorsAsFatal = false;<br>
   SuppressSystemWarnings = false;<br>
   SuppressAllDiagnostics = false;<br>
+  ElideType = true;<br>
+  PrintTemplateTree = false;<br>
+  ShowColors = false;<br>
   ShowOverloads = Ovl_All;<br>
   ExtBehavior = Ext_Ignore;<br>
<br>
@@ -660,6 +663,8 @@<br>
   /// QualTypeVals - Pass a vector of arrays so that QualType names can be<br>
   /// compared to see if more information is needed to be printed.<br>
   SmallVector<intptr_t, 2> QualTypeVals;<br>
+  SmallVector<char, 64> Tree;<br>
+<br>
   for (unsigned i = 0, e = getNumArgs(); i < e; ++i)<br>
     if (getArgKind(i) == DiagnosticsEngine::ak_qualtype)<br>
       QualTypeVals.push_back(getRawArg(i));<br>
@@ -711,7 +716,20 @@<br>
     assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");<br>
     unsigned ArgNo = *DiagStr++ - '0';<br>
<br>
+    // Only used for type diffing.<br>
+    unsigned ArgNo2 = ArgNo;<br>
+<br>
     DiagnosticsEngine::ArgumentKind Kind = getArgKind(ArgNo);<br>
+    if (Kind == DiagnosticsEngine::ak_qualtype &&<br>
+        ModifierIs(Modifier, ModifierLen, "diff")) {<br>
+      Kind = DiagnosticsEngine::ak_qualtype_pair;<br>
+      assert(*DiagStr == ',' && isdigit(*(DiagStr + 1)) &&<br>
+             "Invalid format for diff modifier");<br>
+      ++DiagStr;  // Comma.<br>
+      ArgNo2 = *DiagStr++ - '0';<br>
+      assert(getArgKind(ArgNo2) == DiagnosticsEngine::ak_qualtype &&<br>
+             "Second value of type diff must be a qualtype");<br>
+    }<br>
<br>
     switch (Kind) {<br>
     // ---- STRINGS ----<br>
@@ -796,18 +814,77 @@<br>
                                      FormattedArgs.data(), FormattedArgs.size(),<br>
                                      OutStr, QualTypeVals);<br>
       break;<br>
+    case DiagnosticsEngine::ak_qualtype_pair:<br>
+      // Create a struct with all the info needed for printing.<br>
+      TemplateDiffTypes TDT;<br>
+      TDT.FromType = getRawArg(ArgNo);<br>
+      TDT.ToType = getRawArg(ArgNo2);<br>
+      TDT.ElideType = getDiags()->ElideType;<br>
+      TDT.ShowColors = getDiags()->ShowColors;<br>
+      intptr_t val = reinterpret_cast<intptr_t>(&TDT);<br>
+<br>
+      // Print the tree.<br>
+      if (getDiags()->PrintTemplateTree) {<br>
+        TDT.PrintFromType = true;<br>
+        TDT.PrintTree = true;<br>
+        getDiags()->ConvertArgToString(Kind, val,<br>
+                                       Modifier, ModifierLen,<br>
+                                       Argument, ArgumentLen,<br>
+                                       FormattedArgs.data(),<br>
+                                       FormattedArgs.size(),<br>
+                                       Tree, QualTypeVals);<br>
+        // If there is no tree information, fall back to regular printing.<br>
+        if (!Tree.empty())<br>
+          break;<br>
+      }<br>
+<br>
+      // Non-tree printing, also the fall-back when tree printing fails.<br>
+      // The fall-back is triggered when the types compared are not templates.<br>
+      const char *ArgumentEnd = Argument + ArgumentLen;<br>
+      const char *FirstPipe = ScanFormat(Argument, ArgumentEnd, '|');<br>
+      const char *SecondPipe = ScanFormat(FirstPipe + 1, ArgumentEnd, '|');<br>
+<br>
+      // Append before text<br>
+      FormatDiagnostic(Argument, FirstPipe, OutStr);<br>
+<br>
+      // Append first type<br>
+      TDT.PrintTree = false;<br>
+      TDT.PrintFromType = true;<br>
+      getDiags()->ConvertArgToString(Kind, val,<br>
+                                     Modifier, ModifierLen,<br>
+                                     Argument, ArgumentLen,<br>
+                                     FormattedArgs.data(), FormattedArgs.size(),<br>
+                                     OutStr, QualTypeVals);<br>
+      // Append middle text<br>
+      FormatDiagnostic(FirstPipe + 1, SecondPipe, OutStr);<br>
+<br>
+      // Append second type<br>
+      TDT.PrintFromType = false;<br>
+      getDiags()->ConvertArgToString(Kind, val,<br>
+                                     Modifier, ModifierLen,<br>
+                                     Argument, ArgumentLen,<br>
+                                     FormattedArgs.data(), FormattedArgs.size(),<br>
+                                     OutStr, QualTypeVals);<br>
+      // Append end text<br>
+      FormatDiagnostic(SecondPipe + 1, ArgumentEnd, OutStr);<br>
+      break;<br>
     }<br>
<br>
     // Remember this argument info for subsequent formatting operations.  Turn<br>
     // std::strings into a null terminated string to make it be the same case as<br>
     // all the other ones.<br>
-    if (Kind != DiagnosticsEngine::ak_std_string)<br>
+    if (Kind == DiagnosticsEngine::ak_qualtype_pair)<br>
+      continue;<br>
+    else if (Kind != DiagnosticsEngine::ak_std_string)<br>
       FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo)));<br>
     else<br>
       FormattedArgs.push_back(std::make_pair(DiagnosticsEngine::ak_c_string,<br>
                                         (intptr_t)getArgStdStr(ArgNo).c_str()));<br>
<br>
   }<br>
+<br>
+  // Append the type tree to the end of the diagnostics.<br>
+  OutStr.append(Tree.begin(), Tree.end());<br>
 }<br>
<br>
 StoredDiagnostic::StoredDiagnostic() { }<br>
<br>
Modified: cfe/trunk/lib/Driver/Tools.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Driver/Tools.cpp (original)<br>
+++ cfe/trunk/lib/Driver/Tools.cpp Tue Jun 26 13:18:47 2012<br>
@@ -2203,6 +2203,8 @@<br>
   Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info);<br>
   Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names);<br>
   Args.AddLastArg(CmdArgs, options::OPT_faltivec);<br>
+  Args.AddLastArg(CmdArgs, options::OPT_fdiagnostics_show_template_tree);<br>
+  Args.AddLastArg(CmdArgs, options::OPT_fno_elide_type);<br>
<br>
   // Report and error for -faltivec on anything other then PowerPC.<br>
   if (const Arg *A = Args.getLastArg(options::OPT_faltivec))<br>
<br>
Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Tue Jun 26 13:18:47 2012<br>
@@ -1349,6 +1349,8 @@<br>
   Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);<br>
   Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits);<br>
   Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);<br>
+  Opts.ElideType = !Args.hasArg(OPT_fno_elide_type);<br>
+  Opts.ShowTemplateTree = Args.hasArg(OPT_fdiagnostics_show_template_tree);<br>
   Opts.ErrorLimit = Args.getLastArgIntValue(OPT_ferror_limit, 0, Diags);<br>
   Opts.MacroBacktraceLimit<br>
     = Args.getLastArgIntValue(OPT_fmacro_backtrace_limit,<br>
<br>
Modified: cfe/trunk/lib/Frontend/TextDiagnostic.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/TextDiagnostic.cpp?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/TextDiagnostic.cpp?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Frontend/TextDiagnostic.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/TextDiagnostic.cpp Tue Jun 26 13:18:47 2012<br>
@@ -31,12 +31,29 @@<br>
   raw_ostream::GREEN;<br>
 static const enum raw_ostream::Colors warningColor =<br>
   raw_ostream::MAGENTA;<br>
+static const enum raw_ostream::Colors templateColor =<br>
+  raw_ostream::CYAN;<br>
 static const enum raw_ostream::Colors errorColor = raw_ostream::RED;<br>
 static const enum raw_ostream::Colors fatalColor = raw_ostream::RED;<br>
 // Used for changing only the bold attribute.<br>
 static const enum raw_ostream::Colors savedColor =<br>
   raw_ostream::SAVEDCOLOR;<br>
<br>
+/// \brief Add highlights to differences in template strings.<br>
+static void applyTemplateHighlighting(raw_ostream &OS, StringRef Str,<br>
+                                      bool &Normal) {<br>
+  for (unsigned i = 0, e = Str.size(); i < e; ++i)<br>
+    if (Str[i] != ToggleHighlight) {<br>
+      OS << Str[i];<br>
+    } else {<br>
+      if (Normal)<br>
+        OS.changeColor(templateColor, true);<br>
+      else<br>
+        OS.resetColor();<br>
+      Normal = !Normal;<br>
+    }<br>
+}<br>
+<br>
 /// \brief Number of spaces to indent when word-wrapping.<br>
 const unsigned WordWrapIndentation = 6;<br>
<br>
@@ -578,6 +595,7 @@<br>
                              unsigned Column = 0,<br>
                              unsigned Indentation = WordWrapIndentation) {<br>
   const unsigned Length = std::min(Str.find('\n'), Str.size());<br>
+  bool TextNormal = true;<br>
<br>
   // The string used to indent each line.<br>
   SmallString<16> IndentStr;<br>
@@ -601,7 +619,8 @@<br>
         OS << ' ';<br>
         Column += 1;<br>
       }<br>
-      OS << Str.substr(WordStart, WordLength);<br>
+      applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),<br>
+                                TextNormal);<br>
       Column += WordLength;<br>
       continue;<br>
     }<br>
@@ -610,13 +629,16 @@<br>
     // line.<br>
     OS << '\n';<br>
     OS.write(&IndentStr[0], Indentation);<br>
-    OS << Str.substr(WordStart, WordLength);<br>
+    applyTemplateHighlighting(OS, Str.substr(WordStart, WordLength),<br>
+                              TextNormal);<br>
     Column = Indentation + WordLength;<br>
     Wrapped = true;<br>
   }<br>
<br>
   // Append any remaning text from the message with its existing formatting.<br>
-  OS << Str.substr(Length);<br>
+  applyTemplateHighlighting(OS, Str.substr(Length), TextNormal);<br>
+<br>
+  assert(TextNormal && "Text highlighted at end of diagnostic message.");<br>
<br>
   return Wrapped;<br>
 }<br>
<br>
Modified: cfe/trunk/lib/Frontend/Warnings.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Warnings.cpp?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/Warnings.cpp?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Frontend/Warnings.cpp (original)<br>
+++ cfe/trunk/lib/Frontend/Warnings.cpp Tue Jun 26 13:18:47 2012<br>
@@ -53,7 +53,11 @@<br>
   Diags.setIgnoreAllWarnings(Opts.IgnoreWarnings);<br>
   Diags.setShowOverloads(<br>
     static_cast<DiagnosticsEngine::OverloadsShown>(Opts.ShowOverloads));<br>
-<br>
+<br>
+  Diags.setElideType(Opts.ElideType);<br>
+  Diags.setPrintTemplateTree(Opts.ShowTemplateTree);<br>
+  Diags.setShowColors(Opts.ShowColors);<br>
+<br>
   // Handle -ferror-limit<br>
   if (Opts.ErrorLimit)<br>
     Diags.setErrorLimit(Opts.ErrorLimit);<br>
<br>
Modified: cfe/trunk/test/Misc/diag-aka-types.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-aka-types.cpp?rev=159216&r1=159215&r2=159216&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-aka-types.cpp?rev=159216&r1=159215&r2=159216&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/Misc/diag-aka-types.cpp (original)<br>
+++ cfe/trunk/test/Misc/diag-aka-types.cpp Tue Jun 26 13:18:47 2012<br>
@@ -30,27 +30,6 @@<br>
   bar::f(x); // expected-error{{cannot initialize a parameter of type 'Foo::foo *' (aka 'bar::Foo::foo *') with an lvalue of type 'Foo::foo *'}}<br>
 }<br>
<br>
-// PR9548 - "no known conversion from 'vector<string>' to 'vector<string>'"<br>
-// vector<string> refers to two different types here.  Make sure the message<br>
-// gives a way to tell them apart.<br>
-class versa_string;<br>
-typedef versa_string string;<br>
-<br>
-namespace std {template <typename T> class vector;}<br>
-using std::vector;<br>
-<br>
-void f(vector<string> v);  // expected-note {{candidate function not viable: no known conversion from 'vector<string>' (aka 'std::vector<std::basic_string>') to 'vector<string>' (aka 'std::vector<versa_string>') for 1st argument}}<br>

-<br>
-namespace std {<br>
-  class basic_string;<br>
-  typedef basic_string string;<br>
-  template <typename T> class vector {};<br>
-  void g() {<br>
-    vector<string> v;<br>
-    f(v);  // expected-error{{no matching function for call to 'f'}}<br>
-  }<br>
-}<br>
-<br>
 namespace ns {<br>
  struct str {<br>
    static void method(struct data *) {}<br>
<br>
Added: cfe/trunk/test/Misc/diag-template-diffing.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=159216&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=159216&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/test/Misc/diag-template-diffing.cpp (added)<br>
+++ cfe/trunk/test/Misc/diag-template-diffing.cpp Tue Jun 26 13:18:47 2012<br>
@@ -0,0 +1,433 @@<br>
+// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 2>&1 | FileCheck %s -check-prefix=CHECK-ELIDE-NOTREE<br>
+// RUN: %clang_cc1 -fsyntax-only %s -fno-elide-type -std=c++11 2>&1 | FileCheck %s -check-prefix=CHECK-NOELIDE-NOTREE<br>
+// RUN: %clang_cc1 -fsyntax-only %s -fdiagnostics-show-template-tree -std=c++11 2>&1 | FileCheck %s -check-prefix=CHECK-ELIDE-TREE<br>
+// RUN: %clang_cc1 -fsyntax-only %s -fno-elide-type -fdiagnostics-show-template-tree -std=c++11 2>&1 | FileCheck %s -check-prefix=CHECK-NOELIDE-TREE<br>
+<br>
+// PR9548 - "no known conversion from 'vector<string>' to 'vector<string>'"<br>
+// vector<string> refers to two different types here.  Make sure the message<br>
+// gives a way to tell them apart.<br>
+class versa_string;<br>
+typedef versa_string string;<br>
+<br>
+namespace std {template <typename T> class vector;}<br>
+using std::vector;<br>
+<br>
+void f(vector<string> v);<br>
+<br>
+namespace std {<br>
+  class basic_string;<br>
+  typedef basic_string string;<br>
+  template <typename T> class vector {};<br>
+  void g() {<br>
+    vector<string> v;<br>
+    f(v);<br>
+  }<br>
+} // end namespace std<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'f'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<class std::basic_string>' to 'vector<class versa_string>' for 1st argument<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'f'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'vector<class std::basic_string>' to 'vector<class versa_string>' for 1st argument<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'f'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion  for 1st argument<br>
+// CHECK-ELIDE-TREE:   vector<<br>
+// CHECK-ELIDE-TREE:     [class std::basic_string != class versa_string]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'f'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-NOELIDE-TREE:   vector<<br>
+// CHECK-NOELIDE-TREE:     [class std::basic_string != class versa_string]><br>
+<br>
+template <int... A><br>
+class I1{};<br>
+void set1(I1<1,2,3,4,2,3,4,3>) {};<br>
+void test1() {<br>
+  set1(I1<1,2,3,4,2,2,4,3,7>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set1'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'I1<[5 * ...], 2, [2 * ...], 7>' to 'I1<[5 * ...], 3, [2 * ...], (no argument)>' for 1st argument<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set1'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'I1<1, 2, 3, 4, 2, 2, 4, 3, 7>' to 'I1<1, 2, 3, 4, 2, 3, 4, 3, (no argument)>' for 1st argument<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set1'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-ELIDE-TREE:   I1<<br>
+// CHECK-ELIDE-TREE:     [5 * ...],<br>
+// CHECK-ELIDE-TREE:     [2 != 3],<br>
+// CHECK-ELIDE-TREE:     [2 * ...],<br>
+// CHECK-ELIDE-TREE:     [7 != (no argument)]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set1'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-NOELIDE-TREE:   I1<<br>
+// CHECK-NOELIDE-TREE:     1,<br>
+// CHECK-NOELIDE-TREE:     2,<br>
+// CHECK-NOELIDE-TREE:     3,<br>
+// CHECK-NOELIDE-TREE:     4,<br>
+// CHECK-NOELIDE-TREE:     2,<br>
+// CHECK-NOELIDE-TREE:     [2 != 3],<br>
+// CHECK-NOELIDE-TREE:     4,<br>
+// CHECK-NOELIDE-TREE:     3,<br>
+// CHECK-NOELIDE-TREE:     [7 != (no argument)]><br>
+<br>
+template <class A, class B, class C = void><br>
+class I2{};<br>
+void set2(I2<int, int>) {};<br>
+void test2() {<br>
+  set2(I2<double, int, int>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set2'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'I2<double, [...], int>' to 'I2<int, [...], (default) void>' for 1st argument<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set2'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'I2<double, int, int>' to 'I2<int, int, (default) void>' for 1st argument<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set2'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-ELIDE-TREE:   I2<<br>
+// CHECK-ELIDE-TREE:     [double != int],<br>
+// CHECK-ELIDE-TREE:     [...],<br>
+// CHECK-ELIDE-TREE:     [int != (default) void]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set2'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-NOELIDE-TREE:   I2<<br>
+// CHECK-NOELIDE-TREE:     [double != int],<br>
+// CHECK-NOELIDE-TREE:     int,<br>
+// CHECK-NOELIDE-TREE:     [int != (default) void]><br>
+<br>
+int V1, V2, V3;<br>
+template <int* A, int *B><br>
+class I3{};<br>
+void set3(I3<&V1, &V2>) {};<br>
+void test3() {<br>
+  set3(I3<&V3, &V2>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set3'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'I3<&V3, [...]>' to 'I3<&V1, [...]>' for 1st argument<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set3'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'I3<&V3, &V2>' to 'I3<&V1, &V2>' for 1st argument<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set3'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-ELIDE-TREE:   I3<<br>
+// CHECK-ELIDE-TREE:     [&V3 != &V1]<br>
+// CHECK-ELIDE-TREE:     [...]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set3'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-NOELIDE-TREE:   I3<<br>
+// CHECK-NOELIDE-TREE:     [&V3 != &V1]<br>
+// CHECK-NOELIDE-TREE:     &V2><br>
+<br>
+template <class A, class B><br>
+class Alpha{};<br>
+template <class A, class B><br>
+class Beta{};<br>
+template <class A, class B><br>
+class Gamma{};<br>
+template <class A, class B><br>
+class Delta{};<br>
+<br>
+void set4(Alpha<int, int>);<br>
+void test4() {<br>
+  set4(Beta<void, void>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set4'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'Beta<void, void>' to 'Alpha<int, int>' for 1st argument<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set4'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'Beta<void, void>' to 'Alpha<int, int>' for 1st argument<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set4'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from 'Beta<void, void>' to 'Alpha<int, int>' for 1st argument<br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set4'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from 'Beta<void, void>' to 'Alpha<int, int>' for 1st argument<br>
+<br>
+void set5(Alpha<Beta<Gamma<Delta<int, int>, int>, int>, int>);<br>
+void test5() {<br>
+  set5(Alpha<Beta<Gamma<void, void>, double>, double>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set5'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<Beta<Gamma<void, void>, double>, double>' to 'Alpha<Beta<Gamma<Delta<int, int>, int>, int>, int>' for 1st argument<br>

+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set5'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<Beta<Gamma<void, void>, double>, double>' to 'Alpha<Beta<Gamma<Delta<int, int>, int>, int>, int>' for 1st argument<br>

+// CHECK-ELIDE-TREE: no matching function for call to 'set5'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-ELIDE-TREE:   Alpha<<br>
+// CHECK-ELIDE-TREE:     Beta<<br>
+// CHECK-ELIDE-TREE:       Gamma<<br>
+// CHECK-ELIDE-TREE:         [void != Delta<int, int>],<br>
+// CHECK-ELIDE-TREE:         [void != int]><br>
+// CHECK-ELIDE-TREE:       [double != int]><br>
+// CHECK-ELIDE-TREE:     [double != int]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set5'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-NOELIDE-TREE:   Alpha<<br>
+// CHECK-NOELIDE-TREE:     Beta<<br>
+// CHECK-NOELIDE-TREE:       Gamma<<br>
+// CHECK-NOELIDE-TREE:         [void != Delta<int, int>],<br>
+// CHECK-NOELIDE-TREE:         [void != int]><br>
+// CHECK-NOELIDE-TREE:       [double != int]><br>
+// CHECK-NOELIDE-TREE:     [double != int]><br>
+<br>
+void test6() {<br>
+  set5(Alpha<Beta<Delta<int, int>, int>, int>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set5'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<Beta<Delta<int, int>, [...]>, [...]>' to 'Alpha<Beta<Gamma<Delta<int, int>, int>, [...]>, [...]>' for 1st argument<br>

+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set5'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'Alpha<Beta<Delta<int, int>, int>, int>' to 'Alpha<Beta<Gamma<Delta<int, int>, int>, int>, int>' for 1st argument<br>

+// CHECK-ELIDE-TREE: no matching function for call to 'set5'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-ELIDE-TREE:   Alpha<<br>
+// CHECK-ELIDE-TREE:     Beta<<br>
+// CHECK-ELIDE-TREE:       [Delta<int, int> != Gamma<Delta<int, int>, int>],<br>
+// CHECK-ELIDE-TREE:       [...]><br>
+// CHECK-ELIDE-TREE:     [...]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set5'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument<br>
+// CHECK-NOELIDE-TREE:   Alpha<<br>
+// CHECK-NOELIDE-TREE:     Beta<<br>
+// CHECK-NOELIDE-TREE:       [Delta<int, int> != Gamma<Delta<int, int>, int>],<br>
+// CHECK-NOELIDE-TREE:       int><br>
+// CHECK-NOELIDE-TREE:     int><br>
+<br>
+int a7, b7;<br>
+int c7[] = {1,2,3};<br>
+template<int *A><br>
+class class7 {};<br>
+void set7(class7<&a7> A) {}<br>
+void test7() {<br>
+  set7(class7<&a7>());<br>
+  set7(class7<&b7>());<br>
+  set7(class7<c7>());<br>
+  set7(class7<nullptr>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set7'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class7<&b7>' to 'class7<&a7>' for 1st argument;<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set7'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class7<c7>' to 'class7<&a7>' for 1st argument;<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set7'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class7<nullptr>' to 'class7<&a7>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set7'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class7<&b7>' to 'class7<&a7>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set7'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class7<c7>' to 'class7<&a7>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set7'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class7<nullptr>' to 'class7<&a7>' for 1st argument;<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set7'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class7<<br>
+// CHECK-ELIDE-TREE:     [&b7 != &a7]><br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set7'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class7<<br>
+// CHECK-ELIDE-TREE:     [c7 != &a7]><br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set7'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class7<<br>
+// CHECK-ELIDE-TREE:     [nullptr != &a7]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set7'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class7<<br>
+// CHECK-NOELIDE-TREE:     [&b7 != &a7]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set7'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class7<<br>
+// CHECK-NOELIDE-TREE:     [c7 != &a7]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set7'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class7<<br>
+// CHECK-NOELIDE-TREE:     [nullptr != &a7]><br>
+<br>
+template<typename ...T> struct S8 {};<br>
+template<typename T> using U8 = S8<int, char, T>;<br>
+int f8(S8<int, char, double>);<br>
+int k8 = f8(U8<char>());<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'f8'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'S8<[2 * ...], char>' to 'S8<[2 * ...], double>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'f8'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'S8<int, char, char>' to 'S8<int, char, double>' for 1st argument;<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'f8'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   S8<<br>
+// CHECK-ELIDE-TREE:     [2 * ...],<br>
+// CHECK-ELIDE-TREE:     [char != double]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'f8'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   S8<<br>
+// CHECK-NOELIDE-TREE:     int,<br>
+// CHECK-NOELIDE-TREE:     char,<br>
+// CHECK-NOELIDE-TREE:     [char != double]><br>
+<br>
+template<typename ...T> struct S9 {};<br>
+template<typename T> using U9 = S9<int, char, T>;<br>
+template<typename T> using V9 = U9<U9<T>>;<br>
+int f9(S9<int, char, U9<const double>>);<br>
+int k9 = f9(V9<double>());<br>
+<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'f9'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<[2 * ...], S9<[2 * ...], double>>' to 'S9<[2 * ...], S9<[2 * ...], const double>>' for 1st argument;<br>

+// CHECK-NOELIDE-NOTREE: no matching function for call to 'f9'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<int, char, S9<int, char, double>>' to 'S9<int, char, S9<int, char, const double>>' for 1st argument;<br>

+// CHECK-ELIDE-TREE: no matching function for call to 'f9'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   S9<<br>
+// CHECK-ELIDE-TREE:     [2 * ...],<br>
+// CHECK-ELIDE-TREE:     S9<<br>
+// CHECK-ELIDE-TREE:       [2 * ...],<br>
+// CHECK-ELIDE-TREE:       [double != const double]>><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'f9'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   S9<<br>
+// CHECK-NOELIDE-TREE:     int,<br>
+// CHECK-NOELIDE-TREE:     char,<br>
+// CHECK-NOELIDE-TREE:     S9<<br>
+// CHECK-NOELIDE-TREE:       int,<br>
+// CHECK-NOELIDE-TREE:       char,<br>
+// CHECK-NOELIDE-TREE:       [double != const double]>><br>
+<br>
+template<typename ...A> class class_types {};<br>
+void set10(class_types<int, int>) {}<br>
+void test10() {<br>
+  set10(class_types<int>());<br>
+  set10(class_types<int, int, int>());<br>
+}<br>
+<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set10'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_types<[...], (no argument)>' to 'class_types<[...], int>' for 1st argument;<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set10'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_types<[2 * ...], int>' to 'class_types<[2 * ...], (no argument)>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set10'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class_types<int, (no argument)>' to 'class_types<int, int>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set10'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class_types<int, int, int>' to 'class_types<int, int, (no argument)>' for 1st argument;<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set10'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class_types<<br>
+// CHECK-ELIDE-TREE:     [...],<br>
+// CHECK-ELIDE-TREE:     [(no argument) != int]><br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set10'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class_types<<br>
+// CHECK-ELIDE-TREE:     [2 * ...],<br>
+// CHECK-ELIDE-TREE:     [int != (no argument)]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set10'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class_types<<br>
+// CHECK-NOELIDE-TREE:     int,<br>
+// CHECK-NOELIDE-TREE:     [(no argument) != int]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set10'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class_types<<br>
+// CHECK-NOELIDE-TREE:     int,<br>
+// CHECK-NOELIDE-TREE:     int,<br>
+// CHECK-NOELIDE-TREE:     [int != (no argument)]><br>
+<br>
+template<int ...A> class class_ints {};<br>
+void set11(class_ints<2, 3>) {}<br>
+void test11() {<br>
+  set11(class_ints<1>());<br>
+  set11(class_ints<0, 3, 6>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set11'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ints<1, (no argument)>' to 'class_ints<2, 3>' for 1st argument;<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set11'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ints<0, [...], 6>' to 'class_ints<2, [...], (no argument)>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set11'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ints<1, (no argument)>' to 'class_ints<2, 3>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set11'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ints<0, 3, 6>' to 'class_ints<2, 3, (no argument)>' for 1st argument;<br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set11'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class_ints<<br>
+// CHECK-ELIDE-TREE:     [1 != 2],<br>
+// CHECK-ELIDE-TREE:     [(no argument) != 3]><br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set11'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class_ints<<br>
+// CHECK-ELIDE-TREE:     [0 != 2],<br>
+// CHECK-ELIDE-TREE:     [...],<br>
+// CHECK-ELIDE-TREE:     [6 != (no argument)]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set11'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class_ints<<br>
+// CHECK-NOELIDE-TREE:     [1 != 2],<br>
+// CHECK-NOELIDE-TREE:     [(no argument) != 3]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set11'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class_ints<<br>
+// CHECK-NOELIDE-TREE:     [0 != 2],<br>
+// CHECK-NOELIDE-TREE:     3,<br>
+// CHECK-NOELIDE-TREE:     [6 != (no argument)]><br>
+<br>
+template<template<class> class ...A> class class_template_templates {};<br>
+template<class> class tt1 {};<br>
+template<class> class tt2 {};<br>
+void set12(class_template_templates<tt1, tt1>) {}<br>
+void test12() {<br>
+  set12(class_template_templates<tt2>());<br>
+  set12(class_template_templates<tt1, tt1, tt1>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set12'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_template_templates<template tt2, template (no argument)>' to 'class_template_templates<template tt1, template tt1>' for 1st argument;<br>

+// CHECK-ELIDE-NOTREE: no matching function for call to 'set12'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_template_templates<[2 * ...], template tt1>' to 'class_template_templates<[2 * ...], template (no argument)>' for 1st argument;<br>

+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set12'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class_template_templates<template tt2, template (no argument)>' to 'class_template_templates<template tt1, template tt1>' for 1st argument;<br>

+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set12'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class_template_templates<template tt1, template tt1, template tt1>' to 'class_template_templates<template tt1, template tt1, template (no argument)>' for 1st argument;<br>

+// CHECK-ELIDE-TREE: no matching function for call to 'set12'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class_template_templates<<br>
+// CHECK-ELIDE-TREE:     [template tt2 != template tt1],<br>
+// CHECK-ELIDE-TREE:     [template (no argument) != template tt1]><br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set12'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class_template_templates<<br>
+// CHECK-ELIDE-TREE:     [2 * ...],<br>
+// CHECK-ELIDE-TREE:     [template tt1 != template (no argument)]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set12'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class_template_templates<<br>
+// CHECK-NOELIDE-TREE:     [template tt2 != template tt1],<br>
+// CHECK-NOELIDE-TREE:     [template (no argument) != template tt1]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set12'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class_template_templates<<br>
+// CHECK-NOELIDE-TREE:     template tt1,<br>
+// CHECK-NOELIDE-TREE:     template tt1,<br>
+// CHECK-NOELIDE-TREE:     [template tt1 != template (no argument)]><br>
+<br>
+double a13, b13, c13, d13;<br>
+template<double* ...A> class class_ptrs {};<br>
+void set13(class_ptrs<&a13, &b13>) {}<br>
+void test13() {<br>
+  set13(class_ptrs<&c13>());<br>
+  set13(class_ptrss<&a13, &b13, &d13>());<br>
+}<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set13'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ptrs<&c13, (no argument)>' to 'class_ptrs<&a13, &b13>' for 1st argument;<br>
+// CHECK-ELIDE-NOTREE: no matching function for call to 'set13'<br>
+// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ptrs<[2 * ...], &d13>' to 'class_ptrs<[2 * ...], (no argument)>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set13'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ptrs<&c13, (no argument)>' to 'class_ptrs<&a13, &b13>' for 1st argument;<br>
+// CHECK-NOELIDE-NOTREE: no matching function for call to 'set13'<br>
+// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'class_ptrs<&a13, &b13, &d13>' to 'class_ptrs<&a13, &b13, (no argument)>' for 1st argument;<br>

+// CHECK-ELIDE-TREE: no matching function for call to 'set13'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class_ptrs<<br>
+// CHECK-ELIDE-TREE:     [&c13 != &a13],<br>
+// CHECK-ELIDE-TREE:     [(no argument) != &b13]><br>
+// CHECK-ELIDE-TREE: no matching function for call to 'set13'<br>
+// CHECK-ELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-ELIDE-TREE:   class_ptrs<<br>
+// CHECK-ELIDE-TREE:     [2 * ...],<br>
+// CHECK-ELIDE-TREE:     [&d13 != (no argument)]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set13'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class_ptrs<<br>
+// CHECK-NOELIDE-TREE:     [&c13 != &a13],<br>
+// CHECK-NOELIDE-TREE:     [(no argument) != &b13]><br>
+// CHECK-NOELIDE-TREE: no matching function for call to 'set13'<br>
+// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion for 1st argument;<br>
+// CHECK-NOELIDE-TREE:   class_ptrs<<br>
+// CHECK-NOELIDE-TREE:     &a13,<br>
+// CHECK-NOELIDE-TREE:     &b13,<br>
+// CHECK-NOELIDE-TREE:     [&d13 != (no argument)]><br>
+<br>
+<br>
+// CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.<br>
+// CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.<br>
+// CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.<br>
+// CHECK-NOELIDE-TREE: {{[0-9]*}} errors generated.<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></font></div>