[cfe-commits] [PATCH] PR13824 warn if reinterpret_cast used for up/downcast
Alexander Zinenko
ftynse at gmail.com
Wed Mar 20 16:26:38 PDT 2013
Hello, John!
Thanks for your comments and sorry that it's taking so long to polish my
code.
Please find the updated version attached.
On 20 March 2013 07:02, John McCall <rjmccall at apple.com> wrote:
> On Mar 14, 2013, at 8:47 AM, Alexander Zinenko <ftynse at gmail.com> wrote:
>
> Thanks for review!
>
> I attached a quiet version of a patch that doesn't warn if any of the
> paths is a non-virtually-derived base at offset zero.
> During first iteration, Jordan proposed to make a separate switch to
> enable a noisy version that warns even if the cast is safe, though. If it
> is still required, it can be easily added back.
> Processing multiple base paths made checking a bit heavier, but I see no
> other approach.
>
>
> + if(!SrcRD || !SrcRD->hasDefinition())
> + return;
> +
> + const CXXRecordDecl *DestRD = DestType->getPointeeCXXRecordDecl();
> +
> + if(!DestRD || !DestRD->hasDefinition())
> + return;
>
> Please add a comment saying that we're deliberately not instantiating
> templates here because we're not allowed to.
>
Actually, we do not call CheckReinterpretCast if the cast is
type-dependent. The reason behind these checks is the following case with
forward declaration
class A;
class B {};
void foo(A *a) {
reinterpret_cast<B *>(a);
}
in which we can't examine the definition of A since we don't have it yet.
I added a comment and mentioned templates at the end though.
--
Alex
>
> Also, I think this needs to use isCompleteDefinition().
>
> On 12 March 2013 20:14, John McCall <rjmccall at apple.com> wrote:
>
>> On Mar 12, 2013, at 10:01 AM, Jordan Rose <jordan_rose at apple.com> wrote:
>> > Pinging this myself, adding Richard Smith as another reviewer. I don't
>> quite feel qualified to give the final word on it, but I'm fixing an
>> analyzer bug that's basically "don't crash when the user does this in
>> exactly the right wrong way", and it'd be nice to have a warning so that
>> they fix their code.
>>
>> +def ReinterpretUpDownCastZeroAdjustment :
>> + DiagGroup<"reinterpret-updown-zero-adjustment">;
>> +def ReinterpretUpDownCast : DiagGroup<"reinterpret-updown",
>>
>> How about -Wreinterpret-base and -Wreinterpret-primary-base?
>
> We only need reinterpret-primary-base now.
>
>
> Let's call it -Wreinterpret-base-class, actually.
>
> +def warn_reinterpret_wrong_subobject : Warning<
>> + "'reinterpret_cast' might return a pointer to wrong subobject">,
>>
>> How about "reinterpret_cast %select{from|to}3 class %0 %select{to|from}3
>> %select{virtual base|base at non-zero offset}2 %1 behaves differently from
>> static_cast"?
>>
> Fixed. Shouldn't we provide some details on what causes the difference?
>
>
> Well, my suggestion mentions that it's a virtual base or a base at a
> non-zero
> offset, but if you want something more or different, feel free.
>
>
> +static void DiagnoseReinterpretUpDownCast(Sema &Self, ExprResult &SrcExpr,
>> + QualType DestType,
>> + const SourceRange &OpRange) {
>>
>> You should take SrcExpr as a const Expr * and OpRange as a SourceRange.
>>
> Fixed.
>
>>
>> + const Type *SrcUnqualType = SrcType.getTypePtr();
>> + const Type *DestUnqualType = DestType.getTypePtr();
>>
>> This is unnecessary and also doesn't necessarily actually give you an
>> unqualified type.
>>
> Deleted.
>
>>
>> + // When casting from pointer or reference, get pointee type; use
>> original
>> + // type otherwise.
>> + const CXXRecordDecl *SrcPointeeRD =
>> SrcUnqualType->getPointeeCXXRecordDecl();
>> + const CXXRecordDecl *SrcRD =
>> + SrcPointeeRD ? SrcPointeeRD : SrcUnqualType->getAsCXXRecordDecl();
>>
>> It'd be good to remember the original non-pointer sugared types here for
>> diagnostic purposes.
>>
>> Also, at this point in semantic analysis you can differentiate between
>> the pointer and reference cases by just checking SrcExpr->isRValue().
>
> Warning "wrong cast to T*" looks clearer to me than "wrong cast to T" if
> the code is reinterpret_cast<T *>(...).
>
>
> That's fine.
>
>
>> + CXXBasePaths SrcBP, DestBP;
>> +
>> ...
>> + const ASTRecordLayout &SrcLayout =
>> Self.Context.getASTRecordLayout(SrcRD);
>> + const ASTRecordLayout &DestLayout =
>> Self.Context.getASTRecordLayout(DestRD);
>>
>> 1. Please sink this down to the point where you need it.
>> 2. Please only actually get the layout for the derived class.
>
> We actually need the layout of any derived class in the pass to process
> indirect base offsets correctly.
>
>
> Good point. But we definitely don't need the layout of the base class. :)
>
> + enum {
> + ReinterpretNormalCast = -1,
> + ReinterpretUpcast,
> + ReinterpretDowncast
> + } ReinterpretKind;
> + ReinterpretKind = ReinterpretNormalCast;
>
> You don't need ReinterpretNormalCast. Just leave it uninitialized;
> any reasonable -Wuninitialized will be able to figure out that it's
> initialized
> along every path.
>
> Otherwise, this looks great. Feel free to check in with these changes.
>
> John.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130321/26da6c29/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 13824quiet.patch
Type: application/octet-stream
Size: 16934 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130321/26da6c29/attachment.obj>
More information about the cfe-commits
mailing list