[cfe-commits] r134273 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/Sema/Sema.h lib/AST/ASTContext.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/SemaCXXCast.cpp lib/Sema/SemaType.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp test/SemaObjCXX/arc-type-conversion.mm
Argyrios Kyrtzidis
akyrtzi at gmail.com
Fri Jul 1 15:22:50 PDT 2011
Author: akirtzidis
Date: Fri Jul 1 17:22:50 2011
New Revision: 134273
URL: http://llvm.org/viewvc/llvm-project?rev=134273&view=rev
Log:
[ARC] When casting from a pointer to an objective-c object with known ownership, if the
cast type has no ownership specified, implicitly "transfer" the ownership of the cast'ed type
to the cast type:
id x;
static_cast<NSString**>(&x); // Casting as (__strong NSString**).
This currently only works for C++ named casts, C casts to follow.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/Parse/ParseExprCXX.cpp
cfe/trunk/lib/Sema/SemaCXXCast.cpp
cfe/trunk/lib/Sema/SemaType.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
cfe/trunk/test/SemaObjCXX/arc-type-conversion.mm
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=134273&r1=134272&r2=134273&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Jul 1 17:22:50 2011
@@ -1347,6 +1347,10 @@
/// integer type.
QualType getPromotedIntegerType(QualType PromotableType) const;
+ /// \brief Recurses in pointer/array types until it finds an objc retainable
+ /// type and returns its ownership.
+ Qualifiers::ObjCLifetime getInnerObjCOwnership(QualType T) const;
+
/// \brief Whether this is a promotable bitfield reference according
/// to C99 6.3.1.1p2, bullet 2 (and GCC extensions).
///
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=134273&r1=134272&r2=134273&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Jul 1 17:22:50 2011
@@ -783,6 +783,7 @@
QualType BuildParenType(QualType T);
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
+ TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo);
/// \brief Package the given type and TSI into a ParsedType.
@@ -2825,7 +2826,7 @@
ExprResult ActOnCXXNamedCast(SourceLocation OpLoc,
tok::TokenKind Kind,
SourceLocation LAngleBracketLoc,
- ParsedType Ty,
+ Declarator &D,
SourceLocation RAngleBracketLoc,
SourceLocation LParenLoc,
Expr *E,
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=134273&r1=134272&r2=134273&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Jul 1 17:22:50 2011
@@ -3512,6 +3512,25 @@
return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy;
}
+/// \brief Recurses in pointer/array types until it finds an objc retainable
+/// type and returns its ownership.
+Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const {
+ while (!T.isNull()) {
+ if (T.getObjCLifetime() != Qualifiers::OCL_None)
+ return T.getObjCLifetime();
+ if (T->isArrayType())
+ T = getBaseElementType(T);
+ else if (const PointerType *PT = T->getAs<PointerType>())
+ T = PT->getPointeeType();
+ else if (const ReferenceType *RT = T->getAs<ReferenceType>())
+ RT->getPointeeType();
+ else
+ break;
+ }
+
+ return Qualifiers::OCL_None;
+}
+
/// getIntegerTypeOrder - Returns the highest ranked integer type:
/// C99 6.3.1.8p1. If LHS > RHS, return 1. If LHS == RHS, return 0. If
/// LHS < RHS, return -1.
Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=134273&r1=134272&r2=134273&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Jul 1 17:22:50 2011
@@ -538,7 +538,14 @@
if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
return ExprError();
- TypeResult CastTy = ParseTypeName();
+ // Parse the common declaration-specifiers piece.
+ DeclSpec DS(AttrFactory);
+ ParseSpecifierQualifierList(DS);
+
+ // Parse the abstract-declarator, if present.
+ Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
+ ParseDeclarator(DeclaratorInfo);
+
SourceLocation RAngleBracketLoc = Tok.getLocation();
if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
@@ -554,9 +561,9 @@
// Match the ')'.
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
- if (!Result.isInvalid() && !CastTy.isInvalid())
+ if (!Result.isInvalid() && !DeclaratorInfo.isInvalidType())
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
- LAngleBracketLoc, CastTy.get(),
+ LAngleBracketLoc, DeclaratorInfo,
RAngleBracketLoc,
LParenLoc, Result.take(), RParenLoc);
Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=134273&r1=134272&r2=134273&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Fri Jul 1 17:22:50 2011
@@ -134,17 +134,23 @@
/// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's.
ExprResult
Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
- SourceLocation LAngleBracketLoc, ParsedType Ty,
+ SourceLocation LAngleBracketLoc, Declarator &D,
SourceLocation RAngleBracketLoc,
SourceLocation LParenLoc, Expr *E,
SourceLocation RParenLoc) {
-
- TypeSourceInfo *DestTInfo;
- QualType DestType = GetTypeFromParser(Ty, &DestTInfo);
- if (!DestTInfo)
- DestTInfo = Context.getTrivialTypeSourceInfo(DestType, SourceLocation());
- return BuildCXXNamedCast(OpLoc, Kind, DestTInfo, move(E),
+ assert(!D.isInvalidType());
+
+ TypeSourceInfo *TInfo = GetTypeForDeclaratorCast(D, E->getType());
+ if (D.isInvalidType())
+ return ExprError();
+
+ if (getLangOptions().CPlusPlus) {
+ // Check that there are no default arguments (C++ only).
+ CheckExtraCXXDefaultArguments(D);
+ }
+
+ return BuildCXXNamedCast(OpLoc, Kind, TInfo, move(E),
SourceRange(LAngleBracketLoc, RAngleBracketLoc),
SourceRange(LParenLoc, RParenLoc));
}
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=134273&r1=134272&r2=134273&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Jul 1 17:22:50 2011
@@ -2534,6 +2534,117 @@
return GetFullTypeForDeclarator(state, T, ReturnTypeInfo);
}
+static void transferARCOwnershipToDeclSpec(Sema &S,
+ QualType &declSpecTy,
+ Qualifiers::ObjCLifetime ownership) {
+ if (declSpecTy->isObjCRetainableType() &&
+ declSpecTy.getObjCLifetime() == Qualifiers::OCL_None) {
+ Qualifiers qs;
+ qs.addObjCLifetime(ownership);
+ declSpecTy = S.Context.getQualifiedType(declSpecTy, qs);
+ }
+ return;
+}
+
+static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
+ Qualifiers::ObjCLifetime ownership,
+ unsigned chunkIndex) {
+ Sema &S = state.getSema();
+ Declarator &D = state.getDeclarator();
+
+ // Look for an explicit lifetime attribute.
+ DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
+ for (const AttributeList *attr = chunk.getAttrs(); attr;
+ attr = attr->getNext())
+ if (attr->getKind() == AttributeList::AT_objc_ownership)
+ return;
+
+ const char *attrStr = 0;
+ switch (ownership) {
+ case Qualifiers::OCL_None: llvm_unreachable("no ownership!"); break;
+ case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break;
+ case Qualifiers::OCL_Strong: attrStr = "strong"; break;
+ case Qualifiers::OCL_Weak: attrStr = "weak"; break;
+ case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break;
+ }
+ if (!attrStr)
+ return;
+
+ // If there wasn't one, add one (with an invalid source location
+ // so that we don't make an AttributedType for it).
+ AttributeList *attr = D.getAttributePool()
+ .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
+ /*scope*/ 0, SourceLocation(),
+ &S.Context.Idents.get(attrStr), SourceLocation(),
+ /*args*/ 0, 0,
+ /*declspec*/ false, /*C++0x*/ false);
+ spliceAttrIntoList(*attr, chunk.getAttrListRef());
+
+ // TODO: mark whether we did this inference?
+}
+
+static void transferARCOwnership(TypeProcessingState &state,
+ QualType &declSpecTy,
+ Qualifiers::ObjCLifetime ownership) {
+ Sema &S = state.getSema();
+ Declarator &D = state.getDeclarator();
+
+ int inner = -1;
+ for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
+ DeclaratorChunk &chunk = D.getTypeObject(i);
+ switch (chunk.Kind) {
+ case DeclaratorChunk::Paren:
+ // Ignore parens.
+ break;
+
+ case DeclaratorChunk::Array:
+ case DeclaratorChunk::Reference:
+ case DeclaratorChunk::Pointer:
+ inner = i;
+ break;
+
+ case DeclaratorChunk::BlockPointer:
+ return transferARCOwnershipToDeclaratorChunk(state, ownership, i);
+
+ case DeclaratorChunk::Function:
+ case DeclaratorChunk::MemberPointer:
+ return;
+ }
+ }
+
+ if (inner == -1)
+ return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
+
+ DeclaratorChunk &chunk = D.getTypeObject(inner);
+ if (chunk.Kind == DeclaratorChunk::Pointer) {
+ if (declSpecTy->isObjCRetainableType())
+ return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
+ if (declSpecTy->isObjCObjectType())
+ return transferARCOwnershipToDeclaratorChunk(state, ownership, inner);
+ } else {
+ assert(chunk.Kind == DeclaratorChunk::Array ||
+ chunk.Kind == DeclaratorChunk::Reference);
+ return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
+ }
+}
+
+TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
+ TypeProcessingState state(*this, D);
+
+ TypeSourceInfo *ReturnTypeInfo = 0;
+ QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
+ if (declSpecTy.isNull())
+ return Context.getNullTypeSourceInfo();
+
+ if (getLangOptions().ObjCAutoRefCount) {
+ Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
+ if (ownership != Qualifiers::OCL_None)
+ transferARCOwnership(state, declSpecTy, ownership);
+ }
+
+ return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
+}
+
/// Map an AttributedType::Kind to an AttributeList::Kind.
static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
switch (kind) {
Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp?rev=134273&r1=134272&r2=134273&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp Fri Jul 1 17:22:50 2011
@@ -46,7 +46,7 @@
U<auto> v; // expected-error{{'auto' not allowed in template argument}}
int n;
- (void)dynamic_cast<auto&>(S()); // expected-error{{'auto' not allowed here}}
+ (void)dynamic_cast<auto&>(n); // expected-error{{'auto' not allowed here}}
(void)static_cast<auto*>(&n); // expected-error{{'auto' not allowed here}}
(void)reinterpret_cast<auto*>(&n); // expected-error{{'auto' not allowed here}}
(void)const_cast<auto>(n); // expected-error{{'auto' not allowed here}}
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=134273&r1=134272&r2=134273&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/arc-type-conversion.mm (original)
+++ cfe/trunk/test/SemaObjCXX/arc-type-conversion.mm Fri Jul 1 17:22:50 2011
@@ -42,8 +42,7 @@
(void)static_cast<int*>(arg); // expected-error {{cannot cast from type 'id' to pointer type 'int *'}}
(void)static_cast<id>(arg);
(void)static_cast<__autoreleasing id*>(arg); // expected-error{{cannot cast from type 'id' to pointer type '__autoreleasing id *'}}
- (void)static_cast<id*>(arg); // expected-error {{cannot cast from type 'id' to pointer type '__autoreleasing id *'}} \
- // expected-error{{pointer to non-const type 'id' with no explicit ownership}}
+ (void)static_cast<id*>(arg); // expected-error {{cannot cast from type 'id' to pointer type '__strong id *'}}
(void)static_cast<__autoreleasing id**>(voidp_val);
(void)static_cast<void*>(voidp_val);
@@ -196,3 +195,24 @@
aip = vp; // expected-error{{assigning to '__autoreleasing id *' from incompatible type 'void *'}}
uip = vp; // expected-error{{assigning to '__unsafe_unretained id *' from incompatible type 'void *'}}
}
+
+typedef void (^Block)();
+typedef void (^Block_strong)() __strong;
+typedef void (^Block_autoreleasing)() __autoreleasing;
+
+ at class NSString;
+
+void ownership_transfer_in_cast(void *vp, Block *pblk) {
+ __strong NSString **sip2 = static_cast<NSString **>(static_cast<__strong id *>(vp));
+ __weak NSString **wip2 = static_cast<NSString **>(static_cast<__weak id *>(vp));
+ __autoreleasing id *aip2 = static_cast<id *>(static_cast<__autoreleasing id *>(vp));
+ __unsafe_unretained id *uip2 = static_cast<id *>(static_cast<__unsafe_unretained id *>(vp));
+ __strong id *sip3 = reinterpret_cast<id *>(reinterpret_cast<__strong id *>(vp));
+ __weak id *wip3 = reinterpret_cast<id *>(reinterpret_cast<__weak id *>(vp));
+ __autoreleasing id *aip3 = reinterpret_cast<id *>(reinterpret_cast<__autoreleasing id *>(vp));
+ __unsafe_unretained id *uip3 = reinterpret_cast<id *>(reinterpret_cast<__unsafe_unretained id *>(vp));
+
+ Block_strong blk_strong1;
+ Block_strong blk_strong2 = static_cast<Block>(blk_strong1);
+ Block_autoreleasing *blk_auto = static_cast<Block*>(pblk);
+}
More information about the cfe-commits
mailing list