loplugin:cstylecast: Better heuristic...
to determine code shared between C and C++ Change-Id: I1fadf69bf9d0a2bde527b7c3f2ec4c687d70e4ae
This commit is contained in:
parent
46b52c22bf
commit
ba94c97644
@ -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");
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user