clang: lib/ARCMigrate/TransGCAttrs.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

15#include "llvm/ADT/SmallString.h"

16#include "llvm/ADT/TinyPtrVector.h"

17#include "llvm/Support/SaveAndRestore.h"

18

19using namespace clang;

20using namespace arcmt;

21using namespace trans;

22

23namespace {

24

25

28 bool FullyMigratable;

29 std::vector<ObjCPropertyDecl *> &AllProps;

30

32public:

34 std::vector<ObjCPropertyDecl *> &AllProps)

35 : MigrateCtx(ctx), FullyMigratable(false),

36 AllProps(AllProps) { }

37

39

41 handleAttr(TL);

42 return true;

43 }

44

47 return true;

48

50

52 lookForAttribute(PropD, PropD->getTypeSourceInfo());

53 AllProps.push_back(PropD);

54 } else if (DeclaratorDecl *DD = dyn_cast(D)) {

55 lookForAttribute(DD, DD->getTypeSourceInfo());

56 }

58 }

59

61 if (!TInfo)

62 return;

64 while (TL) {

68 if (handleAttr(Attr, D))

69 break;

70 TL = Attr.getModifiedLoc();

73 TL = MDTL.getInnerLoc();

75 TL = Arr.getElementLoc();

77 TL = PT.getPointeeLoc();

79 TL = RT.getPointeeLoc();

80 else

81 break;

82 }

83 }

84

86 auto *OwnershipAttr = TL.getAttrAs();

87 if (!OwnershipAttr)

88 return false;

89

92 if (MigrateCtx.AttrSet.count(OrigLoc))

93 return true;

94

98 Loc = SM.getImmediateExpansionRange(Loc).getBegin();

99 StringRef Spell = OwnershipAttr->getKind()->getName();

101 if (Spell == "strong")

103 else if (Spell == "weak")

105 else

106 return false;

107

108 MigrateCtx.AttrSet.insert(OrigLoc);

111

116 Attr.FullyMigratable = FullyMigratable;

117 return true;

118 }

119

120 bool isMigratable(Decl *D) {

121 if (isa(D))

122 return false;

123

125 return true;

126

127 if (FunctionDecl *FD = dyn_cast(D))

128 return FD->hasBody();

129

131 return hasObjCImpl(ContD);

132

133 if (CXXRecordDecl *RD = dyn_cast(D)) {

134 for (const auto *MI : RD->methods()) {

135 if (MI->isOutOfLine())

136 return true;

137 }

138 return false;

139 }

140

142 }

143

144 static bool hasObjCImpl(Decl *D) {

145 if (D)

146 return false;

149 return ID->getImplementation() != nullptr;

150 if (ObjCCategoryDecl *CD = dyn_cast(ContD))

151 return CD->getImplementation() != nullptr;

152 return isa(ContD);

153 }

154 return false;

155 }

156

158 if (D)

159 return false;

160

163 return false;

164

165 return true;

166 }

167

170 return false;

171

173 return SM.isInFileID(SM.getExpansionLoc(Loc), SM.getMainFileID());

174 }

175};

176

177}

178

181

182 for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {

184 if (Attr.FullyMigratable && Attr.Dcl) {

185 if (Attr.ModifiedType.isNull())

186 continue;

187 if (Attr.ModifiedType->isObjCRetainableType()) {

188 TA.reportError("GC managed memory will become unmanaged in ARC",

190 }

191 }

192 }

193}

194

197

198 for (unsigned i = 0, e = MigrateCtx.GCAttrs.size(); i != e; ++i) {

201 if (Attr.ModifiedType.isNull() ||

202 Attr.ModifiedType->isObjCRetainableType())

203 continue;

205 true)) {

208 TA.replaceText(Attr.Loc, "__weak", "__unsafe_unretained");

210 diag::err_arc_unsupported_weak_class,

212 }

213 }

214 }

215}

216

217typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;

218

222 if (IndProps.empty())

223 return;

224

225 for (IndivPropsTy::iterator

226 PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {

229 return;

230 }

231

233 bool hasWeak = false, hasStrong = false;

235 for (IndivPropsTy::iterator

236 PI = IndProps.begin(), PE = IndProps.end(); PI != PE; ++PI) {

240 if (!TInfo)

241 return;

245 ATLs.push_back(std::make_pair(ATL, PD));

247 hasWeak = true;

249 hasStrong = true;

250 else

251 return;

252 }

253 }

254 if (ATLs.empty())

255 return;

256 if (hasWeak && hasStrong)

257 return;

258

261

262 if (GCAttrsCollector::hasObjCImpl(

263 cast(IndProps.front()->getDeclContext()))) {

264 if (hasWeak)

266

267 } else {

268 StringRef toAttr = "strong";

269 if (hasWeak) {

271 true))

272 toAttr = "weak";

273 else

274 toAttr = "unsafe_unretained";

275 }

278 else

280 }

281

282 for (unsigned i = 0, e = ATLs.size(); i != e; ++i) {

289 TA.clearDiagnostic(diag::err_objc_property_attr_mutually_exclusive, AtLoc);

290 TA.clearDiagnostic(diag::err_arc_inconsistent_property_ownership,

291 ATLs[i].second->getLocation());

293 }

294}

295

