erichkeane updated this revision to Diff 490278.
erichkeane added a comment.

Added tests suggested by Tom, also moved the cast creation after checking of 
the return type, so that we end up not hitting hte assert that Tom came up 
with.  Added 2 tests that show the two conditions (that DID repro as a crash).


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

https://reviews.llvm.org/D141954

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaConcept.cpp
  
clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp

Index: clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
===================================================================
--- /dev/null
+++ clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
@@ -0,0 +1,67 @@
+// RUN: %clang_cc1 -std=c++20 -x c++ -Wno-constant-logical-operand -verify %s
+
+template<typename T> concept C =
+sizeof(T) == 4 && !true;      // requires atomic constraints sizeof(T) == 4 and !true
+
+template<typename T> concept C2 = sizeof(T); // expected-error{{atomic constraint must be of type 'bool' (found }}
+
+template<typename T> struct S {
+  constexpr operator bool() const { return true; }
+};
+
+// expected-error@+3{{atomic constraint must be of type 'bool' (found 'S<int>')}}
+// expected-note@#FINST{{while checking constraint satisfaction}}
+// expected-note@#FINST{{in instantiation of function template specialization}}
+template<typename T> requires (S<T>{})
+void f(T);
+void f(int);
+
+// Ensure this applies to operator && as well.
+// expected-error@+3{{atomic constraint must be of type 'bool' (found 'S<int>')}}
+// expected-note@#F2INST{{while checking constraint satisfaction}}
+// expected-note@#F2INST{{in instantiation of function template specialization}}
+template<typename T> requires (S<T>{} && true)
+void f2(T);
+void f2(int);
+
+template<typename T> requires requires {
+  requires S<T>{};
+  // expected-error@-1{{atomic constraint must be of type 'bool' (found 'S<int>')}}
+  // expected-note@-2{{while checking the satisfaction}}
+  // expected-note@-3{{in instantiation of requirement}}
+  // expected-note@-4{{while checking the satisfaction}}
+  // expected-note@-6{{while substituting template arguments}}
+  // expected-note@#F3INST{{while checking constraint satisfaction}}
+  // expected-note@#F3INST{{in instantiation of function template specialization}}
+  //
+}
+void f3(T);
+void f3(int);
+
+// Doesn't diagnose, since this is no longer a compound requirement.
+template<typename T> requires (bool(1 && 2))
+void f4(T);
+void f4(int);
+
+void g() {
+  f(0); // #FINST
+  f2(0); // #F2INST
+  f3(0); // #F3INST
+  f4(0);
+}
+
+template<typename T>
+auto Nullptr = nullptr;
+
+template<typename T> concept NullTy = Nullptr<T>;
+// expected-error@-1{{atomic constraint must be of type 'bool' (found }}
+// expected-note@+1{{while checking the satisfaction}}
+static_assert(NullTy<int>);
+
+template<typename T>
+auto Struct = S<T>{};
+
+template<typename T> concept StructTy = Struct<T>;
+// expected-error@-1{{atomic constraint must be of type 'bool' (found 'S<int>')}}
+// expected-note@+1{{while checking the satisfaction}}
+static_assert(StructTy<int>);
Index: clang/lib/Sema/SemaConcept.cpp
===================================================================
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -329,14 +329,7 @@
           Sema::SFINAETrap Trap(S);
           SubstitutedExpression =
               S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
-          // Substitution might have stripped off a contextual conversion to
-          // bool if this is the operand of an '&&' or '||'. For example, we
-          // might lose an lvalue-to-rvalue conversion here. If so, put it back
-          // before we try to evaluate.
-          if (SubstitutedExpression.isUsable() &&
-              !SubstitutedExpression.isInvalid())
-            SubstitutedExpression =
-                S.PerformContextuallyConvertToBool(SubstitutedExpression.get());
+
           if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
             // C++2a [temp.constr.atomic]p1
             //   ...If substitution results in an invalid type or expression, the
@@ -373,6 +366,23 @@
         if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
           return ExprError();
 
+        // [temp.constr.atomic]p3: To determine if an atomic constraint is
+        // satisfied, the parameter mapping and template arguments are first
+        // substituted into its expression.  If substitution results in an
+        // invalid type or expression, the constraint is not satisfied.
+        // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
+        // and E shall be a constant expression of type bool.
+        //
+        // Perform the L to R Value conversion if necessary. We do so for all
+        // non-PRValue categories, else we fail to extend the lifetime of
+        // temporaries, and that fails the constant expression check.
+        if (!SubstitutedExpression.get()->isPRValue())
+          SubstitutedExpression = ImplicitCastExpr::Create(
+              S.Context, SubstitutedExpression.get()->getType(),
+              CK_LValueToRValue, SubstitutedExpression.get(),
+              /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
+
+
         return SubstitutedExpression;
       });
 }
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -767,6 +767,9 @@
   and `P1975R0: <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1975r0.html>`_,
   which allows parenthesized aggregate-initialization.
 
+- Fixed an issue with concept requirement evaluation, where we incorrectly allowed implicit
+  conversions to bool for a requirement.  This fixes `GH54524 <https://github.com/llvm/llvm-project/issues/54524>`_.
+
 C++2b Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to