diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 148ff050085526..8c2f737836a9dc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -846,6 +846,7 @@ Bug Fixes to C++ Support - Fix a crash caused by improper use of ``__array_extent``. (#GH80474) - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). +- Fixed handling of brace ellison when building deduction guides. (#GH64625), (#GH83368). Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 7244f3ef4e829e..e805834c0fd38e 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -513,7 +513,7 @@ class InitListChecker { : InitListChecker(S, Entity, IL, T, /*VerifyOnly=*/true, /*TreatUnavailableAsInvalid=*/false, /*InOverloadResolution=*/false, - &AggrDeductionCandidateParamTypes){}; + &AggrDeductionCandidateParamTypes) {} bool HadError() { return hadError; } @@ -1443,7 +1443,21 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // dependent non-array type or an array type with a value-dependent // bound assert(AggrDeductionCandidateParamTypes); - if (!isa_and_nonnull( + + // In the presence of a braced-init-list within the initializer, we should + // not perform brace-elision, even if brace elision would otherwise be + // applicable. For example, given: + // + // template struct Foo { + // T t[2]; + // }; + // + // Foo t = {{1, 2}}; + // + // we don't want the (T, T) but rather (T [2]) in terms of the initializer + // {{1, 2}}. + if (isa(expr) || + !isa_and_present( SemaRef.Context.getAsArrayType(ElemType))) { ++Index; AggrDeductionCandidateParamTypes->push_back(ElemType); @@ -10940,14 +10954,14 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer( // if e_i is of array type and x_i is a braced-init-list, T_i is an // rvalue reference to the declared type of e_i and // C++ [over.match.class.deduct]p1.9: - // if e_i is of array type and x_i is a bstring-literal, T_i is an + // if e_i is of array type and x_i is a string-literal, T_i is an // lvalue reference to the const-qualified declared type of e_i and // C++ [over.match.class.deduct]p1.10: // otherwise, T_i is the declared type of e_i for (int I = 0, E = ListInit->getNumInits(); I < E && !isa(ElementTypes[I]); ++I) if (ElementTypes[I]->isArrayType()) { - if (isa(ListInit->getInit(I))) + if (isa(ListInit->getInit(I))) ElementTypes[I] = Context.getRValueReferenceType(ElementTypes[I]); else if (isa( ListInit->getInit(I)->IgnoreParenImpCasts())) diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index 171c5413feaa7c..163b36519950f8 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -335,3 +335,142 @@ namespace TTP { // CHECK-NEXT: `-TemplateArgument type 'T':'type-parameter-0-0'{{$}} // CHECK-NEXT: `-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0{{$}} // CHECK-NEXT: `-TemplateTypeParm {{.+}} 'T'{{$}} + +namespace GH64625 { + +template struct X { + T t[2]; +}; + +X x = {{1, 2}}; + +// CHECK-LABEL: Dumping GH64625::: +// CHECK-NEXT: FunctionTemplateDecl {{.+}} <{{.+}}:[[#@LINE - 7]]:1, col:27> col:27 implicit +// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} col:17 referenced class depth 0 index 0 T +// CHECK: |-CXXDeductionGuideDecl {{.+}} col:27 implicit 'auto (T (&&)[2]) -> X' aggregate +// CHECK-NEXT: | `-ParmVarDecl {{.+}} col:27 'T (&&)[2]' +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} col:27 implicit used 'auto (int (&&)[2]) -> GH64625::X' implicit_instantiation aggregate +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.+}} 'int' +// CHECK-NEXT: `-ParmVarDecl {{.+}} col:27 'int (&&)[2]' +// CHECK-NEXT: FunctionProtoType {{.+}} 'auto (T (&&)[2]) -> X' dependent trailing_return +// CHECK-NEXT: |-InjectedClassNameType {{.+}} 'X' dependent +// CHECK-NEXT: | `-CXXRecord {{.+}} 'X' +// CHECK-NEXT: `-RValueReferenceType {{.+}} 'T (&&)[2]' dependent +// CHECK-NEXT: `-ConstantArrayType {{.+}} 'T[2]' dependent 2 +// CHECK-NEXT: `-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0 +// CHECK-NEXT: `-TemplateTypeParm {{.+}} 'T' + +template struct TwoArrays { + T t[2]; + U u[3]; +}; + +TwoArrays ta = {{1, 2}, {3, 4, 5}}; +// CHECK-LABEL: Dumping GH64625::: +// CHECK-NEXT: FunctionTemplateDecl {{.+}} <{{.+}}:[[#@LINE - 7]]:1, col:36> col:36 implicit +// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} col:17 referenced class depth 0 index 0 T +// CHECK-NEXT: |-TemplateTypeParmDecl {{.+}} col:26 referenced class depth 0 index 1 U +// CHECK: |-CXXDeductionGuideDecl {{.+}} col:36 implicit 'auto (T (&&)[2], U (&&)[3]) -> TwoArrays' aggregate +// CHECK-NEXT: | |-ParmVarDecl {{.+}} col:36 'T (&&)[2]' +// CHECK-NEXT: | `-ParmVarDecl {{.+}} col:36 'U (&&)[3]' +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} col:36 implicit used 'auto (int (&&)[2], int (&&)[3]) -> GH64625::TwoArrays' implicit_instantiation aggregate +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.+}} 'int' +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.+}} 'int' +// CHECK-NEXT: |-ParmVarDecl {{.+}} col:36 'int (&&)[2]' +// CHECK-NEXT: `-ParmVarDecl {{.+}} col:36 'int (&&)[3]' +// CHECK-NEXT: FunctionProtoType {{.+}} 'auto (T (&&)[2], U (&&)[3]) -> TwoArrays' dependent trailing_return +// CHECK-NEXT: |-InjectedClassNameType {{.+}} 'TwoArrays' dependent +// CHECK-NEXT: | `-CXXRecord {{.+}} 'TwoArrays' +// CHECK-NEXT: |-RValueReferenceType {{.+}} 'T (&&)[2]' dependent +// CHECK-NEXT: | `-ConstantArrayType {{.+}} 'T[2]' dependent 2 +// CHECK-NEXT: | `-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0 +// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'T' +// CHECK-NEXT: `-RValueReferenceType {{.+}} 'U (&&)[3]' dependent +// CHECK-NEXT: `-ConstantArrayType {{.+}} 'U[3]' dependent 3 +// CHECK-NEXT: `-TemplateTypeParmType {{.+}} 'U' dependent depth 0 index 1 +// CHECK-NEXT: `-TemplateTypeParm {{.+}} 'U' + +TwoArrays tb = {1, 2, {3, 4, 5}}; +// CHECK: |-CXXDeductionGuideDecl {{.+}} col:36 implicit 'auto (T, T, U (&&)[3]) -> TwoArrays' aggregate +// CHECK-NEXT: | |-ParmVarDecl {{.+}} col:36 'T' +// CHECK-NEXT: | |-ParmVarDecl {{.+}} col:36 'T' +// CHECK-NEXT: | `-ParmVarDecl {{.+}} col:36 'U (&&)[3]' +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} col:36 implicit used 'auto (int, int, int (&&)[3]) -> GH64625::TwoArrays' implicit_instantiation aggregate +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.+}} 'int' +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.+}} 'int' +// CHECK-NEXT: |-ParmVarDecl {{.+}} col:36 'int' +// CHECK-NEXT: |-ParmVarDecl {{.+}} col:36 'int' +// CHECK-NEXT: `-ParmVarDecl {{.+}} col:36 'int (&&)[3]' +// CHECK-NEXT: FunctionProtoType {{.+}} 'auto (T, T, U (&&)[3]) -> TwoArrays' dependent trailing_return +// CHECK-NEXT: |-InjectedClassNameType {{.+}} 'TwoArrays' dependent +// CHECK-NEXT: | `-CXXRecord {{.+}} 'TwoArrays' +// CHECK-NEXT: |-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0 +// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'T' +// CHECK-NEXT: |-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0 +// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'T' +// CHECK-NEXT: `-RValueReferenceType {{.+}} 'U (&&)[3]' dependent +// CHECK-NEXT: `-ConstantArrayType {{.+}} 'U[3]' dependent 3 +// CHECK-NEXT: `-TemplateTypeParmType {{.+}} 'U' dependent depth 0 index 1 +// CHECK-NEXT: `-TemplateTypeParm {{.+}} 'U' + +TwoArrays tc = {{1, 2}, 3, 4, 5}; +// CHECK: |-CXXDeductionGuideDecl {{.+}} col:36 implicit 'auto (T (&&)[2], U, U, U) -> TwoArrays' aggregate +// CHECK-NEXT: | |-ParmVarDecl {{.+}} col:36 'T (&&)[2]' +// CHECK-NEXT: | |-ParmVarDecl {{.+}} col:36 'U' +// CHECK-NEXT: | |-ParmVarDecl {{.+}} col:36 'U' +// CHECK-NEXT: | `-ParmVarDecl {{.+}} col:36 'U' +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} col:36 implicit used 'auto (int (&&)[2], int, int, int) -> GH64625::TwoArrays' implicit_instantiation aggregate +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.+}} 'int' +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType {{.+}} 'int' +// CHECK-NEXT: |-ParmVarDecl {{.+}} col:36 'int (&&)[2]' +// CHECK-NEXT: |-ParmVarDecl {{.+}} col:36 'int' +// CHECK-NEXT: |-ParmVarDecl {{.+}} col:36 'int' +// CHECK-NEXT: `-ParmVarDecl {{.+}} col:36 'int' +// CHECK-NEXT: FunctionProtoType {{.+}} 'auto (T (&&)[2], U, U, U) -> TwoArrays' dependent trailing_return +// CHECK-NEXT: |-InjectedClassNameType {{.+}} 'TwoArrays' dependent +// CHECK-NEXT: | `-CXXRecord {{.+}} 'TwoArrays' +// CHECK-NEXT: |-RValueReferenceType {{.+}} 'T (&&)[2]' dependent +// CHECK-NEXT: | `-ConstantArrayType {{.+}} 'T[2]' dependent 2 +// CHECK-NEXT: | `-TemplateTypeParmType {{.+}} 'T' dependent depth 0 index 0 +// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'T' +// CHECK-NEXT: |-TemplateTypeParmType {{.+}} 'U' dependent depth 0 index 1 +// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'U' +// CHECK-NEXT: |-TemplateTypeParmType {{.+}} 'U' dependent depth 0 index 1 +// CHECK-NEXT: | `-TemplateTypeParm {{.+}} 'U' +// CHECK-NEXT: `-TemplateTypeParmType {{.+}} 'U' dependent depth 0 index 1 +// CHECK-NEXT: `-TemplateTypeParm {{.+}} 'U' + +} // namespace GH64625 + +namespace GH83368 { + +template struct A { + int f1[N]; +}; + +A a{.f1 = {1}}; + +// CHECK-LABEL: Dumping GH83368::: +// CHECK-NEXT: FunctionTemplateDecl 0x{{.+}} <{{.+}}:[[#@LINE - 7]]:1, col:25> col:25 implicit +// CHECK-NEXT: |-NonTypeTemplateParmDecl {{.+}} col:15 referenced 'int' depth 0 index 0 N +// CHECK: |-CXXDeductionGuideDecl {{.+}} col:25 implicit 'auto (int (&&)[N]) -> A' aggregate +// CHECK-NEXT: | `-ParmVarDecl {{.+}} col:25 'int (&&)[N]' +// CHECK-NEXT: `-CXXDeductionGuideDecl {{.+}} col:25 implicit used 'auto (int (&&)[1]) -> GH83368::A<1>' implicit_instantiation aggregate +// CHECK-NEXT: |-TemplateArgument integral '1' +// CHECK-NEXT: `-ParmVarDecl {{.+}} col:25 'int (&&)[1]' +// CHECK-NEXT: FunctionProtoType {{.+}} 'auto (int (&&)[N]) -> A' dependent trailing_return +// CHECK-NEXT: |-InjectedClassNameType {{.+}} 'A' dependent +// CHECK-NEXT: | `-CXXRecord {{.+}} 'A' +// CHECK-NEXT: `-RValueReferenceType {{.+}} 'int (&&)[N]' dependent +// CHECK-NEXT: `-DependentSizedArrayType {{.+}} 'int[N]' dependent +// CHECK-NEXT: |-BuiltinType {{.+}} 'int' +// CHECK-NEXT: `-DeclRefExpr {{.+}} 'int' NonTypeTemplateParm {{.+}} 'N' 'int' + +} // namespace GH83368