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)' +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits