Skip to content
Merged
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
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/config-file.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ The rules for whitelisting symbols (`include-symbols`, `implementation-defined`,
4. The symbol is a child of a literal pattern representing a namespace.
** For instance, the literal pattern `std` matches `std::filesystem::path::iterator` because `std` is a literal pattern matching a namespace. In other words, these literal patterns represent the namespace and its subnamespaces as if the pattern were `std::**`.

For exclusion rules, the symbol must strictly match the pattern to be excluded.
For exclusion rules, the symbol must strictly match the pattern to be excluded. If a scope is escaped by a pattern, all symbols in that scope are also excluded.

[#config-options-reference]
== Reference
Expand Down
6 changes: 3 additions & 3 deletions docs/mrdocs.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,12 @@
},
"inherit-base-members": {
"default": "copy-dependencies",
"description": "Determine how derived classes inherit members of base classes. When set to `never`, derived classes do not inherit members of base classes and only the relationship is stored. When set to `reference`, derived classes list members of base classes but references are still linked to the base class. When set to `copy`, a copy is created for each base symbol as if it was declared in the derived class. If the base class is a dependency, the extraction mode is copied from the new parent. When set to `copy-dependencies`, a reference is created by default and a copy is created when the base class is a dependency.",
"description": "Determine how derived classes inherit members of base classes. When set to `never`, derived classes do not inherit members of base classes and only the relationship is stored. When set to `reference`, derived classes list members of base classes but references are still linked to the base class. When set to `copy-dependencies`, a reference is created by default and a copy is created when the base class is a dependency. When set to `copy-all`, a copy is created for each base symbol as if it was declared in the derived class. If the base class is a dependency, the extraction mode is copied from the new parent.",
"enum": [
"never",
"reference",
"copy",
"copy-dependencies"
"copy-dependencies",
"copy-all"
],
"title": "Determine how derived classes inherit base members"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{{/unless}}{{>type/declarator type decl-name=name~}}
{{#if default}} = {{default}}{{/if~}}
{{#unless @last}},{{/unless~}}
{{/each~}}{{#if isVariadic}}{{#if params}}, {{/if}}...{{/if}})
{{/each~}}{{#if isVariadic}}{{#if params}}, {{/if}}{{ str "..." }}{{/if}})
{{~#if isConst}} const{{/if~}}
{{#if isVolatile}} volatile{{/if~}}
{{#if refQualifier}} {{refQualifier}}{{/if~}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
{{> symbol/signature member link=member}}
{{/markup/code-block}}

{{#> markup/span class="small" }}{{#> markup/a href=member.url }}{{#>markup/em }}» more...{{/markup/em}}{{/markup/a}}{{/markup/span}}
{{#> markup/span class="small" }}{{#> markup/a href=member.url }}{{#>markup/em }}» more{{ str "..." }}{{/markup/em}}{{/markup/a}}{{/markup/span}}

{{/each}}
{{/if}}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
{{#if (and template (not nolink))}}{{#>markup/a href=template.url}}{{name}}{{/markup/a}}{{else~}}{{name~}}{{/if~}}
{{/if~}}
{{~#if is-pack~}}
...
{{ str "..." }}
{{~/if~}}
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
--}}
{{#if (eq kind "type")~}}
{{#if constraint}}{{>symbol/name-info constraint }}{{else}}{{key}}{{/if~}}
{{#if is-pack}}...{{/if~}}
{{#if is-pack}}{{ str "..." }}{{/if~}}
{{#if name}} {{name}}{{/if~}}
{{#if default}} = {{>template/arg default~}}{{/if~}}
{{else if (eq kind "non-type")~}}
{{>type/declarator type decl-name=name}}{{#if is-pack}}...{{/if~}}
{{>type/declarator type decl-name=name}}{{#if is-pack}}{{ str "..." }}{{/if~}}
{{#if default}} = {{>template/arg default~}}{{/if~}}
{{else if (eq kind "template")~}}
{{>template/head}} typename{{#if is-pack}}...{{/if~}}
{{>template/head}} typename{{#if is-pack}}{{ str "..." }}{{/if~}}
{{#if name}} {{name}}{{/if~}}
{{#if default}} = {{>template/arg default~}}{{/if~}}
{{/if}}
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,5 @@
{{~/if~}}
{{#if is-pack~}}
{{! Pack declarator prefix includes the ellipsis ~}}
...
{{ str "..." }}
{{~/if}}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
{{~#unless @last}}, {{/unless~}}
{{/each~}}
{{! Include final "..." for variadic functions ~}}
{{#if is-variadic}}{{#if param-types}}, {{/if}}...{{/if}}){{!~}}
{{#if is-variadic}}{{#if param-types}}, {{/if}}{{ str "..." }}{{/if}}){{!~}}
{{! cv-qualifiers as literal strings ~}}
{{~#if cv-qualifiers}} {{cv-qualifiers}}{{/if~}}
{{! Refqualifiers as "&" or "&&" ~}}
Expand Down
29 changes: 23 additions & 6 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2821,12 +2821,29 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)

// We should check the exclusion filters first. If a symbol is
// explicitly excluded, there's nothing else to check.
if (!config_->excludeSymbols.empty() &&
checkSymbolFiltersImpl<Strict>(config_->excludeSymbols, symbolName))
if (!config_->excludeSymbols.empty())
{
ExtractionInfo const res{ExtractionMode::Dependency, ExtractionMatchType::Strict};
updateCache(res);
return res;
if (checkSymbolFiltersImpl<Strict>(config_->excludeSymbols, symbolName))
{
ExtractionInfo const res{ExtractionMode::Dependency, ExtractionMatchType::Strict};
updateCache(res);
return res;
}
// If the parent scope is excluded, the symbol should also be excluded
// since it would not be possible to refer to this member.
if (AllowParent)
{
if (Decl const* P = getParent(D))
{
if (auto const [mode, kind] = checkSymbolFilters(P);
mode == ExtractionMode::Dependency)
{
ExtractionInfo const res = {mode, ExtractionMatchType::StrictParent};
updateCache(res);
return res;
}
}
}
}

// If not excluded, we should check the filters in this order:
Expand Down Expand Up @@ -2923,7 +2940,7 @@ checkSymbolFilters(Decl const* D, bool const AllowParent)
// prefixes that can potentially include children, but
// we have to check if any children actually matches
// the pattern strictly.
DeclContext const* DC = cast<DeclContext>(D);
auto const* DC = cast<DeclContext>(D);
auto childrenMode = ExtractionMode::Dependency;
for (auto* M : DC->decls())
{
Expand Down
6 changes: 3 additions & 3 deletions src/lib/Lib/ConfigOptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,13 @@
{
"name": "inherit-base-members",
"brief": "Determine how derived classes inherit base members",
"details": "Determine how derived classes inherit members of base classes. When set to `never`, derived classes do not inherit members of base classes and only the relationship is stored. When set to `reference`, derived classes list members of base classes but references are still linked to the base class. When set to `copy`, a copy is created for each base symbol as if it was declared in the derived class. If the base class is a dependency, the extraction mode is copied from the new parent. When set to `copy-dependencies`, a reference is created by default and a copy is created when the base class is a dependency.",
"details": "Determine how derived classes inherit members of base classes. When set to `never`, derived classes do not inherit members of base classes and only the relationship is stored. When set to `reference`, derived classes list members of base classes but references are still linked to the base class. When set to `copy-dependencies`, a reference is created by default and a copy is created when the base class is a dependency. When set to `copy-all`, a copy is created for each base symbol as if it was declared in the derived class. If the base class is a dependency, the extraction mode is copied from the new parent.",
"type": "enum",
"values": [
"never",
"reference",
"copy",
"copy-dependencies"
"copy-dependencies",
"copy-all"
],
"default": "copy-dependencies"
},
Expand Down
31 changes: 24 additions & 7 deletions src/lib/Metadata/Finalizers/BaseMembersFinalizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ inheritBaseMembers(
inheritBaseMembers(derivedId, derived.Friends, base.Friends);
}

namespace {
bool
shouldCopy(Config const& config, Info const& M)
{

if (config->inheritBaseMembers == PublicSettings::BaseMemberInheritance::CopyDependencies)
{
return M.Extraction == ExtractionMode::Dependency;
}
return config->inheritBaseMembers == PublicSettings::BaseMemberInheritance::CopyAll;
}
}

void
BaseMembersFinalizer::
inheritBaseMembers(
Expand Down Expand Up @@ -122,15 +135,19 @@ inheritBaseMembers(
});
MRDOCS_CHECK_OR_CONTINUE(shadowIt == derived.end());

bool const copyMember =
config_->inheritBaseMembers == PublicSettings::BaseMemberInheritance::CopyDependencies ?
otherInfo.Extraction == ExtractionMode::Dependency :
config_->inheritBaseMembers == PublicSettings::BaseMemberInheritance::Copy;

// Not a shadow, so inherit the base member
if (!copyMember)
if (!shouldCopy(config_, otherInfo))
{
derived.push_back(otherID);
// When it's a dependency, we don't create a reference to
// the member because the reference would be invalid.
// The user can use `copy-dependencies` or `copy` to
// copy the dependencies.
// There could be another option that forces the symbol
// extraction mode to be regular, but that is controversial.
if (otherInfo.Extraction != ExtractionMode::Dependency)
{
derived.push_back(otherID);
}
}
else
{
Expand Down
6 changes: 6 additions & 0 deletions src/test/TestMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ int test_main(int argc, char const** argv)
return EXIT_SUCCESS;
}

#ifdef _NDEBUG
static void reportUnhandledException(
std::exception const& ex)
{
Expand All @@ -126,12 +127,16 @@ static void reportUnhandledException(
report::error("Unhandled exception: {}\n", ex.what());
sys::PrintStackTrace(llvm::errs());
}
#endif

} // mrdocs
} // clang

int main(int argc, char const** argv)
{
#ifndef _NDEBUG
return clang::mrdocs::test_main(argc, argv);
#else
try
{
return clang::mrdocs::test_main(argc, argv);
Expand All @@ -146,4 +151,5 @@ int main(int argc, char const** argv)
clang::mrdocs::reportUnhandledException(ex);
}
return EXIT_FAILURE;
#endif
}
10 changes: 6 additions & 4 deletions src/test/TestRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,10 @@ handleDir(
entry.type() == fs::file_type::directory_file)
{
// Check for a subdirectory-wide config
auto const& subdir = entry.path();
Config::Settings subdirSettings = dirSettings;
std::string const& configPath = files::appendPath(entry.path(), "mrdocs.yml");
subdirSettings.sourceRoot = subdir;
std::string const& configPath = files::appendPath(subdir, "mrdocs.yml");
if (files::exists(configPath))
{
if (auto exp = Config::Settings::load_file(subdirSettings, configPath, dirs_); !exp)
Expand All @@ -290,7 +292,7 @@ handleDir(
return report::error("Failed to normalize config file: {}: \"{}\"", exp.error(), configPath);
}
}
handleDir(entry.path(), subdirSettings);
handleDir(subdir, subdirSettings);
}
else if(
entry.type() == fs::file_type::regular_file &&
Expand Down Expand Up @@ -337,9 +339,9 @@ checkPath(
Config::Settings dirSettings;
testArgs.apply(dirSettings, dirs_, argv);
dirSettings.multipage = false;
dirSettings.sourceRoot = files::appendPath(inputPath, ".");

dirSettings.sourceRoot = inputDir;
std::string const& configPath = files::appendPath(inputDir, "mrdocs.yml");

if (files::exists(configPath))
{
if (auto exp = Config::Settings::load_file(dirSettings, configPath, dirs_); !exp)
Expand Down
30 changes: 18 additions & 12 deletions src/tool/ToolMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ mrdocs_main(int argc, char const** argv)
return EXIT_SUCCESS;
}

#ifdef _NDEBUG
static
void
reportUnhandledException(
Expand All @@ -163,24 +164,29 @@ reportUnhandledException(
report::fatal("Unhandled exception: {}\n", ex.what());
sys::PrintStackTrace(llvm::errs());
}
#endif

} // clang::mrdocs

int
main(int argc, char const** argv)
{
// try
// {
#ifndef _NDEBUG
return clang::mrdocs::mrdocs_main(argc, argv);
#else
try
{
return clang::mrdocs::mrdocs_main(argc, argv);
// }
// catch(clang::mrdocs::Exception const& ex)
// {
}
catch(clang::mrdocs::Exception const& ex)
{
// Thrown Exception should never get here.
// clang::mrdocs::reportUnhandledException(ex);
// }
// catch(std::exception const& ex)
// {
// clang::mrdocs::reportUnhandledException(ex);
// }
// return EXIT_FAILURE;
clang::mrdocs::reportUnhandledException(ex);
}
catch(std::exception const& ex)
{
clang::mrdocs::reportUnhandledException(ex);
}
return EXIT_FAILURE;
#endif
}
Loading