summaryrefslogtreecommitdiff
path: root/compilerplugins
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2016-07-11 16:32:28 +0200
committerStephan Bergmann <sbergman@redhat.com>2016-07-11 16:32:28 +0200
commit6f8d047519c8e80371a646ce4bad8f7304aab6ea (patch)
treef79b5a6cae706b3d4422a02bd109824eb8a2eeaa /compilerplugins
parentc726059adf71f9c812df3363b4902c52023827b6 (diff)
loplugin:salbool: Better heuristic to determine code shared between C and C++
Change-Id: I09c9c57d5adeb665cc2508fad9727085a3289bfb
Diffstat (limited to 'compilerplugins')
-rw-r--r--compilerplugins/clang/salbool.cxx40
1 files changed, 33 insertions, 7 deletions
diff --git a/compilerplugins/clang/salbool.cxx b/compilerplugins/clang/salbool.cxx
index 4b123c77b020..e5e9754d7961 100644
--- a/compilerplugins/clang/salbool.cxx
+++ b/compilerplugins/clang/salbool.cxx
@@ -9,6 +9,7 @@
#include <algorithm>
#include <cassert>
+#include <limits>
#include <set>
#include <string>
@@ -144,14 +145,19 @@ public:
bool TraverseStaticAssertDecl(StaticAssertDecl * decl);
+ bool TraverseLinkageSpecDecl(LinkageSpecDecl * decl);
+
private:
bool isFromCIncludeFile(SourceLocation spellingLocation) const;
+ bool isSharedCAndCppCode(SourceLocation location) const;
+
bool isInSpecialMainFile(SourceLocation spellingLocation) const;
bool rewrite(SourceLocation location);
std::set<VarDecl const *> varDecls_;
+ unsigned int externCContexts_ = 0;
};
void SalBool::run() {
@@ -282,10 +288,9 @@ bool SalBool::VisitCStyleCastExpr(CStyleCastExpr * expr) {
StringRef name { Lexer::getImmediateMacroName(
loc, compiler.getSourceManager(), compiler.getLangOpts()) };
if (name == "sal_False" || name == "sal_True") {
- auto callLoc = compiler.getSourceManager().getSpellingLoc(
- compiler.getSourceManager().getImmediateMacroCallerLoc(
- loc));
- if (!isFromCIncludeFile(callLoc)) {
+ auto callLoc = compiler.getSourceManager()
+ .getImmediateMacroCallerLoc(loc);
+ if (!isSharedCAndCppCode(callLoc)) {
SourceLocation argLoc;
if (compat::isMacroArgExpansion(
compiler, expr->getLocStart(), &argLoc)
@@ -301,17 +306,19 @@ bool SalBool::VisitCStyleCastExpr(CStyleCastExpr * expr) {
}
bool b = name == "sal_True";
if (rewriter != nullptr) {
+ auto callSpellLoc = compiler.getSourceManager()
+ .getSpellingLoc(callLoc);
unsigned n = Lexer::MeasureTokenLength(
- callLoc, compiler.getSourceManager(),
+ callSpellLoc, compiler.getSourceManager(),
compiler.getLangOpts());
if (StringRef(
compiler.getSourceManager().getCharacterData(
- callLoc),
+ callSpellLoc),
n)
== name)
{
return replaceText(
- callLoc, n, b ? "true" : "false");
+ callSpellLoc, n, b ? "true" : "false");
}
}
report(
@@ -725,6 +732,15 @@ bool SalBool::TraverseStaticAssertDecl(StaticAssertDecl * decl) {
|| RecursiveASTVisitor::TraverseStaticAssertDecl(decl);
}
+bool SalBool::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 SalBool::isFromCIncludeFile(SourceLocation spellingLocation) const {
return !compiler.getSourceManager().isInMainFile(spellingLocation)
&& (StringRef(
@@ -733,6 +749,16 @@ bool SalBool::isFromCIncludeFile(SourceLocation spellingLocation) const {
.endswith(".h"));
}
+bool SalBool::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));
+}
+
bool SalBool::isInSpecialMainFile(SourceLocation spellingLocation) const {
if (!compiler.getSourceManager().isInMainFile(spellingLocation)) {
return false;