Skip to content

Commit 3e30b36

Browse files
dougsonosDoug Wyatt
and
Doug Wyatt
authored
[Clang] SemaFunctionEffects: When verifying a function, ignore any conditional noexcept expression. (#115342)
--------- Co-authored-by: Doug Wyatt <[email protected]>
1 parent 0e936e3 commit 3e30b36

File tree

2 files changed

+29
-4
lines changed

2 files changed

+29
-4
lines changed

clang/lib/Sema/SemaFunctionEffects.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

clang/test/Sema/attr-nonblocking-constraints.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,7 @@ void nb26() [[clang::nonblocking]] {
388388
abort_wrapper(); // no diagnostic
389389
}
390390

391-
// --- Make sure we don't traverse a requires clause. ---
391+
// --- Make sure we don't traverse requires and noexcept clauses. ---
392392

393393
// Apparently some requires clauses are able to be collapsed into a constant before the nonblocking
394394
// analysis sees any function calls. This example (extracted from a real-world case where
@@ -420,6 +420,7 @@ class expected {
420420
constexpr expected()
421421
{}
422422

423+
// This is a deliberate corruption of the real implementation for simplicity.
423424
constexpr expected(const expected&)
424425
requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err>)
425426
= default;
@@ -428,11 +429,20 @@ class expected {
428429
void test() [[clang::nonblocking]]
429430
{
430431
expected<int, int> a;
431-
auto b = a;
432+
auto b = a; // Copy constructor.
432433
}
433434

434435
} // namespace ExpectedTest
435436

437+
// Make sure a function call in a noexcept() clause is ignored.
438+
constexpr bool foo() [[clang::nonblocking(false)]] { return true; }
439+
void nb27() noexcept(foo()) [[clang::nonblocking]] {}
440+
441+
// Make sure that simple type traits don't cause violations.
442+
void nb28() [[clang::nonblocking]] {
443+
bool x = __is_constructible(int, const int&);
444+
}
445+
436446
// --- nonblocking implies noexcept ---
437447
#pragma clang diagnostic warning "-Wperf-constraint-implies-noexcept"
438448

0 commit comments

Comments
 (0)