slang_rs_object_ref_count.cpp revision 03981a308201b9123512297c8b9562a0f29bdf31
14b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines/*
24b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Copyright 2010, The Android Open Source Project
34b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
44b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
54b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * you may not use this file except in compliance with the License.
64b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * You may obtain a copy of the License at
74b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
84b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *     http://www.apache.org/licenses/LICENSE-2.0
94b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines *
104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * Unless required by applicable law or agreed to in writing, software
114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * See the License for the specific language governing permissions and
144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines * limitations under the License.
154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines */
164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_object_ref_count.h"
184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <list>
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/DeclGroup.h"
224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Expr.h"
234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/OperationKinds.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Stmt.h"
254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs.h"
284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
30e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::FunctionDecl *RSObjectRefCount::Scope::
331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                  RSExportPrimitiveType::FirstRSObjectType + 1];
351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::FunctionDecl *RSObjectRefCount::Scope::
361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                    RSExportPrimitiveType::FirstRSObjectType + 1];
381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::GetRSRefCountingFunctions(
401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::ASTContext &C) {
411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (unsigned i = 0;
421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i++) {
441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[i] = NULL;
451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[i] = NULL;
461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        assert((FD->getNumParams() == 2) &&
611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines               "Invalid rsSetObject function prototype (# params)");
621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        assert((FD->getNumParams() == 1) &&
651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines               "Invalid rsClearObject function prototype (# params)");
661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
67e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      } else {
681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      assert(PVT->isPointerType() &&
751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             "Invalid rs{Set,Clear}Object function prototype (pointer param)");
761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::DataType DT =
801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      assert(RSExportPrimitiveType::IsRSObjectType(DT)
821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
894464d825c11349068f2917f9ebee86b721423f3cStephen Hinesnamespace {
904464d825c11349068f2917f9ebee86b721423f3cStephen Hines
914464d825c11349068f2917f9ebee86b721423f3cStephen Hinesstatic void AppendToCompoundStatement(clang::ASTContext& C,
924464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      clang::CompoundStmt *CS,
93d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                      std::list<clang::Stmt*> &StmtList,
944464d825c11349068f2917f9ebee86b721423f3cStephen Hines                                      bool InsertAtEndOfBlock) {
951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Destructor code will be inserted before any return statement.
961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Any subsequent statements in the compound statement are then placed
971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // after our new code.
98e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  // TODO(srhines): This should also handle the case of goto/break/continue.
994464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1004464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
1011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned OldStmtCount = 0;
10303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
1041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    OldStmtCount++;
1051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
107d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  unsigned NewStmtCount = StmtList.size();
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
109d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  clang::Stmt **UpdatedStmtList;
110d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount];
1111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned UpdatedStmtCount = 0;
1134464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool FoundReturn = false;
11403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
1151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
1164464d825c11349068f2917f9ebee86b721423f3cStephen Hines      FoundReturn = true;
1171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      break;
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
119d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
1201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1224464d825c11349068f2917f9ebee86b721423f3cStephen Hines  // Always insert before a return that we found, or if we are told
1234464d825c11349068f2917f9ebee86b721423f3cStephen Hines  // to insert at the end of the block
1244464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (FoundReturn || InsertAtEndOfBlock) {
12503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
12603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
12703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines         I != StmtList.end();
1284464d825c11349068f2917f9ebee86b721423f3cStephen Hines         I++) {
129d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *I;
1304464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
1311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Pick up anything left over after a return statement
13403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  for ( ; bI != CS->body_end(); bI++) {
135d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
1361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
138d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
1391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
140d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  delete [] UpdatedStmtList;
1411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
145d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines// This class visits a compound statement and inserts the StmtList containing
1464464d825c11349068f2917f9ebee86b721423f3cStephen Hines// destructors in proper locations. This includes inserting them before any
1474464d825c11349068f2917f9ebee86b721423f3cStephen Hines// return statement in any sub-block, at the end of the logical enclosing
1484464d825c11349068f2917f9ebee86b721423f3cStephen Hines// scope (compound statement), and/or before any break/continue statement that
1494464d825c11349068f2917f9ebee86b721423f3cStephen Hines// would resume outside the declared scope. We will not handle the case for
1504464d825c11349068f2917f9ebee86b721423f3cStephen Hines// goto statements that leave a local scope.
1514464d825c11349068f2917f9ebee86b721423f3cStephen Hines// TODO(srhines): Make this work properly for break/continue.
1524464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
1534464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
1544464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::ASTContext &mC;
155d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> &mStmtList;
1564464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool mTopLevel;
1574464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
158d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
1594464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
1604464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
1614464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
1624464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1634464d825c11349068f2917f9ebee86b721423f3cStephen HinesDestructorVisitor::DestructorVisitor(clang::ASTContext &C,
164d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                     std::list<clang::Stmt*> &StmtList)
1654464d825c11349068f2917f9ebee86b721423f3cStephen Hines  : mC(C),
166d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    mStmtList(StmtList),
1674464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel(true) {
1684464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
1694464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
1704464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1714464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
1724464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (!CS->body_empty()) {
173d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
1744464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel = false;
1754464d825c11349068f2917f9ebee86b721423f3cStephen Hines    VisitStmt(CS);
1764464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
1774464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
1784464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
1794464d825c11349068f2917f9ebee86b721423f3cStephen Hines
1804464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
1814464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1824464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I != E;
1834464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I++) {
1844464d825c11349068f2917f9ebee86b721423f3cStephen Hines    if (clang::Stmt *Child = *I) {
1854464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
1864464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
1874464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
1884464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
1894464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
1904464d825c11349068f2917f9ebee86b721423f3cStephen Hines
19103981a308201b9123512297c8b9562a0f29bdf31Stephen Hinesstatic int ArrayDim(clang::VarDecl *VD) {
19203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
19303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
19403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
19503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
19603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
19703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
19803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
19903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
20003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return (int)CAT->getSize().getSExtValue();
20103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
20203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
20303981a308201b9123512297c8b9562a0f29bdf31Stephen Hinesstatic clang::Stmt *ClearArrayRSObject(clang::VarDecl *VD,
20403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    const clang::Type *T,
20503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    clang::FunctionDecl *ClearObjectFD) {
20603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ASTContext &C = VD->getASTContext();
20703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::SourceRange Range = VD->getQualifierRange();
20803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::SourceLocation Loc = Range.getEnd();
20903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
21003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
21103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int StmtCtr = 0;
21203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
21303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int NumArrayElements = ArrayDim(VD);
21403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
21503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return NULL;
21603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
21703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
21803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
21903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
22003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // (CompoundStmt
22103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (DeclStmt "int rsIntIter")
22203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (ForStmt
22303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '='
22403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
22503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 0))
22603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '<'
22703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
22803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 10)
22903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     NULL << CondVar >>
23003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (UnaryOperator 'int' postfix '++'
23103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
23203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (CallExpr 'void'
23303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
23403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
23503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (UnaryOperator 'rs_font *' prefix '&'
23603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (ArraySubscriptExpr 'rs_font':'rs_font'
23703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
23803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
23903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
24003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
24103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
24203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
24303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
24403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
24503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             VD->getDeclContext(),
24603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
24703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &II,
24803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
24903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
25003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None,
25103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
25203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
25303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
25403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
25503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
25603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
25703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
25803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
25903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
26003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
26103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Init -> "rsIntIter = 0"
26203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
26303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
26403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
26503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
26603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
26703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
26803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 C.IntTy);
26903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
27003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
27103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
27203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
27303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Init =
27403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
27503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Int0,
27603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_Assign,
27703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
27803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
27903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
28003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
28103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
28203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
28303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
28403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
28503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
28603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
28703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
28803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
28903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
29003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
29103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
29203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
29303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
29403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
29503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
29603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
29703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
29803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
29903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
30003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
30103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::QualType ClearObjectFDArgType =
30203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
30303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
30403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::Type *VT = RSExportType::GetTypeOfDecl(VD);
30503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefRSVar =
30603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
30703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
30803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
30903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 VD,
31003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
31103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 VT->getCanonicalTypeInternal());
31203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
31303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSVarPtr =
31403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
31503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          C.getPointerType(T->getCanonicalTypeInternal()),
31603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
31703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          RefRSVar,
31803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          NULL,
31903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
32003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
32103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSVarPtrSubscript =
32203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ArraySubscriptExpr(RefRSVarPtr,
32303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       RefrsIntIter,
32403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       T->getCanonicalTypeInternal(),
32503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       VD->getLocation());
32603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
32703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *AddrRefRSVarPtrSubscript =
32803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefRSVarPtrSubscript,
32903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_AddrOf,
33003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  ClearObjectFDArgType,
33103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  VD->getLocation());
33203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
33303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSClearObjectFD =
33403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
33503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
33603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
33703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFD,
33803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
33903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFDType);
34003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RSClearObjectFP =
34203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
34303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      C.getPointerType(ClearObjectFDType),
34403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      clang::CK_FunctionToPointerDecay,
34503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      RefRSClearObjectFD,
34603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      NULL,
34703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      clang::VK_RValue);
34803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CallExpr *RSClearObjectCall =
35003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CallExpr(C,
35103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             RSClearObjectFP,
35203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &AddrRefRSVarPtrSubscript,
35303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             1,
35403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             ClearObjectFD->getCallResultType(),
35503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc);
35603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
35703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
35803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
35903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
36003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
36103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            NULL,  // no condVar
36203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
36503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
36603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
36703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
36903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  assert(StmtCtr == 2);
37003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
37103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CompoundStmt *CS =
37203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
37303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
37403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return CS;
37503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
37603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
3774464d825c11349068f2917f9ebee86b721423f3cStephen Hines}  // namespace
3784464d825c11349068f2917f9ebee86b721423f3cStephen Hines
3791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
380d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> RSClearObjectCalls;
3811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
3821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
3831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
3841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
385d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    clang::Stmt *E = ClearRSObject(*I);
3861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if (E) {
3871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectCalls.push_back(E);
3881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
3891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
3901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
3914464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
3924464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DV.Visit(mCS);
3931bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
3941bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
3951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
3961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
397d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  bool IsArrayType = false;
3991bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
4001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
4011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
40203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Loop through array types to get to base type
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  while (T && T->isArrayType()) {
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    T = T->getArrayElementTypeNoTypeQual();
40603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    IsArrayType = true;
40703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
40803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
4091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  RSExportPrimitiveType::DataType DT =
4101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
4111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
4131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "Should be RS object");
4141bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Find the rsClearObject() for VD of RS object type DT
4161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::FunctionDecl *ClearObjectFD =
4171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
4181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((ClearObjectFD != NULL) &&
4191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "rsClearObject doesn't cover all RS object types");
4201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (IsArrayType) {
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return ClearArrayRSObject(VD, T, ClearObjectFD);
42303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
42403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
4251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
4261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDArgType =
4271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
4281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
42903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor for "rs_font localFont;"
43003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
4311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // (CallExpr 'void'
4321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
4331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
4341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
43503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
4361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
4381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
4391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
4401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
4411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD->getQualifierRange(),
4421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
4431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
44403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 T->getCanonicalTypeInternal());
4451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Get address of RSObject in VD
4471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *AddrRefRSVar =
448e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
449e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  clang::UO_AddrOf,
450e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  ClearObjectFDArgType,
451e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  Loc);
4521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RefRSClearObjectFD =
4541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
4551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
4561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getQualifierRange(),
4571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD,
4581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getLocation(),
45903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFDType);
4601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RSClearObjectFP =
4621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::ImplicitCastExpr::Create(C,
4631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      C.getPointerType(ClearObjectFDType),
4641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::CK_FunctionToPointerDecay,
4651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      RefRSClearObjectFD,
4661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      NULL,
4671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::VK_RValue);
4681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CallExpr *RSClearObjectCall =
470e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::CallExpr(C,
471e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             RSClearObjectFP,
472e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             &AddrRefRSVar,
473e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             1,
474e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             ClearObjectFD->getCallResultType(),
475e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             clang::SourceLocation());
4761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return RSClearObjectCall;
4781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
4791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
4804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) {
4812d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  bool IsArrayType = false;
4824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
4832d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
4842d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
4852d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
4862d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
4872d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    IsArrayType = true;
4882d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
4892d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
4904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  RSExportPrimitiveType::DataType DT =
4914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
4924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4932d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  if (DT == RSExportPrimitiveType::DataTypeUnknown) {
4944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    return false;
4952d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
4964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (VD->hasInit()) {
498e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    // TODO(srhines): Update the reference count of RS object in initializer.
4994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // This can potentially be done as part of the assignment pass.
5004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  } else {
5014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Expr *ZeroInitializer =
5024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        CreateZeroInitializerForRSSpecificType(DT,
5034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               VD->getASTContext(),
5044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               VD->getLocation());
5054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
5064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (ZeroInitializer) {
5074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      ZeroInitializer->setType(T->getCanonicalTypeInternal());
5084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      VD->setInit(ZeroInitializer);
5094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
5104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
5114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
51203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return RSExportPrimitiveType::IsRSObjectType(DT);
5134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
5144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
5154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
5164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
5174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
5184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
5194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
5204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
5214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
5224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
5234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
5244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
5254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
5264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
5274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
5284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
5294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
5304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
5314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
5324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
5334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
5344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
5354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
5364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
5374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
5384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
5394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
5404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
5414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
5424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
5434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
544e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
5454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
5464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
5474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
5484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
5494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
5504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
5514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
5524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
5534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
5544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
5554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
5564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
5574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
5584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
5594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
5604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
5614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
5624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
5634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
5644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
5654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
5664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
5674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
5684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
5694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
5704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
5714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
5724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
5734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
5744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
5754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
5764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
5774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
5784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
5794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
580e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
5814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
5824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
5834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
5844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
5854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
586e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
5874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
5884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
5894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
5904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
5914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
5924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
5934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
5944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
5954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
5964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
5974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
5984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
5994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
6004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
6014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
6024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
6034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
6044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
6054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
6064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      assert(false && "Not RS object type!");
6074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
6084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
6094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
6104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
6114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
6124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
6134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
6144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
6154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
6164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
6174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
6184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
6194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
6204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
6214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (InitializeRSObject(VD))
6224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
6234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
6244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
6254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
6264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
6274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
6284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
6294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
6304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
6314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
6324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
6334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
6344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
6354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
6364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
637e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    // TODO(srhines): Update reference count of the RS object refenced by
638e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    //                getCurrentScope().
6394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    assert((getCurrentScope() == S) && "Corrupted scope stack!");
6401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
6414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
6424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
6434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
6444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
6454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
6464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
6474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
648e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  // TODO(srhines): Update reference count
6494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
6504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
6514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
6524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
6534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
6544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
6554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
6564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
6574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
6584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
6594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
6604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
6614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
6624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
663e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
664