[PATCH] An lvalue-to-rvalue conversion should be supported in case of a non-volatile glvalue that refers to a non-volatile object defined with constexpr.

Richard Smith richard at metafoo.co.uk
Wed Nov 20 11:59:24 PST 2013


On Tue, Nov 19, 2013 at 10:18 PM, Karthik Bhat <kv.bhat at samsung.com> wrote:

> Hi rsmith,
>
> Hi All,Richard,
> I would like to get few inputs regarding the issue mentioned below.
> Clang fails to compile gcc test case constexpr-initlist2.C with c++11 (
> http://searchcode.com/codesearch/view/8022759)
>
> lvalue-to-rvalue conversion seems to be failing.
>
> As per standard [expr.const] -
> an lvalue-to-rvalue conversion [is not allowed unless it applies to]
> [....]
> — a non-volatile glvalue that refers to a non-volatile object defined with
> constexpr, or that refers
> to a non-mutable sub-object of such an object
>

This does not apply to your testcase. The testcase creates, and tries to
read from, an array temporary (which is not a non-volatile object defined
with 'constexpr' nor a subobject thereof).

[....]
>
> Hence as per standard it seems clang should be able to compile the above
> code(constexpr-initlist2.C)
>
> The problem seems we are not handling this case on ExprConstant
> findCompleteObject function. Added a patch to fix the same.
> I would like to get inputs from community if this is  the right approach?
> Will update/add the test case in case the approach is correct.
>
> Thanks
> Karthik Bhat
>
> http://llvm-reviews.chandlerc.com/D2226
>
> Files:
>   lib/AST/ExprConstant.cpp
>
> Index: lib/AST/ExprConstant.cpp
> ===================================================================
> --- lib/AST/ExprConstant.cpp
> +++ lib/AST/ExprConstant.cpp
> @@ -2503,6 +2503,9 @@
>          //   [...]
>          //   - a [...] glvalue of literal type that refers to a
> non-volatile
>          //     object whose lifetime began within the evaluation of e.
> +        //   [...]
> +        //   - a [...] glvalue that refers to a non-volatile object
> +        //     defined with constexpr
>          //
>          // C++11 misses the 'began within the evaluation of e' check and
>          // instead allows all temporaries, including things like:
>

This text explains what we're doing here, and why.


> @@ -2512,8 +2515,10 @@
>          // Therefore we use the C++1y rules in C++11 too.
>          const ValueDecl *VD = Info.EvaluatingDecl.dyn_cast<const
> ValueDecl*>();
>          const ValueDecl *ED = MTE->getExtendingDecl();
> +        const VarDecl* VarD  = dyn_cast<const VarDecl>(ED);
>          if (!(BaseType.isConstQualified() &&
>                BaseType->isIntegralOrEnumerationType()) &&
> +            !(VarD && VarD->isConstexpr()) &&
>              !(VD && VD->getCanonicalDecl() == ED->getCanonicalDecl())) {
>            Info.Diag(E, diag::note_constexpr_access_static_temporary, 1)
> << AK;
>            Info.Note(MTE->getExprLoc(),
> diag::note_constexpr_temporary_here);
>

That change is not correct; it allows this:

  constexpr int &&r = 0;
  ++r;
  constexpr int n = r; // would have value 0 with your patch
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131120/866e8ecd/attachment.html>


More information about the cfe-commits mailing list