TransARCAssign.cpp 2.2 KB

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