@@ -80,6 +80,7 @@ Expected<FileCache> llvm::localCache(const Twine &CacheNameRef,
8080 sys::fs::TempFile TempFile;
8181 std::string ModuleName;
8282 unsigned Task;
83+ bool Committed = false ;
8384
8485 CacheStream (std::unique_ptr<raw_pwrite_stream> OS, AddBufferFn AddBuffer,
8586 sys::fs::TempFile TempFile, std::string EntryPath,
@@ -88,9 +89,10 @@ Expected<FileCache> llvm::localCache(const Twine &CacheNameRef,
8889 AddBuffer (std::move(AddBuffer)), TempFile(std::move(TempFile)),
8990 ModuleName(ModuleName), Task(Task) {}
9091
91- ~CacheStream () {
92- // TODO: Manually commit rather than using non-trivial destructor,
93- // allowing to replace report_fatal_errors with a return Error.
92+ Error commit () override {
93+ if (Committed)
94+ return Error::success ();
95+ Committed = true ;
9496
9597 // Make sure the stream is closed before committing it.
9698 OS.reset ();
@@ -100,10 +102,12 @@ Expected<FileCache> llvm::localCache(const Twine &CacheNameRef,
100102 MemoryBuffer::getOpenFile (
101103 sys::fs::convertFDToNativeFile (TempFile.FD ), ObjectPathName,
102104 /* FileSize=*/ -1 , /* RequiresNullTerminator=*/ false );
103- if (!MBOrErr)
104- report_fatal_error (Twine (" Failed to open new cache file " ) +
105- TempFile.TmpName + " : " +
106- MBOrErr.getError ().message () + " \n " );
105+ if (!MBOrErr) {
106+ std::error_code EC = MBOrErr.getError ();
107+ return createStringError (EC, Twine (" Failed to open new cache file " ) +
108+ TempFile.TmpName + " : " +
109+ EC.message () + " \n " );
110+ }
107111
108112 // On POSIX systems, this will atomically replace the destination if
109113 // it already exists. We try to emulate this on Windows, but this may
@@ -118,7 +122,10 @@ Expected<FileCache> llvm::localCache(const Twine &CacheNameRef,
118122 E = handleErrors (std::move (E), [&](const ECError &E) -> Error {
119123 std::error_code EC = E.convertToErrorCode ();
120124 if (EC != errc::permission_denied)
121- return errorCodeToError (EC);
125+ return createStringError (
126+ EC, Twine (" Failed to rename temporary file " ) +
127+ TempFile.TmpName + " to " + ObjectPathName + " : " +
128+ EC.message () + " \n " );
122129
123130 auto MBCopy = MemoryBuffer::getMemBufferCopy ((*MBOrErr)->getBuffer (),
124131 ObjectPathName);
@@ -131,11 +138,22 @@ Expected<FileCache> llvm::localCache(const Twine &CacheNameRef,
131138 });
132139
133140 if (E)
134- report_fatal_error (Twine (" Failed to rename temporary file " ) +
135- TempFile.TmpName + " to " + ObjectPathName + " : " +
136- toString (std::move (E)) + " \n " );
141+ return E;
137142
138143 AddBuffer (Task, ModuleName, std::move (*MBOrErr));
144+ return Error::success ();
145+ }
146+
147+ ~CacheStream () {
148+ // In Debug builds, try to track down places where commit() was not
149+ // called before destruction.
150+ assert (Committed);
151+ // In Release builds, fall back to the previous behaviour of committing
152+ // during destruction and reporting errors with report_fatal_error.
153+ if (Committed)
154+ return ;
155+ if (Error Err = commit ())
156+ report_fatal_error (Twine (toString (std::move (Err))));
139157 }
140158 };
141159
0 commit comments