[cfe-dev] f6a164819 We don't want to throw lvalue-to-rvalue casts (...) of certain types in C++ (was: Allow implicit copy constructor (...))

John McCall rjmccall at apple.com
Sun May 4 18:54:18 PDT 2014


On May 4, 2014, at 4:53 AM, Adam Strzelecki <ono at java.pl> wrote:
> John, I kindly ask for an explanation of following change introduced by you in f6a164819:
> 
> git diff f6a164819^! lib/Sema/SemaExpr.cpp
> 
> +    // We don't want to throw lvalue-to-rvalue casts on top of
> +    // expressions of certain types in C++.
> +    if (getLangOptions().CPlusPlus &&
> +        (E->getType() == Context.OverloadTy ||
> +         T->isDependentType() ||
> +         T->isRecordType()))
> +      return;
> 
> The problem with this change is that I explicitly request to use C style assignment (ignoring constructors) on POD type variable having `pod_assign` attribute, but condition above prevents proper cast to be emitted.


It is correct language behavior that, in C++, default l-value conversions — dropping cv-qualifiers and changing the value kind — don’t generally apply to expressions of class type.  We rely on this extensively through the compiler; in particular, we assume that non-POD record types will always be copied by an CXXOperatorCallExpr or CXXConstructExpr.  So removing this will cause assertions in a number of places, and if you simply disable all those assertions, you’ll massively break C++ semantics.

I don’t think you actually need to change this in Sema, though, unless it’s critical that you don’t trigger instantiation of copy constructors and/or assignment operators.  It should be fine to proceed through type-checking normally, maybe marking a few copy expressions as special (e.g. the same way that CXXConstructExprs are marked as elidable, you could alternatively mark them as implementable with memcpy) and then adding special-case logic to IR-generation.

You’re just planning to do this for your edification, right?  I'd have strong reservations about casually accepting work like this into trunk; changing type behavior like this has some pretty serious language design repercussions.  What does it mean, exactly, to use C-style assignment on a specific variable?  Does it only affect initializations of that variable, or does it also affect assignments to it, destruction of it, reads out of it, etc.?  Does your use case really require direct language support, and if so, is there a less invasive change that would let you do the rest in a library?

John.



More information about the cfe-dev mailing list