summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/Expr.h2
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--clang/include/clang/Sema/Sema.h15
-rw-r--r--clang/lib/AST/Expr.cpp25
-rw-r--r--clang/lib/AST/ExprCXX.cpp5
-rw-r--r--clang/lib/AST/ExprClassification.cpp2
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp24
-rw-r--r--clang/lib/CodeGen/CGClass.cpp2
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp2
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp2
-rw-r--r--clang/lib/Parse/ParseExpr.cpp3
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp13
-rw-r--r--clang/lib/Sema/SemaChecking.cpp4
-rw-r--r--clang/lib/Sema/SemaExpr.cpp12
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp34
-rw-r--r--clang/lib/Sema/SemaExprMember.cpp25
-rw-r--r--clang/lib/Sema/SemaOverload.cpp4
-rw-r--r--clang/lib/Sema/SemaPseudoObject.cpp4
-rw-r--r--clang/lib/Sema/TreeTransform.h8
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp2
-rw-r--r--clang/test/SemaCXX/destructor.cpp11
-rw-r--r--clang/test/SemaCXX/pseudo-destructors.cpp6
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
OpenPOWER on IntegriCloud