1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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
16 #include <clang/Lex/Lexer.h>
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
>
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
);
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
);
59 bool DbgUnhandledException::PostTraverseCXXCatchStmt(CXXCatchStmt
* catchStmt
, bool)
61 assert(currCatchStmt
.top() == catchStmt
);
67 bool DbgUnhandledException::TraverseCXXCatchStmt(CXXCatchStmt
* catchStmt
)
69 if (!PreTraverseCXXCatchStmt(catchStmt
))
71 bool ret
= RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt
);
72 if (!PostTraverseCXXCatchStmt(catchStmt
, ret
))
77 bool DbgUnhandledException::VisitCallExpr(const CallExpr
* call
)
79 if (ignoreLocation(call
))
81 const FunctionDecl
* func
= call
->getDirectCallee();
85 if (!func
->getIdentifier() || func
->getName() != "DbgUnhandledException")
88 if (currCatchStmt
.empty())
90 report(DiagnosticsEngine::Warning
, "DBG_UNHANDLED_EXCEPTION outside catch block",
91 compat::getBeginLoc(call
));
94 auto catchBlock
= dyn_cast
<CompoundStmt
>(currCatchStmt
.top()->getHandlerBlock());
97 report(DiagnosticsEngine::Warning
,
98 "something wrong with DBG_UNHANDLED_EXCEPTION, no CompoundStmt?",
99 compat::getBeginLoc(call
));
102 if (catchBlock
->size() < 1)
104 report(DiagnosticsEngine::Warning
,
105 "something wrong with DBG_UNHANDLED_EXCEPTION, CompoundStmt size == 0?",
106 compat::getBeginLoc(call
));
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
));
122 static Plugin::Registration
<DbgUnhandledException
> dbgunhandledexception("dbgunhandledexception");
126 #endif // LO_CLANG_SHARED_PLUGINS
128 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */