From: Richard Trieu Date: Wed, 15 Oct 2014 03:42:06 +0000 (+0000) Subject: Improvements to -Wnull-conversion X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7784ec0b8f8ff28428cc475f83bd641b030862a5;p=clang Improvements to -Wnull-conversion Split logic to separate checking function Refine the macro checking Catch nullptr->bool conversions Add some explanatory comments git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219774 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 70ead3ad09..54d7040ce2 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2490,7 +2490,7 @@ def warn_non_literal_null_pointer : Warning< "expression which evaluates to zero treated as a null pointer constant of " "type %0">, InGroup; def warn_impcast_null_pointer_to_integer : Warning< - "implicit conversion of NULL constant to %0">, + "implicit conversion of %select{NULL|nullptr}0 constant to %1">, InGroup; def warn_impcast_floating_point_to_bool : Warning< "implicit conversion turns floating-point number into bool: %0 to %1">, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index a98b87544a..fd2fa0c3f3 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -6167,6 +6167,41 @@ void CheckImplicitArgumentConversions(Sema &S, CallExpr *TheCall, } } +static void DiagnoseNullConversion(Sema &S, Expr *E, QualType T, + SourceLocation CC) { + if (S.Diags.isIgnored(diag::warn_impcast_null_pointer_to_integer, + E->getExprLoc())) + return; + + // Check for NULL (GNUNull) or nullptr (CXX11_nullptr). + const Expr::NullPointerConstantKind NullKind = + E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull); + if (NullKind != Expr::NPCK_GNUNull && NullKind != Expr::NPCK_CXX11_nullptr) + return; + + // Return if target type is a safe conversion. + if (T->isAnyPointerType() || T->isBlockPointerType() || + T->isMemberPointerType() || !T->isScalarType() || T->isNullPtrType()) + return; + + SourceLocation Loc = E->getSourceRange().getBegin(); + + // __null is usually wrapped in a macro. Go up a macro if that is the case. + if (NullKind == Expr::NPCK_GNUNull) { + if (Loc.isMacroID()) + Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; + } + + // Only warn if the null and context location are in the same macro expansion. + if (S.SourceMgr.getFileID(Loc) != S.SourceMgr.getFileID(CC)) + return; + + S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) + << (NullKind == Expr::NPCK_CXX11_nullptr) << T << clang::SourceRange(CC) + << FixItHint::CreateReplacement(Loc, + S.getFixItZeroLiteralForType(T, Loc)); +} + void CheckImplicitConversion(Sema &S, Expr *E, QualType T, SourceLocation CC, bool *ICContext = nullptr) { if (E->isTypeDependent() || E->isValueDependent()) return; @@ -6309,19 +6344,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, return; } - if ((E->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNotNull) - == Expr::NPCK_GNUNull) && !Target->isAnyPointerType() - && !Target->isBlockPointerType() && !Target->isMemberPointerType() - && Target->isScalarType() && !Target->isNullPtrType()) { - SourceLocation Loc = E->getSourceRange().getBegin(); - if (Loc.isMacroID()) - Loc = S.SourceMgr.getImmediateExpansionRange(Loc).first; - if (!Loc.isMacroID() || CC.isMacroID()) - S.Diag(Loc, diag::warn_impcast_null_pointer_to_integer) - << T << clang::SourceRange(CC) - << FixItHint::CreateReplacement(Loc, - S.getFixItZeroLiteralForType(T, Loc)); - } + DiagnoseNullConversion(S, E, T, CC); if (!Source->isIntegerType() || !Target->isIntegerType()) return; diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index 852bbba7ef..b8f0e076a2 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -90,6 +90,18 @@ void test3() { ; do ; while(NULL_COND(true)); + +#define NULL_WRAPPER NULL_COND(false) + if (NULL_WRAPPER) + ; + while (NULL_WRAPPER) + ; + for (; NULL_WRAPPER;) + ; + do + ; + while (NULL_WRAPPER); + int *ip = NULL; int (*fp)() = NULL; struct foo { @@ -137,3 +149,11 @@ namespace test6 { return NULL; } } + +namespace test7 { + bool fun() { + bool x = nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + if (nullptr) {} // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + return nullptr; // expected-warning {{implicit conversion of nullptr constant to 'bool'}} + } +} diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp index 28798a4f8c..7d765b482c 100644 --- a/test/SemaCXX/nullptr.cpp +++ b/test/SemaCXX/nullptr.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding %s +// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding -Wno-null-conversion %s #include typedef decltype(nullptr) nullptr_t;