slang_rs_object_ref_count.cpp revision a0611e66bec148b176404cf6afe4c9ec9b960414
1/* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "slang_rs_object_ref_count.h" 18 19#include <list> 20 21#include "clang/AST/DeclGroup.h" 22#include "clang/AST/Expr.h" 23#include "clang/AST/OperationKinds.h" 24#include "clang/AST/Stmt.h" 25#include "clang/AST/StmtVisitor.h" 26 27#include "slang_assert.h" 28#include "slang_rs.h" 29#include "slang_rs_export_type.h" 30 31namespace slang { 32 33clang::FunctionDecl *RSObjectRefCount:: 34 RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType - 35 RSExportPrimitiveType::FirstRSObjectType + 1]; 36clang::FunctionDecl *RSObjectRefCount:: 37 RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType - 38 RSExportPrimitiveType::FirstRSObjectType + 1]; 39 40void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) { 41 for (unsigned i = 0; 42 i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*)); 43 i++) { 44 RSSetObjectFD[i] = NULL; 45 RSClearObjectFD[i] = NULL; 46 } 47 48 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); 49 50 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(), 51 E = TUDecl->decls_end(); I != E; I++) { 52 if ((I->getKind() >= clang::Decl::firstFunction) && 53 (I->getKind() <= clang::Decl::lastFunction)) { 54 clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I); 55 56 // points to RSSetObjectFD or RSClearObjectFD 57 clang::FunctionDecl **RSObjectFD; 58 59 if (FD->getName() == "rsSetObject") { 60 slangAssert((FD->getNumParams() == 2) && 61 "Invalid rsSetObject function prototype (# params)"); 62 RSObjectFD = RSSetObjectFD; 63 } else if (FD->getName() == "rsClearObject") { 64 slangAssert((FD->getNumParams() == 1) && 65 "Invalid rsClearObject function prototype (# params)"); 66 RSObjectFD = RSClearObjectFD; 67 } else { 68 continue; 69 } 70 71 const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 72 clang::QualType PVT = PVD->getOriginalType(); 73 // The first parameter must be a pointer like rs_allocation* 74 slangAssert(PVT->isPointerType() && 75 "Invalid rs{Set,Clear}Object function prototype (pointer param)"); 76 77 // The rs object type passed to the FD 78 clang::QualType RST = PVT->getPointeeType(); 79 RSExportPrimitiveType::DataType DT = 80 RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr()); 81 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT) 82 && "must be RS object type"); 83 84 RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD; 85 } 86 } 87} 88 89namespace { 90 91static void AppendToCompoundStatement(clang::ASTContext& C, 92 clang::CompoundStmt *CS, 93 std::list<clang::Stmt*> &StmtList, 94 bool InsertAtEndOfBlock) { 95 // Destructor code will be inserted before any return statement. 96 // Any subsequent statements in the compound statement are then placed 97 // after our new code. 98 // TODO(srhines): This should also handle the case of goto/break/continue. 99 100 clang::CompoundStmt::body_iterator bI = CS->body_begin(); 101 102 unsigned OldStmtCount = 0; 103 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 104 OldStmtCount++; 105 } 106 107 unsigned NewStmtCount = StmtList.size(); 108 109 clang::Stmt **UpdatedStmtList; 110 UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount]; 111 112 unsigned UpdatedStmtCount = 0; 113 bool FoundReturn = false; 114 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 115 if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) { 116 FoundReturn = true; 117 break; 118 } 119 UpdatedStmtList[UpdatedStmtCount++] = *bI; 120 } 121 122 // Always insert before a return that we found, or if we are told 123 // to insert at the end of the block 124 if (FoundReturn || InsertAtEndOfBlock) { 125 std::list<clang::Stmt*>::const_iterator I = StmtList.begin(); 126 for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin(); 127 I != StmtList.end(); 128 I++) { 129 UpdatedStmtList[UpdatedStmtCount++] = *I; 130 } 131 } 132 133 // Pick up anything left over after a return statement 134 for ( ; bI != CS->body_end(); bI++) { 135 UpdatedStmtList[UpdatedStmtCount++] = *bI; 136 } 137 138 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount); 139 140 delete [] UpdatedStmtList; 141 142 return; 143} 144 145static void AppendAfterStmt(clang::ASTContext& C, 146 clang::CompoundStmt *CS, 147 clang::Stmt *OldStmt, 148 clang::Stmt *NewStmt) { 149 slangAssert(CS && OldStmt && NewStmt); 150 clang::CompoundStmt::body_iterator bI = CS->body_begin(); 151 unsigned StmtCount = 1; // Take into account new statement 152 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 153 StmtCount++; 154 } 155 156 clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount]; 157 158 unsigned UpdatedStmtCount = 0; 159 unsigned Once = 0; 160 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 161 UpdatedStmtList[UpdatedStmtCount++] = *bI; 162 if (*bI == OldStmt) { 163 Once++; 164 slangAssert(Once == 1); 165 UpdatedStmtList[UpdatedStmtCount++] = NewStmt; 166 } 167 } 168 169 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount); 170 171 delete [] UpdatedStmtList; 172 173 return; 174} 175 176static void ReplaceInCompoundStmt(clang::ASTContext& C, 177 clang::CompoundStmt *CS, 178 clang::Stmt* OldStmt, 179 clang::Stmt* NewStmt) { 180 clang::CompoundStmt::body_iterator bI = CS->body_begin(); 181 182 unsigned StmtCount = 0; 183 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 184 StmtCount++; 185 } 186 187 clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount]; 188 189 unsigned UpdatedStmtCount = 0; 190 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 191 if (*bI == OldStmt) { 192 UpdatedStmtList[UpdatedStmtCount++] = NewStmt; 193 } else { 194 UpdatedStmtList[UpdatedStmtCount++] = *bI; 195 } 196 } 197 198 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount); 199 200 delete [] UpdatedStmtList; 201 202 return; 203} 204 205 206// This class visits a compound statement and inserts the StmtList containing 207// destructors in proper locations. This includes inserting them before any 208// return statement in any sub-block, at the end of the logical enclosing 209// scope (compound statement), and/or before any break/continue statement that 210// would resume outside the declared scope. We will not handle the case for 211// goto statements that leave a local scope. 212// TODO(srhines): Make this work properly for break/continue. 213class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> { 214 private: 215 clang::ASTContext &mC; 216 std::list<clang::Stmt*> &mStmtList; 217 bool mTopLevel; 218 public: 219 DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList); 220 void VisitStmt(clang::Stmt *S); 221 void VisitCompoundStmt(clang::CompoundStmt *CS); 222}; 223 224DestructorVisitor::DestructorVisitor(clang::ASTContext &C, 225 std::list<clang::Stmt*> &StmtList) 226 : mC(C), 227 mStmtList(StmtList), 228 mTopLevel(true) { 229 return; 230} 231 232void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) { 233 if (!CS->body_empty()) { 234 AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel); 235 mTopLevel = false; 236 VisitStmt(CS); 237 } 238 return; 239} 240 241void DestructorVisitor::VisitStmt(clang::Stmt *S) { 242 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 243 I != E; 244 I++) { 245 if (clang::Stmt *Child = *I) { 246 Visit(Child); 247 } 248 } 249 return; 250} 251 252clang::Expr *ClearSingleRSObject(clang::ASTContext &C, 253 clang::Expr *RefRSVar, 254 clang::SourceLocation Loc) { 255 slangAssert(RefRSVar); 256 const clang::Type *T = RefRSVar->getType().getTypePtr(); 257 slangAssert(!T->isArrayType() && 258 "Should not be destroying arrays with this function"); 259 260 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T); 261 slangAssert((ClearObjectFD != NULL) && 262 "rsClearObject doesn't cover all RS object types"); 263 264 clang::QualType ClearObjectFDType = ClearObjectFD->getType(); 265 clang::QualType ClearObjectFDArgType = 266 ClearObjectFD->getParamDecl(0)->getOriginalType(); 267 268 // Example destructor for "rs_font localFont;" 269 // 270 // (CallExpr 'void' 271 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 272 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 273 // (UnaryOperator 'rs_font *' prefix '&' 274 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont'))) 275 276 // Get address of targeted RS object 277 clang::Expr *AddrRefRSVar = 278 new(C) clang::UnaryOperator(RefRSVar, 279 clang::UO_AddrOf, 280 ClearObjectFDArgType, 281 Loc); 282 283 clang::Expr *RefRSClearObjectFD = 284 clang::DeclRefExpr::Create(C, 285 NULL, 286 ClearObjectFD->getQualifierRange(), 287 ClearObjectFD, 288 ClearObjectFD->getLocation(), 289 ClearObjectFDType); 290 291 clang::Expr *RSClearObjectFP = 292 clang::ImplicitCastExpr::Create(C, 293 C.getPointerType(ClearObjectFDType), 294 clang::CK_FunctionToPointerDecay, 295 RefRSClearObjectFD, 296 NULL, 297 clang::VK_RValue); 298 299 clang::CallExpr *RSClearObjectCall = 300 new(C) clang::CallExpr(C, 301 RSClearObjectFP, 302 &AddrRefRSVar, 303 1, 304 ClearObjectFD->getCallResultType(), 305 Loc); 306 307 return RSClearObjectCall; 308} 309 310static int ArrayDim(const clang::Type *T) { 311 if (!T || !T->isArrayType()) { 312 return 0; 313 } 314 315 const clang::ConstantArrayType *CAT = 316 static_cast<const clang::ConstantArrayType *>(T); 317 return static_cast<int>(CAT->getSize().getSExtValue()); 318} 319 320static clang::Stmt *ClearStructRSObject( 321 clang::ASTContext &C, 322 clang::DeclContext *DC, 323 clang::Expr *RefRSStruct, 324 clang::SourceRange Range, 325 clang::SourceLocation Loc); 326 327static clang::Stmt *ClearArrayRSObject( 328 clang::ASTContext &C, 329 clang::DeclContext *DC, 330 clang::Expr *RefRSArr, 331 clang::SourceRange Range, 332 clang::SourceLocation Loc) { 333 const clang::Type *BaseType = RefRSArr->getType().getTypePtr(); 334 slangAssert(BaseType->isArrayType()); 335 336 int NumArrayElements = ArrayDim(BaseType); 337 // Actually extract out the base RS object type for use later 338 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 339 340 clang::Stmt *StmtArray[2] = {NULL}; 341 int StmtCtr = 0; 342 343 if (NumArrayElements <= 0) { 344 return NULL; 345 } 346 347 // Example destructor loop for "rs_font fontArr[10];" 348 // 349 // (CompoundStmt 350 // (DeclStmt "int rsIntIter") 351 // (ForStmt 352 // (BinaryOperator 'int' '=' 353 // (DeclRefExpr 'int' Var='rsIntIter') 354 // (IntegerLiteral 'int' 0)) 355 // (BinaryOperator 'int' '<' 356 // (DeclRefExpr 'int' Var='rsIntIter') 357 // (IntegerLiteral 'int' 10) 358 // NULL << CondVar >> 359 // (UnaryOperator 'int' postfix '++' 360 // (DeclRefExpr 'int' Var='rsIntIter')) 361 // (CallExpr 'void' 362 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 363 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 364 // (UnaryOperator 'rs_font *' prefix '&' 365 // (ArraySubscriptExpr 'rs_font':'rs_font' 366 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay> 367 // (DeclRefExpr 'rs_font [10]' Var='fontArr')) 368 // (DeclRefExpr 'int' Var='rsIntIter'))))))) 369 370 // Create helper variable for iterating through elements 371 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 372 clang::VarDecl *IIVD = 373 clang::VarDecl::Create(C, 374 DC, 375 Loc, 376 &II, 377 C.IntTy, 378 C.getTrivialTypeSourceInfo(C.IntTy), 379 clang::SC_None, 380 clang::SC_None); 381 clang::Decl *IID = (clang::Decl *)IIVD; 382 383 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 384 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 385 386 // Form the actual destructor loop 387 // for (Init; Cond; Inc) 388 // RSClearObjectCall; 389 390 // Init -> "rsIntIter = 0" 391 clang::DeclRefExpr *RefrsIntIter = 392 clang::DeclRefExpr::Create(C, 393 NULL, 394 Range, 395 IIVD, 396 Loc, 397 C.IntTy); 398 399 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 400 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 401 402 clang::BinaryOperator *Init = 403 new(C) clang::BinaryOperator(RefrsIntIter, 404 Int0, 405 clang::BO_Assign, 406 C.IntTy, 407 Loc); 408 409 // Cond -> "rsIntIter < NumArrayElements" 410 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 411 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 412 413 clang::BinaryOperator *Cond = 414 new(C) clang::BinaryOperator(RefrsIntIter, 415 NumArrayElementsExpr, 416 clang::BO_LT, 417 C.IntTy, 418 Loc); 419 420 // Inc -> "rsIntIter++" 421 clang::UnaryOperator *Inc = 422 new(C) clang::UnaryOperator(RefrsIntIter, 423 clang::UO_PostInc, 424 C.IntTy, 425 Loc); 426 427 // Body -> "rsClearObject(&VD[rsIntIter]);" 428 // Destructor loop operates on individual array elements 429 430 clang::Expr *RefRSArrPtr = 431 clang::ImplicitCastExpr::Create(C, 432 C.getPointerType(BaseType->getCanonicalTypeInternal()), 433 clang::CK_ArrayToPointerDecay, 434 RefRSArr, 435 NULL, 436 clang::VK_RValue); 437 438 clang::Expr *RefRSArrPtrSubscript = 439 new(C) clang::ArraySubscriptExpr(RefRSArrPtr, 440 RefrsIntIter, 441 BaseType->getCanonicalTypeInternal(), 442 Loc); 443 444 RSExportPrimitiveType::DataType DT = 445 RSExportPrimitiveType::GetRSSpecificType(BaseType); 446 447 clang::Stmt *RSClearObjectCall = NULL; 448 if (BaseType->isArrayType()) { 449 RSClearObjectCall = 450 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc); 451 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 452 RSClearObjectCall = 453 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc); 454 } else { 455 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc); 456 } 457 458 clang::ForStmt *DestructorLoop = 459 new(C) clang::ForStmt(C, 460 Init, 461 Cond, 462 NULL, // no condVar 463 Inc, 464 RSClearObjectCall, 465 Loc, 466 Loc, 467 Loc); 468 469 StmtArray[StmtCtr++] = DestructorLoop; 470 slangAssert(StmtCtr == 2); 471 472 clang::CompoundStmt *CS = 473 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 474 475 return CS; 476} 477 478static unsigned CountRSObjectTypes(const clang::Type *T) { 479 slangAssert(T); 480 unsigned RSObjectCount = 0; 481 482 if (T->isArrayType()) { 483 return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual()); 484 } 485 486 RSExportPrimitiveType::DataType DT = 487 RSExportPrimitiveType::GetRSSpecificType(T); 488 if (DT != RSExportPrimitiveType::DataTypeUnknown) { 489 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0); 490 } 491 492 if (!T->isStructureType()) { 493 return 0; 494 } 495 496 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 497 RD = RD->getDefinition(); 498 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 499 FE = RD->field_end(); 500 FI != FE; 501 FI++) { 502 const clang::FieldDecl *FD = *FI; 503 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 504 if (CountRSObjectTypes(FT)) { 505 // Sub-structs should only count once (as should arrays, etc.) 506 RSObjectCount++; 507 } 508 } 509 510 return RSObjectCount; 511} 512 513static clang::Stmt *ClearStructRSObject( 514 clang::ASTContext &C, 515 clang::DeclContext *DC, 516 clang::Expr *RefRSStruct, 517 clang::SourceRange Range, 518 clang::SourceLocation Loc) { 519 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr(); 520 521 slangAssert(!BaseType->isArrayType()); 522 523 RSExportPrimitiveType::DataType DT = 524 RSExportPrimitiveType::GetRSSpecificType(BaseType); 525 526 // Structs should show up as unknown primitive types 527 slangAssert(DT == RSExportPrimitiveType::DataTypeUnknown); 528 529 unsigned FieldsToDestroy = CountRSObjectTypes(BaseType); 530 531 unsigned StmtCount = 0; 532 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy]; 533 for (unsigned i = 0; i < FieldsToDestroy; i++) { 534 StmtArray[i] = NULL; 535 } 536 537 // Populate StmtArray by creating a destructor for each RS object field 538 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl(); 539 RD = RD->getDefinition(); 540 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 541 FE = RD->field_end(); 542 FI != FE; 543 FI++) { 544 // We just look through all field declarations to see if we find a 545 // declaration for an RS object type (or an array of one). 546 bool IsArrayType = false; 547 clang::FieldDecl *FD = *FI; 548 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 549 const clang::Type *OrigType = FT; 550 while (FT && FT->isArrayType()) { 551 FT = FT->getArrayElementTypeNoTypeQual(); 552 IsArrayType = true; 553 } 554 555 if (RSExportPrimitiveType::IsRSObjectType(FT)) { 556 clang::DeclAccessPair FoundDecl = 557 clang::DeclAccessPair::make(FD, clang::AS_none); 558 clang::MemberExpr *RSObjectMember = 559 clang::MemberExpr::Create(C, 560 RefRSStruct, 561 false, 562 NULL, 563 Range, 564 FD, 565 FoundDecl, 566 clang::DeclarationNameInfo(), 567 NULL, 568 OrigType->getCanonicalTypeInternal()); 569 570 slangAssert(StmtCount < FieldsToDestroy); 571 572 if (IsArrayType) { 573 StmtArray[StmtCount++] = ClearArrayRSObject(C, 574 DC, 575 RSObjectMember, 576 Range, 577 Loc); 578 } else { 579 StmtArray[StmtCount++] = ClearSingleRSObject(C, 580 RSObjectMember, 581 Loc); 582 } 583 } else if (FT->isStructureType() && CountRSObjectTypes(FT)) { 584 // In this case, we have a nested struct. We may not end up filling all 585 // of the spaces in StmtArray (sub-structs should handle themselves 586 // with separate compound statements). 587 clang::DeclAccessPair FoundDecl = 588 clang::DeclAccessPair::make(FD, clang::AS_none); 589 clang::MemberExpr *RSObjectMember = 590 clang::MemberExpr::Create(C, 591 RefRSStruct, 592 false, 593 NULL, 594 Range, 595 FD, 596 FoundDecl, 597 clang::DeclarationNameInfo(), 598 NULL, 599 OrigType->getCanonicalTypeInternal()); 600 601 if (IsArrayType) { 602 StmtArray[StmtCount++] = ClearArrayRSObject(C, 603 DC, 604 RSObjectMember, 605 Range, 606 Loc); 607 } else { 608 StmtArray[StmtCount++] = ClearStructRSObject(C, 609 DC, 610 RSObjectMember, 611 Range, 612 Loc); 613 } 614 } 615 } 616 617 slangAssert(StmtCount > 0); 618 clang::CompoundStmt *CS = 619 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc); 620 621 delete [] StmtArray; 622 623 return CS; 624} 625 626static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C, 627 clang::Diagnostic *Diags, 628 clang::Expr *DstExpr, 629 clang::Expr *SrcExpr, 630 clang::SourceLocation Loc) { 631 const clang::Type *T = DstExpr->getType().getTypePtr(); 632 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T); 633 slangAssert((SetObjectFD != NULL) && 634 "rsSetObject doesn't cover all RS object types"); 635 636 clang::QualType SetObjectFDType = SetObjectFD->getType(); 637 clang::QualType SetObjectFDArgType[2]; 638 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 639 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 640 641 clang::Expr *RefRSSetObjectFD = 642 clang::DeclRefExpr::Create(C, 643 NULL, 644 SetObjectFD->getQualifierRange(), 645 SetObjectFD, 646 Loc, 647 SetObjectFDType); 648 649 clang::Expr *RSSetObjectFP = 650 clang::ImplicitCastExpr::Create(C, 651 C.getPointerType(SetObjectFDType), 652 clang::CK_FunctionToPointerDecay, 653 RefRSSetObjectFD, 654 NULL, 655 clang::VK_RValue); 656 657 clang::Expr *ArgList[2]; 658 ArgList[0] = new(C) clang::UnaryOperator(DstExpr, 659 clang::UO_AddrOf, 660 SetObjectFDArgType[0], 661 Loc); 662 ArgList[1] = SrcExpr; 663 664 clang::CallExpr *RSSetObjectCall = 665 new(C) clang::CallExpr(C, 666 RSSetObjectFP, 667 ArgList, 668 2, 669 SetObjectFD->getCallResultType(), 670 Loc); 671 672 return RSSetObjectCall; 673} 674 675static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 676 clang::Diagnostic *Diags, 677 clang::Expr *LHS, 678 clang::Expr *RHS, 679 clang::SourceLocation Loc); 680 681static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C, 682 clang::Diagnostic *Diags, 683 clang::Expr *DstArr, 684 clang::Expr *SrcArr, 685 clang::SourceLocation Loc) { 686 clang::DeclContext *DC = NULL; 687 clang::SourceRange Range; 688 const clang::Type *BaseType = DstArr->getType().getTypePtr(); 689 slangAssert(BaseType->isArrayType()); 690 691 int NumArrayElements = ArrayDim(BaseType); 692 // Actually extract out the base RS object type for use later 693 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 694 695 clang::Stmt *StmtArray[2] = {NULL}; 696 int StmtCtr = 0; 697 698 if (NumArrayElements <= 0) { 699 return NULL; 700 } 701 702 // Create helper variable for iterating through elements 703 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 704 clang::VarDecl *IIVD = 705 clang::VarDecl::Create(C, 706 DC, 707 Loc, 708 &II, 709 C.IntTy, 710 C.getTrivialTypeSourceInfo(C.IntTy), 711 clang::SC_None, 712 clang::SC_None); 713 clang::Decl *IID = (clang::Decl *)IIVD; 714 715 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 716 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 717 718 // Form the actual loop 719 // for (Init; Cond; Inc) 720 // RSSetObjectCall; 721 722 // Init -> "rsIntIter = 0" 723 clang::DeclRefExpr *RefrsIntIter = 724 clang::DeclRefExpr::Create(C, 725 NULL, 726 Range, 727 IIVD, 728 Loc, 729 C.IntTy); 730 731 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 732 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 733 734 clang::BinaryOperator *Init = 735 new(C) clang::BinaryOperator(RefrsIntIter, 736 Int0, 737 clang::BO_Assign, 738 C.IntTy, 739 Loc); 740 741 // Cond -> "rsIntIter < NumArrayElements" 742 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 743 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 744 745 clang::BinaryOperator *Cond = 746 new(C) clang::BinaryOperator(RefrsIntIter, 747 NumArrayElementsExpr, 748 clang::BO_LT, 749 C.IntTy, 750 Loc); 751 752 // Inc -> "rsIntIter++" 753 clang::UnaryOperator *Inc = 754 new(C) clang::UnaryOperator(RefrsIntIter, 755 clang::UO_PostInc, 756 C.IntTy, 757 Loc); 758 759 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);" 760 // Loop operates on individual array elements 761 762 clang::Expr *DstArrPtr = 763 clang::ImplicitCastExpr::Create(C, 764 C.getPointerType(BaseType->getCanonicalTypeInternal()), 765 clang::CK_ArrayToPointerDecay, 766 DstArr, 767 NULL, 768 clang::VK_RValue); 769 770 clang::Expr *DstArrPtrSubscript = 771 new(C) clang::ArraySubscriptExpr(DstArrPtr, 772 RefrsIntIter, 773 BaseType->getCanonicalTypeInternal(), 774 Loc); 775 776 clang::Expr *SrcArrPtr = 777 clang::ImplicitCastExpr::Create(C, 778 C.getPointerType(BaseType->getCanonicalTypeInternal()), 779 clang::CK_ArrayToPointerDecay, 780 SrcArr, 781 NULL, 782 clang::VK_RValue); 783 784 clang::Expr *SrcArrPtrSubscript = 785 new(C) clang::ArraySubscriptExpr(SrcArrPtr, 786 RefrsIntIter, 787 BaseType->getCanonicalTypeInternal(), 788 Loc); 789 790 RSExportPrimitiveType::DataType DT = 791 RSExportPrimitiveType::GetRSSpecificType(BaseType); 792 793 clang::Stmt *RSSetObjectCall = NULL; 794 if (BaseType->isArrayType()) { 795 RSSetObjectCall = CreateArrayRSSetObject(C, Diags, DstArrPtrSubscript, 796 SrcArrPtrSubscript, Loc); 797 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 798 RSSetObjectCall = CreateStructRSSetObject(C, Diags, DstArrPtrSubscript, 799 SrcArrPtrSubscript, Loc); 800 } else { 801 RSSetObjectCall = CreateSingleRSSetObject(C, Diags, DstArrPtrSubscript, 802 SrcArrPtrSubscript, Loc); 803 } 804 805 clang::ForStmt *DestructorLoop = 806 new(C) clang::ForStmt(C, 807 Init, 808 Cond, 809 NULL, // no condVar 810 Inc, 811 RSSetObjectCall, 812 Loc, 813 Loc, 814 Loc); 815 816 StmtArray[StmtCtr++] = DestructorLoop; 817 slangAssert(StmtCtr == 2); 818 819 clang::CompoundStmt *CS = 820 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 821 822 return CS; 823} 824 825static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 826 clang::Diagnostic *Diags, 827 clang::Expr *LHS, 828 clang::Expr *RHS, 829 clang::SourceLocation Loc) { 830 clang::SourceRange Range; 831 clang::QualType QT = LHS->getType(); 832 const clang::Type *T = QT.getTypePtr(); 833 slangAssert(T->isStructureType()); 834 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T)); 835 836 // Keep an extra slot for the original copy (memcpy) 837 unsigned FieldsToSet = CountRSObjectTypes(T) + 1; 838 839 unsigned StmtCount = 0; 840 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet]; 841 for (unsigned i = 0; i < FieldsToSet; i++) { 842 StmtArray[i] = NULL; 843 } 844 845 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 846 RD = RD->getDefinition(); 847 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 848 FE = RD->field_end(); 849 FI != FE; 850 FI++) { 851 bool IsArrayType = false; 852 clang::FieldDecl *FD = *FI; 853 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 854 const clang::Type *OrigType = FT; 855 856 if (!CountRSObjectTypes(FT)) { 857 // Skip to next if we don't have any viable RS object types 858 continue; 859 } 860 861 clang::DeclAccessPair FoundDecl = 862 clang::DeclAccessPair::make(FD, clang::AS_none); 863 clang::MemberExpr *DstMember = 864 clang::MemberExpr::Create(C, 865 LHS, 866 false, 867 NULL, 868 Range, 869 FD, 870 FoundDecl, 871 clang::DeclarationNameInfo(), 872 NULL, 873 OrigType->getCanonicalTypeInternal()); 874 875 clang::MemberExpr *SrcMember = 876 clang::MemberExpr::Create(C, 877 RHS, 878 false, 879 NULL, 880 Range, 881 FD, 882 FoundDecl, 883 clang::DeclarationNameInfo(), 884 NULL, 885 OrigType->getCanonicalTypeInternal()); 886 887 if (FT->isArrayType()) { 888 FT = FT->getArrayElementTypeNoTypeQual(); 889 IsArrayType = true; 890 } 891 892 RSExportPrimitiveType::DataType DT = 893 RSExportPrimitiveType::GetRSSpecificType(FT); 894 895 if (IsArrayType) { 896 Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error, 897 "Arrays of RS object types within structures cannot be copied")); 898 // TODO(srhines): Support setting arrays of RS objects 899 // StmtArray[StmtCount++] = 900 // CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, Loc); 901 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 902 StmtArray[StmtCount++] = 903 CreateStructRSSetObject(C, Diags, DstMember, SrcMember, Loc); 904 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) { 905 StmtArray[StmtCount++] = 906 CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, Loc); 907 } else { 908 slangAssert(false); 909 } 910 } 911 912 slangAssert(StmtCount > 0 && StmtCount < FieldsToSet); 913 914 // We still need to actually do the overall struct copy. For simplicity, 915 // we just do a straight-up assignment (which will still preserve all 916 // the proper RS object reference counts). 917 clang::BinaryOperator *CopyStruct = 918 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, Loc); 919 StmtArray[StmtCount++] = CopyStruct; 920 921 clang::CompoundStmt *CS = 922 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc); 923 924 delete [] StmtArray; 925 926 return CS; 927} 928 929} // namespace 930 931void RSObjectRefCount::Scope::ReplaceRSObjectAssignment( 932 clang::BinaryOperator *AS, 933 clang::Diagnostic *Diags) { 934 935 clang::QualType QT = AS->getType(); 936 937 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 938 RSExportPrimitiveType::DataTypeRSFont)->getASTContext(); 939 940 clang::SourceLocation Loc = AS->getLocEnd(); 941 clang::Stmt *UpdatedStmt = NULL; 942 943 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) { 944 // By definition, this is a struct assignment if we get here 945 UpdatedStmt = 946 CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc); 947 } else { 948 UpdatedStmt = 949 CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc); 950 } 951 952 ReplaceInCompoundStmt(C, mCS, AS, UpdatedStmt); 953 return; 954} 955 956void RSObjectRefCount::Scope::AppendRSObjectInit( 957 clang::Diagnostic *Diags, 958 clang::VarDecl *VD, 959 clang::DeclStmt *DS, 960 RSExportPrimitiveType::DataType DT, 961 clang::Expr *InitExpr) { 962 slangAssert(VD); 963 964 if (!InitExpr) { 965 return; 966 } 967 968 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 969 RSExportPrimitiveType::DataTypeRSFont)->getASTContext(); 970 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD( 971 RSExportPrimitiveType::DataTypeRSFont)->getLocation(); 972 973 if (DT == RSExportPrimitiveType::DataTypeIsStruct) { 974 // TODO(srhines): Skip struct initialization right now 975 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 976 clang::DeclRefExpr *RefRSVar = 977 clang::DeclRefExpr::Create(C, 978 NULL, 979 VD->getQualifierRange(), 980 VD, 981 Loc, 982 T->getCanonicalTypeInternal()); 983 984 clang::Stmt *RSSetObjectOps = 985 CreateStructRSSetObject(C, Diags, RefRSVar, InitExpr, Loc); 986 987 AppendAfterStmt(C, mCS, DS, RSSetObjectOps); 988 return; 989 } 990 991 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT); 992 slangAssert((SetObjectFD != NULL) && 993 "rsSetObject doesn't cover all RS object types"); 994 995 clang::QualType SetObjectFDType = SetObjectFD->getType(); 996 clang::QualType SetObjectFDArgType[2]; 997 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 998 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 999 1000 clang::Expr *RefRSSetObjectFD = 1001 clang::DeclRefExpr::Create(C, 1002 NULL, 1003 SetObjectFD->getQualifierRange(), 1004 SetObjectFD, 1005 Loc, 1006 SetObjectFDType); 1007 1008 clang::Expr *RSSetObjectFP = 1009 clang::ImplicitCastExpr::Create(C, 1010 C.getPointerType(SetObjectFDType), 1011 clang::CK_FunctionToPointerDecay, 1012 RefRSSetObjectFD, 1013 NULL, 1014 clang::VK_RValue); 1015 1016 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1017 clang::DeclRefExpr *RefRSVar = 1018 clang::DeclRefExpr::Create(C, 1019 NULL, 1020 VD->getQualifierRange(), 1021 VD, 1022 Loc, 1023 T->getCanonicalTypeInternal()); 1024 1025 clang::Expr *ArgList[2]; 1026 ArgList[0] = new(C) clang::UnaryOperator(RefRSVar, 1027 clang::UO_AddrOf, 1028 SetObjectFDArgType[0], 1029 Loc); 1030 ArgList[1] = InitExpr; 1031 1032 clang::CallExpr *RSSetObjectCall = 1033 new(C) clang::CallExpr(C, 1034 RSSetObjectFP, 1035 ArgList, 1036 2, 1037 SetObjectFD->getCallResultType(), 1038 Loc); 1039 1040 AppendAfterStmt(C, mCS, DS, RSSetObjectCall); 1041 1042 return; 1043} 1044 1045void RSObjectRefCount::Scope::InsertLocalVarDestructors() { 1046 std::list<clang::Stmt*> RSClearObjectCalls; 1047 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(), 1048 E = mRSO.end(); 1049 I != E; 1050 I++) { 1051 clang::Stmt *S = ClearRSObject(*I); 1052 if (S) { 1053 RSClearObjectCalls.push_back(S); 1054 } 1055 } 1056 if (RSClearObjectCalls.size() > 0) { 1057 DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls); 1058 DV.Visit(mCS); 1059 } 1060 return; 1061} 1062 1063clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) { 1064 slangAssert(VD); 1065 clang::ASTContext &C = VD->getASTContext(); 1066 clang::DeclContext *DC = VD->getDeclContext(); 1067 clang::SourceRange Range = VD->getQualifierRange(); 1068 clang::SourceLocation Loc = VD->getLocation(); 1069 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1070 1071 // Reference expr to target RS object variable 1072 clang::DeclRefExpr *RefRSVar = 1073 clang::DeclRefExpr::Create(C, 1074 NULL, 1075 Range, 1076 VD, 1077 Loc, 1078 T->getCanonicalTypeInternal()); 1079 1080 if (T->isArrayType()) { 1081 return ClearArrayRSObject(C, DC, RefRSVar, Range, Loc); 1082 } 1083 1084 RSExportPrimitiveType::DataType DT = 1085 RSExportPrimitiveType::GetRSSpecificType(T); 1086 1087 if (DT == RSExportPrimitiveType::DataTypeUnknown || 1088 DT == RSExportPrimitiveType::DataTypeIsStruct) { 1089 return ClearStructRSObject(C, DC, RefRSVar, Range, Loc); 1090 } 1091 1092 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) && 1093 "Should be RS object"); 1094 1095 return ClearSingleRSObject(C, RefRSVar, Loc); 1096} 1097 1098bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD, 1099 RSExportPrimitiveType::DataType *DT, 1100 clang::Expr **InitExpr) { 1101 slangAssert(VD && DT && InitExpr); 1102 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1103 1104 // Loop through array types to get to base type 1105 while (T && T->isArrayType()) { 1106 T = T->getArrayElementTypeNoTypeQual(); 1107 } 1108 1109 bool DataTypeIsStructWithRSObject = false; 1110 *DT = RSExportPrimitiveType::GetRSSpecificType(T); 1111 1112 if (*DT == RSExportPrimitiveType::DataTypeUnknown) { 1113 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) { 1114 *DT = RSExportPrimitiveType::DataTypeIsStruct; 1115 DataTypeIsStructWithRSObject = true; 1116 } else { 1117 return false; 1118 } 1119 } 1120 1121 bool DataTypeIsRSObject = false; 1122 if (DataTypeIsStructWithRSObject) { 1123 DataTypeIsRSObject = true; 1124 } else { 1125 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT); 1126 } 1127 *InitExpr = VD->getInit(); 1128 1129 if (!DataTypeIsRSObject && *InitExpr) { 1130 // If we already have an initializer for a matrix type, we are done. 1131 return DataTypeIsRSObject; 1132 } 1133 1134 clang::Expr *ZeroInitializer = 1135 CreateZeroInitializerForRSSpecificType(*DT, 1136 VD->getASTContext(), 1137 VD->getLocation()); 1138 1139 if (ZeroInitializer) { 1140 ZeroInitializer->setType(T->getCanonicalTypeInternal()); 1141 VD->setInit(ZeroInitializer); 1142 } 1143 1144 return DataTypeIsRSObject; 1145} 1146 1147clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType( 1148 RSExportPrimitiveType::DataType DT, 1149 clang::ASTContext &C, 1150 const clang::SourceLocation &Loc) { 1151 clang::Expr *Res = NULL; 1152 switch (DT) { 1153 case RSExportPrimitiveType::DataTypeIsStruct: 1154 case RSExportPrimitiveType::DataTypeRSElement: 1155 case RSExportPrimitiveType::DataTypeRSType: 1156 case RSExportPrimitiveType::DataTypeRSAllocation: 1157 case RSExportPrimitiveType::DataTypeRSSampler: 1158 case RSExportPrimitiveType::DataTypeRSScript: 1159 case RSExportPrimitiveType::DataTypeRSMesh: 1160 case RSExportPrimitiveType::DataTypeRSProgramFragment: 1161 case RSExportPrimitiveType::DataTypeRSProgramVertex: 1162 case RSExportPrimitiveType::DataTypeRSProgramRaster: 1163 case RSExportPrimitiveType::DataTypeRSProgramStore: 1164 case RSExportPrimitiveType::DataTypeRSFont: { 1165 // (ImplicitCastExpr 'nullptr_t' 1166 // (IntegerLiteral 0))) 1167 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0); 1168 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc); 1169 clang::Expr *CastToNull = 1170 clang::ImplicitCastExpr::Create(C, 1171 C.NullPtrTy, 1172 clang::CK_IntegralToPointer, 1173 Int0, 1174 NULL, 1175 clang::VK_RValue); 1176 1177 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc); 1178 break; 1179 } 1180 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 1181 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 1182 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 1183 // RS matrix is not completely an RS object. They hold data by themselves. 1184 // (InitListExpr rs_matrix2x2 1185 // (InitListExpr float[4] 1186 // (FloatingLiteral 0) 1187 // (FloatingLiteral 0) 1188 // (FloatingLiteral 0) 1189 // (FloatingLiteral 0))) 1190 clang::QualType FloatTy = C.FloatTy; 1191 // Constructor sets value to 0.0f by default 1192 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy)); 1193 clang::FloatingLiteral *Float0Val = 1194 clang::FloatingLiteral::Create(C, 1195 Val, 1196 /* isExact = */true, 1197 FloatTy, 1198 Loc); 1199 1200 unsigned N = 0; 1201 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2) 1202 N = 2; 1203 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3) 1204 N = 3; 1205 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4) 1206 N = 4; 1207 1208 // Directly allocate 16 elements instead of dynamically allocate N*N 1209 clang::Expr *InitVals[16]; 1210 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++) 1211 InitVals[i] = Float0Val; 1212 clang::Expr *InitExpr = 1213 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc); 1214 InitExpr->setType(C.getConstantArrayType(FloatTy, 1215 llvm::APInt(32, 4), 1216 clang::ArrayType::Normal, 1217 /* EltTypeQuals = */0)); 1218 1219 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc); 1220 break; 1221 } 1222 case RSExportPrimitiveType::DataTypeUnknown: 1223 case RSExportPrimitiveType::DataTypeFloat16: 1224 case RSExportPrimitiveType::DataTypeFloat32: 1225 case RSExportPrimitiveType::DataTypeFloat64: 1226 case RSExportPrimitiveType::DataTypeSigned8: 1227 case RSExportPrimitiveType::DataTypeSigned16: 1228 case RSExportPrimitiveType::DataTypeSigned32: 1229 case RSExportPrimitiveType::DataTypeSigned64: 1230 case RSExportPrimitiveType::DataTypeUnsigned8: 1231 case RSExportPrimitiveType::DataTypeUnsigned16: 1232 case RSExportPrimitiveType::DataTypeUnsigned32: 1233 case RSExportPrimitiveType::DataTypeUnsigned64: 1234 case RSExportPrimitiveType::DataTypeBoolean: 1235 case RSExportPrimitiveType::DataTypeUnsigned565: 1236 case RSExportPrimitiveType::DataTypeUnsigned5551: 1237 case RSExportPrimitiveType::DataTypeUnsigned4444: 1238 case RSExportPrimitiveType::DataTypeMax: { 1239 slangAssert(false && "Not RS object type!"); 1240 } 1241 // No default case will enable compiler detecting the missing cases 1242 } 1243 1244 return Res; 1245} 1246 1247void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) { 1248 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1249 I != E; 1250 I++) { 1251 clang::Decl *D = *I; 1252 if (D->getKind() == clang::Decl::Var) { 1253 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D); 1254 RSExportPrimitiveType::DataType DT = 1255 RSExportPrimitiveType::DataTypeUnknown; 1256 clang::Expr *InitExpr = NULL; 1257 if (InitializeRSObject(VD, &DT, &InitExpr)) { 1258 getCurrentScope()->addRSObject(VD); 1259 getCurrentScope()->AppendRSObjectInit(mDiags, VD, DS, DT, InitExpr); 1260 } 1261 } 1262 } 1263 return; 1264} 1265 1266void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) { 1267 if (!CS->body_empty()) { 1268 // Push a new scope 1269 Scope *S = new Scope(CS); 1270 mScopeStack.push(S); 1271 1272 VisitStmt(CS); 1273 1274 // Destroy the scope 1275 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!"); 1276 S->InsertLocalVarDestructors(); 1277 mScopeStack.pop(); 1278 delete S; 1279 } 1280 return; 1281} 1282 1283void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) { 1284 clang::QualType QT = AS->getType(); 1285 1286 if (CountRSObjectTypes(QT.getTypePtr())) { 1287 getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags); 1288 } 1289 1290 return; 1291} 1292 1293void RSObjectRefCount::VisitStmt(clang::Stmt *S) { 1294 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 1295 I != E; 1296 I++) { 1297 if (clang::Stmt *Child = *I) { 1298 Visit(Child); 1299 } 1300 } 1301 return; 1302} 1303 1304} // namespace slang 1305