unsigned ElideConstructors : 1; // Whether C++ copy constructors should be
// elided if possible.
+ unsigned ObjCNewGCAPI : 1; // Generate objective-c's new GC API
private:
unsigned GC : 2; // Objective-C Garbage Collection modes. We
// declare this enum as unsigned because MSVC
OverflowChecking = 0;
ObjCGCBitmapPrint = 0;
+ ObjCNewGCAPI = 0;
InstantiationDepth = 99;
Builder.CreateStore(Vec, Dst.getExtVectorAddr(), Dst.isVolatileQualified());
}
+// setObjCGCLValueClass - sets class of he lvalue for the purpose of
+// generating write-barries API. It is currently a global, ivar,
+// or neither.
+static
+void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
+ if (Ctx.getLangOptions().getGCMode() == LangOptions::NonGC ||
+ !Ctx.getLangOptions().ObjCNewGCAPI)
+ return;
+
+ if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
+ if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
+ if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
+ VD->isFileVarDecl())
+ LV.SetGlobalObjCRef(LV, true);
+ }
+ }
+ else if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E))
+ setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+ else if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E))
+ setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+ else if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E))
+ setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+ else if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E))
+ setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+ else if (const ArraySubscriptExpr *Exp = dyn_cast<ArraySubscriptExpr>(E))
+ setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
+ else if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
+ setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
+ }
+}
+
LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl());
E->getType().getAddressSpace());
}
LValue::SetObjCNonGC(LV, NonGCable);
+ setObjCGCLValueClass(getContext(), E, LV);
return LV;
} else if (VD && VD->isFileVarDecl()) {
llvm::Value *V = CGM.GetAddrOfGlobalVar(VD);
LValue LV = LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()),
E->getType().getAddressSpace());
- LV.SetGlobalObjCRef(LV, true);
+ setObjCGCLValueClass(getContext(), E, LV);
return LV;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
llvm::Value* V = CGM.GetAddrOfFunction(FD);
getContext().getObjCGCAttrKind(T),
E->getBase()->getType().getAddressSpace());
if (getContext().getLangOptions().ObjC1 &&
- getContext().getLangOptions().getGCMode() != LangOptions::NonGC)
+ getContext().getLangOptions().getGCMode() != LangOptions::NonGC) {
LValue::SetObjCNonGC(LV, !E->isOBJCGCCandidate(getContext()));
+ setObjCGCLValueClass(getContext(), E, LV);
+ }
return LV;
}
CVRQualifiers);
LValue::SetObjCIvar(MemExpLV, isIvar);
LValue::SetObjCNonGC(MemExpLV, isNonGC);
+ setObjCGCLValueClass(getContext(), E, MemExpLV);
return MemExpLV;
}
-// RUN: clang-cc -fnext-runtime -fobjc-gc -emit-llvm -o %t %s &&
-// RUN: grep -F '@objc_assign_global' %t | count 2 &&
+// RUN: clang-cc -fnext-runtime -fobjc-gc -fobjc-newgc-api -emit-llvm -o %t %s &&
+// RUN: grep -F '@objc_assign_global' %t | count 26 &&
// RUN: true
-id a;
+
+@class NSObject;
+typedef const struct __CFDictionary * CFDictionaryRef;
+typedef struct {
+ id element;
+ id elementArray[10];
+ __strong CFDictionaryRef cfElement;
+ __strong CFDictionaryRef cfElementArray[10];
+} struct_with_ids_t;
+
+
+// assignments to these should generate objc_assign_global
+@interface A
+@end
+
+typedef struct s0 {
+ A *a[4];
+} T;
+
+T g0;
+
+extern id FileExternID;
+static id FileStaticID;
+id GlobalId;
+id GlobalArray[20];
+NSObject *GlobalObject;
+NSObject *GlobalObjectArray[20];
+__strong CFDictionaryRef Gdict;
+__strong CFDictionaryRef Gdictarray[10];
+struct_with_ids_t GlobalStruct;
+struct_with_ids_t GlobalStructArray[10];
+
+#define ASSIGNTEST(expr, global) expr = rhs
+void *rhs = 0;
+
int main() {
- a = 0;
+ static id staticGlobalId;
+ static id staticGlobalArray[20];
+ static NSObject *staticGlobalObject;
+ static NSObject *staticGlobalObjectArray[20];
+ static __strong CFDictionaryRef staticGdict;
+ static __strong CFDictionaryRef staticGdictarray[10];
+ static struct_with_ids_t staticGlobalStruct;
+ static struct_with_ids_t staticGlobalStructArray[10];
+ extern id ExID;
+ id localID;
+
+ ASSIGNTEST(GlobalId, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalObject, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalObjectArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(Gdict, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(Gdictarray[1], GlobalAssigns); // objc_assign_global
+
+ ASSIGNTEST(GlobalStruct.element, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalStruct.cfElement, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(GlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global
+
+ ASSIGNTEST(staticGlobalId, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalObject, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalObjectArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGdict, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGdictarray[1], GlobalAssigns); // objc_assign_global
+
+ ASSIGNTEST(staticGlobalStruct.element, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalStruct.elementArray[0], GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalStruct.cfElement, GlobalAssigns); // objc_assign_global
+ ASSIGNTEST(staticGlobalStruct.cfElementArray[0], GlobalAssigns); // objc_assign_global
+
+ ExID = 0;
+ localID = 0;
+ FileStaticID = 0;
+ FileExternID=0;
+ g0.a[0] = 0;
+ ((T*) &g0)->a[0] = 0;
}
ObjCEnableGC("fobjc-gc",
llvm::cl::desc("Enable Objective-C garbage collection"));
+static llvm::cl::opt<bool>
+ObjCEnableNewGCAPI("fobjc-newgc-api",
+ llvm::cl::desc("Enable Objective-C garbage collection's new API"));
+
static llvm::cl::opt<bool>
ObjCEnableGCBitmapPrint("print-ivar-layout",
llvm::cl::desc("Enable Objective-C Ivar layout bitmap print trace"));
else if (ObjCEnableGC)
Options.setGCMode(LangOptions::HybridGC);
+ if (ObjCEnableNewGCAPI)
+ Options.ObjCNewGCAPI = 1;
+
if (ObjCEnableGCBitmapPrint)
Options.ObjCGCBitmapPrint = 1;