[arcmt] In GC, error out when there is a call that returns a pointer to
GC managed non-objc object memory. llvm-svn: 143747
This commit is contained in:
parent
b0a48e1dd8
commit
6b2d47d829
|
@ -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())) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -82,6 +82,8 @@ public:
|
|||
Traversers.push_back(traverser);
|
||||
}
|
||||
|
||||
bool isGCOwnedNonObjC(QualType T);
|
||||
|
||||
void traverse(TranslationUnitDecl *TU);
|
||||
};
|
||||
|
||||
|
|
|
@ -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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue