slang_rs_object_ref_count.cpp revision e79fb5ec220e20bd04cd6f6059cbc9748181ce21
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
145e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesstatic void AppendAfterStmt(clang::ASTContext& C,
146e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::CompoundStmt *CS,
147e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Stmt *OldStmt,
148e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Stmt *NewStmt) {
149e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  assert(CS && OldStmt && NewStmt);
150e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
151e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned StmtCount = 1;  // Take into account new statement
152e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
153e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    StmtCount++;
154e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
155e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
156e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
157e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
158e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned UpdatedStmtCount = 0;
159e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  unsigned Once = 0;
160e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
161e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    UpdatedStmtList[UpdatedStmtCount++] = *bI;
162e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    if (*bI == OldStmt) {
163e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      Once++;
164e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      assert(Once == 1);
165e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
166e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    }
167e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
168e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
169e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
170e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
171e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  delete [] UpdatedStmtList;
172e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
173e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
174e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
175e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
176e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesstatic void ReplaceInCompoundStmt(clang::ASTContext& C,
177c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::CompoundStmt *CS,
178c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::Stmt* OldStmt,
179c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                  clang::Stmt* NewStmt) {
180c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CompoundStmt::body_iterator bI = CS->body_begin();
181c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
182c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  unsigned StmtCount = 0;
183c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
184c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    StmtCount++;
185c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
186c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
187c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
188c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
189c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  unsigned UpdatedStmtCount = 0;
190c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
191c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    if (*bI == OldStmt) {
192c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
193c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    } else {
194c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      UpdatedStmtList[UpdatedStmtCount++] = *bI;
195c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    }
196c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
197c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
198c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
199c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
200c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  delete [] UpdatedStmtList;
201c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
202c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
203c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
204c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
205c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
206d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines// This class visits a compound statement and inserts the StmtList containing
2074464d825c11349068f2917f9ebee86b721423f3cStephen Hines// destructors in proper locations. This includes inserting them before any
2084464d825c11349068f2917f9ebee86b721423f3cStephen Hines// return statement in any sub-block, at the end of the logical enclosing
2094464d825c11349068f2917f9ebee86b721423f3cStephen Hines// scope (compound statement), and/or before any break/continue statement that
2104464d825c11349068f2917f9ebee86b721423f3cStephen Hines// would resume outside the declared scope. We will not handle the case for
2114464d825c11349068f2917f9ebee86b721423f3cStephen Hines// goto statements that leave a local scope.
2124464d825c11349068f2917f9ebee86b721423f3cStephen Hines// TODO(srhines): Make this work properly for break/continue.
2134464d825c11349068f2917f9ebee86b721423f3cStephen Hinesclass DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
2144464d825c11349068f2917f9ebee86b721423f3cStephen Hines private:
2154464d825c11349068f2917f9ebee86b721423f3cStephen Hines  clang::ASTContext &mC;
216d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> &mStmtList;
2174464d825c11349068f2917f9ebee86b721423f3cStephen Hines  bool mTopLevel;
2184464d825c11349068f2917f9ebee86b721423f3cStephen Hines public:
219d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
2204464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitStmt(clang::Stmt *S);
2214464d825c11349068f2917f9ebee86b721423f3cStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
2224464d825c11349068f2917f9ebee86b721423f3cStephen Hines};
2234464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2244464d825c11349068f2917f9ebee86b721423f3cStephen HinesDestructorVisitor::DestructorVisitor(clang::ASTContext &C,
225d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines                                     std::list<clang::Stmt*> &StmtList)
2264464d825c11349068f2917f9ebee86b721423f3cStephen Hines  : mC(C),
227d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    mStmtList(StmtList),
2284464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel(true) {
2294464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2304464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2314464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2324464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
2334464d825c11349068f2917f9ebee86b721423f3cStephen Hines  if (!CS->body_empty()) {
234d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines    AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
2354464d825c11349068f2917f9ebee86b721423f3cStephen Hines    mTopLevel = false;
2364464d825c11349068f2917f9ebee86b721423f3cStephen Hines    VisitStmt(CS);
2374464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2384464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2394464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2404464d825c11349068f2917f9ebee86b721423f3cStephen Hines
2414464d825c11349068f2917f9ebee86b721423f3cStephen Hinesvoid DestructorVisitor::VisitStmt(clang::Stmt *S) {
2424464d825c11349068f2917f9ebee86b721423f3cStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
2434464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I != E;
2444464d825c11349068f2917f9ebee86b721423f3cStephen Hines       I++) {
2454464d825c11349068f2917f9ebee86b721423f3cStephen Hines    if (clang::Stmt *Child = *I) {
2464464d825c11349068f2917f9ebee86b721423f3cStephen Hines      Visit(Child);
2474464d825c11349068f2917f9ebee86b721423f3cStephen Hines    }
2484464d825c11349068f2917f9ebee86b721423f3cStephen Hines  }
2494464d825c11349068f2917f9ebee86b721423f3cStephen Hines  return;
2504464d825c11349068f2917f9ebee86b721423f3cStephen Hines}
2514464d825c11349068f2917f9ebee86b721423f3cStephen Hines
25203981a308201b9123512297c8b9562a0f29bdf31Stephen Hinesstatic int ArrayDim(clang::VarDecl *VD) {
25303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
25403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
25503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (!T || !T->isArrayType()) {
25603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return 0;
25703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
25803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
25903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::ConstantArrayType *CAT =
26003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    static_cast<const clang::ConstantArrayType *>(T);
2619d2c0fa6490e09b3ff5603796bce42d97788e5c8Stephen Hines  return static_cast<int>(CAT->getSize().getSExtValue());
26203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
26303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
26403981a308201b9123512297c8b9562a0f29bdf31Stephen Hinesstatic clang::Stmt *ClearArrayRSObject(clang::VarDecl *VD,
26503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    const clang::Type *T,
26603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    clang::FunctionDecl *ClearObjectFD) {
26703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ASTContext &C = VD->getASTContext();
26803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::SourceRange Range = VD->getQualifierRange();
26903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::SourceLocation Loc = Range.getEnd();
27003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
27103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Stmt *StmtArray[2] = {NULL};
27203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int StmtCtr = 0;
27303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
27403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  int NumArrayElements = ArrayDim(VD);
27503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (NumArrayElements <= 0) {
27603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return NULL;
27703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
27803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
27903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor loop for "rs_font fontArr[10];"
28003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
28103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // (CompoundStmt
28203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (DeclStmt "int rsIntIter")
28303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   (ForStmt
28403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '='
28503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
28603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 0))
28703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (BinaryOperator 'int' '<'
28803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter')
28903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (IntegerLiteral 'int' 10)
29003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     NULL << CondVar >>
29103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (UnaryOperator 'int' postfix '++'
29203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (DeclRefExpr 'int' Var='rsIntIter'))
29303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (CallExpr 'void'
29403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
29503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
29603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //       (UnaryOperator 'rs_font *' prefix '&'
29703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //         (ArraySubscriptExpr 'rs_font':'rs_font'
29803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
29903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
30003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
30103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
30203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Create helper variable for iterating through elements
30303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
30403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::VarDecl *IIVD =
30503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::VarDecl::Create(C,
30603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             VD->getDeclContext(),
30703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc,
30803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &II,
30903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.IntTy,
31003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             C.getTrivialTypeSourceInfo(C.IntTy),
31103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None,
31203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             clang::SC_None);
31303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Decl *IID = (clang::Decl *)IIVD;
31403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
31503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
31603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
31703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
31803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Form the actual destructor loop
31903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // for (Init; Cond; Inc)
32003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //   RSClearObjectCall;
32103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
32203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Init -> "rsIntIter = 0"
32303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefrsIntIter =
32403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
32503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
32603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
32703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 IIVD,
32803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
32903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 C.IntTy);
33003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
33103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
33203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
33303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
33403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Init =
33503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
33603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Int0,
33703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_Assign,
33803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
33903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
34003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Cond -> "rsIntIter < NumArrayElements"
34203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
34303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
34403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
34503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::BinaryOperator *Cond =
34603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::BinaryOperator(RefrsIntIter,
34703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   NumArrayElementsExpr,
34803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   clang::BO_LT,
34903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   C.IntTy,
35003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                   Loc);
35103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
35203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Inc -> "rsIntIter++"
35303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::UnaryOperator *Inc =
35403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefrsIntIter,
35503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_PostInc,
35603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  C.IntTy,
35703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  Loc);
35803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
35903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Body -> "rsClearObject(&VD[rsIntIter]);"
36003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Destructor loop operates on individual array elements
36103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
36203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::QualType ClearObjectFDArgType =
36303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
36403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
36503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  const clang::Type *VT = RSExportType::GetTypeOfDecl(VD);
36603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::DeclRefExpr *RefRSVar =
36703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
36803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
36903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
37003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 VD,
37103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
37203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 VT->getCanonicalTypeInternal());
37303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
37403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSVarPtr =
37503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
37603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          C.getPointerType(T->getCanonicalTypeInternal()),
37703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::CK_ArrayToPointerDecay,
37803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          RefRSVar,
37903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          NULL,
38003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines          clang::VK_RValue);
38103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSVarPtrSubscript =
38303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ArraySubscriptExpr(RefRSVarPtr,
38403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       RefrsIntIter,
38503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       T->getCanonicalTypeInternal(),
38603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                       VD->getLocation());
38703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
38803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *AddrRefRSVarPtrSubscript =
38903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::UnaryOperator(RefRSVarPtrSubscript,
39003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  clang::UO_AddrOf,
39103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  ClearObjectFDArgType,
39203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                  VD->getLocation());
39303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
39403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RefRSClearObjectFD =
39503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::DeclRefExpr::Create(C,
39603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 NULL,
39703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Range,
39803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFD,
39903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 Loc,
40003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFDType);
40103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
40203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::Expr *RSClearObjectFP =
40303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      clang::ImplicitCastExpr::Create(C,
40403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      C.getPointerType(ClearObjectFDType),
40503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      clang::CK_FunctionToPointerDecay,
40603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      RefRSClearObjectFD,
40703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      NULL,
40803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                      clang::VK_RValue);
40903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CallExpr *RSClearObjectCall =
41103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CallExpr(C,
41203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             RSClearObjectFP,
41303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             &AddrRefRSVarPtrSubscript,
41403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             1,
41503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             ClearObjectFD->getCallResultType(),
41603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                             Loc);
41703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
41803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::ForStmt *DestructorLoop =
41903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::ForStmt(C,
42003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Init,
42103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Cond,
42203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            NULL,  // no condVar
42303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Inc,
42403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            RSClearObjectCall,
42503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
42603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc,
42703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                            Loc);
42803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
42903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  StmtArray[StmtCtr++] = DestructorLoop;
43003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  assert(StmtCtr == 2);
43103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  clang::CompoundStmt *CS =
43303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
43403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
43503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  return CS;
43603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines}
43703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
4384464d825c11349068f2917f9ebee86b721423f3cStephen Hines}  // namespace
4394464d825c11349068f2917f9ebee86b721423f3cStephen Hines
440c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hinesvoid RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
441c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    clang::BinaryOperator *AS) {
442c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
443c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
444c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  RSExportPrimitiveType::DataType DT =
445c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(QT.getTypePtr());
446c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
447c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::FunctionDecl *SetObjectFD =
448c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      RSSetObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
449c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  assert((SetObjectFD != NULL) &&
450c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      "rsSetObject doesn't cover all RS object types");
451c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::ASTContext &C = SetObjectFD->getASTContext();
452c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
453c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
454c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType SetObjectFDArgType[2];
455c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
456c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
457c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
458c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::SourceLocation Loc = SetObjectFD->getLocation();
459c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RefRSSetObjectFD =
460c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::DeclRefExpr::Create(C,
461c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 NULL,
462c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD->getQualifierRange(),
463c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFD,
464c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 Loc,
465c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                 SetObjectFDType);
466c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
467c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *RSSetObjectFP =
468c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      clang::ImplicitCastExpr::Create(C,
469c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      C.getPointerType(SetObjectFDType),
470c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::CK_FunctionToPointerDecay,
471c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      RefRSSetObjectFD,
472c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      NULL,
473c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                      clang::VK_RValue);
474c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
475c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::Expr *ArgList[2];
476c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(AS->getLHS(),
477c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           clang::UO_AddrOf,
478c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           SetObjectFDArgType[0],
479c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                                           Loc);
480c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  ArgList[1] = AS->getRHS();
481c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
482c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::CallExpr *RSSetObjectCall =
483c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      new(C) clang::CallExpr(C,
484c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             RSSetObjectFP,
485c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             ArgList,
486c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             2,
487c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             SetObjectFD->getCallResultType(),
488c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines                             Loc);
489c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
490e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ReplaceInCompoundStmt(C, mCS, AS, RSSetObjectCall);
491e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
492e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return;
493e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines}
494e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
495e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesvoid RSObjectRefCount::Scope::AppendRSObjectInit(
496e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::VarDecl *VD,
497e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::DeclStmt *DS,
498e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    RSExportPrimitiveType::DataType DT,
499e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    clang::Expr *InitExpr) {
500e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  assert(VD);
501e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
502e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!InitExpr) {
503e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return;
504e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
505e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
506e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::FunctionDecl *SetObjectFD =
507e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      RSSetObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
508e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  assert((SetObjectFD != NULL) &&
509e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      "rsSetObject doesn't cover all RS object types");
510e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::ASTContext &C = SetObjectFD->getASTContext();
511e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
512e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDType = SetObjectFD->getType();
513e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::QualType SetObjectFDArgType[2];
514e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
515e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
516e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
517e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::SourceLocation Loc = SetObjectFD->getLocation();
518e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RefRSSetObjectFD =
519e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
520e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 NULL,
521e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD->getQualifierRange(),
522e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFD,
523e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
524e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 SetObjectFDType);
525e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
526e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *RSSetObjectFP =
527e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::ImplicitCastExpr::Create(C,
528e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      C.getPointerType(SetObjectFDType),
529e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::CK_FunctionToPointerDecay,
530e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      RefRSSetObjectFD,
531e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      NULL,
532e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                      clang::VK_RValue);
533e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
534e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
535e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::DeclRefExpr *RefRSVar =
536e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::DeclRefExpr::Create(C,
537e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 NULL,
538e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD->getQualifierRange(),
539e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 VD,
540e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 Loc,
541e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 T->getCanonicalTypeInternal());
542e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
543e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ArgList[2];
544e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
545e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           clang::UO_AddrOf,
546e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           SetObjectFDArgType[0],
547e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                           Loc);
548e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  ArgList[1] = InitExpr;
549e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
550e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::CallExpr *RSSetObjectCall =
551e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      new(C) clang::CallExpr(C,
552e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             RSSetObjectFP,
553e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             ArgList,
554e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             2,
555e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             SetObjectFD->getCallResultType(),
556e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                             Loc);
557e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
558e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  AppendAfterStmt(C, mCS, DS, RSSetObjectCall);
559c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
560c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  return;
561c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines}
562c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
5631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hinesvoid RSObjectRefCount::Scope::InsertLocalVarDestructors() {
564d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  std::list<clang::Stmt*> RSClearObjectCalls;
5651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
5661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines          E = mRSO.end();
5671bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I != E;
5681bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines        I++) {
569a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    clang::Stmt *S = ClearRSObject(*I);
570a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines    if (S) {
571a858cb6f3d9223d65bf73e1230c6324ded4095f6Stephen Hines      RSClearObjectCalls.push_back(S);
5721bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
5731bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
5741bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  if (RSClearObjectCalls.size() > 0) {
5754464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
5764464d825c11349068f2917f9ebee86b721423f3cStephen Hines    DV.Visit(mCS);
5771bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
5781bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return;
5791bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
5801bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
581d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hinesclang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
58203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  bool IsArrayType = false;
5831bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::ASTContext &C = VD->getASTContext();
5841bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::SourceLocation Loc = VD->getLocation();
5851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
58603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
58703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Loop through array types to get to base type
58803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  while (T && T->isArrayType()) {
58903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    T = T->getArrayElementTypeNoTypeQual();
59003981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    IsArrayType = true;
59103981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
59203981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
5931bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  RSExportPrimitiveType::DataType DT =
5941bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(T);
5951bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
5961bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
5971bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "Should be RS object");
5981bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
5991bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Find the rsClearObject() for VD of RS object type DT
6001bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::FunctionDecl *ClearObjectFD =
6011bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
6021bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  assert((ClearObjectFD != NULL) &&
6031bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      "rsClearObject doesn't cover all RS object types");
6041bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
60503981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  if (IsArrayType) {
60603981a308201b9123512297c8b9562a0f29bdf31Stephen Hines    return ClearArrayRSObject(VD, T, ClearObjectFD);
60703981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  }
60803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines
6091bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
6101bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::QualType ClearObjectFDArgType =
6111bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      ClearObjectFD->getParamDecl(0)->getOriginalType();
6121bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
61303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  // Example destructor for "rs_font localFont;"
61403981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //
6151bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // (CallExpr 'void'
6161bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
6171bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
6181bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  //   (UnaryOperator 'rs_font *' prefix '&'
61903981a308201b9123512297c8b9562a0f29bdf31Stephen Hines  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
6201bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6211bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Reference expr to target RS object variable
6221bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::DeclRefExpr *RefRSVar =
6231bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
6241bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
6251bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD->getQualifierRange(),
6261bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 VD,
6271bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 Loc,
62803981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 T->getCanonicalTypeInternal());
6291bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  // Get address of RSObject in VD
6311bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *AddrRefRSVar =
632e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::UnaryOperator(RefRSVar,
633e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  clang::UO_AddrOf,
634e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  ClearObjectFDArgType,
635e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                                  Loc);
6361bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6371bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RefRSClearObjectFD =
6381bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::DeclRefExpr::Create(C,
6391bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 NULL,
6401bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getQualifierRange(),
6411bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD,
6421bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                 ClearObjectFD->getLocation(),
64303981a308201b9123512297c8b9562a0f29bdf31Stephen Hines                                 ClearObjectFDType);
6441bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6451bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::Expr *RSClearObjectFP =
6461bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      clang::ImplicitCastExpr::Create(C,
6471bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      C.getPointerType(ClearObjectFDType),
6481bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::CK_FunctionToPointerDecay,
6491bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      RefRSClearObjectFD,
6501bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      NULL,
6511bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines                                      clang::VK_RValue);
6521bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6531bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  clang::CallExpr *RSClearObjectCall =
654e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      new(C) clang::CallExpr(C,
655e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             RSClearObjectFP,
656e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             &AddrRefRSVar,
657e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             1,
658e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             ClearObjectFD->getCallResultType(),
659e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines                             clang::SourceLocation());
6601bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
6611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  return RSClearObjectCall;
6621bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines}
6631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
664e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hinesbool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
665e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          RSExportPrimitiveType::DataType *DT,
666e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                          clang::Expr **InitExpr) {
667e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  assert(VD && DT && InitExpr);
6684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
6692d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
6702d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  // Loop through array types to get to base type
6712d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  while (T && T->isArrayType()) {
6722d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines    T = T->getArrayElementTypeNoTypeQual();
6732d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
6742d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines
675e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
6764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
677e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
6784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    return false;
6792d095046682d9c372e8c4f102cd1b340ec14bebaStephen Hines  }
6804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
681e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  bool DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
682e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  *InitExpr = VD->getInit();
683e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
684e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (!DataTypeIsRSObject && *InitExpr) {
685e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    // If we already have an initializer for a matrix type, we are done.
686e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    return DataTypeIsRSObject;
6874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
6884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
689e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  clang::Expr *ZeroInitializer =
690e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      CreateZeroInitializerForRSSpecificType(*DT,
691e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getASTContext(),
692e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                             VD->getLocation());
693e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
694e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  if (ZeroInitializer) {
695e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    ZeroInitializer->setType(T->getCanonicalTypeInternal());
696e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines    VD->setInit(ZeroInitializer);
697e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  }
698e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
699e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  return DataTypeIsRSObject;
7004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
7014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
7024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
7034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    RSExportPrimitiveType::DataType DT,
7044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::ASTContext &C,
7054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    const clang::SourceLocation &Loc) {
7064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  clang::Expr *Res = NULL;
7074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  switch (DT) {
7084b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSElement:
7094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSType:
7104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSAllocation:
7114b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSSampler:
7124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSScript:
7134b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMesh:
7144b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramFragment:
7154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramVertex:
7164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramRaster:
7174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSProgramStore:
7184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSFont: {
7194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //    (ImplicitCastExpr 'nullptr_t'
7204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //      (IntegerLiteral 0)))
7214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
7224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
7234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *CastToNull =
7244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::ImplicitCastExpr::Create(C,
7254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          C.NullPtrTy,
7264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::CK_IntegralToPointer,
7274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          Int0,
7284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          NULL,
7294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                          clang::VK_RValue);
7304b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
731e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
7324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
7334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
7344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
7354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
7364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
7374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // RS matrix is not completely an RS object. They hold data by themselves.
7384b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // (InitListExpr rs_matrix2x2
7394b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //   (InitListExpr float[4]
7404b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
7414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
7424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)
7434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      //     (FloatingLiteral 0)))
7444b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::QualType FloatTy = C.FloatTy;
7454b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Constructor sets value to 0.0f by default
7464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
7474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::FloatingLiteral *Float0Val =
7484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines          clang::FloatingLiteral::Create(C,
7494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Val,
7504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         /* isExact = */true,
7514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         FloatTy,
7524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                         Loc);
7534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
7544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      unsigned N = 0;
7554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
7564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 2;
7574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
7584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 3;
7594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
7604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        N = 4;
7614b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
7624b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      // Directly allocate 16 elements instead of dynamically allocate N*N
7634b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitVals[16];
7644b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
7654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        InitVals[i] = Float0Val;
7664b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::Expr *InitExpr =
767e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
7684b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      InitExpr->setType(C.getConstantArrayType(FloatTy,
7694b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               llvm::APInt(32, 4),
7704b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               clang::ArrayType::Normal,
7714b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines                                               /* EltTypeQuals = */0));
7724b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
773e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
7744b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      break;
7754b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
7764b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnknown:
7774b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat16:
7784b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat32:
7794b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeFloat64:
7804b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned8:
7814b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned16:
7824b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned32:
7834b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeSigned64:
7844b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned8:
7854b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned16:
7864b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned32:
7874b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned64:
7884b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeBoolean:
7894b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned565:
7904b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned5551:
7914b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeUnsigned4444:
7924b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    case RSExportPrimitiveType::DataTypeMax: {
7934b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      assert(false && "Not RS object type!");
7944b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
7954b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // No default case will enable compiler detecting the missing cases
7964b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
7974b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
7984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return Res;
7994b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
8024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
8034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
8044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
8054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    clang::Decl *D = *I;
8064b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (D->getKind() == clang::Decl::Var) {
8074b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
808e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      RSExportPrimitiveType::DataType DT =
809e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines          RSExportPrimitiveType::DataTypeUnknown;
810e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      clang::Expr *InitExpr = NULL;
811e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      if (InitializeRSObject(VD, &DT, &InitExpr)) {
8124b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines        getCurrentScope()->addRSObject(VD);
813e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines        getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
814e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines      }
8154b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
8164b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
8174b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
8184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8194b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
8214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  if (!CS->body_empty()) {
8224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Push a new scope
8234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    Scope *S = new Scope(CS);
8244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.push(S);
8254b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    VisitStmt(CS);
8274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    // Destroy the scope
8294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    assert((getCurrentScope() == S) && "Corrupted scope stack!");
8301bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    S->InsertLocalVarDestructors();
8314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    mScopeStack.pop();
8324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    delete S;
8334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
8344b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
8354b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8364b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8374b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
838c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  clang::QualType QT = AS->getType();
839c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  RSExportPrimitiveType::DataType DT =
840c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines      RSExportPrimitiveType::GetRSSpecificType(QT.getTypePtr());
841c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
842c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  if (RSExportPrimitiveType::IsRSObjectType(DT)) {
843c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines    getCurrentScope()->ReplaceRSObjectAssignment(AS);
844c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines  }
845c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
8464b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
8474b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
8494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesvoid RSObjectRefCount::VisitStmt(clang::Stmt *S) {
8504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
8514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I != E;
8524b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines       I++) {
8534b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    if (clang::Stmt *Child = *I) {
8544b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      Visit(Child);
8554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
8564b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
8574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  return;
8584b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
8594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
860e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
861