ChuanqiXu added a comment.

In D119544#3494281 <https://reviews.llvm.org/D119544#3494281>, @erichkeane 
wrote:

> Updated to include the fix for the libcxx issue, which was that we weren't 
> properly differentiating between 'friend' functions based on concepts.  I'll 
> likely be submitting this early monday or so, but would like to give 
> @ChuanqiXu  a chance to check out the changes.
>
> This is the same as my 'last' committed version of this patch, plus the 
> changes I split out into here for easier review: 
> https://reviews.llvm.org/D125020

Sorry that I missed the ping. The change in that revision looks good to me.

> I THINK what we want to do instead of trying to 're setup' the template 
> arguments (and instead of just 'keeping' the uninstantiated expression) is to 
> run some level of 'tree-transform' that updates the names of the template 
> parameters (including depths/etc), but without doing lookup. This I think 
> would fix our 'friend function' issue, and our 'comparing constraints' stuff 
> work correctly as well (rather than storing an instantiated version, but not 
> reusing it except for comparing them).

I agree this should be a better direction.

In D119544#3524844 <https://reviews.llvm.org/D119544#3524844>, @erichkeane 
wrote:

> @rsmith pointed out https://eel.is/c++draft/temp#friend-9 which I think is 
> supposed to fix the friend function issues:
>
>> A non-template friend declaration with a requires-clause shall be a 
>> definition.
>> A friend function template with a constraint that depends on a template 
>> parameter from an enclosing template shall be a definition.
>> Such a constrained friend function or function template declaration does not 
>> declare the same function or function template as a declaration in any other 
>> scope.
>
> To me, this says that
>
>   template<typename T>
>   struct S {
>       friend void foo() requires true {}
>   };
>   void bar() {
>   S<int> s;
>   S<float> s2;
>   }
>
> Should be perfectly fine, and NOT a redefinition?  At least this: 
> https://godbolt.org/z/PaK1Yhn1E seems to show that all 3 compilers get this 
> wrong currently?  Or I'm misreading this.

I agree this one should be fine. I think we could fix the problem by making 
non-template function inside a template class to be a dependent type. Like this 
one is accepted: https://godbolt.org/z/MorzcqE1a
This bug might not be horrible since few developer would write friend function 
definition which doesn't touch the enclosing class.

> It ALSO means that:
>
>   template<typename T>
>   struct S {
>   template<typename U>
>   friend void foo() requires constriant<T> {}
>   };
>   void bar() {
>   S<int> s;
>   S<float> s2;
>   }
>
> is perfectly fine, and not a redefinition. (CURRENT Clang and GCC get this 
> right, but MSVC seems to get it wrong: https://godbolt.org/z/a7dYezoPW)
>
> HOWEVER, By reading the rule, a slightly DIFFERENT version of that
>
>   template<typename T>
>   struct S {
>   template<typename U>
>   friend void foo() requires constriant<U> {} // No longer relies on the 
> enclosing template
>   };
>   void bar() {
>   S<int> s;
>   S<float> s2;
>   }
>
> Is a redefinition.  All 3 compilers diagnose this. 
> https://godbolt.org/z/7qbYsb635

I agree with the two judgement here. It looks like the implementation of clang 
is right on these two versions here.



================
Comment at: clang/lib/Sema/SemaConcept.cpp:169
       //    operand is satisfied.
-      return false;
+      return LHSRes.isUsable() ? BO.recreateBinOp(S, LHSRes) : ExprEmpty();
 
----------------



================
Comment at: clang/lib/Sema/SemaConcept.cpp:178
       //    the second operand is satisfied.
-      return false;
+      return LHSRes.isUsable() ? BO.recreateBinOp(S, LHSRes) : ExprEmpty();
 
----------------



================
Comment at: clang/lib/Sema/SemaConcept.cpp:185-186
+
+    if (!LHSRes.isUsable() || !RHSRes.isUsable())
+      return ExprEmpty();
+    return BO.recreateBinOp(S, LHSRes, RHSRes);
----------------



================
Comment at: clang/lib/Sema/SemaConcept.cpp:70
+    assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
+    assert(LHS.isUsable() && RHS.isUsable() && "Side not usable?");
+    // We should just be able to 'normalize' these to the builtin Binary
----------------
erichkeane wrote:
> ChuanqiXu wrote:
> > I feel like the usage of the API could be further simplified.
> Heh, the suggestion is inverted slightly (those should be `!isUsable`) which 
> caught me for a while :)  Either way, I think it is a good suggestion.
Oh, my bad. It is a typo.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119544/new/

https://reviews.llvm.org/D119544

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to