[cfe-dev] For Review: C++ Casting Patch

Chris Lattner clattner at apple.com
Sun Mar 30 23:43:03 PDT 2008


On Mar 28, 2008, at 10:03 PM, Bill Wendling wrote:

> Attached is my long-awaited patch to implement checking of C++  
> casting operators. It's not 100% complete, but it's a start in the  
> right direction. It checks that the reinterpret_cast, static_cast,  
> and dynamic_cast operators don't "cast away const". The const_cast  
> can, of course, do this, but only if the underlying base type is the  
> same.
>
> So a const_cast can cast from 'const double *' to 'double *', but  
> not from 'const double *' to 'float *'. Whereas a reinterpret_cast  
> can cast from 'const double *' to 'const float *', but not from  
> 'const double *' to 'float *'. Etc.
>
> Also, a reinterpret_cast cannot cast to a type that has smaller  
> precision. So you can't cast from a 'void *' to 'char'.

Some thoughts:

+    for (QualType QT = CastFrom; QT->isPointerType(); ++DepthCastFrom)
+      QT = cast<PointerType>(QT)->getPointeeType();

This isn't safe: just because something "isPointerType()" doesn't mean  
you can use cast<> (it might be a typedef).  I'd suggest:

   PointerType *PT;
   for (QualType QT = CastFrom; PT = QT->getAsPointerType(); + 
+DepthCastFrom)
     QT = PT->getPointeeType();

This occurs a couple of times.

+    if (!isa<PointerType>(To)) break;
+
+    To = cast<PointerType>(To)->getPointeeType();
+    From = cast<PointerType>(From)->getPointeeType();

Not typedef safe.

+  if (CastTo->isReferenceType() && CastFrom->isReferenceType()) {
+    QualType From = cast<ReferenceType>(CastFrom)->getReferenceeType();
+    QualType To = cast<ReferenceType>(CastTo)->getReferenceeType();

likewise.  Many other examples as well.


-  return new CXXCastExpr(Op, QualType::getFromOpaquePtr(Ty),  
(Expr*)E, OpLoc);
+
+  if (ResultTy.isNull())
+    return true;

Don't leak the argument expression if an error occurs.  You should  
'delete Exp'.



+  // TODO: Finish.

Be explicit, what is missing?  Also, tag with FIXME, not TODO.

+      Diag(OpLoc, diag::err_cannot_cast_ptr_to_smaller_integral,
+           From.getAsString(), To.getAsString(), SourceRange(OpLoc));

Why are you making a source range on OpLoc?  That seems really  
strange.  I'd suggest passing the sourcerange of "E" instead.


You pass tons of stuff into CheckReinterpretCastOperator and friends  
that isn't used, please remove the dead arguments.  The unused stuff  
should be passed into ActOnCXXCasts (because it could be implemented  
by a client that cares) but not into helpers in sema.


+    QualType QT =
+      CheckConstCastOperator(OpLoc, LAngleBracketLoc, TypeLoc,
+			     Context.getPointerType(CT),
+			     RAngleBracketLoc, LParenLoc,
+                             E, OpLoc);

Tabs.


+bool Sema::CastsNullPointer(const Expr *Exp) {
+  return Exp->isNullPointerConstant(Context);
+}

Why not just call isNullPointerConstant directly?  Also, this only has  
one call site.



+  /// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure  
we have a
+  /// constant expression of type int with a value greater than  
zero.  If the
+  /// array has an incomplete type or a valid constant size, return  
false,
+  /// otherwise emit a diagnostic and return true.
+  bool VerifyConstantArrayType(const ArrayType *ary, SourceLocation  
loc);

This is dead.

-Chris








More information about the cfe-dev mailing list