blob: f5f6cfe6497184096e715bffc16eee8c4f2b2c15 [file] [log] [blame]
Chris Lattner77cd2a02007-10-11 00:43:27 +00001//===--- RewriteTest.cpp - Playground for the code rewriter ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under the
6// University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Hacks and fun related to the code rewriter.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ASTConsumers.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000015#include "clang/Rewrite/Rewriter.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000016#include "clang/AST/AST.h"
17#include "clang/AST/ASTConsumer.h"
Chris Lattner8a12c272007-10-11 18:38:32 +000018#include "clang/Basic/SourceManager.h"
Chris Lattner77cd2a02007-10-11 00:43:27 +000019using namespace clang;
20
21
22namespace {
Chris Lattner8a12c272007-10-11 18:38:32 +000023 class RewriteTest : public ASTConsumer {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000024 Rewriter Rewrite;
Chris Lattner01c57482007-10-17 22:35:30 +000025 ASTContext *Context;
Chris Lattner77cd2a02007-10-11 00:43:27 +000026 SourceManager *SM;
Chris Lattner8a12c272007-10-11 18:38:32 +000027 unsigned MainFileID;
Chris Lattner2c64b7b2007-10-16 21:07:07 +000028 SourceLocation LastIncLoc;
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000029 llvm::SmallVector<ObjcImplementationDecl *, 8> ClassImplementation;
30 llvm::SmallVector<ObjcCategoryImplDecl *, 8> CategoryImplementation;
31 static const int OBJC_ABI_VERSION =7 ;
Chris Lattner77cd2a02007-10-11 00:43:27 +000032 public:
Chris Lattner01c57482007-10-17 22:35:30 +000033 void Initialize(ASTContext &context, unsigned mainFileID) {
34 Context = &context;
35 SM = &Context->SourceMgr;
Chris Lattner8a12c272007-10-11 18:38:32 +000036 MainFileID = mainFileID;
Chris Lattner01c57482007-10-17 22:35:30 +000037 Rewrite.setSourceMgr(Context->SourceMgr);
Chris Lattner77cd2a02007-10-11 00:43:27 +000038 }
39
40 virtual void HandleTopLevelDecl(Decl *D);
Chris Lattner8a12c272007-10-11 18:38:32 +000041
Chris Lattner2c64b7b2007-10-16 21:07:07 +000042 void HandleDeclInMainFile(Decl *D);
43 void RewriteInclude(SourceLocation Loc);
Chris Lattner311ff022007-10-16 22:36:42 +000044
45 void RewriteFunctionBody(Stmt *S);
46 void RewriteAtEncode(ObjCEncodeExpr *Exp);
Chris Lattner2c64b7b2007-10-16 21:07:07 +000047
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +000048 void WriteObjcClassMetaData(ObjcImplementationDecl *IDecl);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +000049 void WriteObjcMetaData();
50
Chris Lattner8a12c272007-10-11 18:38:32 +000051 ~RewriteTest();
Chris Lattner77cd2a02007-10-11 00:43:27 +000052 };
53}
54
Chris Lattner8a12c272007-10-11 18:38:32 +000055ASTConsumer *clang::CreateCodeRewriterTest() { return new RewriteTest(); }
Chris Lattner77cd2a02007-10-11 00:43:27 +000056
Chris Lattner8a12c272007-10-11 18:38:32 +000057void RewriteTest::HandleTopLevelDecl(Decl *D) {
Chris Lattner2c64b7b2007-10-16 21:07:07 +000058 // Two cases: either the decl could be in the main file, or it could be in a
59 // #included file. If the former, rewrite it now. If the later, check to see
60 // if we rewrote the #include/#import.
61 SourceLocation Loc = D->getLocation();
62 Loc = SM->getLogicalLoc(Loc);
63
64 // If this is for a builtin, ignore it.
65 if (Loc.isInvalid()) return;
66
67 if (SM->getDecomposedFileLoc(Loc).first == MainFileID)
68 return HandleDeclInMainFile(D);
69
70 RewriteInclude(Loc);
71}
72
73void RewriteTest::RewriteInclude(SourceLocation Loc) {
74 // Rip up the #include stack to the main file.
75 SourceLocation IncLoc = Loc, NextLoc = Loc;
76 do {
77 IncLoc = Loc;
78 Loc = SM->getLogicalLoc(NextLoc);
79 NextLoc = SM->getIncludeLoc(Loc);
80 } while (!NextLoc.isInvalid());
81
82 // Loc is now the location of the #include filename "foo" or <foo/bar.h>.
83 // IncLoc indicates the header that was included if it is useful.
84 IncLoc = SM->getLogicalLoc(IncLoc);
85 if (SM->getDecomposedFileLoc(Loc).first != MainFileID ||
86 Loc == LastIncLoc)
87 return;
88 LastIncLoc = Loc;
89
90 unsigned IncCol = SM->getColumnNumber(Loc);
91 SourceLocation LineStartLoc = Loc.getFileLocWithOffset(-IncCol+1);
92
93 // Replace the #import with #include.
94 Rewrite.ReplaceText(LineStartLoc, IncCol-1, "#include ", strlen("#include "));
95}
96
97/// HandleDeclInMainFile - This is called for each top-level decl defined in the
98/// main file of the input.
99void RewriteTest::HandleDeclInMainFile(Decl *D) {
Chris Lattner311ff022007-10-16 22:36:42 +0000100 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
101 if (Stmt *Body = FD->getBody())
102 RewriteFunctionBody(Body);
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000103
104 if (ObjcImplementationDecl *CI = dyn_cast<ObjcImplementationDecl>(D))
105 ClassImplementation.push_back(CI);
106 else if (ObjcCategoryImplDecl *CI = dyn_cast<ObjcCategoryImplDecl>(D))
107 CategoryImplementation.push_back(CI);
Chris Lattner2c64b7b2007-10-16 21:07:07 +0000108 // Nothing yet.
Chris Lattner8a12c272007-10-11 18:38:32 +0000109}
110
111
Chris Lattner311ff022007-10-16 22:36:42 +0000112void RewriteTest::RewriteFunctionBody(Stmt *S) {
113 // Handle specific things.
114 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))
115 return RewriteAtEncode(AtEncode);
116
117 // Otherwise, just rewrite all children.
118 for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
119 CI != E; ++CI)
Chris Lattner50754772007-10-17 21:28:00 +0000120 if (*CI)
121 RewriteFunctionBody(*CI);
Chris Lattner311ff022007-10-16 22:36:42 +0000122}
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000123
Chris Lattner311ff022007-10-16 22:36:42 +0000124void RewriteTest::RewriteAtEncode(ObjCEncodeExpr *Exp) {
Chris Lattner01c57482007-10-17 22:35:30 +0000125 // Create a new string expression.
126 QualType StrType = Context->getPointerType(Context->CharTy);
127 Expr *Replacement = new StringLiteral("foo", 3, false, StrType,
128 SourceLocation(), SourceLocation());
129 Rewrite.ReplaceStmt(Exp, Replacement);
130 delete Replacement;
Chris Lattner311ff022007-10-16 22:36:42 +0000131}
132
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000133void RewriteTest::WriteObjcClassMetaData(ObjcImplementationDecl *IDecl) {
134 ObjcInterfaceDecl *CDecl = IDecl->getClassInterface();
135
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000136 // Build _objc_ivar_list metadata for classes ivars if needed
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000137 if (IDecl->getImplDeclNumIvars() > 0 ||
138 CDecl&& CDecl->getIntfDeclNumIvars() > 0) {
139 static bool objc_ivar = false;
140
141 int NumIvars = IDecl->getImplDeclNumIvars() > 0
142 ? IDecl->getImplDeclNumIvars()
143 : CDecl->getIntfDeclNumIvars();
144
145 if (!objc_ivar) {
146 /* struct _objc_ivar {
147 char *ivar_name;
148 char *ivar_type;
149 int ivar_offset;
150 };
151 */
152 printf("\nstruct _objc_ivar {\n");
153 printf("\tchar *ivar_name;\n");
154 printf("\tchar *ivar_type;\n");
155 printf("\tint ivar_offset;\n");
156 printf("};\n");
157 objc_ivar = true;
158 }
159
160 /* struct _objc_ivar_list {
161 int ivar_count;
162 struct _objc_ivar ivar_list[ivar_count];
163 };
164 */
165 printf("\nstatic struct {\n");
166 printf("\tint ivar_count;\n");
167 printf("\tstruct _objc_ivar ivar_list[%d];\n", NumIvars);
168 printf("} _OBJC_INSTANCE_VARIABLES_%s "
169 "__attribute__ ((section (\"__OBJC, __instance_vars\")))= "
170 "{\n\t%d\n",IDecl->getName(),
171 NumIvars);
172 ObjcIvarDecl **Ivars = IDecl->getImplDeclIVars()
173 ? IDecl->getImplDeclIVars()
174 : CDecl->getIntfDeclIvars();
175 for (int i = 0; i < NumIvars; i++)
176 // TODO: 1) ivar names may have to go to another section. 2) encode
177 // ivar_type type of each ivar . 3) compute and add ivar offset.
178 printf("\t,\"%s\", \"\", 0\n", Ivars[i]->getName());
179 printf("};\n");
180 }
181
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000182 // Build _objc_method for class's instance or class methods metadata if needed
183 static bool objc_impl_method = false;
184 if (IDecl->getNumInstanceMethods() > 0 || IDecl->getNumClassMethods() > 0) {
185 if (!objc_impl_method) {
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000186 /* struct _objc_method {
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000187 SEL _cmd;
188 char *method_types;
189 void *_imp;
190 }
191 */
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000192 printf("\nstruct _objc_method {\n");
193 printf("\tSEL _cmd;\n");
194 printf("\tchar *method_types;\n");
195 printf("\tvoid *_imp;\n");
196 printf("};\n");
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000197 objc_impl_method = true;
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000198 }
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000199 }
200 // Build _objc_method_list for class's instance methods if needed
201 if (IDecl->getNumInstanceMethods() > 0) {
202 int NumMethods = IDecl->getNumInstanceMethods();
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000203 /* struct _objc_method_list {
204 struct objc_method_list *next_method;
205 int method_count;
206 struct _objc_method method_list[method_count];
207 }
208 */
209 printf("\nstatic struct {\n");
210 printf("\tstruct objc_method_list *next_method;\n");
211 printf("\tint method_count;\n");
212 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
213 printf("} _OBJC_INSTANCE_METHODS_%s "
214 "__attribute__ ((section (\"__OBJC, __inst_meth\")))= "
215 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
216 ObjcMethodDecl **Methods = IDecl->getInstanceMethods();
217 for (int i = 0; i < NumMethods; i++)
218 // TODO: 1) method selector name may hav to go into their own section
219 // 2) encode method types for use here (which may have to go into
220 // __meth_var_types section, 3) Need method address as 3rd initializer.
221 printf("\t,(SEL)\"%s\", \"\", 0\n",
222 Methods[i]->getSelector().getName().c_str());
223 printf("};\n");
224 }
225
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000226 // Build _objc_method_list for class's class methods if needed
227 if (IDecl->getNumClassMethods() > 0) {
228 int NumMethods = IDecl->getNumClassMethods();
229 /* struct _objc_method_list {
230 struct objc_method_list *next_method;
231 int method_count;
232 struct _objc_method method_list[method_count];
233 }
234 */
235 printf("\nstatic struct {\n");
236 printf("\tstruct objc_method_list *next_method;\n");
237 printf("\tint method_count;\n");
238 printf("\tstruct _objc_method method_list[%d];\n", NumMethods);
239 printf("} _OBJC_CLASS_METHODS_%s "
240 "__attribute__ ((section (\"__OBJC, __cls_meth\")))= "
241 "{\n\t0, %d\n", IDecl->getName(), NumMethods);
242 ObjcMethodDecl **Methods = IDecl->getClassMethods();
243 for (int i = 0; i < NumMethods; i++)
244 // TODO: 1) method selector name may hav to go into their own section
245 // 2) encode method types for use here (which may have to go into
246 // __meth_var_types section, 3) Need method address as 3rd initializer.
247 printf("\t,(SEL)\"%s\", \"\", 0\n",
248 Methods[i]->getSelector().getName().c_str());
249 printf("};\n");
250 }
Fariborz Jahanian776d6ff2007-10-19 00:36:46 +0000251
Fariborz Jahaniane887c092007-10-22 21:41:37 +0000252 // Protocols referenced in class declaration?
253 static bool objc_protocol_methods = false;
254 int NumProtocols = CDecl->getNumIntfRefProtocols();
255 if (NumProtocols > 0) {
256 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
257 for (int i = 0; i < NumProtocols; i++) {
258 ObjcProtocolDecl *PDecl = Protocols[i];
259 // Output struct protocol_methods holder of method selector and type.
260 if (!objc_protocol_methods &&
261 (PDecl->getNumInstanceMethods() > 0
262 || PDecl->getNumClassMethods() > 0)) {
263 /* struct protocol_methods {
264 SEL _cmd;
265 char *method_types;
266 }
267 */
268 printf("\nstruct protocol_methods {\n");
269 printf("\tSEL _cmd;\n");
270 printf("\tchar *method_types;\n");
271 printf("};\n");
272 objc_protocol_methods = true;
273 }
274 // Output instance methods declared in this protocol.
275 /* struct _objc_protocol_method_list {
276 int protocol_method_count;
277 struct protocol_methods protocols[protocol_method_count];
278 }
279 */
280 int NumMethods = PDecl->getNumInstanceMethods();
281 if (NumMethods > 0) {
282 printf("\nstatic struct {\n");
283 printf("\tint protocol_method_count;\n");
284 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
285 printf("} _OBJC_PROTOCOL_INSTANCE_METHODS_%s "
286 "__attribute__ ((section (\"__OBJC, __cat_inst_meth\")))= "
287 "{\n\t%d\n",PDecl->getName(), NumMethods);
288 ObjcMethodDecl **Methods = PDecl->getInstanceMethods();
289 for (int i = 0; i < NumMethods; i++)
290 // TODO: 1) method selector name may hav to go into their own section
291 // 2) encode method types for use here (which may have to go into
292 // __meth_var_types section.
293 printf("\t,(SEL)\"%s\", \"\"\n",
294 Methods[i]->getSelector().getName().c_str());
295 printf("};\n");
296 }
297
298 // Output class methods declared in this protocol.
299 NumMethods = PDecl->getNumClassMethods();
300 if (NumMethods > 0) {
301 printf("\nstatic struct {\n");
302 printf("\tint protocol_method_count;\n");
303 printf("\tstruct protocol_methods protocols[%d];\n", NumMethods);
304 printf("} _OBJC_PROTOCOL_CLASS_METHODS_%s "
305 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
306 "{\n\t%d\n",PDecl->getName(), NumMethods);
307 ObjcMethodDecl **Methods = PDecl->getClassMethods();
308 for (int i = 0; i < NumMethods; i++)
309 // TODO: 1) method selector name may hav to go into their own section
310 // 2) encode method types for use here (which may have to go into
311 // __meth_var_types section.
312 printf("\t,(SEL)\"%s\", \"\"\n",
313 Methods[i]->getSelector().getName().c_str());
314 printf("};\n");
315 }
316 // Output:
317 /* struct _objc_protocol {
318 // Objective-C 1.0 extensions
319 struct _objc_protocol_extension *isa;
320 char *protocol_name;
321 struct _objc_protocol **protocol_list;
322 struct _objc__method_prototype_list *instance_methods;
323 struct _objc__method_prototype_list *class_methods;
324 };
325 */
326 static bool objc_protocol = false;
327 if (!objc_protocol) {
328 printf("\nstruct _objc_protocol {\n");
329 printf("\tstruct _objc_protocol_extension *isa;\n");
330 printf("\tchar *protocol_name;\n");
331 printf("\tstruct _objc_protocol **protocol_list;\n");
332 printf("\tstruct _objc__method_prototype_list *instance_methods;\n");
333 printf("\tstruct _objc__method_prototype_list *class_methods;\n");
334 printf("};\n");
335 objc_protocol = true;
336 }
337
338 printf("\nstatic struct _objc_protocol _OBJC_PROTOCOL_%s "
339 "__attribute__ ((section (\"__OBJC, __protocol\")))= "
340 "{\n\t0, \"%s\", 0, ", PDecl->getName(), PDecl->getName());
341 if (PDecl->getInstanceMethods() > 0)
342 printf("(struct _objc__method_prototype_list *)"
343 "&_OBJC_PROTOCOL_INSTANCE_METHODS_%s, ", PDecl->getName());
344 else
345 printf("0, ");
346 if (PDecl->getClassMethods() > 0)
347 printf("(struct _objc__method_prototype_list *)"
348 "&_OBJC_PROTOCOL_CLASS_METHODS_%s\n", PDecl->getName());
349 else
350 printf("0\n");
351 printf("};\n");
352 }
353 }
354 if (NumProtocols > 0) {
355 // Output the top lovel protocol meta-data for the class.
356 /* struct _objc_protocol_list {
357 struct _objc_protocol_list *next;
358 int protocol_count;
359 struct _objc_protocol *class_protocols[protocol_count];
360 }
361 */
362 printf("\nstatic struct {\n");
363 printf("\tstruct _objc_protocol_list *next;\n");
364 printf("\tint protocol_count;\n");
365 printf("\tstruct _objc_protocol *class_protocols[%d];\n"
366 "} _OBJC_CLASS_PROTOCOLS_%s "
367 "__attribute__ ((section (\"__OBJC, __cat_cls_meth\")))= "
368 "{\n\t0, %d\n",NumProtocols, CDecl->getName(), NumProtocols);
369 ObjcProtocolDecl **Protocols = CDecl->getReferencedProtocols();
370 for (int i = 0; i < NumProtocols; i++) {
371 ObjcProtocolDecl *PDecl = Protocols[i];
372 printf("\t,&_OBJC_PROTOCOL_%s \n",
373 PDecl->getName());
374 }
375 printf("};\n");
376 }
377 }
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000378
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000379void RewriteTest::WriteObjcMetaData() {
380 int ClsDefCount = ClassImplementation.size();
381 int CatDefCount = CategoryImplementation.size();
382 if (ClsDefCount == 0 && CatDefCount == 0)
383 return;
Fariborz Jahanianf4d331d2007-10-18 22:09:03 +0000384
385 // For each defined class, write out all its meta data.
386 for (int i = 0; i < ClsDefCount; i++)
387 WriteObjcClassMetaData(ClassImplementation[i]);
388
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000389 // Write objc_symtab metadata
390 /*
391 struct _objc_symtab
392 {
393 long sel_ref_cnt;
394 SEL *refs;
395 short cls_def_cnt;
396 short cat_def_cnt;
397 void *defs[cls_def_cnt + cat_def_cnt];
398 };
399 */
400
401 printf("\nstruct _objc_symtab {\n");
402 printf("\tlong sel_ref_cnt;\n");
403 printf("\tSEL *refs;\n");
404 printf("\tshort cls_def_cnt;\n");
405 printf("\tshort cat_def_cnt;\n");
406 printf("\tvoid *defs[%d];\n", ClsDefCount + CatDefCount);
407 printf("};\n\n");
408
409 printf("static struct _objc_symtab "
410 "_OBJC_SYMBOLS __attribute__ ((section (\"__OBJC, __symbols\")))= {\n");
411 printf("\t0, 0, %d, %d\n", ClsDefCount, CatDefCount);
412 for (int i = 0; i < ClsDefCount; i++)
413 printf("\t,_OBJC_CLASS_%s\n", ClassImplementation[i]->getName());
414
415 for (int i = 0; i < CatDefCount; i++)
416 printf("\t,_OBJC_CATEGORY_%s_%s\n",
417 CategoryImplementation[i]->getClassInterface()->getName(),
418 CategoryImplementation[i]->getName());
419
420 printf("};\n\n");
421
422 // Write objc_module metadata
423
424 /*
425 struct _objc_module {
426 long version;
427 long size;
428 const char *name;
429 struct _objc_symtab *symtab;
430 }
431 */
432
433 printf("\nstruct _objc_module {\n");
434 printf("\tlong version;\n");
435 printf("\tlong size;\n");
436 printf("\tconst char *name;\n");
437 printf("\tstruct _objc_symtab *symtab;");
438 printf("};\n\n");
439 printf("static struct _objc_module "
440 "_OBJC_MODULES __attribute__ ((section (\"__OBJC, __module_info\")))= {\n");
441 printf("\t%d, %d, \"\", &_OBJC_SYMBOLS\n", OBJC_ABI_VERSION, 16);
442 printf("};\n\n");
443}
Chris Lattner311ff022007-10-16 22:36:42 +0000444
Chris Lattner8a12c272007-10-11 18:38:32 +0000445RewriteTest::~RewriteTest() {
Chris Lattner8a12c272007-10-11 18:38:32 +0000446 // Get the top-level buffer that this corresponds to.
447 std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
448 const char *MainBufStart = MainBuf.first;
449 const char *MainBufEnd = MainBuf.second;
450
451 // Loop over the whole file, looking for tabs.
452 for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
453 if (*BufPtr != '\t')
454 continue;
455
456 // Okay, we found a tab. This tab will turn into at least one character,
457 // but it depends on which 'virtual column' it is in. Compute that now.
458 unsigned VCol = 0;
459 while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
460 BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
461 ++VCol;
462
463 // Okay, now that we know the virtual column, we know how many spaces to
464 // insert. We assume 8-character tab-stops.
465 unsigned Spaces = 8-(VCol & 7);
466
467 // Get the location of the tab.
468 SourceLocation TabLoc =
469 SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
470
471 // Rewrite the single tab character into a sequence of spaces.
Chris Lattner57c337d2007-10-13 00:46:29 +0000472 Rewrite.ReplaceText(TabLoc, 1, " ", Spaces);
Chris Lattner8a12c272007-10-11 18:38:32 +0000473 }
474
475 // Get the buffer corresponding to MainFileID. If we haven't changed it, then
476 // we are done.
477 if (const RewriteBuffer *RewriteBuf =
478 Rewrite.getRewriteBufferFor(MainFileID)) {
Chris Lattner7c239602007-10-13 00:11:23 +0000479 printf("Changed:\n");
480 std::string S(RewriteBuf->begin(), RewriteBuf->end());
481 printf("%s\n", S.c_str());
Chris Lattner8a12c272007-10-11 18:38:32 +0000482 } else {
483 printf("No changes\n");
484 }
Fariborz Jahanian545b9ae2007-10-18 19:23:00 +0000485 // Rewrite Objective-c meta data*
486 WriteObjcMetaData();
Chris Lattner77cd2a02007-10-11 00:43:27 +0000487}