[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