[cfe-commits] [PATCH] Warning for suspicious implicit conversions from floating point to bool
Hans Wennborg
hans at chromium.org
Thu Aug 23 09:04:36 PDT 2012
On Thu, Aug 23, 2012 at 2:48 PM, Andreas Eckleder <aeckleder at google.com> wrote:
> Hi Hans,
>
> Thank you very much for the review. I have reworked my code according to
> your suggestions.
Thanks! I think it's much clearer now.
I noticed that there seems to be trailing whitespace on some of the
lines. The rest of my comments are inline below.
> +++ b/include/clang/Basic/DiagnosticGroups.td
> +def ImplicitConversionFloatingPointToBool : DiagGroup<"implicit-conversion-floating-point-to-bool">;
I see that there are other lines in this file that are 80+ columns,
but I also see some like this that are wrapped, e.g.
ImplicitFallthroughPerFunction, so I think wrapping this line after
the ':' would better.
> +++ b/lib/Sema/SemaChecking.cpp
> +static bool IsImplicitBoolFloatConversion(Sema &S, Expr *Ex, bool ToBool) {
I'm not super happy about the ToBool parameter here and the logic
where it's used in the function below. I was thinking that if the
function could just take the source and target builtin types as
parameters, the function could be written as:
- Check that the expression is a cast
- Get the QualTypes for the outer and inner expressions
- return TypeA->isSpecificBuiltinType(SrcTy) &&
TypeB->isSpecificBuiltinType(DstTy); (I don't think you need to check
that they're builtins first; i believe isSpecificBuiltinType will
return false if they're not.)
> + Expr *InnerE = Ex->IgnoreParenImpCasts();
> + const Type *Target = S.Context.getCanonicalType(Ex->getType()).getTypePtr();
> + const Type *Source =
> + S.Context.getCanonicalType(InnerE->getType()).getTypePtr();
I don't think getTypePtr() is needed; working with the QualType
objects should work just as well.
> + if (Target == Source)
Isn't this check redundant based on the code below?
> + const BuiltinType *FloatCandidateBT =
> + dyn_cast<BuiltinType>(ToBool ? Source : Target);
> + const Type *BoolCandidateType = ToBool ? Target : Source;
This is the part that I find confusing.
> +void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall,
> + SourceLocation CC) {
> + unsigned NumArgs = TheCall->getNumArgs();
> + for (unsigned i = 0; i < NumArgs; ++i) {
> + Expr *CurrA = TheCall->getArg(i);
> + if (!isa<ImplicitCastExpr>(CurrA))
This if statement is redundant since you have the same check inside
IsImplicitBoolFloatConversion.
> + bool IsSwapped = ((i > 0) &&
> + IsImplicitBoolFloatConversion(S,TheCall->getArg(i - 1), false));
I think this should be indented two spaces more, and there should be a
space after the S argument. The same applies below.
> + IsSwapped |= ((i < (NumArgs - 1)) &&
> + IsImplicitBoolFloatConversion(S,TheCall->getArg(i + 1), false));
> + if (IsSwapped)
The lack of braces around the if statement makes me nervous even
though I know that it should work :)
> + // Warn on this floating-point to bool conversion
> + DiagnoseImpCast(S, CurrA->IgnoreParenImpCasts(),
> + CurrA->getType(), CC,
> + diag::warn_impcast_floating_point_to_bool);
> + }
> +}
> +
> @@ -4488,6 +4531,26 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
> }
> }
>
> + // If the target is bool, warn if expr is a function or method call
I like periods at the end of comments. This applies below as well. And
I don't think there's any need to distinguish between function and
method calls; just call expression is fine.
> + if (Target->isSpecificBuiltinType(BuiltinType::Bool) &&
> + isa<CallExpr>(E)) {
> + // Check last argument of function or method call to see if it is an
> + // implicit cast from a type matching the type the method result
> + // is being cast to
> + CallExpr *CEx = static_cast<CallExpr*>(E);
I think this static_cast<> should be a cast<>. See
http://llvm.org/docs/ProgrammersManual.html#isa
> + // Check implicit argument conversions for function calls
> + if (isa<CallExpr>(E))
> + CheckImplicitArgumentConversions(S, static_cast<CallExpr*>(E), CC);
Instead of isa<> and then static_cast<> (which should be cast<>
really), I think it's more common to do:
if (CallExpr *Call = dyn_cast<CallExpr>(E))
CheckImplicitConversion(S, Call, CC);
> +// RUN: %clang_cc1 -x c++ -verify -fsyntax-only -Wimplicit-conversion-floating-point-to-bool %s
I don't think '-x c++' is necessary; Clang will pick it up based on
the file extension.
> +float foof (float x);
> +double food (double x);
> +void foo (bool b, float f);
Having a space between the function name and the '(' looks a little
unusual. I don't think there's any reason to line up the functions
this way.
> + b = foof(c < 1); // expected-warning {{implicit conversion turns floating-point number into bool: 'float' to 'bool'}}
Hmm, so I guess this won't warn in C, where the type of 'c < 1' is int
rather than bool? Might not be a big deal, but it seems a little
unfortunate.
More information about the cfe-commits
mailing list