Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Frontend/Rewrite/RewriteObjC.cpp
35266 views
1
//===--- RewriteObjC.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/Config/config.h"
23
#include "clang/Lex/Lexer.h"
24
#include "clang/Rewrite/Core/Rewriter.h"
25
#include "llvm/ADT/DenseSet.h"
26
#include "llvm/ADT/SmallPtrSet.h"
27
#include "llvm/ADT/StringExtras.h"
28
#include "llvm/Support/MemoryBuffer.h"
29
#include "llvm/Support/raw_ostream.h"
30
#include <memory>
31
32
#if CLANG_ENABLE_OBJC_REWRITER
33
34
using namespace clang;
35
using llvm::utostr;
36
37
namespace {
38
class RewriteObjC : public ASTConsumer {
39
protected:
40
enum {
41
BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
42
block, ... */
43
BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
44
BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
45
__block variable */
46
BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
47
helpers */
48
BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
49
support routines */
50
BLOCK_BYREF_CURRENT_MAX = 256
51
};
52
53
enum {
54
BLOCK_NEEDS_FREE = (1 << 24),
55
BLOCK_HAS_COPY_DISPOSE = (1 << 25),
56
BLOCK_HAS_CXX_OBJ = (1 << 26),
57
BLOCK_IS_GC = (1 << 27),
58
BLOCK_IS_GLOBAL = (1 << 28),
59
BLOCK_HAS_DESCRIPTOR = (1 << 29)
60
};
61
static const int OBJC_ABI_VERSION = 7;
62
63
Rewriter Rewrite;
64
DiagnosticsEngine &Diags;
65
const LangOptions &LangOpts;
66
ASTContext *Context;
67
SourceManager *SM;
68
TranslationUnitDecl *TUDecl;
69
FileID MainFileID;
70
const char *MainFileStart, *MainFileEnd;
71
Stmt *CurrentBody;
72
ParentMap *PropParentMap; // created lazily.
73
std::string InFileName;
74
std::unique_ptr<raw_ostream> OutFile;
75
std::string Preamble;
76
77
TypeDecl *ProtocolTypeDecl;
78
VarDecl *GlobalVarDecl;
79
unsigned RewriteFailedDiag;
80
// ObjC string constant support.
81
unsigned NumObjCStringLiterals;
82
VarDecl *ConstantStringClassReference;
83
RecordDecl *NSStringRecord;
84
85
// ObjC foreach break/continue generation support.
86
int BcLabelCount;
87
88
unsigned TryFinallyContainsReturnDiag;
89
// Needed for super.
90
ObjCMethodDecl *CurMethodDef;
91
RecordDecl *SuperStructDecl;
92
RecordDecl *ConstantStringDecl;
93
94
FunctionDecl *MsgSendFunctionDecl;
95
FunctionDecl *MsgSendSuperFunctionDecl;
96
FunctionDecl *MsgSendStretFunctionDecl;
97
FunctionDecl *MsgSendSuperStretFunctionDecl;
98
FunctionDecl *MsgSendFpretFunctionDecl;
99
FunctionDecl *GetClassFunctionDecl;
100
FunctionDecl *GetMetaClassFunctionDecl;
101
FunctionDecl *GetSuperClassFunctionDecl;
102
FunctionDecl *SelGetUidFunctionDecl;
103
FunctionDecl *CFStringFunctionDecl;
104
FunctionDecl *SuperConstructorFunctionDecl;
105
FunctionDecl *CurFunctionDef;
106
FunctionDecl *CurFunctionDeclToDeclareForBlock;
107
108
/* Misc. containers needed for meta-data rewrite. */
109
SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
110
SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
111
llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
112
llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
113
llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
114
llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
115
SmallVector<Stmt *, 32> Stmts;
116
SmallVector<int, 8> ObjCBcLabelNo;
117
// Remember all the @protocol(<expr>) expressions.
118
llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
119
120
llvm::DenseSet<uint64_t> CopyDestroyCache;
121
122
// Block expressions.
123
SmallVector<BlockExpr *, 32> Blocks;
124
SmallVector<int, 32> InnerDeclRefsCount;
125
SmallVector<DeclRefExpr *, 32> InnerDeclRefs;
126
127
SmallVector<DeclRefExpr *, 32> BlockDeclRefs;
128
129
// Block related declarations.
130
SmallVector<ValueDecl *, 8> BlockByCopyDecls;
131
llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet;
132
SmallVector<ValueDecl *, 8> BlockByRefDecls;
133
llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
134
llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
135
llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
136
llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
137
138
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
139
140
// This maps an original source AST to it's rewritten form. This allows
141
// us to avoid rewriting the same node twice (which is very uncommon).
142
// This is needed to support some of the exotic property rewriting.
143
llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
144
145
// Needed for header files being rewritten
146
bool IsHeader;
147
bool SilenceRewriteMacroWarning;
148
bool objc_impl_method;
149
150
bool DisableReplaceStmt;
151
class DisableReplaceStmtScope {
152
RewriteObjC &R;
153
bool SavedValue;
154
155
public:
156
DisableReplaceStmtScope(RewriteObjC &R)
157
: R(R), SavedValue(R.DisableReplaceStmt) {
158
R.DisableReplaceStmt = true;
159
}
160
161
~DisableReplaceStmtScope() {
162
R.DisableReplaceStmt = SavedValue;
163
}
164
};
165
166
void InitializeCommon(ASTContext &context);
167
168
public:
169
// Top Level Driver code.
170
bool HandleTopLevelDecl(DeclGroupRef D) override {
171
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
172
if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {
173
if (!Class->isThisDeclarationADefinition()) {
174
RewriteForwardClassDecl(D);
175
break;
176
}
177
}
178
179
if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {
180
if (!Proto->isThisDeclarationADefinition()) {
181
RewriteForwardProtocolDecl(D);
182
break;
183
}
184
}
185
186
HandleTopLevelSingleDecl(*I);
187
}
188
return true;
189
}
190
191
void HandleTopLevelSingleDecl(Decl *D);
192
void HandleDeclInMainFile(Decl *D);
193
RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
194
DiagnosticsEngine &D, const LangOptions &LOpts,
195
bool silenceMacroWarn);
196
197
~RewriteObjC() override {}
198
199
void HandleTranslationUnit(ASTContext &C) override;
200
201
void ReplaceStmt(Stmt *Old, Stmt *New) {
202
ReplaceStmtWithRange(Old, New, Old->getSourceRange());
203
}
204
205
void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
206
assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");
207
208
Stmt *ReplacingStmt = ReplacedNodes[Old];
209
if (ReplacingStmt)
210
return; // We can't rewrite the same node twice.
211
212
if (DisableReplaceStmt)
213
return;
214
215
// Measure the old text.
216
int Size = Rewrite.getRangeSize(SrcRange);
217
if (Size == -1) {
218
Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
219
<< Old->getSourceRange();
220
return;
221
}
222
// Get the new text.
223
std::string SStr;
224
llvm::raw_string_ostream S(SStr);
225
New->printPretty(S, nullptr, PrintingPolicy(LangOpts));
226
const std::string &Str = S.str();
227
228
// If replacement succeeded or warning disabled return with no warning.
229
if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
230
ReplacedNodes[Old] = New;
231
return;
232
}
233
if (SilenceRewriteMacroWarning)
234
return;
235
Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)
236
<< Old->getSourceRange();
237
}
238
239
void InsertText(SourceLocation Loc, StringRef Str,
240
bool InsertAfter = true) {
241
// If insertion succeeded or warning disabled return with no warning.
242
if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||
243
SilenceRewriteMacroWarning)
244
return;
245
246
Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
247
}
248
249
void ReplaceText(SourceLocation Start, unsigned OrigLength,
250
StringRef Str) {
251
// If removal succeeded or warning disabled return with no warning.
252
if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||
253
SilenceRewriteMacroWarning)
254
return;
255
256
Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
257
}
258
259
// Syntactic Rewriting.
260
void RewriteRecordBody(RecordDecl *RD);
261
void RewriteInclude();
262
void RewriteForwardClassDecl(DeclGroupRef D);
263
void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);
264
void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
265
const std::string &typedefString);
266
void RewriteImplementations();
267
void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
268
ObjCImplementationDecl *IMD,
269
ObjCCategoryImplDecl *CID);
270
void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
271
void RewriteImplementationDecl(Decl *Dcl);
272
void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
273
ObjCMethodDecl *MDecl, std::string &ResultStr);
274
void RewriteTypeIntoString(QualType T, std::string &ResultStr,
275
const FunctionType *&FPRetType);
276
void RewriteByRefString(std::string &ResultStr, const std::string &Name,
277
ValueDecl *VD, bool def=false);
278
void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
279
void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
280
void RewriteForwardProtocolDecl(DeclGroupRef D);
281
void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);
282
void RewriteMethodDeclaration(ObjCMethodDecl *Method);
283
void RewriteProperty(ObjCPropertyDecl *prop);
284
void RewriteFunctionDecl(FunctionDecl *FD);
285
void RewriteBlockPointerType(std::string& Str, QualType Type);
286
void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);
287
void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
288
void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
289
void RewriteTypeOfDecl(VarDecl *VD);
290
void RewriteObjCQualifiedInterfaceTypes(Expr *E);
291
292
// Expression Rewriting.
293
Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
294
Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
295
Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);
296
Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);
297
Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
298
Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
299
Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
300
Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
301
void RewriteTryReturnStmts(Stmt *S);
302
void RewriteSyncReturnStmts(Stmt *S, std::string buf);
303
Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
304
Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
305
Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
306
Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
307
SourceLocation OrigEnd);
308
Stmt *RewriteBreakStmt(BreakStmt *S);
309
Stmt *RewriteContinueStmt(ContinueStmt *S);
310
void RewriteCastExpr(CStyleCastExpr *CE);
311
312
// Block rewriting.
313
void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
314
315
// Block specific rewrite rules.
316
void RewriteBlockPointerDecl(NamedDecl *VD);
317
void RewriteByRefVar(VarDecl *VD);
318
Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);
319
Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
320
void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
321
322
void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
323
std::string &Result);
324
325
void Initialize(ASTContext &context) override = 0;
326
327
// Metadata Rewriting.
328
virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;
329
virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
330
StringRef prefix,
331
StringRef ClassName,
332
std::string &Result) = 0;
333
virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
334
std::string &Result) = 0;
335
virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
336
StringRef prefix,
337
StringRef ClassName,
338
std::string &Result) = 0;
339
virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
340
std::string &Result) = 0;
341
342
// Rewriting ivar access
343
virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;
344
virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
345
std::string &Result) = 0;
346
347
// Misc. AST transformation routines. Sometimes they end up calling
348
// rewriting routines on the new ASTs.
349
CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
350
ArrayRef<Expr *> Args,
351
SourceLocation StartLoc=SourceLocation(),
352
SourceLocation EndLoc=SourceLocation());
353
CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
354
QualType msgSendType,
355
QualType returnType,
356
SmallVectorImpl<QualType> &ArgTypes,
357
SmallVectorImpl<Expr*> &MsgExprs,
358
ObjCMethodDecl *Method);
359
Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,
360
SourceLocation StartLoc=SourceLocation(),
361
SourceLocation EndLoc=SourceLocation());
362
363
void SynthCountByEnumWithState(std::string &buf);
364
void SynthMsgSendFunctionDecl();
365
void SynthMsgSendSuperFunctionDecl();
366
void SynthMsgSendStretFunctionDecl();
367
void SynthMsgSendFpretFunctionDecl();
368
void SynthMsgSendSuperStretFunctionDecl();
369
void SynthGetClassFunctionDecl();
370
void SynthGetMetaClassFunctionDecl();
371
void SynthGetSuperClassFunctionDecl();
372
void SynthSelGetUidFunctionDecl();
373
void SynthSuperConstructorFunctionDecl();
374
375
std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
376
std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
377
StringRef funcName, std::string Tag);
378
std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
379
StringRef funcName, std::string Tag);
380
std::string SynthesizeBlockImpl(BlockExpr *CE,
381
std::string Tag, std::string Desc);
382
std::string SynthesizeBlockDescriptor(std::string DescTag,
383
std::string ImplTag,
384
int i, StringRef funcName,
385
unsigned hasCopy);
386
Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
387
void SynthesizeBlockLiterals(SourceLocation FunLocStart,
388
StringRef FunName);
389
FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);
390
Stmt *SynthBlockInitExpr(BlockExpr *Exp,
391
const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);
392
393
// Misc. helper routines.
394
QualType getProtocolType();
395
void WarnAboutReturnGotoStmts(Stmt *S);
396
void HasReturnStmts(Stmt *S, bool &hasReturns);
397
void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
398
void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
399
void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
400
401
bool IsDeclStmtInForeachHeader(DeclStmt *DS);
402
void CollectBlockDeclRefInfo(BlockExpr *Exp);
403
void GetBlockDeclRefExprs(Stmt *S);
404
void GetInnerBlockDeclRefExprs(Stmt *S,
405
SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
406
llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);
407
408
// We avoid calling Type::isBlockPointerType(), since it operates on the
409
// canonical type. We only care if the top-level type is a closure pointer.
410
bool isTopLevelBlockPointerType(QualType T) {
411
return isa<BlockPointerType>(T);
412
}
413
414
/// convertBlockPointerToFunctionPointer - Converts a block-pointer type
415
/// to a function pointer type and upon success, returns true; false
416
/// otherwise.
417
bool convertBlockPointerToFunctionPointer(QualType &T) {
418
if (isTopLevelBlockPointerType(T)) {
419
const auto *BPT = T->castAs<BlockPointerType>();
420
T = Context->getPointerType(BPT->getPointeeType());
421
return true;
422
}
423
return false;
424
}
425
426
bool needToScanForQualifiers(QualType T);
427
QualType getSuperStructType();
428
QualType getConstantStringStructType();
429
QualType convertFunctionTypeOfBlocks(const FunctionType *FT);
430
bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
431
432
void convertToUnqualifiedObjCType(QualType &T) {
433
if (T->isObjCQualifiedIdType())
434
T = Context->getObjCIdType();
435
else if (T->isObjCQualifiedClassType())
436
T = Context->getObjCClassType();
437
else if (T->isObjCObjectPointerType() &&
438
T->getPointeeType()->isObjCQualifiedInterfaceType()) {
439
if (const ObjCObjectPointerType * OBJPT =
440
T->getAsObjCInterfacePointerType()) {
441
const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();
442
T = QualType(IFaceT, 0);
443
T = Context->getPointerType(T);
444
}
445
}
446
}
447
448
// FIXME: This predicate seems like it would be useful to add to ASTContext.
449
bool isObjCType(QualType T) {
450
if (!LangOpts.ObjC)
451
return false;
452
453
QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
454
455
if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
456
OCT == Context->getCanonicalType(Context->getObjCClassType()))
457
return true;
458
459
if (const PointerType *PT = OCT->getAs<PointerType>()) {
460
if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
461
PT->getPointeeType()->isObjCQualifiedIdType())
462
return true;
463
}
464
return false;
465
}
466
bool PointerTypeTakesAnyBlockArguments(QualType QT);
467
bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);
468
void GetExtentOfArgList(const char *Name, const char *&LParen,
469
const char *&RParen);
470
471
void QuoteDoublequotes(std::string &From, std::string &To) {
472
for (unsigned i = 0; i < From.length(); i++) {
473
if (From[i] == '"')
474
To += "\\\"";
475
else
476
To += From[i];
477
}
478
}
479
480
QualType getSimpleFunctionType(QualType result,
481
ArrayRef<QualType> args,
482
bool variadic = false) {
483
if (result == Context->getObjCInstanceType())
484
result = Context->getObjCIdType();
485
FunctionProtoType::ExtProtoInfo fpi;
486
fpi.Variadic = variadic;
487
return Context->getFunctionType(result, args, fpi);
488
}
489
490
// Helper function: create a CStyleCastExpr with trivial type source info.
491
CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
492
CastKind Kind, Expr *E) {
493
TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
494
return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,
495
FPOptionsOverride(), TInfo,
496
SourceLocation(), SourceLocation());
497
}
498
499
StringLiteral *getStringLiteral(StringRef Str) {
500
QualType StrType = Context->getConstantArrayType(
501
Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,
502
ArraySizeModifier::Normal, 0);
503
return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,
504
/*Pascal=*/false, StrType, SourceLocation());
505
}
506
};
507
508
class RewriteObjCFragileABI : public RewriteObjC {
509
public:
510
RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,
511
DiagnosticsEngine &D, const LangOptions &LOpts,
512
bool silenceMacroWarn)
513
: RewriteObjC(inFile, std::move(OS), D, LOpts, silenceMacroWarn) {}
514
515
~RewriteObjCFragileABI() override {}
516
void Initialize(ASTContext &context) override;
517
518
// Rewriting metadata
519
template<typename MethodIterator>
520
void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
521
MethodIterator MethodEnd,
522
bool IsInstanceMethod,
523
StringRef prefix,
524
StringRef ClassName,
525
std::string &Result);
526
void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
527
StringRef prefix, StringRef ClassName,
528
std::string &Result) override;
529
void RewriteObjCProtocolListMetaData(
530
const ObjCList<ObjCProtocolDecl> &Prots,
531
StringRef prefix, StringRef ClassName, std::string &Result) override;
532
void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
533
std::string &Result) override;
534
void RewriteMetaDataIntoBuffer(std::string &Result) override;
535
void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
536
std::string &Result) override;
537
538
// Rewriting ivar
539
void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
540
std::string &Result) override;
541
Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) override;
542
};
543
} // end anonymous namespace
544
545
void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
546
NamedDecl *D) {
547
if (const FunctionProtoType *fproto
548
= dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {
549
for (const auto &I : fproto->param_types())
550
if (isTopLevelBlockPointerType(I)) {
551
// All the args are checked/rewritten. Don't call twice!
552
RewriteBlockPointerDecl(D);
553
break;
554
}
555
}
556
}
557
558
void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
559
const PointerType *PT = funcType->getAs<PointerType>();
560
if (PT && PointerTypeTakesAnyBlockArguments(funcType))
561
RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
562
}
563
564
static bool IsHeaderFile(const std::string &Filename) {
565
std::string::size_type DotPos = Filename.rfind('.');
566
567
if (DotPos == std::string::npos) {
568
// no file extension
569
return false;
570
}
571
572
std::string Ext = Filename.substr(DotPos + 1);
573
// C header: .h
574
// C++ header: .hh or .H;
575
return Ext == "h" || Ext == "hh" || Ext == "H";
576
}
577
578
RewriteObjC::RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,
579
DiagnosticsEngine &D, const LangOptions &LOpts,
580
bool silenceMacroWarn)
581
: Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),
582
SilenceRewriteMacroWarning(silenceMacroWarn) {
583
IsHeader = IsHeaderFile(inFile);
584
RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,
585
"rewriting sub-expression within a macro (may not be correct)");
586
TryFinallyContainsReturnDiag = Diags.getCustomDiagID(
587
DiagnosticsEngine::Warning,
588
"rewriter doesn't support user-specified control flow semantics "
589
"for @try/@finally (code may not execute properly)");
590
}
591
592
std::unique_ptr<ASTConsumer>
593
clang::CreateObjCRewriter(const std::string &InFile,
594
std::unique_ptr<raw_ostream> OS,
595
DiagnosticsEngine &Diags, const LangOptions &LOpts,
596
bool SilenceRewriteMacroWarning) {
597
return std::make_unique<RewriteObjCFragileABI>(
598
InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);
599
}
600
601
void RewriteObjC::InitializeCommon(ASTContext &context) {
602
Context = &context;
603
SM = &Context->getSourceManager();
604
TUDecl = Context->getTranslationUnitDecl();
605
MsgSendFunctionDecl = nullptr;
606
MsgSendSuperFunctionDecl = nullptr;
607
MsgSendStretFunctionDecl = nullptr;
608
MsgSendSuperStretFunctionDecl = nullptr;
609
MsgSendFpretFunctionDecl = nullptr;
610
GetClassFunctionDecl = nullptr;
611
GetMetaClassFunctionDecl = nullptr;
612
GetSuperClassFunctionDecl = nullptr;
613
SelGetUidFunctionDecl = nullptr;
614
CFStringFunctionDecl = nullptr;
615
ConstantStringClassReference = nullptr;
616
NSStringRecord = nullptr;
617
CurMethodDef = nullptr;
618
CurFunctionDef = nullptr;
619
CurFunctionDeclToDeclareForBlock = nullptr;
620
GlobalVarDecl = nullptr;
621
SuperStructDecl = nullptr;
622
ProtocolTypeDecl = nullptr;
623
ConstantStringDecl = nullptr;
624
BcLabelCount = 0;
625
SuperConstructorFunctionDecl = nullptr;
626
NumObjCStringLiterals = 0;
627
PropParentMap = nullptr;
628
CurrentBody = nullptr;
629
DisableReplaceStmt = false;
630
objc_impl_method = false;
631
632
// Get the ID and start/end of the main file.
633
MainFileID = SM->getMainFileID();
634
llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);
635
MainFileStart = MainBuf.getBufferStart();
636
MainFileEnd = MainBuf.getBufferEnd();
637
638
Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
639
}
640
641
//===----------------------------------------------------------------------===//
642
// Top Level Driver Code
643
//===----------------------------------------------------------------------===//
644
645
void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
646
if (Diags.hasErrorOccurred())
647
return;
648
649
// Two cases: either the decl could be in the main file, or it could be in a
650
// #included file. If the former, rewrite it now. If the later, check to see
651
// if we rewrote the #include/#import.
652
SourceLocation Loc = D->getLocation();
653
Loc = SM->getExpansionLoc(Loc);
654
655
// If this is for a builtin, ignore it.
656
if (Loc.isInvalid()) return;
657
658
// Look for built-in declarations that we need to refer during the rewrite.
659
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
660
RewriteFunctionDecl(FD);
661
} else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
662
// declared in <Foundation/NSString.h>
663
if (FVD->getName() == "_NSConstantStringClassReference") {
664
ConstantStringClassReference = FVD;
665
return;
666
}
667
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
668
if (ID->isThisDeclarationADefinition())
669
RewriteInterfaceDecl(ID);
670
} else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
671
RewriteCategoryDecl(CD);
672
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
673
if (PD->isThisDeclarationADefinition())
674
RewriteProtocolDecl(PD);
675
} else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
676
// Recurse into linkage specifications
677
for (DeclContext::decl_iterator DI = LSD->decls_begin(),
678
DIEnd = LSD->decls_end();
679
DI != DIEnd; ) {
680
if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {
681
if (!IFace->isThisDeclarationADefinition()) {
682
SmallVector<Decl *, 8> DG;
683
SourceLocation StartLoc = IFace->getBeginLoc();
684
do {
685
if (isa<ObjCInterfaceDecl>(*DI) &&
686
!cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&
687
StartLoc == (*DI)->getBeginLoc())
688
DG.push_back(*DI);
689
else
690
break;
691
692
++DI;
693
} while (DI != DIEnd);
694
RewriteForwardClassDecl(DG);
695
continue;
696
}
697
}
698
699
if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {
700
if (!Proto->isThisDeclarationADefinition()) {
701
SmallVector<Decl *, 8> DG;
702
SourceLocation StartLoc = Proto->getBeginLoc();
703
do {
704
if (isa<ObjCProtocolDecl>(*DI) &&
705
!cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&
706
StartLoc == (*DI)->getBeginLoc())
707
DG.push_back(*DI);
708
else
709
break;
710
711
++DI;
712
} while (DI != DIEnd);
713
RewriteForwardProtocolDecl(DG);
714
continue;
715
}
716
}
717
718
HandleTopLevelSingleDecl(*DI);
719
++DI;
720
}
721
}
722
// If we have a decl in the main file, see if we should rewrite it.
723
if (SM->isWrittenInMainFile(Loc))
724
return HandleDeclInMainFile(D);
725
}
726
727
//===----------------------------------------------------------------------===//
728
// Syntactic (non-AST) Rewriting Code
729
//===----------------------------------------------------------------------===//
730
731
void RewriteObjC::RewriteInclude() {
732
SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
733
StringRef MainBuf = SM->getBufferData(MainFileID);
734
const char *MainBufStart = MainBuf.begin();
735
const char *MainBufEnd = MainBuf.end();
736
size_t ImportLen = strlen("import");
737
738
// Loop over the whole file, looking for includes.
739
for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
740
if (*BufPtr == '#') {
741
if (++BufPtr == MainBufEnd)
742
return;
743
while (*BufPtr == ' ' || *BufPtr == '\t')
744
if (++BufPtr == MainBufEnd)
745
return;
746
if (!strncmp(BufPtr, "import", ImportLen)) {
747
// replace import with include
748
SourceLocation ImportLoc =
749
LocStart.getLocWithOffset(BufPtr-MainBufStart);
750
ReplaceText(ImportLoc, ImportLen, "include");
751
BufPtr += ImportLen;
752
}
753
}
754
}
755
}
756
757
static std::string getIvarAccessString(ObjCIvarDecl *OID) {
758
const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface();
759
std::string S;
760
S = "((struct ";
761
S += ClassDecl->getIdentifier()->getName();
762
S += "_IMPL *)self)->";
763
S += OID->getName();
764
return S;
765
}
766
767
void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
768
ObjCImplementationDecl *IMD,
769
ObjCCategoryImplDecl *CID) {
770
static bool objcGetPropertyDefined = false;
771
static bool objcSetPropertyDefined = false;
772
SourceLocation startLoc = PID->getBeginLoc();
773
InsertText(startLoc, "// ");
774
const char *startBuf = SM->getCharacterData(startLoc);
775
assert((*startBuf == '@') && "bogus @synthesize location");
776
const char *semiBuf = strchr(startBuf, ';');
777
assert((*semiBuf == ';') && "@synthesize: can't find ';'");
778
SourceLocation onePastSemiLoc =
779
startLoc.getLocWithOffset(semiBuf-startBuf+1);
780
781
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
782
return; // FIXME: is this correct?
783
784
// Generate the 'getter' function.
785
ObjCPropertyDecl *PD = PID->getPropertyDecl();
786
ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
787
788
if (!OID)
789
return;
790
791
unsigned Attributes = PD->getPropertyAttributes();
792
if (PID->getGetterMethodDecl() && !PID->getGetterMethodDecl()->isDefined()) {
793
bool GenGetProperty =
794
!(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&
795
(Attributes & (ObjCPropertyAttribute::kind_retain |
796
ObjCPropertyAttribute::kind_copy));
797
std::string Getr;
798
if (GenGetProperty && !objcGetPropertyDefined) {
799
objcGetPropertyDefined = true;
800
// FIXME. Is this attribute correct in all cases?
801
Getr = "\nextern \"C\" __declspec(dllimport) "
802
"id objc_getProperty(id, SEL, long, bool);\n";
803
}
804
RewriteObjCMethodDecl(OID->getContainingInterface(),
805
PID->getGetterMethodDecl(), Getr);
806
Getr += "{ ";
807
// Synthesize an explicit cast to gain access to the ivar.
808
// See objc-act.c:objc_synthesize_new_getter() for details.
809
if (GenGetProperty) {
810
// return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)
811
Getr += "typedef ";
812
const FunctionType *FPRetType = nullptr;
813
RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,
814
FPRetType);
815
Getr += " _TYPE";
816
if (FPRetType) {
817
Getr += ")"; // close the precedence "scope" for "*".
818
819
// Now, emit the argument types (if any).
820
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){
821
Getr += "(";
822
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
823
if (i) Getr += ", ";
824
std::string ParamStr =
825
FT->getParamType(i).getAsString(Context->getPrintingPolicy());
826
Getr += ParamStr;
827
}
828
if (FT->isVariadic()) {
829
if (FT->getNumParams())
830
Getr += ", ";
831
Getr += "...";
832
}
833
Getr += ")";
834
} else
835
Getr += "()";
836
}
837
Getr += ";\n";
838
Getr += "return (_TYPE)";
839
Getr += "objc_getProperty(self, _cmd, ";
840
RewriteIvarOffsetComputation(OID, Getr);
841
Getr += ", 1)";
842
}
843
else
844
Getr += "return " + getIvarAccessString(OID);
845
Getr += "; }";
846
InsertText(onePastSemiLoc, Getr);
847
}
848
849
if (PD->isReadOnly() || !PID->getSetterMethodDecl() ||
850
PID->getSetterMethodDecl()->isDefined())
851
return;
852
853
// Generate the 'setter' function.
854
std::string Setr;
855
bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |
856
ObjCPropertyAttribute::kind_copy);
857
if (GenSetProperty && !objcSetPropertyDefined) {
858
objcSetPropertyDefined = true;
859
// FIXME. Is this attribute correct in all cases?
860
Setr = "\nextern \"C\" __declspec(dllimport) "
861
"void objc_setProperty (id, SEL, long, id, bool, bool);\n";
862
}
863
864
RewriteObjCMethodDecl(OID->getContainingInterface(),
865
PID->getSetterMethodDecl(), Setr);
866
Setr += "{ ";
867
// Synthesize an explicit cast to initialize the ivar.
868
// See objc-act.c:objc_synthesize_new_setter() for details.
869
if (GenSetProperty) {
870
Setr += "objc_setProperty (self, _cmd, ";
871
RewriteIvarOffsetComputation(OID, Setr);
872
Setr += ", (id)";
873
Setr += PD->getName();
874
Setr += ", ";
875
if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
876
Setr += "0, ";
877
else
878
Setr += "1, ";
879
if (Attributes & ObjCPropertyAttribute::kind_copy)
880
Setr += "1)";
881
else
882
Setr += "0)";
883
}
884
else {
885
Setr += getIvarAccessString(OID) + " = ";
886
Setr += PD->getName();
887
}
888
Setr += "; }";
889
InsertText(onePastSemiLoc, Setr);
890
}
891
892
static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,
893
std::string &typedefString) {
894
typedefString += "#ifndef _REWRITER_typedef_";
895
typedefString += ForwardDecl->getNameAsString();
896
typedefString += "\n";
897
typedefString += "#define _REWRITER_typedef_";
898
typedefString += ForwardDecl->getNameAsString();
899
typedefString += "\n";
900
typedefString += "typedef struct objc_object ";
901
typedefString += ForwardDecl->getNameAsString();
902
typedefString += ";\n#endif\n";
903
}
904
905
void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,
906
const std::string &typedefString) {
907
SourceLocation startLoc = ClassDecl->getBeginLoc();
908
const char *startBuf = SM->getCharacterData(startLoc);
909
const char *semiPtr = strchr(startBuf, ';');
910
// Replace the @class with typedefs corresponding to the classes.
911
ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);
912
}
913
914
void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {
915
std::string typedefString;
916
for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {
917
ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I);
918
if (I == D.begin()) {
919
// Translate to typedef's that forward reference structs with the same name
920
// as the class. As a convenience, we include the original declaration
921
// as a comment.
922
typedefString += "// @class ";
923
typedefString += ForwardDecl->getNameAsString();
924
typedefString += ";\n";
925
}
926
RewriteOneForwardClassDecl(ForwardDecl, typedefString);
927
}
928
DeclGroupRef::iterator I = D.begin();
929
RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);
930
}
931
932
void RewriteObjC::RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &D) {
933
std::string typedefString;
934
for (unsigned i = 0; i < D.size(); i++) {
935
ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);
936
if (i == 0) {
937
typedefString += "// @class ";
938
typedefString += ForwardDecl->getNameAsString();
939
typedefString += ";\n";
940
}
941
RewriteOneForwardClassDecl(ForwardDecl, typedefString);
942
}
943
RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);
944
}
945
946
void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
947
// When method is a synthesized one, such as a getter/setter there is
948
// nothing to rewrite.
949
if (Method->isImplicit())
950
return;
951
SourceLocation LocStart = Method->getBeginLoc();
952
SourceLocation LocEnd = Method->getEndLoc();
953
954
if (SM->getExpansionLineNumber(LocEnd) >
955
SM->getExpansionLineNumber(LocStart)) {
956
InsertText(LocStart, "#if 0\n");
957
ReplaceText(LocEnd, 1, ";\n#endif\n");
958
} else {
959
InsertText(LocStart, "// ");
960
}
961
}
962
963
void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
964
SourceLocation Loc = prop->getAtLoc();
965
966
ReplaceText(Loc, 0, "// ");
967
// FIXME: handle properties that are declared across multiple lines.
968
}
969
970
void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
971
SourceLocation LocStart = CatDecl->getBeginLoc();
972
973
// FIXME: handle category headers that are declared across multiple lines.
974
ReplaceText(LocStart, 0, "// ");
975
976
for (auto *I : CatDecl->instance_properties())
977
RewriteProperty(I);
978
for (auto *I : CatDecl->instance_methods())
979
RewriteMethodDeclaration(I);
980
for (auto *I : CatDecl->class_methods())
981
RewriteMethodDeclaration(I);
982
983
// Lastly, comment out the @end.
984
ReplaceText(CatDecl->getAtEndRange().getBegin(),
985
strlen("@end"), "/* @end */");
986
}
987
988
void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
989
SourceLocation LocStart = PDecl->getBeginLoc();
990
assert(PDecl->isThisDeclarationADefinition());
991
992
// FIXME: handle protocol headers that are declared across multiple lines.
993
ReplaceText(LocStart, 0, "// ");
994
995
for (auto *I : PDecl->instance_methods())
996
RewriteMethodDeclaration(I);
997
for (auto *I : PDecl->class_methods())
998
RewriteMethodDeclaration(I);
999
for (auto *I : PDecl->instance_properties())
1000
RewriteProperty(I);
1001
1002
// Lastly, comment out the @end.
1003
SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
1004
ReplaceText(LocEnd, strlen("@end"), "/* @end */");
1005
1006
// Must comment out @optional/@required
1007
const char *startBuf = SM->getCharacterData(LocStart);
1008
const char *endBuf = SM->getCharacterData(LocEnd);
1009
for (const char *p = startBuf; p < endBuf; p++) {
1010
if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
1011
SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
1012
ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");
1013
1014
}
1015
else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
1016
SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);
1017
ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");
1018
1019
}
1020
}
1021
}
1022
1023
void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {
1024
SourceLocation LocStart = (*D.begin())->getBeginLoc();
1025
if (LocStart.isInvalid())
1026
llvm_unreachable("Invalid SourceLocation");
1027
// FIXME: handle forward protocol that are declared across multiple lines.
1028
ReplaceText(LocStart, 0, "// ");
1029
}
1030
1031
void
1032
RewriteObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {
1033
SourceLocation LocStart = DG[0]->getBeginLoc();
1034
if (LocStart.isInvalid())
1035
llvm_unreachable("Invalid SourceLocation");
1036
// FIXME: handle forward protocol that are declared across multiple lines.
1037
ReplaceText(LocStart, 0, "// ");
1038
}
1039
1040
void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,
1041
const FunctionType *&FPRetType) {
1042
if (T->isObjCQualifiedIdType())
1043
ResultStr += "id";
1044
else if (T->isFunctionPointerType() ||
1045
T->isBlockPointerType()) {
1046
// needs special handling, since pointer-to-functions have special
1047
// syntax (where a decaration models use).
1048
QualType retType = T;
1049
QualType PointeeTy;
1050
if (const PointerType* PT = retType->getAs<PointerType>())
1051
PointeeTy = PT->getPointeeType();
1052
else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
1053
PointeeTy = BPT->getPointeeType();
1054
if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
1055
ResultStr +=
1056
FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());
1057
ResultStr += "(*";
1058
}
1059
} else
1060
ResultStr += T.getAsString(Context->getPrintingPolicy());
1061
}
1062
1063
void RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,
1064
ObjCMethodDecl *OMD,
1065
std::string &ResultStr) {
1066
//fprintf(stderr,"In RewriteObjCMethodDecl\n");
1067
const FunctionType *FPRetType = nullptr;
1068
ResultStr += "\nstatic ";
1069
RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);
1070
ResultStr += " ";
1071
1072
// Unique method name
1073
std::string NameStr;
1074
1075
if (OMD->isInstanceMethod())
1076
NameStr += "_I_";
1077
else
1078
NameStr += "_C_";
1079
1080
NameStr += IDecl->getNameAsString();
1081
NameStr += "_";
1082
1083
if (ObjCCategoryImplDecl *CID =
1084
dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
1085
NameStr += CID->getNameAsString();
1086
NameStr += "_";
1087
}
1088
// Append selector names, replacing ':' with '_'
1089
{
1090
std::string selString = OMD->getSelector().getAsString();
1091
int len = selString.size();
1092
for (int i = 0; i < len; i++)
1093
if (selString[i] == ':')
1094
selString[i] = '_';
1095
NameStr += selString;
1096
}
1097
// Remember this name for metadata emission
1098
MethodInternalNames[OMD] = NameStr;
1099
ResultStr += NameStr;
1100
1101
// Rewrite arguments
1102
ResultStr += "(";
1103
1104
// invisible arguments
1105
if (OMD->isInstanceMethod()) {
1106
QualType selfTy = Context->getObjCInterfaceType(IDecl);
1107
selfTy = Context->getPointerType(selfTy);
1108
if (!LangOpts.MicrosoftExt) {
1109
if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))
1110
ResultStr += "struct ";
1111
}
1112
// When rewriting for Microsoft, explicitly omit the structure name.
1113
ResultStr += IDecl->getNameAsString();
1114
ResultStr += " *";
1115
}
1116
else
1117
ResultStr += Context->getObjCClassType().getAsString(
1118
Context->getPrintingPolicy());
1119
1120
ResultStr += " self, ";
1121
ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());
1122
ResultStr += " _cmd";
1123
1124
// Method arguments.
1125
for (const auto *PDecl : OMD->parameters()) {
1126
ResultStr += ", ";
1127
if (PDecl->getType()->isObjCQualifiedIdType()) {
1128
ResultStr += "id ";
1129
ResultStr += PDecl->getNameAsString();
1130
} else {
1131
std::string Name = PDecl->getNameAsString();
1132
QualType QT = PDecl->getType();
1133
// Make sure we convert "t (^)(...)" to "t (*)(...)".
1134
(void)convertBlockPointerToFunctionPointer(QT);
1135
QT.getAsStringInternal(Name, Context->getPrintingPolicy());
1136
ResultStr += Name;
1137
}
1138
}
1139
if (OMD->isVariadic())
1140
ResultStr += ", ...";
1141
ResultStr += ") ";
1142
1143
if (FPRetType) {
1144
ResultStr += ")"; // close the precedence "scope" for "*".
1145
1146
// Now, emit the argument types (if any).
1147
if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
1148
ResultStr += "(";
1149
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {
1150
if (i) ResultStr += ", ";
1151
std::string ParamStr =
1152
FT->getParamType(i).getAsString(Context->getPrintingPolicy());
1153
ResultStr += ParamStr;
1154
}
1155
if (FT->isVariadic()) {
1156
if (FT->getNumParams())
1157
ResultStr += ", ";
1158
ResultStr += "...";
1159
}
1160
ResultStr += ")";
1161
} else {
1162
ResultStr += "()";
1163
}
1164
}
1165
}
1166
1167
void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
1168
ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
1169
ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
1170
assert((IMD || CID) && "Unknown ImplementationDecl");
1171
1172
InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// ");
1173
1174
for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {
1175
if (!OMD->getBody())
1176
continue;
1177
std::string ResultStr;
1178
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
1179
SourceLocation LocStart = OMD->getBeginLoc();
1180
SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
1181
1182
const char *startBuf = SM->getCharacterData(LocStart);
1183
const char *endBuf = SM->getCharacterData(LocEnd);
1184
ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1185
}
1186
1187
for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {
1188
if (!OMD->getBody())
1189
continue;
1190
std::string ResultStr;
1191
RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);
1192
SourceLocation LocStart = OMD->getBeginLoc();
1193
SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();
1194
1195
const char *startBuf = SM->getCharacterData(LocStart);
1196
const char *endBuf = SM->getCharacterData(LocEnd);
1197
ReplaceText(LocStart, endBuf-startBuf, ResultStr);
1198
}
1199
for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())
1200
RewritePropertyImplDecl(I, IMD, CID);
1201
1202
InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");
1203
}
1204
1205
void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
1206
std::string ResultStr;
1207
if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) {
1208
// we haven't seen a forward decl - generate a typedef.
1209
ResultStr = "#ifndef _REWRITER_typedef_";
1210
ResultStr += ClassDecl->getNameAsString();
1211
ResultStr += "\n";
1212
ResultStr += "#define _REWRITER_typedef_";
1213
ResultStr += ClassDecl->getNameAsString();
1214
ResultStr += "\n";
1215
ResultStr += "typedef struct objc_object ";
1216
ResultStr += ClassDecl->getNameAsString();
1217
ResultStr += ";\n#endif\n";
1218
// Mark this typedef as having been generated.
1219
ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl());
1220
}
1221
RewriteObjCInternalStruct(ClassDecl, ResultStr);
1222
1223
for (auto *I : ClassDecl->instance_properties())
1224
RewriteProperty(I);
1225
for (auto *I : ClassDecl->instance_methods())
1226
RewriteMethodDeclaration(I);
1227
for (auto *I : ClassDecl->class_methods())
1228
RewriteMethodDeclaration(I);
1229
1230
// Lastly, comment out the @end.
1231
ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),
1232
"/* @end */");
1233
}
1234
1235
Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {
1236
SourceRange OldRange = PseudoOp->getSourceRange();
1237
1238
// We just magically know some things about the structure of this
1239
// expression.
1240
ObjCMessageExpr *OldMsg =
1241
cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(
1242
PseudoOp->getNumSemanticExprs() - 1));
1243
1244
// Because the rewriter doesn't allow us to rewrite rewritten code,
1245
// we need to suppress rewriting the sub-statements.
1246
Expr *Base, *RHS;
1247
{
1248
DisableReplaceStmtScope S(*this);
1249
1250
// Rebuild the base expression if we have one.
1251
Base = nullptr;
1252
if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
1253
Base = OldMsg->getInstanceReceiver();
1254
Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1255
Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1256
}
1257
1258
// Rebuild the RHS.
1259
RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS();
1260
RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();
1261
RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));
1262
}
1263
1264
// TODO: avoid this copy.
1265
SmallVector<SourceLocation, 1> SelLocs;
1266
OldMsg->getSelectorLocs(SelLocs);
1267
1268
ObjCMessageExpr *NewMsg = nullptr;
1269
switch (OldMsg->getReceiverKind()) {
1270
case ObjCMessageExpr::Class:
1271
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1272
OldMsg->getValueKind(),
1273
OldMsg->getLeftLoc(),
1274
OldMsg->getClassReceiverTypeInfo(),
1275
OldMsg->getSelector(),
1276
SelLocs,
1277
OldMsg->getMethodDecl(),
1278
RHS,
1279
OldMsg->getRightLoc(),
1280
OldMsg->isImplicit());
1281
break;
1282
1283
case ObjCMessageExpr::Instance:
1284
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1285
OldMsg->getValueKind(),
1286
OldMsg->getLeftLoc(),
1287
Base,
1288
OldMsg->getSelector(),
1289
SelLocs,
1290
OldMsg->getMethodDecl(),
1291
RHS,
1292
OldMsg->getRightLoc(),
1293
OldMsg->isImplicit());
1294
break;
1295
1296
case ObjCMessageExpr::SuperClass:
1297
case ObjCMessageExpr::SuperInstance:
1298
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1299
OldMsg->getValueKind(),
1300
OldMsg->getLeftLoc(),
1301
OldMsg->getSuperLoc(),
1302
OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
1303
OldMsg->getSuperType(),
1304
OldMsg->getSelector(),
1305
SelLocs,
1306
OldMsg->getMethodDecl(),
1307
RHS,
1308
OldMsg->getRightLoc(),
1309
OldMsg->isImplicit());
1310
break;
1311
}
1312
1313
Stmt *Replacement = SynthMessageExpr(NewMsg);
1314
ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1315
return Replacement;
1316
}
1317
1318
Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {
1319
SourceRange OldRange = PseudoOp->getSourceRange();
1320
1321
// We just magically know some things about the structure of this
1322
// expression.
1323
ObjCMessageExpr *OldMsg =
1324
cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());
1325
1326
// Because the rewriter doesn't allow us to rewrite rewritten code,
1327
// we need to suppress rewriting the sub-statements.
1328
Expr *Base = nullptr;
1329
{
1330
DisableReplaceStmtScope S(*this);
1331
1332
// Rebuild the base expression if we have one.
1333
if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {
1334
Base = OldMsg->getInstanceReceiver();
1335
Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();
1336
Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));
1337
}
1338
}
1339
1340
// Intentionally empty.
1341
SmallVector<SourceLocation, 1> SelLocs;
1342
SmallVector<Expr*, 1> Args;
1343
1344
ObjCMessageExpr *NewMsg = nullptr;
1345
switch (OldMsg->getReceiverKind()) {
1346
case ObjCMessageExpr::Class:
1347
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1348
OldMsg->getValueKind(),
1349
OldMsg->getLeftLoc(),
1350
OldMsg->getClassReceiverTypeInfo(),
1351
OldMsg->getSelector(),
1352
SelLocs,
1353
OldMsg->getMethodDecl(),
1354
Args,
1355
OldMsg->getRightLoc(),
1356
OldMsg->isImplicit());
1357
break;
1358
1359
case ObjCMessageExpr::Instance:
1360
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1361
OldMsg->getValueKind(),
1362
OldMsg->getLeftLoc(),
1363
Base,
1364
OldMsg->getSelector(),
1365
SelLocs,
1366
OldMsg->getMethodDecl(),
1367
Args,
1368
OldMsg->getRightLoc(),
1369
OldMsg->isImplicit());
1370
break;
1371
1372
case ObjCMessageExpr::SuperClass:
1373
case ObjCMessageExpr::SuperInstance:
1374
NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),
1375
OldMsg->getValueKind(),
1376
OldMsg->getLeftLoc(),
1377
OldMsg->getSuperLoc(),
1378
OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,
1379
OldMsg->getSuperType(),
1380
OldMsg->getSelector(),
1381
SelLocs,
1382
OldMsg->getMethodDecl(),
1383
Args,
1384
OldMsg->getRightLoc(),
1385
OldMsg->isImplicit());
1386
break;
1387
}
1388
1389
Stmt *Replacement = SynthMessageExpr(NewMsg);
1390
ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);
1391
return Replacement;
1392
}
1393
1394
/// SynthCountByEnumWithState - To print:
1395
/// ((unsigned int (*)
1396
/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
1397
/// (void *)objc_msgSend)((id)l_collection,
1398
/// sel_registerName(
1399
/// "countByEnumeratingWithState:objects:count:"),
1400
/// &enumState,
1401
/// (id *)__rw_items, (unsigned int)16)
1402
///
1403
void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1404
buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
1405
"id *, unsigned int))(void *)objc_msgSend)";
1406
buf += "\n\t\t";
1407
buf += "((id)l_collection,\n\t\t";
1408
buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1409
buf += "\n\t\t";
1410
buf += "&enumState, "
1411
"(id *)__rw_items, (unsigned int)16)";
1412
}
1413
1414
/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
1415
/// statement to exit to its outer synthesized loop.
1416
///
1417
Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {
1418
if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1419
return S;
1420
// replace break with goto __break_label
1421
std::string buf;
1422
1423
SourceLocation startLoc = S->getBeginLoc();
1424
buf = "goto __break_label_";
1425
buf += utostr(ObjCBcLabelNo.back());
1426
ReplaceText(startLoc, strlen("break"), buf);
1427
1428
return nullptr;
1429
}
1430
1431
/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
1432
/// statement to continue with its inner synthesized loop.
1433
///
1434
Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {
1435
if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1436
return S;
1437
// replace continue with goto __continue_label
1438
std::string buf;
1439
1440
SourceLocation startLoc = S->getBeginLoc();
1441
buf = "goto __continue_label_";
1442
buf += utostr(ObjCBcLabelNo.back());
1443
ReplaceText(startLoc, strlen("continue"), buf);
1444
1445
return nullptr;
1446
}
1447
1448
/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
1449
/// It rewrites:
1450
/// for ( type elem in collection) { stmts; }
1451
1452
/// Into:
1453
/// {
1454
/// type elem;
1455
/// struct __objcFastEnumerationState enumState = { 0 };
1456
/// id __rw_items[16];
1457
/// id l_collection = (id)collection;
1458
/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1459
/// objects:__rw_items count:16];
1460
/// if (limit) {
1461
/// unsigned long startMutations = *enumState.mutationsPtr;
1462
/// do {
1463
/// unsigned long counter = 0;
1464
/// do {
1465
/// if (startMutations != *enumState.mutationsPtr)
1466
/// objc_enumerationMutation(l_collection);
1467
/// elem = (type)enumState.itemsPtr[counter++];
1468
/// stmts;
1469
/// __continue_label: ;
1470
/// } while (counter < limit);
1471
/// } while (limit = [l_collection countByEnumeratingWithState:&enumState
1472
/// objects:__rw_items count:16]);
1473
/// elem = nil;
1474
/// __break_label: ;
1475
/// }
1476
/// else
1477
/// elem = nil;
1478
/// }
1479
///
1480
Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
1481
SourceLocation OrigEnd) {
1482
assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
1483
assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
1484
"ObjCForCollectionStmt Statement stack mismatch");
1485
assert(!ObjCBcLabelNo.empty() &&
1486
"ObjCForCollectionStmt - Label No stack empty");
1487
1488
SourceLocation startLoc = S->getBeginLoc();
1489
const char *startBuf = SM->getCharacterData(startLoc);
1490
StringRef elementName;
1491
std::string elementTypeAsString;
1492
std::string buf;
1493
buf = "\n{\n\t";
1494
if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
1495
// type elem;
1496
NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1497
QualType ElementType = cast<ValueDecl>(D)->getType();
1498
if (ElementType->isObjCQualifiedIdType() ||
1499
ElementType->isObjCQualifiedInterfaceType())
1500
// Simply use 'id' for all qualified types.
1501
elementTypeAsString = "id";
1502
else
1503
elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());
1504
buf += elementTypeAsString;
1505
buf += " ";
1506
elementName = D->getName();
1507
buf += elementName;
1508
buf += ";\n\t";
1509
}
1510
else {
1511
DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
1512
elementName = DR->getDecl()->getName();
1513
ValueDecl *VD = DR->getDecl();
1514
if (VD->getType()->isObjCQualifiedIdType() ||
1515
VD->getType()->isObjCQualifiedInterfaceType())
1516
// Simply use 'id' for all qualified types.
1517
elementTypeAsString = "id";
1518
else
1519
elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());
1520
}
1521
1522
// struct __objcFastEnumerationState enumState = { 0 };
1523
buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
1524
// id __rw_items[16];
1525
buf += "id __rw_items[16];\n\t";
1526
// id l_collection = (id)
1527
buf += "id l_collection = (id)";
1528
// Find start location of 'collection' the hard way!
1529
const char *startCollectionBuf = startBuf;
1530
startCollectionBuf += 3; // skip 'for'
1531
startCollectionBuf = strchr(startCollectionBuf, '(');
1532
startCollectionBuf++; // skip '('
1533
// find 'in' and skip it.
1534
while (*startCollectionBuf != ' ' ||
1535
*(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
1536
(*(startCollectionBuf+3) != ' ' &&
1537
*(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
1538
startCollectionBuf++;
1539
startCollectionBuf += 3;
1540
1541
// Replace: "for (type element in" with string constructed thus far.
1542
ReplaceText(startLoc, startCollectionBuf - startBuf, buf);
1543
// Replace ')' in for '(' type elem in collection ')' with ';'
1544
SourceLocation rightParenLoc = S->getRParenLoc();
1545
const char *rparenBuf = SM->getCharacterData(rightParenLoc);
1546
SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);
1547
buf = ";\n\t";
1548
1549
// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1550
// objects:__rw_items count:16];
1551
// which is synthesized into:
1552
// unsigned int limit =
1553
// ((unsigned int (*)
1554
// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
1555
// (void *)objc_msgSend)((id)l_collection,
1556
// sel_registerName(
1557
// "countByEnumeratingWithState:objects:count:"),
1558
// (struct __objcFastEnumerationState *)&state,
1559
// (id *)__rw_items, (unsigned int)16);
1560
buf += "unsigned long limit =\n\t\t";
1561
SynthCountByEnumWithState(buf);
1562
buf += ";\n\t";
1563
/// if (limit) {
1564
/// unsigned long startMutations = *enumState.mutationsPtr;
1565
/// do {
1566
/// unsigned long counter = 0;
1567
/// do {
1568
/// if (startMutations != *enumState.mutationsPtr)
1569
/// objc_enumerationMutation(l_collection);
1570
/// elem = (type)enumState.itemsPtr[counter++];
1571
buf += "if (limit) {\n\t";
1572
buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1573
buf += "do {\n\t\t";
1574
buf += "unsigned long counter = 0;\n\t\t";
1575
buf += "do {\n\t\t\t";
1576
buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1577
buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
1578
buf += elementName;
1579
buf += " = (";
1580
buf += elementTypeAsString;
1581
buf += ")enumState.itemsPtr[counter++];";
1582
// Replace ')' in for '(' type elem in collection ')' with all of these.
1583
ReplaceText(lparenLoc, 1, buf);
1584
1585
/// __continue_label: ;
1586
/// } while (counter < limit);
1587
/// } while (limit = [l_collection countByEnumeratingWithState:&enumState
1588
/// objects:__rw_items count:16]);
1589
/// elem = nil;
1590
/// __break_label: ;
1591
/// }
1592
/// else
1593
/// elem = nil;
1594
/// }
1595
///
1596
buf = ";\n\t";
1597
buf += "__continue_label_";
1598
buf += utostr(ObjCBcLabelNo.back());
1599
buf += ": ;";
1600
buf += "\n\t\t";
1601
buf += "} while (counter < limit);\n\t";
1602
buf += "} while (limit = ";
1603
SynthCountByEnumWithState(buf);
1604
buf += ");\n\t";
1605
buf += elementName;
1606
buf += " = ((";
1607
buf += elementTypeAsString;
1608
buf += ")0);\n\t";
1609
buf += "__break_label_";
1610
buf += utostr(ObjCBcLabelNo.back());
1611
buf += ": ;\n\t";
1612
buf += "}\n\t";
1613
buf += "else\n\t\t";
1614
buf += elementName;
1615
buf += " = ((";
1616
buf += elementTypeAsString;
1617
buf += ")0);\n\t";
1618
buf += "}\n";
1619
1620
// Insert all these *after* the statement body.
1621
// FIXME: If this should support Obj-C++, support CXXTryStmt
1622
if (isa<CompoundStmt>(S->getBody())) {
1623
SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);
1624
InsertText(endBodyLoc, buf);
1625
} else {
1626
/* Need to treat single statements specially. For example:
1627
*
1628
* for (A *a in b) if (stuff()) break;
1629
* for (A *a in b) xxxyy;
1630
*
1631
* The following code simply scans ahead to the semi to find the actual end.
1632
*/
1633
const char *stmtBuf = SM->getCharacterData(OrigEnd);
1634
const char *semiBuf = strchr(stmtBuf, ';');
1635
assert(semiBuf && "Can't find ';'");
1636
SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);
1637
InsertText(endBodyLoc, buf);
1638
}
1639
Stmts.pop_back();
1640
ObjCBcLabelNo.pop_back();
1641
return nullptr;
1642
}
1643
1644
/// RewriteObjCSynchronizedStmt -
1645
/// This routine rewrites @synchronized(expr) stmt;
1646
/// into:
1647
/// objc_sync_enter(expr);
1648
/// @try stmt @finally { objc_sync_exit(expr); }
1649
///
1650
Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
1651
// Get the start location and compute the semi location.
1652
SourceLocation startLoc = S->getBeginLoc();
1653
const char *startBuf = SM->getCharacterData(startLoc);
1654
1655
assert((*startBuf == '@') && "bogus @synchronized location");
1656
1657
std::string buf;
1658
buf = "objc_sync_enter((id)";
1659
const char *lparenBuf = startBuf;
1660
while (*lparenBuf != '(') lparenBuf++;
1661
ReplaceText(startLoc, lparenBuf-startBuf+1, buf);
1662
// We can't use S->getSynchExpr()->getEndLoc() to find the end location, since
1663
// the sync expression is typically a message expression that's already
1664
// been rewritten! (which implies the SourceLocation's are invalid).
1665
SourceLocation endLoc = S->getSynchBody()->getBeginLoc();
1666
const char *endBuf = SM->getCharacterData(endLoc);
1667
while (*endBuf != ')') endBuf--;
1668
SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf);
1669
buf = ");\n";
1670
// declare a new scope with two variables, _stack and _rethrow.
1671
buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1672
buf += "int buf[18/*32-bit i386*/];\n";
1673
buf += "char *pointers[4];} _stack;\n";
1674
buf += "id volatile _rethrow = 0;\n";
1675
buf += "objc_exception_try_enter(&_stack);\n";
1676
buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1677
ReplaceText(rparenLoc, 1, buf);
1678
startLoc = S->getSynchBody()->getEndLoc();
1679
startBuf = SM->getCharacterData(startLoc);
1680
1681
assert((*startBuf == '}') && "bogus @synchronized block");
1682
SourceLocation lastCurlyLoc = startLoc;
1683
buf = "}\nelse {\n";
1684
buf += " _rethrow = objc_exception_extract(&_stack);\n";
1685
buf += "}\n";
1686
buf += "{ /* implicit finally clause */\n";
1687
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1688
1689
std::string syncBuf;
1690
syncBuf += " objc_sync_exit(";
1691
1692
Expr *syncExpr = S->getSynchExpr();
1693
CastKind CK = syncExpr->getType()->isObjCObjectPointerType()
1694
? CK_BitCast :
1695
syncExpr->getType()->isBlockPointerType()
1696
? CK_BlockPointerToObjCPointerCast
1697
: CK_CPointerToObjCPointerCast;
1698
syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
1699
CK, syncExpr);
1700
std::string syncExprBufS;
1701
llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1702
assert(syncExpr != nullptr && "Expected non-null Expr");
1703
syncExpr->printPretty(syncExprBuf, nullptr, PrintingPolicy(LangOpts));
1704
syncBuf += syncExprBuf.str();
1705
syncBuf += ");";
1706
1707
buf += syncBuf;
1708
buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1709
buf += "}\n";
1710
buf += "}";
1711
1712
ReplaceText(lastCurlyLoc, 1, buf);
1713
1714
bool hasReturns = false;
1715
HasReturnStmts(S->getSynchBody(), hasReturns);
1716
if (hasReturns)
1717
RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
1718
1719
return nullptr;
1720
}
1721
1722
void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
1723
{
1724
// Perform a bottom up traversal of all children.
1725
for (Stmt *SubStmt : S->children())
1726
if (SubStmt)
1727
WarnAboutReturnGotoStmts(SubStmt);
1728
1729
if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1730
Diags.Report(Context->getFullLoc(S->getBeginLoc()),
1731
TryFinallyContainsReturnDiag);
1732
}
1733
}
1734
1735
void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
1736
{
1737
// Perform a bottom up traversal of all children.
1738
for (Stmt *SubStmt : S->children())
1739
if (SubStmt)
1740
HasReturnStmts(SubStmt, hasReturns);
1741
1742
if (isa<ReturnStmt>(S))
1743
hasReturns = true;
1744
}
1745
1746
void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
1747
// Perform a bottom up traversal of all children.
1748
for (Stmt *SubStmt : S->children())
1749
if (SubStmt) {
1750
RewriteTryReturnStmts(SubStmt);
1751
}
1752
if (isa<ReturnStmt>(S)) {
1753
SourceLocation startLoc = S->getBeginLoc();
1754
const char *startBuf = SM->getCharacterData(startLoc);
1755
const char *semiBuf = strchr(startBuf, ';');
1756
assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
1757
SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
1758
1759
std::string buf;
1760
buf = "{ objc_exception_try_exit(&_stack); return";
1761
1762
ReplaceText(startLoc, 6, buf);
1763
InsertText(onePastSemiLoc, "}");
1764
}
1765
}
1766
1767
void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
1768
// Perform a bottom up traversal of all children.
1769
for (Stmt *SubStmt : S->children())
1770
if (SubStmt) {
1771
RewriteSyncReturnStmts(SubStmt, syncExitBuf);
1772
}
1773
if (isa<ReturnStmt>(S)) {
1774
SourceLocation startLoc = S->getBeginLoc();
1775
const char *startBuf = SM->getCharacterData(startLoc);
1776
1777
const char *semiBuf = strchr(startBuf, ';');
1778
assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
1779
SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);
1780
1781
std::string buf;
1782
buf = "{ objc_exception_try_exit(&_stack);";
1783
buf += syncExitBuf;
1784
buf += " return";
1785
1786
ReplaceText(startLoc, 6, buf);
1787
InsertText(onePastSemiLoc, "}");
1788
}
1789
}
1790
1791
Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
1792
// Get the start location and compute the semi location.
1793
SourceLocation startLoc = S->getBeginLoc();
1794
const char *startBuf = SM->getCharacterData(startLoc);
1795
1796
assert((*startBuf == '@') && "bogus @try location");
1797
1798
std::string buf;
1799
// declare a new scope with two variables, _stack and _rethrow.
1800
buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
1801
buf += "int buf[18/*32-bit i386*/];\n";
1802
buf += "char *pointers[4];} _stack;\n";
1803
buf += "id volatile _rethrow = 0;\n";
1804
buf += "objc_exception_try_enter(&_stack);\n";
1805
buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1806
1807
ReplaceText(startLoc, 4, buf);
1808
1809
startLoc = S->getTryBody()->getEndLoc();
1810
startBuf = SM->getCharacterData(startLoc);
1811
1812
assert((*startBuf == '}') && "bogus @try block");
1813
1814
SourceLocation lastCurlyLoc = startLoc;
1815
if (S->getNumCatchStmts()) {
1816
startLoc = startLoc.getLocWithOffset(1);
1817
buf = " /* @catch begin */ else {\n";
1818
buf += " id _caught = objc_exception_extract(&_stack);\n";
1819
buf += " objc_exception_try_enter (&_stack);\n";
1820
buf += " if (_setjmp(_stack.buf))\n";
1821
buf += " _rethrow = objc_exception_extract(&_stack);\n";
1822
buf += " else { /* @catch continue */";
1823
1824
InsertText(startLoc, buf);
1825
} else { /* no catch list */
1826
buf = "}\nelse {\n";
1827
buf += " _rethrow = objc_exception_extract(&_stack);\n";
1828
buf += "}";
1829
ReplaceText(lastCurlyLoc, 1, buf);
1830
}
1831
Stmt *lastCatchBody = nullptr;
1832
for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {
1833
ObjCAtCatchStmt *Catch = S->getCatchStmt(I);
1834
VarDecl *catchDecl = Catch->getCatchParamDecl();
1835
1836
if (I == 0)
1837
buf = "if ("; // we are generating code for the first catch clause
1838
else
1839
buf = "else if (";
1840
startLoc = Catch->getBeginLoc();
1841
startBuf = SM->getCharacterData(startLoc);
1842
1843
assert((*startBuf == '@') && "bogus @catch location");
1844
1845
const char *lParenLoc = strchr(startBuf, '(');
1846
1847
if (Catch->hasEllipsis()) {
1848
// Now rewrite the body...
1849
lastCatchBody = Catch->getCatchBody();
1850
SourceLocation bodyLoc = lastCatchBody->getBeginLoc();
1851
const char *bodyBuf = SM->getCharacterData(bodyLoc);
1852
assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' &&
1853
"bogus @catch paren location");
1854
assert((*bodyBuf == '{') && "bogus @catch body location");
1855
1856
buf += "1) { id _tmp = _caught;";
1857
Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
1858
} else if (catchDecl) {
1859
QualType t = catchDecl->getType();
1860
if (t == Context->getObjCIdType()) {
1861
buf += "1) { ";
1862
ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1863
} else if (const ObjCObjectPointerType *Ptr =
1864
t->getAs<ObjCObjectPointerType>()) {
1865
// Should be a pointer to a class.
1866
ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();
1867
if (IDecl) {
1868
buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
1869
buf += IDecl->getNameAsString();
1870
buf += "\"), (struct objc_object *)_caught)) { ";
1871
ReplaceText(startLoc, lParenLoc-startBuf+1, buf);
1872
}
1873
}
1874
// Now rewrite the body...
1875
lastCatchBody = Catch->getCatchBody();
1876
SourceLocation rParenLoc = Catch->getRParenLoc();
1877
SourceLocation bodyLoc = lastCatchBody->getBeginLoc();
1878
const char *bodyBuf = SM->getCharacterData(bodyLoc);
1879
const char *rParenBuf = SM->getCharacterData(rParenLoc);
1880
assert((*rParenBuf == ')') && "bogus @catch paren location");
1881
assert((*bodyBuf == '{') && "bogus @catch body location");
1882
1883
// Here we replace ") {" with "= _caught;" (which initializes and
1884
// declares the @catch parameter).
1885
ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;");
1886
} else {
1887
llvm_unreachable("@catch rewrite bug");
1888
}
1889
}
1890
// Complete the catch list...
1891
if (lastCatchBody) {
1892
SourceLocation bodyLoc = lastCatchBody->getEndLoc();
1893
assert(*SM->getCharacterData(bodyLoc) == '}' &&
1894
"bogus @catch body location");
1895
1896
// Insert the last (implicit) else clause *before* the right curly brace.
1897
bodyLoc = bodyLoc.getLocWithOffset(-1);
1898
buf = "} /* last catch end */\n";
1899
buf += "else {\n";
1900
buf += " _rethrow = _caught;\n";
1901
buf += " objc_exception_try_exit(&_stack);\n";
1902
buf += "} } /* @catch end */\n";
1903
if (!S->getFinallyStmt())
1904
buf += "}\n";
1905
InsertText(bodyLoc, buf);
1906
1907
// Set lastCurlyLoc
1908
lastCurlyLoc = lastCatchBody->getEndLoc();
1909
}
1910
if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
1911
startLoc = finalStmt->getBeginLoc();
1912
startBuf = SM->getCharacterData(startLoc);
1913
assert((*startBuf == '@') && "bogus @finally start");
1914
1915
ReplaceText(startLoc, 8, "/* @finally */");
1916
1917
Stmt *body = finalStmt->getFinallyBody();
1918
SourceLocation startLoc = body->getBeginLoc();
1919
SourceLocation endLoc = body->getEndLoc();
1920
assert(*SM->getCharacterData(startLoc) == '{' &&
1921
"bogus @finally body location");
1922
assert(*SM->getCharacterData(endLoc) == '}' &&
1923
"bogus @finally body location");
1924
1925
startLoc = startLoc.getLocWithOffset(1);
1926
InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n");
1927
endLoc = endLoc.getLocWithOffset(-1);
1928
InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n");
1929
1930
// Set lastCurlyLoc
1931
lastCurlyLoc = body->getEndLoc();
1932
1933
// Now check for any return/continue/go statements within the @try.
1934
WarnAboutReturnGotoStmts(S->getTryBody());
1935
} else { /* no finally clause - make sure we synthesize an implicit one */
1936
buf = "{ /* implicit finally clause */\n";
1937
buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1938
buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
1939
buf += "}";
1940
ReplaceText(lastCurlyLoc, 1, buf);
1941
1942
// Now check for any return/continue/go statements within the @try.
1943
// The implicit finally clause won't called if the @try contains any
1944
// jump statements.
1945
bool hasReturns = false;
1946
HasReturnStmts(S->getTryBody(), hasReturns);
1947
if (hasReturns)
1948
RewriteTryReturnStmts(S->getTryBody());
1949
}
1950
// Now emit the final closing curly brace...
1951
lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1);
1952
InsertText(lastCurlyLoc, " } /* @try scope end */\n");
1953
return nullptr;
1954
}
1955
1956
// This can't be done with ReplaceStmt(S, ThrowExpr), since
1957
// the throw expression is typically a message expression that's already
1958
// been rewritten! (which implies the SourceLocation's are invalid).
1959
Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
1960
// Get the start location and compute the semi location.
1961
SourceLocation startLoc = S->getBeginLoc();
1962
const char *startBuf = SM->getCharacterData(startLoc);
1963
1964
assert((*startBuf == '@') && "bogus @throw location");
1965
1966
std::string buf;
1967
/* void objc_exception_throw(id) __attribute__((noreturn)); */
1968
if (S->getThrowExpr())
1969
buf = "objc_exception_throw(";
1970
else // add an implicit argument
1971
buf = "objc_exception_throw(_caught";
1972
1973
// handle "@ throw" correctly.
1974
const char *wBuf = strchr(startBuf, 'w');
1975
assert((*wBuf == 'w') && "@throw: can't find 'w'");
1976
ReplaceText(startLoc, wBuf-startBuf+1, buf);
1977
1978
const char *semiBuf = strchr(startBuf, ';');
1979
assert((*semiBuf == ';') && "@throw: can't find ';'");
1980
SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);
1981
ReplaceText(semiLoc, 1, ");");
1982
return nullptr;
1983
}
1984
1985
Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
1986
// Create a new string expression.
1987
std::string StrEncoding;
1988
Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
1989
Expr *Replacement = getStringLiteral(StrEncoding);
1990
ReplaceStmt(Exp, Replacement);
1991
1992
// Replace this subexpr in the parent.
1993
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
1994
return Replacement;
1995
}
1996
1997
Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
1998
if (!SelGetUidFunctionDecl)
1999
SynthSelGetUidFunctionDecl();
2000
assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
2001
// Create a call to sel_registerName("selName").
2002
SmallVector<Expr*, 8> SelExprs;
2003
SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
2004
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2005
SelExprs);
2006
ReplaceStmt(Exp, SelExp);
2007
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
2008
return SelExp;
2009
}
2010
2011
CallExpr *
2012
RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,
2013
ArrayRef<Expr *> Args,
2014
SourceLocation StartLoc,
2015
SourceLocation EndLoc) {
2016
// Get the type, we will need to reference it in a couple spots.
2017
QualType msgSendType = FD->getType();
2018
2019
// Create a reference to the objc_msgSend() declaration.
2020
DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,
2021
VK_LValue, SourceLocation());
2022
2023
// Now, we cast the reference to a pointer to the objc_msgSend type.
2024
QualType pToFunc = Context->getPointerType(msgSendType);
2025
ImplicitCastExpr *ICE =
2026
ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,
2027
DRE, nullptr, VK_PRValue, FPOptionsOverride());
2028
2029
const auto *FT = msgSendType->castAs<FunctionType>();
2030
2031
CallExpr *Exp =
2032
CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),
2033
VK_PRValue, EndLoc, FPOptionsOverride());
2034
return Exp;
2035
}
2036
2037
static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
2038
const char *&startRef, const char *&endRef) {
2039
while (startBuf < endBuf) {
2040
if (*startBuf == '<')
2041
startRef = startBuf; // mark the start.
2042
if (*startBuf == '>') {
2043
if (startRef && *startRef == '<') {
2044
endRef = startBuf; // mark the end.
2045
return true;
2046
}
2047
return false;
2048
}
2049
startBuf++;
2050
}
2051
return false;
2052
}
2053
2054
static void scanToNextArgument(const char *&argRef) {
2055
int angle = 0;
2056
while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
2057
if (*argRef == '<')
2058
angle++;
2059
else if (*argRef == '>')
2060
angle--;
2061
argRef++;
2062
}
2063
assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
2064
}
2065
2066
bool RewriteObjC::needToScanForQualifiers(QualType T) {
2067
if (T->isObjCQualifiedIdType())
2068
return true;
2069
if (const PointerType *PT = T->getAs<PointerType>()) {
2070
if (PT->getPointeeType()->isObjCQualifiedIdType())
2071
return true;
2072
}
2073
if (T->isObjCObjectPointerType()) {
2074
T = T->getPointeeType();
2075
return T->isObjCQualifiedInterfaceType();
2076
}
2077
if (T->isArrayType()) {
2078
QualType ElemTy = Context->getBaseElementType(T);
2079
return needToScanForQualifiers(ElemTy);
2080
}
2081
return false;
2082
}
2083
2084
void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
2085
QualType Type = E->getType();
2086
if (needToScanForQualifiers(Type)) {
2087
SourceLocation Loc, EndLoc;
2088
2089
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
2090
Loc = ECE->getLParenLoc();
2091
EndLoc = ECE->getRParenLoc();
2092
} else {
2093
Loc = E->getBeginLoc();
2094
EndLoc = E->getEndLoc();
2095
}
2096
// This will defend against trying to rewrite synthesized expressions.
2097
if (Loc.isInvalid() || EndLoc.isInvalid())
2098
return;
2099
2100
const char *startBuf = SM->getCharacterData(Loc);
2101
const char *endBuf = SM->getCharacterData(EndLoc);
2102
const char *startRef = nullptr, *endRef = nullptr;
2103
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2104
// Get the locations of the startRef, endRef.
2105
SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);
2106
SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);
2107
// Comment out the protocol references.
2108
InsertText(LessLoc, "/*");
2109
InsertText(GreaterLoc, "*/");
2110
}
2111
}
2112
}
2113
2114
void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
2115
SourceLocation Loc;
2116
QualType Type;
2117
const FunctionProtoType *proto = nullptr;
2118
if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2119
Loc = VD->getLocation();
2120
Type = VD->getType();
2121
}
2122
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2123
Loc = FD->getLocation();
2124
// Check for ObjC 'id' and class types that have been adorned with protocol
2125
// information (id<p>, C<p>*). The protocol references need to be rewritten!
2126
const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2127
assert(funcType && "missing function type");
2128
proto = dyn_cast<FunctionProtoType>(funcType);
2129
if (!proto)
2130
return;
2131
Type = proto->getReturnType();
2132
}
2133
else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2134
Loc = FD->getLocation();
2135
Type = FD->getType();
2136
}
2137
else
2138
return;
2139
2140
if (needToScanForQualifiers(Type)) {
2141
// Since types are unique, we need to scan the buffer.
2142
2143
const char *endBuf = SM->getCharacterData(Loc);
2144
const char *startBuf = endBuf;
2145
while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
2146
startBuf--; // scan backward (from the decl location) for return type.
2147
const char *startRef = nullptr, *endRef = nullptr;
2148
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2149
// Get the locations of the startRef, endRef.
2150
SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);
2151
SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);
2152
// Comment out the protocol references.
2153
InsertText(LessLoc, "/*");
2154
InsertText(GreaterLoc, "*/");
2155
}
2156
}
2157
if (!proto)
2158
return; // most likely, was a variable
2159
// Now check arguments.
2160
const char *startBuf = SM->getCharacterData(Loc);
2161
const char *startFuncBuf = startBuf;
2162
for (unsigned i = 0; i < proto->getNumParams(); i++) {
2163
if (needToScanForQualifiers(proto->getParamType(i))) {
2164
// Since types are unique, we need to scan the buffer.
2165
2166
const char *endBuf = startBuf;
2167
// scan forward (from the decl location) for argument types.
2168
scanToNextArgument(endBuf);
2169
const char *startRef = nullptr, *endRef = nullptr;
2170
if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2171
// Get the locations of the startRef, endRef.
2172
SourceLocation LessLoc =
2173
Loc.getLocWithOffset(startRef-startFuncBuf);
2174
SourceLocation GreaterLoc =
2175
Loc.getLocWithOffset(endRef-startFuncBuf+1);
2176
// Comment out the protocol references.
2177
InsertText(LessLoc, "/*");
2178
InsertText(GreaterLoc, "*/");
2179
}
2180
startBuf = ++endBuf;
2181
}
2182
else {
2183
// If the function name is derived from a macro expansion, then the
2184
// argument buffer will not follow the name. Need to speak with Chris.
2185
while (*startBuf && *startBuf != ')' && *startBuf != ',')
2186
startBuf++; // scan forward (from the decl location) for argument types.
2187
startBuf++;
2188
}
2189
}
2190
}
2191
2192
void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) {
2193
QualType QT = ND->getType();
2194
const Type* TypePtr = QT->getAs<Type>();
2195
if (!isa<TypeOfExprType>(TypePtr))
2196
return;
2197
while (isa<TypeOfExprType>(TypePtr)) {
2198
const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
2199
QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
2200
TypePtr = QT->getAs<Type>();
2201
}
2202
// FIXME. This will not work for multiple declarators; as in:
2203
// __typeof__(a) b,c,d;
2204
std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));
2205
SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
2206
const char *startBuf = SM->getCharacterData(DeclLoc);
2207
if (ND->getInit()) {
2208
std::string Name(ND->getNameAsString());
2209
TypeAsString += " " + Name + " = ";
2210
Expr *E = ND->getInit();
2211
SourceLocation startLoc;
2212
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
2213
startLoc = ECE->getLParenLoc();
2214
else
2215
startLoc = E->getBeginLoc();
2216
startLoc = SM->getExpansionLoc(startLoc);
2217
const char *endBuf = SM->getCharacterData(startLoc);
2218
ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2219
}
2220
else {
2221
SourceLocation X = ND->getEndLoc();
2222
X = SM->getExpansionLoc(X);
2223
const char *endBuf = SM->getCharacterData(X);
2224
ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);
2225
}
2226
}
2227
2228
// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
2229
void RewriteObjC::SynthSelGetUidFunctionDecl() {
2230
IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
2231
SmallVector<QualType, 16> ArgTys;
2232
ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2233
QualType getFuncType =
2234
getSimpleFunctionType(Context->getObjCSelType(), ArgTys);
2235
SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2236
SourceLocation(),
2237
SourceLocation(),
2238
SelGetUidIdent, getFuncType,
2239
nullptr, SC_Extern);
2240
}
2241
2242
void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
2243
// declared in <objc/objc.h>
2244
if (FD->getIdentifier() &&
2245
FD->getName() == "sel_registerName") {
2246
SelGetUidFunctionDecl = FD;
2247
return;
2248
}
2249
RewriteObjCQualifiedInterfaceTypes(FD);
2250
}
2251
2252
void RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {
2253
std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
2254
const char *argPtr = TypeString.c_str();
2255
if (!strchr(argPtr, '^')) {
2256
Str += TypeString;
2257
return;
2258
}
2259
while (*argPtr) {
2260
Str += (*argPtr == '^' ? '*' : *argPtr);
2261
argPtr++;
2262
}
2263
}
2264
2265
// FIXME. Consolidate this routine with RewriteBlockPointerType.
2266
void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,
2267
ValueDecl *VD) {
2268
QualType Type = VD->getType();
2269
std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));
2270
const char *argPtr = TypeString.c_str();
2271
int paren = 0;
2272
while (*argPtr) {
2273
switch (*argPtr) {
2274
case '(':
2275
Str += *argPtr;
2276
paren++;
2277
break;
2278
case ')':
2279
Str += *argPtr;
2280
paren--;
2281
break;
2282
case '^':
2283
Str += '*';
2284
if (paren == 1)
2285
Str += VD->getNameAsString();
2286
break;
2287
default:
2288
Str += *argPtr;
2289
break;
2290
}
2291
argPtr++;
2292
}
2293
}
2294
2295
void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
2296
SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
2297
const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2298
const FunctionProtoType *proto = dyn_cast_or_null<FunctionProtoType>(funcType);
2299
if (!proto)
2300
return;
2301
QualType Type = proto->getReturnType();
2302
std::string FdStr = Type.getAsString(Context->getPrintingPolicy());
2303
FdStr += " ";
2304
FdStr += FD->getName();
2305
FdStr += "(";
2306
unsigned numArgs = proto->getNumParams();
2307
for (unsigned i = 0; i < numArgs; i++) {
2308
QualType ArgType = proto->getParamType(i);
2309
RewriteBlockPointerType(FdStr, ArgType);
2310
if (i+1 < numArgs)
2311
FdStr += ", ";
2312
}
2313
FdStr += ");\n";
2314
InsertText(FunLocStart, FdStr);
2315
CurFunctionDeclToDeclareForBlock = nullptr;
2316
}
2317
2318
// SynthSuperConstructorFunctionDecl - id objc_super(id obj, id super);
2319
void RewriteObjC::SynthSuperConstructorFunctionDecl() {
2320
if (SuperConstructorFunctionDecl)
2321
return;
2322
IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
2323
SmallVector<QualType, 16> ArgTys;
2324
QualType argT = Context->getObjCIdType();
2325
assert(!argT.isNull() && "Can't find 'id' type");
2326
ArgTys.push_back(argT);
2327
ArgTys.push_back(argT);
2328
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2329
ArgTys);
2330
SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2331
SourceLocation(),
2332
SourceLocation(),
2333
msgSendIdent, msgSendType,
2334
nullptr, SC_Extern);
2335
}
2336
2337
// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
2338
void RewriteObjC::SynthMsgSendFunctionDecl() {
2339
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
2340
SmallVector<QualType, 16> ArgTys;
2341
QualType argT = Context->getObjCIdType();
2342
assert(!argT.isNull() && "Can't find 'id' type");
2343
ArgTys.push_back(argT);
2344
argT = Context->getObjCSelType();
2345
assert(!argT.isNull() && "Can't find 'SEL' type");
2346
ArgTys.push_back(argT);
2347
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2348
ArgTys, /*variadic=*/true);
2349
MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2350
SourceLocation(),
2351
SourceLocation(),
2352
msgSendIdent, msgSendType,
2353
nullptr, SC_Extern);
2354
}
2355
2356
// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
2357
void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2358
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
2359
SmallVector<QualType, 16> ArgTys;
2360
RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
2361
SourceLocation(), SourceLocation(),
2362
&Context->Idents.get("objc_super"));
2363
QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
2364
assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
2365
ArgTys.push_back(argT);
2366
argT = Context->getObjCSelType();
2367
assert(!argT.isNull() && "Can't find 'SEL' type");
2368
ArgTys.push_back(argT);
2369
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2370
ArgTys, /*variadic=*/true);
2371
MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2372
SourceLocation(),
2373
SourceLocation(),
2374
msgSendIdent, msgSendType,
2375
nullptr, SC_Extern);
2376
}
2377
2378
// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
2379
void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2380
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
2381
SmallVector<QualType, 16> ArgTys;
2382
QualType argT = Context->getObjCIdType();
2383
assert(!argT.isNull() && "Can't find 'id' type");
2384
ArgTys.push_back(argT);
2385
argT = Context->getObjCSelType();
2386
assert(!argT.isNull() && "Can't find 'SEL' type");
2387
ArgTys.push_back(argT);
2388
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2389
ArgTys, /*variadic=*/true);
2390
MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2391
SourceLocation(),
2392
SourceLocation(),
2393
msgSendIdent, msgSendType,
2394
nullptr, SC_Extern);
2395
}
2396
2397
// SynthMsgSendSuperStretFunctionDecl -
2398
// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
2399
void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2400
IdentifierInfo *msgSendIdent =
2401
&Context->Idents.get("objc_msgSendSuper_stret");
2402
SmallVector<QualType, 16> ArgTys;
2403
RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
2404
SourceLocation(), SourceLocation(),
2405
&Context->Idents.get("objc_super"));
2406
QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
2407
assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
2408
ArgTys.push_back(argT);
2409
argT = Context->getObjCSelType();
2410
assert(!argT.isNull() && "Can't find 'SEL' type");
2411
ArgTys.push_back(argT);
2412
QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),
2413
ArgTys, /*variadic=*/true);
2414
MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2415
SourceLocation(),
2416
SourceLocation(),
2417
msgSendIdent,
2418
msgSendType, nullptr,
2419
SC_Extern);
2420
}
2421
2422
// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
2423
void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2424
IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
2425
SmallVector<QualType, 16> ArgTys;
2426
QualType argT = Context->getObjCIdType();
2427
assert(!argT.isNull() && "Can't find 'id' type");
2428
ArgTys.push_back(argT);
2429
argT = Context->getObjCSelType();
2430
assert(!argT.isNull() && "Can't find 'SEL' type");
2431
ArgTys.push_back(argT);
2432
QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,
2433
ArgTys, /*variadic=*/true);
2434
MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2435
SourceLocation(),
2436
SourceLocation(),
2437
msgSendIdent, msgSendType,
2438
nullptr, SC_Extern);
2439
}
2440
2441
// SynthGetClassFunctionDecl - id objc_getClass(const char *name);
2442
void RewriteObjC::SynthGetClassFunctionDecl() {
2443
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
2444
SmallVector<QualType, 16> ArgTys;
2445
ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2446
QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
2447
ArgTys);
2448
GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2449
SourceLocation(),
2450
SourceLocation(),
2451
getClassIdent, getClassType,
2452
nullptr, SC_Extern);
2453
}
2454
2455
// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);
2456
void RewriteObjC::SynthGetSuperClassFunctionDecl() {
2457
IdentifierInfo *getSuperClassIdent =
2458
&Context->Idents.get("class_getSuperclass");
2459
SmallVector<QualType, 16> ArgTys;
2460
ArgTys.push_back(Context->getObjCClassType());
2461
QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),
2462
ArgTys);
2463
GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2464
SourceLocation(),
2465
SourceLocation(),
2466
getSuperClassIdent,
2467
getClassType, nullptr,
2468
SC_Extern);
2469
}
2470
2471
// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name);
2472
void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2473
IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
2474
SmallVector<QualType, 16> ArgTys;
2475
ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2476
QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),
2477
ArgTys);
2478
GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2479
SourceLocation(),
2480
SourceLocation(),
2481
getClassIdent, getClassType,
2482
nullptr, SC_Extern);
2483
}
2484
2485
Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
2486
assert(Exp != nullptr && "Expected non-null ObjCStringLiteral");
2487
QualType strType = getConstantStringStructType();
2488
2489
std::string S = "__NSConstantStringImpl_";
2490
2491
std::string tmpName = InFileName;
2492
unsigned i;
2493
for (i=0; i < tmpName.length(); i++) {
2494
char c = tmpName.at(i);
2495
// replace any non-alphanumeric characters with '_'.
2496
if (!isAlphanumeric(c))
2497
tmpName[i] = '_';
2498
}
2499
S += tmpName;
2500
S += "_";
2501
S += utostr(NumObjCStringLiterals++);
2502
2503
Preamble += "static __NSConstantStringImpl " + S;
2504
Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2505
Preamble += "0x000007c8,"; // utf8_str
2506
// The pretty printer for StringLiteral handles escape characters properly.
2507
std::string prettyBufS;
2508
llvm::raw_string_ostream prettyBuf(prettyBufS);
2509
Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));
2510
Preamble += prettyBuf.str();
2511
Preamble += ",";
2512
Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
2513
2514
VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
2515
SourceLocation(), &Context->Idents.get(S),
2516
strType, nullptr, SC_Static);
2517
DeclRefExpr *DRE = new (Context)
2518
DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());
2519
Expr *Unop = UnaryOperator::Create(
2520
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
2521
Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
2522
SourceLocation(), false, FPOptionsOverride());
2523
// cast to NSConstantString *
2524
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
2525
CK_CPointerToObjCPointerCast, Unop);
2526
ReplaceStmt(Exp, cast);
2527
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
2528
return cast;
2529
}
2530
2531
// struct objc_super { struct objc_object *receiver; struct objc_class *super; };
2532
QualType RewriteObjC::getSuperStructType() {
2533
if (!SuperStructDecl) {
2534
SuperStructDecl = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
2535
SourceLocation(), SourceLocation(),
2536
&Context->Idents.get("objc_super"));
2537
QualType FieldTypes[2];
2538
2539
// struct objc_object *receiver;
2540
FieldTypes[0] = Context->getObjCIdType();
2541
// struct objc_class *super;
2542
FieldTypes[1] = Context->getObjCClassType();
2543
2544
// Create fields
2545
for (unsigned i = 0; i < 2; ++i) {
2546
SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
2547
SourceLocation(),
2548
SourceLocation(), nullptr,
2549
FieldTypes[i], nullptr,
2550
/*BitWidth=*/nullptr,
2551
/*Mutable=*/false,
2552
ICIS_NoInit));
2553
}
2554
2555
SuperStructDecl->completeDefinition();
2556
}
2557
return Context->getTagDeclType(SuperStructDecl);
2558
}
2559
2560
QualType RewriteObjC::getConstantStringStructType() {
2561
if (!ConstantStringDecl) {
2562
ConstantStringDecl = RecordDecl::Create(
2563
*Context, TagTypeKind::Struct, TUDecl, SourceLocation(),
2564
SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));
2565
QualType FieldTypes[4];
2566
2567
// struct objc_object *receiver;
2568
FieldTypes[0] = Context->getObjCIdType();
2569
// int flags;
2570
FieldTypes[1] = Context->IntTy;
2571
// char *str;
2572
FieldTypes[2] = Context->getPointerType(Context->CharTy);
2573
// long length;
2574
FieldTypes[3] = Context->LongTy;
2575
2576
// Create fields
2577
for (unsigned i = 0; i < 4; ++i) {
2578
ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
2579
ConstantStringDecl,
2580
SourceLocation(),
2581
SourceLocation(), nullptr,
2582
FieldTypes[i], nullptr,
2583
/*BitWidth=*/nullptr,
2584
/*Mutable=*/true,
2585
ICIS_NoInit));
2586
}
2587
2588
ConstantStringDecl->completeDefinition();
2589
}
2590
return Context->getTagDeclType(ConstantStringDecl);
2591
}
2592
2593
CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,
2594
QualType msgSendType,
2595
QualType returnType,
2596
SmallVectorImpl<QualType> &ArgTypes,
2597
SmallVectorImpl<Expr*> &MsgExprs,
2598
ObjCMethodDecl *Method) {
2599
// Create a reference to the objc_msgSend_stret() declaration.
2600
DeclRefExpr *STDRE =
2601
new (Context) DeclRefExpr(*Context, MsgSendStretFlavor, false,
2602
msgSendType, VK_LValue, SourceLocation());
2603
// Need to cast objc_msgSend_stret to "void *" (see above comment).
2604
CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,
2605
Context->getPointerType(Context->VoidTy),
2606
CK_BitCast, STDRE);
2607
// Now do the "normal" pointer to function cast.
2608
QualType castType = getSimpleFunctionType(returnType, ArgTypes,
2609
Method ? Method->isVariadic()
2610
: false);
2611
castType = Context->getPointerType(castType);
2612
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2613
cast);
2614
2615
// Don't forget the parens to enforce the proper binding.
2616
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
2617
2618
const auto *FT = msgSendType->castAs<FunctionType>();
2619
CallExpr *STCE =
2620
CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_PRValue,
2621
SourceLocation(), FPOptionsOverride());
2622
return STCE;
2623
}
2624
2625
Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,
2626
SourceLocation StartLoc,
2627
SourceLocation EndLoc) {
2628
if (!SelGetUidFunctionDecl)
2629
SynthSelGetUidFunctionDecl();
2630
if (!MsgSendFunctionDecl)
2631
SynthMsgSendFunctionDecl();
2632
if (!MsgSendSuperFunctionDecl)
2633
SynthMsgSendSuperFunctionDecl();
2634
if (!MsgSendStretFunctionDecl)
2635
SynthMsgSendStretFunctionDecl();
2636
if (!MsgSendSuperStretFunctionDecl)
2637
SynthMsgSendSuperStretFunctionDecl();
2638
if (!MsgSendFpretFunctionDecl)
2639
SynthMsgSendFpretFunctionDecl();
2640
if (!GetClassFunctionDecl)
2641
SynthGetClassFunctionDecl();
2642
if (!GetSuperClassFunctionDecl)
2643
SynthGetSuperClassFunctionDecl();
2644
if (!GetMetaClassFunctionDecl)
2645
SynthGetMetaClassFunctionDecl();
2646
2647
// default to objc_msgSend().
2648
FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
2649
// May need to use objc_msgSend_stret() as well.
2650
FunctionDecl *MsgSendStretFlavor = nullptr;
2651
if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
2652
QualType resultType = mDecl->getReturnType();
2653
if (resultType->isRecordType())
2654
MsgSendStretFlavor = MsgSendStretFunctionDecl;
2655
else if (resultType->isRealFloatingType())
2656
MsgSendFlavor = MsgSendFpretFunctionDecl;
2657
}
2658
2659
// Synthesize a call to objc_msgSend().
2660
SmallVector<Expr*, 8> MsgExprs;
2661
switch (Exp->getReceiverKind()) {
2662
case ObjCMessageExpr::SuperClass: {
2663
MsgSendFlavor = MsgSendSuperFunctionDecl;
2664
if (MsgSendStretFlavor)
2665
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2666
assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
2667
2668
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
2669
2670
SmallVector<Expr*, 4> InitExprs;
2671
2672
// set the receiver to self, the first argument to all methods.
2673
InitExprs.push_back(NoTypeInfoCStyleCastExpr(
2674
Context, Context->getObjCIdType(), CK_BitCast,
2675
new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
2676
Context->getObjCIdType(), VK_PRValue,
2677
SourceLocation()))); // set the 'receiver'.
2678
2679
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2680
SmallVector<Expr*, 8> ClsExprs;
2681
ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
2682
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2683
ClsExprs, StartLoc, EndLoc);
2684
// (Class)objc_getClass("CurrentClass")
2685
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2686
Context->getObjCClassType(),
2687
CK_BitCast, Cls);
2688
ClsExprs.clear();
2689
ClsExprs.push_back(ArgExpr);
2690
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2691
StartLoc, EndLoc);
2692
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2693
// To turn off a warning, type-cast to 'id'
2694
InitExprs.push_back( // set 'super class', using class_getSuperclass().
2695
NoTypeInfoCStyleCastExpr(Context,
2696
Context->getObjCIdType(),
2697
CK_BitCast, Cls));
2698
// struct objc_super
2699
QualType superType = getSuperStructType();
2700
Expr *SuperRep;
2701
2702
if (LangOpts.MicrosoftExt) {
2703
SynthSuperConstructorFunctionDecl();
2704
// Simulate a constructor call...
2705
DeclRefExpr *DRE = new (Context)
2706
DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
2707
VK_LValue, SourceLocation());
2708
SuperRep =
2709
CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
2710
SourceLocation(), FPOptionsOverride());
2711
// The code for super is a little tricky to prevent collision with
2712
// the structure definition in the header. The rewriter has it's own
2713
// internal definition (__rw_objc_super) that is uses. This is why
2714
// we need the cast below. For example:
2715
// (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
2716
//
2717
SuperRep = UnaryOperator::Create(
2718
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
2719
Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
2720
SourceLocation(), false, FPOptionsOverride());
2721
SuperRep = NoTypeInfoCStyleCastExpr(Context,
2722
Context->getPointerType(superType),
2723
CK_BitCast, SuperRep);
2724
} else {
2725
// (struct objc_super) { <exprs from above> }
2726
InitListExpr *ILE =
2727
new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
2728
SourceLocation());
2729
TypeSourceInfo *superTInfo
2730
= Context->getTrivialTypeSourceInfo(superType);
2731
SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
2732
superType, VK_LValue,
2733
ILE, false);
2734
// struct objc_super *
2735
SuperRep = UnaryOperator::Create(
2736
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
2737
Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
2738
SourceLocation(), false, FPOptionsOverride());
2739
}
2740
MsgExprs.push_back(SuperRep);
2741
break;
2742
}
2743
2744
case ObjCMessageExpr::Class: {
2745
SmallVector<Expr*, 8> ClsExprs;
2746
auto *Class =
2747
Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();
2748
IdentifierInfo *clsName = Class->getIdentifier();
2749
ClsExprs.push_back(getStringLiteral(clsName->getName()));
2750
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2751
StartLoc, EndLoc);
2752
MsgExprs.push_back(Cls);
2753
break;
2754
}
2755
2756
case ObjCMessageExpr::SuperInstance:{
2757
MsgSendFlavor = MsgSendSuperFunctionDecl;
2758
if (MsgSendStretFlavor)
2759
MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
2760
assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
2761
ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();
2762
SmallVector<Expr*, 4> InitExprs;
2763
2764
InitExprs.push_back(NoTypeInfoCStyleCastExpr(
2765
Context, Context->getObjCIdType(), CK_BitCast,
2766
new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,
2767
Context->getObjCIdType(), VK_PRValue,
2768
SourceLocation()))); // set the 'receiver'.
2769
2770
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2771
SmallVector<Expr*, 8> ClsExprs;
2772
ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));
2773
CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,
2774
StartLoc, EndLoc);
2775
// (Class)objc_getClass("CurrentClass")
2776
CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,
2777
Context->getObjCClassType(),
2778
CK_BitCast, Cls);
2779
ClsExprs.clear();
2780
ClsExprs.push_back(ArgExpr);
2781
Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,
2782
StartLoc, EndLoc);
2783
2784
// (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))
2785
// To turn off a warning, type-cast to 'id'
2786
InitExprs.push_back(
2787
// set 'super class', using class_getSuperclass().
2788
NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2789
CK_BitCast, Cls));
2790
// struct objc_super
2791
QualType superType = getSuperStructType();
2792
Expr *SuperRep;
2793
2794
if (LangOpts.MicrosoftExt) {
2795
SynthSuperConstructorFunctionDecl();
2796
// Simulate a constructor call...
2797
DeclRefExpr *DRE = new (Context)
2798
DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,
2799
VK_LValue, SourceLocation());
2800
SuperRep =
2801
CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,
2802
SourceLocation(), FPOptionsOverride());
2803
// The code for super is a little tricky to prevent collision with
2804
// the structure definition in the header. The rewriter has it's own
2805
// internal definition (__rw_objc_super) that is uses. This is why
2806
// we need the cast below. For example:
2807
// (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
2808
//
2809
SuperRep = UnaryOperator::Create(
2810
const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,
2811
Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,
2812
SourceLocation(), false, FPOptionsOverride());
2813
SuperRep = NoTypeInfoCStyleCastExpr(Context,
2814
Context->getPointerType(superType),
2815
CK_BitCast, SuperRep);
2816
} else {
2817
// (struct objc_super) { <exprs from above> }
2818
InitListExpr *ILE =
2819
new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,
2820
SourceLocation());
2821
TypeSourceInfo *superTInfo
2822
= Context->getTrivialTypeSourceInfo(superType);
2823
SuperRep = new (Context) CompoundLiteralExpr(
2824
SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);
2825
}
2826
MsgExprs.push_back(SuperRep);
2827
break;
2828
}
2829
2830
case ObjCMessageExpr::Instance: {
2831
// Remove all type-casts because it may contain objc-style types; e.g.
2832
// Foo<Proto> *.
2833
Expr *recExpr = Exp->getInstanceReceiver();
2834
while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
2835
recExpr = CE->getSubExpr();
2836
CastKind CK = recExpr->getType()->isObjCObjectPointerType()
2837
? CK_BitCast : recExpr->getType()->isBlockPointerType()
2838
? CK_BlockPointerToObjCPointerCast
2839
: CK_CPointerToObjCPointerCast;
2840
2841
recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2842
CK, recExpr);
2843
MsgExprs.push_back(recExpr);
2844
break;
2845
}
2846
}
2847
2848
// Create a call to sel_registerName("selName"), it will be the 2nd argument.
2849
SmallVector<Expr*, 8> SelExprs;
2850
SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));
2851
CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2852
SelExprs, StartLoc, EndLoc);
2853
MsgExprs.push_back(SelExp);
2854
2855
// Now push any user supplied arguments.
2856
for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
2857
Expr *userExpr = Exp->getArg(i);
2858
// Make all implicit casts explicit...ICE comes in handy:-)
2859
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
2860
// Reuse the ICE type, it is exactly what the doctor ordered.
2861
QualType type = ICE->getType();
2862
if (needToScanForQualifiers(type))
2863
type = Context->getObjCIdType();
2864
// Make sure we convert "type (^)(...)" to "type (*)(...)".
2865
(void)convertBlockPointerToFunctionPointer(type);
2866
const Expr *SubExpr = ICE->IgnoreParenImpCasts();
2867
CastKind CK;
2868
if (SubExpr->getType()->isIntegralType(*Context) &&
2869
type->isBooleanType()) {
2870
CK = CK_IntegralToBoolean;
2871
} else if (type->isObjCObjectPointerType()) {
2872
if (SubExpr->getType()->isBlockPointerType()) {
2873
CK = CK_BlockPointerToObjCPointerCast;
2874
} else if (SubExpr->getType()->isPointerType()) {
2875
CK = CK_CPointerToObjCPointerCast;
2876
} else {
2877
CK = CK_BitCast;
2878
}
2879
} else {
2880
CK = CK_BitCast;
2881
}
2882
2883
userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);
2884
}
2885
// Make id<P...> cast into an 'id' cast.
2886
else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
2887
if (CE->getType()->isObjCQualifiedIdType()) {
2888
while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2889
userExpr = CE->getSubExpr();
2890
CastKind CK;
2891
if (userExpr->getType()->isIntegralType(*Context)) {
2892
CK = CK_IntegralToPointer;
2893
} else if (userExpr->getType()->isBlockPointerType()) {
2894
CK = CK_BlockPointerToObjCPointerCast;
2895
} else if (userExpr->getType()->isPointerType()) {
2896
CK = CK_CPointerToObjCPointerCast;
2897
} else {
2898
CK = CK_BitCast;
2899
}
2900
userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2901
CK, userExpr);
2902
}
2903
}
2904
MsgExprs.push_back(userExpr);
2905
// We've transferred the ownership to MsgExprs. For now, we *don't* null
2906
// out the argument in the original expression (since we aren't deleting
2907
// the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.
2908
//Exp->setArg(i, 0);
2909
}
2910
// Generate the funky cast.
2911
CastExpr *cast;
2912
SmallVector<QualType, 8> ArgTypes;
2913
QualType returnType;
2914
2915
// Push 'id' and 'SEL', the 2 implicit arguments.
2916
if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2917
ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
2918
else
2919
ArgTypes.push_back(Context->getObjCIdType());
2920
ArgTypes.push_back(Context->getObjCSelType());
2921
if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
2922
// Push any user argument types.
2923
for (const auto *PI : OMD->parameters()) {
2924
QualType t = PI->getType()->isObjCQualifiedIdType()
2925
? Context->getObjCIdType()
2926
: PI->getType();
2927
// Make sure we convert "t (^)(...)" to "t (*)(...)".
2928
(void)convertBlockPointerToFunctionPointer(t);
2929
ArgTypes.push_back(t);
2930
}
2931
returnType = Exp->getType();
2932
convertToUnqualifiedObjCType(returnType);
2933
(void)convertBlockPointerToFunctionPointer(returnType);
2934
} else {
2935
returnType = Context->getObjCIdType();
2936
}
2937
// Get the type, we will need to reference it in a couple spots.
2938
QualType msgSendType = MsgSendFlavor->getType();
2939
2940
// Create a reference to the objc_msgSend() declaration.
2941
DeclRefExpr *DRE = new (Context) DeclRefExpr(
2942
*Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());
2943
2944
// Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
2945
// If we don't do this cast, we get the following bizarre warning/note:
2946
// xx.m:13: warning: function called through a non-compatible type
2947
// xx.m:13: note: if this code is reached, the program will abort
2948
cast = NoTypeInfoCStyleCastExpr(Context,
2949
Context->getPointerType(Context->VoidTy),
2950
CK_BitCast, DRE);
2951
2952
// Now do the "normal" pointer to function cast.
2953
// If we don't have a method decl, force a variadic cast.
2954
const ObjCMethodDecl *MD = Exp->getMethodDecl();
2955
QualType castType =
2956
getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);
2957
castType = Context->getPointerType(castType);
2958
cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,
2959
cast);
2960
2961
// Don't forget the parens to enforce the proper binding.
2962
ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);
2963
2964
const auto *FT = msgSendType->castAs<FunctionType>();
2965
CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),
2966
VK_PRValue, EndLoc, FPOptionsOverride());
2967
Stmt *ReplacingStmt = CE;
2968
if (MsgSendStretFlavor) {
2969
// We have the method which returns a struct/union. Must also generate
2970
// call to objc_msgSend_stret and hang both varieties on a conditional
2971
// expression which dictate which one to envoke depending on size of
2972
// method's return type.
2973
2974
CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,
2975
msgSendType, returnType,
2976
ArgTypes, MsgExprs,
2977
Exp->getMethodDecl());
2978
2979
// Build sizeof(returnType)
2980
UnaryExprOrTypeTraitExpr *sizeofExpr =
2981
new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf,
2982
Context->getTrivialTypeSourceInfo(returnType),
2983
Context->getSizeType(), SourceLocation(),
2984
SourceLocation());
2985
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
2986
// FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
2987
// For X86 it is more complicated and some kind of target specific routine
2988
// is needed to decide what to do.
2989
unsigned IntSize =
2990
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
2991
IntegerLiteral *limit = IntegerLiteral::Create(*Context,
2992
llvm::APInt(IntSize, 8),
2993
Context->IntTy,
2994
SourceLocation());
2995
BinaryOperator *lessThanExpr = BinaryOperator::Create(
2996
*Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue,
2997
OK_Ordinary, SourceLocation(), FPOptionsOverride());
2998
// (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
2999
ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
3000
lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType,
3001
VK_PRValue, OK_Ordinary);
3002
ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
3003
CondExpr);
3004
}
3005
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3006
return ReplacingStmt;
3007
}
3008
3009
Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
3010
Stmt *ReplacingStmt =
3011
SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());
3012
3013
// Now do the actual rewrite.
3014
ReplaceStmt(Exp, ReplacingStmt);
3015
3016
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3017
return ReplacingStmt;
3018
}
3019
3020
// typedef struct objc_object Protocol;
3021
QualType RewriteObjC::getProtocolType() {
3022
if (!ProtocolTypeDecl) {
3023
TypeSourceInfo *TInfo
3024
= Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
3025
ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
3026
SourceLocation(), SourceLocation(),
3027
&Context->Idents.get("Protocol"),
3028
TInfo);
3029
}
3030
return Context->getTypeDeclType(ProtocolTypeDecl);
3031
}
3032
3033
/// RewriteObjCProtocolExpr - Rewrite a protocol expression into
3034
/// a synthesized/forward data reference (to the protocol's metadata).
3035
/// The forward references (and metadata) are generated in
3036
/// RewriteObjC::HandleTranslationUnit().
3037
Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
3038
std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();
3039
IdentifierInfo *ID = &Context->Idents.get(Name);
3040
VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
3041
SourceLocation(), ID, getProtocolType(),
3042
nullptr, SC_Extern);
3043
DeclRefExpr *DRE = new (Context) DeclRefExpr(
3044
*Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());
3045
Expr *DerefExpr = UnaryOperator::Create(
3046
const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,
3047
Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,
3048
SourceLocation(), false, FPOptionsOverride());
3049
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
3050
CK_BitCast,
3051
DerefExpr);
3052
ReplaceStmt(Exp, castExpr);
3053
ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());
3054
// delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.
3055
return castExpr;
3056
}
3057
3058
bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
3059
const char *endBuf) {
3060
while (startBuf < endBuf) {
3061
if (*startBuf == '#') {
3062
// Skip whitespace.
3063
for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
3064
;
3065
if (!strncmp(startBuf, "if", strlen("if")) ||
3066
!strncmp(startBuf, "ifdef", strlen("ifdef")) ||
3067
!strncmp(startBuf, "ifndef", strlen("ifndef")) ||
3068
!strncmp(startBuf, "define", strlen("define")) ||
3069
!strncmp(startBuf, "undef", strlen("undef")) ||
3070
!strncmp(startBuf, "else", strlen("else")) ||
3071
!strncmp(startBuf, "elif", strlen("elif")) ||
3072
!strncmp(startBuf, "endif", strlen("endif")) ||
3073
!strncmp(startBuf, "pragma", strlen("pragma")) ||
3074
!strncmp(startBuf, "include", strlen("include")) ||
3075
!strncmp(startBuf, "import", strlen("import")) ||
3076
!strncmp(startBuf, "include_next", strlen("include_next")))
3077
return true;
3078
}
3079
startBuf++;
3080
}
3081
return false;
3082
}
3083
3084
/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to
3085
/// an objective-c class with ivars.
3086
void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,
3087
std::string &Result) {
3088
assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
3089
assert(CDecl->getName() != "" &&
3090
"Name missing in SynthesizeObjCInternalStruct");
3091
// Do not synthesize more than once.
3092
if (ObjCSynthesizedStructs.count(CDecl))
3093
return;
3094
ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
3095
int NumIvars = CDecl->ivar_size();
3096
SourceLocation LocStart = CDecl->getBeginLoc();
3097
SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();
3098
3099
const char *startBuf = SM->getCharacterData(LocStart);
3100
const char *endBuf = SM->getCharacterData(LocEnd);
3101
3102
// If no ivars and no root or if its root, directly or indirectly,
3103
// have no ivars (thus not synthesized) then no need to synthesize this class.
3104
if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) &&
3105
(!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
3106
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3107
ReplaceText(LocStart, endBuf-startBuf, Result);
3108
return;
3109
}
3110
3111
// FIXME: This has potential of causing problem. If
3112
// SynthesizeObjCInternalStruct is ever called recursively.
3113
Result += "\nstruct ";
3114
Result += CDecl->getNameAsString();
3115
if (LangOpts.MicrosoftExt)
3116
Result += "_IMPL";
3117
3118
if (NumIvars > 0) {
3119
const char *cursor = strchr(startBuf, '{');
3120
assert((cursor && endBuf)
3121
&& "SynthesizeObjCInternalStruct - malformed @interface");
3122
// If the buffer contains preprocessor directives, we do more fine-grained
3123
// rewrites. This is intended to fix code that looks like (which occurs in
3124
// NSURL.h, for example):
3125
//
3126
// #ifdef XYZ
3127
// @interface Foo : NSObject
3128
// #else
3129
// @interface FooBar : NSObject
3130
// #endif
3131
// {
3132
// int i;
3133
// }
3134
// @end
3135
//
3136
// This clause is segregated to avoid breaking the common case.
3137
if (BufferContainsPPDirectives(startBuf, cursor)) {
3138
SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :
3139
CDecl->getAtStartLoc();
3140
const char *endHeader = SM->getCharacterData(L);
3141
endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);
3142
3143
if (CDecl->protocol_begin() != CDecl->protocol_end()) {
3144
// advance to the end of the referenced protocols.
3145
while (endHeader < cursor && *endHeader != '>') endHeader++;
3146
endHeader++;
3147
}
3148
// rewrite the original header
3149
ReplaceText(LocStart, endHeader-startBuf, Result);
3150
} else {
3151
// rewrite the original header *without* disturbing the '{'
3152
ReplaceText(LocStart, cursor-startBuf, Result);
3153
}
3154
if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
3155
Result = "\n struct ";
3156
Result += RCDecl->getNameAsString();
3157
Result += "_IMPL ";
3158
Result += RCDecl->getNameAsString();
3159
Result += "_IVARS;\n";
3160
3161
// insert the super class structure definition.
3162
SourceLocation OnePastCurly =
3163
LocStart.getLocWithOffset(cursor-startBuf+1);
3164
InsertText(OnePastCurly, Result);
3165
}
3166
cursor++; // past '{'
3167
3168
// Now comment out any visibility specifiers.
3169
while (cursor < endBuf) {
3170
if (*cursor == '@') {
3171
SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3172
// Skip whitespace.
3173
for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
3174
/*scan*/;
3175
3176
// FIXME: presence of @public, etc. inside comment results in
3177
// this transformation as well, which is still correct c-code.
3178
if (!strncmp(cursor, "public", strlen("public")) ||
3179
!strncmp(cursor, "private", strlen("private")) ||
3180
!strncmp(cursor, "package", strlen("package")) ||
3181
!strncmp(cursor, "protected", strlen("protected")))
3182
InsertText(atLoc, "// ");
3183
}
3184
// FIXME: If there are cases where '<' is used in ivar declaration part
3185
// of user code, then scan the ivar list and use needToScanForQualifiers
3186
// for type checking.
3187
else if (*cursor == '<') {
3188
SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3189
InsertText(atLoc, "/* ");
3190
cursor = strchr(cursor, '>');
3191
cursor++;
3192
atLoc = LocStart.getLocWithOffset(cursor-startBuf);
3193
InsertText(atLoc, " */");
3194
} else if (*cursor == '^') { // rewrite block specifier.
3195
SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf);
3196
ReplaceText(caretLoc, 1, "*");
3197
}
3198
cursor++;
3199
}
3200
// Don't forget to add a ';'!!
3201
InsertText(LocEnd.getLocWithOffset(1), ";");
3202
} else { // we don't have any instance variables - insert super struct.
3203
endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3204
Result += " {\n struct ";
3205
Result += RCDecl->getNameAsString();
3206
Result += "_IMPL ";
3207
Result += RCDecl->getNameAsString();
3208
Result += "_IVARS;\n};\n";
3209
ReplaceText(LocStart, endBuf-startBuf, Result);
3210
}
3211
// Mark this struct as having been generated.
3212
if (!ObjCSynthesizedStructs.insert(CDecl).second)
3213
llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct");
3214
}
3215
3216
//===----------------------------------------------------------------------===//
3217
// Meta Data Emission
3218
//===----------------------------------------------------------------------===//
3219
3220
/// RewriteImplementations - This routine rewrites all method implementations
3221
/// and emits meta-data.
3222
3223
void RewriteObjC::RewriteImplementations() {
3224
int ClsDefCount = ClassImplementation.size();
3225
int CatDefCount = CategoryImplementation.size();
3226
3227
// Rewrite implemented methods
3228
for (int i = 0; i < ClsDefCount; i++)
3229
RewriteImplementationDecl(ClassImplementation[i]);
3230
3231
for (int i = 0; i < CatDefCount; i++)
3232
RewriteImplementationDecl(CategoryImplementation[i]);
3233
}
3234
3235
void RewriteObjC::RewriteByRefString(std::string &ResultStr,
3236
const std::string &Name,
3237
ValueDecl *VD, bool def) {
3238
assert(BlockByRefDeclNo.count(VD) &&
3239
"RewriteByRefString: ByRef decl missing");
3240
if (def)
3241
ResultStr += "struct ";
3242
ResultStr += "__Block_byref_" + Name +
3243
"_" + utostr(BlockByRefDeclNo[VD]) ;
3244
}
3245
3246
static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
3247
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
3248
return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
3249
return false;
3250
}
3251
3252
std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
3253
StringRef funcName,
3254
std::string Tag) {
3255
const FunctionType *AFT = CE->getFunctionType();
3256
QualType RT = AFT->getReturnType();
3257
std::string StructRef = "struct " + Tag;
3258
std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +
3259
funcName.str() + "_" + "block_func_" + utostr(i);
3260
3261
BlockDecl *BD = CE->getBlockDecl();
3262
3263
if (isa<FunctionNoProtoType>(AFT)) {
3264
// No user-supplied arguments. Still need to pass in a pointer to the
3265
// block (to reference imported block decl refs).
3266
S += "(" + StructRef + " *__cself)";
3267
} else if (BD->param_empty()) {
3268
S += "(" + StructRef + " *__cself)";
3269
} else {
3270
const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);
3271
assert(FT && "SynthesizeBlockFunc: No function proto");
3272
S += '(';
3273
// first add the implicit argument.
3274
S += StructRef + " *__cself, ";
3275
std::string ParamStr;
3276
for (BlockDecl::param_iterator AI = BD->param_begin(),
3277
E = BD->param_end(); AI != E; ++AI) {
3278
if (AI != BD->param_begin()) S += ", ";
3279
ParamStr = (*AI)->getNameAsString();
3280
QualType QT = (*AI)->getType();
3281
(void)convertBlockPointerToFunctionPointer(QT);
3282
QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());
3283
S += ParamStr;
3284
}
3285
if (FT->isVariadic()) {
3286
if (!BD->param_empty()) S += ", ";
3287
S += "...";
3288
}
3289
S += ')';
3290
}
3291
S += " {\n";
3292
3293
// Create local declarations to avoid rewriting all closure decl ref exprs.
3294
// First, emit a declaration for all "by ref" decls.
3295
for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
3296
E = BlockByRefDecls.end(); I != E; ++I) {
3297
S += " ";
3298
std::string Name = (*I)->getNameAsString();
3299
std::string TypeString;
3300
RewriteByRefString(TypeString, Name, (*I));
3301
TypeString += " *";
3302
Name = TypeString + Name;
3303
S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
3304
}
3305
// Next, emit a declaration for all "by copy" declarations.
3306
for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
3307
E = BlockByCopyDecls.end(); I != E; ++I) {
3308
S += " ";
3309
// Handle nested closure invocation. For example:
3310
//
3311
// void (^myImportedClosure)(void);
3312
// myImportedClosure = ^(void) { setGlobalInt(x + y); };
3313
//
3314
// void (^anotherClosure)(void);
3315
// anotherClosure = ^(void) {
3316
// myImportedClosure(); // import and invoke the closure
3317
// };
3318
//
3319
if (isTopLevelBlockPointerType((*I)->getType())) {
3320
RewriteBlockPointerTypeVariable(S, (*I));
3321
S += " = (";
3322
RewriteBlockPointerType(S, (*I)->getType());
3323
S += ")";
3324
S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";
3325
}
3326
else {
3327
std::string Name = (*I)->getNameAsString();
3328
QualType QT = (*I)->getType();
3329
if (HasLocalVariableExternalStorage(*I))
3330
QT = Context->getPointerType(QT);
3331
QT.getAsStringInternal(Name, Context->getPrintingPolicy());
3332
S += Name + " = __cself->" +
3333
(*I)->getNameAsString() + "; // bound by copy\n";
3334
}
3335
}
3336
std::string RewrittenStr = RewrittenBlockExprs[CE];
3337
const char *cstr = RewrittenStr.c_str();
3338
while (*cstr++ != '{') ;
3339
S += cstr;
3340
S += "\n";
3341
return S;
3342
}
3343
3344
std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
3345
StringRef funcName,
3346
std::string Tag) {
3347
std::string StructRef = "struct " + Tag;
3348
std::string S = "static void __";
3349
3350
S += funcName;
3351
S += "_block_copy_" + utostr(i);
3352
S += "(" + StructRef;
3353
S += "*dst, " + StructRef;
3354
S += "*src) {";
3355
for (ValueDecl *VD : ImportedBlockDecls) {
3356
S += "_Block_object_assign((void*)&dst->";
3357
S += VD->getNameAsString();
3358
S += ", (void*)src->";
3359
S += VD->getNameAsString();
3360
if (BlockByRefDeclsPtrSet.count(VD))
3361
S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
3362
else if (VD->getType()->isBlockPointerType())
3363
S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
3364
else
3365
S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
3366
}
3367
S += "}\n";
3368
3369
S += "\nstatic void __";
3370
S += funcName;
3371
S += "_block_dispose_" + utostr(i);
3372
S += "(" + StructRef;
3373
S += "*src) {";
3374
for (ValueDecl *VD : ImportedBlockDecls) {
3375
S += "_Block_object_dispose((void*)src->";
3376
S += VD->getNameAsString();
3377
if (BlockByRefDeclsPtrSet.count(VD))
3378
S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";
3379
else if (VD->getType()->isBlockPointerType())
3380
S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";
3381
else
3382
S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";
3383
}
3384
S += "}\n";
3385
return S;
3386
}
3387
3388
std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
3389
std::string Desc) {
3390
std::string S = "\nstruct " + Tag;
3391
std::string Constructor = " " + Tag;
3392
3393
S += " {\n struct __block_impl impl;\n";
3394
S += " struct " + Desc;
3395
S += "* Desc;\n";
3396
3397
Constructor += "(void *fp, "; // Invoke function pointer.
3398
Constructor += "struct " + Desc; // Descriptor pointer.
3399
Constructor += " *desc";
3400
3401
if (BlockDeclRefs.size()) {
3402
// Output all "by copy" declarations.
3403
for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
3404
E = BlockByCopyDecls.end(); I != E; ++I) {
3405
S += " ";
3406
std::string FieldName = (*I)->getNameAsString();
3407
std::string ArgName = "_" + FieldName;
3408
// Handle nested closure invocation. For example:
3409
//
3410
// void (^myImportedBlock)(void);
3411
// myImportedBlock = ^(void) { setGlobalInt(x + y); };
3412
//
3413
// void (^anotherBlock)(void);
3414
// anotherBlock = ^(void) {
3415
// myImportedBlock(); // import and invoke the closure
3416
// };
3417
//
3418
if (isTopLevelBlockPointerType((*I)->getType())) {
3419
S += "struct __block_impl *";
3420
Constructor += ", void *" + ArgName;
3421
} else {
3422
QualType QT = (*I)->getType();
3423
if (HasLocalVariableExternalStorage(*I))
3424
QT = Context->getPointerType(QT);
3425
QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());
3426
QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());
3427
Constructor += ", " + ArgName;
3428
}
3429
S += FieldName + ";\n";
3430
}
3431
// Output all "by ref" declarations.
3432
for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
3433
E = BlockByRefDecls.end(); I != E; ++I) {
3434
S += " ";
3435
std::string FieldName = (*I)->getNameAsString();
3436
std::string ArgName = "_" + FieldName;
3437
{
3438
std::string TypeString;
3439
RewriteByRefString(TypeString, FieldName, (*I));
3440
TypeString += " *";
3441
FieldName = TypeString + FieldName;
3442
ArgName = TypeString + ArgName;
3443
Constructor += ", " + ArgName;
3444
}
3445
S += FieldName + "; // by ref\n";
3446
}
3447
// Finish writing the constructor.
3448
Constructor += ", int flags=0)";
3449
// Initialize all "by copy" arguments.
3450
bool firsTime = true;
3451
for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
3452
E = BlockByCopyDecls.end(); I != E; ++I) {
3453
std::string Name = (*I)->getNameAsString();
3454
if (firsTime) {
3455
Constructor += " : ";
3456
firsTime = false;
3457
}
3458
else
3459
Constructor += ", ";
3460
if (isTopLevelBlockPointerType((*I)->getType()))
3461
Constructor += Name + "((struct __block_impl *)_" + Name + ")";
3462
else
3463
Constructor += Name + "(_" + Name + ")";
3464
}
3465
// Initialize all "by ref" arguments.
3466
for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
3467
E = BlockByRefDecls.end(); I != E; ++I) {
3468
std::string Name = (*I)->getNameAsString();
3469
if (firsTime) {
3470
Constructor += " : ";
3471
firsTime = false;
3472
}
3473
else
3474
Constructor += ", ";
3475
Constructor += Name + "(_" + Name + "->__forwarding)";
3476
}
3477
3478
Constructor += " {\n";
3479
if (GlobalVarDecl)
3480
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
3481
else
3482
Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
3483
Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3484
3485
Constructor += " Desc = desc;\n";
3486
} else {
3487
// Finish writing the constructor.
3488
Constructor += ", int flags=0) {\n";
3489
if (GlobalVarDecl)
3490
Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";
3491
else
3492
Constructor += " impl.isa = &_NSConcreteStackBlock;\n";
3493
Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";
3494
Constructor += " Desc = desc;\n";
3495
}
3496
Constructor += " ";
3497
Constructor += "}\n";
3498
S += Constructor;
3499
S += "};\n";
3500
return S;
3501
}
3502
3503
std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,
3504
std::string ImplTag, int i,
3505
StringRef FunName,
3506
unsigned hasCopy) {
3507
std::string S = "\nstatic struct " + DescTag;
3508
3509
S += " {\n unsigned long reserved;\n";
3510
S += " unsigned long Block_size;\n";
3511
if (hasCopy) {
3512
S += " void (*copy)(struct ";
3513
S += ImplTag; S += "*, struct ";
3514
S += ImplTag; S += "*);\n";
3515
3516
S += " void (*dispose)(struct ";
3517
S += ImplTag; S += "*);\n";
3518
}
3519
S += "} ";
3520
3521
S += DescTag + "_DATA = { 0, sizeof(struct ";
3522
S += ImplTag + ")";
3523
if (hasCopy) {
3524
S += ", __" + FunName.str() + "_block_copy_" + utostr(i);
3525
S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);
3526
}
3527
S += "};\n";
3528
return S;
3529
}
3530
3531
void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,
3532
StringRef FunName) {
3533
// Insert declaration for the function in which block literal is used.
3534
if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())
3535
RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
3536
bool RewriteSC = (GlobalVarDecl &&
3537
!Blocks.empty() &&
3538
GlobalVarDecl->getStorageClass() == SC_Static &&
3539
GlobalVarDecl->getType().getCVRQualifiers());
3540
if (RewriteSC) {
3541
std::string SC(" void __");
3542
SC += GlobalVarDecl->getNameAsString();
3543
SC += "() {}";
3544
InsertText(FunLocStart, SC);
3545
}
3546
3547
// Insert closures that were part of the function.
3548
for (unsigned i = 0, count=0; i < Blocks.size(); i++) {
3549
CollectBlockDeclRefInfo(Blocks[i]);
3550
// Need to copy-in the inner copied-in variables not actually used in this
3551
// block.
3552
for (int j = 0; j < InnerDeclRefsCount[i]; j++) {
3553
DeclRefExpr *Exp = InnerDeclRefs[count++];
3554
ValueDecl *VD = Exp->getDecl();
3555
BlockDeclRefs.push_back(Exp);
3556
if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
3557
BlockByCopyDeclsPtrSet.insert(VD);
3558
BlockByCopyDecls.push_back(VD);
3559
}
3560
if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
3561
BlockByRefDeclsPtrSet.insert(VD);
3562
BlockByRefDecls.push_back(VD);
3563
}
3564
// imported objects in the inner blocks not used in the outer
3565
// blocks must be copied/disposed in the outer block as well.
3566
if (VD->hasAttr<BlocksAttr>() ||
3567
VD->getType()->isObjCObjectPointerType() ||
3568
VD->getType()->isBlockPointerType())
3569
ImportedBlockDecls.insert(VD);
3570
}
3571
3572
std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);
3573
std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);
3574
3575
std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);
3576
3577
InsertText(FunLocStart, CI);
3578
3579
std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);
3580
3581
InsertText(FunLocStart, CF);
3582
3583
if (ImportedBlockDecls.size()) {
3584
std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);
3585
InsertText(FunLocStart, HF);
3586
}
3587
std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,
3588
ImportedBlockDecls.size() > 0);
3589
InsertText(FunLocStart, BD);
3590
3591
BlockDeclRefs.clear();
3592
BlockByRefDecls.clear();
3593
BlockByRefDeclsPtrSet.clear();
3594
BlockByCopyDecls.clear();
3595
BlockByCopyDeclsPtrSet.clear();
3596
ImportedBlockDecls.clear();
3597
}
3598
if (RewriteSC) {
3599
// Must insert any 'const/volatile/static here. Since it has been
3600
// removed as result of rewriting of block literals.
3601
std::string SC;
3602
if (GlobalVarDecl->getStorageClass() == SC_Static)
3603
SC = "static ";
3604
if (GlobalVarDecl->getType().isConstQualified())
3605
SC += "const ";
3606
if (GlobalVarDecl->getType().isVolatileQualified())
3607
SC += "volatile ";
3608
if (GlobalVarDecl->getType().isRestrictQualified())
3609
SC += "restrict ";
3610
InsertText(FunLocStart, SC);
3611
}
3612
3613
Blocks.clear();
3614
InnerDeclRefsCount.clear();
3615
InnerDeclRefs.clear();
3616
RewrittenBlockExprs.clear();
3617
}
3618
3619
void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {
3620
SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
3621
StringRef FuncName = FD->getName();
3622
3623
SynthesizeBlockLiterals(FunLocStart, FuncName);
3624
}
3625
3626
static void BuildUniqueMethodName(std::string &Name,
3627
ObjCMethodDecl *MD) {
3628
ObjCInterfaceDecl *IFace = MD->getClassInterface();
3629
Name = std::string(IFace->getName());
3630
Name += "__" + MD->getSelector().getAsString();
3631
// Convert colons to underscores.
3632
std::string::size_type loc = 0;
3633
while ((loc = Name.find(':', loc)) != std::string::npos)
3634
Name.replace(loc, 1, "_");
3635
}
3636
3637
void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {
3638
// fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");
3639
// SourceLocation FunLocStart = MD->getBeginLoc();
3640
SourceLocation FunLocStart = MD->getBeginLoc();
3641
std::string FuncName;
3642
BuildUniqueMethodName(FuncName, MD);
3643
SynthesizeBlockLiterals(FunLocStart, FuncName);
3644
}
3645
3646
void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {
3647
for (Stmt *SubStmt : S->children())
3648
if (SubStmt) {
3649
if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))
3650
GetBlockDeclRefExprs(CBE->getBody());
3651
else
3652
GetBlockDeclRefExprs(SubStmt);
3653
}
3654
// Handle specific things.
3655
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
3656
if (DRE->refersToEnclosingVariableOrCapture() ||
3657
HasLocalVariableExternalStorage(DRE->getDecl()))
3658
// FIXME: Handle enums.
3659
BlockDeclRefs.push_back(DRE);
3660
}
3661
3662
void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,
3663
SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,
3664
llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {
3665
for (Stmt *SubStmt : S->children())
3666
if (SubStmt) {
3667
if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {
3668
InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));
3669
GetInnerBlockDeclRefExprs(CBE->getBody(),
3670
InnerBlockDeclRefs,
3671
InnerContexts);
3672
}
3673
else
3674
GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);
3675
}
3676
// Handle specific things.
3677
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
3678
if (DRE->refersToEnclosingVariableOrCapture() ||
3679
HasLocalVariableExternalStorage(DRE->getDecl())) {
3680
if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))
3681
InnerBlockDeclRefs.push_back(DRE);
3682
if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))
3683
if (Var->isFunctionOrMethodVarDecl())
3684
ImportedLocalExternalDecls.insert(Var);
3685
}
3686
}
3687
}
3688
3689
/// convertFunctionTypeOfBlocks - This routine converts a function type
3690
/// whose result type may be a block pointer or whose argument type(s)
3691
/// might be block pointers to an equivalent function type replacing
3692
/// all block pointers to function pointers.
3693
QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {
3694
const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
3695
// FTP will be null for closures that don't take arguments.
3696
// Generate a funky cast.
3697
SmallVector<QualType, 8> ArgTypes;
3698
QualType Res = FT->getReturnType();
3699
bool HasBlockType = convertBlockPointerToFunctionPointer(Res);
3700
3701
if (FTP) {
3702
for (auto &I : FTP->param_types()) {
3703
QualType t = I;
3704
// Make sure we convert "t (^)(...)" to "t (*)(...)".
3705
if (convertBlockPointerToFunctionPointer(t))
3706
HasBlockType = true;
3707
ArgTypes.push_back(t);
3708
}
3709
}
3710
QualType FuncType;
3711
// FIXME. Does this work if block takes no argument but has a return type
3712
// which is of block type?
3713
if (HasBlockType)
3714
FuncType = getSimpleFunctionType(Res, ArgTypes);
3715
else FuncType = QualType(FT, 0);
3716
return FuncType;
3717
}
3718
3719
Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {
3720
// Navigate to relevant type information.
3721
const BlockPointerType *CPT = nullptr;
3722
3723
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {
3724
CPT = DRE->getType()->getAs<BlockPointerType>();
3725
} else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {
3726
CPT = MExpr->getType()->getAs<BlockPointerType>();
3727
}
3728
else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {
3729
return SynthesizeBlockCall(Exp, PRE->getSubExpr());
3730
}
3731
else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))
3732
CPT = IEXPR->getType()->getAs<BlockPointerType>();
3733
else if (const ConditionalOperator *CEXPR =
3734
dyn_cast<ConditionalOperator>(BlockExp)) {
3735
Expr *LHSExp = CEXPR->getLHS();
3736
Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);
3737
Expr *RHSExp = CEXPR->getRHS();
3738
Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);
3739
Expr *CONDExp = CEXPR->getCond();
3740
ConditionalOperator *CondExpr = new (Context) ConditionalOperator(
3741
CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),
3742
cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);
3743
return CondExpr;
3744
} else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {
3745
CPT = IRE->getType()->getAs<BlockPointerType>();
3746
} else if (const PseudoObjectExpr *POE
3747
= dyn_cast<PseudoObjectExpr>(BlockExp)) {
3748
CPT = POE->getType()->castAs<BlockPointerType>();
3749
} else {
3750
assert(false && "RewriteBlockClass: Bad type");
3751
}
3752
assert(CPT && "RewriteBlockClass: Bad type");
3753
const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();
3754
assert(FT && "RewriteBlockClass: Bad type");
3755
const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);
3756
// FTP will be null for closures that don't take arguments.
3757
3758
RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
3759
SourceLocation(), SourceLocation(),
3760
&Context->Idents.get("__block_impl"));
3761
QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD));
3762
3763
// Generate a funky cast.
3764
SmallVector<QualType, 8> ArgTypes;
3765
3766
// Push the block argument type.
3767
ArgTypes.push_back(PtrBlock);
3768
if (FTP) {
3769
for (auto &I : FTP->param_types()) {
3770
QualType t = I;
3771
// Make sure we convert "t (^)(...)" to "t (*)(...)".
3772
if (!convertBlockPointerToFunctionPointer(t))
3773
convertToUnqualifiedObjCType(t);
3774
ArgTypes.push_back(t);
3775
}
3776
}
3777
// Now do the pointer to function cast.
3778
QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);
3779
3780
PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);
3781
3782
CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,
3783
CK_BitCast,
3784
const_cast<Expr*>(BlockExp));
3785
// Don't forget the parens to enforce the proper binding.
3786
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
3787
BlkCast);
3788
//PE->dump();
3789
3790
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
3791
SourceLocation(),
3792
&Context->Idents.get("FuncPtr"),
3793
Context->VoidPtrTy, nullptr,
3794
/*BitWidth=*/nullptr, /*Mutable=*/true,
3795
ICIS_NoInit);
3796
MemberExpr *ME = MemberExpr::CreateImplicit(
3797
*Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);
3798
3799
CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,
3800
CK_BitCast, ME);
3801
PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);
3802
3803
SmallVector<Expr*, 8> BlkExprs;
3804
// Add the implicit argument.
3805
BlkExprs.push_back(BlkCast);
3806
// Add the user arguments.
3807
for (CallExpr::arg_iterator I = Exp->arg_begin(),
3808
E = Exp->arg_end(); I != E; ++I) {
3809
BlkExprs.push_back(*I);
3810
}
3811
CallExpr *CE =
3812
CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,
3813
SourceLocation(), FPOptionsOverride());
3814
return CE;
3815
}
3816
3817
// We need to return the rewritten expression to handle cases where the
3818
// BlockDeclRefExpr is embedded in another expression being rewritten.
3819
// For example:
3820
//
3821
// int main() {
3822
// __block Foo *f;
3823
// __block int i;
3824
//
3825
// void (^myblock)() = ^() {
3826
// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).
3827
// i = 77;
3828
// };
3829
//}
3830
Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {
3831
// Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR
3832
// for each DeclRefExp where BYREFVAR is name of the variable.
3833
ValueDecl *VD = DeclRefExp->getDecl();
3834
bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||
3835
HasLocalVariableExternalStorage(DeclRefExp->getDecl());
3836
3837
FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),
3838
SourceLocation(),
3839
&Context->Idents.get("__forwarding"),
3840
Context->VoidPtrTy, nullptr,
3841
/*BitWidth=*/nullptr, /*Mutable=*/true,
3842
ICIS_NoInit);
3843
MemberExpr *ME =
3844
MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD,
3845
FD->getType(), VK_LValue, OK_Ordinary);
3846
3847
StringRef Name = VD->getName();
3848
FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),
3849
&Context->Idents.get(Name),
3850
Context->VoidPtrTy, nullptr,
3851
/*BitWidth=*/nullptr, /*Mutable=*/true,
3852
ICIS_NoInit);
3853
ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),
3854
VK_LValue, OK_Ordinary);
3855
3856
// Need parens to enforce precedence.
3857
ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),
3858
DeclRefExp->getExprLoc(),
3859
ME);
3860
ReplaceStmt(DeclRefExp, PE);
3861
return PE;
3862
}
3863
3864
// Rewrites the imported local variable V with external storage
3865
// (static, extern, etc.) as *V
3866
//
3867
Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
3868
ValueDecl *VD = DRE->getDecl();
3869
if (VarDecl *Var = dyn_cast<VarDecl>(VD))
3870
if (!ImportedLocalExternalDecls.count(Var))
3871
return DRE;
3872
Expr *Exp = UnaryOperator::Create(
3873
const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),
3874
VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());
3875
// Need parens to enforce precedence.
3876
ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
3877
Exp);
3878
ReplaceStmt(DRE, PE);
3879
return PE;
3880
}
3881
3882
void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
3883
SourceLocation LocStart = CE->getLParenLoc();
3884
SourceLocation LocEnd = CE->getRParenLoc();
3885
3886
// Need to avoid trying to rewrite synthesized casts.
3887
if (LocStart.isInvalid())
3888
return;
3889
// Need to avoid trying to rewrite casts contained in macros.
3890
if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))
3891
return;
3892
3893
const char *startBuf = SM->getCharacterData(LocStart);
3894
const char *endBuf = SM->getCharacterData(LocEnd);
3895
QualType QT = CE->getType();
3896
const Type* TypePtr = QT->getAs<Type>();
3897
if (isa<TypeOfExprType>(TypePtr)) {
3898
const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);
3899
QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();
3900
std::string TypeAsString = "(";
3901
RewriteBlockPointerType(TypeAsString, QT);
3902
TypeAsString += ")";
3903
ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);
3904
return;
3905
}
3906
// advance the location to startArgList.
3907
const char *argPtr = startBuf;
3908
3909
while (*argPtr++ && (argPtr < endBuf)) {
3910
switch (*argPtr) {
3911
case '^':
3912
// Replace the '^' with '*'.
3913
LocStart = LocStart.getLocWithOffset(argPtr-startBuf);
3914
ReplaceText(LocStart, 1, "*");
3915
break;
3916
}
3917
}
3918
}
3919
3920
void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {
3921
SourceLocation DeclLoc = FD->getLocation();
3922
unsigned parenCount = 0;
3923
3924
// We have 1 or more arguments that have closure pointers.
3925
const char *startBuf = SM->getCharacterData(DeclLoc);
3926
const char *startArgList = strchr(startBuf, '(');
3927
3928
assert((*startArgList == '(') && "Rewriter fuzzy parser confused");
3929
3930
parenCount++;
3931
// advance the location to startArgList.
3932
DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);
3933
assert((DeclLoc.isValid()) && "Invalid DeclLoc");
3934
3935
const char *argPtr = startArgList;
3936
3937
while (*argPtr++ && parenCount) {
3938
switch (*argPtr) {
3939
case '^':
3940
// Replace the '^' with '*'.
3941
DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);
3942
ReplaceText(DeclLoc, 1, "*");
3943
break;
3944
case '(':
3945
parenCount++;
3946
break;
3947
case ')':
3948
parenCount--;
3949
break;
3950
}
3951
}
3952
}
3953
3954
bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {
3955
const FunctionProtoType *FTP;
3956
const PointerType *PT = QT->getAs<PointerType>();
3957
if (PT) {
3958
FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
3959
} else {
3960
const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
3961
assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3962
FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
3963
}
3964
if (FTP) {
3965
for (const auto &I : FTP->param_types())
3966
if (isTopLevelBlockPointerType(I))
3967
return true;
3968
}
3969
return false;
3970
}
3971
3972
bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {
3973
const FunctionProtoType *FTP;
3974
const PointerType *PT = QT->getAs<PointerType>();
3975
if (PT) {
3976
FTP = PT->getPointeeType()->getAs<FunctionProtoType>();
3977
} else {
3978
const BlockPointerType *BPT = QT->getAs<BlockPointerType>();
3979
assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
3980
FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();
3981
}
3982
if (FTP) {
3983
for (const auto &I : FTP->param_types()) {
3984
if (I->isObjCQualifiedIdType())
3985
return true;
3986
if (I->isObjCObjectPointerType() &&
3987
I->getPointeeType()->isObjCQualifiedInterfaceType())
3988
return true;
3989
}
3990
3991
}
3992
return false;
3993
}
3994
3995
void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,
3996
const char *&RParen) {
3997
const char *argPtr = strchr(Name, '(');
3998
assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
3999
4000
LParen = argPtr; // output the start.
4001
argPtr++; // skip past the left paren.
4002
unsigned parenCount = 1;
4003
4004
while (*argPtr && parenCount) {
4005
switch (*argPtr) {
4006
case '(': parenCount++; break;
4007
case ')': parenCount--; break;
4008
default: break;
4009
}
4010
if (parenCount) argPtr++;
4011
}
4012
assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
4013
RParen = argPtr; // output the end
4014
}
4015
4016
void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
4017
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
4018
RewriteBlockPointerFunctionArgs(FD);
4019
return;
4020
}
4021
// Handle Variables and Typedefs.
4022
SourceLocation DeclLoc = ND->getLocation();
4023
QualType DeclT;
4024
if (VarDecl *VD = dyn_cast<VarDecl>(ND))
4025
DeclT = VD->getType();
4026
else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
4027
DeclT = TDD->getUnderlyingType();
4028
else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
4029
DeclT = FD->getType();
4030
else
4031
llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");
4032
4033
const char *startBuf = SM->getCharacterData(DeclLoc);
4034
const char *endBuf = startBuf;
4035
// scan backward (from the decl location) for the end of the previous decl.
4036
while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
4037
startBuf--;
4038
SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);
4039
std::string buf;
4040
unsigned OrigLength=0;
4041
// *startBuf != '^' if we are dealing with a pointer to function that
4042
// may take block argument types (which will be handled below).
4043
if (*startBuf == '^') {
4044
// Replace the '^' with '*', computing a negative offset.
4045
buf = '*';
4046
startBuf++;
4047
OrigLength++;
4048
}
4049
while (*startBuf != ')') {
4050
buf += *startBuf;
4051
startBuf++;
4052
OrigLength++;
4053
}
4054
buf += ')';
4055
OrigLength++;
4056
4057
if (PointerTypeTakesAnyBlockArguments(DeclT) ||
4058
PointerTypeTakesAnyObjCQualifiedType(DeclT)) {
4059
// Replace the '^' with '*' for arguments.
4060
// Replace id<P> with id/*<>*/
4061
DeclLoc = ND->getLocation();
4062
startBuf = SM->getCharacterData(DeclLoc);
4063
const char *argListBegin, *argListEnd;
4064
GetExtentOfArgList(startBuf, argListBegin, argListEnd);
4065
while (argListBegin < argListEnd) {
4066
if (*argListBegin == '^')
4067
buf += '*';
4068
else if (*argListBegin == '<') {
4069
buf += "/*";
4070
buf += *argListBegin++;
4071
OrigLength++;
4072
while (*argListBegin != '>') {
4073
buf += *argListBegin++;
4074
OrigLength++;
4075
}
4076
buf += *argListBegin;
4077
buf += "*/";
4078
}
4079
else
4080
buf += *argListBegin;
4081
argListBegin++;
4082
OrigLength++;
4083
}
4084
buf += ')';
4085
OrigLength++;
4086
}
4087
ReplaceText(Start, OrigLength, buf);
4088
}
4089
4090
/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:
4091
/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,
4092
/// struct Block_byref_id_object *src) {
4093
/// _Block_object_assign (&_dest->object, _src->object,
4094
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4095
/// [|BLOCK_FIELD_IS_WEAK]) // object
4096
/// _Block_object_assign(&_dest->object, _src->object,
4097
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4098
/// [|BLOCK_FIELD_IS_WEAK]) // block
4099
/// }
4100
/// And:
4101
/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {
4102
/// _Block_object_dispose(_src->object,
4103
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT
4104
/// [|BLOCK_FIELD_IS_WEAK]) // object
4105
/// _Block_object_dispose(_src->object,
4106
/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK
4107
/// [|BLOCK_FIELD_IS_WEAK]) // block
4108
/// }
4109
4110
std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,
4111
int flag) {
4112
std::string S;
4113
if (CopyDestroyCache.count(flag))
4114
return S;
4115
CopyDestroyCache.insert(flag);
4116
S = "static void __Block_byref_id_object_copy_";
4117
S += utostr(flag);
4118
S += "(void *dst, void *src) {\n";
4119
4120
// offset into the object pointer is computed as:
4121
// void * + void* + int + int + void* + void *
4122
unsigned IntSize =
4123
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4124
unsigned VoidPtrSize =
4125
static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));
4126
4127
unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();
4128
S += " _Block_object_assign((char*)dst + ";
4129
S += utostr(offset);
4130
S += ", *(void * *) ((char*)src + ";
4131
S += utostr(offset);
4132
S += "), ";
4133
S += utostr(flag);
4134
S += ");\n}\n";
4135
4136
S += "static void __Block_byref_id_object_dispose_";
4137
S += utostr(flag);
4138
S += "(void *src) {\n";
4139
S += " _Block_object_dispose(*(void * *) ((char*)src + ";
4140
S += utostr(offset);
4141
S += "), ";
4142
S += utostr(flag);
4143
S += ");\n}\n";
4144
return S;
4145
}
4146
4147
/// RewriteByRefVar - For each __block typex ND variable this routine transforms
4148
/// the declaration into:
4149
/// struct __Block_byref_ND {
4150
/// void *__isa; // NULL for everything except __weak pointers
4151
/// struct __Block_byref_ND *__forwarding;
4152
/// int32_t __flags;
4153
/// int32_t __size;
4154
/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object
4155
/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object
4156
/// typex ND;
4157
/// };
4158
///
4159
/// It then replaces declaration of ND variable with:
4160
/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,
4161
/// __size=sizeof(struct __Block_byref_ND),
4162
/// ND=initializer-if-any};
4163
///
4164
///
4165
void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
4166
// Insert declaration for the function in which block literal is
4167
// used.
4168
if (CurFunctionDeclToDeclareForBlock)
4169
RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);
4170
int flag = 0;
4171
int isa = 0;
4172
SourceLocation DeclLoc = ND->getTypeSpecStartLoc();
4173
if (DeclLoc.isInvalid())
4174
// If type location is missing, it is because of missing type (a warning).
4175
// Use variable's location which is good for this case.
4176
DeclLoc = ND->getLocation();
4177
const char *startBuf = SM->getCharacterData(DeclLoc);
4178
SourceLocation X = ND->getEndLoc();
4179
X = SM->getExpansionLoc(X);
4180
const char *endBuf = SM->getCharacterData(X);
4181
std::string Name(ND->getNameAsString());
4182
std::string ByrefType;
4183
RewriteByRefString(ByrefType, Name, ND, true);
4184
ByrefType += " {\n";
4185
ByrefType += " void *__isa;\n";
4186
RewriteByRefString(ByrefType, Name, ND);
4187
ByrefType += " *__forwarding;\n";
4188
ByrefType += " int __flags;\n";
4189
ByrefType += " int __size;\n";
4190
// Add void *__Block_byref_id_object_copy;
4191
// void *__Block_byref_id_object_dispose; if needed.
4192
QualType Ty = ND->getType();
4193
bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);
4194
if (HasCopyAndDispose) {
4195
ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";
4196
ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";
4197
}
4198
4199
QualType T = Ty;
4200
(void)convertBlockPointerToFunctionPointer(T);
4201
T.getAsStringInternal(Name, Context->getPrintingPolicy());
4202
4203
ByrefType += " " + Name + ";\n";
4204
ByrefType += "};\n";
4205
// Insert this type in global scope. It is needed by helper function.
4206
SourceLocation FunLocStart;
4207
if (CurFunctionDef)
4208
FunLocStart = CurFunctionDef->getTypeSpecStartLoc();
4209
else {
4210
assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");
4211
FunLocStart = CurMethodDef->getBeginLoc();
4212
}
4213
InsertText(FunLocStart, ByrefType);
4214
if (Ty.isObjCGCWeak()) {
4215
flag |= BLOCK_FIELD_IS_WEAK;
4216
isa = 1;
4217
}
4218
4219
if (HasCopyAndDispose) {
4220
flag = BLOCK_BYREF_CALLER;
4221
QualType Ty = ND->getType();
4222
// FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.
4223
if (Ty->isBlockPointerType())
4224
flag |= BLOCK_FIELD_IS_BLOCK;
4225
else
4226
flag |= BLOCK_FIELD_IS_OBJECT;
4227
std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);
4228
if (!HF.empty())
4229
InsertText(FunLocStart, HF);
4230
}
4231
4232
// struct __Block_byref_ND ND =
4233
// {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),
4234
// initializer-if-any};
4235
bool hasInit = (ND->getInit() != nullptr);
4236
unsigned flags = 0;
4237
if (HasCopyAndDispose)
4238
flags |= BLOCK_HAS_COPY_DISPOSE;
4239
Name = ND->getNameAsString();
4240
ByrefType.clear();
4241
RewriteByRefString(ByrefType, Name, ND);
4242
std::string ForwardingCastType("(");
4243
ForwardingCastType += ByrefType + " *)";
4244
if (!hasInit) {
4245
ByrefType += " " + Name + " = {(void*)";
4246
ByrefType += utostr(isa);
4247
ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
4248
ByrefType += utostr(flags);
4249
ByrefType += ", ";
4250
ByrefType += "sizeof(";
4251
RewriteByRefString(ByrefType, Name, ND);
4252
ByrefType += ")";
4253
if (HasCopyAndDispose) {
4254
ByrefType += ", __Block_byref_id_object_copy_";
4255
ByrefType += utostr(flag);
4256
ByrefType += ", __Block_byref_id_object_dispose_";
4257
ByrefType += utostr(flag);
4258
}
4259
ByrefType += "};\n";
4260
unsigned nameSize = Name.size();
4261
// for block or function pointer declaration. Name is already
4262
// part of the declaration.
4263
if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())
4264
nameSize = 1;
4265
ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);
4266
}
4267
else {
4268
SourceLocation startLoc;
4269
Expr *E = ND->getInit();
4270
if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))
4271
startLoc = ECE->getLParenLoc();
4272
else
4273
startLoc = E->getBeginLoc();
4274
startLoc = SM->getExpansionLoc(startLoc);
4275
endBuf = SM->getCharacterData(startLoc);
4276
ByrefType += " " + Name;
4277
ByrefType += " = {(void*)";
4278
ByrefType += utostr(isa);
4279
ByrefType += "," + ForwardingCastType + "&" + Name + ", ";
4280
ByrefType += utostr(flags);
4281
ByrefType += ", ";
4282
ByrefType += "sizeof(";
4283
RewriteByRefString(ByrefType, Name, ND);
4284
ByrefType += "), ";
4285
if (HasCopyAndDispose) {
4286
ByrefType += "__Block_byref_id_object_copy_";
4287
ByrefType += utostr(flag);
4288
ByrefType += ", __Block_byref_id_object_dispose_";
4289
ByrefType += utostr(flag);
4290
ByrefType += ", ";
4291
}
4292
ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);
4293
4294
// Complete the newly synthesized compound expression by inserting a right
4295
// curly brace before the end of the declaration.
4296
// FIXME: This approach avoids rewriting the initializer expression. It
4297
// also assumes there is only one declarator. For example, the following
4298
// isn't currently supported by this routine (in general):
4299
//
4300
// double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;
4301
//
4302
const char *startInitializerBuf = SM->getCharacterData(startLoc);
4303
const char *semiBuf = strchr(startInitializerBuf, ';');
4304
assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");
4305
SourceLocation semiLoc =
4306
startLoc.getLocWithOffset(semiBuf-startInitializerBuf);
4307
4308
InsertText(semiLoc, "}");
4309
}
4310
}
4311
4312
void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {
4313
// Add initializers for any closure decl refs.
4314
GetBlockDeclRefExprs(Exp->getBody());
4315
if (BlockDeclRefs.size()) {
4316
// Unique all "by copy" declarations.
4317
for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
4318
if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4319
if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4320
BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4321
BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl());
4322
}
4323
}
4324
// Unique all "by ref" declarations.
4325
for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
4326
if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) {
4327
if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) {
4328
BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl());
4329
BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl());
4330
}
4331
}
4332
// Find any imported blocks...they will need special attention.
4333
for (unsigned i = 0; i < BlockDeclRefs.size(); i++)
4334
if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4335
BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4336
BlockDeclRefs[i]->getType()->isBlockPointerType())
4337
ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());
4338
}
4339
}
4340
4341
FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {
4342
IdentifierInfo *ID = &Context->Idents.get(name);
4343
QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);
4344
return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),
4345
SourceLocation(), ID, FType, nullptr, SC_Extern,
4346
false, false);
4347
}
4348
4349
Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,
4350
const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {
4351
const BlockDecl *block = Exp->getBlockDecl();
4352
Blocks.push_back(Exp);
4353
4354
CollectBlockDeclRefInfo(Exp);
4355
4356
// Add inner imported variables now used in current block.
4357
int countOfInnerDecls = 0;
4358
if (!InnerBlockDeclRefs.empty()) {
4359
for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {
4360
DeclRefExpr *Exp = InnerBlockDeclRefs[i];
4361
ValueDecl *VD = Exp->getDecl();
4362
if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) {
4363
// We need to save the copied-in variables in nested
4364
// blocks because it is needed at the end for some of the API generations.
4365
// See SynthesizeBlockLiterals routine.
4366
InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4367
BlockDeclRefs.push_back(Exp);
4368
BlockByCopyDeclsPtrSet.insert(VD);
4369
BlockByCopyDecls.push_back(VD);
4370
}
4371
if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) {
4372
InnerDeclRefs.push_back(Exp); countOfInnerDecls++;
4373
BlockDeclRefs.push_back(Exp);
4374
BlockByRefDeclsPtrSet.insert(VD);
4375
BlockByRefDecls.push_back(VD);
4376
}
4377
}
4378
// Find any imported blocks...they will need special attention.
4379
for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)
4380
if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||
4381
InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||
4382
InnerBlockDeclRefs[i]->getType()->isBlockPointerType())
4383
ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());
4384
}
4385
InnerDeclRefsCount.push_back(countOfInnerDecls);
4386
4387
std::string FuncName;
4388
4389
if (CurFunctionDef)
4390
FuncName = CurFunctionDef->getNameAsString();
4391
else if (CurMethodDef)
4392
BuildUniqueMethodName(FuncName, CurMethodDef);
4393
else if (GlobalVarDecl)
4394
FuncName = std::string(GlobalVarDecl->getNameAsString());
4395
4396
std::string BlockNumber = utostr(Blocks.size()-1);
4397
4398
std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;
4399
std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;
4400
4401
// Get a pointer to the function type so we can cast appropriately.
4402
QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());
4403
QualType FType = Context->getPointerType(BFT);
4404
4405
FunctionDecl *FD;
4406
Expr *NewRep;
4407
4408
// Simulate a constructor call...
4409
FD = SynthBlockInitFunctionDecl(Tag);
4410
DeclRefExpr *DRE = new (Context)
4411
DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());
4412
4413
SmallVector<Expr*, 4> InitExprs;
4414
4415
// Initialize the block function.
4416
FD = SynthBlockInitFunctionDecl(Func);
4417
DeclRefExpr *Arg = new (Context) DeclRefExpr(
4418
*Context, FD, false, FD->getType(), VK_LValue, SourceLocation());
4419
CastExpr *castExpr =
4420
NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg);
4421
InitExprs.push_back(castExpr);
4422
4423
// Initialize the block descriptor.
4424
std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";
4425
4426
VarDecl *NewVD = VarDecl::Create(
4427
*Context, TUDecl, SourceLocation(), SourceLocation(),
4428
&Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);
4429
UnaryOperator *DescRefExpr = UnaryOperator::Create(
4430
const_cast<ASTContext &>(*Context),
4431
new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,
4432
VK_LValue, SourceLocation()),
4433
UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,
4434
OK_Ordinary, SourceLocation(), false, FPOptionsOverride());
4435
InitExprs.push_back(DescRefExpr);
4436
4437
// Add initializers for any closure decl refs.
4438
if (BlockDeclRefs.size()) {
4439
Expr *Exp;
4440
// Output all "by copy" declarations.
4441
for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(),
4442
E = BlockByCopyDecls.end(); I != E; ++I) {
4443
if (isObjCType((*I)->getType())) {
4444
// FIXME: Conform to ABI ([[obj retain] autorelease]).
4445
FD = SynthBlockInitFunctionDecl((*I)->getName());
4446
Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
4447
VK_LValue, SourceLocation());
4448
if (HasLocalVariableExternalStorage(*I)) {
4449
QualType QT = (*I)->getType();
4450
QT = Context->getPointerType(QT);
4451
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
4452
UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
4453
SourceLocation(), false,
4454
FPOptionsOverride());
4455
}
4456
} else if (isTopLevelBlockPointerType((*I)->getType())) {
4457
FD = SynthBlockInitFunctionDecl((*I)->getName());
4458
Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
4459
VK_LValue, SourceLocation());
4460
Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast,
4461
Arg);
4462
} else {
4463
FD = SynthBlockInitFunctionDecl((*I)->getName());
4464
Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
4465
VK_LValue, SourceLocation());
4466
if (HasLocalVariableExternalStorage(*I)) {
4467
QualType QT = (*I)->getType();
4468
QT = Context->getPointerType(QT);
4469
Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,
4470
UO_AddrOf, QT, VK_PRValue, OK_Ordinary,
4471
SourceLocation(), false,
4472
FPOptionsOverride());
4473
}
4474
}
4475
InitExprs.push_back(Exp);
4476
}
4477
// Output all "by ref" declarations.
4478
for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(),
4479
E = BlockByRefDecls.end(); I != E; ++I) {
4480
ValueDecl *ND = (*I);
4481
std::string Name(ND->getNameAsString());
4482
std::string RecName;
4483
RewriteByRefString(RecName, Name, ND, true);
4484
IdentifierInfo *II = &Context->Idents.get(RecName.c_str()
4485
+ sizeof("struct"));
4486
RecordDecl *RD =
4487
RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
4488
SourceLocation(), SourceLocation(), II);
4489
assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");
4490
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
4491
4492
FD = SynthBlockInitFunctionDecl((*I)->getName());
4493
Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),
4494
VK_LValue, SourceLocation());
4495
bool isNestedCapturedVar = false;
4496
if (block)
4497
for (const auto &CI : block->captures()) {
4498
const VarDecl *variable = CI.getVariable();
4499
if (variable == ND && CI.isNested()) {
4500
assert (CI.isByRef() &&
4501
"SynthBlockInitExpr - captured block variable is not byref");
4502
isNestedCapturedVar = true;
4503
break;
4504
}
4505
}
4506
// captured nested byref variable has its address passed. Do not take
4507
// its address again.
4508
if (!isNestedCapturedVar)
4509
Exp = UnaryOperator::Create(
4510
const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,
4511
Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,
4512
SourceLocation(), false, FPOptionsOverride());
4513
Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);
4514
InitExprs.push_back(Exp);
4515
}
4516
}
4517
if (ImportedBlockDecls.size()) {
4518
// generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR
4519
int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);
4520
unsigned IntSize =
4521
static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
4522
Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),
4523
Context->IntTy, SourceLocation());
4524
InitExprs.push_back(FlagExp);
4525
}
4526
NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,
4527
SourceLocation(), FPOptionsOverride());
4528
NewRep = UnaryOperator::Create(
4529
const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,
4530
Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,
4531
SourceLocation(), false, FPOptionsOverride());
4532
NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,
4533
NewRep);
4534
BlockDeclRefs.clear();
4535
BlockByRefDecls.clear();
4536
BlockByRefDeclsPtrSet.clear();
4537
BlockByCopyDecls.clear();
4538
BlockByCopyDeclsPtrSet.clear();
4539
ImportedBlockDecls.clear();
4540
return NewRep;
4541
}
4542
4543
bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {
4544
if (const ObjCForCollectionStmt * CS =
4545
dyn_cast<ObjCForCollectionStmt>(Stmts.back()))
4546
return CS->getElement() == DS;
4547
return false;
4548
}
4549
4550
//===----------------------------------------------------------------------===//
4551
// Function Body / Expression rewriting
4552
//===----------------------------------------------------------------------===//
4553
4554
Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
4555
if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4556
isa<DoStmt>(S) || isa<ForStmt>(S))
4557
Stmts.push_back(S);
4558
else if (isa<ObjCForCollectionStmt>(S)) {
4559
Stmts.push_back(S);
4560
ObjCBcLabelNo.push_back(++BcLabelCount);
4561
}
4562
4563
// Pseudo-object operations and ivar references need special
4564
// treatment because we're going to recursively rewrite them.
4565
if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {
4566
if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {
4567
return RewritePropertyOrImplicitSetter(PseudoOp);
4568
} else {
4569
return RewritePropertyOrImplicitGetter(PseudoOp);
4570
}
4571
} else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
4572
return RewriteObjCIvarRefExpr(IvarRefExpr);
4573
}
4574
4575
SourceRange OrigStmtRange = S->getSourceRange();
4576
4577
// Perform a bottom up rewrite of all children.
4578
for (Stmt *&childStmt : S->children())
4579
if (childStmt) {
4580
Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);
4581
if (newStmt) {
4582
childStmt = newStmt;
4583
}
4584
}
4585
4586
if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
4587
SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;
4588
llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
4589
InnerContexts.insert(BE->getBlockDecl());
4590
ImportedLocalExternalDecls.clear();
4591
GetInnerBlockDeclRefExprs(BE->getBody(),
4592
InnerBlockDeclRefs, InnerContexts);
4593
// Rewrite the block body in place.
4594
Stmt *SaveCurrentBody = CurrentBody;
4595
CurrentBody = BE->getBody();
4596
PropParentMap = nullptr;
4597
// block literal on rhs of a property-dot-sytax assignment
4598
// must be replaced by its synthesize ast so getRewrittenText
4599
// works as expected. In this case, what actually ends up on RHS
4600
// is the blockTranscribed which is the helper function for the
4601
// block literal; as in: self.c = ^() {[ace ARR];};
4602
bool saveDisableReplaceStmt = DisableReplaceStmt;
4603
DisableReplaceStmt = false;
4604
RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
4605
DisableReplaceStmt = saveDisableReplaceStmt;
4606
CurrentBody = SaveCurrentBody;
4607
PropParentMap = nullptr;
4608
ImportedLocalExternalDecls.clear();
4609
// Now we snarf the rewritten text and stash it away for later use.
4610
std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
4611
RewrittenBlockExprs[BE] = Str;
4612
4613
Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);
4614
4615
//blockTranscribed->dump();
4616
ReplaceStmt(S, blockTranscribed);
4617
return blockTranscribed;
4618
}
4619
// Handle specific things.
4620
if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
4621
return RewriteAtEncode(AtEncode);
4622
4623
if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))
4624
return RewriteAtSelector(AtSelector);
4625
4626
if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))
4627
return RewriteObjCStringLiteral(AtString);
4628
4629
if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {
4630
#if 0
4631
// Before we rewrite it, put the original message expression in a comment.
4632
SourceLocation startLoc = MessExpr->getBeginLoc();
4633
SourceLocation endLoc = MessExpr->getEndLoc();
4634
4635
const char *startBuf = SM->getCharacterData(startLoc);
4636
const char *endBuf = SM->getCharacterData(endLoc);
4637
4638
std::string messString;
4639
messString += "// ";
4640
messString.append(startBuf, endBuf-startBuf+1);
4641
messString += "\n";
4642
4643
// FIXME: Missing definition of
4644
// InsertText(clang::SourceLocation, char const*, unsigned int).
4645
// InsertText(startLoc, messString);
4646
// Tried this, but it didn't work either...
4647
// ReplaceText(startLoc, 0, messString.c_str(), messString.size());
4648
#endif
4649
return RewriteMessageExpr(MessExpr);
4650
}
4651
4652
if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))
4653
return RewriteObjCTryStmt(StmtTry);
4654
4655
if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))
4656
return RewriteObjCSynchronizedStmt(StmtTry);
4657
4658
if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))
4659
return RewriteObjCThrowStmt(StmtThrow);
4660
4661
if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))
4662
return RewriteObjCProtocolExpr(ProtocolExp);
4663
4664
if (ObjCForCollectionStmt *StmtForCollection =
4665
dyn_cast<ObjCForCollectionStmt>(S))
4666
return RewriteObjCForCollectionStmt(StmtForCollection,
4667
OrigStmtRange.getEnd());
4668
if (BreakStmt *StmtBreakStmt =
4669
dyn_cast<BreakStmt>(S))
4670
return RewriteBreakStmt(StmtBreakStmt);
4671
if (ContinueStmt *StmtContinueStmt =
4672
dyn_cast<ContinueStmt>(S))
4673
return RewriteContinueStmt(StmtContinueStmt);
4674
4675
// Need to check for protocol refs (id <P>, Foo <P> *) in variable decls
4676
// and cast exprs.
4677
if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {
4678
// FIXME: What we're doing here is modifying the type-specifier that
4679
// precedes the first Decl. In the future the DeclGroup should have
4680
// a separate type-specifier that we can rewrite.
4681
// NOTE: We need to avoid rewriting the DeclStmt if it is within
4682
// the context of an ObjCForCollectionStmt. For example:
4683
// NSArray *someArray;
4684
// for (id <FooProtocol> index in someArray) ;
4685
// This is because RewriteObjCForCollectionStmt() does textual rewriting
4686
// and it depends on the original text locations/positions.
4687
if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))
4688
RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());
4689
4690
// Blocks rewrite rules.
4691
for (auto *SD : DS->decls()) {
4692
if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {
4693
if (isTopLevelBlockPointerType(ND->getType()))
4694
RewriteBlockPointerDecl(ND);
4695
else if (ND->getType()->isFunctionPointerType())
4696
CheckFunctionPointerDecl(ND->getType(), ND);
4697
if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {
4698
if (VD->hasAttr<BlocksAttr>()) {
4699
static unsigned uniqueByrefDeclCount = 0;
4700
assert(!BlockByRefDeclNo.count(ND) &&
4701
"RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
4702
BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
4703
RewriteByRefVar(VD);
4704
}
4705
else
4706
RewriteTypeOfDecl(VD);
4707
}
4708
}
4709
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
4710
if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4711
RewriteBlockPointerDecl(TD);
4712
else if (TD->getUnderlyingType()->isFunctionPointerType())
4713
CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4714
}
4715
}
4716
}
4717
4718
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))
4719
RewriteObjCQualifiedInterfaceTypes(CE);
4720
4721
if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||
4722
isa<DoStmt>(S) || isa<ForStmt>(S)) {
4723
assert(!Stmts.empty() && "Statement stack is empty");
4724
assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||
4725
isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))
4726
&& "Statement stack mismatch");
4727
Stmts.pop_back();
4728
}
4729
// Handle blocks rewriting.
4730
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
4731
ValueDecl *VD = DRE->getDecl();
4732
if (VD->hasAttr<BlocksAttr>())
4733
return RewriteBlockDeclRefExpr(DRE);
4734
if (HasLocalVariableExternalStorage(VD))
4735
return RewriteLocalVariableExternalStorage(DRE);
4736
}
4737
4738
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
4739
if (CE->getCallee()->getType()->isBlockPointerType()) {
4740
Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());
4741
ReplaceStmt(S, BlockCall);
4742
return BlockCall;
4743
}
4744
}
4745
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {
4746
RewriteCastExpr(CE);
4747
}
4748
#if 0
4749
if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {
4750
CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),
4751
ICE->getSubExpr(),
4752
SourceLocation());
4753
// Get the new text.
4754
std::string SStr;
4755
llvm::raw_string_ostream Buf(SStr);
4756
Replacement->printPretty(Buf);
4757
const std::string &Str = Buf.str();
4758
4759
printf("CAST = %s\n", &Str[0]);
4760
InsertText(ICE->getSubExpr()->getBeginLoc(), Str);
4761
delete S;
4762
return Replacement;
4763
}
4764
#endif
4765
// Return this stmt unmodified.
4766
return S;
4767
}
4768
4769
void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {
4770
for (auto *FD : RD->fields()) {
4771
if (isTopLevelBlockPointerType(FD->getType()))
4772
RewriteBlockPointerDecl(FD);
4773
if (FD->getType()->isObjCQualifiedIdType() ||
4774
FD->getType()->isObjCQualifiedInterfaceType())
4775
RewriteObjCQualifiedInterfaceTypes(FD);
4776
}
4777
}
4778
4779
/// HandleDeclInMainFile - This is called for each top-level decl defined in the
4780
/// main file of the input.
4781
void RewriteObjC::HandleDeclInMainFile(Decl *D) {
4782
switch (D->getKind()) {
4783
case Decl::Function: {
4784
FunctionDecl *FD = cast<FunctionDecl>(D);
4785
if (FD->isOverloadedOperator())
4786
return;
4787
4788
// Since function prototypes don't have ParmDecl's, we check the function
4789
// prototype. This enables us to rewrite function declarations and
4790
// definitions using the same code.
4791
RewriteBlocksInFunctionProtoType(FD->getType(), FD);
4792
4793
if (!FD->isThisDeclarationADefinition())
4794
break;
4795
4796
// FIXME: If this should support Obj-C++, support CXXTryStmt
4797
if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {
4798
CurFunctionDef = FD;
4799
CurFunctionDeclToDeclareForBlock = FD;
4800
CurrentBody = Body;
4801
Body =
4802
cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4803
FD->setBody(Body);
4804
CurrentBody = nullptr;
4805
if (PropParentMap) {
4806
delete PropParentMap;
4807
PropParentMap = nullptr;
4808
}
4809
// This synthesizes and inserts the block "impl" struct, invoke function,
4810
// and any copy/dispose helper functions.
4811
InsertBlockLiteralsWithinFunction(FD);
4812
CurFunctionDef = nullptr;
4813
CurFunctionDeclToDeclareForBlock = nullptr;
4814
}
4815
break;
4816
}
4817
case Decl::ObjCMethod: {
4818
ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);
4819
if (CompoundStmt *Body = MD->getCompoundBody()) {
4820
CurMethodDef = MD;
4821
CurrentBody = Body;
4822
Body =
4823
cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));
4824
MD->setBody(Body);
4825
CurrentBody = nullptr;
4826
if (PropParentMap) {
4827
delete PropParentMap;
4828
PropParentMap = nullptr;
4829
}
4830
InsertBlockLiteralsWithinMethod(MD);
4831
CurMethodDef = nullptr;
4832
}
4833
break;
4834
}
4835
case Decl::ObjCImplementation: {
4836
ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);
4837
ClassImplementation.push_back(CI);
4838
break;
4839
}
4840
case Decl::ObjCCategoryImpl: {
4841
ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);
4842
CategoryImplementation.push_back(CI);
4843
break;
4844
}
4845
case Decl::Var: {
4846
VarDecl *VD = cast<VarDecl>(D);
4847
RewriteObjCQualifiedInterfaceTypes(VD);
4848
if (isTopLevelBlockPointerType(VD->getType()))
4849
RewriteBlockPointerDecl(VD);
4850
else if (VD->getType()->isFunctionPointerType()) {
4851
CheckFunctionPointerDecl(VD->getType(), VD);
4852
if (VD->getInit()) {
4853
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
4854
RewriteCastExpr(CE);
4855
}
4856
}
4857
} else if (VD->getType()->isRecordType()) {
4858
RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl();
4859
if (RD->isCompleteDefinition())
4860
RewriteRecordBody(RD);
4861
}
4862
if (VD->getInit()) {
4863
GlobalVarDecl = VD;
4864
CurrentBody = VD->getInit();
4865
RewriteFunctionBodyOrGlobalInitializer(VD->getInit());
4866
CurrentBody = nullptr;
4867
if (PropParentMap) {
4868
delete PropParentMap;
4869
PropParentMap = nullptr;
4870
}
4871
SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());
4872
GlobalVarDecl = nullptr;
4873
4874
// This is needed for blocks.
4875
if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {
4876
RewriteCastExpr(CE);
4877
}
4878
}
4879
break;
4880
}
4881
case Decl::TypeAlias:
4882
case Decl::Typedef: {
4883
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
4884
if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
4885
RewriteBlockPointerDecl(TD);
4886
else if (TD->getUnderlyingType()->isFunctionPointerType())
4887
CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);
4888
}
4889
break;
4890
}
4891
case Decl::CXXRecord:
4892
case Decl::Record: {
4893
RecordDecl *RD = cast<RecordDecl>(D);
4894
if (RD->isCompleteDefinition())
4895
RewriteRecordBody(RD);
4896
break;
4897
}
4898
default:
4899
break;
4900
}
4901
// Nothing yet.
4902
}
4903
4904
void RewriteObjC::HandleTranslationUnit(ASTContext &C) {
4905
if (Diags.hasErrorOccurred())
4906
return;
4907
4908
RewriteInclude();
4909
4910
// Here's a great place to add any extra declarations that may be needed.
4911
// Write out meta data for each @protocol(<expr>).
4912
for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls)
4913
RewriteObjCProtocolMetaData(ProtDecl, "", "", Preamble);
4914
4915
InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);
4916
if (ClassImplementation.size() || CategoryImplementation.size())
4917
RewriteImplementations();
4918
4919
// Get the buffer corresponding to MainFileID. If we haven't changed it, then
4920
// we are done.
4921
if (const RewriteBuffer *RewriteBuf =
4922
Rewrite.getRewriteBufferFor(MainFileID)) {
4923
//printf("Changed:\n");
4924
*OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
4925
} else {
4926
llvm::errs() << "No changes\n";
4927
}
4928
4929
if (ClassImplementation.size() || CategoryImplementation.size() ||
4930
ProtocolExprDecls.size()) {
4931
// Rewrite Objective-c meta data*
4932
std::string ResultStr;
4933
RewriteMetaDataIntoBuffer(ResultStr);
4934
// Emit metadata.
4935
*OutFile << ResultStr;
4936
}
4937
OutFile->flush();
4938
}
4939
4940
void RewriteObjCFragileABI::Initialize(ASTContext &context) {
4941
InitializeCommon(context);
4942
4943
// declaring objc_selector outside the parameter list removes a silly
4944
// scope related warning...
4945
if (IsHeader)
4946
Preamble = "#pragma once\n";
4947
Preamble += "struct objc_selector; struct objc_class;\n";
4948
Preamble += "struct __rw_objc_super { struct objc_object *object; ";
4949
Preamble += "struct objc_object *superClass; ";
4950
if (LangOpts.MicrosoftExt) {
4951
// Add a constructor for creating temporary objects.
4952
Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
4953
": ";
4954
Preamble += "object(o), superClass(s) {} ";
4955
}
4956
Preamble += "};\n";
4957
Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
4958
Preamble += "typedef struct objc_object Protocol;\n";
4959
Preamble += "#define _REWRITER_typedef_Protocol\n";
4960
Preamble += "#endif\n";
4961
if (LangOpts.MicrosoftExt) {
4962
Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
4963
Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
4964
} else
4965
Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
4966
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
4967
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
4968
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
4969
Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
4970
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";
4971
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
4972
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";
4973
Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
4974
Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
4975
Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
4976
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
4977
Preamble += "(const char *);\n";
4978
Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";
4979
Preamble += "(struct objc_class *);\n";
4980
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
4981
Preamble += "(const char *);\n";
4982
Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
4983
Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
4984
Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
4985
Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
4986
Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
4987
Preamble += "(struct objc_class *, struct objc_object *);\n";
4988
// @synchronized hooks.
4989
Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";
4990
Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";
4991
Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
4992
Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
4993
Preamble += "struct __objcFastEnumerationState {\n\t";
4994
Preamble += "unsigned long state;\n\t";
4995
Preamble += "void **itemsPtr;\n\t";
4996
Preamble += "unsigned long *mutationsPtr;\n\t";
4997
Preamble += "unsigned long extra[5];\n};\n";
4998
Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
4999
Preamble += "#define __FASTENUMERATIONSTATE\n";
5000
Preamble += "#endif\n";
5001
Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
5002
Preamble += "struct __NSConstantStringImpl {\n";
5003
Preamble += " int *isa;\n";
5004
Preamble += " int flags;\n";
5005
Preamble += " char *str;\n";
5006
Preamble += " long length;\n";
5007
Preamble += "};\n";
5008
Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
5009
Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
5010
Preamble += "#else\n";
5011
Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
5012
Preamble += "#endif\n";
5013
Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
5014
Preamble += "#endif\n";
5015
// Blocks preamble.
5016
Preamble += "#ifndef BLOCK_IMPL\n";
5017
Preamble += "#define BLOCK_IMPL\n";
5018
Preamble += "struct __block_impl {\n";
5019
Preamble += " void *isa;\n";
5020
Preamble += " int Flags;\n";
5021
Preamble += " int Reserved;\n";
5022
Preamble += " void *FuncPtr;\n";
5023
Preamble += "};\n";
5024
Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
5025
Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
5026
Preamble += "extern \"C\" __declspec(dllexport) "
5027
"void _Block_object_assign(void *, const void *, const int);\n";
5028
Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
5029
Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
5030
Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
5031
Preamble += "#else\n";
5032
Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
5033
Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
5034
Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
5035
Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
5036
Preamble += "#endif\n";
5037
Preamble += "#endif\n";
5038
if (LangOpts.MicrosoftExt) {
5039
Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
5040
Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
5041
Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.
5042
Preamble += "#define __attribute__(X)\n";
5043
Preamble += "#endif\n";
5044
Preamble += "#define __weak\n";
5045
}
5046
else {
5047
Preamble += "#define __block\n";
5048
Preamble += "#define __weak\n";
5049
}
5050
// NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long
5051
// as this avoids warning in any 64bit/32bit compilation model.
5052
Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";
5053
}
5054
5055
/// RewriteIvarOffsetComputation - This routine synthesizes computation of
5056
/// ivar offset.
5057
void RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,
5058
std::string &Result) {
5059
if (ivar->isBitField()) {
5060
// FIXME: The hack below doesn't work for bitfields. For now, we simply
5061
// place all bitfields at offset 0.
5062
Result += "0";
5063
} else {
5064
Result += "__OFFSETOFIVAR__(struct ";
5065
Result += ivar->getContainingInterface()->getNameAsString();
5066
if (LangOpts.MicrosoftExt)
5067
Result += "_IMPL";
5068
Result += ", ";
5069
Result += ivar->getNameAsString();
5070
Result += ")";
5071
}
5072
}
5073
5074
/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.
5075
void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(
5076
ObjCProtocolDecl *PDecl, StringRef prefix,
5077
StringRef ClassName, std::string &Result) {
5078
static bool objc_protocol_methods = false;
5079
5080
// Output struct protocol_methods holder of method selector and type.
5081
if (!objc_protocol_methods && PDecl->hasDefinition()) {
5082
/* struct protocol_methods {
5083
SEL _cmd;
5084
char *method_types;
5085
}
5086
*/
5087
Result += "\nstruct _protocol_methods {\n";
5088
Result += "\tstruct objc_selector *_cmd;\n";
5089
Result += "\tchar *method_types;\n";
5090
Result += "};\n";
5091
5092
objc_protocol_methods = true;
5093
}
5094
// Do not synthesize the protocol more than once.
5095
if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))
5096
return;
5097
5098
if (ObjCProtocolDecl *Def = PDecl->getDefinition())
5099
PDecl = Def;
5100
5101
if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
5102
unsigned NumMethods = std::distance(PDecl->instmeth_begin(),
5103
PDecl->instmeth_end());
5104
/* struct _objc_protocol_method_list {
5105
int protocol_method_count;
5106
struct protocol_methods protocols[];
5107
}
5108
*/
5109
Result += "\nstatic struct {\n";
5110
Result += "\tint protocol_method_count;\n";
5111
Result += "\tstruct _protocol_methods protocol_methods[";
5112
Result += utostr(NumMethods);
5113
Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";
5114
Result += PDecl->getNameAsString();
5115
Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "
5116
"{\n\t" + utostr(NumMethods) + "\n";
5117
5118
// Output instance methods declared in this protocol.
5119
for (ObjCProtocolDecl::instmeth_iterator
5120
I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
5121
I != E; ++I) {
5122
if (I == PDecl->instmeth_begin())
5123
Result += "\t ,{{(struct objc_selector *)\"";
5124
else
5125
Result += "\t ,{(struct objc_selector *)\"";
5126
Result += (*I)->getSelector().getAsString();
5127
std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
5128
Result += "\", \"";
5129
Result += MethodTypeString;
5130
Result += "\"}\n";
5131
}
5132
Result += "\t }\n};\n";
5133
}
5134
5135
// Output class methods declared in this protocol.
5136
unsigned NumMethods = std::distance(PDecl->classmeth_begin(),
5137
PDecl->classmeth_end());
5138
if (NumMethods > 0) {
5139
/* struct _objc_protocol_method_list {
5140
int protocol_method_count;
5141
struct protocol_methods protocols[];
5142
}
5143
*/
5144
Result += "\nstatic struct {\n";
5145
Result += "\tint protocol_method_count;\n";
5146
Result += "\tstruct _protocol_methods protocol_methods[";
5147
Result += utostr(NumMethods);
5148
Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";
5149
Result += PDecl->getNameAsString();
5150
Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
5151
"{\n\t";
5152
Result += utostr(NumMethods);
5153
Result += "\n";
5154
5155
// Output instance methods declared in this protocol.
5156
for (ObjCProtocolDecl::classmeth_iterator
5157
I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
5158
I != E; ++I) {
5159
if (I == PDecl->classmeth_begin())
5160
Result += "\t ,{{(struct objc_selector *)\"";
5161
else
5162
Result += "\t ,{(struct objc_selector *)\"";
5163
Result += (*I)->getSelector().getAsString();
5164
std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);
5165
Result += "\", \"";
5166
Result += MethodTypeString;
5167
Result += "\"}\n";
5168
}
5169
Result += "\t }\n};\n";
5170
}
5171
5172
// Output:
5173
/* struct _objc_protocol {
5174
// Objective-C 1.0 extensions
5175
struct _objc_protocol_extension *isa;
5176
char *protocol_name;
5177
struct _objc_protocol **protocol_list;
5178
struct _objc_protocol_method_list *instance_methods;
5179
struct _objc_protocol_method_list *class_methods;
5180
};
5181
*/
5182
static bool objc_protocol = false;
5183
if (!objc_protocol) {
5184
Result += "\nstruct _objc_protocol {\n";
5185
Result += "\tstruct _objc_protocol_extension *isa;\n";
5186
Result += "\tchar *protocol_name;\n";
5187
Result += "\tstruct _objc_protocol **protocol_list;\n";
5188
Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";
5189
Result += "\tstruct _objc_protocol_method_list *class_methods;\n";
5190
Result += "};\n";
5191
5192
objc_protocol = true;
5193
}
5194
5195
Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";
5196
Result += PDecl->getNameAsString();
5197
Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "
5198
"{\n\t0, \"";
5199
Result += PDecl->getNameAsString();
5200
Result += "\", 0, ";
5201
if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {
5202
Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";
5203
Result += PDecl->getNameAsString();
5204
Result += ", ";
5205
}
5206
else
5207
Result += "0, ";
5208
if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {
5209
Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";
5210
Result += PDecl->getNameAsString();
5211
Result += "\n";
5212
}
5213
else
5214
Result += "0\n";
5215
Result += "};\n";
5216
5217
// Mark this protocol as having been generated.
5218
if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)
5219
llvm_unreachable("protocol already synthesized");
5220
}
5221
5222
void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(
5223
const ObjCList<ObjCProtocolDecl> &Protocols,
5224
StringRef prefix, StringRef ClassName,
5225
std::string &Result) {
5226
if (Protocols.empty()) return;
5227
5228
for (unsigned i = 0; i != Protocols.size(); i++)
5229
RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);
5230
5231
// Output the top lovel protocol meta-data for the class.
5232
/* struct _objc_protocol_list {
5233
struct _objc_protocol_list *next;
5234
int protocol_count;
5235
struct _objc_protocol *class_protocols[];
5236
}
5237
*/
5238
Result += "\nstatic struct {\n";
5239
Result += "\tstruct _objc_protocol_list *next;\n";
5240
Result += "\tint protocol_count;\n";
5241
Result += "\tstruct _objc_protocol *class_protocols[";
5242
Result += utostr(Protocols.size());
5243
Result += "];\n} _OBJC_";
5244
Result += prefix;
5245
Result += "_PROTOCOLS_";
5246
Result += ClassName;
5247
Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "
5248
"{\n\t0, ";
5249
Result += utostr(Protocols.size());
5250
Result += "\n";
5251
5252
Result += "\t,{&_OBJC_PROTOCOL_";
5253
Result += Protocols[0]->getNameAsString();
5254
Result += " \n";
5255
5256
for (unsigned i = 1; i != Protocols.size(); i++) {
5257
Result += "\t ,&_OBJC_PROTOCOL_";
5258
Result += Protocols[i]->getNameAsString();
5259
Result += "\n";
5260
}
5261
Result += "\t }\n};\n";
5262
}
5263
5264
void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
5265
std::string &Result) {
5266
ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();
5267
5268
// Explicitly declared @interface's are already synthesized.
5269
if (CDecl->isImplicitInterfaceDecl()) {
5270
// FIXME: Implementation of a class with no @interface (legacy) does not
5271
// produce correct synthesis as yet.
5272
RewriteObjCInternalStruct(CDecl, Result);
5273
}
5274
5275
// Build _objc_ivar_list metadata for classes ivars if needed
5276
unsigned NumIvars =
5277
!IDecl->ivar_empty() ? IDecl->ivar_size() : CDecl->ivar_size();
5278
if (NumIvars > 0) {
5279
static bool objc_ivar = false;
5280
if (!objc_ivar) {
5281
/* struct _objc_ivar {
5282
char *ivar_name;
5283
char *ivar_type;
5284
int ivar_offset;
5285
};
5286
*/
5287
Result += "\nstruct _objc_ivar {\n";
5288
Result += "\tchar *ivar_name;\n";
5289
Result += "\tchar *ivar_type;\n";
5290
Result += "\tint ivar_offset;\n";
5291
Result += "};\n";
5292
5293
objc_ivar = true;
5294
}
5295
5296
/* struct {
5297
int ivar_count;
5298
struct _objc_ivar ivar_list[nIvars];
5299
};
5300
*/
5301
Result += "\nstatic struct {\n";
5302
Result += "\tint ivar_count;\n";
5303
Result += "\tstruct _objc_ivar ivar_list[";
5304
Result += utostr(NumIvars);
5305
Result += "];\n} _OBJC_INSTANCE_VARIABLES_";
5306
Result += IDecl->getNameAsString();
5307
Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "
5308
"{\n\t";
5309
Result += utostr(NumIvars);
5310
Result += "\n";
5311
5312
ObjCInterfaceDecl::ivar_iterator IVI, IVE;
5313
SmallVector<ObjCIvarDecl *, 8> IVars;
5314
if (!IDecl->ivar_empty()) {
5315
for (auto *IV : IDecl->ivars())
5316
IVars.push_back(IV);
5317
IVI = IDecl->ivar_begin();
5318
IVE = IDecl->ivar_end();
5319
} else {
5320
IVI = CDecl->ivar_begin();
5321
IVE = CDecl->ivar_end();
5322
}
5323
Result += "\t,{{\"";
5324
Result += IVI->getNameAsString();
5325
Result += "\", \"";
5326
std::string TmpString, StrEncoding;
5327
Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);
5328
QuoteDoublequotes(TmpString, StrEncoding);
5329
Result += StrEncoding;
5330
Result += "\", ";
5331
RewriteIvarOffsetComputation(*IVI, Result);
5332
Result += "}\n";
5333
for (++IVI; IVI != IVE; ++IVI) {
5334
Result += "\t ,{\"";
5335
Result += IVI->getNameAsString();
5336
Result += "\", \"";
5337
std::string TmpString, StrEncoding;
5338
Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);
5339
QuoteDoublequotes(TmpString, StrEncoding);
5340
Result += StrEncoding;
5341
Result += "\", ";
5342
RewriteIvarOffsetComputation(*IVI, Result);
5343
Result += "}\n";
5344
}
5345
5346
Result += "\t }\n};\n";
5347
}
5348
5349
// Build _objc_method_list for class's instance methods if needed
5350
SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
5351
5352
// If any of our property implementations have associated getters or
5353
// setters, produce metadata for them as well.
5354
for (const auto *Prop : IDecl->property_impls()) {
5355
if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
5356
continue;
5357
if (!Prop->getPropertyIvarDecl())
5358
continue;
5359
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
5360
if (!PD)
5361
continue;
5362
if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
5363
if (!Getter->isDefined())
5364
InstanceMethods.push_back(Getter);
5365
if (PD->isReadOnly())
5366
continue;
5367
if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
5368
if (!Setter->isDefined())
5369
InstanceMethods.push_back(Setter);
5370
}
5371
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5372
true, "", IDecl->getName(), Result);
5373
5374
// Build _objc_method_list for class's class methods if needed
5375
RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
5376
false, "", IDecl->getName(), Result);
5377
5378
// Protocols referenced in class declaration?
5379
RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),
5380
"CLASS", CDecl->getName(), Result);
5381
5382
// Declaration of class/meta-class metadata
5383
/* struct _objc_class {
5384
struct _objc_class *isa; // or const char *root_class_name when metadata
5385
const char *super_class_name;
5386
char *name;
5387
long version;
5388
long info;
5389
long instance_size;
5390
struct _objc_ivar_list *ivars;
5391
struct _objc_method_list *methods;
5392
struct objc_cache *cache;
5393
struct objc_protocol_list *protocols;
5394
const char *ivar_layout;
5395
struct _objc_class_ext *ext;
5396
};
5397
*/
5398
static bool objc_class = false;
5399
if (!objc_class) {
5400
Result += "\nstruct _objc_class {\n";
5401
Result += "\tstruct _objc_class *isa;\n";
5402
Result += "\tconst char *super_class_name;\n";
5403
Result += "\tchar *name;\n";
5404
Result += "\tlong version;\n";
5405
Result += "\tlong info;\n";
5406
Result += "\tlong instance_size;\n";
5407
Result += "\tstruct _objc_ivar_list *ivars;\n";
5408
Result += "\tstruct _objc_method_list *methods;\n";
5409
Result += "\tstruct objc_cache *cache;\n";
5410
Result += "\tstruct _objc_protocol_list *protocols;\n";
5411
Result += "\tconst char *ivar_layout;\n";
5412
Result += "\tstruct _objc_class_ext *ext;\n";
5413
Result += "};\n";
5414
objc_class = true;
5415
}
5416
5417
// Meta-class metadata generation.
5418
ObjCInterfaceDecl *RootClass = nullptr;
5419
ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();
5420
while (SuperClass) {
5421
RootClass = SuperClass;
5422
SuperClass = SuperClass->getSuperClass();
5423
}
5424
SuperClass = CDecl->getSuperClass();
5425
5426
Result += "\nstatic struct _objc_class _OBJC_METACLASS_";
5427
Result += CDecl->getNameAsString();
5428
Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "
5429
"{\n\t(struct _objc_class *)\"";
5430
Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());
5431
Result += "\"";
5432
5433
if (SuperClass) {
5434
Result += ", \"";
5435
Result += SuperClass->getNameAsString();
5436
Result += "\", \"";
5437
Result += CDecl->getNameAsString();
5438
Result += "\"";
5439
}
5440
else {
5441
Result += ", 0, \"";
5442
Result += CDecl->getNameAsString();
5443
Result += "\"";
5444
}
5445
// Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.
5446
// 'info' field is initialized to CLS_META(2) for metaclass
5447
Result += ", 0,2, sizeof(struct _objc_class), 0";
5448
if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
5449
Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";
5450
Result += IDecl->getNameAsString();
5451
Result += "\n";
5452
}
5453
else
5454
Result += ", 0\n";
5455
if (CDecl->protocol_begin() != CDecl->protocol_end()) {
5456
Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";
5457
Result += CDecl->getNameAsString();
5458
Result += ",0,0\n";
5459
}
5460
else
5461
Result += "\t,0,0,0,0\n";
5462
Result += "};\n";
5463
5464
// class metadata generation.
5465
Result += "\nstatic struct _objc_class _OBJC_CLASS_";
5466
Result += CDecl->getNameAsString();
5467
Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "
5468
"{\n\t&_OBJC_METACLASS_";
5469
Result += CDecl->getNameAsString();
5470
if (SuperClass) {
5471
Result += ", \"";
5472
Result += SuperClass->getNameAsString();
5473
Result += "\", \"";
5474
Result += CDecl->getNameAsString();
5475
Result += "\"";
5476
}
5477
else {
5478
Result += ", 0, \"";
5479
Result += CDecl->getNameAsString();
5480
Result += "\"";
5481
}
5482
// 'info' field is initialized to CLS_CLASS(1) for class
5483
Result += ", 0,1";
5484
if (!ObjCSynthesizedStructs.count(CDecl))
5485
Result += ",0";
5486
else {
5487
// class has size. Must synthesize its size.
5488
Result += ",sizeof(struct ";
5489
Result += CDecl->getNameAsString();
5490
if (LangOpts.MicrosoftExt)
5491
Result += "_IMPL";
5492
Result += ")";
5493
}
5494
if (NumIvars > 0) {
5495
Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";
5496
Result += CDecl->getNameAsString();
5497
Result += "\n\t";
5498
}
5499
else
5500
Result += ",0";
5501
if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
5502
Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";
5503
Result += CDecl->getNameAsString();
5504
Result += ", 0\n\t";
5505
}
5506
else
5507
Result += ",0,0";
5508
if (CDecl->protocol_begin() != CDecl->protocol_end()) {
5509
Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";
5510
Result += CDecl->getNameAsString();
5511
Result += ", 0,0\n";
5512
}
5513
else
5514
Result += ",0,0,0\n";
5515
Result += "};\n";
5516
}
5517
5518
void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {
5519
int ClsDefCount = ClassImplementation.size();
5520
int CatDefCount = CategoryImplementation.size();
5521
5522
// For each implemented class, write out all its meta data.
5523
for (int i = 0; i < ClsDefCount; i++)
5524
RewriteObjCClassMetaData(ClassImplementation[i], Result);
5525
5526
// For each implemented category, write out all its meta data.
5527
for (int i = 0; i < CatDefCount; i++)
5528
RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);
5529
5530
// Write objc_symtab metadata
5531
/*
5532
struct _objc_symtab
5533
{
5534
long sel_ref_cnt;
5535
SEL *refs;
5536
short cls_def_cnt;
5537
short cat_def_cnt;
5538
void *defs[cls_def_cnt + cat_def_cnt];
5539
};
5540
*/
5541
5542
Result += "\nstruct _objc_symtab {\n";
5543
Result += "\tlong sel_ref_cnt;\n";
5544
Result += "\tSEL *refs;\n";
5545
Result += "\tshort cls_def_cnt;\n";
5546
Result += "\tshort cat_def_cnt;\n";
5547
Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";
5548
Result += "};\n\n";
5549
5550
Result += "static struct _objc_symtab "
5551
"_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";
5552
Result += "\t0, 0, " + utostr(ClsDefCount)
5553
+ ", " + utostr(CatDefCount) + "\n";
5554
for (int i = 0; i < ClsDefCount; i++) {
5555
Result += "\t,&_OBJC_CLASS_";
5556
Result += ClassImplementation[i]->getNameAsString();
5557
Result += "\n";
5558
}
5559
5560
for (int i = 0; i < CatDefCount; i++) {
5561
Result += "\t,&_OBJC_CATEGORY_";
5562
Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();
5563
Result += "_";
5564
Result += CategoryImplementation[i]->getNameAsString();
5565
Result += "\n";
5566
}
5567
5568
Result += "};\n\n";
5569
5570
// Write objc_module metadata
5571
5572
/*
5573
struct _objc_module {
5574
long version;
5575
long size;
5576
const char *name;
5577
struct _objc_symtab *symtab;
5578
}
5579
*/
5580
5581
Result += "\nstruct _objc_module {\n";
5582
Result += "\tlong version;\n";
5583
Result += "\tlong size;\n";
5584
Result += "\tconst char *name;\n";
5585
Result += "\tstruct _objc_symtab *symtab;\n";
5586
Result += "};\n\n";
5587
Result += "static struct _objc_module "
5588
"_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";
5589
Result += "\t" + utostr(OBJC_ABI_VERSION) +
5590
", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";
5591
Result += "};\n\n";
5592
5593
if (LangOpts.MicrosoftExt) {
5594
if (ProtocolExprDecls.size()) {
5595
Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";
5596
Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";
5597
for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {
5598
Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";
5599
Result += ProtDecl->getNameAsString();
5600
Result += " = &_OBJC_PROTOCOL_";
5601
Result += ProtDecl->getNameAsString();
5602
Result += ";\n";
5603
}
5604
Result += "#pragma data_seg(pop)\n\n";
5605
}
5606
Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";
5607
Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";
5608
Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";
5609
Result += "&_OBJC_MODULES;\n";
5610
Result += "#pragma data_seg(pop)\n\n";
5611
}
5612
}
5613
5614
/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category
5615
/// implementation.
5616
void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,
5617
std::string &Result) {
5618
ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();
5619
// Find category declaration for this implementation.
5620
ObjCCategoryDecl *CDecl
5621
= ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());
5622
5623
std::string FullCategoryName = ClassDecl->getNameAsString();
5624
FullCategoryName += '_';
5625
FullCategoryName += IDecl->getNameAsString();
5626
5627
// Build _objc_method_list for class's instance methods if needed
5628
SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());
5629
5630
// If any of our property implementations have associated getters or
5631
// setters, produce metadata for them as well.
5632
for (const auto *Prop : IDecl->property_impls()) {
5633
if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
5634
continue;
5635
if (!Prop->getPropertyIvarDecl())
5636
continue;
5637
ObjCPropertyDecl *PD = Prop->getPropertyDecl();
5638
if (!PD)
5639
continue;
5640
if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())
5641
InstanceMethods.push_back(Getter);
5642
if (PD->isReadOnly())
5643
continue;
5644
if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())
5645
InstanceMethods.push_back(Setter);
5646
}
5647
RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),
5648
true, "CATEGORY_", FullCategoryName, Result);
5649
5650
// Build _objc_method_list for class's class methods if needed
5651
RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),
5652
false, "CATEGORY_", FullCategoryName, Result);
5653
5654
// Protocols referenced in class declaration?
5655
// Null CDecl is case of a category implementation with no category interface
5656
if (CDecl)
5657
RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",
5658
FullCategoryName, Result);
5659
/* struct _objc_category {
5660
char *category_name;
5661
char *class_name;
5662
struct _objc_method_list *instance_methods;
5663
struct _objc_method_list *class_methods;
5664
struct _objc_protocol_list *protocols;
5665
// Objective-C 1.0 extensions
5666
uint32_t size; // sizeof (struct _objc_category)
5667
struct _objc_property_list *instance_properties; // category's own
5668
// @property decl.
5669
};
5670
*/
5671
5672
static bool objc_category = false;
5673
if (!objc_category) {
5674
Result += "\nstruct _objc_category {\n";
5675
Result += "\tchar *category_name;\n";
5676
Result += "\tchar *class_name;\n";
5677
Result += "\tstruct _objc_method_list *instance_methods;\n";
5678
Result += "\tstruct _objc_method_list *class_methods;\n";
5679
Result += "\tstruct _objc_protocol_list *protocols;\n";
5680
Result += "\tunsigned int size;\n";
5681
Result += "\tstruct _objc_property_list *instance_properties;\n";
5682
Result += "};\n";
5683
objc_category = true;
5684
}
5685
Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";
5686
Result += FullCategoryName;
5687
Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";
5688
Result += IDecl->getNameAsString();
5689
Result += "\"\n\t, \"";
5690
Result += ClassDecl->getNameAsString();
5691
Result += "\"\n";
5692
5693
if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {
5694
Result += "\t, (struct _objc_method_list *)"
5695
"&_OBJC_CATEGORY_INSTANCE_METHODS_";
5696
Result += FullCategoryName;
5697
Result += "\n";
5698
}
5699
else
5700
Result += "\t, 0\n";
5701
if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {
5702
Result += "\t, (struct _objc_method_list *)"
5703
"&_OBJC_CATEGORY_CLASS_METHODS_";
5704
Result += FullCategoryName;
5705
Result += "\n";
5706
}
5707
else
5708
Result += "\t, 0\n";
5709
5710
if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {
5711
Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";
5712
Result += FullCategoryName;
5713
Result += "\n";
5714
}
5715
else
5716
Result += "\t, 0\n";
5717
Result += "\t, sizeof(struct _objc_category), 0\n};\n";
5718
}
5719
5720
// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
5721
/// class methods.
5722
template<typename MethodIterator>
5723
void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
5724
MethodIterator MethodEnd,
5725
bool IsInstanceMethod,
5726
StringRef prefix,
5727
StringRef ClassName,
5728
std::string &Result) {
5729
if (MethodBegin == MethodEnd) return;
5730
5731
if (!objc_impl_method) {
5732
/* struct _objc_method {
5733
SEL _cmd;
5734
char *method_types;
5735
void *_imp;
5736
}
5737
*/
5738
Result += "\nstruct _objc_method {\n";
5739
Result += "\tSEL _cmd;\n";
5740
Result += "\tchar *method_types;\n";
5741
Result += "\tvoid *_imp;\n";
5742
Result += "};\n";
5743
5744
objc_impl_method = true;
5745
}
5746
5747
// Build _objc_method_list for class's methods if needed
5748
5749
/* struct {
5750
struct _objc_method_list *next_method;
5751
int method_count;
5752
struct _objc_method method_list[];
5753
}
5754
*/
5755
unsigned NumMethods = std::distance(MethodBegin, MethodEnd);
5756
Result += "\nstatic struct {\n";
5757
Result += "\tstruct _objc_method_list *next_method;\n";
5758
Result += "\tint method_count;\n";
5759
Result += "\tstruct _objc_method method_list[";
5760
Result += utostr(NumMethods);
5761
Result += "];\n} _OBJC_";
5762
Result += prefix;
5763
Result += IsInstanceMethod ? "INSTANCE" : "CLASS";
5764
Result += "_METHODS_";
5765
Result += ClassName;
5766
Result += " __attribute__ ((used, section (\"__OBJC, __";
5767
Result += IsInstanceMethod ? "inst" : "cls";
5768
Result += "_meth\")))= ";
5769
Result += "{\n\t0, " + utostr(NumMethods) + "\n";
5770
5771
Result += "\t,{{(SEL)\"";
5772
Result += (*MethodBegin)->getSelector().getAsString();
5773
std::string MethodTypeString =
5774
Context->getObjCEncodingForMethodDecl(*MethodBegin);
5775
Result += "\", \"";
5776
Result += MethodTypeString;
5777
Result += "\", (void *)";
5778
Result += MethodInternalNames[*MethodBegin];
5779
Result += "}\n";
5780
for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {
5781
Result += "\t ,{(SEL)\"";
5782
Result += (*MethodBegin)->getSelector().getAsString();
5783
std::string MethodTypeString =
5784
Context->getObjCEncodingForMethodDecl(*MethodBegin);
5785
Result += "\", \"";
5786
Result += MethodTypeString;
5787
Result += "\", (void *)";
5788
Result += MethodInternalNames[*MethodBegin];
5789
Result += "}\n";
5790
}
5791
Result += "\t }\n};\n";
5792
}
5793
5794
Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {
5795
SourceRange OldRange = IV->getSourceRange();
5796
Expr *BaseExpr = IV->getBase();
5797
5798
// Rewrite the base, but without actually doing replaces.
5799
{
5800
DisableReplaceStmtScope S(*this);
5801
BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));
5802
IV->setBase(BaseExpr);
5803
}
5804
5805
ObjCIvarDecl *D = IV->getDecl();
5806
5807
Expr *Replacement = IV;
5808
if (CurMethodDef) {
5809
if (BaseExpr->getType()->isObjCObjectPointerType()) {
5810
const ObjCInterfaceType *iFaceDecl =
5811
dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
5812
assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
5813
// lookup which class implements the instance variable.
5814
ObjCInterfaceDecl *clsDeclared = nullptr;
5815
iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
5816
clsDeclared);
5817
assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
5818
5819
// Synthesize an explicit cast to gain access to the ivar.
5820
std::string RecName =
5821
std::string(clsDeclared->getIdentifier()->getName());
5822
RecName += "_IMPL";
5823
IdentifierInfo *II = &Context->Idents.get(RecName);
5824
RecordDecl *RD =
5825
RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
5826
SourceLocation(), SourceLocation(), II);
5827
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5828
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
5829
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
5830
CK_BitCast,
5831
IV->getBase());
5832
// Don't forget the parens to enforce the proper binding.
5833
ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),
5834
OldRange.getEnd(),
5835
castExpr);
5836
if (IV->isFreeIvar() &&
5837
declaresSameEntity(CurMethodDef->getClassInterface(),
5838
iFaceDecl->getDecl())) {
5839
MemberExpr *ME = MemberExpr::CreateImplicit(
5840
*Context, PE, true, D, D->getType(), VK_LValue, OK_Ordinary);
5841
Replacement = ME;
5842
} else {
5843
IV->setBase(PE);
5844
}
5845
}
5846
} else { // we are outside a method.
5847
assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
5848
5849
// Explicit ivar refs need to have a cast inserted.
5850
// FIXME: consider sharing some of this code with the code above.
5851
if (BaseExpr->getType()->isObjCObjectPointerType()) {
5852
const ObjCInterfaceType *iFaceDecl =
5853
dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
5854
// lookup which class implements the instance variable.
5855
ObjCInterfaceDecl *clsDeclared = nullptr;
5856
iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
5857
clsDeclared);
5858
assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
5859
5860
// Synthesize an explicit cast to gain access to the ivar.
5861
std::string RecName =
5862
std::string(clsDeclared->getIdentifier()->getName());
5863
RecName += "_IMPL";
5864
IdentifierInfo *II = &Context->Idents.get(RecName);
5865
RecordDecl *RD =
5866
RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,
5867
SourceLocation(), SourceLocation(), II);
5868
assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
5869
QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
5870
CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
5871
CK_BitCast,
5872
IV->getBase());
5873
// Don't forget the parens to enforce the proper binding.
5874
ParenExpr *PE = new (Context) ParenExpr(
5875
IV->getBase()->getBeginLoc(), IV->getBase()->getEndLoc(), castExpr);
5876
// Cannot delete IV->getBase(), since PE points to it.
5877
// Replace the old base with the cast. This is important when doing
5878
// embedded rewrites. For example, [newInv->_container addObject:0].
5879
IV->setBase(PE);
5880
}
5881
}
5882
5883
ReplaceStmtWithRange(IV, Replacement, OldRange);
5884
return Replacement;
5885
}
5886
5887
#endif // CLANG_ENABLE_OBJC_REWRITER
5888
5889