534 changes: 426 additions & 108 deletions clang/lib/AST/ItaniumMangle.cpp

Large diffs are not rendered by default.

36 changes: 27 additions & 9 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3549,24 +3549,40 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
for (const std::string &F : Opts.NoSanitizeFiles)
GenerateArg(Consumer, OPT_fsanitize_ignorelist_EQ, F);

if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver3_8)
switch (Opts.getClangABICompat()) {
case LangOptions::ClangABI::Ver3_8:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "3.8");
else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver4)
break;
case LangOptions::ClangABI::Ver4:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "4.0");
else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver6)
break;
case LangOptions::ClangABI::Ver6:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "6.0");
else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver7)
break;
case LangOptions::ClangABI::Ver7:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "7.0");
else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver9)
break;
case LangOptions::ClangABI::Ver9:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "9.0");
else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver11)
break;
case LangOptions::ClangABI::Ver11:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "11.0");
else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver12)
break;
case LangOptions::ClangABI::Ver12:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "12.0");
else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver14)
break;
case LangOptions::ClangABI::Ver14:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "14.0");
else if (Opts.getClangABICompat() == LangOptions::ClangABI::Ver15)
break;
case LangOptions::ClangABI::Ver15:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "15.0");
break;
case LangOptions::ClangABI::Ver17:
GenerateArg(Consumer, OPT_fclang_abi_compat_EQ, "17.0");
break;
case LangOptions::ClangABI::Latest:
break;
}

if (Opts.getSignReturnAddressScope() ==
LangOptions::SignReturnAddressScopeKind::All)
Expand Down Expand Up @@ -4052,6 +4068,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.setClangABICompat(LangOptions::ClangABI::Ver14);
else if (Major <= 15)
Opts.setClangABICompat(LangOptions::ClangABI::Ver15);
else if (Major <= 17)
Opts.setClangABICompat(LangOptions::ClangABI::Ver17);
} else if (Ver != "latest") {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Parse/ParseExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3493,11 +3493,11 @@ ExprResult Parser::ParseRequiresExpression() {
SourceLocation RequiresKWLoc = ConsumeToken(); // Consume 'requires'

llvm::SmallVector<ParmVarDecl *, 2> LocalParameterDecls;
BalancedDelimiterTracker Parens(*this, tok::l_paren);
if (Tok.is(tok::l_paren)) {
// requirement parameter list is present.
ParseScope LocalParametersScope(this, Scope::FunctionPrototypeScope |
Scope::DeclScope);
BalancedDelimiterTracker Parens(*this, tok::l_paren);
Parens.consumeOpen();
if (!Tok.is(tok::r_paren)) {
ParsedAttributes FirstArgAttrs(getAttrFactory());
Expand Down Expand Up @@ -3769,8 +3769,9 @@ ExprResult Parser::ParseRequiresExpression() {
Braces.consumeClose();
Actions.ActOnFinishRequiresExpr();
ParsingBodyDecl.complete(Body);
return Actions.ActOnRequiresExpr(RequiresKWLoc, Body, LocalParameterDecls,
Requirements, Braces.getCloseLocation());
return Actions.ActOnRequiresExpr(
RequiresKWLoc, Body, Parens.getOpenLocation(), LocalParameterDecls,
Parens.getCloseLocation(), Requirements, Braces.getCloseLocation());
}

static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) {
Expand Down
16 changes: 8 additions & 8 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9191,14 +9191,14 @@ void Sema::ActOnFinishRequiresExpr() {
assert(CurContext && "Popped translation unit!");
}

ExprResult
Sema::ActOnRequiresExpr(SourceLocation RequiresKWLoc,
RequiresExprBodyDecl *Body,
ArrayRef<ParmVarDecl *> LocalParameters,
ArrayRef<concepts::Requirement *> Requirements,
SourceLocation ClosingBraceLoc) {
auto *RE = RequiresExpr::Create(Context, RequiresKWLoc, Body, LocalParameters,
Requirements, ClosingBraceLoc);
ExprResult Sema::ActOnRequiresExpr(
SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
SourceLocation ClosingBraceLoc) {
auto *RE = RequiresExpr::Create(Context, RequiresKWLoc, Body, LParenLoc,
LocalParameters, RParenLoc, Requirements,
ClosingBraceLoc);
if (DiagnoseUnexpandedParameterPackInRequiresExpr(RE))
return ExprError();
return RE;
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2344,8 +2344,9 @@ ExprResult TemplateInstantiator::TransformRequiresTypeParams(
// here.
TransReqs.push_back(RebuildTypeRequirement(createSubstDiag(
SemaRef, Info, [&](llvm::raw_ostream &OS) { OS << *FailedDecl; })));
return getDerived().RebuildRequiresExpr(KWLoc, Body, TransParams, TransReqs,
RBraceLoc);
return getDerived().RebuildRequiresExpr(KWLoc, Body, RE->getLParenLoc(),
TransParams, RE->getRParenLoc(),
TransReqs, RBraceLoc);
}

return ExprResult{};
Expand Down
16 changes: 10 additions & 6 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,8 @@ class TreeTransform {
DeclarationNameInfo
TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo);

bool TransformRequiresExprRequirements(ArrayRef<concepts::Requirement *> Reqs,
bool TransformRequiresExprRequirements(
ArrayRef<concepts::Requirement *> Reqs,
llvm::SmallVectorImpl<concepts::Requirement *> &Transformed);
concepts::TypeRequirement *
TransformTypeRequirement(concepts::TypeRequirement *Req);
Expand Down Expand Up @@ -3616,11 +3617,14 @@ class TreeTransform {
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildRequiresExpr(SourceLocation RequiresKWLoc,
RequiresExprBodyDecl *Body,
SourceLocation LParenLoc,
ArrayRef<ParmVarDecl *> LocalParameters,
SourceLocation RParenLoc,
ArrayRef<concepts::Requirement *> Requirements,
SourceLocation ClosingBraceLoc) {
return RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body,
LocalParameters, Requirements, ClosingBraceLoc);
return RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body, LParenLoc,
LocalParameters, RParenLoc, Requirements,
ClosingBraceLoc);
}

concepts::TypeRequirement *
Expand Down Expand Up @@ -12968,9 +12972,9 @@ TreeTransform<Derived>::TransformRequiresExpr(RequiresExpr *E) {
}
}

return getDerived().RebuildRequiresExpr(E->getRequiresKWLoc(), Body,
TransParams, TransReqs,
E->getRBraceLoc());
return getDerived().RebuildRequiresExpr(
E->getRequiresKWLoc(), Body, E->getLParenLoc(), TransParams,
E->getRParenLoc(), TransReqs, E->getRBraceLoc());
}

template<typename Derived>
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Serialization/ASTReaderStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,8 @@ void ASTStmtReader::VisitRequiresExpr(RequiresExpr *E) {
}
std::copy(Requirements.begin(), Requirements.end(),
E->getTrailingObjects<concepts::Requirement *>());
E->LParenLoc = Record.readSourceLocation();
E->RParenLoc = Record.readSourceLocation();
E->RBraceLoc = Record.readSourceLocation();
}

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Serialization/ASTWriterStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@ void ASTStmtWriter::VisitRequiresExpr(RequiresExpr *E) {
}
}
}
Record.AddSourceLocation(E->getLParenLoc());
Record.AddSourceLocation(E->getRParenLoc());
Record.AddSourceLocation(E->getEndLoc());

Code = serialization::EXPR_REQUIRES;
Expand Down
212 changes: 209 additions & 3 deletions clang/test/CodeGenCXX/mangle-concept.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,222 @@
// RUN: %clang_cc1 -verify -Wno-return-type -Wno-main -std=c++2a -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
// RUN: %clang_cc1 -verify -frelaxed-template-template-args -std=c++20 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
// RUN: %clang_cc1 -verify -frelaxed-template-template-args -std=c++20 -emit-llvm -triple %itanium_abi_triple -o - %s -fclang-abi-compat=16 | FileCheck %s --check-prefix=CLANG16
// expected-no-diagnostics

namespace test1 {
template <bool> struct S {};
template <typename> concept C = true;
template <typename T = int> S<C<T>> f0() { return S<C<T>>{}; }
template S<C<int>> f0<>();
// CHECK: @_ZN5test12f0IiEENS_1SIL_ZNS_1CIT_EEEEEv(
// CHECK: @_ZN5test12f0IiEENS_1SIX1CIT_EEEEv(
// CLANG16: @_ZN5test12f0IiEENS_1SIL_ZNS_1CIT_EEEEEv(
}

template <bool> struct S {};
template <typename> concept C = true;
template <typename, typename> concept D = true;

template <typename T = int> S<test1::C<T>> f0a() { return S<C<T>>{}; }
template S<test1::C<int>> f0a<>();
// CHECK: @_Z3f0aIiE1SIXsr5test1E1CIT_EEEv(
// CLANG16: @_Z3f0aIiE1SIL_ZN5test11CIT_EEEEv(

template <typename T = int> S<C<T>> f0() { return S<C<T>>{}; }
template S<C<int>> f0<>();
// CHECK: @_Z2f0IiE1SIL_Z1CIT_EEEv(
// CHECK: @_Z2f0IiE1SIX1CIT_EEEv(
// CLANG16: @_Z2f0IiE1SIL_Z1CIT_EEEv(

template<typename T> concept True = true;

namespace test2 {
// Member-like friends.
template<typename T> struct A {
friend void f(...) requires True<T> {}

template<typename U = void>
friend void g(...) requires True<T> && True<U> {}

template<typename U = void>
friend void h(...) requires True<U> {}

template<typename U = void> requires True<T> && True<U>
friend void i(...) {}

template<typename U = void> requires True<U>
friend void j(...) {}

template<True U = void> requires True<T>
friend void k(...) {}

template<True U = void>
friend void l(...) {}
};

A<int> ai;

// CHECK-LABEL: define {{.*}}@{{.*}}test2{{.*}}use
void use() {
// CHECK: call {{.*}}@_ZN5test21AIiEF1fEzQ4TrueIT_E(
// CLANG16: call {{.*}}@_ZN5test21fEz(
f(ai);
// CHECK: call {{.*}}@_ZN5test2F1gIvEEvzQaa4TrueIT_E4TrueITL0__E(
// CLANG16: call {{.*}}@_ZN5test21gIvEEvz(
g(ai);
// CHECK: call {{.*}}@_ZN5test21hIvEEvzQ4TrueITL0__E(
// CLANG16: call {{.*}}@_ZN5test21hIvEEvz(
h(ai);
// CHECK: call {{.*}}@_ZN5test2F1iIvQaa4TrueIT_E4TrueITL0__EEEvz(
// CLANG16: call {{.*}}@_ZN5test21iIvEEvz(
i(ai);
// CHECK: call {{.*}}@_ZN5test21jIvQ4TrueITL0__EEEvz(
// CLANG16: call {{.*}}@_ZN5test21jIvEEvz(
j(ai);
// CHECK: call {{.*}}@_ZN5test2F1kITk4TruevQ4TrueIT_EEEvz(
// CLANG16: call {{.*}}@_ZN5test21kIvEEvz(
k(ai);
// CHECK: call {{.*}}@_ZN5test21lITk4TruevEEvz(
// CLANG16: call {{.*}}@_ZN5test21lIvEEvz(
l(ai);
}
}

namespace test3 {
// Unconstrained auto.
template<auto> void d() {}
template void d<0>();
// CHECK: define {{.*}}@_ZN5test31dITnDaLi0EEEvv(
// CLANG16: define {{.*}}@_ZN5test31dILi0EEEvv(

template<decltype(auto)> void e() {}
template void e<0>();
// CHECK: define {{.*}}@_ZN5test31eITnDcLi0EEEvv(
// CLANG16: define {{.*}}@_ZN5test31eILi0EEEvv(

// Constrained auto.
template<C auto> void f() {}
template void f<0>();
// CHECK: define {{.*}}@_ZN5test31fITnDk1CLi0EEEvv(
// CLANG16: define {{.*}}@_ZN5test31fILi0EEEvv(

template<D<int> auto> void g() {}
template void g<0>();
// CHECK: define {{.*}}@_ZN5test31gITnDk1DIiELi0EEEvv(
// CLANG16: define {{.*}}@_ZN5test31gILi0EEEvv(

template<typename T, D<T> auto> void h() {}
template void h<int, 0>();
// CHECK: define {{.*}}@_ZN5test31hIiTnDk1DIT_ELi0EEEvv(
// CLANG16: define {{.*}}@_ZN5test31hIiLi0EEEvv(

template<typename T> void i(decltype(new C auto(T()))) {}
template void i<int>(int*);
// CHECK: define {{.*}}@_ZN5test31iIiEEvDTnw_Dk1CpicvT__EEE(
// CLANG16: define {{.*}}@_ZN5test31iIiEEvDTnw_DapicvT__EEE(

template<typename T> void j(decltype(new C decltype(auto)(T()))) {}
template void j<int>(int*);
// CHECK: define {{.*}}@_ZN5test31jIiEEvDTnw_DK1CpicvT__EEE(
// CLANG16: define {{.*}}@_ZN5test31jIiEEvDTnw_DcpicvT__EEE(
}

namespace test4 {
// Constrained type parameters.
template<C> void f() {}
template void f<int>();
// CHECK: define {{.*}}@_ZN5test41fITk1CiEEvv(
// CLANG16: define {{.*}}@_ZN5test41fIiEEvv(

template<D<int>> void g() {}
template void g<int>();
// CHECK: define {{.*}}@_ZN5test41gITk1DIiEiEEvv(
// CLANG16: define {{.*}}@_ZN5test41gIiEEvv(
}

namespace test5 {
// Exact-match vs non-exact-match template template parameters.
template<typename T, T V> struct X {};
template<typename T, T V> requires C<T> struct Y {};
template<C T, T V> struct Z {};

template<template<typename T, T> typename> void f() {}
// CHECK: define {{.*}}@_ZN5test51fINS_1XEEEvv(
template void f<X>();
// CHECK: define {{.*}}@_ZN5test51fITtTyTnTL0__ENS_1YEEEvv(
template void f<Y>();
// CHECK: define {{.*}}@_ZN5test51fITtTyTnTL0__ENS_1ZEEEvv(
template void f<Z>();

template<template<typename T, T> requires C<T> typename> void g() {}
// CHECK: define {{.*}}@_ZN5test51gITtTyTnTL0__Q1CIS1_EENS_1XEEEvv(
template void g<X>();
// CHECK: define {{.*}}@_ZN5test51gINS_1YEEEvv(
template void g<Y>();
// CHECK: define {{.*}}@_ZN5test51gITtTyTnTL0__Q1CIS1_EENS_1ZEEEvv(
template void g<Z>();

template<template<C T, T> typename> void h() {}
// CHECK: define {{.*}}@_ZN5test51hITtTk1CTnTL0__ENS_1XEEEvv(
template void h<X>();
// CHECK: define {{.*}}@_ZN5test51hITtTk1CTnTL0__ENS_1YEEEvv(
template void h<Y>();
// CHECK: define {{.*}}@_ZN5test51hINS_1ZEEEvv(
template void h<Z>();

// Packs must match the first argument.
template<template<C T, T> typename...> void i() {}
// CHECK: define {{.*}}@_ZN5test51iITpTtTk1CTnTL0__EJNS_1XENS_1YENS_1ZEEEEvv(
template void i<X, Y, Z>();
// CHECK: define {{.*}}@_ZN5test51iITpTtTk1CTnTL0__EJNS_1YENS_1ZENS_1XEEEEvv(
template void i<Y, Z, X>();
// CHECK: define {{.*}}@_ZN5test51iIJNS_1ZENS_1XENS_1YEEEEvv(
template void i<Z, X, Y>();

template<typename ...T> struct A {};
template<typename, typename> struct B {};

template<template<typename ...> typename> void p() {}
// CHECK: define {{.*}}@_ZN5test51pINS_1AEEEvv(
// CLANG16: define {{.*}}@_ZN5test51pINS_1AEEEvv(
template void p<A>();
// CHECK: define {{.*}}@_ZN5test51pITtTpTyENS_1BEEEvv(
// CLANG16: define {{.*}}@_ZN5test51pINS_1BEEEvv(
template void p<B>();

template<template<typename, typename> typename> void q() {}
// CHECK: define {{.*}}@_ZN5test51qITtTyTyENS_1AEEEvv(
// CLANG16: define {{.*}}@_ZN5test51qINS_1AEEEvv(
template void q<A>();
// CHECK: define {{.*}}@_ZN5test51qINS_1BEEEvv(
// CLANG16: define {{.*}}@_ZN5test51qINS_1BEEEvv(
template void q<B>();
}

namespace test6 {
// Abbreviated function templates.
void f(C auto) {}
// CHECK: define {{.*}}@_ZN5test61fITk1CiEEvT_(
// CLANG16: define {{.*}}@_ZN5test61fIiEEvT_(
template void f(int);

template<typename T>
void g(D<T> auto) {}
// CHECK: define {{.*}}@_ZN5test61gIiTk1DIT_EiEEvT0_(
// CLANG16: define {{.*}}@_ZN5test61gIiiEEvT0_(
template void g<int>(int);
}

namespace test7 {
// Constrained lambdas.
template<typename T> void f() {
// Ensure that requires-clauses affect lambda numbering.
// CHECK-LABEL: define {{.*}}@_ZN5test71fIiEEvv(
// CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E_clIiiEEDaS3_Q1CIDtfp_EE(
([]<typename U> requires C<T> && C<U> (auto x) requires C<decltype(x)> {}).template operator()<int>(0);
// CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E0_clIiiEEDaS3_Qaa1CIDtfp_EELb1E(
([]<typename U> requires C<T> && C<U> (auto x) requires C<decltype(x)> && true {}).template operator()<int>(0);
// CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E1_clIiiEEDaS3_Q1CIDtfp_EE(
([]<typename U> requires C<T> && C<U> (auto x) requires C<decltype(x)> {}).template operator()<int>(0);
// CHECK: call {{.*}}@_ZZN5test71fIiEEvvENKUlTyT0_E_clIiiEEDaS1_(
([]<typename U> (auto x){}).template operator()<int>(0);
}
template void f<int>();
}
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/mangle-exprs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ namespace Casts {
template void static_<4>(void*);
// CHECK-LABEL: define weak_odr void @_ZN5Casts12reinterpret_ILj4EiEEvPN9enable_ifIXleT_szrcPT0_Li0EEvE4typeE
template void reinterpret_<4, int>(void*);
// CHECK-LABEL: define weak_odr void @_ZN5Casts6const_IiXadL_ZNS_1iEEEEEvPN9enable_ifIXleLi0EszccPT_T0_EvE4typeE
// CHECK-LABEL: define weak_odr void @_ZN5Casts6const_IiTnPT_XadL_ZNS_1iEEEEEvPN9enable_ifIXleLi0EszccS2_T0_EvE4typeE
template void const_<int, &i>(void*);
// CHECK-LABEL: define weak_odr void @_ZN5Casts8dynamic_INS_1SEXadL_ZNS_1sEEEEEvPN9enable_ifIXleLi0EszdcPT_T0_EvE4typeE
// CHECK-LABEL: define weak_odr void @_ZN5Casts8dynamic_INS_1SETnPT_XadL_ZNS_1sEEEEEvPN9enable_ifIXleLi0EszdcS3_T0_EvE4typeE
template void dynamic_<struct S, &s>(void*);

// CHECK-LABEL: define weak_odr void @_ZN5Casts1fILi6EEENS_1TIXT_EEEv
Expand Down
24 changes: 12 additions & 12 deletions clang/test/CodeGenCXX/mangle-nttp-anon-union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,40 +74,40 @@ template<auto tparam> void dummy(){}
void uses() {
// Zero init'ed cases.
dummy<wrapper1<int>{}>();
// CHECK: call void @_Z5dummyIXtl8wrapper1IiEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper1IiEEEEvv
// DEMANGLED: call void @void dummy<wrapper1<int>{}>()()
dummy<wrapper2<float>{}>();
// CHECK: call void @_Z5dummyIXtl8wrapper2IfEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper2IfEEEEvv
// DEMANGLED: call void @void dummy<wrapper2<float>{}>()()
dummy<wrapper3<short>{}>();
// CHECK: call void @_Z5dummyIXtl8wrapper3IsEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper3IsEEEEvv
// DEMANGLED: call void @void dummy<wrapper3<short>{}>()()
dummy<wrapper4<double>{}>();
// CHECK: call void @_Z5dummyIXtl8wrapper4IdEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper4IdEEEEvv
// DEMANGLED: call void @void dummy<wrapper4<double>{}>()()
dummy<wrapper5<long long>{}>();
// CHECK: call void @_Z5dummyIXtl8wrapper5IxEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper5IxEEEEvv
// DEMANGLED: call void @void dummy<wrapper5<long long>{}>()()
dummy<wrapper6<int>{}>();
// CHECK: call void @_Z5dummyIXtl8wrapper6IiEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper6IiEEEEvv
// DEMANGLED: call void @void dummy<wrapper6<int>{}>()()

dummy<wrapper1<double>{123.0}>();
// CHECK: call void @_Z5dummyIXtl8wrapper1IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_ELd405ec00000000000EEEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper1IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_ELd405ec00000000000EEEEEEvv
// DEMANGLED: call void @void dummy<wrapper1<double>{wrapper1<double>::'unnamed'{.RightName = wrapper1<double>::'unnamed'::'unnamed'{0x1.ec{{.*}}p+6}}}>()()
dummy<wrapper2<double>{123.0}>();
// CHECK: call void @_Z5dummyIXtl8wrapper2IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_ELd405ec00000000000EEEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper2IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_ELd405ec00000000000EEEEEEvv
// DEMANGLED: call void @void dummy<wrapper2<double>{wrapper2<double>::'unnamed'{.RightName = wrapper2<double>::'unnamed'::'unnamed'{0x1.ec{{.*}}p+6}}}>()()
dummy<wrapper3<double>{123, 456}>();
// CHECK: call void @_Z5dummyIXtl8wrapper3IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_Etl4BaseLi123EELd407c800000000000EEEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper3IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_Etl4BaseLi123EELd407c800000000000EEEEEEvv
// DEMANGLED: call void @void dummy<wrapper3<double>{wrapper3<double>::'unnamed'{.RightName = wrapper3<double>::'unnamed'::'unnamed'{Base{123}, 0x1.c8{{.*}}p+8}}}>()()
dummy<wrapper4<double>{123}>();
// CHECK: call void @_Z5dummyIXtl8wrapper4IdEtlNS1_Ut_Edi9RightNameLi123EEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper4IdEtlNS1_Ut_Edi9RightNameLi123EEEEEvv
// DEMANGLED: call void @void dummy<wrapper4<double>{wrapper4<double>::'unnamed'{.RightName = 123}}>()()
dummy<wrapper5<double>{123.0, 456.0}>();
// CHECK: call void @_Z5dummyIXtl8wrapper5IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_EtlNS3_Ut_ELd405ec00000000000EELd407c800000000000EEEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper5IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_EtlNS3_Ut_ELd405ec00000000000EELd407c800000000000EEEEEEvv
// DEMANGLED: call void @void dummy<wrapper5<double>{wrapper5<double>::'unnamed'{.RightName = wrapper5<double>::'unnamed'::'unnamed'{wrapper5<double>::'unnamed'::'unnamed'::'unnamed'{0x1.ec{{.*}}p+6}, 0x1.c8{{.*}}p+8}}}>()()
dummy<wrapper6<double>{1}>();
// CHECK: call void @_Z5dummyIXtl8wrapper6IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_Edi9RightNameLd3ff0000000000000EEEEEEvv
// CHECK: call void @_Z5dummyITnDaXtl8wrapper6IdEtlNS1_Ut_Edi9RightNametlNS2_Ut_Edi9RightNameLd3ff0000000000000EEEEEEvv
// DEMANGELD: call void @void dummy<wrapper6<double>{wrapper6<double>::'unnamed'{.RightName = wrapper6<double>::'unnamed'::'unnamed'{.RightName = 0x1{{.*}}p+0}}}>()()
}
34 changes: 34 additions & 0 deletions clang/test/CodeGenCXX/mangle-requires.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// RUN: %clang_cc1 -verify -std=c++2a -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s
// expected-no-diagnostics

template <typename T, int N> concept SmallerThan = sizeof(T) < N;
template <typename T> concept Small = SmallerThan<T, 1000>;

template <typename T> struct X { using type = T; };

template <typename T> void f(int n) requires requires {
// simple-requirement
T();
n;
n == T();
// compound-requirement
{T() + 1} -> Small;
{T() - 1} noexcept;
{T() * 2} noexcept -> SmallerThan<1234>;
// type-requirement
typename T;
typename X<T>;
typename X<T>::type;
typename X<decltype(n)>;
// nested-requirement
requires SmallerThan<T, 256>;
} {}
// CHECK: define {{.*}}@_Z1fIiEviQrqXcvT__EXfp_Xeqfp_cvS0__EXplcvS0__ELi1ER5SmallXmicvS0__ELi1ENXmlcvS0__ELi2ENR11SmallerThanILi1234EETS0_T1XIS0_ETNS3_4typeETS2_IiEQ11SmallerThanIS0_Li256EEE(
template void f<int>(int);

template <typename T> void g(int n) requires requires (T m) {
// reference to our parameter vs an enclosing parameter
n + m;
} {}
// CHECK: define {{.*}}@_Z1gIiEviQrQT__XplfL0p_fp_E(
template void g<int>(int);
8 changes: 4 additions & 4 deletions clang/test/CodeGenCXX/mangle-template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,13 @@ namespace test12 {
const int n = 10;
template<typename T, T v> void test() {}
void use() {
// CHECK-LABEL: define internal {{.*}}void @_ZN6test124testIFivEXadL_ZNS_L1fEvEEEEvv(
// CHECK-LABEL: define internal {{.*}}void @_ZN6test124testIFivETnT_XadL_ZNS_L1fEvEEEEvv(
test<int(), &f>();
// CHECK-LABEL: define internal {{.*}}void @_ZN6test124testIRFivEL_ZNS_L1fEvEEEvv(
// CHECK-LABEL: define internal {{.*}}void @_ZN6test124testIRFivETnT_L_ZNS_L1fEvEEEvv(
test<int(&)(), f>();
// CHECK-LABEL: define internal {{.*}}void @_ZN6test124testIPKiXadL_ZNS_L1nEEEEEvv(
// CHECK-LABEL: define internal {{.*}}void @_ZN6test124testIPKiTnT_XadL_ZNS_L1nEEEEEvv(
test<const int*, &n>();
// CHECK-LABEL: define internal {{.*}}void @_ZN6test124testIRKiL_ZNS_L1nEEEEvv(
// CHECK-LABEL: define internal {{.*}}void @_ZN6test124testIRKiTnT_L_ZNS_L1nEEEEvv(
test<const int&, n>();
}
}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenCXX/matrix-type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,10 @@ void test_auto_t() {
// CHECK-LABEL: define{{.*}} void @_Z11test_auto_tv()
// CHECK-NEXT: entry:
// CHECK-NEXT: %m = alloca [130 x i32], align 4
// CHECK-NEXT: call void @_Z3fooILm13EEvRu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(520) %m)
// CHECK-NEXT: call void @_Z3fooITnDaLm13EEvRu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(520) %m)
// CHECK-NEXT: ret void

// CHECK-LABEL: define linkonce_odr void @_Z3fooILm13EEvRu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(520) %m)
// CHECK-LABEL: define linkonce_odr void @_Z3fooITnDaLm13EEvRu11matrix_typeIXT_ELm10EiE(ptr nonnull align 4 dereferenceable(520) %m)
// CHECK-NEXT: entry:
// CHECK-NEXT: %m.addr = alloca ptr, align 8
// CHECK-NEXT: store ptr %m, ptr %m.addr, align 8
Expand Down
8 changes: 4 additions & 4 deletions clang/test/OpenMP/tile_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -983,11 +983,11 @@ extern "C" void tfoo7() {
// CHECK1-LABEL: define {{[^@]+}}@tfoo7
// CHECK1-SAME: () #[[ATTR0]] {
// CHECK1-NEXT: entry:
// CHECK1-NEXT: call void @_Z4foo7IiLi3ELi5EEvT_S0_(i32 noundef 0, i32 noundef 42)
// CHECK1-NEXT: call void @_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_(i32 noundef 0, i32 noundef 42)
// CHECK1-NEXT: ret void
//
//
// CHECK1-LABEL: define {{[^@]+}}@_Z4foo7IiLi3ELi5EEvT_S0_
// CHECK1-LABEL: define {{[^@]+}}@_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_
// CHECK1-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]]) #[[ATTR0]] comdat {
// CHECK1-NEXT: entry:
// CHECK1-NEXT: [[START_ADDR:%.*]] = alloca i32, align 4
Expand Down Expand Up @@ -1977,11 +1977,11 @@ extern "C" void tfoo7() {
// CHECK2-LABEL: define {{[^@]+}}@tfoo7
// CHECK2-SAME: () #[[ATTR2]] {
// CHECK2-NEXT: entry:
// CHECK2-NEXT: call void @_Z4foo7IiLi3ELi5EEvT_S0_(i32 noundef 0, i32 noundef 42)
// CHECK2-NEXT: call void @_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_(i32 noundef 0, i32 noundef 42)
// CHECK2-NEXT: ret void
//
//
// CHECK2-LABEL: define {{[^@]+}}@_Z4foo7IiLi3ELi5EEvT_S0_
// CHECK2-LABEL: define {{[^@]+}}@_Z4foo7IiTnT_Li3ETnS0_Li5EEvS0_S0_
// CHECK2-SAME: (i32 noundef [[START:%.*]], i32 noundef [[END:%.*]]) #[[ATTR2]] comdat {
// CHECK2-NEXT: entry:
// CHECK2-NEXT: [[START_ADDR:%.*]] = alloca i32, align 4
Expand Down
499 changes: 426 additions & 73 deletions libcxxabi/src/demangle/ItaniumDemangle.h

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions libcxxabi/src/demangle/ItaniumNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ NODE(SpecialName)
NODE(CtorVtableSpecialName)
NODE(QualifiedName)
NODE(NestedName)
NODE(MemberLikeFriendName)
NODE(LocalName)
NODE(ModuleName)
NODE(ModuleEntity)
Expand All @@ -44,7 +45,9 @@ NODE(PixelVectorType)
NODE(BinaryFPType)
NODE(BitIntType)
NODE(SyntheticTemplateParamName)
NODE(TemplateParamQualifiedArg)
NODE(TypeTemplateParamDecl)
NODE(ConstrainedTypeTemplateParamDecl)
NODE(NonTypeTemplateParamDecl)
NODE(TemplateTemplateParamDecl)
NODE(TemplateParamPackDecl)
Expand Down Expand Up @@ -91,5 +94,9 @@ NODE(DoubleLiteral)
NODE(LongDoubleLiteral)
NODE(BracedExpr)
NODE(BracedRangeExpr)
NODE(RequiresExpr)
NODE(ExprRequirement)
NODE(TypeRequirement)
NODE(NestedRequirement)

#undef NODE
53 changes: 50 additions & 3 deletions libcxxabi/test/test_demangle.pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29995,10 +29995,10 @@ const char* cases[][2] =
{"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE", "void test_uuidofType<TestStruct>(decltype(__uuidof(TestStruct)))"},
{"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr<HasMember>(decltype(__uuidof(HasMember::member)))"},

// C++2a char8_t:
// C++20 char8_t:
{"_ZTSPDu", "typeinfo name for char8_t*"},

// C++2a lambda-expressions:
// C++20 lambda-expressions:
{"_ZNK1xMUlTyT_E_clIiEEDaS_", "auto x::'lambda'<typename $T>($T)::operator()<int>(x) const"},
{"_ZNK1xMUlTnPA3_ivE_clILS0_0EEEDav", "auto x::'lambda'<int (*$N) [3]>()::operator()<(int [3])0>() const"},
{"_ZNK1xMUlTyTtTyTnT_TpTnPA3_TL0__ETpTyvE_clIi1XJfEEEDav", "auto x::'lambda'<typename $T, template<typename $T0, $T $N, $T0 (*...$N0) [3]> typename $TT, typename ...$T1>()::operator()<int, X, float>() const"},
Expand All @@ -30015,8 +30015,10 @@ const char* cases[][2] =
// See https://github.com/itanium-cxx-abi/cxx-abi/issues/106.
{"_ZN1XIZ1fIiEvOT_EUlS2_DpT0_E_EclIJEEEvDpT_", "void X<void f<int>(int&&)::'lambda'(int&&, auto...)>::operator()<>()"},
{"_ZZZZN6abcdef9abcdefghi29abcdefabcdefabcdefabcefabcdef27xxxxxxxxxxxxxxxxxxxxxxxxxxxEN4absl8DurationERKNSt3__u12basic_stringIcNS4_11char_traitsIcEENS4_9allocatorIcEEEEPNS1_19yyyyyyyyyyyyyyyyyyyEENK3$_5clEvENKUlvE_clEvE6zzzzzz", "abcdef::abcdefghi::abcdefabcdefabcdefabcefabcdef::xxxxxxxxxxxxxxxxxxxxxxxxxxx(absl::Duration, std::__u::basic_string<char, std::__u::char_traits<char>, std::__u::allocator<char>> const&, abcdef::abcdefghi::abcdefabcdefabcdefabcefabcdef::yyyyyyyyyyyyyyyyyyy*)::$_5::operator()() const::'lambda'()::operator()() const::zzzzzz"},
// See https://github.com/itanium-cxx-abi/cxx-abi/issues/165.
{"_ZN1C1fIiEEvDTtlNS_UlT_TL0__E_EEE", "void C::f<int>(decltype(C::'lambda'(int, auto){}))"},

// C++2a class type non-type template parameters:
// C++20 class type non-type template parameters:
{"_Z1fIXtl1BLPi0ELi1EEEEvv", "void f<B{(int*)0, 1}>()"},
{"_Z1fIXtl1BLPi32EEEEvv", "void f<B{(int*)32}>()"},
{"_Z1fIXtl1BrcPiLi0EEEEvv", "void f<B{reinterpret_cast<int*>(0)}>()"},
Expand Down Expand Up @@ -30089,6 +30091,51 @@ const char* cases[][2] =
{"_ZW1ML4Oink", "Oink@M"},
{"_ZW1ML1fi", "f@M(int)"},

// C++20 concepts, see https://github.com/itanium-cxx-abi/cxx-abi/issues/24.
{"_Z2f0IiE1SIX1CIT_EEEv", "S<C<int>> f0<int>()"},
{"_ZN5test21AIiEF1fEzQ4TrueIT_E", "test2::A<int>::friend f(...) requires True<T>"},
{"_ZN5test2F1gIvEEvzQaa4TrueIT_E4TrueITL0__E", "void test2::friend g<void>(...) requires True<T> && True<TL0_>"},
{"_ZN5test21hIvEEvzQ4TrueITL0__E", "void test2::h<void>(...) requires True<TL0_>"},
{"_ZN5test2F1iIvQaa4TrueIT_E4TrueITL0__EEEvz", "void test2::friend i<void>(...)"},
{"_ZN5test21jIvQ4TrueITL0__EEEvz", "void test2::j<void>(...)"},
{"_ZN5test2F1kITk4TruevQ4TrueIT_EEEvz", "void test2::friend k<void>(...)"},
{"_ZN5test21lITk4TruevEEvz", "void test2::l<void>(...)"},
{"_ZN5test31dITnDaLi0EEEvv", "void test3::d<0>()"},
{"_ZN5test31eITnDcLi0EEEvv", "void test3::e<0>()"},
{"_ZN5test31fITnDk1CLi0EEEvv", "void test3::f<0>()"},
{"_ZN5test31gITnDk1DIiELi0EEEvv", "void test3::g<0>()"},
{"_ZN5test31hIiTnDk1DIT_ELi0EEEvv", "void test3::h<int, 0>()"},
{"_ZN5test31iIiEEvDTnw_Dk1CpicvT__EEE", "void test3::i<int>(decltype(new C auto((int)())))"},
{"_ZN5test31jIiEEvDTnw_DK1CpicvT__EEE", "void test3::j<int>(decltype(new C decltype(auto)((int)())))"},
{"_ZN5test41fITk1CiEEvv", "void test4::f<int>()"},
{"_ZN5test41gITk1DIiEiEEvv", "void test4::g<int>()"},
{"_ZN5test51fINS_1XEEEvv", "void test5::f<test5::X>()"},
{"_ZN5test51fITtTyTnTL0__ENS_1YEEEvv", "void test5::f<test5::Y>()"},
{"_ZN5test51fITtTyTnTL0__ENS_1ZEEEvv", "void test5::f<test5::Z>()"},
{"_ZN5test51gITtTyTnTL0__Q1CIS1_EENS_1XEEEvv", "void test5::g<test5::X>()"},
{"_ZN5test51gINS_1YEEEvv", "void test5::g<test5::Y>()"},
{"_ZN5test51gITtTyTnTL0__Q1CIS1_EENS_1ZEEEvv", "void test5::g<test5::Z>()"},
{"_ZN5test51hITtTk1CTnTL0__ENS_1XEEEvv", "void test5::h<test5::X>()"},
{"_ZN5test51hITtTk1CTnTL0__ENS_1YEEEvv", "void test5::h<test5::Y>()"},
{"_ZN5test51hINS_1ZEEEvv", "void test5::h<test5::Z>()"},
{"_ZN5test51iITpTtTk1CTnTL0__EJNS_1XENS_1YENS_1ZEEEEvv", "void test5::i<test5::X, test5::Y, test5::Z>()"},
{"_ZN5test51iITpTtTk1CTnTL0__EJNS_1YENS_1ZENS_1XEEEEvv", "void test5::i<test5::Y, test5::Z, test5::X>()"},
{"_ZN5test51iIJNS_1ZENS_1XENS_1YEEEEvv", "void test5::i<test5::Z, test5::X, test5::Y>()"},
{"_ZN5test51pINS_1AEEEvv", "void test5::p<test5::A>()"},
{"_ZN5test51pITtTpTyENS_1BEEEvv", "void test5::p<test5::B>()"},
{"_ZN5test51qITtTyTyENS_1AEEEvv", "void test5::q<test5::A>()"},
{"_ZN5test51qINS_1BEEEvv", "void test5::q<test5::B>()"},
{"_ZN5test61fITk1CiEEvT_", "void test6::f<int>(int)"},
{"_ZN5test61gIiTk1DIT_EiEEvT0_", "void test6::g<int, int>(int)"},
{"_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E_clIiiEEDaS3_Q1CIDtfp_EE", "auto void test7::f<int>()::'lambda'<typename $T> requires C<T> && C<TL0_> (auto)::operator()<int, int>(auto) const requires C<decltype(fp)>"},
{"_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E0_clIiiEEDaS3_Qaa1CIDtfp_EELb1E", "auto void test7::f<int>()::'lambda0'<typename $T> requires C<T> && C<TL0_> (auto)::operator()<int, int>(auto) const requires C<decltype(fp)> && true"},
{"_ZZN5test71fIiEEvvENKUlTyQaa1CIT_E1CITL0__ET0_E1_clIiiEEDaS3_Q1CIDtfp_EE", "auto void test7::f<int>()::'lambda1'<typename $T> requires C<T> && C<TL0_> (auto)::operator()<int, int>(auto) const requires C<decltype(fp)>"},
{"_ZZN5test71fIiEEvvENKUlTyT0_E_clIiiEEDaS1_", "auto void test7::f<int>()::'lambda'<typename $T>(auto)::operator()<int, int>(auto) const"},

// C++20 requires expressions, see https://github.com/itanium-cxx-abi/cxx-abi/issues/24.
{"_Z1fIiEviQrqXcvT__EXfp_Xeqfp_cvS0__EXplcvS0__ELi1ER5SmallXmicvS0__ELi1ENXmlcvS0__ELi2ENR11SmallerThanILi1234EETS0_T1XIS0_ETNS3_4typeETS2_IiEQ11SmallerThanIS0_Li256EEE", "void f<int>(int) requires requires { (T)(); fp; fp == (T)(); {(T)() + 1} -> Small; {(T)() - 1} noexcept; {(T)() * 2} noexcept -> SmallerThan<1234>; typename T; typename X<T>; typename X<T>::type; typename X<int>; requires SmallerThan<T, 256>; }"},
{"_Z1gIiEviQrQT__XplfL0p_fp_E", "void g<int>(int) requires requires (T) { fp + fp; }"},

// Special Substs a, b, d, i, o, s (not including std::)
{"_Z1fSaIiE", "f(std::allocator<int>)"},
{"_Z1fSbIiE", "f(std::basic_string<int>)"},
Expand Down
522 changes: 442 additions & 80 deletions llvm/include/llvm/Demangle/ItaniumDemangle.h

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions llvm/include/llvm/Demangle/ItaniumNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ NODE(SpecialName)
NODE(CtorVtableSpecialName)
NODE(QualifiedName)
NODE(NestedName)
NODE(MemberLikeFriendName)
NODE(LocalName)
NODE(ModuleName)
NODE(ModuleEntity)
Expand All @@ -44,7 +45,9 @@ NODE(PixelVectorType)
NODE(BinaryFPType)
NODE(BitIntType)
NODE(SyntheticTemplateParamName)
NODE(TemplateParamQualifiedArg)
NODE(TypeTemplateParamDecl)
NODE(ConstrainedTypeTemplateParamDecl)
NODE(NonTypeTemplateParamDecl)
NODE(TemplateTemplateParamDecl)
NODE(TemplateParamPackDecl)
Expand Down Expand Up @@ -91,5 +94,9 @@ NODE(DoubleLiteral)
NODE(LongDoubleLiteral)
NODE(BracedExpr)
NODE(BracedRangeExpr)
NODE(RequiresExpr)
NODE(ExprRequirement)
NODE(TypeRequirement)
NODE(NestedRequirement)

#undef NODE