 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
67.0% |
1062 / 1585 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
88.2% |
1398 / 1585 |
| |
|
Line Coverage: |
88.7% |
2463 / 2776 |
| |
 |
|
 |
1 : //===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // Hacks and fun related to the code rewriter.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "clang/Frontend/ASTConsumers.h"
15 : #include "clang/Rewrite/Rewriter.h"
16 : #include "clang/AST/AST.h"
17 : #include "clang/AST/ASTConsumer.h"
18 : #include "clang/AST/ParentMap.h"
19 : #include "clang/Basic/SourceManager.h"
20 : #include "clang/Basic/IdentifierTable.h"
21 : #include "clang/Basic/Diagnostic.h"
22 : #include "clang/Lex/Lexer.h"
23 : #include "llvm/Support/MemoryBuffer.h"
24 : #include "llvm/Support/raw_ostream.h"
25 : #include "llvm/ADT/StringExtras.h"
26 : #include "llvm/ADT/SmallPtrSet.h"
27 : #include "llvm/ADT/OwningPtr.h"
28 : #include "llvm/ADT/DenseSet.h"
29 : using namespace clang;
30 : using llvm::utostr;
31 :
32 : namespace {
33 : class RewriteObjC : public ASTConsumer {
34 : enum {
35 : BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
36 : block, ... */
37 : BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
38 : BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the
39 : __block variable */
40 : BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy
41 : helpers */
42 : BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose
43 : support routines */
44 : BLOCK_BYREF_CURRENT_MAX = 256
45 : };
46 :
47 : enum {
48 : BLOCK_NEEDS_FREE = (1 << 24),
49 : BLOCK_HAS_COPY_DISPOSE = (1 << 25),
50 : BLOCK_HAS_CXX_OBJ = (1 << 26),
51 : BLOCK_IS_GC = (1 << 27),
52 : BLOCK_IS_GLOBAL = (1 << 28),
53 : BLOCK_HAS_DESCRIPTOR = (1 << 29)
54 : };
55 :
56 : Rewriter Rewrite;
57 : Diagnostic &Diags;
58 : const LangOptions &LangOpts;
59 : unsigned RewriteFailedDiag;
60 : unsigned TryFinallyContainsReturnDiag;
61 :
62 : ASTContext *Context;
63 : SourceManager *SM;
64 : TranslationUnitDecl *TUDecl;
65 : FileID MainFileID;
66 : const char *MainFileStart, *MainFileEnd;
67 : SourceLocation LastIncLoc;
68 :
69 : llvm::SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
70 : llvm::SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
71 : llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
72 : llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
73 : llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
74 : llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
75 : llvm::SmallVector<Stmt *, 32> Stmts;
76 : llvm::SmallVector<int, 8> ObjCBcLabelNo;
77 : // Remember all the @protocol(<expr>) expressions.
78 : llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
79 :
80 : llvm::DenseSet<uint64_t> CopyDestroyCache;
81 :
82 : unsigned NumObjCStringLiterals;
83 :
84 : FunctionDecl *MsgSendFunctionDecl;
85 : FunctionDecl *MsgSendSuperFunctionDecl;
86 : FunctionDecl *MsgSendStretFunctionDecl;
87 : FunctionDecl *MsgSendSuperStretFunctionDecl;
88 : FunctionDecl *MsgSendFpretFunctionDecl;
89 : FunctionDecl *GetClassFunctionDecl;
90 : FunctionDecl *GetMetaClassFunctionDecl;
91 : FunctionDecl *SelGetUidFunctionDecl;
92 : FunctionDecl *CFStringFunctionDecl;
93 : FunctionDecl *SuperContructorFunctionDecl;
94 :
95 : // ObjC string constant support.
96 : VarDecl *ConstantStringClassReference;
97 : RecordDecl *NSStringRecord;
98 :
99 : // ObjC foreach break/continue generation support.
100 : int BcLabelCount;
101 :
102 : // Needed for super.
103 : ObjCMethodDecl *CurMethodDef;
104 : RecordDecl *SuperStructDecl;
105 : RecordDecl *ConstantStringDecl;
106 :
107 : TypeDecl *ProtocolTypeDecl;
108 : QualType getProtocolType();
109 :
110 : // Needed for header files being rewritten
111 : bool IsHeader;
112 :
113 : std::string InFileName;
114 : llvm::raw_ostream* OutFile;
115 :
116 : bool SilenceRewriteMacroWarning;
117 : bool objc_impl_method;
118 :
119 : std::string Preamble;
120 :
121 : // Block expressions.
122 : llvm::SmallVector<BlockExpr *, 32> Blocks;
123 : llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
124 : llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs;
125 :
126 : // Block related declarations.
127 : llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
128 : llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
129 : llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
130 : llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
131 :
132 : llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
133 :
134 : // This maps a property to it's assignment statement.
135 : llvm::DenseMap<ObjCPropertyRefExpr *, BinaryOperator *> PropSetters;
136 : // This maps a property to it's synthesied message expression.
137 : // This allows us to rewrite chained getters (e.g. o.a.b.c).
138 : llvm::DenseMap<ObjCPropertyRefExpr *, Stmt *> PropGetters;
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 : FunctionDecl *CurFunctionDef;
146 : FunctionDecl *CurFunctionDeclToDeclareForBlock;
147 : VarDecl *GlobalVarDecl;
148 :
149 : bool DisableReplaceStmt;
150 :
151 : static const int OBJC_ABI_VERSION =7 ;
152 : public:
153 : virtual void Initialize(ASTContext &context);
154 :
155 : // Top Level Driver code.
156 320: virtual void HandleTopLevelDecl(DeclGroupRef D) {
330: branch 2 taken
320: branch 3 taken
157 650: for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
158 330: HandleTopLevelSingleDecl(*I);
159 320: }
160 : void HandleTopLevelSingleDecl(Decl *D);
161 : void HandleDeclInMainFile(Decl *D);
162 : RewriteObjC(std::string inFile, llvm::raw_ostream *OS,
163 : Diagnostic &D, const LangOptions &LOpts,
164 : bool silenceMacroWarn);
165 :
51: branch 25 taken
0: branch 26 not taken
0: branch 53 not taken
0: branch 54 not taken
166 51: ~RewriteObjC() {}
167 :
168 : virtual void HandleTranslationUnit(ASTContext &C);
169 :
170 138: void ReplaceStmt(Stmt *Old, Stmt *New) {
171 138: Stmt *ReplacingStmt = ReplacedNodes[Old];
172 :
0: branch 0 not taken
138: branch 1 taken
173 138: if (ReplacingStmt)
174 0: return; // We can't rewrite the same node twice.
175 :
5: branch 0 taken
133: branch 1 taken
176 138: if (DisableReplaceStmt)
177 5: return; // Used when rewriting the assignment of a property setter.
178 :
179 : // If replacement succeeded or warning disabled return with no warning.
133: branch 1 taken
0: branch 2 not taken
180 133: if (!Rewrite.ReplaceStmt(Old, New)) {
181 133: ReplacedNodes[Old] = New;
182 133: return;
183 : }
0: branch 0 not taken
0: branch 1 not taken
184 0: if (SilenceRewriteMacroWarning)
185 0: return;
186 : Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
187 0: << Old->getSourceRange();
188 : }
189 :
190 7: void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
191 : // Measaure the old text.
192 7: int Size = Rewrite.getRangeSize(SrcRange);
0: branch 0 not taken
7: branch 1 taken
193 7: if (Size == -1) {
194 : Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
195 0: << Old->getSourceRange();
196 0: return;
197 : }
198 : // Get the new text.
199 7: std::string SStr;
200 7: llvm::raw_string_ostream S(SStr);
201 7: New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts));
202 7: const std::string &Str = S.str();
203 :
204 : // If replacement succeeded or warning disabled return with no warning.
7: branch 3 taken
0: branch 4 not taken
205 7: if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
206 7: ReplacedNodes[Old] = New;
207 7: return;
208 : }
0: branch 0 not taken
0: branch 1 not taken
209 0: if (SilenceRewriteMacroWarning)
210 : return;
211 : Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
0: branch 7 not taken
7: branch 8 taken
0: branch 10 not taken
7: branch 11 taken
212 0: << Old->getSourceRange();
213 : }
214 :
215 : void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen,
216 445: bool InsertAfter = true) {
217 : // If insertion succeeded or warning disabled return with no warning.
0: branch 2 not taken
445: branch 3 taken
445: branch 4 taken
445: branch 5 taken
445: branch 6 taken
0: branch 7 not taken
218 445: if (!Rewrite.InsertText(Loc, llvm::StringRef(StrData, StrLen),
219 : InsertAfter) ||
220 : SilenceRewriteMacroWarning)
221 445: return;
222 :
223 0: Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
224 : }
225 :
226 : void RemoveText(SourceLocation Loc, unsigned StrLen) {
227 : // If removal succeeded or warning disabled return with no warning.
228 : if (!Rewrite.RemoveText(Loc, StrLen) || SilenceRewriteMacroWarning)
229 : return;
230 :
231 : Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
232 : }
233 :
234 : void ReplaceText(SourceLocation Start, unsigned OrigLength,
235 349: const char *NewStr, unsigned NewLength) {
236 : // If removal succeeded or warning disabled return with no warning.
0: branch 2 not taken
349: branch 3 taken
349: branch 4 taken
349: branch 5 taken
349: branch 6 taken
0: branch 7 not taken
237 349: if (!Rewrite.ReplaceText(Start, OrigLength,
238 : llvm::StringRef(NewStr, NewLength)) ||
239 : SilenceRewriteMacroWarning)
240 349: return;
241 :
242 0: Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
243 : }
244 :
245 : // Syntactic Rewriting.
246 : void RewritePrologue(SourceLocation Loc);
247 : void RewriteInclude();
248 : void RewriteTabs();
249 : void RewriteForwardClassDecl(ObjCClassDecl *Dcl);
250 : void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
251 : ObjCImplementationDecl *IMD,
252 : ObjCCategoryImplDecl *CID);
253 : void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
254 : void RewriteImplementationDecl(Decl *Dcl);
255 : void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr);
256 : void RewriteByRefString(std::string &ResultStr, const std::string &Name,
257 : ValueDecl *VD);
258 : void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
259 : void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
260 : void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl);
261 : void RewriteMethodDeclaration(ObjCMethodDecl *Method);
262 : void RewriteProperty(ObjCPropertyDecl *prop);
263 : void RewriteFunctionDecl(FunctionDecl *FD);
264 : void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
265 : void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
266 : void RewriteObjCQualifiedInterfaceTypes(Expr *E);
267 : bool needToScanForQualifiers(QualType T);
268 : ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr);
269 : QualType getSuperStructType();
270 : QualType getConstantStringStructType();
271 : bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
272 :
273 : // Expression Rewriting.
274 : Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
275 : void CollectPropertySetters(Stmt *S);
276 :
277 : Stmt *CurrentBody;
278 : ParentMap *PropParentMap; // created lazily.
279 :
280 : Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
281 : Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart,
282 : bool &replaced);
283 : Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced);
284 : Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr);
285 : Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
286 : SourceRange SrcRange);
287 : Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
288 : Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
289 : Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
290 : Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
291 : void WarnAboutReturnGotoStmts(Stmt *S);
292 : void HasReturnStmts(Stmt *S, bool &hasReturns);
293 : void RewriteTryReturnStmts(Stmt *S);
294 : void RewriteSyncReturnStmts(Stmt *S, std::string buf);
295 : Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
296 : Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
297 : Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S);
298 : Stmt *RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S);
299 : Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
300 : Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
301 : SourceLocation OrigEnd);
302 : CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
303 : Expr **args, unsigned nargs);
304 : Stmt *SynthMessageExpr(ObjCMessageExpr *Exp);
305 : Stmt *RewriteBreakStmt(BreakStmt *S);
306 : Stmt *RewriteContinueStmt(ContinueStmt *S);
307 : void SynthCountByEnumWithState(std::string &buf);
308 :
309 : void SynthMsgSendFunctionDecl();
310 : void SynthMsgSendSuperFunctionDecl();
311 : void SynthMsgSendStretFunctionDecl();
312 : void SynthMsgSendFpretFunctionDecl();
313 : void SynthMsgSendSuperStretFunctionDecl();
314 : void SynthGetClassFunctionDecl();
315 : void SynthGetMetaClassFunctionDecl();
316 : void SynthSelGetUidFunctionDecl();
317 : void SynthSuperContructorFunctionDecl();
318 :
319 : // Metadata emission.
320 : void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
321 : std::string &Result);
322 :
323 : void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
324 : std::string &Result);
325 :
326 : template<typename MethodIterator>
327 : void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
328 : MethodIterator MethodEnd,
329 : bool IsInstanceMethod,
330 : const char *prefix,
331 : const char *ClassName,
332 : std::string &Result);
333 :
334 : void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
335 : const char *prefix,
336 : const char *ClassName,
337 : std::string &Result);
338 : void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
339 : const char *prefix,
340 : const char *ClassName,
341 : std::string &Result);
342 : void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
343 : std::string &Result);
344 : void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl,
345 : ObjCIvarDecl *ivar,
346 : std::string &Result);
347 : void RewriteImplementations();
348 : void SynthesizeMetaDataIntoBuffer(std::string &Result);
349 :
350 : // Block rewriting.
351 : void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
352 : void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
353 :
354 : void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
355 : void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
356 :
357 : // Block specific rewrite rules.
358 : void RewriteBlockCall(CallExpr *Exp);
359 : void RewriteBlockPointerDecl(NamedDecl *VD);
360 : void RewriteByRefVar(VarDecl *VD);
361 : std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
362 : Stmt *RewriteBlockDeclRefExpr(Expr *VD);
363 : void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
364 :
365 : std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
366 : const char *funcName, std::string Tag);
367 : std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
368 : const char *funcName, std::string Tag);
369 : std::string SynthesizeBlockImpl(BlockExpr *CE,
370 : std::string Tag, std::string Desc);
371 : std::string SynthesizeBlockDescriptor(std::string DescTag,
372 : std::string ImplTag,
373 : int i, const char *funcName,
374 : unsigned hasCopy);
375 : Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
376 : void SynthesizeBlockLiterals(SourceLocation FunLocStart,
377 : const char *FunName);
378 : void RewriteRecordBody(RecordDecl *RD);
379 :
380 : void CollectBlockDeclRefInfo(BlockExpr *Exp);
381 : void GetBlockCallExprs(Stmt *S);
382 : void GetBlockDeclRefExprs(Stmt *S);
383 :
384 : // We avoid calling Type::isBlockPointerType(), since it operates on the
385 : // canonical type. We only care if the top-level type is a closure pointer.
386 285: bool isTopLevelBlockPointerType(QualType T) {
387 285: return isa<BlockPointerType>(T);
388 : }
389 :
390 : // FIXME: This predicate seems like it would be useful to add to ASTContext.
391 4: bool isObjCType(QualType T) {
2: branch 0 taken
2: branch 1 taken
2: branch 2 taken
0: branch 3 not taken
392 4: if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
393 2: return false;
394 :
395 2: QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
396 :
0: branch 4 not taken
2: branch 5 taken
0: branch 10 not taken
0: branch 11 not taken
2: branch 12 taken
0: branch 13 not taken
397 2: if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
398 : OCT == Context->getCanonicalType(Context->getObjCClassType()))
399 2: return true;
400 :
0: branch 2 not taken
0: branch 3 not taken
401 0: if (const PointerType *PT = OCT->getAs<PointerType>()) {
0: branch 2 not taken
0: branch 3 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 9 not taken
0: branch 10 not taken
402 0: if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
403 : PT->getPointeeType()->isObjCQualifiedIdType())
404 0: return true;
405 : }
406 0: return false;
407 : }
408 : bool PointerTypeTakesAnyBlockArguments(QualType QT);
409 : void GetExtentOfArgList(const char *Name, const char *&LParen,
410 : const char *&RParen);
411 : void RewriteCastExpr(CStyleCastExpr *CE);
412 :
413 : FunctionDecl *SynthBlockInitFunctionDecl(const char *name);
414 : Stmt *SynthBlockInitExpr(BlockExpr *Exp);
415 :
416 24: void QuoteDoublequotes(std::string &From, std::string &To) {
162: branch 1 taken
24: branch 2 taken
417 186: for (unsigned i = 0; i < From.length(); i++) {
18: branch 1 taken
144: branch 2 taken
418 162: if (From[i] == '"')
419 18: To += "\\\"";
420 : else
421 144: To += From[i];
422 : }
423 24: }
424 : };
425 :
426 : // Helper function: create a CStyleCastExpr with trivial type source info.
427 : CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
428 295: CastExpr::CastKind Kind, Expr *E) {
429 295: TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
430 : return new (Ctx) CStyleCastExpr(Ty, Kind, E, TInfo,
295: branch 3 taken
0: branch 4 not taken
431 295: SourceLocation(), SourceLocation());
432 : }
433 : }
434 :
435 : void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
436 61: NamedDecl *D) {
32: branch 1 taken
29: branch 2 taken
437 61: if (FunctionProtoType *fproto = dyn_cast<FunctionProtoType>(funcType)) {
61: branch 1 taken
0: branch 2 not taken
34: branch 3 taken
27: branch 4 taken
438 93: for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(),
439 32: E = fproto->arg_type_end(); I && (I != E); ++I)
5: branch 1 taken
29: branch 2 taken
440 34: if (isTopLevelBlockPointerType(*I)) {
441 : // All the args are checked/rewritten. Don't call twice!
442 5: RewriteBlockPointerDecl(D);
443 5: break;
444 : }
445 : }
446 61: }
447 :
448 1: void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
449 1: const PointerType *PT = funcType->getAs<PointerType>();
1: branch 0 taken
0: branch 1 not taken
0: branch 3 not taken
1: branch 4 taken
0: branch 5 not taken
1: branch 6 taken
450 1: if (PT && PointerTypeTakesAnyBlockArguments(funcType))
451 0: RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
452 1: }
453 :
454 51: static bool IsHeaderFile(const std::string &Filename) {
455 51: std::string::size_type DotPos = Filename.rfind('.');
456 :
0: branch 0 not taken
51: branch 1 taken
457 51: if (DotPos == std::string::npos) {
458 : // no file extension
459 0: return false;
460 : }
461 :
462 51: std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
463 : // C header: .h
464 : // C++ header: .hh or .H;
51: branch 1 taken
0: branch 2 not taken
51: branch 4 taken
0: branch 5 not taken
0: branch 7 not taken
51: branch 8 taken
465 51: return Ext == "h" || Ext == "hh" || Ext == "H";
466 : }
467 :
468 : RewriteObjC::RewriteObjC(std::string inFile, llvm::raw_ostream* OS,
469 : Diagnostic &D, const LangOptions &LOpts,
470 51: bool silenceMacroWarn)
471 : : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS),
472 51: SilenceRewriteMacroWarning(silenceMacroWarn) {
473 51: IsHeader = IsHeaderFile(inFile);
474 : RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
475 51: "rewriting sub-expression within a macro (may not be correct)");
476 : TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning,
477 : "rewriter doesn't support user-specified control flow semantics "
478 51: "for @try/@finally (code may not execute properly)");
479 51: }
480 :
481 : ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile,
482 : llvm::raw_ostream* OS,
483 : Diagnostic &Diags,
484 : const LangOptions &LOpts,
485 51: bool SilenceRewriteMacroWarning) {
486 51: return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
487 : }
488 :
489 51: void RewriteObjC::Initialize(ASTContext &context) {
490 51: Context = &context;
491 51: SM = &Context->getSourceManager();
492 51: TUDecl = Context->getTranslationUnitDecl();
493 51: MsgSendFunctionDecl = 0;
494 51: MsgSendSuperFunctionDecl = 0;
495 51: MsgSendStretFunctionDecl = 0;
496 51: MsgSendSuperStretFunctionDecl = 0;
497 51: MsgSendFpretFunctionDecl = 0;
498 51: GetClassFunctionDecl = 0;
499 51: GetMetaClassFunctionDecl = 0;
500 51: SelGetUidFunctionDecl = 0;
501 51: CFStringFunctionDecl = 0;
502 51: ConstantStringClassReference = 0;
503 51: NSStringRecord = 0;
504 51: CurMethodDef = 0;
505 51: CurFunctionDef = 0;
506 51: CurFunctionDeclToDeclareForBlock = 0;
507 51: GlobalVarDecl = 0;
508 51: SuperStructDecl = 0;
509 51: ProtocolTypeDecl = 0;
510 51: ConstantStringDecl = 0;
511 51: BcLabelCount = 0;
512 51: SuperContructorFunctionDecl = 0;
513 51: NumObjCStringLiterals = 0;
514 51: PropParentMap = 0;
515 51: CurrentBody = 0;
516 51: DisableReplaceStmt = false;
517 51: objc_impl_method = false;
518 :
519 : // Get the ID and start/end of the main file.
520 51: MainFileID = SM->getMainFileID();
521 51: const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
522 51: MainFileStart = MainBuf->getBufferStart();
523 51: MainFileEnd = MainBuf->getBufferEnd();
524 :
525 51: Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions());
526 :
527 : // declaring objc_selector outside the parameter list removes a silly
528 : // scope related warning...
0: branch 0 not taken
51: branch 1 taken
529 51: if (IsHeader)
530 0: Preamble = "#pragma once\n";
531 51: Preamble += "struct objc_selector; struct objc_class;\n";
532 51: Preamble += "struct __rw_objc_super { struct objc_object *object; ";
533 51: Preamble += "struct objc_object *superClass; ";
12: branch 0 taken
39: branch 1 taken
534 51: if (LangOpts.Microsoft) {
535 : // Add a constructor for creating temporary objects.
536 : Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
537 12: ": ";
538 12: Preamble += "object(o), superClass(s) {} ";
539 : }
540 51: Preamble += "};\n";
541 51: Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
542 51: Preamble += "typedef struct objc_object Protocol;\n";
543 51: Preamble += "#define _REWRITER_typedef_Protocol\n";
544 51: Preamble += "#endif\n";
12: branch 0 taken
39: branch 1 taken
545 51: if (LangOpts.Microsoft) {
546 12: Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
547 12: Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
548 : } else
549 39: Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
550 51: Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
551 51: Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
552 51: Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
553 51: Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
554 51: Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend_stret";
555 51: Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
556 51: Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper_stret";
557 51: Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
558 51: Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
559 51: Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
560 51: Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
561 51: Preamble += "(const char *);\n";
562 51: Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
563 51: Preamble += "(const char *);\n";
564 51: Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
565 51: Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
566 51: Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
567 51: Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
568 51: Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
569 51: Preamble += "(struct objc_class *, struct objc_object *);\n";
570 : // @synchronized hooks.
571 51: Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
572 51: Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
573 51: Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
574 51: Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
575 51: Preamble += "struct __objcFastEnumerationState {\n\t";
576 51: Preamble += "unsigned long state;\n\t";
577 51: Preamble += "void **itemsPtr;\n\t";
578 51: Preamble += "unsigned long *mutationsPtr;\n\t";
579 51: Preamble += "unsigned long extra[5];\n};\n";
580 51: Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
581 51: Preamble += "#define __FASTENUMERATIONSTATE\n";
582 51: Preamble += "#endif\n";
583 51: Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
584 51: Preamble += "struct __NSConstantStringImpl {\n";
585 51: Preamble += " int *isa;\n";
586 51: Preamble += " int flags;\n";
587 51: Preamble += " char *str;\n";
588 51: Preamble += " long length;\n";
589 51: Preamble += "};\n";
590 51: Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
591 51: Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
592 51: Preamble += "#else\n";
593 51: Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
594 51: Preamble += "#endif\n";
595 51: Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
596 51: Preamble += "#endif\n";
597 : // Blocks preamble.
598 51: Preamble += "#ifndef BLOCK_IMPL\n";
599 51: Preamble += "#define BLOCK_IMPL\n";
600 51: Preamble += "struct __block_impl {\n";
601 51: Preamble += " void *isa;\n";
602 51: Preamble += " int Flags;\n";
603 51: Preamble += " int Reserved;\n";
604 51: Preamble += " void *FuncPtr;\n";
605 51: Preamble += "};\n";
606 51: Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
607 51: Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
608 51: Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_assign(void *, const void *, const int);\n";
609 51: Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
610 51: Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
611 51: Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
612 51: Preamble += "#else\n";
613 51: Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
614 51: Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
615 51: Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
616 51: Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
617 51: Preamble += "#endif\n";
618 51: Preamble += "#endif\n";
12: branch 0 taken
39: branch 1 taken
619 51: if (LangOpts.Microsoft) {
620 12: Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
621 12: Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
622 12: Preamble += "#define __attribute__(X)\n";
623 12: Preamble += "#define __weak\n";
624 : }
625 : else {
626 39: Preamble += "#define __block\n";
627 39: Preamble += "#define __weak\n";
628 : }
629 51: }
630 :
631 :
632 : //===----------------------------------------------------------------------===//
633 : // Top Level Driver Code
634 : //===----------------------------------------------------------------------===//
635 :
636 339: void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
0: branch 1 not taken
339: branch 2 taken
637 339: if (Diags.hasErrorOccurred())
638 0: return;
639 :
640 : // Two cases: either the decl could be in the main file, or it could be in a
641 : // #included file. If the former, rewrite it now. If the later, check to see
642 : // if we rewrote the #include/#import.
643 339: SourceLocation Loc = D->getLocation();
644 339: Loc = SM->getInstantiationLoc(Loc);
645 :
646 : // If this is for a builtin, ignore it.
339: branch 1 taken
0: branch 2 not taken
647 339: if (Loc.isInvalid()) return;
648 :
649 : // Look for built-in declarations that we need to refer during the rewrite.
61: branch 1 taken
278: branch 2 taken
650 339: if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
651 61: RewriteFunctionDecl(FD);
15: branch 1 taken
263: branch 2 taken
652 278: } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
653 : // declared in <Foundation/NSString.h>
0: branch 2 not taken
15: branch 3 taken
654 15: if (strcmp(FVD->getNameAsCString(), "_NSConstantStringClassReference") == 0) {
655 0: ConstantStringClassReference = FVD;
656 0: return;
657 : }
62: branch 1 taken
201: branch 2 taken
658 263: } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) {
659 62: RewriteInterfaceDecl(MD);
6: branch 1 taken
195: branch 2 taken
660 201: } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
661 6: RewriteCategoryDecl(CD);
12: branch 1 taken
183: branch 2 taken
662 195: } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
663 12: RewriteProtocolDecl(PD);
2: branch 0 taken
181: branch 1 taken
664 183: } else if (ObjCForwardProtocolDecl *FP =
665 183: dyn_cast<ObjCForwardProtocolDecl>(D)){
666 2: RewriteForwardProtocolDecl(FP);
8: branch 1 taken
173: branch 2 taken
667 181: } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
668 : // Recurse into linkage specifications
9: branch 3 taken
8: branch 4 taken
669 25: for (DeclContext::decl_iterator DI = LSD->decls_begin(),
670 8: DIEnd = LSD->decls_end();
671 : DI != DIEnd; ++DI)
672 9: HandleTopLevelSingleDecl(*DI);
673 : }
674 : // If we have a decl in the main file, see if we should rewrite it.
286: branch 1 taken
53: branch 2 taken
675 339: if (SM->isFromMainFile(Loc))
676 286: return HandleDeclInMainFile(D);
677 : }
678 :
679 : //===----------------------------------------------------------------------===//
680 : // Syntactic (non-AST) Rewriting Code
681 : //===----------------------------------------------------------------------===//
682 :
683 51: void RewriteObjC::RewriteInclude() {
684 51: SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
685 51: std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
686 51: const char *MainBufStart = MainBuf.first;
687 51: const char *MainBufEnd = MainBuf.second;
688 51: size_t ImportLen = strlen("import");
689 51: size_t IncludeLen = strlen("include");
690 :
691 : // Loop over the whole file, looking for includes.
24038: branch 0 taken
51: branch 1 taken
692 24089: for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
2: branch 0 taken
24036: branch 1 taken
693 24038: if (*BufPtr == '#') {
0: branch 0 not taken
2: branch 1 taken
694 2: if (++BufPtr == MainBufEnd)
695 0: return;
0: branch 0 not taken
2: branch 1 taken
0: branch 2 not taken
2: branch 3 taken
696 4: while (*BufPtr == ' ' || *BufPtr == '\t')
0: branch 0 not taken
0: branch 1 not taken
697 0: if (++BufPtr == MainBufEnd)
698 0: return;
0: branch 1 not taken
2: branch 2 taken
699 2: if (!strncmp(BufPtr, "import", ImportLen)) {
700 : // replace import with include
701 : SourceLocation ImportLoc =
702 0: LocStart.getFileLocWithOffset(BufPtr-MainBufStart);
703 0: ReplaceText(ImportLoc, ImportLen, "include", IncludeLen);
704 0: BufPtr += ImportLen;
705 : }
706 : }
707 : }
708 : }
709 :
710 0: void RewriteObjC::RewriteTabs() {
711 0: std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
712 0: const char *MainBufStart = MainBuf.first;
713 0: const char *MainBufEnd = MainBuf.second;
714 :
715 : // Loop over the whole file, looking for tabs.
0: branch 0 not taken
0: branch 1 not taken
716 0: for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
0: branch 0 not taken
0: branch 1 not taken
717 0: if (*BufPtr != '\t')
718 0: continue;
719 :
720 : // Okay, we found a tab. This tab will turn into at least one character,
721 : // but it depends on which 'virtual column' it is in. Compute that now.
722 0: unsigned VCol = 0;
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
0: branch 7 not taken
723 0: while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
724 : BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
725 0: ++VCol;
726 :
727 : // Okay, now that we know the virtual column, we know how many spaces to
728 : // insert. We assume 8-character tab-stops.
729 0: unsigned Spaces = 8-(VCol & 7);
730 :
731 : // Get the location of the tab.
732 0: SourceLocation TabLoc = SM->getLocForStartOfFile(MainFileID);
733 0: TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart);
734 :
735 : // Rewrite the single tab character into a sequence of spaces.
736 0: ReplaceText(TabLoc, 1, " ", Spaces);
737 : }
738 0: }
739 :
740 : static std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl,
741 5: ObjCIvarDecl *OID) {
742 5: std::string S;
743 5: S = "((struct ";
744 5: S += ClassDecl->getIdentifier()->getName();
745 5: S += "_IMPL *)self)->";
746 5: S += OID->getName();
747 : return S;
748 : }
749 :
750 : void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
751 : ObjCImplementationDecl *IMD,
752 4: ObjCCategoryImplDecl *CID) {
753 4: SourceLocation startLoc = PID->getLocStart();
754 4: InsertText(startLoc, "// ", 3);
755 4: const char *startBuf = SM->getCharacterData(startLoc);
0: branch 0 not taken
4: branch 1 taken
756 4: assert((*startBuf == '@') && "bogus @synthesize location");
757 4: const char *semiBuf = strchr(startBuf, ';');
0: branch 0 not taken
4: branch 1 taken
758 4: assert((*semiBuf == ';') && "@synthesize: can't find ';'");
759 : SourceLocation onePastSemiLoc =
760 4: startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
761 :
1: branch 1 taken
3: branch 2 taken
762 4: if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
763 1: return; // FIXME: is this correct?
764 :
765 : // Generate the 'getter' function.
766 3: ObjCPropertyDecl *PD = PID->getPropertyDecl();
767 3: ObjCInterfaceDecl *ClassDecl = PD->getGetterMethodDecl()->getClassInterface();
768 3: ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
769 :
0: branch 0 not taken
3: branch 1 taken
770 3: if (!OID)
771 0: return;
772 :
773 3: std::string Getr;
774 3: RewriteObjCMethodDecl(PD->getGetterMethodDecl(), Getr);
775 3: Getr += "{ ";
776 : // Synthesize an explicit cast to gain access to the ivar.
777 : // FIXME: deal with code generation implications for various property
778 : // attributes (copy, retain, nonatomic).
779 : // See objc-act.c:objc_synthesize_new_getter() for details.
780 3: Getr += "return " + getIvarAccessString(ClassDecl, OID);
781 3: Getr += "; }";
782 3: InsertText(onePastSemiLoc, Getr.c_str(), Getr.size());
1: branch 1 taken
2: branch 2 taken
783 3: if (PD->isReadOnly())
784 1: return;
785 :
786 : // Generate the 'setter' function.
787 2: std::string Setr;
788 2: RewriteObjCMethodDecl(PD->getSetterMethodDecl(), Setr);
789 2: Setr += "{ ";
790 : // Synthesize an explicit cast to initialize the ivar.
791 : // FIXME: deal with code generation implications for various property
792 : // attributes (copy, retain, nonatomic).
793 : // See objc-act.c:objc_synthesize_new_setter() for details.
794 2: Setr += getIvarAccessString(ClassDecl, OID) + " = ";
795 2: Setr += PD->getNameAsCString();
796 2: Setr += "; }";
2: branch 5 taken
1: branch 6 taken
797 2: InsertText(onePastSemiLoc, Setr.c_str(), Setr.size());
798 : }
799 :
800 8: void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) {
801 : // Get the start location and compute the semi location.
802 8: SourceLocation startLoc = ClassDecl->getLocation();
803 8: const char *startBuf = SM->getCharacterData(startLoc);
804 8: const char *semiPtr = strchr(startBuf, ';');
805 :
806 : // Translate to typedef's that forward reference structs with the same name
807 : // as the class. As a convenience, we include the original declaration
808 : // as a comment.
809 8: std::string typedefString;
810 8: typedefString += "// @class ";
18: branch 2 taken
8: branch 3 taken
811 26: for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
812 : I != E; ++I) {
813 18: ObjCInterfaceDecl *ForwardDecl = I->getInterface();
814 18: typedefString += ForwardDecl->getNameAsString();
10: branch 0 taken
8: branch 1 taken
815 18: if (I+1 != E)
816 10: typedefString += ", ";
817 : else
818 8: typedefString += ";\n";
819 : }
820 :
18: branch 2 taken
8: branch 3 taken
821 26: for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
822 : I != E; ++I) {
823 18: ObjCInterfaceDecl *ForwardDecl = I->getInterface();
824 18: typedefString += "#ifndef _REWRITER_typedef_";
825 18: typedefString += ForwardDecl->getNameAsString();
826 18: typedefString += "\n";
827 18: typedefString += "#define _REWRITER_typedef_";
828 18: typedefString += ForwardDecl->getNameAsString();
829 18: typedefString += "\n";
830 18: typedefString += "typedef struct objc_object ";
831 18: typedefString += ForwardDecl->getNameAsString();
832 18: typedefString += ";\n#endif\n";
833 : }
834 :
835 : // Replace the @class with typedefs corresponding to the classes.
836 : ReplaceText(startLoc, semiPtr-startBuf+1,
837 8: typedefString.c_str(), typedefString.size());
838 8: }
839 :
840 55: void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
841 : // When method is a synthesized one, such as a getter/setter there is
842 : // nothing to rewrite.
11: branch 1 taken
44: branch 2 taken
843 55: if (Method->isSynthesized())
844 11: return;
845 44: SourceLocation LocStart = Method->getLocStart();
846 44: SourceLocation LocEnd = Method->getLocEnd();
847 :
0: branch 2 not taken
44: branch 3 taken
848 44: if (SM->getInstantiationLineNumber(LocEnd) >
849 : SM->getInstantiationLineNumber(LocStart)) {
850 0: InsertText(LocStart, "#if 0\n", 6);
851 0: ReplaceText(LocEnd, 1, ";\n#endif\n", 9);
852 : } else {
853 44: InsertText(LocStart, "// ", 3);
854 : }
855 : }
856 :
857 7: void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
858 7: SourceLocation Loc = prop->getAtLoc();
859 :
860 7: ReplaceText(Loc, 0, "// ", 3);
861 : // FIXME: handle properties that are declared across multiple lines.
862 7: }
863 :
864 6: void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
865 6: SourceLocation LocStart = CatDecl->getLocStart();
866 :
867 : // FIXME: handle category headers that are declared across multiple lines.
868 6: ReplaceText(LocStart, 0, "// ", 3);
869 :
1: branch 3 taken
6: branch 4 taken
870 13: for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(),
871 6: E = CatDecl->prop_end(); I != E; ++I)
872 1: RewriteProperty(*I);
873 :
6: branch 2 taken
6: branch 3 taken
874 12: for (ObjCCategoryDecl::instmeth_iterator
875 6: I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end();
876 : I != E; ++I)
877 6: RewriteMethodDeclaration(*I);
0: branch 2 not taken
6: branch 3 taken
878 6: for (ObjCCategoryDecl::classmeth_iterator
879 6: I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end();
880 : I != E; ++I)
881 0: RewriteMethodDeclaration(*I);
882 :
883 : // Lastly, comment out the @end.
884 6: ReplaceText(CatDecl->getAtEndRange().getBegin(), 0, "// ", 3);
885 6: }
886 :
887 12: void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
888 12: std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
889 :
890 12: SourceLocation LocStart = PDecl->getLocStart();
891 :
892 : // FIXME: handle protocol headers that are declared across multiple lines.
893 12: ReplaceText(LocStart, 0, "// ", 3);
894 :
5: branch 2 taken
12: branch 3 taken
895 17: for (ObjCProtocolDecl::instmeth_iterator
896 12: I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
897 : I != E; ++I)
898 5: RewriteMethodDeclaration(*I);
1: branch 2 taken
12: branch 3 taken
899 13: for (ObjCProtocolDecl::classmeth_iterator
900 12: I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
901 : I != E; ++I)
902 1: RewriteMethodDeclaration(*I);
903 :
904 : // Lastly, comment out the @end.
905 12: SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
906 12: ReplaceText(LocEnd, 0, "// ", 3);
907 :
908 : // Must comment out @optional/@required
909 12: const char *startBuf = SM->getCharacterData(LocStart);
910 12: const char *endBuf = SM->getCharacterData(LocEnd);
384: branch 0 taken
12: branch 1 taken
911 396: for (const char *p = startBuf; p < endBuf; p++) {
12: branch 0 taken
372: branch 1 taken
0: branch 3 not taken
12: branch 4 taken
912 384: if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
913 0: std::string CommentedOptional = "/* @optional */";
914 0: SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
915 : ReplaceText(OptionalLoc, strlen("@optional"),
916 0: CommentedOptional.c_str(), CommentedOptional.size());
917 :
918 : }
12: branch 0 taken
372: branch 1 taken
0: branch 3 not taken
12: branch 4 taken
919 384: else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
920 0: std::string CommentedRequired = "/* @required */";
921 0: SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
922 : ReplaceText(OptionalLoc, strlen("@required"),
923 0: CommentedRequired.c_str(), CommentedRequired.size());
924 :
925 : }
926 : }
927 12: }
928 :
929 2: void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) {
930 2: SourceLocation LocStart = PDecl->getLocation();
0: branch 1 not taken
2: branch 2 taken
931 2: if (LocStart.isInvalid())
932 0: assert(false && "Invalid SourceLocation");
933 : // FIXME: handle forward protocol that are declared across multiple lines.
934 2: ReplaceText(LocStart, 0, "// ", 3);
935 2: }
936 :
937 : void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD,
938 53: std::string &ResultStr) {
939 : //fprintf(stderr,"In RewriteObjCMethodDecl\n");
940 53: const FunctionType *FPRetType = 0;
941 53: ResultStr += "\nstatic ";
2: branch 3 taken
51: branch 4 taken
942 53: if (OMD->getResultType()->isObjCQualifiedIdType())
943 2: ResultStr += "id";
51: branch 3 taken
0: branch 4 not taken
0: branch 8 not taken
51: branch 9 taken
0: branch 10 not taken
51: branch 11 taken
944 51: else if (OMD->getResultType()->isFunctionPointerType() ||
945 : OMD->getResultType()->isBlockPointerType()) {
946 : // needs special handling, since pointer-to-functions have special
947 : // syntax (where a decaration models use).
948 0: QualType retType = OMD->getResultType();
949 0: QualType PointeeTy;
0: branch 2 not taken
0: branch 3 not taken
950 0: if (const PointerType* PT = retType->getAs<PointerType>())
951 0: PointeeTy = PT->getPointeeType();
0: branch 2 not taken
0: branch 3 not taken
952 0: else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
953 0: PointeeTy = BPT->getPointeeType();
0: branch 2 not taken
0: branch 3 not taken
954 0: if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
955 0: ResultStr += FPRetType->getResultType().getAsString();
956 0: ResultStr += "(*";
957 : }
958 : } else
959 51: ResultStr += OMD->getResultType().getAsString();
960 53: ResultStr += " ";
961 :
962 : // Unique method name
963 53: std::string NameStr;
964 :
48: branch 1 taken
5: branch 2 taken
965 53: if (OMD->isInstanceMethod())
966 48: NameStr += "_I_";
967 : else
968 5: NameStr += "_C_";
969 :
970 53: NameStr += OMD->getClassInterface()->getNameAsString();
971 53: NameStr += "_";
972 :
6: branch 0 taken
47: branch 1 taken
973 53: if (ObjCCategoryImplDecl *CID =
974 53: dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
975 6: NameStr += CID->getNameAsString();
976 6: NameStr += "_";
977 : }
978 : // Append selector names, replacing ':' with '_'
979 : {
980 53: std::string selString = OMD->getSelector().getAsString();
981 53: int len = selString.size();
682: branch 0 taken
53: branch 1 taken
982 735: for (int i = 0; i < len; i++)
34: branch 1 taken
648: branch 2 taken
983 682: if (selString[i] == ':')
984 34: selString[i] = '_';
985 53: NameStr += selString;
986 : }
987 : // Remember this name for metadata emission
988 53: MethodInternalNames[OMD] = NameStr;
989 53: ResultStr += NameStr;
990 :
991 : // Rewrite arguments
992 53: ResultStr += "(";
993 :
994 : // invisible arguments
48: branch 1 taken
5: branch 2 taken
995 53: if (OMD->isInstanceMethod()) {
996 48: QualType selfTy = Context->getObjCInterfaceType(OMD->getClassInterface());
997 48: selfTy = Context->getPointerType(selfTy);
40: branch 0 taken
8: branch 1 taken
998 48: if (!LangOpts.Microsoft) {
13: branch 2 taken
27: branch 3 taken
999 40: if (ObjCSynthesizedStructs.count(OMD->getClassInterface()))
1000 13: ResultStr += "struct ";
1001 : }
1002 : // When rewriting for Microsoft, explicitly omit the structure name.
1003 48: ResultStr += OMD->getClassInterface()->getNameAsString();
1004 48: ResultStr += " *";
1005 : }
1006 : else
1007 5: ResultStr += Context->getObjCClassType().getAsString();
1008 :
1009 53: ResultStr += " self, ";
1010 53: ResultStr += Context->getObjCSelType().getAsString();
1011 53: ResultStr += " _cmd";
1012 :
1013 : // Method arguments.
34: branch 1 taken
53: branch 2 taken
1014 140: for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
1015 53: E = OMD->param_end(); PI != E; ++PI) {
1016 34: ParmVarDecl *PDecl = *PI;
1017 34: ResultStr += ", ";
1: branch 3 taken
33: branch 4 taken
1018 34: if (PDecl->getType()->isObjCQualifiedIdType()) {
1019 1: ResultStr += "id ";
1020 1: ResultStr += PDecl->getNameAsString();
1021 : } else {
1022 33: std::string Name = PDecl->getNameAsString();
0: branch 2 not taken
33: branch 3 taken
1023 33: if (isTopLevelBlockPointerType(PDecl->getType())) {
1024 : // Make sure we convert "t (^)(...)" to "t (*)(...)".
1025 0: const BlockPointerType *BPT = PDecl->getType()->getAs<BlockPointerType>();
1026 : Context->getPointerType(BPT->getPointeeType()).getAsStringInternal(Name,
1027 0: Context->PrintingPolicy);
1028 : } else
1029 33: PDecl->getType().getAsStringInternal(Name, Context->PrintingPolicy);
1030 33: ResultStr += Name;
1031 : }
1032 : }
1: branch 1 taken
52: branch 2 taken
1033 53: if (OMD->isVariadic())
1034 1: ResultStr += ", ...";
1035 53: ResultStr += ") ";
1036 :
0: branch 0 not taken
53: branch 1 taken
1037 53: if (FPRetType) {
1038 0: ResultStr += ")"; // close the precedence "scope" for "*".
1039 :
1040 : // Now, emit the argument types (if any).
0: branch 1 not taken
0: branch 2 not taken
1041 0: if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
1042 0: ResultStr += "(";
0: branch 2 not taken
0: branch 3 not taken
1043 0: for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
0: branch 0 not taken
0: branch 1 not taken
1044 0: if (i) ResultStr += ", ";
1045 0: std::string ParamStr = FT->getArgType(i).getAsString();
1046 0: ResultStr += ParamStr;
1047 : }
0: branch 1 not taken
0: branch 2 not taken
1048 0: if (FT->isVariadic()) {
0: branch 1 not taken
0: branch 2 not taken
1049 0: if (FT->getNumArgs()) ResultStr += ", ";
1050 0: ResultStr += "...";
1051 : }
1052 0: ResultStr += ")";
1053 : } else {
1054 0: ResultStr += "()";
1055 : }
1056 53: }
1057 53: }
1058 41: void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
1059 41: ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
1060 41: ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
1061 :
35: branch 0 taken
6: branch 1 taken
1062 41: if (IMD)
1063 35: InsertText(IMD->getLocStart(), "// ", 3);
1064 : else
1065 6: InsertText(CID->getLocStart(), "// ", 3);
1066 :
43: branch 3 taken
41: branch 4 taken
1067 84: for (ObjCCategoryImplDecl::instmeth_iterator
35: branch 0 taken
6: branch 1 taken
1068 41: I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(),
35: branch 0 taken
6: branch 1 taken
1069 41: E = IMD ? IMD->instmeth_end() : CID->instmeth_end();
1070 : I != E; ++I) {
1071 43: std::string ResultStr;
1072 43: ObjCMethodDecl *OMD = *I;
1073 43: RewriteObjCMethodDecl(OMD, ResultStr);
1074 43: SourceLocation LocStart = OMD->getLocStart();
1075 43: SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
1076 :
1077 43: const char *startBuf = SM->getCharacterData(LocStart);
1078 43: const char *endBuf = SM->getCharacterData(LocEnd);
1079 : ReplaceText(LocStart, endBuf-startBuf,
1080 43: ResultStr.c_str(), ResultStr.size());
1081 : }
1082 :
5: branch 3 taken
41: branch 4 taken
1083 46: for (ObjCCategoryImplDecl::classmeth_iterator
35: branch 0 taken
6: branch 1 taken
1084 41: I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(),
35: branch 0 taken
6: branch 1 taken
1085 41: E = IMD ? IMD->classmeth_end() : CID->classmeth_end();
1086 : I != E; ++I) {
1087 5: std::string ResultStr;
1088 5: ObjCMethodDecl *OMD = *I;
1089 5: RewriteObjCMethodDecl(OMD, ResultStr);
1090 5: SourceLocation LocStart = OMD->getLocStart();
1091 5: SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
1092 :
1093 5: const char *startBuf = SM->getCharacterData(LocStart);
1094 5: const char *endBuf = SM->getCharacterData(LocEnd);
1095 : ReplaceText(LocStart, endBuf-startBuf,
1096 5: ResultStr.c_str(), ResultStr.size());
1097 : }
4: branch 2 taken
41: branch 3 taken
1098 45: for (ObjCCategoryImplDecl::propimpl_iterator
35: branch 0 taken
6: branch 1 taken
1099 41: I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(),
35: branch 0 taken
6: branch 1 taken
1100 41: E = IMD ? IMD->propimpl_end() : CID->propimpl_end();
1101 : I != E; ++I) {
1102 4: RewritePropertyImplDecl(*I, IMD, CID);
1103 : }
1104 :
35: branch 0 taken
6: branch 1 taken
1105 41: if (IMD)
1106 35: InsertText(IMD->getLocEnd(), "// ", 3);
1107 : else
1108 6: InsertText(CID->getLocEnd(), "// ", 3);
1109 41: }
1110 :
1111 62: void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
1112 62: std::string ResultStr;
62: branch 1 taken
0: branch 2 not taken
1113 62: if (!ObjCForwardDecls.count(ClassDecl)) {
1114 : // we haven't seen a forward decl - generate a typedef.
1115 62: ResultStr = "#ifndef _REWRITER_typedef_";
1116 62: ResultStr += ClassDecl->getNameAsString();
1117 62: ResultStr += "\n";
1118 62: ResultStr += "#define _REWRITER_typedef_";
1119 62: ResultStr += ClassDecl->getNameAsString();
1120 62: ResultStr += "\n";
1121 62: ResultStr += "typedef struct objc_object ";
1122 62: ResultStr += ClassDecl->getNameAsString();
1123 62: ResultStr += ";\n#endif\n";
1124 : // Mark this typedef as having been generated.
1125 62: ObjCForwardDecls.insert(ClassDecl);
1126 : }
1127 62: SynthesizeObjCInternalStruct(ClassDecl, ResultStr);
1128 :
6: branch 3 taken
62: branch 4 taken
1129 130: for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(),
1130 62: E = ClassDecl->prop_end(); I != E; ++I)
1131 6: RewriteProperty(*I);
36: branch 2 taken
62: branch 3 taken
1132 98: for (ObjCInterfaceDecl::instmeth_iterator
1133 62: I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end();
1134 : I != E; ++I)
1135 36: RewriteMethodDeclaration(*I);
7: branch 2 taken
62: branch 3 taken
1136 69: for (ObjCInterfaceDecl::classmeth_iterator
1137 62: I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end();
1138 : I != E; ++I)
1139 7: RewriteMethodDeclaration(*I);
1140 :
1141 : // Lastly, comment out the @end.
1142 62: ReplaceText(ClassDecl->getAtEndRange().getBegin(), 0, "// ", 3);
1143 62: }
1144 :
1145 : Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
1146 7: SourceRange SrcRange) {
1147 : // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
1148 : // This allows us to reuse all the fun and games in SynthMessageExpr().
1149 7: ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS());
1150 : ObjCMessageExpr *MsgExpr;
1151 7: ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
1152 7: llvm::SmallVector<Expr *, 1> ExprVec;
1153 7: ExprVec.push_back(newStmt);
1154 :
1155 7: Stmt *Receiver = PropRefExpr->getBase();
1156 7: ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
1: branch 0 taken
6: branch 1 taken
1: branch 3 taken
0: branch 4 not taken
1: branch 5 taken
6: branch 6 taken
1157 7: if (PRE && PropGetters[PRE]) {
1158 : // This allows us to handle chain/nested property getters.
1159 1: Receiver = PropGetters[PRE];
1160 : }
1161 : MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver),
1162 : PDecl->getSetterName(), PDecl->getType(),
1163 : PDecl->getSetterMethodDecl(),
1164 : SourceLocation(), SourceLocation(),
7: branch 8 taken
0: branch 9 not taken
1165 7: &ExprVec[0], 1);
1166 7: Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
1167 :
1168 : // Now do the actual rewrite.
1169 7: ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange);
1170 : //delete BinOp;
1171 : // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
1172 : // to things that stay around.
1173 7: Context->Deallocate(MsgExpr);
1174 7: return ReplacingStmt;
1175 : }
1176 :
1177 9: Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) {
1178 : // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
1179 : // This allows us to reuse all the fun and games in SynthMessageExpr().
1180 : ObjCMessageExpr *MsgExpr;
1181 9: ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
1182 :
1183 9: Stmt *Receiver = PropRefExpr->getBase();
1184 :
1185 9: ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
1: branch 0 taken
8: branch 1 taken
1: branch 3 taken
0: branch 4 not taken
1: branch 5 taken
8: branch 6 taken
1186 9: if (PRE && PropGetters[PRE]) {
1187 : // This allows us to handle chain/nested property getters.
1188 1: Receiver = PropGetters[PRE];
1189 : }
1190 : MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver),
1191 : PDecl->getGetterName(), PDecl->getType(),
1192 : PDecl->getGetterMethodDecl(),
1193 : SourceLocation(), SourceLocation(),
9: branch 7 taken
0: branch 8 not taken
1194 9: 0, 0);
1195 :
1196 9: Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
1197 :
1: branch 0 taken
8: branch 1 taken
1198 9: if (!PropParentMap)
1199 1: PropParentMap = new ParentMap(CurrentBody);
1200 :
1201 9: Stmt *Parent = PropParentMap->getParent(PropRefExpr);
9: branch 0 taken
0: branch 1 not taken
2: branch 3 taken
7: branch 4 taken
2: branch 5 taken
7: branch 6 taken
1202 9: if (Parent && isa<ObjCPropertyRefExpr>(Parent)) {
1203 : // We stash away the ReplacingStmt since actually doing the
1204 : // replacement/rewrite won't work for nested getters (e.g. obj.p.i)
1205 2: PropGetters[PropRefExpr] = ReplacingStmt;
1206 : // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
1207 : // to things that stay around.
1208 2: Context->Deallocate(MsgExpr);
1209 2: return PropRefExpr; // return the original...
1210 : } else {
1211 7: ReplaceStmt(PropRefExpr, ReplacingStmt);
1212 : // delete PropRefExpr; elsewhere...
1213 : // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
1214 : // to things that stay around.
1215 7: Context->Deallocate(MsgExpr);
1216 7: return ReplacingStmt;
1217 : }
1218 : }
1219 :
1220 : Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
1221 : SourceLocation OrigStart,
1222 28: bool &replaced) {
1223 28: ObjCIvarDecl *D = IV->getDecl();
1224 28: const Expr *BaseExpr = IV->getBase();
23: branch 0 taken
5: branch 1 taken
1225 28: if (CurMethodDef) {
23: branch 3 taken
0: branch 4 not taken
1226 23: if (BaseExpr->getType()->isObjCObjectPointerType()) {
1227 : ObjCInterfaceType *iFaceDecl =
1228 23: dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
0: branch 0 not taken
23: branch 1 taken
1229 23: assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
1230 : // lookup which class implements the instance variable.
1231 23: ObjCInterfaceDecl *clsDeclared = 0;
1232 : iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
1233 23: clsDeclared);
0: branch 0 not taken
23: branch 1 taken
1234 23: assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
1235 :
1236 : // Synthesize an explicit cast to gain access to the ivar.
1237 23: std::string RecName = clsDeclared->getIdentifier()->getName();
1238 23: RecName += "_IMPL";
1239 23: IdentifierInfo *II = &Context->Idents.get(RecName.c_str());
1240 : RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
23: branch 2 taken
0: branch 3 not taken
1241 23: SourceLocation(), II);
0: branch 0 not taken
23: branch 1 taken
1242 23: assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
1243 23: QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
1244 : CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
1245 : CastExpr::CK_Unknown,
1246 23: IV->getBase());
1247 : // Don't forget the parens to enforce the proper binding.
1248 : ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
1249 : IV->getBase()->getLocEnd(),
23: branch 5 taken
0: branch 6 not taken
1250 23: castExpr);
1251 23: replaced = true;
13: branch 1 taken
10: branch 2 taken
13: branch 5 taken
0: branch 6 not taken
13: branch 7 taken
10: branch 8 taken
1252 23: if (IV->isFreeIvar() &&
1253 : CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {
1254 : MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
1255 : IV->getLocation(),
13: branch 3 taken
0: branch 4 not taken
1256 13: D->getType());
1257 : // delete IV; leak for now, see RewritePropertySetter() usage for more info.
1258 13: return ME;
1259 : }
1260 : // Get the new text
1261 : // Cannot delete IV->getBase(), since PE points to it.
1262 : // Replace the old base with the cast. This is important when doing
1263 : // embedded rewrites. For example, [newInv->_container addObject:0].
1264 10: IV->setBase(PE);
1265 10: return IV;
1266 : }
1267 : } else { // we are outside a method.
5: branch 1 taken
0: branch 2 not taken
1268 5: assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
1269 :
1270 : // Explicit ivar refs need to have a cast inserted.
1271 : // FIXME: consider sharing some of this code with the code above.
5: branch 3 taken
0: branch 4 not taken
1272 5: if (BaseExpr->getType()->isObjCObjectPointerType()) {
1273 : ObjCInterfaceType *iFaceDecl =
1274 5: dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
1275 : // lookup which class implements the instance variable.
1276 5: ObjCInterfaceDecl *clsDeclared = 0;
1277 : iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
1278 5: clsDeclared);
0: branch 0 not taken
5: branch 1 taken
1279 5: assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
1280 :
1281 : // Synthesize an explicit cast to gain access to the ivar.
1282 5: std::string RecName = clsDeclared->getIdentifier()->getName();
1283 5: RecName += "_IMPL";
1284 5: IdentifierInfo *II = &Context->Idents.get(RecName.c_str());
1285 : RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
5: branch 2 taken
0: branch 3 not taken
1286 5: SourceLocation(), II);
0: branch 0 not taken
5: branch 1 taken
1287 5: assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
1288 5: QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
1289 : CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
1290 : CastExpr::CK_Unknown,
1291 5: IV->getBase());
1292 : // Don't forget the parens to enforce the proper binding.
1293 : ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
5: branch 5 taken
0: branch 6 not taken
1294 5: IV->getBase()->getLocEnd(), castExpr);
1295 5: replaced = true;
1296 : // Cannot delete IV->getBase(), since PE points to it.
1297 : // Replace the old base with the cast. This is important when doing
1298 : // embedded rewrites. For example, [newInv->_container addObject:0].
1299 5: IV->setBase(PE);
1300 5: return IV;
1301 : }
1302 : }
1303 0: return IV;
1304 : }
1305 :
1306 69: Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) {
45: branch 4 taken
69: branch 5 taken
1307 114: for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
1308 : CI != E; ++CI) {
45: branch 1 taken
0: branch 2 not taken
1309 45: if (*CI) {
1310 45: Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced);
45: branch 0 taken
0: branch 1 not taken
1311 45: if (newStmt)
1312 45: *CI = newStmt;
1313 : }
1314 : }
28: branch 1 taken
41: branch 2 taken
1315 69: if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
1316 28: SourceRange OrigStmtRange = S->getSourceRange();
1317 : Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(),
1318 28: replaced);
1319 28: return newStmt;
1320 : }
3: branch 1 taken
38: branch 2 taken
1321 41: if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) {
1322 3: Stmt *newStmt = SynthMessageExpr(MsgRefExpr);
1323 3: return newStmt;
1324 : }
1325 38: return S;
1326 : }
1327 :
1328 : /// SynthCountByEnumWithState - To print:
1329 : /// ((unsigned int (*)
1330 : /// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
1331 : /// (void *)objc_msgSend)((id)l_collection,
1332 : /// sel_registerName(
1333 : /// "countByEnumeratingWithState:objects:count:"),
1334 : /// &enumState,
1335 : /// (id *)items, (unsigned int)16)
1336 : ///
1337 32: void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
1338 : buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
1339 32: "id *, unsigned int))(void *)objc_msgSend)";
1340 32: buf += "\n\t\t";
1341 32: buf += "((id)l_collection,\n\t\t";
1342 32: buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
1343 32: buf += "\n\t\t";
1344 : buf += "&enumState, "
1345 32: "(id *)items, (unsigned int)16)";
1346 32: }
1347 :
1348 : /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
1349 : /// statement to exit to its outer synthesized loop.
1350 : ///
1351 6: Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {
6: branch 1 taken
0: branch 2 not taken
4: branch 5 taken
2: branch 6 taken
4: branch 7 taken
2: branch 8 taken
1352 6: if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1353 4: return S;
1354 : // replace break with goto __break_label
1355 2: std::string buf;
1356 :
1357 2: SourceLocation startLoc = S->getLocStart();
1358 2: buf = "goto __break_label_";
1359 2: buf += utostr(ObjCBcLabelNo.back());
1360 2: ReplaceText(startLoc, strlen("break"), buf.c_str(), buf.size());
1361 :
1362 2: return 0;
1363 : }
1364 :
1365 : /// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
1366 : /// statement to continue with its inner synthesized loop.
1367 : ///
1368 2: Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {
2: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
2: branch 6 taken
0: branch 7 not taken
2: branch 8 taken
1369 2: if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
1370 0: return S;
1371 : // replace continue with goto __continue_label
1372 2: std::string buf;
1373 :
1374 2: SourceLocation startLoc = S->getLocStart();
1375 2: buf = "goto __continue_label_";
1376 2: buf += utostr(ObjCBcLabelNo.back());
1377 2: ReplaceText(startLoc, strlen("continue"), buf.c_str(), buf.size());
1378 :
1379 2: return 0;
1380 : }
1381 :
1382 : /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
1383 : /// It rewrites:
1384 : /// for ( type elem in collection) { stmts; }
1385 :
1386 : /// Into:
1387 : /// {
1388 : /// type elem;
1389 : /// struct __objcFastEnumerationState enumState = { 0 };
1390 : /// id items[16];
1391 : /// id l_collection = (id)collection;
1392 : /// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1393 : /// objects:items count:16];
1394 : /// if (limit) {
1395 : /// unsigned long startMutations = *enumState.mutationsPtr;
1396 : /// do {
1397 : /// unsigned long counter = 0;
1398 : /// do {
1399 : /// if (startMutations != *enumState.mutationsPtr)
1400 : /// objc_enumerationMutation(l_collection);
1401 : /// elem = (type)enumState.itemsPtr[counter++];
1402 : /// stmts;
1403 : /// __continue_label: ;
1404 : /// } while (counter < limit);
1405 : /// } while (limit = [l_collection countByEnumeratingWithState:&enumState
1406 : /// objects:items count:16]);
1407 : /// elem = nil;
1408 : /// __break_label: ;
1409 : /// }
1410 : /// else
1411 : /// elem = nil;
1412 : /// }
1413 : ///
1414 : Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
1415 16: SourceLocation OrigEnd) {
16: branch 1 taken
0: branch 2 not taken
1416 16: assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
1417 : assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
16: branch 2 taken
0: branch 3 not taken
1418 16: "ObjCForCollectionStmt Statement stack mismatch");
1419 : assert(!ObjCBcLabelNo.empty() &&
16: branch 1 taken
0: branch 2 not taken
1420 16: "ObjCForCollectionStmt - Label No stack empty");
1421 :
1422 16: SourceLocation startLoc = S->getLocStart();
1423 16: const char *startBuf = SM->getCharacterData(startLoc);
1424 : const char *elementName;
1425 16: std::string elementTypeAsString;
1426 16: std::string buf;
1427 16: buf = "\n{\n\t";
7: branch 2 taken
9: branch 3 taken
1428 16: if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
1429 : // type elem;
1430 7: NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
1431 7: QualType ElementType = cast<ValueDecl>(D)->getType();
7: branch 2 taken
0: branch 3 not taken
0: branch 6 not taken
7: branch 7 taken
0: branch 8 not taken
7: branch 9 taken
1432 7: if (ElementType->isObjCQualifiedIdType() ||
1433 : ElementType->isObjCQualifiedInterfaceType())
1434 : // Simply use 'id' for all qualified types.
1435 0: elementTypeAsString = "id";
1436 : else
1437 7: elementTypeAsString = ElementType.getAsString();
1438 7: buf += elementTypeAsString;
1439 7: buf += " ";
1440 7: elementName = D->getNameAsCString();
1441 7: buf += elementName;
1442 7: buf += ";\n\t";
1443 : }
1444 : else {
1445 9: DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
1446 9: elementName = DR->getDecl()->getNameAsCString();
1447 9: ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
9: branch 3 taken
0: branch 4 not taken
0: branch 8 not taken
9: branch 9 taken
0: branch 10 not taken
9: branch 11 taken
1448 9: if (VD->getType()->isObjCQualifiedIdType() ||
1449 : VD->getType()->isObjCQualifiedInterfaceType())
1450 : // Simply use 'id' for all qualified types.
1451 0: elementTypeAsString = "id";
1452 : else
1453 9: elementTypeAsString = VD->getType().getAsString();
1454 : }
1455 :
1456 : // struct __objcFastEnumerationState enumState = { 0 };
1457 16: buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
1458 : // id items[16];
1459 16: buf += "id items[16];\n\t";
1460 : // id l_collection = (id)
1461 16: buf += "id l_collection = (id)";
1462 : // Find start location of 'collection' the hard way!
1463 16: const char *startCollectionBuf = startBuf;
1464 16: startCollectionBuf += 3; // skip 'for'
1465 16: startCollectionBuf = strchr(startCollectionBuf, '(');
1466 16: startCollectionBuf++; // skip '('
1467 : // find 'in' and skip it.
81: branch 0 taken
25: branch 1 taken
9: branch 2 taken
16: branch 3 taken
0: branch 4 not taken
16: branch 5 taken
3: branch 6 taken
13: branch 7 taken
1: branch 8 taken
2: branch 9 taken
0: branch 10 not taken
1: branch 11 taken
1468 122: while (*startCollectionBuf != ' ' ||
1469 : *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
1470 : (*(startCollectionBuf+3) != ' ' &&
1471 : *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
1472 90: startCollectionBuf++;
1473 16: startCollectionBuf += 3;
1474 :
1475 : // Replace: "for (type element in" with string constructed thus far.
1476 : ReplaceText(startLoc, startCollectionBuf - startBuf,
1477 16: buf.c_str(), buf.size());
1478 : // Replace ')' in for '(' type elem in collection ')' with ';'
1479 16: SourceLocation rightParenLoc = S->getRParenLoc();
1480 16: const char *rparenBuf = SM->getCharacterData(rightParenLoc);
1481 16: SourceLocation lparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf);
1482 16: buf = ";\n\t";
1483 :
1484 : // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
1485 : // objects:items count:16];
1486 : // which is synthesized into:
1487 : // unsigned int limit =
1488 : // ((unsigned int (*)
1489 : // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
1490 : // (void *)objc_msgSend)((id)l_collection,
1491 : // sel_registerName(
1492 : // "countByEnumeratingWithState:objects:count:"),
1493 : // (struct __objcFastEnumerationState *)&state,
1494 : // (id *)items, (unsigned int)16);
1495 16: buf += "unsigned long limit =\n\t\t";
1496 16: SynthCountByEnumWithState(buf);
1497 16: buf += ";\n\t";
1498 : /// if (limit) {
1499 : /// unsigned long startMutations = *enumState.mutationsPtr;
1500 : /// do {
1501 : /// unsigned long counter = 0;
1502 : /// do {
1503 : /// if (startMutations != *enumState.mutationsPtr)
1504 : /// objc_enumerationMutation(l_collection);
1505 : /// elem = (type)enumState.itemsPtr[counter++];
1506 16: buf += "if (limit) {\n\t";
1507 16: buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
1508 16: buf += "do {\n\t\t";
1509 16: buf += "unsigned long counter = 0;\n\t\t";
1510 16: buf += "do {\n\t\t\t";
1511 16: buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
1512 16: buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
1513 16: buf += elementName;
1514 16: buf += " = (";
1515 16: buf += elementTypeAsString;
1516 16: buf += ")enumState.itemsPtr[counter++];";
1517 : // Replace ')' in for '(' type elem in collection ')' with all of these.
1518 16: ReplaceText(lparenLoc, 1, buf.c_str(), buf.size());
1519 :
1520 : /// __continue_label: ;
1521 : /// } while (counter < limit);
1522 : /// } while (limit = [l_collection countByEnumeratingWithState:&enumState
1523 : /// objects:items count:16]);
1524 : /// elem = nil;
1525 : /// __break_label: ;
1526 : /// }
1527 : /// else
1528 : /// elem = nil;
1529 : /// }
1530 : ///
1531 16: buf = ";\n\t";
1532 16: buf += "__continue_label_";
1533 16: buf += utostr(ObjCBcLabelNo.back());
1534 16: buf += ": ;";
1535 16: buf += "\n\t\t";
1536 16: buf += "} while (counter < limit);\n\t";
1537 16: buf += "} while (limit = ";
1538 16: SynthCountByEnumWithState(buf);
1539 16: buf += ");\n\t";
1540 16: buf += elementName;
1541 16: buf += " = ((";
1542 16: buf += elementTypeAsString;
1543 16: buf += ")0);\n\t";
1544 16: buf += "__break_label_";
1545 16: buf += utostr(ObjCBcLabelNo.back());
1546 16: buf += ": ;\n\t";
1547 16: buf += "}\n\t";
1548 16: buf += "else\n\t\t";
1549 16: buf += elementName;
1550 16: buf += " = ((";
1551 16: buf += elementTypeAsString;
1552 16: buf += ")0);\n\t";
1553 16: buf += "}\n";
1554 :
1555 : // Insert all these *after* the statement body.
1556 : // FIXME: If this should support Obj-C++, support CXXTryStmt
10: branch 2 taken
6: branch 3 taken
1557 16: if (isa<CompoundStmt>(S->getBody())) {
1558 10: SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1);
1559 10: InsertText(endBodyLoc, buf.c_str(), buf.size());
1560 : } else {
1561 : /* Need to treat single statements specially. For example:
1562 : *
1563 : * for (A *a in b) if (stuff()) break;
1564 : * for (A *a in b) xxxyy;
1565 : *
1566 : * The following code simply scans ahead to the semi to find the actual end.
1567 : */
1568 6: const char *stmtBuf = SM->getCharacterData(OrigEnd);
1569 6: const char *semiBuf = strchr(stmtBuf, ';');
0: branch 0 not taken
6: branch 1 taken
1570 6: assert(semiBuf && "Can't find ';'");
1571 6: SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(semiBuf-stmtBuf+1);
1572 6: InsertText(endBodyLoc, buf.c_str(), buf.size());
1573 : }
1574 16: Stmts.pop_back();
1575 16: ObjCBcLabelNo.pop_back();
1576 16: return 0;
1577 : }
1578 :
1579 : /// RewriteObjCSynchronizedStmt -
1580 : /// This routine rewrites @synchronized(expr) stmt;
1581 : /// into:
1582 : /// objc_sync_enter(expr);
1583 : /// @try stmt @finally { objc_sync_exit(expr); }
1584 : ///
1585 3: Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
1586 : // Get the start location and compute the semi location.
1587 3: SourceLocation startLoc = S->getLocStart();
1588 3: const char *startBuf = SM->getCharacterData(startLoc);
1589 :
0: branch 0 not taken
3: branch 1 taken
1590 3: assert((*startBuf == '@') && "bogus @synchronized location");
1591 :
1592 3: std::string buf;
1593 3: buf = "objc_sync_enter((id)";
1594 3: const char *lparenBuf = startBuf;
42: branch 0 taken
3: branch 1 taken
1595 3: while (*lparenBuf != '(') lparenBuf++;
1596 3: ReplaceText(startLoc, lparenBuf-startBuf+1, buf.c_str(), buf.size());
1597 : // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
1598 : // the sync expression is typically a message expression that's already
1599 : // been rewritten! (which implies the SourceLocation's are invalid).
1600 3: SourceLocation endLoc = S->getSynchBody()->getLocStart();
1601 3: const char *endBuf = SM->getCharacterData(endLoc);
6: branch 0 taken
3: branch 1 taken
1602 3: while (*endBuf != ')') endBuf--;
1603 3: SourceLocation rparenLoc = startLoc.getFileLocWithOffset(endBuf-startBuf);
1604 3: buf = ");\n";
1605 : // declare a new scope with two variables, _stack and _rethrow.
1606 3: buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";
1607 3: buf += "int buf[18/*32-bit i386*/];\n";
1608 3: buf += "char *pointers[4];} _stack;\n";
1609 3: buf += "id volatile _rethrow = 0;\n";
1610 3: buf += "objc_exception_try_enter(&_stack);\n";
1611 3: buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1612 3: ReplaceText(rparenLoc, 1, buf.c_str(), buf.size());
1613 3: startLoc = S->getSynchBody()->getLocEnd();
1614 3: startBuf = SM->getCharacterData(startLoc);
1615 :
0: branch 0 not taken
3: branch 1 taken
1616 3: assert((*startBuf == '}') && "bogus @synchronized block");
1617 3: SourceLocation lastCurlyLoc = startLoc;
1618 3: buf = "}\nelse {\n";
1619 3: buf += " _rethrow = objc_exception_extract(&_stack);\n";
1620 3: buf += "}\n";
1621 3: buf += "{ /* implicit finally clause */\n";
1622 3: buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1623 :
1624 3: std::string syncBuf;
1625 3: syncBuf += " objc_sync_exit(";
1626 : Expr *syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
1627 : CastExpr::CK_Unknown,
1628 3: S->getSynchExpr());
1629 3: std::string syncExprBufS;
1630 3: llvm::raw_string_ostream syncExprBuf(syncExprBufS);
1631 : syncExpr->printPretty(syncExprBuf, *Context, 0,
1632 3: PrintingPolicy(LangOpts));
1633 3: syncBuf += syncExprBuf.str();
1634 3: syncBuf += ");";
1635 :
1636 3: buf += syncBuf;
1637 3: buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n";
1638 3: buf += "}\n";
1639 3: buf += "}";
1640 :
1641 3: ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
1642 :
1643 3: bool hasReturns = false;
1644 3: HasReturnStmts(S->getSynchBody(), hasReturns);
3: branch 0 taken
0: branch 1 not taken
1645 3: if (hasReturns)
1646 3: RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
1647 :
1648 3: return 0;
1649 : }
1650 :
1651 26: void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
1652 : {
1653 : // Perform a bottom up traversal of all children.
22: branch 4 taken
26: branch 5 taken
1654 48: for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
1655 : CI != E; ++CI)
22: branch 1 taken
0: branch 2 not taken
1656 22: if (*CI)
1657 22: WarnAboutReturnGotoStmts(*CI);
1658 :
25: branch 1 taken
1: branch 2 taken
0: branch 4 not taken
25: branch 5 taken
1: branch 6 taken
25: branch 7 taken
1659 26: if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
1660 : Diags.Report(Context->getFullLoc(S->getLocStart()),
1661 1: TryFinallyContainsReturnDiag);
1662 : }
1663 : return;
1664 : }
1665 :
1666 23: void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)
1667 : {
1668 : // Perform a bottom up traversal of all children.
16: branch 4 taken
23: branch 5 taken
1669 39: for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
1670 : CI != E; ++CI)
16: branch 1 taken
0: branch 2 not taken
1671 16: if (*CI)
1672 16: HasReturnStmts(*CI, hasReturns);
1673 :
4: branch 1 taken
19: branch 2 taken
1674 23: if (isa<ReturnStmt>(S))
1675 4: hasReturns = true;
1676 : return;
1677 : }
1678 :
1679 2: void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
1680 : // Perform a bottom up traversal of all children.
1: branch 4 taken
2: branch 5 taken
1681 3: for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
1682 : CI != E; ++CI)
1: branch 1 taken
0: branch 2 not taken
1683 1: if (*CI) {
1684 1: RewriteTryReturnStmts(*CI);
1685 : }
1: branch 1 taken
1: branch 2 taken
1686 2: if (isa<ReturnStmt>(S)) {
1687 1: SourceLocation startLoc = S->getLocStart();
1688 1: const char *startBuf = SM->getCharacterData(startLoc);
1689 :
1690 1: const char *semiBuf = strchr(startBuf, ';');
0: branch 0 not taken
1: branch 1 taken
1691 1: assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
1692 1: SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
1693 :
1694 1: std::string buf;
1695 1: buf = "{ objc_exception_try_exit(&_stack); return";
1696 :
1697 1: ReplaceText(startLoc, 6, buf.c_str(), buf.size());
1698 1: InsertText(onePastSemiLoc, "}", 1);
1699 : }
1700 : return;
1701 : }
1702 :
1703 12: void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
1704 : // Perform a bottom up traversal of all children.
9: branch 4 taken
12: branch 5 taken
1705 21: for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
1706 : CI != E; ++CI)
9: branch 1 taken
0: branch 2 not taken
1707 9: if (*CI) {
1708 9: RewriteSyncReturnStmts(*CI, syncExitBuf);
1709 : }
3: branch 1 taken
9: branch 2 taken
1710 12: if (isa<ReturnStmt>(S)) {
1711 3: SourceLocation startLoc = S->getLocStart();
1712 3: const char *startBuf = SM->getCharacterData(startLoc);
1713 :
1714 3: const char *semiBuf = strchr(startBuf, ';');
0: branch 0 not taken
3: branch 1 taken
1715 3: assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
1716 3: SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
1717 :
1718 3: std::string buf;
1719 3: buf = "{ objc_exception_try_exit(&_stack);";
1720 3: buf += syncExitBuf;
1721 3: buf += " return";
1722 :
1723 3: ReplaceText(startLoc, 6, buf.c_str(), buf.size());
1724 3: InsertText(onePastSemiLoc, "}", 1);
1725 : }
1726 : return;
1727 : }
1728 :
1729 8: Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
1730 : // Get the start location and compute the semi location.
1731 8: SourceLocation startLoc = S->getLocStart();
1732 8: const char *startBuf = SM->getCharacterData(startLoc);
1733 :
0: branch 0 not taken
8: branch 1 taken
1734 8: assert((*startBuf == '@') && "bogus @try location");
1735 :
1736 8: std::string buf;
1737 : // declare a new scope with two variables, _stack and _rethrow.
1738 8: buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
1739 8: buf += "int buf[18/*32-bit i386*/];\n";
1740 8: buf += "char *pointers[4];} _stack;\n";
1741 8: buf += "id volatile _rethrow = 0;\n";
1742 8: buf += "objc_exception_try_enter(&_stack);\n";
1743 8: buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
1744 :
1745 8: ReplaceText(startLoc, 4, buf.c_str(), buf.size());
1746 :
1747 8: startLoc = S->getTryBody()->getLocEnd();
1748 8: startBuf = SM->getCharacterData(startLoc);
1749 :
0: branch 0 not taken
8: branch 1 taken
1750 8: assert((*startBuf == '}') && "bogus @try block");
1751 :
1752 8: SourceLocation lastCurlyLoc = startLoc;
1753 8: ObjCAtCatchStmt *catchList = S->getCatchStmts();
4: branch 0 taken
4: branch 1 taken
1754 8: if (catchList) {
1755 4: startLoc = startLoc.getFileLocWithOffset(1);
1756 4: buf = " /* @catch begin */ else {\n";
1757 4: buf += " id _caught = objc_exception_extract(&_stack);\n";
1758 4: buf += " objc_exception_try_enter (&_stack);\n";
1759 4: buf += " if (_setjmp(_stack.buf))\n";
1760 4: buf += " _rethrow = objc_exception_extract(&_stack);\n";
1761 4: buf += " else { /* @catch continue */";
1762 :
1763 4: InsertText(startLoc, buf.c_str(), buf.size());
1764 : } else { /* no catch list */
1765 4: buf = "}\nelse {\n";
1766 4: buf += " _rethrow = objc_exception_extract(&_stack);\n";
1767 4: buf += "}";
1768 4: ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
1769 : }
1770 8: bool sawIdTypedCatch = false;
1771 8: Stmt *lastCatchBody = 0;
6: branch 0 taken
8: branch 1 taken
1772 22: while (catchList) {
1773 6: ParmVarDecl *catchDecl = catchList->getCatchParamDecl();
1774 :
4: branch 1 taken
2: branch 2 taken
1775 6: if (catchList == S->getCatchStmts())
1776 4: buf = "if ("; // we are generating code for the first catch clause
1777 : else
1778 2: buf = "else if (";
1779 6: startLoc = catchList->getLocStart();
1780 6: startBuf = SM->getCharacterData(startLoc);
1781 :
0: branch 0 not taken
6: branch 1 taken
1782 6: assert((*startBuf == '@') && "bogus @catch location");
1783 :
1784 6: const char *lParenLoc = strchr(startBuf, '(');
1785 :
2: branch 1 taken
4: branch 2 taken
1786 6: if (catchList->hasEllipsis()) {
1787 : // Now rewrite the body...
1788 2: lastCatchBody = catchList->getCatchBody();
1789 2: SourceLocation bodyLoc = lastCatchBody->getLocStart();
1790 2: const char *bodyBuf = SM->getCharacterData(bodyLoc);
1791 : assert(*SM->getCharacterData(catchList->getRParenLoc()) == ')' &&
2: branch 2 taken
0: branch 3 not taken
1792 2: "bogus @catch paren location");
0: branch 0 not taken
2: branch 1 taken
1793 2: assert((*bodyBuf == '{') && "bogus @catch body location");
1794 :
1795 2: buf += "1) { id _tmp = _caught;";
1796 2: Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
4: branch 0 taken
0: branch 1 not taken
1797 4: } else if (catchDecl) {
1798 4: QualType t = catchDecl->getType();
1: branch 2 taken
3: branch 3 taken
1799 4: if (t == Context->getObjCIdType()) {
1800 1: buf += "1) { ";
1801 1: ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size());
1802 1: sawIdTypedCatch = true;
3: branch 2 taken
0: branch 3 not taken
1803 3: } else if (t->isObjCObjectPointerType()) {
1804 3: QualType InterfaceTy = t->getPointeeType();
1805 : const ObjCInterfaceType *cls = // Should be a pointer to a class.
1806 3: InterfaceTy->getAs<ObjCInterfaceType>();
3: branch 0 taken
0: branch 1 not taken
1807 3: if (cls) {
1808 3: buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
1809 3: buf += cls->getDecl()->getNameAsString();
1810 3: buf += "\"), (struct objc_object *)_caught)) { ";
1811 3: ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size());
1812 : }
1813 : }
1814 : // Now rewrite the body...
1815 4: lastCatchBody = catchList->getCatchBody();
1816 4: SourceLocation rParenLoc = catchList->getRParenLoc();
1817 4: SourceLocation bodyLoc = lastCatchBody->getLocStart();
1818 4: const char *bodyBuf = SM->getCharacterData(bodyLoc);
1819 4: const char *rParenBuf = SM->getCharacterData(rParenLoc);
0: branch 0 not taken
4: branch 1 taken
1820 4: assert((*rParenBuf == ')') && "bogus @catch paren location");
0: branch 0 not taken
4: branch 1 taken
1821 4: assert((*bodyBuf == '{') && "bogus @catch body location");
1822 :
1823 4: buf = " = _caught;";
1824 : // Here we replace ") {" with "= _caught;" (which initializes and
1825 : // declares the @catch parameter).
1826 4: ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, buf.c_str(), buf.size());
1827 : } else {
1828 0: assert(false && "@catch rewrite bug");
1829 : }
1830 : // make sure all the catch bodies get rewritten!
1831 6: catchList = catchList->getNextCatchStmt();
1832 : }
1833 : // Complete the catch list...
4: branch 0 taken
4: branch 1 taken
1834 8: if (lastCatchBody) {
1835 4: SourceLocation bodyLoc = lastCatchBody->getLocEnd();
1836 : assert(*SM->getCharacterData(bodyLoc) == '}' &&
4: branch 1 taken
0: branch 2 not taken
1837 4: "bogus @catch body location");
1838 :
1839 : // Insert the last (implicit) else clause *before* the right curly brace.
1840 4: bodyLoc = bodyLoc.getFileLocWithOffset(-1);
1841 4: buf = "} /* last catch end */\n";
1842 4: buf += "else {\n";
1843 4: buf += " _rethrow = _caught;\n";
1844 4: buf += " objc_exception_try_exit(&_stack);\n";
1845 4: buf += "} } /* @catch end */\n";
4: branch 1 taken
0: branch 2 not taken
1846 4: if (!S->getFinallyStmt())
1847 4: buf += "}\n";
1848 4: InsertText(bodyLoc, buf.c_str(), buf.size());
1849 :
1850 : // Set lastCurlyLoc
1851 4: lastCurlyLoc = lastCatchBody->getLocEnd();
1852 : }
4: branch 1 taken
4: branch 2 taken
1853 8: if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
1854 4: startLoc = finalStmt->getLocStart();
1855 4: startBuf = SM->getCharacterData(startLoc);
0: branch 0 not taken
4: branch 1 taken
1856 4: assert((*startBuf == '@') && "bogus @finally start");
1857 :
1858 4: buf = "/* @finally */";
1859 4: ReplaceText(startLoc, 8, buf.c_str(), buf.size());
1860 :
1861 4: Stmt *body = finalStmt->getFinallyBody();
1862 4: SourceLocation startLoc = body->getLocStart();
1863 4: SourceLocation endLoc = body->getLocEnd();
1864 : assert(*SM->getCharacterData(startLoc) == '{' &&
4: branch 1 taken
0: branch 2 not taken
1865 4: "bogus @finally body location");
1866 : assert(*SM->getCharacterData(endLoc) == '}' &&
4: branch 1 taken
0: branch 2 not taken
1867 4: "bogus @finally body location");
1868 :
1869 4: startLoc = startLoc.getFileLocWithOffset(1);
1870 4: buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1871 4: InsertText(startLoc, buf.c_str(), buf.size());
1872 4: endLoc = endLoc.getFileLocWithOffset(-1);
1873 4: buf = " if (_rethrow) objc_exception_throw(_rethrow);\n";
1874 4: InsertText(endLoc, buf.c_str(), buf.size());
1875 :
1876 : // Set lastCurlyLoc
1877 4: lastCurlyLoc = body->getLocEnd();
1878 :
1879 : // Now check for any return/continue/go statements within the @try.
1880 4: WarnAboutReturnGotoStmts(S->getTryBody());
1881 : } else { /* no finally clause - make sure we synthesize an implicit one */
1882 4: buf = "{ /* implicit finally clause */\n";
1883 4: buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
1884 4: buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
1885 4: buf += "}";
1886 4: ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
1887 :
1888 : // Now check for any return/continue/go statements within the @try.
1889 : // The implicit finally clause won't called if the @try contains any
1890 : // jump statements.
1891 4: bool hasReturns = false;
1892 4: HasReturnStmts(S->getTryBody(), hasReturns);
1: branch 0 taken
3: branch 1 taken
1893 4: if (hasReturns)
1894 1: RewriteTryReturnStmts(S->getTryBody());
1895 : }
1896 : // Now emit the final closing curly brace...
1897 8: lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
1898 8: buf = " } /* @try scope end */\n";
1899 8: InsertText(lastCurlyLoc, buf.c_str(), buf.size());
1900 8: return 0;
1901 : }
1902 :
1903 0: Stmt *RewriteObjC::RewriteObjCCatchStmt(ObjCAtCatchStmt *S) {
1904 0: return 0;
1905 : }
1906 :
1907 0: Stmt *RewriteObjC::RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S) {
1908 0: return 0;
1909 : }
1910 :
1911 : // This can't be done with ReplaceStmt(S, ThrowExpr), since
1912 : // the throw expression is typically a message expression that's already
1913 : // been rewritten! (which implies the SourceLocation's are invalid).
1914 2: Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
1915 : // Get the start location and compute the semi location.
1916 2: SourceLocation startLoc = S->getLocStart();
1917 2: const char *startBuf = SM->getCharacterData(startLoc);
1918 :
0: branch 0 not taken
2: branch 1 taken
1919 2: assert((*startBuf == '@') && "bogus @throw location");
1920 :
1921 2: std::string buf;
1922 : /* void objc_exception_throw(id) __attribute__((noreturn)); */
0: branch 1 not taken
2: branch 2 taken
1923 2: if (S->getThrowExpr())
1924 0: buf = "objc_exception_throw(";
1925 : else // add an implicit argument
1926 2: buf = "objc_exception_throw(_caught";
1927 :
1928 : // handle "@ throw" correctly.
1929 2: const char *wBuf = strchr(startBuf, 'w');
0: branch 0 not taken
2: branch 1 taken
1930 2: assert((*wBuf == 'w') && "@throw: can't find 'w'");
1931 2: ReplaceText(startLoc, wBuf-startBuf+1, buf.c_str(), buf.size());
1932 :
1933 2: const char *semiBuf = strchr(startBuf, ';');
0: branch 0 not taken
2: branch 1 taken
1934 2: assert((*semiBuf == ';') && "@throw: can't find ';'");
1935 2: SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf);
1936 2: buf = ");";
1937 2: ReplaceText(semiLoc, 1, buf.c_str(), buf.size());
1938 2: return 0;
1939 : }
1940 :
1941 0: Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
1942 : // Create a new string expression.
1943 0: QualType StrType = Context->getPointerType(Context->CharTy);
1944 0: std::string StrEncoding;
1945 0: Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
1946 : Expr *Replacement = StringLiteral::Create(*Context,StrEncoding.c_str(),
1947 : StrEncoding.length(), false,StrType,
1948 0: SourceLocation());
1949 0: ReplaceStmt(Exp, Replacement);
1950 :
1951 : // Replace this subexpr in the parent.
1952 : // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
1953 0: return Replacement;
1954 : }
1955 :
1956 0: Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
0: branch 0 not taken
0: branch 1 not taken
1957 0: if (!SelGetUidFunctionDecl)
1958 0: SynthSelGetUidFunctionDecl();
0: branch 0 not taken
0: branch 1 not taken
1959 0: assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
1960 : // Create a call to sel_registerName("selName").
1961 0: llvm::SmallVector<Expr*, 8> SelExprs;
1962 0: QualType argType = Context->getPointerType(Context->CharTy);
1963 : SelExprs.push_back(StringLiteral::Create(*Context,
1964 : Exp->getSelector().getAsString().c_str(),
1965 : Exp->getSelector().getAsString().size(),
1966 0: false, argType, SourceLocation()));
1967 : CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
1968 0: &SelExprs[0], SelExprs.size());
1969 0: ReplaceStmt(Exp, SelExp);
1970 : // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
1971 0: return SelExp;
1972 : }
1973 :
1974 : CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
1975 56: FunctionDecl *FD, Expr **args, unsigned nargs) {
1976 : // Get the type, we will need to reference it in a couple spots.
1977 56: QualType msgSendType = FD->getType();
1978 :
1979 : // Create a reference to the objc_msgSend() declaration.
56: branch 2 taken
0: branch 3 not taken
1980 56: DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, msgSendType, SourceLocation());
1981 :
1982 : // Now, we cast the reference to a pointer to the objc_msgSend type.
1983 56: QualType pToFunc = Context->getPointerType(msgSendType);
1984 : ImplicitCastExpr *ICE = new (Context) ImplicitCastExpr(pToFunc,
1985 : CastExpr::CK_Unknown,
1986 : DRE,
56: branch 1 taken
0: branch 2 not taken
1987 56: /*isLvalue=*/false);
1988 :
1989 56: const FunctionType *FT = msgSendType->getAs<FunctionType>();
1990 :
1991 : return new (Context) CallExpr(*Context, ICE, args, nargs, FT->getResultType(),
56: branch 3 taken
0: branch 4 not taken
1992 56: SourceLocation());
1993 : }
1994 :
1995 : static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
1996 22: const char *&startRef, const char *&endRef) {
313: branch 0 taken
0: branch 1 not taken
1997 335: while (startBuf < endBuf) {
22: branch 0 taken
291: branch 1 taken
1998 313: if (*startBuf == '<')
1999 22: startRef = startBuf; // mark the start.
22: branch 0 taken
291: branch 1 taken
2000 313: if (*startBuf == '>') {
22: branch 0 taken
0: branch 1 not taken
22: branch 2 taken
0: branch 3 not taken
2001 22: if (startRef && *startRef == '<') {
2002 22: endRef = startBuf; // mark the end.
2003 22: return true;
2004 : }
2005 0: return false;
2006 : }
2007 291: startBuf++;
2008 : }
2009 0: return false;
2010 : }
2011 :
2012 6: static void scanToNextArgument(const char *&argRef) {
2013 6: int angle = 0;
144: branch 0 taken
3: branch 1 taken
139: branch 2 taken
5: branch 3 taken
2: branch 4 taken
3: branch 5 taken
2014 153: while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
6: branch 0 taken
135: branch 1 taken
2015 141: if (*argRef == '<')
2016 6: angle++;
6: branch 0 taken
129: branch 1 taken
2017 135: else if (*argRef == '>')
2018 6: angle--;
2019 141: argRef++;
2020 : }
0: branch 0 not taken
6: branch 1 taken
2021 6: assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
2022 6: }
2023 :
2024 181: bool RewriteObjC::needToScanForQualifiers(QualType T) {
7: branch 2 taken
174: branch 3 taken
2025 181: if (T->isObjCQualifiedIdType())
2026 7: return true;
29: branch 2 taken
145: branch 3 taken
2027 174: if (const PointerType *PT = T->getAs<PointerType>()) {
1: branch 3 taken
28: branch 4 taken
2028 29: if (PT->getPointeeType()->isObjCQualifiedIdType())
2029 1: return true;
2030 : }
62: branch 2 taken
111: branch 3 taken
2031 173: if (T->isObjCObjectPointerType()) {
2032 62: T = T->getPointeeType();
2033 62: return T->isObjCQualifiedInterfaceType();
2034 : }
2035 111: return false;
2036 : }
2037 :
2038 25: void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
2039 25: QualType Type = E->getType();
8: branch 1 taken
17: branch 2 taken
2040 25: if (needToScanForQualifiers(Type)) {
2041 8: SourceLocation Loc, EndLoc;
2042 :
8: branch 1 taken
0: branch 2 not taken
2043 8: if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
2044 8: Loc = ECE->getLParenLoc();
2045 8: EndLoc = ECE->getRParenLoc();
2046 : } else {
2047 0: Loc = E->getLocStart();
2048 0: EndLoc = E->getLocEnd();
2049 : }
2050 : // This will defend against trying to rewrite synthesized expressions.
8: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
8: branch 5 taken
0: branch 6 not taken
8: branch 7 taken
2051 8: if (Loc.isInvalid() || EndLoc.isInvalid())
2052 0: return;
2053 :
2054 8: const char *startBuf = SM->getCharacterData(Loc);
2055 8: const char *endBuf = SM->getCharacterData(EndLoc);
2056 8: const char *startRef = 0, *endRef = 0;
8: branch 1 taken
0: branch 2 not taken
2057 8: if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2058 : // Get the locations of the startRef, endRef.
2059 8: SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
2060 8: SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
2061 : // Comment out the protocol references.
2062 8: InsertText(LessLoc, "/*", 2);
2063 8: InsertText(GreaterLoc, "*/", 2);
2064 : }
2065 : }
2066 : }
2067 :
2068 151: void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
2069 151: SourceLocation Loc;
2070 151: QualType Type;
2071 151: const FunctionProtoType *proto = 0;
90: branch 1 taken
61: branch 2 taken
2072 151: if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
2073 90: Loc = VD->getLocation();
2074 90: Type = VD->getType();
2075 : }
61: branch 1 taken
0: branch 2 not taken
2076 61: else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
2077 61: Loc = FD->getLocation();
2078 : // Check for ObjC 'id' and class types that have been adorned with protocol
2079 : // information (id<p>, C<p>*). The protocol references need to be rewritten!
2080 61: const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
0: branch 0 not taken
61: branch 1 taken
2081 61: assert(funcType && "missing function type");
2082 61: proto = dyn_cast<FunctionProtoType>(funcType);
29: branch 0 taken
32: branch 1 taken
2083 61: if (!proto)
2084 29: return;
2085 32: Type = proto->getResultType();
2086 : }
0: branch 1 not taken
0: branch 2 not taken
2087 0: else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
2088 0: Loc = FD->getLocation();
2089 0: Type = FD->getType();
2090 : }
2091 : else
2092 0: return;
2093 :
8: branch 1 taken
114: branch 2 taken
2094 122: if (needToScanForQualifiers(Type)) {
2095 : // Since types are unique, we need to scan the buffer.
2096 :
2097 8: const char *endBuf = SM->getCharacterData(Loc);
2098 8: const char *startBuf = endBuf;
145: branch 0 taken
0: branch 1 not taken
137: branch 2 taken
8: branch 3 taken
137: branch 4 taken
0: branch 5 not taken
2099 153: while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
2100 137: startBuf--; // scan backward (from the decl location) for return type.
2101 8: const char *startRef = 0, *endRef = 0;
8: branch 1 taken
0: branch 2 not taken
2102 8: if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2103 : // Get the locations of the startRef, endRef.
2104 8: SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
2105 8: SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
2106 : // Comment out the protocol references.
2107 8: InsertText(LessLoc, "/*", 2);
2108 8: InsertText(GreaterLoc, "*/", 2);
2109 : }
2110 : }
90: branch 0 taken
32: branch 1 taken
2111 122: if (!proto)
2112 90: return; // most likely, was a variable
2113 : // Now check arguments.
2114 32: const char *startBuf = SM->getCharacterData(Loc);
2115 32: const char *startFuncBuf = startBuf;
34: branch 1 taken
32: branch 2 taken
2116 66: for (unsigned i = 0; i < proto->getNumArgs(); i++) {
6: branch 2 taken
28: branch 3 taken
2117 34: if (needToScanForQualifiers(proto->getArgType(i))) {
2118 : // Since types are unique, we need to scan the buffer.
2119 :
2120 6: const char *endBuf = startBuf;
2121 : // scan forward (from the decl location) for argument types.
2122 6: scanToNextArgument(endBuf);
2123 6: const char *startRef = 0, *endRef = 0;
6: branch 1 taken
0: branch 2 not taken
2124 6: if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
2125 : // Get the locations of the startRef, endRef.
2126 : SourceLocation LessLoc =
2127 6: Loc.getFileLocWithOffset(startRef-startFuncBuf);
2128 : SourceLocation GreaterLoc =
2129 6: Loc.getFileLocWithOffset(endRef-startFuncBuf+1);
2130 : // Comment out the protocol references.
2131 6: InsertText(LessLoc, "/*", 2);
2132 6: InsertText(GreaterLoc, "*/", 2);
2133 : }
2134 6: startBuf = ++endBuf;
2135 : }
2136 : else {
2137 : // If the function name is derived from a macro expansion, then the
2138 : // argument buffer will not follow the name. Need to speak with Chris.
512: branch 0 taken
0: branch 1 not taken
491: branch 2 taken
21: branch 3 taken
484: branch 4 taken
7: branch 5 taken
2139 540: while (*startBuf && *startBuf != ')' && *startBuf != ',')
2140 484: startBuf++; // scan forward (from the decl location) for argument types.
2141 28: startBuf++;
2142 : }
2143 : }
2144 : }
2145 :
2146 : // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
2147 19: void RewriteObjC::SynthSelGetUidFunctionDecl() {
2148 19: IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
2149 19: llvm::SmallVector<QualType, 16> ArgTys;
2150 19: ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2151 : QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(),
2152 : &ArgTys[0], ArgTys.size(),
2153 19: false /*isVariadic*/, 0);
2154 : SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2155 : SourceLocation(),
2156 : SelGetUidIdent, getFuncType, 0,
19: branch 2 taken
0: branch 3 not taken
2157 19: FunctionDecl::Extern, false);
2158 19: }
2159 :
2160 61: void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
2161 : // declared in <objc/objc.h>
61: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
61: branch 6 taken
0: branch 7 not taken
61: branch 8 taken
2162 61: if (FD->getIdentifier() &&
2163 : strcmp(FD->getNameAsCString(), "sel_registerName") == 0) {
2164 0: SelGetUidFunctionDecl = FD;
2165 0: return;
2166 : }
2167 61: RewriteObjCQualifiedInterfaceTypes(FD);
2168 : }
2169 :
2170 17: void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
2171 17: SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
2172 17: const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
2173 17: const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
11: branch 0 taken
6: branch 1 taken
2174 17: if (!proto)
2175 11: return;
2176 6: QualType Type = proto->getResultType();
2177 6: std::string FdStr = Type.getAsString();
2178 6: FdStr += " ";
2179 6: FdStr += FD->getNameAsCString();
2180 6: FdStr += "(";
2181 6: unsigned numArgs = proto->getNumArgs();
4: branch 0 taken
6: branch 1 taken
2182 10: for (unsigned i = 0; i < numArgs; i++) {
2183 4: QualType ArgType = proto->getArgType(i);
2184 4: FdStr += ArgType.getAsString();
2185 :
1: branch 0 taken
3: branch 1 taken
2186 4: if (i+1 < numArgs)
2187 1: FdStr += ", ";
2188 : }
2189 6: FdStr += ");\n";
2190 6: InsertText(FunLocStart, FdStr.c_str(), FdStr.size());
2191 6: CurFunctionDeclToDeclareForBlock = 0;
2192 : }
2193 :
2194 : // SynthSuperContructorFunctionDecl - id objc_super(id obj, id super);
2195 0: void RewriteObjC::SynthSuperContructorFunctionDecl() {
0: branch 0 not taken
0: branch 1 not taken
2196 0: if (SuperContructorFunctionDecl)
2197 0: return;
2198 0: IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
2199 0: llvm::SmallVector<QualType, 16> ArgTys;
2200 0: QualType argT = Context->getObjCIdType();
0: branch 1 not taken
0: branch 2 not taken
2201 0: assert(!argT.isNull() && "Can't find 'id' type");
2202 0: ArgTys.push_back(argT);
2203 0: ArgTys.push_back(argT);
2204 : QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
2205 : &ArgTys[0], ArgTys.size(),
2206 0: false, 0);
2207 : SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2208 : SourceLocation(),
2209 : msgSendIdent, msgSendType, 0,
0: branch 2 not taken
0: branch 3 not taken
2210 0: FunctionDecl::Extern, false);
2211 : }
2212 :
2213 : // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
2214 19: void RewriteObjC::SynthMsgSendFunctionDecl() {
2215 19: IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
2216 19: llvm::SmallVector<QualType, 16> ArgTys;
2217 19: QualType argT = Context->getObjCIdType();
19: branch 1 taken
0: branch 2 not taken
2218 19: assert(!argT.isNull() && "Can't find 'id' type");
2219 19: ArgTys.push_back(argT);
2220 19: argT = Context->getObjCSelType();
19: branch 1 taken
0: branch 2 not taken
2221 19: assert(!argT.isNull() && "Can't find 'SEL' type");
2222 19: ArgTys.push_back(argT);
2223 : QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
2224 : &ArgTys[0], ArgTys.size(),
2225 19: true /*isVariadic*/, 0);
2226 : MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2227 : SourceLocation(),
2228 : msgSendIdent, msgSendType, 0,
19: branch 2 taken
0: branch 3 not taken
2229 38: FunctionDecl::Extern, false);
2230 19: }
2231 :
2232 : // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
2233 19: void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
2234 19: IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
2235 19: llvm::SmallVector<QualType, 16> ArgTys;
2236 : RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
2237 : SourceLocation(),
19: branch 4 taken
0: branch 5 not taken
2238 19: &Context->Idents.get("objc_super"));
2239 19: QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
19: branch 1 taken
0: branch 2 not taken
2240 19: assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
2241 19: ArgTys.push_back(argT);
2242 19: argT = Context->getObjCSelType();
19: branch 1 taken
0: branch 2 not taken
2243 19: assert(!argT.isNull() && "Can't find 'SEL' type");
2244 19: ArgTys.push_back(argT);
2245 : QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
2246 : &ArgTys[0], ArgTys.size(),
2247 19: true /*isVariadic*/, 0);
2248 : MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2249 : SourceLocation(),
2250 : msgSendIdent, msgSendType, 0,
19: branch 2 taken
0: branch 3 not taken
2251 38: FunctionDecl::Extern, false);
2252 19: }
2253 :
2254 : // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
2255 19: void RewriteObjC::SynthMsgSendStretFunctionDecl() {
2256 19: IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
2257 19: llvm::SmallVector<QualType, 16> ArgTys;
2258 19: QualType argT = Context->getObjCIdType();
19: branch 1 taken
0: branch 2 not taken
2259 19: assert(!argT.isNull() && "Can't find 'id' type");
2260 19: ArgTys.push_back(argT);
2261 19: argT = Context->getObjCSelType();
19: branch 1 taken
0: branch 2 not taken
2262 19: assert(!argT.isNull() && "Can't find 'SEL' type");
2263 19: ArgTys.push_back(argT);
2264 : QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
2265 : &ArgTys[0], ArgTys.size(),
2266 19: true /*isVariadic*/, 0);
2267 : MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2268 : SourceLocation(),
2269 : msgSendIdent, msgSendType, 0,
19: branch 2 taken
0: branch 3 not taken
2270 38: FunctionDecl::Extern, false);
2271 19: }
2272 :
2273 : // SynthMsgSendSuperStretFunctionDecl -
2274 : // id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
2275 19: void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
2276 : IdentifierInfo *msgSendIdent =
2277 19: &Context->Idents.get("objc_msgSendSuper_stret");
2278 19: llvm::SmallVector<QualType, 16> ArgTys;
2279 : RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
2280 : SourceLocation(),
19: branch 4 taken
0: branch 5 not taken
2281 19: &Context->Idents.get("objc_super"));
2282 19: QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
19: branch 1 taken
0: branch 2 not taken
2283 19: assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
2284 19: ArgTys.push_back(argT);
2285 19: argT = Context->getObjCSelType();
19: branch 1 taken
0: branch 2 not taken
2286 19: assert(!argT.isNull() && "Can't find 'SEL' type");
2287 19: ArgTys.push_back(argT);
2288 : QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
2289 : &ArgTys[0], ArgTys.size(),
2290 19: true /*isVariadic*/, 0);
2291 : MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2292 : SourceLocation(),
2293 : msgSendIdent, msgSendType, 0,
19: branch 2 taken
0: branch 3 not taken
2294 38: FunctionDecl::Extern, false);
2295 19: }
2296 :
2297 : // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
2298 19: void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
2299 19: IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
2300 19: llvm::SmallVector<QualType, 16> ArgTys;
2301 19: QualType argT = Context->getObjCIdType();
19: branch 1 taken
0: branch 2 not taken
2302 19: assert(!argT.isNull() && "Can't find 'id' type");
2303 19: ArgTys.push_back(argT);
2304 19: argT = Context->getObjCSelType();
19: branch 1 taken
0: branch 2 not taken
2305 19: assert(!argT.isNull() && "Can't find 'SEL' type");
2306 19: ArgTys.push_back(argT);
2307 : QualType msgSendType = Context->getFunctionType(Context->DoubleTy,
2308 : &ArgTys[0], ArgTys.size(),
2309 19: true /*isVariadic*/, 0);
2310 : MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2311 : SourceLocation(),
2312 : msgSendIdent, msgSendType, 0,
19: branch 2 taken
0: branch 3 not taken
2313 38: FunctionDecl::Extern, false);
2314 19: }
2315 :
2316 : // SynthGetClassFunctionDecl - id objc_getClass(const char *name);
2317 19: void RewriteObjC::SynthGetClassFunctionDecl() {
2318 19: IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
2319 19: llvm::SmallVector<QualType, 16> ArgTys;
2320 19: ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2321 : QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
2322 : &ArgTys[0], ArgTys.size(),
2323 19: false /*isVariadic*/, 0);
2324 : GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2325 : SourceLocation(),
2326 : getClassIdent, getClassType, 0,
19: branch 2 taken
0: branch 3 not taken
2327 19: FunctionDecl::Extern, false);
2328 19: }
2329 :
2330 : // SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
2331 19: void RewriteObjC::SynthGetMetaClassFunctionDecl() {
2332 19: IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
2333 19: llvm::SmallVector<QualType, 16> ArgTys;
2334 19: ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
2335 : QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
2336 : &ArgTys[0], ArgTys.size(),
2337 19: false /*isVariadic*/, 0);
2338 : GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
2339 : SourceLocation(),
2340 : getClassIdent, getClassType, 0,
19: branch 2 taken
0: branch 3 not taken
2341 19: FunctionDecl::Extern, false);
2342 19: }
2343 :
2344 16: Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
2345 16: QualType strType = getConstantStringStructType();
2346 :
2347 16: std::string S = "__NSConstantStringImpl_";
2348 :
2349 16: std::string tmpName = InFileName;
2350 : unsigned i;
1004: branch 1 taken
16: branch 2 taken
2351 1020: for (i=0; i < tmpName.length(); i++) {
2352 1004: char c = tmpName.at(i);
2353 : // replace any non alphanumeric characters with '_'.
192: branch 1 taken
812: branch 2 taken
4: branch 3 taken
188: branch 4 taken
0: branch 5 not taken
4: branch 6 taken
2354 1004: if (!isalpha(c) && (c < '0' || c > '9'))
2355 188: tmpName[i] = '_';
2356 : }
2357 16: S += tmpName;
2358 16: S += "_";
2359 16: S += utostr(NumObjCStringLiterals++);
2360 :
2361 16: Preamble += "static __NSConstantStringImpl " + S;
2362 16: Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
2363 16: Preamble += "0x000007c8,"; // utf8_str
2364 : // The pretty printer for StringLiteral handles escape characters properly.
2365 16: std::string prettyBufS;
2366 16: llvm::raw_string_ostream prettyBuf(prettyBufS);
2367 : Exp->getString()->printPretty(prettyBuf, *Context, 0,
2368 16: PrintingPolicy(LangOpts));
2369 16: Preamble += prettyBuf.str();
2370 16: Preamble += ",";
2371 16: Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
2372 :
2373 : VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
2374 : &Context->Idents.get(S.c_str()), strType, 0,
16: branch 4 taken
0: branch 5 not taken
2375 16: VarDecl::Static);
16: branch 2 taken
0: branch 3 not taken
2376 16: DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation());
2377 : Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
2378 : Context->getPointerType(DRE->getType()),
16: branch 4 taken
0: branch 5 not taken
2379 16: SourceLocation());
2380 : // cast to NSConstantString *
2381 : CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
2382 16: CastExpr::CK_Unknown, Unop);
2383 16: ReplaceStmt(Exp, cast);
2384 : // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
2385 16: return cast;
2386 : }
2387 :
2388 43: ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) {
2389 : // check if we are sending a message to 'super'
37: branch 0 taken
6: branch 1 taken
6: branch 3 taken
31: branch 4 taken
12: branch 5 taken
31: branch 6 taken
2390 43: if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return 0;
2391 :
1: branch 1 taken
30: branch 2 taken
2392 31: if (ObjCSuperExpr *Super = dyn_cast<ObjCSuperExpr>(recExpr)) {
2393 : const ObjCObjectPointerType *OPT =
2394 1: Super->getType()->getAs<ObjCObjectPointerType>();
0: branch 0 not taken
1: branch 1 taken
2395 1: assert(OPT);
2396 1: const ObjCInterfaceType *IT = OPT->getInterfaceType();
2397 1: return IT->getDecl();
2398 : }
2399 30: return 0;
2400 : }
2401 :
2402 : // struct objc_super { struct objc_object *receiver; struct objc_class *super; };
2403 2: QualType RewriteObjC::getSuperStructType() {
1: branch 0 taken
1: branch 1 taken
2404 2: if (!SuperStructDecl) {
2405 : SuperStructDecl = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
2406 : SourceLocation(),
1: branch 4 taken
0: branch 5 not taken
2407 1: &Context->Idents.get("objc_super"));
2: branch 1 taken
1: branch 2 taken
2408 1: QualType FieldTypes[2];
2409 :
2410 : // struct objc_object *receiver;
2411 1: FieldTypes[0] = Context->getObjCIdType();
2412 : // struct objc_class *super;
2413 1: FieldTypes[1] = Context->getObjCClassType();
2414 :
2415 : // Create fields
2: branch 0 taken
1: branch 1 taken
2416 3: for (unsigned i = 0; i < 2; ++i) {
2417 : SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
2418 : SourceLocation(), 0,
2419 : FieldTypes[i], 0,
2420 : /*BitWidth=*/0,
2: branch 1 taken
0: branch 2 not taken
2421 2: /*Mutable=*/false));
2422 : }
2423 :
2424 1: SuperStructDecl->completeDefinition(*Context);
2425 : }
2426 2: return Context->getTagDeclType(SuperStructDecl);
2427 : }
2428 :
2429 16: QualType RewriteObjC::getConstantStringStructType() {
2: branch 0 taken
14: branch 1 taken
2430 16: if (!ConstantStringDecl) {
2431 : ConstantStringDecl = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
2432 : SourceLocation(),
2: branch 4 taken
0: branch 5 not taken
2433 2: &Context->Idents.get("__NSConstantStringImpl"));
8: branch 1 taken
2: branch 2 taken
2434 2: QualType FieldTypes[4];
2435 :
2436 : // struct objc_object *receiver;
2437 2: FieldTypes[0] = Context->getObjCIdType();
2438 : // int flags;
2439 2: FieldTypes[1] = Context->IntTy;
2440 : // char *str;
2441 2: FieldTypes[2] = Context->getPointerType(Context->CharTy);
2442 : // long length;
2443 2: FieldTypes[3] = Context->LongTy;
2444 :
2445 : // Create fields
8: branch 0 taken
2: branch 1 taken
2446 10: for (unsigned i = 0; i < 4; ++i) {
2447 : ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
2448 : ConstantStringDecl,
2449 : SourceLocation(), 0,
2450 : FieldTypes[i], 0,
2451 : /*BitWidth=*/0,
8: branch 1 taken
0: branch 2 not taken
2452 8: /*Mutable=*/true));
2453 : }
2454 :
2455 2: ConstantStringDecl->completeDefinition(*Context);
2456 : }
2457 16: return Context->getTagDeclType(ConstantStringDecl);
2458 : }
2459 :
2460 49: Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
19: branch 0 taken
30: branch 1 taken
2461 49: if (!SelGetUidFunctionDecl)
2462 19: SynthSelGetUidFunctionDecl();
19: branch 0 taken
30: branch 1 taken
2463 49: if (!MsgSendFunctionDecl)
2464 19: SynthMsgSendFunctionDecl();
19: branch 0 taken
30: branch 1 taken
2465 49: if (!MsgSendSuperFunctionDecl)
2466 19: SynthMsgSendSuperFunctionDecl();
19: branch 0 taken
30: branch 1 taken
2467 49: if (!MsgSendStretFunctionDecl)
2468 19: SynthMsgSendStretFunctionDecl();
19: branch 0 taken
30: branch 1 taken
2469 49: if (!MsgSendSuperStretFunctionDecl)
2470 19: SynthMsgSendSuperStretFunctionDecl();
19: branch 0 taken
30: branch 1 taken
2471 49: if (!MsgSendFpretFunctionDecl)
2472 19: SynthMsgSendFpretFunctionDecl();
19: branch 0 taken
30: branch 1 taken
2473 49: if (!GetClassFunctionDecl)
2474 19: SynthGetClassFunctionDecl();
19: branch 0 taken
30: branch 1 taken
2475 49: if (!GetMetaClassFunctionDecl)
2476 19: SynthGetMetaClassFunctionDecl();
2477 :
2478 : // default to objc_msgSend().
2479 49: FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
2480 : // May need to use objc_msgSend_stret() as well.
2481 49: FunctionDecl *MsgSendStretFlavor = 0;
43: branch 1 taken
6: branch 2 taken
2482 49: if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
2483 43: QualType resultType = mDecl->getResultType();
42: branch 2 taken
1: branch 3 taken
0: branch 6 not taken
42: branch 7 taken
1: branch 8 taken
42: branch 9 taken
2484 43: if (resultType->isStructureType() || resultType->isUnionType())
2485 1: MsgSendStretFlavor = MsgSendStretFunctionDecl;
0: branch 2 not taken
42: branch 3 taken
2486 42: else if (resultType->isRealFloatingType())
2487 0: MsgSendFlavor = MsgSendFpretFunctionDecl;
2488 : }
2489 :
2490 : // Synthesize a call to objc_msgSend().
2491 49: llvm::SmallVector<Expr*, 8> MsgExprs;
2492 49: IdentifierInfo *clsName = Exp->getClassName();
2493 :
2494 : // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
6: branch 0 taken
43: branch 1 taken
2495 49: if (clsName) { // class message.
2496 : // FIXME: We need to fix Sema (and the AST for ObjCMessageExpr) to handle
2497 : // the 'super' idiom within a class method.
0: branch 3 not taken
6: branch 4 taken
2498 6: if (clsName->getName() == "super") {
2499 0: MsgSendFlavor = MsgSendSuperFunctionDecl;
0: branch 0 not taken
0: branch 1 not taken
2500 0: if (MsgSendStretFlavor)
2501 0: MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
0: branch 0 not taken
0: branch 1 not taken
2502 0: assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
2503 :
2504 : ObjCInterfaceDecl *SuperDecl =
2505 0: CurMethodDef->getClassInterface()->getSuperClass();
2506 :
2507 0: llvm::SmallVector<Expr*, 4> InitExprs;
2508 :
2509 : // set the receiver to self, the first argument to all methods.
2510 : InitExprs.push_back(
2511 : NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2512 : CastExpr::CK_Unknown,
2513 : new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
2514 : Context->getObjCIdType(),
2515 : SourceLocation()))
0: branch 4 not taken
0: branch 5 not taken
2516 0: ); // set the 'receiver'.
2517 :
2518 0: llvm::SmallVector<Expr*, 8> ClsExprs;
2519 0: QualType argType = Context->getPointerType(Context->CharTy);
2520 : ClsExprs.push_back(StringLiteral::Create(*Context,
2521 : SuperDecl->getIdentifier()->getNameStart(),
2522 : SuperDecl->getIdentifier()->getLength(),
2523 0: false, argType, SourceLocation()));
2524 : CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
2525 : &ClsExprs[0],
2526 0: ClsExprs.size());
2527 : // To turn off a warning, type-cast to 'id'
2528 : InitExprs.push_back( // set 'super class', using objc_getClass().
2529 : NoTypeInfoCStyleCastExpr(Context,
2530 : Context->getObjCIdType(),
2531 0: CastExpr::CK_Unknown, Cls));
2532 : // struct objc_super
2533 0: QualType superType = getSuperStructType();
2534 : Expr *SuperRep;
2535 :
0: branch 0 not taken
0: branch 1 not taken
2536 0: if (LangOpts.Microsoft) {
2537 0: SynthSuperContructorFunctionDecl();
2538 : // Simulate a contructor call...
2539 : DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
0: branch 2 not taken
0: branch 3 not taken
2540 0: superType, SourceLocation());
2541 : SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
2542 : InitExprs.size(),
0: branch 4 not taken
0: branch 5 not taken
2543 0: superType, SourceLocation());
2544 : // The code for super is a little tricky to prevent collision with
2545 : // the structure definition in the header. The rewriter has it's own
2546 : // internal definition (__rw_objc_super) that is uses. This is why
2547 : // we need the cast below. For example:
2548 : // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
2549 : //
2550 : SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
2551 : Context->getPointerType(SuperRep->getType()),
0: branch 4 not taken
0: branch 5 not taken
2552 0: SourceLocation());
2553 : SuperRep = NoTypeInfoCStyleCastExpr(Context,
2554 : Context->getPointerType(superType),
2555 0: CastExpr::CK_Unknown, SuperRep);
2556 : } else {
2557 : // (struct objc_super) { <exprs from above> }
2558 : InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(),
2559 : &InitExprs[0], InitExprs.size(),
0: branch 5 not taken
0: branch 6 not taken
2560 0: SourceLocation());
2561 : TypeSourceInfo *superTInfo
2562 0: = Context->getTrivialTypeSourceInfo(superType);
2563 : SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
0: branch 2 not taken
0: branch 3 not taken
2564 0: superType, ILE, false);
2565 : // struct objc_super *
2566 : SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
2567 : Context->getPointerType(SuperRep->getType()),
0: branch 4 not taken
0: branch 5 not taken
2568 0: SourceLocation());
2569 : }
2570 0: MsgExprs.push_back(SuperRep);
2571 : } else {
2572 6: llvm::SmallVector<Expr*, 8> ClsExprs;
2573 6: QualType argType = Context->getPointerType(Context->CharTy);
2574 : ClsExprs.push_back(StringLiteral::Create(*Context,
2575 : clsName->getNameStart(),
2576 : clsName->getLength(),
2577 : false, argType,
2578 6: SourceLocation()));
2579 : CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
2580 : &ClsExprs[0],
2581 6: ClsExprs.size());
2582 6: MsgExprs.push_back(Cls);
2583 : }
2584 : } else { // instance message.
2585 43: Expr *recExpr = Exp->getReceiver();
2586 :
1: branch 1 taken
42: branch 2 taken
2587 43: if (ObjCInterfaceDecl *SuperDecl = isSuperReceiver(recExpr)) {
2588 1: MsgSendFlavor = MsgSendSuperFunctionDecl;
0: branch 0 not taken
1: branch 1 taken
2589 1: if (MsgSendStretFlavor)
2590 0: MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
0: branch 0 not taken
1: branch 1 taken
2591 1: assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
2592 :
2593 1: llvm::SmallVector<Expr*, 4> InitExprs;
2594 :
2595 : InitExprs.push_back(
2596 : NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2597 : CastExpr::CK_Unknown,
2598 : new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
2599 : Context->getObjCIdType(),
2600 : SourceLocation()))
1: branch 4 taken
0: branch 5 not taken
2601 1: ); // set the 'receiver'.
2602 :
2603 1: llvm::SmallVector<Expr*, 8> ClsExprs;
2604 1: QualType argType = Context->getPointerType(Context->CharTy);
2605 : ClsExprs.push_back(StringLiteral::Create(*Context,
2606 : SuperDecl->getIdentifier()->getNameStart(),
2607 : SuperDecl->getIdentifier()->getLength(),
2608 1: false, argType, SourceLocation()));
2609 : CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
2610 : &ClsExprs[0],
2611 1: ClsExprs.size());
2612 : // To turn off a warning, type-cast to 'id'
2613 : InitExprs.push_back(
2614 : // set 'super class', using objc_getClass().
2615 : NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2616 1: CastExpr::CK_Unknown, Cls));
2617 : // struct objc_super
2618 1: QualType superType = getSuperStructType();
2619 : Expr *SuperRep;
2620 :
0: branch 0 not taken
1: branch 1 taken
2621 1: if (LangOpts.Microsoft) {
2622 0: SynthSuperContructorFunctionDecl();
2623 : // Simulate a contructor call...
2624 : DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
0: branch 2 not taken
0: branch 3 not taken
2625 0: superType, SourceLocation());
2626 : SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
2627 : InitExprs.size(),
0: branch 4 not taken
0: branch 5 not taken
2628 0: superType, SourceLocation());
2629 : // The code for super is a little tricky to prevent collision with
2630 : // the structure definition in the header. The rewriter has it's own
2631 : // internal definition (__rw_objc_super) that is uses. This is why
2632 : // we need the cast below. For example:
2633 : // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
2634 : //
2635 : SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
2636 : Context->getPointerType(SuperRep->getType()),
0: branch 4 not taken
0: branch 5 not taken
2637 0: SourceLocation());
2638 : SuperRep = NoTypeInfoCStyleCastExpr(Context,
2639 : Context->getPointerType(superType),
2640 0: CastExpr::CK_Unknown, SuperRep);
2641 : } else {
2642 : // (struct objc_super) { <exprs from above> }
2643 : InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(),
2644 : &InitExprs[0], InitExprs.size(),
1: branch 5 taken
0: branch 6 not taken
2645 1: SourceLocation());
2646 : TypeSourceInfo *superTInfo
2647 1: = Context->getTrivialTypeSourceInfo(superType);
2648 : SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
1: branch 2 taken
0: branch 3 not taken
2649 1: superType, ILE, false);
2650 : }
2651 1: MsgExprs.push_back(SuperRep);
2652 : } else {
2653 : // Remove all type-casts because it may contain objc-style types; e.g.
2654 : // Foo<Proto> *.
5: branch 1 taken
42: branch 2 taken
2655 52: while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
2656 5: recExpr = CE->getSubExpr();
2657 : recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2658 42: CastExpr::CK_Unknown, recExpr);
2659 42: MsgExprs.push_back(recExpr);
2660 : }
2661 : }
2662 : // Create a call to sel_registerName("selName"), it will be the 2nd argument.
2663 49: llvm::SmallVector<Expr*, 8> SelExprs;
2664 49: QualType argType = Context->getPointerType(Context->CharTy);
2665 : SelExprs.push_back(StringLiteral::Create(*Context,
2666 : Exp->getSelector().getAsString().c_str(),
2667 : Exp->getSelector().getAsString().size(),
2668 49: false, argType, SourceLocation()));
2669 : CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
2670 49: &SelExprs[0], SelExprs.size());
2671 49: MsgExprs.push_back(SelExp);
2672 :
2673 : // Now push any user supplied arguments.
31: branch 1 taken
49: branch 2 taken
2674 80: for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
2675 31: Expr *userExpr = Exp->getArg(i);
2676 : // Make all implicit casts explicit...ICE comes in handy:-)
4: branch 1 taken
27: branch 2 taken
2677 31: if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
2678 : // Reuse the ICE type, it is exactly what the doctor ordered.
2679 : QualType type = ICE->getType()->isObjCQualifiedIdType()
2680 : ? Context->getObjCIdType()
0: branch 3 not taken
4: branch 4 taken
2681 4: : ICE->getType();
2682 : userExpr = NoTypeInfoCStyleCastExpr(Context, type, CastExpr::CK_Unknown,
2683 4: userExpr);
2684 : }
2685 : // Make id<P...> cast into an 'id' cast.
13: branch 1 taken
14: branch 2 taken
2686 27: else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
1: branch 3 taken
12: branch 4 taken
2687 13: if (CE->getType()->isObjCQualifiedIdType()) {
1: branch 1 taken
1: branch 2 taken
2688 3: while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
2689 1: userExpr = CE->getSubExpr();
2690 : userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
2691 1: CastExpr::CK_Unknown, userExpr);
2692 : }
2693 : }
2694 31: MsgExprs.push_back(userExpr);
2695 : // We've transferred the ownership to MsgExprs. For now, we *don't* null
2696 : // out the argument in the original expression (since we aren't deleting
2697 : // the ObjCMessageExpr). See RewritePropertySetter() usage for more info.
2698 : //Exp->setArg(i, 0);
2699 : }
2700 : // Generate the funky cast.
2701 : CastExpr *cast;
2702 49: llvm::SmallVector<QualType, 8> ArgTypes;
2703 49: QualType returnType;
2704 :
2705 : // Push 'id' and 'SEL', the 2 implicit arguments.
1: branch 0 taken
48: branch 1 taken
2706 49: if (MsgSendFlavor == MsgSendSuperFunctionDecl)
2707 1: ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
2708 : else
2709 48: ArgTypes.push_back(Context->getObjCIdType());
2710 49: ArgTypes.push_back(Context->getObjCSelType());
43: branch 1 taken
6: branch 2 taken
2711 49: if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
2712 : // Push any user argument types.
18: branch 1 taken
43: branch 2 taken
2713 104: for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
2714 43: E = OMD->param_end(); PI != E; ++PI) {
2715 : QualType t = (*PI)->getType()->isObjCQualifiedIdType()
2716 : ? Context->getObjCIdType()
1: branch 3 taken
17: branch 4 taken
2717 18: : (*PI)->getType();
2718 : // Make sure we convert "t (^)(...)" to "t (*)(...)".
0: branch 1 not taken
18: branch 2 taken
2719 18: if (isTopLevelBlockPointerType(t)) {
2720 0: const BlockPointerType *BPT = t->getAs<BlockPointerType>();
2721 0: t = Context->getPointerType(BPT->getPointeeType());
2722 : }
2723 18: ArgTypes.push_back(t);
2724 : }
2725 : returnType = OMD->getResultType()->isObjCQualifiedIdType()
1: branch 3 taken
42: branch 4 taken
2726 43: ? Context->getObjCIdType() : OMD->getResultType();
2727 : } else {
2728 6: returnType = Context->getObjCIdType();
2729 : }
2730 : // Get the type, we will need to reference it in a couple spots.
2731 49: QualType msgSendType = MsgSendFlavor->getType();
2732 :
2733 : // Create a reference to the objc_msgSend() declaration.
2734 : DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType,
49: branch 2 taken
0: branch 3 not taken
2735 49: SourceLocation());
2736 :
2737 : // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
2738 : // If we don't do this cast, we get the following bizarre warning/note:
2739 : // xx.m:13: warning: function called through a non-compatible type
2740 : // xx.m:13: note: if this code is reached, the program will abort
2741 : cast = NoTypeInfoCStyleCastExpr(Context,
2742 : Context->getPointerType(Context->VoidTy),
2743 49: CastExpr::CK_Unknown, DRE);
2744 :
2745 : // Now do the "normal" pointer to function cast.
2746 : QualType castType = Context->getFunctionType(returnType,
2747 : &ArgTypes[0], ArgTypes.size(),
2748 : // If we don't have a method decl, force a variadic cast.
43: branch 1 taken
6: branch 2 taken
2749 49: Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true, 0);
2750 49: castType = Context->getPointerType(castType);
2751 : cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
2752 49: cast);
2753 :
2754 : // Don't forget the parens to enforce the proper binding.
49: branch 3 taken
0: branch 4 not taken
2755 49: ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
2756 :
2757 49: const FunctionType *FT = msgSendType->getAs<FunctionType>();
2758 : CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
2759 : MsgExprs.size(),
49: branch 5 taken
0: branch 6 not taken
2760 49: FT->getResultType(), SourceLocation());
2761 49: Stmt *ReplacingStmt = CE;
1: branch 0 taken
48: branch 1 taken
2762 49: if (MsgSendStretFlavor) {
2763 : // We have the method which returns a struct/union. Must also generate
2764 : // call to objc_msgSend_stret and hang both varieties on a conditional
2765 : // expression which dictate which one to envoke depending on size of
2766 : // method's return type.
2767 :
2768 : // Create a reference to the objc_msgSend_stret() declaration.
2769 : DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType,
1: branch 2 taken
0: branch 3 not taken
2770 1: SourceLocation());
2771 : // Need to cast objc_msgSend_stret to "void *" (see above comment).
2772 : cast = NoTypeInfoCStyleCastExpr(Context,
2773 : Context->getPointerType(Context->VoidTy),
2774 1: CastExpr::CK_Unknown, STDRE);
2775 : // Now do the "normal" pointer to function cast.
2776 : castType = Context->getFunctionType(returnType,
2777 : &ArgTypes[0], ArgTypes.size(),
1: branch 1 taken
0: branch 2 not taken
2778 1: Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false, 0);
2779 1: castType = Context->getPointerType(castType);
2780 : cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
2781 1: cast);
2782 :
2783 : // Don't forget the parens to enforce the proper binding.
1: branch 3 taken
0: branch 4 not taken
2784 1: PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
2785 :
2786 1: FT = msgSendType->getAs<FunctionType>();
2787 : CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
2788 : MsgExprs.size(),
1: branch 5 taken
0: branch 6 not taken
2789 1: FT->getResultType(), SourceLocation());
2790 :
2791 : // Build sizeof(returnType)
2792 : SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
2793 : Context->getTrivialTypeSourceInfo(returnType),
2794 : Context->getSizeType(),
1: branch 7 taken
0: branch 8 not taken
2795 1: SourceLocation(), SourceLocation());
2796 : // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
2797 : // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
2798 : // For X86 it is more complicated and some kind of target specific routine
2799 : // is needed to decide what to do.
2800 : unsigned IntSize =
2801 1: static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
2802 : IntegerLiteral *limit = new (Context) IntegerLiteral(llvm::APInt(IntSize, 8),
2803 : Context->IntTy,
1: branch 4 taken
0: branch 5 not taken
2804 1: SourceLocation());
2805 : BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit,
2806 : BinaryOperator::LE,
2807 : Context->IntTy,
1: branch 3 taken
0: branch 4 not taken
2808 1: SourceLocation());
2809 : // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
2810 : ConditionalOperator *CondExpr =
2811 : new (Context) ConditionalOperator(lessThanExpr,
2812 : SourceLocation(), CE,
1: branch 3 taken
0: branch 4 not taken
2813 1: SourceLocation(), STCE, returnType);
1: branch 3 taken
0: branch 4 not taken
2814 1: ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), CondExpr);
2815 : }
2816 : // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
2817 49: return ReplacingStmt;
2818 : }
2819 :
2820 30: Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
2821 30: Stmt *ReplacingStmt = SynthMessageExpr(Exp);
2822 :
2823 : // Now do the actual rewrite.
2824 30: ReplaceStmt(Exp, ReplacingStmt);
2825 :
2826 : // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
2827 30: return ReplacingStmt;
2828 : }
2829 :
2830 : // typedef struct objc_object Protocol;
2831 2: QualType RewriteObjC::getProtocolType() {
1: branch 0 taken
1: branch 1 taken
2832 2: if (!ProtocolTypeDecl) {
2833 : TypeSourceInfo *TInfo
2834 1: = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
2835 : ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
2836 : SourceLocation(),
2837 : &Context->Idents.get("Protocol"),
1: branch 3 taken
0: branch 4 not taken
2838 1: TInfo);
2839 : }
2840 2: return Context->getTypeDeclType(ProtocolTypeDecl);
2841 : }
2842 :
2843 : /// RewriteObjCProtocolExpr - Rewrite a protocol expression into
2844 : /// a synthesized/forward data reference (to the protocol's metadata).
2845 : /// The forward references (and metadata) are generated in
2846 : /// RewriteObjC::HandleTranslationUnit().
2847 1: Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
2848 1: std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();
2849 1: IdentifierInfo *ID = &Context->Idents.get(Name);
2850 : VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
1: branch 2 taken
0: branch 3 not taken
2851 1: ID, getProtocolType(), 0, VarDecl::Extern);
1: branch 3 taken
0: branch 4 not taken
2852 1: DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation());
2853 : Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
2854 : Context->getPointerType(DRE->getType()),
1: branch 4 taken
0: branch 5 not taken
2855 1: SourceLocation());
2856 : CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
2857 : CastExpr::CK_Unknown,
2858 1: DerefExpr);
2859 1: ReplaceStmt(Exp, castExpr);
2860 1: ProtocolExprDecls.insert(Exp->getProtocol());
2861 : // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
2862 1: return castExpr;
2863 :
2864 : }
2865 :
2866 : bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
2867 21: const char *endBuf) {
499: branch 0 taken
21: branch 1 taken
2868 541: while (startBuf < endBuf) {
0: branch 0 not taken
499: branch 1 taken
2869 499: if (*startBuf == '#') {
2870 : // Skip whitespace.
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
2871 0: for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
2872 : ;
0: branch 1 not taken
0: branch 2 not taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 10 not taken
0: branch 11 not taken
0: branch 13 not taken
0: branch 14 not taken
0: branch 16 not taken
0: branch 17 not taken
0: branch 19 not taken
0: branch 20 not taken
0: branch 22 not taken
0: branch 23 not taken
0: branch 25 not taken
0: branch 26 not taken
0: branch 28 not taken
0: branch 29 not taken
0: branch 31 not taken
0: branch 32 not taken
0: branch 34 not taken
0: branch 35 not taken
2873 0: if (!strncmp(startBuf, "if", strlen("if")) ||
2874 : !strncmp(startBuf, "ifdef", strlen("ifdef")) ||
2875 : !strncmp(startBuf, "ifndef", strlen("ifndef")) ||
2876 : !strncmp(startBuf, "define", strlen("define")) ||
2877 : !strncmp(startBuf, "undef", strlen("undef")) ||
2878 : !strncmp(startBuf, "else", strlen("else")) ||
2879 : !strncmp(startBuf, "elif", strlen("elif")) ||
2880 : !strncmp(startBuf, "endif", strlen("endif")) ||
2881 : !strncmp(startBuf, "pragma", strlen("pragma")) ||
2882 : !strncmp(startBuf, "include", strlen("include")) ||
2883 : !strncmp(startBuf, "import", strlen("import")) ||
2884 : !strncmp(startBuf, "include_next", strlen("include_next")))
2885 0: return true;
2886 : }
2887 499: startBuf++;
2888 : }
2889 21: return false;
2890 : }
2891 :
2892 : /// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to
2893 : /// an objective-c class with ivars.
2894 : void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
2895 64: std::string &Result) {
0: branch 0 not taken
64: branch 1 taken
2896 64: assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
2897 : assert(CDecl->getNameAsCString() &&
64: branch 1 taken
0: branch 2 not taken
2898 64: "Name missing in SynthesizeObjCInternalStruct");
2899 : // Do not synthesize more than once.
64: branch 1 taken
0: branch 2 not taken
2900 64: if (ObjCSynthesizedStructs.count(CDecl))
2901 0: return;
2902 64: ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
2903 64: int NumIvars = CDecl->ivar_size();
2904 64: SourceLocation LocStart = CDecl->getLocStart();
2905 64: SourceLocation LocEnd = CDecl->getLocEnd();
2906 :
2907 64: const char *startBuf = SM->getCharacterData(LocStart);
2908 64: const char *endBuf = SM->getCharacterData(LocEnd);
2909 :
2910 : // If no ivars and no root or if its root, directly or indirectly,
2911 : // have no ivars (thus not synthesized) then no need to synthesize this class.
64: branch 1 taken
0: branch 2 not taken
43: branch 3 taken
21: branch 4 taken
3: branch 5 taken
40: branch 6 taken
3: branch 8 taken
0: branch 9 not taken
43: branch 10 taken
21: branch 11 taken
2912 64: if ((CDecl->isForwardDecl() || NumIvars == 0) &&
2913 : (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
2914 43: endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
2915 43: ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size());
2916 43: return;
2917 : }
2918 :
2919 : // FIXME: This has potential of causing problem. If
2920 : // SynthesizeObjCInternalStruct is ever called recursively.
2921 21: Result += "\nstruct ";
2922 21: Result += CDecl->getNameAsString();
10: branch 0 taken
11: branch 1 taken
2923 21: if (LangOpts.Microsoft)
2924 10: Result += "_IMPL";
2925 :
21: branch 0 taken
0: branch 1 not taken
2926 21: if (NumIvars > 0) {
2927 21: const char *cursor = strchr(startBuf, '{');
2928 : assert((cursor && endBuf)
21: branch 0 taken
0: branch 1 not taken
0: branch 2 not taken
21: branch 3 taken
2929 21: && "SynthesizeObjCInternalStruct - malformed @interface");
2930 : // If the buffer contains preprocessor directives, we do more fine-grained
2931 : // rewrites. This is intended to fix code that looks like (which occurs in
2932 : // NSURL.h, for example):
2933 : //
2934 : // #ifdef XYZ
2935 : // @interface Foo : NSObject
2936 : // #else
2937 : // @interface FooBar : NSObject
2938 : // #endif
2939 : // {
2940 : // int i;
2941 : // }
2942 : // @end
2943 : //
2944 : // This clause is segregated to avoid breaking the common case.
0: branch 1 not taken
21: branch 2 taken
2945 21: if (BufferContainsPPDirectives(startBuf, cursor)) {
2946 : SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :
0: branch 0 not taken
0: branch 1 not taken
2947 0: CDecl->getClassLoc();
2948 0: const char *endHeader = SM->getCharacterData(L);
2949 0: endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);
2950 :
0: branch 2 not taken
0: branch 3 not taken
2951 0: if (CDecl->protocol_begin() != CDecl->protocol_end()) {
2952 : // advance to the end of the referenced protocols.
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
2953 0: while (endHeader < cursor && *endHeader != '>') endHeader++;
2954 0: endHeader++;
2955 : }
2956 : // rewrite the original header
2957 0: ReplaceText(LocStart, endHeader-startBuf, Result.c_str(), Result.size());
2958 : } else {
2959 : // rewrite the original header *without* disturbing the '{'
2960 21: ReplaceText(LocStart, cursor-startBuf, Result.c_str(), Result.size());
2961 : }
4: branch 0 taken
17: branch 1 taken
1: branch 3 taken
3: branch 4 taken
1: branch 5 taken
20: branch 6 taken
2962 21: if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
2963 1: Result = "\n struct ";
2964 1: Result += RCDecl->getNameAsString();
2965 1: Result += "_IMPL ";
2966 1: Result += RCDecl->getNameAsString();
2967 1: Result += "_IVARS;\n";
2968 :
2969 : // insert the super class structure definition.
2970 : SourceLocation OnePastCurly =
2971 1: LocStart.getFileLocWithOffset(cursor-startBuf+1);
2972 1: InsertText(OnePastCurly, Result.c_str(), Result.size());
2973 : }
2974 21: cursor++; // past '{'
2975 :
2976 : // Now comment out any visibility specifiers.
677: branch 0 taken
21: branch 1 taken
2977 719: while (cursor < endBuf) {
10: branch 0 taken
667: branch 1 taken
2978 677: if (*cursor == '@') {
2979 10: SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
2980 : // Skip whitespace.
0: branch 0 not taken
10: branch 1 taken
0: branch 2 not taken
10: branch 3 taken
2981 10: for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
2982 : /*scan*/;
2983 :
2984 : // FIXME: presence of @public, etc. inside comment results in
2985 : // this transformation as well, which is still correct c-code.
3: branch 1 taken
7: branch 2 taken
0: branch 4 not taken
3: branch 5 taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 10 not taken
0: branch 11 not taken
2986 10: if (!strncmp(cursor, "public", strlen("public")) ||
2987 : !strncmp(cursor, "private", strlen("private")) ||
2988 : !strncmp(cursor, "package", strlen("package")) ||
2989 : !strncmp(cursor, "protected", strlen("protected")))
2990 10: InsertText(atLoc, "// ", 3);
2991 : }
2992 : // FIXME: If there are cases where '<' is used in ivar declaration part
2993 : // of user code, then scan the ivar list and use needToScanForQualifiers
2994 : // for type checking.
0: branch 0 not taken
667: branch 1 taken
2995 667: else if (*cursor == '<') {
2996 0: SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
2997 0: InsertText(atLoc, "/* ", 3);
2998 0: cursor = strchr(cursor, '>');
2999 0: cursor++;
3000 0: atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
3001 0: InsertText(atLoc, " */", 3);
1: branch 0 taken
666: branch 1 taken
3002 667: } else if (*cursor == '^') { // rewrite block specifier.
3003 1: SourceLocation caretLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
3004 1: ReplaceText(caretLoc, 1, "*", 1);
3005 : }
3006 677: cursor++;
3007 : }
3008 : // Don't forget to add a ';'!!
3009 21: InsertText(LocEnd.getFileLocWithOffset(1), ";", 1);
3010 : } else { // we don't have any instance variables - insert super struct.
3011 0: endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
3012 0: Result += " {\n struct ";
3013 0: Result += RCDecl->getNameAsString();
3014 0: Result += "_IMPL ";
3015 0: Result += RCDecl->getNameAsString();
3016 0: Result += "_IVARS;\n};\n";
3017 0: ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size());
3018 : }
3019 : // Mark this struct as having been generated.
0: branch 1 not taken
21: branch 2 taken
3020 21: if (!ObjCSynthesizedStructs.insert(CDecl))
3021 0: assert(false && "struct already synthesize- SynthesizeObjCInternalStruct");
3022 : }
3023 :
3024 : // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
3025 : /// class methods.
3026 : template<typename MethodIterator>
3027 : void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
3028 : MethodIterator MethodEnd,
3029 : bool Is