From ed75aa271956824c89b7c9df2c06e4ad09a74734 Mon Sep 17 00:00:00 2001 From: Noel Grandin Date: Thu, 28 Aug 2014 08:58:48 +0200 Subject: create clang plugin to warn about C-style casts We don't like C-style casts in our nice C++ code Change-Id: I94e7ec90de9275cd6e20c4146d4f3a74bed93c9d Reviewed-on: https://gerrit.libreoffice.org/10367 Reviewed-by: Stephan Bergmann Reviewed-by: Norbert Thiebaud Tested-by: Norbert Thiebaud --- compilerplugins/clang/cstylecast.cxx | 88 ++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 compilerplugins/clang/cstylecast.cxx (limited to 'compilerplugins') diff --git a/compilerplugins/clang/cstylecast.cxx b/compilerplugins/clang/cstylecast.cxx new file mode 100644 index 000000000000..5183e26ff27e --- /dev/null +++ b/compilerplugins/clang/cstylecast.cxx @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include +#include "plugin.hxx" +#include "compat.hxx" + +// +// We don't like using C-style casts in C++ code +// + +namespace { + +class CStyleCast: + public RecursiveASTVisitor, public loplugin::Plugin +{ +public: + explicit CStyleCast(InstantiationData const & data): Plugin(data) {} + + virtual void run() override { TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); } + + bool VisitCStyleCastExpr(const CStyleCastExpr * expr); +}; + +static const char * recommendedFix(clang::CastKind ck) { + switch(ck) { + case CK_IntegralToPointer: return "reinterpret_cast"; + case CK_PointerToIntegral: return "reinterpret_cast"; + case CK_BaseToDerived: return "static_cast"; + default: return "???"; + } +} + +bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) { + if (ignoreLocation(expr)) { + return true; + } + // casting to void is typically used when a parameter or field is only used in + // debug mode, and we want to eliminate an "unused" warning + if( expr->getCastKind() == CK_ToVoid ) { + return true; + } + // ignore integral-type conversions for now, there is unsufficient agreement about + // the merits of C++ style casting in this case + if( expr->getCastKind() == CK_IntegralCast ) { + return true; + } + if( expr->getCastKind() == CK_NoOp ) { + return true; + } + // ignore pointer-type conversions for now + if( expr->getCastKind() == CK_BitCast ) { + return true; + } + SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc( + expr->getLocStart()); + StringRef filename = compiler.getSourceManager().getFilename(spellingLocation); + // ignore C code + if ( filename.endswith(".h") || filename.endswith(".c") ) { + return true; + } + if ( compat::isInMainFile(compiler.getSourceManager(), spellingLocation) + ? (filename.startswith(SRCDIR "/sal")) // sal has tons of weird stuff going on that I don't understand enough to fix + : (filename.startswith(SRCDIR "/include/tools/solar.h")) ) { + return true; + } + report( + DiagnosticsEngine::Warning, + "c-style cast, type=%0, from=%1, recommendedFix=%2", + expr->getSourceRange().getBegin()) + << expr->getCastKind() + << expr->getSubExprAsWritten()->getType() + << recommendedFix(expr->getCastKind()) + << expr->getSourceRange(); + return true; +} + +loplugin::Plugin::Registration< CStyleCast > X("cstylecast"); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit