diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2016-07-11 14:32:07 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2016-07-11 14:32:07 +0200 |
commit | f541b99855bd70781f8d7d655ab259ff9eb596f0 (patch) | |
tree | 162ea1823d835f484f08aaaf2390a9130a23d5e9 /compilerplugins | |
parent | 545d5157f26b7fd3c5648ae6e727b1e1addca68f (diff) |
loplugin:nullptr: Better heuristic to determine code shared between C and C++
Change-Id: I51e1c5fa4639e51fac90f92adf3d87d12960d589
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/nullptr.cxx | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/compilerplugins/clang/nullptr.cxx b/compilerplugins/clang/nullptr.cxx index 8250d519abdd..0ebbcde832f4 100644 --- a/compilerplugins/clang/nullptr.cxx +++ b/compilerplugins/clang/nullptr.cxx @@ -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"); } |