xref: /llvm-project/clang-tools-extra/clang-tidy/openmp/ExceptionEscapeCheck.cpp (revision 7d2ea6c422d3f5712b7253407005e1a465a76946)
1462446fdSRoman Lebedev //===--- ExceptionEscapeCheck.cpp - clang-tidy ----------------------------===//
2462446fdSRoman Lebedev //
3462446fdSRoman Lebedev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4462446fdSRoman Lebedev // See https://llvm.org/LICENSE.txt for license information.
5462446fdSRoman Lebedev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6462446fdSRoman Lebedev //
7462446fdSRoman Lebedev //===----------------------------------------------------------------------===//
8462446fdSRoman Lebedev 
9462446fdSRoman Lebedev #include "ExceptionEscapeCheck.h"
10462446fdSRoman Lebedev #include "clang/AST/ASTContext.h"
11462446fdSRoman Lebedev #include "clang/AST/OpenMPClause.h"
12462446fdSRoman Lebedev #include "clang/AST/Stmt.h"
13462446fdSRoman Lebedev #include "clang/AST/StmtOpenMP.h"
14462446fdSRoman Lebedev #include "clang/ASTMatchers/ASTMatchFinder.h"
15462446fdSRoman Lebedev #include "clang/ASTMatchers/ASTMatchers.h"
16462446fdSRoman Lebedev #include "clang/ASTMatchers/ASTMatchersMacros.h"
17462446fdSRoman Lebedev 
18462446fdSRoman Lebedev using namespace clang::ast_matchers;
19462446fdSRoman Lebedev 
20*7d2ea6c4SCarlos Galvez namespace clang::tidy::openmp {
21462446fdSRoman Lebedev 
ExceptionEscapeCheck(StringRef Name,ClangTidyContext * Context)22462446fdSRoman Lebedev ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name,
23462446fdSRoman Lebedev                                            ClangTidyContext *Context)
24462446fdSRoman Lebedev     : ClangTidyCheck(Name, Context),
25462446fdSRoman Lebedev       RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) {
26462446fdSRoman Lebedev   llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec,
27462446fdSRoman Lebedev       IgnoredExceptionsVec;
28462446fdSRoman Lebedev 
29462446fdSRoman Lebedev   llvm::StringSet<> IgnoredExceptions;
30462446fdSRoman Lebedev   StringRef(RawIgnoredExceptions).split(IgnoredExceptionsVec, ",", -1, false);
31462446fdSRoman Lebedev   llvm::transform(IgnoredExceptionsVec, IgnoredExceptionsVec.begin(),
32462446fdSRoman Lebedev                   [](StringRef S) { return S.trim(); });
33462446fdSRoman Lebedev   IgnoredExceptions.insert(IgnoredExceptionsVec.begin(),
34462446fdSRoman Lebedev                            IgnoredExceptionsVec.end());
35462446fdSRoman Lebedev   Tracer.ignoreExceptions(std::move(IgnoredExceptions));
36462446fdSRoman Lebedev   Tracer.ignoreBadAlloc(true);
37462446fdSRoman Lebedev }
38462446fdSRoman Lebedev 
storeOptions(ClangTidyOptions::OptionMap & Opts)39462446fdSRoman Lebedev void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
40462446fdSRoman Lebedev   Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions);
41462446fdSRoman Lebedev }
42462446fdSRoman Lebedev 
registerMatchers(MatchFinder * Finder)43462446fdSRoman Lebedev void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) {
44462446fdSRoman Lebedev   Finder->addMatcher(ompExecutableDirective(
45462446fdSRoman Lebedev                          unless(isStandaloneDirective()),
46462446fdSRoman Lebedev                          hasStructuredBlock(stmt().bind("structured-block")))
47462446fdSRoman Lebedev                          .bind("directive"),
48462446fdSRoman Lebedev                      this);
49462446fdSRoman Lebedev }
50462446fdSRoman Lebedev 
check(const MatchFinder::MatchResult & Result)51462446fdSRoman Lebedev void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) {
52462446fdSRoman Lebedev   const auto *Directive =
53462446fdSRoman Lebedev       Result.Nodes.getNodeAs<OMPExecutableDirective>("directive");
54462446fdSRoman Lebedev   assert(Directive && "Expected to match some OpenMP Executable directive.");
55462446fdSRoman Lebedev   const auto *StructuredBlock =
56462446fdSRoman Lebedev       Result.Nodes.getNodeAs<Stmt>("structured-block");
57462446fdSRoman Lebedev   assert(StructuredBlock && "Expected to get some OpenMP Structured Block.");
58462446fdSRoman Lebedev 
59462446fdSRoman Lebedev   if (Tracer.analyze(StructuredBlock).getBehaviour() !=
60462446fdSRoman Lebedev       utils::ExceptionAnalyzer::State::Throwing)
61462446fdSRoman Lebedev     return; // No exceptions have been proven to escape out of the struc. block.
62462446fdSRoman Lebedev 
63462446fdSRoman Lebedev   // FIXME: We should provide more information about the exact location where
64462446fdSRoman Lebedev   // the exception is thrown, maybe the full path the exception escapes.
65462446fdSRoman Lebedev 
66ee143107SRoman Lebedev   diag(StructuredBlock->getBeginLoc(),
67462446fdSRoman Lebedev        "an exception thrown inside of the OpenMP '%0' region is not caught in "
68462446fdSRoman Lebedev        "that same region")
69462446fdSRoman Lebedev       << getOpenMPDirectiveName(Directive->getDirectiveKind());
70462446fdSRoman Lebedev }
71462446fdSRoman Lebedev 
72*7d2ea6c4SCarlos Galvez } // namespace clang::tidy::openmp
73