Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -7760,6 +7760,9 @@ "format specifies type %0 but the argument has " "%select{type|underlying type}2 %1">, InGroup; +def warn_pointer_to_bool : Warning< + "passing %0 as a boolean">, + InGroup; def warn_format_argument_needs_cast : Warning< "%select{values of type|enum values with underlying type}2 '%0' should not " "be used as format arguments; add an explicit cast to %1 instead">, Index: lib/Sema/SemaChecking.cpp =================================================================== --- lib/Sema/SemaChecking.cpp +++ lib/Sema/SemaChecking.cpp @@ -2545,6 +2545,27 @@ } } +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +void DiagnoseImpCast(Sema &S, const Expr *E, QualType SourceType, QualType T, + SourceLocation CContext, unsigned diag, + bool pruneControlFlow = false) { + if (pruneControlFlow) { + S.DiagRuntimeBehavior(E->getExprLoc(), E, + S.PDiag(diag) + << SourceType << T << E->getSourceRange() + << SourceRange(CContext)); + return; + } + S.Diag(E->getExprLoc(), diag) + << SourceType << T << E->getSourceRange() << SourceRange(CContext); +} + +/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. +void DiagnoseImpCast(Sema &S, const Expr *E, QualType T, SourceLocation CContext, + unsigned diag, bool pruneControlFlow = false) { + DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); +} + /// Handles the checks for format strings, non-POD arguments to vararg /// functions, NULL arguments passed to non-NULL parameters, and diagnose_if /// attributes. @@ -2589,6 +2610,28 @@ } } + if (FD) { + for (unsigned ArgIdx = 0; ArgIdx < Args.size(); ++ArgIdx) { + // Args[ArgIdx] can be null in malformed code. + if (const Expr *Arg = Args[ArgIdx]) { + if (auto C = dyn_cast(Arg)) { + if (C->getCastKind() == CK_PointerToBoolean) { + if (auto ICast = dyn_cast(C->getSubExpr())) { + if (ICast->getCastKind() == CK_LValueToRValue) { + const Expr *Pointer = ICast->getSubExpr(); + QualType QT = Pointer->getType()->getPointeeType(); + if (!QT.isNull() && QT->isBooleanType()) + // Warn on bool* to bool conversion. + DiagnoseImpCast(*this, Pointer, QT, Arg->getLocStart(), + diag::warn_pointer_to_bool); + } + } + } + } + } + } + } + if (FDecl || Proto) { CheckNonNullArguments(*this, FDecl, Proto, Args, Loc); @@ -8941,27 +8984,6 @@ AnalyzeImplicitConversions(S, E->getRHS(), E->getOperatorLoc()); } -/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. -void DiagnoseImpCast(Sema &S, Expr *E, QualType SourceType, QualType T, - SourceLocation CContext, unsigned diag, - bool pruneControlFlow = false) { - if (pruneControlFlow) { - S.DiagRuntimeBehavior(E->getExprLoc(), E, - S.PDiag(diag) - << SourceType << T << E->getSourceRange() - << SourceRange(CContext)); - return; - } - S.Diag(E->getExprLoc(), diag) - << SourceType << T << E->getSourceRange() << SourceRange(CContext); -} - -/// Diagnose an implicit cast; purely a helper for CheckImplicitConversion. -void DiagnoseImpCast(Sema &S, Expr *E, QualType T, SourceLocation CContext, - unsigned diag, bool pruneControlFlow = false) { - DiagnoseImpCast(S, E, E->getType(), T, CContext, diag, pruneControlFlow); -} - /// Diagnose an implicit cast from a floating point value to an integer value. void DiagnoseFloatingImpCast(Sema &S, Expr *E, QualType T, Index: test/SemaCXX/warn-bool-ptr-to-bool.cpp =================================================================== --- /dev/null +++ test/SemaCXX/warn-bool-ptr-to-bool.cpp @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +int foo(bool *b) { + if (b) // no-warning + return 10; + return 0; +} + +int bar(bool b) { + return b; +} + +int baz() { + bool *b; + bar(b); + // expected-warning@-1 {{passing 'bool *' as a boolean}} + return 0; +} + +template +T foo1(T *ptr) { + return ptr ? *ptr : T{}; // no-warning +} + +bool bar1(bool *ptr) { + return foo1(ptr); +} +