diff options
24 files changed, 96 insertions, 117 deletions
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 32adaae0743..c8f121bc193 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2276,7 +2276,7 @@ public: /// getCallReturnType - Get the return type of the call expr. This is not /// always the type of the expr itself, if the return type is a reference /// type. - QualType getCallReturnType() const; + QualType getCallReturnType(const ASTContext &Ctx) const; SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 83eec6eab62..16d93375741 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5645,8 +5645,8 @@ def err_pseudo_dtor_type_mismatch : Error< def err_pseudo_dtor_call_with_args : Error< "call to pseudo-destructor cannot have any arguments">; def err_dtor_expr_without_call : Error< - "%select{destructor reference|pseudo-destructor expression}0 must be " - "called immediately with '()'">; + "reference to %select{destructor|pseudo-destructor}0 must be called" + "%select{|; did you mean to call it with no arguments?}1">; def err_pseudo_dtor_destructor_non_type : Error< "%0 does not refer to a type name in pseudo-destructor expression; expected " "the name of type %1">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index dc0b94250f3..712e0cedba4 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3665,7 +3665,6 @@ public: Scope *S; UnqualifiedId &Id; Decl *ObjCImpDecl; - bool HasTrailingLParen; }; ExprResult BuildMemberReferenceExpr( @@ -3704,8 +3703,7 @@ public: CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Member, - Decl *ObjCImpDecl, - bool HasTrailingLParen); + Decl *ObjCImpDecl); void ActOnDefaultCtorInitializers(Decl *CDtorDecl); bool ConvertArgumentsForCall(CallExpr *Call, Expr *Fn, @@ -4563,8 +4561,6 @@ public: ParsedType &ObjectType, bool &MayBePseudoDestructor); - ExprResult DiagnoseDtorReference(SourceLocation NameLoc, Expr *MemExpr); - ExprResult BuildPseudoDestructorExpr(Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, @@ -4572,8 +4568,7 @@ public: TypeSourceInfo *ScopeType, SourceLocation CCLoc, SourceLocation TildeLoc, - PseudoDestructorTypeStorage DestroyedType, - bool HasTrailingLParen); + PseudoDestructorTypeStorage DestroyedType); ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SourceLocation OpLoc, @@ -4582,15 +4577,13 @@ public: UnqualifiedId &FirstTypeName, SourceLocation CCLoc, SourceLocation TildeLoc, - UnqualifiedId &SecondTypeName, - bool HasTrailingLParen); + UnqualifiedId &SecondTypeName); ExprResult ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation TildeLoc, - const DeclSpec& DS, - bool HasTrailingLParen); + const DeclSpec& DS); /// MaybeCreateExprWithCleanups - If the current full-expression /// requires any cleanups, surround it with a ExprWithCleanups node. diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 6f540085f8e..ae807903127 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1271,16 +1271,21 @@ bool CallExpr::isUnevaluatedBuiltinCall(ASTContext &Ctx) const { return false; } -QualType CallExpr::getCallReturnType() const { - QualType CalleeType = getCallee()->getType(); - if (const PointerType *FnTypePtr = CalleeType->getAs<PointerType>()) +QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { + const Expr *Callee = getCallee(); + QualType CalleeType = Callee->getType(); + if (const auto *FnTypePtr = CalleeType->getAs<PointerType>()) { CalleeType = FnTypePtr->getPointeeType(); - else if (const BlockPointerType *BPT = CalleeType->getAs<BlockPointerType>()) + } else if (const auto *BPT = CalleeType->getAs<BlockPointerType>()) { CalleeType = BPT->getPointeeType(); - else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) + } else if (CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)) { + if (isa<CXXPseudoDestructorExpr>(Callee->IgnoreParens())) + return Ctx.VoidTy; + // This should never be overloaded and so should never return null. - CalleeType = Expr::findBoundMemberType(getCallee()); - + CalleeType = Expr::findBoundMemberType(Callee); + } + const FunctionType *FnType = CalleeType->castAs<FunctionType>(); return FnType->getReturnType(); } @@ -2170,8 +2175,8 @@ bool Expr::isUnusedResultAWarning(const Expr *&WarnE, SourceLocation &Loc, case OO_Greater: case OO_GreaterEqual: case OO_LessEqual: - if (Op->getCallReturnType()->isReferenceType() || - Op->getCallReturnType()->isVoidType()) + if (Op->getCallReturnType(Ctx)->isReferenceType() || + Op->getCallReturnType(Ctx)->isVoidType()) break; WarnE = this; Loc = Op->getOperatorLoc(); @@ -2423,7 +2428,7 @@ QualType Expr::findBoundMemberType(const Expr *expr) { return type; } - assert(isa<UnresolvedMemberExpr>(expr)); + assert(isa<UnresolvedMemberExpr>(expr) || isa<CXXPseudoDestructorExpr>(expr)); return QualType(); } diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 1f54d24c471..f23b3eb79ce 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -238,10 +238,7 @@ CXXPseudoDestructorExpr::CXXPseudoDestructorExpr(const ASTContext &Context, SourceLocation ColonColonLoc, SourceLocation TildeLoc, PseudoDestructorTypeStorage DestroyedType) : Expr(CXXPseudoDestructorExprClass, - Context.getPointerType(Context.getFunctionType( - Context.VoidTy, None, - FunctionProtoType::ExtProtoInfo( - Context.getDefaultCallingConvention(false, true)))), + Context.BoundMemberTy, VK_RValue, OK_Ordinary, /*isTypeDependent=*/(Base->isTypeDependent() || (DestroyedType.getTypeSourceInfo() && diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index 124b4675ca8..3073a53dab0 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -283,7 +283,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::CXXMemberCallExprClass: case Expr::UserDefinedLiteralClass: case Expr::CUDAKernelCallExprClass: - return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType()); + return ClassifyUnnamed(Ctx, cast<CallExpr>(E)->getCallReturnType(Ctx)); // __builtin_choose_expr is equivalent to the chosen expression. case Expr::ChooseExprClass: diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3d9a83d91c9..bf7d86fb12f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -2608,7 +2608,7 @@ Function *CodeGenFunction::LookupNeonLLVMIntrinsic(unsigned IntrinsicID, // Return type. SmallVector<llvm::Type *, 3> Tys; if (Modifier & AddRetType) { - llvm::Type *Ty = ConvertType(E->getCallReturnType()); + llvm::Type *Ty = ConvertType(E->getCallReturnType(getContext())); if (Modifier & VectorizeRetType) Ty = llvm::VectorType::get( Ty, VectorSize ? VectorSize / Ty->getPrimitiveSizeInBits() : 1); @@ -4322,36 +4322,36 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vceqzs_f32: Ops.push_back(EmitScalarExpr(E->getArg(0))); return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OEQ, - ICmpInst::ICMP_EQ, "vceqz"); + Ops[0], ConvertType(E->getCallReturnType(getContext())), + ICmpInst::FCMP_OEQ, ICmpInst::ICMP_EQ, "vceqz"); case NEON::BI__builtin_neon_vcgezd_s64: case NEON::BI__builtin_neon_vcgezd_f64: case NEON::BI__builtin_neon_vcgezs_f32: Ops.push_back(EmitScalarExpr(E->getArg(0))); return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OGE, - ICmpInst::ICMP_SGE, "vcgez"); + Ops[0], ConvertType(E->getCallReturnType(getContext())), + ICmpInst::FCMP_OGE, ICmpInst::ICMP_SGE, "vcgez"); case NEON::BI__builtin_neon_vclezd_s64: case NEON::BI__builtin_neon_vclezd_f64: case NEON::BI__builtin_neon_vclezs_f32: Ops.push_back(EmitScalarExpr(E->getArg(0))); return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OLE, - ICmpInst::ICMP_SLE, "vclez"); + Ops[0], ConvertType(E->getCallReturnType(getContext())), + ICmpInst::FCMP_OLE, ICmpInst::ICMP_SLE, "vclez"); case NEON::BI__builtin_neon_vcgtzd_s64: case NEON::BI__builtin_neon_vcgtzd_f64: case NEON::BI__builtin_neon_vcgtzs_f32: Ops.push_back(EmitScalarExpr(E->getArg(0))); return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OGT, - ICmpInst::ICMP_SGT, "vcgtz"); + Ops[0], ConvertType(E->getCallReturnType(getContext())), + ICmpInst::FCMP_OGT, ICmpInst::ICMP_SGT, "vcgtz"); case NEON::BI__builtin_neon_vcltzd_s64: case NEON::BI__builtin_neon_vcltzd_f64: case NEON::BI__builtin_neon_vcltzs_f32: Ops.push_back(EmitScalarExpr(E->getArg(0))); return EmitAArch64CompareBuiltinExpr( - Ops[0], ConvertType(E->getCallReturnType()), ICmpInst::FCMP_OLT, - ICmpInst::ICMP_SLT, "vcltz"); + Ops[0], ConvertType(E->getCallReturnType(getContext())), + ICmpInst::FCMP_OLT, ICmpInst::ICMP_SLT, "vcltz"); case NEON::BI__builtin_neon_vceqzd_u64: { llvm::Type *Ty = llvm::Type::getInt64Ty(getLLVMContext()); @@ -4803,7 +4803,7 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, case NEON::BI__builtin_neon_vfmad_lane_f64: case NEON::BI__builtin_neon_vfmad_laneq_f64: { Ops.push_back(EmitScalarExpr(E->getArg(3))); - llvm::Type *Ty = ConvertType(E->getCallReturnType()); + llvm::Type *Ty = ConvertType(E->getCallReturnType(getContext())); Value *F = CGM.getIntrinsic(Intrinsic::fma, Ty); Ops[2] = Builder.CreateExtractElement(Ops[2], Ops[3], "extract"); return Builder.CreateCall3(F, Ops[1], Ops[2], Ops[0]); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 66ab6152c21..5649708d780 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2205,7 +2205,7 @@ CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base, // Check if this is a call expr that returns a record type. if (const CallExpr *CE = dyn_cast<CallExpr>(Base)) - return CE->getCallReturnType()->isRecordType(); + return CE->getCallReturnType(getContext())->isRecordType(); // We can't devirtualize the call. return false; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index e8ee446ea92..78e80a15836 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3198,7 +3198,7 @@ LValue CodeGenFunction::EmitCallExprLValue(const CallExpr *E) { if (!RV.isScalar()) return MakeAddrLValue(RV.getAggregateAddr(), E->getType()); - assert(E->getCallReturnType()->isReferenceType() && + assert(E->getCallReturnType(getContext())->isReferenceType() && "Can't have a scalar return unless the return type is a " "reference type!"); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index dd2da23cd85..5b0d9f00dbb 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -741,7 +741,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { } void AggExprEmitter::VisitCallExpr(const CallExpr *E) { - if (E->getCallReturnType()->isReferenceType()) { + if (E->getCallReturnType(CGF.getContext())->isReferenceType()) { EmitAggLoadOfLValue(E); return; } diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index e0ac08b1aa6..b2228f094c1 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -377,7 +377,7 @@ VisitImaginaryLiteral(const ImaginaryLiteral *IL) { ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) { - if (E->getCallReturnType()->isReferenceType()) + if (E->getCallReturnType(CGF.getContext())->isReferenceType()) return EmitLoadOfLValue(E); return CGF.EmitCallExpr(E).getComplexVal(); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 95269dc7875..dc12dd84249 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -320,7 +320,7 @@ public: Value *VisitCastExpr(CastExpr *E); Value *VisitCallExpr(const CallExpr *E) { - if (E->getCallReturnType()->isReferenceType()) + if (E->getCallReturnType(CGF.getContext())->isReferenceType()) return EmitLoadOfLValue(E); Value *V = CGF.EmitCallExpr(E).getScalarVal(); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 4183ae4d3b3..07af62ff099 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1566,8 +1566,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.get(), OpLoc, OpKind, SS, TemplateKWLoc, Name, CurParsedObjCImpl ? CurParsedObjCImpl->Dcl - : nullptr, - Tok.is(tok::l_paren)); + : nullptr); break; } case tok::plusplus: // postfix-expression: postfix-expression '++' diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index d91744115cc..6cff1c59975 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1493,9 +1493,8 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, ParseDecltypeSpecifier(DS); if (DS.getTypeSpecType() == TST_error) return ExprError(); - return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, - OpKind, TildeLoc, DS, - Tok.is(tok::l_paren)); + return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind, + TildeLoc, DS); } if (!Tok.is(tok::identifier)) { @@ -1518,11 +1517,9 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, /*AssumeTemplateName=*/true)) return ExprError(); - return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, - OpLoc, OpKind, - SS, FirstTypeName, CCLoc, - TildeLoc, SecondTypeName, - Tok.is(tok::l_paren)); + return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind, + SS, FirstTypeName, CCLoc, TildeLoc, + SecondTypeName); } /// ParseCXXBoolLiteral - This handles the C++ Boolean literals. diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 409a1b6ebd5..bdaba9a7ce9 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -184,7 +184,7 @@ static bool SemaBuiltinCallWithStaticChain(Sema &S, CallExpr *BuiltinCall) { return true; } - QualType ReturnTy = CE->getCallReturnType(); + QualType ReturnTy = CE->getCallReturnType(S.Context); QualType ArgTys[2] = { ReturnTy, ChainResult.get()->getType() }; QualType BuiltinTy = S.Context.getFunctionType( ReturnTy, ArgTys, FunctionProtoType::ExtProtoInfo()); @@ -6860,7 +6860,7 @@ static bool CheckForReference(Sema &SemaRef, const Expr *E, if (!M->getMemberDecl()->getType()->isReferenceType()) return false; } else if (const CallExpr *Call = dyn_cast<CallExpr>(E)) { - if (!Call->getCallReturnType()->isReferenceType()) + if (!Call->getCallReturnType(SemaRef.Context)->isReferenceType()) return false; FD = Call->getDirectCallee(); } else { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 1b2af7d0133..3725b2d1f3c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -13966,7 +13966,17 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { // Bound member functions. case BuiltinType::BoundMember: { ExprResult result = E; - tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function), + const Expr *BME = E->IgnoreParens(); + PartialDiagnostic PD = PDiag(diag::err_bound_member_function); + // Try to give a nicer diagnostic if it is a bound member that we recognize. + if (isa<CXXPseudoDestructorExpr>(BME)) { + PD = PDiag(diag::err_dtor_expr_without_call) << /*pseudo-destructor*/ 1; + } else if (const auto *ME = dyn_cast<MemberExpr>(BME)) { + if (ME->getMemberNameInfo().getName().getNameKind() == + DeclarationName::CXXDestructorName) + PD = PDiag(diag::err_dtor_expr_without_call) << /*destructor*/ 0; + } + tryToRecoverWithCall(result, PD, /*complain*/ true); return result; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 0a6b0c85458..d24a653b348 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5164,7 +5164,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { if (Call == TopCall) continue; - if (CheckCallReturnType(Call->getCallReturnType(), + if (CheckCallReturnType(Call->getCallReturnType(Context), Call->getLocStart(), Call, Call->getDirectCallee())) return ExprError(); @@ -5365,20 +5365,6 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, return Base; } -ExprResult Sema::DiagnoseDtorReference(SourceLocation NameLoc, - Expr *MemExpr) { - SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(NameLoc); - Diag(MemExpr->getLocStart(), diag::err_dtor_expr_without_call) - << isa<CXXPseudoDestructorExpr>(MemExpr) - << FixItHint::CreateInsertion(ExpectedLParenLoc, "()"); - - return ActOnCallExpr(/*Scope*/ nullptr, - MemExpr, - /*LPLoc*/ ExpectedLParenLoc, - None, - /*RPLoc*/ ExpectedLParenLoc); -} - static bool CheckArrow(Sema& S, QualType& ObjectType, Expr *&Base, tok::TokenKind& OpKind, SourceLocation OpLoc) { if (Base->hasPlaceholderType()) { @@ -5419,8 +5405,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, TypeSourceInfo *ScopeTypeInfo, SourceLocation CCLoc, SourceLocation TildeLoc, - PseudoDestructorTypeStorage Destructed, - bool HasTrailingLParen) { + PseudoDestructorTypeStorage Destructed) { TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo(); QualType ObjectType; @@ -5508,10 +5493,7 @@ ExprResult Sema::BuildPseudoDestructorExpr(Expr *Base, TildeLoc, Destructed); - if (HasTrailingLParen) - return Result; - - return DiagnoseDtorReference(Destructed.getLocation(), Result); + return Result; } ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, @@ -5521,8 +5503,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, UnqualifiedId &FirstTypeName, SourceLocation CCLoc, SourceLocation TildeLoc, - UnqualifiedId &SecondTypeName, - bool HasTrailingLParen) { + UnqualifiedId &SecondTypeName) { assert((FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) && "Invalid first type name in pseudo-destructor"); @@ -5649,15 +5630,14 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, SS, ScopeTypeInfo, CCLoc, TildeLoc, - Destructed, HasTrailingLParen); + Destructed); } ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, SourceLocation TildeLoc, - const DeclSpec& DS, - bool HasTrailingLParen) { + const DeclSpec& DS) { QualType ObjectType; if (CheckArrow(*this, ObjectType, Base, OpKind, OpLoc)) return ExprError(); @@ -5673,7 +5653,7 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, return BuildPseudoDestructorExpr(Base, OpLoc, OpKind, CXXScopeSpec(), nullptr, SourceLocation(), TildeLoc, - Destructed, HasTrailingLParen); + Destructed); } ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index af1cf904611..002c823e3a8 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -969,8 +969,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, CXXScopeSpec TempSS(SS); RetryExpr = ActOnMemberAccessExpr( ExtraArgs->S, RetryExpr.get(), OpLoc, tok::arrow, TempSS, - TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl, - ExtraArgs->HasTrailingLParen); + TemplateKWLoc, ExtraArgs->Id, ExtraArgs->ObjCImpDecl); } if (Trap.hasErrorOccurred()) RetryExpr = ExprError(); @@ -1591,9 +1590,6 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, /// possibilities, including destructor and operator references. /// /// \param OpKind either tok::arrow or tok::period -/// \param HasTrailingLParen whether the next token is '(', which -/// is used to diagnose mis-uses of special members that can -/// only be called /// \param ObjCImpDecl the current Objective-C \@implementation /// decl; this is an ugly hack around the fact that Objective-C /// \@implementations aren't properly put in the context chain @@ -1603,24 +1599,10 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, - Decl *ObjCImpDecl, - bool HasTrailingLParen) { + Decl *ObjCImpDecl) { if (SS.isSet() && SS.isInvalid()) return ExprError(); - // The only way a reference to a destructor can be used is to - // immediately call it. If the next token is not a '(', produce - // a diagnostic and build the call now. - if (!HasTrailingLParen && - Id.getKind() == UnqualifiedId::IK_DestructorName) { - ExprResult DtorAccess = - ActOnMemberAccessExpr(S, Base, OpLoc, OpKind, SS, TemplateKWLoc, Id, - ObjCImpDecl, /*HasTrailingLParen*/true); - if (DtorAccess.isInvalid()) - return DtorAccess; - return DiagnoseDtorReference(Id.getLocStart(), DtorAccess.get()); - } - // Warn about the explicit constructor calls Microsoft extension. if (getLangOpts().MicrosoftExt && Id.getKind() == UnqualifiedId::IK_ConstructorName) @@ -1653,8 +1635,7 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, NameInfo, TemplateArgs); } - ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl, - HasTrailingLParen}; + ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; return BuildMemberReferenceExpr(Base, Base->getType(), OpLoc, IsArrow, SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs, &ExtraArgs); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 65ee2f59472..664b6a48482 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -11595,6 +11595,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, return MaybeBindToTemporary(call); } + if (isa<CXXPseudoDestructorExpr>(NakedMemExpr)) + return new (Context) + CallExpr(Context, MemExprE, Args, Context.VoidTy, VK_RValue, RParenLoc); + UnbridgedCastsSet UnbridgedCasts; if (checkArgPlaceholdersForOverload(*this, Args, UnbridgedCasts)) return ExprError(); diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index 89fb76cfceb..935128b7ecd 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -1442,7 +1442,7 @@ ExprResult MSPropertyOpBuilder::buildGet() { ExprResult GetterExpr = S.ActOnMemberAccessExpr( S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), - GetterName, nullptr, true); + GetterName, nullptr); if (GetterExpr.isInvalid()) { S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_accessor) << 0 /* getter */ @@ -1472,7 +1472,7 @@ ExprResult MSPropertyOpBuilder::buildSet(Expr *op, SourceLocation sl, ExprResult SetterExpr = S.ActOnMemberAccessExpr( S.getCurScope(), RefExpr->getBaseExpr(), SourceLocation(), RefExpr->isArrow() ? tok::arrow : tok::period, SS, SourceLocation(), - SetterName, nullptr, true); + SetterName, nullptr); if (SetterExpr.isInvalid()) { S.Diag(RefExpr->getMemberLoc(), diag::error_cannot_find_suitable_accessor) << 1 /* setter */ diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8cbc75a7ce1..e1d0d18dde4 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -10727,11 +10727,9 @@ TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(Expr *Base, !BaseType->getAs<PointerType>()->getPointeeType() ->template getAs<RecordType>())){ // This pseudo-destructor expression is still a pseudo-destructor. - return SemaRef.BuildPseudoDestructorExpr(Base, OperatorLoc, - isArrow? tok::arrow : tok::period, - SS, ScopeType, CCLoc, TildeLoc, - Destroyed, - /*FIXME?*/true); + return SemaRef.BuildPseudoDestructorExpr( + Base, OperatorLoc, isArrow ? tok::arrow : tok::period, SS, ScopeType, + CCLoc, TildeLoc, Destroyed); } TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo(); diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 366672bca16..55c7a65e6a6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -3340,7 +3340,7 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { // See if it's one of the specific functions we know how to eval. bool canEval = false; - QualType ResultTy = CE->getCallReturnType(); + QualType ResultTy = CE->getCallReturnType(C.getASTContext()); if (ResultTy->isObjCIdType()) { // Handle: id NSMakeCollectable(CFTypeRef) canEval = II->isStr("NSMakeCollectable"); diff --git a/clang/test/SemaCXX/destructor.cpp b/clang/test/SemaCXX/destructor.cpp index c66ec9f2c75..60cb0ef0908 100644 --- a/clang/test/SemaCXX/destructor.cpp +++ b/clang/test/SemaCXX/destructor.cpp @@ -392,3 +392,14 @@ struct S { volatile ~S() { } // expected-error{{destructor cannot have a return type}} }; } + +namespace PR22668 { +struct S { +}; +void f(S s) { + (s.~S)(); +} +void g(S s) { + (s.~S); // expected-error{{reference to destructor must be called}} +} +} diff --git a/clang/test/SemaCXX/pseudo-destructors.cpp b/clang/test/SemaCXX/pseudo-destructors.cpp index 95363e5f6ba..3971881a6b8 100644 --- a/clang/test/SemaCXX/pseudo-destructors.cpp +++ b/clang/test/SemaCXX/pseudo-destructors.cpp @@ -59,7 +59,11 @@ void f(A* a, Foo *f, int *i, double *d, int ii) { typedef int Integer; void destroy_without_call(int *ip) { - ip->~Integer; // expected-error{{called immediately}} + ip->~Integer; // expected-error{{reference to pseudo-destructor must be called}} +} + +void paren_destroy_with_call(int *ip) { + (ip->~Integer)(); } // PR5530 |