diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2018-04-03 11:56:52 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2018-04-03 14:54:55 +0200 |
commit | 0e493cae407cca65f58329b3319d9c836cdf5096 (patch) | |
tree | 97e90d58ea005ec20b0197f2c1663ae6275cbd4e /compilerplugins | |
parent | b76037f44660808a978ff39864769a5621eab893 (diff) |
new loplugin:dbgunhandledexception
enforce that DBG_UNHANDLED_EXCEPTION is called first in a catch block,
otherwise it cannot do it's job properly
Change-Id: I906436c6861212c44f8f21552ccbceb54f15c6e1
Reviewed-on: https://gerrit.libreoffice.org/52303
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'compilerplugins')
-rw-r--r-- | compilerplugins/clang/dbgunhandledexception.cxx | 107 | ||||
-rw-r--r-- | compilerplugins/clang/test/dbgunhandledexception.cxx | 37 |
2 files changed, 144 insertions, 0 deletions
diff --git a/compilerplugins/clang/dbgunhandledexception.cxx b/compilerplugins/clang/dbgunhandledexception.cxx new file mode 100644 index 000000000000..54b00f57f758 --- /dev/null +++ b/compilerplugins/clang/dbgunhandledexception.cxx @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * Based on LLVM/Clang. + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + */ + +#include "check.hxx" +#include "plugin.hxx" +#include <clang/Lex/Lexer.h> +#include <fstream> +#include <set> + +namespace loplugin +{ +/* +This is a compile check. + +Check that DBG_UNHANDLED_EXCEPTION is always the first statement in a catch block, otherwise +it does not work properly. +*/ + +class DbgUnhandledException : public RecursiveASTVisitor<DbgUnhandledException>, public Plugin +{ +public: + explicit DbgUnhandledException(InstantiationData const& data); + virtual void run() override; + bool VisitCallExpr(CallExpr const* call); + bool TraverseCXXCatchStmt(CXXCatchStmt*); + +private: + CXXCatchStmt const* currCatchStmt = nullptr; +}; + +DbgUnhandledException::DbgUnhandledException(const InstantiationData& data) + : Plugin(data) +{ +} + +void DbgUnhandledException::run() +{ + TraverseDecl(compiler.getASTContext().getTranslationUnitDecl()); +} + +bool DbgUnhandledException::TraverseCXXCatchStmt(CXXCatchStmt* catchStmt) +{ + auto prevCatchStmt = currCatchStmt; + currCatchStmt = catchStmt; + auto rv = RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt); + currCatchStmt = prevCatchStmt; + return rv; +} + +bool DbgUnhandledException::VisitCallExpr(const CallExpr* call) +{ + if (ignoreLocation(call)) + return true; + const FunctionDecl* func = call->getDirectCallee(); + if (!func) + return true; + + if (!func->getIdentifier() || func->getName() != "DbgUnhandledException") + return true; + + if (!currCatchStmt) + { + report(DiagnosticsEngine::Warning, "DBG_UNHANDLED_EXCEPTION outside catch block", + call->getLocStart()); + return true; + } + auto catchBlock = dyn_cast<CompoundStmt>(currCatchStmt->getHandlerBlock()); + if (!catchBlock) + { + report(DiagnosticsEngine::Warning, + "something wrong with DBG_UNHANDLED_EXCEPTION, no CompoundStmt?", + call->getLocStart()); + return true; + } + if (catchBlock->size() < 1) + { + report(DiagnosticsEngine::Warning, + "something wrong with DBG_UNHANDLED_EXCEPTION, CompoundStmt size == 0?", + call->getLocStart()); + return true; + } + + Stmt const* firstStmt = *catchBlock->body_begin(); + if (auto exprWithCleanups = dyn_cast<ExprWithCleanups>(firstStmt)) + firstStmt = exprWithCleanups->getSubExpr(); + if (firstStmt != call) + { + report(DiagnosticsEngine::Warning, + "DBG_UNHANDLED_EXCEPTION must be first statement in catch block", + call->getLocStart()); + } + return true; +} + +static Plugin::Registration<DbgUnhandledException> X("dbgunhandledexception"); + +} // namespace + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/compilerplugins/clang/test/dbgunhandledexception.cxx b/compilerplugins/clang/test/dbgunhandledexception.cxx new file mode 100644 index 000000000000..0abaef0dd06d --- /dev/null +++ b/compilerplugins/clang/test/dbgunhandledexception.cxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * 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 <tools/diagnose_ex.h> + +void func1(); + +int main() +{ + try + { + func1(); + } + catch (std::exception const&) + { + SAL_WARN("xmloff", "message"); + DBG_UNHANDLED_EXCEPTION( + "xmloff", + "message"); // expected-error@-2 {{DBG_UNHANDLED_EXCEPTION must be first statement in catch block [loplugin:dbgunhandledexception]}} + } + try + { + func1(); + } + catch (std::exception const&) + { + DBG_UNHANDLED_EXCEPTION("xmloff", "message"); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ |