├── .clang-format
├── .github
├── issue_template.md
└── workflows
│ └── ci.yml
├── CMakeLists.txt
├── LICENSE.md
├── README.md
├── cmake
└── CodeCoverage.cmake
├── example
├── CMakeLists.txt
├── README.md
├── ast_printer.cpp
├── comparison.cpp
├── documentation_generator.cpp
├── enum_category.cpp
├── enum_to_string.cpp
├── example_parser.hpp
└── serialization.cpp
├── external
├── external.cmake
└── tpl
│ ├── CMakeLists.txt
│ ├── process.cpp
│ ├── process.hpp
│ ├── process_unix.cpp
│ └── process_win.cpp
├── include
└── cppast
│ ├── code_generator.hpp
│ ├── compile_config.hpp
│ ├── cpp_alias_template.hpp
│ ├── cpp_array_type.hpp
│ ├── cpp_attribute.hpp
│ ├── cpp_class.hpp
│ ├── cpp_class_template.hpp
│ ├── cpp_concept.hpp
│ ├── cpp_decltype_type.hpp
│ ├── cpp_entity.hpp
│ ├── cpp_entity_container.hpp
│ ├── cpp_entity_index.hpp
│ ├── cpp_entity_kind.hpp
│ ├── cpp_entity_ref.hpp
│ ├── cpp_enum.hpp
│ ├── cpp_expression.hpp
│ ├── cpp_file.hpp
│ ├── cpp_forward_declarable.hpp
│ ├── cpp_friend.hpp
│ ├── cpp_function.hpp
│ ├── cpp_function_template.hpp
│ ├── cpp_function_type.hpp
│ ├── cpp_language_linkage.hpp
│ ├── cpp_member_function.hpp
│ ├── cpp_member_variable.hpp
│ ├── cpp_namespace.hpp
│ ├── cpp_preprocessor.hpp
│ ├── cpp_static_assert.hpp
│ ├── cpp_storage_class_specifiers.hpp
│ ├── cpp_template.hpp
│ ├── cpp_template_parameter.hpp
│ ├── cpp_token.hpp
│ ├── cpp_type.hpp
│ ├── cpp_type_alias.hpp
│ ├── cpp_variable.hpp
│ ├── cpp_variable_base.hpp
│ ├── cpp_variable_template.hpp
│ ├── cppast_fwd.hpp
│ ├── detail
│ ├── assert.hpp
│ └── intrusive_list.hpp
│ ├── diagnostic.hpp
│ ├── diagnostic_logger.hpp
│ ├── libclang_parser.hpp
│ ├── parser.hpp
│ └── visitor.hpp
├── src
├── CMakeLists.txt
├── code_generator.cpp
├── cpp_alias_template.cpp
├── cpp_attribute.cpp
├── cpp_class.cpp
├── cpp_class_template.cpp
├── cpp_concept.cpp
├── cpp_entity.cpp
├── cpp_entity_index.cpp
├── cpp_entity_kind.cpp
├── cpp_enum.cpp
├── cpp_expression.cpp
├── cpp_file.cpp
├── cpp_forward_declarable.cpp
├── cpp_friend.cpp
├── cpp_function.cpp
├── cpp_function_template.cpp
├── cpp_language_linkage.cpp
├── cpp_member_function.cpp
├── cpp_member_variable.cpp
├── cpp_namespace.cpp
├── cpp_preprocessor.cpp
├── cpp_static_assert.cpp
├── cpp_template_parameter.cpp
├── cpp_token.cpp
├── cpp_type.cpp
├── cpp_type_alias.cpp
├── cpp_variable.cpp
├── cpp_variable_template.cpp
├── diagnostic_logger.cpp
├── libclang
│ ├── class_parser.cpp
│ ├── concept_parser.cpp
│ ├── cxtokenizer.cpp
│ ├── cxtokenizer.hpp
│ ├── debug_helper.cpp
│ ├── debug_helper.hpp
│ ├── enum_parser.cpp
│ ├── expression_parser.cpp
│ ├── friend_parser.cpp
│ ├── function_parser.cpp
│ ├── language_linkage_parser.cpp
│ ├── libclang_parser.cpp
│ ├── libclang_visitor.hpp
│ ├── namespace_parser.cpp
│ ├── parse_error.hpp
│ ├── parse_functions.cpp
│ ├── parse_functions.hpp
│ ├── preprocessor.cpp
│ ├── preprocessor.hpp
│ ├── raii_wrapper.hpp
│ ├── template_parser.cpp
│ ├── type_parser.cpp
│ └── variable_parser.cpp
└── visitor.cpp
├── test
├── CMakeLists.txt
├── code_generator.cpp
├── cpp_alias_template.cpp
├── cpp_attribute.cpp
├── cpp_class.cpp
├── cpp_class_template.cpp
├── cpp_concept.cpp
├── cpp_enum.cpp
├── cpp_friend.cpp
├── cpp_function.cpp
├── cpp_function_template.cpp
├── cpp_language_linkage.cpp
├── cpp_member_function.cpp
├── cpp_member_variable.cpp
├── cpp_namespace.cpp
├── cpp_preprocessor.cpp
├── cpp_static_assert.cpp
├── cpp_template_parameter.cpp
├── cpp_token.cpp
├── cpp_type_alias.cpp
├── cpp_variable.cpp
├── integration.cpp
├── libclang_parser.cpp
├── parser.cpp
├── preprocessor.cpp
├── test.cpp
├── test_parser.hpp
└── visitor.cpp
└── tool
├── CMakeLists.txt
└── main.cpp
/.clang-format:
--------------------------------------------------------------------------------
1 | AccessModifierOffset: -4
2 | AlignAfterOpenBracket: Align
3 | AlignConsecutiveAssignments: true
4 | AlignConsecutiveDeclarations: true
5 | AlignEscapedNewlinesLeft: Right
6 | AlignOperands: true
7 | AlignTrailingComments: true
8 | AllowAllParametersOfDeclarationOnNextLine: false
9 | AllowShortBlocksOnASingleLine: false
10 | AllowShortCaseLabelsOnASingleLine: false
11 | AllowShortFunctionsOnASingleLine: Empty
12 | AllowShortIfStatementsOnASingleLine: false
13 | AllowShortLoopsOnASingleLine: false
14 | AlwaysBreakAfterReturnType: None
15 | AlwaysBreakBeforeMultilineStrings: false
16 | AlwaysBreakTemplateDeclarations: true
17 | BinPackArguments: true
18 | BinPackParameters: true
19 | BreakBeforeBraces: Custom
20 | BraceWrapping:
21 | AfterClass: true
22 | AfterControlStatement: true
23 | AfterEnum: true
24 | AfterFunction: true
25 | AfterNamespace: true
26 | AfterStruct: true
27 | AfterUnion: true
28 | AfterExternBlock: true
29 | BeforeCatch: true
30 | BeforeElse: true
31 | SplitEmptyFunction: false
32 | SplitEmptyRecord: false
33 | SplitEmptyNamespace: false
34 | BreakBeforeBinaryOperators: All
35 | BreakBeforeTernaryOperators: true
36 | BreakConstructorInitializers: BeforeColon
37 | BreakStringLiterals: false
38 | ColumnLimit: 100
39 | CompactNamespaces: true
40 | ConstructorInitializerAllOnOneLineOrOnePerLine: false
41 | ConstructorInitializerIndentWidth: 0
42 | ContinuationIndentWidth: 4
43 | Cpp11BracedListStyle: true
44 | DerivePointerAlignment: false
45 | FixNamespaceComments: true
46 | IncludeBlocks: Preserve
47 | IndentCaseLabels: false
48 | IndentPPDirectives: AfterHash
49 | IndentWidth: 4
50 | IndentWrappedFunctionNames: true
51 | KeepEmptyLinesAtTheStartOfBlocks: false
52 | Language: Cpp
53 | MaxEmptyLinesToKeep: 1
54 | NamespaceIndentation: Inner
55 | PenaltyBreakBeforeFirstCallParameter: 19937
56 | PenaltyReturnTypeOnItsOwnLine: 19937
57 | PointerAlignment: Left
58 | ReflowComments: true
59 | SortIncludes: true
60 | SortUsingDeclarations: true
61 | SpaceAfterCStyleCast: false
62 | SpaceAfterTemplateKeyword: true
63 | SpaceBeforeAssignmentOperators: true
64 | SpaceBeforeParens: ControlStatements
65 | SpaceInEmptyParentheses: false
66 | SpacesBeforeTrailingComments: 1
67 | SpacesInAngles: false
68 | SpacesInCStyleCastParentheses: false
69 | SpacesInParentheses: false
70 | SpacesInSquareBrackets: false
71 | Standard: Cpp11
72 | TabWidth: 4
73 | UseTab: Never
74 |
--------------------------------------------------------------------------------
/.github/issue_template.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | * cppast version:
4 | * parser: `libclang_parser`
5 | * clang version:
6 |
7 | Explanation of the error.
8 |
9 | Input:
10 |
11 | ```cpp
12 | Minimal source code reproducing the error
13 | ```
14 |
15 | Input flags:
16 |
17 | Output:
18 |
19 |
20 |
21 | ```
22 | Output of `cppast -v `
23 | ```
24 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | # Here we're keeping on arbitrary LLVM version fixed and varying GCC.
6 | linux-gcc:
7 | strategy:
8 | fail-fast: false
9 | matrix:
10 | image:
11 | # List: https://github.com/conan-io/conan-docker-tools
12 | - gcc10
13 | - gcc9
14 | - gcc8
15 | - gcc7
16 | - gcc6
17 |
18 | runs-on: ubuntu-latest
19 | container:
20 | image: conanio/${{matrix.image}}
21 | options: --user root
22 |
23 | steps:
24 | - uses: actions/checkout@v2
25 | - name: Create Build Environment
26 | run: cmake -E make_directory build
27 | - name: Install libclang
28 | run: apt-get -qq update && apt-get install -y llvm clang libclang-dev
29 | - name: Install ninja
30 | run: type ninja || apt-get install -y ninja-build
31 |
32 | - name: Configure
33 | working-directory: build/
34 | run: cmake -GNinja $GITHUB_WORKSPACE
35 | - name: Build
36 | working-directory: build/
37 | run: cmake --build .
38 | - name: Test
39 | working-directory: build/
40 | run: ctest --output-on-failure
41 |
42 | # Here we're varying the LLVM version and using its clang for compiling as well.
43 | linux-clang:
44 | strategy:
45 | fail-fast: false
46 | matrix:
47 | version: [7, 8, 9, 10]
48 |
49 | runs-on: ubuntu-latest
50 | container:
51 | # Just one of the newer images.
52 | image: conanio/gcc10
53 | options: --user root
54 |
55 | steps:
56 | - uses: actions/checkout@v2
57 | - name: Create Build Environment
58 | run: cmake -E make_directory build
59 | - name: Install libclang
60 | run: apt-get -qq update && apt-get install -y llvm-${{matrix.version}} clang-${{matrix.version}} libclang-${{matrix.version}}-dev
61 | - name: Install ninja
62 | run: type ninja || apt-get install -y ninja-build
63 |
64 | - name: Configure
65 | working-directory: build/
66 | run: cmake -GNinja $GITHUB_WORKSPACE -DCMAKE_CXX_COMPILER=clang++-${{matrix.version}}
67 | - name: Build
68 | working-directory: build/
69 | run: cmake --build .
70 | - name: Test
71 | working-directory: build/
72 | run: ctest --output-on-failure
73 |
74 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | # SPDX-License-Identifier: MIT
3 | # found in the top-level directory of this distribution.
4 |
5 | cmake_minimum_required(VERSION 3.11)
6 | project(cppast VERSION 0.1.0)
7 |
8 | if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
9 | set(is_top_level_project TRUE)
10 | else()
11 | set(is_top_level_project FALSE)
12 | endif()
13 |
14 | # options
15 | option(CPPAST_BUILD_TEST "whether or not to build the tests" OFF)
16 | option(CPPAST_BUILD_EXAMPLE "whether or not to build the examples" OFF)
17 | option(CPPAST_BUILD_TOOL "whether or not to build the tool" OFF)
18 |
19 | if(${CPPAST_BUILD_TEST} OR ${is_top_level_project})
20 | set(build_test ON)
21 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # for the self integration test
22 | else()
23 | set(build_test OFF)
24 | endif()
25 |
26 | if(${CPPAST_BUILD_EXAMPLE} OR ${is_top_level_project})
27 | set(build_example ON)
28 | else()
29 | set(build_example OFF)
30 | endif()
31 |
32 | if(${CPPAST_BUILD_TOOL} OR ${is_top_level_project})
33 | set(build_tool ON)
34 | else()
35 | set(build_tool OFF)
36 | endif()
37 |
38 | include(external/external.cmake)
39 |
40 | if(build_test AND CPPAST_TEST_GCOV AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
41 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
42 | include(CodeCoverage)
43 | APPEND_COVERAGE_COMPILER_FLAGS()
44 | endif()
45 |
46 | add_subdirectory(src)
47 |
48 | if(${build_test})
49 | enable_testing()
50 | add_subdirectory(test)
51 | endif()
52 | if(${build_example})
53 | add_subdirectory(example)
54 | endif()
55 | if(${build_tool})
56 | add_subdirectory(tool)
57 | endif()
58 |
--------------------------------------------------------------------------------
/example/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | # SPDX-License-Identifier: MIT
3 | # found in the top-level directory of this distribution.
4 |
5 | function(_cppast_example name)
6 | add_executable(cppast_example_${name} ${name}.cpp example_parser.hpp)
7 | target_link_libraries(cppast_example_${name} PUBLIC cppast)
8 | endfunction()
9 |
10 | _cppast_example(ast_printer)
11 | _cppast_example(comparison)
12 | _cppast_example(documentation_generator)
13 | _cppast_example(enum_category)
14 | _cppast_example(enum_to_string)
15 | _cppast_example(serialization)
16 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | # cppast - examples
2 |
3 | This directory contains example tools written using cppast.
4 |
5 | ***Note:** These are not meant to be production ready tools, just a proof of concept!*
6 |
7 | All example executables get a single parameter,
8 | which is the directory where a `compile_commands.json` file is located.
9 | This file is a compilation database, you can read more about it [here](https://clang.llvm.org/docs/JSONCompilationDatabase.html).
10 | CMake, for example, can generate on when the option `CMAKE_EXPORT_COMPILE_COMMANDS` is `ON`.
11 |
12 | The tools will parse each file in the database and process it.
13 | Output will be written to `stdout`.
14 |
15 | ## List of examples:
16 |
17 | ### `ast_printer.cpp`
18 |
19 | It is a very simplified implementation of the cppast tool, it will print an AST.
20 | This is the starting example, it showcases entity visitation.
21 |
22 | ### `documentation_generator.cpp`
23 |
24 | It is a very simplified documentation generator.
25 | This showcases usage of the `cppast::code_generator`.
26 |
27 | ### Attributes example
28 |
29 | * `comparison.cpp`
30 | * `documentation_generator.cpp`
31 | * `enum_category.cpp`
32 | * `enum_to_string.cpp`
33 | * `serialization.cpp`
34 |
35 | Those examples were created as a part of my talk [Fun With (User-Defined) Attributes](http://foonathan.net/meetingcpp2017.html).
36 | Check the talk video to learn more about them.
37 |
--------------------------------------------------------------------------------
/example/ast_printer.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | /// \file
5 | /// This is a very primitive version of the cppast tool.
6 | ///
7 | /// Given an input file it will print the AST.
8 |
9 | #include // visit()
10 |
11 | #include "example_parser.hpp"
12 |
13 | void print_ast(const cppast::cpp_file& file)
14 | {
15 | std::string prefix;
16 | // visit each entity in the file
17 | cppast::visit(file, [&](const cppast::cpp_entity& e, cppast::visitor_info info) {
18 | if (info.event == cppast::visitor_info::container_entity_exit) // exiting an old container
19 | prefix.pop_back();
20 | else if (info.event == cppast::visitor_info::container_entity_enter)
21 | // entering a new container
22 | {
23 | std::cout << prefix << "'" << e.name() << "' - " << cppast::to_string(e.kind()) << '\n';
24 | prefix += "\t";
25 | }
26 | else // if (info.event == cppast::visitor_info::leaf_entity) // a non-container entity
27 | std::cout << prefix << "'" << e.name() << "' - " << cppast::to_string(e.kind()) << '\n';
28 | });
29 | }
30 |
31 | int main(int argc, char* argv[])
32 | {
33 | return example_main(argc, argv, {}, &print_ast);
34 | }
35 |
--------------------------------------------------------------------------------
/example/comparison.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | /// \file
5 | /// Generate equality comparisons.
6 | ///
7 | /// Given an input file, it will generate comparison operators for each class that has the
8 | /// [[generate::comparison]] attribute.
9 |
10 | #include
11 | #include
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | #include "example_parser.hpp"
18 |
19 | // whether or not the token string contains the given token
20 | bool has_token(const cppast::cpp_token_string& str, const char* token)
21 | {
22 | auto iter = std::find_if(str.begin(), str.end(),
23 | [&](const cppast::cpp_token& tok) { return tok.spelling == token; });
24 | return iter != str.end();
25 | }
26 |
27 | // generates equality operator for a class
28 | void generate_op_equal(std::ostream& out, const cppast::cpp_class& c)
29 | {
30 | out << "inline bool operator==(const " << c.name() << "& lhs, const " << c.name()
31 | << "& rhs) {\n";
32 | out << " return ";
33 |
34 | auto first = true;
35 |
36 | // compare bases
37 | for (auto& base : c.bases())
38 | {
39 | if (cppast::has_attribute(base, "generate::transient"))
40 | // if they are not marked not to be compared
41 | continue;
42 |
43 | if (first)
44 | first = false;
45 | else
46 | out << " && ";
47 | out << "static_cast(lhs) == static_cast(rhs)\n";
49 | }
50 |
51 | // compare members
52 | for (auto& member : c)
53 | if (member.kind() == cppast::cpp_entity_kind::member_variable_t
54 | && !cppast::has_attribute(member, "generate::transient"))
55 | {
56 | // generate comparison code for non-transient member variables
57 | if (first)
58 | first = false;
59 | else
60 | out << " && ";
61 | out << "lhs." << member.name() << " == "
62 | << "rhs." << member.name() << "\n";
63 | }
64 |
65 | out << " ;\n";
66 | out << "}\n\n";
67 | }
68 |
69 | // generate non equality operator for a class
70 | void generate_op_non_equal(std::ostream& out, const cppast::cpp_class& c)
71 | {
72 | // just forwards
73 | out << "inline bool operator!=(const " << c.name() << "& lhs, const " << c.name()
74 | << "& rhs) {\n";
75 | out << " return !(lhs == rhs);\n";
76 | out << "}\n\n";
77 | }
78 |
79 | // generate comparison operators for all classes in the file
80 | void generate_comparison(const cppast::cpp_file& file)
81 | {
82 | cppast::visit(
83 | file,
84 | [](const cppast::cpp_entity& e) {
85 | // only visit non-templated class definitions that have the attribute set
86 | return (!cppast::is_templated(e) && e.kind() == cppast::cpp_entity_kind::class_t
87 | && cppast::is_definition(e) && cppast::has_attribute(e, "generate::comparison"))
88 | // or all namespaces
89 | || e.kind() == cppast::cpp_entity_kind::namespace_t;
90 | },
91 | [](const cppast::cpp_entity& e, const cppast::visitor_info& info) {
92 | if (e.kind() == cppast::cpp_entity_kind::class_t && !info.is_old_entity())
93 | {
94 | // it is a new class
95 | auto& class_ = static_cast(e);
96 | auto& attribute = cppast::has_attribute(e, "generate::comparison").value();
97 |
98 | // generate requested operators
99 | if (attribute.arguments())
100 | {
101 | if (has_token(attribute.arguments().value(), "=="))
102 | generate_op_equal(std::cout, class_);
103 | if (has_token(attribute.arguments().value(), "!="))
104 | generate_op_non_equal(std::cout, class_);
105 | }
106 | else
107 | {
108 | generate_op_equal(std::cout, class_);
109 | generate_op_non_equal(std::cout, class_);
110 | }
111 | }
112 | else if (e.kind() == cppast::cpp_entity_kind::namespace_t)
113 | {
114 | if (info.event == cppast::visitor_info::container_entity_enter)
115 | // open namespace
116 | std::cout << "namespace " << e.name() << " {\n\n";
117 | else // if (info.event == cppast::visitor_info::container_entity_exit)
118 | // close namespace
119 | std::cout << "}\n";
120 | }
121 | });
122 | }
123 |
124 | int main(int argc, char* argv[])
125 | {
126 | return example_main(argc, argv, {}, &generate_comparison);
127 | }
128 |
--------------------------------------------------------------------------------
/example/enum_category.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | /// \file
5 | /// Generates enum category functions.
6 | ///
7 | /// Given an input file, it will generate definitions for functions marked with
8 | /// [[generate::enum_category(name)]]. The function takes an enumerator and will return true if it
9 | /// is marked with the same category.
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | #include // cpp_enum
16 | #include // cpp_function
17 | #include // visit()
18 |
19 | #include "example_parser.hpp"
20 |
21 | // returns whether or not the given enumerator has the given category
22 | bool is_category(const cppast::cpp_enum_value& e, const std::string& name)
23 | {
24 | if (auto attr = cppast::has_attribute(e, "generate::enum_category"))
25 | {
26 | // ... by looking for the token
27 | auto iter
28 | = std::find_if(attr.value().arguments().value().begin(),
29 | attr.value().arguments().value().end(),
30 | [&](const cppast::cpp_token& tok) { return tok.spelling == name; });
31 | return iter != attr.value().arguments().value().end();
32 | }
33 | else
34 | return false;
35 | }
36 |
37 | // returns the enum the parameter type refers to
38 | const cppast::cpp_enum& get_enum(const cppast::cpp_entity_index& index,
39 | const cppast::cpp_function_parameter& param)
40 | {
41 | auto& param_type = param.type();
42 | // it is an enum
43 | assert(param_type.kind() == cppast::cpp_type_kind::user_defined_t);
44 | // lookup definition
45 | auto& definition = static_cast(param_type)
46 | .entity()
47 | .get(index)[0u]
48 | .get();
49 |
50 | assert(definition.kind() == cppast::cpp_entity_kind::enum_t);
51 | return static_cast(definition);
52 | }
53 |
54 | // generates the function definitions
55 | void generate_enum_category(const cppast::cpp_entity_index& index, const cppast::cpp_file& file)
56 | {
57 | cppast::visit(
58 | file,
59 | [](const cppast::cpp_entity& e) {
60 | // only visit function declarations that have the attribute set
61 | return (e.kind() == cppast::cpp_entity_kind::function_t && !cppast::is_definition(e)
62 | && cppast::has_attribute(e, "generate::enum_category"))
63 | // or all namespaces
64 | || e.kind() == cppast::cpp_entity_kind::namespace_t;
65 | },
66 | [&](const cppast::cpp_entity& e, const cppast::visitor_info& info) {
67 | if (e.kind() == cppast::cpp_entity_kind::function_t)
68 | {
69 | // a new function, generate implementation
70 | assert(info.is_new_entity());
71 |
72 | auto category = cppast::has_attribute(e, "generate::enum_category")
73 | .value()
74 | .arguments()
75 | .value()
76 | .as_string();
77 |
78 | auto& func = static_cast(e);
79 | // return type must be bool
80 | assert(func.return_type().kind() == cppast::cpp_type_kind::builtin_t
81 | && static_cast(func.return_type())
82 | .builtin_type_kind()
83 | == cppast::cpp_bool);
84 |
85 | // single parameter...
86 | assert(std::next(func.parameters().begin()) == func.parameters().end());
87 | auto& param = *func.parameters().begin();
88 | auto& enum_ = get_enum(index, param);
89 |
90 | // generate function definition
91 | std::cout << "inline bool " << func.name() << "(" << cppast::to_string(param.type())
92 | << " e) {\n";
93 |
94 | // generate switch
95 | std::cout << " switch (e) {\n";
96 | for (const auto& enumerator : enum_)
97 | {
98 | std::cout << " case " << enum_.name() << "::" << enumerator.name() << ":\n";
99 | if (is_category(enumerator, category))
100 | std::cout << " return true;\n";
101 | else
102 | std::cout << " return false;\n";
103 | }
104 | std::cout << " }\n";
105 |
106 | std::cout << "}\n\n";
107 | }
108 | else if (e.kind() == cppast::cpp_entity_kind::namespace_t)
109 | {
110 | if (info.event == cppast::visitor_info::container_entity_enter)
111 | // open namespace
112 | std::cout << "namespace " << e.name() << " {\n\n";
113 | else // if (info.event == cppast::visitor_info::container_entity_exit)
114 | // close namespace
115 | std::cout << "}\n";
116 | }
117 | });
118 | }
119 |
120 | int main(int argc, char* argv[])
121 | {
122 | cppast::cpp_entity_index index;
123 | return example_main(argc, argv, index,
124 | [&](const cppast::cpp_file& file) { generate_enum_category(index, file); });
125 | }
126 |
--------------------------------------------------------------------------------
/example/enum_to_string.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | /// \file
5 | /// Generates enum `to_string()` code.
6 | ///
7 | /// Given an input file, it will generate a to_string() function for all enums marked with
8 | /// [[generate::to_string]].
9 |
10 | #include
11 |
12 | #include // cpp_enum
13 | #include // visit()
14 |
15 | #include "example_parser.hpp"
16 |
17 | void generate_to_string(const cppast::cpp_file& file)
18 | {
19 | cppast::visit(
20 | file,
21 | [](const cppast::cpp_entity& e) {
22 | // only visit enum definitions that have the attribute set
23 | return (e.kind() == cppast::cpp_entity_kind::enum_t && cppast::is_definition(e)
24 | && cppast::has_attribute(e, "generate::to_string"))
25 | // or all namespaces
26 | || e.kind() == cppast::cpp_entity_kind::namespace_t;
27 | },
28 | [](const cppast::cpp_entity& e, const cppast::visitor_info& info) {
29 | if (e.kind() == cppast::cpp_entity_kind::enum_t && !info.is_old_entity())
30 | {
31 | // a new enum, generate to string function
32 | auto& enum_ = static_cast(e);
33 |
34 | // write function header
35 | std::cout << "inline const char* to_string(const " << enum_.name() << "& e) {\n";
36 |
37 | // generate switch
38 | std::cout << " switch (e) {\n";
39 | for (const auto& enumerator : enum_)
40 | {
41 | std::cout << " case " << enum_.name() << "::" << enumerator.name() << ":\n";
42 |
43 | // attribute can be used to override the string
44 | if (auto attr = cppast::has_attribute(enumerator, "generate::to_string"))
45 | std::cout << " return " << attr.value().arguments().value().as_string()
46 | << ";\n";
47 | else
48 | std::cout << " return \"" << enumerator.name() << "\";\n";
49 | }
50 | std::cout << " }\n";
51 |
52 | std::cout << "}\n\n";
53 | }
54 | else if (e.kind() == cppast::cpp_entity_kind::namespace_t)
55 | {
56 | if (info.event == cppast::visitor_info::container_entity_enter)
57 | // open namespace
58 | std::cout << "namespace " << e.name() << " {\n\n";
59 | else // if (info.event == cppast::visitor_info::container_entity_exit)
60 | // close namespace
61 | std::cout << "}\n";
62 | }
63 | });
64 | }
65 |
66 | int main(int argc, char* argv[])
67 | {
68 | return example_main(argc, argv, {}, &generate_to_string);
69 | }
70 |
--------------------------------------------------------------------------------
/example/example_parser.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_EXAMPLE_PARSER_HPP_INCLUDED
5 | #define CPPAST_EXAMPLE_PARSER_HPP_INCLUDED
6 |
7 | #include
8 |
9 | #include
10 |
11 | // reads the database directory from the command line argument
12 | // parses all files in that directory
13 | // and invokes the callback for each of them
14 | template
15 | int example_main(int argc, char* argv[], const cppast::cpp_entity_index& index, Callback cb)
16 | try
17 | {
18 | if (argc != 2)
19 | {
20 | std::cerr << "usage: " << argv[0] << " \n";
21 | return 1;
22 | }
23 | else
24 | {
25 | cppast::libclang_compilation_database database(argv[1]); // the compilation database
26 |
27 | // simple_file_parser allows parsing multiple files and stores the results for us
28 | cppast::simple_file_parser parser(type_safe::ref(index));
29 | try
30 | {
31 | cppast::parse_database(parser, database); // parse all files in the database
32 | }
33 | catch (cppast::libclang_error& ex)
34 | {
35 | std::cerr << "fatal libclang error: " << ex.what() << '\n';
36 | return 1;
37 | }
38 |
39 | if (parser.error())
40 | // a non-fatal parse error
41 | // error has been logged to stderr
42 | return 1;
43 |
44 | for (auto& file : parser.files())
45 | cb(file);
46 | }
47 |
48 | return 0;
49 | }
50 | catch (std::exception& ex)
51 | {
52 | std::cerr << ex.what() << '\n';
53 | return 1;
54 | }
55 |
56 | #endif // CPPAST_EXAMPLE_PARSER_HPP_INCLUDED
57 |
--------------------------------------------------------------------------------
/example/serialization.cpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | /// \file
5 | /// Serialization code generation.
6 | ///
7 | /// Given an input file, it will generate a serialize() function for each class marked with
8 | /// [[generate::serialize]].
9 |
10 | #include
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include "example_parser.hpp"
18 |
19 | // whether or not a type is a C string, i.e. char pointer
20 | bool is_c_string(const cppast::cpp_type& type)
21 | {
22 | if (type.kind() != cppast::cpp_type_kind::pointer_t)
23 | return false;
24 |
25 | // get the pointee
26 | auto& pointee = cppast::remove_cv(static_cast(type).pointee());
27 | if (pointee.kind() != cppast::cpp_type_kind::builtin_t)
28 | return false;
29 |
30 | // check the builtin type kind
31 | auto builtin = static_cast(pointee).builtin_type_kind();
32 | return builtin == cppast::cpp_char || builtin == cppast::cpp_char16
33 | || builtin == cppast::cpp_char32 || builtin == cppast::cpp_wchar;
34 | }
35 |
36 | // generate a serialization call for a member
37 | void generate_serialize_member(std::ostream& out, const cppast::cpp_member_variable& member)
38 | {
39 | auto& type = cppast::remove_cv(member.type());
40 |
41 | if (cppast::has_attribute(member, "generate::transient"))
42 | // don't serialize transient members
43 | return;
44 | else if (auto attr = cppast::has_attribute(member, "generate::serialize"))
45 | {
46 | // generate code as specified by the attributes
47 | out << " " << attr.value().arguments().value().as_string() << ";\n";
48 | }
49 | else if (type.kind() == cppast::cpp_type_kind::builtin_t)
50 | {
51 | // generate hypothetical member function call for builtin types
52 | out << " s.serialize(obj." << member.name() << ");\n";
53 | }
54 | else if (type.kind() == cppast::cpp_type_kind::user_defined_t)
55 | {
56 | // generate ADL call
57 | out << " serialize(s, obj." << member.name() << ");\n";
58 | }
59 | else if (is_c_string(type))
60 | {
61 | // generate another hypothetical member function call
62 | out << " s.serialize_string(obj." << member.name() << ");\n";
63 | }
64 | else
65 | throw std::invalid_argument("cannot serialize member " + member.name());
66 | }
67 |
68 | // generate serialization function
69 | void generate_serialize(const cppast::cpp_file& file)
70 | {
71 | cppast::visit(
72 | file,
73 | [](const cppast::cpp_entity& e) {
74 | // only visit non-templated class definitions that have the attribute set
75 | return (!cppast::is_templated(e) && e.kind() == cppast::cpp_entity_kind::class_t
76 | && cppast::is_definition(e) && cppast::has_attribute(e, "generate::serialize"))
77 | // or all namespaces
78 | || e.kind() == cppast::cpp_entity_kind::namespace_t;
79 | },
80 | [](const cppast::cpp_entity& e, const cppast::visitor_info& info) {
81 | if (e.kind() == cppast::cpp_entity_kind::class_t && !info.is_old_entity())
82 | {
83 | auto& class_ = static_cast(e);
84 |
85 | std::cout << "inline void serialize(const foo::serializer& s, const "
86 | << class_.name() << "& obj) {\n";
87 |
88 | // serialize base classes
89 | for (auto& base : class_.bases())
90 | if (!cppast::has_attribute(base, "generate::transient"))
91 | std::cout << " serialize(s, static_cast(obj));\n";
93 |
94 | // serialize member variables
95 | for (auto& member : class_)
96 | {
97 | if (member.kind() == cppast::cpp_entity_kind::member_variable_t)
98 | generate_serialize_member(std::cout,
99 | static_cast(
100 | member));
101 | }
102 |
103 | std::cout << "}\n\n";
104 | }
105 | else if (e.kind() == cppast::cpp_entity_kind::namespace_t)
106 | {
107 | if (info.event == cppast::visitor_info::container_entity_enter)
108 | // open namespace
109 | std::cout << "namespace " << e.name() << " {\n\n";
110 | else // if (info.event == cppast::visitor_info::container_entity_exit)
111 | // close namespace
112 | std::cout << "}\n";
113 | }
114 | });
115 | }
116 |
117 | int main(int argc, char* argv[])
118 | {
119 | return example_main(argc, argv, {}, generate_serialize);
120 | }
121 |
--------------------------------------------------------------------------------
/external/tpl/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.1)
2 |
3 | project(tiny-process-library)
4 |
5 | if(CMAKE_SOURCE_DIR STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
6 | option(BUILD_TESTING "set ON to build library tests" ON)
7 | else()
8 | option(BUILD_TESTING "set ON to build library tests" OFF)
9 | endif()
10 |
11 | add_library(tiny-process-library process.cpp)
12 | add_library(tiny-process-library::tiny-process-library ALIAS tiny-process-library)
13 |
14 | if(MSVC)
15 | target_compile_definitions(tiny-process-library PRIVATE /D_CRT_SECURE_NO_WARNINGS)
16 | else()
17 | target_compile_options(tiny-process-library PRIVATE -std=c++11 -Wall -Wextra)
18 | endif()
19 |
20 | if(WIN32)
21 | set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
22 | target_sources(tiny-process-library PRIVATE process_win.cpp)
23 | #If compiled using MSYS2, use sh to run commands
24 | if(MSYS)
25 | target_compile_definitions(tiny-process-library PUBLIC MSYS_PROCESS_USE_SH)
26 | endif()
27 | else()
28 | target_sources(tiny-process-library PRIVATE process_unix.cpp)
29 | endif()
30 |
31 | find_package(Threads REQUIRED)
32 |
33 | target_link_libraries(tiny-process-library ${CMAKE_THREAD_LIBS_INIT})
34 | target_include_directories(tiny-process-library PUBLIC $
35 | $)
36 |
37 | # if tiny-process-library is not a sub-project:
38 | if(CMAKE_SOURCE_DIR STREQUAL "${CMAKE_CURRENT_SOURCE_DIR}")
39 | if(MSVC)
40 | add_definitions(/D_CRT_SECURE_NO_WARNINGS)
41 | else()
42 | add_compile_options(-std=c++11 -Wall -Wextra)
43 | endif()
44 |
45 | add_executable(examples examples.cpp)
46 | target_link_libraries(examples tiny-process-library)
47 |
48 | install(TARGETS tiny-process-library
49 | EXPORT ${PROJECT_NAME}-config
50 | ARCHIVE DESTINATION lib
51 | LIBRARY DESTINATION lib
52 | RUNTIME DESTINATION bin)
53 |
54 | install(EXPORT ${PROJECT_NAME}-config
55 | FILE ${PROJECT_NAME}-config.cmake
56 | NAMESPACE ${PROJECT_NAME}::
57 | DESTINATION lib/cmake/${PROJECT_NAME}
58 | )
59 |
60 | install(FILES process.hpp DESTINATION include)
61 | endif()
62 |
63 | if(BUILD_TESTING)
64 | enable_testing()
65 | add_subdirectory(tests)
66 | endif()
67 |
--------------------------------------------------------------------------------
/external/tpl/process.cpp:
--------------------------------------------------------------------------------
1 | #include "process.hpp"
2 |
3 | namespace TinyProcessLib {
4 |
5 | Process::Process(const std::vector &arguments, const string_type &path,
6 | std::function read_stdout,
7 | std::function read_stderr,
8 | bool open_stdin, const Config &config) noexcept
9 | : closed(true), read_stdout(std::move(read_stdout)), read_stderr(std::move(read_stderr)), open_stdin(open_stdin), config(config) {
10 | open(arguments, path);
11 | async_read();
12 | }
13 |
14 | Process::Process(const string_type &command, const string_type &path,
15 | std::function read_stdout,
16 | std::function read_stderr,
17 | bool open_stdin, const Config &config) noexcept
18 | : closed(true), read_stdout(std::move(read_stdout)), read_stderr(std::move(read_stderr)), open_stdin(open_stdin), config(config) {
19 | open(command, path);
20 | async_read();
21 | }
22 |
23 | Process::Process(const std::vector &arguments, const string_type &path,
24 | const environment_type &environment,
25 | std::function read_stdout,
26 | std::function read_stderr,
27 | bool open_stdin, const Config &config) noexcept
28 | : closed(true), read_stdout(std::move(read_stdout)), read_stderr(std::move(read_stderr)), open_stdin(open_stdin), config(config) {
29 | open(arguments, path, &environment);
30 | async_read();
31 | }
32 |
33 | Process::Process(const string_type &command, const string_type &path,
34 | const environment_type &environment,
35 | std::function read_stdout,
36 | std::function read_stderr,
37 | bool open_stdin, const Config &config) noexcept
38 | : closed(true), read_stdout(std::move(read_stdout)), read_stderr(std::move(read_stderr)), open_stdin(open_stdin), config(config) {
39 | open(command, path, &environment);
40 | async_read();
41 | }
42 |
43 | Process::~Process() noexcept {
44 | close_fds();
45 | }
46 |
47 | Process::id_type Process::get_id() const noexcept {
48 | return data.id;
49 | }
50 |
51 | bool Process::write(const std::string &str) {
52 | return write(str.c_str(), str.size());
53 | }
54 |
55 | } // namespace TinyProcessLib
56 |
--------------------------------------------------------------------------------
/include/cppast/cpp_alias_template.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_ALIAS_TEMPLATE_HPP_INCLUDED
5 | #define CPPAST_CPP_ALIAS_TEMPLATE_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | /// A [cppast::cpp_entity]() modelling a C++ alias template.
13 | class cpp_alias_template final : public cpp_template
14 | {
15 | public:
16 | static cpp_entity_kind kind() noexcept;
17 |
18 | /// Builder for [cppast::cpp_alias_template]().
19 | class builder : public basic_builder
20 | {
21 | public:
22 | using basic_builder::basic_builder;
23 | };
24 |
25 | /// \returns A reference to the type alias that is being templated.
26 | const cpp_type_alias& type_alias() const noexcept
27 | {
28 | return static_cast(*begin());
29 | }
30 |
31 | private:
32 | cpp_alias_template(std::unique_ptr alias)
33 | : cpp_template(std::unique_ptr(alias.release()))
34 | {}
35 |
36 | cpp_entity_kind do_get_entity_kind() const noexcept override;
37 |
38 | friend basic_builder;
39 | };
40 | } // namespace cppast
41 |
42 | #endif // CPPAST_CPP_ALIAS_TEMPLATE_HPP_INCLUDED
43 |
--------------------------------------------------------------------------------
/include/cppast/cpp_array_type.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_ARRAY_TYPE_HPP_INCLUDED
5 | #define CPPAST_CPP_ARRAY_TYPE_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | /// An array of a [cppast::cpp_type]().
13 | class cpp_array_type final : public cpp_type
14 | {
15 | public:
16 | /// \returns A newly created array.
17 | /// \notes `size` may be `nullptr`.
18 | static std::unique_ptr build(std::unique_ptr type,
19 | std::unique_ptr size)
20 | {
21 | return std::unique_ptr(
22 | new cpp_array_type(std::move(type), std::move(size)));
23 | }
24 |
25 | /// \returns A reference to the value [cppast::cpp_type]().
26 | const cpp_type& value_type() const noexcept
27 | {
28 | return *type_;
29 | }
30 |
31 | /// \returns An optional reference to the [cppast::cpp_expression]() that is the size of the
32 | /// array. \notes An unsized array - `T[]` - does not have a size.
33 | type_safe::optional_ref size() const noexcept
34 | {
35 | return type_safe::opt_cref(size_.get());
36 | }
37 |
38 | private:
39 | cpp_array_type(std::unique_ptr type, std::unique_ptr size)
40 | : type_(std::move(type)), size_(std::move(size))
41 | {}
42 |
43 | cpp_type_kind do_get_kind() const noexcept override
44 | {
45 | return cpp_type_kind::array_t;
46 | }
47 |
48 | std::unique_ptr type_;
49 | std::unique_ptr size_;
50 | };
51 | } // namespace cppast
52 |
53 | #endif // CPPAST_CPP_ARRAY_TYPE_HPP_INCLUDED
54 |
--------------------------------------------------------------------------------
/include/cppast/cpp_attribute.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_ATTRIBUTE_HPP_INCLUDED
5 | #define CPPAST_CPP_ATTRIBUTE_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 |
13 | #include
14 |
15 | namespace cppast
16 | {
17 | /// The known C++ attributes.
18 | enum class cpp_attribute_kind
19 | {
20 | // update get_attribute_kind() in tokenizer, when updating this
21 |
22 | alignas_,
23 | carries_dependency,
24 | deprecated,
25 | fallthrough,
26 | maybe_unused,
27 | nodiscard,
28 | noreturn,
29 |
30 | unknown, //< An unknown attribute.
31 | };
32 |
33 | /// A C++ attribute, including `alignas` specifiers.
34 | ///
35 | /// It consists of a name, an optional namespace scope and optional arguments.
36 | /// The scope is just a single identifier and doesn't include the `::` and can be given explicitly
37 | /// or via using. The arguments are as specified in the source code but do not include the
38 | /// outer-most `(` and `)`. It can also be variadic or not.
39 | ///
40 | /// An attribute can be known or unknown.
41 | /// A known attribute will have the [cppast::cpp_attribute_kind]() set properly.
42 | class cpp_attribute
43 | {
44 | public:
45 | /// \effects Creates a known attribute, potentially with arguments.
46 | cpp_attribute(cpp_attribute_kind kind, type_safe::optional arguments);
47 |
48 | /// \effects Creates an unknown attribute giving it the optional scope, names, arguments and
49 | /// whether it is variadic.
50 | cpp_attribute(type_safe::optional scope, std::string name,
51 | type_safe::optional arguments, bool is_variadic)
52 | : scope_(std::move(scope)), arguments_(std::move(arguments)), name_(std::move(name)),
53 | variadic_(is_variadic)
54 | {}
55 |
56 | /// \returns The kind of attribute, if it is known.
57 | const cpp_attribute_kind& kind() const noexcept
58 | {
59 | return kind_;
60 | }
61 |
62 | /// \returns The name of the attribute.
63 | const std::string& name() const noexcept
64 | {
65 | return name_;
66 | }
67 |
68 | /// \returns The scope of the attribute, if there is any.
69 | const type_safe::optional& scope() const noexcept
70 | {
71 | return scope_;
72 | }
73 |
74 | /// \returns Whether or not the attribute is variadic.
75 | bool is_variadic() const noexcept
76 | {
77 | return variadic_;
78 | }
79 |
80 | /// \returns The arguments of the attribute, if they are any.
81 | const type_safe::optional& arguments() const noexcept
82 | {
83 | return arguments_;
84 | }
85 |
86 | private:
87 | type_safe::optional scope_;
88 | type_safe::optional arguments_;
89 | std::string name_;
90 | cpp_attribute_kind kind_ = cpp_attribute_kind::unknown;
91 | bool variadic_;
92 | };
93 |
94 | /// A list of C++ attributes.
95 | using cpp_attribute_list = std::vector;
96 |
97 | /// Checks whether an attribute is given.
98 | /// \returns `true` if the given attribute list (1-2) / entity (3-4) contain
99 | /// an attribute of the given name (1+3) / kind (2+4).
100 | /// `false` otherwise.
101 | /// \group has_attribute
102 | type_safe::optional_ref has_attribute(const cpp_attribute_list& attributes,
103 | const std::string& name);
104 |
105 | /// \group has_attribute
106 | type_safe::optional_ref has_attribute(const cpp_attribute_list& attributes,
107 | cpp_attribute_kind kind);
108 |
109 | /// \group has_attribute
110 | type_safe::optional_ref has_attribute(const cpp_entity& e,
111 | const std::string& name);
112 |
113 | /// \group has_attribute
114 | type_safe::optional_ref has_attribute(const cpp_entity& e,
115 | cpp_attribute_kind kind);
116 | } // namespace cppast
117 |
118 | #endif // CPPAST_CPP_ATTRIBUTE_HPP_INCLUDED
119 |
--------------------------------------------------------------------------------
/include/cppast/cpp_class_template.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_CLASS_TEMPLATE_HPP_INCLUDED
5 | #define CPPAST_CPP_CLASS_TEMPLATE_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | /// A [cppast::cpp_entity]() modelling a class template.
13 | class cpp_class_template final : public cpp_template
14 | {
15 | public:
16 | static cpp_entity_kind kind() noexcept;
17 |
18 | /// Builder for [cppast::cpp_class_template]().
19 | class builder : public basic_builder
20 | {
21 | public:
22 | using basic_builder::basic_builder;
23 | };
24 |
25 | /// A reference to the class that is being templated.
26 | const cpp_class& class_() const noexcept
27 | {
28 | return static_cast(*begin());
29 | }
30 |
31 | private:
32 | cpp_class_template(std::unique_ptr func)
33 | : cpp_template(std::unique_ptr(func.release()))
34 | {}
35 |
36 | cpp_entity_kind do_get_entity_kind() const noexcept override;
37 |
38 | friend basic_builder;
39 | };
40 |
41 | /// A [cppast::cpp_entity]() modelling a class template specialization.
42 | class cpp_class_template_specialization final : public cpp_template_specialization
43 | {
44 | public:
45 | static cpp_entity_kind kind() noexcept;
46 |
47 | /// Builder for [cppast::cpp_class_template_specialization]().
48 | class builder : public specialization_builder
49 | {
50 | public:
51 | using specialization_builder::specialization_builder;
52 | };
53 |
54 | /// A reference to the class that is being specialized.
55 | const cpp_class& class_() const noexcept
56 | {
57 | return static_cast(*begin());
58 | }
59 |
60 | private:
61 | cpp_class_template_specialization(std::unique_ptr func, cpp_template_ref primary)
62 | : cpp_template_specialization(std::unique_ptr(func.release()), primary)
63 | {}
64 |
65 | cpp_entity_kind do_get_entity_kind() const noexcept override;
66 |
67 | friend specialization_builder;
68 | };
69 | } // namespace cppast
70 |
71 | #endif // CPPAST_CPP_CLASS_TEMPLATE_HPP_INCLUDED
72 |
--------------------------------------------------------------------------------
/include/cppast/cpp_concept.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_CONCEPT_HPP_INCLUDED
5 | #define CPPAST_CPP_CONCEPT_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | namespace cppast
12 | {
13 | /// A [[cppast::cpp_entity]() modelling a c++ concept declaration
14 | /// \notes while concepts are technically templates,
15 | /// this is not a [cppast::cpp_template](),
16 | /// as concepts act very differently from other templates
17 | class cpp_concept final : public cpp_entity
18 | {
19 | public:
20 | static cpp_entity_kind kind() noexcept;
21 |
22 | /// \returns the template parameters as a string
23 | const cpp_token_string& parameters() const noexcept
24 | {
25 | return parameters_;
26 | }
27 |
28 | /// \returns the [cppast::cpp_expression]() defining the concept constraint
29 | const cpp_expression& constraint_expression() const noexcept
30 | {
31 | return *expression_;
32 | }
33 |
34 | class builder
35 | {
36 | public:
37 | builder(std::string name) : concept_(new cpp_concept(std::move(name))) {}
38 |
39 | cpp_token_string& set_parameters(cpp_token_string string) noexcept
40 | {
41 | concept_->parameters_ = std::move(string);
42 | return concept_->parameters_;
43 | }
44 |
45 | cpp_expression& set_expression(std::unique_ptr expression) noexcept
46 | {
47 | concept_->expression_ = std::move(expression);
48 | return *concept_->expression_;
49 | }
50 |
51 | std::unique_ptr finish(const cpp_entity_index& idx, cpp_entity_id id);
52 |
53 | private:
54 | std::unique_ptr concept_;
55 | };
56 |
57 | private:
58 | cpp_concept(std::string name) : cpp_entity(std::move(name)), parameters_({}) {}
59 |
60 | cpp_entity_kind do_get_entity_kind() const noexcept override;
61 |
62 | cpp_token_string parameters_;
63 |
64 | std::unique_ptr expression_;
65 | };
66 |
67 | } // namespace cppast
68 |
69 | #endif
70 |
--------------------------------------------------------------------------------
/include/cppast/cpp_decltype_type.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_DECLTYPE_TYPE_HPP_INCLUDED
5 | #define CPPAST_CPP_DECLTYPE_TYPE_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | /// A [cppast::cpp_type]() that isn't given but taken from an expression.
13 | class cpp_decltype_type final : public cpp_type
14 | {
15 | public:
16 | /// \returns A newly created `decltype` type.
17 | static std::unique_ptr build(std::unique_ptr expr)
18 | {
19 | return std::unique_ptr(new cpp_decltype_type(std::move(expr)));
20 | }
21 |
22 | /// \returns A reference to the expression given.
23 | const cpp_expression& expression() const noexcept
24 | {
25 | return *expr_;
26 | }
27 |
28 | private:
29 | cpp_decltype_type(std::unique_ptr expr) : expr_(std::move(expr)) {}
30 |
31 | cpp_type_kind do_get_kind() const noexcept override
32 | {
33 | return cpp_type_kind::decltype_t;
34 | }
35 |
36 | std::unique_ptr expr_;
37 | };
38 |
39 | /// A [cppast::cpp_type]() that isn't given but deduced using the `decltype` rules.
40 | class cpp_decltype_auto_type final : public cpp_type
41 | {
42 | public:
43 | /// \returns A newly created `auto` type.
44 | static std::unique_ptr build()
45 | {
46 | return std::unique_ptr(new cpp_decltype_auto_type);
47 | }
48 |
49 | private:
50 | cpp_decltype_auto_type() = default;
51 |
52 | cpp_type_kind do_get_kind() const noexcept override
53 | {
54 | return cpp_type_kind::decltype_auto_t;
55 | }
56 | };
57 | } // namespace cppast
58 |
59 | #endif // CPPAST_CPP_DECLTYPE_TYPE_HPP_INCLUDED
60 |
--------------------------------------------------------------------------------
/include/cppast/cpp_entity_container.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_ENTITY_CONTAINER_HPP_INCLUDED
5 | #define CPPAST_CPP_ENTITY_CONTAINER_HPP_INCLUDED
6 |
7 | #include
8 |
9 | namespace cppast
10 | {
11 | /// Helper class for entities that are containers.
12 | ///
13 | /// Inherit from it to generate container access.
14 | template
15 | class cpp_entity_container
16 | {
17 | public:
18 | using iterator = typename detail::intrusive_list::const_iterator;
19 |
20 | /// \returns A const iterator to the first child.
21 | iterator begin() const noexcept
22 | {
23 | return children_.begin();
24 | }
25 |
26 | /// \returns A const iterator to the last child.
27 | iterator end() const noexcept
28 | {
29 | return children_.end();
30 | }
31 |
32 | protected:
33 | /// \effects Adds a new child to the container.
34 | void add_child(std::unique_ptr ptr) noexcept
35 | {
36 | children_.push_back(static_cast(*this), std::move(ptr));
37 | }
38 |
39 | /// \returns A non-const iterator to the first child.
40 | typename detail::intrusive_list::iterator mutable_begin() noexcept
41 | {
42 | return children_.begin();
43 | }
44 |
45 | /// \returns A non-const iterator one past the last child.
46 | typename detail::intrusive_list::iterator mutable_end() noexcept
47 | {
48 | return children_.begin();
49 | }
50 |
51 | ~cpp_entity_container() noexcept = default;
52 |
53 | private:
54 | detail::intrusive_list children_;
55 | };
56 | } // namespace cppast
57 |
58 | #endif // CPPAST_CPP_ENTITY_CONTAINER_HPP_INCLUDED
59 |
--------------------------------------------------------------------------------
/include/cppast/cpp_entity_kind.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_ENTITY_KIND_HPP_INCLUDED
5 | #define CPPAST_CPP_ENTITY_KIND_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | /// All possible kinds of C++ entities.
13 | enum class cpp_entity_kind
14 | {
15 | file_t,
16 |
17 | macro_parameter_t,
18 | macro_definition_t,
19 | include_directive_t,
20 |
21 | language_linkage_t,
22 |
23 | namespace_t,
24 | namespace_alias_t,
25 | using_directive_t,
26 | using_declaration_t,
27 |
28 | type_alias_t,
29 |
30 | enum_t,
31 | enum_value_t,
32 |
33 | class_t,
34 | access_specifier_t,
35 | base_class_t,
36 |
37 | variable_t,
38 | member_variable_t,
39 | bitfield_t,
40 |
41 | function_parameter_t,
42 | function_t,
43 | member_function_t,
44 | conversion_op_t,
45 | constructor_t,
46 | destructor_t,
47 |
48 | friend_t,
49 |
50 | template_type_parameter_t,
51 | non_type_template_parameter_t,
52 | template_template_parameter_t,
53 |
54 | alias_template_t,
55 | variable_template_t,
56 | function_template_t,
57 | function_template_specialization_t,
58 | class_template_t,
59 | class_template_specialization_t,
60 | concept_t,
61 |
62 | static_assert_t,
63 |
64 | unexposed_t,
65 |
66 | count,
67 | };
68 |
69 | /// \returns A human readable string describing the entity kind.
70 | const char* to_string(cpp_entity_kind kind) noexcept;
71 |
72 | /// \returns Whether or not a given entity kind is a C++ function,
73 | /// that is, it dervies from [cppast::cpp_function_base]().
74 | bool is_function(cpp_entity_kind kind) noexcept;
75 |
76 | /// \returns Whether or not a given entity kind is a C++ (template) parameter.
77 | bool is_parameter(cpp_entity_kind kind) noexcept;
78 |
79 | /// \returns Whether or not a given entity kind is a C++ template,
80 | /// that is, it dervies from [cppast::cpp_template]().
81 | /// \notes A template template parameter is not considered a template for this function.
82 | /// \notes Template specializations are also considered templates here.
83 | bool is_template(cpp_entity_kind kind) noexcept;
84 |
85 | /// \returns Whether or not a given entity kind is a specialization of a C++ template,
86 | /// that is, it derives from [cppast::cpp_template_specialization]().
87 | bool is_template_specialization(cpp_entity_kind kind) noexcept;
88 | } // namespace cppast
89 |
90 | #endif // CPPAST_CPP_ENTITY_KIND_HPP_INCLUDED
91 |
--------------------------------------------------------------------------------
/include/cppast/cpp_entity_ref.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_ENTITY_REF_HPP_INCLUDED
5 | #define CPPAST_CPP_ENTITY_REF_HPP_INCLUDED
6 |
7 | #include
8 |
9 | #include
10 |
11 | #include
12 | #include
13 |
14 | namespace cppast
15 | {
16 |
17 | /// A basic reference to some kind of [cppast::cpp_entity]().
18 | ///
19 | /// It can either refer to a single [cppast::cpp_entity]()
20 | /// or multiple.
21 | /// In the later case it is *overloaded*.
22 | template
23 | class basic_cpp_entity_ref
24 | {
25 | public:
26 | /// \effects Creates it giving it the target id and name.
27 | basic_cpp_entity_ref(cpp_entity_id target_id, std::string target_name)
28 | : target_(std::move(target_id)), name_(std::move(target_name))
29 | {}
30 |
31 | /// \effects Creates it giving it multiple target ids and name.
32 | /// \notes This is to refer to an overloaded function.
33 | basic_cpp_entity_ref(std::vector target_ids, std::string target_name)
34 | : target_(std::move(target_ids)), name_(std::move(target_name))
35 | {}
36 |
37 | /// \returns The name of the reference, as spelled in the source code.
38 | const std::string& name() const noexcept
39 | {
40 | return name_;
41 | }
42 |
43 | /// \returns Whether or not it refers to multiple entities.
44 | bool is_overloaded() const noexcept
45 | {
46 | return target_.has_value(type_safe::variant_type>{});
47 | }
48 |
49 | /// \returns The number of entities it refers to.
50 | type_safe::size_t no_overloaded() const noexcept
51 | {
52 | return id().size();
53 | }
54 |
55 | /// \returns An array reference to the id or ids it refers to.
56 | type_safe::array_ref id() const noexcept
57 | {
58 | if (is_overloaded())
59 | {
60 | auto& vec = target_.value(type_safe::variant_type>{});
61 | return type_safe::ref(vec.data(), vec.size());
62 | }
63 | else
64 | {
65 | auto& id = target_.value(type_safe::variant_type{});
66 | return type_safe::ref(&id, 1u);
67 | }
68 | }
69 |
70 | /// \returns An array reference to the entities it refers to.
71 | /// The return type provides `operator[]` + `size()`,
72 | /// as well as `begin()` and `end()` returning forward iterators.
73 | /// \exclude return
74 | std::vector> get(const cpp_entity_index& idx) const
75 | {
76 | std::vector> result;
77 | get_impl(std::is_convertible{}, result, idx);
78 | return result;
79 | }
80 |
81 | private:
82 | void get_impl(std::true_type, std::vector>& result,
83 | const cpp_entity_index& idx) const
84 | {
85 | for (auto& cur : id())
86 | for (auto& ns : idx.lookup_namespace(cur))
87 | result.push_back(ns);
88 | if (!std::is_same::value)
89 | get_impl(std::false_type{}, result, idx);
90 | }
91 |
92 | void get_impl(std::false_type, std::vector>& result,
93 | const cpp_entity_index& idx) const
94 | {
95 | for (auto& cur : id())
96 | {
97 | auto entity = idx.lookup(cur).map([](const cpp_entity& e) {
98 | DEBUG_ASSERT(Predicate{}(e), detail::precondition_error_handler{},
99 | "invalid entity type");
100 | return type_safe::ref(static_cast(e));
101 | });
102 | if (entity)
103 | result.push_back(type_safe::ref(entity.value()));
104 | }
105 | }
106 |
107 | type_safe::variant> target_;
108 | std::string name_;
109 | };
110 |
111 | /// \exclude
112 | namespace detail
113 | {
114 | struct cpp_entity_ref_predicate
115 | {
116 | bool operator()(const cpp_entity&)
117 | {
118 | return true;
119 | }
120 | };
121 | } // namespace detail
122 |
123 | /// A [cppast::basic_cpp_entity_ref]() to any [cppast::cpp_entity]().
124 | using cpp_entity_ref = basic_cpp_entity_ref;
125 | } // namespace cppast
126 |
127 | #endif // CPPAST_CPP_ENTITY_REF_HPP_INCLUDED
128 |
--------------------------------------------------------------------------------
/include/cppast/cpp_enum.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_ENUM_HPP_INCLUDED
5 | #define CPPAST_CPP_ENUM_HPP_INCLUDED
6 |
7 | #include
8 |
9 | #include
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 |
18 | namespace cppast
19 | {
20 | /// A [cppast::cpp_entity]() modelling the value of an [cppast::cpp_enum]().
21 | class cpp_enum_value final : public cpp_entity
22 | {
23 | public:
24 | static cpp_entity_kind kind() noexcept;
25 |
26 | /// \returns A newly created and registered enum value.
27 | /// \notes `value` may be `nullptr`, in which case the enum has an implicit value.
28 | static std::unique_ptr build(const cpp_entity_index& idx, cpp_entity_id id,
29 | std::string name,
30 | std::unique_ptr value = nullptr);
31 |
32 | /// \returns A [ts::optional_ref]() to the [cppast::cpp_expression]() that is the enum value.
33 | /// \notes It only has an associated expression if the value is explictly given.
34 | type_safe::optional_ref value() const noexcept
35 | {
36 | return type_safe::opt_cref(value_.get());
37 | }
38 |
39 | private:
40 | cpp_enum_value(std::string name, std::unique_ptr value)
41 | : cpp_entity(std::move(name)), value_(std::move(value))
42 | {}
43 |
44 | cpp_entity_kind do_get_entity_kind() const noexcept override;
45 |
46 | std::unique_ptr value_;
47 | };
48 |
49 | /// A [cppast::cpp_entity]() modelling a C++ enumeration.
50 | ///
51 | /// This can either be a definition or just a forward declaration.
52 | /// If it is just forward declared, it will not have any children.
53 | class cpp_enum final : public cpp_entity,
54 | public cpp_entity_container,
55 | public cpp_forward_declarable
56 | {
57 | public:
58 | static cpp_entity_kind kind() noexcept;
59 |
60 | /// Builds a [cppast::cpp_enum]().
61 | class builder
62 | {
63 | public:
64 | /// \effects Sets the name, underlying type and whether it is scoped.
65 | builder(std::string name, bool scoped, std::unique_ptr type, bool explicit_type)
66 | : enum_(new cpp_enum(std::move(name), std::move(type), explicit_type, scoped))
67 | {}
68 |
69 | /// \effects Adds a [cppast::cpp_enum_value]().
70 | void add_value(std::unique_ptr value)
71 | {
72 | enum_->add_child(std::move(value));
73 | }
74 |
75 | /// \returns The not yet finished enumeration.
76 | cpp_enum& get() noexcept
77 | {
78 | return *enum_;
79 | }
80 |
81 | /// \effects Registers the enum in the [cppast::cpp_entity_index](),
82 | /// using the given [cppast::cpp_entity_id]().
83 | /// \returns The finished enum.
84 | std::unique_ptr finish(
85 | const cpp_entity_index& idx, cpp_entity_id id,
86 | type_safe::optional semantic_parent) noexcept
87 | {
88 | enum_->set_semantic_parent(std::move(semantic_parent));
89 | idx.register_definition(std::move(id), type_safe::ref(*enum_));
90 | return std::move(enum_);
91 | }
92 |
93 | /// \effects Marks the enum as forward declaration.
94 | /// \returns The finished enum.
95 | std::unique_ptr finish_declaration(const cpp_entity_index& idx,
96 | cpp_entity_id definition_id) noexcept
97 | {
98 | enum_->mark_declaration(definition_id);
99 | idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*enum_));
100 | return std::move(enum_);
101 | }
102 |
103 | private:
104 | std::unique_ptr enum_;
105 | };
106 |
107 | /// \returns A reference to the underlying [cppast::cpp_type]() of the enum.
108 | const cpp_type& underlying_type() const noexcept
109 | {
110 | return *type_;
111 | }
112 |
113 | /// \returns Whether or not the underlying type is explictly given.
114 | bool has_explicit_type() const noexcept
115 | {
116 | return type_given_;
117 | }
118 |
119 | /// \returns Whether or not it is a scoped enumeration (i.e. an `enum class`).
120 | bool is_scoped() const noexcept
121 | {
122 | return scoped_;
123 | }
124 |
125 | private:
126 | cpp_enum(std::string name, std::unique_ptr type, bool type_given, bool scoped)
127 | : cpp_entity(std::move(name)), type_(std::move(type)), scoped_(scoped), type_given_(type_given)
128 | {}
129 |
130 | cpp_entity_kind do_get_entity_kind() const noexcept override;
131 |
132 | type_safe::optional do_get_scope_name() const override;
133 |
134 | std::unique_ptr type_;
135 | bool scoped_, type_given_;
136 | };
137 | } // namespace cppast
138 |
139 | #endif // CPPAST_CPP_ENUM_HPP_INCLUDED
140 |
--------------------------------------------------------------------------------
/include/cppast/cpp_expression.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_EXPRESSION_HPP_INCLUDED
5 | #define CPPAST_CPP_EXPRESSION_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 |
13 | namespace cppast
14 | {
15 | /// The kind of a [cppast::cpp_expression]().
16 | enum class cpp_expression_kind
17 | {
18 | literal_t,
19 |
20 | unexposed_t,
21 | };
22 |
23 | /// Base class for all C++ expressions.
24 | class cpp_expression
25 | {
26 | public:
27 | cpp_expression(const cpp_expression&) = delete;
28 | cpp_expression& operator=(const cpp_expression&) = delete;
29 |
30 | virtual ~cpp_expression() noexcept = default;
31 |
32 | /// \returns The [cppast::cpp_expression_kind]().
33 | cpp_expression_kind kind() const noexcept
34 | {
35 | return do_get_kind();
36 | }
37 |
38 | /// \returns The type of the expression.
39 | const cpp_type& type() const noexcept
40 | {
41 | return *type_;
42 | }
43 |
44 | /// \returns The specified user data.
45 | void* user_data() const noexcept
46 | {
47 | return user_data_.load();
48 | }
49 |
50 | /// \effects Sets some kind of user data.
51 | ///
52 | /// User data is just some kind of pointer, there are no requirements.
53 | /// The class will do no lifetime management.
54 | ///
55 | /// User data is useful if you need to store additional data for an entity without the need to
56 | /// maintain a registry.
57 | void set_user_data(void* data) const noexcept
58 | {
59 | user_data_ = data;
60 | }
61 |
62 | protected:
63 | /// \effects Creates it given the type.
64 | /// \requires The type must not be `nullptr`.
65 | cpp_expression(std::unique_ptr type) : type_(std::move(type)), user_data_(nullptr)
66 | {
67 | DEBUG_ASSERT(type_ != nullptr, detail::precondition_error_handler{});
68 | }
69 |
70 | private:
71 | /// \returns The [cppast::cpp_expression_kind]().
72 | virtual cpp_expression_kind do_get_kind() const noexcept = 0;
73 |
74 | std::unique_ptr type_;
75 | mutable std::atomic user_data_;
76 | };
77 |
78 | /// An unexposed [cppast::cpp_expression]().
79 | ///
80 | /// There is no further information than a string available.
81 | class cpp_unexposed_expression final : public cpp_expression
82 | {
83 | public:
84 | /// \returns A newly created unexposed expression.
85 | static std::unique_ptr build(std::unique_ptr type,
86 | cpp_token_string str)
87 | {
88 | return std::unique_ptr(
89 | new cpp_unexposed_expression(std::move(type), std::move(str)));
90 | }
91 |
92 | /// \returns The expression as a string.
93 | const cpp_token_string& expression() const noexcept
94 | {
95 | return str_;
96 | }
97 |
98 | private:
99 | cpp_unexposed_expression(std::unique_ptr type, cpp_token_string str)
100 | : cpp_expression(std::move(type)), str_(std::move(str))
101 | {}
102 |
103 | cpp_expression_kind do_get_kind() const noexcept override
104 | {
105 | return cpp_expression_kind::unexposed_t;
106 | }
107 |
108 | cpp_token_string str_;
109 | };
110 |
111 | /// A [cppast::cpp_expression]() that is a literal.
112 | class cpp_literal_expression final : public cpp_expression
113 | {
114 | public:
115 | /// \returns A newly created literal expression.
116 | static std::unique_ptr build(std::unique_ptr type,
117 | std::string value)
118 | {
119 | return std::unique_ptr(
120 | new cpp_literal_expression(std::move(type), std::move(value)));
121 | }
122 |
123 | /// \returns The value of the literal, as string.
124 | const std::string& value() const noexcept
125 | {
126 | return value_;
127 | }
128 |
129 | private:
130 | cpp_literal_expression(std::unique_ptr type, std::string value)
131 | : cpp_expression(std::move(type)), value_(std::move(value))
132 | {}
133 |
134 | cpp_expression_kind do_get_kind() const noexcept override
135 | {
136 | return cpp_expression_kind::literal_t;
137 | }
138 |
139 | std::string value_;
140 | };
141 |
142 | /// \exclude
143 | namespace detail
144 | {
145 | void write_expression(code_generator::output& output, const cpp_expression& expr);
146 | } // namespace detail
147 | } // namespace cppast
148 |
149 | #endif // CPPAST_CPP_EXPRESSION_HPP_INCLUDED
150 |
--------------------------------------------------------------------------------
/include/cppast/cpp_file.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_FILE_HPP_INCLUDED
5 | #define CPPAST_CPP_FILE_HPP_INCLUDED
6 |
7 | #include
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | namespace cppast
14 | {
15 | /// An unmatched documentation comment.
16 | struct cpp_doc_comment
17 | {
18 | std::string content;
19 | unsigned line;
20 |
21 | cpp_doc_comment(std::string content, unsigned line) : content(std::move(content)), line(line) {}
22 | };
23 |
24 | /// A [cppast::cpp_entity]() modelling a file.
25 | ///
26 | /// This is the top-level entity of the AST.
27 | class cpp_file final : public cpp_entity, public cpp_entity_container
28 | {
29 | public:
30 | static cpp_entity_kind kind() noexcept;
31 |
32 | /// Builds a [cppast::cpp_file]().
33 | class builder
34 | {
35 | public:
36 | /// \effects Sets the file name.
37 | explicit builder(std::string name) : file_(new cpp_file(std::move(name))) {}
38 |
39 | /// \effects Adds an entity.
40 | void add_child(std::unique_ptr child) noexcept
41 | {
42 | file_->add_child(std::move(child));
43 | }
44 |
45 | /// \effects Adds an unmatched documentation comment.
46 | void add_unmatched_comment(cpp_doc_comment comment)
47 | {
48 | file_->comments_.push_back(std::move(comment));
49 | }
50 |
51 | /// \returns The not yet finished file.
52 | cpp_file& get() noexcept
53 | {
54 | return *file_;
55 | }
56 |
57 | /// \effects Registers the file in the [cppast::cpp_entity_index]().
58 | /// It will use the file name as identifier.
59 | /// \returns The finished file, or `nullptr`, if that file was already registered.
60 | std::unique_ptr finish(const cpp_entity_index& idx) noexcept
61 | {
62 | auto res = idx.register_file(cpp_entity_id(file_->name()), type_safe::ref(*file_));
63 | return res ? std::move(file_) : nullptr;
64 | }
65 |
66 | private:
67 | std::unique_ptr file_;
68 | };
69 |
70 | /// \returns The unmatched documentation comments.
71 | type_safe::array_ref unmatched_comments() const noexcept
72 | {
73 | return type_safe::ref(comments_.data(), comments_.size());
74 | }
75 |
76 | private:
77 | cpp_file(std::string name) : cpp_entity(std::move(name)) {}
78 |
79 | /// \returns [cpp_entity_type::file_t]().
80 | cpp_entity_kind do_get_entity_kind() const noexcept override;
81 |
82 | std::vector comments_;
83 | };
84 |
85 | /// \exclude
86 | namespace detail
87 | {
88 | struct cpp_file_ref_predicate
89 | {
90 | bool operator()(const cpp_entity& e);
91 | };
92 | } // namespace detail
93 |
94 | /// A reference to a [cppast::cpp_file]().
95 | using cpp_file_ref = basic_cpp_entity_ref;
96 | } // namespace cppast
97 |
98 | #endif // CPPAST_CPP_FILE_HPP_INCLUDED
99 |
--------------------------------------------------------------------------------
/include/cppast/cpp_forward_declarable.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_FORWARD_DECLARABLE_HPP_INCLUDED
5 | #define CPPAST_CPP_FORWARD_DECLARABLE_HPP_INCLUDED
6 |
7 | #include
8 |
9 | #include
10 |
11 | #include
12 | #include
13 |
14 | namespace cppast
15 | {
16 | /// Mixin base class for all entities that can have a forward declaration.
17 | ///
18 | /// Examples are [cppast::cpp_enum]() or [cppast::cpp_class](),
19 | /// but also [cppast::cpp_function_base]().
20 | /// Those entities can have multiple declarations and one definition.
21 | class cpp_forward_declarable
22 | {
23 | public:
24 | /// \returns Whether or not the entity is the definition.
25 | bool is_definition() const noexcept
26 | {
27 | return !definition_.has_value();
28 | }
29 |
30 | /// \returns Whether or not the entity is "just" a declaration.
31 | bool is_declaration() const noexcept
32 | {
33 | return definition_.has_value();
34 | }
35 |
36 | /// \returns The [cppast::cpp_entity_id]() of the definition,
37 | /// if the current entity is not the definition.
38 | const type_safe::optional& definition() const noexcept
39 | {
40 | return definition_;
41 | }
42 |
43 | /// \returns A reference to the semantic parent of the entity.
44 | /// This applies only to out-of-line definitions
45 | /// and is the entity which owns the declaration.
46 | const type_safe::optional& semantic_parent() const noexcept
47 | {
48 | return semantic_parent_;
49 | }
50 |
51 | /// \returns The name of the semantic parent, if it has one,
52 | /// else the empty string.
53 | /// \notes This may include template parameters.
54 | std::string semantic_scope() const noexcept
55 | {
56 | return type_safe::copy(semantic_parent_.map(&cpp_entity_ref::name)).value_or("");
57 | }
58 |
59 | protected:
60 | /// \effects Marks the entity as definition.
61 | /// \notes If it is not a definition,
62 | /// [*set_definition]() must be called.
63 | cpp_forward_declarable() noexcept = default;
64 |
65 | ~cpp_forward_declarable() noexcept = default;
66 |
67 | /// \effects Sets the definition entity,
68 | /// marking it as a forward declaration.
69 | void mark_declaration(cpp_entity_id def) noexcept
70 | {
71 | definition_ = std::move(def);
72 | }
73 |
74 | /// \effects Sets the semantic parent of the entity.
75 | void set_semantic_parent(type_safe::optional semantic_parent) noexcept
76 | {
77 | semantic_parent_ = std::move(semantic_parent);
78 | }
79 |
80 | private:
81 | type_safe::optional semantic_parent_;
82 | type_safe::optional definition_;
83 | };
84 |
85 | /// \returns Whether or not the given entity is a definition.
86 | bool is_definition(const cpp_entity& e) noexcept;
87 |
88 | /// Gets the definition of an entity.
89 | /// \returns A [ts::optional_ref]() to the entity that is the definition.
90 | /// If the entity is a definition or not derived from [cppast::cpp_forward_declarable]() (only valid
91 | /// for the generic entity overload), returns a reference to the entity itself. Otherwise lookups
92 | /// the definition id and returns it. \notes The return value will only be `nullptr`, if the
93 | /// definition is not registered. \group get_definition
94 | type_safe::optional_ref get_definition(const cpp_entity_index& idx,
95 | const cpp_entity& e);
96 | /// \group get_definition
97 | type_safe::optional_ref get_definition(const cpp_entity_index& idx,
98 | const cpp_enum& e);
99 | /// \group get_definition
100 | type_safe::optional_ref get_definition(const cpp_entity_index& idx,
101 | const cpp_class& e);
102 | /// \group get_definition
103 | type_safe::optional_ref get_definition(const cpp_entity_index& idx,
104 | const cpp_variable& e);
105 | /// \group get_definition
106 | type_safe::optional_ref get_definition(const cpp_entity_index& idx,
107 | const cpp_function_base& e);
108 |
109 | } // namespace cppast
110 |
111 | #endif // CPPAST_CPP_FORWARD_DECLARABLE_HPP_INCLUDED
112 |
--------------------------------------------------------------------------------
/include/cppast/cpp_friend.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_FRIEND_HPP_INCLUDED
5 | #define CPPAST_CPP_FRIEND_HPP_INCLUDED
6 |
7 | #include
8 |
9 | #include
10 | #include
11 | #include
12 |
13 | namespace cppast
14 | {
15 | /// A [cppast::cpp_entity]() representing a friend declaration.
16 | ///
17 | /// It can either declare or define a `friend` function (template), declare a `friend` class,
18 | /// or refer to an existing type.
19 | class cpp_friend : public cpp_entity, private cpp_entity_container
20 | {
21 | public:
22 | static cpp_entity_kind kind() noexcept;
23 |
24 | /// \returns A newly created friend declaring the given entity as `friend`.
25 | /// \notes The friend declaration itself will not be registered,
26 | /// but the referring entity is.
27 | static std::unique_ptr build(std::unique_ptr e)
28 | {
29 | return std::unique_ptr(new cpp_friend(std::move(e)));
30 | }
31 |
32 | /// \returns A newly created friend declaring the given type as `friend`.
33 | /// \notes It will not be registered.
34 | static std::unique_ptr build(std::unique_ptr type)
35 | {
36 | return std::unique_ptr(new cpp_friend(std::move(type)));
37 | }
38 |
39 | /// \returns An optional reference to the entity it declares as friend, or `nullptr`.
40 | type_safe::optional_ref entity() const noexcept
41 | {
42 | if (begin() == end())
43 | return nullptr;
44 | return type_safe::ref(*begin());
45 | }
46 |
47 | /// \returns An optional reference to the type it declares as friend, or `nullptr`.
48 | type_safe::optional_ref type() const noexcept
49 | {
50 | return type_safe::opt_ref(type_.get());
51 | }
52 |
53 | private:
54 | cpp_friend(std::unique_ptr e) : cpp_entity("")
55 | {
56 | add_child(std::move(e));
57 | }
58 |
59 | cpp_friend(std::unique_ptr type) : cpp_entity(""), type_(std::move(type)) {}
60 |
61 | cpp_entity_kind do_get_entity_kind() const noexcept override;
62 |
63 | std::unique_ptr type_;
64 |
65 | friend cpp_entity_container;
66 | };
67 | } // namespace cppast
68 |
69 | #endif // CPPAST_CPP_FRIEND_HPP_INCLUDED
70 |
--------------------------------------------------------------------------------
/include/cppast/cpp_function_template.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_FUNCTION_TEMPLATE_HPP_INCLUDED
5 | #define CPPAST_CPP_FUNCTION_TEMPLATE_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | /// A [cppast::cpp_entity]() modelling a function template.
13 | class cpp_function_template final : public cpp_template
14 | {
15 | public:
16 | static cpp_entity_kind kind() noexcept;
17 |
18 | /// Builder for [cppast::cpp_function_template]().
19 | class builder : public basic_builder
20 | {
21 | public:
22 | using basic_builder::basic_builder;
23 | };
24 |
25 | /// A reference to the function that is being templated.
26 | const cpp_function_base& function() const noexcept
27 | {
28 | return static_cast(*begin());
29 | }
30 |
31 | private:
32 | cpp_function_template(std::unique_ptr func)
33 | : cpp_template(std::unique_ptr(func.release()))
34 | {}
35 |
36 | cpp_entity_kind do_get_entity_kind() const noexcept override;
37 |
38 | friend basic_builder;
39 | };
40 |
41 | /// A [cppast::cpp_entity]() modelling a function template specialization.
42 | class cpp_function_template_specialization final : public cpp_template_specialization
43 | {
44 | public:
45 | static cpp_entity_kind kind() noexcept;
46 |
47 | /// Builder for [cppast::cpp_function_template_specialization]().
48 | class builder
49 | : public specialization_builder
50 | {
51 | public:
52 | using specialization_builder::specialization_builder;
53 |
54 | private:
55 | using specialization_builder::add_parameter;
56 | };
57 |
58 | /// A reference to the function that is being specialized.
59 | const cpp_function_base& function() const noexcept
60 | {
61 | return static_cast(*begin());
62 | }
63 |
64 | private:
65 | cpp_function_template_specialization(std::unique_ptr func,
66 | cpp_template_ref primary)
67 | : cpp_template_specialization(std::unique_ptr(func.release()), primary)
68 | {}
69 |
70 | cpp_entity_kind do_get_entity_kind() const noexcept override;
71 |
72 | friend specialization_builder;
73 | };
74 | } // namespace cppast
75 |
76 | #endif // CPPAST_CPP_FUNCTION_TEMPLATE_HPP_INCLUDED
77 |
--------------------------------------------------------------------------------
/include/cppast/cpp_language_linkage.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_LANGUAGE_LINKAGE_HPP_INCLUDED
5 | #define CPPAST_CPP_LANGUAGE_LINKAGE_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | /// A [cppast::cpp_entity]() modelling a language linkage.
13 | class cpp_language_linkage final : public cpp_entity,
14 | public cpp_entity_container
15 | {
16 | public:
17 | static cpp_entity_kind kind() noexcept;
18 |
19 | /// Builds a [cppast::cpp_language_linkage]().
20 | class builder
21 | {
22 | public:
23 | /// \effects Sets the name, that is the kind of language linkage.
24 | explicit builder(std::string name) : linkage_(new cpp_language_linkage(std::move(name))) {}
25 |
26 | /// \effects Adds an entity to the language linkage.
27 | void add_child(std::unique_ptr child)
28 | {
29 | linkage_->add_child(std::move(child));
30 | }
31 |
32 | /// \returns The not yet finished language linkage.
33 | cpp_language_linkage& get() const noexcept
34 | {
35 | return *linkage_;
36 | }
37 |
38 | /// \returns The finalized language linkage.
39 | /// \notes It is not registered on purpose as nothing can refer to it.
40 | std::unique_ptr finish()
41 | {
42 | return std::move(linkage_);
43 | }
44 |
45 | private:
46 | std::unique_ptr linkage_;
47 | };
48 |
49 | /// \returns `true` if the linkage is a block, `false` otherwise.
50 | bool is_block() const noexcept;
51 |
52 | private:
53 | using cpp_entity::cpp_entity;
54 |
55 | cpp_entity_kind do_get_entity_kind() const noexcept override;
56 | };
57 | } // namespace cppast
58 |
59 | #endif // CPPAST_CPP_LANGUAGE_LINKAGE_HPP_INCLUDED
60 |
--------------------------------------------------------------------------------
/include/cppast/cpp_member_variable.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_MEMBER_VARIABLE_HPP_INCLUDED
5 | #define CPPAST_CPP_MEMBER_VARIABLE_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | /// Base class for all kinds of member variables.
13 | class cpp_member_variable_base : public cpp_entity, public cpp_variable_base
14 | {
15 | public:
16 | /// \returns Whether or not the member variable is declared `mutable`.
17 | bool is_mutable() const noexcept
18 | {
19 | return mutable_;
20 | }
21 |
22 | cpp_member_variable_base(std::string name, std::unique_ptr type,
23 | std::unique_ptr def, bool is_mutable)
24 | : cpp_entity(std::move(name)), cpp_variable_base(std::move(type), std::move(def)),
25 | mutable_(is_mutable)
26 | {}
27 |
28 | private:
29 | bool mutable_;
30 | };
31 |
32 | /// A [cppast::cpp_entity]() modelling a C++ member variable.
33 | class cpp_member_variable final : public cpp_member_variable_base
34 | {
35 | public:
36 | static cpp_entity_kind kind() noexcept;
37 |
38 | /// \returns A newly created and registered member variable.
39 | /// \notes `def` may be `nullptr` in which case there is no member initializer provided.
40 | static std::unique_ptr build(const cpp_entity_index& idx, cpp_entity_id id,
41 | std::string name,
42 | std::unique_ptr type,
43 | std::unique_ptr def,
44 | bool is_mutable);
45 |
46 | private:
47 | using cpp_member_variable_base::cpp_member_variable_base;
48 |
49 | cpp_entity_kind do_get_entity_kind() const noexcept override;
50 | };
51 |
52 | /// A [cppast::cpp_entity]() modelling a C++ bitfield.
53 | class cpp_bitfield final : public cpp_member_variable_base
54 | {
55 | public:
56 | static cpp_entity_kind kind() noexcept;
57 |
58 | /// \returns A newly created and registered bitfield.
59 | /// \notes It cannot have a member initializer, i.e. default value.
60 | static std::unique_ptr build(const cpp_entity_index& idx, cpp_entity_id id,
61 | std::string name, std::unique_ptr type,
62 | unsigned no_bits, bool is_mutable);
63 |
64 | /// \returns A newly created unnamed bitfield.
65 | /// \notes It will not be registered, as it is unnamed.
66 | static std::unique_ptr build(std::unique_ptr type, unsigned no_bits,
67 | bool is_mutable);
68 |
69 | /// \returns The number of bits of the bitfield.
70 | unsigned no_bits() const noexcept
71 | {
72 | return bits_;
73 | }
74 |
75 | private:
76 | cpp_bitfield(std::string name, std::unique_ptr type, unsigned no_bits,
77 | bool is_mutable)
78 | : cpp_member_variable_base(std::move(name), std::move(type), nullptr, is_mutable),
79 | bits_(no_bits)
80 | {}
81 |
82 | cpp_entity_kind do_get_entity_kind() const noexcept override;
83 |
84 | unsigned bits_;
85 | };
86 | } // namespace cppast
87 |
88 | #endif // CPPAST_CPP_MEMBER_VARIABLE_HPP_INCLUDED
89 |
--------------------------------------------------------------------------------
/include/cppast/cpp_static_assert.hpp:
--------------------------------------------------------------------------------
1 | // Copyright (C) 2017-2023 Jonathan Müller and cppast contributors
2 | // SPDX-License-Identifier: MIT
3 |
4 | #ifndef CPPAST_CPP_STATIC_ASSERT_HPP_INCLUDED
5 | #define CPPAST_CPP_STATIC_ASSERT_HPP_INCLUDED
6 |
7 | #include
8 | #include
9 |
10 | namespace cppast
11 | {
12 | class cpp_static_assert : public cpp_entity
13 | {
14 | public:
15 | static cpp_entity_kind kind() noexcept;
16 |
17 | /// \returns A newly created `static_assert()` entity.
18 | /// \notes It will not be registered as nothing can refer to it.
19 | static std::unique_ptr