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) {
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 ()
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 ()
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 (.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 .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