16 const Type *ExceptionType) {
17 assert(ExceptionType !=
nullptr &&
"Only valid types are accepted");
19 ThrownExceptions.insert(ExceptionType);
24 if (Exceptions.size() == 0)
27 ThrownExceptions.insert(Exceptions.begin(), Exceptions.end());
43 ContainsUnknown = ContainsUnknown || Other.ContainsUnknown;
44 ThrownExceptions.insert(Other.ThrownExceptions.begin(),
45 Other.ThrownExceptions.end());
50 const auto *DerivedClass = DerivedType->getAsCXXRecordDecl();
51 const auto *BaseClass = BaseType->getAsCXXRecordDecl();
52 if (!DerivedClass || !BaseClass)
55 return !DerivedClass->forallBases(
56 [BaseClass](
const CXXRecordDecl *Cur) {
return Cur != BaseClass; });
60 llvm::SmallVector<const Type *, 8> TypesToDelete;
61 for (
const Type *T : ThrownExceptions) {
62 if (T == BaseClass ||
isBaseOf(T, BaseClass))
63 TypesToDelete.push_back(T);
66 for (
const Type *T : TypesToDelete)
67 ThrownExceptions.erase(T);
69 reevaluateBehaviour();
70 return TypesToDelete.size() > 0;
75 const llvm::StringSet<> &IgnoredTypes,
bool IgnoreBadAlloc) {
76 llvm::SmallVector<const Type *, 8> TypesToDelete;
79 for (
const Type *T : ThrownExceptions) {
80 if (
const auto *TD = T->getAsTagDecl()) {
81 if (TD->getDeclName().isIdentifier()) {
82 if ((IgnoreBadAlloc &&
83 (TD->getName() ==
"bad_alloc" && TD->isInStdNamespace())) ||
84 (IgnoredTypes.count(TD->getName()) > 0))
85 TypesToDelete.push_back(T);
89 for (
const Type *T : TypesToDelete)
90 ThrownExceptions.erase(T);
92 reevaluateBehaviour();
98 ContainsUnknown =
false;
99 ThrownExceptions.clear();
102 void ExceptionAnalyzer::ExceptionInfo::reevaluateBehaviour() {
103 if (ThrownExceptions.size() == 0)
113 const FunctionDecl *Func,
114 llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
115 if (CallStack.count(Func))
118 if (
const Stmt *Body = Func->getBody()) {
119 CallStack.insert(Func);
120 ExceptionInfo Result =
122 CallStack.erase(Func);
127 if (
const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) {
128 for (
const QualType &Ex : FPT->exceptions())
129 Result.registerException(Ex.getTypePtr());
136 ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
138 llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
143 if (
const auto *Throw = dyn_cast<CXXThrowExpr>(St)) {
144 if (
const auto *ThrownExpr = Throw->getSubExpr()) {
145 const auto *ThrownType =
146 ThrownExpr->getType()->getUnqualifiedDesugaredType();
147 if (ThrownType->isReferenceType())
148 ThrownType = ThrownType->castAs<ReferenceType>()
150 ->getUnqualifiedDesugaredType();
152 ThrownExpr->getType()->getUnqualifiedDesugaredType());
157 Results.registerExceptions(Caught);
158 }
else if (
const auto *Try = dyn_cast<CXXTryStmt>(St)) {
159 ExceptionInfo Uncaught =
160 throwsException(Try->getTryBlock(), Caught, CallStack);
161 for (
unsigned i = 0; i < Try->getNumHandlers(); ++i) {
162 const CXXCatchStmt *Catch = Try->getHandler(i);
165 if (!Catch->getExceptionDecl()) {
166 ExceptionInfo Rethrown = throwsException(
167 Catch->getHandlerBlock(), Uncaught.getExceptionTypes(), CallStack);
171 const auto *CaughtType =
172 Catch->getCaughtType()->getUnqualifiedDesugaredType();
173 if (CaughtType->isReferenceType()) {
174 CaughtType = CaughtType->castAs<ReferenceType>()
176 ->getUnqualifiedDesugaredType();
183 if (Uncaught.filterByCatch(CaughtType)) {
185 CaughtExceptions.insert(CaughtType);
186 ExceptionInfo Rethrown = throwsException(Catch->getHandlerBlock(),
187 CaughtExceptions, CallStack);
193 }
else if (
const auto *Call = dyn_cast<CallExpr>(St)) {
194 if (
const FunctionDecl *Func = Call->getDirectCallee()) {
195 ExceptionInfo Excs = throwsException(Func, CallStack);
199 for (
const Stmt *Child : St->children()) {
200 ExceptionInfo Excs = throwsException(Child, Caught, CallStack);
207 ExceptionAnalyzer::ExceptionInfo
208 ExceptionAnalyzer::analyzeImpl(
const FunctionDecl *Func) {
209 ExceptionInfo ExceptionList;
212 if (FunctionCache.count(Func) == 0) {
213 llvm::SmallSet<const FunctionDecl *, 32> CallStack;
214 ExceptionList = throwsException(Func, CallStack);
220 FunctionCache.insert(std::make_pair(Func, ExceptionList));
222 ExceptionList = FunctionCache[Func];
224 return ExceptionList;
227 ExceptionAnalyzer::ExceptionInfo
228 ExceptionAnalyzer::analyzeImpl(
const Stmt *Stmt) {
229 llvm::SmallSet<const FunctionDecl *, 32> CallStack;
233 template <
typename T>
234 ExceptionAnalyzer::ExceptionInfo
235 ExceptionAnalyzer::analyzeDispatch(
const T *Node) {
236 ExceptionInfo ExceptionList = analyzeImpl(Node);
240 return ExceptionList;
244 ExceptionList.filterIgnoredExceptions(IgnoredExceptions, IgnoreBadAlloc);
246 return ExceptionList;
249 ExceptionAnalyzer::ExceptionInfo
251 return analyzeDispatch(Func);
256 return analyzeDispatch(Stmt);