This is an archive of the discontinued LLVM Phabricator instance.

Forbid implicit conversion of constraint expression to bool
ClosedPublic

Authored by erichkeane on Jan 17 2023, 11:32 AM.

Details

Reviewers
tahonermann
Group Reviewers
Restricted Project
Restricted Project
Commits
rGb5d9f00b2096: Forbid implicit conversion of constraint expression to bool
Summary

As reported in https://github.com/llvm/llvm-project/issues/54524, and
later in https://github.com/llvm/llvm-project/issues/60038, we were not
properly implmenting temp.constr.atomic P3. This patch stops implicitly
converting constraints to bool, and ensures the Rvalue conversion takes
place as needed.

Diff Detail

Event Timeline

erichkeane created this revision.Jan 17 2023, 11:32 AM
Herald added a project: Restricted Project. · View Herald TranscriptJan 17 2023, 11:32 AM
erichkeane requested review of this revision.Jan 17 2023, 11:32 AM

@ldionne @Mordante The libcxx failure isn't clear what it is complaining about, but I thought this fix might end up breaking a libcxx test, since it would be easy to fall into the trap of having an implicit conversion here.

Any chance you could prod at that test a little and see whose fault it is?

ALSO: NOTE TO SELF: need release note!

@ldionne @Mordante The libcxx failure isn't clear what it is complaining about, but I thought this fix might end up breaking a libcxx test, since it would be easy to fall into the trap of having an implicit conversion here.

Any chance you could prod at that test a little and see whose fault it is?

ALSO: NOTE TO SELF: need release note!

I think the problem is that __type_traits/common_reference.h doesn't re-export __type_traits/common_type.h in the modulemap. It should be enough to add export common_type to module common_reference (libcxx/include/module.modulemap.in:1399). See module is_arithmetic for an example. This is just a guess though, this stuff can be very weird.

@ldionne @Mordante The libcxx failure isn't clear what it is complaining about, but I thought this fix might end up breaking a libcxx test, since it would be easy to fall into the trap of having an implicit conversion here.

Any chance you could prod at that test a little and see whose fault it is?

ALSO: NOTE TO SELF: need release note!

I think the problem is that __type_traits/common_reference.h doesn't re-export __type_traits/common_type.h in the modulemap. It should be enough to add export common_type to module common_reference (libcxx/include/module.modulemap.in:1399). See module is_arithmetic for an example. This is just a guess though, this stuff can be very weird.

Oh man, I hope the others know what you're talking about :) I don't really know how I caused this though :/

shafik added a subscriber: shafik.Jan 17 2023, 4:13 PM
shafik added inline comments.
clang/lib/Sema/SemaConcept.cpp
379

minor fix

@ldionne @Mordante The libcxx failure isn't clear what it is complaining about, but I thought this fix might end up breaking a libcxx test, since it would be easy to fall into the trap of having an implicit conversion here.

Any chance you could prod at that test a little and see whose fault it is?

ALSO: NOTE TO SELF: need release note!

I think the problem is that __type_traits/common_reference.h doesn't re-export __type_traits/common_type.h in the modulemap. It should be enough to add export common_type to module common_reference (libcxx/include/module.modulemap.in:1399). See module is_arithmetic for an example. This is just a guess though, this stuff can be very weird.

Oh man, I hope the others know what you're talking about :) I don't really know how I caused this though :/

I've applied your patch locally and this diff fixes the issue:

diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 5d4cf53aa334..30209b353d6b 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -747,7 +747,10 @@ module std [system] {
       module assignable                 { private header "__concepts/assignable.h" }
       module boolean_testable           { private header "__concepts/boolean_testable.h" }
       module class_or_enum              { private header "__concepts/class_or_enum.h" }
-      module common_reference_with      { private header "__concepts/common_reference_with.h" }
+      module common_reference_with      {
+        private header "__concepts/common_reference_with.h"
+        export type_traits.common_reference
+      }
       module common_with                { private header "__concepts/common_with.h" }
       module constructible              { private header "__concepts/constructible.h" }
       module convertible_to             { private header "__concepts/convertible_to.h" }

I don't know why your patch changes the behaviour of clang here, but I wouldn't worry too much about it. There is a lot of weirdness around modules and dependent type names resulting in pretty much useless error messages. I hope the work on C++ modules reduces this weirdness, but I don't really know how that stuff works.

erichkeane marked an inline comment as done.Jan 18 2023, 5:50 AM

@ldionne @Mordante The libcxx failure isn't clear what it is complaining about, but I thought this fix might end up breaking a libcxx test, since it would be easy to fall into the trap of having an implicit conversion here.

Any chance you could prod at that test a little and see whose fault it is?

ALSO: NOTE TO SELF: need release note!

I think the problem is that __type_traits/common_reference.h doesn't re-export __type_traits/common_type.h in the modulemap. It should be enough to add export common_type to module common_reference (libcxx/include/module.modulemap.in:1399). See module is_arithmetic for an example. This is just a guess though, this stuff can be very weird.

Oh man, I hope the others know what you're talking about :) I don't really know how I caused this though :/

I've applied your patch locally and this diff fixes the issue:

diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 5d4cf53aa334..30209b353d6b 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -747,7 +747,10 @@ module std [system] {
       module assignable                 { private header "__concepts/assignable.h" }
       module boolean_testable           { private header "__concepts/boolean_testable.h" }
       module class_or_enum              { private header "__concepts/class_or_enum.h" }
-      module common_reference_with      { private header "__concepts/common_reference_with.h" }
+      module common_reference_with      {
+        private header "__concepts/common_reference_with.h"
+        export type_traits.common_reference
+      }
       module common_with                { private header "__concepts/common_with.h" }
       module constructible              { private header "__concepts/constructible.h" }
       module convertible_to             { private header "__concepts/convertible_to.h" }

I don't know why your patch changes the behaviour of clang here, but I wouldn't worry too much about it. There is a lot of weirdness around modules and dependent type names resulting in pretty much useless error messages. I hope the work on C++ modules reduces this weirdness, but I don't really know how that stuff works.

Thanks! I'll apply that patch here and see if it makes the bot happy.

erichkeane added a reviewer: Restricted Project.

Add module map fix, add nit from Shafik.

Also, I forgot I added the release notes in that last patch :)

Speaking of: I guess the libcxx failure is NOT caused by me? https://reviews.llvm.org/D141992

I see this on a different review, despite this not being committed.

Speaking of: I guess the libcxx failure is NOT caused by me? https://reviews.llvm.org/D141992

I see this on a different review, despite this not being committed.

That's not great. Seems like some recently landed patch broke this. Do you mind committing the libc++-part of this patch to get the Clang CI green again? (Assuming the libc++ CI is green)

Speaking of: I guess the libcxx failure is NOT caused by me? https://reviews.llvm.org/D141992

I see this on a different review, despite this not being committed.

That's not great. Seems like some recently landed patch broke this. Do you mind committing the libc++-part of this patch to get the Clang CI green again? (Assuming the libc++ CI is green)

If this passes, I might just do the module-map patch as a separate commit to fix the CI, else the libcxx history is going to be awful strange :) I'm probably a bit from having this review approved anyway, as it is still 'night time' for most of my reviewers :)

