[cfe-commits] r64955 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/Basic/DiagnosticSemaKinds.def lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaDeclObjC.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaExprObjC.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp test/Sema/overloadable.c test/SemaCXX/attr-unavailable.cpp test/SemaObjC/protocol-atttribute-1.m

Douglas Gregor dgregor at apple.com
Wed Feb 18 13:56:38 PST 2009


Author: dgregor
Date: Wed Feb 18 15:56:37 2009
New Revision: 64955

URL: http://llvm.org/viewvc/llvm-project?rev=64955&view=rev
Log:
Downgrade complaints about calling unavailable functions to a warning
(as GCC does), except when we've performed overload resolution and
found an unavailable function: in this case, we actually error.

Merge the checking of unavailable functions with the checking for
deprecated functions. This unifies a bit of code, and makes sure that
we're checking for unavailable functions in the right places. Also,
this check can cause an error. We may, eventually, want an option to
make "unavailable" warnings into errors.

Implement much of the logic needed for C++0x deleted functions, which
are effectively the same as "unavailable" functions (but always cause
an error when referenced). However, we don't have the syntax to
specify deleted functions yet :)


Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclObjC.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/Sema/overloadable.c
    cfe/trunk/test/SemaCXX/attr-unavailable.cpp
    cfe/trunk/test/SemaObjC/protocol-atttribute-1.m

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Wed Feb 18 15:56:37 2009
@@ -536,6 +536,7 @@
   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 @@
       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 @@
   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 {

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Wed Feb 18 15:56:37 2009
@@ -465,24 +465,37 @@
      "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 @@
      "%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 @@
      "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")

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb 18 15:56:37 2009
@@ -438,7 +438,8 @@
   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 @@
   //===--------------------------------------------------------------------===//
   // 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,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 18 15:56:37 2009
@@ -64,15 +64,15 @@
 
   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 @@
     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 @@
     }
 
     MergeAttributes(New, Old);
+
+    // Merge the "deleted" flag.
+    if (Old->isDeleted())
+      New->setDeleted();
     
     return false;
   }
@@ -3125,8 +3134,8 @@
   }
 
   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

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Feb 18 15:56:37 2009
@@ -1650,6 +1650,18 @@
       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 @@
     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 @@
       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;
     }
   }

Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Wed Feb 18 15:56:37 2009
@@ -111,7 +111,7 @@
 
     // 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 @@
       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 @@
   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;

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb 18 15:56:37 2009
@@ -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 @@
       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 @@
       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 @@
     }
   }
 
-  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 @@
                                   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 @@
           << 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 @@
           << 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 @@
     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 @@
       // 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 @@
 
     // 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 @@
     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 @@
       }
     }
     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 @@
         }
       }
 
-      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 @@
     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 @@
       // 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 @@
                                                                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 @@
           << 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 @@
           << 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

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 18 15:56:37 2009
@@ -473,6 +473,13 @@
       << 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 @@
     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;

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Wed Feb 18 15:56:37 2009
@@ -288,8 +288,8 @@
   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 @@
           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 @@
               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 @@
       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();

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Feb 18 15:56:37 2009
@@ -1409,6 +1409,7 @@
       }
       
     case OR_No_Viable_Function:
+    case OR_Deleted:
       // No conversion here! We're done.
       return false;
 
@@ -3426,6 +3427,14 @@
   }
   
   // 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 @@
   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 @@
       << 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 @@
       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 @@
       << 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 @@
       << "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.

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Feb 18 15:56:37 2009
@@ -1174,6 +1174,9 @@
       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()) {

Modified: cfe/trunk/test/Sema/overloadable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/overloadable.c?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/test/Sema/overloadable.c (original)
+++ cfe/trunk/test/Sema/overloadable.c Wed Feb 18 15:56:37 2009
@@ -43,11 +43,11 @@
 
 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'}}
 }
 
 

Modified: cfe/trunk/test/SemaCXX/attr-unavailable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-unavailable.cpp?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/attr-unavailable.cpp (original)
+++ cfe/trunk/test/SemaCXX/attr-unavailable.cpp Wed Feb 18 15:56:37 2009
@@ -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}}
 
 void test_foo(short* sp) {
   int &ir = foo(1);
   double &dr = foo(1.0);
-  foo(sp); // expected-error{{call to function 'foo' that has been intentionally made unavailable}}
+  foo(sp); // expected-error{{call to unavailable function 'foo'}}
+
+  void (*fp)(...) = &bar; // expected-warning{{'bar' is unavailable}}
+  void (*fp2)(...) = bar; // expected-warning{{'bar' is unavailable}}
+
+  int &(*fp3)(int) = foo;
+  void (*fp4)(...) = foo; // expected-warning{{'foo' is unavailable}}
 }

Modified: cfe/trunk/test/SemaObjC/protocol-atttribute-1.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocol-atttribute-1.m?rev=64955&r1=64954&r2=64955&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/protocol-atttribute-1.m (original)
+++ cfe/trunk/test/SemaObjC/protocol-atttribute-1.m Wed Feb 18 15:56:37 2009
@@ -1,7 +1,7 @@
 // RUN: clang -fsyntax-only -verify %s
 
 __attribute ((unavailable))
- at protocol FwProto;
+ at protocol FwProto; // expected-note{{marked unavailable}}
 
 Class <FwProto> cFw = 0;  // expected-warning {{'FwProto' is unavailable}}
 
@@ -33,12 +33,12 @@
 
 Class <MyProto1> clsP1 = 0;  // expected-warning {{'MyProto1' is deprecated}}
 
- at protocol FwProto @end
+ at protocol FwProto @end // expected-note{{marked unavailable}}
 
 @interface MyClass2 <FwProto> // expected-warning {{'FwProto' is unavailable}}
 @end
 
-__attribute ((unavailable)) __attribute ((deprecated)) @protocol XProto;
+__attribute ((unavailable)) __attribute ((deprecated)) @protocol XProto; // expected-note{{marked unavailable}}
 
 id <XProto> idX = 0; // expected-warning {{'XProto' is unavailable}} expected-warning {{'XProto' is deprecated}}
 





More information about the cfe-commits mailing list