https://github.com/dougsonos updated https://github.com/llvm/llvm-project/pull/115342
>From a0b6093fcf24ade7ce9ee0c3d65f679a41751225 Mon Sep 17 00:00:00 2001 From: Doug Wyatt <dwy...@apple.com> Date: Tue, 5 Nov 2024 13:35:50 -0800 Subject: [PATCH 1/2] [Clang] SemaFunctionEffects: When verifying a function, ignore any conditional noexcept expression. --- clang/lib/Sema/SemaFunctionEffects.cpp | 19 +++++++++++++++++-- .../Sema/attr-nonblocking-constraints.cpp | 12 ++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index ab728f24d8a271..70f6f9b6784cd8 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -972,6 +972,7 @@ class Analyzer { CallableInfo &CurrentCaller; ViolationSite VSite; const Expr *TrailingRequiresClause = nullptr; + const Expr *NoexceptExpr = nullptr; FunctionBodyASTVisitor(Analyzer &Outer, PendingFunctionAnalysis &CurrentFunction, @@ -986,9 +987,22 @@ class Analyzer { if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl)) followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor); - if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) + if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl)) { TrailingRequiresClause = FD->getTrailingRequiresClause(); + // Note that FD->getType->getAs<FunctionProtoType>() can yield a + // noexcept Expr which has been boiled down to a constant expression. + // Going through the TypeSourceInfo obtains the actual expression which + // will be traversed as part of the function -- unless we capture it + // here and have TraverseStmt skip it. + if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) { + FunctionProtoTypeLoc TL = + TSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); + if (const FunctionProtoType *FPT = TL.getTypePtr()) + NoexceptExpr = FPT->getNoexceptExpr(); + } + } + // Do an AST traversal of the function/block body TraverseDecl(const_cast<Decl *>(CurrentCaller.CDecl)); } @@ -1269,7 +1283,8 @@ class Analyzer { // We skip the traversal of lambdas (beyond their captures, see // TraverseLambdaExpr below), so just caching this from our constructor // should suffice. - if (Statement != TrailingRequiresClause) + // The exact same is true for a conditional `noexcept()` clause. + if (Statement != TrailingRequiresClause && Statement != NoexceptExpr) return Base::TraverseStmt(Statement); return true; } diff --git a/clang/test/Sema/attr-nonblocking-constraints.cpp b/clang/test/Sema/attr-nonblocking-constraints.cpp index 19a4c3b7942b12..169c42ee35fe83 100644 --- a/clang/test/Sema/attr-nonblocking-constraints.cpp +++ b/clang/test/Sema/attr-nonblocking-constraints.cpp @@ -388,7 +388,7 @@ void nb26() [[clang::nonblocking]] { abort_wrapper(); // no diagnostic } -// --- Make sure we don't traverse a requires clause. --- +// --- Make sure we don't traverse requires and noexcept clauses. --- // Apparently some requires clauses are able to be collapsed into a constant before the nonblocking // analysis sees any function calls. This example (extracted from a real-world case where @@ -420,7 +420,9 @@ class expected { constexpr expected() {} + // This is a deliberate corruption of the real implementation for simplicity. constexpr expected(const expected&) + noexcept(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err>) requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err>) = default; }; @@ -428,11 +430,17 @@ class expected { void test() [[clang::nonblocking]] { expected<int, int> a; - auto b = a; + auto b = a; // Copy constructor. } } // namespace ExpectedTest +// Make sure that simple type traits don't cause violations. + +void nb27() [[clang::nonblocking]] { + bool x = __is_constructible(int, const int&); +} + // --- nonblocking implies noexcept --- #pragma clang diagnostic warning "-Wperf-constraint-implies-noexcept" >From 02f1fc7974fffb97b9f23d7fb072f23bd9bdd89a Mon Sep 17 00:00:00 2001 From: Doug Wyatt <dwy...@apple.com> Date: Fri, 8 Nov 2024 09:22:33 -0800 Subject: [PATCH 2/2] Review feedback: Check for no-prototype. Simplify test. --- clang/lib/Sema/SemaFunctionEffects.cpp | 8 ++++---- clang/test/Sema/attr-nonblocking-constraints.cpp | 8 +++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index 70f6f9b6784cd8..a76a0a41276896 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -996,10 +996,10 @@ class Analyzer { // will be traversed as part of the function -- unless we capture it // here and have TraverseStmt skip it. if (TypeSourceInfo *TSI = FD->getTypeSourceInfo()) { - FunctionProtoTypeLoc TL = - TSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); - if (const FunctionProtoType *FPT = TL.getTypePtr()) - NoexceptExpr = FPT->getNoexceptExpr(); + if (FunctionProtoTypeLoc TL = + TSI->getTypeLoc().getAs<FunctionProtoTypeLoc>()) + if (const FunctionProtoType *FPT = TL.getTypePtr()) + NoexceptExpr = FPT->getNoexceptExpr(); } } diff --git a/clang/test/Sema/attr-nonblocking-constraints.cpp b/clang/test/Sema/attr-nonblocking-constraints.cpp index 169c42ee35fe83..cc9108c0a4fbd6 100644 --- a/clang/test/Sema/attr-nonblocking-constraints.cpp +++ b/clang/test/Sema/attr-nonblocking-constraints.cpp @@ -422,7 +422,6 @@ class expected { // This is a deliberate corruption of the real implementation for simplicity. constexpr expected(const expected&) - noexcept(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err>) requires(is_copy_constructible_v<_Tp> && is_copy_constructible_v<_Err>) = default; }; @@ -435,9 +434,12 @@ void test() [[clang::nonblocking]] } // namespace ExpectedTest -// Make sure that simple type traits don't cause violations. +// Make sure a function call in a noexcept() clause is ignored. +constexpr bool foo() [[clang::nonblocking(false)]] { return true; } +void nb27() noexcept(foo()) [[clang::nonblocking]] {} -void nb27() [[clang::nonblocking]] { +// Make sure that simple type traits don't cause violations. +void nb28() [[clang::nonblocking]] { bool x = __is_constructible(int, const int&); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits