diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1bc76c9..cf1053e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,13 +7,13 @@ on:
   pull_request:
   schedule:
     # run CI every day even if no PRs/merges occur
-    - cron:  '0 12 * * *'
+    - cron: '0 12 * * *'
 
 jobs:
   lint:
-    runs-on: ubuntu-18.04
+    runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v3
 
       - name: deps
         run: |
@@ -30,7 +30,7 @@ jobs:
   pe-parse:
     strategy:
       matrix:
-        platform: ["ubuntu-18.04", "macos-latest"]
+        platform: ["ubuntu-latest", "macos-latest"]
         build-type: ["Debug", "Release"]
         build-shared: ["0", "1"]
         compiler:
@@ -41,14 +41,9 @@ jobs:
           compiler: { CC: "gcc", CXX: "g++" }
     runs-on: ${{ matrix.platform }}
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
       with:
         submodules: 'true'
-    # https://github.com/actions/virtual-environments/issues/3376
-    - name: Workaround GHA Issue with GCC 11
-      if: matrix.compiler.CC == 'clang' && matrix.platform == 'ubuntu-18.04'
-      run: |
-        sudo apt remove libgcc-11-dev gcc-11
     - name: Enable ASan+UBSan Sanitizers
       if: matrix.build-type == 'Debug'
       run: |
@@ -78,27 +73,32 @@ jobs:
   pepy:
     strategy:
       matrix:
-        platform: ["ubuntu-18.04", "macos-latest"]
+        platform: ["ubuntu-latest", "macos-latest"]
         python:
-          - "3.6"
           - "3.7"
           - "3.8"
+          - "3.9"
+          - "3.10"
     runs-on: ${{ matrix.platform }}
     steps:
-    - uses: actions/checkout@v2
-    - uses: actions/setup-python@v2
+    - uses: actions/checkout@v3
+    - uses: actions/setup-python@v3
       with:
         python-version: ${{ matrix.python }}
     - name: build
       run: |
-        python3 setup.py build
-    - name: sdist and install
+        python -m pip install build wheel setuptools
+        python -m build
+    - name: test distributions
       run: |
