[clang] d144eb1 - [Clang] Back out the source location workaround for CXXConstructExpr (#145260)

via cfe-commits cfe-commits at lists.llvm.org
Thu Jun 26 02:02:17 PDT 2025


Author: Younan Zhang
Date: 2025-06-26T17:02:13+08:00
New Revision: d144eb1d8cd3abdaec23c902aa3e5a129c9827ef

URL: https://github.com/llvm/llvm-project/commit/d144eb1d8cd3abdaec23c902aa3e5a129c9827ef
DIFF: https://github.com/llvm/llvm-project/commit/d144eb1d8cd3abdaec23c902aa3e5a129c9827ef.diff

LOG: [Clang] Back out the source location workaround for CXXConstructExpr (#145260)

This removes the workaround introduced in 3e1a9cf3b8 and 1ba7dc38d.

The workaround overwrote the right parenthesis location of the sub
expression, which could be wrong when a CXXTemporaryObjectExpr occurs
within a nested expression, e.g. `A(A(1, 2))`.

To completely take it down, we now propagate the left parenthesis source
location throughout SemaCast, such that the ParenOrBraceRange can be
properly set at the point of its creation.

Fixes https://github.com/llvm/llvm-project/issues/143711

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Sema/Initialization.h
    clang/lib/Sema/SemaCast.cpp
    clang/test/AST/ast-dump-expr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a9de3d0d8a8f7..9cfe39fca52ee 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -884,6 +884,7 @@ Bug Fixes to AST Handling
 - Fixed a malformed printout of ``CXXParenListInitExpr`` in certain contexts.
 - Fixed a malformed printout of certain calling convention function attributes. (#GH143160)
 - Fixed dependency calculation for TypedefTypes (#GH89774)
+- Fixed the right parenthesis source location of ``CXXTemporaryObjectExpr``. (#GH143711)
 
 Miscellaneous Bug Fixes
 ^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index 0455e1fa5016b..a1c156eed5394 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -676,11 +676,12 @@ class InitializationKind {
   }
 
   /// Create a direct initialization for a functional cast.
-  static InitializationKind CreateFunctionalCast(SourceRange TypeRange,
+  static InitializationKind CreateFunctionalCast(SourceLocation StartLoc,
+                                                 SourceRange ParenRange,
                                                  bool InitList) {
     return InitializationKind(InitList ? IK_DirectList : IK_Direct,
-                              IC_FunctionalCast, TypeRange.getBegin(),
-                              TypeRange.getBegin(), TypeRange.getEnd());
+                              IC_FunctionalCast, StartLoc,
+                              ParenRange.getBegin(), ParenRange.getEnd());
   }
 
   /// Create a copy initialization.

diff  --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index e15a43c116516..e27ed8fd4de14 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -98,7 +98,36 @@ namespace {
     CXXCastPath BasePath;
     bool IsARCUnbridgedCast;
 
-    SourceRange OpRange;
+    struct OpRangeType {
+      SourceLocation Locations[3];
+
+      OpRangeType(SourceLocation Begin, SourceLocation LParen,
+                  SourceLocation RParen)
+          : Locations{Begin, LParen, RParen} {}
+
+      OpRangeType() = default;
+
+      SourceLocation getBegin() const { return Locations[0]; }
+
+      SourceLocation getLParenLoc() const { return Locations[1]; }
+
+      SourceLocation getRParenLoc() const { return Locations[2]; }
+
+      friend const StreamingDiagnostic &
+      operator<<(const StreamingDiagnostic &DB, OpRangeType Op) {
+        return DB << SourceRange(Op);
+      }
+
+      SourceRange getParenRange() const {
+        return SourceRange(getLParenLoc(), getRParenLoc());
+      }
+
+      operator SourceRange() const {
+        return SourceRange(getBegin(), getRParenLoc());
+      }
+    };
+
+    OpRangeType OpRange;
     SourceRange DestRange;
 
     // Top-level semantics-checking routines.
@@ -237,49 +266,46 @@ static TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
                                            CastKind &Kind,
                                            CXXCastPath &BasePath,
                                            unsigned &msg);
-static TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
-                                               QualType DestType, bool CStyle,
-                                               SourceRange OpRange,
-                                               unsigned &msg,
-                                               CastKind &Kind,
-                                               CXXCastPath &BasePath);
-static TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
-                                              QualType DestType, bool CStyle,
-                                              SourceRange OpRange,
-                                              unsigned &msg,
-                                              CastKind &Kind,
-                                              CXXCastPath &BasePath);
+static TryCastResult
+TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
+                           bool CStyle, CastOperation::OpRangeType OpRange,
+                           unsigned &msg, CastKind &Kind,
+                           CXXCastPath &BasePath);
+static TryCastResult
+TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
+                         bool CStyle, CastOperation::OpRangeType OpRange,
+                         unsigned &msg, CastKind &Kind, CXXCastPath &BasePath);
 static TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
                                        CanQualType DestType, bool CStyle,
-                                       SourceRange OpRange,
+                                       CastOperation::OpRangeType OpRange,
                                        QualType OrigSrcType,
                                        QualType OrigDestType, unsigned &msg,
-                                       CastKind &Kind,
-                                       CXXCastPath &BasePath);
-static TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr,
-                                               QualType SrcType,
-                                               QualType DestType,bool CStyle,
-                                               SourceRange OpRange,
-                                               unsigned &msg,
-                                               CastKind &Kind,
-                                               CXXCastPath &BasePath);
-
+                                       CastKind &Kind, CXXCastPath &BasePath);
 static TryCastResult
-TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
-                      CheckedConversionKind CCK, SourceRange OpRange,
-                      unsigned &msg, CastKind &Kind, bool ListInitialization);
+TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
+                             QualType DestType, bool CStyle,
+                             CastOperation::OpRangeType OpRange, unsigned &msg,
+                             CastKind &Kind, CXXCastPath &BasePath);
+
+static TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
+                                           QualType DestType,
+                                           CheckedConversionKind CCK,
+                                           CastOperation::OpRangeType OpRange,
+                                           unsigned &msg, CastKind &Kind,
+                                           bool ListInitialization);
 static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
                                    QualType DestType, CheckedConversionKind CCK,
-                                   SourceRange OpRange, unsigned &msg,
-                                   CastKind &Kind, CXXCastPath &BasePath,
+                                   CastOperation::OpRangeType OpRange,
+                                   unsigned &msg, CastKind &Kind,
+                                   CXXCastPath &BasePath,
                                    bool ListInitialization);
 static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
                                   QualType DestType, bool CStyle,
                                   unsigned &msg);
 static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
                                         QualType DestType, bool CStyle,
-                                        SourceRange OpRange, unsigned &msg,
-                                        CastKind &Kind);
+                                        CastOperation::OpRangeType OpRange,
+                                        unsigned &msg, CastKind &Kind);
 static TryCastResult TryAddressSpaceCast(Sema &Self, ExprResult &SrcExpr,
                                          QualType DestType, bool CStyle,
                                          unsigned &msg, CastKind &Kind);
@@ -319,7 +345,8 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
       DestType->isDependentType() || Ex.get()->isTypeDependent();
 
   CastOperation Op(*this, DestType, E);
-  Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
+  Op.OpRange =
+      CastOperation::OpRangeType(OpLoc, Parens.getBegin(), Parens.getEnd());
   Op.DestRange = AngleBrackets;
 
   Op.checkQualifiedDestType();
@@ -412,7 +439,7 @@ ExprResult Sema::BuildBuiltinBitCastExpr(SourceLocation KWLoc,
                                          TypeSourceInfo *TSI, Expr *Operand,
                                          SourceLocation RParenLoc) {
   CastOperation Op(*this, TSI->getType(), Operand);
-  Op.OpRange = SourceRange(KWLoc, RParenLoc);
+  Op.OpRange = CastOperation::OpRangeType(KWLoc, KWLoc, RParenLoc);
   TypeLoc TL = TSI->getTypeLoc();
   Op.DestRange = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
 
@@ -431,8 +458,8 @@ ExprResult Sema::BuildBuiltinBitCastExpr(SourceLocation KWLoc,
 /// Try to diagnose a failed overloaded cast.  Returns true if
 /// diagnostics were emitted.
 static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
-                                      SourceRange range, Expr *src,
-                                      QualType destType,
+                                      CastOperation::OpRangeType range,
+                                      Expr *src, QualType destType,
                                       bool listInitialization) {
   switch (CT) {
   // These cast kinds don't consider user-defined conversions.
@@ -454,12 +481,13 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
     return false;
 
   InitializedEntity entity = InitializedEntity::InitializeTemporary(destType);
-  InitializationKind initKind
-    = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(),
-                                                      range, listInitialization)
-    : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range,
-                                                             listInitialization)
-    : InitializationKind::CreateCast(/*type range?*/ range);
+  InitializationKind initKind =
+      (CT == CT_CStyle) ? InitializationKind::CreateCStyleCast(
+                              range.getBegin(), range, listInitialization)
+      : (CT == CT_Functional)
+          ? InitializationKind::CreateFunctionalCast(
+                range.getBegin(), range.getParenRange(), listInitialization)
+          : InitializationKind::CreateCast(/*type range?*/ range);
   InitializationSequence sequence(S, entity, initKind, src);
 
   // It could happen that a constructor failed to be used because
@@ -544,8 +572,8 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
 
 /// Diagnose a failed cast.
 static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
-                            SourceRange opRange, Expr *src, QualType destType,
-                            bool listInitialization) {
+                            CastOperation::OpRangeType opRange, Expr *src,
+                            QualType destType, bool listInitialization) {
   if (msg == diag::err_bad_cxx_cast_generic &&
       tryDiagnoseOverloadedCast(S, castType, opRange, src, destType,
                                 listInitialization))
@@ -1018,7 +1046,7 @@ void CastOperation::CheckAddrspaceCast() {
 /// or downcast between respective pointers or references.
 static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
                                           QualType DestType,
-                                          SourceRange OpRange) {
+                                          CastOperation::OpRangeType OpRange) {
   QualType SrcType = SrcExpr->getType();
   // When casting from pointer or reference, get pointee type; use original
   // type otherwise.
@@ -1361,8 +1389,9 @@ static bool IsAddressSpaceConversion(QualType SrcType, QualType DestType) {
 /// and casting away constness.
 static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
                                    QualType DestType, CheckedConversionKind CCK,
-                                   SourceRange OpRange, unsigned &msg,
-                                   CastKind &Kind, CXXCastPath &BasePath,
+                                   CastOperation::OpRangeType OpRange,
+                                   unsigned &msg, CastKind &Kind,
+                                   CXXCastPath &BasePath,
                                    bool ListInitialization) {
   // Determine whether we have the semantics of a C-style cast.
   bool CStyle = (CCK == CheckedConversionKind::CStyleCast ||
@@ -1625,11 +1654,11 @@ TryCastResult TryLValueToRValueCast(Sema &Self, Expr *SrcExpr,
 }
 
 /// Tests whether a conversion according to C++ 5.2.9p5 is valid.
-TryCastResult
-TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
-                           bool CStyle, SourceRange OpRange,
-                           unsigned &msg, CastKind &Kind,
-                           CXXCastPath &BasePath) {
+TryCastResult TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr,
+                                         QualType DestType, bool CStyle,
+                                         CastOperation::OpRangeType OpRange,
+                                         unsigned &msg, CastKind &Kind,
+                                         CXXCastPath &BasePath) {
   // C++ 5.2.9p5: An lvalue of type "cv1 B", where B is a class type, can be
   //   cast to type "reference to cv2 D", where D is a class derived from B,
   //   if a valid standard conversion from "pointer to D" to "pointer to B"
@@ -1663,11 +1692,11 @@ TryStaticReferenceDowncast(Sema &Self, Expr *SrcExpr, QualType DestType,
 }
 
 /// Tests whether a conversion according to C++ 5.2.9p8 is valid.
-TryCastResult
-TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
-                         bool CStyle, SourceRange OpRange,
-                         unsigned &msg, CastKind &Kind,
-                         CXXCastPath &BasePath) {
+TryCastResult TryStaticPointerDowncast(Sema &Self, QualType SrcType,
+                                       QualType DestType, bool CStyle,
+                                       CastOperation::OpRangeType OpRange,
+                                       unsigned &msg, CastKind &Kind,
+                                       CXXCastPath &BasePath) {
   // C++ 5.2.9p8: An rvalue of type "pointer to cv1 B", where B is a class
   //   type, can be converted to an rvalue of type "pointer to cv2 D", where D
   //   is a class derived from B, if a valid standard conversion from "pointer
@@ -1697,11 +1726,12 @@ TryStaticPointerDowncast(Sema &Self, QualType SrcType, QualType DestType,
 /// TryStaticDowncast - Common functionality of TryStaticReferenceDowncast and
 /// TryStaticPointerDowncast. Tests whether a static downcast from SrcType to
 /// DestType is possible and allowed.
-TryCastResult
-TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
-                  bool CStyle, SourceRange OpRange, QualType OrigSrcType,
-                  QualType OrigDestType, unsigned &msg,
-                  CastKind &Kind, CXXCastPath &BasePath) {
+TryCastResult TryStaticDowncast(Sema &Self, CanQualType SrcType,
+                                CanQualType DestType, bool CStyle,
+                                CastOperation::OpRangeType OpRange,
+                                QualType OrigSrcType, QualType OrigDestType,
+                                unsigned &msg, CastKind &Kind,
+                                CXXCastPath &BasePath) {
   // We can only work with complete types. But don't complain if it doesn't work
   if (!Self.isCompleteType(OpRange.getBegin(), SrcType) ||
       !Self.isCompleteType(OpRange.getBegin(), DestType))
@@ -1810,12 +1840,12 @@ TryStaticDowncast(Sema &Self, CanQualType SrcType, CanQualType DestType,
 ///   converted to an rvalue of type "pointer to member of B of type cv2 T",
 ///   where B is a base class of D [...].
 ///
-TryCastResult
-TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
-                             QualType DestType, bool CStyle,
-                             SourceRange OpRange,
-                             unsigned &msg, CastKind &Kind,
-                             CXXCastPath &BasePath) {
+TryCastResult TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr,
+                                           QualType SrcType, QualType DestType,
+                                           bool CStyle,
+                                           CastOperation::OpRangeType OpRange,
+                                           unsigned &msg, CastKind &Kind,
+                                           CXXCastPath &BasePath) {
   const MemberPointerType *DestMemPtr = DestType->getAs<MemberPointerType>();
   if (!DestMemPtr)
     return TC_NotApplicable;
@@ -1881,8 +1911,9 @@ TryStaticMemberPointerUpcast(Sema &Self, ExprResult &SrcExpr, QualType SrcType,
 TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
                                     QualType DestType,
                                     CheckedConversionKind CCK,
-                                    SourceRange OpRange, unsigned &msg,
-                                    CastKind &Kind, bool ListInitialization) {
+                                    CastOperation::OpRangeType OpRange,
+                                    unsigned &msg, CastKind &Kind,
+                                    bool ListInitialization) {
   if (DestType->isRecordType()) {
     if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
                                  diag::err_bad_cast_incomplete) ||
@@ -1899,8 +1930,8 @@ TryCastResult TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr,
           ? InitializationKind::CreateCStyleCast(OpRange.getBegin(), OpRange,
                                                  ListInitialization)
       : (CCK == CheckedConversionKind::FunctionalCast)
-          ? InitializationKind::CreateFunctionalCast(OpRange,
-                                                     ListInitialization)
+          ? InitializationKind::CreateFunctionalCast(
+                OpRange.getBegin(), OpRange.getParenRange(), ListInitialization)
           : InitializationKind::CreateCast(OpRange);
   Expr *SrcExprRaw = SrcExpr.get();
   // FIXME: Per DR242, we should check for an implicit conversion sequence
@@ -2112,7 +2143,8 @@ static void DiagnoseCastOfObjCSEL(Sema &Self, const ExprResult &SrcExpr,
 /// Diagnose casts that change the calling convention of a pointer to a function
 /// defined in the current TU.
 static void DiagnoseCallingConvCast(Sema &Self, const ExprResult &SrcExpr,
-                                    QualType DstType, SourceRange OpRange) {
+                                    QualType DstType,
+                                    CastOperation::OpRangeType OpRange) {
   // Check if this cast would change the calling convention of a function
   // pointer type.
   QualType SrcType = SrcExpr.get()->getType();
@@ -2255,9 +2287,8 @@ static bool fixOverloadedReinterpretCastExpr(Sema &Self, QualType DestType,
 
 static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
                                         QualType DestType, bool CStyle,
-                                        SourceRange OpRange,
-                                        unsigned &msg,
-                                        CastKind &Kind) {
+                                        CastOperation::OpRangeType OpRange,
+                                        unsigned &msg, CastKind &Kind) {
   bool IsLValueCast = false;
 
   DestType = Self.Context.getCanonicalType(DestType);
@@ -3413,7 +3444,7 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc,
                                      Expr *CastExpr) {
   CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
   Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
-  Op.OpRange = SourceRange(LPLoc, CastExpr->getEndLoc());
+  Op.OpRange = CastOperation::OpRangeType(LPLoc, LPLoc, CastExpr->getEndLoc());
 
   if (getLangOpts().CPlusPlus) {
     Op.CheckCXXCStyleCast(/*FunctionalCast=*/ false,
@@ -3443,7 +3474,8 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
   assert(LPLoc.isValid() && "List-initialization shouldn't get here.");
   CastOperation Op(*this, Type, CastExpr);
   Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
-  Op.OpRange = SourceRange(Op.DestRange.getBegin(), RPLoc);
+  Op.OpRange =
+      CastOperation::OpRangeType(Op.DestRange.getBegin(), LPLoc, RPLoc);
 
   Op.CheckCXXCStyleCast(/*FunctionalCast=*/true, /*ListInit=*/false);
   if (Op.SrcExpr.isInvalid())
@@ -3451,12 +3483,6 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
 
   Op.checkQualifiedDestType();
 
-  auto *SubExpr = Op.SrcExpr.get();
-  if (auto *BindExpr = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
-    SubExpr = BindExpr->getSubExpr();
-  if (auto *ConstructExpr = dyn_cast<CXXConstructExpr>(SubExpr))
-    ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
-
   // -Wcast-qual
   DiagnoseCastQual(Op.Self, Op.SrcExpr, Op.DestType);
 

diff  --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp
index 2efd0b5e8ac21..8ccb39f8f3165 100644
--- a/clang/test/AST/ast-dump-expr.cpp
+++ b/clang/test/AST/ast-dump-expr.cpp
@@ -589,3 +589,13 @@ void leakNewFn() { new struct Sock; }
 // CHECK: CXXNewExpr {{.*}} <col:20, col:31> 'struct Sock *'
 }
 
+namespace GH143711 {
+struct S {
+  S(int, int);
+};
+
+void f() {
+  S(S(0, 1));
+}
+// CHECK: CXXTemporaryObjectExpr {{.*}} <col:5, col:11> 'S':'GH143711::S' 'void (int, int)'
+}


        


More information about the cfe-commits mailing list