summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2016-07-11 14:32:07 +0200
committerStephan Bergmann <sbergman@redhat.com>2016-07-11 14:32:07 +0200
commitf541b99855bd70781f8d7d655ab259ff9eb596f0 (patch)
tree162ea1823d835f484f08aaaf2390a9130a23d5e9 /compilerplugins
parent545d5157f26b7fd3c5648ae6e727b1e1addca68f (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.cxx35
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");
}