[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