[cfe-commits] r167252 - in /cfe/trunk: lib/AST/ASTDiagnostic.cpp test/Misc/diag-template-diffing.cpp

Richard Trieu rtrieu at google.com
Thu Nov 1 14:29:28 PDT 2012


Author: rtrieu
Date: Thu Nov  1 16:29:28 2012
New Revision: 167252

URL: http://llvm.org/viewvc/llvm-project?rev=167252&view=rev
Log:
Fix the template type diffing to handle integral template arguments.

Modified:
    cfe/trunk/lib/AST/ASTDiagnostic.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=167252&r1=167251&r2=167252&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Thu Nov  1 16:29:28 2012
@@ -433,6 +433,12 @@
       /// 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;
+
       /// FromDefault, ToDefault - Whether the argument is a default argument.
       bool FromDefault, ToDefault;
 
@@ -483,6 +489,15 @@
       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;
@@ -566,6 +581,12 @@
              (FlatTree[ReadNode].FromTD || FlatTree[ReadNode].ToTD);
     }
 
+    /// NodeIsAPSInt - Returns true if the arugments are stored in APSInt's.
+    bool NodeIsAPSInt() {
+      return FlatTree[ReadNode].IsValidFromInt ||
+             FlatTree[ReadNode].IsValidToInt;
+    }
+
     /// GetNode - Gets the FromType and ToType.
     void GetNode(QualType &FromType, QualType &ToType) {
       FromType = FlatTree[ReadNode].FromType;
@@ -584,6 +605,15 @@
       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;
@@ -817,12 +847,41 @@
       if (NonTypeTemplateParmDecl *DefaultNTTPD =
               dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {
         Expr *FromExpr, *ToExpr;
-        GetExpr(FromIter, DefaultNTTPD, FromExpr);
-        GetExpr(ToIter, DefaultNTTPD, ToExpr);
-        Tree.SetNode(FromExpr, ToExpr);
-        Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
-        Tree.SetDefault(FromIter.isEnd() && FromExpr,
-                        ToIter.isEnd() && ToExpr);
+        llvm::APSInt FromInt, ToInt;
+        bool HasFromInt = !FromIter.isEnd() &&
+                          FromIter->getKind() == TemplateArgument::Integral;
+        bool HasToInt = !ToIter.isEnd() &&
+                        ToIter->getKind() == TemplateArgument::Integral;
+        //bool IsValidFromInt = false, IsValidToInt = false;
+        if (HasFromInt)
+          FromInt = FromIter->getAsIntegral();
+        else
+          GetExpr(FromIter, DefaultNTTPD, FromExpr);
+
+        if (HasToInt)
+          ToInt = ToIter->getAsIntegral();
+        else
+          GetExpr(ToIter, DefaultNTTPD, ToExpr);
+
+        if (!HasFromInt && !HasToInt) {
+          Tree.SetNode(FromExpr, ToExpr);
+          Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
+          Tree.SetDefault(FromIter.isEnd() && FromExpr,
+                          ToIter.isEnd() && ToExpr);
+        } else {
+          if (!HasFromInt && FromExpr) {
+            FromInt = FromExpr->EvaluateKnownConstInt(Context);
+            HasFromInt = true;
+          }
+          if (!HasToInt && ToExpr) {
+            ToInt = ToExpr->EvaluateKnownConstInt(Context);
+            HasToInt = true;
+          }
+          Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
+          Tree.SetSame(llvm::APSInt::isSameValue(FromInt, ToInt));
+          Tree.SetDefault(FromIter.isEnd() && HasFromInt,
+                          ToIter.isEnd() && HasToInt);
+        }
       }
 
       // Handle Templates
@@ -1038,6 +1097,15 @@
                               Tree.ToDefault(), Tree.NodeIsSame());
         return;
       }
+
+      if (Tree.NodeIsAPSInt()) {
+        llvm::APSInt FromInt, ToInt;
+        bool IsValidFromInt, IsValidToInt;
+        Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt);
+        PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt,
+                    Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
+        return;
+      }
       llvm_unreachable("Unable to deduce template difference.");
     }
 
@@ -1212,6 +1280,34 @@
     }
   }
 
+  /// PrintAPSInt - Handles printing of integral arguments, highlighting
+  /// argument differences.
+  void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt,
+                   bool IsValidFromInt, bool IsValidToInt, 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) {
+      OS << (FromDefault ? "(default) " : "");
+      Bold();
+      OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)");
+      Unbold();
+    } else {
+      OS << (FromDefault ? "[(default) " : "[");
+      Bold();
+      OS << (IsValidFromInt ? FromInt.toString(10) : "(no argument)");
+      Unbold();
+      OS << " != " << (ToDefault ? "(default) " : "");
+      Bold();
+      OS << (IsValidToInt ? ToInt.toString(10) : "(no argument)");
+      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.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=167252&r1=167251&r2=167252&view=diff
==============================================================================
--- cfe/trunk/test/Misc/diag-template-diffing.cpp (original)
+++ cfe/trunk/test/Misc/diag-template-diffing.cpp Thu Nov  1 16:29:28 2012
@@ -630,6 +630,169 @@
 // CHECK-NOELIDE-TREE:   D23<
 // CHECK-NOELIDE-TREE:     [char != A23<>]>
 
+namespace PR14015 {
+template <unsigned N> class Foo1 {};
+template <unsigned N = 2> class Foo2 {};
+template <unsigned ...N> class Foo3 {};
+
+void Play1() {
+  Foo1<1> F1;
+  Foo1<2> F2, F3;
+  F2 = F1;
+  F1 = F2;
+  F2 = F3;
+  F3 = F2;
+}
+
+// CHECK-ELIDE-NOTREE: no viable overloaded '='
+// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo1<1>' to 'Foo1<2>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo1<1>' to 'Foo1<2>' for 1st argument
+// CHECK-ELIDE-NOTREE: no viable overloaded '='
+// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo1<2>' to 'Foo1<1>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo1<2>' to 'Foo1<1>' for 1st argument
+// CHECK-NOELIDE-NOTREE: no viable overloaded '='
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo1<1>' to 'Foo1<2>' for 1st argument
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo1<1>' to 'Foo1<2>' for 1st argument
+// CHECK-NOELIDE-NOTREE: no viable overloaded '='
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo1<2>' to 'Foo1<1>' for 1st argument
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo1<2>' to 'Foo1<1>' for 1st argument
+// CHECK-ELIDE-TREE: no viable overloaded '='
+// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo1<
+// CHECK-ELIDE-TREE:     [1 != 2]>
+// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo1<
+// CHECK-ELIDE-TREE:     [1 != 2]>
+// CHECK-ELIDE-TREE: no viable overloaded '='
+// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo1<
+// CHECK-ELIDE-TREE:     [2 != 1]>
+// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo1<
+// CHECK-ELIDE-TREE:     [2 != 1]>
+// CHECK-NOELIDE-TREE: no viable overloaded '='
+// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo1<
+// CHECK-NOELIDE-TREE:     [1 != 2]>
+// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo1<
+// CHECK-NOELIDE-TREE:     [1 != 2]>
+// CHECK-NOELIDE-TREE: no viable overloaded '='
+// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo1<
+// CHECK-NOELIDE-TREE:     [2 != 1]>
+// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo1<
+// CHECK-NOELIDE-TREE:     [2 != 1]>
+
+void Play2() {
+  Foo2<1> F1;
+  Foo2<> F2, F3;
+  F2 = F1;
+  F1 = F2;
+  F2 = F3;
+  F3 = F2;
+}
+// CHECK-ELIDE-NOTREE: no viable overloaded '='
+// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo2<1>' to 'Foo2<2>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo2<1>' to 'Foo2<2>' for 1st argument
+// CHECK-ELIDE-NOTREE: no viable overloaded '='
+// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo2<(default) 2>' to 'Foo2<1>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo2<(default) 2>' to 'Foo2<1>' for 1st argument
+// CHECK-NOELIDE-NOTREE: no viable overloaded '='
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo2<1>' to 'Foo2<2>' for 1st argument
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo2<1>' to 'Foo2<2>' for 1st argument
+// CHECK-NOELIDE-NOTREE: no viable overloaded '='
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo2<(default) 2>' to 'Foo2<1>' for 1st argument
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo2<(default) 2>' to 'Foo2<1>' for 1st argument
+// CHECK-ELIDE-TREE: no viable overloaded '='
+// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo2<
+// CHECK-ELIDE-TREE:     [1 != 2]>
+// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo2<
+// CHECK-ELIDE-TREE:     [1 != 2]>
+// CHECK-ELIDE-TREE: no viable overloaded '='
+// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo2<
+// CHECK-ELIDE-TREE:     [(default) 2 != 1]>
+// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo2<
+// CHECK-ELIDE-TREE:     [(default) 2 != 1]>
+// CHECK-NOELIDE-TREE: no viable overloaded '='
+// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo2<
+// CHECK-NOELIDE-TREE:     [1 != 2]>
+// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo2<
+// CHECK-NOELIDE-TREE:     [1 != 2]>
+// CHECK-NOELIDE-TREE: no viable overloaded '='
+// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo2<
+// CHECK-NOELIDE-TREE:     [(default) 2 != 1]>
+// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo2<
+// CHECK-NOELIDE-TREE:     [(default) 2 != 1]>
+
+void Play3() {
+  Foo3<1> F1;
+  Foo3<2, 1> F2, F3;
+  F2 = F1;
+  F1 = F2;
+  F2 = F3;
+  F3 = F2;
+}
+// CHECK-ELIDE-NOTREE: no viable overloaded '='
+// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo3<1, (no argument)>' to 'Foo3<2, 1>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo3<1, (no argument)>' to 'Foo3<2, 1>' for 1st argument
+// CHECK-ELIDE-NOTREE: no viable overloaded '='
+// CHECK-ELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo3<2, 1>' to 'Foo3<1, (no argument)>' for 1st argument
+// CHECK-ELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo3<2, 1>' to 'Foo3<1, (no argument)>' for 1st argument
+// CHECK-NOELIDE-NOTREE: no viable overloaded '='
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo3<1, (no argument)>' to 'Foo3<2, 1>' for 1st argument
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo3<1, (no argument)>' to 'Foo3<2, 1>' for 1st argument
+// CHECK-NOELIDE-NOTREE: no viable overloaded '='
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from 'Foo3<2, 1>' to 'Foo3<1, (no argument)>' for 1st argument
+// CHECK-NOELIDE-NOTREE: candidate function (the implicit move assignment operator) not viable: no known conversion from 'Foo3<2, 1>' to 'Foo3<1, (no argument)>' for 1st argument
+// CHECK-ELIDE-TREE: no viable overloaded '='
+// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo3<
+// CHECK-ELIDE-TREE:     [1 != 2], 
+// CHECK-ELIDE-TREE:     [(no argument) != 1]>
+// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo3<
+// CHECK-ELIDE-TREE:     [1 != 2],
+// CHECK-ELIDE-TREE:     [(no argument) != 1]>
+// CHECK-ELIDE-TREE: no viable overloaded '='
+// CHECK-ELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo3<
+// CHECK-ELIDE-TREE:     [2 != 1],
+// CHECK-ELIDE-TREE:     [1 != (no argument)]>
+// CHECK-ELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-ELIDE-TREE:   Foo3<
+// CHECK-ELIDE-TREE:     [2 != 1], 
+// CHECK-ELIDE-TREE:     [1 != (no argument)]>
+// CHECK-NOELIDE-TREE: no viable overloaded '='
+// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo3<
+// CHECK-NOELIDE-TREE:     [1 != 2], 
+// CHECK-NOELIDE-TREE:     [(no argument) != 1]>
+// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo3<
+// CHECK-NOELIDE-TREE:     [1 != 2], 
+// CHECK-NOELIDE-TREE:     [(no argument) != 1]>
+// CHECK-NOELIDE-TREE: no viable overloaded '='
+// CHECK-NOELIDE-TREE: candidate function (the implicit copy assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo3<
+// CHECK-NOELIDE-TREE:     [2 != 1], 
+// CHECK-NOELIDE-TREE:     [1 != (no argument)]>
+// CHECK-NOELIDE-TREE: candidate function (the implicit move assignment operator) not viable: no known conversion from argument type to parameter type for 1st argument
+// CHECK-NOELIDE-TREE:   Foo3<
+// CHECK-NOELIDE-TREE:     [2 != 1], 
+// CHECK-NOELIDE-TREE:     [1 != (no argument)]>
+}
+
+
 // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.





More information about the cfe-commits mailing list