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