From 6f9bd07cafbd332d5153b7a04c8c064f05434fe1 Mon Sep 17 00:00:00 2001
From: alandefreitas <alandefreitas@gmail.com>
Date: Wed, 22 Jan 2025 01:19:15 -0300
Subject: [PATCH] SFINAE return type constraints

#feat
---
 src/lib/AST/ASTVisitor.cpp                   | 14 ++++++++++++++
 test-files/golden-tests/core/libcxx.adoc     |  3 ++-
 test-files/golden-tests/core/libcxx.html     |  3 ++-
 test-files/golden-tests/core/libcxx.xml      |  2 +-
 test-files/golden-tests/metadata/sfinae.adoc | 12 ++++++++----
 test-files/golden-tests/metadata/sfinae.html | 12 ++++++++----
 test-files/golden-tests/metadata/sfinae.xml  |  8 ++++----
 test-files/golden-tests/snippets/sqrt.adoc   |  3 ++-
 test-files/golden-tests/snippets/sqrt.html   |  3 ++-
 test-files/golden-tests/snippets/sqrt.xml    |  2 +-
 10 files changed, 44 insertions(+), 18 deletions(-)

diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp
index 05f3956be..2ba05ca62 100644
--- a/src/lib/AST/ASTVisitor.cpp
+++ b/src/lib/AST/ASTVisitor.cpp
@@ -872,6 +872,20 @@ populate(
     }
     else
     {
+        // Return type SFINAE constraints
+        if (I.ReturnType &&
+            !I.ReturnType->Constraints.empty())
+        {
+            for (ExprInfo const& constraint: I.ReturnType->Constraints)
+            {
+                if (!I.Requires.Written.empty())
+                {
+                    I.Requires.Written += " && ";
+                }
+                I.Requires.Written += constraint.Written;
+            }
+        }
+
         // Iterate I.Params to find trailing requires clauses
         for (auto it = I.Params.begin(); it != I.Params.end(); )
         {
diff --git a/test-files/golden-tests/core/libcxx.adoc b/test-files/golden-tests/core/libcxx.adoc
index 4b3178f4b..3f74a3679 100644
--- a/test-files/golden-tests/core/libcxx.adoc
+++ b/test-files/golden-tests/core/libcxx.adoc
@@ -31,7 +31,8 @@ Declared in `&lt;libcxx&period;cpp&gt;`
 ----
 template&lt;typename T&gt;
 T
-sqrt(T value);
+sqrt(T value)
+requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;;
 ----
 
 === Description
diff --git a/test-files/golden-tests/core/libcxx.html b/test-files/golden-tests/core/libcxx.html
index a2f4bce73..e79644870 100644
--- a/test-files/golden-tests/core/libcxx.html
+++ b/test-files/golden-tests/core/libcxx.html
@@ -41,7 +41,8 @@ <h3>Synopsis</h3>
 <code class="source-code cpp">
 template&lt;typename T&gt;
 T
-sqrt(T value);
+sqrt(T value)
+requires std::is_integral_v&lt;T&gt;;
 </code>
 </pre>
 </div>
diff --git a/test-files/golden-tests/core/libcxx.xml b/test-files/golden-tests/core/libcxx.xml
index f961338fb..8db6bbd8c 100644
--- a/test-files/golden-tests/core/libcxx.xml
+++ b/test-files/golden-tests/core/libcxx.xml
@@ -4,7 +4,7 @@
 <namespace id="//////////////////////////8=">
   <template>
     <tparam name="T" class="type"/>
-    <function name="sqrt" id="ulFDUE1svTCX8fV/h8EIp4NNbWs=">
+    <function name="sqrt" requires="std::is_integral_v&lt;T&gt;" id="ulFDUE1svTCX8fV/h8EIp4NNbWs=">
       <file short-path="libcxx.cpp" source-path="libcxx.cpp" line="149"/>
       <return>
         <type name="T"/>
diff --git a/test-files/golden-tests/metadata/sfinae.adoc b/test-files/golden-tests/metadata/sfinae.adoc
index 396745725..eb09a0cdb 100644
--- a/test-files/golden-tests/metadata/sfinae.adoc
+++ b/test-files/golden-tests/metadata/sfinae.adoc
@@ -246,7 +246,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
 ----
 template&lt;class T&gt;
 T
-f1(T value);
+f1(T value)
+requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;;
 ----
 
 [#f10]
@@ -294,7 +295,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
 ----
 template&lt;class T&gt;
 int
-f2(T value);
+f2(T value)
+requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;;
 ----
 
 [#f3]
@@ -312,7 +314,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
 ----
 template&lt;class T&gt;
 <<B,B>>::<<B-C,C>>
-f3(T value);
+f3(T value)
+requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;;
 ----
 
 [#f4]
@@ -330,7 +333,8 @@ Declared in `&lt;sfinae&period;cpp&gt;`
 ----
 template&lt;class T&gt;
 T
-f4(T value);
+f4(T value)
+requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;;
 ----
 
 [#f5]
diff --git a/test-files/golden-tests/metadata/sfinae.html b/test-files/golden-tests/metadata/sfinae.html
index 379940625..d04a5958e 100644
--- a/test-files/golden-tests/metadata/sfinae.html
+++ b/test-files/golden-tests/metadata/sfinae.html
@@ -290,7 +290,8 @@ <h3>Synopsis</h3>
 <code class="source-code cpp">
 template&lt;class T&gt;
 T
-f1(T value);
+f1(T value)
+requires std::is_integral_v&lt;T&gt;;
 </code>
 </pre>
 </div>
@@ -343,7 +344,8 @@ <h3>Synopsis</h3>
 <code class="source-code cpp">
 template&lt;class T&gt;
 int
-f2(T value);
+f2(T value)
+requires std::is_integral_v&lt;T&gt;;
 </code>
 </pre>
 </div>
@@ -365,7 +367,8 @@ <h3>Synopsis</h3>
 <code class="source-code cpp">
 template&lt;class T&gt;
 <a href="#B">B</a>::<a href="#B-C">C</a>
-f3(T value);
+f3(T value)
+requires std::is_integral_v&lt;T&gt;;
 </code>
 </pre>
 </div>
@@ -387,7 +390,8 @@ <h3>Synopsis</h3>
 <code class="source-code cpp">
 template&lt;class T&gt;
 T
-f4(T value);
+f4(T value)
+requires std::is_integral_v&lt;T&gt;;
 </code>
 </pre>
 </div>
diff --git a/test-files/golden-tests/metadata/sfinae.xml b/test-files/golden-tests/metadata/sfinae.xml
index 5289f1e46..27a60ee98 100644
--- a/test-files/golden-tests/metadata/sfinae.xml
+++ b/test-files/golden-tests/metadata/sfinae.xml
@@ -4,7 +4,7 @@
 <namespace id="//////////////////////////8=">
   <template>
     <tparam name="T" class="type"/>
-    <function name="f1" id="Bs19YS1cqZhrsbv149xgnjRFUAk=">
+    <function name="f1" requires="std::is_integral_v&lt;T&gt;" id="Bs19YS1cqZhrsbv149xgnjRFUAk=">
       <file short-path="sfinae.cpp" source-path="sfinae.cpp" line="5"/>
       <return>
         <type name="T"/>
@@ -21,7 +21,7 @@
   </template>
   <template>
     <tparam name="T" class="type"/>
-    <function name="f2" id="uckUKgu5WdbIitoodkl2kXQ7RWI=">
+    <function name="f2" requires="std::is_integral_v&lt;T&gt;" id="uckUKgu5WdbIitoodkl2kXQ7RWI=">
       <file short-path="sfinae.cpp" source-path="sfinae.cpp" line="10"/>
       <return>
         <type name="int"/>
@@ -43,7 +43,7 @@
   </namespace>
   <template>
     <tparam name="T" class="type"/>
-    <function name="f3" id="HIZ4NeNKvHJFhj0tJIjpjaLL30U=">
+    <function name="f3" requires="std::is_integral_v&lt;T&gt;" id="HIZ4NeNKvHJFhj0tJIjpjaLL30U=">
       <file short-path="sfinae.cpp" source-path="sfinae.cpp" line="19"/>
       <return>
         <type id="r/5vKTgl4cXSK5TnuZ/+P7qmkJ0=" name="B::C"/>
@@ -60,7 +60,7 @@
   </template>
   <template>
     <tparam name="T" class="type"/>
-    <function name="f4" id="45LJB0/nCsN3KRlVtnRqNrJG818=">
+    <function name="f4" requires="std::is_integral_v&lt;T&gt;" id="45LJB0/nCsN3KRlVtnRqNrJG818=">
       <file short-path="sfinae.cpp" source-path="sfinae.cpp" line="24"/>
       <return>
         <type name="T"/>
diff --git a/test-files/golden-tests/snippets/sqrt.adoc b/test-files/golden-tests/snippets/sqrt.adoc
index 5f4548efa..bdd814338 100644
--- a/test-files/golden-tests/snippets/sqrt.adoc
+++ b/test-files/golden-tests/snippets/sqrt.adoc
@@ -31,7 +31,8 @@ Declared in `&lt;sqrt&period;cpp&gt;`
 ----
 template&lt;typename T&gt;
 T
-sqrt(T value);
+sqrt(T value)
+requires std&colon;&colon;is&lowbar;integral&lowbar;v&lt;T&gt;;
 ----
 
 === Description
diff --git a/test-files/golden-tests/snippets/sqrt.html b/test-files/golden-tests/snippets/sqrt.html
index 1aec9d79b..48dc20a98 100644
--- a/test-files/golden-tests/snippets/sqrt.html
+++ b/test-files/golden-tests/snippets/sqrt.html
@@ -41,7 +41,8 @@ <h3>Synopsis</h3>
 <code class="source-code cpp">
 template&lt;typename T&gt;
 T
-sqrt(T value);
+sqrt(T value)
+requires std::is_integral_v&lt;T&gt;;
 </code>
 </pre>
 </div>
diff --git a/test-files/golden-tests/snippets/sqrt.xml b/test-files/golden-tests/snippets/sqrt.xml
index c9dc1b9a2..1a423974b 100644
--- a/test-files/golden-tests/snippets/sqrt.xml
+++ b/test-files/golden-tests/snippets/sqrt.xml
@@ -4,7 +4,7 @@
 <namespace id="//////////////////////////8=">
   <template>
     <tparam name="T" class="type"/>
-    <function name="sqrt" id="ulFDUE1svTCX8fV/h8EIp4NNbWs=">
+    <function name="sqrt" requires="std::is_integral_v&lt;T&gt;" id="ulFDUE1svTCX8fV/h8EIp4NNbWs=">
       <file short-path="sqrt.cpp" source-path="sqrt.cpp" line="15" class="def"/>
       <return>
         <type name="T"/>