https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/128890
>From 90977892092a206e120cdfea2960d2fb7929ef44 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Thu, 20 Feb 2025 03:43:23 -0800 Subject: [PATCH 1/2] [clang] Fix issues with #embed and intializer lists/template arguments 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 --- clang/include/clang/AST/Expr.h | 10 ++++ clang/lib/Sema/SemaInit.cpp | 2 +- clang/lib/Sema/SemaOverload.cpp | 12 ++-- clang/lib/Sema/SemaTemplateDeduction.cpp | 3 +- clang/test/SemaCXX/embed-init-list.cpp | 71 ++++++++++++++++++++++++ 5 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 clang/test/SemaCXX/embed-init-list.cpp diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 0f98d237dcbcd..cfe49acf20b77 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -5189,6 +5189,16 @@ class InitListExpr : public Expr { unsigned getNumInits() const { return InitExprs.size(); } + /// getNumInits but if the list has an EmbedExpr inside includes full length + /// of embedded data. + unsigned getNumInitsWithEmbedExpanded() const { + unsigned Sum = InitExprs.size(); + for (auto *IE : InitExprs) + if (auto *EE = dyn_cast<EmbedExpr>(IE)) + Sum += EE->getDataElementCount() - 1; + return Sum; + } + /// Retrieve the set of initializers. Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 340e51adf190d..2387bb4e5b9ae 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4260,7 +4260,7 @@ static bool TryInitializerListConstruction(Sema &S, QualType ArrayType = S.Context.getConstantArrayType( E.withConst(), llvm::APInt(S.Context.getTypeSize(S.Context.getSizeType()), - List->getNumInits()), + List->getNumInitsWithEmbedExpanded()), nullptr, clang::ArraySizeModifier::Normal, 0); InitializedEntity HiddenArray = InitializedEntity::InitializeTemporary(ArrayType); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 08586b4908dd4..c344b6fff40c6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5710,12 +5710,14 @@ TryListConversion(Sema &S, InitListExpr *From, QualType ToType, // - if the initializer list has one element that is not itself an // initializer list, the implicit conversion sequence is the one // required to convert the element to the parameter type. + // Bail out on EmbedExpr as well since we never create EmbedExpr for a + // single integer. unsigned NumInits = From->getNumInits(); - if (NumInits == 1 && !isa<InitListExpr>(From->getInit(0))) - Result = TryCopyInitialization(S, From->getInit(0), ToType, - SuppressUserConversions, - InOverloadResolution, - AllowObjCWritebackConversion); + if (NumInits == 1 && !isa<InitListExpr>(From->getInit(0)) && + !isa<EmbedExpr>(From->getInit(0))) + Result = TryCopyInitialization( + S, From->getInit(0), ToType, SuppressUserConversions, + InOverloadResolution, AllowObjCWritebackConversion); // - if the initializer list has no elements, the implicit conversion // sequence is the identity conversion. else if (NumInits == 0) { diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 627cd82ed1c77..dbd73ead8a63f 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4506,7 +4506,8 @@ static TemplateDeductionResult DeduceFromInitializerList( // C++ [temp.deduct.type]p13: // The type of N in the type T[N] is std::size_t. QualType T = S.Context.getSizeType(); - llvm::APInt Size(S.Context.getIntWidth(T), ILE->getNumInits()); + llvm::APInt Size(S.Context.getIntWidth(T), + ILE->getNumInitsWithEmbedExpanded()); if (auto Result = DeduceNonTypeTemplateArgument( S, TemplateParams, NTTP, llvm::APSInt(Size), T, /*ArrayBound=*/true, Info, /*PartialOrdering=*/false, Deduced, diff --git a/clang/test/SemaCXX/embed-init-list.cpp b/clang/test/SemaCXX/embed-init-list.cpp new file mode 100644 index 0000000000000..c511ca707a537 --- /dev/null +++ b/clang/test/SemaCXX/embed-init-list.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c23-extensions %s +// expected-no-diagnostics + +namespace std { +typedef decltype(sizeof(int)) size_t; + +template <class _E> class initializer_list { + const _E *__begin_; + size_t __size_; + + constexpr initializer_list(const _E *__b, size_t __s) + : __begin_(__b), __size_(__s) {} + +public: + constexpr initializer_list() : __begin_(nullptr), __size_(0) {} +}; +} // namespace std + +template <typename T> struct S { + S(std::initializer_list<T>); +}; + +template <> struct S<char> { + S(std::initializer_list<char>); +}; + +struct S1 { + S<char> data; + int a; +}; + +template <typename _Tp, std::size_t _Nm> void to_array(_Tp (&&__a)[_Nm]) {} + + +template<typename T> +void tfn(T) {} + +void tests() { + + S<char>{{ +#embed __FILE__ + }}; + + S1 ss{std::initializer_list<char>{ +#embed __FILE__ + }}; + + S sss = { +#embed __FILE__ + }; + + std::initializer_list<int> il{ +#embed __FILE__ + }; + + static constexpr auto initializer_list = std::initializer_list<char>{ +#embed __FILE__ + , '\0'}; + + static constexpr auto intinitializer_list = std::initializer_list<int>{ +#embed __FILE__ + , '\0'}; + + to_array({ +#embed __FILE__ + }); + + tfn<std::initializer_list<int>>({ +#embed __FILE__ + }); +} >From 3cf136ee719525bbca4c97bacd2ec77ead02ce52 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Thu, 27 Feb 2025 02:12:54 -0800 Subject: [PATCH 2/2] Add changelog --- clang/docs/ReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 65e411cb816eb..550cdb5ff6466 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -210,6 +210,8 @@ Bug Fixes in This Version - Clang now outputs correct values when #embed data contains bytes with negative signed char values (#GH102798). +- Fixed rejects-valid problem when #embed appears in std::initializer_list or + when it can affect template argument deduction (#GH122306). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits