summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Stellard <thomas.stellard@amd.com>2015-05-04 18:23:52 +0000
committerTom Stellard <thomas.stellard@amd.com>2015-05-04 18:23:52 +0000
commit2f12d29b03b69f9e5bdf55bc8cd2167d683cb85f (patch)
tree6e7ba0f9e86a5a43cd2e65a31bc95637cd5b623b
parentdd36addd9cf0be92ee8455345fe6ca4b78c40172 (diff)
Merging r230603:
------------------------------------------------------------------------ r230603 | rtrieu | 2015-02-25 21:40:48 -0500 (Wed, 25 Feb 2015) | 8 lines Update assumption in template diffing about integer template arguments. 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/branches/release_36@236439 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ASTDiagnostic.cpp20
-rw-r--r--test/Misc/diag-template-diffing.cpp13
2 files changed, 27 insertions, 6 deletions
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index f55e0326c4..000588face 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -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;
}
diff --git a/test/Misc/diag-template-diffing.cpp b/test/Misc/diag-template-diffing.cpp
index 9f4806f64c..0f2edfb635 100644
--- a/test/Misc/diag-template-diffing.cpp
+++ b/test/Misc/diag-template-diffing.cpp
@@ -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.