r257869 - Add new diff modes to template type diffing.

Richard Trieu via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 14 21:01:53 PST 2016


Author: rtrieu
Date: Thu Jan 14 23:01:53 2016
New Revision: 257869

URL: http://llvm.org/viewvc/llvm-project?rev=257869&view=rev
Log:
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).

Modified:
    cfe/trunk/lib/AST/ASTDiagnostic.cpp
    cfe/trunk/test/Misc/diag-template-diffing-color.cpp
    cfe/trunk/test/Misc/diag-template-diffing.cpp

Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=257869&r1=257868&r2=257869&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Thu Jan 14 23:01:53 2016
@@ -511,7 +511,10 @@ class TemplateDiff {
       /// Integer difference
       Integer,
       /// Declaration difference, nullptr arguments are included here
-      Declaration
+      Declaration,
+      /// One argument being integer and the other being declaration
+      FromIntegerAndToDeclaration,
+      FromDeclarationAndToInteger
     };
 
   private:
@@ -648,6 +651,40 @@ class TemplateDiff {
       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.");
@@ -761,6 +798,38 @@ class TemplateDiff {
       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;
@@ -1139,18 +1208,31 @@ class TemplateDiff {
                                    HasToInt, ToIntType, ToNullPtr, ToExpr,
                                    ToValueDecl, NeedToAddressOf);
 
-    bool FromDeclaration = FromValueDecl || FromNullPtr;
-    bool ToDeclaration = ToValueDecl || ToNullPtr;
-
-    assert(((!HasFromInt && !HasToInt) ||
-            (!FromDeclaration && !ToDeclaration)) &&
-           "Template argument cannot be both integer and declaration");
-
     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) {
       Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,
                           ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);
@@ -1383,6 +1465,42 @@ class TemplateDiff {
                        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;
@@ -1715,6 +1833,48 @@ class TemplateDiff {
 
   }
 
+  /// 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) {

Modified: cfe/trunk/test/Misc/diag-template-diffing-color.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing-color.cpp?rev=257869&r1=257868&r2=257869&view=diff
==============================================================================
--- cfe/trunk/test/Misc/diag-template-diffing-color.cpp (original)
+++ cfe/trunk/test/Misc/diag-template-diffing-color.cpp Thu Jan 14 23:01:53 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/trunk/test/Misc/diag-template-diffing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=257869&r1=257868&r2=257869&view=diff
==============================================================================
--- cfe/trunk/test/Misc/diag-template-diffing.cpp (original)
+++ cfe/trunk/test/Misc/diag-template-diffing.cpp Thu Jan 14 23:01:53 2016
@@ -1287,6 +1287,89 @@ void foo() {
 // 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]>
+}
 
 // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.




More information about the cfe-commits mailing list