clang 24.0.0git
RewriteModernObjC.cpp
Go to the documentation of this file.
1//===-- RewriteModernObjC.cpp - Playground for the code rewriter ----------===//
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// Hacks and fun related to the code rewriter.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/AST.h"
15#include "clang/AST/Attr.h"
16#include "clang/AST/ParentMap.h"
22#include "clang/Config/config.h"
23#include "clang/Lex/Lexer.h"
26#include "llvm/ADT/DenseSet.h"
27#include "llvm/ADT/SetVector.h"
28#include "llvm/ADT/SmallPtrSet.h"
29#include "llvm/ADT/StringExtras.h"
30#include "llvm/Support/MemoryBuffer.h"
31#include "llvm/Support/raw_ostream.h"
32#include <memory>
33
34#if CLANG_ENABLE_OBJC_REWRITER
35
36using namespace clang;
37using llvm::RewriteBuffer;
38using llvm::utostr;
39
40namespace {
41 class RewriteModernObjC : public ASTConsumer {
42 protected:
43
44 enum {
45 BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
46 block, ... */
47 BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
48 BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
49 __block variable */
50 BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
51 helpers */
52 BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
53 support routines */
55 };
56
57 enum {
58 BLOCK_NEEDS_FREE = (1 << 24),
59 BLOCK_HAS_COPY_DISPOSE = (1 << 25),
60 BLOCK_HAS_CXX_OBJ = (1 << 26),
61 BLOCK_IS_GC = (1 << 27),
62 BLOCK_IS_GLOBAL = (1 << 28),
63 BLOCK_HAS_DESCRIPTOR = (1 << 29)
64 };
65
66 Rewriter Rewrite;
67 DiagnosticsEngine &Diags;
68 const LangOptions &LangOpts;
69 ASTContext *Context;
70 SourceManager *SM;
71 TranslationUnitDecl *TUDecl;
72 FileID MainFileID;
73 const char *MainFileStart, *MainFileEnd;
74 Stmt *CurrentBody;
75 ParentMap *PropParentMap; // created lazily.
76 std::string InFileName;
77 std::unique_ptr<raw_ostream> OutFile;
78 std::string Preamble;
79
80 TypeDecl *ProtocolTypeDecl;
81 VarDecl *GlobalVarDecl;
82 Expr *GlobalConstructionExp;
83 unsigned RewriteFailedDiag;
84 unsigned GlobalBlockRewriteFailedDiag;
85 // ObjC string constant support.
86 unsigned NumObjCStringLiterals;
87 VarDecl *ConstantStringClassReference;
88 RecordDecl *NSStringRecord;
89
90 // ObjC foreach break/continue generation support.
91 int BcLabelCount;
92
93 unsigned TryFinallyContainsReturnDiag;
94 // Needed for super.
95 ObjCMethodDecl *CurMethodDef;
96 RecordDecl *SuperStructDecl;
97 RecordDecl *ConstantStringDecl;
98
99 FunctionDecl *MsgSendFunctionDecl;
100 FunctionDecl *MsgSendSuperFunctionDecl;
101 FunctionDecl *MsgSendStretFunctionDecl;
102 FunctionDecl *MsgSendSuperStretFunctionDecl;
103 FunctionDecl *MsgSendFpretFunctionDecl;
104 FunctionDecl *GetClassFunctionDecl;
105 FunctionDecl *GetMetaClassFunctionDecl;
106 FunctionDecl *GetSuperClassFunctionDecl;
107 FunctionDecl *SelGetUidFunctionDecl;
108 FunctionDecl *CFStringFunctionDecl;
109 FunctionDecl *SuperConstructorFunctionDecl;
110 FunctionDecl *CurFunctionDef;
111
112 /* Misc. containers needed for meta-data rewrite. */
113 SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
114 SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
115 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
116 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
117 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;
118 llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;
119 SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;
120 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
121 SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;
122
123 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
124 SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories;
125
126 SmallVector<Stmt *, 32> Stmts;
127 SmallVector<int, 8> ObjCBcLabelNo;
128 // Remember all the @protocol(<expr>) expressions.
129 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
130
131 llvm::DenseSet<uint64_t> CopyDestroyCache;
132
133 // Block expressions.
134 SmallVector<BlockExpr *, 32> Blocks;
135 SmallVector<int, 32> InnerDeclRefsCount;
136 SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
137
138 SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
139
140 // Block related declarations.
141 llvm::SmallSetVector<ValueDecl *, 8> BlockByCopyDecls;
142 llvm::SmallSetVector<ValueDecl *, 8> BlockByRefDecls;
143 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
144 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
145 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
146
147 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
148 llvm::DenseMap<ObjCInterfaceDecl *,
149 llvm::SmallSetVector<ObjCIvarDecl *, 8> > ReferencedIvars;
150
151 // ivar bitfield grouping containers
152 llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups;
153 llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber;
154 // This container maps an <class, group number for ivar> tuple to the type
155 // of the struct where the bitfield belongs.
156 llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType;
157 SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen;
158
159 // This maps an original source AST to it's rewritten form. This allows
160 // us to avoid rewriting the same node twice (which is very uncommon).
161 // This is needed to support some of the exotic property rewriting.
162 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
163
164 // Needed for header files being rewritten
165 bool IsHeader;
166 bool SilenceRewriteMacroWarning;
167 bool GenerateLineInfo;
168 bool objc_impl_method;
169
170 bool DisableReplaceStmt;
171 class DisableReplaceStmtScope {
172 RewriteModernObjC &R;
173 bool SavedValue;
174
175 public:
176 DisableReplaceStmtScope(RewriteModernObjC &R)
177 : R(R), SavedValue(R.DisableReplaceStmt) {
178 R.DisableReplaceStmt = true;
179 }
180 ~DisableReplaceStmtScope() {
181 R.DisableReplaceStmt = SavedValue;
182 }
183 };
184 void InitializeCommon(ASTContext &context);
185
186 public:
187 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
188
189 // Top Level Driver code.
190 bool HandleTopLevelDecl(DeclGroupRef D) override {
191 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
192 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
193 if (!Class->isThisDeclarationADefinition()) {
194 RewriteForwardClassDecl(D);
195 break;
196 } else {
197 // Keep track of all interface declarations seen.
198 ObjCInterfacesSeen.push_back(Class);
199 break;
200 }
201 }
202
203 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
204 if (!Proto->isThisDeclarationADefinition()) {
205 RewriteForwardProtocolDecl(D);
206 break;
207 }
208 }
209
210 if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I)) {
211 // Under modern abi, we cannot translate body of the function
212 // yet until all class extensions and its implementation is seen.
213 // This is because they may introduce new bitfields which must go
214 // into their grouping struct.
215 if (FDecl->isThisDeclarationADefinition() &&
216 // Not c functions defined inside an objc container.
217 !FDecl->isTopLevelDeclInObjCContainer()) {
218 FunctionDefinitionsSeen.push_back(FDecl);
219 break;
220 }
221 }
222 HandleTopLevelSingleDecl(*I);
223 }
224 return true;
225 }
226
227 void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {
228 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
229 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(*I)) {
230 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
231 RewriteBlockPointerDecl(TD);
232 else if (TD->getUnderlyingType()->isFunctionPointerType())
233 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
234 else
235 RewriteObjCQualifiedInterfaceTypes(TD);
236 }
237 }
238 }
239
240 void HandleTopLevelSingleDecl(Decl *D);
241 void HandleDeclInMainFile(Decl *D);
242 RewriteModernObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
243 DiagnosticsEngine &D, const LangOptions &LOpts,
244 bool silenceMacroWarn, bool LineInfo);
245
246 ~RewriteModernObjC() override {}
247
248 void HandleTranslationUnit(ASTContext &C) override;
249
250 void ReplaceStmt(Stmt *Old, Stmt *New) {
251 ReplaceStmtWithRange(Old, New, Old->getSourceRange());
252 }
253
254 void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
255 assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");
256
257 Stmt *ReplacingStmt = ReplacedNodes[Old];
258 if (ReplacingStmt)
259 return; // We can't rewrite the same node twice.
260
261 if (DisableReplaceStmt)
262 return;
263
264 // Measure the old text.
265 int Size = Rewrite.getRangeSize(SrcRange);
266 if (Size == -1) {
267 Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
268 << Old->getSourceRange();
269 return;
270 }
271 // Get the new text.
272 std::string SStr;
273 llvm::raw_string_ostream S(SStr);
274 New->printPretty(S, nullptr, PrintingPolicy(LangOpts));
275
276 // If replacement succeeded or warning disabled return with no warning.
277 if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, SStr)) {
278 ReplacedNodes[Old] = New;
279 return;
280 }
281 if (SilenceRewriteMacroWarning)
282 return;
283 Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
284 << Old->getSourceRange();
285 }
286
287 void InsertText(SourceLocation Loc, StringRef Str,
288 bool InsertAfter = true) {
289 // If insertion succeeded or warning disabled return with no warning.
290 if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
291 SilenceRewriteMacroWarning)
292 return;
293
294 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
295 }
296
297 void ReplaceText(SourceLocation Start, unsigned OrigLength,
298 StringRef Str) {
299 // If removal succeeded or warning disabled return with no warning.
300 if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
301 SilenceRewriteMacroWarning)
302 return;
303
304 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
305 }
306
307 // Syntactic Rewriting.
308 void RewriteRecordBody(RecordDecl *RD);
309 void RewriteInclude();
310 void RewriteLineDirective(const Decl *D);
311 void ConvertSourceLocationToLineDirective(SourceLocation Loc,
312 std::string &LineString);
313 void RewriteForwardClassDecl(DeclGroupRef D);
314 void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);
315 void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
316 const std::string &typedefString);
317 void RewriteImplementations();
318 void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
319 ObjCImplementationDecl *IMD,
320 ObjCCategoryImplDecl *CID);
321 void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
322 void RewriteImplementationDecl(Decl *Dcl);
323 void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
324 ObjCMethodDecl *MDecl, std::string &ResultStr);
325 void RewriteTypeIntoString(QualType T, std::string &ResultStr,
326 const FunctionType *&FPRetType);
327 void RewriteByRefString(std::string &ResultStr, const std::string &Name,
328 ValueDecl *VD, bool def=false);
329 void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
330 void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
331 void RewriteForwardProtocolDecl(DeclGroupRef D);
332 void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);
333 void RewriteMethodDeclaration(ObjCMethodDecl *Method);
334 void RewriteProperty(ObjCPropertyDecl *prop);
335 void RewriteFunctionDecl(FunctionDecl *FD);
336 void RewriteBlockPointerType(std::string& Str, QualType Type);
337 void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
338 void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
339 void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
340 void RewriteTypeOfDecl(VarDecl *VD);
341 void RewriteObjCQualifiedInterfaceTypes(Expr *E);
342
343 std::string getIvarAccessString(ObjCIvarDecl *D);
344
345 // Expression Rewriting.
346 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
347 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
348 Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
349 Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
350 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
351 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
352 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
353 Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);
354 Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);
355 Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);
356 Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);
357 Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
358 Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
359 Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
360 Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
361 Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
362 Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
363 SourceLocation OrigEnd);
364 Stmt *RewriteBreakStmt(BreakStmt *S);
365 Stmt *RewriteContinueStmt(ContinueStmt *S);
366 void RewriteCastExpr(CStyleCastExpr *CE);
367 void RewriteImplicitCastObjCExpr(CastExpr *IE);
368
369 // Computes ivar bitfield group no.
370 unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV);
371 // Names field decl. for ivar bitfield group.
372 void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result);
373 // Names struct type for ivar bitfield group.
374 void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result);
375 // Names symbol for ivar bitfield group field offset.
376 void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result);
377 // Given an ivar bitfield, it builds (or finds) its group record type.
378 QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV);
379 QualType SynthesizeBitfieldGroupStructType(
380 ObjCIvarDecl *IV,
381 SmallVectorImpl<ObjCIvarDecl *> &IVars);
382
383 // Block rewriting.
384 void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
385
386 // Block specific rewrite rules.
387 void RewriteBlockPointerDecl(NamedDecl *VD);
388 void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);
389 Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
390 Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
391 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
392
393 void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
394 std::string &Result);
395
396 void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);
397 bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,
398 bool &IsNamedDefinition);
399 void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
400 std::string &Result);
401
402 bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);
403
404 void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
405 std::string &Result);
406
407 void Initialize(ASTContext &context) override;
408
409 // Misc. AST transformation routines. Sometimes they end up calling
410 // rewriting routines on the new ASTs.
411 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
412 ArrayRef<Expr *> Args,
413 SourceLocation StartLoc=SourceLocation(),
414 SourceLocation EndLoc=SourceLocation());
415
416 Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
417 QualType returnType,
418 SmallVectorImpl<QualType> &ArgTypes,
419 SmallVectorImpl<Expr*> &MsgExprs,
420 ObjCMethodDecl *Method);
421
422 Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
423 SourceLocation StartLoc=SourceLocation(),
424 SourceLocation EndLoc=SourceLocation());
425
426 void SynthCountByEnumWithState(std::string &buf);
427 void SynthMsgSendFunctionDecl();
428 void SynthMsgSendSuperFunctionDecl();
429 void SynthMsgSendStretFunctionDecl();
430 void SynthMsgSendFpretFunctionDecl();
431 void SynthMsgSendSuperStretFunctionDecl();
432 void SynthGetClassFunctionDecl();
433 void SynthGetMetaClassFunctionDecl();
434 void SynthGetSuperClassFunctionDecl();
435 void SynthSelGetUidFunctionDecl();
436 void SynthSuperConstructorFunctionDecl();
437
438 // Rewriting metadata
439 template<typename MethodIterator>
440 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
441 MethodIterator MethodEnd,
442 bool IsInstanceMethod,
443 StringRef prefix,
444 StringRef ClassName,
445 std::string &Result);
446 void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
447 std::string &Result);
448 void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
449 std::string &Result);
450 void RewriteClassSetupInitHook(std::string &Result);
451
452 void RewriteMetaDataIntoBuffer(std::string &Result);
453 void WriteImageInfo(std::string &Result);
454 void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
455 std::string &Result);
456 void RewriteCategorySetupInitHook(std::string &Result);
457
458 // Rewriting ivar
459 void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
460 std::string &Result);
461 Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
462
463
464 std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
465 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
466 StringRef funcName,
467 const std::string &Tag);
468 std::string SynthesizeBlockFunc(BlockExpr *CE, int i, StringRef funcName,
469 const std::string &Tag);
470 std::string SynthesizeBlockImpl(BlockExpr *CE, const std::string &Tag,
471 const std::string &Desc);
472 std::string SynthesizeBlockDescriptor(const std::string &DescTag,
473 const std::string &ImplTag, int i,
474 StringRef funcName, unsigned hasCopy);
475 Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
476 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
477 StringRef FunName);
478 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
479 Stmt *SynthBlockInitExpr(BlockExpr *Exp,
480 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);
481
482 // Misc. helper routines.
483 QualType getProtocolType();
484 void WarnAboutReturnGotoStmts(Stmt *S);
485 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
486 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
487 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
488
489 bool IsDeclStmtInForeachHeader(DeclStmt *DS);
490 void CollectBlockDeclRefInfo(BlockExpr *Exp);
491 void GetBlockDeclRefExprs(Stmt *S);
492 void GetInnerBlockDeclRefExprs(Stmt *S,
493 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
494 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
495
496 // We avoid calling Type::isBlockPointerType(), since it operates on the
497 // canonical type. We only care if the top-level type is a closure pointer.
498 bool isTopLevelBlockPointerType(QualType T) {
499 return isa<BlockPointerType>(T);
500 }
501
502 /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
503 /// to a function pointer type and upon success, returns true; false
504 /// otherwise.
505 bool convertBlockPointerToFunctionPointer(QualType &T) {
506 if (isTopLevelBlockPointerType(T)) {
507 const auto *BPT = T->castAs<BlockPointerType>();
508 T = Context->getPointerType(BPT->getPointeeType());
509 return true;
510 }
511 return false;
512 }
513
514 bool convertObjCTypeToCStyleType(QualType &T);
515
516 bool needToScanForQualifiers(QualType T);
517 QualType getSuperStructType();
518 QualType getConstantStringStructType();
519 QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
520
521 void convertToUnqualifiedObjCType(QualType &T) {
522 if (T->isObjCQualifiedIdType()) {
523 bool isConst = T.isConstQualified();
524 T = isConst ? Context->getObjCIdType().withConst()
525 : Context->getObjCIdType();
526 }
527 else if (T->isObjCQualifiedClassType())
528 T = Context->getObjCClassType();
529 else if (T->isObjCObjectPointerType() &&
531 if (const ObjCObjectPointerType * OBJPT =
533 const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
534 T = QualType(IFaceT, 0);
535 T = Context->getPointerType(T);
536 }
537 }
538 }
539
540 // FIXME: This predicate seems like it would be useful to add to ASTContext.
541 bool isObjCType(QualType T) {
542 if (!LangOpts.ObjC)
543 return false;
544
545 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
546
547 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
548 OCT == Context->getCanonicalType(Context->getObjCClassType()))
549 return true;
550
551 if (const PointerType *PT = OCT->getAs<PointerType>()) {
552 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
553 PT->getPointeeType()->isObjCQualifiedIdType())
554 return true;
555 }
556 return false;
557 }
558
559 bool PointerTypeTakesAnyBlockArguments(QualType QT);
560 bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
561 void GetExtentOfArgList(const char *Name, const char *&LParen,
562 const char *&RParen);
563
564 void QuoteDoublequotes(std::string &From, std::string &To) {
565 for (unsigned i = 0; i < From.length(); i++) {
566 if (From[i] == '"')
567 To += "\\\"";
568 else
569 To += From[i];
570 }
571 }
572
573 QualType getSimpleFunctionType(QualType result,
574 ArrayRef<QualType> args,
575 bool variadic = false) {
576 if (result == Context->getObjCInstanceType())
577 result = Context->getObjCIdType();
578 FunctionProtoType::ExtProtoInfo fpi;
579 fpi.Variadic = variadic;
580 return Context->getFunctionType(result, args, fpi);
581 }
582
583 // Helper function: create a CStyleCastExpr with trivial type source info.
584 CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
585 CastKind Kind, Expr *E) {
586 TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
587 return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,
588 FPOptionsOverride(), TInfo,
589 SourceLocation(), SourceLocation());
590 }
591
592 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
593 const IdentifierInfo *II = &Context->Idents.get("load");
594 Selector LoadSel = Context->Selectors.getSelector(0, &II);
595 return OD->getClassMethod(LoadSel) != nullptr;
596 }
597
598 StringLiteral *getStringLiteral(StringRef Str) {
599 QualType StrType = Context->getConstantArrayType(
600 Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,
601 ArraySizeModifier::Normal, 0);
602 return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,
603 /*Pascal=*/false, StrType, SourceLocation());
604 }
605 };
606} // end anonymous namespace
607
608void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
609 NamedDecl *D) {
610 if (const FunctionProtoType *fproto
611 = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
612 for (const auto &I : fproto->param_types())
613 if (isTopLevelBlockPointerType(I)) {
614 // All the args are checked/rewritten. Don't call twice!
615 RewriteBlockPointerDecl(D);
616 break;
617 }
618 }
619}
620
621void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
622 const PointerType *PT = funcType->getAs<PointerType>();
623 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
624 RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
625}
626
627static bool IsHeaderFile(const std::string &Filename) {
628 std::string::size_type DotPos = Filename.rfind('.');
629
630 if (DotPos == std::string::npos) {
631 // no file extension
632 return false;
633 }
634
635 std::string Ext = Filename.substr(DotPos + 1);
636 // C header: .h
637 // C++ header: .hh or .H;
638 return Ext == "h" || Ext == "hh" || Ext == "H";
639}
640
641RewriteModernObjC::RewriteModernObjC(std::string inFile,
642 std::unique_ptr<raw_ostream> OS,
644 const LangOptions &LOpts,
645 bool silenceMacroWarn, bool LineInfo)
646 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
647 SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) {
648 IsHeader = IsHeaderFile(inFile);
649 RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
650 "rewriting sub-expression within a macro (may not be correct)");
651 // FIXME. This should be an error. But if block is not called, it is OK. And it
652 // may break including some headers.
653 GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
654 "rewriting block literal declared in global scope is not implemented");
655
656 TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
658 "rewriter doesn't support user-specified control flow semantics "
659 "for @try/@finally (code may not execute properly)");
660}
661
662std::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter(
663 const std::string &InFile, std::unique_ptr<raw_ostream> OS,
664 DiagnosticsEngine &Diags, const LangOptions &LOpts,
665 bool SilenceRewriteMacroWarning, bool LineInfo) {
666 return std::make_unique<RewriteModernObjC>(InFile, std::move(OS), Diags,
667 LOpts, SilenceRewriteMacroWarning,
668 LineInfo);
669}
670
671void RewriteModernObjC::InitializeCommon(ASTContext &context) {
672 Context = &context;
673 SM = &Context->getSourceManager();
674 TUDecl = Context->getTranslationUnitDecl();
675 MsgSendFunctionDecl = nullptr;
676 MsgSendSuperFunctionDecl = nullptr;
677 MsgSendStretFunctionDecl = nullptr;
678 MsgSendSuperStretFunctionDecl = nullptr;
679 MsgSendFpretFunctionDecl = nullptr;
680 GetClassFunctionDecl = nullptr;
681 GetMetaClassFunctionDecl = nullptr;
682 GetSuperClassFunctionDecl = nullptr;
683 SelGetUidFunctionDecl = nullptr;
684 CFStringFunctionDecl = nullptr;
685 ConstantStringClassReference = nullptr;
686 NSStringRecord = nullptr;
687 CurMethodDef = nullptr;
688 CurFunctionDef = nullptr;
689 GlobalVarDecl = nullptr;
690 GlobalConstructionExp = nullptr;
691 SuperStructDecl = nullptr;
692 ProtocolTypeDecl = nullptr;
693 ConstantStringDecl = nullptr;
694 BcLabelCount = 0;
695 SuperConstructorFunctionDecl = nullptr;
696 NumObjCStringLiterals = 0;
697 PropParentMap = nullptr;
698 CurrentBody = nullptr;
699 DisableReplaceStmt = false;
700 objc_impl_method = false;
701
702 // Get the ID and start/end of the main file.
703 MainFileID = SM->getMainFileID();
704 llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);
705 MainFileStart = MainBuf.getBufferStart();
706 MainFileEnd = MainBuf.getBufferEnd();
707
708 Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
709}
710
711//===----------------------------------------------------------------------===//
712// Top Level Driver Code
713//===----------------------------------------------------------------------===//
714
715void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
716 if (Diags.hasErrorOccurred())
717 return;
718
719 // Two cases: either the decl could be in the main file, or it could be in a
720 // #included file. If the former, rewrite it now. If the later, check to see
721 // if we rewrote the #include/#import.
722 SourceLocation Loc = D->getLocation();
723 Loc = SM->getExpansionLoc(Loc);
724
725 // If this is for a builtin, ignore it.
726 if (Loc.isInvalid()) return;
727
728 // Look for built-in declarations that we need to refer during the rewrite.
729 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
730 RewriteFunctionDecl(FD);
731 } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
732 // declared in <Foundation/NSString.h>
733 if (FVD->getName() == "_NSConstantStringClassReference") {
734 ConstantStringClassReference = FVD;
735 return;
736 }
737 } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
738 RewriteCategoryDecl(CD);
739 } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
740 if (PD->isThisDeclarationADefinition())
741 RewriteProtocolDecl(PD);
742 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
743 // Recurse into linkage specifications
744 for (DeclContext::decl_iterator DI = LSD->decls_begin(),
745 DIEnd = LSD->decls_end();
746 DI != DIEnd; ) {
747 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
748 if (!IFace->isThisDeclarationADefinition()) {
750 SourceLocation StartLoc = IFace->getBeginLoc();
751 do {
752 if (isa<ObjCInterfaceDecl>(*DI) &&
753 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
754 StartLoc == (*DI)->getBeginLoc())
755 DG.push_back(*DI);
756 else
757 break;
758
759 ++DI;
760 } while (DI != DIEnd);
761 RewriteForwardClassDecl(DG);
762 continue;
763 }
764 else {
765 // Keep track of all interface declarations seen.
766 ObjCInterfacesSeen.push_back(IFace);
767 ++DI;
768 continue;
769 }
770 }
771
772 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
773 if (!Proto->isThisDeclarationADefinition()) {
775 SourceLocation StartLoc = Proto->getBeginLoc();
776 do {
777 if (isa<ObjCProtocolDecl>(*DI) &&
778 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
779 StartLoc == (*DI)->getBeginLoc())
780 DG.push_back(*DI);
781 else
782 break;
783
784 ++DI;
785 } while (DI != DIEnd);
786 RewriteForwardProtocolDecl(DG);
787 continue;
788 }
789 }
790
791 HandleTopLevelSingleDecl(*DI);
792 ++DI;
793 }
794 }
795 // If we have a decl in the main file, see if we should rewrite it.
796 if (SM->isWrittenInMainFile(Loc))
797 return HandleDeclInMainFile(D);
798}
799
800//===----------------------------------------------------------------------===//
801// Syntactic (non-AST) Rewriting Code
802//===----------------------------------------------------------------------===//
803
804void RewriteModernObjC::RewriteInclude() {
805 SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
806 StringRef MainBuf = SM->getBufferData(MainFileID);
807 const char *MainBufStart = MainBuf.begin();
808 const char *MainBufEnd = MainBuf.end();
809 size_t ImportLen = strlen("import");
810
811 // Loop over the whole file, looking for includes.
812 for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
813 if (*BufPtr == '#') {
814 if (++BufPtr == MainBufEnd)
815 return;
816 while (*BufPtr == ' ' || *BufPtr == '\t')
817 if (++BufPtr == MainBufEnd)
818 return;
819 if (!strncmp(BufPtr, "import", ImportLen)) {
820 // replace import with include
821 SourceLocation ImportLoc =
822 LocStart.getLocWithOffset(BufPtr-MainBufStart);
823 ReplaceText(ImportLoc, ImportLen, "include");
824 BufPtr += ImportLen;
825 }
826 }
827 }
828}
829
830static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,
831 ObjCIvarDecl *IvarDecl, std::string &Result) {
832 Result += "OBJC_IVAR_$_";
833 Result += IDecl->getName();
834 Result += "$";
835 Result += IvarDecl->getName();
836}
837
838std::string
839RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
840 const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();
841
842 // Build name of symbol holding ivar offset.
843 std::string IvarOffsetName;
844 if (D->isBitField())
845 ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
846 else
847 WriteInternalIvarName(ClassDecl, D, IvarOffsetName);
848
849 std::string S = "(*(";
850 QualType IvarT = D->getType();
851 if (D->isBitField())
852 IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
853
854 if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {
855 RecordDecl *RD = IvarT->castAsCanonical<RecordType>()->getDecl();
856 RD = RD->getDefinition();
857 if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
858 // decltype(((Foo_IMPL*)0)->bar) *
859 auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());
860 // ivar in class extensions requires special treatment.
861 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
862 CDecl = CatDecl->getClassInterface();
863 std::string RecName = std::string(CDecl->getName());
864 RecName += "_IMPL";
865 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
866 SourceLocation(), SourceLocation(),
867 &Context->Idents.get(RecName));
868 QualType PtrStructIMPL =
869 Context->getPointerType(Context->getCanonicalTagType(RD));
870 unsigned UnsignedIntSize =
871 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
872 Expr *Zero = IntegerLiteral::Create(*Context,
873 llvm::APInt(UnsignedIntSize, 0),
874 Context->UnsignedIntTy, SourceLocation());
875 Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
876 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
877 Zero);
878 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
879 SourceLocation(),
880 &Context->Idents.get(D->getNameAsString()),
881 IvarT, nullptr,
882 /*BitWidth=*/nullptr, /*Mutable=*/true,
885 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
886 IvarT = Context->getDecltypeType(ME, ME->getType());
887 }
888 }
889 convertObjCTypeToCStyleType(IvarT);
890 QualType castT = Context->getPointerType(IvarT);
891 std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));
892 S += TypeString;
893 S += ")";
894
895 // ((char *)self + IVAR_OFFSET_SYMBOL_NAME)
896 S += "((char *)self + ";
897 S += IvarOffsetName;
898 S += "))";
899 if (D->isBitField()) {
900 S += ".";
901 S += D->getNameAsString();
902 }
903 ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D);
904 return S;
905}
906
907/// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not
908/// been found in the class implementation. In this case, it must be synthesized.
909static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,
911 bool getter) {
912 auto *OMD = IMP->getInstanceMethod(getter ? PD->getGetterName()
913 : PD->getSetterName());
914 return !OMD || OMD->isSynthesizedAccessorStub();
915}
916
917void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
920 static bool objcGetPropertyDefined = false;
921 static bool objcSetPropertyDefined = false;
922 SourceLocation startGetterSetterLoc;
923
924 if (PID->getBeginLoc().isValid()) {
925 SourceLocation startLoc = PID->getBeginLoc();
926 InsertText(startLoc, "// ");
927 const char *startBuf = SM->getCharacterData(startLoc);
928 assert((*startBuf == '@') && "bogus @synthesize location");
929 const char *semiBuf = strchr(startBuf, ';');
930 assert((*semiBuf == ';') && "@synthesize: can't find ';'");
931 startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
932 } else
933 startGetterSetterLoc = IMD ? IMD->getEndLoc() : CID->getEndLoc();
934
936 return; // FIXME: is this correct?
937
938 // Generate the 'getter' function.
940 ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
941 assert(IMD && OID && "Synthesized ivars must be attached to @implementation");
942
943 unsigned Attributes = PD->getPropertyAttributes();
944 if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {
945 bool GenGetProperty =
949 std::string Getr;
950 if (GenGetProperty && !objcGetPropertyDefined) {
951 objcGetPropertyDefined = true;
952 // FIXME. Is this attribute correct in all cases?
953 Getr = "\nextern \"C\" __declspec(dllimport) "
954 "id objc_getProperty(id, SEL, long, bool);\n";
955 }
956 RewriteObjCMethodDecl(OID->getContainingInterface(),
957 PID->getGetterMethodDecl(), Getr);
958 Getr += "{ ";
959 // Synthesize an explicit cast to gain access to the ivar.
960 // See objc-act.c:objc_synthesize_new_getter() for details.
961 if (GenGetProperty) {
962 // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
963 Getr += "typedef ";
964 const FunctionType *FPRetType = nullptr;
965 RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,
966 FPRetType);
967 Getr += " _TYPE";
968 if (FPRetType) {
969 Getr += ")"; // close the precedence "scope" for "*".
970
971 // Now, emit the argument types (if any).
972 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
973 Getr += "(";
974 for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
975 if (i) Getr += ", ";
976 std::string ParamStr =
977 FT->getParamType(i).getAsString(Context->getPrintingPolicy());
978 Getr += ParamStr;
979 }
980 if (FT->isVariadic()) {
981 if (FT->getNumParams())
982 Getr += ", ";
983 Getr += "...";
984 }
985 Getr += ")";
986 } else
987 Getr += "()";
988 }
989 Getr += ";\n";
990 Getr += "return (_TYPE)";
991 Getr += "objc_getProperty(self, _cmd, ";
992 RewriteIvarOffsetComputation(OID, Getr);
993 Getr += ", 1)";
994 }
995 else
996 Getr += "return " + getIvarAccessString(OID);
997 Getr += "; }";
998 InsertText(startGetterSetterLoc, Getr);
999 }
1000
1001 if (PD->isReadOnly() ||
1002 !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/))
1003 return;
1004
1005 // Generate the 'setter' function.
1006 std::string Setr;
1007 bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |
1009 if (GenSetProperty && !objcSetPropertyDefined) {
1010 objcSetPropertyDefined = true;
1011 // FIXME. Is this attribute correct in all cases?
1012 Setr = "\nextern \"C\" __declspec(dllimport) "
1013 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";
1014 }
1015
1016 RewriteObjCMethodDecl(OID->getContainingInterface(),
1017 PID->getSetterMethodDecl(), Setr);
1018 Setr += "{ ";
1019 // Synthesize an explicit cast to initialize the ivar.
1020 // See objc-act.c:objc_synthesize_new_setter() for details.
1021 if (GenSetProperty) {
1022 Setr += "objc_setProperty (self, _cmd, ";
1023 RewriteIvarOffsetComputation(OID, Setr);
1024 Setr += ", (id)";
1025 Setr += PD->getName();
1026 Setr += ", ";
1028 Setr += "0, ";
1029 else
1030 Setr += "1, ";
1031 if (Attributes & ObjCPropertyAttribute::kind_copy)
1032 Setr += "1)";
1033 else
1034 Setr += "0)";
1035 }
1036 else {
1037 Setr += getIvarAccessString(OID) + " = ";
1038 Setr += PD->getName();
1039 }
1040 Setr += "; }\n";
1041 InsertText(startGetterSetterLoc, Setr);
1042}
1043
1044static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
1045 std::string &typedefString) {
1046 typedefString += "\n#ifndef _REWRITER_typedef_";
1047 typedefString += ForwardDecl->getNameAsString();
1048 typedefString += "\n";
1049 typedefString += "#define _REWRITER_typedef_";
1050 typedefString += ForwardDecl->getNameAsString();
1051 typedefString += "\n";
1052 typedefString += "typedef struct objc_object ";
1053 typedefString += ForwardDecl->getNameAsString();
1054 // typedef struct { } _objc_exc_Classname;
1055 typedefString += ";\ntypedef struct {} _objc_exc_";
1056 typedefString += ForwardDecl->getNameAsString();
1057 typedefString += ";\n#endif\n";
1058}
1059
1060void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
1061 const std::string &typedefString) {
1062 SourceLocation startLoc = ClassDecl->getBeginLoc();
1063 const char *startBuf = SM->getCharacterData(startLoc);
1064 const char *semiPtr = strchr(startBuf, ';');
1065 // Replace the @class with typedefs corresponding to the classes.
1066 ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);
1067}
1068
1069void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {
1070 std::string typedefString;
1071 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
1072 if (ObjCInterfaceDecl *ForwardDecl = dyn_cast<ObjCInterfaceDecl>(*I)) {
1073 if (I == D.begin()) {
1074 // Translate to typedef's that forward reference structs with the same name
1075 // as the class. As a convenience, we include the original declaration
1076 // as a comment.
1077 typedefString += "// @class ";
1078 typedefString += ForwardDecl->getNameAsString();
1079 typedefString += ";";
1080 }
1081 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
1082 }
1083 else
1084 HandleTopLevelSingleDecl(*I);
1085 }
1087 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
1088}
1089
1090void RewriteModernObjC::RewriteForwardClassDecl(
1091 const SmallVectorImpl<Decl *> &D) {
1092 std::string typedefString;
1093 for (unsigned i = 0; i < D.size(); i++) {
1094 ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
1095 if (i == 0) {
1096 typedefString += "// @class ";
1097 typedefString += ForwardDecl->getNameAsString();
1098 typedefString += ";";
1099 }
1100 RewriteOneForwardClassDecl(ForwardDecl, typedefString);
1101 }
1102 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
1103}
1104
1105void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
1106 // When method is a synthesized one, such as a getter/setter there is
1107 // nothing to rewrite.
1108 if (Method->isImplicit())
1109 return;
1110 SourceLocation LocStart = Method->getBeginLoc();
1111 SourceLocation LocEnd = Method->getEndLoc();
1112
1113 if (SM->getExpansionLineNumber(LocEnd) >
1114 SM->getExpansionLineNumber(LocStart)) {
1115 InsertText(LocStart, "#if 0\n");
1116 ReplaceText(LocEnd, 1, ";\n#endif\n");
1117 } else {
1118 InsertText(LocStart, "// ");
1119 }
1120}
1121
1122void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {
1123 SourceLocation Loc = prop->getAtLoc();
1124
1125 ReplaceText(Loc, 0, "// ");
1126 // FIXME: handle properties that are declared across multiple lines.
1127}
1128
1129void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
1130 SourceLocation LocStart = CatDecl->getBeginLoc();
1131
1132 // FIXME: handle category headers that are declared across multiple lines.
1133 if (CatDecl->getIvarRBraceLoc().isValid()) {
1134 ReplaceText(LocStart, 1, "/** ");
1135 ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ ");
1136 }
1137 else {
1138 ReplaceText(LocStart, 0, "// ");
1139 }
1140
1141 for (auto *I : CatDecl->instance_properties())
1142 RewriteProperty(I);
1143
1144 for (auto *I : CatDecl->instance_methods())
1145 RewriteMethodDeclaration(I);
1146 for (auto *I : CatDecl->class_methods())
1147 RewriteMethodDeclaration(I);
1148
1149 // Lastly, comment out the @end.
1150 ReplaceText(CatDecl->getAtEndRange().getBegin(),
1151 strlen("@end"), "/* @end */\n");
1152}
1153
1154void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
1155 SourceLocation LocStart = PDecl->getBeginLoc();
1156 assert(PDecl->isThisDeclarationADefinition());
1157
1158 // FIXME: handle protocol headers that are declared across multiple lines.
1159 ReplaceText(LocStart, 0, "// ");
1160
1161 for (auto *I : PDecl->instance_methods())
1162 RewriteMethodDeclaration(I);
1163 for (auto *I : PDecl->class_methods())
1164 RewriteMethodDeclaration(I);
1165 for (auto *I : PDecl->instance_properties())
1166 RewriteProperty(I);
1167
1168 // Lastly, comment out the @end.
1169 SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
1170 ReplaceText(LocEnd, strlen("@end"), "/* @end */\n");
1171
1172 // Must comment out @optional/@required
1173 const char *startBuf = SM->getCharacterData(LocStart);
1174 const char *endBuf = SM->getCharacterData(LocEnd);
1175 for (const char *p = startBuf; p < endBuf; p++) {
1176 if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
1177 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
1178 ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
1179
1180 }
1181 else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
1182 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
1183 ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
1184
1185 }
1186 }
1187}
1188
1189void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
1190 SourceLocation LocStart = (*D.begin())->getBeginLoc();
1191 if (LocStart.isInvalid())
1192 llvm_unreachable("Invalid SourceLocation");
1193 // FIXME: handle forward protocol that are declared across multiple lines.
1194 ReplaceText(LocStart, 0, "// ");
1195}
1196
1197void
1198RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
1199 SourceLocation LocStart = DG[0]->getBeginLoc();
1200 if (LocStart.isInvalid())
1201 llvm_unreachable("Invalid SourceLocation");
1202 // FIXME: handle forward protocol that are declared across multiple lines.
1203 ReplaceText(LocStart, 0, "// ");
1204}
1205
1206void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
1207 const FunctionType *&FPRetType) {
1208 if (T->isObjCQualifiedIdType())
1209 ResultStr += "id";
1210 else if (T->isFunctionPointerType() ||
1211 T->isBlockPointerType()) {
1212 // needs special handling, since pointer-to-functions have special
1213 // syntax (where a decaration models use).
1214 QualType retType = T;
1215 QualType PointeeTy;
1216 if (const PointerType* PT = retType->getAs<PointerType>())
1217 PointeeTy = PT->getPointeeType();
1218 else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
1219 PointeeTy = BPT->getPointeeType();
1220 if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
1221 ResultStr +=
1222 FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());
1223 ResultStr += "(*";
1224 }
1225 } else
1226 ResultStr += T.getAsString(Context->getPrintingPolicy());
1227}
1228
1229void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
1230 ObjCMethodDecl *OMD,
1231 std::string &ResultStr) {
1232 //fprintf(stderr,"In RewriteObjCMethodDecl\n");
1233 const FunctionType *FPRetType = nullptr;
1234 ResultStr += "\nstatic ";
1235 RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);
1236 ResultStr += " ";
1237
1238 // Unique method name
1239 std::string NameStr;
1240
1241 if (OMD->isInstanceMethod())
1242 NameStr += "_I_";
1243 else
1244 NameStr += "_C_";
1245
1246 NameStr += IDecl->getNameAsString();
1247 NameStr += "_";
1248
1249 if (ObjCCategoryImplDecl *CID =
1250 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
1251 NameStr += CID->getNameAsString();
1252 NameStr += "_";
1253 }
1254 // Append selector names, replacing ':' with '_'
1255 {
1256 std::string selString = OMD->getSelector().getAsString();
1257 int len = selString.size();
1258 for (int i = 0; i < len; i++)
1259 if (selString[i] == ':')
1260 selString[i] = '_';
1261 NameStr += selString;
1262 }
1263 // Remember this name for metadata emission
1264 MethodInternalNames[OMD] = NameStr;
1265 ResultStr += NameStr;
1266
1267 // Rewrite arguments
1268 ResultStr += "(";
1269
1270 // invisible arguments
1271 if (OMD->isInstanceMethod()) {
1272 QualType selfTy = Context->getObjCInterfaceType(IDecl);
1273 selfTy = Context->getPointerType(selfTy);
1274 if (!LangOpts.MicrosoftExt) {
1275 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
1276 ResultStr += "struct ";
1277 }
1278 // When rewriting for Microsoft, explicitly omit the structure name.
1279 ResultStr += IDecl->getNameAsString();
1280 ResultStr += " *";
1281 }
1282 else
1283 ResultStr += Context->getObjCClassType().getAsString(
1284 Context->getPrintingPolicy());
1285
1286 ResultStr += " self, ";
1287 ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
1288 ResultStr += " _cmd";
1289
1290 // Method arguments.
1291 for (const auto *PDecl : OMD->parameters()) {
1292 ResultStr += ", ";
1293 if (PDecl->getType()->isObjCQualifiedIdType()) {
1294 ResultStr += "id ";
1295 ResultStr += PDecl->getNameAsString();
1296 } else {
1297 std::string Name = PDecl->getNameAsString();
1298 QualType QT = PDecl->getType();
1299 // Make sure we convert "t (^)(...)" to "t (*)(...)".
1300 (void)convertBlockPointerToFunctionPointer(QT);
1301 QT.getAsStringInternal(Name, Context->getPrintingPolicy());
1302 ResultStr += Name;
1303 }
1304 }
1305 if (OMD->isVariadic())
1306 ResultStr += ", ...";
1307 ResultStr += ") ";
1308
1309 if (FPRetType) {
1310 ResultStr += ")"; // close the precedence "scope" for "*".
1311
1312 // Now, emit the argument types (if any).
1313 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
1314 ResultStr += "(";
1315 for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
1316 if (i) ResultStr += ", ";
1317 std::string ParamStr =
1318 FT->getParamType(i).getAsString(Context->getPrintingPolicy());
1319 ResultStr += ParamStr;
1320 }
1321 if (FT->isVariadic()) {
1322 if (FT->getNumParams())
1323 ResultStr += ", ";
1324 ResultStr += "...";
1325 }
1326 ResultStr += ")";
1327 } else {
1328 ResultStr += "()";
1329 }
1330 }
1331}
1332
1333void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {
1334 ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
1335 ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
1336 assert((IMD || CID) && "Unknown implementation type");
1337
1338 if (IMD) {
1339 if (IMD->getIvarRBraceLoc().isValid()) {
1340 ReplaceText(IMD->getBeginLoc(), 1, "/** ");
1341 ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ ");
1342 }
1343 else {
1344 InsertText(IMD->getBeginLoc(), "// ");
1345 }
1346 }
1347 else
1348 InsertText(CID->getBeginLoc(), "// ");
1349
1350 for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
1351 if (!OMD->getBody())
1352 continue;
1353 std::string ResultStr;
1354 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
1355 SourceLocation LocStart = OMD->getBeginLoc();
1356 SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
1357
1358 const char *startBuf = SM->getCharacterData(LocStart);
1359 const char *endBuf = SM->getCharacterData(LocEnd);
1360 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1361 }
1362
1363 for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
1364 if (!OMD->getBody())
1365 continue;
1366 std::string ResultStr;
1367 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
1368 SourceLocation LocStart = OMD->getBeginLoc();
1369 SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
1370
1371 const char *startBuf = SM->getCharacterData(LocStart);
1372 const char *endBuf = SM->getCharacterData(LocEnd);
1373 ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1374 }
1375 for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())
1376 RewritePropertyImplDecl(I, IMD, CID);
1377
1378 InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");
1379}
1380
1381void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
1382 // Do not synthesize more than once.
1383 if (ObjCSynthesizedStructs.count(ClassDecl))
1384 return;
1385 // Make sure super class's are written before current class is written.
1386 ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass();
1387 while (SuperClass) {
1388 RewriteInterfaceDecl(SuperClass);
1389 SuperClass = SuperClass->getSuperClass();
1390 }
1391 std::string ResultStr;
1392 if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) {
1393 // we haven't seen a forward decl - generate a typedef.
1394 RewriteOneForwardClassDecl(ClassDecl, ResultStr);
1395 RewriteIvarOffsetSymbols(ClassDecl, ResultStr);
1396
1397 RewriteObjCInternalStruct(ClassDecl, ResultStr);
1398 // Mark this typedef as having been written into its c++ equivalent.
1399 ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl());
1400
1401 for (auto *I : ClassDecl->instance_properties())
1402 RewriteProperty(I);
1403 for (auto *I : ClassDecl->instance_methods())
1404 RewriteMethodDeclaration(I);
1405 for (auto *I : ClassDecl->class_methods())
1406 RewriteMethodDeclaration(I);
1407
1408 // Lastly, comment out the @end.
1409 ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
1410 "/* @end */\n");
1411 }
1412}
1413
1414Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {
1415 SourceRange OldRange = PseudoOp->getSourceRange();
1416
1417 // We just magically know some things about the structure of this
1418 // expression.
1419 ObjCMessageExpr *OldMsg =
1421 PseudoOp->getNumSemanticExprs() - 1));
1422
1423 // Because the rewriter doesn't allow us to rewrite rewritten code,
1424 // we need to suppress rewriting the sub-statements.
1425 Expr *Base;
1427 {
1428 DisableReplaceStmtScope S(*this);
1429
1430 // Rebuild the base expression if we have one.
1431 Base = nullptr;
1432 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
1433 Base = OldMsg->getInstanceReceiver();
1434 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1435 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1436 }
1437
1438 unsigned numArgs = OldMsg->getNumArgs();
1439 for (unsigned i = 0; i < numArgs; i++) {
1440 Expr *Arg = OldMsg->getArg(i);
1441 if (isa<OpaqueValueExpr>(Arg))
1442 Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();
1443 Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));
1444 Args.push_back(Arg);
1445 }
1446 }
1447
1448 // TODO: avoid this copy.
1450 OldMsg->getSelectorLocs(SelLocs);
1451
1452 ObjCMessageExpr *NewMsg = nullptr;
1453 switch (OldMsg->getReceiverKind()) {
1455 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1456 OldMsg->getValueKind(),
1457 OldMsg->getLeftLoc(),
1458 OldMsg->getClassReceiverTypeInfo(),
1459 OldMsg->getSelector(),
1460 SelLocs,
1461 OldMsg->getMethodDecl(),
1462 Args,
1463 OldMsg->getRightLoc(),
1464 OldMsg->isImplicit());
1465 break;
1466
1468 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1469 OldMsg->getValueKind(),
1470 OldMsg->getLeftLoc(),
1471 Base,
1472 OldMsg->getSelector(),
1473 SelLocs,
1474 OldMsg->getMethodDecl(),
1475 Args,
1476 OldMsg->getRightLoc(),
1477 OldMsg->isImplicit());
1478 break;
1479
1482 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1483 OldMsg->getValueKind(),
1484 OldMsg->getLeftLoc(),
1485 OldMsg->getSuperLoc(),
1487 OldMsg->getSuperType(),
1488 OldMsg->getSelector(),
1489 SelLocs,
1490 OldMsg->getMethodDecl(),
1491 Args,
1492 OldMsg->getRightLoc(),
1493 OldMsg->isImplicit());
1494 break;
1495 }
1496
1497 Stmt *Replacement = SynthMessageExpr(NewMsg);
1498 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1499 return Replacement;
1500}
1501
1502Stmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {
1503 SourceRange OldRange = PseudoOp->getSourceRange();
1504
1505 // We just magically know some things about the structure of this
1506 // expression.
1507 ObjCMessageExpr *OldMsg =
1509
1510 // Because the rewriter doesn't allow us to rewrite rewritten code,
1511 // we need to suppress rewriting the sub-statements.
1512 Expr *Base = nullptr;
1514 {
1515 DisableReplaceStmtScope S(*this);
1516 // Rebuild the base expression if we have one.
1517 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
1518 Base = OldMsg->getInstanceReceiver();
1519 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1520 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1521 }
1522 unsigned numArgs = OldMsg->getNumArgs();
1523 for (unsigned i = 0; i < numArgs; i++) {
1524 Expr *Arg = OldMsg->getArg(i);
1525 if (isa<OpaqueValueExpr>(Arg))
1526 Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();
1527 Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));
1528 Args.push_back(Arg);
1529 }
1530 }
1531
1532 // Intentionally empty.
1534
1535 ObjCMessageExpr *NewMsg = nullptr;
1536 switch (OldMsg->getReceiverKind()) {
1538 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1539 OldMsg->getValueKind(),
1540 OldMsg->getLeftLoc(),
1541 OldMsg->getClassReceiverTypeInfo(),
1542 OldMsg->getSelector(),
1543 SelLocs,
1544 OldMsg->getMethodDecl(),
1545 Args,
1546 OldMsg->getRightLoc(),
1547 OldMsg->isImplicit());
1548 break;
1549
1551 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1552 OldMsg->getValueKind(),
1553 OldMsg->getLeftLoc(),
1554 Base,
1555 OldMsg->getSelector(),
1556 SelLocs,
1557 OldMsg->getMethodDecl(),
1558 Args,
1559 OldMsg->getRightLoc(),
1560 OldMsg->isImplicit());
1561 break;
1562
1565 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1566 OldMsg->getValueKind(),
1567 OldMsg->getLeftLoc(),
1568 OldMsg->getSuperLoc(),
1570 OldMsg->getSuperType(),
1571 OldMsg->getSelector(),
1572 SelLocs,
1573 OldMsg->getMethodDecl(),
1574 Args,
1575 OldMsg->getRightLoc(),
1576 OldMsg->isImplicit());
1577 break;
1578 }
1579
1580 Stmt *Replacement = SynthMessageExpr(NewMsg);
1581 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1582 return Replacement;
1583}
1584
1585/// SynthCountByEnumWithState - To print:
1586/// ((NSUInteger (*)
1587/// (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))
1588/// (void *)objc_msgSend)((id)l_collection,
1589/// sel_registerName(
1590/// "countByEnumeratingWithState:objects:count:"),
1591/// &enumState,
1592/// (id *)__rw_items, (NSUInteger)16)
1593///
1594void RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) {
1595 buf += "((_WIN_NSUInteger (*) (id, SEL, struct __objcFastEnumerationState *, "
1596 "id *, _WIN_NSUInteger))(void *)objc_msgSend)";
1597 buf += "\n\t\t";
1598 buf += "((id)l_collection,\n\t\t";
1599 buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1600 buf += "\n\t\t";
1601 buf += "&enumState, "
1602 "(id *)__rw_items, (_WIN_NSUInteger)16)";
1603}
1604
1605/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
1606/// statement to exit to its outer synthesized loop.
1607///
1608Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) {
1609 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1610 return S;
1611 // replace break with goto __break_label
1612 std::string buf;
1613
1614 SourceLocation startLoc = S->getBeginLoc();
1615 buf = "goto __break_label_";
1616 buf += utostr(ObjCBcLabelNo.back());
1617 ReplaceText(startLoc, strlen("break"), buf);
1618
1619 return nullptr;
1620}
1621
1622void RewriteModernObjC::ConvertSourceLocationToLineDirective(
1623 SourceLocation Loc,
1624 std::string &LineString) {
1625 if (Loc.isFileID() && GenerateLineInfo) {
1626 LineString += "\n#line ";
1627 PresumedLoc PLoc = SM->getPresumedLoc(Loc);
1628 LineString += utostr(PLoc.getLine());
1629 LineString += " \"";
1630 LineString += Lexer::Stringify(PLoc.getFilename());
1631 LineString += "\"\n";
1632 }
1633}
1634
1635/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
1636/// statement to continue with its inner synthesized loop.
1637///
1638Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) {
1639 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1640 return S;
1641 // replace continue with goto __continue_label
1642 std::string buf;
1643
1644 SourceLocation startLoc = S->getBeginLoc();
1645 buf = "goto __continue_label_";
1646 buf += utostr(ObjCBcLabelNo.back());
1647 ReplaceText(startLoc, strlen("continue"), buf);
1648
1649 return nullptr;
1650}
1651
1652/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
1653/// It rewrites:
1654/// for ( type elem in collection) { stmts; }
1655
1656/// Into:
1657/// {
1658/// type elem;
1659/// struct __objcFastEnumerationState enumState = { 0 };
1660/// id __rw_items[16];
1661/// id l_collection = (id)collection;
1662/// NSUInteger limit = [l_collection countByEnumeratingWithState:&enumState
1663/// objects:__rw_items count:16];
1664/// if (limit) {
1665/// unsigned long startMutations = *enumState.mutationsPtr;
1666/// do {
1667/// unsigned long counter = 0;
1668/// do {
1669/// if (startMutations != *enumState.mutationsPtr)
1670/// objc_enumerationMutation(l_collection);
1671/// elem = (type)enumState.itemsPtr[counter++];
1672/// stmts;
1673/// __continue_label: ;
1674/// } while (counter < limit);
1675/// } while ((limit = [l_collection countByEnumeratingWithState:&enumState
1676/// objects:__rw_items count:16]));
1677/// elem = nil;
1678/// __break_label: ;
1679/// }
1680/// else
1681/// elem = nil;
1682/// }
1683///
1684Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
1685 SourceLocation OrigEnd) {
1686 assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
1687 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1688 "ObjCForCollectionStmt Statement stack mismatch");
1689 assert(!ObjCBcLabelNo.empty() &&
1690 "ObjCForCollectionStmt - Label No stack empty");
1691
1692 SourceLocation startLoc = S->getBeginLoc();
1693 const char *startBuf = SM->getCharacterData(startLoc);
1694 StringRef elementName;
1695 std::string elementTypeAsString;
1696 std::string buf;
1697 // line directive first.
1698 SourceLocation ForEachLoc = S->getForLoc();
1699 ConvertSourceLocationToLineDirective(ForEachLoc, buf);
1700 buf += "{\n\t";
1701 if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
1702 // type elem;
1703 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1704 QualType ElementType = cast<ValueDecl>(D)->getType();
1705 if (ElementType->isObjCQualifiedIdType() ||
1706 ElementType->isObjCQualifiedInterfaceType())
1707 // Simply use 'id' for all qualified types.
1708 elementTypeAsString = "id";
1709 else
1710 elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());
1711 buf += elementTypeAsString;
1712 buf += " ";
1713 elementName = D->getName();
1714 buf += elementName;
1715 buf += ";\n\t";
1716 }
1717 else {
1719 elementName = DR->getDecl()->getName();
1720 ValueDecl *VD = DR->getDecl();
1721 if (VD->getType()->isObjCQualifiedIdType() ||
1723 // Simply use 'id' for all qualified types.
1724 elementTypeAsString = "id";
1725 else
1726 elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());
1727 }
1728
1729 // struct __objcFastEnumerationState enumState = { 0 };
1730 buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
1731 // id __rw_items[16];
1732 buf += "id __rw_items[16];\n\t";
1733 // id l_collection = (id)
1734 buf += "id l_collection = (id)";
1735 // Find start location of 'collection' the hard way!
1736 const char *startCollectionBuf = startBuf;
1737 startCollectionBuf += 3; // skip 'for'
1738 startCollectionBuf = strchr(startCollectionBuf, '(');
1739 startCollectionBuf++; // skip '('
1740 // find 'in' and skip it.
1741 while (*startCollectionBuf != ' ' ||
1742 *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
1743 (*(startCollectionBuf+3) != ' ' &&
1744 *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
1745 startCollectionBuf++;
1746 startCollectionBuf += 3;
1747
1748 // Replace: "for (type element in" with string constructed thus far.
1749 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1750 // Replace ')' in for '(' type elem in collection ')' with ';'
1751 SourceLocation rightParenLoc = S->getRParenLoc();
1752 const char *rparenBuf = SM->getCharacterData(rightParenLoc);
1753 SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);
1754 buf = ";\n\t";
1755
1756 // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1757 // objects:__rw_items count:16];
1758 // which is synthesized into:
1759 // NSUInteger limit =
1760 // ((NSUInteger (*)
1761 // (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))
1762 // (void *)objc_msgSend)((id)l_collection,
1763 // sel_registerName(
1764 // "countByEnumeratingWithState:objects:count:"),
1765 // (struct __objcFastEnumerationState *)&state,
1766 // (id *)__rw_items, (NSUInteger)16);
1767 buf += "_WIN_NSUInteger limit =\n\t\t";
1768 SynthCountByEnumWithState(buf);
1769 buf += ";\n\t";
1770 /// if (limit) {
1771 /// unsigned long startMutations = *enumState.mutationsPtr;
1772 /// do {
1773 /// unsigned long counter = 0;
1774 /// do {
1775 /// if (startMutations != *enumState.mutationsPtr)
1776 /// objc_enumerationMutation(l_collection);
1777 /// elem = (type)enumState.itemsPtr[counter++];
1778 buf += "if (limit) {\n\t";
1779 buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1780 buf += "do {\n\t\t";
1781 buf += "unsigned long counter = 0;\n\t\t";
1782 buf += "do {\n\t\t\t";
1783 buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1784 buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
1785 buf += elementName;
1786 buf += " = (";
1787 buf += elementTypeAsString;
1788 buf += ")enumState.itemsPtr[counter++];";
1789 // Replace ')' in for '(' type elem in collection ')' with all of these.
1790 ReplaceText(lparenLoc, 1, buf);
1791
1792 /// __continue_label: ;
1793 /// } while (counter < limit);
1794 /// } while ((limit = [l_collection countByEnumeratingWithState:&enumState
1795 /// objects:__rw_items count:16]));
1796 /// elem = nil;
1797 /// __break_label: ;
1798 /// }
1799 /// else
1800 /// elem = nil;
1801 /// }
1802 ///
1803 buf = ";\n\t";
1804 buf += "__continue_label_";
1805 buf += utostr(ObjCBcLabelNo.back());
1806 buf += ": ;";
1807 buf += "\n\t\t";
1808 buf += "} while (counter < limit);\n\t";
1809 buf += "} while ((limit = ";
1810 SynthCountByEnumWithState(buf);
1811 buf += "));\n\t";
1812 buf += elementName;
1813 buf += " = ((";
1814 buf += elementTypeAsString;
1815 buf += ")0);\n\t";
1816 buf += "__break_label_";
1817 buf += utostr(ObjCBcLabelNo.back());
1818 buf += ": ;\n\t";
1819 buf += "}\n\t";
1820 buf += "else\n\t\t";
1821 buf += elementName;
1822 buf += " = ((";
1823 buf += elementTypeAsString;
1824 buf += ")0);\n\t";
1825 buf += "}\n";
1826
1827 // Insert all these *after* the statement body.
1828 // FIXME: If this should support Obj-C++, support CXXTryStmt
1829 if (isa<CompoundStmt>(S->getBody())) {
1830 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);
1831 InsertText(endBodyLoc, buf);
1832 } else {
1833 /* Need to treat single statements specially. For example:
1834 *
1835 * for (A *a in b) if (stuff()) break;
1836 * for (A *a in b) xxxyy;
1837 *
1838 * The following code simply scans ahead to the semi to find the actual end.
1839 */
1840 const char *stmtBuf = SM->getCharacterData(OrigEnd);
1841 const char *semiBuf = strchr(stmtBuf, ';');
1842 assert(semiBuf && "Can't find ';'");
1843 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);
1844 InsertText(endBodyLoc, buf);
1845 }
1846 Stmts.pop_back();
1847 ObjCBcLabelNo.pop_back();
1848 return nullptr;
1849}
1850
1851static void Write_RethrowObject(std::string &buf) {
1852 buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n";
1853 buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n";
1854 buf += "\tid rethrow;\n";
1855 buf += "\t} _fin_force_rethow(_rethrow);";
1856}
1857
1858/// RewriteObjCSynchronizedStmt -
1859/// This routine rewrites @synchronized(expr) stmt;
1860/// into:
1861/// objc_sync_enter(expr);
1862/// @try stmt @finally { objc_sync_exit(expr); }
1863///
1864Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
1865 // Get the start location and compute the semi location.
1866 SourceLocation startLoc = S->getBeginLoc();
1867 const char *startBuf = SM->getCharacterData(startLoc);
1868
1869 assert((*startBuf == '@') && "bogus @synchronized location");
1870
1871 std::string buf;
1872 SourceLocation SynchLoc = S->getAtSynchronizedLoc();
1873 ConvertSourceLocationToLineDirective(SynchLoc, buf);
1874 buf += "{ id _rethrow = 0; id _sync_obj = (id)";
1875
1876 const char *lparenBuf = startBuf;
1877 while (*lparenBuf != '(') lparenBuf++;
1878 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1879
1880 buf = "; objc_sync_enter(_sync_obj);\n";
1881 buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}";
1882 buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}";
1883 buf += "\n\tid sync_exit;";
1884 buf += "\n\t} _sync_exit(_sync_obj);\n";
1885
1886 // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since
1887 // the sync expression is typically a message expression that's already
1888 // been rewritten! (which implies the SourceLocation's are invalid).
1889 SourceLocation RParenExprLoc = S->getSynchBody()->getBeginLoc();
1890 const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);
1891 while (*RParenExprLocBuf != ')') RParenExprLocBuf--;
1892 RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);
1893
1894 SourceLocation LBranceLoc = S->getSynchBody()->getBeginLoc();
1895 const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);
1896 assert (*LBraceLocBuf == '{');
1897 ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);
1898
1899 SourceLocation startRBraceLoc = S->getSynchBody()->getEndLoc();
1900 assert((*SM->getCharacterData(startRBraceLoc) == '}') &&
1901 "bogus @synchronized block");
1902
1903 buf = "} catch (id e) {_rethrow = e;}\n";
1904 Write_RethrowObject(buf);
1905 buf += "}\n";
1906 buf += "}\n";
1907
1908 ReplaceText(startRBraceLoc, 1, buf);
1909
1910 return nullptr;
1911}
1912
1913void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)
1914{
1915 // Perform a bottom up traversal of all children.
1916 for (Stmt *SubStmt : S->children())
1917 if (SubStmt)
1918 WarnAboutReturnGotoStmts(SubStmt);
1919
1920 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1921 Diags.Report(Context->getFullLoc(S->getBeginLoc()),
1922 TryFinallyContainsReturnDiag);
1923 }
1924}
1925
1926Stmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {
1927 SourceLocation startLoc = S->getAtLoc();
1928 ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");
1929 ReplaceText(S->getSubStmt()->getBeginLoc(), 1,
1930 "{ __AtAutoreleasePool __autoreleasepool; ");
1931
1932 return nullptr;
1933}
1934
1935Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
1936 ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt();
1937 bool noCatch = S->getNumCatchStmts() == 0;
1938 std::string buf;
1939 SourceLocation TryLocation = S->getAtTryLoc();
1940 ConvertSourceLocationToLineDirective(TryLocation, buf);
1941
1942 if (finalStmt) {
1943 if (noCatch)
1944 buf += "{ id volatile _rethrow = 0;\n";
1945 else {
1946 buf += "{ id volatile _rethrow = 0;\ntry {\n";
1947 }
1948 }
1949 // Get the start location and compute the semi location.
1950 SourceLocation startLoc = S->getBeginLoc();
1951 const char *startBuf = SM->getCharacterData(startLoc);
1952
1953 assert((*startBuf == '@') && "bogus @try location");
1954 if (finalStmt)
1955 ReplaceText(startLoc, 1, buf);
1956 else
1957 // @try -> try
1958 ReplaceText(startLoc, 1, "");
1959
1960 for (ObjCAtCatchStmt *Catch : S->catch_stmts()) {
1961 VarDecl *catchDecl = Catch->getCatchParamDecl();
1962
1963 startLoc = Catch->getBeginLoc();
1964 bool AtRemoved = false;
1965 if (catchDecl) {
1966 QualType t = catchDecl->getType();
1967 if (const ObjCObjectPointerType *Ptr =
1969 // Should be a pointer to a class.
1970 ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
1971 if (IDecl) {
1972 std::string Result;
1973 ConvertSourceLocationToLineDirective(Catch->getBeginLoc(), Result);
1974
1975 startBuf = SM->getCharacterData(startLoc);
1976 assert((*startBuf == '@') && "bogus @catch location");
1977 SourceLocation rParenLoc = Catch->getRParenLoc();
1978 const char *rParenBuf = SM->getCharacterData(rParenLoc);
1979
1980 // _objc_exc_Foo *_e as argument to catch.
1981 Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString();
1982 Result += " *_"; Result += catchDecl->getNameAsString();
1983 Result += ")";
1984 ReplaceText(startLoc, rParenBuf-startBuf+1, Result);
1985 // Foo *e = (Foo *)_e;
1986 Result.clear();
1987 Result = "{ ";
1988 Result += IDecl->getNameAsString();
1989 Result += " *"; Result += catchDecl->getNameAsString();
1990 Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";
1991 Result += "_"; Result += catchDecl->getNameAsString();
1992
1993 Result += "; ";
1994 SourceLocation lBraceLoc = Catch->getCatchBody()->getBeginLoc();
1995 ReplaceText(lBraceLoc, 1, Result);
1996 AtRemoved = true;
1997 }
1998 }
1999 }
2000 if (!AtRemoved)
2001 // @catch -> catch
2002 ReplaceText(startLoc, 1, "");
2003
2004 }
2005 if (finalStmt) {
2006 buf.clear();
2007 SourceLocation FinallyLoc = finalStmt->getBeginLoc();
2008
2009 if (noCatch) {
2010 ConvertSourceLocationToLineDirective(FinallyLoc, buf);
2011 buf += "catch (id e) {_rethrow = e;}\n";
2012 }
2013 else {
2014 buf += "}\n";
2015 ConvertSourceLocationToLineDirective(FinallyLoc, buf);
2016 buf += "catch (id e) {_rethrow = e;}\n";
2017 }
2018
2019 SourceLocation startFinalLoc = finalStmt->getBeginLoc();
2020 ReplaceText(startFinalLoc, 8, buf);
2021 Stmt *body = finalStmt->getFinallyBody();
2022 SourceLocation startFinalBodyLoc = body->getBeginLoc();
2023 buf.clear();
2024 Write_RethrowObject(buf);
2025 ReplaceText(startFinalBodyLoc, 1, buf);
2026
2027 SourceLocation endFinalBodyLoc = body->getEndLoc();
2028 ReplaceText(endFinalBodyLoc, 1, "}\n}");
2029 // Now check for any return/continue/go statements within the @try.
2030 WarnAboutReturnGotoStmts(S->getTryBody());
2031 }
2032
2033 return nullptr;
2034}
2035
2036// This can't be done with ReplaceStmt(S, ThrowExpr), since
2037// the throw expression is typically a message expression that's already
2038// been rewritten! (which implies the SourceLocation's are invalid).
2039Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
2040 // Get the start location and compute the semi location.
2041 SourceLocation startLoc = S->getBeginLoc();
2042 const char *startBuf = SM->getCharacterData(startLoc);
2043
2044 assert((*startBuf == '@') && "bogus @throw location");
2045
2046 std::string buf;
2047 /* void objc_exception_throw(id) __attribute__((noreturn)); */
2048 if (S->getThrowExpr())
2049 buf = "objc_exception_throw(";
2050 else
2051 buf = "throw";
2052
2053 // handle "@ throw" correctly.
2054 const char *wBuf = strchr(startBuf, 'w');
2055 assert((*wBuf == 'w') && "@throw: can't find 'w'");
2056 ReplaceText(startLoc, wBuf-startBuf+1, buf);
2057
2058 SourceLocation endLoc = S->getEndLoc();
2059 const char *endBuf = SM->getCharacterData(endLoc);
2060 const char *semiBuf = strchr(endBuf, ';');
2061 assert((*semiBuf == ';') && "@throw: can't find ';'");
2062 SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
2063 if (S->getThrowExpr())
2064 ReplaceText(semiLoc, 1, ");");
2065 return nullptr;
2066}
2067
2068Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
2069 // Create a new string expression.
2070 std::string StrEncoding;
2071 Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
2072 Expr *Replacement = getStringLiteral(StrEncoding);
2073 ReplaceStmt(Exp, Replacement);
2074
2075 // Replace this subexpr in the parent.
2076 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
2077 return Replacement;
2078}
2079
2080Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
2081 if (!SelGetUidFunctionDecl)
2082 SynthSelGetUidFunctionDecl();
2083 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
2084 // Create a call to sel_registerName("selName").
2085 SmallVector<Expr*, 8> SelExprs;
2086 SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
2087 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2088 SelExprs);
2089 ReplaceStmt(Exp, SelExp);
2090 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
2091 return SelExp;
2092}
2093
2094CallExpr *
2095RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
2096 ArrayRef<Expr *> Args,
2097 SourceLocation StartLoc,
2098 SourceLocation EndLoc) {
2099 // Get the type, we will need to reference it in a couple spots.
2100 QualType msgSendType = FD->getType();
2101
2102 // Create a reference to the objc_msgSend() declaration.
2103 DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,
2104 VK_LValue, SourceLocation());
2105
2106 // Now, we cast the reference to a pointer to the objc_msgSend type.
2107 QualType pToFunc = Context->getPointerType(msgSendType);
2108 ImplicitCastExpr *ICE =
2109 ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
2110 DRE, nullptr, VK_PRValue, FPOptionsOverride());
2111
2112 const auto *FT = msgSendType->castAs<FunctionType>();
2113 CallExpr *Exp =
2114 CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
2115 VK_PRValue, EndLoc, FPOptionsOverride());
2116 return Exp;
2117}
2118
2119static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
2120 const char *&startRef, const char *&endRef) {
2121 while (startBuf < endBuf) {
2122 if (*startBuf == '<')
2123 startRef = startBuf; // mark the start.
2124 if (*startBuf == '>') {
2125 if (startRef && *startRef == '<') {
2126 endRef = startBuf; // mark the end.
2127 return true;
2128 }
2129 return false;
2130 }
2131 startBuf++;
2132 }
2133 return false;
2134}
2135
2136static void scanToNextArgument(const char *&argRef) {
2137 int angle = 0;
2138 while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
2139 if (*argRef == '<')
2140 angle++;
2141 else if (*argRef == '>')
2142 angle--;
2143 argRef++;
2144 }
2145 assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
2146}
2147
2148bool RewriteModernObjC::needToScanForQualifiers(QualType T) {
2149 if (T->isObjCQualifiedIdType())
2150 return true;
2151 if (const PointerType *PT = T->getAs<PointerType>()) {
2152 if (PT->getPointeeType()->isObjCQualifiedIdType())
2153 return true;
2154 }
2155 if (T->isObjCObjectPointerType()) {
2156 T = T->getPointeeType();
2157 return T->isObjCQualifiedInterfaceType();
2158 }
2159 if (T->isArrayType()) {
2160 QualType ElemTy = Context->getBaseElementType(T);
2161 return needToScanForQualifiers(ElemTy);
2162 }
2163 return false;
2164}
2165
2166void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
2167 QualType Type = E->getType();
2168 if (needToScanForQualifiers(Type)) {
2169 SourceLocation Loc, EndLoc;
2170
2171 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
2172 Loc = ECE->getLParenLoc();
2173 EndLoc = ECE->getRParenLoc();
2174 } else {
2175 Loc = E->getBeginLoc();
2176 EndLoc = E->getEndLoc();
2177 }
2178 // This will defend against trying to rewrite synthesized expressions.
2179 if (Loc.isInvalid() || EndLoc.isInvalid())
2180 return;
2181
2182 const char *startBuf = SM->getCharacterData(Loc);
2183 const char *endBuf = SM->getCharacterData(EndLoc);
2184 const char *startRef = nullptr, *endRef = nullptr;
2185 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2186 // Get the locations of the startRef, endRef.
2187 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
2188 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);
2189 // Comment out the protocol references.
2190 InsertText(LessLoc, "/*");
2191 InsertText(GreaterLoc, "*/");
2192 }
2193 }
2194}
2195
2196void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
2197 SourceLocation Loc;
2198 QualType Type;
2199 const FunctionProtoType *proto = nullptr;
2200 if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2201 Loc = VD->getLocation();
2202 Type = VD->getType();
2203 }
2204 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2205 Loc = FD->getLocation();
2206 // Check for ObjC 'id' and class types that have been adorned with protocol
2207 // information (id<p>, C<p>*). The protocol references need to be rewritten!
2208 const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2209 assert(funcType && "missing function type");
2210 proto = dyn_cast<FunctionProtoType>(funcType);
2211 if (!proto)
2212 return;
2213 Type = proto->getReturnType();
2214 }
2215 else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2216 Loc = FD->getLocation();
2217 Type = FD->getType();
2218 }
2219 else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) {
2220 Loc = TD->getLocation();
2221 Type = TD->getUnderlyingType();
2222 }
2223 else
2224 return;
2225
2226 if (needToScanForQualifiers(Type)) {
2227 // Since types are unique, we need to scan the buffer.
2228
2229 const char *endBuf = SM->getCharacterData(Loc);
2230 const char *startBuf = endBuf;
2231 while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
2232 startBuf--; // scan backward (from the decl location) for return type.
2233 const char *startRef = nullptr, *endRef = nullptr;
2234 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2235 // Get the locations of the startRef, endRef.
2236 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
2237 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);
2238 // Comment out the protocol references.
2239 InsertText(LessLoc, "/*");
2240 InsertText(GreaterLoc, "*/");
2241 }
2242 }
2243 if (!proto)
2244 return; // most likely, was a variable
2245 // Now check arguments.
2246 const char *startBuf = SM->getCharacterData(Loc);
2247 const char *startFuncBuf = startBuf;
2248 for (unsigned i = 0; i < proto->getNumParams(); i++) {
2249 if (needToScanForQualifiers(proto->getParamType(i))) {
2250 // Since types are unique, we need to scan the buffer.
2251
2252 const char *endBuf = startBuf;
2253 // scan forward (from the decl location) for argument types.
2254 scanToNextArgument(endBuf);
2255 const char *startRef = nullptr, *endRef = nullptr;
2256 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2257 // Get the locations of the startRef, endRef.
2258 SourceLocation LessLoc =
2259 Loc.getLocWithOffset(startRef-startFuncBuf);
2260 SourceLocation GreaterLoc =
2261 Loc.getLocWithOffset(endRef-startFuncBuf+1);
2262 // Comment out the protocol references.
2263 InsertText(LessLoc, "/*");
2264 InsertText(GreaterLoc, "*/");
2265 }
2266 startBuf = ++endBuf;
2267 }
2268 else {
2269 // If the function name is derived from a macro expansion, then the
2270 // argument buffer will not follow the name. Need to speak with Chris.
2271 while (*startBuf && *startBuf != ')' && *startBuf != ',')
2272 startBuf++; // scan forward (from the decl location) for argument types.
2273 startBuf++;
2274 }
2275 }
2276}
2277
2278void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) {
2279 QualType QT = ND->getType();
2280 const Type* TypePtr = QT->getAs<Type>();
2281 if (!isa<TypeOfExprType>(TypePtr))
2282 return;
2283 while (isa<TypeOfExprType>(TypePtr)) {
2284 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2285 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
2286 TypePtr = QT->getAs<Type>();
2287 }
2288 // FIXME. This will not work for multiple declarators; as in:
2289 // __typeof__(a) b,c,d;
2290 std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));
2291 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
2292 const char *startBuf = SM->getCharacterData(DeclLoc);
2293 if (ND->getInit()) {
2294 std::string Name(ND->getNameAsString());
2295 TypeAsString += " " + Name + " = ";
2296 Expr *E = ND->getInit();
2297 SourceLocation startLoc;
2298 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
2299 startLoc = ECE->getLParenLoc();
2300 else
2301 startLoc = E->getBeginLoc();
2302 startLoc = SM->getExpansionLoc(startLoc);
2303 const char *endBuf = SM->getCharacterData(startLoc);
2304 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2305 }
2306 else {
2307 SourceLocation X = ND->getEndLoc();
2308 X = SM->getExpansionLoc(X);
2309 const char *endBuf = SM->getCharacterData(X);
2310 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2311 }
2312}
2313
2314// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
2315void RewriteModernObjC::SynthSelGetUidFunctionDecl() {
2316 IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
2318 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2319 QualType getFuncType =
2320 getSimpleFunctionType(Context->getObjCSelType(), ArgTys);
2321 SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2322 SourceLocation(),
2323 SourceLocation(),
2324 SelGetUidIdent, getFuncType,
2325 nullptr, SC_Extern);
2326}
2327
2328void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {
2329 // declared in <objc/objc.h>
2330 if (FD->getIdentifier() &&
2331 FD->getName() == "sel_registerName") {
2332 SelGetUidFunctionDecl = FD;
2333 return;
2334 }
2335 RewriteObjCQualifiedInterfaceTypes(FD);
2336}
2337
2338void RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {
2339 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
2340 const char *argPtr = TypeString.c_str();
2341 if (!strchr(argPtr, '^')) {
2342 Str += TypeString;
2343 return;
2344 }
2345 while (*argPtr) {
2346 Str += (*argPtr == '^' ? '*' : *argPtr);
2347 argPtr++;
2348 }
2349}
2350
2351// FIXME. Consolidate this routine with RewriteBlockPointerType.
2352void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2353 ValueDecl *VD) {
2354 QualType Type = VD->getType();
2355 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
2356 const char *argPtr = TypeString.c_str();
2357 int paren = 0;
2358 while (*argPtr) {
2359 switch (*argPtr) {
2360 case '(':
2361 Str += *argPtr;
2362 paren++;
2363 break;
2364 case ')':
2365 Str += *argPtr;
2366 paren--;
2367 break;
2368 case '^':
2369 Str += '*';
2370 if (paren == 1)
2371 Str += VD->getNameAsString();
2372 break;
2373 default:
2374 Str += *argPtr;
2375 break;
2376 }
2377 argPtr++;
2378 }
2379}
2380
2381void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
2382 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
2383 const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2384 const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
2385 if (!proto)
2386 return;
2387 QualType Type = proto->getReturnType();
2388 std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
2389 FdStr += " ";
2390 FdStr += FD->getName();
2391 FdStr += "(";
2392 unsigned numArgs = proto->getNumParams();
2393 for (unsigned i = 0; i < numArgs; i++) {
2394 QualType ArgType = proto->getParamType(i);
2395 RewriteBlockPointerType(FdStr, ArgType);
2396 if (i+1 < numArgs)
2397 FdStr += ", ";
2398 }
2399 if (FD->isVariadic()) {
2400 FdStr += (numArgs > 0) ? ", ...);\n" : "...);\n";
2401 }
2402 else
2403 FdStr += ");\n";
2404 InsertText(FunLocStart, FdStr);
2405}
2406
2407// SynthSuperConstructorFunctionDecl - id __rw_objc_super(id obj, id super);
2408void RewriteModernObjC::SynthSuperConstructorFunctionDecl() {
2409 if (SuperConstructorFunctionDecl)
2410 return;
2411 IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
2413 QualType argT = Context->getObjCIdType();
2414 assert(!argT.isNull() && "Can't find 'id' type");
2415 ArgTys.push_back(argT);
2416 ArgTys.push_back(argT);
2417 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2418 ArgTys);
2419 SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2420 SourceLocation(),
2421 SourceLocation(),
2422 msgSendIdent, msgSendType,
2423 nullptr, SC_Extern);
2424}
2425
2426// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
2427void RewriteModernObjC::SynthMsgSendFunctionDecl() {
2428 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
2430 QualType argT = Context->getObjCIdType();
2431 assert(!argT.isNull() && "Can't find 'id' type");
2432 ArgTys.push_back(argT);
2433 argT = Context->getObjCSelType();
2434 assert(!argT.isNull() && "Can't find 'SEL' type");
2435 ArgTys.push_back(argT);
2436 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2437 ArgTys, /*variadic=*/true);
2438 MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2439 SourceLocation(),
2440 SourceLocation(),
2441 msgSendIdent, msgSendType, nullptr,
2442 SC_Extern);
2443}
2444
2445// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void);
2446void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {
2447 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
2449 ArgTys.push_back(Context->VoidTy);
2450 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2451 ArgTys, /*variadic=*/true);
2452 MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2453 SourceLocation(),
2454 SourceLocation(),
2455 msgSendIdent, msgSendType,
2456 nullptr, SC_Extern);
2457}
2458
2459// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
2460void RewriteModernObjC::SynthMsgSendStretFunctionDecl() {
2461 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
2463 QualType argT = Context->getObjCIdType();
2464 assert(!argT.isNull() && "Can't find 'id' type");
2465 ArgTys.push_back(argT);
2466 argT = Context->getObjCSelType();
2467 assert(!argT.isNull() && "Can't find 'SEL' type");
2468 ArgTys.push_back(argT);
2469 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2470 ArgTys, /*variadic=*/true);
2471 MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2472 SourceLocation(),
2473 SourceLocation(),
2474 msgSendIdent, msgSendType,
2475 nullptr, SC_Extern);
2476}
2477
2478// SynthMsgSendSuperStretFunctionDecl -
2479// id objc_msgSendSuper_stret(void);
2480void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {
2481 IdentifierInfo *msgSendIdent =
2482 &Context->Idents.get("objc_msgSendSuper_stret");
2484 ArgTys.push_back(Context->VoidTy);
2485 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2486 ArgTys, /*variadic=*/true);
2487 MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2488 SourceLocation(),
2489 SourceLocation(),
2490 msgSendIdent,
2491 msgSendType, nullptr,
2492 SC_Extern);
2493}
2494
2495// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
2496void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() {
2497 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
2499 QualType argT = Context->getObjCIdType();
2500 assert(!argT.isNull() && "Can't find 'id' type");
2501 ArgTys.push_back(argT);
2502 argT = Context->getObjCSelType();
2503 assert(!argT.isNull() && "Can't find 'SEL' type");
2504 ArgTys.push_back(argT);
2505 QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
2506 ArgTys, /*variadic=*/true);
2507 MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2508 SourceLocation(),
2509 SourceLocation(),
2510 msgSendIdent, msgSendType,
2511 nullptr, SC_Extern);
2512}
2513
2514// SynthGetClassFunctionDecl - Class objc_getClass(const char *name);
2515void RewriteModernObjC::SynthGetClassFunctionDecl() {
2516 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
2518 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2519 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2520 ArgTys);
2521 GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2522 SourceLocation(),
2523 SourceLocation(),
2524 getClassIdent, getClassType,
2525 nullptr, SC_Extern);
2526}
2527
2528// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
2529void RewriteModernObjC::SynthGetSuperClassFunctionDecl() {
2530 IdentifierInfo *getSuperClassIdent =
2531 &Context->Idents.get("class_getSuperclass");
2533 ArgTys.push_back(Context->getObjCClassType());
2534 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2535 ArgTys);
2536 GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2537 SourceLocation(),
2538 SourceLocation(),
2539 getSuperClassIdent,
2540 getClassType, nullptr,
2541 SC_Extern);
2542}
2543
2544// SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name);
2545void RewriteModernObjC::SynthGetMetaClassFunctionDecl() {
2546 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
2548 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2549 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2550 ArgTys);
2551 GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2552 SourceLocation(),
2553 SourceLocation(),
2554 getClassIdent, getClassType,
2555 nullptr, SC_Extern);
2556}
2557
2558Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
2559 assert (Exp != nullptr && "Expected non-null ObjCStringLiteral");
2560 QualType strType = getConstantStringStructType();
2561
2562 std::string S = "__NSConstantStringImpl_";
2563
2564 std::string tmpName = InFileName;
2565 unsigned i;
2566 for (i=0; i < tmpName.length(); i++) {
2567 char c = tmpName.at(i);
2568 // replace any non-alphanumeric characters with '_'.
2569 if (!isAlphanumeric(c))
2570 tmpName[i] = '_';
2571 }
2572 S += tmpName;
2573 S += "_";
2574 S += utostr(NumObjCStringLiterals++);
2575
2576 Preamble += "static __NSConstantStringImpl " + S;
2577 Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2578 Preamble += "0x000007c8,"; // utf8_str
2579 // The pretty printer for StringLiteral handles escape characters properly.
2580 std::string prettyBufS;
2581 llvm::raw_string_ostream prettyBuf(prettyBufS);
2582 Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));
2583 Preamble += prettyBufS;
2584 Preamble += ",";
2585 Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
2586
2587 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
2588 SourceLocation(), &Context->Idents.get(S),
2589 strType, nullptr, SC_Static);
2590 DeclRefExpr *DRE = new (Context)
2591 DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
2593 const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
2594 Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
2595 SourceLocation(), false, FPOptionsOverride());
2596 // cast to NSConstantString *
2597 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
2598 CK_CPointerToObjCPointerCast, Unop);
2599 ReplaceStmt(Exp, cast);
2600 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
2601 return cast;
2602}
2603
2604Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {
2605 unsigned IntSize =
2606 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
2607
2608 Expr *FlagExp = IntegerLiteral::Create(*Context,
2609 llvm::APInt(IntSize, Exp->getValue()),
2610 Context->IntTy, Exp->getLocation());
2611 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy,
2612 CK_BitCast, FlagExp);
2613 ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),
2614 cast);
2615 ReplaceStmt(Exp, PE);
2616 return PE;
2617}
2618
2619Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {
2620 // synthesize declaration of helper functions needed in this routine.
2621 if (!SelGetUidFunctionDecl)
2622 SynthSelGetUidFunctionDecl();
2623 // use objc_msgSend() for all.
2624 if (!MsgSendFunctionDecl)
2625 SynthMsgSendFunctionDecl();
2626 if (!GetClassFunctionDecl)
2627 SynthGetClassFunctionDecl();
2628
2629 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
2630 SourceLocation StartLoc = Exp->getBeginLoc();
2631 SourceLocation EndLoc = Exp->getEndLoc();
2632
2633 // Synthesize a call to objc_msgSend().
2634 SmallVector<Expr*, 4> MsgExprs;
2635 SmallVector<Expr*, 4> ClsExprs;
2636
2637 // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument.
2638 ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod();
2639 ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface();
2640
2641 IdentifierInfo *clsName = BoxingClass->getIdentifier();
2642 ClsExprs.push_back(getStringLiteral(clsName->getName()));
2643 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2644 StartLoc, EndLoc);
2645 MsgExprs.push_back(Cls);
2646
2647 // Create a call to sel_registerName("<BoxingMethod>:"), etc.
2648 // it will be the 2nd argument.
2649 SmallVector<Expr*, 4> SelExprs;
2650 SelExprs.push_back(
2651 getStringLiteral(BoxingMethod->getSelector().getAsString()));
2652 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2653 SelExprs, StartLoc, EndLoc);
2654 MsgExprs.push_back(SelExp);
2655
2656 // User provided sub-expression is the 3rd, and last, argument.
2657 Expr *subExpr = Exp->getSubExpr();
2658 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) {
2659 QualType type = ICE->getType();
2660 const Expr *SubExpr = ICE->IgnoreParenImpCasts();
2661 CastKind CK = CK_BitCast;
2662 if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType())
2663 CK = CK_IntegralToBoolean;
2664 subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr);
2665 }
2666 MsgExprs.push_back(subExpr);
2667
2668 SmallVector<QualType, 4> ArgTypes;
2669 ArgTypes.push_back(Context->getObjCClassType());
2670 ArgTypes.push_back(Context->getObjCSelType());
2671 for (const auto PI : BoxingMethod->parameters())
2672 ArgTypes.push_back(PI->getType());
2673
2674 QualType returnType = Exp->getType();
2675 // Get the type, we will need to reference it in a couple spots.
2676 QualType msgSendType = MsgSendFlavor->getType();
2677
2678 // Create a reference to the objc_msgSend() declaration.
2679 DeclRefExpr *DRE = new (Context) DeclRefExpr(
2680 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
2681
2682 CastExpr *cast = NoTypeInfoCStyleCastExpr(
2683 Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
2684
2685 // Now do the "normal" pointer to function cast.
2686 QualType castType =
2687 getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic());
2688 castType = Context->getPointerType(castType);
2689 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2690 cast);
2691
2692 // Don't forget the parens to enforce the proper binding.
2693 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
2694
2695 auto *FT = msgSendType->castAs<FunctionType>();
2696 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2697 VK_PRValue, EndLoc, FPOptionsOverride());
2698 ReplaceStmt(Exp, CE);
2699 return CE;
2700}
2701
2702Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {
2703 // synthesize declaration of helper functions needed in this routine.
2704 if (!SelGetUidFunctionDecl)
2705 SynthSelGetUidFunctionDecl();
2706 // use objc_msgSend() for all.
2707 if (!MsgSendFunctionDecl)
2708 SynthMsgSendFunctionDecl();
2709 if (!GetClassFunctionDecl)
2710 SynthGetClassFunctionDecl();
2711
2712 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
2713 SourceLocation StartLoc = Exp->getBeginLoc();
2714 SourceLocation EndLoc = Exp->getEndLoc();
2715
2716 // Build the expression: __NSContainer_literal(int, ...).arr
2717 QualType IntQT = Context->IntTy;
2718 QualType NSArrayFType =
2719 getSimpleFunctionType(Context->VoidTy, IntQT, true);
2720 std::string NSArrayFName("__NSContainer_literal");
2721 FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);
2722 DeclRefExpr *NSArrayDRE = new (Context) DeclRefExpr(
2723 *Context, NSArrayFD, false, NSArrayFType, VK_PRValue, SourceLocation());
2724
2725 SmallVector<Expr*, 16> InitExprs;
2726 unsigned NumElements = Exp->getNumElements();
2727 unsigned UnsignedIntSize =
2728 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
2729 Expr *count = IntegerLiteral::Create(*Context,
2730 llvm::APInt(UnsignedIntSize, NumElements),
2731 Context->UnsignedIntTy, SourceLocation());
2732 InitExprs.push_back(count);
2733 for (unsigned i = 0; i < NumElements; i++)
2734 InitExprs.push_back(Exp->getElement(i));
2735 Expr *NSArrayCallExpr =
2736 CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue,
2737 SourceLocation(), FPOptionsOverride());
2738
2739 FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
2740 SourceLocation(),
2741 &Context->Idents.get("arr"),
2742 Context->getPointerType(Context->VoidPtrTy),
2743 nullptr, /*BitWidth=*/nullptr,
2744 /*Mutable=*/true, ICIS_NoInit);
2745 MemberExpr *ArrayLiteralME =
2746 MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD,
2747 ARRFD->getType(), VK_LValue, OK_Ordinary);
2748 QualType ConstIdT = Context->getObjCIdType().withConst();
2749 CStyleCastExpr * ArrayLiteralObjects =
2750 NoTypeInfoCStyleCastExpr(Context,
2751 Context->getPointerType(ConstIdT),
2752 CK_BitCast,
2753 ArrayLiteralME);
2754
2755 // Synthesize a call to objc_msgSend().
2756 SmallVector<Expr*, 32> MsgExprs;
2757 SmallVector<Expr*, 4> ClsExprs;
2758 QualType expType = Exp->getType();
2759
2760 // Create a call to objc_getClass("NSArray"). It will be th 1st argument.
2761 ObjCInterfaceDecl *Class =
2762 expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();
2763
2764 IdentifierInfo *clsName = Class->getIdentifier();
2765 ClsExprs.push_back(getStringLiteral(clsName->getName()));
2766 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2767 StartLoc, EndLoc);
2768 MsgExprs.push_back(Cls);
2769
2770 // Create a call to sel_registerName("arrayWithObjects:count:").
2771 // it will be the 2nd argument.
2772 SmallVector<Expr*, 4> SelExprs;
2773 ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod();
2774 SelExprs.push_back(
2775 getStringLiteral(ArrayMethod->getSelector().getAsString()));
2776 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2777 SelExprs, StartLoc, EndLoc);
2778 MsgExprs.push_back(SelExp);
2779
2780 // (const id [])objects
2781 MsgExprs.push_back(ArrayLiteralObjects);
2782
2783 // (NSUInteger)cnt
2784 Expr *cnt = IntegerLiteral::Create(*Context,
2785 llvm::APInt(UnsignedIntSize, NumElements),
2786 Context->UnsignedIntTy, SourceLocation());
2787 MsgExprs.push_back(cnt);
2788
2789 SmallVector<QualType, 4> ArgTypes;
2790 ArgTypes.push_back(Context->getObjCClassType());
2791 ArgTypes.push_back(Context->getObjCSelType());
2792 for (const auto *PI : ArrayMethod->parameters())
2793 ArgTypes.push_back(PI->getType());
2794
2795 QualType returnType = Exp->getType();
2796 // Get the type, we will need to reference it in a couple spots.
2797 QualType msgSendType = MsgSendFlavor->getType();
2798
2799 // Create a reference to the objc_msgSend() declaration.
2800 DeclRefExpr *DRE = new (Context) DeclRefExpr(
2801 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
2802
2803 CastExpr *cast = NoTypeInfoCStyleCastExpr(
2804 Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
2805
2806 // Now do the "normal" pointer to function cast.
2807 QualType castType =
2808 getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic());
2809 castType = Context->getPointerType(castType);
2810 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2811 cast);
2812
2813 // Don't forget the parens to enforce the proper binding.
2814 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
2815
2816 const FunctionType *FT = msgSendType->castAs<FunctionType>();
2817 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2818 VK_PRValue, EndLoc, FPOptionsOverride());
2819 ReplaceStmt(Exp, CE);
2820 return CE;
2821}
2822
2823Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) {
2824 // synthesize declaration of helper functions needed in this routine.
2825 if (!SelGetUidFunctionDecl)
2826 SynthSelGetUidFunctionDecl();
2827 // use objc_msgSend() for all.
2828 if (!MsgSendFunctionDecl)
2829 SynthMsgSendFunctionDecl();
2830 if (!GetClassFunctionDecl)
2831 SynthGetClassFunctionDecl();
2832
2833 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
2834 SourceLocation StartLoc = Exp->getBeginLoc();
2835 SourceLocation EndLoc = Exp->getEndLoc();
2836
2837 // Build the expression: __NSContainer_literal(int, ...).arr
2838 QualType IntQT = Context->IntTy;
2839 QualType NSDictFType =
2840 getSimpleFunctionType(Context->VoidTy, IntQT, true);
2841 std::string NSDictFName("__NSContainer_literal");
2842 FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);
2843 DeclRefExpr *NSDictDRE = new (Context) DeclRefExpr(
2844 *Context, NSDictFD, false, NSDictFType, VK_PRValue, SourceLocation());
2845
2846 SmallVector<Expr*, 16> KeyExprs;
2847 SmallVector<Expr*, 16> ValueExprs;
2848
2849 unsigned NumElements = Exp->getNumElements();
2850 unsigned UnsignedIntSize =
2851 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
2852 Expr *count = IntegerLiteral::Create(*Context,
2853 llvm::APInt(UnsignedIntSize, NumElements),
2854 Context->UnsignedIntTy, SourceLocation());
2855 KeyExprs.push_back(count);
2856 ValueExprs.push_back(count);
2857 for (unsigned i = 0; i < NumElements; i++) {
2858 ObjCDictionaryElement Element = Exp->getKeyValueElement(i);
2859 KeyExprs.push_back(Element.Key);
2860 ValueExprs.push_back(Element.Value);
2861 }
2862
2863 // (const id [])objects
2864 Expr *NSValueCallExpr =
2865 CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue,
2866 SourceLocation(), FPOptionsOverride());
2867
2868 FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
2869 SourceLocation(),
2870 &Context->Idents.get("arr"),
2871 Context->getPointerType(Context->VoidPtrTy),
2872 nullptr, /*BitWidth=*/nullptr,
2873 /*Mutable=*/true, ICIS_NoInit);
2874 MemberExpr *DictLiteralValueME =
2875 MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD,
2876 ARRFD->getType(), VK_LValue, OK_Ordinary);
2877 QualType ConstIdT = Context->getObjCIdType().withConst();
2878 CStyleCastExpr * DictValueObjects =
2879 NoTypeInfoCStyleCastExpr(Context,
2880 Context->getPointerType(ConstIdT),
2881 CK_BitCast,
2882 DictLiteralValueME);
2883 // (const id <NSCopying> [])keys
2884 Expr *NSKeyCallExpr =
2885 CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue,
2886 SourceLocation(), FPOptionsOverride());
2887
2888 MemberExpr *DictLiteralKeyME =
2889 MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD,
2890 ARRFD->getType(), VK_LValue, OK_Ordinary);
2891
2892 CStyleCastExpr * DictKeyObjects =
2893 NoTypeInfoCStyleCastExpr(Context,
2894 Context->getPointerType(ConstIdT),
2895 CK_BitCast,
2896 DictLiteralKeyME);
2897
2898 // Synthesize a call to objc_msgSend().
2899 SmallVector<Expr*, 32> MsgExprs;
2900 SmallVector<Expr*, 4> ClsExprs;
2901 QualType expType = Exp->getType();
2902
2903 // Create a call to objc_getClass("NSArray"). It will be th 1st argument.
2904 ObjCInterfaceDecl *Class =
2905 expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();
2906
2907 IdentifierInfo *clsName = Class->getIdentifier();
2908 ClsExprs.push_back(getStringLiteral(clsName->getName()));
2909 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2910 StartLoc, EndLoc);
2911 MsgExprs.push_back(Cls);
2912
2913 // Create a call to sel_registerName("arrayWithObjects:count:").
2914 // it will be the 2nd argument.
2915 SmallVector<Expr*, 4> SelExprs;
2916 ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod();
2917 SelExprs.push_back(getStringLiteral(DictMethod->getSelector().getAsString()));
2918 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2919 SelExprs, StartLoc, EndLoc);
2920 MsgExprs.push_back(SelExp);
2921
2922 // (const id [])objects
2923 MsgExprs.push_back(DictValueObjects);
2924
2925 // (const id <NSCopying> [])keys
2926 MsgExprs.push_back(DictKeyObjects);
2927
2928 // (NSUInteger)cnt
2929 Expr *cnt = IntegerLiteral::Create(*Context,
2930 llvm::APInt(UnsignedIntSize, NumElements),
2931 Context->UnsignedIntTy, SourceLocation());
2932 MsgExprs.push_back(cnt);
2933
2934 SmallVector<QualType, 8> ArgTypes;
2935 ArgTypes.push_back(Context->getObjCClassType());
2936 ArgTypes.push_back(Context->getObjCSelType());
2937 for (const auto *PI : DictMethod->parameters()) {
2938 QualType T = PI->getType();
2939 if (const PointerType* PT = T->getAs<PointerType>()) {
2940 QualType PointeeTy = PT->getPointeeType();
2941 convertToUnqualifiedObjCType(PointeeTy);
2942 T = Context->getPointerType(PointeeTy);
2943 }
2944 ArgTypes.push_back(T);
2945 }
2946
2947 QualType returnType = Exp->getType();
2948 // Get the type, we will need to reference it in a couple spots.
2949 QualType msgSendType = MsgSendFlavor->getType();
2950
2951 // Create a reference to the objc_msgSend() declaration.
2952 DeclRefExpr *DRE = new (Context) DeclRefExpr(
2953 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
2954
2955 CastExpr *cast = NoTypeInfoCStyleCastExpr(
2956 Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);
2957
2958 // Now do the "normal" pointer to function cast.
2959 QualType castType =
2960 getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic());
2961 castType = Context->getPointerType(castType);
2962 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2963 cast);
2964
2965 // Don't forget the parens to enforce the proper binding.
2966 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
2967
2968 const FunctionType *FT = msgSendType->castAs<FunctionType>();
2969 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2970 VK_PRValue, EndLoc, FPOptionsOverride());
2971 ReplaceStmt(Exp, CE);
2972 return CE;
2973}
2974
2975// struct __rw_objc_super {
2976// struct objc_object *object; struct objc_object *superClass;
2977// };
2978QualType RewriteModernObjC::getSuperStructType() {
2979 if (!SuperStructDecl) {
2980 SuperStructDecl = RecordDecl::Create(
2981 *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),
2982 SourceLocation(), &Context->Idents.get("__rw_objc_super"));
2983 QualType FieldTypes[2];
2984
2985 // struct objc_object *object;
2986 FieldTypes[0] = Context->getObjCIdType();
2987 // struct objc_object *superClass;
2988 FieldTypes[1] = Context->getObjCIdType();
2989
2990 // Create fields
2991 for (unsigned i = 0; i < 2; ++i) {
2992 SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
2993 SourceLocation(),
2994 SourceLocation(), nullptr,
2995 FieldTypes[i], nullptr,
2996 /*BitWidth=*/nullptr,
2997 /*Mutable=*/false,
2998 ICIS_NoInit));
2999 }
3000
3001 SuperStructDecl->completeDefinition();
3002 }
3003 return Context->getCanonicalTagType(SuperStructDecl);
3004}
3005
3006QualType RewriteModernObjC::getConstantStringStructType() {
3007 if (!ConstantStringDecl) {
3008 ConstantStringDecl = RecordDecl::Create(
3009 *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),
3010 SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));
3011 QualType FieldTypes[4];
3012
3013 // struct objc_object *receiver;
3014 FieldTypes[0] = Context->getObjCIdType();
3015 // int flags;
3016 FieldTypes[1] = Context->IntTy;
3017 // char *str;
3018 FieldTypes[2] = Context->getPointerType(Context->CharTy);
3019 // long length;
3020 FieldTypes[3] = Context->LongTy;
3021
3022 // Create fields
3023 for (unsigned i = 0; i < 4; ++i) {
3024 ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
3025 ConstantStringDecl,
3026 SourceLocation(),
3027 SourceLocation(), nullptr,
3028 FieldTypes[i], nullptr,
3029 /*BitWidth=*/nullptr,
3030 /*Mutable=*/true,
3031 ICIS_NoInit));
3032 }
3033
3034 ConstantStringDecl->completeDefinition();
3035 }
3036 return Context->getCanonicalTagType(ConstantStringDecl);
3037}
3038
3039/// getFunctionSourceLocation - returns start location of a function
3040/// definition. Complication arises when function has declared as
3041/// extern "C" or extern "C" {...}
3042static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,
3043 FunctionDecl *FD) {
3044 if (FD->isExternC() && !FD->isMain()) {
3045 const DeclContext *DC = FD->getDeclContext();
3046 if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
3047 // if it is extern "C" {...}, return function decl's own location.
3048 if (!LSD->getRBraceLoc().isValid())
3049 return LSD->getExternLoc();
3050 }
3051 if (FD->getStorageClass() != SC_None)
3052 R.RewriteBlockLiteralFunctionDecl(FD);
3053 return FD->getTypeSpecStartLoc();
3054}
3055
3056void RewriteModernObjC::RewriteLineDirective(const Decl *D) {
3057
3058 SourceLocation Location = D->getLocation();
3059
3060 if (Location.isFileID() && GenerateLineInfo) {
3061 std::string LineString("\n#line ");
3062 PresumedLoc PLoc = SM->getPresumedLoc(Location);
3063 LineString += utostr(PLoc.getLine());
3064 LineString += " \"";
3065 LineString += Lexer::Stringify(PLoc.getFilename());
3066 if (isa<ObjCMethodDecl>(D))
3067 LineString += "\"";
3068 else LineString += "\"\n";
3069
3070 Location = D->getBeginLoc();
3071 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
3072 if (FD->isExternC() && !FD->isMain()) {
3073 const DeclContext *DC = FD->getDeclContext();
3074 if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))
3075 // if it is extern "C" {...}, return function decl's own location.
3076 if (!LSD->getRBraceLoc().isValid())
3077 Location = LSD->getExternLoc();
3078 }
3079 }
3080 InsertText(Location, LineString);
3081 }
3082}
3083
3084/// SynthMsgSendStretCallExpr - This routine translates message expression
3085/// into a call to objc_msgSend_stret() entry point. Tricky part is that
3086/// nil check on receiver must be performed before calling objc_msgSend_stret.
3087/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)
3088/// msgSendType - function type of objc_msgSend_stret(...)
3089/// returnType - Result type of the method being synthesized.
3090/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.
3091/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,
3092/// starting with receiver.
3093/// Method - Method being rewritten.
3094Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
3095 QualType returnType,
3096 SmallVectorImpl<QualType> &ArgTypes,
3097 SmallVectorImpl<Expr*> &MsgExprs,
3098 ObjCMethodDecl *Method) {
3099 // Now do the "normal" pointer to function cast.
3100 QualType FuncType = getSimpleFunctionType(
3101 returnType, ArgTypes, Method ? Method->isVariadic() : false);
3102 QualType castType = Context->getPointerType(FuncType);
3103
3104 // build type for containing the objc_msgSend_stret object.
3105 static unsigned stretCount=0;
3106 std::string name = "__Stret"; name += utostr(stretCount);
3107 std::string str =
3108 "extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n";
3109 str += "namespace {\n";
3110 str += "struct "; str += name;
3111 str += " {\n\t";
3112 str += name;
3113 str += "(id receiver, SEL sel";
3114 for (unsigned i = 2; i < ArgTypes.size(); i++) {
3115 std::string ArgName = "arg"; ArgName += utostr(i);
3116 ArgTypes[i].getAsStringInternal(ArgName, Context->getPrintingPolicy());
3117 str += ", "; str += ArgName;
3118 }
3119 // could be vararg.
3120 for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
3121 std::string ArgName = "arg"; ArgName += utostr(i);
3122 MsgExprs[i]->getType().getAsStringInternal(ArgName,
3123 Context->getPrintingPolicy());
3124 str += ", "; str += ArgName;
3125 }
3126
3127 str += ") {\n";
3128 str += "\t unsigned size = sizeof(";
3129 str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n";
3130
3131 str += "\t if (size == 1 || size == 2 || size == 4 || size == 8)\n";
3132
3133 str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());
3134 str += ")(void *)objc_msgSend)(receiver, sel";
3135 for (unsigned i = 2; i < ArgTypes.size(); i++) {
3136 str += ", arg"; str += utostr(i);
3137 }
3138 // could be vararg.
3139 for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
3140 str += ", arg"; str += utostr(i);
3141 }
3142 str+= ");\n";
3143
3144 str += "\t else if (receiver == 0)\n";
3145 str += "\t memset((void*)&s, 0, sizeof(s));\n";
3146 str += "\t else\n";
3147
3148 str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());
3149 str += ")(void *)objc_msgSend_stret)(receiver, sel";
3150 for (unsigned i = 2; i < ArgTypes.size(); i++) {
3151 str += ", arg"; str += utostr(i);
3152 }
3153 // could be vararg.
3154 for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {
3155 str += ", arg"; str += utostr(i);
3156 }
3157 str += ");\n";
3158
3159 str += "\t}\n";
3160 str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());
3161 str += " s;\n";
3162 str += "};\n};\n\n";
3163 SourceLocation FunLocStart;
3164 if (CurFunctionDef)
3165 FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
3166 else {
3167 assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null");
3168 FunLocStart = CurMethodDef->getBeginLoc();
3169 }
3170
3171 InsertText(FunLocStart, str);
3172 ++stretCount;
3173
3174 // AST for __Stretn(receiver, args).s;
3175 IdentifierInfo *ID = &Context->Idents.get(name);
3176 FunctionDecl *FD =
3177 FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(),
3178 ID, FuncType, nullptr, SC_Extern, false, false);
3179 DeclRefExpr *DRE = new (Context)
3180 DeclRefExpr(*Context, FD, false, castType, VK_PRValue, SourceLocation());
3181 CallExpr *STCE =
3182 CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue,
3183 SourceLocation(), FPOptionsOverride());
3184
3185 FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
3186 SourceLocation(),
3187 &Context->Idents.get("s"),
3188 returnType, nullptr,
3189 /*BitWidth=*/nullptr,
3190 /*Mutable=*/true, ICIS_NoInit);
3192 *Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary);
3193
3194 return ME;
3195}
3196
3197Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
3198 SourceLocation StartLoc,
3199 SourceLocation EndLoc) {
3200 if (!SelGetUidFunctionDecl)
3201 SynthSelGetUidFunctionDecl();
3202 if (!MsgSendFunctionDecl)
3203 SynthMsgSendFunctionDecl();
3204 if (!MsgSendSuperFunctionDecl)
3205 SynthMsgSendSuperFunctionDecl();
3206 if (!MsgSendStretFunctionDecl)
3207 SynthMsgSendStretFunctionDecl();
3208 if (!MsgSendSuperStretFunctionDecl)
3209 SynthMsgSendSuperStretFunctionDecl();
3210 if (!MsgSendFpretFunctionDecl)
3211 SynthMsgSendFpretFunctionDecl();
3212 if (!GetClassFunctionDecl)
3213 SynthGetClassFunctionDecl();
3214 if (!GetSuperClassFunctionDecl)
3215 SynthGetSuperClassFunctionDecl();
3216 if (!GetMetaClassFunctionDecl)
3217 SynthGetMetaClassFunctionDecl();
3218
3219 // default to objc_msgSend().
3220 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
3221 // May need to use objc_msgSend_stret() as well.
3222 FunctionDecl *MsgSendStretFlavor = nullptr;
3223 if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
3224 QualType resultType = mDecl->getReturnType();
3225 if (resultType->isRecordType())
3226 MsgSendStretFlavor = MsgSendStretFunctionDecl;
3227 else if (resultType->isRealFloatingType())
3228 MsgSendFlavor = MsgSendFpretFunctionDecl;
3229 }
3230
3231 // Synthesize a call to objc_msgSend().
3232 SmallVector<Expr*, 8> MsgExprs;
3233 switch (Exp->getReceiverKind()) {
3235 MsgSendFlavor = MsgSendSuperFunctionDecl;
3236 if (MsgSendStretFlavor)
3237 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
3238 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
3239
3240 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
3241
3242 SmallVector<Expr*, 4> InitExprs;
3243
3244 // set the receiver to self, the first argument to all methods.
3245 InitExprs.push_back(NoTypeInfoCStyleCastExpr(
3246 Context, Context->getObjCIdType(), CK_BitCast,
3247 new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
3248 Context->getObjCIdType(), VK_PRValue,
3249 SourceLocation()))); // set the 'receiver'.
3250
3251 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
3252 SmallVector<Expr*, 8> ClsExprs;
3253 ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
3254 // (Class)objc_getClass("CurrentClass")
3255 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
3256 ClsExprs, StartLoc, EndLoc);
3257 ClsExprs.clear();
3258 ClsExprs.push_back(Cls);
3259 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
3260 StartLoc, EndLoc);
3261
3262 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
3263 // To turn off a warning, type-cast to 'id'
3264 InitExprs.push_back( // set 'super class', using class_getSuperclass().
3265 NoTypeInfoCStyleCastExpr(Context,
3266 Context->getObjCIdType(),
3267 CK_BitCast, Cls));
3268 // struct __rw_objc_super
3269 QualType superType = getSuperStructType();
3270 Expr *SuperRep;
3271
3272 if (LangOpts.MicrosoftExt) {
3273 SynthSuperConstructorFunctionDecl();
3274 // Simulate a constructor call...
3275 DeclRefExpr *DRE = new (Context)
3276 DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
3277 VK_LValue, SourceLocation());
3278 SuperRep =
3279 CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
3280 SourceLocation(), FPOptionsOverride());
3281 // The code for super is a little tricky to prevent collision with
3282 // the structure definition in the header. The rewriter has it's own
3283 // internal definition (__rw_objc_super) that is uses. This is why
3284 // we need the cast below. For example:
3285 // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
3286 //
3287 SuperRep = UnaryOperator::Create(
3288 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
3289 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
3290 SourceLocation(), false, FPOptionsOverride());
3291 SuperRep = NoTypeInfoCStyleCastExpr(Context,
3292 Context->getPointerType(superType),
3293 CK_BitCast, SuperRep);
3294 } else {
3295 // (struct __rw_objc_super) { <exprs from above> }
3296 InitListExpr *ILE =
3297 new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
3298 SourceLocation(), /*isExplicit=*/true);
3299 TypeSourceInfo *superTInfo
3300 = Context->getTrivialTypeSourceInfo(superType);
3301 SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
3302 superType, VK_LValue,
3303 ILE, false);
3304 // struct __rw_objc_super *
3305 SuperRep = UnaryOperator::Create(
3306 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
3307 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
3308 SourceLocation(), false, FPOptionsOverride());
3309 }
3310 MsgExprs.push_back(SuperRep);
3311 break;
3312 }
3313
3315 SmallVector<Expr*, 8> ClsExprs;
3316 ObjCInterfaceDecl *Class
3317 = Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();
3318 IdentifierInfo *clsName = Class->getIdentifier();
3319 ClsExprs.push_back(getStringLiteral(clsName->getName()));
3320 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
3321 StartLoc, EndLoc);
3322 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
3323 Context->getObjCIdType(),
3324 CK_BitCast, Cls);
3325 MsgExprs.push_back(ArgExpr);
3326 break;
3327 }
3328
3330 MsgSendFlavor = MsgSendSuperFunctionDecl;
3331 if (MsgSendStretFlavor)
3332 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
3333 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
3334 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
3335 SmallVector<Expr*, 4> InitExprs;
3336
3337 InitExprs.push_back(NoTypeInfoCStyleCastExpr(
3338 Context, Context->getObjCIdType(), CK_BitCast,
3339 new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
3340 Context->getObjCIdType(), VK_PRValue,
3341 SourceLocation()))); // set the 'receiver'.
3342
3343 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
3344 SmallVector<Expr*, 8> ClsExprs;
3345 ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
3346 // (Class)objc_getClass("CurrentClass")
3347 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
3348 StartLoc, EndLoc);
3349 ClsExprs.clear();
3350 ClsExprs.push_back(Cls);
3351 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
3352 StartLoc, EndLoc);
3353
3354 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
3355 // To turn off a warning, type-cast to 'id'
3356 InitExprs.push_back(
3357 // set 'super class', using class_getSuperclass().
3358 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
3359 CK_BitCast, Cls));
3360 // struct __rw_objc_super
3361 QualType superType = getSuperStructType();
3362 Expr *SuperRep;
3363
3364 if (LangOpts.MicrosoftExt) {
3365 SynthSuperConstructorFunctionDecl();
3366 // Simulate a constructor call...
3367 DeclRefExpr *DRE = new (Context)
3368 DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
3369 VK_LValue, SourceLocation());
3370 SuperRep =
3371 CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
3372 SourceLocation(), FPOptionsOverride());
3373 // The code for super is a little tricky to prevent collision with
3374 // the structure definition in the header. The rewriter has it's own
3375 // internal definition (__rw_objc_super) that is uses. This is why
3376 // we need the cast below. For example:
3377 // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
3378 //
3379 SuperRep = UnaryOperator::Create(
3380 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
3381 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
3382 SourceLocation(), false, FPOptionsOverride());
3383 SuperRep = NoTypeInfoCStyleCastExpr(Context,
3384 Context->getPointerType(superType),
3385 CK_BitCast, SuperRep);
3386 } else {
3387 // (struct __rw_objc_super) { <exprs from above> }
3388 InitListExpr *ILE =
3389 new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
3390 SourceLocation(), /*isExplicit=*/true);
3391 TypeSourceInfo *superTInfo
3392 = Context->getTrivialTypeSourceInfo(superType);
3393 SuperRep = new (Context) CompoundLiteralExpr(
3394 SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);
3395 }
3396 MsgExprs.push_back(SuperRep);
3397 break;
3398 }
3399
3401 // Remove all type-casts because it may contain objc-style types; e.g.
3402 // Foo<Proto> *.
3403 Expr *recExpr = Exp->getInstanceReceiver();
3404 while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
3405 recExpr = CE->getSubExpr();
3406 CastKind CK = recExpr->getType()->isObjCObjectPointerType()
3407 ? CK_BitCast : recExpr->getType()->isBlockPointerType()
3408 ? CK_BlockPointerToObjCPointerCast
3409 : CK_CPointerToObjCPointerCast;
3410
3411 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
3412 CK, recExpr);
3413 MsgExprs.push_back(recExpr);
3414 break;
3415 }
3416 }
3417
3418 // Create a call to sel_registerName("selName"), it will be the 2nd argument.
3419 SmallVector<Expr*, 8> SelExprs;
3420 SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
3421 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
3422 SelExprs, StartLoc, EndLoc);
3423 MsgExprs.push_back(SelExp);
3424
3425 // Now push any user supplied arguments.
3426 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
3427 Expr *userExpr = Exp->getArg(i);
3428 // Make all implicit casts explicit...ICE comes in handy:-)
3429 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
3430 // Reuse the ICE type, it is exactly what the doctor ordered.
3431 QualType type = ICE->getType();
3432 if (needToScanForQualifiers(type))
3433 type = Context->getObjCIdType();
3434 // Make sure we convert "type (^)(...)" to "type (*)(...)".
3435 (void)convertBlockPointerToFunctionPointer(type);
3436 const Expr *SubExpr = ICE->IgnoreParenImpCasts();
3437 CastKind CK;
3438 if (SubExpr->getType()->isIntegralType(*Context) &&
3439 type->isBooleanType()) {
3440 CK = CK_IntegralToBoolean;
3441 } else if (type->isObjCObjectPointerType()) {
3442 if (SubExpr->getType()->isBlockPointerType()) {
3443 CK = CK_BlockPointerToObjCPointerCast;
3444 } else if (SubExpr->getType()->isPointerType()) {
3445 CK = CK_CPointerToObjCPointerCast;
3446 } else {
3447 CK = CK_BitCast;
3448 }
3449 } else {
3450 CK = CK_BitCast;
3451 }
3452
3453 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
3454 }
3455 // Make id<P...> cast into an 'id' cast.
3456 else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
3457 if (CE->getType()->isObjCQualifiedIdType()) {
3458 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
3459 userExpr = CE->getSubExpr();
3460 CastKind CK;
3461 if (userExpr->getType()->isIntegralType(*Context)) {
3462 CK = CK_IntegralToPointer;
3463 } else if (userExpr->getType()->isBlockPointerType()) {
3464 CK = CK_BlockPointerToObjCPointerCast;
3465 } else if (userExpr->getType()->isPointerType()) {
3466 CK = CK_CPointerToObjCPointerCast;
3467 } else {
3468 CK = CK_BitCast;
3469 }
3470 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
3471 CK, userExpr);
3472 }
3473 }
3474 MsgExprs.push_back(userExpr);
3475 // We've transferred the ownership to MsgExprs. For now, we *don't* null
3476 // out the argument in the original expression (since we aren't deleting
3477 // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
3478 //Exp->setArg(i, 0);
3479 }
3480 // Generate the funky cast.
3481 CastExpr *cast;
3482 SmallVector<QualType, 8> ArgTypes;
3483 QualType returnType;
3484
3485 // Push 'id' and 'SEL', the 2 implicit arguments.
3486 if (MsgSendFlavor == MsgSendSuperFunctionDecl)
3487 ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
3488 else
3489 ArgTypes.push_back(Context->getObjCIdType());
3490 ArgTypes.push_back(Context->getObjCSelType());
3491 if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
3492 // Push any user argument types.
3493 for (const auto *PI : OMD->parameters()) {
3494 QualType t = PI->getType()->isObjCQualifiedIdType()
3495 ? Context->getObjCIdType()
3496 : PI->getType();
3497 // Make sure we convert "t (^)(...)" to "t (*)(...)".
3498 (void)convertBlockPointerToFunctionPointer(t);
3499 ArgTypes.push_back(t);
3500 }
3501 returnType = Exp->getType();
3502 convertToUnqualifiedObjCType(returnType);
3503 (void)convertBlockPointerToFunctionPointer(returnType);
3504 } else {
3505 returnType = Context->getObjCIdType();
3506 }
3507 // Get the type, we will need to reference it in a couple spots.
3508 QualType msgSendType = MsgSendFlavor->getType();
3509
3510 // Create a reference to the objc_msgSend() declaration.
3511 DeclRefExpr *DRE = new (Context) DeclRefExpr(
3512 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
3513
3514 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
3515 // If we don't do this cast, we get the following bizarre warning/note:
3516 // xx.m:13: warning: function called through a non-compatible type
3517 // xx.m:13: note: if this code is reached, the program will abort
3518 cast = NoTypeInfoCStyleCastExpr(Context,
3519 Context->getPointerType(Context->VoidTy),
3520 CK_BitCast, DRE);
3521
3522 // Now do the "normal" pointer to function cast.
3523 // If we don't have a method decl, force a variadic cast.
3524 const ObjCMethodDecl *MD = Exp->getMethodDecl();
3525 QualType castType =
3526 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);
3527 castType = Context->getPointerType(castType);
3528 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
3529 cast);
3530
3531 // Don't forget the parens to enforce the proper binding.
3532 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
3533
3534 const FunctionType *FT = msgSendType->castAs<FunctionType>();
3535 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
3536 VK_PRValue, EndLoc, FPOptionsOverride());
3537 Stmt *ReplacingStmt = CE;
3538 if (MsgSendStretFlavor) {
3539 // We have the method which returns a struct/union. Must also generate
3540 // call to objc_msgSend_stret and hang both varieties on a conditional
3541 // expression which dictate which one to envoke depending on size of
3542 // method's return type.
3543
3544 Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
3545 returnType,
3546 ArgTypes, MsgExprs,
3547 Exp->getMethodDecl());
3548 ReplacingStmt = STCE;
3549 }
3550 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3551 return ReplacingStmt;
3552}
3553
3554Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
3555 Stmt *ReplacingStmt =
3556 SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());
3557
3558 // Now do the actual rewrite.
3559 ReplaceStmt(Exp, ReplacingStmt);
3560
3561 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3562 return ReplacingStmt;
3563}
3564
3565// typedef struct objc_object Protocol;
3566QualType RewriteModernObjC::getProtocolType() {
3567 if (!ProtocolTypeDecl) {
3568 TypeSourceInfo *TInfo
3569 = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
3570 ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
3571 SourceLocation(), SourceLocation(),
3572 &Context->Idents.get("Protocol"),
3573 TInfo);
3574 }
3575 return Context->getTypeDeclType(ProtocolTypeDecl);
3576}
3577
3578/// RewriteObjCProtocolExpr - Rewrite a protocol expression into
3579/// a synthesized/forward data reference (to the protocol's metadata).
3580/// The forward references (and metadata) are generated in
3581/// RewriteModernObjC::HandleTranslationUnit().
3582Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
3583 std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +
3584 Exp->getProtocol()->getNameAsString();
3585 IdentifierInfo *ID = &Context->Idents.get(Name);
3586 VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
3587 SourceLocation(), ID, getProtocolType(),
3588 nullptr, SC_Extern);
3589 DeclRefExpr *DRE = new (Context) DeclRefExpr(
3590 *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());
3591 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(
3592 Context, Context->getPointerType(DRE->getType()), CK_BitCast, DRE);
3593 ReplaceStmt(Exp, castExpr);
3594 ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
3595 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3596 return castExpr;
3597}
3598
3599/// IsTagDefinedInsideClass - This routine checks that a named tagged type
3600/// is defined inside an objective-c class. If so, it returns true.
3601bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,
3602 TagDecl *Tag,
3603 bool &IsNamedDefinition) {
3604 if (!IDecl)
3605 return false;
3606 SourceLocation TagLocation;
3607 if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) {
3608 RD = RD->getDefinition();
3609 if (!RD || !RD->getDeclName().getAsIdentifierInfo())
3610 return false;
3611 IsNamedDefinition = true;
3612 TagLocation = RD->getLocation();
3613 return Context->getSourceManager().isBeforeInTranslationUnit(
3614 IDecl->getLocation(), TagLocation);
3615 }
3616 if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) {
3617 if (!ED || !ED->getDeclName().getAsIdentifierInfo())
3618 return false;
3619 IsNamedDefinition = true;
3620 TagLocation = ED->getLocation();
3621 return Context->getSourceManager().isBeforeInTranslationUnit(
3622 IDecl->getLocation(), TagLocation);
3623 }
3624 return false;
3625}
3626
3627/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer.
3628/// It handles elaborated types, as well as enum types in the process.
3629bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,
3630 std::string &Result) {
3631 if (Type->getAs<TypedefType>()) {
3632 Result += "\t";
3633 return false;
3634 }
3635
3636 if (Type->isArrayType()) {
3637 QualType ElemTy = Context->getBaseElementType(Type);
3638 return RewriteObjCFieldDeclType(ElemTy, Result);
3639 }
3640 else if (Type->isRecordType()) {
3641 auto *RD = Type->castAsRecordDecl();
3642 if (RD->isCompleteDefinition()) {
3643 if (RD->isStruct())
3644 Result += "\n\tstruct ";
3645 else if (RD->isUnion())
3646 Result += "\n\tunion ";
3647 else
3648 assert(false && "class not allowed as an ivar type");
3649
3650 Result += RD->getName();
3651 if (GlobalDefinedTags.count(RD)) {
3652 // struct/union is defined globally, use it.
3653 Result += " ";
3654 return true;
3655 }
3656 Result += " {\n";
3657 for (auto *FD : RD->fields())
3658 RewriteObjCFieldDecl(FD, Result);
3659 Result += "\t} ";
3660 return true;
3661 }
3662 } else if (auto *ED = Type->getAsEnumDecl();
3663 ED && ED->isCompleteDefinition()) {
3664 Result += "\n\tenum ";
3665 Result += ED->getName();
3666 if (GlobalDefinedTags.count(ED)) {
3667 // Enum is globall defined, use it.
3668 Result += " ";
3669 return true;
3670 }
3671
3672 Result += " {\n";
3673 for (const auto *EC : ED->enumerators()) {
3674 Result += "\t";
3675 Result += EC->getName();
3676 Result += " = ";
3677 Result += toString(EC->getInitVal(), 10);
3678 Result += ",\n";
3679 }
3680 Result += "\t} ";
3681 return true;
3682 }
3683
3684 Result += "\t";
3685 convertObjCTypeToCStyleType(Type);
3686 return false;
3687}
3688
3689
3690/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer.
3691/// It handles elaborated types, as well as enum types in the process.
3692void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
3693 std::string &Result) {
3694 QualType Type = fieldDecl->getType();
3695 std::string Name = fieldDecl->getNameAsString();
3696
3697 bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);
3698 if (!EleboratedType)
3699 Type.getAsStringInternal(Name, Context->getPrintingPolicy());
3700 Result += Name;
3701 if (fieldDecl->isBitField()) {
3702 Result += " : ";
3703 Result += utostr(fieldDecl->getBitWidthValue());
3704 }
3705 else if (EleboratedType && Type->isArrayType()) {
3706 const ArrayType *AT = Context->getAsArrayType(Type);
3707 do {
3708 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {
3709 Result += "[";
3710 llvm::APInt Dim = CAT->getSize();
3711 Result += utostr(Dim.getZExtValue());
3712 Result += "]";
3713 }
3714 AT = Context->getAsArrayType(AT->getElementType());
3715 } while (AT);
3716 }
3717
3718 Result += ";\n";
3719}
3720
3721/// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined
3722/// named aggregate types into the input buffer.
3723void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
3724 std::string &Result) {
3725 QualType Type = fieldDecl->getType();
3726 if (Type->getAs<TypedefType>())
3727 return;
3728 if (Type->isArrayType())
3729 Type = Context->getBaseElementType(Type);
3730
3731 auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());
3732
3733 if (auto *TD = Type->getAsTagDecl()) {
3734 if (GlobalDefinedTags.count(TD))
3735 return;
3736
3737 bool IsNamedDefinition = false;
3738 if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {
3739 RewriteObjCFieldDeclType(Type, Result);
3740 Result += ";";
3741 }
3742 if (IsNamedDefinition)
3743 GlobalDefinedTags.insert(TD);
3744 }
3745}
3746
3747unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) {
3748 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3749 if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) {
3750 return IvarGroupNumber[IV];
3751 }
3752 unsigned GroupNo = 0;
3754 for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
3755 IVD; IVD = IVD->getNextIvar())
3756 IVars.push_back(IVD);
3757
3758 for (unsigned i = 0, e = IVars.size(); i < e; i++)
3759 if (IVars[i]->isBitField()) {
3760 IvarGroupNumber[IVars[i++]] = ++GroupNo;
3761 while (i < e && IVars[i]->isBitField())
3762 IvarGroupNumber[IVars[i++]] = GroupNo;
3763 if (i < e)
3764 --i;
3765 }
3766
3767 ObjCInterefaceHasBitfieldGroups.insert(CDecl);
3768 return IvarGroupNumber[IV];
3769}
3770
3771QualType RewriteModernObjC::SynthesizeBitfieldGroupStructType(
3772 ObjCIvarDecl *IV,
3774 std::string StructTagName;
3775 ObjCIvarBitfieldGroupType(IV, StructTagName);
3777 *Context, TagTypeKind::Struct, Context->getTranslationUnitDecl(),
3778 SourceLocation(), SourceLocation(), &Context->Idents.get(StructTagName));
3779 for (unsigned i=0, e = IVars.size(); i < e; i++) {
3780 ObjCIvarDecl *Ivar = IVars[i];
3781 RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(),
3782 &Context->Idents.get(Ivar->getName()),
3783 Ivar->getType(),
3784 nullptr, /*Expr *BW */Ivar->getBitWidth(),
3785 false, ICIS_NoInit));
3786 }
3787 RD->completeDefinition();
3788 return Context->getCanonicalTagType(RD);
3789}
3790
3791QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) {
3792 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3793 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3794 std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo);
3795 if (auto It = GroupRecordType.find(tuple); It != GroupRecordType.end())
3796 return It->second;
3797
3799 for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
3800 IVD; IVD = IVD->getNextIvar()) {
3801 if (IVD->isBitField())
3802 IVars.push_back(const_cast<ObjCIvarDecl *>(IVD));
3803 else {
3804 if (!IVars.empty()) {
3805 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);
3806 // Generate the struct type for this group of bitfield ivars.
3807 GroupRecordType[std::make_pair(CDecl, GroupNo)] =
3808 SynthesizeBitfieldGroupStructType(IVars[0], IVars);
3809 IVars.clear();
3810 }
3811 }
3812 }
3813 if (!IVars.empty()) {
3814 // Do the last one.
3815 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);
3816 GroupRecordType[std::make_pair(CDecl, GroupNo)] =
3817 SynthesizeBitfieldGroupStructType(IVars[0], IVars);
3818 }
3819 QualType RetQT = GroupRecordType[tuple];
3820 assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL");
3821
3822 return RetQT;
3823}
3824
3825/// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group.
3826/// Name would be: classname__GRBF_n where n is the group number for this ivar.
3827void RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV,
3828 std::string &Result) {
3829 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3830 Result += CDecl->getName();
3831 Result += "__GRBF_";
3832 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3833 Result += utostr(GroupNo);
3834}
3835
3836/// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group.
3837/// Name of the struct would be: classname__T_n where n is the group number for
3838/// this ivar.
3839void RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV,
3840 std::string &Result) {
3841 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3842 Result += CDecl->getName();
3843 Result += "__T_";
3844 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3845 Result += utostr(GroupNo);
3846}
3847
3848/// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset.
3849/// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for
3850/// this ivar.
3851void RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV,
3852 std::string &Result) {
3853 Result += "OBJC_IVAR_$_";
3854 ObjCIvarBitfieldGroupDecl(IV, Result);
3855}
3856
3857#define SKIP_BITFIELDS(IX, ENDIX, VEC) { \
3858 while ((IX < ENDIX) && VEC[IX]->isBitField()) \
3859 ++IX; \
3860 if (IX < ENDIX) \
3861 --IX; \
3862}
3863
3864/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
3865/// an objective-c class with ivars.
3866void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
3867 std::string &Result) {
3868 assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
3869 assert(CDecl->getName() != "" &&
3870 "Name missing in SynthesizeObjCInternalStruct");
3871 ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
3873 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
3874 IVD; IVD = IVD->getNextIvar())
3875 IVars.push_back(IVD);
3876
3877 SourceLocation LocStart = CDecl->getBeginLoc();
3878 SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
3879
3880 const char *startBuf = SM->getCharacterData(LocStart);
3881 const char *endBuf = SM->getCharacterData(LocEnd);
3882
3883 // If no ivars and no root or if its root, directly or indirectly,
3884 // have no ivars (thus not synthesized) then no need to synthesize this class.
3885 if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&
3886 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3887 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3888 ReplaceText(LocStart, endBuf-startBuf, Result);
3889 return;
3890 }
3891
3892 // Insert named struct/union definitions inside class to
3893 // outer scope. This follows semantics of locally defined
3894 // struct/unions in objective-c classes.
3895 for (unsigned i = 0, e = IVars.size(); i < e; i++)
3896 RewriteLocallyDefinedNamedAggregates(IVars[i], Result);
3897
3898 // Insert named structs which are syntheized to group ivar bitfields
3899 // to outer scope as well.
3900 for (unsigned i = 0, e = IVars.size(); i < e; i++)
3901 if (IVars[i]->isBitField()) {
3902 ObjCIvarDecl *IV = IVars[i];
3903 QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV);
3904 RewriteObjCFieldDeclType(QT, Result);
3905 Result += ";";
3906 // skip over ivar bitfields in this group.
3907 SKIP_BITFIELDS(i , e, IVars);
3908 }
3909
3910 Result += "\nstruct ";
3911 Result += CDecl->getNameAsString();
3912 Result += "_IMPL {\n";
3913
3914 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
3915 Result += "\tstruct "; Result += RCDecl->getNameAsString();
3916 Result += "_IMPL "; Result += RCDecl->getNameAsString();
3917 Result += "_IVARS;\n";
3918 }
3919
3920 for (unsigned i = 0, e = IVars.size(); i < e; i++) {
3921 if (IVars[i]->isBitField()) {
3922 ObjCIvarDecl *IV = IVars[i];
3923 Result += "\tstruct ";
3924 ObjCIvarBitfieldGroupType(IV, Result); Result += " ";
3925 ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n";
3926 // skip over ivar bitfields in this group.
3927 SKIP_BITFIELDS(i , e, IVars);
3928 }
3929 else
3930 RewriteObjCFieldDecl(IVars[i], Result);
3931 }
3932
3933 Result += "};\n";
3934 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3935 ReplaceText(LocStart, endBuf-startBuf, Result);
3936 // Mark this struct as having been generated.
3937 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3938 llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct");
3939}
3940
3941/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which
3942/// have been referenced in an ivar access expression.
3943void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
3944 std::string &Result) {
3945 // write out ivar offset symbols which have been referenced in an ivar
3946 // access expression.
3947 llvm::SmallSetVector<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl];
3948
3949 if (Ivars.empty())
3950 return;
3951
3952 llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput;
3953 for (ObjCIvarDecl *IvarDecl : Ivars) {
3954 const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface();
3955 unsigned GroupNo = 0;
3956 if (IvarDecl->isBitField()) {
3957 GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl);
3958 if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo)))
3959 continue;
3960 }
3961 Result += "\n";
3962 if (LangOpts.MicrosoftExt)
3963 Result += "__declspec(allocate(\".objc_ivar$B\")) ";
3964 Result += "extern \"C\" ";
3965 if (LangOpts.MicrosoftExt &&
3966 IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&
3968 Result += "__declspec(dllimport) ";
3969
3970 Result += "unsigned long ";
3971 if (IvarDecl->isBitField()) {
3972 ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
3973 GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo));
3974 }
3975 else
3976 WriteInternalIvarName(CDecl, IvarDecl, Result);
3977 Result += ";";
3978 }
3979}
3980
3981//===----------------------------------------------------------------------===//
3982// Meta Data Emission
3983//===----------------------------------------------------------------------===//
3984
3985/// RewriteImplementations - This routine rewrites all method implementations
3986/// and emits meta-data.
3987
3988void RewriteModernObjC::RewriteImplementations() {
3989 int ClsDefCount = ClassImplementation.size();
3990 int CatDefCount = CategoryImplementation.size();
3991
3992 // Rewrite implemented methods
3993 for (int i = 0; i < ClsDefCount; i++) {
3994 ObjCImplementationDecl *OIMP = ClassImplementation[i];
3995 ObjCInterfaceDecl *CDecl = OIMP->getClassInterface();
3996 if (CDecl->isImplicitInterfaceDecl())
3997 assert(false &&
3998 "Legacy implicit interface rewriting not supported in moder abi");
3999 RewriteImplementationDecl(OIMP);
4000 }
4001
4002 for (int i = 0; i < CatDefCount; i++) {
4003 ObjCCategoryImplDecl *CIMP = CategoryImplementation[i];
4004 ObjCInterfaceDecl *CDecl = CIMP->getClassInterface();
4005 if (CDecl->isImplicitInterfaceDecl())
4006 assert(false &&
4007 "Legacy implicit interface rewriting not supported in moder abi");
4008 RewriteImplementationDecl(CIMP);
4009 }
4010}
4011
4012void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,
4013 const std::string &Name,
4014 ValueDecl *VD, bool def) {
4015 assert(BlockByRefDeclNo.count(VD) &&
4016 "RewriteByRefString: ByRef decl missing");
4017 if (def)
4018 ResultStr += "struct ";
4019 ResultStr += "__Block_byref_" + Name +
4020 "_" + utostr(BlockByRefDeclNo[VD]) ;
4021}
4022
4023static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
4024 if (VarDecl *Var = dyn_cast<VarDecl>(VD))
4025 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
4026 return false;
4027}
4028
4029std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
4030 StringRef funcName,
4031 const std::string &Tag) {
4032 const FunctionType *AFT = CE->getFunctionType();
4033 QualType RT = AFT->getReturnType();
4034 std::string StructRef = "struct " + Tag;
4035 SourceLocation BlockLoc = CE->getExprLoc();
4036 std::string S;
4037 ConvertSourceLocationToLineDirective(BlockLoc, S);
4038
4039 S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
4040 funcName.str() + "_block_func_" + utostr(i);
4041
4042 BlockDecl *BD = CE->getBlockDecl();
4043
4044 if (isa<FunctionNoProtoType>(AFT)) {
4045 // No user-supplied arguments. Still need to pass in a pointer to the
4046 // block (to reference imported block decl refs).
4047 S += "(" + StructRef + " *__cself)";
4048 } else if (BD->param_empty()) {
4049 S += "(" + StructRef + " *__cself)";
4050 } else {
4052 assert(FT && "SynthesizeBlockFunc: No function proto");
4053 S += '(';
4054 // first add the implicit argument.
4055 S += StructRef + " *__cself, ";
4056 std::string ParamStr;
4057 for (BlockDecl::param_iterator AI = BD->param_begin(),
4058 E = BD->param_end(); AI != E; ++AI) {
4059 if (AI != BD->param_begin()) S += ", ";
4060 ParamStr = (*AI)->getNameAsString();
4061 QualType QT = (*AI)->getType();
4062 (void)convertBlockPointerToFunctionPointer(QT);
4063 QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
4064 S += ParamStr;
4065 }
4066 if (FT->isVariadic()) {
4067 if (!BD->param_empty()) S += ", ";
4068 S += "...";
4069 }
4070 S += ')';
4071 }
4072 S += " {\n";
4073
4074 // Create local declarations to avoid rewriting all closure decl ref exprs.
4075 // First, emit a declaration for all "by ref" decls.
4076 for (ValueDecl *VD : BlockByRefDecls) {
4077 S += " ";
4078 std::string Name = VD->getNameAsString();
4079 std::string TypeString;
4080 RewriteByRefString(TypeString, Name, VD);
4081 TypeString += " *";
4082 Name = TypeString + Name;
4083 S += Name + " = __cself->" + VD->getNameAsString() + "; // bound by ref\n";
4084 }
4085 // Next, emit a declaration for all "by copy" declarations.
4086 for (ValueDecl *VD : BlockByCopyDecls) {
4087 S += " ";
4088 // Handle nested closure invocation. For example:
4089 //
4090 // void (^myImportedClosure)(void);
4091 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
4092 //
4093 // void (^anotherClosure)(void);
4094 // anotherClosure = ^(void) {
4095 // myImportedClosure(); // import and invoke the closure
4096 // };
4097 //
4098 if (isTopLevelBlockPointerType(VD->getType())) {
4099 RewriteBlockPointerTypeVariable(S, VD);
4100 S += " = (";
4101 RewriteBlockPointerType(S, VD->getType());
4102 S += ")";
4103 S += "__cself->" + VD->getNameAsString() + "; // bound by copy\n";
4104 } else {
4105 std::string Name = VD->getNameAsString();
4106 QualType QT = VD->getType();
4107 if (HasLocalVariableExternalStorage(VD))
4108 QT = Context->getPointerType(QT);
4109 QT.getAsStringInternal(Name, Context->getPrintingPolicy());
4110 S += Name + " = __cself->" + VD->getNameAsString() +
4111 "; // bound by copy\n";
4112 }
4113 }
4114 std::string RewrittenStr = RewrittenBlockExprs[CE];
4115 const char *cstr = RewrittenStr.c_str();
4116 while (*cstr++ != '{') ;
4117 S += cstr;
4118 S += "\n";
4119 return S;
4120}
4121
4122std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(
4123 BlockExpr *CE, int i, StringRef funcName, const std::string &Tag) {
4124 std::string StructRef = "struct " + Tag;
4125 std::string S = "static void __";
4126
4127 S += funcName;
4128 S += "_block_copy_" + utostr(i);
4129 S += "(" + StructRef;
4130 S += "*dst, " + StructRef;
4131 S += "*src) {";
4132 for (ValueDecl *VD : ImportedBlockDecls) {
4133 S += "_Block_object_assign((void*)&dst->";
4134 S += VD->getNameAsString();
4135 S += ", (void*)src->";
4136 S += VD->getNameAsString();
4137 if (BlockByRefDecls.count(VD))
4138 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
4139 else if (VD->getType()->isBlockPointerType())
4140 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
4141 else
4142 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
4143 }
4144 S += "}\n";
4145
4146 S += "\nstatic void __";
4147 S += funcName;
4148 S += "_block_dispose_" + utostr(i);
4149 S += "(" + StructRef;
4150 S += "*src) {";
4151 for (ValueDecl *VD : ImportedBlockDecls) {
4152 S += "_Block_object_dispose((void*)src->";
4153 S += VD->getNameAsString();
4154 if (BlockByRefDecls.count(VD))
4155 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
4156 else if (VD->getType()->isBlockPointerType())
4157 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
4158 else
4159 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
4160 }
4161 S += "}\n";
4162 return S;
4163}
4164
4165std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE,
4166 const std::string &Tag,
4167 const std::string &Desc) {
4168 std::string S = "\nstruct " + Tag;
4169 std::string Constructor = " " + Tag;
4170
4171 S += " {\n struct __block_impl impl;\n";
4172 S += " struct " + Desc;
4173 S += "* Desc;\n";
4174
4175 Constructor += "(void *fp, "; // Invoke function pointer.
4176 Constructor += "struct " + Desc; // Descriptor pointer.
4177 Constructor += " *desc";
4178
4179 if (BlockDeclRefs.size()) {
4180 // Output all "by copy" declarations.
4181 for (ValueDecl *VD : BlockByCopyDecls) {
4182 S += " ";
4183 std::string FieldName = VD->getNameAsString();
4184 std::string ArgName = "_" + FieldName;
4185 // Handle nested closure invocation. For example:
4186 //
4187 // void (^myImportedBlock)(void);
4188 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
4189 //
4190 // void (^anotherBlock)(void);
4191 // anotherBlock = ^(void) {
4192 // myImportedBlock(); // import and invoke the closure
4193 // };
4194 //
4195 if (isTopLevelBlockPointerType(VD->getType())) {
4196 S += "struct __block_impl *";
4197 Constructor += ", void *" + ArgName;
4198 } else {
4199 QualType QT = VD->getType();
4200 if (HasLocalVariableExternalStorage(VD))
4201 QT = Context->getPointerType(QT);
4202 QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
4203 QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
4204 Constructor += ", " + ArgName;
4205 }
4206 S += FieldName + ";\n";
4207 }
4208 // Output all "by ref" declarations.
4209 for (ValueDecl *VD : BlockByRefDecls) {
4210 S += " ";
4211 std::string FieldName = VD->getNameAsString();
4212 std::string ArgName = "_" + FieldName;
4213 {
4214 std::string TypeString;
4215 RewriteByRefString(TypeString, FieldName, VD);
4216 TypeString += " *";
4217 FieldName = TypeString + FieldName;
4218 ArgName = TypeString + ArgName;
4219 Constructor += ", " + ArgName;
4220 }
4221 S += FieldName + "; // by ref\n";
4222 }
4223 // Finish writing the constructor.
4224 Constructor += ", int flags=0)";
4225 // Initialize all "by copy" arguments.
4226 bool firsTime = true;
4227 for (const ValueDecl *VD : BlockByCopyDecls) {
4228 std::string Name = VD->getNameAsString();
4229 if (firsTime) {
4230 Constructor += " : ";
4231 firsTime = false;
4232 } else
4233 Constructor += ", ";
4234 if (isTopLevelBlockPointerType(VD->getType()))
4235 Constructor += Name + "((struct __block_impl *)_" + Name + ")";
4236 else
4237 Constructor += Name + "(_" + Name + ")";
4238 }
4239 // Initialize all "by ref" arguments.
4240 for (const ValueDecl *VD : BlockByRefDecls) {
4241 std::string Name = VD->getNameAsString();
4242 if (firsTime) {
4243 Constructor += " : ";
4244 firsTime = false;
4245 }
4246 else
4247 Constructor += ", ";
4248 Constructor += Name + "(_" + Name + "->__forwarding)";
4249 }
4250
4251 Constructor += " {\n";
4252 if (GlobalVarDecl)
4253 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
4254 else
4255 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
4256 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
4257
4258 Constructor += " Desc = desc;\n";
4259 } else {
4260 // Finish writing the constructor.
4261 Constructor += ", int flags=0) {\n";
4262 if (GlobalVarDecl)
4263 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
4264 else
4265 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
4266 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
4267 Constructor += " Desc = desc;\n";
4268 }
4269 Constructor += " ";
4270 Constructor += "}\n";
4271 S += Constructor;
4272 S += "};\n";
4273 return S;
4274}
4275
4276std::string RewriteModernObjC::SynthesizeBlockDescriptor(
4277 const std::string &DescTag, const std::string &ImplTag, int i,
4278 StringRef FunName, unsigned hasCopy) {
4279 std::string S = "\nstatic struct " + DescTag;
4280
4281 S += " {\n size_t reserved;\n";
4282 S += " size_t Block_size;\n";
4283 if (hasCopy) {
4284 S += " void (*copy)(struct ";
4285 S += ImplTag; S += "*, struct ";
4286 S += ImplTag; S += "*);\n";
4287
4288 S += " void (*dispose)(struct ";
4289 S += ImplTag; S += "*);\n";
4290 }
4291 S += "} ";
4292
4293 S += DescTag + "_DATA = { 0, sizeof(struct ";
4294 S += ImplTag + ")";
4295 if (hasCopy) {
4296 S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
4297 S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
4298 }
4299 S += "};\n";
4300 return S;
4301}
4302
4303void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
4304 StringRef FunName) {
4305 bool RewriteSC = (GlobalVarDecl &&
4306 !Blocks.empty() &&
4307 GlobalVarDecl->getStorageClass() == SC_Static &&
4308 GlobalVarDecl->getType().getCVRQualifiers());
4309 if (RewriteSC) {
4310 std::string SC(" void __");
4311 SC += GlobalVarDecl->getNameAsString();
4312 SC += "() {}";
4313 InsertText(FunLocStart, SC);
4314 }
4315
4316 // Insert closures that were part of the function.
4317 for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
4318 CollectBlockDeclRefInfo(Blocks[i]);
4319 // Need to copy-in the inner copied-in variables not actually used in this
4320 // block.
4321 for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
4322 DeclRefExpr *Exp = InnerDeclRefs[count++];
4323 ValueDecl *VD = Exp->getDecl();
4324 BlockDeclRefs.push_back(Exp);
4325 if (!VD->hasAttr<BlocksAttr>()) {
4326 BlockByCopyDecls.insert(VD);
4327 continue;
4328 }
4329
4330 BlockByRefDecls.insert(VD);
4331
4332 // imported objects in the inner blocks not used in the outer
4333 // blocks must be copied/disposed in the outer block as well.
4334 if (VD->getType()->isObjCObjectPointerType() ||
4335 VD->getType()->isBlockPointerType())
4336 ImportedBlockDecls.insert(VD);
4337 }
4338
4339 std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
4340 std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
4341
4342 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
4343
4344 InsertText(FunLocStart, CI);
4345
4346 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
4347
4348 InsertText(FunLocStart, CF);
4349
4350 if (ImportedBlockDecls.size()) {
4351 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
4352 InsertText(FunLocStart, HF);
4353 }
4354 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
4355 ImportedBlockDecls.size() > 0);
4356 InsertText(FunLocStart, BD);
4357
4358 BlockDeclRefs.clear();
4359 BlockByRefDecls.clear();
4360 BlockByCopyDecls.clear();
4361 ImportedBlockDecls.clear();
4362 }
4363 if (RewriteSC) {
4364 // Must insert any 'const/volatile/static here. Since it has been
4365 // removed as result of rewriting of block literals.
4366 std::string SC;
4367 if (GlobalVarDecl->getStorageClass() == SC_Static)
4368 SC = "static ";
4369 if (GlobalVarDecl->getType().isConstQualified())
4370 SC += "const ";
4371 if (GlobalVarDecl->getType().isVolatileQualified())
4372 SC += "volatile ";
4373 if (GlobalVarDecl->getType().isRestrictQualified())
4374 SC += "restrict ";
4375 InsertText(FunLocStart, SC);
4376 }
4377 if (GlobalConstructionExp) {
4378 // extra fancy dance for global literal expression.
4379
4380 // Always the latest block expression on the block stack.
4381 std::string Tag = "__";
4382 Tag += FunName;
4383 Tag += "_block_impl_";
4384 Tag += utostr(Blocks.size()-1);
4385 std::string globalBuf = "static ";
4386 globalBuf += Tag; globalBuf += " ";
4387 std::string SStr;
4388
4389 llvm::raw_string_ostream constructorExprBuf(SStr);
4390 GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,
4391 PrintingPolicy(LangOpts));
4392 globalBuf += SStr;
4393 globalBuf += ";\n";
4394 InsertText(FunLocStart, globalBuf);
4395 GlobalConstructionExp = nullptr;
4396 }
4397
4398 Blocks.clear();
4399 InnerDeclRefsCount.clear();
4400 InnerDeclRefs.clear();
4401 RewrittenBlockExprs.clear();
4402}
4403
4404void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
4405 SourceLocation FunLocStart =
4406 (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD)
4407 : FD->getTypeSpecStartLoc();
4408 StringRef FuncName = FD->getName();
4409
4410 SynthesizeBlockLiterals(FunLocStart, FuncName);
4411}
4412
4413static void BuildUniqueMethodName(std::string &Name,
4414 ObjCMethodDecl *MD) {
4415 ObjCInterfaceDecl *IFace = MD->getClassInterface();
4416 Name = std::string(IFace->getName());
4417 Name += "__" + MD->getSelector().getAsString();
4418 // Convert colons to underscores.
4419 std::string::size_type loc = 0;
4420 while ((loc = Name.find(':', loc)) != std::string::npos)
4421 Name.replace(loc, 1, "_");
4422}
4423
4424void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
4425 // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
4426 // SourceLocation FunLocStart = MD->getBeginLoc();
4427 SourceLocation FunLocStart = MD->getBeginLoc();
4428 std::string FuncName;
4429 BuildUniqueMethodName(FuncName, MD);
4430 SynthesizeBlockLiterals(FunLocStart, FuncName);
4431}
4432
4433void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
4434 for (Stmt *SubStmt : S->children())
4435 if (SubStmt) {
4436 if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
4437 GetBlockDeclRefExprs(CBE->getBody());
4438 else
4439 GetBlockDeclRefExprs(SubStmt);
4440 }
4441 // Handle specific things.
4442 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
4444 HasLocalVariableExternalStorage(DRE->getDecl()))
4445 // FIXME: Handle enums.
4446 BlockDeclRefs.push_back(DRE);
4447}
4448
4449void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,
4450 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
4451 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
4452 for (Stmt *SubStmt : S->children())
4453 if (SubStmt) {
4454 if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
4455 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
4456 GetInnerBlockDeclRefExprs(CBE->getBody(),
4457 InnerBlockDeclRefs,
4458 InnerContexts);
4459 }
4460 else
4461 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
4462 }
4463 // Handle specific things.
4464 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4466 HasLocalVariableExternalStorage(DRE->getDecl())) {
4467 if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
4468 InnerBlockDeclRefs.push_back(DRE);
4469 if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
4470 if (Var->isFunctionOrMethodVarDecl())
4471 ImportedLocalExternalDecls.insert(Var);
4472 }
4473 }
4474}
4475
4476/// convertObjCTypeToCStyleType - This routine converts such objc types
4477/// as qualified objects, and blocks to their closest c/c++ types that
4478/// it can. It returns true if input type was modified.
4479bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {
4480 QualType oldT = T;
4481 convertBlockPointerToFunctionPointer(T);
4482 if (T->isFunctionPointerType()) {
4483 QualType PointeeTy;
4484 if (const PointerType* PT = T->getAs<PointerType>()) {
4485 PointeeTy = PT->getPointeeType();
4486 if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
4487 T = convertFunctionTypeOfBlocks(FT);
4488 T = Context->getPointerType(T);
4489 }
4490 }
4491 }
4492
4493 convertToUnqualifiedObjCType(T);
4494 return T != oldT;
4495}
4496
4497/// convertFunctionTypeOfBlocks - This routine converts a function type
4498/// whose result type may be a block pointer or whose argument type(s)
4499/// might be block pointers to an equivalent function type replacing
4500/// all block pointers to function pointers.
4501QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
4502 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
4503 // FTP will be null for closures that don't take arguments.
4504 // Generate a funky cast.
4505 SmallVector<QualType, 8> ArgTypes;
4506 QualType Res = FT->getReturnType();
4507 bool modified = convertObjCTypeToCStyleType(Res);
4508
4509 if (FTP) {
4510 for (auto &I : FTP->param_types()) {
4511 QualType t = I;
4512 // Make sure we convert "t (^)(...)" to "t (*)(...)".
4513 if (convertObjCTypeToCStyleType(t))
4514 modified = true;
4515 ArgTypes.push_back(t);
4516 }
4517 }
4518 QualType FuncType;
4519 if (modified)
4520 FuncType = getSimpleFunctionType(Res, ArgTypes);
4521 else FuncType = QualType(FT, 0);
4522 return FuncType;
4523}
4524
4525Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
4526 // Navigate to relevant type information.
4527 const BlockPointerType *CPT = nullptr;
4528
4529 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
4530 CPT = DRE->getType()->getAs<BlockPointerType>();
4531 } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
4532 CPT = MExpr->getType()->getAs<BlockPointerType>();
4533 }
4534 else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
4535 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
4536 }
4537 else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
4538 CPT = IEXPR->getType()->getAs<BlockPointerType>();
4539 else if (const ConditionalOperator *CEXPR =
4540 dyn_cast<ConditionalOperator>(BlockExp)) {
4541 Expr *LHSExp = CEXPR->getLHS();
4542 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
4543 Expr *RHSExp = CEXPR->getRHS();
4544 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
4545 Expr *CONDExp = CEXPR->getCond();
4546 ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
4547 CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
4548 cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
4549 return CondExpr;
4550 } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
4551 CPT = IRE->getType()->getAs<BlockPointerType>();
4552 } else if (const PseudoObjectExpr *POE
4553 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
4554 CPT = POE->getType()->castAs<BlockPointerType>();
4555 } else {
4556 assert(false && "RewriteBlockClass: Bad type");
4557 }
4558 assert(CPT && "RewriteBlockClass: Bad type");
4559 const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
4560 assert(FT && "RewriteBlockClass: Bad type");
4561 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
4562 // FTP will be null for closures that don't take arguments.
4563
4564 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
4565 SourceLocation(), SourceLocation(),
4566 &Context->Idents.get("__block_impl"));
4567 QualType PtrBlock = Context->getPointerType(Context->getCanonicalTagType(RD));
4568
4569 // Generate a funky cast.
4570 SmallVector<QualType, 8> ArgTypes;
4571
4572 // Push the block argument type.
4573 ArgTypes.push_back(PtrBlock);
4574 if (FTP) {
4575 for (auto &I : FTP->param_types()) {
4576 QualType t = I;
4577 // Make sure we convert "t (^)(...)" to "t (*)(...)".
4578 if (!convertBlockPointerToFunctionPointer(t))
4579 convertToUnqualifiedObjCType(t);
4580 ArgTypes.push_back(t);
4581 }
4582 }
4583 // Now do the pointer to function cast.
4584 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);
4585
4586 PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
4587
4588 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
4589 CK_BitCast,
4590 const_cast<Expr*>(BlockExp));
4591 // Don't forget the parens to enforce the proper binding.
4592 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
4593 BlkCast);
4594 //PE->dump();
4595
4596 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
4597 SourceLocation(),
4598 &Context->Idents.get("FuncPtr"),
4599 Context->VoidPtrTy, nullptr,
4600 /*BitWidth=*/nullptr, /*Mutable=*/true,
4601 ICIS_NoInit);
4603 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
4604
4605 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
4606 CK_BitCast, ME);
4607 PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
4608
4609 SmallVector<Expr*, 8> BlkExprs;
4610 // Add the implicit argument.
4611 BlkExprs.push_back(BlkCast);
4612 // Add the user arguments.
4613 for (CallExpr::arg_iterator I = Exp->arg_begin(),
4614 E = Exp->arg_end(); I != E; ++I) {
4615 BlkExprs.push_back(*I);
4616 }
4617 CallExpr *CE =
4618 CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,
4619 SourceLocation(), FPOptionsOverride());
4620 return CE;
4621}
4622
4623// We need to return the rewritten expression to handle cases where the
4624// DeclRefExpr is embedded in another expression being rewritten.
4625// For example:
4626//
4627// int main() {
4628// __block Foo *f;
4629// __block int i;
4630//
4631// void (^myblock)() = ^() {
4632// [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten).
4633// i = 77;
4634// };
4635//}
4636Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
4637 // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
4638 // for each DeclRefExp where BYREFVAR is name of the variable.
4639 ValueDecl *VD = DeclRefExp->getDecl();
4640 bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
4641 HasLocalVariableExternalStorage(DeclRefExp->getDecl());
4642
4643 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
4644 SourceLocation(),
4645 &Context->Idents.get("__forwarding"),
4646 Context->VoidPtrTy, nullptr,
4647 /*BitWidth=*/nullptr, /*Mutable=*/true,
4648 ICIS_NoInit);
4650 *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary);
4651
4652 StringRef Name = VD->getName();
4653 FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
4654 &Context->Idents.get(Name),
4655 Context->VoidPtrTy, nullptr,
4656 /*BitWidth=*/nullptr, /*Mutable=*/true,
4657 ICIS_NoInit);
4658 ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),
4660
4661 // Need parens to enforce precedence.
4662 ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
4663 DeclRefExp->getExprLoc(),
4664 ME);
4665 ReplaceStmt(DeclRefExp, PE);
4666 return PE;
4667}
4668
4669// Rewrites the imported local variable V with external storage
4670// (static, extern, etc.) as *V
4671//
4672Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
4673 ValueDecl *VD = DRE->getDecl();
4674 if (VarDecl *Var = dyn_cast<VarDecl>(VD))
4675 if (!ImportedLocalExternalDecls.count(Var))
4676 return DRE;
4678 const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),
4680 // Need parens to enforce precedence.
4681 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
4682 Exp);
4683 ReplaceStmt(DRE, PE);
4684 return PE;
4685}
4686
4687void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {
4688 SourceLocation LocStart = CE->getLParenLoc();
4689 SourceLocation LocEnd = CE->getRParenLoc();
4690
4691 // Need to avoid trying to rewrite synthesized casts.
4692 if (LocStart.isInvalid())
4693 return;
4694 // Need to avoid trying to rewrite casts contained in macros.
4695 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
4696 return;
4697
4698 const char *startBuf = SM->getCharacterData(LocStart);
4699 const char *endBuf = SM->getCharacterData(LocEnd);
4700 QualType QT = CE->getType();
4701 const Type* TypePtr = QT->getAs<Type>();
4702 if (isa<TypeOfExprType>(TypePtr)) {
4703 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
4704 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
4705 std::string TypeAsString = "(";
4706 RewriteBlockPointerType(TypeAsString, QT);
4707 TypeAsString += ")";
4708 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
4709 return;
4710 }
4711 // advance the location to startArgList.
4712 const char *argPtr = startBuf;
4713
4714 while (*argPtr++ && (argPtr < endBuf)) {
4715 switch (*argPtr) {
4716 case '^':
4717 // Replace the '^' with '*'.
4718 LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
4719 ReplaceText(LocStart, 1, "*");
4720 break;
4721 }
4722 }
4723}
4724
4725void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {
4727 if (CastKind != CK_BlockPointerToObjCPointerCast &&
4728 CastKind != CK_AnyPointerToBlockPointerCast)
4729 return;
4730
4731 QualType QT = IC->getType();
4732 (void)convertBlockPointerToFunctionPointer(QT);
4733 std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));
4734 std::string Str = "(";
4735 Str += TypeString;
4736 Str += ")";
4737 InsertText(IC->getSubExpr()->getBeginLoc(), Str);
4738}
4739
4740void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
4741 SourceLocation DeclLoc = FD->getLocation();
4742 unsigned parenCount = 0;
4743
4744 // We have 1 or more arguments that have closure pointers.
4745 const char *startBuf = SM->getCharacterData(DeclLoc);
4746 const char *startArgList = strchr(startBuf, '(');
4747
4748 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
4749
4750 parenCount++;
4751 // advance the location to startArgList.
4752 DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
4753 assert((DeclLoc.isValid()) && "Invalid DeclLoc");
4754
4755 const char *argPtr = startArgList;
4756
4757 while (*argPtr++ && parenCount) {
4758 switch (*argPtr) {
4759 case '^':
4760 // Replace the '^' with '*'.
4761 DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
4762 ReplaceText(DeclLoc, 1, "*");
4763 break;
4764 case '(':
4765 parenCount++;
4766 break;
4767 case ')':
4768 parenCount--;
4769 break;
4770 }
4771 }
4772}
4773
4774bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
4775 const FunctionProtoType *FTP;
4776 const PointerType *PT = QT->getAs<PointerType>();
4777 if (PT) {
4778 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
4779 } else {
4780 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
4781 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
4782 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
4783 }
4784 if (FTP) {
4785 for (const auto &I : FTP->param_types())
4786 if (isTopLevelBlockPointerType(I))
4787 return true;
4788 }
4789 return false;
4790}
4791
4792bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
4793 const FunctionProtoType *FTP;
4794 const PointerType *PT = QT->getAs<PointerType>();
4795 if (PT) {
4796 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
4797 } else {
4798 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
4799 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
4800 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
4801 }
4802 if (FTP) {
4803 for (const auto &I : FTP->param_types()) {
4804 if (I->isObjCQualifiedIdType())
4805 return true;
4806 if (I->isObjCObjectPointerType() &&
4807 I->getPointeeType()->isObjCQualifiedInterfaceType())
4808 return true;
4809 }
4810
4811 }
4812 return false;
4813}
4814
4815void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
4816 const char *&RParen) {
4817 const char *argPtr = strchr(Name, '(');
4818 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
4819
4820 LParen = argPtr; // output the start.
4821 argPtr++; // skip past the left paren.
4822 unsigned parenCount = 1;
4823
4824 while (*argPtr && parenCount) {
4825 switch (*argPtr) {
4826 case '(': parenCount++; break;
4827 case ')': parenCount--; break;
4828 default: break;
4829 }
4830 if (parenCount) argPtr++;
4831 }
4832 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
4833 RParen = argPtr; // output the end
4834}
4835
4836void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
4837 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
4838 RewriteBlockPointerFunctionArgs(FD);
4839 return;
4840 }
4841 // Handle Variables and Typedefs.
4842 SourceLocation DeclLoc = ND->getLocation();
4843 QualType DeclT;
4844 if (VarDecl *VD = dyn_cast<VarDecl>(ND))
4845 DeclT = VD->getType();
4846 else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
4847 DeclT = TDD->getUnderlyingType();
4848 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4849 DeclT = FD->getType();
4850 else
4851 llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
4852
4853 const char *startBuf = SM->getCharacterData(DeclLoc);
4854 const char *endBuf = startBuf;
4855 // scan backward (from the decl location) for the end of the previous decl.
4856 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
4857 startBuf--;
4858 SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
4859 std::string buf;
4860 unsigned OrigLength=0;
4861 // *startBuf != '^' if we are dealing with a pointer to function that
4862 // may take block argument types (which will be handled below).
4863 if (*startBuf == '^') {
4864 // Replace the '^' with '*', computing a negative offset.
4865 buf = '*';
4866 startBuf++;
4867 OrigLength++;
4868 }
4869 while (*startBuf != ')') {
4870 buf += *startBuf;
4871 startBuf++;
4872 OrigLength++;
4873 }
4874 buf += ')';
4875 OrigLength++;
4876
4877 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4878 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4879 // Replace the '^' with '*' for arguments.
4880 // Replace id<P> with id/*<>*/
4881 DeclLoc = ND->getLocation();
4882 startBuf = SM->getCharacterData(DeclLoc);
4883 const char *argListBegin, *argListEnd;
4884 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4885 while (argListBegin < argListEnd) {
4886 if (*argListBegin == '^')
4887 buf += '*';
4888 else if (*argListBegin == '<') {
4889 buf += "/*";
4890 buf += *argListBegin++;
4891 OrigLength++;
4892 while (*argListBegin != '>') {
4893 buf += *argListBegin++;
4894 OrigLength++;
4895 }
4896 buf += *argListBegin;
4897 buf += "*/";
4898 }
4899 else
4900 buf += *argListBegin;
4901 argListBegin++;
4902 OrigLength++;
4903 }
4904 buf += ')';
4905 OrigLength++;
4906 }
4907 ReplaceText(Start, OrigLength, buf);
4908}
4909
4910/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
4911/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
4912/// struct Block_byref_id_object *src) {
4913/// _Block_object_assign (&_dest->object, _src->object,
4914/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4915/// [|BLOCK_FIELD_IS_WEAK]) // object
4916/// _Block_object_assign(&_dest->object, _src->object,
4917/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4918/// [|BLOCK_FIELD_IS_WEAK]) // block
4919/// }
4920/// And:
4921/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
4922/// _Block_object_dispose(_src->object,
4923/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4924/// [|BLOCK_FIELD_IS_WEAK]) // object
4925/// _Block_object_dispose(_src->object,
4926/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4927/// [|BLOCK_FIELD_IS_WEAK]) // block
4928/// }
4929
4930std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
4931 int flag) {
4932 std::string S;
4933 if (CopyDestroyCache.count(flag))
4934 return S;
4935 CopyDestroyCache.insert(flag);
4936 S = "static void __Block_byref_id_object_copy_";
4937 S += utostr(flag);
4938 S += "(void *dst, void *src) {\n";
4939
4940 // offset into the object pointer is computed as:
4941 // void * + void* + int + int + void* + void *
4942 unsigned IntSize =
4943 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4944 unsigned VoidPtrSize =
4945 static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
4946
4947 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
4948 S += " _Block_object_assign((char*)dst + ";
4949 S += utostr(offset);
4950 S += ", *(void * *) ((char*)src + ";
4951 S += utostr(offset);
4952 S += "), ";
4953 S += utostr(flag);
4954 S += ");\n}\n";
4955
4956 S += "static void __Block_byref_id_object_dispose_";
4957 S += utostr(flag);
4958 S += "(void *src) {\n";
4959 S += " _Block_object_dispose(*(void * *) ((char*)src + ";
4960 S += utostr(offset);
4961 S += "), ";
4962 S += utostr(flag);
4963 S += ");\n}\n";
4964 return S;
4965}
4966
4967/// RewriteByRefVar - For each __block typex ND variable this routine transforms
4968/// the declaration into:
4969/// struct __Block_byref_ND {
4970/// void *__isa; // NULL for everything except __weak pointers
4971/// struct __Block_byref_ND *__forwarding;
4972/// int32_t __flags;
4973/// int32_t __size;
4974/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
4975/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
4976/// typex ND;
4977/// };
4978///
4979/// It then replaces declaration of ND variable with:
4980/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
4981/// __size=sizeof(struct __Block_byref_ND),
4982/// ND=initializer-if-any};
4983///
4984///
4985void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
4986 bool lastDecl) {
4987 int flag = 0;
4988 int isa = 0;
4989 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
4990 if (DeclLoc.isInvalid())
4991 // If type location is missing, it is because of missing type (a warning).
4992 // Use variable's location which is good for this case.
4993 DeclLoc = ND->getLocation();
4994 const char *startBuf = SM->getCharacterData(DeclLoc);
4995 SourceLocation X = ND->getEndLoc();
4996 X = SM->getExpansionLoc(X);
4997 const char *endBuf = SM->getCharacterData(X);
4998 std::string Name(ND->getNameAsString());
4999 std::string ByrefType;
5000 RewriteByRefString(ByrefType, Name, ND, true);
5001 ByrefType += " {\n";
5002 ByrefType += " void *__isa;\n";
5003 RewriteByRefString(ByrefType, Name, ND);
5004 ByrefType += " *__forwarding;\n";
5005 ByrefType += " int __flags;\n";
5006 ByrefType += " int __size;\n";
5007 // Add void *__Block_byref_id_object_copy;
5008 // void *__Block_byref_id_object_dispose; if needed.
5009 QualType Ty = ND->getType();
5010 bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
5011 if (HasCopyAndDispose) {
5012 ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
5013 ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
5014 }
5015
5016 QualType T = Ty;
5017 (void)convertBlockPointerToFunctionPointer(T);
5018 T.getAsStringInternal(Name, Context->getPrintingPolicy());
5019
5020 ByrefType += " " + Name + ";\n";
5021 ByrefType += "};\n";
5022 // Insert this type in global scope. It is needed by helper function.
5023 SourceLocation FunLocStart;
5024 if (CurFunctionDef)
5025 FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
5026 else {
5027 assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
5028 FunLocStart = CurMethodDef->getBeginLoc();
5029 }
5030 InsertText(FunLocStart, ByrefType);
5031
5032 if (Ty.isObjCGCWeak()) {
5033 flag |= BLOCK_FIELD_IS_WEAK;
5034 isa = 1;
5035 }
5036 if (HasCopyAndDispose) {
5037 flag = BLOCK_BYREF_CALLER;
5038 QualType Ty = ND->getType();
5039 // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
5040 if (Ty->isBlockPointerType())
5041 flag |= BLOCK_FIELD_IS_BLOCK;
5042 else
5043 flag |= BLOCK_FIELD_IS_OBJECT;
5044 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
5045 if (!HF.empty())
5046 Preamble += HF;
5047 }
5048
5049 // struct __Block_byref_ND ND =
5050 // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
5051 // initializer-if-any};
5052 bool hasInit = (ND->getInit() != nullptr);
5053 // FIXME. rewriter does not support __block c++ objects which
5054 // require construction.
5055 if (hasInit)
5056 if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) {
5057 CXXConstructorDecl *CXXDecl = CExp->getConstructor();
5058 if (CXXDecl && CXXDecl->isDefaultConstructor())
5059 hasInit = false;
5060 }
5061
5062 unsigned flags = 0;
5063 if (HasCopyAndDispose)
5064 flags |= BLOCK_HAS_COPY_DISPOSE;
5065 Name = ND->getNameAsString();
5066 ByrefType.clear();
5067 RewriteByRefString(ByrefType, Name, ND);
5068 std::string ForwardingCastType("(");
5069 ForwardingCastType += ByrefType + " *)";
5070 ByrefType += " " + Name + " = {(void*)";
5071 ByrefType += utostr(isa);
5072 ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
5073 ByrefType += utostr(flags);
5074 ByrefType += ", ";
5075 ByrefType += "sizeof(";
5076 RewriteByRefString(ByrefType, Name, ND);
5077 ByrefType += ")";
5078 if (HasCopyAndDispose) {
5079 ByrefType += ", __Block_byref_id_object_copy_";
5080 ByrefType += utostr(flag);
5081 ByrefType += ", __Block_byref_id_object_dispose_";
5082 ByrefType += utostr(flag);
5083 }
5084
5085 if (!firstDecl) {
5086 // In multiple __block declarations, and for all but 1st declaration,
5087 // find location of the separating comma. This would be start location
5088 // where new text is to be inserted.
5089 DeclLoc = ND->getLocation();
5090 const char *startDeclBuf = SM->getCharacterData(DeclLoc);
5091 const char *commaBuf = startDeclBuf;
5092 while (*commaBuf != ',')
5093 commaBuf--;
5094 assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','");
5095 DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf);
5096 startBuf = commaBuf;
5097 }
5098
5099 if (!hasInit) {
5100 ByrefType += "};\n";
5101 unsigned nameSize = Name.size();
5102 // for block or function pointer declaration. Name is already
5103 // part of the declaration.
5104 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
5105 nameSize = 1;
5106 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
5107 }
5108 else {
5109 ByrefType += ", ";
5110 SourceLocation startLoc;
5111 Expr *E = ND->getInit();
5112 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
5113 startLoc = ECE->getLParenLoc();
5114 else
5115 startLoc = E->getBeginLoc();
5116 startLoc = SM->getExpansionLoc(startLoc);
5117 endBuf = SM->getCharacterData(startLoc);
5118 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
5119
5120 const char separator = lastDecl ? ';' : ',';
5121 const char *startInitializerBuf = SM->getCharacterData(startLoc);
5122 const char *separatorBuf = strchr(startInitializerBuf, separator);
5123 assert((*separatorBuf == separator) &&
5124 "RewriteByRefVar: can't find ';' or ','");
5125 SourceLocation separatorLoc =
5126 startLoc.getLocWithOffset(separatorBuf-startInitializerBuf);
5127
5128 InsertText(separatorLoc, lastDecl ? "}" : "};\n");
5129 }
5130}
5131
5132void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
5133 // Add initializers for any closure decl refs.
5134 GetBlockDeclRefExprs(Exp->getBody());
5135 if (BlockDeclRefs.size()) {
5136 // Unique all "by copy" declarations.
5137 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5138 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())
5139 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());
5140 // Unique all "by ref" declarations.
5141 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5142 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())
5143 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());
5144 // Find any imported blocks...they will need special attention.
5145 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5146 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
5147 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
5148 BlockDeclRefs[i]->getType()->isBlockPointerType())
5149 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
5150 }
5151}
5152
5153FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {
5154 IdentifierInfo *ID = &Context->Idents.get(name);
5155 QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
5156 return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
5157 SourceLocation(), ID, FType, nullptr, SC_Extern,
5158 false, false);
5159}
5160
5161Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
5162 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {
5163 const BlockDecl *block = Exp->getBlockDecl();
5164
5165 Blocks.push_back(Exp);
5166
5167 CollectBlockDeclRefInfo(Exp);
5168
5169 // Add inner imported variables now used in current block.
5170 int countOfInnerDecls = 0;
5171 if (!InnerBlockDeclRefs.empty()) {
5172 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
5173 DeclRefExpr *Exp = InnerBlockDeclRefs[i];
5174 ValueDecl *VD = Exp->getDecl();
5175 if (!VD->hasAttr<BlocksAttr>() && BlockByCopyDecls.insert(VD)) {
5176 // We need to save the copied-in variables in nested
5177 // blocks because it is needed at the end for some of the API
5178 // generations. See SynthesizeBlockLiterals routine.
5179 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
5180 BlockDeclRefs.push_back(Exp);
5181 }
5182 if (VD->hasAttr<BlocksAttr>() && BlockByRefDecls.insert(VD)) {
5183 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
5184 BlockDeclRefs.push_back(Exp);
5185 }
5186 }
5187 // Find any imported blocks...they will need special attention.
5188 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
5189 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
5190 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
5191 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
5192 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
5193 }
5194 InnerDeclRefsCount.push_back(countOfInnerDecls);
5195
5196 std::string FuncName;
5197
5198 if (CurFunctionDef)
5199 FuncName = CurFunctionDef->getNameAsString();
5200 else if (CurMethodDef)
5201 BuildUniqueMethodName(FuncName, CurMethodDef);
5202 else if (GlobalVarDecl)
5203 FuncName = std::string(GlobalVarDecl->getNameAsString());
5204
5205 bool GlobalBlockExpr =
5207
5208 if (GlobalBlockExpr && !GlobalVarDecl) {
5209 Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
5210 GlobalBlockExpr = false;
5211 }
5212
5213 std::string BlockNumber = utostr(Blocks.size()-1);
5214
5215 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
5216
5217 // Get a pointer to the function type so we can cast appropriately.
5218 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
5219 QualType FType = Context->getPointerType(BFT);
5220
5221 FunctionDecl *FD;
5222 Expr *NewRep;
5223
5224 // Simulate a constructor call...
5225 std::string Tag;
5226
5227 if (GlobalBlockExpr)
5228 Tag = "__global_";
5229 else
5230 Tag = "__";
5231 Tag += FuncName + "_block_impl_" + BlockNumber;
5232
5233 FD = SynthBlockInitFunctionDecl(Tag);
5234 DeclRefExpr *DRE = new (Context)
5235 DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());
5236
5237 SmallVector<Expr*, 4> InitExprs;
5238
5239 // Initialize the block function.
5240 FD = SynthBlockInitFunctionDecl(Func);
5241 DeclRefExpr *Arg = new (Context) DeclRefExpr(
5242 *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());
5243 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
5244 CK_BitCast, Arg);
5245 InitExprs.push_back(castExpr);
5246
5247 // Initialize the block descriptor.
5248 std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
5249
5250 VarDecl *NewVD = VarDecl::Create(
5251 *Context, TUDecl, SourceLocation(), SourceLocation(),
5252 &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
5253 UnaryOperator *DescRefExpr = UnaryOperator::Create(
5254 const_cast<ASTContext &>(*Context),
5255 new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
5256 VK_LValue, SourceLocation()),
5257 UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,
5258 OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
5259 InitExprs.push_back(DescRefExpr);
5260
5261 // Add initializers for any closure decl refs.
5262 if (BlockDeclRefs.size()) {
5263 Expr *Exp;
5264 // Output all "by copy" declarations.
5265 for (ValueDecl *VD : BlockByCopyDecls) {
5266 if (isObjCType(VD->getType())) {
5267 // FIXME: Conform to ABI ([[obj retain] autorelease]).
5268 FD = SynthBlockInitFunctionDecl(VD->getName());
5269 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
5270 VK_LValue, SourceLocation());
5271 if (HasLocalVariableExternalStorage(VD)) {
5272 QualType QT = VD->getType();
5273 QT = Context->getPointerType(QT);
5274 Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
5275 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
5276 SourceLocation(), false,
5278 }
5279 } else if (isTopLevelBlockPointerType(VD->getType())) {
5280 FD = SynthBlockInitFunctionDecl(VD->getName());
5281 Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
5282 VK_LValue, SourceLocation());
5283 Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
5284 CK_BitCast, Arg);
5285 } else {
5286 FD = SynthBlockInitFunctionDecl(VD->getName());
5287 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
5288 VK_LValue, SourceLocation());
5289 if (HasLocalVariableExternalStorage(VD)) {
5290 QualType QT = VD->getType();
5291 QT = Context->getPointerType(QT);
5292 Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
5293 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
5294 SourceLocation(), false,
5296 }
5297 }
5298 InitExprs.push_back(Exp);
5299 }
5300 // Output all "by ref" declarations.
5301 for (ValueDecl *ND : BlockByRefDecls) {
5302 std::string Name(ND->getNameAsString());
5303 std::string RecName;
5304 RewriteByRefString(RecName, Name, ND, true);
5305 IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
5306 + sizeof("struct"));
5307 RecordDecl *RD =
5308 RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
5309 SourceLocation(), SourceLocation(), II);
5310 assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
5311 QualType castT =
5312 Context->getPointerType(Context->getCanonicalTagType(RD));
5313
5314 FD = SynthBlockInitFunctionDecl(ND->getName());
5315 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
5316 VK_LValue, SourceLocation());
5317 bool isNestedCapturedVar = false;
5318 for (const auto &CI : block->captures()) {
5319 const VarDecl *variable = CI.getVariable();
5320 if (variable == ND && CI.isNested()) {
5321 assert(CI.isByRef() &&
5322 "SynthBlockInitExpr - captured block variable is not byref");
5323 isNestedCapturedVar = true;
5324 break;
5325 }
5326 }
5327 // captured nested byref variable has its address passed. Do not take
5328 // its address again.
5329 if (!isNestedCapturedVar)
5331 const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
5332 Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,
5333 SourceLocation(), false, FPOptionsOverride());
5334 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
5335 InitExprs.push_back(Exp);
5336 }
5337 }
5338 if (ImportedBlockDecls.size()) {
5339 // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
5340 int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
5341 unsigned IntSize =
5342 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
5343 Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
5344 Context->IntTy, SourceLocation());
5345 InitExprs.push_back(FlagExp);
5346 }
5347 NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
5348 SourceLocation(), FPOptionsOverride());
5349
5350 if (GlobalBlockExpr) {
5351 assert (!GlobalConstructionExp &&
5352 "SynthBlockInitExpr - GlobalConstructionExp must be null");
5353 GlobalConstructionExp = NewRep;
5354 NewRep = DRE;
5355 }
5356
5357 NewRep = UnaryOperator::Create(
5358 const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
5359 Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,
5360 SourceLocation(), false, FPOptionsOverride());
5361 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
5362 NewRep);
5363 // Put Paren around the call.
5364 NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
5365 NewRep);
5366
5367 BlockDeclRefs.clear();
5368 BlockByRefDecls.clear();
5369 BlockByCopyDecls.clear();
5370 ImportedBlockDecls.clear();
5371 return NewRep;
5372}
5373
5374bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
5375 if (const ObjCForCollectionStmt * CS =
5376 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
5377 return CS->getElement() == DS;
5378 return false;
5379}
5380
5381//===----------------------------------------------------------------------===//
5382// Function Body / Expression rewriting
5383//===----------------------------------------------------------------------===//
5384
5385Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
5386 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
5387 isa<DoStmt>(S) || isa<ForStmt>(S))
5388 Stmts.push_back(S);
5389 else if (isa<ObjCForCollectionStmt>(S)) {
5390 Stmts.push_back(S);
5391 ObjCBcLabelNo.push_back(++BcLabelCount);
5392 }
5393
5394 // Pseudo-object operations and ivar references need special
5395 // treatment because we're going to recursively rewrite them.
5396 if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
5397 if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
5398 return RewritePropertyOrImplicitSetter(PseudoOp);
5399 } else {
5400 return RewritePropertyOrImplicitGetter(PseudoOp);
5401 }
5402 } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
5403 return RewriteObjCIvarRefExpr(IvarRefExpr);
5404 }
5405 else if (isa<OpaqueValueExpr>(S))
5406 S = cast<OpaqueValueExpr>(S)->getSourceExpr();
5407
5408 SourceRange OrigStmtRange = S->getSourceRange();
5409
5410 // Perform a bottom up rewrite of all children.
5411 for (Stmt *&childStmt : S->children())
5412 if (childStmt) {
5413 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
5414 if (newStmt) {
5415 childStmt = newStmt;
5416 }
5417 }
5418
5419 if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
5420 SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;
5422 InnerContexts.insert(BE->getBlockDecl());
5423 ImportedLocalExternalDecls.clear();
5424 GetInnerBlockDeclRefExprs(BE->getBody(),
5425 InnerBlockDeclRefs, InnerContexts);
5426 // Rewrite the block body in place.
5427 Stmt *SaveCurrentBody = CurrentBody;
5428 CurrentBody = BE->getBody();
5429 PropParentMap = nullptr;
5430 // block literal on rhs of a property-dot-sytax assignment
5431 // must be replaced by its synthesize ast so getRewrittenText
5432 // works as expected. In this case, what actually ends up on RHS
5433 // is the blockTranscribed which is the helper function for the
5434 // block literal; as in: self.c = ^() {[ace ARR];};
5435 bool saveDisableReplaceStmt = DisableReplaceStmt;
5436 DisableReplaceStmt = false;
5437 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
5438 DisableReplaceStmt = saveDisableReplaceStmt;
5439 CurrentBody = SaveCurrentBody;
5440 PropParentMap = nullptr;
5441 ImportedLocalExternalDecls.clear();
5442 // Now we snarf the rewritten text and stash it away for later use.
5443 std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
5444 RewrittenBlockExprs[BE] = Str;
5445
5446 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
5447
5448 //blockTranscribed->dump();
5449 ReplaceStmt(S, blockTranscribed);
5450 return blockTranscribed;
5451 }
5452 // Handle specific things.
5453 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
5454 return RewriteAtEncode(AtEncode);
5455
5456 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
5457 return RewriteAtSelector(AtSelector);
5458
5459 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
5460 return RewriteObjCStringLiteral(AtString);
5461
5462 if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))
5463 return RewriteObjCBoolLiteralExpr(BoolLitExpr);
5464
5465 if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))
5466 return RewriteObjCBoxedExpr(BoxedExpr);
5467
5468 if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))
5469 return RewriteObjCArrayLiteralExpr(ArrayLitExpr);
5470
5471 if (ObjCDictionaryLiteral *DictionaryLitExpr =
5472 dyn_cast<ObjCDictionaryLiteral>(S))
5473 return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr);
5474
5475 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
5476#if 0
5477 // Before we rewrite it, put the original message expression in a comment.
5478 SourceLocation startLoc = MessExpr->getBeginLoc();
5479 SourceLocation endLoc = MessExpr->getEndLoc();
5480
5481 const char *startBuf = SM->getCharacterData(startLoc);
5482 const char *endBuf = SM->getCharacterData(endLoc);
5483
5484 std::string messString;
5485 messString += "// ";
5486 messString.append(startBuf, endBuf-startBuf+1);
5487 messString += "\n";
5488
5489 // FIXME: Missing definition of
5490 // InsertText(clang::SourceLocation, char const*, unsigned int).
5491 // InsertText(startLoc, messString);
5492 // Tried this, but it didn't work either...
5493 // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
5494#endif
5495 return RewriteMessageExpr(MessExpr);
5496 }
5497
5498 if (ObjCAutoreleasePoolStmt *StmtAutoRelease =
5499 dyn_cast<ObjCAutoreleasePoolStmt>(S)) {
5500 return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease);
5501 }
5502
5503 if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
5504 return RewriteObjCTryStmt(StmtTry);
5505
5506 if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
5507 return RewriteObjCSynchronizedStmt(StmtTry);
5508
5509 if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
5510 return RewriteObjCThrowStmt(StmtThrow);
5511
5512 if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
5513 return RewriteObjCProtocolExpr(ProtocolExp);
5514
5515 if (ObjCForCollectionStmt *StmtForCollection =
5516 dyn_cast<ObjCForCollectionStmt>(S))
5517 return RewriteObjCForCollectionStmt(StmtForCollection,
5518 OrigStmtRange.getEnd());
5519 if (BreakStmt *StmtBreakStmt =
5520 dyn_cast<BreakStmt>(S))
5521 return RewriteBreakStmt(StmtBreakStmt);
5522 if (ContinueStmt *StmtContinueStmt =
5523 dyn_cast<ContinueStmt>(S))
5524 return RewriteContinueStmt(StmtContinueStmt);
5525
5526 // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
5527 // and cast exprs.
5528 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
5529 // FIXME: What we're doing here is modifying the type-specifier that
5530 // precedes the first Decl. In the future the DeclGroup should have
5531 // a separate type-specifier that we can rewrite.
5532 // NOTE: We need to avoid rewriting the DeclStmt if it is within
5533 // the context of an ObjCForCollectionStmt. For example:
5534 // NSArray *someArray;
5535 // for (id <FooProtocol> index in someArray) ;
5536 // This is because RewriteObjCForCollectionStmt() does textual rewriting
5537 // and it depends on the original text locations/positions.
5538 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
5539 RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
5540
5541 // Blocks rewrite rules.
5542 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
5543 DI != DE; ++DI) {
5544 Decl *SD = *DI;
5545 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
5546 if (isTopLevelBlockPointerType(ND->getType()))
5547 RewriteBlockPointerDecl(ND);
5548 else if (ND->getType()->isFunctionPointerType())
5549 CheckFunctionPointerDecl(ND->getType(), ND);
5550 if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
5551 if (VD->hasAttr<BlocksAttr>()) {
5552 static unsigned uniqueByrefDeclCount = 0;
5553 assert(!BlockByRefDeclNo.count(ND) &&
5554 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
5555 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
5556 RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE));
5557 }
5558 else
5559 RewriteTypeOfDecl(VD);
5560 }
5561 }
5562 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
5563 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
5564 RewriteBlockPointerDecl(TD);
5565 else if (TD->getUnderlyingType()->isFunctionPointerType())
5566 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
5567 }
5568 }
5569 }
5570
5571 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
5572 RewriteObjCQualifiedInterfaceTypes(CE);
5573
5574 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
5575 isa<DoStmt>(S) || isa<ForStmt>(S)) {
5576 assert(!Stmts.empty() && "Statement stack is empty");
5577 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
5578 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
5579 && "Statement stack mismatch");
5580 Stmts.pop_back();
5581 }
5582 // Handle blocks rewriting.
5583 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
5584 ValueDecl *VD = DRE->getDecl();
5585 if (VD->hasAttr<BlocksAttr>())
5586 return RewriteBlockDeclRefExpr(DRE);
5587 if (HasLocalVariableExternalStorage(VD))
5588 return RewriteLocalVariableExternalStorage(DRE);
5589 }
5590
5591 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
5592 if (CE->getCallee()->getType()->isBlockPointerType()) {
5593 Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
5594 ReplaceStmt(S, BlockCall);
5595 return BlockCall;
5596 }
5597 }
5598 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
5599 RewriteCastExpr(CE);
5600 }
5601 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
5602 RewriteImplicitCastObjCExpr(ICE);
5603 }
5604#if 0
5605
5606 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
5607 CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
5608 ICE->getSubExpr(),
5609 SourceLocation());
5610 // Get the new text.
5611 std::string SStr;
5612 llvm::raw_string_ostream Buf(SStr);
5613 Replacement->printPretty(Buf);
5614 const std::string &Str = Buf.str();
5615
5616 printf("CAST = %s\n", &Str[0]);
5617 InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
5618 delete S;
5619 return Replacement;
5620 }
5621#endif
5622 // Return this stmt unmodified.
5623 return S;
5624}
5625
5626void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) {
5627 for (auto *FD : RD->fields()) {
5628 if (isTopLevelBlockPointerType(FD->getType()))
5629 RewriteBlockPointerDecl(FD);
5630 if (FD->getType()->isObjCQualifiedIdType() ||
5632 RewriteObjCQualifiedInterfaceTypes(FD);
5633 }
5634}
5635
5636/// HandleDeclInMainFile - This is called for each top-level decl defined in the
5637/// main file of the input.
5638void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {
5639 switch (D->getKind()) {
5640 case Decl::Function: {
5642 if (FD->isOverloadedOperator())
5643 return;
5644
5645 // Since function prototypes don't have ParmDecl's, we check the function
5646 // prototype. This enables us to rewrite function declarations and
5647 // definitions using the same code.
5648 RewriteBlocksInFunctionProtoType(FD->getType(), FD);
5649
5651 break;
5652
5653 // FIXME: If this should support Obj-C++, support CXXTryStmt
5654 if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
5655 CurFunctionDef = FD;
5656 CurrentBody = Body;
5657 Body =
5658 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
5659 FD->setBody(Body);
5660 CurrentBody = nullptr;
5661 if (PropParentMap) {
5662 delete PropParentMap;
5663 PropParentMap = nullptr;
5664 }
5665 // This synthesizes and inserts the block "impl" struct, invoke function,
5666 // and any copy/dispose helper functions.
5667 InsertBlockLiteralsWithinFunction(FD);
5668 RewriteLineDirective(D);
5669 CurFunctionDef = nullptr;
5670 }
5671 break;
5672 }
5673 case Decl::ObjCMethod: {
5675 if (CompoundStmt *Body = MD->getCompoundBody()) {
5676 CurMethodDef = MD;
5677 CurrentBody = Body;
5678 Body =
5679 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
5680 MD->setBody(Body);
5681 CurrentBody = nullptr;
5682 if (PropParentMap) {
5683 delete PropParentMap;
5684 PropParentMap = nullptr;
5685 }
5686 InsertBlockLiteralsWithinMethod(MD);
5687 RewriteLineDirective(D);
5688 CurMethodDef = nullptr;
5689 }
5690 break;
5691 }
5692 case Decl::ObjCImplementation: {
5694 ClassImplementation.push_back(CI);
5695 break;
5696 }
5697 case Decl::ObjCCategoryImpl: {
5699 CategoryImplementation.push_back(CI);
5700 break;
5701 }
5702 case Decl::Var: {
5703 VarDecl *VD = cast<VarDecl>(D);
5704 RewriteObjCQualifiedInterfaceTypes(VD);
5705 if (isTopLevelBlockPointerType(VD->getType()))
5706 RewriteBlockPointerDecl(VD);
5707 else if (VD->getType()->isFunctionPointerType()) {
5708 CheckFunctionPointerDecl(VD->getType(), VD);
5709 if (VD->getInit()) {
5710 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
5711 RewriteCastExpr(CE);
5712 }
5713 }
5714 } else if (VD->getType()->isRecordType()) {
5715 auto *RD = VD->getType()->castAsRecordDecl();
5716 if (RD->isCompleteDefinition())
5717 RewriteRecordBody(RD);
5718 }
5719 if (VD->getInit()) {
5720 GlobalVarDecl = VD;
5721 CurrentBody = VD->getInit();
5722 RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
5723 CurrentBody = nullptr;
5724 if (PropParentMap) {
5725 delete PropParentMap;
5726 PropParentMap = nullptr;
5727 }
5728 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
5729 GlobalVarDecl = nullptr;
5730
5731 // This is needed for blocks.
5732 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
5733 RewriteCastExpr(CE);
5734 }
5735 }
5736 break;
5737 }
5738 case Decl::TypeAlias:
5739 case Decl::Typedef: {
5740 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
5741 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
5742 RewriteBlockPointerDecl(TD);
5743 else if (TD->getUnderlyingType()->isFunctionPointerType())
5744 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
5745 else
5746 RewriteObjCQualifiedInterfaceTypes(TD);
5747 }
5748 break;
5749 }
5750 case Decl::CXXRecord:
5751 case Decl::Record: {
5753 if (RD->isCompleteDefinition())
5754 RewriteRecordBody(RD);
5755 break;
5756 }
5757 default:
5758 break;
5759 }
5760 // Nothing yet.
5761}
5762
5763/// Write_ProtocolExprReferencedMetadata - This routine writer out the
5764/// protocol reference symbols in the for of:
5765/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.
5766static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,
5767 ObjCProtocolDecl *PDecl,
5768 std::string &Result) {
5769 // Also output .objc_protorefs$B section and its meta-data.
5770 if (Context->getLangOpts().MicrosoftExt)
5771 Result += "static ";
5772 Result += "struct _protocol_t *";
5773 Result += "_OBJC_PROTOCOL_REFERENCE_$_";
5774 Result += PDecl->getNameAsString();
5775 Result += " = &";
5776 Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
5777 Result += ";\n";
5778}
5779
5780void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
5781 if (Diags.hasErrorOccurred())
5782 return;
5783
5784 RewriteInclude();
5785
5786 for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) {
5787 // translation of function bodies were postponed until all class and
5788 // their extensions and implementations are seen. This is because, we
5789 // cannot build grouping structs for bitfields until they are all seen.
5790 FunctionDecl *FDecl = FunctionDefinitionsSeen[i];
5791 HandleTopLevelSingleDecl(FDecl);
5792 }
5793
5794 // Here's a great place to add any extra declarations that may be needed.
5795 // Write out meta data for each @protocol(<expr>).
5796 for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {
5797 RewriteObjCProtocolMetaData(ProtDecl, Preamble);
5798 Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble);
5799 }
5800
5801 InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
5802
5803 if (ClassImplementation.size() || CategoryImplementation.size())
5804 RewriteImplementations();
5805
5806 for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {
5807 ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];
5808 // Write struct declaration for the class matching its ivar declarations.
5809 // Note that for modern abi, this is postponed until the end of TU
5810 // because class extensions and the implementation might declare their own
5811 // private ivars.
5812 RewriteInterfaceDecl(CDecl);
5813 }
5814
5815 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
5816 // we are done.
5817 if (const RewriteBuffer *RewriteBuf =
5818 Rewrite.getRewriteBufferFor(MainFileID)) {
5819 //printf("Changed:\n");
5820 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
5821 } else {
5822 llvm::errs() << "No changes\n";
5823 }
5824
5825 if (ClassImplementation.size() || CategoryImplementation.size() ||
5826 ProtocolExprDecls.size()) {
5827 // Rewrite Objective-c meta data*
5828 std::string ResultStr;
5829 RewriteMetaDataIntoBuffer(ResultStr);
5830 // Emit metadata.
5831 *OutFile << ResultStr;
5832 }
5833 // Emit ImageInfo;
5834 {
5835 std::string ResultStr;
5836 WriteImageInfo(ResultStr);
5837 *OutFile << ResultStr;
5838 }
5839 OutFile->flush();
5840}
5841
5842void RewriteModernObjC::Initialize(ASTContext &context) {
5843 InitializeCommon(context);
5844
5845 Preamble += "#ifndef __OBJC2__\n";
5846 Preamble += "#define __OBJC2__\n";
5847 Preamble += "#endif\n";
5848
5849 // declaring objc_selector outside the parameter list removes a silly
5850 // scope related warning...
5851 if (IsHeader)
5852 Preamble = "#pragma once\n";
5853 Preamble += "struct objc_selector; struct objc_class;\n";
5854 Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; ";
5855 Preamble += "\n\tstruct objc_object *superClass; ";
5856 // Add a constructor for creating temporary objects.
5857 Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) ";
5858 Preamble += ": object(o), superClass(s) {} ";
5859 Preamble += "\n};\n";
5860
5861 if (LangOpts.MicrosoftExt) {
5862 // Define all sections using syntax that makes sense.
5863 // These are currently generated.
5864 Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";
5865 Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";
5866 Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";
5867 Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";
5868 Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";
5869 // These are generated but not necessary for functionality.
5870 Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";
5871 Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";
5872 Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";
5873 Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";
5874
5875 // These need be generated for performance. Currently they are not,
5876 // using API calls instead.
5877 Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";
5878 Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";
5879 Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";
5880
5881 }
5882 Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
5883 Preamble += "typedef struct objc_object Protocol;\n";
5884 Preamble += "#define _REWRITER_typedef_Protocol\n";
5885 Preamble += "#endif\n";
5886 if (LangOpts.MicrosoftExt) {
5887 Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
5888 Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
5889 }
5890 else
5891 Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
5892
5893 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";
5894 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";
5895 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";
5896 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n";
5897 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n";
5898
5899 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass";
5900 Preamble += "(const char *);\n";
5901 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
5902 Preamble += "(struct objc_class *);\n";
5903 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass";
5904 Preamble += "(const char *);\n";
5905 Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n";
5906 // @synchronized hooks.
5907 Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n";
5908 Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n";
5909 Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
5910 Preamble += "#ifdef _WIN64\n";
5911 Preamble += "typedef unsigned long long _WIN_NSUInteger;\n";
5912 Preamble += "#else\n";
5913 Preamble += "typedef unsigned int _WIN_NSUInteger;\n";
5914 Preamble += "#endif\n";
5915 Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
5916 Preamble += "struct __objcFastEnumerationState {\n\t";
5917 Preamble += "unsigned long state;\n\t";
5918 Preamble += "void **itemsPtr;\n\t";
5919 Preamble += "unsigned long *mutationsPtr;\n\t";
5920 Preamble += "unsigned long extra[5];\n};\n";
5921 Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
5922 Preamble += "#define __FASTENUMERATIONSTATE\n";
5923 Preamble += "#endif\n";
5924 Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
5925 Preamble += "struct __NSConstantStringImpl {\n";
5926 Preamble += " int *isa;\n";
5927 Preamble += " int flags;\n";
5928 Preamble += " char *str;\n";
5929 Preamble += "#if _WIN64\n";
5930 Preamble += " long long length;\n";
5931 Preamble += "#else\n";
5932 Preamble += " long length;\n";
5933 Preamble += "#endif\n";
5934 Preamble += "};\n";
5935 Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
5936 Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5937 Preamble += "#else\n";
5938 Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5939 Preamble += "#endif\n";
5940 Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
5941 Preamble += "#endif\n";
5942 // Blocks preamble.
5943 Preamble += "#ifndef BLOCK_IMPL\n";
5944 Preamble += "#define BLOCK_IMPL\n";
5945 Preamble += "struct __block_impl {\n";
5946 Preamble += " void *isa;\n";
5947 Preamble += " int Flags;\n";
5948 Preamble += " int Reserved;\n";
5949 Preamble += " void *FuncPtr;\n";
5950 Preamble += "};\n";
5951 Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
5952 Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
5953 Preamble += "extern \"C\" __declspec(dllexport) "
5954 "void _Block_object_assign(void *, const void *, const int);\n";
5955 Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5956 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5957 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5958 Preamble += "#else\n";
5959 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5960 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5961 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5962 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5963 Preamble += "#endif\n";
5964 Preamble += "#endif\n";
5965 if (LangOpts.MicrosoftExt) {
5966 Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
5967 Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
5968 Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.
5969 Preamble += "#define __attribute__(X)\n";
5970 Preamble += "#endif\n";
5971 Preamble += "#ifndef __weak\n";
5972 Preamble += "#define __weak\n";
5973 Preamble += "#endif\n";
5974 Preamble += "#ifndef __block\n";
5975 Preamble += "#define __block\n";
5976 Preamble += "#endif\n";
5977 }
5978 else {
5979 Preamble += "#define __block\n";
5980 Preamble += "#define __weak\n";
5981 }
5982
5983 // Declarations required for modern objective-c array and dictionary literals.
5984 Preamble += "\n#include <stdarg.h>\n";
5985 Preamble += "struct __NSContainer_literal {\n";
5986 Preamble += " void * *arr;\n";
5987 Preamble += " __NSContainer_literal (unsigned int count, ...) {\n";
5988 Preamble += "\tva_list marker;\n";
5989 Preamble += "\tva_start(marker, count);\n";
5990 Preamble += "\tarr = new void *[count];\n";
5991 Preamble += "\tfor (unsigned i = 0; i < count; i++)\n";
5992 Preamble += "\t arr[i] = va_arg(marker, void *);\n";
5993 Preamble += "\tva_end( marker );\n";
5994 Preamble += " };\n";
5995 Preamble += " ~__NSContainer_literal() {\n";
5996 Preamble += "\tdelete[] arr;\n";
5997 Preamble += " }\n";
5998 Preamble += "};\n";
5999
6000 // Declaration required for implementation of @autoreleasepool statement.
6001 Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n";
6002 Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n";
6003 Preamble += "struct __AtAutoreleasePool {\n";
6004 Preamble += " __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n";
6005 Preamble += " ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n";
6006 Preamble += " void * atautoreleasepoolobj;\n";
6007 Preamble += "};\n";
6008
6009 // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
6010 // as this avoids warning in any 64bit/32bit compilation model.
6011 Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
6012}
6013
6014/// RewriteIvarOffsetComputation - This routine synthesizes computation of
6015/// ivar offset.
6016void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
6017 std::string &Result) {
6018 Result += "__OFFSETOFIVAR__(struct ";
6020 if (LangOpts.MicrosoftExt)
6021 Result += "_IMPL";
6022 Result += ", ";
6023 if (ivar->isBitField())
6024 ObjCIvarBitfieldGroupDecl(ivar, Result);
6025 else
6026 Result += ivar->getNameAsString();
6027 Result += ")";
6028}
6029
6030/// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI.
6031/// struct _prop_t {
6032/// const char *name;
6033/// char *attributes;
6034/// }
6035
6036/// struct _prop_list_t {
6037/// uint32_t entsize; // sizeof(struct _prop_t)
6038/// uint32_t count_of_properties;
6039/// struct _prop_t prop_list[count_of_properties];
6040/// }
6041
6042/// struct _protocol_t;
6043
6044/// struct _protocol_list_t {
6045/// long protocol_count; // Note, this is 32/64 bit
6046/// struct _protocol_t * protocol_list[protocol_count];
6047/// }
6048
6049/// struct _objc_method {
6050/// SEL _cmd;
6051/// const char *method_type;
6052/// char *_imp;
6053/// }
6054
6055/// struct _method_list_t {
6056/// uint32_t entsize; // sizeof(struct _objc_method)
6057/// uint32_t method_count;
6058/// struct _objc_method method_list[method_count];
6059/// }
6060
6061/// struct _protocol_t {
6062/// id isa; // NULL
6063/// const char *protocol_name;
6064/// const struct _protocol_list_t * protocol_list; // super protocols
6065/// const struct method_list_t *instance_methods;
6066/// const struct method_list_t *class_methods;
6067/// const struct method_list_t *optionalInstanceMethods;
6068/// const struct method_list_t *optionalClassMethods;
6069/// const struct _prop_list_t * properties;
6070/// const uint32_t size; // sizeof(struct _protocol_t)
6071/// const uint32_t flags; // = 0
6072/// const char ** extendedMethodTypes;
6073/// }
6074
6075/// struct _ivar_t {
6076/// unsigned long int *offset; // pointer to ivar offset location
6077/// const char *name;
6078/// const char *type;
6079/// uint32_t alignment;
6080/// uint32_t size;
6081/// }
6082
6083/// struct _ivar_list_t {
6084/// uint32 entsize; // sizeof(struct _ivar_t)
6085/// uint32 count;
6086/// struct _ivar_t list[count];
6087/// }
6088
6089/// struct _class_ro_t {
6090/// uint32_t flags;
6091/// uint32_t instanceStart;
6092/// uint32_t instanceSize;
6093/// uint32_t reserved; // only when building for 64bit targets
6094/// const uint8_t *ivarLayout;
6095/// const char *name;
6096/// const struct _method_list_t *baseMethods;
6097/// const struct _protocol_list_t *baseProtocols;
6098/// const struct _ivar_list_t *ivars;
6099/// const uint8_t *weakIvarLayout;
6100/// const struct _prop_list_t *properties;
6101/// }
6102
6103/// struct _class_t {
6104/// struct _class_t *isa;
6105/// struct _class_t *superclass;
6106/// void *cache;
6107/// IMP *vtable;
6108/// struct _class_ro_t *ro;
6109/// }
6110
6111/// struct _category_t {
6112/// const char *name;
6113/// struct _class_t *cls;
6114/// const struct _method_list_t *instance_methods;
6115/// const struct _method_list_t *class_methods;
6116/// const struct _protocol_list_t *protocols;
6117/// const struct _prop_list_t *properties;
6118/// }
6119
6120/// MessageRefTy - LLVM for:
6121/// struct _message_ref_t {
6122/// IMP messenger;
6123/// SEL name;
6124/// };
6125
6126/// SuperMessageRefTy - LLVM for:
6127/// struct _super_message_ref_t {
6128/// SUPER_IMP messenger;
6129/// SEL name;
6130/// };
6131
6132static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) {
6133 static bool meta_data_declared = false;
6134 if (meta_data_declared)
6135 return;
6136
6137 Result += "\nstruct _prop_t {\n";
6138 Result += "\tconst char *name;\n";
6139 Result += "\tconst char *attributes;\n";
6140 Result += "};\n";
6141
6142 Result += "\nstruct _protocol_t;\n";
6143
6144 Result += "\nstruct _objc_method {\n";
6145 Result += "\tstruct objc_selector * _cmd;\n";
6146 Result += "\tconst char *method_type;\n";
6147 Result += "\tvoid *_imp;\n";
6148 Result += "};\n";
6149
6150 Result += "\nstruct _protocol_t {\n";
6151 Result += "\tvoid * isa; // NULL\n";
6152 Result += "\tconst char *protocol_name;\n";
6153 Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n";
6154 Result += "\tconst struct method_list_t *instance_methods;\n";
6155 Result += "\tconst struct method_list_t *class_methods;\n";
6156 Result += "\tconst struct method_list_t *optionalInstanceMethods;\n";
6157 Result += "\tconst struct method_list_t *optionalClassMethods;\n";
6158 Result += "\tconst struct _prop_list_t * properties;\n";
6159 Result += "\tconst unsigned int size; // sizeof(struct _protocol_t)\n";
6160 Result += "\tconst unsigned int flags; // = 0\n";
6161 Result += "\tconst char ** extendedMethodTypes;\n";
6162 Result += "};\n";
6163
6164 Result += "\nstruct _ivar_t {\n";
6165 Result += "\tunsigned long int *offset; // pointer to ivar offset location\n";
6166 Result += "\tconst char *name;\n";
6167 Result += "\tconst char *type;\n";
6168 Result += "\tunsigned int alignment;\n";
6169 Result += "\tunsigned int size;\n";
6170 Result += "};\n";
6171
6172 Result += "\nstruct _class_ro_t {\n";
6173 Result += "\tunsigned int flags;\n";
6174 Result += "\tunsigned int instanceStart;\n";
6175 Result += "\tunsigned int instanceSize;\n";
6176 const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
6177 if (Triple.getArch() == llvm::Triple::x86_64)
6178 Result += "\tunsigned int reserved;\n";
6179 Result += "\tconst unsigned char *ivarLayout;\n";
6180 Result += "\tconst char *name;\n";
6181 Result += "\tconst struct _method_list_t *baseMethods;\n";
6182 Result += "\tconst struct _objc_protocol_list *baseProtocols;\n";
6183 Result += "\tconst struct _ivar_list_t *ivars;\n";
6184 Result += "\tconst unsigned char *weakIvarLayout;\n";
6185 Result += "\tconst struct _prop_list_t *properties;\n";
6186 Result += "};\n";
6187
6188 Result += "\nstruct _class_t {\n";
6189 Result += "\tstruct _class_t *isa;\n";
6190 Result += "\tstruct _class_t *superclass;\n";
6191 Result += "\tvoid *cache;\n";
6192 Result += "\tvoid *vtable;\n";
6193 Result += "\tstruct _class_ro_t *ro;\n";
6194 Result += "};\n";
6195
6196 Result += "\nstruct _category_t {\n";
6197 Result += "\tconst char *name;\n";
6198 Result += "\tstruct _class_t *cls;\n";
6199 Result += "\tconst struct _method_list_t *instance_methods;\n";
6200 Result += "\tconst struct _method_list_t *class_methods;\n";
6201 Result += "\tconst struct _protocol_list_t *protocols;\n";
6202 Result += "\tconst struct _prop_list_t *properties;\n";
6203 Result += "};\n";
6204
6205 Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";
6206 Result += "#pragma warning(disable:4273)\n";
6207 meta_data_declared = true;
6208}
6209
6210static void Write_protocol_list_t_TypeDecl(std::string &Result,
6211 long super_protocol_count) {
6212 Result += "struct /*_protocol_list_t*/"; Result += " {\n";
6213 Result += "\tlong protocol_count; // Note, this is 32/64 bit\n";
6214 Result += "\tstruct _protocol_t *super_protocols[";
6215 Result += utostr(super_protocol_count); Result += "];\n";
6216 Result += "}";
6217}
6218
6219static void Write_method_list_t_TypeDecl(std::string &Result,
6220 unsigned int method_count) {
6221 Result += "struct /*_method_list_t*/"; Result += " {\n";
6222 Result += "\tunsigned int entsize; // sizeof(struct _objc_method)\n";
6223 Result += "\tunsigned int method_count;\n";
6224 Result += "\tstruct _objc_method method_list[";
6225 Result += utostr(method_count); Result += "];\n";
6226 Result += "}";
6227}
6228
6229static void Write__prop_list_t_TypeDecl(std::string &Result,
6230 unsigned int property_count) {
6231 Result += "struct /*_prop_list_t*/"; Result += " {\n";
6232 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";
6233 Result += "\tunsigned int count_of_properties;\n";
6234 Result += "\tstruct _prop_t prop_list[";
6235 Result += utostr(property_count); Result += "];\n";
6236 Result += "}";
6237}
6238
6239static void Write__ivar_list_t_TypeDecl(std::string &Result,
6240 unsigned int ivar_count) {
6241 Result += "struct /*_ivar_list_t*/"; Result += " {\n";
6242 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";
6243 Result += "\tunsigned int count;\n";
6244 Result += "\tstruct _ivar_t ivar_list[";
6245 Result += utostr(ivar_count); Result += "];\n";
6246 Result += "}";
6247}
6248
6249static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result,
6250 ArrayRef<ObjCProtocolDecl *> SuperProtocols,
6251 StringRef VarName,
6252 StringRef ProtocolName) {
6253 if (SuperProtocols.size() > 0) {
6254 Result += "\nstatic ";
6255 Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());
6256 Result += " "; Result += VarName;
6257 Result += ProtocolName;
6258 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6259 Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";
6260 for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {
6261 ObjCProtocolDecl *SuperPD = SuperProtocols[i];
6262 Result += "\t&"; Result += "_OBJC_PROTOCOL_";
6263 Result += SuperPD->getNameAsString();
6264 if (i == e-1)
6265 Result += "\n};\n";
6266 else
6267 Result += ",\n";
6268 }
6269 }
6270}
6271
6272static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,
6273 ASTContext *Context, std::string &Result,
6275 StringRef VarName,
6276 StringRef TopLevelDeclName,
6277 bool MethodImpl) {
6278 if (Methods.size() > 0) {
6279 Result += "\nstatic ";
6280 Write_method_list_t_TypeDecl(Result, Methods.size());
6281 Result += " "; Result += VarName;
6282 Result += TopLevelDeclName;
6283 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6284 Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";
6285 Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";
6286 for (unsigned i = 0, e = Methods.size(); i < e; i++) {
6287 ObjCMethodDecl *MD = Methods[i];
6288 if (i == 0)
6289 Result += "\t{{(struct objc_selector *)\"";
6290 else
6291 Result += "\t{(struct objc_selector *)\"";
6292 Result += (MD)->getSelector().getAsString(); Result += "\"";
6293 Result += ", ";
6294 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(MD);
6295 Result += "\""; Result += MethodTypeString; Result += "\"";
6296 Result += ", ";
6297 if (!MethodImpl)
6298 Result += "0";
6299 else {
6300 Result += "(void *)";
6301 Result += RewriteObj.MethodInternalNames[MD];
6302 }
6303 if (i == e-1)
6304 Result += "}}\n";
6305 else
6306 Result += "},\n";
6307 }
6308 Result += "};\n";
6309 }
6310}
6311
6312static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,
6313 ASTContext *Context, std::string &Result,
6315 const Decl *Container,
6316 StringRef VarName,
6317 StringRef ProtocolName) {
6318 if (Properties.size() > 0) {
6319 Result += "\nstatic ";
6320 Write__prop_list_t_TypeDecl(Result, Properties.size());
6321 Result += " "; Result += VarName;
6322 Result += ProtocolName;
6323 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6324 Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";
6325 Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";
6326 for (unsigned i = 0, e = Properties.size(); i < e; i++) {
6327 ObjCPropertyDecl *PropDecl = Properties[i];
6328 if (i == 0)
6329 Result += "\t{{\"";
6330 else
6331 Result += "\t{\"";
6332 Result += PropDecl->getName(); Result += "\",";
6333 std::string PropertyTypeString =
6334 Context->getObjCEncodingForPropertyDecl(PropDecl, Container);
6335 std::string QuotePropertyTypeString;
6336 RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);
6337 Result += "\""; Result += QuotePropertyTypeString; Result += "\"";
6338 if (i == e-1)
6339 Result += "}}\n";
6340 else
6341 Result += "},\n";
6342 }
6343 Result += "};\n";
6344 }
6345}
6346
6347// Metadata flags
6348enum MetaDataDlags {
6349 CLS = 0x0,
6350 CLS_META = 0x1,
6351 CLS_ROOT = 0x2,
6352 OBJC2_CLS_HIDDEN = 0x10,
6353 CLS_EXCEPTION = 0x20,
6354
6355 /// (Obsolete) ARC-specific: this class has a .release_ivars method
6356 CLS_HAS_IVAR_RELEASER = 0x40,
6357 /// class was compiled with -fobjc-arr
6358 CLS_COMPILED_BY_ARC = 0x80 // (1<<7)
6359};
6360
6361static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,
6362 unsigned int flags,
6363 const std::string &InstanceStart,
6364 const std::string &InstanceSize,
6365 ArrayRef<ObjCMethodDecl *>baseMethods,
6366 ArrayRef<ObjCProtocolDecl *>baseProtocols,
6369 StringRef VarName,
6370 StringRef ClassName) {
6371 Result += "\nstatic struct _class_ro_t ";
6372 Result += VarName; Result += ClassName;
6373 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6374 Result += "\t";
6375 Result += llvm::utostr(flags); Result += ", ";
6376 Result += InstanceStart; Result += ", ";
6377 Result += InstanceSize; Result += ", \n";
6378 Result += "\t";
6379 const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
6380 if (Triple.getArch() == llvm::Triple::x86_64)
6381 // uint32_t const reserved; // only when building for 64bit targets
6382 Result += "(unsigned int)0, \n\t";
6383 // const uint8_t * const ivarLayout;
6384 Result += "0, \n\t";
6385 Result += "\""; Result += ClassName; Result += "\",\n\t";
6386 bool metaclass = ((flags & CLS_META) != 0);
6387 if (baseMethods.size() > 0) {
6388 Result += "(const struct _method_list_t *)&";
6389 if (metaclass)
6390 Result += "_OBJC_$_CLASS_METHODS_";
6391 else
6392 Result += "_OBJC_$_INSTANCE_METHODS_";
6393 Result += ClassName;
6394 Result += ",\n\t";
6395 }
6396 else
6397 Result += "0, \n\t";
6398
6399 if (!metaclass && baseProtocols.size() > 0) {
6400 Result += "(const struct _objc_protocol_list *)&";
6401 Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName;
6402 Result += ",\n\t";
6403 }
6404 else
6405 Result += "0, \n\t";
6406
6407 if (!metaclass && ivars.size() > 0) {
6408 Result += "(const struct _ivar_list_t *)&";
6409 Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName;
6410 Result += ",\n\t";
6411 }
6412 else
6413 Result += "0, \n\t";
6414
6415 // weakIvarLayout
6416 Result += "0, \n\t";
6417 if (!metaclass && Properties.size() > 0) {
6418 Result += "(const struct _prop_list_t *)&";
6419 Result += "_OBJC_$_PROP_LIST_"; Result += ClassName;
6420 Result += ",\n";
6421 }
6422 else
6423 Result += "0, \n";
6424
6425 Result += "};\n";
6426}
6427
6428static void Write_class_t(ASTContext *Context, std::string &Result,
6429 StringRef VarName,
6430 const ObjCInterfaceDecl *CDecl, bool metaclass) {
6431 bool rootClass = (!CDecl->getSuperClass());
6432 const ObjCInterfaceDecl *RootClass = CDecl;
6433
6434 if (!rootClass) {
6435 // Find the Root class
6436 RootClass = CDecl->getSuperClass();
6437 while (RootClass->getSuperClass()) {
6438 RootClass = RootClass->getSuperClass();
6439 }
6440 }
6441
6442 if (metaclass && rootClass) {
6443 // Need to handle a case of use of forward declaration.
6444 Result += "\n";
6445 Result += "extern \"C\" ";
6446 if (CDecl->getImplementation())
6447 Result += "__declspec(dllexport) ";
6448 else
6449 Result += "__declspec(dllimport) ";
6450
6451 Result += "struct _class_t OBJC_CLASS_$_";
6452 Result += CDecl->getNameAsString();
6453 Result += ";\n";
6454 }
6455 // Also, for possibility of 'super' metadata class not having been defined yet.
6456 if (!rootClass) {
6457 ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
6458 Result += "\n";
6459 Result += "extern \"C\" ";
6460 if (SuperClass->getImplementation())
6461 Result += "__declspec(dllexport) ";
6462 else
6463 Result += "__declspec(dllimport) ";
6464
6465 Result += "struct _class_t ";
6466 Result += VarName;
6467 Result += SuperClass->getNameAsString();
6468 Result += ";\n";
6469
6470 if (metaclass && RootClass != SuperClass) {
6471 Result += "extern \"C\" ";
6472 if (RootClass->getImplementation())
6473 Result += "__declspec(dllexport) ";
6474 else
6475 Result += "__declspec(dllimport) ";
6476
6477 Result += "struct _class_t ";
6478 Result += VarName;
6479 Result += RootClass->getNameAsString();
6480 Result += ";\n";
6481 }
6482 }
6483
6484 Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";
6485 Result += VarName; Result += CDecl->getNameAsString();
6486 Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";
6487 Result += "\t";
6488 if (metaclass) {
6489 if (!rootClass) {
6490 Result += "0, // &"; Result += VarName;
6491 Result += RootClass->getNameAsString();
6492 Result += ",\n\t";
6493 Result += "0, // &"; Result += VarName;
6494 Result += CDecl->getSuperClass()->getNameAsString();
6495 Result += ",\n\t";
6496 }
6497 else {
6498 Result += "0, // &"; Result += VarName;
6499 Result += CDecl->getNameAsString();
6500 Result += ",\n\t";
6501 Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6502 Result += ",\n\t";
6503 }
6504 }
6505 else {
6506 Result += "0, // &OBJC_METACLASS_$_";
6507 Result += CDecl->getNameAsString();
6508 Result += ",\n\t";
6509 if (!rootClass) {
6510 Result += "0, // &"; Result += VarName;
6511 Result += CDecl->getSuperClass()->getNameAsString();
6512 Result += ",\n\t";
6513 }
6514 else
6515 Result += "0,\n\t";
6516 }
6517 Result += "0, // (void *)&_objc_empty_cache,\n\t";
6518 Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t";
6519 if (metaclass)
6520 Result += "&_OBJC_METACLASS_RO_$_";
6521 else
6522 Result += "&_OBJC_CLASS_RO_$_";
6523 Result += CDecl->getNameAsString();
6524 Result += ",\n};\n";
6525
6526 // Add static function to initialize some of the meta-data fields.
6527 // avoid doing it twice.
6528 if (metaclass)
6529 return;
6530
6531 const ObjCInterfaceDecl *SuperClass =
6532 rootClass ? CDecl : CDecl->getSuperClass();
6533
6534 Result += "static void OBJC_CLASS_SETUP_$_";
6535 Result += CDecl->getNameAsString();
6536 Result += "(void ) {\n";
6537 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6538 Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
6539 Result += RootClass->getNameAsString(); Result += ";\n";
6540
6541 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6542 Result += ".superclass = ";
6543 if (rootClass)
6544 Result += "&OBJC_CLASS_$_";
6545 else
6546 Result += "&OBJC_METACLASS_$_";
6547
6548 Result += SuperClass->getNameAsString(); Result += ";\n";
6549
6550 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6551 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
6552
6553 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6554 Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
6555 Result += CDecl->getNameAsString(); Result += ";\n";
6556
6557 if (!rootClass) {
6558 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6559 Result += ".superclass = "; Result += "&OBJC_CLASS_$_";
6560 Result += SuperClass->getNameAsString(); Result += ";\n";
6561 }
6562
6563 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6564 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
6565 Result += "}\n";
6566}
6567
6568static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
6569 std::string &Result,
6570 ObjCCategoryDecl *CatDecl,
6571 ObjCInterfaceDecl *ClassDecl,
6572 ArrayRef<ObjCMethodDecl *> InstanceMethods,
6573 ArrayRef<ObjCMethodDecl *> ClassMethods,
6574 ArrayRef<ObjCProtocolDecl *> RefedProtocols,
6575 ArrayRef<ObjCPropertyDecl *> ClassProperties) {
6576 StringRef CatName = CatDecl->getName();
6577 StringRef ClassName = ClassDecl->getName();
6578 // must declare an extern class object in case this class is not implemented
6579 // in this TU.
6580 Result += "\n";
6581 Result += "extern \"C\" ";
6582 if (ClassDecl->getImplementation())
6583 Result += "__declspec(dllexport) ";
6584 else
6585 Result += "__declspec(dllimport) ";
6586
6587 Result += "struct _class_t ";
6588 Result += "OBJC_CLASS_$_"; Result += ClassName;
6589 Result += ";\n";
6590
6591 Result += "\nstatic struct _category_t ";
6592 Result += "_OBJC_$_CATEGORY_";
6593 Result += ClassName; Result += "_$_"; Result += CatName;
6594 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
6595 Result += "{\n";
6596 Result += "\t\""; Result += ClassName; Result += "\",\n";
6597 Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;
6598 Result += ",\n";
6599 if (InstanceMethods.size() > 0) {
6600 Result += "\t(const struct _method_list_t *)&";
6601 Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
6602 Result += ClassName; Result += "_$_"; Result += CatName;
6603 Result += ",\n";
6604 }
6605 else
6606 Result += "\t0,\n";
6607
6608 if (ClassMethods.size() > 0) {
6609 Result += "\t(const struct _method_list_t *)&";
6610 Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";
6611 Result += ClassName; Result += "_$_"; Result += CatName;
6612 Result += ",\n";
6613 }
6614 else
6615 Result += "\t0,\n";
6616
6617 if (RefedProtocols.size() > 0) {
6618 Result += "\t(const struct _protocol_list_t *)&";
6619 Result += "_OBJC_CATEGORY_PROTOCOLS_$_";
6620 Result += ClassName; Result += "_$_"; Result += CatName;
6621 Result += ",\n";
6622 }
6623 else
6624 Result += "\t0,\n";
6625
6626 if (ClassProperties.size() > 0) {
6627 Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_";
6628 Result += ClassName; Result += "_$_"; Result += CatName;
6629 Result += ",\n";
6630 }
6631 else
6632 Result += "\t0,\n";
6633
6634 Result += "};\n";
6635
6636 // Add static function to initialize the class pointer in the category structure.
6637 Result += "static void OBJC_CATEGORY_SETUP_$_";
6638 Result += ClassDecl->getNameAsString();
6639 Result += "_$_";
6640 Result += CatName;
6641 Result += "(void ) {\n";
6642 Result += "\t_OBJC_$_CATEGORY_";
6643 Result += ClassDecl->getNameAsString();
6644 Result += "_$_";
6645 Result += CatName;
6646 Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName;
6647 Result += ";\n}\n";
6648}
6649
6650static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,
6651 ASTContext *Context, std::string &Result,
6653 StringRef VarName,
6654 StringRef ProtocolName) {
6655 if (Methods.size() == 0)
6656 return;
6657
6658 Result += "\nstatic const char *";
6659 Result += VarName; Result += ProtocolName;
6660 Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
6661 Result += "{\n";
6662 for (unsigned i = 0, e = Methods.size(); i < e; i++) {
6663 ObjCMethodDecl *MD = Methods[i];
6664 std::string MethodTypeString =
6665 Context->getObjCEncodingForMethodDecl(MD, true);
6666 std::string QuoteMethodTypeString;
6667 RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);
6668 Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";
6669 if (i == e-1)
6670 Result += "\n};\n";
6671 else {
6672 Result += ",\n";
6673 }
6674 }
6675}
6676
6677static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,
6678 ASTContext *Context,
6679 std::string &Result,
6681 ObjCInterfaceDecl *CDecl) {
6682 // FIXME. visibility of offset symbols may have to be set; for Darwin
6683 // this is what happens:
6684 /**
6685 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6686 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6687 Class->getVisibility() == HiddenVisibility)
6688 Visibility should be: HiddenVisibility;
6689 else
6690 Visibility should be: DefaultVisibility;
6691 */
6692
6693 Result += "\n";
6694 for (unsigned i =0, e = Ivars.size(); i < e; i++) {
6695 ObjCIvarDecl *IvarDecl = Ivars[i];
6696 if (Context->getLangOpts().MicrosoftExt)
6697 Result += "__declspec(allocate(\".objc_ivar$B\")) ";
6698
6699 if (!Context->getLangOpts().MicrosoftExt ||
6700 IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||
6702 Result += "extern \"C\" unsigned long int ";
6703 else
6704 Result += "extern \"C\" __declspec(dllexport) unsigned long int ";
6705 if (Ivars[i]->isBitField())
6706 RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
6707 else
6708 WriteInternalIvarName(CDecl, IvarDecl, Result);
6709 Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))";
6710 Result += " = ";
6711 RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result);
6712 Result += ";\n";
6713 if (Ivars[i]->isBitField()) {
6714 // skip over rest of the ivar bitfields.
6715 SKIP_BITFIELDS(i , e, Ivars);
6716 }
6717 }
6718}
6719
6720static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,
6721 ASTContext *Context, std::string &Result,
6722 ArrayRef<ObjCIvarDecl *> OriginalIvars,
6723 StringRef VarName,
6724 ObjCInterfaceDecl *CDecl) {
6725 if (OriginalIvars.size() > 0) {
6726 Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl);
6728 // strip off all but the first ivar bitfield from each group of ivars.
6729 // Such ivars in the ivar list table will be replaced by their grouping struct
6730 // 'ivar'.
6731 for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) {
6732 if (OriginalIvars[i]->isBitField()) {
6733 Ivars.push_back(OriginalIvars[i]);
6734 // skip over rest of the ivar bitfields.
6735 SKIP_BITFIELDS(i , e, OriginalIvars);
6736 }
6737 else
6738 Ivars.push_back(OriginalIvars[i]);
6739 }
6740
6741 Result += "\nstatic ";
6742 Write__ivar_list_t_TypeDecl(Result, Ivars.size());
6743 Result += " "; Result += VarName;
6744 Result += CDecl->getNameAsString();
6745 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6746 Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n";
6747 Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n";
6748 for (unsigned i =0, e = Ivars.size(); i < e; i++) {
6749 ObjCIvarDecl *IvarDecl = Ivars[i];
6750 if (i == 0)
6751 Result += "\t{{";
6752 else
6753 Result += "\t {";
6754 Result += "(unsigned long int *)&";
6755 if (Ivars[i]->isBitField())
6756 RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
6757 else
6758 WriteInternalIvarName(CDecl, IvarDecl, Result);
6759 Result += ", ";
6760
6761 Result += "\"";
6762 if (Ivars[i]->isBitField())
6763 RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result);
6764 else
6765 Result += IvarDecl->getName();
6766 Result += "\", ";
6767
6768 QualType IVQT = IvarDecl->getType();
6769 if (IvarDecl->isBitField())
6770 IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl);
6771
6772 std::string IvarTypeString, QuoteIvarTypeString;
6773 Context->getObjCEncodingForType(IVQT, IvarTypeString,
6774 IvarDecl);
6775 RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);
6776 Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";
6777
6778 // FIXME. this alignment represents the host alignment and need be changed to
6779 // represent the target alignment.
6780 unsigned Align = Context->getTypeAlign(IVQT)/8;
6781 Align = llvm::Log2_32(Align);
6782 Result += llvm::utostr(Align); Result += ", ";
6783 CharUnits Size = Context->getTypeSizeInChars(IVQT);
6784 Result += llvm::utostr(Size.getQuantity());
6785 if (i == e-1)
6786 Result += "}}\n";
6787 else
6788 Result += "},\n";
6789 }
6790 Result += "};\n";
6791 }
6792}
6793
6794/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
6795void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
6796 std::string &Result) {
6797
6798 // Do not synthesize the protocol more than once.
6799 if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
6800 return;
6801 WriteModernMetadataDeclarations(Context, Result);
6802
6803 if (ObjCProtocolDecl *Def = PDecl->getDefinition())
6804 PDecl = Def;
6805 // Must write out all protocol definitions in current qualifier list,
6806 // and in their nested qualifiers before writing out current definition.
6807 for (auto *I : PDecl->protocols())
6808 RewriteObjCProtocolMetaData(I, Result);
6809
6810 // Construct method lists.
6811 std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;
6812 std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;
6813 for (auto *MD : PDecl->instance_methods()) {
6815 OptInstanceMethods.push_back(MD);
6816 } else {
6817 InstanceMethods.push_back(MD);
6818 }
6819 }
6820
6821 for (auto *MD : PDecl->class_methods()) {
6823 OptClassMethods.push_back(MD);
6824 } else {
6825 ClassMethods.push_back(MD);
6826 }
6827 }
6828 std::vector<ObjCMethodDecl *> AllMethods;
6829 for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++)
6830 AllMethods.push_back(InstanceMethods[i]);
6831 for (unsigned i = 0, e = ClassMethods.size(); i < e; i++)
6832 AllMethods.push_back(ClassMethods[i]);
6833 for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++)
6834 AllMethods.push_back(OptInstanceMethods[i]);
6835 for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++)
6836 AllMethods.push_back(OptClassMethods[i]);
6837
6838 Write__extendedMethodTypes_initializer(*this, Context, Result,
6839 AllMethods,
6840 "_OBJC_PROTOCOL_METHOD_TYPES_",
6841 PDecl->getNameAsString());
6842 // Protocol's super protocol list
6843 SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());
6844 Write_protocol_list_initializer(Context, Result, SuperProtocols,
6845 "_OBJC_PROTOCOL_REFS_",
6846 PDecl->getNameAsString());
6847
6848 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
6849 "_OBJC_PROTOCOL_INSTANCE_METHODS_",
6850 PDecl->getNameAsString(), false);
6851
6852 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
6853 "_OBJC_PROTOCOL_CLASS_METHODS_",
6854 PDecl->getNameAsString(), false);
6855
6856 Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,
6857 "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",
6858 PDecl->getNameAsString(), false);
6859
6860 Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,
6861 "_OBJC_PROTOCOL_OPT_CLASS_METHODS_",
6862 PDecl->getNameAsString(), false);
6863
6864 // Protocol's property metadata.
6865 SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(
6866 PDecl->instance_properties());
6867 Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,
6868 /* Container */nullptr,
6869 "_OBJC_PROTOCOL_PROPERTIES_",
6870 PDecl->getNameAsString());
6871
6872 // Writer out root metadata for current protocol: struct _protocol_t
6873 Result += "\n";
6874 if (LangOpts.MicrosoftExt)
6875 Result += "static ";
6876 Result += "struct _protocol_t _OBJC_PROTOCOL_";
6877 Result += PDecl->getNameAsString();
6878 Result += " __attribute__ ((used)) = {\n";
6879 Result += "\t0,\n"; // id is; is null
6880 Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n";
6881 if (SuperProtocols.size() > 0) {
6882 Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_";
6883 Result += PDecl->getNameAsString(); Result += ",\n";
6884 }
6885 else
6886 Result += "\t0,\n";
6887 if (InstanceMethods.size() > 0) {
6888 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
6889 Result += PDecl->getNameAsString(); Result += ",\n";
6890 }
6891 else
6892 Result += "\t0,\n";
6893
6894 if (ClassMethods.size() > 0) {
6895 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";
6896 Result += PDecl->getNameAsString(); Result += ",\n";
6897 }
6898 else
6899 Result += "\t0,\n";
6900
6901 if (OptInstanceMethods.size() > 0) {
6902 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";
6903 Result += PDecl->getNameAsString(); Result += ",\n";
6904 }
6905 else
6906 Result += "\t0,\n";
6907
6908 if (OptClassMethods.size() > 0) {
6909 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";
6910 Result += PDecl->getNameAsString(); Result += ",\n";
6911 }
6912 else
6913 Result += "\t0,\n";
6914
6915 if (ProtocolProperties.size() > 0) {
6916 Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";
6917 Result += PDecl->getNameAsString(); Result += ",\n";
6918 }
6919 else
6920 Result += "\t0,\n";
6921
6922 Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";
6923 Result += "\t0,\n";
6924
6925 if (AllMethods.size() > 0) {
6926 Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";
6927 Result += PDecl->getNameAsString();
6928 Result += "\n};\n";
6929 }
6930 else
6931 Result += "\t0\n};\n";
6932
6933 if (LangOpts.MicrosoftExt)
6934 Result += "static ";
6935 Result += "struct _protocol_t *";
6936 Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();
6937 Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
6938 Result += ";\n";
6939
6940 // Mark this protocol as having been generated.
6941 if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
6942 llvm_unreachable("protocol already synthesized");
6943}
6944
6945/// hasObjCExceptionAttribute - Return true if this class or any super
6946/// class has the __objc_exception__ attribute.
6947/// FIXME. Move this to ASTContext.cpp as it is also used for IRGen.
6948static bool hasObjCExceptionAttribute(ASTContext &Context,
6949 const ObjCInterfaceDecl *OID) {
6950 if (OID->hasAttr<ObjCExceptionAttr>())
6951 return true;
6952 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
6953 return hasObjCExceptionAttribute(Context, Super);
6954 return false;
6955}
6956
6957void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
6958 std::string &Result) {
6959 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
6960
6961 // Explicitly declared @interface's are already synthesized.
6962 if (CDecl->isImplicitInterfaceDecl())
6963 assert(false &&
6964 "Legacy implicit interface rewriting not supported in moder abi");
6965
6966 WriteModernMetadataDeclarations(Context, Result);
6968
6969 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
6970 IVD; IVD = IVD->getNextIvar()) {
6971 // Ignore unnamed bit-fields.
6972 if (!IVD->getDeclName())
6973 continue;
6974 IVars.push_back(IVD);
6975 }
6976
6977 Write__ivar_list_t_initializer(*this, Context, Result, IVars,
6978 "_OBJC_$_INSTANCE_VARIABLES_",
6979 CDecl);
6980
6981 // Build _objc_method_list for class's instance methods if needed
6982 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
6983
6984 // If any of our property implementations have associated getters or
6985 // setters, produce metadata for them as well.
6986 for (const auto *Prop : IDecl->property_impls()) {
6987 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
6988 continue;
6989 if (!Prop->getPropertyIvarDecl())
6990 continue;
6991 ObjCPropertyDecl *PD = Prop->getPropertyDecl();
6992 if (!PD)
6993 continue;
6994 if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
6995 if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))
6996 InstanceMethods.push_back(Getter);
6997 if (PD->isReadOnly())
6998 continue;
6999 if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
7000 if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))
7001 InstanceMethods.push_back(Setter);
7002 }
7003
7004 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
7005 "_OBJC_$_INSTANCE_METHODS_",
7006 IDecl->getNameAsString(), true);
7007
7008 SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
7009
7010 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
7011 "_OBJC_$_CLASS_METHODS_",
7012 IDecl->getNameAsString(), true);
7013
7014 // Protocols referenced in class declaration?
7015 // Protocol's super protocol list
7016 std::vector<ObjCProtocolDecl *> RefedProtocols;
7017 const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();
7018 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
7019 E = Protocols.end();
7020 I != E; ++I) {
7021 RefedProtocols.push_back(*I);
7022 // Must write out all protocol definitions in current qualifier list,
7023 // and in their nested qualifiers before writing out current definition.
7024 RewriteObjCProtocolMetaData(*I, Result);
7025 }
7026
7027 Write_protocol_list_initializer(Context, Result,
7028 RefedProtocols,
7029 "_OBJC_CLASS_PROTOCOLS_$_",
7030 IDecl->getNameAsString());
7031
7032 // Protocol's property metadata.
7033 SmallVector<ObjCPropertyDecl *, 8> ClassProperties(
7034 CDecl->instance_properties());
7035 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
7036 /* Container */IDecl,
7037 "_OBJC_$_PROP_LIST_",
7038 CDecl->getNameAsString());
7039
7040 // Data for initializing _class_ro_t metaclass meta-data
7041 uint32_t flags = CLS_META;
7042 std::string InstanceSize;
7043 std::string InstanceStart;
7044
7045 bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;
7046 if (classIsHidden)
7047 flags |= OBJC2_CLS_HIDDEN;
7048
7049 if (!CDecl->getSuperClass())
7050 // class is root
7051 flags |= CLS_ROOT;
7052 InstanceSize = "sizeof(struct _class_t)";
7053 InstanceStart = InstanceSize;
7054 Write__class_ro_t_initializer(Context, Result, flags,
7055 InstanceStart, InstanceSize,
7056 ClassMethods,
7057 nullptr,
7058 nullptr,
7059 nullptr,
7060 "_OBJC_METACLASS_RO_$_",
7061 CDecl->getNameAsString());
7062
7063 // Data for initializing _class_ro_t meta-data
7064 flags = CLS;
7065 if (classIsHidden)
7066 flags |= OBJC2_CLS_HIDDEN;
7067
7068 if (hasObjCExceptionAttribute(*Context, CDecl))
7069 flags |= CLS_EXCEPTION;
7070
7071 if (!CDecl->getSuperClass())
7072 // class is root
7073 flags |= CLS_ROOT;
7074
7075 InstanceSize.clear();
7076 InstanceStart.clear();
7077 if (!ObjCSynthesizedStructs.count(CDecl)) {
7078 InstanceSize = "0";
7079 InstanceStart = "0";
7080 }
7081 else {
7082 InstanceSize = "sizeof(struct ";
7083 InstanceSize += CDecl->getNameAsString();
7084 InstanceSize += "_IMPL)";
7085
7086 ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
7087 if (IVD) {
7088 RewriteIvarOffsetComputation(IVD, InstanceStart);
7089 }
7090 else
7091 InstanceStart = InstanceSize;
7092 }
7093 Write__class_ro_t_initializer(Context, Result, flags,
7094 InstanceStart, InstanceSize,
7095 InstanceMethods,
7096 RefedProtocols,
7097 IVars,
7098 ClassProperties,
7099 "_OBJC_CLASS_RO_$_",
7100 CDecl->getNameAsString());
7101
7102 Write_class_t(Context, Result,
7103 "OBJC_METACLASS_$_",
7104 CDecl, /*metaclass*/true);
7105
7106 Write_class_t(Context, Result,
7107 "OBJC_CLASS_$_",
7108 CDecl, /*metaclass*/false);
7109
7110 if (ImplementationIsNonLazy(IDecl))
7111 DefinedNonLazyClasses.push_back(CDecl);
7112}
7113
7114void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {
7115 int ClsDefCount = ClassImplementation.size();
7116 if (!ClsDefCount)
7117 return;
7118 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
7119 Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
7120 Result += "static void *OBJC_CLASS_SETUP[] = {\n";
7121 for (int i = 0; i < ClsDefCount; i++) {
7122 ObjCImplementationDecl *IDecl = ClassImplementation[i];
7123 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
7124 Result += "\t(void *)&OBJC_CLASS_SETUP_$_";
7125 Result += CDecl->getName(); Result += ",\n";
7126 }
7127 Result += "};\n";
7128}
7129
7130void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
7131 int ClsDefCount = ClassImplementation.size();
7132 int CatDefCount = CategoryImplementation.size();
7133
7134 // For each implemented class, write out all its meta data.
7135 for (int i = 0; i < ClsDefCount; i++)
7136 RewriteObjCClassMetaData(ClassImplementation[i], Result);
7137
7138 RewriteClassSetupInitHook(Result);
7139
7140 // For each implemented category, write out all its meta data.
7141 for (int i = 0; i < CatDefCount; i++)
7142 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
7143
7144 RewriteCategorySetupInitHook(Result);
7145
7146 if (ClsDefCount > 0) {
7147 if (LangOpts.MicrosoftExt)
7148 Result += "__declspec(allocate(\".objc_classlist$B\")) ";
7149 Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";
7150 Result += llvm::utostr(ClsDefCount); Result += "]";
7151 Result +=
7152 " __attribute__((used, section (\"__DATA, __objc_classlist,"
7153 "regular,no_dead_strip\")))= {\n";
7154 for (int i = 0; i < ClsDefCount; i++) {
7155 Result += "\t&OBJC_CLASS_$_";
7156 Result += ClassImplementation[i]->getNameAsString();
7157 Result += ",\n";
7158 }
7159 Result += "};\n";
7160
7161 if (!DefinedNonLazyClasses.empty()) {
7162 if (LangOpts.MicrosoftExt)
7163 Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";
7164 Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t";
7165 for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) {
7166 Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString();
7167 Result += ",\n";
7168 }
7169 Result += "};\n";
7170 }
7171 }
7172
7173 if (CatDefCount > 0) {
7174 if (LangOpts.MicrosoftExt)
7175 Result += "__declspec(allocate(\".objc_catlist$B\")) ";
7176 Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";
7177 Result += llvm::utostr(CatDefCount); Result += "]";
7178 Result +=
7179 " __attribute__((used, section (\"__DATA, __objc_catlist,"
7180 "regular,no_dead_strip\")))= {\n";
7181 for (int i = 0; i < CatDefCount; i++) {
7182 Result += "\t&_OBJC_$_CATEGORY_";
7183 Result +=
7184 CategoryImplementation[i]->getClassInterface()->getNameAsString();
7185 Result += "_$_";
7186 Result += CategoryImplementation[i]->getNameAsString();
7187 Result += ",\n";
7188 }
7189 Result += "};\n";
7190 }
7191
7192 if (!DefinedNonLazyCategories.empty()) {
7193 if (LangOpts.MicrosoftExt)
7194 Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";
7195 Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";
7196 for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {
7197 Result += "\t&_OBJC_$_CATEGORY_";
7198 Result +=
7199 DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();
7200 Result += "_$_";
7201 Result += DefinedNonLazyCategories[i]->getNameAsString();
7202 Result += ",\n";
7203 }
7204 Result += "};\n";
7205 }
7206}
7207
7208void RewriteModernObjC::WriteImageInfo(std::string &Result) {
7209 if (LangOpts.MicrosoftExt)
7210 Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";
7211
7212 Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";
7213 // version 0, ObjCABI is 2
7214 Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";
7215}
7216
7217/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
7218/// implementation.
7219void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
7220 std::string &Result) {
7221 WriteModernMetadataDeclarations(Context, Result);
7222 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
7223 // Find category declaration for this implementation.
7224 ObjCCategoryDecl *CDecl
7225 = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
7226
7227 std::string FullCategoryName = ClassDecl->getNameAsString();
7228 FullCategoryName += "_$_";
7229 FullCategoryName += CDecl->getNameAsString();
7230
7231 // Build _objc_method_list for class's instance methods if needed
7232 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
7233
7234 // If any of our property implementations have associated getters or
7235 // setters, produce metadata for them as well.
7236 for (const auto *Prop : IDecl->property_impls()) {
7237 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
7238 continue;
7239 if (!Prop->getPropertyIvarDecl())
7240 continue;
7241 ObjCPropertyDecl *PD = Prop->getPropertyDecl();
7242 if (!PD)
7243 continue;
7244 if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
7245 InstanceMethods.push_back(Getter);
7246 if (PD->isReadOnly())
7247 continue;
7248 if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
7249 InstanceMethods.push_back(Setter);
7250 }
7251
7252 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
7253 "_OBJC_$_CATEGORY_INSTANCE_METHODS_",
7254 FullCategoryName, true);
7255
7256 SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
7257
7258 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
7259 "_OBJC_$_CATEGORY_CLASS_METHODS_",
7260 FullCategoryName, true);
7261
7262 // Protocols referenced in class declaration?
7263 // Protocol's super protocol list
7264 SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols());
7265 for (auto *I : CDecl->protocols())
7266 // Must write out all protocol definitions in current qualifier list,
7267 // and in their nested qualifiers before writing out current definition.
7268 RewriteObjCProtocolMetaData(I, Result);
7269
7270 Write_protocol_list_initializer(Context, Result,
7271 RefedProtocols,
7272 "_OBJC_CATEGORY_PROTOCOLS_$_",
7273 FullCategoryName);
7274
7275 // Protocol's property metadata.
7276 SmallVector<ObjCPropertyDecl *, 8> ClassProperties(
7277 CDecl->instance_properties());
7278 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
7279 /* Container */IDecl,
7280 "_OBJC_$_PROP_LIST_",
7281 FullCategoryName);
7282
7283 Write_category_t(*this, Context, Result,
7284 CDecl,
7285 ClassDecl,
7286 InstanceMethods,
7287 ClassMethods,
7288 RefedProtocols,
7289 ClassProperties);
7290
7291 // Determine if this category is also "non-lazy".
7292 if (ImplementationIsNonLazy(IDecl))
7293 DefinedNonLazyCategories.push_back(CDecl);
7294}
7295
7296void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) {
7297 int CatDefCount = CategoryImplementation.size();
7298 if (!CatDefCount)
7299 return;
7300 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
7301 Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
7302 Result += "static void *OBJC_CATEGORY_SETUP[] = {\n";
7303 for (int i = 0; i < CatDefCount; i++) {
7304 ObjCCategoryImplDecl *IDecl = CategoryImplementation[i];
7305 ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl();
7306 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
7307 Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_";
7308 Result += ClassDecl->getName();
7309 Result += "_$_";
7310 Result += CatDecl->getName();
7311 Result += ",\n";
7312 }
7313 Result += "};\n";
7314}
7315
7316// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
7317/// class methods.
7318template<typename MethodIterator>
7319void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
7320 MethodIterator MethodEnd,
7321 bool IsInstanceMethod,
7322 StringRef prefix,
7323 StringRef ClassName,
7324 std::string &Result) {
7325 if (MethodBegin == MethodEnd) return;
7326
7327 if (!objc_impl_method) {
7328 /* struct _objc_method {
7329 SEL _cmd;
7330 char *method_types;
7331 void *_imp;
7332 }
7333 */
7334 Result += "\nstruct _objc_method {\n";
7335 Result += "\tSEL _cmd;\n";
7336 Result += "\tchar *method_types;\n";
7337 Result += "\tvoid *_imp;\n";
7338 Result += "};\n";
7339
7340 objc_impl_method = true;
7341 }
7342
7343 // Build _objc_method_list for class's methods if needed
7344
7345 /* struct {
7346 struct _objc_method_list *next_method;
7347 int method_count;
7348 struct _objc_method method_list[];
7349 }
7350 */
7351 unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
7352 Result += "\n";
7353 if (LangOpts.MicrosoftExt) {
7354 if (IsInstanceMethod)
7355 Result += "__declspec(allocate(\".inst_meth$B\")) ";
7356 else
7357 Result += "__declspec(allocate(\".cls_meth$B\")) ";
7358 }
7359 Result += "static struct {\n";
7360 Result += "\tstruct _objc_method_list *next_method;\n";
7361 Result += "\tint method_count;\n";
7362 Result += "\tstruct _objc_method method_list[";
7363 Result += utostr(NumMethods);
7364 Result += "];\n} _OBJC_";
7365 Result += prefix;
7366 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
7367 Result += "_METHODS_";
7368 Result += ClassName;
7369 Result += " __attribute__ ((used, section (\"__OBJC, __";
7370 Result += IsInstanceMethod ? "inst" : "cls";
7371 Result += "_meth\")))= ";
7372 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
7373
7374 Result += "\t,{{(SEL)\"";
7375 Result += (*MethodBegin)->getSelector().getAsString().c_str();
7376 std::string MethodTypeString;
7377 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
7378 Result += "\", \"";
7379 Result += MethodTypeString;
7380 Result += "\", (void *)";
7381 Result += MethodInternalNames[*MethodBegin];
7382 Result += "}\n";
7383 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
7384 Result += "\t ,{(SEL)\"";
7385 Result += (*MethodBegin)->getSelector().getAsString().c_str();
7386 std::string MethodTypeString;
7387 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
7388 Result += "\", \"";
7389 Result += MethodTypeString;
7390 Result += "\", (void *)";
7391 Result += MethodInternalNames[*MethodBegin];
7392 Result += "}\n";
7393 }
7394 Result += "\t }\n};\n";
7395}
7396
7397Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
7398 SourceRange OldRange = IV->getSourceRange();
7399 Expr *BaseExpr = IV->getBase();
7400
7401 // Rewrite the base, but without actually doing replaces.
7402 {
7403 DisableReplaceStmtScope S(*this);
7404 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
7405 IV->setBase(BaseExpr);
7406 }
7407
7408 ObjCIvarDecl *D = IV->getDecl();
7409
7410 Expr *Replacement = IV;
7411
7412 if (BaseExpr->getType()->isObjCObjectPointerType()) {
7413 const ObjCInterfaceType *iFaceDecl =
7414 dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
7415 assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
7416 // lookup which class implements the instance variable.
7417 ObjCInterfaceDecl *clsDeclared = nullptr;
7418 iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
7419 clsDeclared);
7420 assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
7421
7422 // Build name of symbol holding ivar offset.
7423 std::string IvarOffsetName;
7424 if (D->isBitField())
7425 ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
7426 else
7427 WriteInternalIvarName(clsDeclared, D, IvarOffsetName);
7428
7429 ReferencedIvars[clsDeclared].insert(D);
7430
7431 // cast offset to "char *".
7432 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,
7433 Context->getPointerType(Context->CharTy),
7434 CK_BitCast,
7435 BaseExpr);
7436 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
7437 SourceLocation(), &Context->Idents.get(IvarOffsetName),
7438 Context->UnsignedLongTy, nullptr,
7439 SC_Extern);
7440 DeclRefExpr *DRE = new (Context)
7441 DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy,
7442 VK_LValue, SourceLocation());
7444 *Context, castExpr, DRE, BO_Add,
7445 Context->getPointerType(Context->CharTy), VK_PRValue, OK_Ordinary,
7446 SourceLocation(), FPOptionsOverride());
7447 // Don't forget the parens to enforce the proper binding.
7448 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
7449 SourceLocation(),
7450 addExpr);
7451 QualType IvarT = D->getType();
7452 if (D->isBitField())
7453 IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
7454
7455 if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {
7456 RecordDecl *RD = IvarT->castAsCanonical<RecordType>()->getDecl();
7457 RD = RD->getDefinition();
7458 if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
7459 // decltype(((Foo_IMPL*)0)->bar) *
7460 auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());
7461 // ivar in class extensions requires special treatment.
7462 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
7463 CDecl = CatDecl->getClassInterface();
7464 std::string RecName = std::string(CDecl->getName());
7465 RecName += "_IMPL";
7467 *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),
7468 SourceLocation(), &Context->Idents.get(RecName));
7469 QualType PtrStructIMPL =
7470 Context->getPointerType(Context->getCanonicalTagType(RD));
7471 unsigned UnsignedIntSize =
7472 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
7473 Expr *Zero = IntegerLiteral::Create(*Context,
7474 llvm::APInt(UnsignedIntSize, 0),
7475 Context->UnsignedIntTy, SourceLocation());
7476 Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
7477 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
7478 Zero);
7479 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
7480 SourceLocation(),
7481 &Context->Idents.get(D->getNameAsString()),
7482 IvarT, nullptr,
7483 /*BitWidth=*/nullptr,
7484 /*Mutable=*/true, ICIS_NoInit);
7486 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
7487 IvarT = Context->getDecltypeType(ME, ME->getType());
7488 }
7489 }
7490 convertObjCTypeToCStyleType(IvarT);
7491 QualType castT = Context->getPointerType(IvarT);
7492
7493 castExpr = NoTypeInfoCStyleCastExpr(Context,
7494 castT,
7495 CK_BitCast,
7496 PE);
7497
7499 const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT,
7500 VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
7501 PE = new (Context) ParenExpr(OldRange.getBegin(),
7502 OldRange.getEnd(),
7503 Exp);
7504
7505 if (D->isBitField()) {
7506 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
7507 SourceLocation(),
7508 &Context->Idents.get(D->getNameAsString()),
7509 D->getType(), nullptr,
7510 /*BitWidth=*/D->getBitWidth(),
7511 /*Mutable=*/true, ICIS_NoInit);
7512 MemberExpr *ME =
7513 MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD,
7514 FD->getType(), VK_LValue, OK_Ordinary);
7515 Replacement = ME;
7516
7517 }
7518 else
7519 Replacement = PE;
7520 }
7521
7522 ReplaceStmtWithRange(IV, Replacement, OldRange);
7523 return Replacement;
7524}
7525
7526#endif // CLANG_ENABLE_OBJC_REWRITER
Defines the Diagnostic-related interfaces.
static bool hasObjCExceptionAttribute(ASTContext &Context, const ObjCInterfaceDecl *OID)
hasObjCExceptionAttribute - Return true if this class or any super class has the objc_exception attri...
TokenType getType() const
Returns the token's type, e.g.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Result
Implement __builtin_bit_cast and related operations.
#define X(type, name)
Definition Value.h:97
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static bool hasAttr(const Decl *D, bool IgnoreImplicitAttr)
Definition SemaCUDA.cpp:183
Defines the SourceManager interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType getObjCClassType() const
Represents the Objective-C Class type.
FullSourceLoc getFullLoc(SourceLocation Loc) const
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
IdentifierTable & Idents
Definition ASTContext.h:823
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
SelectorTable & Selectors
Definition ASTContext.h:824
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type.
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType CharTy
QualType getObjCIdType() const
Represents the Objective-CC id type.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Represents a member of a struct/union/class.
Definition Decl.h:3294
static FieldDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle)
Definition Decl.cpp:4763
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
Definition ASTConsumer.h:35
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3836
QualType getElementType() const
Definition TypeBase.h:3848
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4049
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
Definition Expr.cpp:5108
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition Decl.h:4806
param_iterator param_end()
Definition Decl.h:4905
MutableArrayRef< ParmVarDecl * >::iterator param_iterator
Definition Decl.h:4900
param_iterator param_begin()
Definition Decl.h:4904
ArrayRef< Capture > captures() const
Definition Decl.h:4933
bool param_empty() const
Definition Decl.h:4903
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition Expr.h:6689
const Stmt * getBody() const
Definition Expr.cpp:2552
const FunctionProtoType * getFunctionType() const
getFunctionType - Return the underlying function type for this block.
Definition Expr.cpp:2543
const BlockDecl * getBlockDecl() const
Definition Expr.h:6701
Pointer to a block type.
Definition TypeBase.h:3656
QualType getPointeeType() const
Definition TypeBase.h:3668
BreakStmt - This represents a break.
Definition Stmt.h:3144
CStyleCastExpr - An explicit cast in C (C99 6.5.4) or a C-style cast in C++ (C++ [expr....
Definition Expr.h:3980
SourceLocation getRParenLoc() const
Definition Expr.h:4015
SourceLocation getLParenLoc() const
Definition Expr.h:4012
Represents a call to a C++ constructor.
Definition ExprCXX.h:1551
Represents a C++ constructor within a class.
Definition DeclCXX.h:2637
bool isDefaultConstructor() const
Whether this constructor is a default constructor (C++ [class.ctor]p5), which can be used to default-...
Definition DeclCXX.cpp:3049
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2954
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition Expr.cpp:1523
ExprIterator arg_iterator
Definition Expr.h:3201
arg_iterator arg_begin()
Definition Expr.h:3211
arg_iterator arg_end()
Definition Expr.h:3214
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3687
CastKind getCastKind() const
Definition Expr.h:3731
Expr * getSubExpr()
Definition Expr.h:3737
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3616
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1749
SourceLocation getBeginLoc() const
Definition Stmt.h:1863
SourceLocation getEndLoc() const
Definition Stmt.h:1864
ConditionalOperator - The ?
Definition Expr.h:4402
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3874
ContinueStmt - This represents a continue.
Definition Stmt.h:3128
decl_iterator - Iterates through the declarations stored within this context.
Definition DeclBase.h:2360
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
bool isFileContext() const
Definition DeclBase.h:2197
DeclContext * getRedeclContext()
getRedeclContext - Retrieve the context in which an entity conflicts with other entities of the same ...
void addDecl(Decl *D)
Add the declaration D into this context.
iterator begin()
Definition DeclGroup.h:95
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1281
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
Definition Expr.h:1485
ValueDecl * getDecl()
Definition Expr.h:1349
SourceLocation getLocation() const
Definition Expr.h:1357
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1640
decl_iterator decl_end()
Definition Stmt.h:1695
decl_iterator decl_begin()
Definition Stmt.h:1694
DeclGroupRef::iterator decl_iterator
Definition Stmt.h:1683
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition DeclBase.h:443
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
TranslationUnitDecl * getTranslationUnitDecl()
Definition DeclBase.cpp:535
bool hasAttr() const
Definition DeclBase.h:585
Kind getKind() const
Definition DeclBase.h:450
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
SourceLocation getTypeSpecStartLoc() const
Definition Decl.cpp:2005
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:234
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition Diagnostic.h:926
bool hasErrorOccurred() const
Definition Diagnostic.h:893
Represents an enum.
Definition Decl.h:4145
This represents one expression.
Definition Expr.h:112
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:447
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3101
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3089
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3397
Expr * getBitWidth() const
Returns the expression that represents the bit width, if this field is a bit field.
Definition Decl.h:3410
Represents a function declaration or definition.
Definition Decl.h:2058
static FunctionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass SC, bool UsesFPIntrin=false, bool isInlineSpecified=false, bool hasWrittenPrototype=true, ConstexprSpecKind ConstexprKind=ConstexprSpecKind::Unspecified, const AssociatedConstraint &TrailingRequiresClause={})
Definition Decl.h:2302
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
Definition Decl.cpp:3267
bool isThisDeclarationADefinition() const
Returns whether this specific declaration of the function is also a definition that does not contain ...
Definition Decl.h:2427
bool isVariadic() const
Whether this function is variadic.
Definition Decl.cpp:3120
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:3018
bool isExternC() const
Determines whether this function is a function with external, C linkage.
Definition Decl.cpp:3661
bool isMain() const
Determines whether this function is "main", which is the entry point into an executable program.
Definition Decl.cpp:3411
bool isOverloadedOperator() const
Whether this function declaration represents an C++ overloaded operator, e.g., "operator+".
Definition Decl.h:3063
void setBody(Stmt *B)
Definition Decl.cpp:3279
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5421
unsigned getNumParams() const
Definition TypeBase.h:5699
QualType getParamType(unsigned i) const
Definition TypeBase.h:5701
bool isVariadic() const
Whether this function prototype is variadic.
Definition TypeBase.h:5825
ArrayRef< QualType > param_types() const
Definition TypeBase.h:5861
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4617
QualType getReturnType() const
Definition TypeBase.h:4957
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Definition Expr.h:3864
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2081
Describes an C or C++ initializer list.
Definition Expr.h:5319
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition Expr.cpp:981
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
Definition Lexer.cpp:509
static std::string Stringify(StringRef Str, bool Charify=false)
Stringify - Convert the specified string into a C string by i) escaping '\' and " characters and ii) ...
Definition Lexer.cpp:320
Represents a linkage specification.
Definition DeclCXX.h:3040
SourceLocation getBeginLoc() const
Definition Stmt.h:3094
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition Expr.h:3375
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
Definition Expr.h:3436
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
Visibility getVisibility() const
Determines the visibility of this entity.
Definition Decl.h:444
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition Decl.h:317
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp,...
Definition ExprObjC.h:220
Expr * getElement(unsigned Index)
getElement - Return the Element at the specified index.
Definition ExprObjC.h:265
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprObjC.h:246
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c array literal.
Definition ExprObjC.h:257
ObjCMethodDecl * getArrayWithObjectsMethod() const
Definition ExprObjC.h:274
SourceLocation getEndLoc() const LLVM_READONLY
Definition ExprObjC.h:247
Represents Objective-C's @catch statement.
Definition StmtObjC.h:77
Represents Objective-C's @finally statement.
Definition StmtObjC.h:127
const Stmt * getFinallyBody() const
Definition StmtObjC.h:139
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtObjC.h:143
Represents Objective-C's @synchronized statement.
Definition StmtObjC.h:303
const CompoundStmt * getSynchBody() const
Definition StmtObjC.h:323
SourceLocation getAtSynchronizedLoc() const
Definition StmtObjC.h:320
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtObjC.h:339
Represents Objective-C's @throw statement.
Definition StmtObjC.h:358
const Expr * getThrowExpr() const
Definition StmtObjC.h:370
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtObjC.h:377
SourceLocation getEndLoc() const LLVM_READONLY
Definition StmtObjC.h:378
Represents Objective-C's @try ... @catch ... @finally statement.
Definition StmtObjC.h:167
const ObjCAtFinallyStmt * getFinallyStmt() const
Retrieve the @finally statement, if any.
Definition StmtObjC.h:241
unsigned getNumCatchStmts() const
Retrieve the number of @catch statements in this try-catch-finally block.
Definition StmtObjC.h:220
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtObjC.h:258
const Stmt * getTryBody() const
Retrieve the @try body.
Definition StmtObjC.h:214
SourceLocation getAtTryLoc() const
Retrieve the location of the @ in the @try.
Definition StmtObjC.h:210
catch_range catch_stmts()
Definition StmtObjC.h:282
Represents Objective-C's @autoreleasepool Statement.
Definition StmtObjC.h:394
SourceLocation getAtLoc() const
Definition StmtObjC.h:414
const Stmt * getSubStmt() const
Definition StmtObjC.h:405
ObjCBoolLiteralExpr - Objective-C Boolean Literal.
Definition ExprObjC.h:119
SourceLocation getLocation() const
Definition ExprObjC.h:138
ObjCBoxedExpr - used for generalized expression boxing.
Definition ExprObjC.h:159
ObjCMethodDecl * getBoxingMethod() const
Definition ExprObjC.h:181
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprObjC.h:187
SourceLocation getEndLoc() const LLVM_READONLY
Definition ExprObjC.h:188
ObjCCategoryDecl - Represents a category declaration.
Definition DeclObjC.h:2335
ObjCInterfaceDecl * getClassInterface()
Definition DeclObjC.h:2378
SourceLocation getIvarRBraceLoc() const
Definition DeclObjC.h:2472
protocol_range protocols() const
Definition DeclObjC.h:2409
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.
Definition DeclObjC.h:2551
ObjCCategoryDecl * getCategoryDecl() const
ObjCContainerDecl - Represents a container for method declarations.
Definition DeclObjC.h:954
SourceRange getAtEndRange() const
Definition DeclObjC.h:1109
instmeth_range instance_methods() const
Definition DeclObjC.h:1039
instprop_range instance_properties() const
Definition DeclObjC.h:988
ObjCMethodDecl * getClassMethod(Selector Sel, bool AllowHidden=false) const
Definition DeclObjC.h:1077
classmeth_range class_methods() const
Definition DeclObjC.h:1056
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
Definition DeclObjC.h:1072
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition ExprObjC.h:342
unsigned getNumElements() const
getNumElements - Return number of elements of objective-c dictionary literal.
Definition ExprObjC.h:392
ObjCMethodDecl * getDictWithObjectsMethod() const
Definition ExprObjC.h:409
ObjCDictionaryElement getKeyValueElement(unsigned Index) const
Definition ExprObjC.h:394
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprObjC.h:413
SourceLocation getEndLoc() const LLVM_READONLY
Definition ExprObjC.h:414
ObjCEncodeExpr, used for @encode in Objective-C.
Definition ExprObjC.h:441
QualType getEncodedType() const
Definition ExprObjC.h:460
Represents Objective-C's collection statement.
Definition StmtObjC.h:23
SourceLocation getForLoc() const
Definition StmtObjC.h:52
SourceLocation getRParenLoc() const
Definition StmtObjC.h:54
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtObjC.h:57
propimpl_range property_impls() const
Definition DeclObjC.h:2519
const ObjCInterfaceDecl * getClassInterface() const
Definition DeclObjC.h:2492
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Definition DeclObjC.h:2603
SourceLocation getIvarRBraceLoc() const
Definition DeclObjC.h:2750
std::string getNameAsString() const
Get the name of the class associated with this interface.
Definition DeclObjC.h:2735
Represents an ObjC class declaration.
Definition DeclObjC.h:1160
ObjCIvarDecl * lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared)
Definition DeclObjC.cpp:634
bool isImplicitInterfaceDecl() const
isImplicitInterfaceDecl - check that this is an implicitly declared ObjCInterfaceDecl node.
Definition DeclObjC.h:1899
ObjCIvarDecl * all_declared_ivar_begin()
all_declared_ivar_begin - return first ivar declared in this class, its extensions and its implementa...
ObjCCategoryDecl * FindCategoryDeclaration(const IdentifierInfo *CategoryId) const
FindCategoryDeclaration - Finds category declaration in the list of categories for this class and ret...
bool isThisDeclarationADefinition() const
Determine whether this particular declaration of this class is actually also a definition.
Definition DeclObjC.h:1529
const ObjCProtocolList & getReferencedProtocols() const
Definition DeclObjC.h:1339
ObjCImplementationDecl * getImplementation() const
SourceLocation getEndOfDefinitionLoc() const
Definition DeclObjC.h:1884
ObjCInterfaceDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C class.
Definition DeclObjC.h:1921
ObjCInterfaceDecl * getSuperClass() const
Definition DeclObjC.cpp:349
Represents typeof(type), a C23 feature and GCC extension, or `typeof_unqual(type),...
Definition TypeBase.h:8066
ObjCInterfaceDecl * getDecl() const
Get the declaration of this interface.
Definition Type.cpp:988
ObjCIvarDecl - Represents an ObjC instance variable.
Definition DeclObjC.h:1958
AccessControl getAccessControl() const
Definition DeclObjC.h:2006
ObjCInterfaceDecl * getContainingInterface()
Return the class interface that this ivar is logically contained in; this is either the interface whe...
ObjCIvarDecl * getNextIvar()
Definition DeclObjC.h:1993
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition ExprObjC.h:582
void setBase(Expr *base)
Definition ExprObjC.h:618
ObjCIvarDecl * getDecl()
Definition ExprObjC.h:612
const Expr * getBase() const
Definition ExprObjC.h:616
ObjCList - This is a simple template class used to hold various lists of decls etc,...
Definition DeclObjC.h:82
iterator end() const
Definition DeclObjC.h:91
iterator begin() const
Definition DeclObjC.h:90
T *const * iterator
Definition DeclObjC.h:88
An expression that sends a message to the given Objective-C object or class.
Definition ExprObjC.h:973
static ObjCMessageExpr * Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, bool IsInstanceSuper, QualType SuperType, Selector Sel, ArrayRef< SourceLocation > SelLocs, ObjCMethodDecl *Method, ArrayRef< Expr * > Args, SourceLocation RBracLoc, bool isImplicit)
Create a message send to super.
Definition ExprObjC.cpp:183
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition ExprObjC.h:1436
void getSelectorLocs(SmallVectorImpl< SourceLocation > &SelLocs) const
Definition ExprObjC.cpp:266
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
Definition ExprObjC.h:1258
SourceLocation getBeginLoc() const LLVM_READONLY
Definition ExprObjC.h:1491
SourceLocation getLeftLoc() const
Definition ExprObjC.h:1457
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition ExprObjC.h:1301
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super',...
Definition ExprObjC.h:1342
Selector getSelector() const
Definition ExprObjC.cpp:301
@ SuperInstance
The receiver is the instance of the superclass object.
Definition ExprObjC.h:987
@ Instance
The receiver is an object instance.
Definition ExprObjC.h:981
@ SuperClass
The receiver is a superclass.
Definition ExprObjC.h:984
@ Class
The receiver is a class.
Definition ExprObjC.h:978
TypeSourceInfo * getClassReceiverTypeInfo() const
Returns a type-source information of a class message send, or nullptr if the message is not a class m...
Definition ExprObjC.h:1329
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
Definition ExprObjC.h:1320
QualType getSuperType() const
Retrieve the type referred to by 'super'.
Definition ExprObjC.h:1377
const ObjCMethodDecl * getMethodDecl() const
Definition ExprObjC.h:1397
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Definition ExprObjC.h:1262
SourceLocation getEndLoc() const LLVM_READONLY
Definition ExprObjC.h:1492
SourceLocation getRightLoc() const
Definition ExprObjC.h:1458
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver.
Definition ExprObjC.h:1423
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
ImplicitParamDecl * getSelfDecl() const
Definition DeclObjC.h:421
ArrayRef< ParmVarDecl * > parameters() const
Definition DeclObjC.h:376
CompoundStmt * getCompoundBody()
Definition DeclObjC.h:533
bool isVariadic() const
Definition DeclObjC.h:434
void setBody(Stmt *B)
Definition DeclObjC.h:534
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
Definition DeclObjC.cpp:927
bool isSynthesizedAccessorStub() const
Definition DeclObjC.h:447
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclObjC.h:285
Selector getSelector() const
Definition DeclObjC.h:330
bool isInstanceMethod() const
Definition DeclObjC.h:429
QualType getReturnType() const
Definition DeclObjC.h:332
ObjCImplementationControl getImplementationControl() const
Definition DeclObjC.h:503
ObjCInterfaceDecl * getClassInterface()
Represents a pointer to an Objective C object.
Definition TypeBase.h:8122
Represents one property declaration in an Objective-C interface.
Definition DeclObjC.h:734
SourceLocation getAtLoc() const
Definition DeclObjC.h:802
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
Definition DeclObjC.h:844
Selector getSetterName() const
Definition DeclObjC.h:899
Selector getGetterName() const
Definition DeclObjC.h:891
ObjCPropertyAttribute::Kind getPropertyAttributes() const
Definition DeclObjC.h:821
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
Definition DeclObjC.h:2811
ObjCIvarDecl * getPropertyIvarDecl() const
Definition DeclObjC.h:2885
Kind getPropertyImplementation() const
Definition DeclObjC.h:2881
ObjCPropertyDecl * getPropertyDecl() const
Definition DeclObjC.h:2876
ObjCMethodDecl * getSetterMethodDecl() const
Definition DeclObjC.h:2910
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclObjC.h:2873
ObjCMethodDecl * getGetterMethodDecl() const
Definition DeclObjC.h:2907
Represents an Objective-C protocol declaration.
Definition DeclObjC.h:2090
bool isThisDeclarationADefinition() const
Determine whether this particular declaration is also the definition.
Definition DeclObjC.h:2267
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
Definition DeclObjC.h:2256
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
Definition DeclObjC.h:2303
protocol_range protocols() const
Definition DeclObjC.h:2167
ObjCProtocolExpr used for protocol expression in Objective-C.
Definition ExprObjC.h:538
ObjCProtocolDecl * getProtocol() const
Definition ExprObjC.h:555
ObjCSelectorExpr used for @selector in Objective-C.
Definition ExprObjC.h:486
Selector getSelector() const
Definition ExprObjC.h:500
ObjCStringLiteral, used for Objective-C string literals i.e.
Definition ExprObjC.h:84
StringLiteral * getString()
Definition ExprObjC.h:96
ParenExpr - This represents a parenthesized expression, e.g.
Definition Expr.h:2193
Represents an unpacked "presumed" location which can be presented to the user.
const char * getFilename() const
Return the presumed filename of this location.
unsigned getLine() const
Return the presumed line number of this location.
PseudoObjectExpr - An expression which accesses a pseudo-object l-value.
Definition Expr.h:6821
Expr * getResultExpr()
Return the result-bearing expression, or null if there is none.
Definition Expr.h:6869
unsigned getNumSemanticExprs() const
Definition Expr.h:6878
Expr * getSemanticExpr(unsigned index)
Definition Expr.h:6900
Expr * getSyntacticForm()
Return the syntactic form of this expression, i.e.
Definition Expr.h:6858
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8588
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
Definition TypeBase.h:8582
QualType IgnoreParens() const
Returns the specified type after dropping any outer-level parentheses.
Definition TypeBase.h:1331
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8577
bool isObjCGCWeak() const
true when Type is objc's weak.
Definition TypeBase.h:1444
unsigned getCVRQualifiers() const
Retrieve the set of CVR (const-volatile-restrict) qualifiers applied to this type.
Definition TypeBase.h:8550
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition TypeBase.h:1348
Represents a struct/union/class.
Definition Decl.h:4459
field_range fields() const
Definition Decl.h:4662
static RecordDecl * Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl *PrevDecl=nullptr)
Definition Decl.cpp:5295
virtual void completeDefinition()
Note that the definition of this type is now complete.
Definition Decl.cpp:5354
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4643
static bool isRewritable(SourceLocation Loc)
isRewritable - Return true if this location is a raw file location, which is rewritable.
Definition Rewriter.h:83
std::string getAsString() const
Derive the full selector name (e.g.
bool isValid() const
Return true if this is a valid SourceLocation object.
PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives=true) const
Returns the "presumed" location of a SourceLocation specifies.
unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
FileID getMainFileID() const
Returns the FileID of the main source file.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.
llvm::MemoryBufferRef getBufferOrFake(FileID FID, SourceLocation Loc=SourceLocation()) const
Return the buffer for the specified FileID.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file.
bool isWrittenInMainFile(SourceLocation Loc) const
Returns true if the spelling location for the given location is in the main file buffer.
SourceLocation getExpansionLoc(SourceLocation Loc) const
Given a SourceLocation object Loc, return the expansion location referenced by the ID.
SourceLocation getBegin() const
Stmt - This represents one statement.
Definition Stmt.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
child_range children()
Definition Stmt.cpp:304
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
unsigned getByteLength() const
Definition Expr.h:1919
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3851
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3952
bool isStruct() const
Definition Decl.h:4059
bool isUnion() const
Definition Decl.h:4062
Represents a typeof (or typeof) expression (a C23 feature and GCC extension) or a typeof_unqual expre...
Definition TypeBase.h:6332
Expr * getUnderlyingExpr() const
Definition TypeBase.h:6343
A container of type source information.
Definition TypeBase.h:8475
bool isBlockPointerType() const
Definition TypeBase.h:8761
bool isFunctionPointerType() const
Definition TypeBase.h:8808
bool isPointerType() const
Definition TypeBase.h:8741
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9407
const ObjCObjectPointerType * getAsObjCInterfacePointerType() const
Definition Type.cpp:1976
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2186
bool isObjCQualifiedIdType() const
Definition TypeBase.h:8941
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isObjCQualifiedInterfaceType() const
Definition Type.cpp:1944
bool isObjCObjectPointerType() const
Definition TypeBase.h:8920
bool isObjCQualifiedClassType() const
Definition TypeBase.h:8947
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2435
const T * castAsCanonical() const
Return this type's canonical type cast to the specified type.
Definition TypeBase.h:3005
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9340
bool isRecordType() const
Definition TypeBase.h:8868
static TypedefDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, TypeSourceInfo *TInfo)
Definition Decl.cpp:5829
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3696
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition Expr.h:2255
static UnaryOperator * Create(const ASTContext &C, Expr *input, Opcode opc, QualType type, ExprValueKind VK, ExprObjectKind OK, SourceLocation l, bool CanOverflow, FPOptionsOverride FPFeatures)
Definition Expr.cpp:5165
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2132
const Expr * getInit() const
Definition Decl.h:1391
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1174
Defines the clang::TargetInfo interface.
@ BLOCK_HAS_COPY_DISPOSE
Definition CGBlocks.h:50
@ BLOCK_FIELD_IS_BYREF
Definition CGBlocks.h:92
@ BLOCK_FIELD_IS_WEAK
Definition CGBlocks.h:94
@ BLOCK_FIELD_IS_BLOCK
Definition CGBlocks.h:90
@ BLOCK_BYREF_CURRENT_MAX
Definition CGBlocks.h:99
@ BLOCK_FIELD_IS_OBJECT
Definition CGBlocks.h:88
const internal::VariadicDynCastAllOfMatcher< Decl, FieldDecl > fieldDecl
Matches field declarations.
const internal::VariadicDynCastAllOfMatcher< Stmt, CastExpr > castExpr
Matches any cast nodes of Clang's AST.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
@ CF
Indicates that the tracked object is a CF object.
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ Rewrite
We are substituting template parameters for (typically) other template parameters in order to rewrite...
Definition Template.h:54
@ ICIS_NoInit
No in-class initializer.
Definition Specifiers.h:273
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:152
@ SC_Extern
Definition Specifiers.h:252
@ SC_Static
Definition Specifiers.h:253
@ SC_None
Definition Specifiers.h:251
LLVM_READONLY bool isAlphanumeric(unsigned char c)
Return true if this character is an ASCII letter or digit: [a-zA-Z0-9].
Definition CharInfo.h:138
const FunctionProtoType * T
std::unique_ptr< ASTConsumer > CreateModernObjCRewriter(const std::string &InFile, std::unique_ptr< raw_ostream > OS, DiagnosticsEngine &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning, bool LineInfo)
@ Struct
The "struct" keyword.
Definition TypeBase.h:6047
CastKind
CastKind - The kind of operation required for a conversion.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:136
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:140
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:6031
@ HiddenVisibility
Objects with "hidden" visibility are not seen by the dynamic linker.
Definition Visibility.h:37
CLINKAGE int printf(__constant const char *st,...) __attribute__((format(printf
__packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 __packed_splat2 __packed_splat4 __packed_splat2 __packed_splat8 __packed_splat4 uint32_t
An element in an Objective-C dictionary literal.
Definition ExprObjC.h:295
Expr * Value
The value of the dictionary element.
Definition ExprObjC.h:300
Expr * Key
The key for the dictionary element.
Definition ExprObjC.h:297
Describes how types, statements, expressions, and declarations should be printed.