tdf#130857 qt weld: Support "Insert Breaks" dialog
[LibreOffice.git] / compilerplugins / clang / dbgunhandledexception.cxx
blob699297b5a24877c27d8157b9f7e51e3873b8ecad
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>
19 #include <stack>
21 namespace loplugin
24 This is a compile check.
26 Check that DBG_UNHANDLED_EXCEPTION is always the first statement in a catch block, otherwise
27 it does not work properly.
30 class DbgUnhandledException : public loplugin::FilteringPlugin<DbgUnhandledException>
32 public:
33 explicit DbgUnhandledException(InstantiationData const& data);
34 virtual void run() override;
35 bool VisitCallExpr(CallExpr const* call);
36 bool TraverseCXXCatchStmt(CXXCatchStmt*);
37 bool PreTraverseCXXCatchStmt(CXXCatchStmt*);
38 bool PostTraverseCXXCatchStmt(CXXCatchStmt*, bool traverseOk);
40 private:
41 std::stack<CXXCatchStmt const*> currCatchStmt;
44 DbgUnhandledException::DbgUnhandledException(const InstantiationData& data)
45 : FilteringPlugin(data)
49 void DbgUnhandledException::run()
51 TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
54 bool DbgUnhandledException::PreTraverseCXXCatchStmt(CXXCatchStmt* catchStmt)
56 currCatchStmt.push(catchStmt);
57 return true;
60 bool DbgUnhandledException::PostTraverseCXXCatchStmt(CXXCatchStmt* catchStmt, bool)
62 assert(currCatchStmt.top() == catchStmt);
63 (void)catchStmt;
64 currCatchStmt.pop();
65 return true;
68 bool DbgUnhandledException::TraverseCXXCatchStmt(CXXCatchStmt* catchStmt)
70 if (!PreTraverseCXXCatchStmt(catchStmt))
71 return false;
72 bool ret = RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt);
73 if (!PostTraverseCXXCatchStmt(catchStmt, ret))
74 return false;
75 return ret;
78 bool DbgUnhandledException::VisitCallExpr(const CallExpr* call)
80 if (ignoreLocation(call))
81 return true;
82 const FunctionDecl* func = call->getDirectCallee();
83 if (!func)
84 return true;
86 if (!func->getIdentifier() || func->getName() != "DbgUnhandledException")
87 return true;
89 if (currCatchStmt.empty())
91 report(DiagnosticsEngine::Warning, "DBG_UNHANDLED_EXCEPTION outside catch block",
92 call->getBeginLoc());
93 return true;
95 auto catchBlock = dyn_cast<CompoundStmt>(currCatchStmt.top()->getHandlerBlock());
96 if (!catchBlock)
98 report(DiagnosticsEngine::Warning,
99 "something wrong with DBG_UNHANDLED_EXCEPTION, no CompoundStmt?",
100 call->getBeginLoc());
101 return true;
103 if (catchBlock->size() < 1)
105 report(DiagnosticsEngine::Warning,
106 "something wrong with DBG_UNHANDLED_EXCEPTION, CompoundStmt size == 0?",
107 call->getBeginLoc());
108 return true;
111 Stmt const* firstStmt = *catchBlock->body_begin();
112 if (auto exprWithCleanups = dyn_cast<ExprWithCleanups>(firstStmt))
113 firstStmt = exprWithCleanups->getSubExpr();
114 if (firstStmt != call)
116 report(DiagnosticsEngine::Warning,
117 "DBG_UNHANDLED_EXCEPTION must be first statement in catch block",
118 call->getBeginLoc());
120 return true;
123 static Plugin::Registration<DbgUnhandledException> dbgunhandledexception("dbgunhandledexception");
125 } // namespace
127 #endif // LO_CLANG_SHARED_PLUGINS
129 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */