[llvm-branch-commits] [cfe-branch] r259422 - Merging r257831, r257838, r257853, r257861, r257869, r257870, r257871.

Hans Wennborg via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Feb 1 14:13:54 PST 2016


Author: hans
Date: Mon Feb  1 16:13:54 2016
New Revision: 259422

URL: http://llvm.org/viewvc/llvm-project?rev=259422&view=rev
Log:
Merging r257831, r257838, r257853, r257861, r257869, r257870, r257871.

------------------------------------------------------------------------
r257831 | rtrieu | 2016-01-14 14:56:39 -0800 (Thu, 14 Jan 2016) | 13 lines

Refactor template type diffing

1) Instead of using pairs of From/To* fields, combine fields into a struct
TemplateArgInfo and have two in each DiffNode.
2) Use default initialization in DiffNode so that the constructor shows the
only field that is initialized differently on construction.
3) Use Set and Get functions per each DiffKind to make sure all fields for the
diff is set.  In one case, the Expr fields were not set.
4) Don't print boolean literals for boolean template arguments.  This prevents
printing 'false aka 0'

Only #3 has a functional change, which is reflected in the test change.
------------------------------------------------------------------------

------------------------------------------------------------------------
r257838 | rtrieu | 2016-01-14 15:30:12 -0800 (Thu, 14 Jan 2016) | 6 lines

Change the TSTiterator in Template Type Diffing.

Modify the TSTiterator to have two internal iterators, which will walk
the provided sugared type and the desugared type.  This will provide better
access to the template argument information.  No functional changes.
------------------------------------------------------------------------

------------------------------------------------------------------------
r257853 | rtrieu | 2016-01-14 17:08:56 -0800 (Thu, 14 Jan 2016) | 11 lines

Make template type diffing use the new desguared iterator.

If available, use the canonical template argument to fill in information for
template type diffing instead of attempting to special case and evaluate Expr's
for the value.  Since those are the values used in template instantiation,
we don't have to worry about difference between our evaluator and theirs.  Also
move the nullptr template arguments from DiffKind::Expression to
DiffKind::Declaration and allow DiffKind::Declaration to set an Expr.  The only
effect that should result is that a named nullptr will show up as
'ptr aka nullptr' in diagnostics.
------------------------------------------------------------------------

------------------------------------------------------------------------
r257861 | rtrieu | 2016-01-14 18:55:17 -0800 (Thu, 14 Jan 2016) | 7 lines

Save the integer type for integral template arguments.

Save the integer type when diffing integers in template type diffing.  When
integers are different sizes, print out the type along with the integer value.
Also with the type information, print true and false instead of 1 and 0 for
boolean values.
------------------------------------------------------------------------

------------------------------------------------------------------------
r257869 | rtrieu | 2016-01-14 21:01:53 -0800 (Thu, 14 Jan 2016) | 6 lines

Add new diff modes to template type diffing.

Remove an old assertion that does not hold.  It is possible for a template
argument to be a declaration in one instantiation and an integer in another.
Create two new diff kinds for these (decl vs int and int vs decl).
------------------------------------------------------------------------

------------------------------------------------------------------------
r257870 | rtrieu | 2016-01-14 21:48:38 -0800 (Thu, 14 Jan 2016) | 10 lines

Fixing more issues with template type diffing

1) Print qualifiers for templates with zero arguments
2) Add a few more tests for the template type diffing refactoring.
Specifically, PR24587 has been fixed and has a test case from
http://reviews.llvm.org/D15384
3) Adds asserts to check the DiffTree is in correct state when moving nodes
4) Rename the field FromType and ToType since it is heavily used within
member functions.
------------------------------------------------------------------------

------------------------------------------------------------------------
r257871 | jyknight | 2016-01-14 21:57:41 -0800 (Thu, 14 Jan 2016) | 1 line

Fix a -Wparentheses warning in ASTDiagnostic.cpp.
------------------------------------------------------------------------

Modified:
    cfe/branches/release_38/   (props changed)
    cfe/branches/release_38/lib/AST/ASTDiagnostic.cpp
    cfe/branches/release_38/test/Misc/diag-template-diffing-color.cpp
    cfe/branches/release_38/test/Misc/diag-template-diffing.cpp

Propchange: cfe/branches/release_38/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Feb  1 16:13:54 2016
@@ -1,4 +1,4 @@
 /cfe/branches/type-system-rewrite:134693-134817
-/cfe/trunk:257652,257695,257710,257947,258110,258396,259260
+/cfe/trunk:257652,257695,257710,257831,257838,257853,257861,257869-257871,257947,258110,258396,259260
 /cfe/trunk/test:170344
 /cfe/trunk/test/SemaTemplate:126920

Modified: cfe/branches/release_38/lib/AST/ASTDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_38/lib/AST/ASTDiagnostic.cpp?rev=259422&r1=259421&r2=259422&view=diff
==============================================================================
--- cfe/branches/release_38/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/branches/release_38/lib/AST/ASTDiagnostic.cpp Mon Feb  1 16:13:54 2016
@@ -473,14 +473,14 @@ class TemplateDiff {
   /// ShowColor - Diagnostics support color, so bolding will be used.
   bool ShowColor;
 
-  /// FromType - When single type printing is selected, this is the type to be
-  /// be printed.  When tree printing is selected, this type will show up first
-  /// in the tree.
-  QualType FromType;
-
-  /// ToType - The type that FromType is compared to.  Only in tree printing
-  /// will this type be outputed.
-  QualType ToType;
+  /// FromTemplateType - When single type printing is selected, this is the
+  /// type to be be printed.  When tree printing is selected, this type will
+  /// show up first in the tree.
+  QualType FromTemplateType;
+
+  /// ToTemplateType - The type that FromType is compared to.  Only in tree
+  /// printing will this type be outputed.
+  QualType ToTemplateType;
 
   /// OS - The stream used to construct the output strings.
   raw_ostream &OS;
@@ -491,82 +491,70 @@ class TemplateDiff {
   /// DiffTree - A tree representation the differences between two types.
   class DiffTree {
   public:
-    /// DiffKind - The difference in a DiffNode and which fields are used.
+    /// DiffKind - The difference in a DiffNode.  Fields of
+    /// TemplateArgumentInfo needed by each difference can be found in the
+    /// Set* and Get* functions.
     enum DiffKind {
       /// Incomplete or invalid node.
       Invalid,
-      /// Another level of templates, uses TemplateDecl and Qualifiers
+      /// Another level of templates, requires that
       Template,
-      /// Type difference, uses QualType
+      /// Type difference, all type differences except those falling under
+      /// the Template difference.
       Type,
-      /// Expression difference, uses Expr
+      /// Expression difference, this is only when both arguments are
+      /// expressions.  If one argument is an expression and the other is
+      /// Integer or Declaration, then use that diff type instead.
       Expression,
-      /// Template argument difference, uses TemplateDecl
+      /// Template argument difference
       TemplateTemplate,
-      /// Integer difference, uses APSInt and Expr
+      /// Integer difference
       Integer,
-      /// Declaration difference, uses ValueDecl
-      Declaration
+      /// Declaration difference, nullptr arguments are included here
+      Declaration,
+      /// One argument being integer and the other being declaration
+      FromIntegerAndToDeclaration,
+      FromDeclarationAndToInteger
     };
+
   private:
+    /// TemplateArgumentInfo - All the information needed to pretty print
+    /// a template argument.  See the Set* and Get* functions to see which
+    /// fields are used for each DiffKind.
+    struct TemplateArgumentInfo {
+      QualType ArgType;
+      Qualifiers Qual;
+      llvm::APSInt Val;
+      bool IsValidInt = false;
+      Expr *ArgExpr = nullptr;
+      TemplateDecl *TD = nullptr;
+      ValueDecl *VD = nullptr;
+      bool NeedAddressOf = false;
+      bool IsNullPtr = false;
+      bool IsDefault = false;
+    };
+
     /// DiffNode - The root node stores the original type.  Each child node
     /// stores template arguments of their parents.  For templated types, the
     /// template decl is also stored.
     struct DiffNode {
-      DiffKind Kind;
+      DiffKind Kind = Invalid;
 
       /// NextNode - The index of the next sibling node or 0.
-      unsigned NextNode;
+      unsigned NextNode = 0;
 
       /// ChildNode - The index of the first child node or 0.
-      unsigned ChildNode;
+      unsigned ChildNode = 0;
 
       /// ParentNode - The index of the parent node.
-      unsigned ParentNode;
-
-      /// FromType, ToType - The type arguments.
-      QualType FromType, ToType;
-
-      /// FromExpr, ToExpr - The expression arguments.
-      Expr *FromExpr, *ToExpr;
-
-      /// FromNullPtr, ToNullPtr - If the template argument is a nullptr
-      bool FromNullPtr, ToNullPtr;
-
-      /// FromTD, ToTD - The template decl for template template
-      /// arguments or the type arguments that are templates.
-      TemplateDecl *FromTD, *ToTD;
+      unsigned ParentNode = 0;
 
-      /// FromQual, ToQual - Qualifiers for template types.
-      Qualifiers FromQual, ToQual;
-
-      /// FromInt, ToInt - APSInt's for integral arguments.
-      llvm::APSInt FromInt, ToInt;
-
-      /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid.
-      bool IsValidFromInt, IsValidToInt;
-
-      /// FromValueDecl, ToValueDecl - Whether the argument is a decl.
-      ValueDecl *FromValueDecl, *ToValueDecl;
-
-      /// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of
-      /// operator before it.
-      bool FromAddressOf, ToAddressOf;
-
-      /// FromDefault, ToDefault - Whether the argument is a default argument.
-      bool FromDefault, ToDefault;
+      TemplateArgumentInfo FromArgInfo, ToArgInfo;
 
       /// Same - Whether the two arguments evaluate to the same value.
-      bool Same;
+      bool Same = false;
 
-      DiffNode(unsigned ParentNode = 0)
-        : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode),
-          FromType(), ToType(), FromExpr(nullptr), ToExpr(nullptr),
-          FromNullPtr(false), ToNullPtr(false),
-          FromTD(nullptr), ToTD(nullptr), IsValidFromInt(false),
-          IsValidToInt(false), FromValueDecl(nullptr), ToValueDecl(nullptr),
-          FromAddressOf(false), ToAddressOf(false), FromDefault(false),
-          ToDefault(false), Same(false) {}
+      DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {}
     };
 
     /// FlatTree - A flattened tree used to store the DiffNodes.
@@ -581,54 +569,127 @@ class TemplateDiff {
 
     /// ReadNode - The index of the current node being read.
     unsigned ReadNode;
-  
+
   public:
     DiffTree() :
         CurrentNode(0), NextFreeNode(1) {
       FlatTree.push_back(DiffNode());
     }
 
-    // Node writing functions.
-    /// SetNode - Sets FromTD and ToTD of the current node.
-    void SetNode(TemplateDecl *FromTD, TemplateDecl *ToTD) {
-      FlatTree[CurrentNode].FromTD = FromTD;
-      FlatTree[CurrentNode].ToTD = ToTD;
-    }
-
-    /// SetNode - Sets FromType and ToType of the current node.
-    void SetNode(QualType FromType, QualType ToType) {
-      FlatTree[CurrentNode].FromType = FromType;
-      FlatTree[CurrentNode].ToType = ToType;
-    }
-
-    /// SetNode - Set FromExpr and ToExpr of the current node.
-    void SetNode(Expr *FromExpr, Expr *ToExpr) {
-      FlatTree[CurrentNode].FromExpr = FromExpr;
-      FlatTree[CurrentNode].ToExpr = ToExpr;
-    }
-
-    /// SetNode - Set FromInt and ToInt of the current node.
-    void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt,
-                 bool IsValidFromInt, bool IsValidToInt) {
-      FlatTree[CurrentNode].FromInt = FromInt;
-      FlatTree[CurrentNode].ToInt = ToInt;
-      FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt;
-      FlatTree[CurrentNode].IsValidToInt = IsValidToInt;
-    }
-
-    /// SetNode - Set FromQual and ToQual of the current node.
-    void SetNode(Qualifiers FromQual, Qualifiers ToQual) {
-      FlatTree[CurrentNode].FromQual = FromQual;
-      FlatTree[CurrentNode].ToQual = ToQual;
-    }
-
-    /// SetNode - Set FromValueDecl and ToValueDecl of the current node.
-    void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
-                 bool FromAddressOf, bool ToAddressOf) {
-      FlatTree[CurrentNode].FromValueDecl = FromValueDecl;
-      FlatTree[CurrentNode].ToValueDecl = ToValueDecl;
-      FlatTree[CurrentNode].FromAddressOf = FromAddressOf;
-      FlatTree[CurrentNode].ToAddressOf = ToAddressOf;
+    // Node writing functions, one for each valid DiffKind element.
+    void SetTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,
+                         Qualifiers FromQual, Qualifiers ToQual,
+                         bool FromDefault, bool ToDefault) {
+      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
+      FlatTree[CurrentNode].Kind = Template;
+      FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
+      FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
+      FlatTree[CurrentNode].FromArgInfo.Qual = FromQual;
+      FlatTree[CurrentNode].ToArgInfo.Qual = ToQual;
+      SetDefault(FromDefault, ToDefault);
+    }
+
+    void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault,
+                     bool ToDefault) {
+      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
+      FlatTree[CurrentNode].Kind = Type;
+      FlatTree[CurrentNode].FromArgInfo.ArgType = FromType;
+      FlatTree[CurrentNode].ToArgInfo.ArgType = ToType;
+      SetDefault(FromDefault, ToDefault);
+    }
+
+    void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault,
+                           bool ToDefault) {
+      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
+      FlatTree[CurrentNode].Kind = Expression;
+      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
+      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
+      SetDefault(FromDefault, ToDefault);
+    }
+
+    void SetTemplateTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,
+                                 bool FromDefault, bool ToDefault) {
+      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
+      FlatTree[CurrentNode].Kind = TemplateTemplate;
+      FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
+      FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
+      SetDefault(FromDefault, ToDefault);
+    }
+
+    void SetIntegerDiff(llvm::APSInt FromInt, llvm::APSInt ToInt,
+                        bool IsValidFromInt, bool IsValidToInt,
+                        QualType FromIntType, QualType ToIntType,
+                        Expr *FromExpr, Expr *ToExpr, bool FromDefault,
+                        bool ToDefault) {
+      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
+      FlatTree[CurrentNode].Kind = Integer;
+      FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
+      FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
+      FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
+      FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
+      FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
+      FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
+      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
+      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
+      SetDefault(FromDefault, ToDefault);
+    }
+
+    void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
+                            bool FromAddressOf, bool ToAddressOf,
+                            bool FromNullPtr, bool ToNullPtr, Expr *FromExpr,
+                            Expr *ToExpr, bool FromDefault, bool ToDefault) {
+      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
+      FlatTree[CurrentNode].Kind = Declaration;
+      FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
+      FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
+      FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
+      FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
+      FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
+      FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
+      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
+      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
+      SetDefault(FromDefault, ToDefault);
+    }
+
+    void SetFromDeclarationAndToIntegerDiff(
+        ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr,
+        Expr *FromExpr, llvm::APSInt ToInt, bool IsValidToInt,
+        QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) {
+      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
+      FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger;
+      FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
+      FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
+      FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
+      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
+      FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
+      FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
+      FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
+      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
+      SetDefault(FromDefault, ToDefault);
+    }
+
+    void SetFromIntegerAndToDeclarationDiff(
+        llvm::APSInt FromInt, bool IsValidFromInt, QualType FromIntType,
+        Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf,
+        bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) {
+      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
+      FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration;
+      FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
+      FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
+      FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
+      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
+      FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
+      FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
+      FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
+      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
+      SetDefault(FromDefault, ToDefault);
+    }
+
+    /// SetDefault - Sets FromDefault and ToDefault flags of the current node.
+    void SetDefault(bool FromDefault, bool ToDefault) {
+      assert((!FromDefault || !ToDefault) && "Both arguments cannot be default.");
+      FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault;
+      FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault;
     }
 
     /// SetSame - Sets the same flag of the current node.
@@ -636,18 +697,6 @@ class TemplateDiff {
       FlatTree[CurrentNode].Same = Same;
     }
 
-    /// SetNullPtr - Sets the NullPtr flags of the current node.
-    void SetNullPtr(bool FromNullPtr, bool ToNullPtr) {
-      FlatTree[CurrentNode].FromNullPtr = FromNullPtr;
-      FlatTree[CurrentNode].ToNullPtr = ToNullPtr;
-    }
-
-    /// SetDefault - Sets FromDefault and ToDefault flags of the current node.
-    void SetDefault(bool FromDefault, bool ToDefault) {
-      FlatTree[CurrentNode].FromDefault = FromDefault;
-      FlatTree[CurrentNode].ToDefault = ToDefault;
-    }
-
     /// SetKind - Sets the current node's type.
     void SetKind(DiffKind Kind) {
       FlatTree[CurrentNode].Kind = Kind;
@@ -655,12 +704,16 @@ class TemplateDiff {
 
     /// Up - Changes the node to the parent of the current node.
     void Up() {
+      assert(FlatTree[CurrentNode].Kind != Invalid &&
+             "Cannot exit node before setting node information.");
       CurrentNode = FlatTree[CurrentNode].ParentNode;
     }
 
     /// AddNode - Adds a child node to the current node, then sets that node
     /// node as the current node.
     void AddNode() {
+      assert(FlatTree[CurrentNode].Kind == Template &&
+             "Only Template nodes can have children nodes.");
       FlatTree.push_back(DiffNode(CurrentNode));
       DiffNode &Node = FlatTree[CurrentNode];
       if (Node.ChildNode == 0) {
@@ -692,46 +745,103 @@ class TemplateDiff {
       ReadNode = FlatTree[ReadNode].ParentNode;
     }
 
-    /// GetNode - Gets the FromType and ToType.
-    void GetNode(QualType &FromType, QualType &ToType) {
-      FromType = FlatTree[ReadNode].FromType;
-      ToType = FlatTree[ReadNode].ToType;
-    }
-
-    /// GetNode - Gets the FromExpr and ToExpr.
-    void GetNode(Expr *&FromExpr, Expr *&ToExpr) {
-      FromExpr = FlatTree[ReadNode].FromExpr;
-      ToExpr = FlatTree[ReadNode].ToExpr;
-    }
-
-    /// GetNode - Gets the FromTD and ToTD.
-    void GetNode(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {
-      FromTD = FlatTree[ReadNode].FromTD;
-      ToTD = FlatTree[ReadNode].ToTD;
-    }
-
-    /// GetNode - Gets the FromInt and ToInt.
-    void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
-                 bool &IsValidFromInt, bool &IsValidToInt) {
-      FromInt = FlatTree[ReadNode].FromInt;
-      ToInt = FlatTree[ReadNode].ToInt;
-      IsValidFromInt = FlatTree[ReadNode].IsValidFromInt;
-      IsValidToInt = FlatTree[ReadNode].IsValidToInt;
-    }
-
-    /// GetNode - Gets the FromQual and ToQual.
-    void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) {
-      FromQual = FlatTree[ReadNode].FromQual;
-      ToQual = FlatTree[ReadNode].ToQual;
-    }
-
-    /// GetNode - Gets the FromValueDecl and ToValueDecl.
-    void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
-                 bool &FromAddressOf, bool &ToAddressOf) {
-      FromValueDecl = FlatTree[ReadNode].FromValueDecl;
-      ToValueDecl = FlatTree[ReadNode].ToValueDecl;
-      FromAddressOf = FlatTree[ReadNode].FromAddressOf;
-      ToAddressOf = FlatTree[ReadNode].ToAddressOf;
+    void GetTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD,
+                         Qualifiers &FromQual, Qualifiers &ToQual) {
+      assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind.");
+      FromTD = FlatTree[ReadNode].FromArgInfo.TD;
+      ToTD = FlatTree[ReadNode].ToArgInfo.TD;
+      FromQual = FlatTree[ReadNode].FromArgInfo.Qual;
+      ToQual = FlatTree[ReadNode].ToArgInfo.Qual;
+    }
+
+    void GetTypeDiff(QualType &FromType, QualType &ToType) {
+      assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind");
+      FromType = FlatTree[ReadNode].FromArgInfo.ArgType;
+      ToType = FlatTree[ReadNode].ToArgInfo.ArgType;
+    }
+
+    void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) {
+      assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind");
+      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
+      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
+    }
+
+    void GetTemplateTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {
+      assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind.");
+      FromTD = FlatTree[ReadNode].FromArgInfo.TD;
+      ToTD = FlatTree[ReadNode].ToArgInfo.TD;
+    }
+
+    void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
+                        bool &IsValidFromInt, bool &IsValidToInt,
+                        QualType &FromIntType, QualType &ToIntType,
+                        Expr *&FromExpr, Expr *&ToExpr) {
+      assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind.");
+      FromInt = FlatTree[ReadNode].FromArgInfo.Val;
+      ToInt = FlatTree[ReadNode].ToArgInfo.Val;
+      IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
+      IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
+      FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
+      ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
+      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
+      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
+    }
+
+    void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
+                            bool &FromAddressOf, bool &ToAddressOf,
+                            bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr,
+                            Expr *&ToExpr) {
+      assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind.");
+      FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
+      ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
+      FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
+      ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
+      FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
+      ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
+      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
+      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
+    }
+
+    void GetFromDeclarationAndToIntegerDiff(
+        ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr,
+        Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt,
+        QualType &ToIntType, Expr *&ToExpr) {
+      assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger &&
+             "Unexpected kind.");
+      FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
+      FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
+      FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
+      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
+      ToInt = FlatTree[ReadNode].ToArgInfo.Val;
+      IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
+      ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
+      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
+    }
+
+    void GetFromIntegerAndToDeclarationDiff(
+        llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType,
+        Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf,
+        bool &ToNullPtr, Expr *&ToExpr) {
+      assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration &&
+             "Unexpected kind.");
+      FromInt = FlatTree[ReadNode].FromArgInfo.Val;
+      IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
+      FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
+      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
+      ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
+      ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
+      ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
+      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
+    }
+
+    /// FromDefault - Return true if the from argument is the default.
+    bool FromDefault() {
+      return FlatTree[ReadNode].FromArgInfo.IsDefault;
+    }
+
+    /// ToDefault - Return true if the to argument is the default.
+    bool ToDefault() {
+      return FlatTree[ReadNode].ToArgInfo.IsDefault;
     }
 
     /// NodeIsSame - Returns true the arguments are the same.
@@ -764,26 +874,6 @@ class TemplateDiff {
       return FlatTree[ReadNode].NextNode != 0;
     }
 
-    /// FromNullPtr - Returns true if the from argument is null.
-    bool FromNullPtr() {
-      return FlatTree[ReadNode].FromNullPtr;
-    }
-
-    /// ToNullPtr - Returns true if the to argument is null.
-    bool ToNullPtr() {
-      return FlatTree[ReadNode].ToNullPtr;
-    }
-
-    /// FromDefault - Return true if the from argument is the default.
-    bool FromDefault() {
-      return FlatTree[ReadNode].FromDefault;
-    }
-
-    /// ToDefault - Return true if the to argument is the default.
-    bool ToDefault() {
-      return FlatTree[ReadNode].ToDefault;
-    }
-
     /// Empty - Returns true if the tree has no information.
     bool Empty() {
       return GetKind() == Invalid;
@@ -797,102 +887,128 @@ class TemplateDiff {
 
   DiffTree Tree;
 
-  /// TSTiterator - an iterator that is used to enter a
-  /// TemplateSpecializationType and read TemplateArguments inside template
-  /// parameter packs in order with the rest of the TemplateArguments.
-  struct TSTiterator {
+  /// TSTiterator - a pair of iterators that walks the
+  /// TemplateSpecializationType and the desugared TemplateSpecializationType.
+  /// The deseguared TemplateArgument should provide the canonical argument
+  /// for comparisons.
+  class TSTiterator {
     typedef const TemplateArgument& reference;
     typedef const TemplateArgument* pointer;
 
-    /// TST - the template specialization whose arguments this iterator
-    /// traverse over.
-    const TemplateSpecializationType *TST;
-
-    /// DesugarTST - desugared template specialization used to extract
-    /// default argument information
-    const TemplateSpecializationType *DesugarTST;
-
-    /// Index - the index of the template argument in TST.
-    unsigned Index;
-
-    /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA
-    /// points to a TemplateArgument within a parameter pack.
-    TemplateArgument::pack_iterator CurrentTA;
-
-    /// EndTA - the end iterator of a parameter pack
-    TemplateArgument::pack_iterator EndTA;
+    /// InternalIterator - an iterator that is used to enter a
+    /// TemplateSpecializationType and read TemplateArguments inside template
+    /// parameter packs in order with the rest of the TemplateArguments.
+    struct InternalIterator {
+      /// TST - the template specialization whose arguments this iterator
+      /// traverse over.
+      const TemplateSpecializationType *TST;
+
+      /// Index - the index of the template argument in TST.
+      unsigned Index;
+
+      /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA
+      /// points to a TemplateArgument within a parameter pack.
+      TemplateArgument::pack_iterator CurrentTA;
+
+      /// EndTA - the end iterator of a parameter pack
+      TemplateArgument::pack_iterator EndTA;
+
+      /// InternalIterator - Constructs an iterator and sets it to the first
+      /// template argument.
+      InternalIterator(const TemplateSpecializationType *TST)
+          : TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) {
+        if (isEnd()) return;
+
+        // Set to first template argument.  If not a parameter pack, done.
+        TemplateArgument TA = TST->getArg(0);
+        if (TA.getKind() != TemplateArgument::Pack) return;
 
-    /// TSTiterator - Constructs an iterator and sets it to the first template
-    /// argument.
-    TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
-        : TST(TST),
-          DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())),
-          Index(0), CurrentTA(nullptr), EndTA(nullptr) {
-      if (isEnd()) return;
+        // Start looking into the parameter pack.
+        CurrentTA = TA.pack_begin();
+        EndTA = TA.pack_end();
 
-      // Set to first template argument.  If not a parameter pack, done.
-      TemplateArgument TA = TST->getArg(0);
-      if (TA.getKind() != TemplateArgument::Pack) return;
+        // Found a valid template argument.
+        if (CurrentTA != EndTA) return;
 
-      // Start looking into the parameter pack.
-      CurrentTA = TA.pack_begin();
-      EndTA = TA.pack_end();
+        // Parameter pack is empty, use the increment to get to a valid
+        // template argument.
+        ++(*this);
+      }
 
-      // Found a valid template argument.
-      if (CurrentTA != EndTA) return;
+      /// isEnd - Returns true if the iterator is one past the end.
+      bool isEnd() const {
+        return Index >= TST->getNumArgs();
+      }
 
-      // Parameter pack is empty, use the increment to get to a valid
-      // template argument.
-      ++(*this);
-    }
+      /// &operator++ - Increment the iterator to the next template argument.
+      InternalIterator &operator++() {
+        if (isEnd()) {
+          return *this;
+        }
 
-    /// isEnd - Returns true if the iterator is one past the end.
-    bool isEnd() const {
-      return Index >= TST->getNumArgs();
-    }
+        // If in a parameter pack, advance in the parameter pack.
+        if (CurrentTA != EndTA) {
+          ++CurrentTA;
+          if (CurrentTA != EndTA)
+            return *this;
+        }
 
-    /// &operator++ - Increment the iterator to the next template argument.
-    TSTiterator &operator++() {
-      // After the end, Index should be the default argument position in
-      // DesugarTST, if it exists.
-      if (isEnd()) {
-        ++Index;
+        // Loop until a template argument is found, or the end is reached.
+        while (true) {
+          // Advance to the next template argument.  Break if reached the end.
+          if (++Index == TST->getNumArgs())
+            break;
+
+          // If the TemplateArgument is not a parameter pack, done.
+          TemplateArgument TA = TST->getArg(Index);
+          if (TA.getKind() != TemplateArgument::Pack)
+            break;
+
+          // Handle parameter packs.
+          CurrentTA = TA.pack_begin();
+          EndTA = TA.pack_end();
+
+          // If the parameter pack is empty, try to advance again.
+          if (CurrentTA != EndTA)
+            break;
+        }
         return *this;
       }
 
-      // If in a parameter pack, advance in the parameter pack.
-      if (CurrentTA != EndTA) {
-        ++CurrentTA;
-        if (CurrentTA != EndTA)
-          return *this;
+      /// operator* - Returns the appropriate TemplateArgument.
+      reference operator*() const {
+        assert(!isEnd() && "Index exceeds number of arguments.");
+        if (CurrentTA == EndTA)
+          return TST->getArg(Index);
+        else
+          return *CurrentTA;
       }
 
-      // Loop until a template argument is found, or the end is reached.
-      while (true) {
-        // Advance to the next template argument.  Break if reached the end.
-        if (++Index == TST->getNumArgs()) break;
-
-        // If the TemplateArgument is not a parameter pack, done.
-        TemplateArgument TA = TST->getArg(Index);
-        if (TA.getKind() != TemplateArgument::Pack) break;
+      /// operator-> - Allow access to the underlying TemplateArgument.
+      pointer operator->() const {
+        return &operator*();
+      }
+    };
 
-        // Handle parameter packs.
-        CurrentTA = TA.pack_begin();
-        EndTA = TA.pack_end();
+    InternalIterator SugaredIterator;
+    InternalIterator DesugaredIterator;
 
-        // If the parameter pack is empty, try to advance again.
-        if (CurrentTA != EndTA) break;
-      }
+  public:
+    TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
+        : SugaredIterator(TST),
+          DesugaredIterator(
+              GetTemplateSpecializationType(Context, TST->desugar())) {}
+
+    /// &operator++ - Increment the iterator to the next template argument.
+    TSTiterator &operator++() {
+      ++SugaredIterator;
+      ++DesugaredIterator;
       return *this;
     }
 
     /// operator* - Returns the appropriate TemplateArgument.
     reference operator*() const {
-      assert(!isEnd() && "Index exceeds number of arguments.");
-      if (CurrentTA == EndTA)
-        return TST->getArg(Index);
-      else
-        return *CurrentTA;
+      return *SugaredIterator;
     }
 
     /// operator-> - Allow access to the underlying TemplateArgument.
@@ -900,16 +1016,27 @@ class TemplateDiff {
       return &operator*();
     }
 
-    /// getDesugar - Returns the deduced template argument from DesguarTST
-    reference getDesugar() const {
-      return DesugarTST->getArg(Index);
+    /// isEnd - Returns true if no more TemplateArguments are available.
+    bool isEnd() const {
+      return SugaredIterator.isEnd();
+    }
+
+    /// hasDesugaredTA - Returns true if there is another TemplateArgument
+    /// available.
+    bool hasDesugaredTA() const {
+      return !DesugaredIterator.isEnd();
+    }
+
+    /// getDesugaredTA - Returns the desugared TemplateArgument.
+    reference getDesugaredTA() const {
+      return *DesugaredIterator;
     }
   };
 
   // These functions build up the template diff tree, including functions to
-  // retrieve and compare template arguments. 
+  // retrieve and compare template arguments.
 
-  static const TemplateSpecializationType * GetTemplateSpecializationType(
+  static const TemplateSpecializationType *GetTemplateSpecializationType(
       ASTContext &Context, QualType Ty) {
     if (const TemplateSpecializationType *TST =
             Ty->getAs<TemplateSpecializationType>())
@@ -935,108 +1062,136 @@ class TemplateDiff {
     return Ty->getAs<TemplateSpecializationType>();
   }
 
-  /// DiffTypes - Fills a DiffNode with information about a type difference.
-  void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
-                 TemplateTypeParmDecl *FromDefaultTypeDecl,
-                 TemplateTypeParmDecl *ToDefaultTypeDecl) {
-    QualType FromType = GetType(FromIter, FromDefaultTypeDecl);
-    QualType ToType = GetType(ToIter, ToDefaultTypeDecl);
-
-    Tree.SetNode(FromType, ToType);
-    Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(),
-                    ToIter.isEnd() && !ToType.isNull());
-    Tree.SetKind(DiffTree::Type);
+  /// Returns true if the DiffType is Type and false for Template.
+  static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType,
+                                  QualType ToType,
+                                  const TemplateSpecializationType *&FromArgTST,
+                                  const TemplateSpecializationType *&ToArgTST) {
     if (FromType.isNull() || ToType.isNull())
-      return;
+      return true;
 
-    if (Context.hasSameType(FromType, ToType)) {
-      Tree.SetSame(true);
-      return;
-    }
+    if (Context.hasSameType(FromType, ToType))
+      return true;
 
-    const TemplateSpecializationType *FromArgTST =
-        GetTemplateSpecializationType(Context, FromType);
-    if (!FromArgTST)
-      return;
+    FromArgTST = GetTemplateSpecializationType(Context, FromType);
+    ToArgTST = GetTemplateSpecializationType(Context, ToType);
 
-    const TemplateSpecializationType *ToArgTST =
-        GetTemplateSpecializationType(Context, ToType);
-    if (!ToArgTST)
-      return;
+    if (!FromArgTST || !ToArgTST)
+      return true;
 
     if (!hasSameTemplate(FromArgTST, ToArgTST))
-      return;
+      return true;
 
-    Qualifiers FromQual = FromType.getQualifiers(),
-               ToQual = ToType.getQualifiers();
-    FromQual -= QualType(FromArgTST, 0).getQualifiers();
-    ToQual -= QualType(ToArgTST, 0).getQualifiers();
-    Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),
-                 ToArgTST->getTemplateName().getAsTemplateDecl());
-    Tree.SetNode(FromQual, ToQual);
-    Tree.SetKind(DiffTree::Template);
-    DiffTemplate(FromArgTST, ToArgTST);
+    return false;
+  }
+
+  /// DiffTypes - Fills a DiffNode with information about a type difference.
+  void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) {
+    QualType FromType = GetType(FromIter);
+    QualType ToType = GetType(ToIter);
+
+    bool FromDefault = FromIter.isEnd() && !FromType.isNull();
+    bool ToDefault = ToIter.isEnd() && !ToType.isNull();
+
+    const TemplateSpecializationType *FromArgTST = nullptr;
+    const TemplateSpecializationType *ToArgTST = nullptr;
+    if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) {
+      Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault);
+      Tree.SetSame(!FromType.isNull() && !ToType.isNull() &&
+                   Context.hasSameType(FromType, ToType));
+    } else {
+      assert(FromArgTST && ToArgTST &&
+             "Both template specializations need to be valid.");
+      Qualifiers FromQual = FromType.getQualifiers(),
+                 ToQual = ToType.getQualifiers();
+      FromQual -= QualType(FromArgTST, 0).getQualifiers();
+      ToQual -= QualType(ToArgTST, 0).getQualifiers();
+      Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(),
+                           ToArgTST->getTemplateName().getAsTemplateDecl(),
+                           FromQual, ToQual, FromDefault, ToDefault);
+      DiffTemplate(FromArgTST, ToArgTST);
+    }
   }
 
   /// DiffTemplateTemplates - Fills a DiffNode with information about a
   /// template template difference.
   void DiffTemplateTemplates(const TSTiterator &FromIter,
-                             const TSTiterator &ToIter,
-                             TemplateTemplateParmDecl *FromDefaultTemplateDecl,
-                             TemplateTemplateParmDecl *ToDefaultTemplateDecl) {
-    TemplateDecl *FromDecl = GetTemplateDecl(FromIter, FromDefaultTemplateDecl);
-    TemplateDecl *ToDecl = GetTemplateDecl(ToIter, ToDefaultTemplateDecl);
-    Tree.SetNode(FromDecl, ToDecl);
+                             const TSTiterator &ToIter) {
+    TemplateDecl *FromDecl = GetTemplateDecl(FromIter);
+    TemplateDecl *ToDecl = GetTemplateDecl(ToIter);
+    Tree.SetTemplateTemplateDiff(FromDecl, ToDecl, FromIter.isEnd() && FromDecl,
+                                 ToIter.isEnd() && ToDecl);
     Tree.SetSame(FromDecl && ToDecl &&
                  FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());
-    Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl);
-    Tree.SetKind(DiffTree::TemplateTemplate);
   }
 
   /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes
-  static void InitializeNonTypeDiffVariables(
-      ASTContext &Context, const TSTiterator &Iter,
-      NonTypeTemplateParmDecl *Default, bool &HasInt, bool &HasValueDecl,
-      bool &IsNullPtr, Expr *&E, llvm::APSInt &Value, ValueDecl *&VD) {
-    HasInt = !Iter.isEnd() && Iter->getKind() == TemplateArgument::Integral;
-
-    HasValueDecl =
-        !Iter.isEnd() && Iter->getKind() == TemplateArgument::Declaration;
-
-    IsNullPtr = !Iter.isEnd() && Iter->getKind() == TemplateArgument::NullPtr;
-
-    if (HasInt)
-      Value = Iter->getAsIntegral();
-    else if (HasValueDecl)
-      VD = Iter->getAsDecl();
-    else if (!IsNullPtr)
-      E = GetExpr(Iter, Default);
-
-    if (E && Default->getType()->isPointerType())
-      IsNullPtr = CheckForNullPtr(Context, E);
-  }
-
-  /// NeedsAddressOf - Helper function for DiffNonTypes.  Returns true if the
-  /// ValueDecl needs a '&' when printed.
-  static bool NeedsAddressOf(ValueDecl *VD, Expr *E,
-                             NonTypeTemplateParmDecl *Default) {
-    if (!VD)
-      return false;
-
-    if (E) {
-      if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParens())) {
-        if (UO->getOpcode() == UO_AddrOf) {
-          return true;
+  static void InitializeNonTypeDiffVariables(ASTContext &Context,
+                                             const TSTiterator &Iter,
+                                             NonTypeTemplateParmDecl *Default,
+                                             llvm::APSInt &Value, bool &HasInt,
+                                             QualType &IntType, bool &IsNullPtr,
+                                             Expr *&E, ValueDecl *&VD,
+                                             bool &NeedAddressOf) {
+    if (!Iter.isEnd()) {
+      switch (Iter->getKind()) {
+        default:
+          llvm_unreachable("unknown ArgumentKind");
+        case TemplateArgument::Integral:
+          Value = Iter->getAsIntegral();
+          HasInt = true;
+          IntType = Iter->getIntegralType();
+          return;
+        case TemplateArgument::Declaration: {
+          VD = Iter->getAsDecl();
+          QualType ArgType = Iter->getParamTypeForDecl();
+          QualType VDType = VD->getType();
+          if (ArgType->isPointerType() &&
+              Context.hasSameType(ArgType->getPointeeType(), VDType))
+            NeedAddressOf = true;
+          return;
         }
+        case TemplateArgument::NullPtr:
+          IsNullPtr = true;
+          return;
+        case TemplateArgument::Expression:
+          E = Iter->getAsExpr();
       }
-      return false;
+    } else if (!Default->isParameterPack()) {
+      E = Default->getDefaultArgument();
     }
 
-    if (!Default->getType()->isReferenceType()) {
-      return true;
-    }
+    if (!Iter.hasDesugaredTA()) return;
 
-    return false;
+    const TemplateArgument& TA = Iter.getDesugaredTA();
+    switch (TA.getKind()) {
+      default:
+        llvm_unreachable("unknown ArgumentKind");
+      case TemplateArgument::Integral:
+        Value = TA.getAsIntegral();
+        HasInt = true;
+        IntType = TA.getIntegralType();
+        return;
+      case TemplateArgument::Declaration: {
+        VD = TA.getAsDecl();
+        QualType ArgType = TA.getParamTypeForDecl();
+        QualType VDType = VD->getType();
+        if (ArgType->isPointerType() &&
+            Context.hasSameType(ArgType->getPointeeType(), VDType))
+          NeedAddressOf = true;
+        return;
+      }
+      case TemplateArgument::NullPtr:
+        IsNullPtr = true;
+        return;
+      case TemplateArgument::Expression:
+        // TODO: Sometimes, the desugared template argument Expr differs from
+        // the sugared template argument Expr.  It may be useful in the future
+        // but for now, it is just discarded.
+        if (!E)
+          E = TA.getAsExpr();
+        return;
+    }
   }
 
   /// DiffNonTypes - Handles any template parameters not handled by DiffTypes
@@ -1046,85 +1201,68 @@ class TemplateDiff {
                     NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) {
     Expr *FromExpr = nullptr, *ToExpr = nullptr;
     llvm::APSInt FromInt, ToInt;
+    QualType FromIntType, ToIntType;
     ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
-    bool HasFromInt = false, HasToInt = false, HasFromValueDecl = false,
-         HasToValueDecl = false, FromNullPtr = false, ToNullPtr = false;
-    InitializeNonTypeDiffVariables(Context, FromIter, FromDefaultNonTypeDecl,
-                                     HasFromInt, HasFromValueDecl, FromNullPtr,
-                                     FromExpr, FromInt, FromValueDecl);
-    InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl,
-                                     HasToInt, HasToValueDecl, ToNullPtr,
-                                     ToExpr, ToInt, ToValueDecl);
-
-    assert(((!HasFromInt && !HasToInt) ||
-            (!HasFromValueDecl && !HasToValueDecl)) &&
-           "Template argument cannot be both integer and declaration");
-
-    if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) {
-      Tree.SetNode(FromExpr, ToExpr);
-      Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr);
-      if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType()) {
-        if (FromExpr)
-          HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt,
-                              FromDefaultNonTypeDecl->getType());
-        if (ToExpr)
-          HasToInt = GetInt(Context, ToIter, ToExpr, ToInt,
-                            ToDefaultNonTypeDecl->getType());
-      }
-      if (HasFromInt && HasToInt) {
-        Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
-        Tree.SetSame(FromInt == ToInt);
-        Tree.SetKind(DiffTree::Integer);
-      } else if (HasFromInt || HasToInt) {
-        Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
-        Tree.SetSame(false);
-        Tree.SetKind(DiffTree::Integer);
-      } else {
-        Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr) ||
-                     (FromNullPtr && ToNullPtr));
-        Tree.SetNullPtr(FromNullPtr, ToNullPtr);
-        Tree.SetKind(DiffTree::Expression);
-      }
+    bool HasFromInt = false, HasToInt = false, FromNullPtr = false,
+         ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;
+    InitializeNonTypeDiffVariables(
+        Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt,
+        FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf);
+    InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt,
+                                   HasToInt, ToIntType, ToNullPtr, ToExpr,
+                                   ToValueDecl, NeedToAddressOf);
+
+    bool FromDefault = FromIter.isEnd() &&
+                       (FromExpr || FromValueDecl || HasFromInt || FromNullPtr);
+    bool ToDefault = ToIter.isEnd() &&
+                     (ToExpr || ToValueDecl || HasToInt || ToNullPtr);
+
+    bool FromDeclaration = FromValueDecl || FromNullPtr;
+    bool ToDeclaration = ToValueDecl || ToNullPtr;
+
+    if (FromDeclaration && HasToInt) {
+      Tree.SetFromDeclarationAndToIntegerDiff(
+          FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt,
+          HasToInt, ToIntType, ToExpr, FromDefault, ToDefault);
+      Tree.SetSame(false);
+      return;
+
+    }
+
+    if (HasFromInt && ToDeclaration) {
+      Tree.SetFromIntegerAndToDeclarationDiff(
+          FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl,
+          NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault);
+      Tree.SetSame(false);
       return;
     }
 
     if (HasFromInt || HasToInt) {
-      if (!HasFromInt && FromExpr)
-        HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt,
-                            FromDefaultNonTypeDecl->getType());
-      if (!HasToInt && ToExpr)
-        HasToInt = GetInt(Context, ToIter, ToExpr, ToInt,
-                          ToDefaultNonTypeDecl->getType());
-      Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
+      Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,
+                          ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);
       if (HasFromInt && HasToInt) {
-        Tree.SetSame(FromInt == ToInt);
-      } else {
-        Tree.SetSame(false);
+        Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) &&
+                     FromInt == ToInt);
       }
-      Tree.SetDefault(FromIter.isEnd() && HasFromInt,
-                      ToIter.isEnd() && HasToInt);
-      Tree.SetKind(DiffTree::Integer);
       return;
     }
 
-    if (!HasFromValueDecl && FromExpr)
-      FromValueDecl = GetValueDecl(FromIter, FromExpr);
-    if (!HasToValueDecl && ToExpr)
-      ToValueDecl = GetValueDecl(ToIter, ToExpr);
-
-    bool FromAddressOf =
-        NeedsAddressOf(FromValueDecl, FromExpr, FromDefaultNonTypeDecl);
-    bool ToAddressOf =
-        NeedsAddressOf(ToValueDecl, ToExpr, ToDefaultNonTypeDecl);
-
-    Tree.SetNullPtr(FromNullPtr, ToNullPtr);
-    Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
-    Tree.SetSame(FromValueDecl && ToValueDecl &&
-                 FromValueDecl->getCanonicalDecl() ==
-                     ToValueDecl->getCanonicalDecl());
-    Tree.SetDefault(FromIter.isEnd() && FromValueDecl,
-                    ToIter.isEnd() && ToValueDecl);
-    Tree.SetKind(DiffTree::Declaration);
+    if (FromDeclaration || ToDeclaration) {
+      Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf,
+                              NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
+                              ToExpr, FromDefault, ToDefault);
+      bool BothNull = FromNullPtr && ToNullPtr;
+      bool SameValueDecl =
+          FromValueDecl && ToValueDecl &&
+          NeedFromAddressOf == NeedToAddressOf &&
+          FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl();
+      Tree.SetSame(BothNull || SameValueDecl);
+      return;
+    }
+
+    assert((FromExpr || ToExpr) && "Both template arguments cannot be empty.");
+    Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault);
+    Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
   }
 
   /// DiffTemplate - recursively visits template arguments and stores the
@@ -1149,28 +1287,23 @@ class TemplateDiff {
       NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex);
       NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex);
 
-      TemplateTypeParmDecl *FromDefaultTypeDecl =
-          dyn_cast<TemplateTypeParmDecl>(FromParamND);
-      TemplateTypeParmDecl *ToDefaultTypeDecl =
-          dyn_cast<TemplateTypeParmDecl>(ToParamND);
-      if (FromDefaultTypeDecl && ToDefaultTypeDecl)
-        DiffTypes(FromIter, ToIter, FromDefaultTypeDecl, ToDefaultTypeDecl);
-
-      TemplateTemplateParmDecl *FromDefaultTemplateDecl =
-          dyn_cast<TemplateTemplateParmDecl>(FromParamND);
-      TemplateTemplateParmDecl *ToDefaultTemplateDecl =
-          dyn_cast<TemplateTemplateParmDecl>(ToParamND);
-      if (FromDefaultTemplateDecl && ToDefaultTemplateDecl)
-        DiffTemplateTemplates(FromIter, ToIter, FromDefaultTemplateDecl,
-                              ToDefaultTemplateDecl);
-
-      NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =
-          dyn_cast<NonTypeTemplateParmDecl>(FromParamND);
-      NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =
-          dyn_cast<NonTypeTemplateParmDecl>(ToParamND);
-      if (FromDefaultNonTypeDecl && ToDefaultNonTypeDecl)
+      assert(FromParamND->getKind() == ToParamND->getKind() &&
+             "Parameter Decl are not the same kind.");
+
+      if (isa<TemplateTypeParmDecl>(FromParamND)) {
+        DiffTypes(FromIter, ToIter);
+      } else if (isa<TemplateTemplateParmDecl>(FromParamND)) {
+        DiffTemplateTemplates(FromIter, ToIter);
+      } else if (isa<NonTypeTemplateParmDecl>(FromParamND)) {
+        NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =
+            cast<NonTypeTemplateParmDecl>(FromParamND);
+        NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =
+            cast<NonTypeTemplateParmDecl>(ToParamND);
         DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,
                      ToDefaultNonTypeDecl);
+      } else {
+        llvm_unreachable("Unexpected Decl type.");
+      }
 
       ++FromIter;
       ++ToIter;
@@ -1239,140 +1372,27 @@ class TemplateDiff {
 
   /// GetType - Retrieves the template type arguments, including default
   /// arguments.
-  static QualType GetType(const TSTiterator &Iter,
-                          TemplateTypeParmDecl *DefaultTTPD) {
-    bool isVariadic = DefaultTTPD->isParameterPack();
-
+  static QualType GetType(const TSTiterator &Iter) {
     if (!Iter.isEnd())
       return Iter->getAsType();
-    if (isVariadic)
-      return QualType();
-
-    QualType ArgType = DefaultTTPD->getDefaultArgument();
-    if (ArgType->isDependentType())
-      return Iter.getDesugar().getAsType();
-
-    return ArgType;
-  }
-
-  /// GetExpr - Retrieves the template expression argument, including default
-  /// arguments.
-  static Expr *GetExpr(const TSTiterator &Iter,
-                       NonTypeTemplateParmDecl *DefaultNTTPD) {
-    Expr *ArgExpr = nullptr;
-    bool isVariadic = DefaultNTTPD->isParameterPack();
-
-    if (!Iter.isEnd())
-      ArgExpr = Iter->getAsExpr();
-    else if (!isVariadic)
-      ArgExpr = DefaultNTTPD->getDefaultArgument();
-
-    if (ArgExpr)
-      while (SubstNonTypeTemplateParmExpr *SNTTPE =
-                 dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr))
-        ArgExpr = SNTTPE->getReplacement();
-
-    return ArgExpr;
-  }
-
-  /// GetInt - Retrieves the template integer argument, including evaluating
-  /// default arguments.  If the value comes from an expression, extend the
-  /// APSInt to size of IntegerType to match the behavior in
-  /// Sema::CheckTemplateArgument
-  static bool GetInt(ASTContext &Context, const TSTiterator &Iter,
-                     Expr *ArgExpr, llvm::APSInt &Int, QualType IntegerType) {
-    // Default, value-depenedent expressions require fetching
-    // from the desugared TemplateArgument, otherwise expression needs to
-    // be evaluatable.
-    if (Iter.isEnd() && ArgExpr->isValueDependent()) {
-      switch (Iter.getDesugar().getKind()) {
-        case TemplateArgument::Integral:
-          Int = Iter.getDesugar().getAsIntegral();
-          return true;
-        case TemplateArgument::Expression:
-          ArgExpr = Iter.getDesugar().getAsExpr();
-          Int = ArgExpr->EvaluateKnownConstInt(Context);
-          Int = Int.extOrTrunc(Context.getTypeSize(IntegerType));
-          return true;
-        default:
-          llvm_unreachable("Unexpected template argument kind");
-      }
-    } else if (ArgExpr->isEvaluatable(Context)) {
-      Int = ArgExpr->EvaluateKnownConstInt(Context);
-      Int = Int.extOrTrunc(Context.getTypeSize(IntegerType));
-      return true;
-    }
-
-    return false;
-  }
-
-  /// GetValueDecl - Retrieves the template Decl argument, including
-  /// default expression argument.
-  static ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
-    // Default, value-depenedent expressions require fetching
-    // from the desugared TemplateArgument
-    if (Iter.isEnd() && ArgExpr->isValueDependent())
-      switch (Iter.getDesugar().getKind()) {
-        case TemplateArgument::Declaration:
-          return Iter.getDesugar().getAsDecl();
-        case TemplateArgument::Expression:
-          ArgExpr = Iter.getDesugar().getAsExpr();
-          return cast<DeclRefExpr>(ArgExpr)->getDecl();
-        default:
-          llvm_unreachable("Unexpected template argument kind");
-      }
-    DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr);
-    if (!DRE) {
-      UnaryOperator *UO = dyn_cast<UnaryOperator>(ArgExpr->IgnoreParens());
-      if (!UO)
-        return nullptr;
-      DRE = cast<DeclRefExpr>(UO->getSubExpr());
-    }
-
-    return DRE->getDecl();
-  }
-
-  /// CheckForNullPtr - returns true if the expression can be evaluated as
-  /// a null pointer
-  static bool CheckForNullPtr(ASTContext &Context, Expr *E) {
-    assert(E && "Expected expression");
-
-    E = E->IgnoreParenCasts();
-    if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
-      return true;
-
-    DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
-    if (!DRE)
-      return false;
-
-    VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
-    if (!VD || !VD->hasInit())
-      return false;
-
-    return VD->getInit()->IgnoreParenCasts()->isNullPointerConstant(
-        Context, Expr::NPC_ValueDependentIsNull);
+    if (Iter.hasDesugaredTA())
+      return Iter.getDesugaredTA().getAsType();
+    return QualType();
   }
 
   /// GetTemplateDecl - Retrieves the template template arguments, including
   /// default arguments.
-  static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter,
-                                TemplateTemplateParmDecl *DefaultTTPD) {
-    bool isVariadic = DefaultTTPD->isParameterPack();
-
-    TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument();
-    TemplateDecl *DefaultTD = nullptr;
-    if (TA.getKind() != TemplateArgument::Null)
-      DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
-
+  static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) {
     if (!Iter.isEnd())
       return Iter->getAsTemplate().getAsTemplateDecl();
-    if (!isVariadic)
-      return DefaultTD;
-
+    if (Iter.hasDesugaredTA())
+      return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl();
     return nullptr;
   }
 
-  /// IsEqualExpr - Returns true if the expressions evaluate to the same value.
+  /// IsEqualExpr - Returns true if the expressions are the same in regards to
+  /// template arguments.  These expressions are dependent, so profile them
+  /// instead of trying to evaluate them.
   static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {
     if (FromExpr == ToExpr)
       return true;
@@ -1380,47 +1400,10 @@ class TemplateDiff {
     if (!FromExpr || !ToExpr)
       return false;
 
-    DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr->IgnoreParens()),
-                *ToDRE = dyn_cast<DeclRefExpr>(ToExpr->IgnoreParens());
-
-    if (FromDRE || ToDRE) {
-      if (!FromDRE || !ToDRE)
-        return false;
-      return FromDRE->getDecl() == ToDRE->getDecl();
-    }
-
-    Expr::EvalResult FromResult, ToResult;
-    if (!FromExpr->EvaluateAsRValue(FromResult, Context) ||
-        !ToExpr->EvaluateAsRValue(ToResult, Context)) {
-      llvm::FoldingSetNodeID FromID, ToID;
-      FromExpr->Profile(FromID, Context, true);
-      ToExpr->Profile(ToID, Context, true);
-      return FromID == ToID;
-    }
-
-    APValue &FromVal = FromResult.Val;
-    APValue &ToVal = ToResult.Val;
-
-    if (FromVal.getKind() != ToVal.getKind()) return false;
-
-    switch (FromVal.getKind()) {
-      case APValue::Int:
-        return FromVal.getInt() == ToVal.getInt();
-      case APValue::LValue: {
-        APValue::LValueBase FromBase = FromVal.getLValueBase();
-        APValue::LValueBase ToBase = ToVal.getLValueBase();
-        if (FromBase.isNull() && ToBase.isNull())
-          return true;
-        if (FromBase.isNull() || ToBase.isNull())
-          return false;
-        return FromBase.get<const ValueDecl*>() ==
-               ToBase.get<const ValueDecl*>();
-      }
-      case APValue::MemberPointer:
-        return FromVal.getMemberPointerDecl() == ToVal.getMemberPointerDecl();
-      default:
-        llvm_unreachable("Unknown template argument expression.");
-    }
+    llvm::FoldingSetNodeID FromID, ToID;
+    FromExpr->Profile(FromID, Context, true);
+    ToExpr->Profile(ToID, Context, true);
+    return FromID == ToID;
   }
 
   // These functions converts the tree representation of the template
@@ -1442,21 +1425,21 @@ class TemplateDiff {
         llvm_unreachable("Template diffing failed with bad DiffNode");
       case DiffTree::Type: {
         QualType FromType, ToType;
-        Tree.GetNode(FromType, ToType);
+        Tree.GetTypeDiff(FromType, ToType);
         PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),
                        Tree.NodeIsSame());
         return;
       }
       case DiffTree::Expression: {
         Expr *FromExpr, *ToExpr;
-        Tree.GetNode(FromExpr, ToExpr);
-        PrintExpr(FromExpr, ToExpr, Tree.FromNullPtr(), Tree.ToNullPtr(),
-                  Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
+        Tree.GetExpressionDiff(FromExpr, ToExpr);
+        PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
+                  Tree.NodeIsSame());
         return;
       }
       case DiffTree::TemplateTemplate: {
         TemplateDecl *FromTD, *ToTD;
-        Tree.GetNode(FromTD, ToTD);
+        Tree.GetTemplateTemplateDiff(FromTD, ToTD);
         PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),
                               Tree.ToDefault(), Tree.NodeIsSame());
         return;
@@ -1465,26 +1448,70 @@ class TemplateDiff {
         llvm::APSInt FromInt, ToInt;
         Expr *FromExpr, *ToExpr;
         bool IsValidFromInt, IsValidToInt;
-        Tree.GetNode(FromExpr, ToExpr);
-        Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt);
-        PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt,
-                    FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
-                    Tree.NodeIsSame());
+        QualType FromIntType, ToIntType;
+        Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,
+                            FromIntType, ToIntType, FromExpr, ToExpr);
+        PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,
+                    ToIntType, FromExpr, ToExpr, Tree.FromDefault(),
+                    Tree.ToDefault(), Tree.NodeIsSame());
         return;
       }
       case DiffTree::Declaration: {
         ValueDecl *FromValueDecl, *ToValueDecl;
         bool FromAddressOf, ToAddressOf;
-        Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
+        bool FromNullPtr, ToNullPtr;
+        Expr *FromExpr, *ToExpr;
+        Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf,
+                                ToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
+                                ToExpr);
         PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
-                       Tree.FromNullPtr(), Tree.ToNullPtr(), Tree.FromDefault(),
-                       Tree.ToDefault(), Tree.NodeIsSame());
+                       FromNullPtr, ToNullPtr, FromExpr, ToExpr,
+                       Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
+        return;
+      }
+      case DiffTree::FromDeclarationAndToInteger: {
+        ValueDecl *FromValueDecl;
+        bool FromAddressOf;
+        bool FromNullPtr;
+        Expr *FromExpr;
+        llvm::APSInt ToInt;
+        bool IsValidToInt;
+        QualType ToIntType;
+        Expr *ToExpr;
+        Tree.GetFromDeclarationAndToIntegerDiff(
+            FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt,
+            IsValidToInt, ToIntType, ToExpr);
+        assert((FromValueDecl || FromNullPtr) && IsValidToInt);
+        PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr,
+                                 FromExpr, Tree.FromDefault(), ToInt, ToIntType,
+                                 ToExpr, Tree.ToDefault());
+        return;
+      }
+      case DiffTree::FromIntegerAndToDeclaration: {
+        llvm::APSInt FromInt;
+        bool IsValidFromInt;
+        QualType FromIntType;
+        Expr *FromExpr;
+        ValueDecl *ToValueDecl;
+        bool ToAddressOf;
+        bool ToNullPtr;
+        Expr *ToExpr;
+        Tree.GetFromIntegerAndToDeclarationDiff(
+            FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl,
+            ToAddressOf, ToNullPtr, ToExpr);
+        assert(IsValidFromInt && (ToValueDecl || ToNullPtr));
+        PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr,
+                                 Tree.FromDefault(), ToValueDecl, ToAddressOf,
+                                 ToNullPtr, ToExpr, Tree.ToDefault());
         return;
       }
       case DiffTree::Template: {
         // Node is root of template.  Recurse on children.
         TemplateDecl *FromTD, *ToTD;
-        Tree.GetNode(FromTD, ToTD);
+        Qualifiers FromQual, ToQual;
+        Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual);
+
+        PrintQualifiers(FromQual, ToQual);
 
         if (!Tree.HasChildren()) {
           // If we're dealing with a template specialization with zero
@@ -1493,11 +1520,7 @@ class TemplateDiff {
           return;
         }
 
-        Qualifiers FromQual, ToQual;
-        Tree.GetNode(FromQual, ToQual);
-        PrintQualifiers(FromQual, ToQual);
-
-        OS << FromTD->getNameAsString() << '<'; 
+        OS << FromTD->getNameAsString() << '<';
         Tree.MoveToChild();
         unsigned NumElideArgs = 0;
         do {
@@ -1604,40 +1627,36 @@ class TemplateDiff {
 
   /// PrintExpr - Prints out the expr template arguments, highlighting argument
   /// differences.
-  void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromNullPtr,
-                 bool ToNullPtr, bool FromDefault, bool ToDefault, bool Same) {
+  void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault,
+                 bool ToDefault, bool Same) {
     assert((FromExpr || ToExpr) &&
             "Only one template argument may be missing.");
     if (Same) {
-      PrintExpr(FromExpr, FromNullPtr);
+      PrintExpr(FromExpr);
     } else if (!PrintTree) {
       OS << (FromDefault ? "(default) " : "");
       Bold();
-      PrintExpr(FromExpr, FromNullPtr);
+      PrintExpr(FromExpr);
       Unbold();
     } else {
       OS << (FromDefault ? "[(default) " : "[");
       Bold();
-      PrintExpr(FromExpr, FromNullPtr);
+      PrintExpr(FromExpr);
       Unbold();
       OS << " != " << (ToDefault ? "(default) " : "");
       Bold();
-      PrintExpr(ToExpr, ToNullPtr);
+      PrintExpr(ToExpr);
       Unbold();
       OS << ']';
     }
   }
 
   /// PrintExpr - Actual formatting and printing of expressions.
-  void PrintExpr(const Expr *E, bool NullPtr = false) {
+  void PrintExpr(const Expr *E) {
     if (E) {
       E->printPretty(OS, nullptr, Policy);
       return;
     }
-    if (NullPtr) {
-      OS << "nullptr";
-      return;
-    }
     OS << "(no argument)";
   }
 
@@ -1677,28 +1696,40 @@ class TemplateDiff {
   /// PrintAPSInt - Handles printing of integral arguments, highlighting
   /// argument differences.
   void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt,
-                   bool IsValidFromInt, bool IsValidToInt, Expr *FromExpr,
-                   Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) {
+                   bool IsValidFromInt, bool IsValidToInt, QualType FromIntType,
+                   QualType ToIntType, Expr *FromExpr, Expr *ToExpr,
+                   bool FromDefault, bool ToDefault, bool Same) {
     assert((IsValidFromInt || IsValidToInt) &&
            "Only one integral argument may be missing.");
 
     if (Same) {
-      OS << FromInt.toString(10);
-    } else if (!PrintTree) {
+      if (FromIntType->isBooleanType()) {
+        OS << ((FromInt == 0) ? "false" : "true");
+      } else {
+        OS << FromInt.toString(10);
+      }
+      return;
+    }
+
+    bool PrintType = IsValidFromInt && IsValidToInt &&
+                     !Context.hasSameType(FromIntType, ToIntType);
+
+    if (!PrintTree) {
       OS << (FromDefault ? "(default) " : "");
-      PrintAPSInt(FromInt, FromExpr, IsValidFromInt);
+      PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
     } else {
       OS << (FromDefault ? "[(default) " : "[");
-      PrintAPSInt(FromInt, FromExpr, IsValidFromInt);
+      PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
       OS << " != " << (ToDefault ? "(default) " : "");
-      PrintAPSInt(ToInt, ToExpr, IsValidToInt);
+      PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType);
       OS << ']';
     }
   }
 
   /// PrintAPSInt - If valid, print the APSInt.  If the expression is
   /// gives more information, print it too.
-  void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid) {
+  void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid, QualType IntType,
+                   bool PrintType) {
     Bold();
     if (Valid) {
       if (HasExtraInfo(E)) {
@@ -1707,7 +1738,20 @@ class TemplateDiff {
         OS << " aka ";
         Bold();
       }
-      OS << Val.toString(10);
+      if (PrintType) {
+        Unbold();
+        OS << "(";
+        Bold();
+        IntType.print(OS, Context.getPrintingPolicy());
+        Unbold();
+        OS << ") ";
+        Bold();
+      }
+      if (IntType->isBooleanType()) {
+        OS << ((Val == 0) ? "false" : "true");
+      } else {
+        OS << Val.toString(10);
+      }
     } else if (E) {
       PrintExpr(E);
     } else {
@@ -1716,8 +1760,8 @@ class TemplateDiff {
     Unbold();
   }
 
-  /// HasExtraInfo - Returns true if E is not an integer literal or the
-  /// negation of an integer literal
+  /// HasExtraInfo - Returns true if E is not an integer literal, the
+  /// negation of an integer literal, or a boolean literal.
   bool HasExtraInfo(Expr *E) {
     if (!E) return false;
 
@@ -1730,10 +1774,13 @@ class TemplateDiff {
         if (isa<IntegerLiteral>(UO->getSubExpr()))
           return false;
 
+    if (isa<CXXBoolLiteralExpr>(E))
+      return false;
+
     return true;
   }
 
-  void PrintValueDecl(ValueDecl *VD, bool AddressOf, bool NullPtr) {
+  void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) {
     if (VD) {
       if (AddressOf)
         OS << "&";
@@ -1742,6 +1789,17 @@ class TemplateDiff {
     }
 
     if (NullPtr) {
+      if (E && !isa<CXXNullPtrLiteralExpr>(E)) {
+        PrintExpr(E);
+        if (IsBold) {
+          Unbold();
+          OS << " aka ";
+          Bold();
+        } else {
+          OS << " aka ";
+        }
+      }
+
       OS << "nullptr";
       return;
     }
@@ -1753,32 +1811,74 @@ class TemplateDiff {
   /// argument differences.
   void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
                       bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,
-                      bool ToNullPtr, bool FromDefault, bool ToDefault,
-                      bool Same) {
+                      bool ToNullPtr, Expr *FromExpr, Expr *ToExpr,
+                      bool FromDefault, bool ToDefault, bool Same) {
     assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&
            "Only one Decl argument may be NULL");
 
     if (Same) {
-      PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
+      PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
     } else if (!PrintTree) {
       OS << (FromDefault ? "(default) " : "");
       Bold();
-      PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
+      PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
       Unbold();
     } else {
       OS << (FromDefault ? "[(default) " : "[");
       Bold();
-      PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
+      PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
       Unbold();
       OS << " != " << (ToDefault ? "(default) " : "");
       Bold();
-      PrintValueDecl(ToValueDecl, ToAddressOf, ToNullPtr);
+      PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr);
       Unbold();
       OS << ']';
     }
 
   }
 
+  /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and
+  /// APSInt to print a mixed difference.
+  void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf,
+                                bool IsNullPtr, Expr *VDExpr, bool DefaultDecl,
+                                llvm::APSInt Val, QualType IntType,
+                                Expr *IntExpr, bool DefaultInt) {
+    if (!PrintTree) {
+      OS << (DefaultDecl ? "(default) " : "");
+      Bold();
+      PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
+      Unbold();
+    } else {
+      OS << (DefaultDecl ? "[(default) " : "[");
+      Bold();
+      PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
+      Unbold();
+      OS << " != " << (DefaultInt ? "(default) " : "");
+      PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
+      OS << ']';
+    }
+  }
+
+  /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and
+  /// ValueDecl to print a mixed difference.
+  void PrintIntegerAndValueDecl(llvm::APSInt Val, QualType IntType,
+                                Expr *IntExpr, bool DefaultInt, ValueDecl *VD,
+                                bool NeedAddressOf, bool IsNullPtr,
+                                Expr *VDExpr, bool DefaultDecl) {
+    if (!PrintTree) {
+      OS << (DefaultInt ? "(default) " : "");
+      PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
+    } else {
+      OS << (DefaultInt ? "[(default) " : "[");
+      PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
+      OS << " != " << (DefaultDecl ? "(default) " : "");
+      Bold();
+      PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
+      Unbold();
+      OS << ']';
+    }
+  }
+
   // Prints the appropriate placeholder for elided template arguments.
   void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
     if (PrintTree) {
@@ -1866,21 +1966,21 @@ public:
       PrintTree(PrintTree),
       ShowColor(ShowColor),
       // When printing a single type, the FromType is the one printed.
-      FromType(PrintFromType ? FromType : ToType),
-      ToType(PrintFromType ? ToType : FromType),
+      FromTemplateType(PrintFromType ? FromType : ToType),
+      ToTemplateType(PrintFromType ? ToType : FromType),
       OS(OS),
       IsBold(false) {
   }
 
   /// DiffTemplate - Start the template type diffing.
   void DiffTemplate() {
-    Qualifiers FromQual = FromType.getQualifiers(),
-               ToQual = ToType.getQualifiers();
+    Qualifiers FromQual = FromTemplateType.getQualifiers(),
+               ToQual = ToTemplateType.getQualifiers();
 
     const TemplateSpecializationType *FromOrigTST =
-        GetTemplateSpecializationType(Context, FromType);
+        GetTemplateSpecializationType(Context, FromTemplateType);
     const TemplateSpecializationType *ToOrigTST =
-        GetTemplateSpecializationType(Context, ToType);
+        GetTemplateSpecializationType(Context, ToTemplateType);
 
     // Only checking templates.
     if (!FromOrigTST || !ToOrigTST)
@@ -1893,13 +1993,12 @@ public:
 
     FromQual -= QualType(FromOrigTST, 0).getQualifiers();
     ToQual -= QualType(ToOrigTST, 0).getQualifiers();
-    Tree.SetNode(FromType, ToType);
-    Tree.SetNode(FromQual, ToQual);
-    Tree.SetKind(DiffTree::Template);
 
     // Same base template, but different arguments.
-    Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(),
-                 ToOrigTST->getTemplateName().getAsTemplateDecl());
+    Tree.SetTemplateDiff(FromOrigTST->getTemplateName().getAsTemplateDecl(),
+                         ToOrigTST->getTemplateName().getAsTemplateDecl(),
+                         FromQual, ToQual, false /*FromDefault*/,
+                         false /*ToDefault*/);
 
     DiffTemplate(FromOrigTST, ToOrigTST);
   }

Modified: cfe/branches/release_38/test/Misc/diag-template-diffing-color.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_38/test/Misc/diag-template-diffing-color.cpp?rev=259422&r1=259421&r2=259422&view=diff
==============================================================================
--- cfe/branches/release_38/test/Misc/diag-template-diffing-color.cpp (original)
+++ cfe/branches/release_38/test/Misc/diag-template-diffing-color.cpp Mon Feb  1 16:13:54 2016
@@ -1,5 +1,5 @@
-// RUN: not %clang_cc1 -fsyntax-only -fcolor-diagnostics %s 2>&1 | FileCheck %s
-// RUN: not %clang_cc1 -fsyntax-only -fcolor-diagnostics -fdiagnostics-show-template-tree %s 2>&1 | FileCheck %s -check-prefix=TREE
+// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fcolor-diagnostics %s 2>&1 | FileCheck %s
+// RUN: not %clang_cc1 -fsyntax-only -std=c++11 -fcolor-diagnostics -fdiagnostics-show-template-tree %s 2>&1 | FileCheck %s -check-prefix=TREE
 // REQUIRES: ansi-escape-sequences
 template<typename> struct foo {};
 void func(foo<int>);
@@ -82,5 +82,23 @@ namespace default_args {
     // CHECK: no viable conversion from 'A<[2 * ...], (default) [[CYAN]]2[[RESET]][[BOLD]]>' to 'A<[2 * ...], [[CYAN]]0[[RESET]][[BOLD]]>'
     A<0, 2, 0> N2 = M;
   }
+}
 
+namespace MixedDeclarationIntegerArgument {
+  template<typename T, T n = 5> class A{};
+  int x;
+  int y[5];
+  A<int> a1 = A<int&, x>();
+  // CHECK: no viable conversion from 'A<[[CYAN]]int &[[RESET]][[BOLD]], [[CYAN]]x[[RESET]][[BOLD]]>' to 'A<[[CYAN]]int[[RESET]][[BOLD]], (default) [[CYAN]]5[[RESET]][[BOLD]]>'
+  // TREE: no viable conversion
+  // TREE:   A<
+  // TREE:     {{\[}}[[CYAN]]int &[[RESET]][[BOLD]] != [[CYAN]]int[[RESET]][[BOLD]]],
+  // TREE:     {{\[}}[[CYAN]]x[[RESET]][[BOLD]] != (default) [[CYAN]]5[[RESET]][[BOLD]]]>
+
+  A<int**, nullptr> a2 = A<int, 3 + 1>();
+  // CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<[[CYAN]]int[[RESET]][[BOLD]], [[CYAN]]3 + 1[[RESET]][[BOLD]] aka [[CYAN]]4[[RESET]][[BOLD]]>' to 'A<[[CYAN]]int **[[RESET]][[BOLD]], [[CYAN]]nullptr[[RESET]][[BOLD]]>'
+  // TREE: no viable conversion
+  // TREE:   A<
+  // TREE:     {{\[}}[[CYAN]]int[[RESET]][[BOLD]] != [[CYAN]]int **[[RESET]][[BOLD]]],
+  // TREE:     {{\[}}[[CYAN]]3 + 1[[RESET]][[BOLD]] aka [[CYAN]]4[[RESET]][[BOLD]] != [[CYAN]]nullptr[[RESET]][[BOLD]]]>
 }

Modified: cfe/branches/release_38/test/Misc/diag-template-diffing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/release_38/test/Misc/diag-template-diffing.cpp?rev=259422&r1=259421&r2=259422&view=diff
==============================================================================
--- cfe/branches/release_38/test/Misc/diag-template-diffing.cpp (original)
+++ cfe/branches/release_38/test/Misc/diag-template-diffing.cpp Mon Feb  1 16:13:54 2016
@@ -925,7 +925,7 @@ namespace DependentDefault {
     // CHECK-ELIDE-NOTREE: no known conversion from 'A<char, [...]>' to 'A<int, [...]>'
     a3 = a1;
     // CHECK-ELIDE-NOTREE: no viable overloaded '='
-    // CHECK-ELIDE-NOTREE: no known conversion from 'A<[...], (default) 40>' to 'A<[...], 10>'
+    // CHECK-ELIDE-NOTREE: no known conversion from 'A<[...], (default) Trait<T>::V aka 40>' to 'A<[...], 10>'
     a2 = a3;
     // CHECK-ELIDE-NOTREE: no viable overloaded '='
     // CHECK-ELIDE-NOTREE: no known conversion from 'A<int, 10>' to 'A<char, 40>'
@@ -1118,7 +1118,7 @@ int global, global2;
 constexpr int * ptr = nullptr;
 Wrapper<S<ptr>> W = MakeWrapper<S<&global>>();
 // Don't print an extra '&' for 'ptr'
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global>>' to 'Wrapper<S<ptr>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global>>' to 'Wrapper<S<ptr aka nullptr>>'
 
 // Handle parens correctly
 Wrapper<S<(&global2)>> W2 = MakeWrapper<S<&global>>();
@@ -1148,7 +1148,7 @@ S<&global, nullptr> s2 = S<&global, ptr>
 S<&global, nullptr> s3 = S<&global, &global>();
 // CHECK-ELIDE-NOTREE: no viable conversion from 'S<[...], &global>' to 'S<[...], nullptr>'
 S<&global, ptr> s4 = S<&global, &global>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'S<[...], &global>' to 'S<[...], ptr>
+// CHECK-ELIDE-NOTREE: no viable conversion from 'S<[...], &global>' to 'S<[...], ptr aka nullptr>
 
 Wrapper<S<&global, nullptr>> W1 = MakeWrapper<S<&global, ptr>>();
 Wrapper<S<&global, static_cast<int*>(0)>> W2 = MakeWrapper<S<&global, ptr>>();
@@ -1156,7 +1156,7 @@ Wrapper<S<&global, static_cast<int*>(0)>
 Wrapper<S<&global, nullptr>> W3 = MakeWrapper<S<&global, &global>>();
 // CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], nullptr>>'
 Wrapper<S<&global, ptr>> W4 = MakeWrapper<S<&global, &global>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], ptr>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], ptr aka nullptr>>'
 
 Wrapper<S<&global2, ptr>> W5 = MakeWrapper<S<&global, nullptr>>();
 // CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<&global, [...]>>' to 'Wrapper<S<&global2, [...]>>'
@@ -1180,7 +1180,7 @@ Wrapper<S<&global2, nullptr>> W12 =
 Wrapper<S<&global, &global>> W13 = MakeWrapper<S<&global, ptr>>();
 // CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], nullptr>>' to 'Wrapper<S<[...], &global>>'
 Wrapper<S<&global, ptr>> W14 = MakeWrapper<S<&global, &global>>();
-// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], ptr>>'
+// CHECK-ELIDE-NOTREE: no viable conversion from 'Wrapper<S<[...], &global>>' to 'Wrapper<S<[...], ptr aka nullptr>>'
 }
 
 namespace TemplateTemplateDefault {
@@ -1271,7 +1271,160 @@ void test() {
   foo<BoolT<true>>(X);
 }
 // CHECK-ELIDE-NOTREE: no matching function for call to 'foo'
-// CHECK-ELIDE-NOTREE: candidate function [with T = BoolArgumentBitExtended::BoolT<true>] not viable: no known conversion from 'BoolT<0>' to 'BoolT<1>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function [with T = BoolArgumentBitExtended::BoolT<true>] not viable: no known conversion from 'BoolT<false>' to 'BoolT<true>' for 1st argument
+}
+
+namespace DifferentIntegralTypes {
+template<typename T, T n>
+class A{};
+void foo() {
+  A<int, 1> a1 = A<long long, 1>();
+  A<unsigned int, 1> a2 = A<int, 5>();
+  A<bool, true> a3 = A<signed char, true>();
+}
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<long long, (long long) 1>' to 'A<int, (int) 1>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, (int) 5>' to 'A<unsigned int, (unsigned int) 1>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<signed char, (signed char) 1>' to 'A<bool, (bool) true>'
+}
+
+namespace MixedDeclarationIntegerArgument {
+template<typename T, T n> class A{};
+int x;
+int y[5];
+
+A<int, 5> a1 = A<int&, x>();
+A<int, 5 - 1> a2 = A<int*, &x>();
+A<int, 5 + 1> a3 = A<int*, y>();
+A<int, 0> a4 = A<int**, nullptr>();
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int &, x>' to 'A<int, 5>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int *, &x>' to 'A<int, 5 - 1 aka 4>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int *, y>' to 'A<int, 5 + 1 aka 6>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int **, nullptr>' to 'A<int, 0>'
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   A<
+// CHECK-ELIDE-TREE:     [int & != int],
+// CHECK-ELIDE-TREE:     [x != 5]>
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   A<
+// CHECK-ELIDE-TREE:     [int * != int],
+// CHECK-ELIDE-TREE:     [&x != 5 - 1 aka 4]>
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   A<
+// CHECK-ELIDE-TREE:     [int * != int],
+// CHECK-ELIDE-TREE:     [y != 5 + 1 aka 6]>
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   A<
+// CHECK-ELIDE-TREE:     [int ** != int],
+// CHECK-ELIDE-TREE:     [nullptr != 0]>
+
+A<int&, x> a5 = A<int, 3>();
+A<int*, &x> a6 = A<int, 3 - 1>();
+A<int*, y> a7 = A<int, 3 + 1>();
+A<int**, nullptr> a8 = A<int, 3>();
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, 3>' to 'A<int &, x>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, 3 - 1 aka 2>' to 'A<int *, &x>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, 3 + 1 aka 4>' to 'A<int *, y>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<int, 3>' to 'A<int **, nullptr>'
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   A<
+// CHECK-ELIDE-TREE:     [int != int &],
+// CHECK-ELIDE-TREE:     [3 != x]>
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   A<
+// CHECK-ELIDE-TREE:     [int != int *],
+// CHECK-ELIDE-TREE:     [3 - 1 aka 2 != &x]>
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   A<
+// CHECK-ELIDE-TREE:     [int != int *],
+// CHECK-ELIDE-TREE:     [3 + 1 aka 4 != y]>
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   A<
+// CHECK-ELIDE-TREE:     [int != int **],
+// CHECK-ELIDE-TREE:     [3 != nullptr]>
+
+template<class T, T n = x> class B{} ;
+B<int, 5> b1 = B<int&>();
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<int &, (default) x>' to 'B<int, 5>'
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   B<
+// CHECK-ELIDE-TREE:     [int & != int],
+// CHECK-ELIDE-TREE:     [(default) x != 5]>
+
+B<int &> b2 = B<int, 2>();
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<int, 2>' to 'B<int &, (default) x>'
+// CHECK-ELIDE-TREE:   B<
+// CHECK-ELIDE-TREE:     [int != int &],
+// CHECK-ELIDE-TREE:     [2 != (default) x]>
+
+template<class T, T n = 11> class C {};
+C<int> c1 = C<int&, x>();
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'C<int &, x>' to 'C<int, (default) 11>'
+// CHECK-ELIDE-TREE: error: no viable conversion
+// CHECK-ELIDE-TREE:   C<
+// CHECK-ELIDE-TREE:     [int & != int],
+// CHECK-ELIDE-TREE:     [x != (default) 11]>
+
+C<int &, x> c2 = C<int>();
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'C<int, (default) 11>' to 'C<int &, x>'
+// CHECK-ELIDE-TREE:   C<
+// CHECK-ELIDE-TREE:     [int != int &],
+// CHECK-ELIDE-TREE:     [(default) 11 != x]>
+}
+
+namespace default_args {
+  template <int x, int y = 1+1, int z = 2>
+  class A {};
+
+  void foo(A<0> &M) {
+    // CHECK-ELIDE-NOTREE: no viable conversion from 'A<[...], (default) 1 + 1 aka 2, (default) 2>' to 'A<[...], 0, 0>'
+    A<0, 0, 0> N = M;
+
+    // CHECK-ELIDE-NOTREE: no viable conversion from 'A<[2 * ...], (default) 2>' to 'A<[2 * ...], 0>'
+    A<0, 2, 0> N2 = M;
+  }
+}
+
+namespace DefaultNonTypeArgWithDependentType {
+// We used to crash diffing integer template arguments when the argument type
+// is dependent and default arguments were used.
+template <typename SizeType = int, SizeType = 0> struct A {};
+template <typename R = A<>> R bar();
+A<> &foo() { return bar(); }
+// CHECK-ELIDE-NOTREE: error: non-const lvalue reference to type 'A<[2 * ...]>' cannot bind to a temporary of type 'A<[2 * ...]>'
+// CHECK-NOELIDE-NOTREE: error: non-const lvalue reference to type 'A<int, 0>' cannot bind to a temporary of type 'A<int, 0>'
+}
+
+namespace PR24587 {
+template <typename T, T v>
+struct integral_constant {};
+
+auto false_ = integral_constant<bool, false> {};
+
+template <typename T>
+void f(T, decltype(false_));
+
+void run() {
+  f(1, integral_constant<bool, true>{});
+}
+// CHECK-ELIDE-NOTREE: error: no matching function for call to 'f'
+// CHECK-ELIDE-NOTREE: note: candidate function [with T = int] not viable: no known conversion from 'integral_constant<[...], true>' to 'integral_constant<[...], false>' for 2nd argument
+}
+
+namespace ZeroArgs {
+template <int N = 0> class A {};
+template <class T = A<>> class B {};
+A<1> a1 = A<>();
+A<> a2 = A<1>();
+B<> b1 = B<int>();
+B<int> b2 = B<>();
+B<> b3 = B<const A<>>();
+B<const A<>> b4 = B<>();
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<(default) 0>' to 'A<1>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'A<1>' to 'A<(default) 0>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<int>' to 'B<(default) ZeroArgs::A<0>>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<(default) ZeroArgs::A<0>>' to 'B<int>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<const A<[...]>>' to 'B<A<[...]>>'
+// CHECK-ELIDE-NOTREE: error: no viable conversion from 'B<A<[...]>>' to 'B<const A<[...]>>'
 }
 
 // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.




More information about the llvm-branch-commits mailing list