rnk created this revision. rnk added a reviewer: rsmith. rnk added a subscriber: cfe-commits.
In the following example, we end up diffing 'A<int, 0>' against 'A<>'. template <typename SizeType = int, SizeType = 0> struct A {}; template <typename R = A<>> R bar(); A<> &foo() { return bar(); } It appears that we end up comparing the default argument of 'SizeType = 0' against the instantiated argument of 'int = 0'. The type of the default argument is still dependent at this point, and this patch bails out of the comparison at that point. The diagnostic we ultimately give is not that great, but maybe we can live with it: error: non-const lvalue reference to type 'A<[...], (no argument)>' cannot bind to a temporary of type 'A<[...], 0>' http://reviews.llvm.org/D15384 Files: lib/AST/ASTDiagnostic.cpp test/Misc/diag-template-diffing.cpp Index: test/Misc/diag-template-diffing.cpp =================================================================== --- test/Misc/diag-template-diffing.cpp +++ test/Misc/diag-template-diffing.cpp @@ -1274,6 +1274,16 @@ // CHECK-ELIDE-NOTREE: candidate function [with T = BoolArgumentBitExtended::BoolT<true>] not viable: no known conversion from 'BoolT<0>' to 'BoolT<1>' for 1st argument } +namespace DefaultNonTypeArgWithDependentType { +// We used to crash diffing integer template arguments when the argument type +// is dependent and default arguments were used. +template <typename SizeType = int, SizeType = 0> struct A {}; +template <typename R = A<>> R bar(); +A<> &foo() { return bar(); } +// CHECK-ELIDE-NOTREE: error: non-const lvalue reference to type 'A<[...], (no argument)>' cannot bind to a temporary of type 'A<[...], 0>' +// CHECK-NOELIDE-NOTREE: error: non-const lvalue reference to type 'A<int, (no argument)>' cannot bind to a temporary of type 'A<int, 0>' +} + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. Index: lib/AST/ASTDiagnostic.cpp =================================================================== --- lib/AST/ASTDiagnostic.cpp +++ lib/AST/ASTDiagnostic.cpp @@ -1290,14 +1290,20 @@ Int = Iter.getDesugar().getAsIntegral(); return true; case TemplateArgument::Expression: + // Fail if we can't extend or truncate. + if (IntegerType->isDependentType()) + return false; 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)) { + // Fail if we can't extend or truncate. + if (IntegerType->isDependentType()) + return false; Int = ArgExpr->EvaluateKnownConstInt(Context); Int = Int.extOrTrunc(Context.getTypeSize(IntegerType)); return true;
Index: test/Misc/diag-template-diffing.cpp =================================================================== --- test/Misc/diag-template-diffing.cpp +++ test/Misc/diag-template-diffing.cpp @@ -1274,6 +1274,16 @@ // CHECK-ELIDE-NOTREE: candidate function [with T = BoolArgumentBitExtended::BoolT<true>] not viable: no known conversion from 'BoolT<0>' to 'BoolT<1>' for 1st argument } +namespace DefaultNonTypeArgWithDependentType { +// We used to crash diffing integer template arguments when the argument type +// is dependent and default arguments were used. +template <typename SizeType = int, SizeType = 0> struct A {}; +template <typename R = A<>> R bar(); +A<> &foo() { return bar(); } +// CHECK-ELIDE-NOTREE: error: non-const lvalue reference to type 'A<[...], (no argument)>' cannot bind to a temporary of type 'A<[...], 0>' +// CHECK-NOELIDE-NOTREE: error: non-const lvalue reference to type 'A<int, (no argument)>' cannot bind to a temporary of type 'A<int, 0>' +} + // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated. // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated. Index: lib/AST/ASTDiagnostic.cpp =================================================================== --- lib/AST/ASTDiagnostic.cpp +++ lib/AST/ASTDiagnostic.cpp @@ -1290,14 +1290,20 @@ Int = Iter.getDesugar().getAsIntegral(); return true; case TemplateArgument::Expression: + // Fail if we can't extend or truncate. + if (IntegerType->isDependentType()) + return false; 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)) { + // Fail if we can't extend or truncate. + if (IntegerType->isDependentType()) + return false; Int = ArgExpr->EvaluateKnownConstInt(Context); Int = Int.extOrTrunc(Context.getTypeSize(IntegerType)); return true;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits