bump product version to 6.4.0.3
[LibreOffice.git] / compilerplugins / clang / dbgunhandledexception.cxx
blobd1406c18a9dddf4fbcd70b67c5d9925f8887b61f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * Based on LLVM/Clang.
7 * This file is distributed under the University of Illinois Open Source
8 * License. See LICENSE.TXT for details.
12 #ifndef LO_CLANG_SHARED_PLUGINS
14 #include "check.hxx"
15 #include "plugin.hxx"
16 #include <clang/Lex/Lexer.h>
17 #include <fstream>
18 #include <set>
20 namespace loplugin
23 This is a compile check.
25 Check that DBG_UNHANDLED_EXCEPTION is always the first statement in a catch block, otherwise
26 it does not work properly.
29 class DbgUnhandledException : public loplugin::FilteringPlugin<DbgUnhandledException>
31 public:
32 explicit DbgUnhandledException(InstantiationData const& data);
33 virtual void run() override;
34 bool VisitCallExpr(CallExpr const* call);
35 bool TraverseCXXCatchStmt(CXXCatchStmt*);
36 bool PreTraverseCXXCatchStmt(CXXCatchStmt*);
37 bool PostTraverseCXXCatchStmt(CXXCatchStmt*, bool traverseOk);
39 private:
40 std::stack<CXXCatchStmt const*> currCatchStmt;
43 DbgUnhandledException::DbgUnhandledException(const InstantiationData& data)
44 : FilteringPlugin(data)
48 void DbgUnhandledException::run()
50 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
53 bool DbgUnhandledException::PreTraverseCXXCatchStmt(CXXCatchStmt* catchStmt)
55 currCatchStmt.push(catchStmt);
56 return true;
59 bool DbgUnhandledException::PostTraverseCXXCatchStmt(CXXCatchStmt* catchStmt, bool)
61 assert(currCatchStmt.top() == catchStmt);
62 (void)catchStmt;
63 currCatchStmt.pop();
64 return true;
67 bool DbgUnhandledException::TraverseCXXCatchStmt(CXXCatchStmt* catchStmt)
69 if (!PreTraverseCXXCatchStmt(catchStmt))
70 return false;
71 bool ret = RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt);
72 if (!PostTraverseCXXCatchStmt(catchStmt, ret))
73 return false;
74 return ret;
77 bool DbgUnhandledException::VisitCallExpr(const CallExpr* call)
79 if (ignoreLocation(call))
80 return true;
81 const FunctionDecl* func = call->getDirectCallee();
82 if (!func)
83 return true;
85 if (!func->getIdentifier() || func->getName() != "DbgUnhandledException")
86 return true;
88 if (currCatchStmt.empty())
90 report(DiagnosticsEngine::Warning, "DBG_UNHANDLED_EXCEPTION outside catch block",
91 compat::getBeginLoc(call));
92 return true;
94 auto catchBlock = dyn_cast<CompoundStmt>(currCatchStmt.top()->getHandlerBlock());
95 if (!catchBlock)
97 report(DiagnosticsEngine::Warning,
98 "something wrong with DBG_UNHANDLED_EXCEPTION, no CompoundStmt?",
99 compat::getBeginLoc(call));
100 return true;
102 if (catchBlock->size() < 1)
104 report(DiagnosticsEngine::Warning,
105 "something wrong with DBG_UNHANDLED_EXCEPTION, CompoundStmt size == 0?",
106 compat::getBeginLoc(call));
107 return true;
110 Stmt const* firstStmt = *catchBlock->body_begin();
111 if (auto exprWithCleanups = dyn_cast<ExprWithCleanups>(firstStmt))
112 firstStmt = exprWithCleanups->getSubExpr();
113 if (firstStmt != call)
115 report(DiagnosticsEngine::Warning,
116 "DBG_UNHANDLED_EXCEPTION must be first statement in catch block",
117 compat::getBeginLoc(call));
119 return true;
122 static Plugin::Registration<DbgUnhandledException> dbgunhandledexception("dbgunhandledexception");
124 } // namespace
126 #endif // LO_CLANG_SHARED_PLUGINS
128 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */