Skip to content

Commit d7dbd9d

Browse files
committed
Fix clang-cl build and test clang-cl in CI
1 parent f526983 commit d7dbd9d

File tree

4 files changed

+72
-12
lines changed

4 files changed

+72
-12
lines changed

.github/workflows/ci.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,3 +677,25 @@ jobs:
677677
-DCPPTRACE_BUILD_TESTING=On
678678
ninja
679679
./unittest_module
680+
681+
unittest-windows-clangcl:
682+
runs-on: windows-2022
683+
needs: unittest-windows
684+
strategy:
685+
fail-fast: false
686+
matrix:
687+
build_type: [Debug]
688+
steps:
689+
- uses: actions/checkout@v4
690+
- name: Enable Developer Command Prompt
691+
uses: ilammy/msvc-dev-cmd@v1.13.0
692+
- name: build and test
693+
run: |
694+
mkdir build
695+
cd build
696+
cmake .. `
697+
-T ClangCL `
698+
-DCPPTRACE_WERROR_BUILD=On `
699+
-DCPPTRACE_BUILD_TESTING=On
700+
cmake --build . --config ${{matrix.build_type}}
701+
./${{matrix.build_type}}/unittest

include/cpptrace/from_current_macros.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
#ifdef _MSC_VER
2020
#define CPPTRACE_TYPE_FOR(param) \
21-
::cpptrace::detail::argument<void(param)>::type
21+
typename ::cpptrace::detail::argument<void(param)>::type
2222
// this awful double-IILE is due to C2713 "You can't use structured exception handling (__try/__except) and C++
2323
// exception handling (try/catch) in the same function."
2424
#define CPPTRACE_TRY \

src/from_current.cpp

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
#include "utils/utils.hpp"
1313
#include "logging.hpp"
1414

15-
#ifdef _MSC_VER
16-
#include <ehdata.h>
17-
#else
15+
#ifndef _MSC_VER
1816
#include <string.h>
1917
#if IS_WINDOWS
2018
#ifndef WIN32_LEAN_AND_MEAN
@@ -62,15 +60,53 @@ namespace detail {
6260
// https://github.com/ecatmur/stacktrace-from-exception/blob/main/stacktrace-from-exception.cpp
6361
// https://github.com/wine-mirror/wine/blob/7f833db11ffea4f3f4fa07be31d30559aff9c5fb/dlls/msvcrt/except.c#L371
6462
// https://github.com/facebook/folly/blob/d17bf897cb5bbf8f07b122a614e8cffdc38edcde/folly/lang/Exception.cpp
63+
64+
// ClangCL doesn't define ThrowInfo so we use our own
65+
// sources:
66+
// - https://github.com/ecatmur/stacktrace-from-exception/blob/main/stacktrace-from-exception.cpp
67+
// - https://github.com/catboost/catboost/blob/master/contrib/libs/cxxsupp/libcxx/src/support/runtime/exception_pointer_msvc.ipp
68+
// - https://www.geoffchappell.com/studies/msvc/language/predefined/index.htm
69+
#if defined _WIN64
70+
#pragma pack(push, 4)
71+
struct CatchableType {
72+
std::uint32_t properties;
73+
std::int32_t pType;
74+
std::uint32_t non_virtual_adjustment; // these next three are from _PMD
75+
std::uint32_t offset_to_virtual_base_ptr;
76+
std::uint32_t virtual_base_table_index;
77+
std::uint32_t sizeOrOffset;
78+
std::int32_t copyFunction;
79+
};
80+
struct ThrowInfo {
81+
std::uint32_t attributes;
82+
std::int32_t pmfnUnwind;
83+
std::int32_t pForwardCompat;
84+
std::int32_t pCatchableTypeArray;
85+
};
86+
#pragma warning(disable:4200)
87+
struct CatchableTypeArray {
88+
uint32_t nCatchableTypes;
89+
int32_t arrayOfCatchableTypes[];
90+
};
91+
#pragma warning (pop)
92+
#pragma pack(pop)
93+
#else
94+
using CatchableType = ::_CatchableType;
95+
using ThrowInfo = ::_ThrowInfo;
96+
#endif
97+
98+
static constexpr unsigned EH_MAGIC_NUMBER1 = 0x19930520; // '?msc' version magic, see ehdata.h
99+
static constexpr unsigned EH_EXCEPTION_NUMBER = 0xE06D7363; // '?msc', 'msc' | 0xE0000000
100+
65101
using catchable_type_array_t = decltype(ThrowInfo::pCatchableTypeArray);
66102

67103
class catchable_type_info {
68104
HMODULE module_pointer = nullptr;
69-
const _CatchableTypeArray* catchable_types = nullptr;
105+
const CatchableTypeArray* catchable_types = nullptr;
70106
public:
71107
catchable_type_info(const HMODULE module_pointer, catchable_type_array_t catchable_type_array)
72108
: module_pointer(module_pointer) {
73-
catchable_types = rtti_rva<const _CatchableTypeArray*>(catchable_type_array);
109+
catchable_types = rtti_rva<const CatchableTypeArray*>(catchable_type_array);
74110
}
75111

76112
class iterator {

test/unit/tracing/rethrow.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,19 +153,21 @@ TEST(Rethrow, RethrowTraceCorrect) {
153153
EXPECT_TRUE(cpptrace::current_exception_was_rethrown());
154154
EXPECT_EQ(e.what(), "foobar"sv);
155155
auto rethrow_trace = cpptrace::from_current_exception_rethrow();
156+
rethrow_trace.print();
156157
ASSERT_GE(rethrow_trace.frames.size(), 4);
157-
auto it = std::find_if(
158-
rethrow_trace.frames.begin(),
159-
rethrow_trace.frames.end(),
158+
// reverse to get the last one matching instead of "`stacktrace_from_current_rethrow_2'::`1'::catch$4()" on msvc
159+
auto rit = std::find_if(
160+
rethrow_trace.frames.rbegin(),
161+
rethrow_trace.frames.rend(),
160162
[](const cpptrace::stacktrace_frame& frame) {
161-
// catch check is to ignore "`stacktrace_from_current_rethrow_2'::`1'::catch$4()" on msvc
162163
return frame.symbol.find("stacktrace_from_current_rethrow_2") != std::string::npos
163164
&& frame.symbol.find("::catch") == std::string::npos;
164165
}
165166
);
166-
ASSERT_NE(it, rethrow_trace.frames.end()) << rethrow_trace;
167+
ASSERT_NE(rit, rethrow_trace.frames.rend()) << rethrow_trace;
168+
size_t i = static_cast<size_t>(&*rit - &*rethrow_trace.frames.begin());
169+
auto it = rethrow_trace.frames.begin() + i;
167170
clean_trace(rethrow_trace, it);
168-
size_t i = static_cast<size_t>(it - rethrow_trace.frames.begin());
169171
int j = 0;
170172
ASSERT_LT(i, rethrow_trace.frames.size());
171173
ASSERT_LT(j, rethrow_line_numbers.size());

0 commit comments

Comments
 (0)