llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Doug Wyatt (dougsonos) <details> <summary>Changes</summary> Clearly there's an omission here, that a trailing `requires` clause in a called function is being subject to effect analysis. But despite many hours of effort I haven't been able to create a self-contained reproducer. My best effort: ```c++ #include <valarray> #include <type_traits> #include <expected> template <class _Tp, _Tp __v> struct integral_constant { static constexpr _Tp value = __v; typedef _Tp value_type; typedef integral_constant type; constexpr operator value_type() const noexcept { return value; } constexpr value_type operator()() const noexcept { return value; } }; template <typename T> struct IsInt : public integral_constant<bool, false> {}; template <> struct IsInt<int> : public integral_constant<bool, true> {}; template <typename T> inline constexpr bool IsInt_V = IsInt<T>::value; template <typename T, typename E> struct ExpectedLike { ExpectedLike() = default; constexpr ExpectedLike(const ExpectedLike&) // requires(IsInt_V<T> && IsInt_V<E> && IsInt_V<T>) requires(std::is_copy_constructible_v<T> && std::is_copy_constructible_v<E> && std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_constructible_v<E>) = default; }; void nb_xx() [[clang::nonblocking]] { ExpectedLike<int, int> a; auto b = a; // No warning. I don't know why. std::expected<int, int> c; std::expected<int, int> d = c; // ^^ warning: function with 'nonblocking' attribute must not call non-'nonblocking' constructor 'std::expected<int, int>::expected' [-Wfunction-effects] } ``` The two elements of the mystery are: - why doesn't my `ExpectedLike<T, E>` copy constructor reproduce the behavior of `std::expected<T, E>`? - why does reproduction with `std::expected` depend on the global `operator &&` in `<valarray>`? I've verified that the change to SemaFunctionEffects fixes the issue, but I'd sure like to be able to construct a self-contained test. --- Full diff: https://github.com/llvm/llvm-project/pull/114266.diff 1 Files Affected: - (modified) clang/lib/Sema/SemaFunctionEffects.cpp (+10) ``````````diff diff --git a/clang/lib/Sema/SemaFunctionEffects.cpp b/clang/lib/Sema/SemaFunctionEffects.cpp index 3fa326db06ee41..f7ff8b92d8a929 100644 --- a/clang/lib/Sema/SemaFunctionEffects.cpp +++ b/clang/lib/Sema/SemaFunctionEffects.cpp @@ -971,6 +971,7 @@ class Analyzer { PendingFunctionAnalysis &CurrentFunction; CallableInfo &CurrentCaller; ViolationSite VSite; + const Expr *TrailingRequiresClause = nullptr; FunctionBodyASTVisitor(Analyzer &Outer, PendingFunctionAnalysis &CurrentFunction, @@ -985,6 +986,9 @@ 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)) + TrailingRequiresClause = FD->getTrailingRequiresClause(); + // Do an AST traversal of the function/block body TraverseDecl(const_cast<Decl *>(CurrentCaller.CDecl)); } @@ -1259,6 +1263,12 @@ class Analyzer { return true; } + bool TraverseStmt(Stmt *Statement) { + if (Statement != TrailingRequiresClause) + return Base::TraverseStmt(Statement); + return true; + } + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { ViolationSite PrevVS = VSite; if (Init->isAnyMemberInitializer()) `````````` </details> https://github.com/llvm/llvm-project/pull/114266 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits