aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaInit.cpp
AgeCommit message (Collapse)AuthorFilesLines
2025-03-25[clang] Refine handling of C++20 aggregate initialization (#131320)offsetof1-41/+65
* Move parts of `InitializationSequence::InitializeFrom` corresponding to C++ [dcl.init.general] p16.6.1 and p16.6.2 into a separate function,`TryConstructorOrParenListInitialization` * Use it in `TryListInitialization` to implement [dcl.init.list] p3.2 * Fix parenthesized aggregate initialization being attempted in copy-initialization contexts or when the constructor call is ambiguous Co-authored-by: cor3ntin <corentinjabot@gmail.com>
2025-03-20[clang] Introduce "binary" StringLiteral for #embed data (#127629)Mariya Podchishchaeva1-0/+1
StringLiteral is used as internal data of EmbedExpr and we directly use it as an initializer if a single EmbedExpr appears in the initializer list of a char array. It is fast and convenient, but it is causing problems when string literal character values are checked because #embed data values are within a range [0-2^(char width)] but ordinary StringLiteral is of maybe signed char type. This PR introduces new kind of StringLiteral to hold binary data coming from an embedded resource to mitigate these problems. The new kind of StringLiteral is not assumed to have signed char type. The new kind of StringLiteral also helps to prevent crashes when trying to find StringLiteral token locations since these simply do not exist for binary data. Fixes https://github.com/llvm/llvm-project/issues/119256
2025-03-10Revert "[clang] Implement instantiation context note for checking template ↵Nikita Popov1-3/+4
parameters (#126088)" This reverts commit a24523ac8dc07f3478311a5969184b922b520395. This is causing significant compile-time regressions for C++ code, see: https://github.com/llvm/llvm-project/pull/126088#issuecomment-2704874202
2025-03-06[clang] Implement instantiation context note for checking template ↵Matheus Izvekov1-4/+3
parameters (#126088) Instead of manually adding a note pointing to the relevant template parameter to every relevant error, which is very easy to miss, this patch adds a new instantiation context note, so that this can work using RAII magic. This fixes a bunch of places where these notes were missing, and is more future-proof. Some diagnostics are reworked to make better use of this note: - Errors about missing template arguments now refer to the parameter which is missing an argument. - Template Template parameter mismatches now refer to template parameters as parameters instead of arguments. It's likely this will add the note to some diagnostics where the parameter is not super relevant, but this can be reworked with time and the decrease in maintenance burden makes up for it. This bypasses the templight dumper for the new context entry, as the tests are very hard to update. This depends on #125453, which is needed to avoid losing the context note for errors occuring during template argument deduction.
2025-03-05[clang] Fix crash when #embed data does not fit into an array (#129567)Mariya Podchishchaeva1-2/+4
Tune SemaInit code handling #embed to take into account how many array elements remains to initialize. Also issue a warning/error message when the array/struct is at the end but there is still #embed data left. Fixes https://github.com/llvm/llvm-project/issues/128987
2025-02-28[clang] Fix issues with #embed and intializer lists/template arguments (#128890)Mariya Podchishchaeva1-1/+1
Sometimes number of expressions in InitListExpr is used for template argument deduction. So, in these cases we need to pay attention to real number of expressions including expanded #embed data. Fixes https://github.com/llvm/llvm-project/issues/122306
2025-02-27[Clang][Sema] Add special handling of mfloat8 in initializer lists (#125097)Lukacma1-1/+2
This patch fixes assertion failures in clang, caused by unique properties of _mfp8 type, namely it not being either scalar or vector type and it not being either integer or float type.
2025-02-20[NFC][clang] Cleanup in APValue and SemaInit (#127790)Mariya Podchishchaeva1-1/+0
APValue: Additional assignment of AllowConstexprUnknown is not required since it will be handled by copy constructor called above. SemaInit: Remove unnecessary null check. DestRecordDecl can't be null due to being obtained using `cast` and assertion that DestRecordType is present. Spotted by a static analysis tool.
2025-02-18[HLSL] Allow arrays to copy-initialize (#127557)Chris B1-0/+12
This change allows array variables to copy-initialize from other arrays. It also corrects a small error in HLSL C-Style casting that did not error on casting to arrays if elementwise and splat conversions fail. Fixes #127551
2025-02-15[HLSL] Implement HLSL intialization list support (#123141)Chris B1-0/+5
This PR implements HLSL's initialization list behvaior as specified in the draft language specifcation under [*Decl.Init.Agg*](https://microsoft.github.io/hlsl-specs/specs/hlsl.html#Decl.Init.Agg). This behavior is a bit unusual for C/C++ because intermediate braces in initializer lists are ignored and a whole array of additional conversions occur unintuitively to how initializaiton works in C. The implementaiton in this PR generates a valid C/C++ initialization list AST for the HLSL initializer so that there are no changes required to Clang's CodeGen to support this. This design will also allow us to use Clang's rewrite to convert HLSL initializers to valid C/C++ initializers that are equivalent. It does have the downside that it will generate often redundant accesses during codegen. The IR optimizer is extremely good at eliminating those so this will have no impact on the final executable performance. There is some opportunity for optimizing the initializer list generation that we could consider in subsequent commits. One notable opportunity would be to identify aggregate objects that occur in the same place in both initializers and do not require converison, those aggregates could be initialized as aggregates rather than fully scalarized. Closes #56067 --------- Co-authored-by: Finn Plummer <50529406+inbelic@users.noreply.github.com> Co-authored-by: Helena Kotas <hekotas@microsoft.com> Co-authored-by: Justin Bogner <mail@justinbogner.com>
2025-02-11Fix false positive of [[clang::require_explicit_initialization]] on ↵higher-performance1-1/+3
copy/move constructors (#126553) Fixes #126490
2025-02-08[Clang][Sema] Fix wrong initialization kind when handling initializing ↵Yanzuo Liu1-2/+6
structured bindings from an array with direct-list-initialization (#124793) In 377257f063c, elements of structured bindings are copy-initialized. They should be direct-initialized because the form of the initializer of the whole structured bindings is a direct-list-initialization. > [dcl.struct.bind]/1: > ... and each element is copy-initialized or direct-initialized from the corresponding element of the assignment-expression as specified by the form of the initializer. ... For example, ```cpp int arr[2]{}; // elements of `[a, b]` should be direct-initialized auto [a, b]{arr}; ```
2025-02-03[Sema] Note member decl when initializer list default constructs member ↵Brian Foley1-0/+11
(#121854) Recently I had a scenario where I had: 1. A class C with many members m_1...m_n of the same type T 2. T's default constructor was deleted 3. I accidentally omitted an explicitly constructed member in the initializer list C() : m_1(foo), m_2(bar), ... { } Clang told me that T's default constructor was deleted, and told me that the call to T() was in C() (which it implicitly was), but didn't tell me which member was being default constructed. It was difficult to fix this problem because I had no easy way to list all the members of type T in C and C's superclasses which would have let me find which member was missing, clang/test/CXX/class/class.init/p1.cpp is a simplified version of this problem (a2 is missing from the initializer list of B)
2025-01-30Fix false negative when value initializing a field annotated with ↵higher-performance1-1/+3
[[clang::require_field_initialization]] (#124329) It turns out we weren't handling one case: the value-initialization of a field inside a struct. I'm not sure why this falls under `IK_Direct` rather than `IK_Value` in Clang, but it seems to work.
2025-01-14Add Clang attribute to ensure that fields are initialized explicitly (#102040)higher-performance1-0/+58
This is a new Clang-specific attribute to ensure that field initializations are performed explicitly. For example, if we have ``` struct B { [[clang::explicit]] int f1; }; ``` then the diagnostic would trigger if we do `B b{};`: ``` field 'f1' is left uninitialized, but was marked as requiring initialization ``` This prevents callers from accidentally forgetting to initialize fields, particularly when new fields are added to the class.
2025-01-03[clang] Fix #embed "fast path" (#121479)Mariya Podchishchaeva1-7/+2
When a single #embed directive is used to initialize a char array, the case is optimized via swap of EmbedExpr to underlying StringLiteral, resulting in better performance in AST consumers. While browsing through the code, I realized that 7122b70cfc8e23a069410215c363da76d842bda4 which changed type of EmbedExpr made the "fast path" unreachable. This patch fixes this unfortunate situation.
2024-12-10[clang] Fix a crash issue that caused by handling of fields with ↵yronglin1-0/+1
initializers in nested anonymous unions (#113049) Fixes: https://github.com/llvm/llvm-project/issues/112560 This PR create an RecoveryExpr for invalid in-class-initializer. --------- Signed-off-by: yronglin <yronglin777@gmail.com>
2024-11-20[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)Utkarsh Saxena1-1/+1
This PR uses the existing lifetime analysis for the `capture_by` attribute. The analysis is behind `-Wdangling-capture` warning and is disabled by default for now. Once it is found to be stable, it will be default enabled. Planned followup: - add implicit inference of this attribute on STL container methods like `std::vector::push_back`. - (consider) warning if capturing `X` cannot capture anything. It should be a reference, pointer or a view type. - refactoring temporary visitors and other related handlers. - start discussing `__global` vs `global` in the annotation in a separate PR. --------- Co-authored-by: Boaz Brickner <brickner@google.com>
2024-11-16[Sema] Remove unused includes (NFC) (#116461)Kazu Hirata1-4/+0
Identified with misc-include-cleaner.
2024-11-15[Clang] Use TargetInfo when deciding if an address space is compatible ↵Joseph Huber1-9/+10
(#115777) Summary: Address spaces are used in several embedded and GPU targets to describe accesses to different types of memory. Currently we use the address space enumerations to control which address spaces are considered supersets of eachother, however this is also a target level property as described by the C standard's passing mentions. This patch allows the address space checks to use the target information to decide if a pointer conversion is legal. For AMDGPU and NVPTX, all supported address spaces can be converted to the default address space. More semantic checks can be added on top of this, for now I'm mainly looking to get more standard semantics working for C/C++. Right now the address space conversions must all be done explicitly in C/C++ unlike the offloading languages which define their own custom address spaces that just map to the same target specific ones anyway. The main question is if this behavior is a function of the target or the language.
2024-11-06Revert "Reapply "[Clang][Sema] Refactor collection of multi-level template ↵Krystian Stasiowski1-1/+1
argument lists (#106585, #111173)" (#111852)" (#115159) This reverts commit 2bb3d3a3f32ffaef3d9b6a27db7f1941f0cb1136.
2024-11-06Revert "Reapply "[Clang][Sema] Always use latest redeclaration of primary ↵Krystian Stasiowski1-1/+1
template" (#114569)" (#115156) This reverts commit b24650e814e55d90acfc40acf045456c98f32b9c.
2024-11-04[clang][sema] Fixed a crash when mixture of designated and non-designated ↵Congcong Cai1-3/+6
initializers in union (#114424) Fixed: #113855 When the first init element is invalid, StructuredList can be empty. It cause illegal state if we still set initialized field.
2024-11-01Reapply "[Clang][Sema] Always use latest redeclaration of primary template" ↵Krystian Stasiowski1-1/+1
(#114569) This patch reapplies #114258, fixing an infinite recursion bug in `ASTImporter` that occurs when importing the primary template of a class template specialization when the latest redeclaration of that template is a friend declaration in the primary template.
2024-10-30Revert "[Clang][Sema] Always use latest redeclaration of primary template" ↵Felipe de Azevedo Piovezan1-1/+1
(#114304) Clang importer doesn't seem to work well with this change, see discussion in the original PR. Reverts llvm/llvm-project#114258
2024-10-30[Clang][Sema] Always use latest redeclaration of primary template (#114258)Krystian Stasiowski1-1/+1
This patch fixes a couple of regressions introduced in #111852. Consider: ``` template<typename T> struct A { template<bool U> static constexpr bool f() requires U { return true; } }; template<> template<bool U> constexpr bool A<short>::f() requires U { return A<long>::f<U>(); } template<> template<bool U> constexpr bool A<long>::f() requires U { return true; } static_assert(A<short>::f<true>()); // crash here ``` This crashes because when collecting template arguments from the _first_ declaration of `A<long>::f<true>` for constraint checking, we don't add the template arguments from the enclosing class template specialization because there exists another redeclaration that is a member specialization. This also fixes the following example, which happens for a similar reason: ``` // input.cppm export module input; export template<int N> constexpr int f(); template<int N> struct A { template<int J> friend constexpr int f(); }; template struct A<0>; template<int N> constexpr int f() { return N; } ``` ``` // input.cpp import input; static_assert(f<1>() == 1); // error: static assertion failed ```
2024-10-24[clang] Use {} instead of std::nullopt to initialize empty ArrayRef (#109399)Jay Foad1-10/+11
Follow up to #109133.
2024-10-11Reapply "[Clang][Sema] Refactor collection of multi-level template argument ↵Krystian Stasiowski1-1/+1
lists (#106585, #111173)" (#111852) This patch reapplies #111173, fixing a bug when instantiating dependent expressions that name a member template that is later explicitly specialized for a class specialization that is implicitly instantiated. The bug is addressed by adding the `hasMemberSpecialization` function, which return `true` if _any_ redeclaration is a member specialization. This is then used when determining the instantiation pattern for a specialization of a template, and when collecting template arguments for a specialization of a template.
2024-10-11[Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (#86960)yronglin1-0/+2
Depends on [CWG1815](https://github.com/llvm/llvm-project/pull/108039). Fixes https://github.com/llvm/llvm-project/issues/85613. In [[Clang] Implement P2718R0 "Lifetime extension in range-based for loops"](https://github.com/llvm/llvm-project/pull/76361), we've not implement the lifetime extensions for the temporaries which in `CXXDefaultInitExpr`. As the confirmation in https://github.com/llvm/llvm-project/issues/85613, we should extend lifetime for that. To avoid modifying current CodeGen rules, in a lifetime extension context, the cleanup of `CXXDefaultInitExpr` was ignored. --------- Signed-off-by: yronglin <yronglin777@gmail.com>
2024-10-03Add cross builtins and cross HLSL function to DirectX and SPIR-V backend ↵Joshua Batista1-2/+3
(#109180) This PR adds the step intrinsic and an HLSL function that uses it. The SPIRV backend is also implemented. Used https://github.com/llvm/llvm-project/pull/106471 as a reference. Fixes https://github.com/llvm/llvm-project/issues/99095
2024-09-12[HLSL] Allow narrowing in initialization lists (#108035)Chris B1-1/+1
HLSL's initialization lists are _extremely_ generous about allowing conversions. This change demotes the C++11 warning to the legacy warning when in HLSL mode. Required for #56067
2024-09-12Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by ↵yronglin1-6/+17
aggregate initialization using a default member initializer" (#108039) The PR reapply https://github.com/llvm/llvm-project/pull/97308. - Implement [CWG1815](https://wg21.link/CWG1815): Support lifetime extension of temporary created by aggregate initialization using a default member initializer. - Fix crash that introduced in https://github.com/llvm/llvm-project/pull/97308. In `InitListChecker::FillInEmptyInitForField`, when we enter rebuild-default-init context, we copy all the contents of the parent context to the current context, which will cause the `MaybeODRUseExprs` to be lost. But we don't need to copy the entire context, only the `DelayedDefaultInitializationContext` was required, which is used to build `SourceLocExpr`, etc. --------- Signed-off-by: yronglin <yronglin777@gmail.com>
2024-09-09Revert "Reapply "[Clang][CWG1815] Support lifetime extension of temporary ↵Martin Storsjö1-16/+6
created by aggregate initialization using a default member initializer" (#97308)" This reverts commit 45c8766973bb3bb73dd8d996231e114dcf45df9f and 049512e39d96995cb373a76cf2d009a86eaf3aab. This change triggers failed asserts on inputs like this: struct a { } constexpr b; class c { public: c(a); }; class B { public: using d = int; struct e { enum { f } g; int h; c i; d j{}; }; }; B::e k{B::e::f, int(), b}; Compiled like this: clang -target x86_64-linux-gnu -c repro.cpp clang: ../../clang/lib/CodeGen/CGExpr.cpp:3105: clang::CodeGen::LValue clang::CodeGen::CodeGenFunction::EmitDeclRefLValue(const clang::DeclRefExpr*): Assertion `(ND->isUsed(false) || !isa<VarDecl>(ND) || E->isNonOdrUse() || !E->getLocation().isValid()) && "Should not use decl without marking it used!"' failed.
2024-09-08Reapply "[Clang][CWG1815] Support lifetime extension of temporary created by ↵yronglin1-6/+16
aggregate initialization using a default member initializer" (#97308) The PR reapply https://github.com/llvm/llvm-project/pull/92527. Implemented CWG1815 and fixed the bugs mentioned in the comments of https://github.com/llvm/llvm-project/pull/92527 and https://github.com/llvm/llvm-project/pull/87933. The reason why the original PR was reverted was that errors might occur during the rebuild. --------- Signed-off-by: yronglin <yronglin777@gmail.com>
2024-08-29[NFC][Sema] Move `Sema::AssignmentAction` into its own scoped enum (#106453)Dan Liew1-11/+12
The primary motivation behind this is to allow the enum type to be referred to earlier in the Sema.h file which is needed for #106321. It was requested in #106321 that a scoped enum be used (rather than moving the enum declaration earlier in the Sema class declaration). Unfortunately doing this creates a lot of churn as all use sites of the enum constants had to be changed. Appologies to all downstream forks in advanced. Note the AA_ prefix has been dropped from the enum value names as they are now redundant.
2024-08-27[Clang] Support initializing structured bindings from an array with ↵Yanzuo Liu1-19/+64
direct-list-initialization (#102581) When initializing structured bindings from an array with direct-list-initialization, array copy will be performed, which is a special case not following list-initialization. This PR adds support for this case. Fixes #31813.
2024-08-21[Clang] Implement CWG2351 `void{}` (#78060)Mital Ashok1-0/+1
Per [CWG2351](https://wg21.link/CWG2351), allow `void{}`, treated the same as `void()`: a prvalue expression of type `void` that performs no initialization. Note that the AST for the expression `T{}` looks like: ``` // using T = int; CXXFunctionalCastExpr 'T':'int' functional cast to T <NoOp> `-InitListExpr 'T':'int' // using T = const int; CXXFunctionalCastExpr 'int' functional cast to T <NoOp> `-InitListExpr 'int' // using T = void; CXXFunctionalCastExpr 'T':'void' functional cast to T <ToVoid> `-InitListExpr 'void' // using T = const void; CXXFunctionalCastExpr 'void' functional cast to T <ToVoid> `-InitListExpr 'void' ``` As for `void()`/`T() [T = const void]`, that looked like `CXXScalarValueInitExpr 'void'` and is unchanged after this. For reference, C++98 [5.2.3p2] says: > The expression `T()`, where `T` is a simple-type-specifier (7.1.5.2) for a non-array complete object type or the (possibly cv-qualified) void type, creates an rvalue of the specified type, whose value is determined by default-initialization (8.5; no initialization is done for the `void()` case). [*Note:* if `T` is a non-class type that is *cv-qualified*, the `cv-qualifiers` are ignored when determining the type of the resulting rvalue (3.10). ] Though it is a bit of a misnomer that, for `T = void`, `CXXScalarValueInitExpr` does not perform value initialization, it would be a breaking change to change the AST node for `void()`, so I simply reworded the doc comment.
2024-08-08[Clang] Implement CWG2137 (list-initialization from objects of the same ↵Mital Ashok1-10/+46
type) (#94355) [CWG2137](https://cplusplus.github.io/CWG/issues/2137.html) This was previously implemented and then reverted in Clang 18 as #77768 This also implements a workaround for [CWG2311](https://cplusplus.github.io/CWG/issues/2311.html), similarly to the 2024-03-01 comment for [CWG2742](https://cplusplus.github.io/CWG/issues/2742.html). The exact wording this tries to implement, relative to the C++26 draft: [over.match.list]p(1.2) > Otherwise, or if no viable initializer-list constructor is found <ins>and the initializer list does not consist of exactly a single element with the same cv-unqualified class type as `T`</ins>, overload resolution is performed again, [...] [dcl.init.list]p(3.7) > Otherwise, if `T` is a class type, constructors are considered. The applicable constructors are enumerated and the best one is chosen through overload resolution. <ins>If no constructor is found and the initializer list consists of exactly a single element with the same cv-unqualified class type as `T`, the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization). Otherwise,</ins> if a narrowing conversion (see below) is required [...]
2024-08-08[clang] Fix crash when #embed used in a compound literal (#102304)Mariya Podchishchaeva1-2/+2
Fixes https://github.com/llvm/llvm-project/issues/102248
2024-07-29[Clang] prevent checking destructor reference with an invalid initializer ↵Oleksandr T.1-0/+3
(#97860) Fixes #97230
2024-07-19[clang] Fix underlying type of EmbedExpr (#99050)Mariya Podchishchaeva1-1/+1
This patch makes remaining cases of #embed to emit int type since there is an agreement to do that for C. C++ is being discussed, but in general we don't want to produce different types for C and C++.
2024-07-17[Clang] Fix some assertions not looking through type sugar (#92299)Mital Ashok1-1/+1
Fixes #92284 Co-authored-by: cor3ntin <corentinjabot@gmail.com>
2024-07-17[clang] Be careful when choosing "fast path" for initialization with #embed ↵Mariya Podchishchaeva1-4/+13
(#99023) When #embed appears in an initializer list, we may choose a "fast path" if the target declaration is a char array. We simply initialize it with string literal that contains embedded data. However we need to be careful when checking that we actually can use this "fast path" since char array may be nested in a struct.
2024-07-10[clang] fix sema init crashing on initialization sequences (#98102)Yuxuan Chen1-0/+4
We ran into a FE crash and root caused to `ER.get()` on line 5584 here being nullptr. I think this is a result of not checking if ER here is invalid. Example of crash-on-valid C++ https://gist.github.com/yuxuanchen1997/576dce964666f0f8713fccacf5847138 Note that this crash happens only with `-std=c++20`.
2024-07-06[Clang] Simplify release notes and remove irrelevant comment (#96407)Gábor Spaits1-3/+0
As discussed before with @cor3ntin before (https://github.com/llvm/llvm-project/pull/94752) here is the simplification of the release note written for the previously mentioned PR and the removal of a comment that is no longer useful. (Sorry for creating this PR this late.) Co-authored-by: Gabor Spaits <Gabor.Spaits@hightec-rt.com>
2024-07-01[clang][NFC] Move documentation of `Sema` functions into `Sema.h`Vlad Serebrennikov1-2/+0
This patch moves documentation of `Sema` functions from `.cpp` files to `Sema.h` when there was no documentation in the latter, or it can be trivially subsumed. More complicated cases when there's less trivial divergence between documentation attached to declaration and the one attached to implementation are left for a later PR that would require review. It appears that doxygen can find the documentation for a function defined out-of-line even if it's attached to an implementation, and not declaration. But other tools, e.g. clangd, are not as powerful. So this patch significantly improves autocompletion experience for (at least) clangd-based IDEs.
2024-06-27[clang][Sema] Move the initializer lifetime checking code from SemaInit.cpp ↵Haojian Wu1-1230/+2
to a new place, NFC (#96758) This is a refactoring change for better code isolation and reuse, the first step to extend it for assignments.
2024-06-20[Clang] [Sema] Diagnose unknown std::initializer_list layout in SemaInit ↵Mital Ashok1-0/+51
(#95580) This checks if the layout of `std::initializer_list` is something Clang can handle much earlier and deduplicates the checks in CodeGen/CGExprAgg.cpp and AST/ExprConstant.cpp Also now diagnose `union initializer_list` (Fixes #95495), bit-field for the size (Fixes a crash that would happen during codegen if it were unnamed), base classes (that wouldn't be initialized) and polymorphic classes (whose vtable pointer wouldn't be initialized).
2024-06-20Reland [clang][Sema, Lex, Parse] Preprocessor embed in C and C++ (#95802)Mariya Podchishchaeva1-13/+100
This commit implements the entirety of the now-accepted [N3017 -Preprocessor Embed](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3017.htm) and its sister C++ paper [p1967](https://wg21.link/p1967). It implements everything in the specification, and includes an implementation that drastically improves the time it takes to embed data in specific scenarios (the initialization of character type arrays). The mechanisms used to do this are used under the "as-if" rule, and in general when the system cannot detect it is initializing an array object in a variable declaration, will generate EmbedExpr AST node which will be expanded by AST consumers (CodeGen or constant expression evaluators) or expand embed directive as a comma expression. This reverts commit https://github.com/llvm/llvm-project/commit/682d461d5a231cee54d65910e6341769419a67d7. --------- Co-authored-by: The Phantom Derpstorm <phdofthehouse@gmail.com> Co-authored-by: Aaron Ballman <aaron@aaronballman.com> Co-authored-by: cor3ntin <corentinjabot@gmail.com> Co-authored-by: H. Vetinari <h.vetinari@gmx.com>
2024-06-18[Sema][CTAD] Allow user defined conversion for copy-list-initialization (#94752)Gábor Spaits1-4/+2
Fixes #62925. The following code: ```cpp #include <map> int main() { std::map m1 = {std::pair{"foo", 2}, {"bar", 3}}; // guide #2 std::map m2(m1.begin(), m1.end()); // guide #1 } ``` Is rejected by clang, but accepted by both gcc and msvc: https://godbolt.org/z/6v4fvabb5 . So basically CTAD with copy-list-initialization is rejected. Note that this exact code is also used in a cppreference article: https://en.cppreference.com/w/cpp/container/map/deduction_guides I checked the C++11 and C++20 standard drafts to see whether suppressing user conversion is the correct thing to do for user conversions. Based on the standard I don't think that it is correct. ``` 13.3.1.4 Copy-initialization of class by user-defined conversion [over.match.copy] Under the conditions specified in 8.5, as part of a copy-initialization of an object of class type, a user-defined conversion can be invoked to convert an initializer expression to the type of the object being initialized. Overload resolution is used to select the user-defined conversion to be invoked ``` So we could use user defined conversions according to the standard. ``` If a narrowing conversion is required to initialize any of the elements, the program is ill-formed. ``` We should not do narrowing. ``` In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed. ``` We should not use explicit constructors.