The changes to the module map file seemed to make things worse! I reverted it for now, hoping this just goes green.

I see the current main pass for the module build in libc++. The error message seems different, from the message for missing parts of the module map. I'll dig a bit further to see whether I can find what's wrong.

I just tested locally with the latest nightly build

Debian clang version 16.0.0 (++20230116071901+2563ad8ef1a8-1~exp1~20230116072002.532)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

and that passes the test that fails in the CI.

Can you test whether the issue occurs for you in HEAD without your patch.

@ldionne would it make sense to test the Clang CI in the scheduled build too, that would make pin-pointing a possible regression easier.

I just tested locally with the latest nightly build

Debian clang version 16.0.0 (++20230116071901+2563ad8ef1a8-1~exp1~20230116072002.532)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

and that passes the test that fails in the CI.

Can you test whether the issue occurs for you in HEAD without your patch.

@ldionne would it make sense to test the Clang CI in the scheduled build too, that would make pin-pointing a possible regression easier.

I don't have the libcxx build/tests set up in my environment anymore (and it was a bit of a hassle the last time, which was my motivation for asking @ldionne for pre-commit on clang patches :D ), so I don't really have the ability to run that test.

tahonermann added inline comments.
clang/lib/Sema/SemaConcept.cpp
377–380

ImplicitCastExpr::Create() has the following assertion. I wonder if we need to guard against this here.

clang/lib/AST/Expr.cpp:
2073   assert((Kind != CK_LValueToRValue ||
2074           !(T->isNullPtrType() || T->getAsCXXRecordDecl())) &&
2075          "invalid type for lvalue-to-rvalue conversion");

Or perhaps it would be better to call Sema::DefaultLvalueConversion() here?

383

This comment appears to be unnecessary.

clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
3–4

I'm not sure what this is intending to exercise. C isn't used elsewhere; this just appears to validate that a well-formed concept declaration is accepted (even if it is one that will always evaluate as false). I suggest modifying it to drop == 4 && !true and then validate that a diagnostic is issued (which might require a use of the concept).

28

These tests look good.

I think we should also exercise nested requirements to ensure that behavior is consistent:

template<typename T> requires requires {
  requires S<T>{};
}
void f3(T);
void f3(int);

Perhaps also add some examples where && does not denote a conjunction of atomic constraints. For example:

template<typename T> requires (bool(1 && 2))
void f4(T);
void f4(int);
libcxx/include/module.modulemap.in
750–753

I agree with this being done in a separate commit.

erichkeane added inline comments.Jan 18 2023, 12:45 PM
clang/lib/Sema/SemaConcept.cpp
377–380

I don't think we want all the baggage that DefaultLvalueConversion gets us, including diagnostics/etc. That assert IS concerning though... I presume we can come up with something to hit that.

It DOES look like that DefeaultLValue conversion replaces the nullptrtypes with a NullToPointer cast, so perhaps I should do that, and doesn't do anything with a record type.

383

Woops! I thought that wasn't mine :D

clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp
3–4

This is exactly out of the standard, which is why I copied it. however, a test for the diagnostic version seems like a good idea.

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).

tahonermann added inline comments.Jan 18 2023, 2:37 PM
clang/lib/Sema/SemaConcept.cpp
377–380

I'm surprised the additional checks for nullptr aren't tripping that assert; it looks to me like it should. Any ideas?

erichkeane added inline comments.Jan 18 2023, 7:16 PM
clang/lib/Sema/SemaConcept.cpp
377–380

I moved the creation of this AFTER 'CheckConstraintExpression', which will fail unless the type is 'bool' already. SO the expression here cannot be a nullptr or struct type. Before I moved it and wrote the new tests (NullTy and StructTy), it actually did hit the assert you mentioned.

Fix clang-format, hopefully this saves me from the bots ;)

tahonermann accepted this revision as: tahonermann.Jan 19 2023, 9:22 AM

Looks good to me.

clang/lib/Sema/SemaConcept.cpp
377–380

Ah, perfect!

This revision is now accepted and ready to land.Jan 19 2023, 9:22 AM
This revision was landed with ongoing or failed builds.Jan 19 2023, 10:13 AM
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptJan 19 2023, 10:13 AM