Support basic array destructors for RS types.
Bug: 3092382
Change-Id: I8f39672eb9ce4bae6aeb91f186f72def083aa6c1
diff --git a/slang_rs_object_ref_count.cpp b/slang_rs_object_ref_count.cpp
index f296dcb..e2bce4f 100644
--- a/slang_rs_object_ref_count.cpp
+++ b/slang_rs_object_ref_count.cpp
@@ -98,10 +98,9 @@
// TODO(srhines): This should also handle the case of goto/break/continue.
clang::CompoundStmt::body_iterator bI = CS->body_begin();
- clang::CompoundStmt::body_iterator bE = CS->body_end();
unsigned OldStmtCount = 0;
- for (bI = CS->body_begin(); bI != bE; bI++) {
+ for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
OldStmtCount++;
}
@@ -112,7 +111,7 @@
unsigned UpdatedStmtCount = 0;
bool FoundReturn = false;
- for (bI = CS->body_begin(); bI != bE; bI++) {
+ for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
FoundReturn = true;
break;
@@ -123,17 +122,16 @@
// Always insert before a return that we found, or if we are told
// to insert at the end of the block
if (FoundReturn || InsertAtEndOfBlock) {
- std::list<clang::Stmt*>::const_iterator E = StmtList.end();
- for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin(),
- E = StmtList.end();
- I != E;
+ std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
+ for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
+ I != StmtList.end();
I++) {
UpdatedStmtList[UpdatedStmtCount++] = *I;
}
}
// Pick up anything left over after a return statement
- for ( ; bI != bE; bI++) {
+ for ( ; bI != CS->body_end(); bI++) {
UpdatedStmtList[UpdatedStmtCount++] = *bI;
}
@@ -190,6 +188,192 @@
return;
}
+static int ArrayDim(clang::VarDecl *VD) {
+ const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
+
+ if (!T || !T->isArrayType()) {
+ return 0;
+ }
+
+ const clang::ConstantArrayType *CAT =
+ static_cast<const clang::ConstantArrayType *>(T);
+ return (int)CAT->getSize().getSExtValue();
+}
+
+static clang::Stmt *ClearArrayRSObject(clang::VarDecl *VD,
+ const clang::Type *T,
+ clang::FunctionDecl *ClearObjectFD) {
+ clang::ASTContext &C = VD->getASTContext();
+ clang::SourceRange Range = VD->getQualifierRange();
+ clang::SourceLocation Loc = Range.getEnd();
+
+ clang::Stmt *StmtArray[2] = {NULL};
+ int StmtCtr = 0;
+
+ int NumArrayElements = ArrayDim(VD);
+ if (NumArrayElements <= 0) {
+ return NULL;
+ }
+
+ // Example destructor loop for "rs_font fontArr[10];"
+ //
+ // (CompoundStmt
+ // (DeclStmt "int rsIntIter")
+ // (ForStmt
+ // (BinaryOperator 'int' '='
+ // (DeclRefExpr 'int' Var='rsIntIter')
+ // (IntegerLiteral 'int' 0))
+ // (BinaryOperator 'int' '<'
+ // (DeclRefExpr 'int' Var='rsIntIter')
+ // (IntegerLiteral 'int' 10)
+ // NULL << CondVar >>
+ // (UnaryOperator 'int' postfix '++'
+ // (DeclRefExpr 'int' Var='rsIntIter'))
+ // (CallExpr 'void'
+ // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
+ // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
+ // (UnaryOperator 'rs_font *' prefix '&'
+ // (ArraySubscriptExpr 'rs_font':'rs_font'
+ // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
+ // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
+ // (DeclRefExpr 'int' Var='rsIntIter')))))))
+
+ // Create helper variable for iterating through elements
+ clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
+ clang::VarDecl *IIVD =
+ clang::VarDecl::Create(C,
+ VD->getDeclContext(),
+ Loc,
+ &II,
+ C.IntTy,
+ C.getTrivialTypeSourceInfo(C.IntTy),
+ clang::SC_None,
+ clang::SC_None);
+ clang::Decl *IID = (clang::Decl *)IIVD;
+
+ clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
+ StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
+
+ // Form the actual destructor loop
+ // for (Init; Cond; Inc)
+ // RSClearObjectCall;
+
+ // Init -> "rsIntIter = 0"
+ clang::DeclRefExpr *RefrsIntIter =
+ clang::DeclRefExpr::Create(C,
+ NULL,
+ Range,
+ IIVD,
+ Loc,
+ C.IntTy);
+
+ clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
+ llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
+
+ clang::BinaryOperator *Init =
+ new(C) clang::BinaryOperator(RefrsIntIter,
+ Int0,
+ clang::BO_Assign,
+ C.IntTy,
+ Loc);
+
+ // Cond -> "rsIntIter < NumArrayElements"
+ clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
+ llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
+
+ clang::BinaryOperator *Cond =
+ new(C) clang::BinaryOperator(RefrsIntIter,
+ NumArrayElementsExpr,
+ clang::BO_LT,
+ C.IntTy,
+ Loc);
+
+ // Inc -> "rsIntIter++"
+ clang::UnaryOperator *Inc =
+ new(C) clang::UnaryOperator(RefrsIntIter,
+ clang::UO_PostInc,
+ C.IntTy,
+ Loc);
+
+ // Body -> "rsClearObject(&VD[rsIntIter]);"
+ // Destructor loop operates on individual array elements
+ clang::QualType ClearObjectFDType = ClearObjectFD->getType();
+ clang::QualType ClearObjectFDArgType =
+ ClearObjectFD->getParamDecl(0)->getOriginalType();
+
+ const clang::Type *VT = RSExportType::GetTypeOfDecl(VD);
+ clang::DeclRefExpr *RefRSVar =
+ clang::DeclRefExpr::Create(C,
+ NULL,
+ Range,
+ VD,
+ Loc,
+ VT->getCanonicalTypeInternal());
+
+ clang::Expr *RefRSVarPtr =
+ clang::ImplicitCastExpr::Create(C,
+ C.getPointerType(T->getCanonicalTypeInternal()),
+ clang::CK_ArrayToPointerDecay,
+ RefRSVar,
+ NULL,
+ clang::VK_RValue);
+
+ clang::Expr *RefRSVarPtrSubscript =
+ new(C) clang::ArraySubscriptExpr(RefRSVarPtr,
+ RefrsIntIter,
+ T->getCanonicalTypeInternal(),
+ VD->getLocation());
+
+ clang::Expr *AddrRefRSVarPtrSubscript =
+ new(C) clang::UnaryOperator(RefRSVarPtrSubscript,
+ clang::UO_AddrOf,
+ ClearObjectFDArgType,
+ VD->getLocation());
+
+ clang::Expr *RefRSClearObjectFD =
+ clang::DeclRefExpr::Create(C,
+ NULL,
+ Range,
+ ClearObjectFD,
+ Loc,
+ ClearObjectFDType);
+
+ clang::Expr *RSClearObjectFP =
+ clang::ImplicitCastExpr::Create(C,
+ C.getPointerType(ClearObjectFDType),
+ clang::CK_FunctionToPointerDecay,
+ RefRSClearObjectFD,
+ NULL,
+ clang::VK_RValue);
+
+ clang::CallExpr *RSClearObjectCall =
+ new(C) clang::CallExpr(C,
+ RSClearObjectFP,
+ &AddrRefRSVarPtrSubscript,
+ 1,
+ ClearObjectFD->getCallResultType(),
+ Loc);
+
+ clang::ForStmt *DestructorLoop =
+ new(C) clang::ForStmt(C,
+ Init,
+ Cond,
+ NULL, // no condVar
+ Inc,
+ RSClearObjectCall,
+ Loc,
+ Loc,
+ Loc);
+
+ StmtArray[StmtCtr++] = DestructorLoop;
+ assert(StmtCtr == 2);
+
+ clang::CompoundStmt *CS =
+ new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
+
+ return CS;
+}
+
} // namespace
void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
@@ -211,9 +395,17 @@
}
clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
+ bool IsArrayType = false;
clang::ASTContext &C = VD->getASTContext();
clang::SourceLocation Loc = VD->getLocation();
const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
+
+ // Loop through array types to get to base type
+ while (T && T->isArrayType()) {
+ T = T->getArrayElementTypeNoTypeQual();
+ IsArrayType = true;
+ }
+
RSExportPrimitiveType::DataType DT =
RSExportPrimitiveType::GetRSSpecificType(T);
@@ -226,16 +418,21 @@
assert((ClearObjectFD != NULL) &&
"rsClearObject doesn't cover all RS object types");
+ if (IsArrayType) {
+ return ClearArrayRSObject(VD, T, ClearObjectFD);
+ }
+
clang::QualType ClearObjectFDType = ClearObjectFD->getType();
clang::QualType ClearObjectFDArgType =
ClearObjectFD->getParamDecl(0)->getOriginalType();
- // We generate a call to rsClearObject passing &VD as the parameter
+ // Example destructor for "rs_font localFont;"
+ //
// (CallExpr 'void'
// (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
// (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
// (UnaryOperator 'rs_font *' prefix '&'
- // (DeclRefExpr 'rs_font':'rs_font' Var='[var name]')))
+ // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
// Reference expr to target RS object variable
clang::DeclRefExpr *RefRSVar =
@@ -244,8 +441,7 @@
VD->getQualifierRange(),
VD,
Loc,
- T->getCanonicalTypeInternal(),
- NULL);
+ T->getCanonicalTypeInternal());
// Get address of RSObject in VD
clang::Expr *AddrRefRSVar =
@@ -260,8 +456,7 @@
ClearObjectFD->getQualifierRange(),
ClearObjectFD,
ClearObjectFD->getLocation(),
- ClearObjectFDType,
- NULL);
+ ClearObjectFDType);
clang::Expr *RSClearObjectFP =
clang::ImplicitCastExpr::Create(C,
@@ -314,9 +509,7 @@
}
}
- // TODO(srhines): Skip returning true in the case of array objects because
- // we don't have looping destructor support yet.
- return !IsArrayType && RSExportPrimitiveType::IsRSObjectType(DT);
+ return RSExportPrimitiveType::IsRSObjectType(DT);
}
clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(