1 //===--- ExceptionSpecAnalyzer.h - clang-tidy -------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_EXCEPTION_SPEC_ANALYZER_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_EXCEPTION_SPEC_ANALYZER_H
11 
12 #include "clang/AST/DeclCXX.h"
13 #include "llvm/ADT/DenseMap.h"
14 
15 namespace clang::tidy::utils {
16 
17 /// This class analysis if a `FunctionDecl` has been declared implicitly through
18 /// defaulting or explicitly as throwing or not and evaluates noexcept
19 /// expressions if needed. Unlike the `ExceptionAnalyzer` however it can't tell
20 /// you if the function will actually throw an exception or not.
21 class ExceptionSpecAnalyzer {
22 public:
23   enum class State {
24     Throwing,    ///< This function has been declared as possibly throwing.
25     NotThrowing, ///< This function has been declared as not throwing.
26     Unknown, ///< We're unable to tell if this function is declared as throwing
27              ///< or not.
28   };
29 
30   ExceptionSpecAnalyzer() = default;
31 
32   State analyze(const FunctionDecl *FuncDecl);
33 
34 private:
35   enum class DefaultableMemberKind {
36     DefaultConstructor,
37     CopyConstructor,
38     MoveConstructor,
39     CopyAssignment,
40     MoveAssignment,
41     Destructor,
42 
43     CompareEqual,
44     CompareNotEqual,
45     CompareThreeWay,
46     CompareRelational,
47 
48     None,
49   };
50 
51   State analyzeImpl(const FunctionDecl *FuncDecl);
52 
53   State analyzeUnresolvedOrDefaulted(const CXXMethodDecl *MethodDecl,
54                                      const FunctionProtoType *FuncProto);
55 
56   State analyzeFieldDecl(const FieldDecl *FDecl, DefaultableMemberKind Kind);
57 
58   State analyzeBase(const CXXBaseSpecifier &Base, DefaultableMemberKind Kind);
59 
60   enum class SkipMethods : bool {
61     Yes = true,
62     No = false,
63   };
64 
65   State analyzeRecord(const CXXRecordDecl *RecordDecl,
66                       DefaultableMemberKind Kind,
67                       SkipMethods SkipMethods = SkipMethods::No);
68 
69   static State analyzeFunctionEST(const FunctionDecl *FuncDecl,
70                                   const FunctionProtoType *FuncProto);
71 
72   static bool hasTrivialMemberKind(const CXXRecordDecl *RecDecl,
73                                    DefaultableMemberKind Kind);
74 
75   static bool isConstructor(DefaultableMemberKind Kind);
76 
77   static bool isSpecialMember(DefaultableMemberKind Kind);
78 
79   static bool isComparison(DefaultableMemberKind Kind);
80 
81   static DefaultableMemberKind
82   getDefaultableMemberKind(const FunctionDecl *FuncDecl);
83 
84   llvm::DenseMap<const FunctionDecl *, State> FunctionCache{32U};
85 };
86 
87 } // namespace clang::tidy::utils
88 
89 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_EXCEPTION_SPEC_ANALYZER_H
90