diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaCXXCast.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 136 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 176 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 6 |
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)) |