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
17e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#ifndef _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_  // NOLINT
18e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#define _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_
19e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
20e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#include <list>
214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include <stack>
224b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
234b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "clang/AST/StmtVisitor.h"
244b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
25f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines#include "slang_assert.h"
264b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines#include "slang_rs_export_type.h"
274b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
284b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesnamespace clang {
294b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  class Expr;
30d5f9d6c8b6944dfc30d4fea68479c2fcc250a62cStephen Hines  class Stmt;
314b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines}
324b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
33e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hinesnamespace slang {
34e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
3565f23ed862e1a1e16477ba740f295ff4a83ac822David Gross// Recursive check
3665f23ed862e1a1e16477ba740f295ff4a83ac822David Grossbool HasRSObjectType(const clang::Type *T);
3765f23ed862e1a1e16477ba740f295ff4a83ac822David Gross
38292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// This class provides the overall reference counting mechanism for handling
39292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// local variables of RS object types (rs_font, rs_allocation, ...). This
40292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// class ensures that appropriate functions (rsSetObject, rsClearObject) are
41292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// called at proper points in the object's lifetime.
42283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// 1) Each local object of appropriate type must be zero-initialized to
43283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// prevent corruption during subsequent rsSetObject()/rsClearObject() calls.
44292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// 2) Assignments using these types must also be converted into the
45292e00a0259ac28cac1055cb6077cf6fc7c6743cStephen Hines// appropriate (possibly a series of) rsSetObject() calls.
46283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// 3) Finally, rsClearObject() must be called for each local object when it goes
47283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni// out of scope.
484b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hinesclass RSObjectRefCount : public clang::StmtVisitor<RSObjectRefCount> {
494b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines private:
504b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  class Scope {
514b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines   private:
52283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    clang::CompoundStmt *mCS;         // Associated compound statement ({ ... })
53283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    clang::Stmt *mCurrent;            // The statement currently being analyzed
54283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    std::list<clang::VarDecl*> mRSO;  // Declared RS objects in this scope (but
55283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                      // not any scopes nested)
561bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
574b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines   public:
58e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines    explicit Scope(clang::CompoundStmt *CS) : mCS(CS) {
594b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
604b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
61283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    bool hasRSObject() const { return !mRSO.empty(); }
62283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    inline void addRSObject(clang::VarDecl* VD) {
641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      mRSO.push_back(VD);
654b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines    }
661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
67d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    void ReplaceRSObjectAssignment(clang::BinaryOperator *AS);
68c202d2d64fe0172bcc3999b515a14d3d88532420Stephen Hines
69d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines    void AppendRSObjectInit(clang::VarDecl *VD,
70e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::DeclStmt *DS,
71cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet                            DataType DT,
72e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                            clang::Expr *InitExpr);
73e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines
74283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // Inserts rsClearObject() calls at the end and at all exiting points of the
75283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // current scope. At each statement that exits the current scope -- e.g.,
76283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // a return, break, or continue statement in the current or a nested scope
77283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // -- rsClearObject() calls are inserted for local variables defined in the
78283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // current scope before that point.
79283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // Note goto statements are not handled. (See the DestructorVisitor class in
80283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // the .cpp file.)
81283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // Also note this function is called for every nested scope. As a result, for a
82283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // return statement, each rsObject declared in all its (nested) enclosing
83283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // scopes would have a rsClearObject() call properly inserted before
84283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // the return statement.
851bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    void InsertLocalVarDestructors();
861bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
87283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // Sets the current statement being analyzed
88283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    void setCurrentStmt(clang::Stmt *S) { mCurrent = S; }
89283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
90283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // Inserts a statement before the current statement
91283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    void InsertStmt(const clang::ASTContext &C, clang::Stmt *NewStmt);
92283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
93283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // Replaces the current statement with NewStmt;
94283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    void ReplaceStmt(const clang::ASTContext &C, clang::Stmt *NewStmt);
95283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
96283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    // Replaces OldExpr with NewExpr in the current statement
97283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    void ReplaceExpr(const clang::ASTContext& C, clang::Expr* OldExpr,
98283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                     clang::Expr* NewExpr);
99283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
1003f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines    static clang::Stmt *ClearRSObject(clang::VarDecl *VD,
1013f175af8a0644fb5fc53aa90e01c24f75855c5f7Stephen Hines                                      clang::DeclContext *DC);
1024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  };
1034b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
104d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  clang::ASTContext &mCtx;
105283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  std::deque<Scope*> mScopeStack;  // A deque used as a stack to store scopes, but also
106283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni                                   // accessed through its iterator in read-only mode.
107283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  clang::DeclContext* mCurrentDC;
1081bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  bool RSInitFD;
109283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  unsigned mTempID;  // A unique id that can be used to distinguish temporary variables
1104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
111f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // RSSetObjectFD and RSClearObjectFD holds FunctionDecl of rsSetObject()
112f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // and rsClearObject() in the current ASTContext.
113f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  static clang::FunctionDecl *RSSetObjectFD[];
114f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  static clang::FunctionDecl *RSClearObjectFD[];
115f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
116283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  inline bool emptyScope() const { return mScopeStack.empty(); }
117283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
1184b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  inline Scope *getCurrentScope() {
119283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni    return mScopeStack.back();
1204b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  }
1214b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
122283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  // Returns the next available unique id for temporary variables
123283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  unsigned getNextID() { return mTempID++; }
124283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
125f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Initialize RSSetObjectFD and RSClearObjectFD.
126f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  static void GetRSRefCountingFunctions(clang::ASTContext &C);
127f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
128f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // Return false if the type of variable declared in VD does not contain
129f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  // an RS object type.
130e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines  static bool InitializeRSObject(clang::VarDecl *VD,
131cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet                                 DataType *DT,
132e79fb5ec220e20bd04cd6f6059cbc9748181ce21Stephen Hines                                 clang::Expr **InitExpr);
1334b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
134670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines  // Return an empty list initializer expression at the appropriate location.
135670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines  // This construct can then be used to cheaply construct a zero-initializer
136670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines  // for any RenderScript objects (like rs_allocation) or rs_matrix* types
137670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines  // (possibly even embedded within other types). These types are expected to
138670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines  // be zero-initialized always, and so we can use this helper to ensure that
139670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines  // they at least have an empty initializer.
140670ba1d5f33d0914e63732da0c9423f8069ac313Stephen Hines  static clang::Expr *CreateEmptyInitListExpr(
1414b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      clang::ASTContext &C,
1424b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines      const clang::SourceLocation &Loc);
1434b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
144f44e96036289beae53f6b3f345a723d990563f81Yang Ni  // Given a return statement RS that returns an rsObject, creates a temporary
145f44e96036289beae53f6b3f345a723d990563f81Yang Ni  // variable, and sets it to the original return expression using rsSetObject().
146f44e96036289beae53f6b3f345a723d990563f81Yang Ni  // Creates a new return statement that returns the temporary variable.
147f44e96036289beae53f6b3f345a723d990563f81Yang Ni  // Returns a new compound statement that contains the new variable declaration,
148f44e96036289beae53f6b3f345a723d990563f81Yang Ni  // the rsSetOjbect() call, and the new return statement.
149f44e96036289beae53f6b3f345a723d990563f81Yang Ni  static clang::CompoundStmt* CreateRetStmtWithTempVar(
150f44e96036289beae53f6b3f345a723d990563f81Yang Ni      clang::ASTContext& C,
151f44e96036289beae53f6b3f345a723d990563f81Yang Ni      clang::DeclContext* DC,
152f44e96036289beae53f6b3f345a723d990563f81Yang Ni      clang::ReturnStmt* RS,
153f44e96036289beae53f6b3f345a723d990563f81Yang Ni      const unsigned id);
154f44e96036289beae53f6b3f345a723d990563f81Yang Ni
1554b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines public:
156d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  explicit RSObjectRefCount(clang::ASTContext &C)
157283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni      : mCtx(C), RSInitFD(false), mTempID(0) {
1581bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1591bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
160d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines  void Init() {
1611bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    if (!RSInitFD) {
162d0b5edd02be5f09c1d8d211f4a06b031a7b66510Stephen Hines      GetRSRefCountingFunctions(mCtx);
1631bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines      RSInitFD = true;
1641bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines    }
1651bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines  }
1661bdd4978caabcdc9489bdcb7f1cd6087340699e8Stephen Hines
167cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  static clang::FunctionDecl *GetRSSetObjectFD(DataType DT) {
168f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
169cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    if (DT >= 0 && DT < DataTypeMax) {
170474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      return RSSetObjectFD[DT];
171474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet    } else {
172474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      slangAssert(false && "incorrect type");
1735abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes      return nullptr;
174474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet    }
175f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
176f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
177f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  static clang::FunctionDecl *GetRSSetObjectFD(const clang::Type *T) {
178f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return GetRSSetObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
179f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
180f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
181cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet  static clang::FunctionDecl *GetRSClearObjectFD(DataType DT) {
182f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    slangAssert(RSExportPrimitiveType::IsRSObjectType(DT));
183cec9b65aa890dea58e39951900ae13efb8d11703Jean-Luc Brouillet    if (DT >= 0 && DT < DataTypeMax) {
184474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      return RSClearObjectFD[DT];
185474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet    } else {
186474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet      slangAssert(false && "incorrect type");
1875abbe0e9ca2508260b627ffef2bf01e2554e8357Chris Wailes      return nullptr;
188474655a402e70cb329e1bcd4ebbe00bdc5be4206Jean-Luc Brouillet    }
189f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
190f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
191f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  static clang::FunctionDecl *GetRSClearObjectFD(const clang::Type *T) {
192f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines    return GetRSClearObjectFD(RSExportPrimitiveType::GetRSSpecificType(T));
193f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines  }
194f2174cfd6a556b51aadf2b8765e50df080e8f18eStephen Hines
195283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  void SetDeclContext(clang::DeclContext* DC) { mCurrentDC = DC; }
196283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  clang::DeclContext* GetDeclContext() const { return mCurrentDC; }
197283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni
1984b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  void VisitStmt(clang::Stmt *S);
199283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  void VisitCallExpr(clang::CallExpr *CE);
2004b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  void VisitDeclStmt(clang::DeclStmt *DS);
2014b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  void VisitCompoundStmt(clang::CompoundStmt *CS);
2024b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  void VisitBinAssign(clang::BinaryOperator *AS);
203283a6cf32b808c703b219862ac491df3c9fc8b4bYang Ni  void VisitReturnStmt(clang::ReturnStmt *RS);
2044b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  // We believe that RS objects are never involved in CompoundAssignOperator.
2054b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines  // I.e., rs_allocation foo; foo += bar;
206688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines
207688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  // Emit a global destructor to clean up RS objects.
208688e64b2d56e4218c680b9d6523c5de672f55757Stephen Hines  clang::FunctionDecl *CreateStaticGlobalDtor();
2094b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines};
2104b32ffdfc1ac766f8932e7effbcdf7484e804a8eStephen Hines
211e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines}  // namespace slang
212e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines
213e639eb5caa2c386b4a60659a4929e8a6141a2cbeStephen Hines#endif  // _FRAMEWORKS_COMPILE_SLANG_SLANG_RS_OBJECT_REF_COUNT_H_  NOLINT
214