Index: cfe/trunk/docs/ReleaseNotes.rst =================================================================== --- cfe/trunk/docs/ReleaseNotes.rst +++ cfe/trunk/docs/ReleaseNotes.rst @@ -91,6 +91,9 @@ offset is nonzero. It also now warns about arithmetic on a null pointer treated as a cast from integer to pointer (GNU extension). +- ``-Wzero-as-null-pointer-constant`` was adjusted not to warn on null pointer + constants that originate from system macros, except ``NULL`` macro. + Non-comprehensive list of changes in this release ------------------------------------------------- Index: cfe/trunk/lib/Sema/Sema.cpp =================================================================== --- cfe/trunk/lib/Sema/Sema.cpp +++ cfe/trunk/lib/Sema/Sema.cpp @@ -436,12 +436,24 @@ } void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { + if (Diags.isIgnored(diag::warn_zero_as_null_pointer_constant, + E->getLocStart())) + return; + // nullptr only exists from C++11 on, so don't warn on its absence earlier. + if (!getLangOpts().CPlusPlus11) + return; + if (Kind != CK_NullToPointer && Kind != CK_NullToMemberPointer) return; if (E->IgnoreParenImpCasts()->getType()->isNullPtrType()) return; - // nullptr only exists from C++11 on, so don't warn on its absence earlier. - if (!getLangOpts().CPlusPlus11) + + // If it is a macro from system header, and if the macro name is not "NULL", + // do not warn. + SourceLocation MaybeMacroLoc = E->getLocStart(); + if (Diags.getSuppressSystemWarnings() && + SourceMgr.isInSystemMacro(MaybeMacroLoc) && + !findMacroSpelling(MaybeMacroLoc, "NULL")) return; Diag(E->getLocStart(), diag::warn_zero_as_null_pointer_constant) Index: cfe/trunk/test/SemaCXX/Inputs/warn-zero-nullptr.h =================================================================== --- cfe/trunk/test/SemaCXX/Inputs/warn-zero-nullptr.h +++ cfe/trunk/test/SemaCXX/Inputs/warn-zero-nullptr.h @@ -0,0 +1,3 @@ +#define NULL (0) +#define SYSTEM_MACRO (0) +#define OTHER_SYSTEM_MACRO (NULL) Index: cfe/trunk/test/SemaCXX/warn-zero-nullptr.cpp =================================================================== --- cfe/trunk/test/SemaCXX/warn-zero-nullptr.cpp +++ cfe/trunk/test/SemaCXX/warn-zero-nullptr.cpp @@ -1,4 +1,10 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s -Wzero-as-null-pointer-constant -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -isystem %S/Inputs -Wzero-as-null-pointer-constant -std=c++11 +// RUN: %clang_cc1 -fsyntax-only -verify %s -isystem %S/Inputs -DSYSTEM_WARNINGS -Wzero-as-null-pointer-constant -Wsystem-headers -std=c++11 + +#include + +#define MACRO (0) +#define MCRO(x) (x) struct S {}; @@ -15,8 +21,12 @@ 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 f0(void* v = MACRO); // expected-warning{{zero as null pointer constant}} +void f1(void* v = NULL); // expected-warning{{zero as null pointer constant}} +void f2(void* v = MCRO(0)); // expected-warning{{zero as null pointer constant}} +void f3(void* v = MCRO(NULL)); // expected-warning{{zero as null pointer constant}} +void f4(void* v = 0); // expected-warning{{zero as null pointer constant}} +void f5(void* v); void g() { f1(0); // expected-warning{{zero as null pointer constant}} @@ -32,3 +42,51 @@ void func() { if (nullptr == A()) {} } void func2() { if ((nullptr) == A()) {} } } + +template void TmplFunc0(T var) {} +void Func0Test() { + TmplFunc0(0); + TmplFunc0(0); // expected-warning {{zero as null pointer constant}} + TmplFunc0(0); // expected-warning {{zero as null pointer constant}} +} + +// FIXME: this one probably should not warn. +template void TmplFunc1(int a, T default_value = 0) {} // expected-warning{{zero as null pointer constant}} expected-warning{{zero as null pointer constant}} +void FuncTest() { + TmplFunc1(0); + TmplFunc1(0); // expected-note {{in instantiation of default function argument expression for 'TmplFunc1' required here}} + TmplFunc1(0); // expected-note {{in instantiation of default function argument expression for 'TmplFunc1' required here}} +} + +template +class TemplateClass0 { + public: + explicit TemplateClass0(T var) {} +}; +void TemplateClass0Test() { + TemplateClass0 a(0); + TemplateClass0 b(0); // expected-warning {{zero as null pointer constant}} + TemplateClass0 c(0); // expected-warning {{zero as null pointer constant}} +} + +template +class TemplateClass1 { + public: +// FIXME: this one should *NOT* warn. + explicit TemplateClass1(int a, T default_value = 0) {} // expected-warning{{zero as null pointer constant}} expected-warning{{zero as null pointer constant}} +}; +void IgnoreSubstTemplateType1() { + TemplateClass1 a(1); + TemplateClass1 b(1); // expected-note {{in instantiation of default function argument expression for 'TemplateClass1' required here}} + TemplateClass1 c(1); // expected-note {{in instantiation of default function argument expression for 'TemplateClass1' required here}} +} + +#ifndef SYSTEM_WARNINGS +// Do not warn on *any* other macros from system headers, even if they +// expand to/their expansion contains NULL. +void* sys_init = SYSTEM_MACRO; +void* sys_init2 = OTHER_SYSTEM_MACRO; +#else +void* sys_init = SYSTEM_MACRO; // expected-warning {{zero as null pointer constant}} +void* sys_init2 = OTHER_SYSTEM_MACRO; // expected-warning {{zero as null pointer constant}} +#endif