Kaydet (Commit) 5a9a3da7 authored tarafından Stephan Bergmann's avatar Stephan Bergmann

loplugin:nullptr

A plugin to warn about and rewrite null pointer constants that are not written
as nullptr (in C++11 code) resp. NULL (in C and C++03 code).  It is not
activated for the following reasons:

* At least the call to

  pImpl->aFmtNms.insert(pImpl->aFmtNms.begin() + nPos, nullptr);

  in svx/source/items/clipfmtitem.cxx would require
  <https://svn.boost.org/trac/boost/ticket/10540> "missing std::nullptr_t
  support in boost/type_traits/is_pointer.hpp" to be fixed first.

* Additions of code that violate the plugin would probably be frequent, causing
  unnecessary grief for those building with plugins enabled.

* It did not find anything interesting, apart from the above Boost bug and the
  mildly interesting 1da153b6 "Consistently use
  APP_WRITER as an integer, never as a nullptr."

Anyway,

  until make -O -j4 -k check; do make -O -j1 -k check \
    COMPILER_PLUGIN_TOOL=nullptr UPDATE_FILES=all; done

sucessfully executed on a recent master and resulted in

  6798 files changed, 60919 insertions(+), 60919 deletions(-)

Change-Id: I1260227949868e73fcb63fda13d83e79fde685d7
üst 48e1675c
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <cassert>
#include "compat.hxx"
#include "plugin.hxx"
namespace {
char const * kindName(Expr::NullPointerConstantKind kind) {
switch (kind) {
case Expr::NPCK_NotNull:
assert(false); // cannot happen
// fall through
case Expr::NPCK_ZeroExpression:
return "ZeroExpression";
case Expr::NPCK_ZeroLiteral:
return "ZeroLiteral";
case Expr::NPCK_CXX11_nullptr:
return "CXX11_nullptr";
case Expr::NPCK_GNUNull:
return "GNUNull";
}
}
class Nullptr:
public RecursiveASTVisitor<Nullptr>, public loplugin::RewritePlugin
{
public:
explicit Nullptr(InstantiationData const & data): RewritePlugin(data) {}
void run() override
{ TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); }
bool VisitImplicitCastExpr(CastExpr const * expr);
private:
bool isFromCIncludeFile(SourceLocation spellingLocation) const;
bool isMacroBodyExpansion(SourceLocation location) const;
void rewriteOrWarn(
Expr const & expr, char const * castKind,
Expr::NullPointerConstantKind nullPointerkind,
char const * replacement);
};
bool Nullptr::VisitImplicitCastExpr(CastExpr const * expr) {
if (ignoreLocation(expr)) {
return true;
}
switch (expr->getCastKind()) {
case CK_NullToPointer:
case CK_NullToMemberPointer:
break;
default:
return true;
}
Expr::NullPointerConstantKind k = expr->isNullPointerConstant(
compiler.getASTContext(), Expr::NPC_ValueDependentIsNotNull);
switch (k) {
case Expr::NPCK_NotNull:
k = expr->isNullPointerConstant(
compiler.getASTContext(), Expr::NPC_ValueDependentIsNull);
switch (k) {
case Expr::NPCK_NotNull:
break;
case Expr::NPCK_ZeroExpression:
case Expr::NPCK_ZeroLiteral:
report(
DiagnosticsEngine::Warning,
"suspicious ValueDependendIsNull %0", expr->getLocStart())
<< kindName(k) << expr->getSourceRange();
break;
default:
assert(false); // cannot happen
}
break;
case Expr::NPCK_CXX11_nullptr:
break;
default:
{
Expr const * e = expr->getSubExpr();
SourceLocation loc;
for (;;) {
e = e->IgnoreImpCasts();
loc = e->getLocStart();
while (compiler.getSourceManager().isMacroArgExpansion(loc)) {
loc = compiler.getSourceManager()
.getImmediateMacroCallerLoc(
loc);
}
if (isMacroBodyExpansion(loc)) {
if (Lexer::getImmediateMacroName(
loc, compiler.getSourceManager(),
compiler.getLangOpts())
== "NULL")
{
if (!compiler.getLangOpts().CPlusPlus) {
return true;
}
loc = compiler.getSourceManager()
.getImmediateExpansionRange(loc).first;
if (isInUnoIncludeFile(
compiler.getSourceManager().getSpellingLoc(loc))
|| isFromCIncludeFile(
compiler.getSourceManager().getSpellingLoc(
loc)))
{
return true;
}
} else if (ignoreLocation(
compiler.getSourceManager().getSpellingLoc(
loc)))
{
return true;
}
}
ParenExpr const * pe = dyn_cast<ParenExpr>(e);
if (pe == nullptr) {
break;
}
e = pe->getSubExpr();
}
rewriteOrWarn(
*e, expr->getCastKindName(), k,
((!compiler.getLangOpts().CPlusPlus
|| isInUnoIncludeFile(
compiler.getSourceManager().getSpellingLoc(loc))
|| isFromCIncludeFile(
compiler.getSourceManager().getSpellingLoc(loc)))
? "NULL" : "nullptr"));
}
break;
}
return true;
}
bool Nullptr::isFromCIncludeFile(SourceLocation spellingLocation) const {
return !compat::isInMainFile(compiler.getSourceManager(), spellingLocation)
&& (StringRef(
compiler.getSourceManager().getPresumedLoc(spellingLocation)
.getFilename())
.endswith(".h"));
}
bool Nullptr::isMacroBodyExpansion(SourceLocation location) const {
#if (__clang_major__ == 3 && __clang_minor__ >= 3) || __clang_major__ > 3
return compiler.getSourceManager().isMacroBodyExpansion(location);
#else
return location.isMacroID()
&& !compiler.getSourceManager().isMacroArgExpansion(location);
#endif
}
void Nullptr::rewriteOrWarn(
Expr const & expr, char const * castKind,
Expr::NullPointerConstantKind nullPointerKind, char const * replacement)
{
if (rewriter != nullptr) {
SourceLocation locStart(expr.getLocStart());
while (compiler.getSourceManager().isMacroArgExpansion(locStart)) {
locStart = compiler.getSourceManager()
.getImmediateMacroCallerLoc(locStart);
}
if (compiler.getLangOpts().CPlusPlus && isMacroBodyExpansion(locStart)
&& (Lexer::getImmediateMacroName(
locStart, compiler.getSourceManager(),
compiler.getLangOpts())
== "NULL"))
{
locStart = compiler.getSourceManager().getImmediateExpansionRange(
locStart).first;
}
SourceLocation locEnd(expr.getLocEnd());
while (compiler.getSourceManager().isMacroArgExpansion(locEnd)) {
locEnd = compiler.getSourceManager()
.getImmediateMacroCallerLoc(locEnd);
}
if (compiler.getLangOpts().CPlusPlus && isMacroBodyExpansion(locEnd)
&& (Lexer::getImmediateMacroName(
locEnd, compiler.getSourceManager(),
compiler.getLangOpts())
== "NULL"))
{
locEnd = compiler.getSourceManager().getImmediateExpansionRange(
locEnd).first;
}
if (replaceText(SourceRange(compiler.getSourceManager().getSpellingLoc(locStart), compiler.getSourceManager().getSpellingLoc(locEnd)), replacement)) {
return;
}
}
report(
DiagnosticsEngine::Warning, "%0 ValueDependendIsNotNull %1 -> %2",
expr.getLocStart())
<< castKind << kindName(nullPointerKind) << replacement
<< expr.getSourceRange();
}
loplugin::Plugin::Registration<Nullptr> X("nullptr", true);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment