TransARCAssign.cpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. //===--- TransARCAssign.cpp - Transformations to ARC mode -----------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // makeAssignARCSafe:
  11. //
  12. // Add '__strong' where appropriate.
  13. //
  14. // for (id x in collection) {
  15. // x = 0;
  16. // }
  17. // ---->
  18. // for (__strong id x in collection) {
  19. // x = 0;
  20. // }
  21. //
  22. //===----------------------------------------------------------------------===//
  23. #include "Transforms.h"
  24. #include "Internals.h"
  25. #include "clang/AST/ASTContext.h"
  26. #include "clang/Sema/SemaDiagnostic.h"
  27. using namespace clang;
  28. using namespace arcmt;
  29. using namespace trans;
  30. namespace {
  31. class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> {
  32. MigrationPass &Pass;
  33. llvm::DenseSet<VarDecl *> ModifiedVars;
  34. public:
  35. ARCAssignChecker(MigrationPass &pass) : Pass(pass) { }
  36. bool VisitBinaryOperator(BinaryOperator *Exp) {
  37. if (Exp->getType()->isDependentType())
  38. return true;
  39. Expr *E = Exp->getLHS();
  40. SourceLocation OrigLoc = E->getExprLoc();
  41. SourceLocation Loc = OrigLoc;
  42. DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts());
  43. if (declRef && isa<VarDecl>(declRef->getDecl())) {
  44. ASTContext &Ctx = Pass.Ctx;
  45. Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(Ctx, &Loc);
  46. if (IsLV != Expr::MLV_ConstQualified)
  47. return true;
  48. VarDecl *var = cast<VarDecl>(declRef->getDecl());
  49. if (var->isARCPseudoStrong()) {
  50. Transaction Trans(Pass.TA);
  51. if (Pass.TA.clearDiagnostic(diag::err_typecheck_arr_assign_enumeration,
  52. Exp->getOperatorLoc())) {
  53. if (!ModifiedVars.count(var)) {
  54. TypeLoc TLoc = var->getTypeSourceInfo()->getTypeLoc();
  55. Pass.TA.insert(TLoc.getBeginLoc(), "__strong ");
  56. ModifiedVars.insert(var);
  57. }
  58. }
  59. }
  60. }
  61. return true;
  62. }
  63. };
  64. } // anonymous namespace
  65. void trans::makeAssignARCSafe(MigrationPass &pass) {
  66. ARCAssignChecker assignCheck(pass);
  67. assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
  68. }