@@ -972,6 +972,7 @@ class Analyzer {
972
972
CallableInfo &CurrentCaller;
973
973
ViolationSite VSite;
974
974
const Expr *TrailingRequiresClause = nullptr ;
975
+ const Expr *NoexceptExpr = nullptr ;
975
976
976
977
FunctionBodyASTVisitor (Analyzer &Outer,
977
978
PendingFunctionAnalysis &CurrentFunction,
@@ -986,9 +987,22 @@ class Analyzer {
986
987
if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl ))
987
988
followDestructor (dyn_cast<CXXRecordDecl>(Dtor->getParent ()), Dtor);
988
989
989
- if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl ))
990
+ if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl )) {
990
991
TrailingRequiresClause = FD->getTrailingRequiresClause ();
991
992
993
+ // Note that FD->getType->getAs<FunctionProtoType>() can yield a
994
+ // noexcept Expr which has been boiled down to a constant expression.
995
+ // Going through the TypeSourceInfo obtains the actual expression which
996
+ // will be traversed as part of the function -- unless we capture it
997
+ // here and have TraverseStmt skip it.
998
+ if (TypeSourceInfo *TSI = FD->getTypeSourceInfo ()) {
999
+ if (FunctionProtoTypeLoc TL =
1000
+ TSI->getTypeLoc ().getAs <FunctionProtoTypeLoc>())
1001
+ if (const FunctionProtoType *FPT = TL.getTypePtr ())
1002
+ NoexceptExpr = FPT->getNoexceptExpr ();
1003
+ }
1004
+ }
1005
+
992
1006
// Do an AST traversal of the function/block body
993
1007
TraverseDecl (const_cast <Decl *>(CurrentCaller.CDecl ));
994
1008
}
@@ -1269,7 +1283,8 @@ class Analyzer {
1269
1283
// We skip the traversal of lambdas (beyond their captures, see
1270
1284
// TraverseLambdaExpr below), so just caching this from our constructor
1271
1285
// should suffice.
1272
- if (Statement != TrailingRequiresClause)
1286
+ // The exact same is true for a conditional `noexcept()` clause.
1287
+ if (Statement != TrailingRequiresClause && Statement != NoexceptExpr)
1273
1288
return Base::TraverseStmt (Statement);
1274
1289
return true ;
1275
1290
}
0 commit comments