[clang] [Clang] Back out the source location workaround for CXXConstructExpr (PR #145260)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 23 00:46:49 PDT 2025
https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/145260
>From 96f1c3bbbf7c07bf9d11bb907e3a35e196d181aa Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Mon, 23 Jun 2025 12:31:39 +0800
Subject: [PATCH] [Clang] Back out the source location workaround for
CXXConstructExpr
This removes the workaround introduced in 3e1a9cf3b8 and 1ba7dc38d.
The issues should have been already resolved elsewhere, at least removing
these lines doesn't break any existing tests.
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))`.
---
clang/docs/ReleaseNotes.rst | 1 +
clang/include/clang/Sema/Initialization.h | 7 +-
clang/lib/Sema/SemaCast.cpp | 193 ++++++++++++----------
clang/test/AST/ast-dump-expr.cpp | 10 ++
4 files changed, 125 insertions(+), 86 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 96477ef6ddc9a..7822a9a6c3cc6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -877,6 +877,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..c092902c688ad 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 Ranges[3];
+
+ OpRangeType(SourceLocation Begin, SourceLocation LParen,
+ SourceLocation RParen)
+ : Ranges{Begin, LParen, RParen} {}
+
+ OpRangeType() = default;
+
+ SourceLocation getBegin() const { return Ranges[0]; }
+
+ SourceLocation getLParenLoc() const { return Ranges[1]; }
+
+ SourceLocation getRParenLoc() const { return Ranges[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,8 @@ 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(Op.DestRange.getBegin(), LPLoc,
+ CastExpr->getEndLoc());
if (getLangOpts().CPlusPlus) {
Op.CheckCXXCStyleCast(/*FunctionalCast=*/ false,
@@ -3443,7 +3475,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 +3484,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