From: Nico Weber Date: Fri, 5 May 2017 16:11:08 +0000 (+0000) Subject: Introduce Wzero-as-null-pointer-constant. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dc1f3e5a2b9639e3ceb052cd291b3cd58e7c17ae;p=clang Introduce Wzero-as-null-pointer-constant. Add an opt-in warning that fires when 0 is used as a null pointer. gcc has this warning, and there's some demand for it. https://reviews.llvm.org/D32914 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@302247 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0a80c46b7e..444dd978ae 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -8975,6 +8975,9 @@ def warn_nullability_lost : Warning< "implicit conversion from nullable pointer %0 to non-nullable pointer " "type %1">, InGroup, DefaultIgnore; +def warn_zero_as_null_pointer_constant : Warning< + "zero as null pointer constant">, + InGroup>, DefaultIgnore; def err_nullability_cs_multilevel : Error< "nullability keyword %0 cannot be applied to multi-level pointer type %1">; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index eca383bee2..e5961079f7 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3766,6 +3766,9 @@ public: void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType, SourceLocation Loc); + /// Warn when implicitly casting 0 to nullptr. + void diagnoseZeroToNullptrConversion(CastKind Kind, const Expr *E); + ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) { return DelayedDiagnostics.push(pool); } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 94e792c1d1..2f493fa5fb 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -383,6 +383,19 @@ void Sema::diagnoseNullableToNonnullConversion(QualType DstType, Diag(Loc, diag::warn_nullability_lost) << SrcType << DstType; } +void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { + if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer) + return; + if (E->getType()->isNullPtrType()) + return; + // nullptr only exists from C++11 on, so don't warn on its absence earlier. + if (!getLangOpts().CPlusPlus11) + return; + + Diag(E->getLocStart(), diag::warn_zero_as_null_pointer_constant) + << FixItHint::CreateReplacement(E->getSourceRange(), "nullptr"); +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// The result is of the given category. @@ -407,6 +420,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, #endif diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart()); + diagnoseZeroToNullptrConversion(Kind, E); QualType ExprTy = Context.getCanonicalType(E->getType()); QualType TypeTy = Context.getCanonicalType(Ty); diff --git a/test/SemaCXX/warn-zero-nullptr.cpp b/test/SemaCXX/warn-zero-nullptr.cpp new file mode 100644 index 0000000000..edd2a759b7 --- /dev/null +++ b/test/SemaCXX/warn-zero-nullptr.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -Wzero-as-null-pointer-constant -std=c++11 + +struct S {}; + +int (S::*mp0) = nullptr; +void (*fp0)() = nullptr; +void* p0 = nullptr; + +int (S::*mp1) = 0; // expected-warning{{zero as null pointer constant}} +void (*fp1)() = 0; // expected-warning{{zero as null pointer constant}} +void* p1 = 0; // expected-warning{{zero as null pointer constant}} + +// NULL is an integer constant expression, so warn on it too: +void* p2 = __null; // expected-warning{{zero as null pointer constant}} +void (*fp2)() = __null; // expected-warning{{zero as null pointer constant}} +int (S::*mp2) = __null; // expected-warning{{zero as null pointer constant}} + +void f0(void* v = 0); // expected-warning{{zero as null pointer constant}} +void f1(void* v); + +void g() { + f1(0); // expected-warning{{zero as null pointer constant}} +} + +// Warn on these too. Matches gcc and arguably makes sense. +void* pp = (decltype(nullptr))0; // expected-warning{{zero as null pointer constant}} +void* pp2 = static_cast(0); // expected-warning{{zero as null pointer constant}}