bump product version to 6.3.0.0.beta1
[LibreOffice.git] / compilerplugins / clang / dbgunhandledexception.cxx
blob81d6126fb3af2f2e0c4f5b1522cb2e6b3ffb71e5
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 currCatchStmt.pop();
63 return true;
66 bool DbgUnhandledException::TraverseCXXCatchStmt(CXXCatchStmt* catchStmt)
68 if (!PreTraverseCXXCatchStmt(catchStmt))
69 return false;
70 bool ret = RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt);
71 if (!PostTraverseCXXCatchStmt(catchStmt, ret))
72 return false;
73 return ret;
76 bool DbgUnhandledException::VisitCallExpr(const CallExpr* call)
78 if (ignoreLocation(call))
79 return true;
80 const FunctionDecl* func = call->getDirectCallee();
81 if (!func)
82 return true;
84 if (!func->getIdentifier() || func->getName() != "DbgUnhandledException")
85 return true;
87 if (currCatchStmt.empty())
89 report(DiagnosticsEngine::Warning, "DBG_UNHANDLED_EXCEPTION outside catch block",
90 compat::getBeginLoc(call));
91 return true;
93 auto catchBlock = dyn_cast<CompoundStmt>(currCatchStmt.top()->getHandlerBlock());
94 if (!catchBlock)
96 report(DiagnosticsEngine::Warning,
97 "something wrong with DBG_UNHANDLED_EXCEPTION, no CompoundStmt?",
98 compat::getBeginLoc(call));
99 return true;
101 if (catchBlock->size() < 1)
103 report(DiagnosticsEngine::Warning,
104 "something wrong with DBG_UNHANDLED_EXCEPTION, CompoundStmt size == 0?",
105 compat::getBeginLoc(call));
106 return true;
109 Stmt const* firstStmt = *catchBlock->body_begin();
110 if (auto exprWithCleanups = dyn_cast<ExprWithCleanups>(firstStmt))
111 firstStmt = exprWithCleanups->getSubExpr();
112 if (firstStmt != call)
114 report(DiagnosticsEngine::Warning,
115 "DBG_UNHANDLED_EXCEPTION must be first statement in catch block",
116 compat::getBeginLoc(call));
118 return true;
121 static Plugin::Registration<DbgUnhandledException> dbgunhandledexception("dbgunhandledexception");
123 } // namespace
125 #endif // LO_CLANG_SHARED_PLUGINS
127 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */