[clang] [Clang] [CodeGen] Perform derived-to-base conversion on explicit object parameter in lambda (PR #89828)
via cfe-commits
cfe-commits at lists.llvm.org
Mon May 20 09:09:30 PDT 2024
https://github.com/Sirraide updated https://github.com/llvm/llvm-project/pull/89828
>From b5422012a65165f27bb31be7e9490892f663acfe Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Tue, 23 Apr 2024 22:45:29 +0200
Subject: [PATCH 1/5] [Clang] [CodeGen] Perform derived-to-base conversion on
explicit object parameter in lambda
---
clang/docs/ReleaseNotes.rst | 3 +
clang/lib/CodeGen/CGExpr.cpp | 23 +++++++
clang/test/CodeGenCXX/cxx2b-deducing-this.cpp | 63 +++++++++++++++++++
3 files changed, 89 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d1f7293a842bb..34aad4abf3961 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -562,6 +562,9 @@ Bug Fixes to C++ Support
- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()``
function returns a large or negative value. Fixes (#GH89407).
- Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235)
+- Fixed a crash when trying to emit captures in a lambda call operator with an explicit object
+ parameter that is called on a derived type of the lambda.
+ Fixes (#GH87210), (GH89541).
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 931cb391342ea..33795d7d4d192 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4684,6 +4684,29 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field,
else
LambdaLV = MakeAddrLValue(AddrOfExplicitObject,
D->getType().getNonReferenceType());
+
+ // Make sure we have an lvalue to the lambda itself and not a derived class.
+ auto *ThisTy = D->getType().getNonReferenceType()->getAsCXXRecordDecl();
+ auto *LambdaTy = cast<CXXRecordDecl>(Field->getParent());
+ if (ThisTy != LambdaTy) {
+ CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+
+ [[maybe_unused]] bool Derived = ThisTy->isDerivedFrom(LambdaTy, Paths);
+ assert(Derived && "Type not derived from lambda type?");
+
+ const CXXBasePath *Path = &Paths.front();
+ CXXCastPath BasePathArray;
+ for (unsigned I = 0, E = Path->size(); I != E; ++I)
+ BasePathArray.push_back(
+ const_cast<CXXBaseSpecifier *>((*Path)[I].Base));
+
+ Address Base = GetAddressOfBaseClass(
+ LambdaLV.getAddress(*this), ThisTy, BasePathArray.begin(),
+ BasePathArray.end(), /*NullCheckValue=*/false, SourceLocation());
+
+ LambdaLV = MakeAddrLValue(Base, QualType{LambdaTy->getTypeForDecl(), 0});
+ }
} else {
QualType LambdaTagType = getContext().getTagDeclType(Field->getParent());
LambdaLV = MakeNaturalAlignAddrLValue(ThisValue, LambdaTagType);
diff --git a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp
index b755e80db35a1..649fe2afbf4e9 100644
--- a/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp
+++ b/clang/test/CodeGenCXX/cxx2b-deducing-this.cpp
@@ -182,3 +182,66 @@ auto dothing(int num)
fun();
}
}
+
+namespace GH87210 {
+template <typename... Ts>
+struct Overloaded : Ts... {
+ using Ts::operator()...;
+};
+
+template <typename... Ts>
+Overloaded(Ts...) -> Overloaded<Ts...>;
+
+// CHECK-LABEL: define dso_local void @_ZN7GH872101fEv()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[X:%.*]] = alloca i32
+// CHECK-NEXT: [[Over:%.*]] = alloca %"{{.*}}Overloaded"
+// CHECK: call noundef ptr @"_ZZN7GH872101fEvENH3$_0clINS_10OverloadedIJS0_EEEEEDaRT_"(ptr {{.*}} [[Over]])
+void f() {
+ int x;
+ Overloaded o {
+ // CHECK: define internal noundef ptr @"_ZZN7GH872101fEvENH3$_0clINS_10OverloadedIJS0_EEEEEDaRT_"(ptr {{.*}} [[Self:%.*]])
+ // CHECK-NEXT: entry:
+ // CHECK-NEXT: [[SelfAddr:%.*]] = alloca ptr
+ // CHECK-NEXT: store ptr [[Self]], ptr [[SelfAddr]]
+ // CHECK-NEXT: [[SelfPtr:%.*]] = load ptr, ptr [[SelfAddr]]
+ // CHECK-NEXT: [[XRef:%.*]] = getelementptr inbounds %{{.*}}, ptr [[SelfPtr]], i32 0, i32 0
+ // CHECK-NEXT: [[X:%.*]] = load ptr, ptr [[XRef]]
+ // CHECK-NEXT: ret ptr [[X]]
+ [&](this auto& self) {
+ return &x;
+ }
+ };
+ o();
+}
+
+void g() {
+ int x;
+ Overloaded o {
+ [=](this auto& self) {
+ return x;
+ }
+ };
+ o();
+}
+}
+
+namespace GH89541 {
+// Same as above; just check that this doesn't crash.
+int one = 1;
+auto factory(int& x = one) {
+ return [&](this auto self) {
+ x;
+ };
+};
+
+using Base = decltype(factory());
+struct Derived : Base {
+ Derived() : Base(factory()) {}
+};
+
+void f() {
+ Derived d;
+ d();
+}
+}
>From 90d73ea88016307532bb38c4b2e8fa8f082bea75 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Thu, 25 Apr 2024 01:01:18 +0200
Subject: [PATCH 2/5] [Clang] Tentative implementation of CWG 2881
---
clang/include/clang/AST/ASTContext.h | 9 +++
.../clang/Basic/DiagnosticSemaKinds.td | 5 ++
clang/include/clang/Sema/Sema.h | 4 +-
clang/lib/CodeGen/CGExpr.cpp | 17 +----
clang/lib/Sema/SemaLambda.cpp | 61 ++++++++++++----
clang/lib/Sema/SemaOverload.cpp | 15 ++--
clang/test/CXX/drs/dr28xx.cpp | 71 +++++++++++++++++++
7 files changed, 147 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index d5ed20ff50157..3210ef2dfe12b 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -110,6 +110,9 @@ class VarTemplateDecl;
class VTableContextBase;
class XRayFunctionFilter;
+/// A simple array of base specifiers.
+typedef SmallVector<CXXBaseSpecifier *, 4> CXXCastPath;
+
namespace Builtin {
class Context;
@@ -1168,6 +1171,12 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// in device compilation.
llvm::DenseSet<const FunctionDecl *> CUDAImplicitHostDeviceFunUsedByDevice;
+ /// For capturing lambdas with an explicit object parameter whose type is
+ /// derived from the lambda type, we need to perform derived-to-base
+ /// conversion so we can access the captures; the cast paths for that
+ /// are stored here.
+ llvm::DenseMap<const CXXMethodDecl *, CXXCastPath> LambdaCastPaths;
+
ASTContext(LangOptions &LOpts, SourceManager &SM, IdentifierTable &idents,
SelectorTable &sels, Builtin::Context &builtins,
TranslationUnitKind TUKind);
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 63e951daec747..5e04ec82ea152 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7497,6 +7497,11 @@ def err_explicit_object_parameter_mutable: Error<
def err_invalid_explicit_object_type_in_lambda: Error<
"invalid explicit object parameter type %0 in lambda with capture; "
"the type must be the same as, or derived from, the lambda">;
+def err_explicit_object_lambda_ambiguous_base : Error<
+ "lambda %0 is inaccessible due to ambiguity:%1">;
+def err_explicit_object_lambda_inaccessible_base : Error<
+ "invalid explicit object parameter type %0 in lambda with capture; "
+ "the type must derive publicly from the lambda">;
def err_ref_qualifier_overload : Error<
"cannot overload a member function %select{without a ref-qualifier|with "
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1ca523ec88c2f..fa450a7868282 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -7144,7 +7144,9 @@ class Sema final : public SemaBase {
StorageClass SC, ArrayRef<ParmVarDecl *> Params,
bool HasExplicitResultType);
- void DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method);
+ /// Returns true if the explicit object parameter was invalid.
+ bool DiagnoseInvalidExplicitObjectParameterInLambda(CXXMethodDecl *Method,
+ SourceLocation CallLoc);
/// Perform initialization analysis of the init-capture and perform
/// any implicit conversions such as an lvalue-to-rvalue conversion if
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 33795d7d4d192..73f8a67c10fe8 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -4667,7 +4667,8 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field,
llvm::Value *ThisValue) {
bool HasExplicitObjectParameter = false;
- if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(CurCodeDecl)) {
+ const auto *MD = dyn_cast_if_present<CXXMethodDecl>(CurCodeDecl);
+ if (MD) {
HasExplicitObjectParameter = MD->isExplicitObjectMemberFunction();
assert(MD->getParent()->isLambda());
assert(MD->getParent() == Field->getParent());
@@ -4689,22 +4690,10 @@ LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field,
auto *ThisTy = D->getType().getNonReferenceType()->getAsCXXRecordDecl();
auto *LambdaTy = cast<CXXRecordDecl>(Field->getParent());
if (ThisTy != LambdaTy) {
- CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
-
- [[maybe_unused]] bool Derived = ThisTy->isDerivedFrom(LambdaTy, Paths);
- assert(Derived && "Type not derived from lambda type?");
-
- const CXXBasePath *Path = &Paths.front();
- CXXCastPath BasePathArray;
- for (unsigned I = 0, E = Path->size(); I != E; ++I)
- BasePathArray.push_back(
- const_cast<CXXBaseSpecifier *>((*Path)[I].Base));
-
+ const CXXCastPath &BasePathArray = getContext().LambdaCastPaths.at(MD);
Address Base = GetAddressOfBaseClass(
LambdaLV.getAddress(*this), ThisTy, BasePathArray.begin(),
BasePathArray.end(), /*NullCheckValue=*/false, SourceLocation());
-
LambdaLV = MakeAddrLValue(Base, QualType{LambdaTy->getTypeForDecl(), 0});
}
} else {
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 1743afaf15287..c96f376d1e2be 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -12,6 +12,7 @@
#include "clang/Sema/SemaLambda.h"
#include "TypeLocBuilder.h"
#include "clang/AST/ASTLambda.h"
+#include "clang/AST/CXXInheritance.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
@@ -386,30 +387,62 @@ buildTypeForLambdaCallOperator(Sema &S, clang::CXXRecordDecl *Class,
// parameter, if any, of the lambda's function call operator (possibly
// instantiated from a function call operator template) shall be either:
// - the closure type,
-// - class type derived from the closure type, or
+// - class type publicly and unambiguously derived from the closure type, or
// - a reference to a possibly cv-qualified such type.
-void Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
- CXXMethodDecl *Method) {
+bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
+ CXXMethodDecl *Method, SourceLocation CallLoc) {
if (!isLambdaCallWithExplicitObjectParameter(Method))
- return;
+ return false;
CXXRecordDecl *RD = Method->getParent();
if (Method->getType()->isDependentType())
- return;
+ return false;
if (RD->isCapturelessLambda())
- return;
- QualType ExplicitObjectParameterType = Method->getParamDecl(0)
- ->getType()
+ return false;
+
+ ParmVarDecl *Param = Method->getParamDecl(0);
+ QualType ExplicitObjectParameterType = Param->getType()
.getNonReferenceType()
.getUnqualifiedType()
.getDesugaredType(getASTContext());
QualType LambdaType = getASTContext().getRecordType(RD);
if (LambdaType == ExplicitObjectParameterType)
- return;
- if (IsDerivedFrom(RD->getLocation(), ExplicitObjectParameterType, LambdaType))
- return;
- Diag(Method->getParamDecl(0)->getLocation(),
- diag::err_invalid_explicit_object_type_in_lambda)
- << ExplicitObjectParameterType;
+ return false;
+
+ // Don't check the same instantiation twice.
+ //
+ // If this call operator is ill-formed, there is no point in issuing
+ // a diagnostic every time it is called because the problem is in the
+ // definition of the derived type, not at the call site.
+ //
+ // FIXME: Move this check to where we instantiate the method?
+ if (auto It = Context.LambdaCastPaths.find(Method);
+ It != Context.LambdaCastPaths.end())
+ return It->second.empty();
+
+ CXXCastPath &Path = Context.LambdaCastPaths[Method];
+ CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
+ /*DetectVirtual=*/false);
+ if (!IsDerivedFrom(RD->getLocation(), ExplicitObjectParameterType, LambdaType,
+ Paths)) {
+ Diag(Param->getLocation(), diag::err_invalid_explicit_object_type_in_lambda)
+ << ExplicitObjectParameterType;
+ return true;
+ }
+
+ if (Paths.isAmbiguous(LambdaType->getCanonicalTypeUnqualified())) {
+ std::string PathsDisplay = getAmbiguousPathsDisplayString(Paths);
+ Diag(CallLoc, diag::err_explicit_object_lambda_ambiguous_base)
+ << LambdaType << PathsDisplay;
+ return true;
+ }
+
+ if (CheckBaseClassAccess(CallLoc, LambdaType, ExplicitObjectParameterType,
+ Paths.front(),
+ diag::err_explicit_object_lambda_inaccessible_base))
+ return true;
+
+ BuildBasePathArray(Paths, Path);
+ return false;
}
void Sema::handleLambdaNumbering(
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 04cd9e78739d2..88782cf64c95d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6492,17 +6492,20 @@ ExprResult Sema::InitializeExplicitObjectArgument(Sema &S, Expr *Obj,
Obj->getExprLoc(), Obj);
}
-static void PrepareExplicitObjectArgument(Sema &S, CXXMethodDecl *Method,
+static bool PrepareExplicitObjectArgument(Sema &S, CXXMethodDecl *Method,
Expr *Object, MultiExprArg &Args,
SmallVectorImpl<Expr *> &NewArgs) {
assert(Method->isExplicitObjectMemberFunction() &&
"Method is not an explicit member function");
assert(NewArgs.empty() && "NewArgs should be empty");
+
NewArgs.reserve(Args.size() + 1);
Expr *This = GetExplicitObjectExpr(S, Object, Method);
NewArgs.push_back(This);
NewArgs.append(Args.begin(), Args.end());
Args = NewArgs;
+ return S.DiagnoseInvalidExplicitObjectParameterInLambda(
+ Method, Object->getBeginLoc());
}
/// Determine whether the provided type is an integral type, or an enumeration
@@ -15671,8 +15674,10 @@ ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
CallExpr *TheCall = nullptr;
llvm::SmallVector<Expr *, 8> NewArgs;
if (Method->isExplicitObjectMemberFunction()) {
- PrepareExplicitObjectArgument(*this, Method, MemExpr->getBase(), Args,
- NewArgs);
+ if (PrepareExplicitObjectArgument(*this, Method, MemExpr->getBase(), Args,
+ NewArgs))
+ return ExprError();
+
// Build the actual expression node.
ExprResult FnExpr =
CreateFunctionRefExpr(*this, Method, FoundDecl, MemExpr,
@@ -15986,9 +15991,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
// Initialize the object parameter.
llvm::SmallVector<Expr *, 8> NewArgs;
if (Method->isExplicitObjectMemberFunction()) {
- // FIXME: we should do that during the definition of the lambda when we can.
- DiagnoseInvalidExplicitObjectParameterInLambda(Method);
- PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs);
+ IsError |= PrepareExplicitObjectArgument(*this, Method, Obj, Args, NewArgs);
} else {
ExprResult ObjRes = PerformImplicitObjectArgumentInitialization(
Object.get(), /*Qualifier=*/nullptr, Best->FoundDecl, Method);
diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp
index 4d9b0c76758d5..ef140a91b9c49 100644
--- a/clang/test/CXX/drs/dr28xx.cpp
+++ b/clang/test/CXX/drs/dr28xx.cpp
@@ -81,3 +81,74 @@ struct A {
#endif
} // namespace cwg2858
+
+namespace cwg2881 { // cwg2881: 19
+
+#if __cplusplus >= 202302L
+
+template <typename T> struct A : T {};
+template <typename T> struct B : T {};
+template <typename T> struct C : virtual T { C(T t) : T(t) {} };
+template <typename T> struct D : virtual T { D(T t) : T(t) {} };
+
+template <typename Ts>
+struct O1 : A<Ts>, B<Ts> {
+ using A<Ts>::operator();
+ using B<Ts>::operator();
+};
+
+template <typename Ts> struct O2 : protected Ts { // expected-note {{declared protected here}}
+ using Ts::operator();
+ O2(Ts ts) : Ts(ts) {}
+};
+
+template <typename Ts> struct O3 : private Ts { // expected-note {{declared private here}}
+ using Ts::operator();
+ O3(Ts ts) : Ts(ts) {}
+};
+
+// Not ambiguous because of virtual inheritance.
+template <typename Ts>
+struct O4 : C<Ts>, D<Ts> {
+ using C<Ts>::operator();
+ using D<Ts>::operator();
+ O4(Ts t) : Ts(t), C<Ts>(t), D<Ts>(t) {}
+};
+
+// This still has a public path to the lambda, and it's also not
+// ambiguous because of virtual inheritance.
+template <typename Ts>
+struct O5 : private C<Ts>, D<Ts> {
+ using C<Ts>::operator();
+ using D<Ts>::operator();
+ O5(Ts t) : Ts(t), C<Ts>(t), D<Ts>(t) {}
+};
+
+// This is only invalid if we call T's call operator.
+template <typename T, typename U>
+struct O6 : private T, U { // expected-note {{declared private here}}
+ using T::operator();
+ using U::operator();
+ O6(T t, U u) : T(t), U(u) {}
+};
+
+void f() {
+ int x;
+ auto L1 = [=](this auto&& self) { (void) &x; };
+ auto L2 = [&](this auto&& self) { (void) &x; };
+ O1<decltype(L1)>{L1, L1}(); // expected-error {{inaccessible due to ambiguity}}
+ O1<decltype(L2)>{L2, L2}(); // expected-error {{inaccessible due to ambiguity}}
+ O2{L1}(); // expected-error {{must derive publicly from the lambda}}
+ O3{L1}(); // expected-error {{must derive publicly from the lambda}}
+ O4{L1}();
+ O5{L1}();
+ O6 o{L1, L2};
+ o.decltype(L1)::operator()(); // expected-error {{must derive publicly from the lambda}}
+ o.decltype(L1)::operator()(); // No error here because we've already diagnosed this method.
+ o.decltype(L2)::operator()();
+}
+
+#endif
+
+} // namespace cwg2881
+
>From a6d81ad1e5b2ed58cb920ef7d6112276466bff4c Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 29 Apr 2024 09:49:19 +0200
Subject: [PATCH 3/5] [NFC] Add date to dr test
---
clang/test/CXX/drs/dr28xx.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/CXX/drs/dr28xx.cpp b/clang/test/CXX/drs/dr28xx.cpp
index ef140a91b9c49..57c0c7312047d 100644
--- a/clang/test/CXX/drs/dr28xx.cpp
+++ b/clang/test/CXX/drs/dr28xx.cpp
@@ -82,7 +82,7 @@ struct A {
} // namespace cwg2858
-namespace cwg2881 { // cwg2881: 19
+namespace cwg2881 { // cwg2881: 19 open 2024-04-19
#if __cplusplus >= 202302L
>From 8f0bf0e3ce7dffdf007d63a2460894db326097f3 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 20 May 2024 17:41:06 +0200
Subject: [PATCH 4/5] [NFC] Elaborate on FIXME comment
---
clang/lib/Sema/SemaLambda.cpp | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index c96f376d1e2be..276a43ad79b91 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -414,7 +414,14 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
// a diagnostic every time it is called because the problem is in the
// definition of the derived type, not at the call site.
//
- // FIXME: Move this check to where we instantiate the method?
+ // FIXME: Move this check to where we instantiate the method? This should
+ // be possible, but the naive approach of just marking the method as invalid
+ // leads to us emitting more diagnostics than we should have to for this case
+ // (1 error here *and* 1 error about there being no matching overload at the
+ // call site). It might be possible to avoid that by also checking if there
+ // is an empty cast path for the method stored in the context (signalling that
+ // we've already diagnosed it) and then just not building the call, but that
+ // doesn't really seem any simpler than diagnosing it at the call site...
if (auto It = Context.LambdaCastPaths.find(Method);
It != Context.LambdaCastPaths.end())
return It->second.empty();
>From 3dfd23a320a07531c6e8c7c6afb767444dcecbf9 Mon Sep 17 00:00:00 2001
From: Sirraide <aeternalmail at gmail.com>
Date: Mon, 20 May 2024 18:09:15 +0200
Subject: [PATCH 5/5] [Clang][Docs] Run make_cxx_dr_status
---
clang/www/cxx_dr_status.html | 48 +++++++++++++++++-------------------
1 file changed, 22 insertions(+), 26 deletions(-)
diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 5d517d358672c..867d49634532d 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -12890,11 +12890,11 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>Virtual bases in destructors and defaulted assignment operators</td>
<td class="full" align="center">Yes</td>
</tr>
- <tr class="open" id="2181">
+ <tr id="2181">
<td><a href="https://cplusplus.github.io/CWG/issues/2181.html">2181</a></td>
- <td>drafting</td>
+ <td>C++20</td>
<td>Normative requirements in an informative Annex</td>
- <td align="center">Not resolved</td>
+ <td class="unknown" align="center">Unknown</td>
</tr>
<tr class="open" id="2182">
<td><a href="https://cplusplus.github.io/CWG/issues/2182.html">2182</a></td>
@@ -17021,13 +17021,13 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
</tr>
<tr class="open" id="2869">
<td><a href="https://cplusplus.github.io/CWG/issues/2869.html">2869</a></td>
- <td>review</td>
+ <td>tentatively ready</td>
<td><TT>this</TT> in local classes</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2870">
<td><a href="https://cplusplus.github.io/CWG/issues/2870.html">2870</a></td>
- <td>review</td>
+ <td>tentatively ready</td>
<td>Combining absent <I>encoding-prefix</I>es</td>
<td align="center">Not resolved</td>
</tr>
@@ -17039,7 +17039,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
</tr>
<tr class="open" id="2872">
<td><a href="https://cplusplus.github.io/CWG/issues/2872.html">2872</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Linkage and unclear "can be referred to"</td>
<td align="center">Not resolved</td>
</tr>
@@ -17051,25 +17051,25 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
</tr>
<tr class="open" id="2874">
<td><a href="https://cplusplus.github.io/CWG/issues/2874.html">2874</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Qualified declarations of partial specializations</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2875">
<td><a href="https://cplusplus.github.io/CWG/issues/2875.html">2875</a></td>
- <td>open</td>
- <td>Missing support for round-tripping nullptr through indirection/address operators</td>
+ <td>tentatively ready</td>
+ <td>Missing support for round-tripping null pointer values through indirection/address operators</td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2876">
<td><a href="https://cplusplus.github.io/CWG/issues/2876.html">2876</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Disambiguation of <TT>T x = delete("text")</TT></td>
<td align="center">Not resolved</td>
</tr>
<tr class="open" id="2877">
<td><a href="https://cplusplus.github.io/CWG/issues/2877.html">2877</a></td>
- <td>open</td>
+ <td>tentatively ready</td>
<td>Type-only lookup for <I>using-enum-declarator</I></td>
<td align="center">Not resolved</td>
</tr>
@@ -17091,12 +17091,6 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>Accessibility check for destructor of incomplete class type</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2881">
- <td><a href="https://cplusplus.github.io/CWG/issues/2881.html">2881</a></td>
- <td>open</td>
- <td>Type restrictions for the explicit object parameter of a lambda</td>
- <td align="center">Not resolved</td>
- </tr>
<tr class="open" id="2882">
<td><a href="https://cplusplus.github.io/CWG/issues/2882.html">2882</a></td>
<td>open</td>
@@ -17109,15 +17103,15 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>Definition of "odr-usable" ignores lambda scopes</td>
<td align="center">Not resolved</td>
</tr>
- <tr class="open" id="2884">
+ <tr id="2884">
<td><a href="https://cplusplus.github.io/CWG/issues/2884.html">2884</a></td>
- <td>open</td>
+ <td>dup</td>
<td>Qualified declarations of partial specializations</td>
- <td align="center">Not resolved</td>
+ <td class="unknown" align="center">Unknown</td>
</tr>
<tr class="open" id="2885">
<td><a href="https://cplusplus.github.io/CWG/issues/2885.html">2885</a></td>
- <td>open</td>
+ <td>review</td>
<td>Non-eligible trivial default constructors</td>
<td align="center">Not resolved</td>
</tr>
@@ -17150,8 +17144,10 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td>open</td>
<td>Defining members of local classes</td>
<td align="center">Not resolved</td>
- </tr></table>
-
-</div>
-</body>
-</html>
+ </tr>
+ <tr class="open" id="2891">
+ <td><a href="https://cplusplus.github.io/CWG/issues/2891.html">2891</a></td>
+ <td>review</td>
+ <td>Normative status of implementation limits</td>
+ <td align="center">Not resolved</td>
+ </tr>
\ No newline at end of file
More information about the cfe-commits
mailing list