https://github.com/offsetof updated 
https://github.com/llvm/llvm-project/pull/132285

>From ac82e33db6879a8657706129fb28f3565e1899ba Mon Sep 17 00:00:00 2001
From: offsetof <offse...@mailo.com>
Date: Thu, 20 Mar 2025 20:54:58 +0000
Subject: [PATCH 1/2] [clang] Fix static_cast bypassing access control

Fix access and ambiguity checks not being performed when converting to
an rvalue reference to a base class type with `static_cast`.
---
 clang/docs/ReleaseNotes.rst                   |  1 +
 clang/lib/Sema/SemaCast.cpp                   | 24 ++++---
 .../expr/expr.post/expr.static.cast/p3-0x.cpp | 65 ++++++++++++++++++-
 3 files changed, 76 insertions(+), 14 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 159991e8db981..18dcedad810ae 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -357,6 +357,7 @@ Bug Fixes to C++ Support
 - Fixed a Clang regression in C++20 mode where unresolved dependent call 
expressions were created inside non-dependent contexts (#GH122892)
 - Clang now emits the ``-Wunused-variable`` warning when some structured 
bindings are unused
   and the ``[[maybe_unused]]`` attribute is not applied. (#GH125810)
+- Fixed ``static_cast`` not performing access or ambiguity checks when 
converting to an rvalue reference to a base class. (#GH121429)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 718f6bec34910..7d64b4e954e4a 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -221,7 +221,7 @@ static void DiagnoseCastQual(Sema &Self, const ExprResult 
&SrcExpr,
 // %2: Destination Type
 static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
                                            QualType DestType, bool CStyle,
-                                           CastKind &Kind,
+                                           SourceRange OpRange, CastKind &Kind,
                                            CXXCastPath &BasePath,
                                            unsigned &msg);
 static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
@@ -1357,8 +1357,8 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult 
&SrcExpr,
   // C++11 [expr.static.cast]p3:
   //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to cv2
   //   T2" if "cv2 T2" is reference-compatible with "cv1 T1".
-  tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, Kind,
-                              BasePath, msg);
+  tcr = TryLValueToRValueCast(Self, SrcExpr.get(), DestType, CStyle, OpRange,
+                              Kind, BasePath, msg);
   if (tcr != TC_NotApplicable)
     return tcr;
 
@@ -1534,8 +1534,8 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult 
&SrcExpr,
 /// Tests whether a conversion according to N2844 is valid.
 TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
                                     QualType DestType, bool CStyle,
-                                    CastKind &Kind, CXXCastPath &BasePath,
-                                    unsigned &msg) {
+                                    SourceRange OpRange, CastKind &Kind,
+                                    CXXCastPath &BasePath, unsigned &msg) {
   // C++11 [expr.static.cast]p3:
   //   A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
   //   cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
@@ -1548,7 +1548,6 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr 
*SrcExpr,
 
   // Because we try the reference downcast before this function, from now on
   // this is the only cast possibility, so we issue an error if we fail now.
-  // FIXME: Should allow casting away constness if CStyle.
   QualType FromType = SrcExpr->getType();
   QualType ToType = R->getPointeeType();
   if (CStyle) {
@@ -1572,13 +1571,12 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr 
*SrcExpr,
 
   if (RefConv & Sema::ReferenceConversions::DerivedToBase) {
     Kind = CK_DerivedToBase;
-    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
-                       /*DetectVirtual=*/true);
-    if (!Self.IsDerivedFrom(SrcExpr->getBeginLoc(), SrcExpr->getType(),
-                            R->getPointeeType(), Paths))
-      return TC_NotApplicable;
-
-    Self.BuildBasePathArray(Paths, BasePath);
+    if (Self.CheckDerivedToBaseConversion(FromType, ToType,
+                                          SrcExpr->getBeginLoc(), OpRange,
+                                          &BasePath, CStyle)) {
+      msg = 0;
+      return TC_Failed;
+    }
   } else
     Kind = CK_NoOp;
 
diff --git a/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp 
b/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
index 830ccda245baa..0f6968f00f8c1 100644
--- a/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// expected-no-diagnostics
 
 // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
 // cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1" (8.5.3).
@@ -23,3 +22,67 @@ void test(A &a, B &b) {
   const A &&ar10 = static_cast<const A&&>(xvalue<A>());
   const A &&ar11 = static_cast<const A&&>(xvalue<B>());
 }
+
+struct C : private A { // expected-note 4 {{declared private here}}
+    C&& that();
+
+    void f() {
+        (void)static_cast<A&&>(*this);
+        (void)static_cast<const A&&>(*this);
+
+        (void)static_cast<A&&>(that());
+        (void)static_cast<const A&&>(that());
+    }
+};
+C c;
+const C cc;
+
+void f() {
+    static_cast<A&&>(c);        // expected-error {{cannot cast 'C' to its 
private base class 'A'}}
+    static_cast<A&&>(c.that()); // expected-error {{cannot cast 'C' to its 
private base class 'A'}}
+
+    static_cast<const A&&>(c);        // expected-error {{cannot cast 'C' to 
its private base class 'const A'}}
+    static_cast<const A&&>(c.that()); // expected-error {{cannot cast 'C' to 
its private base class 'const A'}}
+}
+
+constexpr auto v = (
+    (A&&)c,
+    (A&&)(C&&)c,
+    (A&&)cc,
+    (A&&)(const C&&)c,
+    (const A&&)c,
+    (const A&&)(C&&)c,
+    (const A&&)cc,
+    (const A&&)(const C&&)c
+);
+
+struct D : A, B { // expected-warning {{direct base 'A' is inaccessible due to 
ambiguity}}
+    D&& rv();
+};
+D d;
+
+void g(const D cd) {
+    static_cast<A&&>(d);      // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+    static_cast<A&&>(d.rv()); // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+
+    static_cast<const A&&>(d);      // expected-error {{ambiguous conversion 
from derived class 'D' to base class 'const A'}}
+    static_cast<const A&&>(d.rv()); // expected-error {{ambiguous conversion 
from derived class 'D' to base class 'const A'}}
+
+    (A&&)d;                  // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+    (A&&)(D&&)d;             // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+    (A&&)cd;                 // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+    (A&&)(const D&&)d;       // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+    (const A&&)d;            // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+    (const A&&)(D&&)d;       // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+    (const A&&)cd;           // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+    (const A&&)(const D&&)d; // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
+}
+
+template<class T, class U>
+auto h(U u = {}) -> decltype(static_cast<T&&>(u));
+
+template<class, class>
+int h();
+
+int i = h<A, C>();
+int j = h<A, D>();

>From 7b015dece6cab815c3245a0395879b35cebc43c4 Mon Sep 17 00:00:00 2001
From: offsetof <offse...@mailo.com>
Date: Mon, 24 Mar 2025 16:12:40 +0000
Subject: [PATCH 2/2] fixup! [clang] Fix static_cast bypassing access control

Update test
---
 .../expr/expr.post/expr.static.cast/p3-0x.cpp | 43 +++++++++----------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp 
b/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
index 0f6968f00f8c1..750741bd4dd97 100644
--- a/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
+++ b/clang/test/CXX/expr/expr.post/expr.static.cast/p3-0x.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++14 -Wno-unused-value -verify %s
 
 // A glvalue of type "cv1 T1" can be cast to type "rvalue reference to
 // cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1" (8.5.3).
@@ -27,11 +27,11 @@ struct C : private A { // expected-note 4 {{declared 
private here}}
     C&& that();
 
     void f() {
-        (void)static_cast<A&&>(*this);
-        (void)static_cast<const A&&>(*this);
+        static_cast<A&&>(*this);
+        static_cast<const A&&>(*this);
 
-        (void)static_cast<A&&>(that());
-        (void)static_cast<const A&&>(that());
+        static_cast<A&&>(that());
+        static_cast<const A&&>(that());
     }
 };
 C c;
@@ -45,23 +45,25 @@ void f() {
     static_cast<const A&&>(c.that()); // expected-error {{cannot cast 'C' to 
its private base class 'const A'}}
 }
 
-constexpr auto v = (
-    (A&&)c,
-    (A&&)(C&&)c,
-    (A&&)cc,
-    (A&&)(const C&&)c,
-    (const A&&)c,
-    (const A&&)(C&&)c,
-    (const A&&)cc,
-    (const A&&)(const C&&)c
-);
+constexpr bool g() {
+    (A&&)c;
+    (A&&)(C&&)c;
+    (A&&)cc;
+    (A&&)(const C&&)c;
+    (const A&&)c;
+    (const A&&)(C&&)c;
+    (const A&&)cc;
+    (const A&&)(const C&&)c;
+    return true;
+}
+static_assert(g(), "");
 
 struct D : A, B { // expected-warning {{direct base 'A' is inaccessible due to 
ambiguity}}
     D&& rv();
 };
 D d;
 
-void g(const D cd) {
+void h(const D cd) {
     static_cast<A&&>(d);      // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
     static_cast<A&&>(d.rv()); // expected-error {{ambiguous conversion from 
derived class 'D' to base class 'A'}}
 
@@ -79,10 +81,7 @@ void g(const D cd) {
 }
 
 template<class T, class U>
-auto h(U u = {}) -> decltype(static_cast<T&&>(u));
-
-template<class, class>
-int h();
+auto s(U u = {}) -> decltype(static_cast<T&&>(u)); // expected-note 2 
{{substitution failure}}
 
-int i = h<A, C>();
-int j = h<A, D>();
+int i = s<A, C>(); // expected-error {{no matching function}}
+int j = s<A, D>(); // expected-error {{no matching function}}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to