Bug Summary

File:clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
Warning:line 4826, column 11
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name RewriteModernObjC.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/tools/clang/lib/Frontend/Rewrite -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/tools/clang/lib/Frontend/Rewrite -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/clang/lib/Frontend/Rewrite -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/clang/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/tools/clang/lib/Frontend/Rewrite -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/clang/lib/Frontend/Rewrite/RewriteModernObjC.cpp
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/Rewrite/Frontend/ASTConsumers.h"
14#include "clang/AST/AST.h"
15#include "clang/AST/ASTConsumer.h"
16#include "clang/AST/Attr.h"
17#include "clang/AST/ParentMap.h"
18#include "clang/Basic/CharInfo.h"
19#include "clang/Basic/Diagnostic.h"
20#include "clang/Basic/IdentifierTable.h"
21#include "clang/Basic/SourceManager.h"
22#include "clang/Basic/TargetInfo.h"
23#include "clang/Config/config.h"
24#include "clang/Lex/Lexer.h"
25#include "clang/Rewrite/Core/Rewriter.h"
26#include "llvm/ADT/DenseSet.h"
27#include "llvm/ADT/SmallPtrSet.h"
28#include "llvm/ADT/StringExtras.h"
29#include "llvm/Support/MemoryBuffer.h"
30#include "llvm/Support/raw_ostream.h"
31#include <memory>
32
33#if CLANG_ENABLE_OBJC_REWRITER1
34
35using namespace clang;
36using llvm::utostr;
37
38namespace {
39 class RewriteModernObjC : public ASTConsumer {
40 protected:
41
42 enum {
43 BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
44 block, ... */
45 BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
46 BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
47 __block variable */
48 BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
49 helpers */
50 BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
51 support routines */
52 BLOCK_BYREF_CURRENT_MAX = 256
53 };
54
55 enum {
56 BLOCK_NEEDS_FREE = (1 << 24),
57 BLOCK_HAS_COPY_DISPOSE = (1 << 25),
58 BLOCK_HAS_CXX_OBJ = (1 << 26),
59 BLOCK_IS_GC = (1 << 27),
60 BLOCK_IS_GLOBAL = (1 << 28),
61 BLOCK_HAS_DESCRIPTOR = (1 << 29)
62 };
63
64 Rewriter Rewrite;
65 DiagnosticsEngine &Diags;
66 const LangOptions &LangOpts;
67 ASTContext *Context;
68 SourceManager *SM;
69 TranslationUnitDecl *TUDecl;
70 FileID MainFileID;
71 const char *MainFileStart, *MainFileEnd;
72 Stmt *CurrentBody;
73 ParentMap *PropParentMap; // created lazily.
74 std::string InFileName;
75 std::unique_ptr<raw_ostream> OutFile;
76 std::string Preamble;
77
78 TypeDecl *ProtocolTypeDecl;
79 VarDecl *GlobalVarDecl;
80 Expr *GlobalConstructionExp;
81 unsigned RewriteFailedDiag;
82 unsigned GlobalBlockRewriteFailedDiag;
83 // ObjC string constant support.
84 unsigned NumObjCStringLiterals;
85 VarDecl *ConstantStringClassReference;
86 RecordDecl *NSStringRecord;
87
88 // ObjC foreach break/continue generation support.
89 int BcLabelCount;
90
91 unsigned TryFinallyContainsReturnDiag;
92 // Needed for super.
93 ObjCMethodDecl *CurMethodDef;
94 RecordDecl *SuperStructDecl;
95 RecordDecl *ConstantStringDecl;
96
97 FunctionDecl *MsgSendFunctionDecl;
98 FunctionDecl *MsgSendSuperFunctionDecl;
99 FunctionDecl *MsgSendStretFunctionDecl;
100 FunctionDecl *MsgSendSuperStretFunctionDecl;
101 FunctionDecl *MsgSendFpretFunctionDecl;
102 FunctionDecl *GetClassFunctionDecl;
103 FunctionDecl *GetMetaClassFunctionDecl;
104 FunctionDecl *GetSuperClassFunctionDecl;
105 FunctionDecl *SelGetUidFunctionDecl;
106 FunctionDecl *CFStringFunctionDecl;
107 FunctionDecl *SuperConstructorFunctionDecl;
108 FunctionDecl *CurFunctionDef;
109
110 /* Misc. containers needed for meta-data rewrite. */
111 SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
112 SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
113 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
114 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
115 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;
116 llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;
117 SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;
118 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
119 SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;
120
121 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
122 SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories;
123
124 SmallVector<Stmt *, 32> Stmts;
125 SmallVector<int, 8> ObjCBcLabelNo;
126 // Remember all the @protocol(<expr>) expressions.
127 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
128
129 llvm::DenseSet<uint64_t> CopyDestroyCache;
130
131 // Block expressions.
132 SmallVector<BlockExpr *, 32> Blocks;
133 SmallVector<int, 32> InnerDeclRefsCount;
134 SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
135
136 SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
137
138 // Block related declarations.
139 SmallVector<ValueDecl *, 8> BlockByCopyDecls;
140 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
141 SmallVector<ValueDecl *, 8> BlockByRefDecls;
142 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
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) {
1
Assuming 'I' is not equal to 'E'
2
Loop condition is true. Entering loop body
229 if (TypedefNameDecl *TD
3.1
'TD' is non-null
= dyn_cast<TypedefNameDecl>(*I)) {
3
Assuming the object is a 'TypedefNameDecl'
4
Taking true branch
230 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
5
Taking true branch
231 RewriteBlockPointerDecl(TD);
6
Calling 'RewriteModernObjC::RewriteBlockPointerDecl'
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")(static_cast<void> (0));
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 const std::string &Str = S.str();
276
277 // If replacement succeeded or warning disabled return with no warning.
278 if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
279 ReplacedNodes[Old] = New;
280 return;
281 }
282 if (SilenceRewriteMacroWarning)
283 return;
284 Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
285 << Old->getSourceRange();
286 }
287
288 void InsertText(SourceLocation Loc, StringRef Str,
289 bool InsertAfter = true) {
290 // If insertion succeeded or warning disabled return with no warning.
291 if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
292 SilenceRewriteMacroWarning)
293 return;
294
295 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
296 }
297
298 void ReplaceText(SourceLocation Start, unsigned OrigLength,
299 StringRef Str) {
300 // If removal succeeded or warning disabled return with no warning.
301 if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
302 SilenceRewriteMacroWarning)
303 return;
304
305 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
306 }
307
308 // Syntactic Rewriting.
309 void RewriteRecordBody(RecordDecl *RD);
310 void RewriteInclude();
311 void RewriteLineDirective(const Decl *D);
312 void ConvertSourceLocationToLineDirective(SourceLocation Loc,
313 std::string &LineString);
314 void RewriteForwardClassDecl(DeclGroupRef D);
315 void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);
316 void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
317 const std::string &typedefString);
318 void RewriteImplementations();
319 void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
320 ObjCImplementationDecl *IMD,
321 ObjCCategoryImplDecl *CID);
322 void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
323 void RewriteImplementationDecl(Decl *Dcl);
324 void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
325 ObjCMethodDecl *MDecl, std::string &ResultStr);
326 void RewriteTypeIntoString(QualType T, std::string &ResultStr,
327 const FunctionType *&FPRetType);
328 void RewriteByRefString(std::string &ResultStr, const std::string &Name,
329 ValueDecl *VD, bool def=false);
330 void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
331 void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
332 void RewriteForwardProtocolDecl(DeclGroupRef D);
333 void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);
334 void RewriteMethodDeclaration(ObjCMethodDecl *Method);
335 void RewriteProperty(ObjCPropertyDecl *prop);
336 void RewriteFunctionDecl(FunctionDecl *FD);
337 void RewriteBlockPointerType(std::string& Str, QualType Type);
338 void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
339 void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
340 void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
341 void RewriteTypeOfDecl(VarDecl *VD);
342 void RewriteObjCQualifiedInterfaceTypes(Expr *E);
343
344 std::string getIvarAccessString(ObjCIvarDecl *D);
345
346 // Expression Rewriting.
347 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
348 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
349 Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
350 Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
351 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
352 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
353 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
354 Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);
355 Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);
356 Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);
357 Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);
358 Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
359 Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
360 Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);
361 Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
362 Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
363 Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
364 SourceLocation OrigEnd);
365 Stmt *RewriteBreakStmt(BreakStmt *S);
366 Stmt *RewriteContinueStmt(ContinueStmt *S);
367 void RewriteCastExpr(CStyleCastExpr *CE);
368 void RewriteImplicitCastObjCExpr(CastExpr *IE);
369
370 // Computes ivar bitfield group no.
371 unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV);
372 // Names field decl. for ivar bitfield group.
373 void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result);
374 // Names struct type for ivar bitfield group.
375 void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result);
376 // Names symbol for ivar bitfield group field offset.
377 void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result);
378 // Given an ivar bitfield, it builds (or finds) its group record type.
379 QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV);
380 QualType SynthesizeBitfieldGroupStructType(
381 ObjCIvarDecl *IV,
382 SmallVectorImpl<ObjCIvarDecl *> &IVars);
383
384 // Block rewriting.
385 void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
386
387 // Block specific rewrite rules.
388 void RewriteBlockPointerDecl(NamedDecl *VD);
389 void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);
390 Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
391 Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
392 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
393
394 void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
395 std::string &Result);
396
397 void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);
398 bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,
399 bool &IsNamedDefinition);
400 void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,
401 std::string &Result);
402
403 bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);
404
405 void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
406 std::string &Result);
407
408 void Initialize(ASTContext &context) override;
409
410 // Misc. AST transformation routines. Sometimes they end up calling
411 // rewriting routines on the new ASTs.
412 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
413 ArrayRef<Expr *> Args,
414 SourceLocation StartLoc=SourceLocation(),
415 SourceLocation EndLoc=SourceLocation());
416
417 Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
418 QualType returnType,
419 SmallVectorImpl<QualType> &ArgTypes,
420 SmallVectorImpl<Expr*> &MsgExprs,
421 ObjCMethodDecl *Method);
422
423 Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
424 SourceLocation StartLoc=SourceLocation(),
425 SourceLocation EndLoc=SourceLocation());
426
427 void SynthCountByEnumWithState(std::string &buf);
428 void SynthMsgSendFunctionDecl();
429 void SynthMsgSendSuperFunctionDecl();
430 void SynthMsgSendStretFunctionDecl();
431 void SynthMsgSendFpretFunctionDecl();
432 void SynthMsgSendSuperStretFunctionDecl();
433 void SynthGetClassFunctionDecl();
434 void SynthGetMetaClassFunctionDecl();
435 void SynthGetSuperClassFunctionDecl();
436 void SynthSelGetUidFunctionDecl();
437 void SynthSuperConstructorFunctionDecl();
438
439 // Rewriting metadata
440 template<typename MethodIterator>
441 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
442 MethodIterator MethodEnd,
443 bool IsInstanceMethod,
444 StringRef prefix,
445 StringRef ClassName,
446 std::string &Result);
447 void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
448 std::string &Result);
449 void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
450 std::string &Result);
451 void RewriteClassSetupInitHook(std::string &Result);
452
453 void RewriteMetaDataIntoBuffer(std::string &Result);
454 void WriteImageInfo(std::string &Result);
455 void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
456 std::string &Result);
457 void RewriteCategorySetupInitHook(std::string &Result);
458
459 // Rewriting ivar
460 void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
461 std::string &Result);
462 Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);
463
464
465 std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
466 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
467 StringRef funcName, std::string Tag);
468 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
469 StringRef funcName, std::string Tag);
470 std::string SynthesizeBlockImpl(BlockExpr *CE,
471 std::string Tag, std::string Desc);
472 std::string SynthesizeBlockDescriptor(std::string DescTag,
473 std::string ImplTag,
474 int i, StringRef funcName,
475 unsigned hasCopy);
476 Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
477 void SynthesizeBlockLiterals(SourceLocation FunLocStart,
478 StringRef FunName);
479 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
480 Stmt *SynthBlockInitExpr(BlockExpr *Exp,
481 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);
482
483 // Misc. helper routines.
484 QualType getProtocolType();
485 void WarnAboutReturnGotoStmts(Stmt *S);
486 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
487 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
488 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
489
490 bool IsDeclStmtInForeachHeader(DeclStmt *DS);
491 void CollectBlockDeclRefInfo(BlockExpr *Exp);
492 void GetBlockDeclRefExprs(Stmt *S);
493 void GetInnerBlockDeclRefExprs(Stmt *S,
494 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
495 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
496
497 // We avoid calling Type::isBlockPointerType(), since it operates on the
498 // canonical type. We only care if the top-level type is a closure pointer.
499 bool isTopLevelBlockPointerType(QualType T) {
500 return isa<BlockPointerType>(T);
501 }
502
503 /// convertBlockPointerToFunctionPointer - Converts a block-pointer type
504 /// to a function pointer type and upon success, returns true; false
505 /// otherwise.
506 bool convertBlockPointerToFunctionPointer(QualType &T) {
507 if (isTopLevelBlockPointerType(T)) {
508 const auto *BPT = T->castAs<BlockPointerType>();
509 T = Context->getPointerType(BPT->getPointeeType());
510 return true;
511 }
512 return false;
513 }
514
515 bool convertObjCTypeToCStyleType(QualType &T);
516
517 bool needToScanForQualifiers(QualType T);
518 QualType getSuperStructType();
519 QualType getConstantStringStructType();
520 QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
521
522 void convertToUnqualifiedObjCType(QualType &T) {
523 if (T->isObjCQualifiedIdType()) {
524 bool isConst = T.isConstQualified();
525 T = isConst ? Context->getObjCIdType().withConst()
526 : Context->getObjCIdType();
527 }
528 else if (T->isObjCQualifiedClassType())
529 T = Context->getObjCClassType();
530 else if (T->isObjCObjectPointerType() &&
531 T->getPointeeType()->isObjCQualifiedInterfaceType()) {
532 if (const ObjCObjectPointerType * OBJPT =
533 T->getAsObjCInterfacePointerType()) {
534 const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
535 T = QualType(IFaceT, 0);
536 T = Context->getPointerType(T);
537 }
538 }
539 }
540
541 // FIXME: This predicate seems like it would be useful to add to ASTContext.
542 bool isObjCType(QualType T) {
543 if (!LangOpts.ObjC)
544 return false;
545
546 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
547
548 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
549 OCT == Context->getCanonicalType(Context->getObjCClassType()))
550 return true;
551
552 if (const PointerType *PT = OCT->getAs<PointerType>()) {
553 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
554 PT->getPointeeType()->isObjCQualifiedIdType())
555 return true;
556 }
557 return false;
558 }
559
560 bool PointerTypeTakesAnyBlockArguments(QualType QT);
561 bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
562 void GetExtentOfArgList(const char *Name, const char *&LParen,
563 const char *&RParen);
564
565 void QuoteDoublequotes(std::string &From, std::string &To) {
566 for (unsigned i = 0; i < From.length(); i++) {
567 if (From[i] == '"')
568 To += "\\\"";
569 else
570 To += From[i];
571 }
572 }
573
574 QualType getSimpleFunctionType(QualType result,
575 ArrayRef<QualType> args,
576 bool variadic = false) {
577 if (result == Context->getObjCInstanceType())
578 result = Context->getObjCIdType();
579 FunctionProtoType::ExtProtoInfo fpi;
580 fpi.Variadic = variadic;
581 return Context->getFunctionType(result, args, fpi);
582 }
583
584 // Helper function: create a CStyleCastExpr with trivial type source info.
585 CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
586 CastKind Kind, Expr *E) {
587 TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
588 return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,
589 FPOptionsOverride(), TInfo,
590 SourceLocation(), SourceLocation());
591 }
592
593 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
594 IdentifierInfo* II = &Context->Idents.get("load");
595 Selector LoadSel = Context->Selectors.getSelector(0, &II);
596 return OD->getClassMethod(LoadSel) != nullptr;
597 }
598
599 StringLiteral *getStringLiteral(StringRef Str) {
600 QualType StrType = Context->getConstantArrayType(
601 Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,
602 ArrayType::Normal, 0);
603 return StringLiteral::Create(*Context, Str, StringLiteral::Ascii,
604 /*Pascal=*/false, StrType, SourceLocation());
605 }
606 };
607} // end anonymous namespace
608
609void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
610 NamedDecl *D) {
611 if (const FunctionProtoType *fproto
612 = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
613 for (const auto &I : fproto->param_types())
614 if (isTopLevelBlockPointerType(I)) {
615 // All the args are checked/rewritten. Don't call twice!
616 RewriteBlockPointerDecl(D);
617 break;
618 }
619 }
620}
621
622void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
623 const PointerType *PT = funcType->getAs<PointerType>();
624 if (PT && PointerTypeTakesAnyBlockArguments(funcType))
625 RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
626}
627
628static bool IsHeaderFile(const std::string &Filename) {
629 std::string::size_type DotPos = Filename.rfind('.');
630
631 if (DotPos == std::string::npos) {
632 // no file extension
633 return false;
634 }
635
636 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
637 // C header: .h
638 // C++ header: .hh or .H;
639 return Ext == "h" || Ext == "hh" || Ext == "H";
640}
641
642RewriteModernObjC::RewriteModernObjC(std::string inFile,
643 std::unique_ptr<raw_ostream> OS,
644 DiagnosticsEngine &D,
645 const LangOptions &LOpts,
646 bool silenceMacroWarn, bool LineInfo)
647 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
648 SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) {
649 IsHeader = IsHeaderFile(inFile);
650 RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
651 "rewriting sub-expression within a macro (may not be correct)");
652 // FIXME. This should be an error. But if block is not called, it is OK. And it
653 // may break including some headers.
654 GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
655 "rewriting block literal declared in global scope is not implemented");
656
657 TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
658 DiagnosticsEngine::Warning,
659 "rewriter doesn't support user-specified control flow semantics "
660 "for @try/@finally (code may not execute properly)");
661}
662
663std::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter(
664 const std::string &InFile, std::unique_ptr<raw_ostream> OS,
665 DiagnosticsEngine &Diags, const LangOptions &LOpts,
666 bool SilenceRewriteMacroWarning, bool LineInfo) {
667 return std::make_unique<RewriteModernObjC>(InFile, std::move(OS), Diags,
668 LOpts, SilenceRewriteMacroWarning,
669 LineInfo);
670}
671
672void RewriteModernObjC::InitializeCommon(ASTContext &context) {
673 Context = &context;
674 SM = &Context->getSourceManager();
675 TUDecl = Context->getTranslationUnitDecl();
676 MsgSendFunctionDecl = nullptr;
677 MsgSendSuperFunctionDecl = nullptr;
678 MsgSendStretFunctionDecl = nullptr;
679 MsgSendSuperStretFunctionDecl = nullptr;
680 MsgSendFpretFunctionDecl = nullptr;
681 GetClassFunctionDecl = nullptr;
682 GetMetaClassFunctionDecl = nullptr;
683 GetSuperClassFunctionDecl = nullptr;
684 SelGetUidFunctionDecl = nullptr;
685 CFStringFunctionDecl = nullptr;
686 ConstantStringClassReference = nullptr;
687 NSStringRecord = nullptr;
688 CurMethodDef = nullptr;
689 CurFunctionDef = nullptr;
690 GlobalVarDecl = nullptr;
691 GlobalConstructionExp = nullptr;
692 SuperStructDecl = nullptr;
693 ProtocolTypeDecl = nullptr;
694 ConstantStringDecl = nullptr;
695 BcLabelCount = 0;
696 SuperConstructorFunctionDecl = nullptr;
697 NumObjCStringLiterals = 0;
698 PropParentMap = nullptr;
699 CurrentBody = nullptr;
700 DisableReplaceStmt = false;
701 objc_impl_method = false;
702
703 // Get the ID and start/end of the main file.
704 MainFileID = SM->getMainFileID();
705 llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);
706 MainFileStart = MainBuf.getBufferStart();
707 MainFileEnd = MainBuf.getBufferEnd();
708
709 Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
710}
711
712//===----------------------------------------------------------------------===//
713// Top Level Driver Code
714//===----------------------------------------------------------------------===//
715
716void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {
717 if (Diags.hasErrorOccurred())
718 return;
719
720 // Two cases: either the decl could be in the main file, or it could be in a
721 // #included file. If the former, rewrite it now. If the later, check to see
722 // if we rewrote the #include/#import.
723 SourceLocation Loc = D->getLocation();
724 Loc = SM->getExpansionLoc(Loc);
725
726 // If this is for a builtin, ignore it.
727 if (Loc.isInvalid()) return;
728
729 // Look for built-in declarations that we need to refer during the rewrite.
730 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
731 RewriteFunctionDecl(FD);
732 } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
733 // declared in <Foundation/NSString.h>
734 if (FVD->getName() == "_NSConstantStringClassReference") {
735 ConstantStringClassReference = FVD;
736 return;
737 }
738 } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
739 RewriteCategoryDecl(CD);
740 } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
741 if (PD->isThisDeclarationADefinition())
742 RewriteProtocolDecl(PD);
743 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
744 // Recurse into linkage specifications
745 for (DeclContext::decl_iterator DI = LSD->decls_begin(),
746 DIEnd = LSD->decls_end();
747 DI != DIEnd; ) {
748 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
749 if (!IFace->isThisDeclarationADefinition()) {
750 SmallVector<Decl *, 8> DG;
751 SourceLocation StartLoc = IFace->getBeginLoc();
752 do {
753 if (isa<ObjCInterfaceDecl>(*DI) &&
754 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
755 StartLoc == (*DI)->getBeginLoc())
756 DG.push_back(*DI);
757 else
758 break;
759
760 ++DI;
761 } while (DI != DIEnd);
762 RewriteForwardClassDecl(DG);
763 continue;
764 }
765 else {
766 // Keep track of all interface declarations seen.
767 ObjCInterfacesSeen.push_back(IFace);
768 ++DI;
769 continue;
770 }
771 }
772
773 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
774 if (!Proto->isThisDeclarationADefinition()) {
775 SmallVector<Decl *, 8> DG;
776 SourceLocation StartLoc = Proto->getBeginLoc();
777 do {
778 if (isa<ObjCProtocolDecl>(*DI) &&
779 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
780 StartLoc == (*DI)->getBeginLoc())
781 DG.push_back(*DI);
782 else
783 break;
784
785 ++DI;
786 } while (DI != DIEnd);
787 RewriteForwardProtocolDecl(DG);
788 continue;
789 }
790 }
791
792 HandleTopLevelSingleDecl(*DI);
793 ++DI;
794 }
795 }
796 // If we have a decl in the main file, see if we should rewrite it.
797 if (SM->isWrittenInMainFile(Loc))
798 return HandleDeclInMainFile(D);
799}
800
801//===----------------------------------------------------------------------===//
802// Syntactic (non-AST) Rewriting Code
803//===----------------------------------------------------------------------===//
804
805void RewriteModernObjC::RewriteInclude() {
806 SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
807 StringRef MainBuf = SM->getBufferData(MainFileID);
808 const char *MainBufStart = MainBuf.begin();
809 const char *MainBufEnd = MainBuf.end();
810 size_t ImportLen = strlen("import");
811
812 // Loop over the whole file, looking for includes.
813 for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
814 if (*BufPtr == '#') {
815 if (++BufPtr == MainBufEnd)
816 return;
817 while (*BufPtr == ' ' || *BufPtr == '\t')
818 if (++BufPtr == MainBufEnd)
819 return;
820 if (!strncmp(BufPtr, "import", ImportLen)) {
821 // replace import with include
822 SourceLocation ImportLoc =
823 LocStart.getLocWithOffset(BufPtr-MainBufStart);
824 ReplaceText(ImportLoc, ImportLen, "include");
825 BufPtr += ImportLen;
826 }
827 }
828 }
829}
830
831static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,
832 ObjCIvarDecl *IvarDecl, std::string &Result) {
833 Result += "OBJC_IVAR_$_";
834 Result += IDecl->getName();
835 Result += "$";
836 Result += IvarDecl->getName();
837}
838
839std::string
840RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {
841 const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();
842
843 // Build name of symbol holding ivar offset.
844 std::string IvarOffsetName;
845 if (D->isBitField())
846 ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
847 else
848 WriteInternalIvarName(ClassDecl, D, IvarOffsetName);
849
850 std::string S = "(*(";
851 QualType IvarT = D->getType();
852 if (D->isBitField())
853 IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
854
855 if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) {
856 RecordDecl *RD = IvarT->castAs<RecordType>()->getDecl();
857 RD = RD->getDefinition();
858 if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
859 // decltype(((Foo_IMPL*)0)->bar) *
860 auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());
861 // ivar in class extensions requires special treatment.
862 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
863 CDecl = CatDecl->getClassInterface();
864 std::string RecName = std::string(CDecl->getName());
865 RecName += "_IMPL";
866 RecordDecl *RD =
867 RecordDecl::Create(*Context, TTK_Struct, TUDecl, SourceLocation(),
868 SourceLocation(), &Context->Idents.get(RecName));
869 QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(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,
883 ICIS_NoInit);
884 MemberExpr *ME = MemberExpr::CreateImplicit(
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,
910 ObjCPropertyDecl *PD,
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,
918 ObjCImplementationDecl *IMD,
919 ObjCCategoryImplDecl *CID) {
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")(static_cast<void> (0));
929 const char *semiBuf = strchr(startBuf, ';');
930 assert((*semiBuf == ';') && "@synthesize: can't find ';'")(static_cast<void> (0));
931 startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
932 } else
933 startGetterSetterLoc = IMD ? IMD->getEndLoc() : CID->getEndLoc();
934
935 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
936 return; // FIXME: is this correct?
937
938 // Generate the 'getter' function.
939 ObjCPropertyDecl *PD = PID->getPropertyDecl();
940 ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
941 assert(IMD && OID && "Synthesized ivars must be attached to @implementation")(static_cast<void> (0));
942
943 unsigned Attributes = PD->getPropertyAttributes();
944 if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {
945 bool GenGetProperty =
946 !(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&
947 (Attributes & (ObjCPropertyAttribute::kind_retain |
948 ObjCPropertyAttribute::kind_copy));
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 |
1008 ObjCPropertyAttribute::kind_copy);
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 += ", ";
1027 if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
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 }
1086 DeclGroupRef::iterator I = D.begin();
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())(static_cast<void> (0));
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")__builtin_unreachable();
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")__builtin_unreachable();
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")(static_cast<void> (0));
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 =
1420 cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(
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;
1426 SmallVector<Expr*, 2> Args;
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.
1449 SmallVector<SourceLocation, 1> SelLocs;
1450 OldMsg->getSelectorLocs(SelLocs);
1451
1452 ObjCMessageExpr *NewMsg = nullptr;
1453 switch (OldMsg->getReceiverKind()) {
1454 case ObjCMessageExpr::Class:
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
1467 case ObjCMessageExpr::Instance:
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
1480 case ObjCMessageExpr::SuperClass:
1481 case ObjCMessageExpr::SuperInstance:
1482 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1483 OldMsg->getValueKind(),
1484 OldMsg->getLeftLoc(),
1485 OldMsg->getSuperLoc(),
1486 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
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 =
1508 cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());
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;
1513 SmallVector<Expr*, 1> Args;
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.
1533 SmallVector<SourceLocation, 1> SelLocs;
1534
1535 ObjCMessageExpr *NewMsg = nullptr;
1536 switch (OldMsg->getReceiverKind()) {
1537 case ObjCMessageExpr::Class:
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
1550 case ObjCMessageExpr::Instance:
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
1563 case ObjCMessageExpr::SuperClass:
1564 case ObjCMessageExpr::SuperInstance:
1565 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1566 OldMsg->getValueKind(),
1567 OldMsg->getLeftLoc(),
1568 OldMsg->getSuperLoc(),
1569 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
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")(static_cast<void> (0));
1687 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&(static_cast<void> (0))
1688 "ObjCForCollectionStmt Statement stack mismatch")(static_cast<void> (0));
1689 assert(!ObjCBcLabelNo.empty() &&(static_cast<void> (0))
1690 "ObjCForCollectionStmt - Label No stack empty")(static_cast<void> (0));
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 {
1718 DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
1719 elementName = DR->getDecl()->getName();
1720 ValueDecl *VD = DR->getDecl();
1721 if (VD->getType()->isObjCQualifiedIdType() ||
1722 VD->getType()->isObjCQualifiedInterfaceType())
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 ';'")(static_cast<void> (0));
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")(static_cast<void> (0));
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 == '{')(static_cast<void> (0));
1897 ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);
1898
1899 SourceLocation startRBraceLoc = S->getSynchBody()->getEndLoc();
1900 assert((*SM->getCharacterData(startRBraceLoc) == '}') &&(static_cast<void> (0))
1901 "bogus @synchronized block")(static_cast<void> (0));
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")(static_cast<void> (0));
1954 if (finalStmt)
1955 ReplaceText(startLoc, 1, buf);
1956 else
1957 // @try -> try
1958 ReplaceText(startLoc, 1, "");
1959
1960 for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
1961 ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
1962 VarDecl *catchDecl = Catch->getCatchParamDecl();
1963
1964 startLoc = Catch->getBeginLoc();
1965 bool AtRemoved = false;
1966 if (catchDecl) {
1967 QualType t = catchDecl->getType();
1968 if (const ObjCObjectPointerType *Ptr = t->getAs<ObjCObjectPointerType>()) {
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")(static_cast<void> (0));
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")(static_cast<void> (0));
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'")(static_cast<void> (0));
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 ';'")(static_cast<void> (0));
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")(static_cast<void> (0));
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")(static_cast<void> (0));
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")(static_cast<void> (0));
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");
2317 SmallVector<QualType, 16> ArgTys;
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");
2412 SmallVector<QualType, 16> ArgTys;
2413 QualType argT = Context->getObjCIdType();
2414 assert(!argT.isNull() && "Can't find 'id' type")(static_cast<void> (0));
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");
2429 SmallVector<QualType, 16> ArgTys;
2430 QualType argT = Context->getObjCIdType();
2431 assert(!argT.isNull() && "Can't find 'id' type")(static_cast<void> (0));
2432 ArgTys.push_back(argT);
2433 argT = Context->getObjCSelType();
2434 assert(!argT.isNull() && "Can't find 'SEL' type")(static_cast<void> (0));
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");
2448 SmallVector<QualType, 2> ArgTys;
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");
2462 SmallVector<QualType, 16> ArgTys;
2463 QualType argT = Context->getObjCIdType();
2464 assert(!argT.isNull() && "Can't find 'id' type")(static_cast<void> (0));
2465 ArgTys.push_back(argT);
2466 argT = Context->getObjCSelType();
2467 assert(!argT.isNull() && "Can't find 'SEL' type")(static_cast<void> (0));
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");
2483 SmallVector<QualType, 2> ArgTys;
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");
2498 SmallVector<QualType, 16> ArgTys;
2499 QualType argT = Context->getObjCIdType();
2500 assert(!argT.isNull() && "Can't find 'id' type")(static_cast<void> (0));
2501 ArgTys.push_back(argT);
2502 argT = Context->getObjCSelType();
2503 assert(!argT.isNull() && "Can't find 'SEL' type")(static_cast<void> (0));
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");
2517 SmallVector<QualType, 16> ArgTys;
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");
2532 SmallVector<QualType, 16> ArgTys;
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");
2547 SmallVector<QualType, 16> ArgTys;
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")(static_cast<void> (0));
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 += prettyBuf.str();
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());
2592 Expr *Unop = UnaryOperator::Create(
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(*Context, TTK_Struct, TUDecl,
2981 SourceLocation(), SourceLocation(),
2982 &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->getTagDeclType(SuperStructDecl);
3004}
3005
3006QualType RewriteModernObjC::getConstantStringStructType() {
3007 if (!ConstantStringDecl) {
3008 ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
3009 SourceLocation(), SourceLocation(),
3010 &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->getTagDeclType(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")(static_cast<void> (0));
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);
3191 MemberExpr *ME = MemberExpr::CreateImplicit(
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()) {
3234 case ObjCMessageExpr::SuperClass: {
3235 MsgSendFlavor = MsgSendSuperFunctionDecl;
3236 if (MsgSendStretFlavor)
3237 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
3238 assert(MsgSendFlavor && "MsgSendFlavor is NULL!")(static_cast<void> (0));
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());
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
3314 case ObjCMessageExpr::Class: {
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
3329 case ObjCMessageExpr::SuperInstance:{
3330 MsgSendFlavor = MsgSendSuperFunctionDecl;
3331 if (MsgSendStretFlavor)
3332 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
3333 assert(MsgSendFlavor && "MsgSendFlavor is NULL!")(static_cast<void> (0));
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());
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
3400 case ObjCMessageExpr::Instance: {
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 (isa<TypedefType>(Type)) {
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 RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
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")(static_cast<void> (0));
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 }
3663 else if (Type->isEnumeralType()) {
3664 EnumDecl *ED = Type->castAs<EnumType>()->getDecl();
3665 if (ED->isCompleteDefinition()) {
3666 Result += "\n\tenum ";
3667 Result += ED->getName();
3668 if (GlobalDefinedTags.count(ED)) {
3669 // Enum is globall defined, use it.
3670 Result += " ";
3671 return true;
3672 }
3673
3674 Result += " {\n";
3675 for (const auto *EC : ED->enumerators()) {
3676 Result += "\t"; Result += EC->getName(); Result += " = ";
3677 Result += toString(EC->getInitVal(), 10);
3678 Result += ",\n";
3679 }
3680 Result += "\t} ";
3681 return true;
3682 }
3683 }
3684
3685 Result += "\t";
3686 convertObjCTypeToCStyleType(Type);
3687 return false;
3688}
3689
3690
3691/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer.
3692/// It handles elaborated types, as well as enum types in the process.
3693void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,
3694 std::string &Result) {
3695 QualType Type = fieldDecl->getType();
3696 std::string Name = fieldDecl->getNameAsString();
3697
3698 bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);
3699 if (!EleboratedType)
3700 Type.getAsStringInternal(Name, Context->getPrintingPolicy());
3701 Result += Name;
3702 if (fieldDecl->isBitField()) {
3703 Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context));
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 (isa<TypedefType>(Type))
3727 return;
3728 if (Type->isArrayType())
3729 Type = Context->getBaseElementType(Type);
3730
3731 auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());
3732
3733 TagDecl *TD = nullptr;
3734 if (Type->isRecordType()) {
3735 TD = Type->castAs<RecordType>()->getDecl();
3736 }
3737 else if (Type->isEnumeralType()) {
3738 TD = Type->castAs<EnumType>()->getDecl();
3739 }
3740
3741 if (TD) {
3742 if (GlobalDefinedTags.count(TD))
3743 return;
3744
3745 bool IsNamedDefinition = false;
3746 if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {
3747 RewriteObjCFieldDeclType(Type, Result);
3748 Result += ";";
3749 }
3750 if (IsNamedDefinition)
3751 GlobalDefinedTags.insert(TD);
3752 }
3753}
3754
3755unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) {
3756 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3757 if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) {
3758 return IvarGroupNumber[IV];
3759 }
3760 unsigned GroupNo = 0;
3761 SmallVector<const ObjCIvarDecl *, 8> IVars;
3762 for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
3763 IVD; IVD = IVD->getNextIvar())
3764 IVars.push_back(IVD);
3765
3766 for (unsigned i = 0, e = IVars.size(); i < e; i++)
3767 if (IVars[i]->isBitField()) {
3768 IvarGroupNumber[IVars[i++]] = ++GroupNo;
3769 while (i < e && IVars[i]->isBitField())
3770 IvarGroupNumber[IVars[i++]] = GroupNo;
3771 if (i < e)
3772 --i;
3773 }
3774
3775 ObjCInterefaceHasBitfieldGroups.insert(CDecl);
3776 return IvarGroupNumber[IV];
3777}
3778
3779QualType RewriteModernObjC::SynthesizeBitfieldGroupStructType(
3780 ObjCIvarDecl *IV,
3781 SmallVectorImpl<ObjCIvarDecl *> &IVars) {
3782 std::string StructTagName;
3783 ObjCIvarBitfieldGroupType(IV, StructTagName);
3784 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct,
3785 Context->getTranslationUnitDecl(),
3786 SourceLocation(), SourceLocation(),
3787 &Context->Idents.get(StructTagName));
3788 for (unsigned i=0, e = IVars.size(); i < e; i++) {
3789 ObjCIvarDecl *Ivar = IVars[i];
3790 RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(),
3791 &Context->Idents.get(Ivar->getName()),
3792 Ivar->getType(),
3793 nullptr, /*Expr *BW */Ivar->getBitWidth(),
3794 false, ICIS_NoInit));
3795 }
3796 RD->completeDefinition();
3797 return Context->getTagDeclType(RD);
3798}
3799
3800QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) {
3801 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3802 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3803 std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo);
3804 if (GroupRecordType.count(tuple))
3805 return GroupRecordType[tuple];
3806
3807 SmallVector<ObjCIvarDecl *, 8> IVars;
3808 for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
3809 IVD; IVD = IVD->getNextIvar()) {
3810 if (IVD->isBitField())
3811 IVars.push_back(const_cast<ObjCIvarDecl *>(IVD));
3812 else {
3813 if (!IVars.empty()) {
3814 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);
3815 // Generate the struct type for this group of bitfield ivars.
3816 GroupRecordType[std::make_pair(CDecl, GroupNo)] =
3817 SynthesizeBitfieldGroupStructType(IVars[0], IVars);
3818 IVars.clear();
3819 }
3820 }
3821 }
3822 if (!IVars.empty()) {
3823 // Do the last one.
3824 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);
3825 GroupRecordType[std::make_pair(CDecl, GroupNo)] =
3826 SynthesizeBitfieldGroupStructType(IVars[0], IVars);
3827 }
3828 QualType RetQT = GroupRecordType[tuple];
3829 assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL")(static_cast<void> (0));
3830
3831 return RetQT;
3832}
3833
3834/// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group.
3835/// Name would be: classname__GRBF_n where n is the group number for this ivar.
3836void RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV,
3837 std::string &Result) {
3838 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3839 Result += CDecl->getName();
3840 Result += "__GRBF_";
3841 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3842 Result += utostr(GroupNo);
3843}
3844
3845/// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group.
3846/// Name of the struct would be: classname__T_n where n is the group number for
3847/// this ivar.
3848void RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV,
3849 std::string &Result) {
3850 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();
3851 Result += CDecl->getName();
3852 Result += "__T_";
3853 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);
3854 Result += utostr(GroupNo);
3855}
3856
3857/// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset.
3858/// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for
3859/// this ivar.
3860void RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV,
3861 std::string &Result) {
3862 Result += "OBJC_IVAR_$_";
3863 ObjCIvarBitfieldGroupDecl(IV, Result);
3864}
3865
3866#define SKIP_BITFIELDS(IX, ENDIX, VEC){ while ((IX < ENDIX) && VEC[IX]->isBitField())
++IX; if (IX < ENDIX) --IX; }
{ \
3867 while ((IX < ENDIX) && VEC[IX]->isBitField()) \
3868 ++IX; \
3869 if (IX < ENDIX) \
3870 --IX; \
3871}
3872
3873/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
3874/// an objective-c class with ivars.
3875void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
3876 std::string &Result) {
3877 assert(CDecl && "Class missing in SynthesizeObjCInternalStruct")(static_cast<void> (0));
3878 assert(CDecl->getName() != "" &&(static_cast<void> (0))
3879 "Name missing in SynthesizeObjCInternalStruct")(static_cast<void> (0));
3880 ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
3881 SmallVector<ObjCIvarDecl *, 8> IVars;
3882 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
3883 IVD; IVD = IVD->getNextIvar())
3884 IVars.push_back(IVD);
3885
3886 SourceLocation LocStart = CDecl->getBeginLoc();
3887 SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
3888
3889 const char *startBuf = SM->getCharacterData(LocStart);
3890 const char *endBuf = SM->getCharacterData(LocEnd);
3891
3892 // If no ivars and no root or if its root, directly or indirectly,
3893 // have no ivars (thus not synthesized) then no need to synthesize this class.
3894 if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&
3895 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3896 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3897 ReplaceText(LocStart, endBuf-startBuf, Result);
3898 return;
3899 }
3900
3901 // Insert named struct/union definitions inside class to
3902 // outer scope. This follows semantics of locally defined
3903 // struct/unions in objective-c classes.
3904 for (unsigned i = 0, e = IVars.size(); i < e; i++)
3905 RewriteLocallyDefinedNamedAggregates(IVars[i], Result);
3906
3907 // Insert named structs which are syntheized to group ivar bitfields
3908 // to outer scope as well.
3909 for (unsigned i = 0, e = IVars.size(); i < e; i++)
3910 if (IVars[i]->isBitField()) {
3911 ObjCIvarDecl *IV = IVars[i];
3912 QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV);
3913 RewriteObjCFieldDeclType(QT, Result);
3914 Result += ";";
3915 // skip over ivar bitfields in this group.
3916 SKIP_BITFIELDS(i , e, IVars){ while ((i < e) && IVars[i]->isBitField()) ++i
; if (i < e) --i; }
;
3917 }
3918
3919 Result += "\nstruct ";
3920 Result += CDecl->getNameAsString();
3921 Result += "_IMPL {\n";
3922
3923 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
3924 Result += "\tstruct "; Result += RCDecl->getNameAsString();
3925 Result += "_IMPL "; Result += RCDecl->getNameAsString();
3926 Result += "_IVARS;\n";
3927 }
3928
3929 for (unsigned i = 0, e = IVars.size(); i < e; i++) {
3930 if (IVars[i]->isBitField()) {
3931 ObjCIvarDecl *IV = IVars[i];
3932 Result += "\tstruct ";
3933 ObjCIvarBitfieldGroupType(IV, Result); Result += " ";
3934 ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n";
3935 // skip over ivar bitfields in this group.
3936 SKIP_BITFIELDS(i , e, IVars){ while ((i < e) && IVars[i]->isBitField()) ++i
; if (i < e) --i; }
;
3937 }
3938 else
3939 RewriteObjCFieldDecl(IVars[i], Result);
3940 }
3941
3942 Result += "};\n";
3943 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3944 ReplaceText(LocStart, endBuf-startBuf, Result);
3945 // Mark this struct as having been generated.
3946 if (!ObjCSynthesizedStructs.insert(CDecl).second)
3947 llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct")__builtin_unreachable();
3948}
3949
3950/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which
3951/// have been referenced in an ivar access expression.
3952void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,
3953 std::string &Result) {
3954 // write out ivar offset symbols which have been referenced in an ivar
3955 // access expression.
3956 llvm::SmallSetVector<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl];
3957
3958 if (Ivars.empty())
3959 return;
3960
3961 llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput;
3962 for (ObjCIvarDecl *IvarDecl : Ivars) {
3963 const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface();
3964 unsigned GroupNo = 0;
3965 if (IvarDecl->isBitField()) {
3966 GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl);
3967 if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo)))
3968 continue;
3969 }
3970 Result += "\n";
3971 if (LangOpts.MicrosoftExt)
3972 Result += "__declspec(allocate(\".objc_ivar$B\")) ";
3973 Result += "extern \"C\" ";
3974 if (LangOpts.MicrosoftExt &&
3975 IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&
3976 IvarDecl->getAccessControl() != ObjCIvarDecl::Package)
3977 Result += "__declspec(dllimport) ";
3978
3979 Result += "unsigned long ";
3980 if (IvarDecl->isBitField()) {
3981 ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
3982 GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo));
3983 }
3984 else
3985 WriteInternalIvarName(CDecl, IvarDecl, Result);
3986 Result += ";";
3987 }
3988}
3989
3990//===----------------------------------------------------------------------===//
3991// Meta Data Emission
3992//===----------------------------------------------------------------------===//
3993
3994/// RewriteImplementations - This routine rewrites all method implementations
3995/// and emits meta-data.
3996
3997void RewriteModernObjC::RewriteImplementations() {
3998 int ClsDefCount = ClassImplementation.size();
3999 int CatDefCount = CategoryImplementation.size();
4000
4001 // Rewrite implemented methods
4002 for (int i = 0; i < ClsDefCount; i++) {
4003 ObjCImplementationDecl *OIMP = ClassImplementation[i];
4004 ObjCInterfaceDecl *CDecl = OIMP->getClassInterface();
4005 if (CDecl->isImplicitInterfaceDecl())
4006 assert(false &&(static_cast<void> (0))
4007 "Legacy implicit interface rewriting not supported in moder abi")(static_cast<void> (0));
4008 RewriteImplementationDecl(OIMP);
4009 }
4010
4011 for (int i = 0; i < CatDefCount; i++) {
4012 ObjCCategoryImplDecl *CIMP = CategoryImplementation[i];
4013 ObjCInterfaceDecl *CDecl = CIMP->getClassInterface();
4014 if (CDecl->isImplicitInterfaceDecl())
4015 assert(false &&(static_cast<void> (0))
4016 "Legacy implicit interface rewriting not supported in moder abi")(static_cast<void> (0));
4017 RewriteImplementationDecl(CIMP);
4018 }
4019}
4020
4021void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,
4022 const std::string &Name,
4023 ValueDecl *VD, bool def) {
4024 assert(BlockByRefDeclNo.count(VD) &&(static_cast<void> (0))
4025 "RewriteByRefString: ByRef decl missing")(static_cast<void> (0));
4026 if (def)
4027 ResultStr += "struct ";
4028 ResultStr += "__Block_byref_" + Name +
4029 "_" + utostr(BlockByRefDeclNo[VD]) ;
4030}
4031
4032static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
4033 if (VarDecl *Var = dyn_cast<VarDecl>(VD))
4034 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
4035 return false;
4036}
4037
4038std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
4039 StringRef funcName,
4040 std::string Tag) {
4041 const FunctionType *AFT = CE->getFunctionType();
4042 QualType RT = AFT->getReturnType();
4043 std::string StructRef = "struct " + Tag;
4044 SourceLocation BlockLoc = CE->getExprLoc();
4045 std::string S;
4046 ConvertSourceLocationToLineDirective(BlockLoc, S);
4047
4048 S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
4049 funcName.str() + "_block_func_" + utostr(i);
4050
4051 BlockDecl *BD = CE->getBlockDecl();
4052
4053 if (isa<FunctionNoProtoType>(AFT)) {
4054 // No user-supplied arguments. Still need to pass in a pointer to the
4055 // block (to reference imported block decl refs).
4056 S += "(" + StructRef + " *__cself)";
4057 } else if (BD->param_empty()) {
4058 S += "(" + StructRef + " *__cself)";
4059 } else {
4060 const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
4061 assert(FT && "SynthesizeBlockFunc: No function proto")(static_cast<void> (0));
4062 S += '(';
4063 // first add the implicit argument.
4064 S += StructRef + " *__cself, ";
4065 std::string ParamStr;
4066 for (BlockDecl::param_iterator AI = BD->param_begin(),
4067 E = BD->param_end(); AI != E; ++AI) {
4068 if (AI != BD->param_begin()) S += ", ";
4069 ParamStr = (*AI)->getNameAsString();
4070 QualType QT = (*AI)->getType();
4071 (void)convertBlockPointerToFunctionPointer(QT);
4072 QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
4073 S += ParamStr;
4074 }
4075 if (FT->isVariadic()) {
4076 if (!BD->param_empty()) S += ", ";
4077 S += "...";
4078 }
4079 S += ')';
4080 }
4081 S += " {\n";
4082
4083 // Create local declarations to avoid rewriting all closure decl ref exprs.
4084 // First, emit a declaration for all "by ref" decls.
4085 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
4086 E = BlockByRefDecls.end(); I != E; ++I) {
4087 S += " ";
4088 std::string Name = (*I)->getNameAsString();
4089 std::string TypeString;
4090 RewriteByRefString(TypeString, Name, (*I));
4091 TypeString += " *";
4092 Name = TypeString + Name;
4093 S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
4094 }
4095 // Next, emit a declaration for all "by copy" declarations.
4096 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
4097 E = BlockByCopyDecls.end(); I != E; ++I) {
4098 S += " ";
4099 // Handle nested closure invocation. For example:
4100 //
4101 // void (^myImportedClosure)(void);
4102 // myImportedClosure = ^(void) { setGlobalInt(x + y); };
4103 //
4104 // void (^anotherClosure)(void);
4105 // anotherClosure = ^(void) {
4106 // myImportedClosure(); // import and invoke the closure
4107 // };
4108 //
4109 if (isTopLevelBlockPointerType((*I)->getType())) {
4110 RewriteBlockPointerTypeVariable(S, (*I));
4111 S += " = (";
4112 RewriteBlockPointerType(S, (*I)->getType());
4113 S += ")";
4114 S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
4115 }
4116 else {
4117 std::string Name = (*I)->getNameAsString();
4118 QualType QT = (*I)->getType();
4119 if (HasLocalVariableExternalStorage(*I))
4120 QT = Context->getPointerType(QT);
4121 QT.getAsStringInternal(Name, Context->getPrintingPolicy());
4122 S += Name + " = __cself->" +
4123 (*I)->getNameAsString() + "; // bound by copy\n";
4124 }
4125 }
4126 std::string RewrittenStr = RewrittenBlockExprs[CE];
4127 const char *cstr = RewrittenStr.c_str();
4128 while (*cstr++ != '{') ;
4129 S += cstr;
4130 S += "\n";
4131 return S;
4132}
4133
4134std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
4135 StringRef funcName,
4136 std::string Tag) {
4137 std::string StructRef = "struct " + Tag;
4138 std::string S = "static void __";
4139
4140 S += funcName;
4141 S += "_block_copy_" + utostr(i);
4142 S += "(" + StructRef;
4143 S += "*dst, " + StructRef;
4144 S += "*src) {";
4145 for (ValueDecl *VD : ImportedBlockDecls) {
4146 S += "_Block_object_assign((void*)&dst->";
4147 S += VD->getNameAsString();
4148 S += ", (void*)src->";
4149 S += VD->getNameAsString();
4150 if (BlockByRefDeclsPtrSet.count(VD))
4151 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
4152 else if (VD->getType()->isBlockPointerType())
4153 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
4154 else
4155 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
4156 }
4157 S += "}\n";
4158
4159 S += "\nstatic void __";
4160 S += funcName;
4161 S += "_block_dispose_" + utostr(i);
4162 S += "(" + StructRef;
4163 S += "*src) {";
4164 for (ValueDecl *VD : ImportedBlockDecls) {
4165 S += "_Block_object_dispose((void*)src->";
4166 S += VD->getNameAsString();
4167 if (BlockByRefDeclsPtrSet.count(VD))
4168 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
4169 else if (VD->getType()->isBlockPointerType())
4170 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
4171 else
4172 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
4173 }
4174 S += "}\n";
4175 return S;
4176}
4177
4178std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
4179 std::string Desc) {
4180 std::string S = "\nstruct " + Tag;
4181 std::string Constructor = " " + Tag;
4182
4183 S += " {\n struct __block_impl impl;\n";
4184 S += " struct " + Desc;
4185 S += "* Desc;\n";
4186
4187 Constructor += "(void *fp, "; // Invoke function pointer.
4188 Constructor += "struct " + Desc; // Descriptor pointer.
4189 Constructor += " *desc";
4190
4191 if (BlockDeclRefs.size()) {
4192 // Output all "by copy" declarations.
4193 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
4194 E = BlockByCopyDecls.end(); I != E; ++I) {
4195 S += " ";
4196 std::string FieldName = (*I)->getNameAsString();
4197 std::string ArgName = "_" + FieldName;
4198 // Handle nested closure invocation. For example:
4199 //
4200 // void (^myImportedBlock)(void);
4201 // myImportedBlock = ^(void) { setGlobalInt(x + y); };
4202 //
4203 // void (^anotherBlock)(void);
4204 // anotherBlock = ^(void) {
4205 // myImportedBlock(); // import and invoke the closure
4206 // };
4207 //
4208 if (isTopLevelBlockPointerType((*I)->getType())) {
4209 S += "struct __block_impl *";
4210 Constructor += ", void *" + ArgName;
4211 } else {
4212 QualType QT = (*I)->getType();
4213 if (HasLocalVariableExternalStorage(*I))
4214 QT = Context->getPointerType(QT);
4215 QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
4216 QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
4217 Constructor += ", " + ArgName;
4218 }
4219 S += FieldName + ";\n";
4220 }
4221 // Output all "by ref" declarations.
4222 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
4223 E = BlockByRefDecls.end(); I != E; ++I) {
4224 S += " ";
4225 std::string FieldName = (*I)->getNameAsString();
4226 std::string ArgName = "_" + FieldName;
4227 {
4228 std::string TypeString;
4229 RewriteByRefString(TypeString, FieldName, (*I));
4230 TypeString += " *";
4231 FieldName = TypeString + FieldName;
4232 ArgName = TypeString + ArgName;
4233 Constructor += ", " + ArgName;
4234 }
4235 S += FieldName + "; // by ref\n";
4236 }
4237 // Finish writing the constructor.
4238 Constructor += ", int flags=0)";
4239 // Initialize all "by copy" arguments.
4240 bool firsTime = true;
4241 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
4242 E = BlockByCopyDecls.end(); I != E; ++I) {
4243 std::string Name = (*I)->getNameAsString();
4244 if (firsTime) {
4245 Constructor += " : ";
4246 firsTime = false;
4247 }
4248 else
4249 Constructor += ", ";
4250 if (isTopLevelBlockPointerType((*I)->getType()))
4251 Constructor += Name + "((struct __block_impl *)_" + Name + ")";
4252 else
4253 Constructor += Name + "(_" + Name + ")";
4254 }
4255 // Initialize all "by ref" arguments.
4256 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
4257 E = BlockByRefDecls.end(); I != E; ++I) {
4258 std::string Name = (*I)->getNameAsString();
4259 if (firsTime) {
4260 Constructor += " : ";
4261 firsTime = false;
4262 }
4263 else
4264 Constructor += ", ";
4265 Constructor += Name + "(_" + Name + "->__forwarding)";
4266 }
4267
4268 Constructor += " {\n";
4269 if (GlobalVarDecl)
4270 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
4271 else
4272 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
4273 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
4274
4275 Constructor += " Desc = desc;\n";
4276 } else {
4277 // Finish writing the constructor.
4278 Constructor += ", int flags=0) {\n";
4279 if (GlobalVarDecl)
4280 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
4281 else
4282 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
4283 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
4284 Constructor += " Desc = desc;\n";
4285 }
4286 Constructor += " ";
4287 Constructor += "}\n";
4288 S += Constructor;
4289 S += "};\n";
4290 return S;
4291}
4292
4293std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag,
4294 std::string ImplTag, int i,
4295 StringRef FunName,
4296 unsigned hasCopy) {
4297 std::string S = "\nstatic struct " + DescTag;
4298
4299 S += " {\n size_t reserved;\n";
4300 S += " size_t Block_size;\n";
4301 if (hasCopy) {
4302 S += " void (*copy)(struct ";
4303 S += ImplTag; S += "*, struct ";
4304 S += ImplTag; S += "*);\n";
4305
4306 S += " void (*dispose)(struct ";
4307 S += ImplTag; S += "*);\n";
4308 }
4309 S += "} ";
4310
4311 S += DescTag + "_DATA = { 0, sizeof(struct ";
4312 S += ImplTag + ")";
4313 if (hasCopy) {
4314 S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
4315 S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
4316 }
4317 S += "};\n";
4318 return S;
4319}
4320
4321void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
4322 StringRef FunName) {
4323 bool RewriteSC = (GlobalVarDecl &&
4324 !Blocks.empty() &&
4325 GlobalVarDecl->getStorageClass() == SC_Static &&
4326 GlobalVarDecl->getType().getCVRQualifiers());
4327 if (RewriteSC) {
4328 std::string SC(" void __");
4329 SC += GlobalVarDecl->getNameAsString();
4330 SC += "() {}";
4331 InsertText(FunLocStart, SC);
4332 }
4333
4334 // Insert closures that were part of the function.
4335 for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
4336 CollectBlockDeclRefInfo(Blocks[i]);
4337 // Need to copy-in the inner copied-in variables not actually used in this
4338 // block.
4339 for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
4340 DeclRefExpr *Exp = InnerDeclRefs[count++];
4341 ValueDecl *VD = Exp->getDecl();
4342 BlockDeclRefs.push_back(Exp);
4343 if (!VD->hasAttr<BlocksAttr>()) {
4344 if (!BlockByCopyDeclsPtrSet.count(VD)) {
4345 BlockByCopyDeclsPtrSet.insert(VD);
4346 BlockByCopyDecls.push_back(VD);
4347 }
4348 continue;
4349 }
4350
4351 if (!BlockByRefDeclsPtrSet.count(VD)) {
4352 BlockByRefDeclsPtrSet.insert(VD);
4353 BlockByRefDecls.push_back(VD);
4354 }
4355
4356 // imported objects in the inner blocks not used in the outer
4357 // blocks must be copied/disposed in the outer block as well.
4358 if (VD->getType()->isObjCObjectPointerType() ||
4359 VD->getType()->isBlockPointerType())
4360 ImportedBlockDecls.insert(VD);
4361 }
4362
4363 std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
4364 std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
4365
4366 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
4367
4368 InsertText(FunLocStart, CI);
4369
4370 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
4371
4372 InsertText(FunLocStart, CF);
4373
4374 if (ImportedBlockDecls.size()) {
4375 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
4376 InsertText(FunLocStart, HF);
4377 }
4378 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
4379 ImportedBlockDecls.size() > 0);
4380 InsertText(FunLocStart, BD);
4381
4382 BlockDeclRefs.clear();
4383 BlockByRefDecls.clear();
4384 BlockByRefDeclsPtrSet.clear();
4385 BlockByCopyDecls.clear();
4386 BlockByCopyDeclsPtrSet.clear();
4387 ImportedBlockDecls.clear();
4388 }
4389 if (RewriteSC) {
4390 // Must insert any 'const/volatile/static here. Since it has been
4391 // removed as result of rewriting of block literals.
4392 std::string SC;
4393 if (GlobalVarDecl->getStorageClass() == SC_Static)
4394 SC = "static ";
4395 if (GlobalVarDecl->getType().isConstQualified())
4396 SC += "const ";
4397 if (GlobalVarDecl->getType().isVolatileQualified())
4398 SC += "volatile ";
4399 if (GlobalVarDecl->getType().isRestrictQualified())
4400 SC += "restrict ";
4401 InsertText(FunLocStart, SC);
4402 }
4403 if (GlobalConstructionExp) {
4404 // extra fancy dance for global literal expression.
4405
4406 // Always the latest block expression on the block stack.
4407 std::string Tag = "__";
4408 Tag += FunName;
4409 Tag += "_block_impl_";
4410 Tag += utostr(Blocks.size()-1);
4411 std::string globalBuf = "static ";
4412 globalBuf += Tag; globalBuf += " ";
4413 std::string SStr;
4414
4415 llvm::raw_string_ostream constructorExprBuf(SStr);
4416 GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,
4417 PrintingPolicy(LangOpts));
4418 globalBuf += constructorExprBuf.str();
4419 globalBuf += ";\n";
4420 InsertText(FunLocStart, globalBuf);
4421 GlobalConstructionExp = nullptr;
4422 }
4423
4424 Blocks.clear();
4425 InnerDeclRefsCount.clear();
4426 InnerDeclRefs.clear();
4427 RewrittenBlockExprs.clear();
4428}
4429
4430void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
4431 SourceLocation FunLocStart =
4432 (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD)
4433 : FD->getTypeSpecStartLoc();
4434 StringRef FuncName = FD->getName();
4435
4436 SynthesizeBlockLiterals(FunLocStart, FuncName);
4437}
4438
4439static void BuildUniqueMethodName(std::string &Name,
4440 ObjCMethodDecl *MD) {
4441 ObjCInterfaceDecl *IFace = MD->getClassInterface();
4442 Name = std::string(IFace->getName());
4443 Name += "__" + MD->getSelector().getAsString();
4444 // Convert colons to underscores.
4445 std::string::size_type loc = 0;
4446 while ((loc = Name.find(':', loc)) != std::string::npos)
4447 Name.replace(loc, 1, "_");
4448}
4449
4450void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
4451 // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
4452 // SourceLocation FunLocStart = MD->getBeginLoc();
4453 SourceLocation FunLocStart = MD->getBeginLoc();
4454 std::string FuncName;
4455 BuildUniqueMethodName(FuncName, MD);
4456 SynthesizeBlockLiterals(FunLocStart, FuncName);
4457}
4458
4459void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {
4460 for (Stmt *SubStmt : S->children())
4461 if (SubStmt) {
4462 if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
4463 GetBlockDeclRefExprs(CBE->getBody());
4464 else
4465 GetBlockDeclRefExprs(SubStmt);
4466 }
4467 // Handle specific things.
4468 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
4469 if (DRE->refersToEnclosingVariableOrCapture() ||
4470 HasLocalVariableExternalStorage(DRE->getDecl()))
4471 // FIXME: Handle enums.
4472 BlockDeclRefs.push_back(DRE);
4473}
4474
4475void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,
4476 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
4477 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
4478 for (Stmt *SubStmt : S->children())
4479 if (SubStmt) {
4480 if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
4481 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
4482 GetInnerBlockDeclRefExprs(CBE->getBody(),
4483 InnerBlockDeclRefs,
4484 InnerContexts);
4485 }
4486 else
4487 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
4488 }
4489 // Handle specific things.
4490 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4491 if (DRE->refersToEnclosingVariableOrCapture() ||
4492 HasLocalVariableExternalStorage(DRE->getDecl())) {
4493 if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
4494 InnerBlockDeclRefs.push_back(DRE);
4495 if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
4496 if (Var->isFunctionOrMethodVarDecl())
4497 ImportedLocalExternalDecls.insert(Var);
4498 }
4499 }
4500}
4501
4502/// convertObjCTypeToCStyleType - This routine converts such objc types
4503/// as qualified objects, and blocks to their closest c/c++ types that
4504/// it can. It returns true if input type was modified.
4505bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {
4506 QualType oldT = T;
4507 convertBlockPointerToFunctionPointer(T);
4508 if (T->isFunctionPointerType()) {
4509 QualType PointeeTy;
4510 if (const PointerType* PT = T->getAs<PointerType>()) {
4511 PointeeTy = PT->getPointeeType();
4512 if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {
4513 T = convertFunctionTypeOfBlocks(FT);
4514 T = Context->getPointerType(T);
4515 }
4516 }
4517 }
4518
4519 convertToUnqualifiedObjCType(T);
4520 return T != oldT;
4521}
4522
4523/// convertFunctionTypeOfBlocks - This routine converts a function type
4524/// whose result type may be a block pointer or whose argument type(s)
4525/// might be block pointers to an equivalent function type replacing
4526/// all block pointers to function pointers.
4527QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
4528 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
4529 // FTP will be null for closures that don't take arguments.
4530 // Generate a funky cast.
4531 SmallVector<QualType, 8> ArgTypes;
4532 QualType Res = FT->getReturnType();
4533 bool modified = convertObjCTypeToCStyleType(Res);
4534
4535 if (FTP) {
4536 for (auto &I : FTP->param_types()) {
4537 QualType t = I;
4538 // Make sure we convert "t (^)(...)" to "t (*)(...)".
4539 if (convertObjCTypeToCStyleType(t))
4540 modified = true;
4541 ArgTypes.push_back(t);
4542 }
4543 }
4544 QualType FuncType;
4545 if (modified)
4546 FuncType = getSimpleFunctionType(Res, ArgTypes);
4547 else FuncType = QualType(FT, 0);
4548 return FuncType;
4549}
4550
4551Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
4552 // Navigate to relevant type information.
4553 const BlockPointerType *CPT = nullptr;
4554
4555 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
4556 CPT = DRE->getType()->getAs<BlockPointerType>();
4557 } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
4558 CPT = MExpr->getType()->getAs<BlockPointerType>();
4559 }
4560 else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
4561 return SynthesizeBlockCall(Exp, PRE->getSubExpr());
4562 }
4563 else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
4564 CPT = IEXPR->getType()->getAs<BlockPointerType>();
4565 else if (const ConditionalOperator *CEXPR =
4566 dyn_cast<ConditionalOperator>(BlockExp)) {
4567 Expr *LHSExp = CEXPR->getLHS();
4568 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
4569 Expr *RHSExp = CEXPR->getRHS();
4570 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
4571 Expr *CONDExp = CEXPR->getCond();
4572 ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
4573 CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
4574 cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
4575 return CondExpr;
4576 } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
4577 CPT = IRE->getType()->getAs<BlockPointerType>();
4578 } else if (const PseudoObjectExpr *POE
4579 = dyn_cast<PseudoObjectExpr>(BlockExp)) {
4580 CPT = POE->getType()->castAs<BlockPointerType>();
4581 } else {
4582 assert(false && "RewriteBlockClass: Bad type")(static_cast<void> (0));
4583 }
4584 assert(CPT && "RewriteBlockClass: Bad type")(static_cast<void> (0));
4585 const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
4586 assert(FT && "RewriteBlockClass: Bad type")(static_cast<void> (0));
4587 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
4588 // FTP will be null for closures that don't take arguments.
4589
4590 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
4591 SourceLocation(), SourceLocation(),
4592 &Context->Idents.get("__block_impl"));
4593 QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
4594
4595 // Generate a funky cast.
4596 SmallVector<QualType, 8> ArgTypes;
4597
4598 // Push the block argument type.
4599 ArgTypes.push_back(PtrBlock);
4600 if (FTP) {
4601 for (auto &I : FTP->param_types()) {
4602 QualType t = I;
4603 // Make sure we convert "t (^)(...)" to "t (*)(...)".
4604 if (!convertBlockPointerToFunctionPointer(t))
4605 convertToUnqualifiedObjCType(t);
4606 ArgTypes.push_back(t);
4607 }
4608 }
4609 // Now do the pointer to function cast.
4610 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);
4611
4612 PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
4613
4614 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
4615 CK_BitCast,
4616 const_cast<Expr*>(BlockExp));
4617 // Don't forget the parens to enforce the proper binding.
4618 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
4619 BlkCast);
4620 //PE->dump();
4621
4622 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
4623 SourceLocation(),
4624 &Context->Idents.get("FuncPtr"),
4625 Context->VoidPtrTy, nullptr,
4626 /*BitWidth=*/nullptr, /*Mutable=*/true,
4627 ICIS_NoInit);
4628 MemberExpr *ME = MemberExpr::CreateImplicit(
4629 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
4630
4631 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
4632 CK_BitCast, ME);
4633 PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
4634
4635 SmallVector<Expr*, 8> BlkExprs;
4636 // Add the implicit argument.
4637 BlkExprs.push_back(BlkCast);
4638 // Add the user arguments.
4639 for (CallExpr::arg_iterator I = Exp->arg_begin(),
4640 E = Exp->arg_end(); I != E; ++I) {
4641 BlkExprs.push_back(*I);
4642 }
4643 CallExpr *CE =
4644 CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,
4645 SourceLocation(), FPOptionsOverride());
4646 return CE;
4647}
4648
4649// We need to return the rewritten expression to handle cases where the
4650// DeclRefExpr is embedded in another expression being rewritten.
4651// For example:
4652//
4653// int main() {
4654// __block Foo *f;
4655// __block int i;
4656//
4657// void (^myblock)() = ^() {
4658// [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten).
4659// i = 77;
4660// };
4661//}
4662Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
4663 // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
4664 // for each DeclRefExp where BYREFVAR is name of the variable.
4665 ValueDecl *VD = DeclRefExp->getDecl();
4666 bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
4667 HasLocalVariableExternalStorage(DeclRefExp->getDecl());
4668
4669 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
4670 SourceLocation(),
4671 &Context->Idents.get("__forwarding"),
4672 Context->VoidPtrTy, nullptr,
4673 /*BitWidth=*/nullptr, /*Mutable=*/true,
4674 ICIS_NoInit);
4675 MemberExpr *ME = MemberExpr::CreateImplicit(
4676 *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary);
4677
4678 StringRef Name = VD->getName();
4679 FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
4680 &Context->Idents.get(Name),
4681 Context->VoidPtrTy, nullptr,
4682 /*BitWidth=*/nullptr, /*Mutable=*/true,
4683 ICIS_NoInit);
4684 ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),
4685 VK_LValue, OK_Ordinary);
4686
4687 // Need parens to enforce precedence.
4688 ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
4689 DeclRefExp->getExprLoc(),
4690 ME);
4691 ReplaceStmt(DeclRefExp, PE);
4692 return PE;
4693}
4694
4695// Rewrites the imported local variable V with external storage
4696// (static, extern, etc.) as *V
4697//
4698Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
4699 ValueDecl *VD = DRE->getDecl();
4700 if (VarDecl *Var = dyn_cast<VarDecl>(VD))
4701 if (!ImportedLocalExternalDecls.count(Var))
4702 return DRE;
4703 Expr *Exp = UnaryOperator::Create(
4704 const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),
4705 VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());
4706 // Need parens to enforce precedence.
4707 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
4708 Exp);
4709 ReplaceStmt(DRE, PE);
4710 return PE;
4711}
4712
4713void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {
4714 SourceLocation LocStart = CE->getLParenLoc();
4715 SourceLocation LocEnd = CE->getRParenLoc();
4716
4717 // Need to avoid trying to rewrite synthesized casts.
4718 if (LocStart.isInvalid())
4719 return;
4720 // Need to avoid trying to rewrite casts contained in macros.
4721 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
4722 return;
4723
4724 const char *startBuf = SM->getCharacterData(LocStart);
4725 const char *endBuf = SM->getCharacterData(LocEnd);
4726 QualType QT = CE->getType();
4727 const Type* TypePtr = QT->getAs<Type>();
4728 if (isa<TypeOfExprType>(TypePtr)) {
4729 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
4730 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
4731 std::string TypeAsString = "(";
4732 RewriteBlockPointerType(TypeAsString, QT);
4733 TypeAsString += ")";
4734 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
4735 return;
4736 }
4737 // advance the location to startArgList.
4738 const char *argPtr = startBuf;
4739
4740 while (*argPtr++ && (argPtr < endBuf)) {
4741 switch (*argPtr) {
4742 case '^':
4743 // Replace the '^' with '*'.
4744 LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
4745 ReplaceText(LocStart, 1, "*");
4746 break;
4747 }
4748 }
4749}
4750
4751void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {
4752 CastKind CastKind = IC->getCastKind();
4753 if (CastKind != CK_BlockPointerToObjCPointerCast &&
4754 CastKind != CK_AnyPointerToBlockPointerCast)
4755 return;
4756
4757 QualType QT = IC->getType();
4758 (void)convertBlockPointerToFunctionPointer(QT);
4759 std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));
4760 std::string Str = "(";
4761 Str += TypeString;
4762 Str += ")";
4763 InsertText(IC->getSubExpr()->getBeginLoc(), Str);
4764}
4765
4766void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
4767 SourceLocation DeclLoc = FD->getLocation();
4768 unsigned parenCount = 0;
4769
4770 // We have 1 or more arguments that have closure pointers.
4771 const char *startBuf = SM->getCharacterData(DeclLoc);
4772 const char *startArgList = strchr(startBuf, '(');
4773
4774 assert((*startArgList == '(') && "Rewriter fuzzy parser confused")(static_cast<void> (0));
4775
4776 parenCount++;
4777 // advance the location to startArgList.
4778 DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
4779 assert((DeclLoc.isValid()) && "Invalid DeclLoc")(static_cast<void> (0));
4780
4781 const char *argPtr = startArgList;
4782
4783 while (*argPtr++ && parenCount) {
4784 switch (*argPtr) {
4785 case '^':
4786 // Replace the '^' with '*'.
4787 DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
4788 ReplaceText(DeclLoc, 1, "*");
4789 break;
4790 case '(':
4791 parenCount++;
4792 break;
4793 case ')':
4794 parenCount--;
4795 break;
4796 }
4797 }
4798}
4799
4800bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
4801 const FunctionProtoType *FTP;
4802 const PointerType *PT = QT->getAs<PointerType>();
4803 if (PT) {
4804 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
4805 } else {
4806 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
4807 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type")(static_cast<void> (0));
4808 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
4809 }
4810 if (FTP) {
4811 for (const auto &I : FTP->param_types())
4812 if (isTopLevelBlockPointerType(I))
4813 return true;
4814 }
4815 return false;
4816}
4817
4818bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
4819 const FunctionProtoType *FTP;
4820 const PointerType *PT = QT->getAs<PointerType>();
24
Assuming the object is not a 'PointerType'
4821 if (PT
24.1
'PT' is null
) {
25
Taking false branch
4822 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
4823 } else {
4824 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
26
Assuming the object is not a 'BlockPointerType'
27
'BPT' initialized to a null pointer value
4825 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type")(static_cast<void> (0));
4826 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
28
Called C++ object pointer is null
4827 }
4828 if (FTP) {
4829 for (const auto &I : FTP->param_types()) {
4830 if (I->isObjCQualifiedIdType())
4831 return true;
4832 if (I->isObjCObjectPointerType() &&
4833 I->getPointeeType()->isObjCQualifiedInterfaceType())
4834 return true;
4835 }
4836
4837 }
4838 return false;
4839}
4840
4841void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
4842 const char *&RParen) {
4843 const char *argPtr = strchr(Name, '(');
4844 assert((*argPtr == '(') && "Rewriter fuzzy parser confused")(static_cast<void> (0));
4845
4846 LParen = argPtr; // output the start.
4847 argPtr++; // skip past the left paren.
4848 unsigned parenCount = 1;
4849
4850 while (*argPtr && parenCount) {
4851 switch (*argPtr) {
4852 case '(': parenCount++; break;
4853 case ')': parenCount--; break;
4854 default: break;
4855 }
4856 if (parenCount) argPtr++;
4857 }
4858 assert((*argPtr == ')') && "Rewriter fuzzy parser confused")(static_cast<void> (0));
4859 RParen = argPtr; // output the end
4860}
4861
4862void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
4863 if (FunctionDecl *FD
7.1
'FD' is null
= dyn_cast<FunctionDecl>(ND)) {
7
Assuming 'ND' is not a 'FunctionDecl'
8
Taking false branch
4864 RewriteBlockPointerFunctionArgs(FD);
4865 return;
4866 }
4867 // Handle Variables and Typedefs.
4868 SourceLocation DeclLoc = ND->getLocation();
4869 QualType DeclT;
4870 if (VarDecl *VD
9.1
'VD' is null
= dyn_cast<VarDecl>(ND))
9
Assuming 'ND' is not a 'VarDecl'
10
Taking false branch
4871 DeclT = VD->getType();
4872 else if (TypedefNameDecl *TDD
11.1
'TDD' is null
= dyn_cast<TypedefNameDecl>(ND))
11
Assuming 'ND' is not a 'TypedefNameDecl'
12
Taking false branch
4873 DeclT = TDD->getUnderlyingType();
4874 else if (FieldDecl *FD
13.1
'FD' is non-null
= dyn_cast<FieldDecl>(ND))
13
Assuming 'ND' is a 'FieldDecl'
14
Taking true branch
4875 DeclT = FD->getType();
4876 else
4877 llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled")__builtin_unreachable();
4878
4879 const char *startBuf = SM->getCharacterData(DeclLoc);
4880 const char *endBuf = startBuf;
4881 // scan backward (from the decl location) for the end of the previous decl.
4882 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
15
Assuming the condition is true
16
Assuming the condition is true
17
Assuming 'startBuf' is equal to field 'MainFileStart'
18
Loop condition is false. Execution continues on line 4884
4883 startBuf--;
4884 SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
4885 std::string buf;
4886 unsigned OrigLength=0;
4887 // *startBuf != '^' if we are dealing with a pointer to function that
4888 // may take block argument types (which will be handled below).
4889 if (*startBuf == '^') {
19
Taking false branch
4890 // Replace the '^' with '*', computing a negative offset.
4891 buf = '*';
4892 startBuf++;
4893 OrigLength++;
4894 }
4895 while (*startBuf != ')') {
20
Assuming the condition is false
21
Loop condition is false. Execution continues on line 4900
4896 buf += *startBuf;
4897 startBuf++;
4898 OrigLength++;
4899 }
4900 buf += ')';
4901 OrigLength++;
4902
4903 if (PointerTypeTakesAnyBlockArguments(DeclT) ||
22
Assuming the condition is false
4904 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
23
Calling 'RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType'
4905 // Replace the '^' with '*' for arguments.
4906 // Replace id<P> with id/*<>*/
4907 DeclLoc = ND->getLocation();
4908 startBuf = SM->getCharacterData(DeclLoc);
4909 const char *argListBegin, *argListEnd;
4910 GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4911 while (argListBegin < argListEnd) {
4912 if (*argListBegin == '^')
4913 buf += '*';
4914 else if (*argListBegin == '<') {
4915 buf += "/*";
4916 buf += *argListBegin++;
4917 OrigLength++;
4918 while (*argListBegin != '>') {
4919 buf += *argListBegin++;
4920 OrigLength++;
4921 }
4922 buf += *argListBegin;
4923 buf += "*/";
4924 }
4925 else
4926 buf += *argListBegin;
4927 argListBegin++;
4928 OrigLength++;
4929 }
4930 buf += ')';
4931 OrigLength++;
4932 }
4933 ReplaceText(Start, OrigLength, buf);
4934}
4935
4936/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
4937/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
4938/// struct Block_byref_id_object *src) {
4939/// _Block_object_assign (&_dest->object, _src->object,
4940/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4941/// [|BLOCK_FIELD_IS_WEAK]) // object
4942/// _Block_object_assign(&_dest->object, _src->object,
4943/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4944/// [|BLOCK_FIELD_IS_WEAK]) // block
4945/// }
4946/// And:
4947/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
4948/// _Block_object_dispose(_src->object,
4949/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4950/// [|BLOCK_FIELD_IS_WEAK]) // object
4951/// _Block_object_dispose(_src->object,
4952/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4953/// [|BLOCK_FIELD_IS_WEAK]) // block
4954/// }
4955
4956std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
4957 int flag) {
4958 std::string S;
4959 if (CopyDestroyCache.count(flag))
4960 return S;
4961 CopyDestroyCache.insert(flag);
4962 S = "static void __Block_byref_id_object_copy_";
4963 S += utostr(flag);
4964 S += "(void *dst, void *src) {\n";
4965
4966 // offset into the object pointer is computed as:
4967 // void * + void* + int + int + void* + void *
4968 unsigned IntSize =
4969 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4970 unsigned VoidPtrSize =
4971 static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
4972
4973 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
4974 S += " _Block_object_assign((char*)dst + ";
4975 S += utostr(offset);
4976 S += ", *(void * *) ((char*)src + ";
4977 S += utostr(offset);
4978 S += "), ";
4979 S += utostr(flag);
4980 S += ");\n}\n";
4981
4982 S += "static void __Block_byref_id_object_dispose_";
4983 S += utostr(flag);
4984 S += "(void *src) {\n";
4985 S += " _Block_object_dispose(*(void * *) ((char*)src + ";
4986 S += utostr(offset);
4987 S += "), ";
4988 S += utostr(flag);
4989 S += ");\n}\n";
4990 return S;
4991}
4992
4993/// RewriteByRefVar - For each __block typex ND variable this routine transforms
4994/// the declaration into:
4995/// struct __Block_byref_ND {
4996/// void *__isa; // NULL for everything except __weak pointers
4997/// struct __Block_byref_ND *__forwarding;
4998/// int32_t __flags;
4999/// int32_t __size;
5000/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
5001/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
5002/// typex ND;
5003/// };
5004///
5005/// It then replaces declaration of ND variable with:
5006/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
5007/// __size=sizeof(struct __Block_byref_ND),
5008/// ND=initializer-if-any};
5009///
5010///
5011void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,
5012 bool lastDecl) {
5013 int flag = 0;
5014 int isa = 0;
5015 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
5016 if (DeclLoc.isInvalid())
5017 // If type location is missing, it is because of missing type (a warning).
5018 // Use variable's location which is good for this case.
5019 DeclLoc = ND->getLocation();
5020 const char *startBuf = SM->getCharacterData(DeclLoc);
5021 SourceLocation X = ND->getEndLoc();
5022 X = SM->getExpansionLoc(X);
5023 const char *endBuf = SM->getCharacterData(X);
5024 std::string Name(ND->getNameAsString());
5025 std::string ByrefType;
5026 RewriteByRefString(ByrefType, Name, ND, true);
5027 ByrefType += " {\n";
5028 ByrefType += " void *__isa;\n";
5029 RewriteByRefString(ByrefType, Name, ND);
5030 ByrefType += " *__forwarding;\n";
5031 ByrefType += " int __flags;\n";
5032 ByrefType += " int __size;\n";
5033 // Add void *__Block_byref_id_object_copy;
5034 // void *__Block_byref_id_object_dispose; if needed.
5035 QualType Ty = ND->getType();
5036 bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
5037 if (HasCopyAndDispose) {
5038 ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
5039 ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
5040 }
5041
5042 QualType T = Ty;
5043 (void)convertBlockPointerToFunctionPointer(T);
5044 T.getAsStringInternal(Name, Context->getPrintingPolicy());
5045
5046 ByrefType += " " + Name + ";\n";
5047 ByrefType += "};\n";
5048 // Insert this type in global scope. It is needed by helper function.
5049 SourceLocation FunLocStart;
5050 if (CurFunctionDef)
5051 FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);
5052 else {
5053 assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null")(static_cast<void> (0));
5054 FunLocStart = CurMethodDef->getBeginLoc();
5055 }
5056 InsertText(FunLocStart, ByrefType);
5057
5058 if (Ty.isObjCGCWeak()) {
5059 flag |= BLOCK_FIELD_IS_WEAK;
5060 isa = 1;
5061 }
5062 if (HasCopyAndDispose) {
5063 flag = BLOCK_BYREF_CALLER;
5064 QualType Ty = ND->getType();
5065 // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
5066 if (Ty->isBlockPointerType())
5067 flag |= BLOCK_FIELD_IS_BLOCK;
5068 else
5069 flag |= BLOCK_FIELD_IS_OBJECT;
5070 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
5071 if (!HF.empty())
5072 Preamble += HF;
5073 }
5074
5075 // struct __Block_byref_ND ND =
5076 // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
5077 // initializer-if-any};
5078 bool hasInit = (ND->getInit() != nullptr);
5079 // FIXME. rewriter does not support __block c++ objects which
5080 // require construction.
5081 if (hasInit)
5082 if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) {
5083 CXXConstructorDecl *CXXDecl = CExp->getConstructor();
5084 if (CXXDecl && CXXDecl->isDefaultConstructor())
5085 hasInit = false;
5086 }
5087
5088 unsigned flags = 0;
5089 if (HasCopyAndDispose)
5090 flags |= BLOCK_HAS_COPY_DISPOSE;
5091 Name = ND->getNameAsString();
5092 ByrefType.clear();
5093 RewriteByRefString(ByrefType, Name, ND);
5094 std::string ForwardingCastType("(");
5095 ForwardingCastType += ByrefType + " *)";
5096 ByrefType += " " + Name + " = {(void*)";
5097 ByrefType += utostr(isa);
5098 ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
5099 ByrefType += utostr(flags);
5100 ByrefType += ", ";
5101 ByrefType += "sizeof(";
5102 RewriteByRefString(ByrefType, Name, ND);
5103 ByrefType += ")";
5104 if (HasCopyAndDispose) {
5105 ByrefType += ", __Block_byref_id_object_copy_";
5106 ByrefType += utostr(flag);
5107 ByrefType += ", __Block_byref_id_object_dispose_";
5108 ByrefType += utostr(flag);
5109 }
5110
5111 if (!firstDecl) {
5112 // In multiple __block declarations, and for all but 1st declaration,
5113 // find location of the separating comma. This would be start location
5114 // where new text is to be inserted.
5115 DeclLoc = ND->getLocation();
5116 const char *startDeclBuf = SM->getCharacterData(DeclLoc);
5117 const char *commaBuf = startDeclBuf;
5118 while (*commaBuf != ',')
5119 commaBuf--;
5120 assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','")(static_cast<void> (0));
5121 DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf);
5122 startBuf = commaBuf;
5123 }
5124
5125 if (!hasInit) {
5126 ByrefType += "};\n";
5127 unsigned nameSize = Name.size();
5128 // for block or function pointer declaration. Name is already
5129 // part of the declaration.
5130 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
5131 nameSize = 1;
5132 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
5133 }
5134 else {
5135 ByrefType += ", ";
5136 SourceLocation startLoc;
5137 Expr *E = ND->getInit();
5138 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
5139 startLoc = ECE->getLParenLoc();
5140 else
5141 startLoc = E->getBeginLoc();
5142 startLoc = SM->getExpansionLoc(startLoc);
5143 endBuf = SM->getCharacterData(startLoc);
5144 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
5145
5146 const char separator = lastDecl ? ';' : ',';
5147 const char *startInitializerBuf = SM->getCharacterData(startLoc);
5148 const char *separatorBuf = strchr(startInitializerBuf, separator);
5149 assert((*separatorBuf == separator) &&(static_cast<void> (0))
5150 "RewriteByRefVar: can't find ';' or ','")(static_cast<void> (0));
5151 SourceLocation separatorLoc =
5152 startLoc.getLocWithOffset(separatorBuf-startInitializerBuf);
5153
5154 InsertText(separatorLoc, lastDecl ? "}" : "};\n");
5155 }
5156}
5157
5158void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
5159 // Add initializers for any closure decl refs.
5160 GetBlockDeclRefExprs(Exp->getBody());
5161 if (BlockDeclRefs.size()) {
5162 // Unique all "by copy" declarations.
5163 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5164 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
5165 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
5166 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
5167 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
5168 }
5169 }
5170 // Unique all "by ref" declarations.
5171 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5172 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
5173 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
5174 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
5175 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
5176 }
5177 }
5178 // Find any imported blocks...they will need special attention.
5179 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
5180 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
5181 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
5182 BlockDeclRefs[i]->getType()->isBlockPointerType())
5183 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
5184 }
5185}
5186
5187FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {
5188 IdentifierInfo *ID = &Context->Idents.get(name);
5189 QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
5190 return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
5191 SourceLocation(), ID, FType, nullptr, SC_Extern,
5192 false, false);
5193}
5194
5195Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,
5196 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {
5197 const BlockDecl *block = Exp->getBlockDecl();
5198
5199 Blocks.push_back(Exp);
5200
5201 CollectBlockDeclRefInfo(Exp);
5202
5203 // Add inner imported variables now used in current block.
5204 int countOfInnerDecls = 0;
5205 if (!InnerBlockDeclRefs.empty()) {
5206 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
5207 DeclRefExpr *Exp = InnerBlockDeclRefs[i];
5208 ValueDecl *VD = Exp->getDecl();
5209 if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
5210 // We need to save the copied-in variables in nested
5211 // blocks because it is needed at the end for some of the API generations.
5212 // See SynthesizeBlockLiterals routine.
5213 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
5214 BlockDeclRefs.push_back(Exp);
5215 BlockByCopyDeclsPtrSet.insert(VD);
5216 BlockByCopyDecls.push_back(VD);
5217 }
5218 if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
5219 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
5220 BlockDeclRefs.push_back(Exp);
5221 BlockByRefDeclsPtrSet.insert(VD);
5222 BlockByRefDecls.push_back(VD);
5223 }
5224 }
5225 // Find any imported blocks...they will need special attention.
5226 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
5227 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
5228 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
5229 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
5230 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
5231 }
5232 InnerDeclRefsCount.push_back(countOfInnerDecls);
5233
5234 std::string FuncName;
5235
5236 if (CurFunctionDef)
5237 FuncName = CurFunctionDef->getNameAsString();
5238 else if (CurMethodDef)
5239 BuildUniqueMethodName(FuncName, CurMethodDef);
5240 else if (GlobalVarDecl)
5241 FuncName = std::string(GlobalVarDecl->getNameAsString());
5242
5243 bool GlobalBlockExpr =
5244 block->getDeclContext()->getRedeclContext()->isFileContext();
5245
5246 if (GlobalBlockExpr && !GlobalVarDecl) {
5247 Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);
5248 GlobalBlockExpr = false;
5249 }
5250
5251 std::string BlockNumber = utostr(Blocks.size()-1);
5252
5253 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
5254
5255 // Get a pointer to the function type so we can cast appropriately.
5256 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
5257 QualType FType = Context->getPointerType(BFT);
5258
5259 FunctionDecl *FD;
5260 Expr *NewRep;
5261
5262 // Simulate a constructor call...
5263 std::string Tag;
5264
5265 if (GlobalBlockExpr)
5266 Tag = "__global_";
5267 else
5268 Tag = "__";
5269 Tag += FuncName + "_block_impl_" + BlockNumber;
5270
5271 FD = SynthBlockInitFunctionDecl(Tag);
5272 DeclRefExpr *DRE = new (Context)
5273 DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());
5274
5275 SmallVector<Expr*, 4> InitExprs;
5276
5277 // Initialize the block function.
5278 FD = SynthBlockInitFunctionDecl(Func);
5279 DeclRefExpr *Arg = new (Context) DeclRefExpr(
5280 *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());
5281 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
5282 CK_BitCast, Arg);
5283 InitExprs.push_back(castExpr);
5284
5285 // Initialize the block descriptor.
5286 std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
5287
5288 VarDecl *NewVD = VarDecl::Create(
5289 *Context, TUDecl, SourceLocation(), SourceLocation(),
5290 &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
5291 UnaryOperator *DescRefExpr = UnaryOperator::Create(
5292 const_cast<ASTContext &>(*Context),
5293 new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
5294 VK_LValue, SourceLocation()),
5295 UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,
5296 OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
5297 InitExprs.push_back(DescRefExpr);
5298
5299 // Add initializers for any closure decl refs.
5300 if (BlockDeclRefs.size()) {
5301 Expr *Exp;
5302 // Output all "by copy" declarations.
5303 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
5304 E = BlockByCopyDecls.end(); I != E; ++I) {
5305 if (isObjCType((*I)->getType())) {
5306 // FIXME: Conform to ABI ([[obj retain] autorelease]).
5307 FD = SynthBlockInitFunctionDecl((*I)->getName());
5308 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
5309 VK_LValue, SourceLocation());
5310 if (HasLocalVariableExternalStorage(*I)) {
5311 QualType QT = (*I)->getType();
5312 QT = Context->getPointerType(QT);
5313 Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
5314 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
5315 SourceLocation(), false,
5316 FPOptionsOverride());
5317 }
5318 } else if (isTopLevelBlockPointerType((*I)->getType())) {
5319 FD = SynthBlockInitFunctionDecl((*I)->getName());
5320 Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
5321 VK_LValue, SourceLocation());
5322 Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,
5323 CK_BitCast, Arg);
5324 } else {
5325 FD = SynthBlockInitFunctionDecl((*I)->getName());
5326 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
5327 VK_LValue, SourceLocation());
5328 if (HasLocalVariableExternalStorage(*I)) {
5329 QualType QT = (*I)->getType();
5330 QT = Context->getPointerType(QT);
5331 Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
5332 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
5333 SourceLocation(), false,
5334 FPOptionsOverride());
5335 }
5336
5337 }
5338 InitExprs.push_back(Exp);
5339 }
5340 // Output all "by ref" declarations.
5341 for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
5342 E = BlockByRefDecls.end(); I != E; ++I) {
5343 ValueDecl *ND = (*I);
5344 std::string Name(ND->getNameAsString());
5345 std::string RecName;
5346 RewriteByRefString(RecName, Name, ND, true);
5347 IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
5348 + sizeof("struct"));
5349 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl,
5350 SourceLocation(), SourceLocation(),
5351 II);
5352 assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl")(static_cast<void> (0));
5353 QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
5354
5355 FD = SynthBlockInitFunctionDecl((*I)->getName());
5356 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
5357 VK_LValue, SourceLocation());
5358 bool isNestedCapturedVar = false;
5359 if (block)
5360 for (const auto &CI : block->captures()) {
5361 const VarDecl *variable = CI.getVariable();
5362 if (variable == ND && CI.isNested()) {
5363 assert (CI.isByRef() &&(static_cast<void> (0))
5364 "SynthBlockInitExpr - captured block variable is not byref")(static_cast<void> (0));
5365 isNestedCapturedVar = true;
5366 break;
5367 }
5368 }
5369 // captured nested byref variable has its address passed. Do not take
5370 // its address again.
5371 if (!isNestedCapturedVar)
5372 Exp = UnaryOperator::Create(
5373 const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
5374 Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,
5375 SourceLocation(), false, FPOptionsOverride());
5376 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
5377 InitExprs.push_back(Exp);
5378 }
5379 }
5380 if (ImportedBlockDecls.size()) {
5381 // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
5382 int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
5383 unsigned IntSize =
5384 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
5385 Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
5386 Context->IntTy, SourceLocation());
5387 InitExprs.push_back(FlagExp);
5388 }
5389 NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
5390 SourceLocation(), FPOptionsOverride());
5391
5392 if (GlobalBlockExpr) {
5393 assert (!GlobalConstructionExp &&(static_cast<void> (0))
5394 "SynthBlockInitExpr - GlobalConstructionExp must be null")(static_cast<void> (0));
5395 GlobalConstructionExp = NewRep;
5396 NewRep = DRE;
5397 }
5398
5399 NewRep = UnaryOperator::Create(
5400 const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
5401 Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,
5402 SourceLocation(), false, FPOptionsOverride());
5403 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
5404 NewRep);
5405 // Put Paren around the call.
5406 NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
5407 NewRep);
5408
5409 BlockDeclRefs.clear();
5410 BlockByRefDecls.clear();
5411 BlockByRefDeclsPtrSet.clear();
5412 BlockByCopyDecls.clear();
5413 BlockByCopyDeclsPtrSet.clear();
5414 ImportedBlockDecls.clear();
5415 return NewRep;
5416}
5417
5418bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
5419 if (const ObjCForCollectionStmt * CS =
5420 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
5421 return CS->getElement() == DS;
5422 return false;
5423}
5424
5425//===----------------------------------------------------------------------===//
5426// Function Body / Expression rewriting
5427//===----------------------------------------------------------------------===//
5428
5429Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
5430 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
5431 isa<DoStmt>(S) || isa<ForStmt>(S))
5432 Stmts.push_back(S);
5433 else if (isa<ObjCForCollectionStmt>(S)) {
5434 Stmts.push_back(S);
5435 ObjCBcLabelNo.push_back(++BcLabelCount);
5436 }
5437
5438 // Pseudo-object operations and ivar references need special
5439 // treatment because we're going to recursively rewrite them.
5440 if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
5441 if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
5442 return RewritePropertyOrImplicitSetter(PseudoOp);
5443 } else {
5444 return RewritePropertyOrImplicitGetter(PseudoOp);
5445 }
5446 } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
5447 return RewriteObjCIvarRefExpr(IvarRefExpr);
5448 }
5449 else if (isa<OpaqueValueExpr>(S))
5450 S = cast<OpaqueValueExpr>(S)->getSourceExpr();
5451
5452 SourceRange OrigStmtRange = S->getSourceRange();
5453
5454 // Perform a bottom up rewrite of all children.
5455 for (Stmt *&childStmt : S->children())
5456 if (childStmt) {
5457 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
5458 if (newStmt) {
5459 childStmt = newStmt;
5460 }
5461 }
5462
5463 if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
5464 SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;
5465 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
5466 InnerContexts.insert(BE->getBlockDecl());
5467 ImportedLocalExternalDecls.clear();
5468 GetInnerBlockDeclRefExprs(BE->getBody(),
5469 InnerBlockDeclRefs, InnerContexts);
5470 // Rewrite the block body in place.
5471 Stmt *SaveCurrentBody = CurrentBody;
5472 CurrentBody = BE->getBody();
5473 PropParentMap = nullptr;
5474 // block literal on rhs of a property-dot-sytax assignment
5475 // must be replaced by its synthesize ast so getRewrittenText
5476 // works as expected. In this case, what actually ends up on RHS
5477 // is the blockTranscribed which is the helper function for the
5478 // block literal; as in: self.c = ^() {[ace ARR];};
5479 bool saveDisableReplaceStmt = DisableReplaceStmt;
5480 DisableReplaceStmt = false;
5481 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
5482 DisableReplaceStmt = saveDisableReplaceStmt;
5483 CurrentBody = SaveCurrentBody;
5484 PropParentMap = nullptr;
5485 ImportedLocalExternalDecls.clear();
5486 // Now we snarf the rewritten text and stash it away for later use.
5487 std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
5488 RewrittenBlockExprs[BE] = Str;
5489
5490 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
5491
5492 //blockTranscribed->dump();
5493 ReplaceStmt(S, blockTranscribed);
5494 return blockTranscribed;
5495 }
5496 // Handle specific things.
5497 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
5498 return RewriteAtEncode(AtEncode);
5499
5500 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
5501 return RewriteAtSelector(AtSelector);
5502
5503 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
5504 return RewriteObjCStringLiteral(AtString);
5505
5506 if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))
5507 return RewriteObjCBoolLiteralExpr(BoolLitExpr);
5508
5509 if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))
5510 return RewriteObjCBoxedExpr(BoxedExpr);
5511
5512 if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))
5513 return RewriteObjCArrayLiteralExpr(ArrayLitExpr);
5514
5515 if (ObjCDictionaryLiteral *DictionaryLitExpr =
5516 dyn_cast<ObjCDictionaryLiteral>(S))
5517 return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr);
5518
5519 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
5520#if 0
5521 // Before we rewrite it, put the original message expression in a comment.
5522 SourceLocation startLoc = MessExpr->getBeginLoc();
5523 SourceLocation endLoc = MessExpr->getEndLoc();
5524
5525 const char *startBuf = SM->getCharacterData(startLoc);
5526 const char *endBuf = SM->getCharacterData(endLoc);
5527
5528 std::string messString;
5529 messString += "// ";
5530 messString.append(startBuf, endBuf-startBuf+1);
5531 messString += "\n";
5532
5533 // FIXME: Missing definition of
5534 // InsertText(clang::SourceLocation, char const*, unsigned int).
5535 // InsertText(startLoc, messString);
5536 // Tried this, but it didn't work either...
5537 // ReplaceText(startLoc, 0, messString.c_str(), messString.size());
5538#endif
5539 return RewriteMessageExpr(MessExpr);
5540 }
5541
5542 if (ObjCAutoreleasePoolStmt *StmtAutoRelease =
5543 dyn_cast<ObjCAutoreleasePoolStmt>(S)) {
5544 return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease);
5545 }
5546
5547 if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
5548 return RewriteObjCTryStmt(StmtTry);
5549
5550 if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
5551 return RewriteObjCSynchronizedStmt(StmtTry);
5552
5553 if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
5554 return RewriteObjCThrowStmt(StmtThrow);
5555
5556 if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
5557 return RewriteObjCProtocolExpr(ProtocolExp);
5558
5559 if (ObjCForCollectionStmt *StmtForCollection =
5560 dyn_cast<ObjCForCollectionStmt>(S))
5561 return RewriteObjCForCollectionStmt(StmtForCollection,
5562 OrigStmtRange.getEnd());
5563 if (BreakStmt *StmtBreakStmt =
5564 dyn_cast<BreakStmt>(S))
5565 return RewriteBreakStmt(StmtBreakStmt);
5566 if (ContinueStmt *StmtContinueStmt =
5567 dyn_cast<ContinueStmt>(S))
5568 return RewriteContinueStmt(StmtContinueStmt);
5569
5570 // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
5571 // and cast exprs.
5572 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
5573 // FIXME: What we're doing here is modifying the type-specifier that
5574 // precedes the first Decl. In the future the DeclGroup should have
5575 // a separate type-specifier that we can rewrite.
5576 // NOTE: We need to avoid rewriting the DeclStmt if it is within
5577 // the context of an ObjCForCollectionStmt. For example:
5578 // NSArray *someArray;
5579 // for (id <FooProtocol> index in someArray) ;
5580 // This is because RewriteObjCForCollectionStmt() does textual rewriting
5581 // and it depends on the original text locations/positions.
5582 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
5583 RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
5584
5585 // Blocks rewrite rules.
5586 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
5587 DI != DE; ++DI) {
5588 Decl *SD = *DI;
5589 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
5590 if (isTopLevelBlockPointerType(ND->getType()))
5591 RewriteBlockPointerDecl(ND);
5592 else if (ND->getType()->isFunctionPointerType())
5593 CheckFunctionPointerDecl(ND->getType(), ND);
5594 if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
5595 if (VD->hasAttr<BlocksAttr>()) {
5596 static unsigned uniqueByrefDeclCount = 0;
5597 assert(!BlockByRefDeclNo.count(ND) &&(static_cast<void> (0))
5598 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl")(static_cast<void> (0));
5599 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
5600 RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE));
5601 }
5602 else
5603 RewriteTypeOfDecl(VD);
5604 }
5605 }
5606 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
5607 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
5608 RewriteBlockPointerDecl(TD);
5609 else if (TD->getUnderlyingType()->isFunctionPointerType())
5610 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
5611 }
5612 }
5613 }
5614
5615 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
5616 RewriteObjCQualifiedInterfaceTypes(CE);
5617
5618 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
5619 isa<DoStmt>(S) || isa<ForStmt>(S)) {
5620 assert(!Stmts.empty() && "Statement stack is empty")(static_cast<void> (0));
5621 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||(static_cast<void> (0))
5622 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))(static_cast<void> (0))
5623 && "Statement stack mismatch")(static_cast<void> (0));
5624 Stmts.pop_back();
5625 }
5626 // Handle blocks rewriting.
5627 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
5628 ValueDecl *VD = DRE->getDecl();
5629 if (VD->hasAttr<BlocksAttr>())
5630 return RewriteBlockDeclRefExpr(DRE);
5631 if (HasLocalVariableExternalStorage(VD))
5632 return RewriteLocalVariableExternalStorage(DRE);
5633 }
5634
5635 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
5636 if (CE->getCallee()->getType()->isBlockPointerType()) {
5637 Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
5638 ReplaceStmt(S, BlockCall);
5639 return BlockCall;
5640 }
5641 }
5642 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
5643 RewriteCastExpr(CE);
5644 }
5645 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
5646 RewriteImplicitCastObjCExpr(ICE);
5647 }
5648#if 0
5649
5650 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
5651 CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
5652 ICE->getSubExpr(),
5653 SourceLocation());
5654 // Get the new text.
5655 std::string SStr;
5656 llvm::raw_string_ostream Buf(SStr);
5657 Replacement->printPretty(Buf);
5658 const std::string &Str = Buf.str();
5659
5660 printf("CAST = %s\n", &Str[0]);
5661 InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
5662 delete S;
5663 return Replacement;
5664 }
5665#endif
5666 // Return this stmt unmodified.
5667 return S;
5668}
5669
5670void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) {
5671 for (auto *FD : RD->fields()) {
5672 if (isTopLevelBlockPointerType(FD->getType()))
5673 RewriteBlockPointerDecl(FD);
5674 if (FD->getType()->isObjCQualifiedIdType() ||
5675 FD->getType()->isObjCQualifiedInterfaceType())
5676 RewriteObjCQualifiedInterfaceTypes(FD);
5677 }
5678}
5679
5680/// HandleDeclInMainFile - This is called for each top-level decl defined in the
5681/// main file of the input.
5682void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {
5683 switch (D->getKind()) {
5684 case Decl::Function: {
5685 FunctionDecl *FD = cast<FunctionDecl>(D);
5686 if (FD->isOverloadedOperator())
5687 return;
5688
5689 // Since function prototypes don't have ParmDecl's, we check the function
5690 // prototype. This enables us to rewrite function declarations and
5691 // definitions using the same code.
5692 RewriteBlocksInFunctionProtoType(FD->getType(), FD);
5693
5694 if (!FD->isThisDeclarationADefinition())
5695 break;
5696
5697 // FIXME: If this should support Obj-C++, support CXXTryStmt
5698 if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
5699 CurFunctionDef = FD;
5700 CurrentBody = Body;
5701 Body =
5702 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
5703 FD->setBody(Body);
5704 CurrentBody = nullptr;
5705 if (PropParentMap) {
5706 delete PropParentMap;
5707 PropParentMap = nullptr;
5708 }
5709 // This synthesizes and inserts the block "impl" struct, invoke function,
5710 // and any copy/dispose helper functions.
5711 InsertBlockLiteralsWithinFunction(FD);
5712 RewriteLineDirective(D);
5713 CurFunctionDef = nullptr;
5714 }
5715 break;
5716 }
5717 case Decl::ObjCMethod: {
5718 ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
5719 if (CompoundStmt *Body = MD->getCompoundBody()) {
5720 CurMethodDef = MD;
5721 CurrentBody = Body;
5722 Body =
5723 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
5724 MD->setBody(Body);
5725 CurrentBody = nullptr;
5726 if (PropParentMap) {
5727 delete PropParentMap;
5728 PropParentMap = nullptr;
5729 }
5730 InsertBlockLiteralsWithinMethod(MD);
5731 RewriteLineDirective(D);
5732 CurMethodDef = nullptr;
5733 }
5734 break;
5735 }
5736 case Decl::ObjCImplementation: {
5737 ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
5738 ClassImplementation.push_back(CI);
5739 break;
5740 }
5741 case Decl::ObjCCategoryImpl: {
5742 ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
5743 CategoryImplementation.push_back(CI);
5744 break;
5745 }
5746 case Decl::Var: {
5747 VarDecl *VD = cast<VarDecl>(D);
5748 RewriteObjCQualifiedInterfaceTypes(VD);
5749 if (isTopLevelBlockPointerType(VD->getType()))
5750 RewriteBlockPointerDecl(VD);
5751 else if (VD->getType()->isFunctionPointerType()) {
5752 CheckFunctionPointerDecl(VD->getType(), VD);
5753 if (VD->getInit()) {
5754 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
5755 RewriteCastExpr(CE);
5756 }
5757 }
5758 } else if (VD->getType()->isRecordType()) {
5759 RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl();
5760 if (RD->isCompleteDefinition())
5761 RewriteRecordBody(RD);
5762 }
5763 if (VD->getInit()) {
5764 GlobalVarDecl = VD;
5765 CurrentBody = VD->getInit();
5766 RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
5767 CurrentBody = nullptr;
5768 if (PropParentMap) {
5769 delete PropParentMap;
5770 PropParentMap = nullptr;
5771 }
5772 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
5773 GlobalVarDecl = nullptr;
5774
5775 // This is needed for blocks.
5776 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
5777 RewriteCastExpr(CE);
5778 }
5779 }
5780 break;
5781 }
5782 case Decl::TypeAlias:
5783 case Decl::Typedef: {
5784 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
5785 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
5786 RewriteBlockPointerDecl(TD);
5787 else if (TD->getUnderlyingType()->isFunctionPointerType())
5788 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
5789 else
5790 RewriteObjCQualifiedInterfaceTypes(TD);
5791 }
5792 break;
5793 }
5794 case Decl::CXXRecord:
5795 case Decl::Record: {
5796 RecordDecl *RD = cast<RecordDecl>(D);
5797 if (RD->isCompleteDefinition())
5798 RewriteRecordBody(RD);
5799 break;
5800 }
5801 default:
5802 break;
5803 }
5804 // Nothing yet.
5805}
5806
5807/// Write_ProtocolExprReferencedMetadata - This routine writer out the
5808/// protocol reference symbols in the for of:
5809/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.
5810static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,
5811 ObjCProtocolDecl *PDecl,
5812 std::string &Result) {
5813 // Also output .objc_protorefs$B section and its meta-data.
5814 if (Context->getLangOpts().MicrosoftExt)
5815 Result += "static ";
5816 Result += "struct _protocol_t *";
5817 Result += "_OBJC_PROTOCOL_REFERENCE_$_";
5818 Result += PDecl->getNameAsString();
5819 Result += " = &";
5820 Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
5821 Result += ";\n";
5822}
5823
5824void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {
5825 if (Diags.hasErrorOccurred())
5826 return;
5827
5828 RewriteInclude();
5829
5830 for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) {
5831 // translation of function bodies were postponed until all class and
5832 // their extensions and implementations are seen. This is because, we
5833 // cannot build grouping structs for bitfields until they are all seen.
5834 FunctionDecl *FDecl = FunctionDefinitionsSeen[i];
5835 HandleTopLevelSingleDecl(FDecl);
5836 }
5837
5838 // Here's a great place to add any extra declarations that may be needed.
5839 // Write out meta data for each @protocol(<expr>).
5840 for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {
5841 RewriteObjCProtocolMetaData(ProtDecl, Preamble);
5842 Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble);
5843 }
5844
5845 InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
5846
5847 if (ClassImplementation.size() || CategoryImplementation.size())
5848 RewriteImplementations();
5849
5850 for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {
5851 ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];
5852 // Write struct declaration for the class matching its ivar declarations.
5853 // Note that for modern abi, this is postponed until the end of TU
5854 // because class extensions and the implementation might declare their own
5855 // private ivars.
5856 RewriteInterfaceDecl(CDecl);
5857 }
5858
5859 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
5860 // we are done.
5861 if (const RewriteBuffer *RewriteBuf =
5862 Rewrite.getRewriteBufferFor(MainFileID)) {
5863 //printf("Changed:\n");
5864 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
5865 } else {
5866 llvm::errs() << "No changes\n";
5867 }
5868
5869 if (ClassImplementation.size() || CategoryImplementation.size() ||
5870 ProtocolExprDecls.size()) {
5871 // Rewrite Objective-c meta data*
5872 std::string ResultStr;
5873 RewriteMetaDataIntoBuffer(ResultStr);
5874 // Emit metadata.
5875 *OutFile << ResultStr;
5876 }
5877 // Emit ImageInfo;
5878 {
5879 std::string ResultStr;
5880 WriteImageInfo(ResultStr);
5881 *OutFile << ResultStr;
5882 }
5883 OutFile->flush();
5884}
5885
5886void RewriteModernObjC::Initialize(ASTContext &context) {
5887 InitializeCommon(context);
5888
5889 Preamble += "#ifndef __OBJC2__\n";
5890 Preamble += "#define __OBJC2__\n";
5891 Preamble += "#endif\n";
5892
5893 // declaring objc_selector outside the parameter list removes a silly
5894 // scope related warning...
5895 if (IsHeader)
5896 Preamble = "#pragma once\n";
5897 Preamble += "struct objc_selector; struct objc_class;\n";
5898 Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; ";
5899 Preamble += "\n\tstruct objc_object *superClass; ";
5900 // Add a constructor for creating temporary objects.
5901 Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) ";
5902 Preamble += ": object(o), superClass(s) {} ";
5903 Preamble += "\n};\n";
5904
5905 if (LangOpts.MicrosoftExt) {
5906 // Define all sections using syntax that makes sense.
5907 // These are currently generated.
5908 Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";
5909 Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";
5910 Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";
5911 Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";
5912 Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";
5913 // These are generated but not necessary for functionality.
5914 Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";
5915 Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";
5916 Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";
5917 Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";
5918
5919 // These need be generated for performance. Currently they are not,
5920 // using API calls instead.
5921 Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";
5922 Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";
5923 Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";
5924
5925 }
5926 Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
5927 Preamble += "typedef struct objc_object Protocol;\n";
5928 Preamble += "#define _REWRITER_typedef_Protocol\n";
5929 Preamble += "#endif\n";
5930 if (LangOpts.MicrosoftExt) {
5931 Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
5932 Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
5933 }
5934 else
5935 Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
5936
5937 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";
5938 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";
5939 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";
5940 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n";
5941 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n";
5942
5943 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass";
5944 Preamble += "(const char *);\n";
5945 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
5946 Preamble += "(struct objc_class *);\n";
5947 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass";
5948 Preamble += "(const char *);\n";
5949 Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n";
5950 // @synchronized hooks.
5951 Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n";
5952 Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n";
5953 Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
5954 Preamble += "#ifdef _WIN64\n";
5955 Preamble += "typedef unsigned long long _WIN_NSUInteger;\n";
5956 Preamble += "#else\n";
5957 Preamble += "typedef unsigned int _WIN_NSUInteger;\n";
5958 Preamble += "#endif\n";
5959 Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
5960 Preamble += "struct __objcFastEnumerationState {\n\t";
5961 Preamble += "unsigned long state;\n\t";
5962 Preamble += "void **itemsPtr;\n\t";
5963 Preamble += "unsigned long *mutationsPtr;\n\t";
5964 Preamble += "unsigned long extra[5];\n};\n";
5965 Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
5966 Preamble += "#define __FASTENUMERATIONSTATE\n";
5967 Preamble += "#endif\n";
5968 Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
5969 Preamble += "struct __NSConstantStringImpl {\n";
5970 Preamble += " int *isa;\n";
5971 Preamble += " int flags;\n";
5972 Preamble += " char *str;\n";
5973 Preamble += "#if _WIN64\n";
5974 Preamble += " long long length;\n";
5975 Preamble += "#else\n";
5976 Preamble += " long length;\n";
5977 Preamble += "#endif\n";
5978 Preamble += "};\n";
5979 Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
5980 Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5981 Preamble += "#else\n";
5982 Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5983 Preamble += "#endif\n";
5984 Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
5985 Preamble += "#endif\n";
5986 // Blocks preamble.
5987 Preamble += "#ifndef BLOCK_IMPL\n";
5988 Preamble += "#define BLOCK_IMPL\n";
5989 Preamble += "struct __block_impl {\n";
5990 Preamble += " void *isa;\n";
5991 Preamble += " int Flags;\n";
5992 Preamble += " int Reserved;\n";
5993 Preamble += " void *FuncPtr;\n";
5994 Preamble += "};\n";
5995 Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
5996 Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
5997 Preamble += "extern \"C\" __declspec(dllexport) "
5998 "void _Block_object_assign(void *, const void *, const int);\n";
5999 Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
6000 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
6001 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
6002 Preamble += "#else\n";
6003 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
6004 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
6005 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
6006 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
6007 Preamble += "#endif\n";
6008 Preamble += "#endif\n";
6009 if (LangOpts.MicrosoftExt) {
6010 Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
6011 Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
6012 Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.
6013 Preamble += "#define __attribute__(X)\n";
6014 Preamble += "#endif\n";
6015 Preamble += "#ifndef __weak\n";
6016 Preamble += "#define __weak\n";
6017 Preamble += "#endif\n";
6018 Preamble += "#ifndef __block\n";
6019 Preamble += "#define __block\n";
6020 Preamble += "#endif\n";
6021 }
6022 else {
6023 Preamble += "#define __block\n";
6024 Preamble += "#define __weak\n";
6025 }
6026
6027 // Declarations required for modern objective-c array and dictionary literals.
6028 Preamble += "\n#include <stdarg.h>\n";
6029 Preamble += "struct __NSContainer_literal {\n";
6030 Preamble += " void * *arr;\n";
6031 Preamble += " __NSContainer_literal (unsigned int count, ...) {\n";
6032 Preamble += "\tva_list marker;\n";
6033 Preamble += "\tva_start(marker, count);\n";
6034 Preamble += "\tarr = new void *[count];\n";
6035 Preamble += "\tfor (unsigned i = 0; i < count; i++)\n";
6036 Preamble += "\t arr[i] = va_arg(marker, void *);\n";
6037 Preamble += "\tva_end( marker );\n";
6038 Preamble += " };\n";
6039 Preamble += " ~__NSContainer_literal() {\n";
6040 Preamble += "\tdelete[] arr;\n";
6041 Preamble += " }\n";
6042 Preamble += "};\n";
6043
6044 // Declaration required for implementation of @autoreleasepool statement.
6045 Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n";
6046 Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n";
6047 Preamble += "struct __AtAutoreleasePool {\n";
6048 Preamble += " __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n";
6049 Preamble += " ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n";
6050 Preamble += " void * atautoreleasepoolobj;\n";
6051 Preamble += "};\n";
6052
6053 // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
6054 // as this avoids warning in any 64bit/32bit compilation model.
6055 Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
6056}
6057
6058/// RewriteIvarOffsetComputation - This routine synthesizes computation of
6059/// ivar offset.
6060void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
6061 std::string &Result) {
6062 Result += "__OFFSETOFIVAR__(struct ";
6063 Result += ivar->getContainingInterface()->getNameAsString();
6064 if (LangOpts.MicrosoftExt)
6065 Result += "_IMPL";
6066 Result += ", ";
6067 if (ivar->isBitField())
6068 ObjCIvarBitfieldGroupDecl(ivar, Result);
6069 else
6070 Result += ivar->getNameAsString();
6071 Result += ")";
6072}
6073
6074/// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI.
6075/// struct _prop_t {
6076/// const char *name;
6077/// char *attributes;
6078/// }
6079
6080/// struct _prop_list_t {
6081/// uint32_t entsize; // sizeof(struct _prop_t)
6082/// uint32_t count_of_properties;
6083/// struct _prop_t prop_list[count_of_properties];
6084/// }
6085
6086/// struct _protocol_t;
6087
6088/// struct _protocol_list_t {
6089/// long protocol_count; // Note, this is 32/64 bit
6090/// struct _protocol_t * protocol_list[protocol_count];
6091/// }
6092
6093/// struct _objc_method {
6094/// SEL _cmd;
6095/// const char *method_type;
6096/// char *_imp;
6097/// }
6098
6099/// struct _method_list_t {
6100/// uint32_t entsize; // sizeof(struct _objc_method)
6101/// uint32_t method_count;
6102/// struct _objc_method method_list[method_count];
6103/// }
6104
6105/// struct _protocol_t {
6106/// id isa; // NULL
6107/// const char *protocol_name;
6108/// const struct _protocol_list_t * protocol_list; // super protocols
6109/// const struct method_list_t *instance_methods;
6110/// const struct method_list_t *class_methods;
6111/// const struct method_list_t *optionalInstanceMethods;
6112/// const struct method_list_t *optionalClassMethods;
6113/// const struct _prop_list_t * properties;
6114/// const uint32_t size; // sizeof(struct _protocol_t)
6115/// const uint32_t flags; // = 0
6116/// const char ** extendedMethodTypes;
6117/// }
6118
6119/// struct _ivar_t {
6120/// unsigned long int *offset; // pointer to ivar offset location
6121/// const char *name;
6122/// const char *type;
6123/// uint32_t alignment;
6124/// uint32_t size;
6125/// }
6126
6127/// struct _ivar_list_t {
6128/// uint32 entsize; // sizeof(struct _ivar_t)
6129/// uint32 count;
6130/// struct _ivar_t list[count];
6131/// }
6132
6133/// struct _class_ro_t {
6134/// uint32_t flags;
6135/// uint32_t instanceStart;
6136/// uint32_t instanceSize;
6137/// uint32_t reserved; // only when building for 64bit targets
6138/// const uint8_t *ivarLayout;
6139/// const char *name;
6140/// const struct _method_list_t *baseMethods;
6141/// const struct _protocol_list_t *baseProtocols;
6142/// const struct _ivar_list_t *ivars;
6143/// const uint8_t *weakIvarLayout;
6144/// const struct _prop_list_t *properties;
6145/// }
6146
6147/// struct _class_t {
6148/// struct _class_t *isa;
6149/// struct _class_t *superclass;
6150/// void *cache;
6151/// IMP *vtable;
6152/// struct _class_ro_t *ro;
6153/// }
6154
6155/// struct _category_t {
6156/// const char *name;
6157/// struct _class_t *cls;
6158/// const struct _method_list_t *instance_methods;
6159/// const struct _method_list_t *class_methods;
6160/// const struct _protocol_list_t *protocols;
6161/// const struct _prop_list_t *properties;
6162/// }
6163
6164/// MessageRefTy - LLVM for:
6165/// struct _message_ref_t {
6166/// IMP messenger;
6167/// SEL name;
6168/// };
6169
6170/// SuperMessageRefTy - LLVM for:
6171/// struct _super_message_ref_t {
6172/// SUPER_IMP messenger;
6173/// SEL name;
6174/// };
6175
6176static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) {
6177 static bool meta_data_declared = false;
6178 if (meta_data_declared)
6179 return;
6180
6181 Result += "\nstruct _prop_t {\n";
6182 Result += "\tconst char *name;\n";
6183 Result += "\tconst char *attributes;\n";
6184 Result += "};\n";
6185
6186 Result += "\nstruct _protocol_t;\n";
6187
6188 Result += "\nstruct _objc_method {\n";
6189 Result += "\tstruct objc_selector * _cmd;\n";
6190 Result += "\tconst char *method_type;\n";
6191 Result += "\tvoid *_imp;\n";
6192 Result += "};\n";
6193
6194 Result += "\nstruct _protocol_t {\n";
6195 Result += "\tvoid * isa; // NULL\n";
6196 Result += "\tconst char *protocol_name;\n";
6197 Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n";
6198 Result += "\tconst struct method_list_t *instance_methods;\n";
6199 Result += "\tconst struct method_list_t *class_methods;\n";
6200 Result += "\tconst struct method_list_t *optionalInstanceMethods;\n";
6201 Result += "\tconst struct method_list_t *optionalClassMethods;\n";
6202 Result += "\tconst struct _prop_list_t * properties;\n";
6203 Result += "\tconst unsigned int size; // sizeof(struct _protocol_t)\n";
6204 Result += "\tconst unsigned int flags; // = 0\n";
6205 Result += "\tconst char ** extendedMethodTypes;\n";
6206 Result += "};\n";
6207
6208 Result += "\nstruct _ivar_t {\n";
6209 Result += "\tunsigned long int *offset; // pointer to ivar offset location\n";
6210 Result += "\tconst char *name;\n";
6211 Result += "\tconst char *type;\n";
6212 Result += "\tunsigned int alignment;\n";
6213 Result += "\tunsigned int size;\n";
6214 Result += "};\n";
6215
6216 Result += "\nstruct _class_ro_t {\n";
6217 Result += "\tunsigned int flags;\n";
6218 Result += "\tunsigned int instanceStart;\n";
6219 Result += "\tunsigned int instanceSize;\n";
6220 const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
6221 if (Triple.getArch() == llvm::Triple::x86_64)
6222 Result += "\tunsigned int reserved;\n";
6223 Result += "\tconst unsigned char *ivarLayout;\n";
6224 Result += "\tconst char *name;\n";
6225 Result += "\tconst struct _method_list_t *baseMethods;\n";
6226 Result += "\tconst struct _objc_protocol_list *baseProtocols;\n";
6227 Result += "\tconst struct _ivar_list_t *ivars;\n";
6228 Result += "\tconst unsigned char *weakIvarLayout;\n";
6229 Result += "\tconst struct _prop_list_t *properties;\n";
6230 Result += "};\n";
6231
6232 Result += "\nstruct _class_t {\n";
6233 Result += "\tstruct _class_t *isa;\n";
6234 Result += "\tstruct _class_t *superclass;\n";
6235 Result += "\tvoid *cache;\n";
6236 Result += "\tvoid *vtable;\n";
6237 Result += "\tstruct _class_ro_t *ro;\n";
6238 Result += "};\n";
6239
6240 Result += "\nstruct _category_t {\n";
6241 Result += "\tconst char *name;\n";
6242 Result += "\tstruct _class_t *cls;\n";
6243 Result += "\tconst struct _method_list_t *instance_methods;\n";
6244 Result += "\tconst struct _method_list_t *class_methods;\n";
6245 Result += "\tconst struct _protocol_list_t *protocols;\n";
6246 Result += "\tconst struct _prop_list_t *properties;\n";
6247 Result += "};\n";
6248
6249 Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";
6250 Result += "#pragma warning(disable:4273)\n";
6251 meta_data_declared = true;
6252}
6253
6254static void Write_protocol_list_t_TypeDecl(std::string &Result,
6255 long super_protocol_count) {
6256 Result += "struct /*_protocol_list_t*/"; Result += " {\n";
6257 Result += "\tlong protocol_count; // Note, this is 32/64 bit\n";
6258 Result += "\tstruct _protocol_t *super_protocols[";
6259 Result += utostr(super_protocol_count); Result += "];\n";
6260 Result += "}";
6261}
6262
6263static void Write_method_list_t_TypeDecl(std::string &Result,
6264 unsigned int method_count) {
6265 Result += "struct /*_method_list_t*/"; Result += " {\n";
6266 Result += "\tunsigned int entsize; // sizeof(struct _objc_method)\n";
6267 Result += "\tunsigned int method_count;\n";
6268 Result += "\tstruct _objc_method method_list[";
6269 Result += utostr(method_count); Result += "];\n";
6270 Result += "}";
6271}
6272
6273static void Write__prop_list_t_TypeDecl(std::string &Result,
6274 unsigned int property_count) {
6275 Result += "struct /*_prop_list_t*/"; Result += " {\n";
6276 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";
6277 Result += "\tunsigned int count_of_properties;\n";
6278 Result += "\tstruct _prop_t prop_list[";
6279 Result += utostr(property_count); Result += "];\n";
6280 Result += "}";
6281}
6282
6283static void Write__ivar_list_t_TypeDecl(std::string &Result,
6284 unsigned int ivar_count) {
6285 Result += "struct /*_ivar_list_t*/"; Result += " {\n";
6286 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";
6287 Result += "\tunsigned int count;\n";
6288 Result += "\tstruct _ivar_t ivar_list[";
6289 Result += utostr(ivar_count); Result += "];\n";
6290 Result += "}";
6291}
6292
6293static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result,
6294 ArrayRef<ObjCProtocolDecl *> SuperProtocols,
6295 StringRef VarName,
6296 StringRef ProtocolName) {
6297 if (SuperProtocols.size() > 0) {
6298 Result += "\nstatic ";
6299 Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());
6300 Result += " "; Result += VarName;
6301 Result += ProtocolName;
6302 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6303 Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";
6304 for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {
6305 ObjCProtocolDecl *SuperPD = SuperProtocols[i];
6306 Result += "\t&"; Result += "_OBJC_PROTOCOL_";
6307 Result += SuperPD->getNameAsString();
6308 if (i == e-1)
6309 Result += "\n};\n";
6310 else
6311 Result += ",\n";
6312 }
6313 }
6314}
6315
6316static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,
6317 ASTContext *Context, std::string &Result,
6318 ArrayRef<ObjCMethodDecl *> Methods,
6319 StringRef VarName,
6320 StringRef TopLevelDeclName,
6321 bool MethodImpl) {
6322 if (Methods.size() > 0) {
6323 Result += "\nstatic ";
6324 Write_method_list_t_TypeDecl(Result, Methods.size());
6325 Result += " "; Result += VarName;
6326 Result += TopLevelDeclName;
6327 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6328 Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";
6329 Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";
6330 for (unsigned i = 0, e = Methods.size(); i < e; i++) {
6331 ObjCMethodDecl *MD = Methods[i];
6332 if (i == 0)
6333 Result += "\t{{(struct objc_selector *)\"";
6334 else
6335 Result += "\t{(struct objc_selector *)\"";
6336 Result += (MD)->getSelector().getAsString(); Result += "\"";
6337 Result += ", ";
6338 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(MD);
6339 Result += "\""; Result += MethodTypeString; Result += "\"";
6340 Result += ", ";
6341 if (!MethodImpl)
6342 Result += "0";
6343 else {
6344 Result += "(void *)";
6345 Result += RewriteObj.MethodInternalNames[MD];
6346 }
6347 if (i == e-1)
6348 Result += "}}\n";
6349 else
6350 Result += "},\n";
6351 }
6352 Result += "};\n";
6353 }
6354}
6355
6356static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,
6357 ASTContext *Context, std::string &Result,
6358 ArrayRef<ObjCPropertyDecl *> Properties,
6359 const Decl *Container,
6360 StringRef VarName,
6361 StringRef ProtocolName) {
6362 if (Properties.size() > 0) {
6363 Result += "\nstatic ";
6364 Write__prop_list_t_TypeDecl(Result, Properties.size());
6365 Result += " "; Result += VarName;
6366 Result += ProtocolName;
6367 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6368 Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";
6369 Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";
6370 for (unsigned i = 0, e = Properties.size(); i < e; i++) {
6371 ObjCPropertyDecl *PropDecl = Properties[i];
6372 if (i == 0)
6373 Result += "\t{{\"";
6374 else
6375 Result += "\t{\"";
6376 Result += PropDecl->getName(); Result += "\",";
6377 std::string PropertyTypeString =
6378 Context->getObjCEncodingForPropertyDecl(PropDecl, Container);
6379 std::string QuotePropertyTypeString;
6380 RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);
6381 Result += "\""; Result += QuotePropertyTypeString; Result += "\"";
6382 if (i == e-1)
6383 Result += "}}\n";
6384 else
6385 Result += "},\n";
6386 }
6387 Result += "};\n";
6388 }
6389}
6390
6391// Metadata flags
6392enum MetaDataDlags {
6393 CLS = 0x0,
6394 CLS_META = 0x1,
6395 CLS_ROOT = 0x2,
6396 OBJC2_CLS_HIDDEN = 0x10,
6397 CLS_EXCEPTION = 0x20,
6398
6399 /// (Obsolete) ARC-specific: this class has a .release_ivars method
6400 CLS_HAS_IVAR_RELEASER = 0x40,
6401 /// class was compiled with -fobjc-arr
6402 CLS_COMPILED_BY_ARC = 0x80 // (1<<7)
6403};
6404
6405static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,
6406 unsigned int flags,
6407 const std::string &InstanceStart,
6408 const std::string &InstanceSize,
6409 ArrayRef<ObjCMethodDecl *>baseMethods,
6410 ArrayRef<ObjCProtocolDecl *>baseProtocols,
6411 ArrayRef<ObjCIvarDecl *>ivars,
6412 ArrayRef<ObjCPropertyDecl *>Properties,
6413 StringRef VarName,
6414 StringRef ClassName) {
6415 Result += "\nstatic struct _class_ro_t ";
6416 Result += VarName; Result += ClassName;
6417 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6418 Result += "\t";
6419 Result += llvm::utostr(flags); Result += ", ";
6420 Result += InstanceStart; Result += ", ";
6421 Result += InstanceSize; Result += ", \n";
6422 Result += "\t";
6423 const llvm::Triple &Triple(Context->getTargetInfo().getTriple());
6424 if (Triple.getArch() == llvm::Triple::x86_64)
6425 // uint32_t const reserved; // only when building for 64bit targets
6426 Result += "(unsigned int)0, \n\t";
6427 // const uint8_t * const ivarLayout;
6428 Result += "0, \n\t";
6429 Result += "\""; Result += ClassName; Result += "\",\n\t";
6430 bool metaclass = ((flags & CLS_META) != 0);
6431 if (baseMethods.size() > 0) {
6432 Result += "(const struct _method_list_t *)&";
6433 if (metaclass)
6434 Result += "_OBJC_$_CLASS_METHODS_";
6435 else
6436 Result += "_OBJC_$_INSTANCE_METHODS_";
6437 Result += ClassName;
6438 Result += ",\n\t";
6439 }
6440 else
6441 Result += "0, \n\t";
6442
6443 if (!metaclass && baseProtocols.size() > 0) {
6444 Result += "(const struct _objc_protocol_list *)&";
6445 Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName;
6446 Result += ",\n\t";
6447 }
6448 else
6449 Result += "0, \n\t";
6450
6451 if (!metaclass && ivars.size() > 0) {
6452 Result += "(const struct _ivar_list_t *)&";
6453 Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName;
6454 Result += ",\n\t";
6455 }
6456 else
6457 Result += "0, \n\t";
6458
6459 // weakIvarLayout
6460 Result += "0, \n\t";
6461 if (!metaclass && Properties.size() > 0) {
6462 Result += "(const struct _prop_list_t *)&";
6463 Result += "_OBJC_$_PROP_LIST_"; Result += ClassName;
6464 Result += ",\n";
6465 }
6466 else
6467 Result += "0, \n";
6468
6469 Result += "};\n";
6470}
6471
6472static void Write_class_t(ASTContext *Context, std::string &Result,
6473 StringRef VarName,
6474 const ObjCInterfaceDecl *CDecl, bool metaclass) {
6475 bool rootClass = (!CDecl->getSuperClass());
6476 const ObjCInterfaceDecl *RootClass = CDecl;
6477
6478 if (!rootClass) {
6479 // Find the Root class
6480 RootClass = CDecl->getSuperClass();
6481 while (RootClass->getSuperClass()) {
6482 RootClass = RootClass->getSuperClass();
6483 }
6484 }
6485
6486 if (metaclass && rootClass) {
6487 // Need to handle a case of use of forward declaration.
6488 Result += "\n";
6489 Result += "extern \"C\" ";
6490 if (CDecl->getImplementation())
6491 Result += "__declspec(dllexport) ";
6492 else
6493 Result += "__declspec(dllimport) ";
6494
6495 Result += "struct _class_t OBJC_CLASS_$_";
6496 Result += CDecl->getNameAsString();
6497 Result += ";\n";
6498 }
6499 // Also, for possibility of 'super' metadata class not having been defined yet.
6500 if (!rootClass) {
6501 ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
6502 Result += "\n";
6503 Result += "extern \"C\" ";
6504 if (SuperClass->getImplementation())
6505 Result += "__declspec(dllexport) ";
6506 else
6507 Result += "__declspec(dllimport) ";
6508
6509 Result += "struct _class_t ";
6510 Result += VarName;
6511 Result += SuperClass->getNameAsString();
6512 Result += ";\n";
6513
6514 if (metaclass && RootClass != SuperClass) {
6515 Result += "extern \"C\" ";
6516 if (RootClass->getImplementation())
6517 Result += "__declspec(dllexport) ";
6518 else
6519 Result += "__declspec(dllimport) ";
6520
6521 Result += "struct _class_t ";
6522 Result += VarName;
6523 Result += RootClass->getNameAsString();
6524 Result += ";\n";
6525 }
6526 }
6527
6528 Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";
6529 Result += VarName; Result += CDecl->getNameAsString();
6530 Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";
6531 Result += "\t";
6532 if (metaclass) {
6533 if (!rootClass) {
6534 Result += "0, // &"; Result += VarName;
6535 Result += RootClass->getNameAsString();
6536 Result += ",\n\t";
6537 Result += "0, // &"; Result += VarName;
6538 Result += CDecl->getSuperClass()->getNameAsString();
6539 Result += ",\n\t";
6540 }
6541 else {
6542 Result += "0, // &"; Result += VarName;
6543 Result += CDecl->getNameAsString();
6544 Result += ",\n\t";
6545 Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6546 Result += ",\n\t";
6547 }
6548 }
6549 else {
6550 Result += "0, // &OBJC_METACLASS_$_";
6551 Result += CDecl->getNameAsString();
6552 Result += ",\n\t";
6553 if (!rootClass) {
6554 Result += "0, // &"; Result += VarName;
6555 Result += CDecl->getSuperClass()->getNameAsString();
6556 Result += ",\n\t";
6557 }
6558 else
6559 Result += "0,\n\t";
6560 }
6561 Result += "0, // (void *)&_objc_empty_cache,\n\t";
6562 Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t";
6563 if (metaclass)
6564 Result += "&_OBJC_METACLASS_RO_$_";
6565 else
6566 Result += "&_OBJC_CLASS_RO_$_";
6567 Result += CDecl->getNameAsString();
6568 Result += ",\n};\n";
6569
6570 // Add static function to initialize some of the meta-data fields.
6571 // avoid doing it twice.
6572 if (metaclass)
6573 return;
6574
6575 const ObjCInterfaceDecl *SuperClass =
6576 rootClass ? CDecl : CDecl->getSuperClass();
6577
6578 Result += "static void OBJC_CLASS_SETUP_$_";
6579 Result += CDecl->getNameAsString();
6580 Result += "(void ) {\n";
6581 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6582 Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
6583 Result += RootClass->getNameAsString(); Result += ";\n";
6584
6585 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6586 Result += ".superclass = ";
6587 if (rootClass)
6588 Result += "&OBJC_CLASS_$_";
6589 else
6590 Result += "&OBJC_METACLASS_$_";
6591
6592 Result += SuperClass->getNameAsString(); Result += ";\n";
6593
6594 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();
6595 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
6596
6597 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6598 Result += ".isa = "; Result += "&OBJC_METACLASS_$_";
6599 Result += CDecl->getNameAsString(); Result += ";\n";
6600
6601 if (!rootClass) {
6602 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6603 Result += ".superclass = "; Result += "&OBJC_CLASS_$_";
6604 Result += SuperClass->getNameAsString(); Result += ";\n";
6605 }
6606
6607 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();
6608 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";
6609 Result += "}\n";
6610}
6611
6612static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,
6613 std::string &Result,
6614 ObjCCategoryDecl *CatDecl,
6615 ObjCInterfaceDecl *ClassDecl,
6616 ArrayRef<ObjCMethodDecl *> InstanceMethods,
6617 ArrayRef<ObjCMethodDecl *> ClassMethods,
6618 ArrayRef<ObjCProtocolDecl *> RefedProtocols,
6619 ArrayRef<ObjCPropertyDecl *> ClassProperties) {
6620 StringRef CatName = CatDecl->getName();
6621 StringRef ClassName = ClassDecl->getName();
6622 // must declare an extern class object in case this class is not implemented
6623 // in this TU.
6624 Result += "\n";
6625 Result += "extern \"C\" ";
6626 if (ClassDecl->getImplementation())
6627 Result += "__declspec(dllexport) ";
6628 else
6629 Result += "__declspec(dllimport) ";
6630
6631 Result += "struct _class_t ";
6632 Result += "OBJC_CLASS_$_"; Result += ClassName;
6633 Result += ";\n";
6634
6635 Result += "\nstatic struct _category_t ";
6636 Result += "_OBJC_$_CATEGORY_";
6637 Result += ClassName; Result += "_$_"; Result += CatName;
6638 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
6639 Result += "{\n";
6640 Result += "\t\""; Result += ClassName; Result += "\",\n";
6641 Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;
6642 Result += ",\n";
6643 if (InstanceMethods.size() > 0) {
6644 Result += "\t(const struct _method_list_t *)&";
6645 Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
6646 Result += ClassName; Result += "_$_"; Result += CatName;
6647 Result += ",\n";
6648 }
6649 else
6650 Result += "\t0,\n";
6651
6652 if (ClassMethods.size() > 0) {
6653 Result += "\t(const struct _method_list_t *)&";
6654 Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";
6655 Result += ClassName; Result += "_$_"; Result += CatName;
6656 Result += ",\n";
6657 }
6658 else
6659 Result += "\t0,\n";
6660
6661 if (RefedProtocols.size() > 0) {
6662 Result += "\t(const struct _protocol_list_t *)&";
6663 Result += "_OBJC_CATEGORY_PROTOCOLS_$_";
6664 Result += ClassName; Result += "_$_"; Result += CatName;
6665 Result += ",\n";
6666 }
6667 else
6668 Result += "\t0,\n";
6669
6670 if (ClassProperties.size() > 0) {
6671 Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_";
6672 Result += ClassName; Result += "_$_"; Result += CatName;
6673 Result += ",\n";
6674 }
6675 else
6676 Result += "\t0,\n";
6677
6678 Result += "};\n";
6679
6680 // Add static function to initialize the class pointer in the category structure.
6681 Result += "static void OBJC_CATEGORY_SETUP_$_";
6682 Result += ClassDecl->getNameAsString();
6683 Result += "_$_";
6684 Result += CatName;
6685 Result += "(void ) {\n";
6686 Result += "\t_OBJC_$_CATEGORY_";
6687 Result += ClassDecl->getNameAsString();
6688 Result += "_$_";
6689 Result += CatName;
6690 Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName;
6691 Result += ";\n}\n";
6692}
6693
6694static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,
6695 ASTContext *Context, std::string &Result,
6696 ArrayRef<ObjCMethodDecl *> Methods,
6697 StringRef VarName,
6698 StringRef ProtocolName) {
6699 if (Methods.size() == 0)
6700 return;
6701
6702 Result += "\nstatic const char *";
6703 Result += VarName; Result += ProtocolName;
6704 Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";
6705 Result += "{\n";
6706 for (unsigned i = 0, e = Methods.size(); i < e; i++) {
6707 ObjCMethodDecl *MD = Methods[i];
6708 std::string MethodTypeString =
6709 Context->getObjCEncodingForMethodDecl(MD, true);
6710 std::string QuoteMethodTypeString;
6711 RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);
6712 Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";
6713 if (i == e-1)
6714 Result += "\n};\n";
6715 else {
6716 Result += ",\n";
6717 }
6718 }
6719}
6720
6721static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,
6722 ASTContext *Context,
6723 std::string &Result,
6724 ArrayRef<ObjCIvarDecl *> Ivars,
6725 ObjCInterfaceDecl *CDecl) {
6726 // FIXME. visibilty of offset symbols may have to be set; for Darwin
6727 // this is what happens:
6728 /**
6729 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
6730 Ivar->getAccessControl() == ObjCIvarDecl::Package ||
6731 Class->getVisibility() == HiddenVisibility)
6732 Visibility should be: HiddenVisibility;
6733 else
6734 Visibility should be: DefaultVisibility;
6735 */
6736
6737 Result += "\n";
6738 for (unsigned i =0, e = Ivars.size(); i < e; i++) {
6739 ObjCIvarDecl *IvarDecl = Ivars[i];
6740 if (Context->getLangOpts().MicrosoftExt)
6741 Result += "__declspec(allocate(\".objc_ivar$B\")) ";
6742
6743 if (!Context->getLangOpts().MicrosoftExt ||
6744 IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||
6745 IvarDecl->getAccessControl() == ObjCIvarDecl::Package)
6746 Result += "extern \"C\" unsigned long int ";
6747 else
6748 Result += "extern \"C\" __declspec(dllexport) unsigned long int ";
6749 if (Ivars[i]->isBitField())
6750 RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
6751 else
6752 WriteInternalIvarName(CDecl, IvarDecl, Result);
6753 Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))";
6754 Result += " = ";
6755 RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result);
6756 Result += ";\n";
6757 if (Ivars[i]->isBitField()) {
6758 // skip over rest of the ivar bitfields.
6759 SKIP_BITFIELDS(i , e, Ivars){ while ((i < e) && Ivars[i]->isBitField()) ++i
; if (i < e) --i; }
;
6760 }
6761 }
6762}
6763
6764static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,
6765 ASTContext *Context, std::string &Result,
6766 ArrayRef<ObjCIvarDecl *> OriginalIvars,
6767 StringRef VarName,
6768 ObjCInterfaceDecl *CDecl) {
6769 if (OriginalIvars.size() > 0) {
6770 Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl);
6771 SmallVector<ObjCIvarDecl *, 8> Ivars;
6772 // strip off all but the first ivar bitfield from each group of ivars.
6773 // Such ivars in the ivar list table will be replaced by their grouping struct
6774 // 'ivar'.
6775 for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) {
6776 if (OriginalIvars[i]->isBitField()) {
6777 Ivars.push_back(OriginalIvars[i]);
6778 // skip over rest of the ivar bitfields.
6779 SKIP_BITFIELDS(i , e, OriginalIvars){ while ((i < e) && OriginalIvars[i]->isBitField
()) ++i; if (i < e) --i; }
;
6780 }
6781 else
6782 Ivars.push_back(OriginalIvars[i]);
6783 }
6784
6785 Result += "\nstatic ";
6786 Write__ivar_list_t_TypeDecl(Result, Ivars.size());
6787 Result += " "; Result += VarName;
6788 Result += CDecl->getNameAsString();
6789 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";
6790 Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n";
6791 Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n";
6792 for (unsigned i =0, e = Ivars.size(); i < e; i++) {
6793 ObjCIvarDecl *IvarDecl = Ivars[i];
6794 if (i == 0)
6795 Result += "\t{{";
6796 else
6797 Result += "\t {";
6798 Result += "(unsigned long int *)&";
6799 if (Ivars[i]->isBitField())
6800 RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);
6801 else
6802 WriteInternalIvarName(CDecl, IvarDecl, Result);
6803 Result += ", ";
6804
6805 Result += "\"";
6806 if (Ivars[i]->isBitField())
6807 RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result);
6808 else
6809 Result += IvarDecl->getName();
6810 Result += "\", ";
6811
6812 QualType IVQT = IvarDecl->getType();
6813 if (IvarDecl->isBitField())
6814 IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl);
6815
6816 std::string IvarTypeString, QuoteIvarTypeString;
6817 Context->getObjCEncodingForType(IVQT, IvarTypeString,
6818 IvarDecl);
6819 RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);
6820 Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";
6821
6822 // FIXME. this alignment represents the host alignment and need be changed to
6823 // represent the target alignment.
6824 unsigned Align = Context->getTypeAlign(IVQT)/8;
6825 Align = llvm::Log2_32(Align);
6826 Result += llvm::utostr(Align); Result += ", ";
6827 CharUnits Size = Context->getTypeSizeInChars(IVQT);
6828 Result += llvm::utostr(Size.getQuantity());
6829 if (i == e-1)
6830 Result += "}}\n";
6831 else
6832 Result += "},\n";
6833 }
6834 Result += "};\n";
6835 }
6836}
6837
6838/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
6839void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,
6840 std::string &Result) {
6841
6842 // Do not synthesize the protocol more than once.
6843 if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
6844 return;
6845 WriteModernMetadataDeclarations(Context, Result);
6846
6847 if (ObjCProtocolDecl *Def = PDecl->getDefinition())
6848 PDecl = Def;
6849 // Must write out all protocol definitions in current qualifier list,
6850 // and in their nested qualifiers before writing out current definition.
6851 for (auto *I : PDecl->protocols())
6852 RewriteObjCProtocolMetaData(I, Result);
6853
6854 // Construct method lists.
6855 std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;
6856 std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;
6857 for (auto *MD : PDecl->instance_methods()) {
6858 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6859 OptInstanceMethods.push_back(MD);
6860 } else {
6861 InstanceMethods.push_back(MD);
6862 }
6863 }
6864
6865 for (auto *MD : PDecl->class_methods()) {
6866 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
6867 OptClassMethods.push_back(MD);
6868 } else {
6869 ClassMethods.push_back(MD);
6870 }
6871 }
6872 std::vector<ObjCMethodDecl *> AllMethods;
6873 for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++)
6874 AllMethods.push_back(InstanceMethods[i]);
6875 for (unsigned i = 0, e = ClassMethods.size(); i < e; i++)
6876 AllMethods.push_back(ClassMethods[i]);
6877 for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++)
6878 AllMethods.push_back(OptInstanceMethods[i]);
6879 for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++)
6880 AllMethods.push_back(OptClassMethods[i]);
6881
6882 Write__extendedMethodTypes_initializer(*this, Context, Result,
6883 AllMethods,
6884 "_OBJC_PROTOCOL_METHOD_TYPES_",
6885 PDecl->getNameAsString());
6886 // Protocol's super protocol list
6887 SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());
6888 Write_protocol_list_initializer(Context, Result, SuperProtocols,
6889 "_OBJC_PROTOCOL_REFS_",
6890 PDecl->getNameAsString());
6891
6892 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
6893 "_OBJC_PROTOCOL_INSTANCE_METHODS_",
6894 PDecl->getNameAsString(), false);
6895
6896 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
6897 "_OBJC_PROTOCOL_CLASS_METHODS_",
6898 PDecl->getNameAsString(), false);
6899
6900 Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,
6901 "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",
6902 PDecl->getNameAsString(), false);
6903
6904 Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,
6905 "_OBJC_PROTOCOL_OPT_CLASS_METHODS_",
6906 PDecl->getNameAsString(), false);
6907
6908 // Protocol's property metadata.
6909 SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(
6910 PDecl->instance_properties());
6911 Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,
6912 /* Container */nullptr,
6913 "_OBJC_PROTOCOL_PROPERTIES_",
6914 PDecl->getNameAsString());
6915
6916 // Writer out root metadata for current protocol: struct _protocol_t
6917 Result += "\n";
6918 if (LangOpts.MicrosoftExt)
6919 Result += "static ";
6920 Result += "struct _protocol_t _OBJC_PROTOCOL_";
6921 Result += PDecl->getNameAsString();
6922 Result += " __attribute__ ((used)) = {\n";
6923 Result += "\t0,\n"; // id is; is null
6924 Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n";
6925 if (SuperProtocols.size() > 0) {
6926 Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_";
6927 Result += PDecl->getNameAsString(); Result += ",\n";
6928 }
6929 else
6930 Result += "\t0,\n";
6931 if (InstanceMethods.size() > 0) {
6932 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
6933 Result += PDecl->getNameAsString(); Result += ",\n";
6934 }
6935 else
6936 Result += "\t0,\n";
6937
6938 if (ClassMethods.size() > 0) {
6939 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";
6940 Result += PDecl->getNameAsString(); Result += ",\n";
6941 }
6942 else
6943 Result += "\t0,\n";
6944
6945 if (OptInstanceMethods.size() > 0) {
6946 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";
6947 Result += PDecl->getNameAsString(); Result += ",\n";
6948 }
6949 else
6950 Result += "\t0,\n";
6951
6952 if (OptClassMethods.size() > 0) {
6953 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";
6954 Result += PDecl->getNameAsString(); Result += ",\n";
6955 }
6956 else
6957 Result += "\t0,\n";
6958
6959 if (ProtocolProperties.size() > 0) {
6960 Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";
6961 Result += PDecl->getNameAsString(); Result += ",\n";
6962 }
6963 else
6964 Result += "\t0,\n";
6965
6966 Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";
6967 Result += "\t0,\n";
6968
6969 if (AllMethods.size() > 0) {
6970 Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";
6971 Result += PDecl->getNameAsString();
6972 Result += "\n};\n";
6973 }
6974 else
6975 Result += "\t0\n};\n";
6976
6977 if (LangOpts.MicrosoftExt)
6978 Result += "static ";
6979 Result += "struct _protocol_t *";
6980 Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();
6981 Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();
6982 Result += ";\n";
6983
6984 // Mark this protocol as having been generated.
6985 if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
6986 llvm_unreachable("protocol already synthesized")__builtin_unreachable();
6987}
6988
6989/// hasObjCExceptionAttribute - Return true if this class or any super
6990/// class has the __objc_exception__ attribute.
6991/// FIXME. Move this to ASTContext.cpp as it is also used for IRGen.
6992static bool hasObjCExceptionAttribute(ASTContext &Context,
6993 const ObjCInterfaceDecl *OID) {
6994 if (OID->hasAttr<ObjCExceptionAttr>())
6995 return true;
6996 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
6997 return hasObjCExceptionAttribute(Context, Super);
6998 return false;
6999}
7000
7001void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
7002 std::string &Result) {
7003 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
7004
7005 // Explicitly declared @interface's are already synthesized.
7006 if (CDecl->isImplicitInterfaceDecl())
7007 assert(false &&(static_cast<void> (0))
7008 "Legacy implicit interface rewriting not supported in moder abi")(static_cast<void> (0));
7009
7010 WriteModernMetadataDeclarations(Context, Result);
7011 SmallVector<ObjCIvarDecl *, 8> IVars;
7012
7013 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
7014 IVD; IVD = IVD->getNextIvar()) {
7015 // Ignore unnamed bit-fields.
7016 if (!IVD->getDeclName())
7017 continue;
7018 IVars.push_back(IVD);
7019 }
7020
7021 Write__ivar_list_t_initializer(*this, Context, Result, IVars,
7022 "_OBJC_$_INSTANCE_VARIABLES_",
7023 CDecl);
7024
7025 // Build _objc_method_list for class's instance methods if needed
7026 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
7027
7028 // If any of our property implementations have associated getters or
7029 // setters, produce metadata for them as well.
7030 for (const auto *Prop : IDecl->property_impls()) {
7031 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
7032 continue;
7033 if (!Prop->getPropertyIvarDecl())
7034 continue;
7035 ObjCPropertyDecl *PD = Prop->getPropertyDecl();
7036 if (!PD)
7037 continue;
7038 if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
7039 if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))
7040 InstanceMethods.push_back(Getter);
7041 if (PD->isReadOnly())
7042 continue;
7043 if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
7044 if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))
7045 InstanceMethods.push_back(Setter);
7046 }
7047
7048 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
7049 "_OBJC_$_INSTANCE_METHODS_",
7050 IDecl->getNameAsString(), true);
7051
7052 SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
7053
7054 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
7055 "_OBJC_$_CLASS_METHODS_",
7056 IDecl->getNameAsString(), true);
7057
7058 // Protocols referenced in class declaration?
7059 // Protocol's super protocol list
7060 std::vector<ObjCProtocolDecl *> RefedProtocols;
7061 const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();
7062 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
7063 E = Protocols.end();
7064 I != E; ++I) {
7065 RefedProtocols.push_back(*I);
7066 // Must write out all protocol definitions in current qualifier list,
7067 // and in their nested qualifiers before writing out current definition.
7068 RewriteObjCProtocolMetaData(*I, Result);
7069 }
7070
7071 Write_protocol_list_initializer(Context, Result,
7072 RefedProtocols,
7073 "_OBJC_CLASS_PROTOCOLS_$_",
7074 IDecl->getNameAsString());
7075
7076 // Protocol's property metadata.
7077 SmallVector<ObjCPropertyDecl *, 8> ClassProperties(
7078 CDecl->instance_properties());
7079 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
7080 /* Container */IDecl,
7081 "_OBJC_$_PROP_LIST_",
7082 CDecl->getNameAsString());
7083
7084 // Data for initializing _class_ro_t metaclass meta-data
7085 uint32_t flags = CLS_META;
7086 std::string InstanceSize;
7087 std::string InstanceStart;
7088
7089 bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;
7090 if (classIsHidden)
7091 flags |= OBJC2_CLS_HIDDEN;
7092
7093 if (!CDecl->getSuperClass())
7094 // class is root
7095 flags |= CLS_ROOT;
7096 InstanceSize = "sizeof(struct _class_t)";
7097 InstanceStart = InstanceSize;
7098 Write__class_ro_t_initializer(Context, Result, flags,
7099 InstanceStart, InstanceSize,
7100 ClassMethods,
7101 nullptr,
7102 nullptr,
7103 nullptr,
7104 "_OBJC_METACLASS_RO_$_",
7105 CDecl->getNameAsString());
7106
7107 // Data for initializing _class_ro_t meta-data
7108 flags = CLS;
7109 if (classIsHidden)
7110 flags |= OBJC2_CLS_HIDDEN;
7111
7112 if (hasObjCExceptionAttribute(*Context, CDecl))
7113 flags |= CLS_EXCEPTION;
7114
7115 if (!CDecl->getSuperClass())
7116 // class is root
7117 flags |= CLS_ROOT;
7118
7119 InstanceSize.clear();
7120 InstanceStart.clear();
7121 if (!ObjCSynthesizedStructs.count(CDecl)) {
7122 InstanceSize = "0";
7123 InstanceStart = "0";
7124 }
7125 else {
7126 InstanceSize = "sizeof(struct ";
7127 InstanceSize += CDecl->getNameAsString();
7128 InstanceSize += "_IMPL)";
7129
7130 ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();
7131 if (IVD) {
7132 RewriteIvarOffsetComputation(IVD, InstanceStart);
7133 }
7134 else
7135 InstanceStart = InstanceSize;
7136 }
7137 Write__class_ro_t_initializer(Context, Result, flags,
7138 InstanceStart, InstanceSize,
7139 InstanceMethods,
7140 RefedProtocols,
7141 IVars,
7142 ClassProperties,
7143 "_OBJC_CLASS_RO_$_",
7144 CDecl->getNameAsString());
7145
7146 Write_class_t(Context, Result,
7147 "OBJC_METACLASS_$_",
7148 CDecl, /*metaclass*/true);
7149
7150 Write_class_t(Context, Result,
7151 "OBJC_CLASS_$_",
7152 CDecl, /*metaclass*/false);
7153
7154 if (ImplementationIsNonLazy(IDecl))
7155 DefinedNonLazyClasses.push_back(CDecl);
7156}
7157
7158void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {
7159 int ClsDefCount = ClassImplementation.size();
7160 if (!ClsDefCount)
7161 return;
7162 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
7163 Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
7164 Result += "static void *OBJC_CLASS_SETUP[] = {\n";
7165 for (int i = 0; i < ClsDefCount; i++) {
7166 ObjCImplementationDecl *IDecl = ClassImplementation[i];
7167 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
7168 Result += "\t(void *)&OBJC_CLASS_SETUP_$_";
7169 Result += CDecl->getName(); Result += ",\n";
7170 }
7171 Result += "};\n";
7172}
7173
7174void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {
7175 int ClsDefCount = ClassImplementation.size();
7176 int CatDefCount = CategoryImplementation.size();
7177
7178 // For each implemented class, write out all its meta data.
7179 for (int i = 0; i < ClsDefCount; i++)
7180 RewriteObjCClassMetaData(ClassImplementation[i], Result);
7181
7182 RewriteClassSetupInitHook(Result);
7183
7184 // For each implemented category, write out all its meta data.
7185 for (int i = 0; i < CatDefCount; i++)
7186 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
7187
7188 RewriteCategorySetupInitHook(Result);
7189
7190 if (ClsDefCount > 0) {
7191 if (LangOpts.MicrosoftExt)
7192 Result += "__declspec(allocate(\".objc_classlist$B\")) ";
7193 Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";
7194 Result += llvm::utostr(ClsDefCount); Result += "]";
7195 Result +=
7196 " __attribute__((used, section (\"__DATA, __objc_classlist,"
7197 "regular,no_dead_strip\")))= {\n";
7198 for (int i = 0; i < ClsDefCount; i++) {
7199 Result += "\t&OBJC_CLASS_$_";
7200 Result += ClassImplementation[i]->getNameAsString();
7201 Result += ",\n";
7202 }
7203 Result += "};\n";
7204
7205 if (!DefinedNonLazyClasses.empty()) {
7206 if (LangOpts.MicrosoftExt)
7207 Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";
7208 Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t";
7209 for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) {
7210 Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString();
7211 Result += ",\n";
7212 }
7213 Result += "};\n";
7214 }
7215 }
7216
7217 if (CatDefCount > 0) {
7218 if (LangOpts.MicrosoftExt)
7219 Result += "__declspec(allocate(\".objc_catlist$B\")) ";
7220 Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";
7221 Result += llvm::utostr(CatDefCount); Result += "]";
7222 Result +=
7223 " __attribute__((used, section (\"__DATA, __objc_catlist,"
7224 "regular,no_dead_strip\")))= {\n";
7225 for (int i = 0; i < CatDefCount; i++) {
7226 Result += "\t&_OBJC_$_CATEGORY_";
7227 Result +=
7228 CategoryImplementation[i]->getClassInterface()->getNameAsString();
7229 Result += "_$_";
7230 Result += CategoryImplementation[i]->getNameAsString();
7231 Result += ",\n";
7232 }
7233 Result += "};\n";
7234 }
7235
7236 if (!DefinedNonLazyCategories.empty()) {
7237 if (LangOpts.MicrosoftExt)
7238 Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";
7239 Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";
7240 for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {
7241 Result += "\t&_OBJC_$_CATEGORY_";
7242 Result +=
7243 DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();
7244 Result += "_$_";
7245 Result += DefinedNonLazyCategories[i]->getNameAsString();
7246 Result += ",\n";
7247 }
7248 Result += "};\n";
7249 }
7250}
7251
7252void RewriteModernObjC::WriteImageInfo(std::string &Result) {
7253 if (LangOpts.MicrosoftExt)
7254 Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";
7255
7256 Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";
7257 // version 0, ObjCABI is 2
7258 Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";
7259}
7260
7261/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
7262/// implementation.
7263void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
7264 std::string &Result) {
7265 WriteModernMetadataDeclarations(Context, Result);
7266 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
7267 // Find category declaration for this implementation.
7268 ObjCCategoryDecl *CDecl
7269 = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
7270
7271 std::string FullCategoryName = ClassDecl->getNameAsString();
7272 FullCategoryName += "_$_";
7273 FullCategoryName += CDecl->getNameAsString();
7274
7275 // Build _objc_method_list for class's instance methods if needed
7276 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
7277
7278 // If any of our property implementations have associated getters or
7279 // setters, produce metadata for them as well.
7280 for (const auto *Prop : IDecl->property_impls()) {
7281 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
7282 continue;
7283 if (!Prop->getPropertyIvarDecl())
7284 continue;
7285 ObjCPropertyDecl *PD = Prop->getPropertyDecl();
7286 if (!PD)
7287 continue;
7288 if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
7289 InstanceMethods.push_back(Getter);
7290 if (PD->isReadOnly())
7291 continue;
7292 if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
7293 InstanceMethods.push_back(Setter);
7294 }
7295
7296 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,
7297 "_OBJC_$_CATEGORY_INSTANCE_METHODS_",
7298 FullCategoryName, true);
7299
7300 SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());
7301
7302 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,
7303 "_OBJC_$_CATEGORY_CLASS_METHODS_",
7304 FullCategoryName, true);
7305
7306 // Protocols referenced in class declaration?
7307 // Protocol's super protocol list
7308 SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols());
7309 for (auto *I : CDecl->protocols())
7310 // Must write out all protocol definitions in current qualifier list,
7311 // and in their nested qualifiers before writing out current definition.
7312 RewriteObjCProtocolMetaData(I, Result);
7313
7314 Write_protocol_list_initializer(Context, Result,
7315 RefedProtocols,
7316 "_OBJC_CATEGORY_PROTOCOLS_$_",
7317 FullCategoryName);
7318
7319 // Protocol's property metadata.
7320 SmallVector<ObjCPropertyDecl *, 8> ClassProperties(
7321 CDecl->instance_properties());
7322 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,
7323 /* Container */IDecl,
7324 "_OBJC_$_PROP_LIST_",
7325 FullCategoryName);
7326
7327 Write_category_t(*this, Context, Result,
7328 CDecl,
7329 ClassDecl,
7330 InstanceMethods,
7331 ClassMethods,
7332 RefedProtocols,
7333 ClassProperties);
7334
7335 // Determine if this category is also "non-lazy".
7336 if (ImplementationIsNonLazy(IDecl))
7337 DefinedNonLazyCategories.push_back(CDecl);
7338}
7339
7340void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) {
7341 int CatDefCount = CategoryImplementation.size();
7342 if (!CatDefCount)
7343 return;
7344 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";
7345 Result += "__declspec(allocate(\".objc_inithooks$B\")) ";
7346 Result += "static void *OBJC_CATEGORY_SETUP[] = {\n";
7347 for (int i = 0; i < CatDefCount; i++) {
7348 ObjCCategoryImplDecl *IDecl = CategoryImplementation[i];
7349 ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl();
7350 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
7351 Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_";
7352 Result += ClassDecl->getName();
7353 Result += "_$_";
7354 Result += CatDecl->getName();
7355 Result += ",\n";
7356 }
7357 Result += "};\n";
7358}
7359
7360// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
7361/// class methods.
7362template<typename MethodIterator>
7363void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
7364 MethodIterator MethodEnd,
7365 bool IsInstanceMethod,
7366 StringRef prefix,
7367 StringRef ClassName,
7368 std::string &Result) {
7369 if (MethodBegin == MethodEnd) return;
7370
7371 if (!objc_impl_method) {
7372 /* struct _objc_method {
7373 SEL _cmd;
7374 char *method_types;
7375 void *_imp;
7376 }
7377 */
7378 Result += "\nstruct _objc_method {\n";
7379 Result += "\tSEL _cmd;\n";
7380 Result += "\tchar *method_types;\n";
7381 Result += "\tvoid *_imp;\n";
7382 Result += "};\n";
7383
7384 objc_impl_method = true;
7385 }
7386
7387 // Build _objc_method_list for class's methods if needed
7388
7389 /* struct {
7390 struct _objc_method_list *next_method;
7391 int method_count;
7392 struct _objc_method method_list[];
7393 }
7394 */
7395 unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
7396 Result += "\n";
7397 if (LangOpts.MicrosoftExt) {
7398 if (IsInstanceMethod)
7399 Result += "__declspec(allocate(\".inst_meth$B\")) ";
7400 else
7401 Result += "__declspec(allocate(\".cls_meth$B\")) ";
7402 }
7403 Result += "static struct {\n";
7404 Result += "\tstruct _objc_method_list *next_method;\n";
7405 Result += "\tint method_count;\n";
7406 Result += "\tstruct _objc_method method_list[";
7407 Result += utostr(NumMethods);
7408 Result += "];\n} _OBJC_";
7409 Result += prefix;
7410 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
7411 Result += "_METHODS_";
7412 Result += ClassName;
7413 Result += " __attribute__ ((used, section (\"__OBJC, __";
7414 Result += IsInstanceMethod ? "inst" : "cls";
7415 Result += "_meth\")))= ";
7416 Result += "{\n\t0, " + utostr(NumMethods) + "\n";
7417
7418 Result += "\t,{{(SEL)\"";
7419 Result += (*MethodBegin)->getSelector().getAsString().c_str();
7420 std::string MethodTypeString;
7421 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
7422 Result += "\", \"";
7423 Result += MethodTypeString;
7424 Result += "\", (void *)";
7425 Result += MethodInternalNames[*MethodBegin];
7426 Result += "}\n";
7427 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
7428 Result += "\t ,{(SEL)\"";
7429 Result += (*MethodBegin)->getSelector().getAsString().c_str();
7430 std::string MethodTypeString;
7431 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);
7432 Result += "\", \"";
7433 Result += MethodTypeString;
7434 Result += "\", (void *)";
7435 Result += MethodInternalNames[*MethodBegin];
7436 Result += "}\n";
7437 }
7438 Result += "\t }\n};\n";
7439}
7440
7441Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
7442 SourceRange OldRange = IV->getSourceRange();
7443 Expr *BaseExpr = IV->getBase();
7444
7445 // Rewrite the base, but without actually doing replaces.
7446 {
7447 DisableReplaceStmtScope S(*this);
7448 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
7449 IV->setBase(BaseExpr);
7450 }
7451
7452 ObjCIvarDecl *D = IV->getDecl();
7453
7454 Expr *Replacement = IV;
7455
7456 if (BaseExpr->getType()->isObjCObjectPointerType()) {
7457 const ObjCInterfaceType *iFaceDecl =
7458 dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
7459 assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null")(static_cast<void> (0));
7460 // lookup which class implements the instance variable.
7461 ObjCInterfaceDecl *clsDeclared = nullptr;
7462 iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
7463 clsDeclared);
7464 assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class")(static_cast<void> (0));
7465
7466 // Build name of symbol holding ivar offset.
7467 std::string IvarOffsetName;
7468 if (D->isBitField())
7469 ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);
7470 else
7471 WriteInternalIvarName(clsDeclared, D, IvarOffsetName);
7472
7473 ReferencedIvars[clsDeclared].insert(D);
7474
7475 // cast offset to "char *".
7476 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,
7477 Context->getPointerType(Context->CharTy),
7478 CK_BitCast,
7479 BaseExpr);
7480 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
7481 SourceLocation(), &Context->Idents.get(IvarOffsetName),
7482 Context->UnsignedLongTy, nullptr,
7483 SC_Extern);
7484 DeclRefExpr *DRE = new (Context)
7485 DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy,
7486 VK_LValue, SourceLocation());
7487 BinaryOperator *addExpr = BinaryOperator::Create(
7488 *Context, castExpr, DRE, BO_Add,
7489 Context->getPointerType(Context->CharTy), VK_PRValue, OK_Ordinary,
7490 SourceLocation(), FPOptionsOverride());
7491 // Don't forget the parens to enforce the proper binding.
7492 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),
7493 SourceLocation(),
7494 addExpr);
7495 QualType IvarT = D->getType();
7496 if (D->isBitField())
7497 IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);
7498
7499 if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) {
7500 RecordDecl *RD = IvarT->castAs<RecordType>()->getDecl();
7501 RD = RD->getDefinition();
7502 if (RD && !RD->getDeclName().getAsIdentifierInfo()) {
7503 // decltype(((Foo_IMPL*)0)->bar) *
7504 auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());
7505 // ivar in class extensions requires special treatment.
7506 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
7507 CDecl = CatDecl->getClassInterface();
7508 std::string RecName = std::string(CDecl->getName());
7509 RecName += "_IMPL";
7510 RecordDecl *RD = RecordDecl::Create(
7511 *Context, TTK_Struct, TUDecl, SourceLocation(), SourceLocation(),
7512 &Context->Idents.get(RecName));
7513 QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD));
7514 unsigned UnsignedIntSize =
7515 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));
7516 Expr *Zero = IntegerLiteral::Create(*Context,
7517 llvm::APInt(UnsignedIntSize, 0),
7518 Context->UnsignedIntTy, SourceLocation());
7519 Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);
7520 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
7521 Zero);
7522 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
7523 SourceLocation(),
7524 &Context->Idents.get(D->getNameAsString()),
7525 IvarT, nullptr,
7526 /*BitWidth=*/nullptr,
7527 /*Mutable=*/true, ICIS_NoInit);
7528 MemberExpr *ME = MemberExpr::CreateImplicit(
7529 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
7530 IvarT = Context->getDecltypeType(ME, ME->getType());
7531 }
7532 }
7533 convertObjCTypeToCStyleType(IvarT);
7534 QualType castT = Context->getPointerType(IvarT);
7535
7536 castExpr = NoTypeInfoCStyleCastExpr(Context,
7537 castT,
7538 CK_BitCast,
7539 PE);
7540
7541 Expr *Exp = UnaryOperator::Create(
7542 const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT,
7543 VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
7544 PE = new (Context) ParenExpr(OldRange.getBegin(),
7545 OldRange.getEnd(),
7546 Exp);
7547
7548 if (D->isBitField()) {
7549 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
7550 SourceLocation(),
7551 &Context->Idents.get(D->getNameAsString()),
7552 D->getType(), nullptr,
7553 /*BitWidth=*/D->getBitWidth(),
7554 /*Mutable=*/true, ICIS_NoInit);
7555 MemberExpr *ME =
7556 MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD,
7557 FD->getType(), VK_LValue, OK_Ordinary);
7558 Replacement = ME;
7559
7560 }
7561 else
7562 Replacement = PE;
7563 }
7564
7565 ReplaceStmtWithRange(IV, Replacement, OldRange);
7566 return Replacement;
7567}
7568
7569#endif // CLANG_ENABLE_OBJC_REWRITER