forked from OSchip/llvm-project
Sema: Parenthesized bound destructor member expressions can be called
We would wrongfully reject (a.~A)() in both the destructor and pseudo-destructor cases. This fixes PR22668. llvm-svn: 230512
This commit is contained in:
parent
6cd04ac963
commit
ced8bdf74a
|
@ -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; }
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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() &&
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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!");
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 '++'
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue