diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2016-07-12 17:53:16 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2016-07-12 17:53:16 +0200 |
commit | ba94c97644bf75d39eb30de30ef29b44ad83233d (patch) | |
tree | 872f9bec307ddad9b93992c291b444e28e3190fd /compilerplugins | |
parent | 46b52c22bfb6b145af3c8407fd96321381e78d99 (diff) |
loplugin:cstylecast: Better heuristic...
to determine code shared between C and C++
Change-Id: I1fadf69bf9d0a2bde527b7c3f2ec4c687d70e4ae
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/cstylecast.cxx | 68 |
1 files changed, 39 insertions, 29 deletions
diff --git a/compilerplugins/clang/cstylecast.cxx b/compilerplugins/clang/cstylecast.cxx index ae95bc2a455b..addf5edd28ba 100644 --- a/compilerplugins/clang/cstylecast.cxx +++ b/compilerplugins/clang/cstylecast.cxx @@ -8,6 +8,7 @@ */ #include <cassert> +#include <limits> #include <string> #include "plugin.hxx" @@ -74,10 +75,6 @@ bool areSimilar(QualType type1, QualType type2) { } } -bool hasCLanguageLinkageType(FunctionDecl const * decl) { - return decl->isExternC() || decl->isInExternCContext(); -} - QualType resolvePointers(QualType type) { while (type->isPointerType()) { type = type->getAs<PointerType>()->getPointeeType(); @@ -89,9 +86,7 @@ class CStyleCast: public RecursiveASTVisitor<CStyleCast>, public loplugin::Plugin { public: - explicit CStyleCast(InstantiationData const & data): - Plugin(data), externCFunction(false) - {} + explicit CStyleCast(InstantiationData const & data): Plugin(data) {} virtual void run() override { if (compiler.getLangOpts().CPlusPlus) { @@ -99,14 +94,18 @@ public: } } - bool TraverseFunctionDecl(FunctionDecl * decl); + bool TraverseLinkageSpecDecl(LinkageSpecDecl * decl); bool VisitCStyleCastExpr(const CStyleCastExpr * expr); private: bool isConstCast(QualType from, QualType to); - bool externCFunction; + bool isFromCIncludeFile(SourceLocation spellingLocation) const; + + bool isSharedCAndCppCode(SourceLocation location) const; + + unsigned int externCContexts_ = 0; }; const char * recommendedFix(clang::CastKind ck) { @@ -118,17 +117,12 @@ const char * recommendedFix(clang::CastKind ck) { } } -bool CStyleCast::TraverseFunctionDecl(FunctionDecl * decl) { - bool ext = hasCLanguageLinkageType(decl) - && decl->isThisDeclarationADefinition(); - if (ext) { - assert(!externCFunction); - externCFunction = true; - } - bool ret = RecursiveASTVisitor::TraverseFunctionDecl(decl); - if (ext) { - externCFunction = false; - } +bool CStyleCast::TraverseLinkageSpecDecl(LinkageSpecDecl * decl) { + assert(externCContexts_ != std::numeric_limits<unsigned int>::max()); //TODO + ++externCContexts_; + bool ret = RecursiveASTVisitor::TraverseLinkageSpecDecl(decl); + assert(externCContexts_ != 0); + --externCContexts_; return ret; } @@ -166,6 +160,9 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) { perf = "const_cast"; } } + if (isSharedCAndCppCode(expr->getLocStart())) { + return true; + } std::string incompFrom; std::string incompTo; if( expr->getCastKind() == CK_BitCast ) { @@ -178,15 +175,6 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) { incompTo = "incomplete "; } } - if (externCFunction || expr->getLocStart().isMacroID()) { - SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc( - expr->getLocStart()); - StringRef filename = compiler.getSourceManager().getFilename(spellingLocation); - // ignore C code - if ( filename.endswith(".h") ) { - return true; - } - } if (perf == nullptr) { perf = recommendedFix(expr->getCastKind()); } @@ -225,6 +213,28 @@ bool CStyleCast::isConstCast(QualType from, QualType to) { return areSimilar(from, to); } +bool CStyleCast::isFromCIncludeFile(SourceLocation spellingLocation) const { + return !compiler.getSourceManager().isInMainFile(spellingLocation) + && (StringRef( + compiler.getSourceManager().getPresumedLoc(spellingLocation) + .getFilename()) + .endswith(".h")); +} + +bool CStyleCast::isSharedCAndCppCode(SourceLocation location) const { + while (compiler.getSourceManager().isMacroArgExpansion(location)) { + location = compiler.getSourceManager().getImmediateMacroCallerLoc( + location); + } + // 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)); +} + loplugin::Plugin::Registration< CStyleCast > X("cstylecast"); } |