]> granicus.if.org Git - clang/commitdiff
Save the integer type for integral template arguments.
authorRichard Trieu <rtrieu@google.com>
Fri, 15 Jan 2016 02:55:17 +0000 (02:55 +0000)
committerRichard Trieu <rtrieu@google.com>
Fri, 15 Jan 2016 02:55:17 +0000 (02:55 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@257861 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTDiagnostic.cpp
test/Misc/diag-template-diffing.cpp

index bd8202aceb8dc3e985acfc3c008b22f1eaa45d8f..c60dfa6e533f6015030fdd8144627786c4414dee 100644 (file)
@@ -615,6 +615,7 @@ class TemplateDiff {
 
     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.");
@@ -623,6 +624,8 @@ class TemplateDiff {
       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);
@@ -730,12 +733,15 @@ class TemplateDiff {
 
     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;
     }
@@ -1047,10 +1053,13 @@ class TemplateDiff {
   }
 
   /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes
-  static void InitializeNonTypeDiffVariables(
-      ASTContext &Context, const TSTiterator &Iter,
-      NonTypeTemplateParmDecl *Default, llvm::APSInt &Value, bool &HasInt,
-      bool &IsNullPtr, Expr *&E, ValueDecl *&VD, bool &NeedAddressOf) {
+  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:
@@ -1058,6 +1067,7 @@ class TemplateDiff {
         case TemplateArgument::Integral:
           Value = Iter->getAsIntegral();
           HasInt = true;
+          IntType = Iter->getIntegralType();
           return;
         case TemplateArgument::Declaration: {
           VD = Iter->getAsDecl();
@@ -1087,6 +1097,7 @@ class TemplateDiff {
       case TemplateArgument::Integral:
         Value = TA.getAsIntegral();
         HasInt = true;
+        IntType = TA.getIntegralType();
         return;
       case TemplateArgument::Declaration: {
         VD = TA.getAsDecl();
@@ -1117,15 +1128,16 @@ 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, FromNullPtr = false,
          ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;
-    InitializeNonTypeDiffVariables(Context, FromIter, FromDefaultNonTypeDecl,
-                                   FromInt, HasFromInt, FromNullPtr, FromExpr,
-                                   FromValueDecl, NeedFromAddressOf);
+    InitializeNonTypeDiffVariables(
+        Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt,
+        FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf);
     InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt,
-                                   HasToInt, ToNullPtr, ToExpr, ToValueDecl,
-                                   NeedToAddressOf);
+                                   HasToInt, ToIntType, ToNullPtr, ToExpr,
+                                   ToValueDecl, NeedToAddressOf);
 
     bool FromDeclaration = FromValueDecl || FromNullPtr;
     bool ToDeclaration = ToValueDecl || ToNullPtr;
@@ -1140,10 +1152,11 @@ class TemplateDiff {
                      (ToExpr || ToValueDecl || HasToInt || ToNullPtr);
 
     if (HasFromInt || HasToInt) {
-      Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromExpr,
-                          ToExpr, FromDefault, ToDefault);
+      Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,
+                          ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);
       if (HasFromInt && HasToInt) {
-        Tree.SetSame(FromInt == ToInt);
+        Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) &&
+                     FromInt == ToInt);
       }
       return;
     }
@@ -1349,11 +1362,12 @@ class TemplateDiff {
         llvm::APSInt FromInt, ToInt;
         Expr *FromExpr, *ToExpr;
         bool IsValidFromInt, IsValidToInt;
+        QualType FromIntType, ToIntType;
         Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,
-                            FromExpr, ToExpr);
-        PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt,
-                    FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
-                    Tree.NodeIsSame());
+                            FromIntType, ToIntType, FromExpr, ToExpr);
+        PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,
+                    ToIntType, FromExpr, ToExpr, Tree.FromDefault(),
+                    Tree.ToDefault(), Tree.NodeIsSame());
         return;
       }
       case DiffTree::Declaration: {
@@ -1560,28 +1574,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)) {
@@ -1590,7 +1616,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 {
index f106c7d03da7fbcb4cb1b040944860b2e123b2e3..424ac51c9a103feb600e93d2342cbfb292e3499a 100644 (file)
@@ -1271,9 +1271,23 @@ 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>'
+}
+
+
 // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.