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
llvm-svn: 302247
"implicit conversion from nullable pointer %0 to non-nullable pointer "
"type %1">,
InGroup<NullableToNonNullConversion>, DefaultIgnore;
+def warn_zero_as_null_pointer_constant : Warning<
+ "zero as null pointer constant">,
+ InGroup<DiagGroup<"zero-as-null-pointer-constant">>, DefaultIgnore;
def err_nullability_cs_multilevel : Error<
"nullability keyword %0 cannot be applied to multi-level pointer type %1">;
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);
}
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.
#endif
diagnoseNullableToNonnullConversion(Ty, E->getType(), E->getLocStart());
+ diagnoseZeroToNullptrConversion(Kind, E);
QualType ExprTy = Context.getCanonicalType(E->getType());
QualType TypeTy = Context.getCanonicalType(Ty);
--- /dev/null
+// 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<decltype(nullptr)>(0); // expected-warning{{zero as null pointer constant}}