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 <cassert>
|
||||||
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "plugin.hxx"
|
#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) {
|
QualType resolvePointers(QualType type) {
|
||||||
while (type->isPointerType()) {
|
while (type->isPointerType()) {
|
||||||
type = type->getAs<PointerType>()->getPointeeType();
|
type = type->getAs<PointerType>()->getPointeeType();
|
||||||
@ -89,9 +86,7 @@ class CStyleCast:
|
|||||||
public RecursiveASTVisitor<CStyleCast>, public loplugin::Plugin
|
public RecursiveASTVisitor<CStyleCast>, public loplugin::Plugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CStyleCast(InstantiationData const & data):
|
explicit CStyleCast(InstantiationData const & data): Plugin(data) {}
|
||||||
Plugin(data), externCFunction(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual void run() override {
|
virtual void run() override {
|
||||||
if (compiler.getLangOpts().CPlusPlus) {
|
if (compiler.getLangOpts().CPlusPlus) {
|
||||||
@ -99,14 +94,18 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TraverseFunctionDecl(FunctionDecl * decl);
|
bool TraverseLinkageSpecDecl(LinkageSpecDecl * decl);
|
||||||
|
|
||||||
bool VisitCStyleCastExpr(const CStyleCastExpr * expr);
|
bool VisitCStyleCastExpr(const CStyleCastExpr * expr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool isConstCast(QualType from, QualType to);
|
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) {
|
const char * recommendedFix(clang::CastKind ck) {
|
||||||
@ -118,17 +117,12 @@ const char * recommendedFix(clang::CastKind ck) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CStyleCast::TraverseFunctionDecl(FunctionDecl * decl) {
|
bool CStyleCast::TraverseLinkageSpecDecl(LinkageSpecDecl * decl) {
|
||||||
bool ext = hasCLanguageLinkageType(decl)
|
assert(externCContexts_ != std::numeric_limits<unsigned int>::max()); //TODO
|
||||||
&& decl->isThisDeclarationADefinition();
|
++externCContexts_;
|
||||||
if (ext) {
|
bool ret = RecursiveASTVisitor::TraverseLinkageSpecDecl(decl);
|
||||||
assert(!externCFunction);
|
assert(externCContexts_ != 0);
|
||||||
externCFunction = true;
|
--externCContexts_;
|
||||||
}
|
|
||||||
bool ret = RecursiveASTVisitor::TraverseFunctionDecl(decl);
|
|
||||||
if (ext) {
|
|
||||||
externCFunction = false;
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,6 +160,9 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) {
|
|||||||
perf = "const_cast";
|
perf = "const_cast";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (isSharedCAndCppCode(expr->getLocStart())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
std::string incompFrom;
|
std::string incompFrom;
|
||||||
std::string incompTo;
|
std::string incompTo;
|
||||||
if( expr->getCastKind() == CK_BitCast ) {
|
if( expr->getCastKind() == CK_BitCast ) {
|
||||||
@ -178,15 +175,6 @@ bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) {
|
|||||||
incompTo = "incomplete ";
|
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) {
|
if (perf == nullptr) {
|
||||||
perf = recommendedFix(expr->getCastKind());
|
perf = recommendedFix(expr->getCastKind());
|
||||||
}
|
}
|
||||||
@ -225,6 +213,28 @@ bool CStyleCast::isConstCast(QualType from, QualType to) {
|
|||||||
return areSimilar(from, 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");
|
loplugin::Plugin::Registration< CStyleCast > X("cstylecast");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user