Skip to content

[Sema] add cast from IncompleteArrayType to ConstantArrayType in TryReferenceListInitialization #65918

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 29, 2023

Conversation

HerrCai0907
Copy link
Contributor

Fixed: #62945
c++20 supports "Permit conversions to arrays of unknown bound". This need additional cast from IncompleteArrayType to ConstantArrayType in TryReferenceListInitialization

…eferenceListInitialization

Fixed: #62945
c++20 supports "Permit conversions to arrays of unknown bound".
This need additional cast from IncompleteArrayType to ConstantArrayType
in TryReferenceListInitialization
@HerrCai0907 HerrCai0907 requested a review from a team as a code owner September 11, 2023 01:18
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 11, 2023
@HerrCai0907
Copy link
Contributor Author

@llvmbot
Copy link
Member

llvmbot commented Sep 11, 2023

@llvm/pr-subscribers-clang

Changes

Fixed: #62945
c++20 supports "Permit conversions to arrays of unknown bound". This need additional cast from IncompleteArrayType to ConstantArrayType in TryReferenceListInitialization

Full diff: https://github.com/llvm/llvm-project/pull/65918.diff

2 Files Affected:

  • (modified) clang/lib/Sema/SemaInit.cpp (+9)
  • (modified) clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp (+9)
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 93f05e2e47285e4..966d35226eec748 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -4532,6 +4532,15 @@ static void TryReferenceListInitialization(Sema &S,
       if (T1Quals.hasAddressSpace())
         Sequence.AddQualificationConversionStep(
             cv1T1, DestType->isRValueReferenceType() ? VK_XValue : VK_LValue);
+      else if (S.getLangOpts().CPlusPlus20 &&
+               isa(T1->getUnqualifiedDesugaredType()) &&
+               DestType->isRValueReferenceType()) {
+        // [dcl.init.list] p3.10
+        // unless T is “reference to array of unknown bound of U”, in which case
+        // the type of the prvalue is the type of x in the declaration U x[] H,
+        // where H is the initializer list.
+        Sequence.AddQualificationConversionStep(cv1T1, VK_XValue);
+      }
     } else
       Sequence.SetFailed(
           InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary);
diff --git a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
index 78f35a024a54014..a29f4d720c1de4e 100644
--- a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
+++ b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp
@@ -23,4 +23,13 @@ auto &frob2(int (&arp)[1]) {
 
   return r2;
 }
+
+// CHECK-LABEL: @_ZN3One3fooEi
+// CHECK-NEXT: entry:
+// CHECK-NEXT: ret void
+void foo(int a) {
+  auto f = [](int(&&)[]) {};
+  f({a});
+}
+
 } // namespace One

@cor3ntin cor3ntin assigned Fznamznon and unassigned Fznamznon Sep 11, 2023
@cor3ntin
Copy link
Contributor

@Fznamznon

Copy link
Contributor

@Fznamznon Fznamznon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs a release note.

cc @erichkeane

// unless T is “reference to array of unknown bound of U”, in which case
// the type of the prvalue is the type of x in the declaration U x[] H,
// where H is the initializer list.
Sequence.AddQualificationConversionStep(cv1T1, VK_XValue);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is qualification conversion right here? I'm not sure we convert qualifiers here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed sequence in the latest commit.
The reason to qualification conversion is that in cpp 20, spec. requires support cast from initializer list to reference to array of unknown bound.

for example:

void foo(int a) {
  auto f = [](int(&&)[]) {};
  f({a});
}

{a} should be casted from int[1] to int[].

ast will look like:

      `-CXXOperatorCallExpr 0x12b904d18 <col:3, col:8> 'void':'void' '()'
        |-ImplicitCastExpr 0x12b904c58 <col:4, col:8> 'void (*)(int (&&)[]) const' <FunctionToPointerDecay>
        | `-DeclRefExpr 0x12b904bd8 <col:4, col:8> 'void (int (&&)[]) const' lvalue CXXMethod 0x12b904008 'operator()' 'void (int (&&)[]) const'
        |-ImplicitCastExpr 0x12b904c70 <col:3> 'const (lambda at ID/test.cpp:2:12)' lvalue <NoOp>
        | `-DeclRefExpr 0x12b904b10 <col:3> '(lambda at ID/test.cpp:2:12)':'(lambda at ID/test.cpp:2:12)' lvalue Var 0x12b8ee210 'f' '(lambda at ID/test.cpp:2:12)':'(lambda at ID/test.cpp:2:12)'
        `-MaterializeTemporaryExpr 0x12b904d00 <col:5, col:7> 'int[]':'int[]' xvalue
          `-ImplicitCastExpr 0x12b904ce8 <col:5, col:7> 'int[]':'int[]' <NoOp>
            `-InitListExpr 0x12b904c88 <col:5, col:7> 'int[1]'
              `-ImplicitCastExpr 0x12b904cc8 <col:6> 'int' <LValueToRValue>
                `-DeclRefExpr 0x12b904b30 <col:6> 'int' lvalue ParmVar 0x12b8edfb8 'a' 'int'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HerrCai0907 I see what you mean and what the patch accomplishes. But my confusion was, why in order to do that AddQualificationConversionStep is called? IMO this is just to convert cv-qualifiers. The goal is to convert one array type to another, right?

Copy link
Contributor Author

@HerrCai0907 HerrCai0907 Sep 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, int[1] to int[] in above example. Because spec. require in this case, type should be int[], but clang will treat initialize list as int[1], which causes crash when IR emit.

@efriedma-quic
Copy link
Collaborator

I guess this ends up producing a CK_NoOp CastExpr? That's probably okay, but can we amend the documentation for CK_NoOp to give this as an example?

@HerrCai0907
Copy link
Contributor Author

I guess this ends up producing a CK_NoOp CastExpr? That's probably okay, but can we amend the documentation for CK_NoOp to give this as an example?

Done

@efriedma-quic
Copy link
Collaborator

LGTM

@HerrCai0907 HerrCai0907 merged commit d89d3a6 into llvm:main Sep 29, 2023
@HerrCai0907 HerrCai0907 deleted the D151515 branch October 10, 2023 00:22
Guzhu-AMD pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Oct 12, 2023
Local branch amd-gfx 6b554b9 Merged main:7ebf3e019488 into amd-gfx:481ed31ee2aa
Remote branch main d89d3a6 [Sema] add cast from IncompleteArrayType to ConstantArrayType in TryReferenceListInitialization (llvm#65918)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

clang crash in CodeGen
5 participants