diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-11-04 23:43:03 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-11-04 23:43:03 +0000 |
commit | 6b2d47d8299ffd74c4418936da2322ce988340f5 (patch) | |
tree | 03f5ef2b90816eccb0076519ab5a3621e4d3fa8b | |
parent | b0a48e1dd808fb95d46cc3f80089ea3b08a49ed6 (diff) | |
download | bcm5719-llvm-6b2d47d8299ffd74c4418936da2322ce988340f5.tar.gz bcm5719-llvm-6b2d47d8299ffd74c4418936da2322ce988340f5.zip |
[arcmt] In GC, error out when there is a call that returns a pointer to
GC managed non-objc object memory.
llvm-svn: 143747
-rw-r--r-- | clang/lib/ARCMigrate/TransGCCalls.cpp | 7 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/TransformActions.cpp | 14 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/Transforms.cpp | 20 | ||||
-rw-r--r-- | clang/lib/ARCMigrate/Transforms.h | 2 | ||||
-rw-r--r-- | clang/test/ARCMT/GC-check.m | 3 |
5 files changed, 46 insertions, 0 deletions
diff --git a/clang/lib/ARCMigrate/TransGCCalls.cpp b/clang/lib/ARCMigrate/TransGCCalls.cpp index 8042c6caba7..94e965df188 100644 --- a/clang/lib/ARCMigrate/TransGCCalls.cpp +++ b/clang/lib/ARCMigrate/TransGCCalls.cpp @@ -35,6 +35,13 @@ public: bool VisitCallExpr(CallExpr *E) { TransformActions &TA = MigrateCtx.getPass().TA; + if (MigrateCtx.isGCOwnedNonObjC(E->getType())) { + TA.reportError("call returns pointer to GC managed memory; " + "it will become unmanaged in ARC", + E->getLocStart(), E->getSourceRange()); + return true; + } + Expr *CEE = E->getCallee()->IgnoreParenImpCasts(); if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) { if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl())) { diff --git a/clang/lib/ARCMigrate/TransformActions.cpp b/clang/lib/ARCMigrate/TransformActions.cpp index ec676e909a3..7ad9b6005dc 100644 --- a/clang/lib/ARCMigrate/TransformActions.cpp +++ b/clang/lib/ARCMigrate/TransformActions.cpp @@ -122,6 +122,8 @@ public: ASTContext &ctx, Preprocessor &PP) : CapturedDiags(capturedDiags), Ctx(ctx), PP(PP), IsInTransaction(false) { } + ASTContext &getASTContext() { return Ctx; } + void startTransaction(); bool commitTransaction(); void abortTransaction(); @@ -674,6 +676,12 @@ void TransformActions::reportError(StringRef error, SourceLocation loc, SourceRange range) { assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() && "Errors should be emitted out of a transaction"); + + SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)-> + getASTContext().getSourceManager(); + if (SM.isInSystemHeader(SM.getExpansionLoc(loc))) + return; + // FIXME: Use a custom category name to distinguish rewriter errors. std::string rewriteErr = "[rewriter] "; rewriteErr += error; @@ -688,6 +696,12 @@ void TransformActions::reportNote(StringRef note, SourceLocation loc, SourceRange range) { assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() && "Errors should be emitted out of a transaction"); + + SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)-> + getASTContext().getSourceManager(); + if (SM.isInSystemHeader(SM.getExpansionLoc(loc))) + return; + // FIXME: Use a custom category name to distinguish rewriter errors. std::string rewriteNote = "[rewriter] "; rewriteNote += note; diff --git a/clang/lib/ARCMigrate/Transforms.cpp b/clang/lib/ARCMigrate/Transforms.cpp index 0decdd6b43b..d0c9bc69c85 100644 --- a/clang/lib/ARCMigrate/Transforms.cpp +++ b/clang/lib/ARCMigrate/Transforms.cpp @@ -324,6 +324,26 @@ MigrationContext::~MigrationContext() { delete *I; } +bool MigrationContext::isGCOwnedNonObjC(QualType T) { + while (!T.isNull()) { + if (const AttributedType *AttrT = T->getAs<AttributedType>()) { + if (AttrT->getAttrKind() == AttributedType::attr_objc_ownership) + return !AttrT->getModifiedType()->isObjCRetainableType(); + } + + if (T->isArrayType()) + T = Pass.Ctx.getBaseElementType(T); + else if (const PointerType *PT = T->getAs<PointerType>()) + T = PT->getPointeeType(); + else if (const ReferenceType *RT = T->getAs<ReferenceType>()) + T = RT->getPointeeType(); + else + break; + } + + return false; +} + void MigrationContext::traverse(TranslationUnitDecl *TU) { ASTTransform(*this).TraverseDecl(TU); } diff --git a/clang/lib/ARCMigrate/Transforms.h b/clang/lib/ARCMigrate/Transforms.h index d935e86ae73..515844656a0 100644 --- a/clang/lib/ARCMigrate/Transforms.h +++ b/clang/lib/ARCMigrate/Transforms.h @@ -82,6 +82,8 @@ public: Traversers.push_back(traverser); } + bool isGCOwnedNonObjC(QualType T); + void traverse(TranslationUnitDecl *TU); }; diff --git a/clang/test/ARCMT/GC-check.m b/clang/test/ARCMT/GC-check.m index 0d5e878d761..f71787ce029 100644 --- a/clang/test/ARCMT/GC-check.m +++ b/clang/test/ARCMT/GC-check.m @@ -2,10 +2,13 @@ // RUN: %clang_cc1 -arcmt-check -verify -triple x86_64-apple-darwin10 -fobjc-gc-only -x objective-c++ %s #define CF_AUTOMATED_REFCOUNT_UNAVAILABLE __attribute__((unavailable("not available in automatic reference counting mode"))) +typedef unsigned NSUInteger; typedef const void * CFTypeRef; CFTypeRef CFMakeCollectable(CFTypeRef cf) CF_AUTOMATED_REFCOUNT_UNAVAILABLE; // expected-note {{unavailable}} +void *__strong NSAllocateCollectable(NSUInteger size, NSUInteger options); void test1(CFTypeRef *cft) { CFTypeRef c = CFMakeCollectable(cft); // expected-error {{CFMakeCollectable will leak the object that it receives in ARC}} \ // expected-error {{unavailable}} + NSAllocateCollectable(100, 0); // expected-error {{call returns pointer to GC managed memory; it will become unmanaged in ARC}} } |