-        python3 setup.py sdist
-        python3 -m pip install --user dist/*.tar.gz
-    - name: test
-      run: |
-        python3 tests/test_pepy.py tests/assets/example.exe
+        for dist in dist/*; do
+          python -m venv test-env
+
+          ./test-env/bin/python -m pip install "${dist}"
+          ./test-env/bin/python tests/test_pepy.py tests/assets/example.exe
+
+          rm -rf test-env
+        done
 
   pe-parse-windows:
     strategy:
@@ -108,7 +108,7 @@ jobs:
         build-shared: ["0", "1"]
     runs-on: windows-2019
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
       with:
         submodules: 'true'
     - name: Enable ASan Sanitizers
@@ -147,18 +147,20 @@ jobs:
     strategy:
       matrix:
         python:
-          - "3.6"
           - "3.7"
           - "3.8"
+          - "3.9"
+          - "3.10"
     runs-on: windows-latest
     steps:
-    - uses: actions/checkout@v2
-    - uses: actions/setup-python@v2
+    - uses: actions/checkout@v3
+    - uses: actions/setup-python@v3
       with:
         python-version: ${{ matrix.python }}
     - name: build
       run: |
-        python setup.py build
+        python -m pip install --upgrade build wheel setuptools
+        python -m build
     - name: install
       run: |
         python -m pip install --user .
diff --git a/pe-parser-library/include/pe-parse/parse.h b/pe-parser-library/include/pe-parse/parse.h
index c4b0777..4407ce2 100644
--- a/pe-parser-library/include/pe-parse/parse.h
+++ b/pe-parser-library/include/pe-parse/parse.h
@@ -40,28 +40,38 @@ THE SOFTWARE.
   err_loc.assign(__func__);     \
   err_loc += ":" + to_string<std::uint32_t>(__LINE__, std::dec);
 
-#define READ_WORD(b, o, inst, member)                                      \
-  if (!readWord(b, o + offsetof(__typeof__(inst), member), inst.member)) { \
-    PE_ERR(PEERR_READ);                                                    \
-    return false;                                                          \
+#define READ_WORD(b, o, inst, member)                                          \
+  if (!readWord(b,                                                             \
+                o + static_cast<uint32_t>(offsetof(__typeof__(inst), member)), \
+                inst.member)) {                                                \
+    PE_ERR(PEERR_READ);                                                        \
+    return false;                                                              \
   }
 
-#define READ_DWORD(b, o, inst, member)                                      \
-  if (!readDword(b, o + offsetof(__typeof__(inst), member), inst.member)) { \
-    PE_ERR(PEERR_READ);                                                     \
-    return false;                                                           \
+#define READ_DWORD(b, o, inst, member)                                   \
+  if (!readDword(                                                        \
+          b,                                                             \
+          o + static_cast<uint32_t>(offsetof(__typeof__(inst), member)), \
+          inst.member)) {                                                \
+    PE_ERR(PEERR_READ);                                                  \
+    return false;                                                        \
   }
 
-#define READ_QWORD(b, o, inst, member)                                      \
-  if (!readQword(b, o + offsetof(__typeof__(inst), member), inst.member)) { \
-    PE_ERR(PEERR_READ);                                                     \
-    return false;                                                           \
+#define READ_QWORD(b, o, inst, member)                                   \
+  if (!readQword(                                                        \
+          b,                                                             \
+          o + static_cast<uint32_t>(offsetof(__typeof__(inst), member)), \
+          inst.member)) {                                                \
+    PE_ERR(PEERR_READ);                                                  \
+    return false;                                                        \
   }
 
-#define READ_BYTE(b, o, inst, member)                                      \
-  if (!readByte(b, o + offsetof(__typeof__(inst), member), inst.member)) { \
-    PE_ERR(PEERR_READ);                                                    \
-    return false;                                                          \
+#define READ_BYTE(b, o, inst, member)                                          \
+  if (!readByte(b,                                                             \
+                o + static_cast<uint32_t>(offsetof(__typeof__(inst), member)), \
+                inst.member)) {                                                \
+    PE_ERR(PEERR_READ);                                                        \
+    return false;                                                              \
   }
 
 #define TEST_MACHINE_CHARACTERISTICS(h, m, ch) \
diff --git a/pe-parser-library/src/parse.cpp b/pe-parser-library/src/parse.cpp
index bb2a8d4..4c964c8 100644
--- a/pe-parser-library/src/parse.cpp
+++ b/pe-parser-library/src/parse.cpp
@@ -1777,7 +1777,7 @@ bool getRelocations(parsed_pe *p) {
         // Mask out the type and assign
         type = entry >> 12;
         // Mask out the offset and assign
-        offset = entry & ~0xf000;
+        offset = entry & static_cast<std::uint16_t>(~0xf000);
 
         // Produce the VA of the relocation
         VA relocVA;
diff --git a/setup.py b/setup.py
index 039488e..d5ac8ec 100644
--- a/setup.py
+++ b/setup.py
@@ -60,10 +60,7 @@ if platform.system() == "Windows":
         os.path.abspath(os.path.join(os.path.dirname(sys.executable), "libs")),
         "C:\\usr\\lib",
     ]
-    COMPILE_ARGS = [
-        "/EHsc",
-        f'/D"PEPARSE_VERSION=\\"{VERSION}\\""',
-    ]
+    COMPILE_ARGS = ["/EHsc"]
 else:
     SOURCE_FILES.append(
         os.path.join(here, "pe-parser-library", "src", "unicode_codecvt.cpp")
@@ -75,10 +72,11 @@ else:
         os.path.join(here, "pe-parser-library", "include"),
     ]
     LIBRARY_DIRS += ["/usr/lib", "/usr/local/lib"]
-    COMPILE_ARGS = ["-std=c++11", f'-DPEPARSE_VERSION="{VERSION}"']
+    COMPILE_ARGS = ["-std=c++17"]
 
 extension_mod = Extension(
     "pepy",
+    define_macros=[("PEPARSE_VERSION", f'"{VERSION}"')],
     sources=SOURCE_FILES,
     extra_compile_args=COMPILE_ARGS,
     language="c++",
@@ -89,7 +87,7 @@ extension_mod = Extension(
 setup(
     name="pepy",
     url="https://github.com/trailofbits/pe-parse",
-    python_requires=">= 3.6",
+    python_requires=">=3.7",
     version=VERSION,
     description="Python bindings for pe-parse",
     long_description=README,