Skip to content

Commit 4b163e3

Browse files
committed
Implement mangling rules for C++20 concepts and requires-expressions.
This implements proposals from: - itanium-cxx-abi/cxx-abi#24: mangling for constraints, requires-clauses, requires-expressions. - itanium-cxx-abi/cxx-abi#31: requires-clauses and template parameters in a lambda expression are mangled into the <lambda-sig>. - itanium-cxx-abi/cxx-abi#47 (STEP 3): mangling for template argument is prefixed by mangling of template parameter declaration if it's not "obvious", for example because the template parameter is constrained (we already implemented STEP 1 and STEP 2). This changes the manglings for a few cases: - Functions and function templates with constraints. - Function templates with template parameters with deduced types: `typename<auto N> void f();` - Function templates with template template parameters where the argument has a different template-head: `template<template<typename...T>> void f(); f<std::vector>();` In each case where a mangling changed, the change fixes a mangling collision. Note that only function templates are affected, not class templates or variable templates, and only new constructs (template parameters with deduced types, constrained templates) and esoteric constructs (templates with template template parameters with non-matching template template arguments, most of which Clang still does not accept by default due to `-frelaxed-template-template-args` not being enabled by default), so the risk to ABI stability from this change is relatively low. Nonetheless, `-fclang-abi-compat=17` can be used to restore the old manglings for cases which we could successfully but incorrectly mangle before. Fixes #48216, #49884, #61273 Reviewed By: erichkeane, #libc_abi Differential Revision: https://reviews.llvm.org/D147655
1 parent 5d95d27 commit 4b163e3

25 files changed

+1735
-335
lines changed

clang/docs/ReleaseNotes.rst

+18
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ C/C++ Language Potentially Breaking Changes
4646

4747
C++ Specific Potentially Breaking Changes
4848
-----------------------------------------
49+
- The name mangling rules for function templates has been changed to take into
50+
account the possibility that functions could be overloaded on their template
51+
parameter lists or requires-clauses. This causes mangled names to change for
52+
function templates in the following cases:
53+
- When the function has any constraints, whether from constrained template
54+
parameters or requires-clauses.
55+
- When the template parameter list includes a deduced type -- either
56+
``auto``, ``decltype(auto)``, or a deduced class template specialization
57+
type.
58+
- When a template template parameter is given a template template argument
59+
that has a different template parameter list.
60+
This fixes a number of issues where valid programs would be rejected due to
61+
mangling collisions, or would in some cases be silently miscompiled. Clang
62+
will use the old manglings if ``-fclang-abi-compat=17`` or lower is
63+
specified.
64+
(`#48216 <https://github.com/llvm/llvm-project/issues/48216>`_),
65+
(`#49884 <https://github.com/llvm/llvm-project/issues/49884>`_), and
66+
(`#61273 <https://github.com/llvm/llvm-project/issues/61273>`_)
4967

5068
ABI Changes in This Version
5169
---------------------------

clang/include/clang/AST/ExprConcepts.h

+13-6
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@ class RequiresExpr final : public Expr,
511511
unsigned NumLocalParameters;
512512
unsigned NumRequirements;
513513
RequiresExprBodyDecl *Body;
514+
SourceLocation LParenLoc;
515+
SourceLocation RParenLoc;
514516
SourceLocation RBraceLoc;
515517

516518
unsigned numTrailingObjects(OverloadToken<ParmVarDecl *>) const {
@@ -522,19 +524,22 @@ class RequiresExpr final : public Expr,
522524
}
523525

524526
RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
525-
RequiresExprBodyDecl *Body,
527+
RequiresExprBodyDecl *Body, SourceLocation LParenLoc,
526528
ArrayRef<ParmVarDecl *> LocalParameters,
529+
SourceLocation RParenLoc,
527530
ArrayRef<concepts::Requirement *> Requirements,
528531
SourceLocation RBraceLoc);
529532
RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters,
530533
unsigned NumRequirements);
531534

