diff options
author | John McCall <rjmccall@apple.com> | 2011-06-24 23:21:27 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-06-24 23:21:27 +0000 |
commit | 0c24c808e4dce43e88abf2d5f98546b901bd4315 (patch) | |
tree | e4f8276e99677f144f3e5a4dfda860369e67da2f /lib/CodeGen/CGDecl.cpp | |
parent | 537c3461166ce074d05fb7c96ffa98ed54c9aaa0 (diff) |
Honor objc_precise_lifetime in GC mode by feeding the value
in the variable to an inline asm which gets run when the variable
goes out of scope.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133840 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGDecl.cpp')
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index b6ad130a40..7e126d95e1 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -364,6 +364,20 @@ namespace { } }; + struct ExtendGCLifetime : EHScopeStack::Cleanup { + const VarDecl &Var; + ExtendGCLifetime(const VarDecl *var) : Var(*var) {} + + void Emit(CodeGenFunction &CGF, bool forEH) { + // Compute the address of the local variable, in case it's a + // byref or something. + DeclRefExpr DRE(const_cast<VarDecl*>(&Var), Var.getType(), VK_LValue, + SourceLocation()); + llvm::Value *value = CGF.EmitLoadOfScalar(CGF.EmitDeclRefLValue(&DRE)); + CGF.EmitExtendGCLifetime(value); + } + }; + struct CallCleanupFunction : EHScopeStack::Cleanup { llvm::Constant *CleanupFn; const CGFunctionInfo &FnInfo; @@ -1029,6 +1043,12 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { } } + // In GC mode, honor objc_precise_lifetime. + if (getLangOptions().getGCMode() != LangOptions::NonGC && + D.hasAttr<ObjCPreciseLifetimeAttr>()) { + EHStack.pushCleanup<ExtendGCLifetime>(NormalCleanup, &D); + } + // Handle the cleanup attribute. if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) { const FunctionDecl *FD = CA->getFunctionDecl(); |