#include <cassert>
#include <cstring>
#include <iostream>
+#include <sstream>
#include "table.h"
namespace libspirv {
+DiagnosticStream::DiagnosticStream(DiagnosticStream&& other)
+ : stream_(),
+ position_(other.position_),
+ consumer_(other.consumer_),
+ error_(other.error_) {
+ // Prevent the other object from emitting output during destruction.
+ other.error_ = SPV_FAILED_MATCH;
+ // Some platforms are missing support for std::ostringstream functionality,
+ // including: move constructor, swap method. Either would have been a
+ // better choice than copying the string.
+ stream_ << other.stream_.str();
+}
+
DiagnosticStream::~DiagnosticStream() {
if (error_ != SPV_FAILED_MATCH && consumer_ != nullptr) {
auto level = SPV_MSG_ERROR;
spv_result_t error)
: position_(position), consumer_(consumer), error_(error) {}
- DiagnosticStream(DiagnosticStream&& other)
- : stream_(other.stream_.str()),
- position_(other.position_),
- consumer_(other.consumer_),
- error_(other.error_) {}
+ // Creates a DiagnosticStream from an expiring DiagnosticStream.
+ // The new object takes the contents of the other, and prevents the
+ // other from emitting anything during destruction.
+ DiagnosticStream(DiagnosticStream&& other);
+ // Destroys a DiagnosticStream.
+ // If its status code is something other than SPV_FAILED_MATCH
+ // then emit the accumulated message to the consumer.
~DiagnosticStream();
// Adds the given value to the diagnostic message to be written.
operator spv_result_t() { return error_; }
private:
- std::stringstream stream_;
+ std::ostringstream stream_;
spv_position_t position_;
- const spvtools::MessageConsumer& consumer_; // Message consumer callback.
+ spvtools::MessageConsumer consumer_; // Message consumer callback.
spv_result_t error_;
};
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <algorithm>
+#include <sstream>
+
+#include "gmock/gmock.h"
#include "unit_spirv.h"
namespace {
using libspirv::DiagnosticStream;
+using ::testing::Eq;
// Returns a newly created diagnostic value.
spv_diagnostic MakeValidDiagnostic() {
spv_result_t(DiagnosticStream({}, nullptr, SPV_FAILED_MATCH)));
}
+TEST(DiagnosticStream, MoveConstructorPreservesPreviousMessagesAndPreventsOutputFromExpiringValue) {
+ std::ostringstream messages;
+ int message_count = 0;
+ auto consumer = [&messages, &message_count](spv_message_level_t, const char*,
+ const spv_position_t&,
+ const char* msg) {
+ message_count++;
+ messages << msg;
+ };
+
+ // Enclose the DiagnosticStream variables in a scope to force destruction.
+ {
+ DiagnosticStream ds0({}, consumer, SPV_ERROR_INVALID_BINARY);
+ ds0 << "First";
+ DiagnosticStream ds1(std::move(ds0));
+ ds1 << "Second";
+ }
+ EXPECT_THAT(message_count, Eq(1));
+ EXPECT_THAT(messages.str(), Eq("FirstSecond"));
+}
+
} // anonymous namespace