@@ -972,6 +972,7 @@ class Analyzer {
972972 CallableInfo &CurrentCaller;
973973 ViolationSite VSite;
974974 const Expr *TrailingRequiresClause = nullptr ;
975+ const Expr *NoexceptExpr = nullptr ;
975976
976977 FunctionBodyASTVisitor (Analyzer &Outer,
977978 PendingFunctionAnalysis &CurrentFunction,
@@ -986,9 +987,22 @@ class Analyzer {
986987 if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl ))
987988 followDestructor (dyn_cast<CXXRecordDecl>(Dtor->getParent ()), Dtor);
988989
989- if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl ))
990+ if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl )) {
990991 TrailingRequiresClause = FD->getTrailingRequiresClause ();
991992
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+
9921006 // Do an AST traversal of the function/block body
9931007 TraverseDecl (const_cast <Decl *>(CurrentCaller.CDecl ));
9941008 }
@@ -1269,7 +1283,8 @@ class Analyzer {
12691283 // We skip the traversal of lambdas (beyond their captures, see
12701284 // TraverseLambdaExpr below), so just caching this from our constructor
12711285 // should suffice.
1272- if (Statement != TrailingRequiresClause)
1286+ // The exact same is true for a conditional `noexcept()` clause.
1287+ if (Statement != TrailingRequiresClause && Statement != NoexceptExpr)
12731288 return Base::TraverseStmt (Statement);
12741289 return true ;
12751290 }
0 commit comments