diff options
-rw-r--r-- | include/clang/AST/Decl.h | 24 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.def | 21 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 144 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 16 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 53 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 3 | ||||
-rw-r--r-- | test/Sema/overloadable.c | 4 | ||||
-rw-r--r-- | test/SemaCXX/attr-unavailable.cpp | 13 | ||||
-rw-r--r-- | test/SemaObjC/protocol-atttribute-1.m | 6 |
14 files changed, 275 insertions, 91 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 18a56cf892..200ada2243 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -536,6 +536,7 @@ private: bool IsVirtual : 1; bool IsPure : 1; bool InheritedPrototype : 1; + bool IsDeleted : 1; // Move to DeclGroup when it is implemented. SourceLocation TypeSpecStartLoc; @@ -548,7 +549,7 @@ protected: DeclContext(DK), ParamInfo(0), Body(0), PreviousDeclaration(0), SClass(S), IsInline(isInline), IsVirtual(false), IsPure(false), - InheritedPrototype(false), TypeSpecStartLoc(TSSL) {} + InheritedPrototype(false), IsDeleted(false), TypeSpecStartLoc(TSSL) {} virtual ~FunctionDecl() {} virtual void Destroy(ASTContext& C); @@ -596,6 +597,27 @@ public: bool inheritedPrototype() { return InheritedPrototype; } void setInheritedPrototype() { InheritedPrototype = true; } + /// \brief Whether this function has been deleted. + /// + /// A function that is "deleted" (via the C++0x "= delete" syntax) + /// acts like a normal function, except that it cannot actually be + /// called or have its address taken. Deleted functions are + /// typically used in C++ overload resolution to attract arguments + /// whose type or lvalue/rvalue-ness would permit the use of a + /// different overload that would behave incorrectly. For example, + /// one might use deleted functions to ban implicit conversion from + /// a floating-point number to an Integer type: + /// + /// @code + /// struct Integer { + /// Integer(long); // construct from a long + /// Integer(double) = delete; // no construction from float or double + /// Integer(long double) = delete; // no construction from long double + /// }; + /// @endcode + bool isDeleted() const { return IsDeleted; } + void setDeleted() { IsDeleted = true; } + /// getPreviousDeclaration - Return the previous declaration of this /// function. const FunctionDecl *getPreviousDeclaration() const { diff --git a/include/clang/Basic/DiagnosticSemaKinds.def b/include/clang/Basic/DiagnosticSemaKinds.def index a283b73ab7..1f67e09a9c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.def +++ b/include/clang/Basic/DiagnosticSemaKinds.def @@ -465,24 +465,37 @@ DIAG(err_ovl_no_viable_member_function_in_call, ERROR, "no matching member function for call to %0") DIAG(err_ovl_ambiguous_call, ERROR, "call to %0 is ambiguous") +DIAG(err_ovl_deleted_call, ERROR, + "call to %select{unavailable|deleted}0 function %1") DIAG(err_ovl_ambiguous_member_call, ERROR, "call to member function %0 is ambiguous") +DIAG(err_ovl_deleted_member_call, ERROR, + "call to %select{unavailable|deleted}0 member function %1") DIAG(err_ovl_candidate, NOTE, "candidate function") +DIAG(err_ovl_candidate_deleted, NOTE, + "candidate function has been explicitly %select{made unavailable|deleted}0") DIAG(err_ovl_builtin_candidate, NOTE, "built-in candidate function %0") DIAG(err_ovl_no_viable_function_in_init, ERROR, "no matching constructor for initialization of %0") DIAG(err_ovl_ambiguous_init, ERROR, "call to constructor of %0 is ambiguous") +DIAG(err_ovl_deleted_init, ERROR, + "call to %select{unavailable|deleted}0 constructor of %1") DIAG(err_ovl_ambiguous_oper, ERROR, "use of overloaded operator '%0' is ambiguous") DIAG(err_ovl_no_viable_oper, ERROR, "no viable overloaded '%0'") +DIAG(err_ovl_deleted_oper, ERROR, + "overload resolution selected %select{unavailable|deleted}0 operator '%1'") + DIAG(err_ovl_no_viable_object_call, ERROR, "no matching function for call to object of type %0") DIAG(err_ovl_ambiguous_object_call, ERROR, "call to object of type %0 is ambiguous") +DIAG(err_ovl_deleted_object_call, ERROR, + "call to %select{unavailable|deleted}0 function call operator in type %1") DIAG(err_ovl_surrogate_cand, NOTE, "conversion candidate of type %0") DIAG(err_member_call_without_object, ERROR, @@ -599,6 +612,8 @@ DIAG(warn_deprecated, WARNING, "%0 is deprecated") DIAG(warn_unavailable, WARNING, "%0 is unavailable") +DIAG(note_unavailable_here, NOTE, + "function has been explicitly marked %select{unavailable|deleted}0 here") DIAG(err_redefinition, ERROR, "redefinition of %0") DIAG(err_static_non_static, ERROR, @@ -1056,10 +1071,8 @@ DIAG(err_typecheck_call_too_few_args, ERROR, "too few arguments to %select{function|block|method}0 call") DIAG(err_typecheck_call_too_many_args, ERROR, "too many arguments to %select{function|block|method}0 call") -DIAG(err_call_deleted_function, ERROR, - "call to function %1 that has been intentionally %select{deleted|made unavailable}0 ") -DIAG(note_deleted_function_here, NOTE, - "%select{deleted|unavailable}0 function is declared here") +DIAG(err_deleted_function_use, ERROR, + "attempt to use a deleted function") DIAG(warn_cannot_pass_non_pod_arg_to_vararg, WARNING, "cannot pass object of non-POD type %0 through variadic " "%select{function|block|method}1; call will abort at runtime") diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 4358051cc5..39d049bd29 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -438,7 +438,8 @@ public: enum OverloadingResult { OR_Success, ///< Overload resolution succeeded. OR_No_Viable_Function, ///< No viable function found. - OR_Ambiguous ///< Ambiguous candidates found. + OR_Ambiguous, ///< Ambiguous candidates found. + OR_Deleted ///< Overload resoltuion refers to a deleted function. }; void AddOverloadCandidate(FunctionDecl *Function, @@ -1022,15 +1023,8 @@ public: //===--------------------------------------------------------------------===// // Expression Parsing Callbacks: SemaExpr.cpp. - /// DiagnoseUseOfDeprecatedDecl - If the specified decl is deprecated or - // unavailable, emit the corresponding diagnostics. - inline void DiagnoseUseOfDeprecatedDecl(NamedDecl *D, SourceLocation Loc) { - if (D->hasAttrs()) - DiagnoseUseOfDeprecatedDeclImpl(D, Loc); - } - void DiagnoseUseOfDeprecatedDeclImpl(NamedDecl *D, SourceLocation Loc); + bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc); - // Primary Expressions. virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc, IdentifierInfo &II, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 661124c579..a276f3c1ce 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -64,15 +64,15 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, if (IIDecl) { if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) { - // If this typename is deprecated, emit a warning. - DiagnoseUseOfDeprecatedDecl(IIDecl, NameLoc); + // Check whether we can use this type + (void)DiagnoseUseOfDecl(IIDecl, NameLoc); return Context.getTypeDeclType(TD).getAsOpaquePtr(); } if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) { - // If this typename is deprecated, emit a warning. - DiagnoseUseOfDeprecatedDecl(IIDecl, NameLoc); + // Check whether we can use this interface. + (void)DiagnoseUseOfDecl(IIDecl, NameLoc); return Context.getObjCInterfaceType(IDecl).getAsOpaquePtr(); } @@ -591,6 +591,11 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { if (OldQType == NewQType) { // We have a redeclaration. MergeAttributes(New, Old); + + // Merge the "deleted" flag. + if (Old->isDeleted()) + New->setDeleted(); + return MergeCXXFunctionDecl(New, Old); } @@ -635,6 +640,10 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { } MergeAttributes(New, Old); + + // Merge the "deleted" flag. + if (Old->isDeleted()) + New->setDeleted(); return false; } @@ -3125,8 +3134,8 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, } if (PrevDecl) { - // If the previous declaration was deprecated, emit a warning. - DiagnoseUseOfDeprecatedDecl(PrevDecl, NameLoc); + // Check whether the previous declaration is usable. + (void)DiagnoseUseOfDecl(PrevDecl, NameLoc); if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) { // If this is a use of a previous tag, or if the tag is already declared diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 9d2e06df85..8dd409bd21 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1650,6 +1650,18 @@ Sema::PerformInitializationByConstructor(QualType ClassType, Diag(Loc, diag::err_ovl_ambiguous_init) << ClassType << Range; PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return 0; + + case OR_Deleted: + if (InitEntity) + Diag(Loc, diag::err_ovl_deleted_init) + << Best->Function->isDeleted() + << InitEntity << Range; + else + Diag(Loc, diag::err_ovl_deleted_init) + << Best->Function->isDeleted() + << InitEntity << Range; + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + return 0; } return 0; @@ -1736,8 +1748,12 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType, if (Fn) { // Since we're performing this reference-initialization for // real, update the initializer with the resulting function. - if (!ICS) + if (!ICS) { + if (DiagnoseUseOfDecl(Fn, Init->getSourceRange().getBegin())) + return true; + FixOverloadedFunctionReference(Init, Fn); + } T2 = Fn->getType(); } @@ -1864,7 +1880,9 @@ Sema::CheckReferenceInit(Expr *&Init, QualType &DeclType, return true; case OR_No_Viable_Function: - // There was no suitable conversion; continue with other checks. + case OR_Deleted: + // There was no suitable conversion, or we found a deleted + // conversion; continue with other checks. break; } } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index dee352b79b..b890637767 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -111,7 +111,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, // Diagnose classes that inherit from deprecated classes. if (SuperClassDecl) - DiagnoseUseOfDeprecatedDecl(SuperClassDecl, SuperLoc); + (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); if (PrevDecl && SuperClassDecl == 0) { // The previous declaration was not a class decl. Check if we have a @@ -270,7 +270,7 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, continue; } - DiagnoseUseOfDeprecatedDecl(PDecl, ProtocolId[i].second); + (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second); // If this is a forward declaration and we are supposed to warn in this // case, do it. @@ -493,7 +493,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, CDecl->setClassInterface(IDecl); // If the interface is deprecated, warn about it. - DiagnoseUseOfDeprecatedDecl(IDecl, ClassLoc); + (void)DiagnoseUseOfDecl(IDecl, ClassLoc); /// Check for duplicate interface declaration for this category ObjCCategoryDecl *CDeclChain; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index b2df86abe6..dd490ec51f 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -26,14 +26,23 @@ #include "clang/Parse/Scope.h" using namespace clang; - -/// DiagnoseUseOfDeprecatedDeclImpl - If the specified decl is deprecated or -// unavailable, emit the corresponding diagnostics. -void Sema::DiagnoseUseOfDeprecatedDeclImpl(NamedDecl *D, SourceLocation Loc) { +/// \brief Determine whether the use of this declaration is valid, and +/// emit any corresponding diagnostics. +/// +/// This routine diagnoses various problems with referencing +/// declarations that can occur when using a declaration. For example, +/// it might warn if a deprecated or unavailable declaration is being +/// used, or produce an error (and return true) if a C++0x deleted +/// function is being used. +/// +/// \returns true if there was an error (this declaration cannot be +/// referenced), false otherwise. +bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // See if the decl is deprecated. if (D->getAttr<DeprecatedAttr>()) { - // Implementing deprecated stuff requires referencing depreated stuff. Don't - // warn if we are implementing a deprecated construct. + // Implementing deprecated stuff requires referencing deprecated + // stuff. Don't warn if we are implementing a deprecated + // construct. bool isSilenced = false; if (NamedDecl *ND = getCurFunctionOrMethodDecl()) { @@ -60,9 +69,22 @@ void Sema::DiagnoseUseOfDeprecatedDeclImpl(NamedDecl *D, SourceLocation Loc) { Diag(Loc, diag::warn_deprecated) << D->getDeclName(); } - // See if hte decl is unavailable. - if (D->getAttr<UnavailableAttr>()) + // See if this is a deleted function. + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (FD->isDeleted()) { + Diag(Loc, diag::err_deleted_function_use); + Diag(D->getLocation(), diag::note_unavailable_here) << true; + return true; + } + + // See if the decl is unavailable + if (D->getAttr<UnavailableAttr>()) { Diag(Loc, diag::warn_unavailable) << D->getDeclName(); + Diag(D->getLocation(), diag::note_unavailable_here) << 0; + } + + + return false; } //===----------------------------------------------------------------------===// @@ -607,7 +629,8 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II)) { // Check if referencing a field with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(IV, Loc); + if (DiagnoseUseOfDecl(IV, Loc)) + return ExprError(); // FIXME: This should use a new expr for a direct reference, don't turn // this into Self->ivar, just return a BareIVarExpr or something. @@ -628,8 +651,12 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, } } - if (getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && - HasTrailingLParen && D == 0) { + // Determine whether this name might be a candidate for + // argument-dependent lookup. + bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && + HasTrailingLParen; + + if (ADL && D == 0) { // We've seen something of the form // // identifier( @@ -791,9 +818,13 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, false, false, SS)); ValueDecl *VD = cast<ValueDecl>(D); - // Check if referencing an identifier with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(VD, Loc); - + // Check whether this declaration can be used. Note that we suppress + // this check when we're going to perform argument-dependent lookup + // on this function name, because this might not be the function + // that overload resolution actually selects. + if (!(ADL && isa<FunctionDecl>(VD)) && DiagnoseUseOfDecl(VD, Loc)) + return ExprError(); + if (VarDecl *Var = dyn_cast<VarDecl>(VD)) { // Warn about constructs like: // if (void *X = foo()) { ... } else { X }. @@ -1296,6 +1327,14 @@ Sema::ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, << Arg->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return ExprError(); + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << UnaryOperator::getOpcodeStr(Opc) + << Arg->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + return ExprError(); } // Either we found no viable overloaded operator or we matched a @@ -1398,6 +1437,14 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc, << LHSExp->getSourceRange() << RHSExp->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return ExprError(); + + case OR_Deleted: + Diag(LLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << "[]" + << LHSExp->getSourceRange() << RHSExp->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + return ExprError(); } // Either we found no viable overloaded operator or we matched a @@ -1621,8 +1668,9 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (MemberDecl->isInvalidDecl()) return ExprError(); - // Check if referencing a field with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(MemberDecl, MemberLoc); + // Check the use of this field + if (DiagnoseUseOfDecl(MemberDecl, MemberLoc)) + return ExprError(); if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { // We may have found a field within an anonymous union or struct @@ -1681,9 +1729,10 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // error cases. if (IV->isInvalidDecl()) return ExprError(); - - // Check if referencing a field with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(IV, MemberLoc); + + // Check whether we can reference this field. + if (DiagnoseUseOfDecl(IV, MemberLoc)) + return ExprError(); ObjCIvarRefExpr *MRef= new (Context) ObjCIvarRefExpr(IV, IV->getType(), MemberLoc, BaseExpr, @@ -1706,8 +1755,9 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // Search for a declared property first. if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(&Member)) { - // Check if referencing a property with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(PD, MemberLoc); + // Check whether we can reference this property. + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr)); @@ -1717,8 +1767,9 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, for (ObjCInterfaceType::qual_iterator I = IFTy->qual_begin(), E = IFTy->qual_end(); I != E; ++I) if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) { - // Check if referencing a property with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(PD, MemberLoc); + // Check whether we can reference this property. + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr)); @@ -1749,8 +1800,9 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, } } if (Getter) { - // Check if referencing a property with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(Getter, MemberLoc); + // Check if we can reference this property. + if (DiagnoseUseOfDecl(Getter, MemberLoc)) + return ExprError(); // If we found a getter then this may be a valid dot-reference, we // will look for the matching setter, in case it is needed. @@ -1775,10 +1827,8 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, } } - if (Setter) - // Check if referencing a property with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(Setter, MemberLoc); - + if (Setter && DiagnoseUseOfDecl(Setter, MemberLoc)) + return ExprError(); // FIXME: we must check that the setter has property type. return Owned(new (Context) ObjCKVCRefExpr(Getter, Getter->getResultType(), @@ -1795,8 +1845,9 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, for (ObjCQualifiedIdType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) { - // Check if referencing a property with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(PD, MemberLoc); + // Check the use of this declaration + if (DiagnoseUseOfDecl(PD, MemberLoc)) + return ExprError(); return Owned(new (Context) ObjCPropertyRefExpr(PD, PD->getType(), MemberLoc, BaseExpr)); @@ -1804,8 +1855,9 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // Also must look for a getter name which uses property syntax. Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) { - // Check if referencing a property with __attribute__((deprecated)). - DiagnoseUseOfDeprecatedDecl(OMD, MemberLoc); + // Check the use of this method. + if (DiagnoseUseOfDecl(OMD, MemberLoc)) + return ExprError(); return Owned(new (Context) ObjCMessageExpr(BaseExpr, Sel, OMD->getResultType(), OMD, OpLoc, MemberLoc, NULL, 0)); @@ -2033,16 +2085,6 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, Context.BoolTy, RParenLoc)); - // Check for a call to a (FIXME: deleted) or unavailable function. - if (FDecl && FDecl->getAttr<UnavailableAttr>()) { - Diag(Fn->getSourceRange().getBegin(), diag::err_call_deleted_function) - << FDecl->getAttr<UnavailableAttr>() << FDecl->getDeclName() - << Fn->getSourceRange(); - Diag(FDecl->getLocation(), diag::note_deleted_function_here) - << FDecl->getAttr<UnavailableAttr>(); - return ExprError(); - } - const FunctionType *FuncT; if (!Fn->getType()->isBlockPointerType()) { // C99 6.5.2.2p1 - "The expression that denotes the called function shall @@ -3912,6 +3954,14 @@ Action::OwningExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc, << lhs->getSourceRange() << rhs->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return ExprError(); + + case OR_Deleted: + Diag(TokLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << BinaryOperator::getOpcodeStr(Opc) + << lhs->getSourceRange() << rhs->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + return ExprError(); } // Either we found no viable overloaded operator or we matched a @@ -4012,6 +4062,14 @@ Action::OwningExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, << Input->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return ExprError(); + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << UnaryOperator::getOpcodeStr(Opc) + << Input->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + return ExprError(); } // Either we found no viable overloaded operator or we matched a diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index d5d2b08130..ea59b644c9 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -473,6 +473,13 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, << Name << Range; PrintOverloadCandidates(Candidates, /*OnlyViable=*/true); return true; + + case OR_Deleted: + Diag(StartLoc, diag::err_ovl_deleted_call) + << Best->Function->isDeleted() + << Name << Range; + PrintOverloadCandidates(Candidates, /*OnlyViable=*/true); + return true; } assert(false && "Unreachable, bad result from BestViableFunction"); return true; @@ -775,20 +782,22 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; case ICK_Array_To_Pointer: + FromType = Context.getArrayDecayedType(FromType); + ImpCastExprToType(From, FromType); + break; + + case ICK_Function_To_Pointer: if (FromType->isOverloadType()) { FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(From, ToType, true); if (!Fn) return true; + if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin())) + return true; + FixOverloadedFunctionReference(From, Fn); FromType = From->getType(); - } else { - FromType = Context.getArrayDecayedType(FromType); } - ImpCastExprToType(From, FromType); - break; - - case ICK_Function_To_Pointer: FromType = Context.getPointerType(FromType); ImpCastExprToType(From, FromType); break; diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index cbcfa056a2..25b41c64de 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -288,8 +288,8 @@ Sema::ExprResult Sema::ActOnClassMessage( if (!Method) Method = ClassDecl->lookupInstanceMethod(Sel); - if (Method) - DiagnoseUseOfDeprecatedDecl(Method, receiverLoc); + if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) + return true; if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, true, lbrac, rbrac, returnType)) @@ -336,8 +336,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, Method = SuperDecl->lookupInstanceMethod(Sel); } - if (Method) - DiagnoseUseOfDeprecatedDecl(Method, receiverLoc); + if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) + return true; if (CheckMessageArgumentTypes(ArgExprs, NumArgs, Sel, Method, false, lbrac, rbrac, returnType)) @@ -370,8 +370,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, ObjCImplementations[ClassDecl->getIdentifier()]) Method = ImpDecl->getClassMethod(Sel); - if (Method) - DiagnoseUseOfDeprecatedDecl(Method, receiverLoc); + if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) + return true; } if (!Method) Method = FactoryMethodPool[Sel].Method; @@ -423,8 +423,8 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, Diag(lbrac, diag::warn_method_not_found_in_protocol) << Sel << SourceRange(lbrac, rbrac); - if (Method) - DiagnoseUseOfDeprecatedDecl(Method, receiverLoc); + if (Method && DiagnoseUseOfDecl(Method, receiverLoc)) + return true; } else { Diag(lbrac, diag::error_bad_receiver_type) << RExpr->getType() << RExpr->getSourceRange(); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index ffb29795f5..f2c7de2fae 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1409,6 +1409,7 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType, } case OR_No_Viable_Function: + case OR_Deleted: // No conversion here! We're done. return false; @@ -3426,6 +3427,14 @@ Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, } // Best is the best viable function. + if (Best->Function && + (Best->Function->isDeleted() || + Best->Function->getAttr<UnavailableAttr>())) + return OR_Deleted; + + // If Best refers to a function that is either deleted (C++0x) or + // unavailable (Clang extension) report an error. + return OR_Success; } @@ -3441,8 +3450,16 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, for (; Cand != LastCand; ++Cand) { if (Cand->Viable || !OnlyViable) { if (Cand->Function) { - // Normal function - Diag(Cand->Function->getLocation(), diag::err_ovl_candidate); + if (Cand->Function->isDeleted() || + Cand->Function->getAttr<UnavailableAttr>()) { + // Deleted or "unavailable" function. + Diag(Cand->Function->getLocation(), diag::err_ovl_candidate_deleted) + << Cand->Function->isDeleted(); + } else { + // Normal function + // FIXME: Give a better reason! + Diag(Cand->Function->getLocation(), diag::err_ovl_candidate); + } } else if (Cand->IsSurrogate) { // Desugar the type of the surrogate down to a function type, // retaining as many typedefs as possible while still showing @@ -3644,6 +3661,14 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, << UnqualifiedName << Fn->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; + + case OR_Deleted: + Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_deleted_call) + << Best->Function->isDeleted() + << UnqualifiedName + << Fn->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + break; } // Overload resolution failed. Destroy all of the subexpressions and @@ -3716,6 +3741,15 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); // FIXME: Leaking incoming expressions! return true; + + case OR_Deleted: + Diag(MemExpr->getSourceRange().getBegin(), + diag::err_ovl_deleted_member_call) + << Best->Function->isDeleted() + << Ovl->getDeclName() << MemExprE->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); + // FIXME: Leaking incoming expressions! + return true; } FixOverloadedFunctionReference(MemExpr, Method); @@ -3831,6 +3865,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, << Object->getType() << Object->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); break; + + case OR_Deleted: + Diag(Object->getSourceRange().getBegin(), + diag::err_ovl_deleted_object_call) + << Best->Function->isDeleted() + << Object->getType() << Object->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + break; } if (Best == CandidateSet.end()) { @@ -3990,6 +4032,13 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, << "operator->" << BasePtr->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); return true; + + case OR_Deleted: + Diag(OpLoc, diag::err_ovl_deleted_oper) + << Best->Function->isDeleted() + << "operator->" << BasePtr->getSourceRange(); + PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + return true; } // Convert the object parameter. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8b7d8fddc0..a47634ba69 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1174,6 +1174,9 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ImpCastExprToType(Arg, ArgType); } else if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) { + if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) + return true; + FixOverloadedFunctionReference(Arg, Fn); ArgType = Arg->getType(); if (ArgType->isFunctionType() && ParamType->isPointerType()) { diff --git a/test/Sema/overloadable.c b/test/Sema/overloadable.c index 22ced49b61..2072292966 100644 --- a/test/Sema/overloadable.c +++ b/test/Sema/overloadable.c @@ -43,11 +43,11 @@ long double promote(long double) __attribute__((__overloadable__)); void promote() __attribute__((__overloadable__)); // expected-error{{'overloadable' function 'promote' must have a prototype}} void promote(...) __attribute__((__overloadable__, __unavailable__)); // \ - // expected-note{{unavailable function is declared here}} + // expected-note{{candidate function}} void test_promote(short* sp) { promote(1.0); - promote(sp); // expected-error{{call to function 'promote' that has been intentionally made unavailable}} + promote(sp); // expected-error{{call to unavailable function 'promote'}} } diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp index 140008a4cb..78e348ae1f 100644 --- a/test/SemaCXX/attr-unavailable.cpp +++ b/test/SemaCXX/attr-unavailable.cpp @@ -2,10 +2,19 @@ int &foo(int); double &foo(double); -void foo(...) __attribute__((__unavailable__)); // expected-note{{unavailable function is declared here}} +void foo(...) __attribute__((__unavailable__)); // expected-note {{candidate function}} \ +// expected-note{{function has been explicitly marked unavailable here}} + +void bar(...) __attribute__((__unavailable__)); // expected-note 2{{explicitly marked unavailable}} |