[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