532535
public:
533-
static RequiresExpr *
534-
Create(ASTContext &C, SourceLocation RequiresKWLoc,
535-
RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> LocalParameters,
536-
ArrayRef<concepts::Requirement *> Requirements,
537-
SourceLocation RBraceLoc);
536+
static RequiresExpr *Create(ASTContext &C, SourceLocation RequiresKWLoc,
537+
RequiresExprBodyDecl *Body,
538+
SourceLocation LParenLoc,
539+
ArrayRef<ParmVarDecl *> LocalParameters,
540+
SourceLocation RParenLoc,
541+
ArrayRef<concepts::Requirement *> Requirements,
542+
SourceLocation RBraceLoc);
538543
static RequiresExpr *
539544
Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters,
540545
unsigned NumRequirements);
@@ -567,6 +572,8 @@ class RequiresExpr final : public Expr,
567572
return RequiresExprBits.RequiresKWLoc;
568573
}
569574

575+
SourceLocation getLParenLoc() const { return LParenLoc; }
576+
SourceLocation getRParenLoc() const { return RParenLoc; }
570577
SourceLocation getRBraceLoc() const { return RBraceLoc; }
571578

572579
static bool classof(const Stmt *T) {

clang/include/clang/Basic/LangOptions.h

+9
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,15 @@ class LangOptions : public LangOptionsBase {
231231
/// - consider classes with defaulted special member functions non-pod.
232232
Ver15,
233233

234+
/// Attempt to be ABI-compatible with code generated by Clang 17.0.x.
235+
/// This causes clang to revert some fixes to its implementation of the
236+
/// Itanium name mangling scheme, with the consequence that overloaded
237+
/// function templates are mangled the same if they differ only by:
238+
/// - constraints
239+
/// - whether a non-type template parameter has a deduced type
240+
/// - the parameter list of a template template parameter
241+
Ver17,
242+
234243
/// Conform to the underlying platform's C and C++ ABIs as closely
235244
/// as we can.
236245
Latest

clang/include/clang/Sema/Sema.h

+2
Original file line numberDiff line numberDiff line change
@@ -8724,7 +8724,9 @@ class Sema final {
87248724
const ASTConstraintSatisfaction &Satisfaction);
87258725
ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc,
87268726
RequiresExprBodyDecl *Body,
8727+
SourceLocation LParenLoc,
87278728
ArrayRef<ParmVarDecl *> LocalParameters,
8729+
SourceLocation RParenLoc,
87288730
ArrayRef<concepts::Requirement *> Requirements,
87298731
SourceLocation ClosingBraceLoc);
87308732

clang/lib/AST/ExprConcepts.cpp

+12-10
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,15 @@ static bool RequirementContainsError(concepts::Requirement *R) {
117117
}
118118

119119
RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
120-
RequiresExprBodyDecl *Body,
120+
RequiresExprBodyDecl *Body, SourceLocation LParenLoc,
121121
ArrayRef<ParmVarDecl *> LocalParameters,
122+
SourceLocation RParenLoc,
122123
ArrayRef<concepts::Requirement *> Requirements,
123124
SourceLocation RBraceLoc)
124125
: Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
125126
NumLocalParameters(LocalParameters.size()),
126-
NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
127+
NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc),
128+
RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) {
127129
RequiresExprBits.IsSatisfied = false;
128130
RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
129131
bool Dependent = false;
@@ -168,18 +170,18 @@ RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
168170
: Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
169171
NumRequirements(NumRequirements) { }
170172

171-
RequiresExpr *
172-
RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
173-
RequiresExprBodyDecl *Body,
174-
ArrayRef<ParmVarDecl *> LocalParameters,
175-
ArrayRef<concepts::Requirement *> Requirements,
176-
SourceLocation RBraceLoc) {
173+
RequiresExpr *RequiresExpr::Create(
174+
ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
175+
SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
176+
SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
177+
SourceLocation RBraceLoc) {
177178
void *Mem =
178179
C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
179180
LocalParameters.size(), Requirements.size()),
180181
alignof(RequiresExpr));
181-
return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
182-
Requirements, RBraceLoc);
182+
return new (Mem)
183+
RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,
184+
RParenLoc, Requirements, RBraceLoc);
183185
}
184186

185187
RequiresExpr *

0 commit comments

Comments
 (0)