Skip to content

Commit 6402dd6

Browse files
Copilotgebner
andauthored
Fix assert support when assert.h is included after c2pulse.h
Agent-Logs-Url: https://github.com/FStarLang/c2pulse/sessions/9442fd81-5e97-4ff4-a291-37a621de7e8f Co-authored-by: gebner <313929+gebner@users.noreply.github.com>
1 parent 2ddef7b commit 6402dd6

2 files changed

Lines changed: 88 additions & 262 deletions

File tree

cpp/impl.cpp

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,6 +1563,54 @@ std::string getResourcesPath() {
15631563
return GetResourcesPath(getBinaryForResourcesPath());
15641564
}
15651565

1566+
// --- Builtin virtual include directory ---
1567+
// c2pulse injects a wrapper assert.h so that #include <assert.h> always
1568+
// results in assert() being translated to __c2pulse_c_assert(), regardless
1569+
// of whether assert.h is included before or after c2pulse.h.
1570+
static const char BUILTIN_INCLUDE_DIR[] = "/c2pulse_builtins";
1571+
static const char BUILTIN_ASSERT_H_PATH[] = "/c2pulse_builtins/assert.h";
1572+
// The wrapper uses #include_next to pull in the real system assert.h and then
1573+
// re-overrides the assert macro so c2pulse can always intercept assert() calls.
1574+
static const char BUILTIN_ASSERT_H_CONTENT[] =
1575+
"#include_next <assert.h>\n"
1576+
"#ifdef C2PULSE\n"
1577+
"#undef assert\n"
1578+
"#define assert(x) __c2pulse_c_assert(x)\n"
1579+
"#endif\n";
1580+
1581+
// Stable unique IDs for builtin virtual filesystem entries (device 2 to avoid
1582+
// collisions with real files which use device 0).
1583+
static const llvm::sys::fs::UniqueID BUILTIN_ASSERT_H_UID(2, 1);
1584+
static const llvm::sys::fs::UniqueID BUILTIN_INCLUDE_DIR_UID(2, 2);
1585+
1586+
// A VFS file that serves static string content (used for builtin headers).
1587+
class BuiltinVFSFile : public llvm::vfs::File {
1588+
llvm::StringRef name;
1589+
llvm::StringRef content;
1590+
1591+
public:
1592+
BuiltinVFSFile(llvm::StringRef n, llvm::StringRef c) : name(n), content(c) {}
1593+
1594+
llvm::ErrorOr<llvm::vfs::Status> status() override {
1595+
llvm::sys::TimePoint<> time;
1596+
return llvm::vfs::Status(
1597+
name, BUILTIN_ASSERT_H_UID, time, 0, 0, content.size(),
1598+
llvm::sys::fs::file_type::regular_file, llvm::sys::fs::perms::all_all);
1599+
}
1600+
1601+
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
1602+
getBuffer(const Twine &Name, int64_t FileSize = -1,
1603+
bool RequiresNullTerminator = true,
1604+
bool IsVolatile = false) override {
1605+
if (!RequiresNullTerminator)
1606+
return llvm::MemoryBuffer::getMemBuffer(content, name);
1607+
return llvm::MemoryBuffer::getMemBufferCopy(content, name);
1608+
}
1609+
1610+
std::error_code close() override { return {}; }
1611+
llvm::ErrorOr<std::string> getName() override { return name.str(); }
1612+
};
1613+
15661614
llvm::vfs::Status mkStatus(Ref<rust::crate::vfs::VFSEntry> entry) {
15671615
auto fileName = entry.get_file_name();
15681616
llvm::sys::fs::UniqueID unique(0, (uint64_t)fileName.as_ptr());
@@ -1607,6 +1655,14 @@ class CtxVFS : public llvm::vfs::FileSystem {
16071655
RefMut<Ctx> ctx;
16081656
IntrusiveRefCntPtr<llvm::vfs::FileSystem> realFS;
16091657

1658+
static bool isBuiltinFile(llvm::StringRef path) {
1659+
return path == BUILTIN_ASSERT_H_PATH;
1660+
}
1661+
1662+
static bool isBuiltinDir(llvm::StringRef path) {
1663+
return path == BUILTIN_INCLUDE_DIR;
1664+
}
1665+
16101666
public:
16111667
CtxVFS(RefMut<Ctx> c) : ctx(c), realFS(llvm::vfs::getRealFileSystem()) {}
16121668

@@ -1615,7 +1671,22 @@ class CtxVFS : public llvm::vfs::FileSystem {
16151671
}
16161672

16171673
llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override {
1618-
auto res = ctx.read_vfs_file(toStr(Path.str()));
1674+
auto pathStr = Path.str();
1675+
if (isBuiltinFile(pathStr)) {
1676+
llvm::sys::TimePoint<> time;
1677+
return llvm::vfs::Status(BUILTIN_ASSERT_H_PATH, BUILTIN_ASSERT_H_UID,
1678+
time, 0, 0, sizeof(BUILTIN_ASSERT_H_CONTENT) - 1,
1679+
llvm::sys::fs::file_type::regular_file,
1680+
llvm::sys::fs::perms::all_all);
1681+
}
1682+
if (isBuiltinDir(pathStr)) {
1683+
llvm::sys::TimePoint<> time;
1684+
return llvm::vfs::Status(BUILTIN_INCLUDE_DIR, BUILTIN_INCLUDE_DIR_UID,
1685+
time, 0, 0, 0,
1686+
llvm::sys::fs::file_type::directory_file,
1687+
llvm::sys::fs::perms::all_all);
1688+
}
1689+
auto res = ctx.read_vfs_file(toStr(pathStr));
16191690
if (!res.is_ok()) {
16201691
// TODO: fallback for directories
16211692
return realFS->status(Path);
@@ -1625,6 +1696,12 @@ class CtxVFS : public llvm::vfs::FileSystem {
16251696

16261697
llvm::ErrorOr<std::unique_ptr<llvm::vfs::File>>
16271698
openFileForRead(const Twine &Path) override {
1699+
if (isBuiltinFile(Path.str())) {
1700+
return std::make_unique<BuiltinVFSFile>(
1701+
llvm::StringRef(BUILTIN_ASSERT_H_PATH),
1702+
llvm::StringRef(BUILTIN_ASSERT_H_CONTENT,
1703+
sizeof(BUILTIN_ASSERT_H_CONTENT) - 1));
1704+
}
16281705
auto res = ctx.read_vfs_file(toStr(Path.str()));
16291706
if (!res.is_ok()) {
16301707
return llvm::errc::no_such_file_or_directory;
@@ -1652,7 +1729,10 @@ class CtxVFS : public llvm::vfs::FileSystem {
16521729
}
16531730

16541731
bool exists(const Twine &Path) override {
1655-
auto res = ctx.read_vfs_file(toStr(Path.str()));
1732+
auto pathStr = Path.str();
1733+
if (isBuiltinFile(pathStr) || isBuiltinDir(pathStr))
1734+
return true;
1735+
auto res = ctx.read_vfs_file(toStr(pathStr));
16561736
if (res.is_ok())
16571737
return true;
16581738

@@ -1705,6 +1785,12 @@ static void parse_file(RefMut<Ctx> ctx) {
17051785
incPath.c_str(), ArgumentInsertPosition::BEGIN));
17061786
}
17071787

1788+
// Add the builtin include directory last so it ends up first in the
1789+
// command line (highest priority). This ensures our wrapper assert.h
1790+
// is found before any system assert.h.
1791+
Tool.appendArgumentsAdjuster(getInsertArgumentAdjuster(
1792+
{"-I", BUILTIN_INCLUDE_DIR}, ArgumentInsertPosition::BEGIN));
1793+
17081794
C2PulseActionFactory factory(ctx, rangeMap);
17091795
Tool.run(&factory);
17101796
}

llvm.sh

Lines changed: 0 additions & 260 deletions
This file was deleted.

0 commit comments

Comments
 (0)