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
);
66 bool DbgUnhandledException::TraverseCXXCatchStmt(CXXCatchStmt
* catchStmt
)
68 if (!PreTraverseCXXCatchStmt(catchStmt
))
70 bool ret
= RecursiveASTVisitor::TraverseCXXCatchStmt(catchStmt
);
71 if (!PostTraverseCXXCatchStmt(catchStmt
, ret
))
76 bool DbgUnhandledException::VisitCallExpr(const CallExpr
* call
)
78 if (ignoreLocation(call
))
80 const FunctionDecl
* func
= call
->getDirectCallee();
84 if (!func
->getIdentifier() || func
->getName() != "DbgUnhandledException")
87 if (currCatchStmt
.empty())
89 report(DiagnosticsEngine::Warning
, "DBG_UNHANDLED_EXCEPTION outside catch block",
90 compat::getBeginLoc(call
));
93 auto catchBlock
= dyn_cast
<CompoundStmt
>(currCatchStmt
.top()->getHandlerBlock());
96 report(DiagnosticsEngine::Warning
,
97 "something wrong with DBG_UNHANDLED_EXCEPTION, no CompoundStmt?",
98 compat::getBeginLoc(call
));
101 if (catchBlock
->size() < 1)
103 report(DiagnosticsEngine::Warning
,
104 "something wrong with DBG_UNHANDLED_EXCEPTION, CompoundStmt size == 0?",
105 compat::getBeginLoc(call
));
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
));
121 static Plugin::Registration
<DbgUnhandledException
> dbgunhandledexception("dbgunhandledexception");
125 #endif // LO_CLANG_SHARED_PLUGINS
127 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */