mirror of
https://github.com/ziglang/zig.git
synced 2024-11-23 04:40:19 +00:00
link-tests: test unwind info emitter via c++ exceptions
This commit is contained in:
parent
835a60a34f
commit
e0ccbff87d
@ -190,6 +190,11 @@ fn addMachOCases(cases: *tests.StandaloneContext) void {
|
||||
.requires_symlinks = true,
|
||||
});
|
||||
|
||||
cases.addBuildFile("test/link/macho/unwind_info/build.zig", .{
|
||||
.build_modes = true,
|
||||
.requires_symlinks = true,
|
||||
});
|
||||
|
||||
cases.addBuildFile("test/link/macho/uuid/build.zig", .{
|
||||
.build_modes = false,
|
||||
.requires_symlinks = true,
|
||||
|
41
test/link/macho/unwind_info/all.h
Normal file
41
test/link/macho/unwind_info/all.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef ALL
|
||||
#define ALL
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
struct SimpleString {
|
||||
SimpleString(size_t max_size);
|
||||
~SimpleString();
|
||||
|
||||
void print(const char* tag) const;
|
||||
bool append_line(const char* x);
|
||||
|
||||
private:
|
||||
size_t max_size;
|
||||
char* buffer;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
struct SimpleStringOwner {
|
||||
SimpleStringOwner(const char* x);
|
||||
~SimpleStringOwner();
|
||||
|
||||
private:
|
||||
SimpleString string;
|
||||
};
|
||||
|
||||
class Error: public std::exception {
|
||||
public:
|
||||
explicit Error(const char* msg) : msg{ msg } {}
|
||||
virtual ~Error() noexcept {}
|
||||
virtual const char* what() const noexcept {
|
||||
return msg.c_str();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
#endif
|
60
test/link/macho/unwind_info/build.zig
Normal file
60
test/link/macho/unwind_info/build.zig
Normal file
@ -0,0 +1,60 @@
|
||||
const std = @import("std");
|
||||
const Builder = std.build.Builder;
|
||||
const LibExeObjectStep = std.build.LibExeObjStep;
|
||||
|
||||
pub fn build(b: *Builder) void {
|
||||
const mode = b.standardReleaseOptions();
|
||||
const target: std.zig.CrossTarget = .{ .os_tag = .macos };
|
||||
|
||||
const test_step = b.step("test", "Test the program");
|
||||
|
||||
testUnwindInfo(b, test_step, mode, target, false);
|
||||
testUnwindInfo(b, test_step, mode, target, true);
|
||||
}
|
||||
|
||||
fn testUnwindInfo(
|
||||
b: *Builder,
|
||||
test_step: *std.build.Step,
|
||||
mode: std.builtin.Mode,
|
||||
target: std.zig.CrossTarget,
|
||||
dead_strip: bool,
|
||||
) void {
|
||||
const exe = createScenario(b, mode, target);
|
||||
exe.link_gc_sections = dead_strip;
|
||||
|
||||
const check = exe.checkObject(.macho);
|
||||
check.checkStart("segname __TEXT");
|
||||
check.checkNext("sectname __gcc_except_tab");
|
||||
check.checkNext("sectname __unwind_info");
|
||||
check.checkNext("sectname __eh_frame");
|
||||
|
||||
check.checkInSymtab();
|
||||
check.checkNext("{*} (__TEXT,__text) external ___gxx_personality_v0");
|
||||
|
||||
const run_cmd = check.runAndCompare();
|
||||
run_cmd.expectStdOutEqual(
|
||||
\\Constructed: a
|
||||
\\Constructed: b
|
||||
\\About to destroy: b
|
||||
\\About to destroy: a
|
||||
\\Error: Not enough memory!
|
||||
\\
|
||||
);
|
||||
|
||||
test_step.dependOn(&run_cmd.step);
|
||||
}
|
||||
|
||||
fn createScenario(b: *Builder, mode: std.builtin.Mode, target: std.zig.CrossTarget) *LibExeObjectStep {
|
||||
const exe = b.addExecutable("test", null);
|
||||
b.default_step.dependOn(&exe.step);
|
||||
exe.addIncludePath(".");
|
||||
exe.addCSourceFiles(&[_][]const u8{
|
||||
"main.cpp",
|
||||
"simple_string.cpp",
|
||||
"simple_string_owner.cpp",
|
||||
}, &[0][]const u8{});
|
||||
exe.setBuildMode(mode);
|
||||
exe.setTarget(target);
|
||||
exe.linkLibCpp();
|
||||
return exe;
|
||||
}
|
24
test/link/macho/unwind_info/main.cpp
Normal file
24
test/link/macho/unwind_info/main.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "all.h"
|
||||
#include <cstdio>
|
||||
|
||||
void fn_c() {
|
||||
SimpleStringOwner c{ "cccccccccc" };
|
||||
}
|
||||
|
||||
void fn_b() {
|
||||
SimpleStringOwner b{ "b" };
|
||||
fn_c();
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
SimpleStringOwner a{ "a" };
|
||||
fn_b();
|
||||
SimpleStringOwner d{ "d" };
|
||||
} catch (const Error& e) {
|
||||
printf("Error: %s\n", e.what());
|
||||
} catch(const std::exception& e) {
|
||||
printf("Exception: %s\n", e.what());
|
||||
}
|
||||
return 0;
|
||||
}
|
30
test/link/macho/unwind_info/simple_string.cpp
Normal file
30
test/link/macho/unwind_info/simple_string.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "all.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
SimpleString::SimpleString(size_t max_size)
|
||||
: max_size{ max_size }, length{} {
|
||||
if (max_size == 0) {
|
||||
throw Error{ "Max size must be at least 1." };
|
||||
}
|
||||
buffer = new char[max_size];
|
||||
buffer[0] = 0;
|
||||
}
|
||||
|
||||
SimpleString::~SimpleString() {
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void SimpleString::print(const char* tag) const {
|
||||
printf("%s: %s", tag, buffer);
|
||||
}
|
||||
|
||||
bool SimpleString::append_line(const char* x) {
|
||||
const auto x_len = strlen(x);
|
||||
if (x_len + length + 2 > max_size) return false;
|
||||
std::strncpy(buffer + length, x, max_size - length);
|
||||
length += x_len;
|
||||
buffer[length++] = '\n';
|
||||
buffer[length] = 0;
|
||||
return true;
|
||||
}
|
12
test/link/macho/unwind_info/simple_string_owner.cpp
Normal file
12
test/link/macho/unwind_info/simple_string_owner.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "all.h"
|
||||
|
||||
SimpleStringOwner::SimpleStringOwner(const char* x) : string{ 10 } {
|
||||
if (!string.append_line(x)) {
|
||||
throw Error{ "Not enough memory!" };
|
||||
}
|
||||
string.print("Constructed");
|
||||
}
|
||||
|
||||
SimpleStringOwner::~SimpleStringOwner() {
|
||||
string.print("About to destroy");
|
||||
}
|
Loading…
Reference in New Issue
Block a user