297 std::vector<ObjCPropertyDecl *> &AllProps) {

298 typedef llvm::TinyPtrVector<ObjCPropertyDecl *> IndivPropsTy;

299 llvm::DenseMap<SourceLocation, IndivPropsTy> AtProps;

300

301 for (unsigned i = 0, e = AllProps.size(); i != e; ++i) {

308 continue;

309 AtProps[AtLoc].push_back(PD);

310 }

311 }

312

313 for (auto I = AtProps.begin(), E = AtProps.end(); I != E; ++I) {

317 }

318}

319

321 std::vector<ObjCPropertyDecl *> AllProps;

322 GCAttrsCollector(MigrateCtx, AllProps).TraverseDecl(

324

328}

329

331 llvm::errs() << "\n################\n";

332 for (unsigned i = 0, e = GCAttrs.size(); i != e; ++i) {

334 llvm::errs() << "KIND: "

336 llvm::errs() << "\nLOC: ";

338 llvm::errs() << "\nTYPE: ";

339 Attr.ModifiedType.dump();

340 if (Attr.Dcl) {

341 llvm::errs() << "DECL:\n";

342 Attr.Dcl->dump();

343 } else {

344 llvm::errs() << "DECL: NONE";

345 }

346 llvm::errs() << "\nMIGRATABLE: " << Attr.FullyMigratable;

347 llvm::errs() << "\n----------------\n";

348 }

349 llvm::errs() << "\n################\n";

350}

Defines the clang::ASTContext interface.

static bool isInMainFile(const clang::Diagnostic &D)

Defines the SourceManager interface.

static void checkAllProps(MigrationContext &MigrateCtx, std::vector< ObjCPropertyDecl * > &AllProps)

static void checkAllAtProps(MigrationContext &MigrateCtx, SourceLocation AtLoc, IndivPropsTy &IndProps)

llvm::TinyPtrVector< ObjCPropertyDecl * > IndivPropsTy

static void checkWeakGCAttrs(MigrationContext &MigrateCtx)

static void errorForGCAttrsOnNonObjC(MigrationContext &MigrateCtx)

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

SourceManager & getSourceManager()

TranslationUnitDecl * getTranslationUnitDecl() const

Wrapper for source info for arrays.

Attr - This represents one attribute.

Type source information for an attributed type.

TypeLoc getModifiedLoc() const

The modified type, which is generally canonically different from the attribute type.

Represents a C++ struct/union/class.

SourceLocation getBegin() const

Decl - This represents one declaration (or definition), e.g.

bool isImplicit() const

isImplicit - Indicates whether the declaration was implicitly generated by the implementation.

redecl_range redecls() const

Returns an iterator range for all the redeclarations of the same decl.

DeclContext * getDeclContext()

Represents a ValueDecl that came out of a declarator.

Represents a function declaration or definition.

ObjCCategoryDecl - Represents a category declaration.

ObjCContainerDecl - Represents a container for method declarations.

Represents an ObjC class declaration.

Represents one property declaration in an Objective-C interface.

SourceLocation getAtLoc() const

TypeSourceInfo * getTypeSourceInfo() const

ObjCPropertyAttribute::Kind getPropertyAttributesAsWritten() const

Wrapper for source info for pointers.

A (possibly-)qualified type.

Qualifiers::ObjCLifetime getObjCLifetime() const

Returns lifetime attribute of this type.

Wrapper of type source information for a type with non-trivial direct qualifiers.

@ OCL_Strong

Assigning into this object requires the old value to be released and the new value to be retained.

@ OCL_Weak

Reading or writing from this object requires a barrier call.

A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...

bool TraverseDecl(Decl *D)

Recursively visit a declaration, by dispatching to Traverse*Decl() based on the argument's dynamic ty...

bool shouldWalkTypesOfTypeLocs() const

Return whether this visitor should recurse into the types of TypeLocs.

Encodes a location in the source.

This class handles loading and caching of source files into memory.

CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const

Return the start/end of the expansion information for an expansion location.

Base wrapper for a particular "section" of type source info.

UnqualTypeLoc getUnqualifiedLoc() const

Skips past any qualifiers, if this is qualified.

QualType getType() const

Get the type for which this source info wrapper provides information.

T getAs() const

Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...

A container of type source information.

TypeLoc getTypeLoc() const

Return the TypeLoc wrapper for the type source info.

QualType getType() const

Return the type wrapped by this type source info.

bool isObjCRetainableType() const

bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)

void remove(SourceRange range)

void reportError(StringRef error, SourceLocation loc, SourceRange range=SourceRange())

void replaceText(SourceLocation loc, StringRef text, StringRef replacementText)

void traverseTU(MigrationContext &MigrateCtx) override

llvm::DenseSet< SourceLocation > AttrSet

bool addPropertyAttribute(StringRef attr, SourceLocation atLoc)

std::vector< GCAttrOccurrence > GCAttrs

llvm::DenseSet< SourceLocation > AtPropsWeak

Set of raw '@' locations for 'assign' properties group that contain GC __weak.

bool rewritePropertyAttribute(StringRef fromAttr, StringRef toAttr, SourceLocation atLoc)

llvm::DenseSet< SourceLocation > RemovedAttrSet

bool canApplyWeak(ASTContext &Ctx, QualType type, bool AllowOnUnknownClass=false)

Determine whether we can add weak to the given type.

The JSON file list parser is used to communicate input to InstallAPI.

const FunctionProtoType * T