From b608b987718c6d841115464f79ab2d1820a63e17 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Fri, 28 Jan 2011 02:26:04 +0000 Subject: [PATCH] Give OpaqueValueExpr a source location, because its source location might be queried in places where we absolutely require a valid location (e.g., for template instantiation). Fixes some major brokenness in the use of __is_convertible_to. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124465 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 11 +++++++++-- include/clang/Sema/Sema.h | 3 ++- lib/AST/Expr.cpp | 2 +- lib/Sema/SemaDeclAttr.cpp | 3 ++- lib/Sema/SemaExpr.cpp | 7 ++++--- lib/Sema/SemaExprCXX.cpp | 2 +- lib/Sema/SemaObjCProperty.cpp | 10 +++++++--- lib/Serialization/ASTReaderStmt.cpp | 1 + lib/Serialization/ASTWriterStmt.cpp | 1 + test/SemaCXX/type-traits.cpp | 6 ++++++ 10 files changed, 34 insertions(+), 12 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 941a982fe3..9fb74d5410 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -3625,15 +3625,22 @@ public: /// context. class OpaqueValueExpr : public Expr { friend class ASTStmtReader; + SourceLocation Loc; + public: - OpaqueValueExpr(QualType T, ExprValueKind VK, ExprObjectKind OK = OK_Ordinary) + OpaqueValueExpr(SourceLocation Loc, QualType T, ExprValueKind VK, + ExprObjectKind OK = OK_Ordinary) : Expr(OpaqueValueExprClass, T, VK, OK, - T->isDependentType(), T->isDependentType(), false) { + T->isDependentType(), T->isDependentType(), false), + Loc(Loc) { } explicit OpaqueValueExpr(EmptyShell Empty) : Expr(OpaqueValueExprClass, Empty) { } + /// \brief Retrieve the location of this expression. + SourceLocation getLocation() const { return Loc; } + virtual SourceRange getSourceRange() const; virtual child_iterator child_begin(); virtual child_iterator child_end(); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a905efe836..781e3588ee 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4551,7 +4551,8 @@ public: /// CheckAssignmentConstraints - Perform type checking for assignment, /// argument passing, variable initialization, and function return values. /// C99 6.5.16. - AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs); + AssignConvertType CheckAssignmentConstraints(SourceLocation Loc, + QualType lhs, QualType rhs); /// Check assignment constraints and prepare for a conversion of the /// RHS to the LHS type. diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index cfe89a8fb0..9e8f801791 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2981,7 +2981,7 @@ Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();} Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); } // OpaqueValueExpr -SourceRange OpaqueValueExpr::getSourceRange() const { return SourceRange(); } +SourceRange OpaqueValueExpr::getSourceRange() const { return Loc; } Stmt::child_iterator OpaqueValueExpr::child_begin() { return child_iterator(); } Stmt::child_iterator OpaqueValueExpr::child_end() { return child_iterator(); } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 474c7cb82f..09fdf8dca4 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1472,7 +1472,8 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { // If this ever proves to be a problem it should be easy to fix. QualType Ty = S.Context.getPointerType(VD->getType()); QualType ParamTy = FD->getParamDecl(0)->getType(); - if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) { + if (S.CheckAssignmentConstraints(FD->getParamDecl(0)->getLocation(), + ParamTy, Ty) != Sema::Compatible) { S.Diag(Attr.getParameterLoc(), diag::err_attribute_cleanup_func_arg_incompatible_type) << Attr.getParameterName() << ParamTy << Ty; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3112ccb55f..098f5396bb 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5507,12 +5507,13 @@ Sema::CheckObjCPointerTypesForAssignment(QualType lhsType, QualType rhsType) { } Sema::AssignConvertType -Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { +Sema::CheckAssignmentConstraints(SourceLocation Loc, + QualType lhsType, QualType rhsType) { // Fake up an opaque expression. We don't actually care about what // cast operations are required, so if CheckAssignmentConstraints // adds casts to this they'll be wasted, but fortunately that doesn't // usually happen on valid code. - OpaqueValueExpr rhs(rhsType, VK_RValue); + OpaqueValueExpr rhs(Loc, rhsType, VK_RValue); Expr *rhsPtr = &rhs; CastKind K = CK_Invalid; @@ -6952,7 +6953,7 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, } } else { // Compound assignment "x += y" - ConvTy = CheckAssignmentConstraints(LHSType, RHSType); + ConvTy = CheckAssignmentConstraints(Loc, LHSType, RHSType); } if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index cf2e10d531..6ba18a54fd 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2531,7 +2531,7 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, BinaryTypeTrait BTT, LhsT = Self.Context.getRValueReferenceType(LhsT); InitializedEntity To(InitializedEntity::InitializeTemporary(RhsT)); - OpaqueValueExpr From(LhsT.getNonLValueExprType(Self.Context), + OpaqueValueExpr From(KeyLoc, LhsT.getNonLValueExprType(Self.Context), Expr::getValueKindForType(LhsT)); Expr *FromPtr = &From; InitializationKind Kind(InitializationKind::CreateCopy(KeyLoc, diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 0951288618..88ad4d7527 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -440,9 +440,13 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Context.canAssignObjCInterfaces( PropType->getAs(), IvarType->getAs()); - else - compat = (CheckAssignmentConstraints(PropType, IvarType) + else { + SourceLocation Loc = PropertyIvarLoc; + if (Loc.isInvalid()) + Loc = PropertyLoc; + compat = (CheckAssignmentConstraints(Loc, PropType, IvarType) == Compatible); + } if (!compat) { Diag(PropertyLoc, diag::error_property_ivar_type) << property->getDeclName() << PropType @@ -663,7 +667,7 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, GetterMethod->getResultType() != property->getType()) { AssignConvertType result = Incompatible; if (property->getType()->isObjCObjectPointerType()) - result = CheckAssignmentConstraints(GetterMethod->getResultType(), + result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(), property->getType()); if (result != Compatible) { Diag(Loc, diag::warn_accessor_property_type_mismatch) diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 79b68e63a8..1a2284bde8 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -1327,6 +1327,7 @@ void ASTStmtReader::VisitSubstNonTypeTemplateParmPackExpr( void ASTStmtReader::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); + E->Loc = ReadSourceLocation(Record, Idx); } Stmt *ASTReader::ReadStmt(PerFileData &F) { diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index 3962439ac5..601de6d8f6 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -1332,6 +1332,7 @@ void ASTStmtWriter::VisitSubstNonTypeTemplateParmPackExpr( void ASTStmtWriter::VisitOpaqueValueExpr(OpaqueValueExpr *E) { VisitExpr(E); + Writer.AddSourceLocation(E->getLocation(), Record); Code = serialization::EXPR_OPAQUE_VALUE; } diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp index 0ecec44963..b7f18aa6bd 100644 --- a/test/SemaCXX/type-traits.cpp +++ b/test/SemaCXX/type-traits.cpp @@ -508,6 +508,11 @@ class PrivateCopy { friend void is_convertible_to(); }; +template +struct X0 { + template X0(const X0&); +}; + void is_convertible_to() { int t01[T(__is_convertible_to(Int, Int))]; int t02[F(__is_convertible_to(Int, IntAr))]; @@ -531,4 +536,5 @@ void is_convertible_to() { int t20[F(__is_convertible_to(const IntAr&, IntAr&))]; int t21[F(__is_convertible_to(Function, Function))]; int t22[F(__is_convertible_to(PrivateCopy, PrivateCopy))]; + int t23[T(__is_convertible_to(X0, X0))]; } -- 2.40.0