[clang] 13fa4e2 - PR42108 Consistently diagnose binding a reference template parameter to
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 19 18:16:52 PST 2020
Author: Richard Smith
Date: 2020-01-19T18:16:36-08:00
New Revision: 13fa4e2e5ae6ab5403be19e24415e0c7a5569681
URL: https://github.com/llvm/llvm-project/commit/13fa4e2e5ae6ab5403be19e24415e0c7a5569681
DIFF: https://github.com/llvm/llvm-project/commit/13fa4e2e5ae6ab5403be19e24415e0c7a5569681.diff
LOG: PR42108 Consistently diagnose binding a reference template parameter to
a temporary.
We previously failed to materialize a temporary when performing an
implicit conversion to a reference type, resulting in our thinking the
argument was a value rather than a reference in some cases.
Added:
Modified:
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 192c237b6c1c..b609bd904cee 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3866,7 +3866,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
ICS.DiagnoseAmbiguousConversion(*this, From->getExprLoc(),
PDiag(diag::err_typecheck_ambiguous_condition)
<< From->getSourceRange());
- return ExprError();
+ return ExprError();
case ImplicitConversionSequence::EllipsisConversion:
llvm_unreachable("Cannot perform an ellipsis conversion");
@@ -4349,6 +4349,16 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
VK_RValue, nullptr, CCK).get();
}
+ // Materialize a temporary if we're implicitly converting to a reference
+ // type. This is not required by the C++ rules but is necessary to maintain
+ // AST invariants.
+ if (ToType->isReferenceType() && From->isRValue()) {
+ ExprResult Res = TemporaryMaterializationConversion(From);
+ if (Res.isInvalid())
+ return ExprError();
+ From = Res.get();
+ }
+
// If this conversion sequence succeeded and involved implicitly converting a
// _Nullable type to a _Nonnull one, complain.
if (!isCast(CCK))
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 661a66246a53..2d87e7b367f3 100755
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -6670,7 +6670,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- a predefined __func__ variable
APValue::LValueBase Base = Value.getLValueBase();
auto *VD = const_cast<ValueDecl *>(Base.dyn_cast<const ValueDecl *>());
- if (Base && !VD) {
+ if (Base && (!VD || isa<LifetimeExtendedTemporaryDecl>(VD))) {
auto *E = Base.dyn_cast<const Expr *>();
if (E && isa<CXXUuidofExpr>(E)) {
Converted = TemplateArgument(ArgResult.get()->IgnoreImpCasts());
diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index 7232598215ac..253ad7bc5606 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
@@ -434,3 +434,17 @@ namespace VoidPtr {
int n;
template void f<(void*)&n>();
}
+
+namespace PR42108 {
+ struct R {};
+ struct S { constexpr S() {} constexpr S(R) {} };
+ struct T { constexpr operator S() { return {}; } };
+ template <const S &> struct A {};
+ void f() {
+ A<R{}>(); // expected-error {{would bind reference to a temporary}}
+ A<S{}>(); // expected-error {{non-type template argument is not a constant expression}} expected-note 2{{temporary}}
+ // FIXME: We could diagnose this better if we treated this as not binding
+ // directly. It's unclear whether that's the intent.
+ A<T{}>(); // expected-error {{non-type template argument is not a constant expression}} expected-note 2{{temporary}}
+ }
+}
More information about the cfe-commits
mailing list