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 &lt;valarray&gt;
#include &lt;type_traits&gt;
#include &lt;expected&gt;

template &lt;class _Tp, _Tp __v&gt;
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 &lt;typename T&gt;
struct IsInt : public integral_constant&lt;bool, false&gt; {};

template &lt;&gt;
struct IsInt&lt;int&gt; : public integral_constant&lt;bool, true&gt; {};

template &lt;typename T&gt;
inline constexpr bool IsInt_V = IsInt&lt;T&gt;::value;

template &lt;typename T, typename E&gt;
struct ExpectedLike {
        ExpectedLike() = default;
        
        constexpr ExpectedLike(const ExpectedLike&amp;)
//      requires(IsInt_V&lt;T&gt; &amp;&amp; IsInt_V&lt;E&gt; &amp;&amp; 
IsInt_V&lt;T&gt;)
    requires(std::is_copy_constructible_v&lt;T&gt; &amp;&amp; 
std::is_copy_constructible_v&lt;E&gt; &amp;&amp; 
std::is_trivially_copy_constructible_v&lt;T&gt; &amp;&amp;
             std::is_trivially_copy_constructible_v&lt;E&gt;)

        = default;
        
};

void nb_xx() [[clang::nonblocking]]
{
        ExpectedLike&lt;int, int&gt; a;
        auto b = a;
// No warning. I don't know why.

        std::expected&lt;int, int&gt; c;
        std::expected&lt;int, int&gt; d = c;
// ^^ warning: function with 'nonblocking' attribute must not call 
non-'nonblocking' constructor 'std::expected&lt;int, int&gt;::expected' 
[-Wfunction-effects]
}
```

The two elements of the mystery are:

- why doesn't my `ExpectedLike&lt;T, E&gt;` copy constructor reproduce the 
behavior of `std::expected&lt;T, E&gt;`?
- why does reproduction with `std::expected` depend on the global `operator 
&amp;&amp;` in `&lt;valarray&gt;`?

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

Reply via email to