aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h24
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.def21
-rw-r--r--lib/Sema/Sema.h12
-rw-r--r--lib/Sema/SemaDecl.cpp21
-rw-r--r--lib/Sema/SemaDeclCXX.cpp22
-rw-r--r--lib/Sema/SemaDeclObjC.cpp6
-rw-r--r--lib/Sema/SemaExpr.cpp144
-rw-r--r--lib/Sema/SemaExprCXX.cpp21
-rw-r--r--lib/Sema/SemaExprObjC.cpp16
-rw-r--r--lib/Sema/SemaOverload.cpp53
-rw-r--r--lib/Sema/SemaTemplate.cpp3
-rw-r--r--test/Sema/overloadable.c4
-rw-r--r--test/SemaCXX/attr-unavailable.cpp13
-rw-r--r--test/SemaObjC/protocol-atttribute-1.m6
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}}