slang_rs_object_ref_count.cpp revision e639eb5caa2c386b4a60659a4929e8a6141a2cbe
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
891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::AppendToCompoundStatement(
901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::ASTContext& C, std::list<clang::Expr*> &ExprList) {
911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Destructor code will be inserted before any return statement.
921bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Any subsequent statements in the compound statement are then placed
931bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // after our new code.
94e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  // TODO(srhines): This should also handle the case of goto/break/continue.
951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CompoundStmt::body_iterator bI = mCS->body_begin();
961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CompoundStmt::body_iterator bE = mCS->body_end();
971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned OldStmtCount = 0;
991bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for ( ; bI != bE; bI++) {
1001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    OldStmtCount++;
1011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned NewExprCount = ExprList.size();
1041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Stmt **StmtList;
1061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  StmtList = new clang::Stmt*[OldStmtCount+NewExprCount];
1071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  unsigned UpdatedStmtCount = 0;
1091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (bI = mCS->body_begin(); bI != bE; bI++) {
1101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
1111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      break;
1121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
1131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    StmtList[UpdatedStmtCount++] = *bI;
1141bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  std::list<clang::Expr*>::const_iterator E = ExprList.end();
1171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::Expr*>::const_iterator I = ExprList.begin(),
1181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = ExprList.end();
1191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       I != E;
1201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines       I++) {
1211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    StmtList[UpdatedStmtCount++] = *I;
1221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1231bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Pick up anything left over after a return statement
1251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for ( ; bI != bE; bI++) {
1261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    StmtList[UpdatedStmtCount++] = *bI;
1271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  mCS->setStmts(C, StmtList, UpdatedStmtCount);
1301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert(UpdatedStmtCount == (OldStmtCount + NewExprCount));
1311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1321bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  delete [] StmtList;
1331bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1341bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1351bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  std::list<clang::Expr*> RSClearObjectCalls;
1391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
1411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
1421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
1431bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::Expr *E = ClearRSObject(*I);
1441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if (E) {
1451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectCalls.push_back(E);
1461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
1471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
1491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    clang::ASTContext &C = (*mRSO.begin())->getASTContext();
1501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    AppendToCompoundStatement(C, RSClearObjectCalls);
151e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    // TODO(srhines): This should also be extended to append destructors to any
1521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    // further nested scope (we need another visitor here from within the
1531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    // current compound statement in case they call return/goto).
1541bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1551bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
1561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
1571bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesclang::Expr *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
1591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
1601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
1611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  RSExportPrimitiveType::DataType DT =
1631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
1641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "Should be RS object");
1671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Find the rsClearObject() for VD of RS object type DT
1691bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::FunctionDecl *ClearObjectFD =
1701bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
1711bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((ClearObjectFD != NULL) &&
1721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "rsClearObject doesn't cover all RS object types");
1731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
1751bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDArgType =
1761bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
1771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // We generate a call to rsClearObject passing &VD as the parameter
1791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // (CallExpr 'void'
1801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
1811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
1821bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
1831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='[var name]')))
1841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
1861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
1871bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
1881bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
1891bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD->getQualifierRange(),
1901bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
1911bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
1921bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 T->getCanonicalTypeInternal(),
1931bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL);
1941bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
1951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Get address of RSObject in VD
1961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *AddrRefRSVar =
197e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
198e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  clang::UO_AddrOf,
199e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  ClearObjectFDArgType,
200e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  Loc);
2011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RefRSClearObjectFD =
2031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
2041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
2051bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getQualifierRange(),
2061bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD,
2071bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getLocation(),
2081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFDType,
2091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL);
2101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RSClearObjectFP =
2121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::ImplicitCastExpr::Create(C,
2131bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      C.getPointerType(ClearObjectFDType),
2141bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::CK_FunctionToPointerDecay,
2151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      RefRSClearObjectFD,
2161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      NULL,
2171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::VK_RValue);
2181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2191bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CallExpr *RSClearObjectCall =
220e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::CallExpr(C,
221e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             RSClearObjectFP,
222e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             &AddrRefRSVar,
223e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             1,
224e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             ClearObjectFD->getCallResultType(),
225e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             clang::SourceLocation());
2261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return RSClearObjectCall;
2281bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
2291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
2304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) {
2314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
2324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  RSExportPrimitiveType::DataType DT =
2334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
2344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (DT == RSExportPrimitiveType::DataTypeUnknown)
2364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    return false;
2374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (VD->hasInit()) {
239e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    // TODO(srhines): Update the reference count of RS object in initializer.
2404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // This can potentially be done as part of the assignment pass.
2414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  } else {
2424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Expr *ZeroInitializer =
2434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        CreateZeroInitializerForRSSpecificType(DT,
2444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               VD->getASTContext(),
2454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               VD->getLocation());
2464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (ZeroInitializer) {
2484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      ZeroInitializer->setType(T->getCanonicalTypeInternal());
2494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      VD->setInit(ZeroInitializer);
2504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
2514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
2524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return RSExportPrimitiveType::IsRSObjectType(DT);
2544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
2554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
2564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
2574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
2584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
2594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
2604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
2614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
2624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
2634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
2644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
2654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
2664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
2674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
2684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
2694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
2704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
2714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
2724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
2734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
2744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
2754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
2764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
2774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
2784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
2794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
2804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
2814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
2824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
2834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
2844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
285e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
2864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
2874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
2884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
2894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
2904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
2914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
2924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
2934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
2944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
2954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
2964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
2974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
2984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
2994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
3004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
3014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
3024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
3034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
3044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
3054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
3064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
3074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
3094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
3104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
3114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
3124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
3134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
3144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
3154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
3174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
3184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
3194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
3204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
321e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
3224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
3234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
3244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
3254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
3264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
327e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
3284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
3294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
3314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
3324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
3334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
3344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
3354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
3364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
3374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
3384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
3394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
3404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
3414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
3424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
3434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
3444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
3454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
3464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
3474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      assert(false && "Not RS object type!");
3484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
3504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
3514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
3534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
3564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
3574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
3584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
3594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
3604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
3614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
3624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (InitializeRSObject(VD))
3634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
3644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
3654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
3664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
3674b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
3704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
3714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
3724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
3734b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
3744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
3764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
378e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    // TODO(srhines): Update reference count of the RS object refenced by
379e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    //                getCurrentScope().
3804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    assert((getCurrentScope() == S) && "Corrupted scope stack!");
3811bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
3824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
3834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
3844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
3854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
3864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
389e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines  // TODO(srhines): Update reference count
3904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
3914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
3924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
3934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
3944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
3954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
3964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
3974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
3984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
3994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
4004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
4014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
4024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
4034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
404e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
405