summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaCXXCast.cpp18
-rw-r--r--clang/lib/Sema/SemaExpr.cpp136
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp15
-rw-r--r--clang/lib/Sema/SemaOverload.cpp176
-rw-r--r--clang/lib/Sema/SemaStmt.cpp6
5 files changed, 192 insertions, 159 deletions
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp
index 648011b1f05..ed54f0f5442 100644
--- a/clang/lib/Sema/SemaCXXCast.cpp
+++ b/clang/lib/Sema/SemaCXXCast.cpp
@@ -160,10 +160,6 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
// FIXME: should we check this in a more fine-grained manner?
bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent();
- if (Ex.get()->isBoundMemberFunction(Context))
- Diag(Ex.get()->getLocStart(), diag::err_invalid_use_of_bound_member_func)
- << Ex.get()->getSourceRange();
-
ExprValueKind VK = VK_RValue;
if (TypeDependent)
VK = Expr::getValueKindForType(DestType);
@@ -305,6 +301,11 @@ 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) {
+ if (src->getType() == S.Context.BoundMemberTy) {
+ (void) S.CheckPlaceholderExpr(src); // will always fail
+ return;
+ }
+
if (msg == diag::err_bad_cxx_cast_generic &&
tryDiagnoseOverloadedCast(S, castType, opRange, src, destType))
return;
@@ -1540,12 +1541,6 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
Expr *CastExpr, CastKind &Kind,
CXXCastPath &BasePath,
bool FunctionalStyle) {
- if (CastExpr->isBoundMemberFunction(Context)) {
- Diag(CastExpr->getLocStart(), diag::err_invalid_use_of_bound_member_func)
- << CastExpr->getSourceRange();
- return ExprError();
- }
-
// This test is outside everything else because it's the only case where
// a non-lvalue-reference target type does not lead to decay.
// C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
@@ -1557,6 +1552,9 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
return ExprError();
CastExpr = CastExprRes.take();
+ if (CastExpr->getType() == Context.BoundMemberTy)
+ return CheckPlaceholderExpr(CastExpr); // will always fail
+
if (CastExpr->getType() == Context.OverloadTy) {
ExprResult SingleFunctionExpr =
ResolveAndFixSingleFunctionTemplateSpecialization(
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c90c5132506..212f584f5fe 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -3934,12 +3934,20 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
}
if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) {
+ ExprValueKind valueKind;
+ QualType type;
+ if (MemberFn->isInstance()) {
+ valueKind = VK_RValue;
+ type = Context.BoundMemberTy;
+ } else {
+ valueKind = VK_LValue;
+ type = MemberFn->getType();
+ }
+
MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(BuildMemberExpr(Context, BaseExpr, IsArrow, SS,
MemberFn, FoundDecl, MemberNameInfo,
- MemberFn->getType(),
- MemberFn->isInstance() ? VK_RValue : VK_LValue,
- OK_Ordinary));
+ type, valueKind, OK_Ordinary));
}
assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?");
@@ -4051,6 +4059,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
<< BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
<< FixItHint::CreateReplacement(OpLoc, ".");
IsArrow = false;
+ } else if (BaseType == Context.BoundMemberTy) {
+ goto fail;
} else {
Diag(MemberLoc, diag::err_typecheck_member_reference_arrow)
<< BaseType << BaseExpr.get()->getSourceRange();
@@ -4424,6 +4434,16 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
}
} else if ((Fun = BaseType->getAs<FunctionType>())) {
TryCall = true;
+ } else if (BaseType == Context.BoundMemberTy) {
+ // Look for the bound-member type. If it's still overloaded,
+ // give up, although we probably should have fallen into the
+ // OverloadExpr case above if we actually have an overloaded
+ // bound member.
+ QualType fnType = Expr::findBoundMemberType(BaseExpr.get());
+ if (!fnType.isNull()) {
+ TryCall = true;
+ Fun = fnType->castAs<FunctionType>();
+ }
}
if (TryCall) {
@@ -4858,91 +4878,33 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
Fn = result.take();
}
- Expr *NakedFn = Fn->IgnoreParens();
-
- // Determine whether this is a call to an unresolved member function.
- if (UnresolvedMemberExpr *MemE = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
- // If lookup was unresolved but not dependent (i.e. didn't find
- // an unresolved using declaration), it has to be an overloaded
- // function set, which means it must contain either multiple
- // declarations (all methods or method templates) or a single
- // method template.
- assert((MemE->getNumDecls() > 1) ||
- isa<FunctionTemplateDecl>(
- (*MemE->decls_begin())->getUnderlyingDecl()));
- (void)MemE;
-
+ if (Fn->getType() == Context.BoundMemberTy) {
return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
RParenLoc);
}
+ }
+
+ // Check for overloaded calls. This can happen even in C due to extensions.
+ if (Fn->getType() == Context.OverloadTy) {
+ OverloadExpr::FindResult find = OverloadExpr::find(Fn);
- // Determine whether this is a call to a member function.
- if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(NakedFn)) {
- NamedDecl *MemDecl = MemExpr->getMemberDecl();
- if (isa<CXXMethodDecl>(MemDecl))
+ // We aren't supposed to apply this logic if there's an '&' involved.
+ if (!find.IsAddressOfOperand) {
+ OverloadExpr *ovl = find.Expression;
+ if (isa<UnresolvedLookupExpr>(ovl)) {
+ UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(ovl);
+ return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
+ RParenLoc, ExecConfig);
+ } else {
return BuildCallToMemberFunction(S, Fn, LParenLoc, Args, NumArgs,
RParenLoc);
- }
-
- // Determine whether this is a call to a pointer-to-member function.
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(NakedFn)) {
- if (BO->getOpcode() == BO_PtrMemD ||
- BO->getOpcode() == BO_PtrMemI) {
- if (const FunctionProtoType *FPT
- = BO->getType()->getAs<FunctionProtoType>()) {
- QualType ResultTy = FPT->getCallResultType(Context);
- ExprValueKind VK = Expr::getValueKindForType(FPT->getResultType());
-
- // Check that the object type isn't more qualified than the
- // member function we're calling.
- Qualifiers FuncQuals = Qualifiers::fromCVRMask(FPT->getTypeQuals());
- Qualifiers ObjectQuals
- = BO->getOpcode() == BO_PtrMemD
- ? BO->getLHS()->getType().getQualifiers()
- : BO->getLHS()->getType()->getAs<PointerType>()
- ->getPointeeType().getQualifiers();
-
- Qualifiers Difference = ObjectQuals - FuncQuals;
- Difference.removeObjCGCAttr();
- Difference.removeAddressSpace();
- if (Difference) {
- std::string QualsString = Difference.getAsString();
- Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
- << BO->getType().getUnqualifiedType()
- << QualsString
- << (QualsString.find(' ') == std::string::npos? 1 : 2);
- }
-
- CXXMemberCallExpr *TheCall
- = new (Context) CXXMemberCallExpr(Context, Fn, Args,
- NumArgs, ResultTy, VK,
- RParenLoc);
-
- if (CheckCallReturnType(FPT->getResultType(),
- BO->getRHS()->getSourceRange().getBegin(),
- TheCall, 0))
- return ExprError();
-
- if (ConvertArgumentsForCall(TheCall, BO, 0, FPT, Args, NumArgs,
- RParenLoc))
- return ExprError();
-
- return MaybeBindToTemporary(TheCall);
- }
}
}
}
// If we're directly calling a function, get the appropriate declaration.
- // Also, in C++, keep track of whether we should perform argument-dependent
- // lookup and whether there were any explicitly-specified template arguments.
Expr *NakedFn = Fn->IgnoreParens();
- if (isa<UnresolvedLookupExpr>(NakedFn)) {
- UnresolvedLookupExpr *ULE = cast<UnresolvedLookupExpr>(NakedFn);
- return BuildOverloadedCallExpr(S, Fn, ULE, LParenLoc, Args, NumArgs,
- RParenLoc, ExecConfig);
- }
NamedDecl *NDecl = 0;
if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(NakedFn))
@@ -4951,6 +4913,8 @@ Sema::ActOnCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
if (isa<DeclRefExpr>(NakedFn))
NDecl = cast<DeclRefExpr>(NakedFn)->getDecl();
+ else if (isa<MemberExpr>(NakedFn))
+ NDecl = cast<MemberExpr>(NakedFn)->getMemberDecl();
return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, Args, NumArgs, RParenLoc,
ExecConfig);
@@ -8282,6 +8246,11 @@ static QualType CheckAddressOfOperand(Sema &S, Expr *OrigOp,
return S.Context.OverloadTy;
if (OrigOp->getType() == S.Context.UnknownAnyTy)
return S.Context.UnknownAnyTy;
+ if (OrigOp->getType() == S.Context.BoundMemberTy) {
+ S.Diag(OpLoc, diag::err_invalid_form_pointer_member_function)
+ << OrigOp->getSourceRange();
+ return QualType();
+ }
assert(!OrigOp->getType()->isPlaceholderType());
@@ -10301,13 +10270,11 @@ ExprResult Sema::CheckBooleanCondition(Expr *E, SourceLocation Loc) {
if (ParenExpr *parenE = dyn_cast<ParenExpr>(E))
DiagnoseEqualityWithExtraParens(parenE);
- if (!E->isTypeDependent()) {
- if (E->isBoundMemberFunction(Context)) {
- Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
- << E->getSourceRange();
- return ExprError();
- }
+ ExprResult result = CheckPlaceholderExpr(E);
+ if (result.isInvalid()) return ExprError();
+ E = result.take();
+ if (!E->isTypeDependent()) {
if (getLangOptions().CPlusPlus)
return CheckCXXBooleanCondition(E); // C++ 6.4p4
@@ -10728,6 +10695,13 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
QualType(),
diag::err_ovl_unresolvable);
+ // Bound member functions.
+ if (type == Context.BoundMemberTy) {
+ Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
+ << E->getSourceRange();
+ return ExprError();
+ }
+
// Expressions of unknown type.
if (type == Context.UnknownAnyTy)
return diagnoseUnknownAnyExpr(*this, E);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index edfa4a532df..f8ad763e4bd 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2857,13 +2857,6 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex,
// second operand.
// The cv qualifiers are the union of those in the pointer and the left side,
// in accordance with 5.5p5 and 5.2.5.
- // FIXME: This returns a dereferenced member function pointer as a normal
- // function type. However, the only operation valid on such functions is
- // calling them. There's also a GCC extension to get a function pointer to the
- // thing, which is another complication, because this type - unlike the type
- // that is the result of this expression - takes the class as the first
- // argument.
- // We probably need a "MemberFunctionClosureType" or something like that.
QualType Result = MemPtr->getPointeeType();
Result = Context.getCVRQualifiedType(Result, LType.getCVRQualifiers());
@@ -2900,12 +2893,14 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &lex, ExprResult &rex,
// operand is a pointer to a member function is a prvalue. The
// result of an ->* expression is an lvalue if its second operand
// is a pointer to data member and a prvalue otherwise.
- if (Result->isFunctionType())
+ if (Result->isFunctionType()) {
VK = VK_RValue;
- else if (isIndirect)
+ return Context.BoundMemberTy;
+ } else if (isIndirect) {
VK = VK_LValue;
- else
+ } else {
VK = lex.get()->getValueKind();
+ }
return Result;
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 06c097c620c..6e6bf22be0b 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -3623,8 +3623,8 @@ ExprResult Sema::PerformContextuallyConvertToBool(Expr *From) {
return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
- return Diag(From->getSourceRange().getBegin(),
- diag::err_typecheck_bool_condition)
+ return Diag(From->getSourceRange().getBegin(),
+ diag::err_typecheck_bool_condition)
<< From->getType() << From->getSourceRange();
return ExprError();
}
@@ -7202,7 +7202,7 @@ public:
if (!TargetFunctionType->isFunctionType()) {
if (OvlExpr->hasExplicitTemplateArgs()) {
DeclAccessPair dap;
- if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
+ if (FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization(
OvlExpr, false, &dap) ) {
if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) {
@@ -7502,32 +7502,29 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetTyp
/// template, where that template-id refers to a single template whose template
/// arguments are either provided by the template-id or have defaults,
/// as described in C++0x [temp.arg.explicit]p3.
-FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
- bool Complain,
- DeclAccessPair* FoundResult) {
+FunctionDecl *
+Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
+ bool Complain,
+ DeclAccessPair *FoundResult) {
// C++ [over.over]p1:
// [...] [Note: any redundant set of parentheses surrounding the
// overloaded function name is ignored (5.1). ]
// C++ [over.over]p1:
// [...] The overloaded function name can be preceded by the &
// operator.
- if (From->getType() != Context.OverloadTy)
- return 0;
-
- OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression;
// If we didn't actually find any template-ids, we're done.
- if (!OvlExpr->hasExplicitTemplateArgs())
+ if (!ovl->hasExplicitTemplateArgs())
return 0;
TemplateArgumentListInfo ExplicitTemplateArgs;
- OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
+ ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs);
// Look through all of the overloaded functions, searching for one
// whose type matches exactly.
FunctionDecl *Matched = 0;
- for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
- E = OvlExpr->decls_end(); I != E; ++I) {
+ for (UnresolvedSetIterator I = ovl->decls_begin(),
+ E = ovl->decls_end(); I != E; ++I) {
// C++0x [temp.arg.explicit]p3:
// [...] In contexts where deduction is done and fails, or in contexts
// where deduction is not done, if a template argument list is
@@ -7544,7 +7541,7 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
// function template specialization, which is added to the set of
// overloaded functions considered.
FunctionDecl *Specialization = 0;
- TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc());
+ TemplateDeductionInfo Info(Context, ovl->getNameLoc());
if (TemplateDeductionResult Result
= DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs,
Specialization, Info)) {
@@ -7553,21 +7550,20 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
continue;
}
+ assert(Specialization && "no specialization and no error?");
+
// Multiple matches; we can't resolve to a single declaration.
if (Matched) {
- if (FoundResult)
- *FoundResult = DeclAccessPair();
-
if (Complain) {
- Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous)
- << OvlExpr->getName();
- NoteAllOverloadCandidates(OvlExpr);
+ Diag(ovl->getExprLoc(), diag::err_addr_ovl_ambiguous)
+ << ovl->getName();
+ NoteAllOverloadCandidates(ovl);
}
return 0;
- }
+ }
- if ((Matched = Specialization) && FoundResult)
- *FoundResult = I.getPair();
+ Matched = Specialization;
+ if (FoundResult) *FoundResult = I.getPair();
}
return Matched;
@@ -7581,39 +7577,65 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From,
// template specialization
// Last three arguments should only be supplied if Complain = true
ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization(
- Expr *SrcExpr, bool DoFunctionPointerConverion, bool Complain,
+ Expr *SrcExpr, bool doFunctionPointerConverion, bool complain,
const SourceRange& OpRangeForComplaining,
QualType DestTypeForComplaining,
- unsigned DiagIDForComplaining ) {
+ unsigned DiagIDForComplaining) {
+ assert(SrcExpr->getType() == Context.OverloadTy);
- assert(SrcExpr->getType() == Context.OverloadTy);
+ OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr);
- DeclAccessPair Found;
- ExprResult SingleFunctionExpression;
- if (FunctionDecl* Fn = ResolveSingleFunctionTemplateSpecialization(
- SrcExpr, false, // false -> Complain
- &Found)) {
- if (!DiagnoseUseOfDecl(Fn, SrcExpr->getSourceRange().getBegin())) {
- // mark the expression as resolved to Fn
- SingleFunctionExpression = Owned(FixOverloadedFunctionReference(SrcExpr,
- Found, Fn));
- if (DoFunctionPointerConverion)
- SingleFunctionExpression =
- DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
- }
- }
- if (!SingleFunctionExpression.isUsable()) {
- if (Complain) {
- OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
- Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
- << oe->getName() << DestTypeForComplaining << OpRangeForComplaining
- << oe->getQualifierLoc().getSourceRange();
- NoteAllOverloadCandidates(SrcExpr);
- }
+ DeclAccessPair found;
+ ExprResult SingleFunctionExpression;
+ if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization(
+ ovl.Expression, /*complain*/ false, &found)) {
+ if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin()))
+ return ExprError();
+
+ // It is only correct to resolve to an instance method if we're
+ // resolving a form that's permitted to be a pointer to member.
+ // Otherwise we'll end up making a bound member expression, which
+ // is illegal in all the contexts we resolve like this.
+ if (!ovl.HasFormOfMemberPointer &&
+ isa<CXXMethodDecl>(fn) &&
+ cast<CXXMethodDecl>(fn)->isInstance()) {
+ if (complain) {
+ Diag(ovl.Expression->getExprLoc(),
+ diag::err_invalid_use_of_bound_member_func)
+ << ovl.Expression->getSourceRange();
+ // TODO: I believe we only end up here if there's a mix of
+ // static and non-static candidates (otherwise the expression
+ // would have 'bound member' type, not 'overload' type).
+ // Ideally we would note which candidate was chosen and why
+ // the static candidates were rejected.
+ }
+
return ExprError();
}
- return SingleFunctionExpression;
+ // Fix the expresion to refer to 'fn'.
+ SingleFunctionExpression =
+ Owned(FixOverloadedFunctionReference(SrcExpr, found, fn));
+
+ // If desired, do function-to-pointer decay.
+ if (doFunctionPointerConverion)
+ SingleFunctionExpression =
+ DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take());
+ }
+
+ if (!SingleFunctionExpression.isUsable()) {
+ if (complain) {
+ Diag(OpRangeForComplaining.getBegin(), DiagIDForComplaining)
+ << ovl.Expression->getName()
+ << DestTypeForComplaining
+ << OpRangeForComplaining
+ << ovl.Expression->getQualifierLoc().getSourceRange();
+ NoteAllOverloadCandidates(SrcExpr);
+ }
+ return ExprError();
+ }
+
+ return SingleFunctionExpression;
}
/// \brief Add a single candidate to the overload set.
@@ -8499,16 +8521,66 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
/// function (and includes the object parameter), Args/NumArgs are the
/// arguments to the function call (not including the object
/// parameter). The caller needs to validate that the member
-/// expression refers to a member function or an overloaded member
-/// function.
+/// expression refers to a non-static member function or an overloaded
+/// member function.
ExprResult
Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
SourceLocation LParenLoc, Expr **Args,
unsigned NumArgs, SourceLocation RParenLoc) {
+ assert(MemExprE->getType() == Context.BoundMemberTy ||
+ MemExprE->getType() == Context.OverloadTy);
+
// Dig out the member expression. This holds both the object
// argument and the member function we're referring to.
Expr *NakedMemExpr = MemExprE->IgnoreParens();
+ // Determine whether this is a call to a pointer-to-member function.
+ if (BinaryOperator *op = dyn_cast<BinaryOperator>(NakedMemExpr)) {
+ assert(op->getType() == Context.BoundMemberTy);
+ assert(op->getOpcode() == BO_PtrMemD || op->getOpcode() == BO_PtrMemI);
+
+ QualType fnType =
+ op->getRHS()->getType()->castAs<MemberPointerType>()->getPointeeType();
+
+ const FunctionProtoType *proto = fnType->castAs<FunctionProtoType>();
+ QualType resultType = proto->getCallResultType(Context);
+ ExprValueKind valueKind = Expr::getValueKindForType(proto->getResultType());
+
+ // Check that the object type isn't more qualified than the
+ // member function we're calling.
+ Qualifiers funcQuals = Qualifiers::fromCVRMask(proto->getTypeQuals());
+
+ QualType objectType = op->getLHS()->getType();
+ if (op->getOpcode() == BO_PtrMemI)
+ objectType = objectType->castAs<PointerType>()->getPointeeType();
+ Qualifiers objectQuals = objectType.getQualifiers();
+
+ Qualifiers difference = objectQuals - funcQuals;
+ difference.removeObjCGCAttr();
+ difference.removeAddressSpace();
+ if (difference) {
+ std::string qualsString = difference.getAsString();
+ Diag(LParenLoc, diag::err_pointer_to_member_call_drops_quals)
+ << fnType.getUnqualifiedType()
+ << qualsString
+ << (qualsString.find(' ') == std::string::npos ? 1 : 2);
+ }
+
+ CXXMemberCallExpr *call
+ = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs,
+ resultType, valueKind, RParenLoc);
+
+ if (CheckCallReturnType(proto->getResultType(),
+ op->getRHS()->getSourceRange().getBegin(),
+ call, 0))
+ return ExprError();
+
+ if (ConvertArgumentsForCall(call, op, 0, proto, Args, NumArgs, RParenLoc))
+ return ExprError();
+
+ return MaybeBindToTemporary(call);
+ }
+
MemberExpr *MemExpr;
CXXMethodDecl *Method = 0;
DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index e6609c08e21..5e21a367588 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -77,12 +77,6 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S) {
if (!E)
return;
- if (E->isBoundMemberFunction(Context)) {
- Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func)
- << E->getSourceRange();
- return;
- }
-
SourceLocation Loc;
SourceRange R1, R2;
if (!E->isUnusedResultAWarning(Loc, R1, R2, Context))
OpenPOWER on IntegriCloud