llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Kunal Dubey (xakep8)
<details>
<summary>Changes</summary>
Clang was adding the initializer-list marker twice when mangling an expression
such as `new std::initializer_list<int>{1}`.
Unwraped the compiler created init list expression and mangled its elements
only once.
Fixes #<!-- -->232531
Stacked on top of #<!-- -->232357 and #<!-- -->232606
---
Full diff: https://github.com/llvm/llvm-project/pull/232629.diff
6 Files Affected:
- (modified) clang/docs/ReleaseNotes.md (+8)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+23-2)
- (modified) clang/lib/Sema/SemaLambda.cpp (+3)
- (modified) clang/test/CodeGenCXX/mangle-cxx2a.cpp (+46)
- (modified) clang/test/CodeGenCXX/mangle-exprs.cpp (+19-1)
- (added) clang/test/SemaCXX/crash-GH170185.cpp (+14)
``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index aba1dba5854fe..3710ab8e36abb 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -64,6 +64,11 @@ in a future version of Clang.
### ABI Changes in This Version
+- Clang now correctly mangles C++20 parenthesized aggregate initialization
+ expressions. Previously, initializer arguments could be omitted from the
+ mangled name, causing distinct entities to receive the same name.
+ (#GH231953)
+
- Except on PlayStation, Clang now derives the x86-64 System V AVX ABI level
for 256- and 512-bit vector arguments and returns from effective per-function
target features. Features and `arch=` CPUs that imply AVX or AVX512F are
@@ -799,6 +804,9 @@ features cannot lower the translation-unit ABI level;
#### Bug Fixes to C++ Support
+- Fixed a crash when a lambda parameter type contains an invalid non-type
+ template argument. (#GH170185)
+
- Fixed lambdas with specifiers or attributes after the capture list being
misparsed as function declarations in direct-initialization contexts under
`-fms-extensions` or in HLSL mode.
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 0e32839a77be5..441aad41edc0d 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -4945,7 +4945,13 @@ void CXXNameMangler::mangleCastExpression(const Expr *E,
StringRef CastEncoding)
const ExplicitCastExpr *ECE = cast<ExplicitCastExpr>(E);
Out << CastEncoding;
mangleType(ECE->getType());
- mangleExpression(ECE->getSubExpr());
+ if (const auto *PLIE = dyn_cast<CXXParenListInitExpr>(ECE->getSubExpr())) {
+ ArrayRef<Expr *> Inits = PLIE->getUserSpecifiedInitExprs();
+ assert(Inits.size() == 1 && "cast must have exactly one operand");
+ mangleExpression(Inits.front());
+ } else {
+ mangleExpression(ECE->getSubExpr());
+ }
}
void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) {
@@ -5338,12 +5344,17 @@ void CXXNameMangler::mangleExpression(const Expr *E,
unsigned Arity,
else
Out << "pi";
const Expr *Init = New->getInitializer();
+ if (const auto *SILE = dyn_cast<CXXStdInitializerListExpr>(Init))
+ Init = SILE->getSubExpr()->IgnoreImplicit();
if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
// Directly inline the initializers.
for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(),
E = CCE->arg_end();
I != E; ++I)
mangleExpression(*I);
+ } else if (const auto *PLE = dyn_cast<CXXParenListInitExpr>(Init)) {
+ for (const Expr *Arg : PLE->getUserSpecifiedInitExprs())
+ mangleExpression(Arg);
} else if (const ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) {
for (unsigned i = 0, e = PLE->getNumExprs(); i != e; ++i)
mangleExpression(PLE->getExpr(i));
@@ -5770,7 +5781,17 @@ void CXXNameMangler::mangleExpression(const Expr *E,
unsigned Arity,
Sub = CCE->getArg(0)->IgnoreImplicit();
if (auto *StdInitList = dyn_cast<CXXStdInitializerListExpr>(Sub))
Sub = StdInitList->getSubExpr()->IgnoreImplicit();
- if (auto *IL = dyn_cast<InitListExpr>(Sub)) {
+ if (auto *PLIE = dyn_cast<CXXParenListInitExpr>(Sub)) {
+ ArrayRef<Expr *> Inits = PLIE->getUserSpecifiedInitExprs();
+ Out << "cv";
+ mangleType(E->getType());
+ if (Inits.size() != 1)
+ Out << '_';
+ for (const Expr *Init : Inits)
+ mangleExpression(Init);
+ if (Inits.size() != 1)
+ Out << 'E';
+ } else if (auto *IL = dyn_cast<InitListExpr>(Sub)) {
Out << "tl";
mangleType(E->getType());
mangleInitListElements(IL);
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 0c9a92cdd0c32..ec74102c0ecaf 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -489,6 +489,9 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
void Sema::handleLambdaNumbering(
CXXRecordDecl *Class, CXXMethodDecl *Method,
std::optional<CXXRecordDecl::LambdaNumbering> NumberingOverride) {
+ if (Method->getType()->containsErrors())
+ return;
+
ContextRAII ManglingContext(*this, Class->getDeclContext());
auto getMangleNumberingContext =
diff --git a/clang/test/CodeGenCXX/mangle-cxx2a.cpp
b/clang/test/CodeGenCXX/mangle-cxx2a.cpp
index 3e4689948a7a7..82dad5cdeb83b 100644
--- a/clang/test/CodeGenCXX/mangle-cxx2a.cpp
+++ b/clang/test/CodeGenCXX/mangle-cxx2a.cpp
@@ -9,3 +9,49 @@ namespace spaceship {
template<typename T> void f(decltype(Y() < X(), T()) x) {}
template void f<int>(int);
}
+
+namespace paren_init {
+ struct A { int a; };
+ struct B { int a, b; };
+ struct D { int a, b = 7; };
+ template <int> struct X {};
+
+ template <int N> void f(X<N + A(1).a>) {}
+ template <int N> void f(X<N + A(2).a>) {}
+
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init1fILi0EEEvNS_1XIXplT_dtcvNS_1AELi1E1aEEE
+ template void f<0>(X<1>);
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init1fILi0EEEvNS_1XIXplT_dtcvNS_1AELi2E1aEEE
+ template void f<0>(X<2>);
+
+ template <int N> void c_style(X<N + ((A)1).a>) {}
+ template <int N> void static_style(X<N + static_cast<A>(1).a>) {}
+
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init7c_styleILi0EEEvNS_1XIXplT_dtcvNS_1AELi1E1aEEE
+ template void c_style<0>(X<1>);
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init12static_styleILi0EEEvNS_1XIXplT_dtscNS_1AELi1E1aEEE
+ template void static_style<0>(X<1>);
+
+ // Check zero and multiple arguments, and a default member initializer.
+ template <int N> void zero(X<N + A().a>) {}
+ template <int N> void two(X<N + B(1, 2).b>) {}
+ template <int N> void defaulted(X<N + D(1).b>) {}
+
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init4zeroILi0EEEvNS_1XIXplT_dtcvNS_1AE_E1aEEE
+ template void zero<0>(X<0>);
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init3twoILi0EEEvNS_1XIXplT_dtcvNS_1BE_Li1ELi2EE1bEEE
+ template void two<0>(X<2>);
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init9defaultedILi0EEEvNS_1XIXplT_dtcvNS_1DELi1E1bEEE
+ template void defaulted<0>(X<7>);
+
+ template <int N> void new_zero(decltype((N, new A()))) {}
+ template <int N> void new_one(decltype((N, new A(1)))) {}
+ template <int N> void new_two(decltype((N, new B(1, 2)))) {}
+
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init8new_zeroILi0EEEvDTcmT_nw_NS_1AEpiEE
+ template void new_zero<0>(A *);
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init7new_oneILi0EEEvDTcmT_nw_NS_1AEpiLi1EEE
+ template void new_one<0>(A *);
+ // CHECK-LABEL: define {{.*}}
@_ZN10paren_init7new_twoILi0EEEvDTcmT_nw_NS_1BEpiLi1ELi2EEE
+ template void new_two<0>(B *);
+}
diff --git a/clang/test/CodeGenCXX/mangle-exprs.cpp
b/clang/test/CodeGenCXX/mangle-exprs.cpp
index b75f2cf3607b3..574cd81952d9a 100644
--- a/clang/test/CodeGenCXX/mangle-exprs.cpp
+++ b/clang/test/CodeGenCXX/mangle-exprs.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Wno-error=return-type -std=c++11 -fclang-abi-compat=latest
-emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
+// RUN: %clang_cc1 -Wno-error=return-type -Wno-dangling-initializer-list
-std=c++11 -fclang-abi-compat=latest -emit-llvm %s -o -
-triple=x86_64-apple-darwin9 | FileCheck %s
namespace std {
typedef decltype(sizeof(int)) size_t;
@@ -212,6 +212,24 @@ namespace test4 {
}
+namespace new_std_initializer_list {
+ template <int N>
+ void empty(decltype((N, new std::initializer_list<int>{}))) {}
+
+ template <int N>
+ void one(decltype((N, new std::initializer_list<int>{1}))) {}
+
+ template <int N>
+ void two(decltype((N, new std::initializer_list<int>{1, 2}))) {}
+
+ // CHECK-LABEL: define {{.*}}
@_ZN24new_std_initializer_list5emptyILi0EEEvDTcmT_nw_St16initializer_listIiEilEE
+ template void empty<0>(std::initializer_list<int> *);
+ // CHECK-LABEL: define {{.*}}
@_ZN24new_std_initializer_list3oneILi0EEEvDTcmT_nw_St16initializer_listIiEilLi1EEE
+ template void one<0>(std::initializer_list<int> *);
+ // CHECK-LABEL: define {{.*}}
@_ZN24new_std_initializer_list3twoILi0EEEvDTcmT_nw_St16initializer_listIiEilLi1ELi2EEE
+ template void two<0>(std::initializer_list<int> *);
+}
+
namespace test5 {
template <typename T> void a(decltype(noexcept(T()))) {}
template void a<int>(decltype(noexcept(int())));
diff --git a/clang/test/SemaCXX/crash-GH170185.cpp
b/clang/test/SemaCXX/crash-GH170185.cpp
new file mode 100644
index 0000000000000..21fb071a1e80f
--- /dev/null
+++ b/clang/test/SemaCXX/crash-GH170185.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+struct Foo; // expected-note 2 {{forward declaration of 'Foo'}}
+
+template <Foo X> // expected-error {{non-type template parameter has
incomplete type 'Foo'}}
+struct Arr;
+
+Foo f; // expected-error {{variable has incomplete type 'Foo'}}
+
+void foo() {
+ []() {
+ (void)[&](Arr<f>) {};
+ }();
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/232629
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits