summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compilerplugins/clang/cstylecast.cxx68
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");
}