[cfe-commits] r142219 - in /cfe/trunk: include/clang/Basic/ include/clang/Sema/ lib/Sema/ test/ARCMT/ test/CXX/over/over.over/ test/SemaCXX/ test/SemaObjC/ test/SemaObjCXX/

John McCall rjmccall at apple.com
Mon Oct 17 11:40:02 PDT 2011


Author: rjmccall
Date: Mon Oct 17 13:40:02 2011
New Revision: 142219

URL: http://llvm.org/viewvc/llvm-project?rev=142219&view=rev
Log:
Teach the ARC compiler to not require __bridge casts when
passing/receiving CF objects at +0 to/from Objective-C methods
or audited C functions.


Added:
    cfe/trunk/test/SemaObjCXX/arc-unbridged-cast.mm
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Initialization.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaCast.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/ARCMT/checking.m
    cfe/trunk/test/ARCMT/nonobjc-to-objc-cast-2.m
    cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
    cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp
    cfe/trunk/test/SemaCXX/member-pointer.cpp
    cfe/trunk/test/SemaCXX/overloaded-name.cpp
    cfe/trunk/test/SemaCXX/overloaded-operator.cpp
    cfe/trunk/test/SemaCXX/unknown-anytype.cpp
    cfe/trunk/test/SemaObjC/arc-type-conversion.m
    cfe/trunk/test/SemaObjC/arc-unbridged-cast.m
    cfe/trunk/test/SemaObjC/arc.m
    cfe/trunk/test/SemaObjCXX/arc-type-conversion.mm

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Oct 17 13:40:02 2011
@@ -3053,8 +3053,9 @@
   "%select{Objective-C|block|C}2 pointer type %3 cannot use %select{__bridge|"
   "__bridge_transfer|__bridge_retained}4">;
 def err_arc_cast_requires_bridge : Error<
-  "cast of %select{Objective-C|block|C}0 pointer type %1 to "
-  "%select{Objective-C|block|C}2 pointer type %3 requires a bridged cast">;
+  "%select{cast|implicit conversion}0 of %select{Objective-C|block|C}1 "
+  "pointer type %2 to %select{Objective-C|block|C}3 pointer type %4 "
+  "requires a bridged cast">;
 def note_arc_bridge : Note<
   "use __bridge to convert directly (no change in ownership)">;
 def note_arc_bridge_transfer : Note<

Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Mon Oct 17 13:40:02 2011
@@ -642,7 +642,10 @@
     /// \brief Initialization of an incomplete type.
     FK_Incomplete,
     /// \brief List initialization failed at some point.
-    FK_ListInitializationFailed
+    FK_ListInitializationFailed,
+    /// \brief Initializer has a placeholder type which cannot be
+    /// resolved by initialization.
+    FK_PlaceholderType
   };
   
 private:

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Oct 17 13:40:02 2011
@@ -5794,10 +5794,16 @@
                                         Expr *CastExpr,
                                         SourceLocation RParenLoc);
 
+  enum ARCConversionResult { ACR_okay, ACR_unbridged };
+
   /// \brief Checks for invalid conversions and casts between
   /// retainable pointers and other pointer kinds.
-  void CheckObjCARCConversion(SourceRange castRange, QualType castType, 
-                              Expr *&op, CheckedConversionKind CCK);
+  ARCConversionResult CheckObjCARCConversion(SourceRange castRange,
+                                             QualType castType, Expr *&op,
+                                             CheckedConversionKind CCK);
+
+  Expr *stripARCUnbridgedCast(Expr *e);
+  void diagnoseARCUnbridgedCast(Expr *e);
     
   bool CheckObjCARCUnavailableWeakConversion(QualType castType,
                                              QualType ExprType);

Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Mon Oct 17 13:40:02 2011
@@ -49,7 +49,7 @@
       : Self(S), SrcExpr(src), DestType(destType),
         ResultType(destType.getNonLValueExprType(S.Context)),
         ValueKind(Expr::getValueKindForType(destType)),
-        Kind(CK_Dependent) {
+        Kind(CK_Dependent), IsARCUnbridgedCast(false) {
 
       if (const BuiltinType *placeholder =
             src.get()->getType()->getAsPlaceholderType()) {
@@ -67,6 +67,7 @@
     CastKind Kind;
     BuiltinType::Kind PlaceholderKind;
     CXXCastPath BasePath;
+    bool IsARCUnbridgedCast;
 
     SourceRange OpRange;
     SourceRange DestRange;
@@ -79,6 +80,20 @@
     void CheckCXXCStyleCast(bool FunctionalCast);
     void CheckCStyleCast();
 
+    /// Complete an apparently-successful cast operation that yields
+    /// the given expression.
+    ExprResult complete(CastExpr *castExpr) {
+      // If this is an unbridged cast, wrap the result in an implicit
+      // cast that yields the unbridged-cast placeholder type.
+      if (IsARCUnbridgedCast) {
+        castExpr = ImplicitCastExpr::Create(Self.Context,
+                                            Self.Context.ARCUnbridgedCastTy,
+                                            CK_Dependent, castExpr, 0,
+                                            castExpr->getValueKind());
+      }
+      return Self.Owned(castExpr);
+    }
+
     // Internal convenience methods.
 
     /// Try to handle the given placeholder expression kind.  Return
@@ -103,8 +118,12 @@
     }
 
     void checkObjCARCConversion(Sema::CheckedConversionKind CCK) {
+      assert(Self.getLangOptions().ObjCAutoRefCount);
+
       Expr *src = SrcExpr.get();
-      Self.CheckObjCARCConversion(OpRange, DestType, src, CCK);
+      if (Self.CheckObjCARCConversion(OpRange, DestType, src, CCK) ==
+            Sema::ACR_unbridged)
+        IsARCUnbridgedCast = true;
       SrcExpr = src;
     }
 
@@ -237,9 +256,9 @@
       if (Op.SrcExpr.isInvalid())
         return ExprError();
     }
-    return Owned(CXXConstCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
-                                          Op.SrcExpr.take(), DestTInfo, OpLoc,
-                                          Parens.getEnd()));
+    return Op.complete(CXXConstCastExpr::Create(Context, Op.ResultType,
+                                  Op.ValueKind, Op.SrcExpr.take(), DestTInfo,
+                                                OpLoc, Parens.getEnd()));
 
   case tok::kw_dynamic_cast: {
     if (!TypeDependent) {
@@ -247,10 +266,10 @@
       if (Op.SrcExpr.isInvalid())
         return ExprError();
     }
-    return Owned(CXXDynamicCastExpr::Create(Context, Op.ResultType,
-                                            Op.ValueKind, Op.Kind,
-                                            Op.SrcExpr.take(), &Op.BasePath,
-                                            DestTInfo, OpLoc, Parens.getEnd()));
+    return Op.complete(CXXDynamicCastExpr::Create(Context, Op.ResultType,
+                                    Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+                                                  &Op.BasePath, DestTInfo,
+                                                  OpLoc, Parens.getEnd()));
   }
   case tok::kw_reinterpret_cast: {
     if (!TypeDependent) {
@@ -258,11 +277,10 @@
       if (Op.SrcExpr.isInvalid())
         return ExprError();
     }
-    return Owned(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
-                                                Op.ValueKind, Op.Kind,
-                                                Op.SrcExpr.take(), 0,
-                                                DestTInfo, OpLoc,
-                                                Parens.getEnd()));
+    return Op.complete(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
+                                    Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+                                                      0, DestTInfo, OpLoc,
+                                                      Parens.getEnd()));
   }
   case tok::kw_static_cast: {
     if (!TypeDependent) {
@@ -271,10 +289,10 @@
         return ExprError();
     }
     
-    return Owned(CXXStaticCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
-                                           Op.Kind, Op.SrcExpr.take(),
-                                           &Op.BasePath, DestTInfo, OpLoc,
-                                           Parens.getEnd()));
+    return Op.complete(CXXStaticCastExpr::Create(Context, Op.ResultType,
+                                   Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+                                                 &Op.BasePath, DestTInfo,
+                                                 OpLoc, Parens.getEnd()));
   }
   }
 
@@ -1841,24 +1859,13 @@
 void CastOperation::CheckCStyleCast() {
   assert(!Self.getLangOptions().CPlusPlus);
 
-  // Handle placeholders.
-  if (isPlaceholder()) {
-    // C-style casts can resolve __unknown_any types.
-    if (claimPlaceholder(BuiltinType::UnknownAny)) {
-      SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType,
-                                         SrcExpr.get(), Kind,
-                                         ValueKind, BasePath);
-      return;
-    }
-
-    // We allow overloads in C, but we don't allow them to be resolved
-    // by anything except calls.
-    SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take());
-    if (SrcExpr.isInvalid())
-      return;
-  }  
-
-  assert(!isPlaceholder());
+  // C-style casts can resolve __unknown_any types.
+  if (claimPlaceholder(BuiltinType::UnknownAny)) {
+    SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType,
+                                       SrcExpr.get(), Kind,
+                                       ValueKind, BasePath);
+    return;
+  }
 
   // C99 6.5.4p2: the cast type needs to be void or scalar and the expression
   // type needs to be scalar.
@@ -1877,6 +1884,7 @@
   if (SrcExpr.isInvalid())
     return;
   QualType SrcType = SrcExpr.get()->getType();
+  assert(!SrcType->isPlaceholderType());
 
   if (Self.RequireCompleteType(OpRange.getBegin(), DestType,
                                diag::err_typecheck_cast_to_incomplete)) {
@@ -2044,9 +2052,9 @@
   if (Op.SrcExpr.isInvalid())
     return ExprError();
 
-  return Owned(CStyleCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
-                                      Op.Kind, Op.SrcExpr.take(), &Op.BasePath,
-                                      CastTypeInfo, LPLoc, RPLoc));
+  return Op.complete(CStyleCastExpr::Create(Context, Op.ResultType,
+                              Op.ValueKind, Op.Kind, Op.SrcExpr.take(),
+                              &Op.BasePath, CastTypeInfo, LPLoc, RPLoc));
 }
 
 ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
@@ -2061,9 +2069,7 @@
   if (Op.SrcExpr.isInvalid())
     return ExprError();
 
-  return Owned(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
-                                             Op.ValueKind, CastTypeInfo,
-                                             Op.DestRange.getBegin(),
-                                             Op.Kind, Op.SrcExpr.take(),
-                                             &Op.BasePath, RPLoc));
+  return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
+                         Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(),
+                         Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc));
 }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Oct 17 13:40:02 2011
@@ -520,11 +520,23 @@
 /// interfaces passed by value.
 ExprResult Sema::DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT,
                                                   FunctionDecl *FDecl) {
-  ExprResult ExprRes = CheckPlaceholderExpr(E);
-  if (ExprRes.isInvalid())
-    return ExprError();
+  if (const BuiltinType *PlaceholderTy = E->getType()->getAsPlaceholderType()) {
+    // Strip the unbridged-cast placeholder expression off, if applicable.
+    if (PlaceholderTy->getKind() == BuiltinType::ARCUnbridgedCast &&
+        (CT == VariadicMethod ||
+         (FDecl && FDecl->hasAttr<CFAuditedTransferAttr>()))) {
+      E = stripARCUnbridgedCast(E);
+
+    // Otherwise, do normal placeholder checking.
+    } else {
+      ExprResult ExprRes = CheckPlaceholderExpr(E);
+      if (ExprRes.isInvalid())
+        return ExprError();
+      E = ExprRes.take();
+    }
+  }
   
-  ExprRes = DefaultArgumentPromotion(E);
+  ExprResult ExprRes = DefaultArgumentPromotion(E);
   if (ExprRes.isInvalid())
     return ExprError();
   E = ExprRes.take();
@@ -3421,6 +3433,12 @@
       if (FDecl && i < FDecl->getNumParams())
         Param = FDecl->getParamDecl(i);
 
+      // Strip the unbridged-cast placeholder expression off, if applicable.
+      if (Arg->getType() == Context.ARCUnbridgedCastTy &&
+          FDecl && FDecl->hasAttr<CFAuditedTransferAttr>() &&
+          (!Param || !Param->hasAttr<CFConsumedAttr>()))
+        Arg = stripARCUnbridgedCast(Arg);
+
       InitializedEntity Entity =
         Param? InitializedEntity::InitializeParameter(Context, Param)
              : InitializedEntity::InitializeParameter(Context, ProtoArgType,
@@ -10029,11 +10047,13 @@
 /// Check for operands with placeholder types and complain if found.
 /// Returns true if there was an error and no recovery was possible.
 ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
-  // Placeholder types are always *exactly* the appropriate builtin type.
-  QualType type = E->getType();
+  const BuiltinType *placeholderType = E->getType()->getAsPlaceholderType();
+  if (!placeholderType) return Owned(E);
+
+  switch (placeholderType->getKind()) {
 
   // Overloaded expressions.
-  if (type == Context.OverloadTy) {
+  case BuiltinType::Overload: {
     // Try to resolve a single function template specialization.
     // This is obligatory.
     ExprResult result = Owned(E);
@@ -10049,19 +10069,57 @@
   }
 
   // Bound member functions.
-  if (type == Context.BoundMemberTy) {
+  case BuiltinType::BoundMember: {
     ExprResult result = Owned(E);
     tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function),
                          /*complain*/ true);
     return result;
-  }    
+  }
+
+  // ARC unbridged casts.
+  case BuiltinType::ARCUnbridgedCast: {
+    Expr *realCast = stripARCUnbridgedCast(E);
+    diagnoseARCUnbridgedCast(realCast);
+    return Owned(realCast);
+  }
 
   // Expressions of unknown type.
-  if (type == Context.UnknownAnyTy)
+  case BuiltinType::UnknownAny:
     return diagnoseUnknownAnyExpr(*this, E);
 
-  assert(!type->isPlaceholderType());
-  return Owned(E);
+  // Everything else should be impossible.  TODO: metaprogram this.
+  case BuiltinType::Void:
+  case BuiltinType::Bool:
+  case BuiltinType::Char_U:
+  case BuiltinType::UChar:
+  case BuiltinType::WChar_U:
+  case BuiltinType::Char16:
+  case BuiltinType::Char32:
+  case BuiltinType::UShort:
+  case BuiltinType::UInt:
+  case BuiltinType::ULong:
+  case BuiltinType::ULongLong:
+  case BuiltinType::UInt128:
+  case BuiltinType::Char_S:
+  case BuiltinType::SChar:
+  case BuiltinType::WChar_S:
+  case BuiltinType::Short:
+  case BuiltinType::Int:
+  case BuiltinType::Long:
+  case BuiltinType::LongLong:
+  case BuiltinType::Int128:
+  case BuiltinType::Float:
+  case BuiltinType::Double:
+  case BuiltinType::LongDouble:
+  case BuiltinType::NullPtr:
+  case BuiltinType::ObjCId:
+  case BuiltinType::ObjCClass:
+  case BuiltinType::ObjCSel:
+  case BuiltinType::Dependent:
+    break;
+  }
+
+  llvm_unreachable("invalid placeholder type!");
 }
 
 bool Sema::CheckCaseExpression(Expr *E) {

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Mon Oct 17 13:40:02 2011
@@ -409,17 +409,23 @@
 
     Expr *argExpr = Args[i];
 
-    ParmVarDecl *Param = Method->param_begin()[i];
+    ParmVarDecl *param = Method->param_begin()[i];
     assert(argExpr && "CheckMessageArgumentTypes(): missing expression");
 
+    // Strip the unbridged-cast placeholder expression off unless it's
+    // a consumed argument.
+    if (argExpr->hasPlaceholderType(BuiltinType::ARCUnbridgedCast) &&
+        !param->hasAttr<CFConsumedAttr>())
+      argExpr = stripARCUnbridgedCast(argExpr);
+
     if (RequireCompleteType(argExpr->getSourceRange().getBegin(),
-                            Param->getType(),
+                            param->getType(),
                             PDiag(diag::err_call_incomplete_argument)
                               << argExpr->getSourceRange()))
       return true;
 
     InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
-                                                                      Param);
+                                                                      param);
     ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr));
     if (ArgE.isInvalid())
       IsError = true;
@@ -1213,6 +1219,12 @@
   // If we have a receiver expression, perform appropriate promotions
   // and determine receiver type.
   if (Receiver) {
+    if (Receiver->hasPlaceholderType()) {
+      ExprResult result = CheckPlaceholderExpr(Receiver);
+      if (result.isInvalid()) return ExprError();
+      Receiver = result.take();
+    }
+
     if (Receiver->isTypeDependent()) {
       // If the receiver is type-dependent, we can't type-check anything
       // at this point. Build a dependent expression.
@@ -1836,7 +1848,90 @@
   };
 }
 
-void 
+static void
+diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
+                          QualType castType, ARCConversionTypeClass castACTC,
+                          Expr *castExpr, ARCConversionTypeClass exprACTC,
+                          Sema::CheckedConversionKind CCK) {
+  SourceLocation loc =
+    (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
+  
+  if (S.makeUnavailableInSystemHeader(loc,
+                "converts between Objective-C and C pointers in -fobjc-arc"))
+    return;
+
+  QualType castExprType = castExpr->getType();
+  
+  unsigned srcKind = 0;
+  switch (exprACTC) {
+  case ACTC_none:
+  case ACTC_coreFoundation:
+  case ACTC_voidPtr:
+    srcKind = (castExprType->isPointerType() ? 1 : 0);
+    break;
+  case ACTC_retainable:
+    srcKind = (castExprType->isBlockPointerType() ? 2 : 3);
+    break;
+  case ACTC_indirectRetainable:
+    srcKind = 4;
+    break;
+  }
+  
+  // Check whether this could be fixed with a bridge cast.
+  SourceLocation afterLParen = S.PP.getLocForEndOfToken(castRange.getBegin());
+  SourceLocation noteLoc = afterLParen.isValid() ? afterLParen : loc;
+
+  // Bridge from an ARC type to a CF type.
+  if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {
+    S.Diag(loc, diag::err_arc_cast_requires_bridge)
+      << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
+      << 2 // of C pointer type
+      << castExprType
+      << unsigned(castType->isBlockPointerType()) // to ObjC|block type
+      << castType
+      << castRange
+      << castExpr->getSourceRange();
+
+    S.Diag(noteLoc, diag::note_arc_bridge)
+      << (CCK != Sema::CCK_CStyleCast ? FixItHint() :
+            FixItHint::CreateInsertion(afterLParen, "__bridge "));
+    S.Diag(noteLoc, diag::note_arc_bridge_transfer)
+      << castExprType
+      << (CCK != Sema::CCK_CStyleCast ? FixItHint() :
+            FixItHint::CreateInsertion(afterLParen, "__bridge_transfer "));
+
+    return;
+  }
+    
+  // Bridge from a CF type to an ARC type.
+  if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
+    S.Diag(loc, diag::err_arc_cast_requires_bridge)
+      << unsigned(CCK == Sema::CCK_ImplicitConversion) // cast|implicit
+      << unsigned(castExprType->isBlockPointerType()) // of ObjC|block type
+      << castExprType
+      << 2 // to C pointer type
+      << castType
+      << castRange
+      << castExpr->getSourceRange();
+
+    S.Diag(noteLoc, diag::note_arc_bridge)
+      << (CCK != Sema::CCK_CStyleCast ? FixItHint() :
+            FixItHint::CreateInsertion(afterLParen, "__bridge "));
+    S.Diag(noteLoc, diag::note_arc_bridge_retained)
+      << castType
+      << (CCK != Sema::CCK_CStyleCast ? FixItHint() :
+            FixItHint::CreateInsertion(afterLParen, "__bridge_retained "));
+
+    return;
+  }
+  
+  S.Diag(loc, diag::err_arc_mismatched_cast)
+    << (CCK != Sema::CCK_ImplicitConversion)
+    << srcKind << castExprType << castType
+    << castRange << castExpr->getSourceRange();
+}
+
+Sema::ARCConversionResult
 Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
                              Expr *&castExpr, CheckedConversionKind CCK) {
   QualType castExprType = castExpr->getType();
@@ -1849,22 +1944,22 @@
   
   ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType);
   ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType);
-  if (exprACTC == castACTC) return;
-  if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return;
+  if (exprACTC == castACTC) return ACR_okay;
+  if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay;
 
   // Allow all of these types to be cast to integer types (but not
   // vice-versa).
   if (castACTC == ACTC_none && castType->isIntegralType(Context))
-    return;
+    return ACR_okay;
   
   // Allow casts between pointers to lifetime types (e.g., __strong id*)
   // and pointers to void (e.g., cv void *). Casting from void* to lifetime*
   // must be explicit.
   if (exprACTC == ACTC_indirectRetainable && castACTC == ACTC_voidPtr)
-    return;
+    return ACR_okay;
   if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
       CCK != CCK_ImplicitConversion)
-    return;
+    return ACR_okay;
 
   switch (ARCCastChecker(Context, exprACTC, castACTC).Visit(castExpr)) {
   // For invalid casts, fall through.
@@ -1874,7 +1969,7 @@
   // Do nothing for both bottom and +0.
   case ACC_bottom:
   case ACC_plusZero:
-    return;
+    return ACR_okay;
 
   // If the result is +1, consume it here.
   case ACC_plusOne:
@@ -1882,74 +1977,94 @@
                                         CK_ARCConsumeObject, castExpr,
                                         0, VK_RValue);
     ExprNeedsCleanups = true;
-    return;
+    return ACR_okay;
   }
-  
-  SourceLocation loc =
-    (castRange.isValid() ? castRange.getBegin() : castExpr->getExprLoc());
-  
-  if (makeUnavailableInSystemHeader(loc,
-                "converts between Objective-C and C pointers in -fobjc-arc"))
-    return;
-  
-  unsigned srcKind = 0;
-  switch (exprACTC) {
-  case ACTC_none:
-  case ACTC_coreFoundation:
-  case ACTC_voidPtr:
-    srcKind = (castExprType->isPointerType() ? 1 : 0);
-    break;
-  case ACTC_retainable:
-    srcKind = (castExprType->isBlockPointerType() ? 2 : 3);
-    break;
-  case ACTC_indirectRetainable:
-    srcKind = 4;
-    break;
+
+  // If this is a non-implicit cast from id or block type to a
+  // CoreFoundation type, delay complaining in case the cast is used
+  // in an acceptable context.
+  if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC) &&
+      CCK != CCK_ImplicitConversion)
+    return ACR_unbridged;
+
+  diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
+                            castExpr, exprACTC, CCK);
+  return ACR_okay;
+}
+
+/// Given that we saw an expression with the ARCUnbridgedCastTy
+/// placeholder type, complain bitterly.
+void Sema::diagnoseARCUnbridgedCast(Expr *e) {
+  // We expect the spurious ImplicitCastExpr to already have been stripped.
+  assert(!e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
+  CastExpr *realCast = cast<CastExpr>(e->IgnoreParens());
+
+  SourceRange castRange;
+  QualType castType;
+  CheckedConversionKind CCK;
+
+  if (CStyleCastExpr *cast = dyn_cast<CStyleCastExpr>(realCast)) {
+    castRange = SourceRange(cast->getLParenLoc(), cast->getRParenLoc());
+    castType = cast->getTypeAsWritten();
+    CCK = CCK_CStyleCast;
+  } else if (ExplicitCastExpr *cast = dyn_cast<ExplicitCastExpr>(realCast)) {
+    castRange = cast->getTypeInfoAsWritten()->getTypeLoc().getSourceRange();
+    castType = cast->getTypeAsWritten();
+    CCK = CCK_OtherCast;
+  } else {
+    castType = cast->getType();
+    CCK = CCK_ImplicitConversion;
   }
-  
-  if (CCK == CCK_CStyleCast) {
-    // Check whether this could be fixed with a bridge cast.
-    SourceLocation AfterLParen = PP.getLocForEndOfToken(castRange.getBegin());
-    SourceLocation NoteLoc = AfterLParen.isValid()? AfterLParen : loc;
-    
-    if (castACTC == ACTC_retainable && isAnyRetainable(exprACTC)) {
-      Diag(loc, diag::err_arc_cast_requires_bridge)
-        << 2
-        << castExprType
-        << (castType->isBlockPointerType()? 1 : 0)
-        << castType
-        << castRange
-        << castExpr->getSourceRange();
-      Diag(NoteLoc, diag::note_arc_bridge)
-        << FixItHint::CreateInsertion(AfterLParen, "__bridge ");
-      Diag(NoteLoc, diag::note_arc_bridge_transfer)
-        << castExprType
-        << FixItHint::CreateInsertion(AfterLParen, "__bridge_transfer ");
-      
-      return;
-    }
-    
-    if (exprACTC == ACTC_retainable && isAnyRetainable(castACTC)) {
-      Diag(loc, diag::err_arc_cast_requires_bridge)
-        << (castExprType->isBlockPointerType()? 1 : 0)
-        << castExprType
-        << 2
-        << castType
-        << castRange
-        << castExpr->getSourceRange();
 
-      Diag(NoteLoc, diag::note_arc_bridge)
-        << FixItHint::CreateInsertion(AfterLParen, "__bridge ");
-      Diag(NoteLoc, diag::note_arc_bridge_retained)
-        << castType
-        << FixItHint::CreateInsertion(AfterLParen, "__bridge_retained ");
-      return;
-    }
+  ARCConversionTypeClass castACTC =
+    classifyTypeForARCConversion(castType.getNonReferenceType());
+
+  Expr *castExpr = realCast->getSubExpr();
+  assert(classifyTypeForARCConversion(castExpr->getType()) == ACTC_retainable);
+
+  diagnoseObjCARCConversion(*this, castRange, castType, castACTC,
+                            castExpr, ACTC_retainable, CCK);
+}
+
+/// stripARCUnbridgedCast - Given an expression of ARCUnbridgedCast
+/// type, remove the placeholder cast.
+Expr *Sema::stripARCUnbridgedCast(Expr *e) {
+  assert(e->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
+
+  if (ParenExpr *pe = dyn_cast<ParenExpr>(e)) {
+    Expr *sub = stripARCUnbridgedCast(pe->getSubExpr());
+    return new (Context) ParenExpr(pe->getLParen(), pe->getRParen(), sub);
+  } else if (UnaryOperator *uo = dyn_cast<UnaryOperator>(e)) {
+    assert(uo->getOpcode() == UO_Extension);
+    Expr *sub = stripARCUnbridgedCast(uo->getSubExpr());
+    return new (Context) UnaryOperator(sub, UO_Extension, sub->getType(),
+                                   sub->getValueKind(), sub->getObjectKind(),
+                                       uo->getOperatorLoc());
+  } else if (GenericSelectionExpr *gse = dyn_cast<GenericSelectionExpr>(e)) {
+    assert(!gse->isResultDependent());
+
+    unsigned n = gse->getNumAssocs();
+    SmallVector<Expr*, 4> subExprs(n);
+    SmallVector<TypeSourceInfo*, 4> subTypes(n);
+    for (unsigned i = 0; i != n; ++i) {
+      subTypes[i] = gse->getAssocTypeSourceInfo(i);
+      Expr *sub = gse->getAssocExpr(i);
+      if (i == gse->getResultIndex())
+        sub = stripARCUnbridgedCast(sub);
+      subExprs[i] = sub;
+    }
+
+    return new (Context) GenericSelectionExpr(Context, gse->getGenericLoc(),
+                                              gse->getControllingExpr(),
+                                              subTypes.data(), subExprs.data(),
+                                              n, gse->getDefaultLoc(),
+                                              gse->getRParenLoc(),
+                                       gse->containsUnexpandedParameterPack(),
+                                              gse->getResultIndex());
+  } else {
+    assert(isa<ImplicitCastExpr>(e) && "bad form of unbridged cast!");
+    return cast<ImplicitCastExpr>(e)->getSubExpr();
   }
-  
-  Diag(loc, diag::err_arc_mismatched_cast)
-    << (CCK != CCK_ImplicitConversion) << srcKind << castExprType << castType
-    << castRange << castExpr->getSourceRange();
 }
 
 bool Sema::CheckObjCARCUnavailableWeakConversion(QualType castType,

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Oct 17 13:40:02 2011
@@ -2427,6 +2427,7 @@
   case FK_ArrayTypeMismatch:
   case FK_NonConstantArrayInit:
   case FK_ListInitializationFailed:
+  case FK_PlaceholderType:
     return false;
 
   case FK_ReferenceInitOverloadFailed:
@@ -3793,8 +3794,20 @@
         return;
       }
       Args[I] = Result.take();
+    } else if (const BuiltinType *PlaceholderTy
+                 = Args[I]->getType()->getAsPlaceholderType()) {
+      // FIXME: should we be doing this here?
+      if (PlaceholderTy->getKind() != BuiltinType::Overload) {
+        ExprResult result = S.CheckPlaceholderExpr(Args[I]);
+        if (result.isInvalid()) {
+          SetFailed(FK_PlaceholderType);
+          return;
+        }
+        Args[I] = result.take();
+      }
     }
 
+
   QualType SourceType;
   Expr *Initializer = 0;
   if (NumArgs == 1) {
@@ -5200,6 +5213,11 @@
            "Inconsistent init list check result.");
     break;
   }
+
+  case FK_PlaceholderType: {
+    // FIXME: Already diagnosed!
+    break;
+  }
   }
 
   PrintInitLocationNote(S, Entity);
@@ -5297,6 +5315,11 @@
 
     case FK_ListInitializationFailed:
       OS << "list initialization checker failure";
+      break;
+
+    case FK_PlaceholderType:
+      OS << "initializer expression isn't contextually valid";
+      break;
     }
     OS << '\n';
     return;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Oct 17 13:40:02 2011
@@ -542,6 +542,88 @@
   Functions.clear();
 }
 
+namespace {
+  class UnbridgedCastsSet {
+    struct Entry {
+      Expr **Addr;
+      Expr *Saved;
+    };
+    SmallVector<Entry, 2> Entries;
+    
+  public:
+    void save(Sema &S, Expr *&E) {
+      assert(E->hasPlaceholderType(BuiltinType::ARCUnbridgedCast));
+      Entry entry = { &E, E };
+      Entries.push_back(entry);
+      E = S.stripARCUnbridgedCast(E);
+    }
+
+    void restore() {
+      for (SmallVectorImpl<Entry>::iterator
+             i = Entries.begin(), e = Entries.end(); i != e; ++i) 
+        *i->Addr = i->Saved;
+    }
+  };
+}
+
+/// checkPlaceholderForOverload - Do any interesting placeholder-like
+/// preprocessing on the given expression.
+///
+/// \param unbridgedCasts a collection to which to add unbridged casts;
+///   without this, they will be immediately diagnosed as errors
+///
+/// Return true on unrecoverable error.
+static bool checkPlaceholderForOverload(Sema &S, Expr *&E,
+                                        UnbridgedCastsSet *unbridgedCasts = 0) {
+  // ObjCProperty l-values are placeholder-like.
+  if (E->getObjectKind() == OK_ObjCProperty) {
+    ExprResult result = S.ConvertPropertyForRValue(E);
+    if (result.isInvalid())
+      return true;
+
+    E = result.take();
+    return false;
+  }
+
+  // Handle true placeholders.
+  if (const BuiltinType *placeholder =  E->getType()->getAsPlaceholderType()) {
+    // We can't handle overloaded expressions here because overload
+    // resolution might reasonably tweak them.
+    if (placeholder->getKind() == BuiltinType::Overload) return false;
+
+    // If the context potentially accepts unbridged ARC casts, strip
+    // the unbridged cast and add it to the collection for later restoration.
+    if (placeholder->getKind() == BuiltinType::ARCUnbridgedCast &&
+        unbridgedCasts) {
+      unbridgedCasts->save(S, E);
+      return false;
+    }
+
+    // Go ahead and check everything else.
+    ExprResult result = S.CheckPlaceholderExpr(E);
+    if (result.isInvalid())
+      return true;
+
+    E = result.take();
+    return false;
+  }
+
+  // Nothing to do.
+  return false;
+}
+
+/// checkArgPlaceholdersForOverload - Check a set of call operands for
+/// placeholders.
+static bool checkArgPlaceholdersForOverload(Sema &S, Expr **args,
+                                            unsigned numArgs,
+                                            UnbridgedCastsSet &unbridged) {
+  for (unsigned i = 0; i != numArgs; ++i)
+    if (checkPlaceholderForOverload(S, args[i], &unbridged))
+      return true;
+
+  return false;
+}
+
 // IsOverload - Determine whether the given New declaration is an
 // overload of the declarations in Old. This routine returns false if
 // New and Old cannot be overloaded, e.g., if New has the same
@@ -8574,6 +8656,10 @@
            "std is associated namespace but not doing ADL");
 #endif
 
+  UnbridgedCastsSet UnbridgedCasts;
+  if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
+    return ExprError();
+
   OverloadCandidateSet CandidateSet(Fn->getExprLoc());
 
   // Add the functions denoted by the callee to the set of candidate
@@ -8600,14 +8686,15 @@
                                  RParenLoc, /*EmptyLookup=*/true);
   }
 
+  UnbridgedCasts.restore();
+
   OverloadCandidateSet::iterator Best;
   switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
   case OR_Success: {
     FunctionDecl *FDecl = Best->Function;
     MarkDeclarationReferenced(Fn->getExprLoc(), FDecl);
     CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
-    DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(),
-                      ULE->getNameLoc());
+    DiagnoseUseOfDecl(FDecl, ULE->getNameLoc());
     Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
     return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc,
                                  ExecConfig);
@@ -8684,12 +8771,8 @@
   // TODO: provide better source location info.
   DeclarationNameInfo OpNameInfo(OpName, OpLoc);
 
-  if (Input->getObjectKind() == OK_ObjCProperty) {
-    ExprResult Result = ConvertPropertyForRValue(Input);
-    if (Result.isInvalid())
-      return ExprError();
-    Input = Result.take();
-  }
+  if (checkPlaceholderForOverload(*this, Input))
+    return ExprError();
 
   Expr *Args[2] = { Input, 0 };
   unsigned NumArgs = 1;
@@ -8922,13 +9005,9 @@
                                                    OpLoc));
   }
 
-  // Always do property rvalue conversions on the RHS.
-  if (Args[1]->getObjectKind() == OK_ObjCProperty) {
-    ExprResult Result = ConvertPropertyForRValue(Args[1]);
-    if (Result.isInvalid())
-      return ExprError();
-    Args[1] = Result.take();
-  }
+  // Always do placeholder-like conversions on the RHS.
+  if (checkPlaceholderForOverload(*this, Args[1]))
+    return ExprError();
 
   // The LHS is more complicated.
   if (Args[0]->getObjectKind() == OK_ObjCProperty) {
@@ -8962,6 +9041,10 @@
     Args[0] = Result.take();
   }
 
+  // Handle all the other placeholders.
+  if (checkPlaceholderForOverload(*this, Args[0]))
+    return ExprError();
+
   // If this is the assignment operator, we only perform overload resolution
   // if the left-hand side is a class or enumeration type. This is actually
   // a hack. The standard requires that we do overload resolution between the
@@ -9184,18 +9267,11 @@
                                                    RLoc));
   }
 
-  if (Args[0]->getObjectKind() == OK_ObjCProperty) {
-    ExprResult Result = ConvertPropertyForRValue(Args[0]);
-    if (Result.isInvalid())
-      return ExprError();
-    Args[0] = Result.take();
-  }
-  if (Args[1]->getObjectKind() == OK_ObjCProperty) {
-    ExprResult Result = ConvertPropertyForRValue(Args[1]);
-    if (Result.isInvalid())
-      return ExprError();
-    Args[1] = Result.take();
-  }
+  // Handle placeholders on both operands.
+  if (checkPlaceholderForOverload(*this, Args[0]))
+    return ExprError();
+  if (checkPlaceholderForOverload(*this, Args[1]))
+    return ExprError();
 
   // Build an empty overload set.
   OverloadCandidateSet CandidateSet(LLoc);
@@ -9396,6 +9472,10 @@
     return MaybeBindToTemporary(call);
   }
 
+  UnbridgedCastsSet UnbridgedCasts;
+  if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
+    return ExprError();
+
   MemberExpr *MemExpr;
   CXXMethodDecl *Method = 0;
   DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public);
@@ -9405,6 +9485,7 @@
     Method = cast<CXXMethodDecl>(MemExpr->getMemberDecl());
     FoundDecl = MemExpr->getFoundDecl();
     Qualifier = MemExpr->getQualifier();
+    UnbridgedCasts.restore();
   } else {
     UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr);
     Qualifier = UnresExpr->getQualifier();
@@ -9458,6 +9539,8 @@
 
     DeclarationName DeclName = UnresExpr->getMemberName();
 
+    UnbridgedCasts.restore();
+
     OverloadCandidateSet::iterator Best;
     switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(),
                                             Best)) {
@@ -9569,12 +9652,13 @@
                                    SourceLocation LParenLoc,
                                    Expr **Args, unsigned NumArgs,
                                    SourceLocation RParenLoc) {
+  if (checkPlaceholderForOverload(*this, Obj))
+    return ExprError();
   ExprResult Object = Owned(Obj);
-  if (Object.get()->getObjectKind() == OK_ObjCProperty) {
-    Object = ConvertPropertyForRValue(Object.take());
-    if (Object.isInvalid())
-      return ExprError();
-  }
+
+  UnbridgedCastsSet UnbridgedCasts;
+  if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
+    return ExprError();
 
   assert(Object.get()->getType()->isRecordType() && "Requires object type argument");
   const RecordType *Record = Object.get()->getType()->getAs<RecordType>();
@@ -9696,6 +9780,8 @@
   if (Best == CandidateSet.end())
     return true;
 
+  UnbridgedCasts.restore();
+
   if (Best->Function == 0) {
     // Since there is no function declaration, this is one of the
     // surrogate candidates. Dig out the conversion function.
@@ -9845,12 +9931,8 @@
   assert(Base->getType()->isRecordType() &&
          "left-hand side must have class type");
 
-  if (Base->getObjectKind() == OK_ObjCProperty) {
-    ExprResult Result = ConvertPropertyForRValue(Base);
-    if (Result.isInvalid())
-      return ExprError();
-    Base = Result.take();
-  }
+  if (checkPlaceholderForOverload(*this, Base))
+    return ExprError();
 
   SourceLocation Loc = Base->getExprLoc();
 

Modified: cfe/trunk/test/ARCMT/checking.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/checking.m?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/checking.m (original)
+++ cfe/trunk/test/ARCMT/checking.m Mon Oct 17 13:40:02 2011
@@ -62,8 +62,8 @@
 
   CFStringRef cfstr;
   NSString *str = (NSString *)cfstr; // expected-error {{cast of C pointer type 'CFStringRef' (aka 'const struct __CFString *') to Objective-C pointer type 'NSString *' requires a bridged cast}} \
-  // expected-note{{use __bridge to convert directly (no change in ownership)}} \
-  // expected-note{{use __bridge_transfer to transfer ownership of a +1 'CFStringRef' (aka 'const struct __CFString *') into ARC}}
+  // expected-note {{use __bridge to convert directly (no change in ownership)}} \
+  // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CFStringRef' (aka 'const struct __CFString *') into ARC}} \
   str = (NSString *)kUTTypePlainText;
   str = b ? kUTTypeRTF : kUTTypePlainText;
   str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
@@ -120,11 +120,11 @@
   (void)(__autoreleasing id**)voidp_val;
   (void)(void*)voidp_val;
   (void)(void**)arg; // expected-error {{disallowed}}
-  cvt((void*)arg); // expected-error {{requires a bridged cast}} expected-error {{disallowed}} \
-                   // expected-note {{use __bridge}} expected-note {{use __bridge_retained}} 
+  cvt((void*)arg); // expected-error 2 {{requires a bridged cast}} \
+                   // expected-note 2 {{use __bridge to}} expected-note {{use __bridge_transfer}} expected-note {{use __bridge_retained}}
   cvt(0);
   (void)(__strong id**)(0);
-  return arg; // expected-error {{disallowed}}
+  return arg; // expected-error {{requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use __bridge_retained}}
 }
 
 

Modified: cfe/trunk/test/ARCMT/nonobjc-to-objc-cast-2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/nonobjc-to-objc-cast-2.m?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/ARCMT/nonobjc-to-objc-cast-2.m (original)
+++ cfe/trunk/test/ARCMT/nonobjc-to-objc-cast-2.m Mon Oct 17 13:40:02 2011
@@ -14,7 +14,7 @@
   NSString *str = (NSString *)cfstr; // expected-error {{cast of C pointer type 'CFStringRef' (aka 'const struct __CFString *') to Objective-C pointer type 'NSString *' requires a bridged cast}} \
     // expected-note{{use __bridge to convert directly (no change in ownership)}} \
     // expected-note{{use __bridge_transfer to transfer ownership of a +1 'CFStringRef' (aka 'const struct __CFString *') into ARC}}
-  void *vp = str;  // expected-error {{disallowed}}
+  void *vp = str;  // expected-error {{requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use __bridge}}
 }
 
 void f2(NSString *s) {

Modified: cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp (original)
+++ cfe/trunk/test/CXX/over/over.over/p2-resolve-single-template-id.cpp Mon Oct 17 13:40:02 2011
@@ -165,8 +165,8 @@
     { bool b = &S::f<char>; }
     { bool b = &S::f<int>; }
     // These next two errors are terrible.
-    { bool b = s.f<char>; } // expected-error {{cannot initialize}}
-    { bool b = s.f<int>; } // expected-error {{cannot initialize}}
+    { bool b = s.f<char>; } // expected-error {{reference to non-static member function must be called}}
+    { bool b = s.f<int>; } // expected-error {{reference to non-static member function must be called}}
     { bool b = &s.f<char>; } // expected-error {{cannot create a non-constant pointer to member function}}
     { bool b = &s.f<int>; } // expected-error {{cannot create a non-constant pointer to member function}}
 

Modified: cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp Mon Oct 17 13:40:02 2011
@@ -57,8 +57,7 @@
 
 struct C {
   C &getC() {
-    // FIXME: this error message is terrible
-    return makeAC; // expected-error{{cannot bind to a value of unrelated type}}
+    return makeAC; // expected-error{{reference to non-static member function must be called}}
   }
 
   C &makeAC();

Modified: cfe/trunk/test/SemaCXX/member-pointer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-pointer.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/member-pointer.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-pointer.cpp Mon Oct 17 13:40:02 2011
@@ -278,7 +278,7 @@
     typedef R T::*F;
     F f_;
     template<class U> int & call(U u)
-    { return u->*f_; } // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type '<bound member function type>'}}
+    { return u->*f_; } // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} expected-error {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
 
     template<class U> int operator()(U u)
     { call(u); } // expected-note{{in instantiation of}}

Modified: cfe/trunk/test/SemaCXX/overloaded-name.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-name.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-name.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-name.cpp Mon Oct 17 13:40:02 2011
@@ -21,11 +21,10 @@
   public:
     const char* text(void);
     void g(void) {
-      // FIXME: why 2x?
       f(text());
-      f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
+      f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
       f(text());
-      f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
+      f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
     }
   };
 }

Modified: cfe/trunk/test/SemaCXX/overloaded-operator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/overloaded-operator.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/overloaded-operator.cpp (original)
+++ cfe/trunk/test/SemaCXX/overloaded-operator.cpp Mon Oct 17 13:40:02 2011
@@ -392,7 +392,7 @@
   };
 
   struct Y {
-    Y &operator<<(int); // expected-note{{candidate function not viable: no known conversion from '<bound member function type>' to 'int'}}
+    Y &operator<<(int);
   };
 
   void f(X x, Y y) {

Modified: cfe/trunk/test/SemaCXX/unknown-anytype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/unknown-anytype.cpp?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/unknown-anytype.cpp (original)
+++ cfe/trunk/test/SemaCXX/unknown-anytype.cpp Mon Oct 17 13:40:02 2011
@@ -14,9 +14,9 @@
     // making sure that these locations check for placeholder types
     // properly.
 
-    int x = foo; // expected-error {{cannot initialize}}
+    int x = foo; // expected-error {{'foo' has unknown type}}
     int y = 0 + foo; // expected-error {{'foo' has unknown type}}
-    return foo; // expected-error {{cannot initialize}}
+    return foo; // expected-error {{'foo' has unknown type}}
   }
 }
 

Modified: cfe/trunk/test/SemaObjC/arc-type-conversion.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-type-conversion.m?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-type-conversion.m (original)
+++ cfe/trunk/test/SemaObjC/arc-type-conversion.m Mon Oct 17 13:40:02 2011
@@ -12,12 +12,15 @@
   (void)(void*)voidp_val;
   (void)(void**)arg; // expected-error {{cast of an Objective-C pointer to 'void **' is disallowed with ARC}}
   cvt((void*)arg); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} \
-                   // expected-error {{implicit conversion of a non-Objective-C pointer type 'void *' to 'id' is disallowed with ARC}} \
-                   // expected-note{{use __bridge to convert directly (no change in ownership)}} \
-                   // expected-note{{use __bridge_retained to make an ARC object available as a +1 'void *'}}
+                   // expected-error {{implicit conversion of C pointer type 'void *' to Objective-C pointer type 'id' requires a bridged cast}} \
+                   // expected-note 2 {{use __bridge to convert directly (no change in ownership)}} \
+                   // expected-note {{use __bridge_retained to make an ARC object available as a +1 'void *'}} \
+                   // expected-note {{use __bridge_transfer to transfer ownership of a +1 'void *' into ARC}}
   cvt(0);
   (void)(__strong id**)(0);
-  return arg; // expected-error {{implicit conversion of an Objective-C pointer to 'void *' is disallowed with ARC}}
+  return arg; // expected-error {{implicit conversion of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} \
+                   // expected-note {{use __bridge to convert directly (no change in ownership)}} \
+                   // expected-note {{use __bridge_retained to make an ARC object available as a +1 'void *'}}
 }
 
 void to_void(__strong id *sip, __weak id *wip,

Modified: cfe/trunk/test/SemaObjC/arc-unbridged-cast.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-unbridged-cast.m?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-unbridged-cast.m (original)
+++ cfe/trunk/test/SemaObjC/arc-unbridged-cast.m Mon Oct 17 13:40:02 2011
@@ -70,3 +70,50 @@
   x = (id) (cond ? (void*) 0 : [object newString]);
   x = (id) (cond ? (CFStringRef) @"help" : [object newString]); // a bit questionable
 }
+
+// rdar://problem/10246264
+ at interface CFTaker
+- (void) takeOrdinary: (CFStringRef) arg;
+- (void) takeVariadic: (int) n, ...;
+- (void) takeConsumed: (CFStringRef __attribute__((cf_consumed))) arg;
+ at end
+void testCFTaker(CFTaker *taker, id string) {
+  [taker takeOrdinary: (CFStringRef) string];
+  [taker takeVariadic: 1, (CFStringRef) string];
+  [taker takeConsumed: (CFStringRef) string]; // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}
+
+void takeCFOrdinaryUnaudited(CFStringRef arg);
+void takeCFVariadicUnaudited(int n, ...);
+void takeCFConsumedUnaudited(CFStringRef __attribute__((cf_consumed)) arg);
+#pragma clang arc_cf_code_audited begin
+void takeCFOrdinaryAudited(CFStringRef arg);
+void takeCFVariadicAudited(int n, ...);
+void takeCFConsumedAudited(CFStringRef __attribute__((cf_consumed)) arg);
+#pragma clang arc_cf_code_audited end
+
+void testTakerFunctions(id string) {
+  takeCFOrdinaryUnaudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFVariadicUnaudited(1, (CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFConsumedUnaudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  void (*taker)(CFStringRef) = 0;
+  taker((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  takeCFOrdinaryAudited((CFStringRef) string);
+  takeCFVariadicAudited(1, (CFStringRef) string);
+  takeCFConsumedAudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}
+
+void testTakerFunctions_parens(id string) {
+  takeCFOrdinaryUnaudited(((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFVariadicUnaudited(1, ((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFConsumedUnaudited(((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  void (*taker)(CFStringRef) = 0;
+  taker(((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  takeCFOrdinaryAudited(((CFStringRef) string));
+  takeCFVariadicAudited(1, ((CFStringRef) string));
+  takeCFConsumedAudited(((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}

Modified: cfe/trunk/test/SemaObjC/arc.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc.m?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc.m (original)
+++ cfe/trunk/test/SemaObjC/arc.m Mon Oct 17 13:40:02 2011
@@ -263,8 +263,8 @@
   b = (vp == nil);
   b = (nil == vp);
 
-  b = (vp == op); // expected-error {{implicit conversion of an Objective-C pointer to 'void *'}}
-  b = (op == vp); // expected-error {{implicit conversion of a non-Objective-C pointer type 'void *' to 'id'}}
+  b = (vp == op); // expected-error {{implicit conversion of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use __bridge_retained}}
+  b = (op == vp); // expected-error {{implicit conversion of C pointer type 'void *' to Objective-C pointer type 'id' requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use __bridge_transfer}}
 }
 
 void test12(id collection) {

Modified: cfe/trunk/test/SemaObjCXX/arc-type-conversion.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-type-conversion.mm?rev=142219&r1=142218&r2=142219&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/arc-type-conversion.mm (original)
+++ cfe/trunk/test/SemaObjCXX/arc-type-conversion.mm Mon Oct 17 13:40:02 2011
@@ -12,10 +12,7 @@
   (void)(__autoreleasing id**)voidp_val;
   (void)(void*)voidp_val;
   (void)(void**)arg; // expected-error {{cast of an Objective-C pointer to 'void **' is disallowed}}
-  cvt((void*)arg); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} \
-                   // expected-error {{no matching function for call to 'cvt'}} \
-  // expected-note{{use __bridge to convert directly (no change in ownership)}} \
-  // expected-note{{use __bridge_retained to make an ARC object available as a +1 'void *'}}
+  cvt((void*)arg); // expected-error {{no matching function for call to 'cvt'}}
   cvt(0);
   (void)(__strong id**)(0);
 

Added: cfe/trunk/test/SemaObjCXX/arc-unbridged-cast.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/arc-unbridged-cast.mm?rev=142219&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjCXX/arc-unbridged-cast.mm (added)
+++ cfe/trunk/test/SemaObjCXX/arc-unbridged-cast.mm Mon Oct 17 13:40:02 2011
@@ -0,0 +1,106 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify %s
+
+typedef const struct __CFString * CFStringRef;
+
+ at interface Object
+ at property CFStringRef property;
+- (CFStringRef) implicitProperty;
+- (CFStringRef) newString;
+- (CFStringRef) makeString;
+ at end
+
+extern Object *object;
+
+// rdar://9744349
+id test0(void) {
+  id p1 = (id)[object property];
+  id p2 = (__bridge_transfer id)[object property];
+  id p3 = (__bridge id)[object property];
+  return (id) object.property;
+}
+
+// rdar://10140692
+CFStringRef unauditedString(void);
+CFStringRef plusOneString(void) __attribute__((cf_returns_retained));
+
+#pragma clang arc_cf_code_audited begin
+CFStringRef auditedString(void);
+CFStringRef auditedCreateString(void);
+#pragma clang arc_cf_code_audited end
+
+void test1(int cond) {
+  id x;
+  x = (id) auditedString();
+  x = (id) (cond ? auditedString() : (void*) 0);
+  x = (id) (cond ? (void*) 0 : auditedString());
+  x = (id) (cond ? (CFStringRef) @"help" : auditedString());
+
+  x = (id) unauditedString(); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? unauditedString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? (void*) 0 : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? (CFStringRef) @"help" : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+
+  x = (id) auditedCreateString(); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? auditedCreateString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? (void*) 0 : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? (CFStringRef) @"help" : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+
+  x = (id) [object property];
+  x = (id) (cond ? [object property] : (void*) 0);
+  x = (id) (cond ? (void*) 0 : [object property]);
+  x = (id) (cond ? (CFStringRef) @"help" : [object property]);  
+
+  x = (id) object.property;
+  x = (id) (cond ? object.property : (void*) 0);
+  x = (id) (cond ? (void*) 0 : object.property);
+  x = (id) (cond ? (CFStringRef) @"help" : object.property);  
+
+  x = (id) object.implicitProperty;
+  x = (id) (cond ? object.implicitProperty : (void*) 0);
+  x = (id) (cond ? (void*) 0 : object.implicitProperty);
+  x = (id) (cond ? (CFStringRef) @"help" : object.implicitProperty);  
+
+  x = (id) [object makeString];
+  x = (id) (cond ? [object makeString] : (void*) 0);
+  x = (id) (cond ? (void*) 0 : [object makeString]);
+  x = (id) (cond ? (CFStringRef) @"help" : [object makeString]);  
+
+  x = (id) [object newString];
+  x = (id) (cond ? [object newString] : (void*) 0);
+  x = (id) (cond ? (void*) 0 : [object newString]);
+  x = (id) (cond ? (CFStringRef) @"help" : [object newString]); // a bit questionable
+}
+
+// rdar://problem/10246264
+ at interface CFTaker
+- (void) takeOrdinary: (CFStringRef) arg;
+- (void) takeVariadic: (int) n, ...;
+- (void) takeConsumed: (CFStringRef __attribute__((cf_consumed))) arg;
+ at end
+void testCFTaker(CFTaker *taker, id string) {
+  [taker takeOrdinary: (CFStringRef) string];
+  [taker takeVariadic: 1, (CFStringRef) string];
+  [taker takeConsumed: (CFStringRef) string]; // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}
+
+void takeCFOrdinaryUnaudited(CFStringRef arg);
+void takeCFVariadicUnaudited(int n, ...);
+void takeCFConsumedUnaudited(CFStringRef __attribute__((cf_consumed)) arg);
+#pragma clang arc_cf_code_audited begin
+void takeCFOrdinaryAudited(CFStringRef arg);
+void takeCFVariadicAudited(int n, ...);
+void takeCFConsumedAudited(CFStringRef __attribute__((cf_consumed)) arg);
+#pragma clang arc_cf_code_audited end
+
+void testTakerFunctions(id string) {
+  takeCFOrdinaryUnaudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFVariadicUnaudited(1, (CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFConsumedUnaudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  void (*taker)(CFStringRef) = 0;
+  taker((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  takeCFOrdinaryAudited((CFStringRef) string);
+  takeCFVariadicAudited(1, (CFStringRef) string);
+  takeCFConsumedAudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}





More information about the cfe-commits mailing list