loplugin:nullptr: Better heuristic to determine code shared between C and C++

Change-Id: I51e1c5fa4639e51fac90f92adf3d87d12960d589
This commit is contained in:
Stephan Bergmann
2016-07-11 14:32:07 +02:00
parent 545d5157f2
commit f541b99855
21 changed files with 100 additions and 71 deletions

View File

@@ -9,6 +9,7 @@
#include <cassert>
#include <cstdlib>
#include <limits>
#include <set>
#include "plugin.hxx"
@@ -59,6 +60,8 @@ public:
bool TraverseConstructorInitializer(CXXCtorInitializer * init);
bool TraverseLinkageSpecDecl(LinkageSpecDecl * decl);
// bool shouldVisitTemplateInstantiations() const { return true; }
private:
@@ -66,6 +69,8 @@ private:
bool isFromCIncludeFile(SourceLocation spellingLocation) const;
bool isSharedCAndCppCode(SourceLocation location) const;
void visitCXXCtorInitializer(CXXCtorInitializer const * init);
void handleZero(Expr const * expr);
@@ -80,6 +85,7 @@ private:
char const * replacement);
std::set<Expr const *> gnuNulls_;
unsigned int externCContexts_ = 0;
};
bool Nullptr::VisitImplicitCastExpr(CastExpr const * expr) {
@@ -202,6 +208,15 @@ bool Nullptr::TraverseConstructorInitializer(CXXCtorInitializer * init) {
return RecursiveASTVisitor::TraverseConstructorInitializer(init);
}
bool Nullptr::TraverseLinkageSpecDecl(LinkageSpecDecl * decl) {
assert(externCContexts_ != std::numeric_limits<unsigned int>::max()); //TODO
++externCContexts_;
bool ret = RecursiveASTVisitor::TraverseLinkageSpecDecl(decl);
assert(externCContexts_ != 0);
--externCContexts_;
return ret;
}
bool Nullptr::isInLokIncludeFile(SourceLocation spellingLocation) const {
return compiler.getSourceManager().getFilename(spellingLocation)
.startswith(SRCDIR "/include/LibreOfficeKit/");
@@ -215,6 +230,16 @@ bool Nullptr::isFromCIncludeFile(SourceLocation spellingLocation) const {
.endswith(".h"));
}
bool Nullptr::isSharedCAndCppCode(SourceLocation location) const {
// Assume that code is intended to be shared between C and C++ if it comes
// from an include file ending in .h, and is either in an extern "C" context
// or the body of a macro definition:
return
isFromCIncludeFile(compiler.getSourceManager().getSpellingLoc(location))
&& (externCContexts_ != 0
|| compiler.getSourceManager().isMacroBodyExpansion(location));
}
void Nullptr::visitCXXCtorInitializer(CXXCtorInitializer const * init) {
if (!init->isWritten()) {
return;
@@ -273,12 +298,16 @@ void Nullptr::handleNull(
}
loc = compiler.getSourceManager()
.getImmediateExpansionRange(loc).first;
if (ignoreLocation(
compiler.getSourceManager().getSpellingLoc(loc)))
{
return;
}
if (isInUnoIncludeFile(
compiler.getSourceManager().getSpellingLoc(loc))
|| isInLokIncludeFile(
compiler.getSourceManager().getSpellingLoc(loc))
|| isFromCIncludeFile(
compiler.getSourceManager().getSpellingLoc(loc)))
|| isSharedCAndCppCode(loc))
{
//TODO: if !castKind, warn if NULL is passed into fn call
// ellipsis, cast to void*
@@ -309,7 +338,7 @@ void Nullptr::handleNull(
auto const asMacro = !compiler.getLangOpts().CPlusPlus
|| isInUnoIncludeFile(compiler.getSourceManager().getSpellingLoc(loc))
|| isInLokIncludeFile(compiler.getSourceManager().getSpellingLoc(loc))
|| isFromCIncludeFile(compiler.getSourceManager().getSpellingLoc(loc));
|| isSharedCAndCppCode(loc);
assert(!asMacro || nullPointerKind != Expr::NPCK_GNUNull);
rewriteOrWarn(e, castKind, nullPointerKind, asMacro ? "NULL" : "nullptr");
}