]> granicus.if.org Git - clang/commitdiff
Update assumption in template diffing about integer template arguments.
authorRichard Trieu <rtrieu@google.com>
Thu, 26 Feb 2015 02:40:48 +0000 (02:40 +0000)
committerRichard Trieu <rtrieu@google.com>
Thu, 26 Feb 2015 02:40:48 +0000 (02:40 +0000)
Fix for PR22017.  Integer template arguments are automatically bit extended to
the size of the integer type.  In template diffing, evaluated expressions were
not having their results extending, leading to comparing two APSInt's with
different widths.  Apply the proper bit extending when evaluating template
arguments.  This mainly affected bool template arguments.

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

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

index f55e0326c44aa5026a0c1a26b64222481f36e9da..000588face96f13a5d2c8dacb7c6826e3b42b785 100644 (file)
@@ -1003,9 +1003,11 @@ class TemplateDiff {
       Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr);
       if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType()) {
         if (FromExpr)
-          HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt);
+          HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt,
+                              FromDefaultNonTypeDecl->getType());
         if (ToExpr)
-          HasToInt = GetInt(Context, ToIter, ToExpr, ToInt);
+          HasToInt = GetInt(Context, ToIter, ToExpr, ToInt,
+                            ToDefaultNonTypeDecl->getType());
       }
       if (HasFromInt && HasToInt) {
         Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
@@ -1026,9 +1028,11 @@ class TemplateDiff {
 
     if (HasFromInt || HasToInt) {
       if (!HasFromInt && FromExpr)
-        HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt);
+        HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt,
+                            FromDefaultNonTypeDecl->getType());
       if (!HasToInt && ToExpr)
-        HasToInt = GetInt(Context, ToIter, ToExpr, ToInt);
+        HasToInt = GetInt(Context, ToIter, ToExpr, ToInt,
+                          ToDefaultNonTypeDecl->getType());
       Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
       if (HasFromInt && HasToInt) {
         Tree.SetSame(FromInt == ToInt);
@@ -1210,9 +1214,11 @@ class TemplateDiff {
   }
 
   /// GetInt - Retrieves the template integer argument, including evaluating
-  /// default arguments.
+  /// 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) {
+                     Expr *ArgExpr, llvm::APSInt &Int, QualType IntegerType) {
     // Default, value-depenedent expressions require fetching
     // from the desugared TemplateArgument, otherwise expression needs to
     // be evaluatable.
@@ -1224,12 +1230,14 @@ class TemplateDiff {
         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;
     }
 
index 9f4806f64c90e3db048ef05dd162ca7a4f1cba3b..0f2edfb635466baba84e512f2f9946dd01bc7b02 100644 (file)
@@ -1261,6 +1261,19 @@ void foo(const T &t) {
 // CHECK-ELIDE-NOTREE: binding of reference to type 'condition<[...]>' to a value of type 'const condition<[...]>' drops qualifiers
 }
 
+namespace BoolArgumentBitExtended {
+template <bool B> struct BoolT {};
+
+template <typename T> void foo(T) {}
+
+void test() {
+  BoolT<false> X;
+  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: {{[0-9]*}} errors generated.
 // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.