blob: 0354f2b655fae74750b334fbef3bd3c05aeb91ac [file] [log] [blame]
Ted Kremenekbfa82c42007-10-16 23:37:27 +00001//===--- SerializationTest.cpp - Experimental Object Serialization --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Ted Kremenek and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements prototype code for serialization of objects in clang.
11// It is not intended yet for public use, but simply is a placeholder to
12// experiment with new serialization features. Serialization will eventually
13// be integrated as a proper component of the clang libraries.
14//
15//===----------------------------------------------------------------------===//
16
17#include "ASTConsumers.h"
Ted Kremenekc4ca2882007-12-03 22:48:14 +000018#include "clang/Basic/TargetInfo.h"
Ted Kremenekdca24662007-12-05 00:26:13 +000019#include "clang/Basic/SourceManager.h"
Ted Kremenekbfa82c42007-10-16 23:37:27 +000020#include "clang/AST/AST.h"
21#include "clang/AST/ASTConsumer.h"
22#include "clang/AST/ASTContext.h"
Ted Kremenek5656b782007-11-29 01:24:25 +000023#include "clang/AST/CFG.h"
Ted Kremenekc4ca2882007-12-03 22:48:14 +000024#include "clang.h"
Ted Kremenekbfa82c42007-10-16 23:37:27 +000025#include "llvm/System/Path.h"
Ted Kremenekc637e6b2007-10-23 22:18:37 +000026#include "llvm/Support/Streams.h"
27#include "llvm/Support/MemoryBuffer.h"
Ted Kremeneka2bfb912007-10-24 19:06:02 +000028#include "llvm/Bitcode/Serialize.h"
29#include "llvm/Bitcode/Deserialize.h"
Ted Kremenekea75c552007-11-28 21:32:21 +000030#include <fstream>
Ted Kremenekc637e6b2007-10-23 22:18:37 +000031#include <stdio.h>
Ted Kremenek018b3952007-11-06 19:50:53 +000032#include <list>
Ted Kremenekc637e6b2007-10-23 22:18:37 +000033
Ted Kremenekbfa82c42007-10-16 23:37:27 +000034using namespace clang;
Ted Kremenekbfa82c42007-10-16 23:37:27 +000035
Ted Kremenek79a2a262007-11-28 19:21:47 +000036//===----------------------------------------------------------------------===//
37// Utility classes
38//===----------------------------------------------------------------------===//
39
Ted Kremenekbfa82c42007-10-16 23:37:27 +000040namespace {
Ted Kremenekbfa82c42007-10-16 23:37:27 +000041
Ted Kremenek79a2a262007-11-28 19:21:47 +000042template<typename T> class Janitor {
Ted Kremenek4ac81212007-11-05 21:39:35 +000043 T* Obj;
Ted Kremenek79a2a262007-11-28 19:21:47 +000044public:
45 explicit Janitor(T* obj) : Obj(obj) {}
Ted Kremenek4ac81212007-11-05 21:39:35 +000046 ~Janitor() { delete Obj; }
Ted Kremenek79a2a262007-11-28 19:21:47 +000047 operator T*() const { return Obj; }
48 T* operator->() { return Obj; }
Ted Kremenek4ac81212007-11-05 21:39:35 +000049};
Ted Kremenek79a2a262007-11-28 19:21:47 +000050
51//===----------------------------------------------------------------------===//
52// Driver code.
53//===----------------------------------------------------------------------===//
54
Ted Kremenek4ac81212007-11-05 21:39:35 +000055class SerializationTest : public ASTConsumer {
56 ASTContext* Context;
Ted Kremenekc4ca2882007-12-03 22:48:14 +000057 Diagnostic &Diags;
Ted Kremenekdca24662007-12-05 00:26:13 +000058 FileManager &FMgr;
Ted Kremenek018b3952007-11-06 19:50:53 +000059 std::list<Decl*> Decls;
Ted Kremenek4ac81212007-11-05 21:39:35 +000060
Ted Kremenekbdbb2852007-11-30 22:46:56 +000061 enum { BasicMetadataBlock = 1,
62 ASTContextBlock = 2,
63 DeclsBlock = 3 };
Ted Kremenek018b3952007-11-06 19:50:53 +000064
65public:
Ted Kremenekdca24662007-12-05 00:26:13 +000066 SerializationTest(Diagnostic &d, FileManager& fmgr)
67 : Context(NULL), Diags(d), FMgr(fmgr) {};
68
Ted Kremenek4ac81212007-11-05 21:39:35 +000069 ~SerializationTest();
70
Ted Kremenek018b3952007-11-06 19:50:53 +000071 virtual void Initialize(ASTContext& context, unsigned) {
72 Context = &context;
73 }
74
75 virtual void HandleTopLevelDecl(Decl *D) {
76 Decls.push_back(D);
77 }
78
79private:
Ted Kremenek79a2a262007-11-28 19:21:47 +000080 void Serialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
81 void Deserialize(llvm::sys::Path& Filename, llvm::sys::Path& FNameDeclPrint);
Ted Kremenek4ac81212007-11-05 21:39:35 +000082};
83
Ted Kremenekc637e6b2007-10-23 22:18:37 +000084} // end anonymous namespace
Ted Kremenekbfa82c42007-10-16 23:37:27 +000085
Ted Kremenekdca24662007-12-05 00:26:13 +000086ASTConsumer*
87clang::CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr) {
88 return new SerializationTest(Diags,FMgr);
Ted Kremenek018b3952007-11-06 19:50:53 +000089}
90
91static void WritePreamble(llvm::BitstreamWriter& Stream) {
92 Stream.Emit((unsigned)'B', 8);
93 Stream.Emit((unsigned)'C', 8);
94 Stream.Emit(0xC, 4);
95 Stream.Emit(0xF, 4);
96 Stream.Emit(0xE, 4);
97 Stream.Emit(0x0, 4);
98}
99
Ted Kremenek07c0fd92007-11-06 23:52:19 +0000100static bool ReadPreamble(llvm::BitstreamReader& Stream) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000101 return Stream.Read(8) != 'B' ||
102 Stream.Read(8) != 'C' ||
103 Stream.Read(4) != 0xC ||
104 Stream.Read(4) != 0xF ||
105 Stream.Read(4) != 0xE ||
106 Stream.Read(4) != 0x0;
107}
108
Ted Kremenek79a2a262007-11-28 19:21:47 +0000109void SerializationTest::Serialize(llvm::sys::Path& Filename,
110 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000111
Ted Kremenek018b3952007-11-06 19:50:53 +0000112 // Reserve 256K for bitstream buffer.
113 std::vector<unsigned char> Buffer;
114 Buffer.reserve(256*1024);
115
116 // Create bitstream and write preamble.
117 llvm::BitstreamWriter Stream(Buffer);
118 WritePreamble(Stream);
119
120 // Create serializer.
121 llvm::Serializer Sezr(Stream);
122
123 // ===---------------------------------------------------===/
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000124 // Serialize the top-level decls.
125 // ===---------------------------------------------------===/
126
Ted Kremenekb899ad22007-11-14 17:46:35 +0000127 Sezr.EnterBlock(DeclsBlock);
Ted Kremeneke7201982007-11-13 22:56:10 +0000128
Ted Kremenek79a2a262007-11-28 19:21:47 +0000129 { // Create a printer to "consume" our deserialized ASTS.
130
131 Janitor<ASTConsumer> Printer(CreateASTPrinter());
Ted Kremenekea75c552007-11-28 21:32:21 +0000132 std::ofstream DeclPP(FNameDeclPrint.c_str());
133 assert (DeclPP && "Could not open file for printing out decls.");
134 Janitor<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremeneke7201982007-11-13 22:56:10 +0000135
Ted Kremenek79a2a262007-11-28 19:21:47 +0000136 for (std::list<Decl*>::iterator I=Decls.begin(), E=Decls.end(); I!=E; ++I) {
137 llvm::cerr << "Serializing: Decl.\n";
138
Ted Kremenek6127b122007-11-29 19:04:54 +0000139 // Only serialize the head of a decl chain. The ASTConsumer interfaces
140 // provides us with each top-level decl, including those nested in
141 // a decl chain, so we may be passed decls that are already serialized.
142 if (!Sezr.isRegistered(*I)) {
143 Printer->HandleTopLevelDecl(*I);
144 FilePrinter->HandleTopLevelDecl(*I);
145
146 if (FunctionDecl* FD = dyn_cast<FunctionDecl>(*I))
147 if (FD->getBody()) {
148 // Construct and print a CFG.
149 Janitor<CFG> cfg(CFG::buildCFG(FD->getBody()));
150 cfg->print(DeclPP);
151 }
152
153 // Serialize the decl.
154 Sezr.EmitOwnedPtr(*I);
155 }
Ted Kremenek79a2a262007-11-28 19:21:47 +0000156 }
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000157 }
158
159 Sezr.ExitBlock();
160
161 // ===---------------------------------------------------===/
Ted Kremenek018b3952007-11-06 19:50:53 +0000162 // Serialize the "Translation Unit" metadata.
163 // ===---------------------------------------------------===/
164
Ted Kremenekb899ad22007-11-14 17:46:35 +0000165 // Emit ASTContext.
166 Sezr.EnterBlock(ASTContextBlock);
167 llvm::cerr << "Serializing: ASTContext.\n";
168 Sezr.EmitOwnedPtr(Context);
169 Sezr.ExitBlock();
170
171
172 Sezr.EnterBlock(BasicMetadataBlock);
Ted Kremenek018b3952007-11-06 19:50:53 +0000173
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000174 // Block for SourceManager and Target. Allows easy skipping around
175 // to the Selectors during deserialization.
176 Sezr.EnterBlock();
177
Ted Kremenek018b3952007-11-06 19:50:53 +0000178 // "Fake" emit the SourceManager.
Ted Kremenekdca24662007-12-05 00:26:13 +0000179 llvm::cerr << "Serializing: SourceManager.\n";
180 Sezr.Emit(Context->SourceMgr);
Ted Kremenek018b3952007-11-06 19:50:53 +0000181
Ted Kremenekc4ca2882007-12-03 22:48:14 +0000182 // Emit the Target.
183 llvm::cerr << "Serializing: Target.\n";
Ted Kremenek018b3952007-11-06 19:50:53 +0000184 Sezr.EmitPtr(&Context->Target);
Ted Kremenekc4ca2882007-12-03 22:48:14 +0000185 Sezr.EmitCStr(Context->Target.getTargetTriple());
Ted Kremenek018b3952007-11-06 19:50:53 +0000186
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000187 Sezr.ExitBlock();
188
189 // Emit the Selectors.
190 llvm::cerr << "Serializing: Selectors.\n";
191 Sezr.Emit(Context->Selectors);
Ted Kremenek018b3952007-11-06 19:50:53 +0000192
193 // Emit the Identifier Table.
194 llvm::cerr << "Serializing: IdentifierTable.\n";
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000195 Sezr.Emit(Context->Idents);
Ted Kremenekb899ad22007-11-14 17:46:35 +0000196
Ted Kremenek018b3952007-11-06 19:50:53 +0000197 Sezr.ExitBlock();
198
199 // ===---------------------------------------------------===/
Ted Kremenek79a2a262007-11-28 19:21:47 +0000200 // Finalize serialization: write the bits to disk.
Ted Kremenekea75c552007-11-28 21:32:21 +0000201 if (FILE* fp = fopen(Filename.c_str(),"wb")) {
202 fwrite((char*)&Buffer.front(), sizeof(char), Buffer.size(), fp);
203 fclose(fp);
204 }
205 else {
206 llvm::cerr << "Error: Cannot open " << Filename.c_str() << "\n";
207 return;
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000208 }
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000209
Ted Kremenek018b3952007-11-06 19:50:53 +0000210 llvm::cerr << "Commited bitstream to disk: " << Filename.c_str() << "\n";
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000211}
212
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000213
Ted Kremenek79a2a262007-11-28 19:21:47 +0000214void SerializationTest::Deserialize(llvm::sys::Path& Filename,
215 llvm::sys::Path& FNameDeclPrint) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000216
217 // Create the memory buffer that contains the contents of the file.
218
219 using llvm::MemoryBuffer;
220
Ted Kremenek79a2a262007-11-28 19:21:47 +0000221 Janitor<MemoryBuffer> MBuffer(MemoryBuffer::getFile(Filename.c_str(),
222 strlen(Filename.c_str())));
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000223
Ted Kremenek4ac81212007-11-05 21:39:35 +0000224 if(!MBuffer) {
225 llvm::cerr << "ERROR: Cannot read file for deserialization.\n";
226 return;
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000227 }
Ted Kremenekbfa82c42007-10-16 23:37:27 +0000228
Ted Kremenek018b3952007-11-06 19:50:53 +0000229 // Check if the file is of the proper length.
Ted Kremenek4ac81212007-11-05 21:39:35 +0000230 if (MBuffer->getBufferSize() & 0x3) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000231 llvm::cerr << "ERROR: AST file length should be a multiple of 4 bytes.\n";
Ted Kremenek4ac81212007-11-05 21:39:35 +0000232 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000233 }
234
Ted Kremenek018b3952007-11-06 19:50:53 +0000235 // Create the bitstream reader.
236 unsigned char *BufPtr = (unsigned char *) MBuffer->getBufferStart();
237 llvm::BitstreamReader Stream(BufPtr,BufPtr+MBuffer->getBufferSize());
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000238
Ted Kremenek018b3952007-11-06 19:50:53 +0000239 // Sniff for the signature in the bitcode file.
Ted Kremenek07c0fd92007-11-06 23:52:19 +0000240 if (ReadPreamble(Stream)) {
Ted Kremenek4ac81212007-11-05 21:39:35 +0000241 llvm::cerr << "ERROR: Invalid AST-bitcode signature.\n";
242 return;
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000243 }
244
245 // Create the deserializer.
Ted Kremenek018b3952007-11-06 19:50:53 +0000246 llvm::Deserializer Dezr(Stream);
247
248 // ===---------------------------------------------------===/
249 // Deserialize the "Translation Unit" metadata.
250 // ===---------------------------------------------------===/
251
Ted Kremenekb899ad22007-11-14 17:46:35 +0000252 // Skip to the BasicMetaDataBlock. First jump to ASTContextBlock
253 // (which will appear earlier) and record its location.
254
255 bool FoundBlock = Dezr.SkipToBlock(ASTContextBlock);
256 assert (FoundBlock);
257
258 llvm::Deserializer::Location ASTContextBlockLoc =
259 Dezr.getCurrentBlockLocation();
260
261 FoundBlock = Dezr.SkipToBlock(BasicMetadataBlock);
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000262 assert (FoundBlock);
263
Ted Kremenekdca24662007-12-05 00:26:13 +0000264 // Read the SourceManager.
265 llvm::cerr << "Deserializing: SourceManager.\n";
266 SourceManager::CreateAndRegister(Dezr,FMgr);
Ted Kremenek018b3952007-11-06 19:50:53 +0000267
Ted Kremenekc4ca2882007-12-03 22:48:14 +0000268 { // Read the TargetInfo.
269 llvm::cerr << "Deserializing: Target.\n";
270 llvm::SerializedPtrID PtrID = Dezr.ReadPtrID();
271 char* triple = Dezr.ReadCStr(NULL,0,true);
272 std::vector<std::string> triples;
273 triples.push_back(triple);
274 delete [] triple;
275 Dezr.RegisterPtr(PtrID,CreateTargetInfo(triples,Diags));
276 }
277
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000278 // For Selectors, we must read the identifier table first because the
279 // SelectorTable depends on the identifiers being already deserialized.
Ted Kremenekc4ca2882007-12-03 22:48:14 +0000280 llvm::Deserializer::Location SelectorBlockLoc =
281 Dezr.getCurrentBlockLocation();
282
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000283 Dezr.SkipBlock();
Ted Kremenek018b3952007-11-06 19:50:53 +0000284
285 // Read the identifier table.
286 llvm::cerr << "Deserializing: IdentifierTable\n";
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000287 IdentifierTable::CreateAndRegister(Dezr);
288
289 // Now jump back and read the selectors.
290 llvm::cerr << "Deserializing: Selectors\n";
291 Dezr.JumpTo(SelectorBlockLoc);
292 SelectorTable::CreateAndRegister(Dezr);
Ted Kremenek018b3952007-11-06 19:50:53 +0000293
Ted Kremenekb899ad22007-11-14 17:46:35 +0000294 // Now jump back to ASTContextBlock and read the ASTContext.
Ted Kremenek018b3952007-11-06 19:50:53 +0000295 llvm::cerr << "Deserializing: ASTContext.\n";
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000296 Dezr.JumpTo(ASTContextBlockLoc);
Ted Kremenek018b3952007-11-06 19:50:53 +0000297 Dezr.ReadOwnedPtr<ASTContext>();
Ted Kremenek79a2a262007-11-28 19:21:47 +0000298
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000299 // "Rewind" the stream. Find the block with the serialized top-level decls.
300 Dezr.Rewind();
Ted Kremenekb899ad22007-11-14 17:46:35 +0000301 FoundBlock = Dezr.SkipToBlock(DeclsBlock);
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000302 assert (FoundBlock);
303 llvm::Deserializer::Location DeclBlockLoc = Dezr.getCurrentBlockLocation();
304
Ted Kremenek79a2a262007-11-28 19:21:47 +0000305 // Create a printer to "consume" our deserialized ASTS.
306 ASTConsumer* Printer = CreateASTPrinter();
307 Janitor<ASTConsumer> PrinterJanitor(Printer);
Ted Kremenekea75c552007-11-28 21:32:21 +0000308 std::ofstream DeclPP(FNameDeclPrint.c_str());
309 assert (DeclPP && "Could not open file for printing out decls.");
310 Janitor<ASTConsumer> FilePrinter(CreateASTPrinter(&DeclPP));
Ted Kremenek79a2a262007-11-28 19:21:47 +0000311
Ted Kremenek018b3952007-11-06 19:50:53 +0000312 // The remaining objects in the file are top-level decls.
Ted Kremenek7a1f4db2007-11-10 02:07:12 +0000313 while (!Dezr.FinishedBlock(DeclBlockLoc)) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000314 llvm::cerr << "Deserializing: Decl.\n";
315 Decl* decl = Dezr.ReadOwnedPtr<Decl>();
Ted Kremenek79a2a262007-11-28 19:21:47 +0000316 Printer->HandleTopLevelDecl(decl);
317 FilePrinter->HandleTopLevelDecl(decl);
Ted Kremenek5656b782007-11-29 01:24:25 +0000318
319 if (FunctionDecl* FD = dyn_cast<FunctionDecl>(decl))
320 if (FD->getBody()) {
321 // Construct and print a CFG.
322 Janitor<CFG> cfg(CFG::buildCFG(FD->getBody()));
323 cfg->print(DeclPP);
324 }
Ted Kremenek018b3952007-11-06 19:50:53 +0000325 }
326}
327
Ted Kremenek79a2a262007-11-28 19:21:47 +0000328namespace {
329 class TmpDirJanitor {
330 llvm::sys::Path& Dir;
331 public:
332 explicit TmpDirJanitor(llvm::sys::Path& dir) : Dir(dir) {}
333
334 ~TmpDirJanitor() {
335 llvm::cerr << "Removing: " << Dir.c_str() << '\n';
336 Dir.eraseFromDisk(true);
337 }
338 };
339}
Ted Kremenek018b3952007-11-06 19:50:53 +0000340
341SerializationTest::~SerializationTest() {
Ted Kremenek79a2a262007-11-28 19:21:47 +0000342
Ted Kremenek018b3952007-11-06 19:50:53 +0000343 std::string ErrMsg;
Ted Kremenek79a2a262007-11-28 19:21:47 +0000344 llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
Ted Kremenek018b3952007-11-06 19:50:53 +0000345
Ted Kremenek79a2a262007-11-28 19:21:47 +0000346 if (Dir.isEmpty()) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000347 llvm::cerr << "Error: " << ErrMsg << "\n";
348 return;
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000349 }
350
Ted Kremenek79a2a262007-11-28 19:21:47 +0000351 TmpDirJanitor RemoveTmpOnExit(Dir);
352
353 llvm::sys::Path FNameDeclBefore = Dir;
354 FNameDeclBefore.appendComponent("test.decl_before.txt");
355
356 if (FNameDeclBefore.makeUnique(true,&ErrMsg)) {
Ted Kremenek018b3952007-11-06 19:50:53 +0000357 llvm::cerr << "Error: " << ErrMsg << "\n";
358 return;
359 }
Ted Kremenek4ac81212007-11-05 21:39:35 +0000360
Ted Kremenek79a2a262007-11-28 19:21:47 +0000361 llvm::sys::Path FNameDeclAfter = Dir;
362 FNameDeclAfter.appendComponent("test.decl_after.txt");
363
364 if (FNameDeclAfter.makeUnique(true,&ErrMsg)) {
365 llvm::cerr << "Error: " << ErrMsg << "\n";
366 return;
367 }
368
369 llvm::sys::Path ASTFilename = Dir;
370 ASTFilename.appendComponent("test.ast");
371
372 if (ASTFilename.makeUnique(true,&ErrMsg)) {
373 llvm::cerr << "Error: " << ErrMsg << "\n";
374 return;
375 }
376
377 // Serialize and then deserialize the ASTs.
378 Serialize(ASTFilename, FNameDeclBefore);
379 Deserialize(ASTFilename, FNameDeclAfter);
380
381 // Read both pretty-printed files and compare them.
382
383 using llvm::MemoryBuffer;
384
385 Janitor<MemoryBuffer>
386 MBufferSer(MemoryBuffer::getFile(FNameDeclBefore.c_str(),
387 strlen(FNameDeclBefore.c_str())));
388
389 if(!MBufferSer) {
390 llvm::cerr << "ERROR: Cannot read pretty-printed file (pre-pickle).\n";
391 return;
392 }
393
394 Janitor<MemoryBuffer>
395 MBufferDSer(MemoryBuffer::getFile(FNameDeclAfter.c_str(),
396 strlen(FNameDeclAfter.c_str())));
397
398 if(!MBufferDSer) {
399 llvm::cerr << "ERROR: Cannot read pretty-printed file (post-pickle).\n";
400 return;
401 }
402
403 const char *p1 = MBufferSer->getBufferStart();
404 const char *e1 = MBufferSer->getBufferEnd();
405 const char *p2 = MBufferDSer->getBufferStart();
406 const char *e2 = MBufferDSer->getBufferEnd();
407
408 if (MBufferSer->getBufferSize() == MBufferDSer->getBufferSize())
409 for ( ; p1 != e1 ; ++p1, ++p2 )
410 if (*p1 != *p2) break;
411
412 if (p1 != e1 || p2 != e2 )
413 llvm::cerr << "ERROR: Pretty-printed files are not the same.\n";
414 else
415 llvm::cerr << "SUCCESS: Pretty-printed files are the same.\n";
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000416}