slang_rs_object_ref_count.cpp revision 1bdd4978caabcdc9489bdcb7f1cd6087340699e8
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
194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/DeclGroup.h"
204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Expr.h"
214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/OperationKinds.h"
224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/Stmt.h"
234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs.h"
264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesusing namespace slang;
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::FunctionDecl *RSObjectRefCount::Scope::
311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                  RSExportPrimitiveType::FirstRSObjectType + 1];
331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::FunctionDecl *RSObjectRefCount::Scope::
341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                    RSExportPrimitiveType::FirstRSObjectType + 1];
361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::GetRSRefCountingFunctions(
381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::ASTContext &C) {
391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (unsigned i = 0;
401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       i++) {
421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSSetObjectFD[i] = NULL;
431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    RSClearObjectFD[i] = NULL;
441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = TUDecl->decls_end(); I != E; I++) {
501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((I->getKind() >= clang::Decl::firstFunction) &&
511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        (I->getKind() <= clang::Decl::lastFunction)) {
521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // points to RSSetObjectFD or RSClearObjectFD
551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::FunctionDecl **RSObjectFD;
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      if (FD->getName() == "rsSetObject") {
581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        assert((FD->getNumParams() == 2) &&
591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines               "Invalid rsSetObject function prototype (# params)");
601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSSetObjectFD;
611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      } else if (FD->getName() == "rsClearObject") {
621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        assert((FD->getNumParams() == 1) &&
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines               "Invalid rsClearObject function prototype (# params)");
641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        RSObjectFD = RSClearObjectFD;
651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      else {
671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        continue;
681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      }
691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType PVT = PVD->getOriginalType();
721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The first parameter must be a pointer like rs_allocation*
731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      assert(PVT->isPointerType() &&
741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             "Invalid rs{Set,Clear}Object function prototype (pointer param)");
751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      // The rs object type passed to the FD
771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::QualType RST = PVT->getPointeeType();
781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::DataType DT =
791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      assert(RSExportPrimitiveType::IsRSObjectType(DT)
811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines             && "must be RS object type");
821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::AppendToCompoundStatement(
891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::ASTContext& C, std::list<clang::Expr*> &ExprList) {
901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Destructor code will be inserted before any return statement.
911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Any subsequent statements in the compound statement are then placed
921bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // after our new code.
931bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // TODO: This should also handle the case of goto/break/continue.
941bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CompoundStmt::body_iterator bI = mCS->body_begin();
951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CompoundStmt::body_iterator bE = mCS->body_end();
961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned OldStmtCount = 0;
981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for ( ; bI != bE; bI++) {
991bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    OldStmtCount++;
1001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned NewExprCount = ExprList.size();
1031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Stmt **StmtList;
1051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  StmtList = new clang::Stmt*[OldStmtCount+NewExprCount];
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned UpdatedStmtCount = 0;
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (bI = mCS->body_begin(); bI != bE; bI++) {
1091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
1101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      break;
1111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
1121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    StmtList[UpdatedStmtCount++] = *bI;
1131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1141bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  std::list<clang::Expr*>::const_iterator E = ExprList.end();
1161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::Expr*>::const_iterator I = ExprList.begin(),
1171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = ExprList.end();
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       I != E;
1191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       I++) {
1201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    StmtList[UpdatedStmtCount++] = *I;
1211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1231bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Pick up anything left over after a return statement
1241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for ( ; bI != bE; bI++) {
1251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    StmtList[UpdatedStmtCount++] = *bI;
1261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  mCS->setStmts(C, StmtList, UpdatedStmtCount);
1291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert(UpdatedStmtCount == (OldStmtCount + NewExprCount));
1301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  delete [] StmtList;
1321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  std::list<clang::Expr*> RSClearObjectCalls;
1381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
1401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
1411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
1421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::Expr *E = ClearRSObject(*I);
1431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if (E) {
1441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectCalls.push_back(E);
1451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
1461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
1481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::ASTContext &C = (*mRSO.begin())->getASTContext();
1491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    AppendToCompoundStatement(C, RSClearObjectCalls);
1501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    // TODO: This should also be extended to append destructors to any
1511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    // further nested scope (we need another visitor here from within the
1521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    // current compound statement in case they call return/goto).
1531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::Expr *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
1581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
1591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
1601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  RSExportPrimitiveType::DataType DT =
1621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
1631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "Should be RS object");
1661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Find the rsClearObject() for VD of RS object type DT
1681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::FunctionDecl *ClearObjectFD =
1691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
1701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((ClearObjectFD != NULL) &&
1711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "rsClearObject doesn't cover all RS object types");
1721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
1741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDArgType =
1751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
1761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // We generate a call to rsClearObject passing &VD as the parameter
1781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // (CallExpr 'void'
1791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
1801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
1811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
1821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='[var name]')))
1831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
1851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
1861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
1871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
1881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD->getQualifierRange(),
1891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
1901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
1911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 T->getCanonicalTypeInternal(),
1921bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL);
1931bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1941bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Get address of RSObject in VD
1951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *AddrRefRSVar =
1961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      new (C) clang::UnaryOperator(RefRSVar,
1971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                   clang::UO_AddrOf,
1981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                   ClearObjectFDArgType,
1991bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                   Loc);
2001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RefRSClearObjectFD =
2021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
2031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
2041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getQualifierRange(),
2051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD,
2061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getLocation(),
2071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFDType,
2081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL);
2091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RSClearObjectFP =
2111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::ImplicitCastExpr::Create(C,
2121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      C.getPointerType(ClearObjectFDType),
2131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::CK_FunctionToPointerDecay,
2141bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      RefRSClearObjectFD,
2151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      NULL,
2161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::VK_RValue);
2171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CallExpr *RSClearObjectCall =
2191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      new (C) clang::CallExpr(C,
2201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                              RSClearObjectFP,
2211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                              &AddrRefRSVar,
2221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                              1,
2231bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                              ClearObjectFD->getCallResultType(),
2241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                              clang::SourceLocation());
2251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return RSClearObjectCall;
2271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
2281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) {
2304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
2314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  RSExportPrimitiveType::DataType DT =
2324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
2334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeUnknown)
2354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    return false;
2364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (VD->hasInit()) {
2384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // TODO: Update the reference count of RS object in initializer.
2394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // This can potentially be done as part of the assignment pass.
2404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  } else {
2414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Expr *ZeroInitializer =
2424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        CreateZeroInitializerForRSSpecificType(DT,
2434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               VD->getASTContext(),
2444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               VD->getLocation());
2454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (ZeroInitializer) {
2474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      ZeroInitializer->setType(T->getCanonicalTypeInternal());
2484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      VD->setInit(ZeroInitializer);
2494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
2504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
2514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return RSExportPrimitiveType::IsRSObjectType(DT);
2534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
2544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
2564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
2574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
2584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
2594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
2604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
2614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
2624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
2634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
2644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
2654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
2664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
2674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
2684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
2694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
2704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
2714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
2724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
2734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
2744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
2754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
2764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
2774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
2784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
2794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
2804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
2814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
2824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
2834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Res = new (C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
2854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
2864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
2874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
2884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
2894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
2904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
2914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
2924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
2934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
2944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
2954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
2964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
2974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
2984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
2994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
3004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
3014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
3024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
3034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
3044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
3054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
3064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
3084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
3094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
3104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
3114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
3124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
3134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
3144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
3164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
3174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
3184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
3194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
3204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          new (C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
3214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
3224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
3234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
3244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
3254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Res = new (C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
3274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
3284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
3304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
3314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
3324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
3334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
3344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
3354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
3364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
3374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
3384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
3394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
3404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
3414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
3424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
3434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
3444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
3454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
3464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      assert(false && "Not RS object type!");
3474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
3494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
3504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
3524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
3554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
3564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
3574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
3584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
3594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
3604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
3614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (InitializeRSObject(VD))
3624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
3634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
3654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
3664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
3694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
3704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
3714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
3724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
3734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
3754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
3774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // TODO: Update reference count of the RS object refenced by
3784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    //       getCurrentScope().
3794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    assert((getCurrentScope() == S) && "Corrupted scope stack!");
3801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
3814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
3824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
3834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
3844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
3854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
3884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  // TODO: Update reference count
3894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
3904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
3934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
3944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
3954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
3964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
3974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
3984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
4004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
4014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
4024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
4031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
404