Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,7 @@ IncludeCategories:
# Comments
FixNamespaceComments: true
CommentPragmas: '^ clang-format'

---
Language: Json
BasedOnStyle: llvm
36 changes: 28 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ jobs:
common-flags-base: {{#if (ieq compiler 'clang')}}-gz=zstd {{/if}}
common-flags: {{{ common-flags-base }}}{{#if msan }}-fsanitize-memory-track-origins {{/if}}
common-ccflags: {{{ ccflags }}} {{{ common-flags }}}
mrdocs-flags: {{{ warning-flags }}}{{#if (and (eq compiler 'gcc') (not asan)) }}-static {{/if}}
mrdocs-flags: {{{ warning-flags }}}
mrdocs-ccflags: {{{ common-ccflags }}} {{{ mrdocs-flags }}}
mrdocs-package-generators: {{#if (ieq os 'windows') }}7Z ZIP WIX{{else}}TGZ TXZ{{/if}}
mrdocs-release-package-artifact: release-packages-{{{ lowercase os }}}
Expand Down Expand Up @@ -287,7 +287,7 @@ jobs:
# section, but which depend on paths not known at that point.
- name: Resolved Matrix
id: rmatrix
run: |
run: |
set -euvx

third_party_dir="$(realpath $(pwd)/..)/third-party"
Expand Down Expand Up @@ -534,8 +534,7 @@ jobs:
- name: CMake Workflow
uses: alandefreitas/cpp-actions/cmake-workflow@v1.8.12
env:
# Bump per-test timeout on Windows to avoid CTest default (1500s) killing slow golden suites.
CTEST_TEST_TIMEOUT: ${{ runner.os == 'Windows' && '3600' || '' }}
CTEST_TEST_TIMEOUT: 3600
with:
cmake-version: '>=3.26'
cxxstd: ${{ matrix.cxxstd }}
Expand Down Expand Up @@ -714,6 +713,22 @@ jobs:
contents: write

steps:
# This calculates a bunch of variables, which would normally go in to the regular matrix extra-values
# section, but which depend on paths not known at that point.
- name: Resolved Matrix
id: rmatrix
run: |
set -euvx

third_party_dir="$(realpath $(pwd)/..)/third-party"
if [[ "${{ runner.os }}" == 'Windows' ]]; then
third_party_dir="$(echo "$third_party_dir" | sed 's/\\/\//g; s|^/d/|D:/|')"
fi
echo "third-party-dir=$third_party_dir" >> $GITHUB_OUTPUT

llvm_path="$third_party_dir/llvm"
echo "llvm-path=$llvm_path" >> $GITHUB_OUTPUT

- name: Ensure Node
if: matrix.container != '' && env.ACT == 'true'
run: |
Expand Down Expand Up @@ -756,6 +771,13 @@ jobs:
compiler: ${{ matrix.compiler }}
version: ${{ matrix.version }}

- name: Cached LLVM Binaries
id: llvm-cache
uses: actions/cache@v4
with:
path: ${{ steps.rmatrix.outputs.llvm-path }}
key: ${{ matrix.llvm-archive-basename }}

- name: Download MrDocs package
uses: actions/download-artifact@v4
with:
Expand All @@ -772,13 +794,11 @@ jobs:
# Print tree structure
find packages -print | sed 's;[^/]*/;|____;g;s;____|; |;g'

dest_dir="${{ steps.rmatrix.outputs.llvm-path }}"

if [[ ${{ runner.os }} != 'Windows' ]]; then
dest_dir="$HOME/local"
mkdir -p "$dest_dir"
find packages -maxdepth 1 -name 'MrDocs-*.tar.gz' -exec tar -vxzf {} -C $dest_dir --strip-components=1 \;
else
dest_dir="$GITHUB_WORKSPACE/usr/local"
dest_dir=$(echo "$dest_dir" | sed 's/\\/\//g')
find packages -maxdepth 1 -name "MrDocs-*.7z" -exec 7z x {} -o$dest_dir \;
if [[ $(ls -1 $dest_dir | wc -l) -eq 1 ]]; then
single_dir=$(ls -1 $dest_dir)
Expand Down
22 changes: 8 additions & 14 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,6 @@ if (NOT EXISTS "${LIBCXX_DIR}")
"Please provide a LLVM with libc++ enabled\n")
endif()

set(STDLIB_INCLUDE_DIR "${LLVM_BINARY_DIR}/lib/clang/${Clang_VERSION_MAJOR}/include"
CACHE PATH "Path to the clang headers include directory")
message(STATUS "STDLIB_INCLUDE_DIR: ${STDLIB_INCLUDE_DIR}")
if (NOT EXISTS "${STDLIB_INCLUDE_DIR}")
message(FATAL_ERROR
"STDLIB_INCLUDE_DIR (${STDLIB_INCLUDE_DIR}) does not exist.\n"
"Missing clang headers\n")
endif()

list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}")
include(HandleLLVMOptions)
add_definitions(${LLVM_DEFINITIONS})
Expand Down Expand Up @@ -388,6 +379,7 @@ if (WIN32)
mrdocs-core
PUBLIC
/permissive- # strict C++
/Zc:__cplusplus # report C++ standard support
/W4 # enable all warnings
/MP # multi-processor compilation
/EHs # C++ Exception handling
Expand All @@ -411,6 +403,13 @@ if (MRDOCS_DOCUMENTATION_BUILD)
return()
endif()

# Replicate the clang resource directory structure within our own build,
# so that libclang will find it when executing directly from the build directory.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "bin")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib/clang")
set(RESOURCE_DIR "lib/clang/${Clang_VERSION_MAJOR}")
file(CREATE_LINK "${LLVM_BINARY_DIR}/${RESOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}/${RESOURCE_DIR}" SYMBOLIC)

#-------------------------------------------------
#
# Tool
Expand Down Expand Up @@ -490,7 +489,6 @@ if (MRDOCS_BUILD_TESTS)
"--addons=${CMAKE_SOURCE_DIR}/share/mrdocs/addons"
--generator=${testgenerator}
"--stdlib-includes=${LIBCXX_DIR}"
"--stdlib-includes=${STDLIB_INCLUDE_DIR}"
"--libc-includes=${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs"
--log-level=warn
)
Expand All @@ -505,7 +503,6 @@ if (MRDOCS_BUILD_TESTS)
"--addons=${CMAKE_SOURCE_DIR}/share/mrdocs/addons"
--generator=${testgenerator}
"--stdlib-includes=${LIBCXX_DIR}"
"--stdlib-includes=${STDLIB_INCLUDE_DIR}"
"--libc-includes=${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs"
--log-level=warn
DEPENDS mrdocs-test
Expand Down Expand Up @@ -703,9 +700,6 @@ if (MRDOCS_INSTALL)
install(DIRECTORY ${LIBCXX_DIR}/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/headers/libcxx
FILES_MATCHING PATTERN "*")
install(DIRECTORY ${STDLIB_INCLUDE_DIR}/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/headers/clang
FILES_MATCHING PATTERN "*")
install(DIRECTORY ${CMAKE_SOURCE_DIR}/share/mrdocs/headers/libc-stubs/
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/mrdocs/headers/libc-stubs
FILES_MATCHING PATTERN "*")
Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/usage.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ It's also common for libraries to depend on the C++ standard library, the C stan

That means unless `-nostdinc` is defined, all systems include paths are included. This is what allows the user to also use headers like `<Windows.h>` or `<linux/version.h>` without explicitly including anything else, even though they are not part of the C standard library. This is often seen as a convenience but can lead to portability issues.

In this context, MrDocs provides the `use-system-stdlib` and `use-system-libc` options. Both are set as `false` by default, meaning MrDocs will compile the code as if the `-nostdinc&plus;&plus; -nostdlib&plus;&plus;` and `-nostdinc` flags were passed to Clang. Additionally:
In this context, MrDocs provides the `use-system-stdlib` and `use-system-libc` options. Both are set as `true` by default; setting both to `false` results in MrDocs compiling the code as if the `-nostdinc&plus;&plus; -nostdlib&plus;&plus;` and `-nostdinc` flags were passed to Clang. Additionally:

- When `use-system-stdlib` is `false`, MrDocs will use the bundled libc&plus;&plus; headers available in `<mrdocs-root>/share/mrdocs/headers/libcxx` and `<mrdocs-root>/share/mrdocs/headers/clang`. These paths can be adjusted with the `stdlib-includes` option.
- When `use-system-libc` is `false`, MrDocs will use the bundled libc stubs available in `<mrdocs-root>/share/mrdocs/headers/libc-stubs`. This path can be adjusted with the `libc-includes` option.
Expand Down
7 changes: 3 additions & 4 deletions docs/mrdocs.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,7 @@
},
"stdlib-includes": {
"default": [
"<mrdocs-root>/share/mrdocs/headers/libcxx",
"<mrdocs-root>/share/mrdocs/headers/clang"
"<mrdocs-root>/share/mrdocs/headers/libcxx"
],
"description": "When `use-system-stdlib` is disabled, the C++ standard library headers are available in these paths.",
"items": {
Expand Down Expand Up @@ -602,7 +601,7 @@
"type": "string"
},
"use-system-libc": {
"default": false,
"default": true,
"description": "To achieve reproducible results, MrDocs bundles the LibC headers with its definitions. To use the C standard library available in the system instead, set this option to true.",
"enum": [
true,
Expand All @@ -612,7 +611,7 @@
"type": "boolean"
},
"use-system-stdlib": {
"default": false,
"default": true,
"description": "To achieve reproducible results, MrDocs bundles the LibC++ headers. To use the C++ standard library available in the system instead, set this option to true.",
"enum": [
true,
Expand Down
1 change: 0 additions & 1 deletion docs/website/snippets/sqrt.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <type_traits>
#include <stdexcept>

/** Computes the square root of an integral value.

Expand Down
8 changes: 6 additions & 2 deletions include/mrdocs/Support/Concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,12 @@ concept range_of_tuple_like =
std::ranges::range<Range> && tuple_like<std::ranges::range_value_t<Range>>;

#ifdef __cpp_lib_reference_from_temporary
using std::reference_constructs_from_temporary_v;
using std::reference_converts_from_temporary_v;
/** True when binding `To` from `From` would require a temporary conversion.
*/
using std::reference_constructs_from_temporary_v;
/** Like `reference_converts_from_temporary_v`, but for construction.
*/
using std::reference_converts_from_temporary_v;
#else
/** True when binding `To` from `From` would require a temporary conversion.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2379,7 +2379,8 @@ extractSFINAEInfo(clang::QualType const T)
Result.Type = resultType->getAsType();
for (std::size_t I = 0; I < Args.size(); ++I)
{
if (SFINAEControl->ControllingParams[I])
if (I < SFINAEControl->ControllingParams.size()
&& SFINAEControl->ControllingParams[I])
{
MRDOCS_SYMBOL_TRACE(Args[I], context_);
clang::TemplateArgument ArgsI = Args[I];
Expand Down
2 changes: 1 addition & 1 deletion src/lib/AST/ExtractDocComment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ class DocCommentVisitor
auto compsExp = parseHTMLStartSpan(C, cur);
if (!compsExp)
{
report::error(
report::warn(
"{} at {} ({})",
compsExp.error().message(),
filename,
Expand Down
7 changes: 3 additions & 4 deletions src/lib/ConfigOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -528,16 +528,15 @@
"brief": "Use the system C++ standard library",
"details": "To achieve reproducible results, MrDocs bundles the LibC++ headers. To use the C++ standard library available in the system instead, set this option to true.",
"type": "bool",
"default": false
"default": true
},
{
"name": "stdlib-includes",
"brief": "C++ Standard Library include paths",
"details": "When `use-system-stdlib` is disabled, the C++ standard library headers are available in these paths.",
"type": "list<path>",
"default": [
"<mrdocs-root>/share/mrdocs/headers/libcxx",
"<mrdocs-root>/share/mrdocs/headers/clang"
"<mrdocs-root>/share/mrdocs/headers/libcxx"
],
"relative-to": "<config-dir>",
"must-exist": false,
Expand All @@ -548,7 +547,7 @@
"brief": "Use the system C standard library",
"details": "To achieve reproducible results, MrDocs bundles the LibC headers with its definitions. To use the C standard library available in the system instead, set this option to true.",
"type": "bool",
"default": false
"default": true
},
{
"name": "libc-includes",
Expand Down
9 changes: 6 additions & 3 deletions src/lib/MrDocsCompilationDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,10 @@ adjustCommandLine(
cmdLineCStrs.data(),
cmdLineCStrs.data() + cmdLineCStrs.size());

auto const systemIncludeFlag = is_clang_cl ? "-external:I" : "-isystem";
char const* systemIncludeFlag = is_clang_cl ? "-external:I" : "-isystem";
// FIXME: No CL equivalent, but not really needed there?
char const* afterIncludeFlag = is_clang_cl ? "-external:I" : "-idirafter";


// ------------------------------------------------------
// Supress all warnings
Expand Down Expand Up @@ -406,10 +409,10 @@ adjustCommandLine(

if (!(*config)->useSystemLibc)
{
new_cmdline.emplace_back("-nostdinc");
new_cmdline.emplace_back(is_clang_cl ? "-X" : "-nostdlibinc");
for (auto const& inc : (*config)->libcIncludes)
{
new_cmdline.emplace_back(systemIncludeFlag);
new_cmdline.emplace_back(afterIncludeFlag);
new_cmdline.emplace_back(inc);
}
}
Expand Down
8 changes: 5 additions & 3 deletions src/lib/MrDocsSettingsDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "MrDocsSettingsDB.hpp"
#include <mrdocs/Support/Path.hpp>
#include <llvm/Support/Program.h>


namespace mrdocs {
Expand Down Expand Up @@ -60,17 +61,18 @@ MrDocsSettingsDB::MrDocsSettingsDB(ConfigImpl const& config)
});
}

llvm::ErrorOr<std::string> clangPath = llvm::sys::findProgramByName(
"clang");

for (auto const& pathName: sourceFiles)
{
// auto fileName = files::getFileName(pathName);
auto parentDir = files::getParentDir(pathName);

std::vector<std::string> cmds;
cmds.emplace_back("clang");
cmds.emplace_back(clangPath ? *clangPath : "clang");
cmds.emplace_back("-fsyntax-only");
cmds.emplace_back("-std=c++23");
cmds.emplace_back("-pedantic-errors");
cmds.emplace_back("-Werror");
cmds.emplace_back("-x");
cmds.emplace_back("c++");
cmds.emplace_back(pathName);
Expand Down
7 changes: 6 additions & 1 deletion src/test/TestRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,16 @@ handleFile(
auto runWith = [&](std::vector<std::string> command)
{
auto const db = makeSingleFileDB(filePath, std::move(command));
std::unordered_map<std::string, std::vector<std::string>>
defaultIncludePaths = {
{ "clang", { MRDOCS_TEST_FILES_DIR "/include" } },
{ "clang-cl", { MRDOCS_TEST_FILES_DIR "/include" } },
};
MrDocsCompilationDatabase compilations(
llvm::StringRef(files::getParentDir(filePath)),
db,
config,
std::unordered_map<std::string, std::vector<std::string>>{});
defaultIncludePaths);
handleCompilationDatabase(filePath, compilations, config, layout);
};

Expand Down
6 changes: 3 additions & 3 deletions src/test/lib/MrDocsCompilationDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ struct MrDocsCompilationDatabase_test {
config->settings_.libcIncludes.push_back("libc-path");

auto adjusted = adjustCompileCommand({ programName }, config);
BOOST_TEST(has(adjusted, "-nostdinc"));
BOOST_TEST(has(adjusted, { "-isystem", "libc-path" }));
BOOST_TEST(has(adjusted, "-nostdlibinc"));
BOOST_TEST(has(adjusted, { "-idirafter", "libc-path" }));
}
}

Expand Down Expand Up @@ -302,7 +302,7 @@ struct MrDocsCompilationDatabase_test {
config->settings_.libcIncludes.push_back("libc-path");

auto adjusted = adjustCompileCommand({ programName }, config);
BOOST_TEST(has(adjusted, "-nostdinc"));
BOOST_TEST(has(adjusted, "-X"));
BOOST_TEST(has(adjusted, { "-external:I", "libc-path" }));
}
}
Expand Down
3 changes: 1 addition & 2 deletions test-files/golden-tests/config/sfinae/redeclare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,4 @@ void f(std::enable_if_t<std::is_class_v<T>>);

template <typename T>
void f(std::enable_if_t<std::is_class_v<T>>)
{
}
{}
2 changes: 2 additions & 0 deletions test-files/golden-tests/config/sfinae/redeclare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
warn-if-doc-error: false
warn-no-paramdoc: false
2 changes: 2 additions & 0 deletions test-files/golden-tests/config/sfinae/return-based.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
warn-if-doc-error: false
warn-no-paramdoc: false
2 changes: 2 additions & 0 deletions test-files/golden-tests/core/libcxx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
use-system-stdlib: false
use-system-libc: false
1 change: 0 additions & 1 deletion test-files/golden-tests/snippets/sqrt.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <type_traits>
#include <stdexcept>

/** Computes the square root of an integral value.

Expand Down
2 changes: 1 addition & 1 deletion test-files/golden-tests/snippets/sqrt.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<template>
<tparam name="T" class="type"/>
<function name="sqrt" requires="std::is_integral_v&lt;T&gt;" id="Ys2WHtLDVIke+oa2xBB2ekE+xds=">
<file short-path="sqrt.cpp" source-path="sqrt.cpp" line="15" class="def"/>
<file short-path="sqrt.cpp" source-path="sqrt.cpp" line="14" class="def"/>
<return>
<type name="T"/>
</return>
Expand Down
2 changes: 2 additions & 0 deletions test-files/golden-tests/snippets/sqrt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
warn-if-doc-error: false
warn-no-paramdoc: false
1 change: 0 additions & 1 deletion test-files/golden-tests/symbols/function/sfinae.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <type_traits>
#include <stdexcept>

/// Enabled via return type
template <class T>
Expand Down
Loading
Loading