Giter Site home page Giter Site logo

cppast's Introduction

logo

standardese

License: MIT Test Gitter

The nextgen Doxygen for C++


Standardese aims to be a nextgen Doxygen. It consists of two parts: a library and a command line tool.

The library aims at becoming the documentation frontend that can be easily extended and customized. It parses C++ code with the help of libclang and provides access to it.

The tool drives the library to generate documentation for user-specified files. It supports a couple of output formats including Markdown and HTML as well as experimental Latex and Man pages.

Read more in the introductory blog posts.

Basic example

Consider the following C++ header file named swap.hpp:

#include <type_traits>

namespace std
{

    /// \effects Exchanges values stored in two locations.
    /// \requires Type `T` shall be `MoveConstructible` and `MoveAssignable`.
    template <class T>
    void swap(T &a, T &b) noexcept(is_nothrow_move_constructible<T>::value &&
                                    is_nothrow_move_assignable<T>::value);
}

This will generate the following documentation:

Header file swap.hpp

namespace std
{
    template <class T>
    void swap(T& a, T& b) noexcept(is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value);
}

Function std::swap

template <class T>
void swap(T& a, T& b) noexcept(is_nothrow_move_constructible<T>::value && is_nothrow_move_assignable<T>::value);

Effects: Exchanges values stored in two locations.

Requires: Type T shall be MoveConstructible and MoveAssignable.

The example makes it already clear: Standardese aims to provide a documentation in a similar way to the C++ standard - hence the name.

This means that it provides commands to introduce so called sections in the documentation. The current sections are all the C++ standard lists in [structure.specifications]/3 like \effects, \requires, \returns and \throws.

For a more complete example check out foonathan's Meeting C++ Lightning Talk.

Installation

Your usual software distribution might already provide standardese. If it does, we recommend to try that path first. Otherwise, here are some alternative paths to install standardese.

conda

A recent version of standardese is packaged by conda-forge for Windows, Linux, and macOS.

  • install a recent version of Miniconda
  • enable conda-forge channels
  • create a new environment with standardese: conda create -n standardese standardese
  • activate your new environment: conda activate standardese

Now standardese should be available on that command line.

Docker

Standardese is also packaged for docker at standardese/standardese.

Building From Source

To build standardese run:

mkdir build
cd build
cmake ../
cmake --build . --target standardese_tool

The result is the executable tool/standardese.

The build system should take care of all dependencies automatically, except for two: Boost and libclang.

We need Boost.ProgramOptions and Boost.Filesystem as statically linked binaries. If they are installed, they should be found automatically.

We also need libclang. If you are under a Linux system, the llvm-config binary should be found automatically, otherwise things are a bit harder. Read the cppast build instructions for more information, they also apply here.

Documentation

If you need help or encounter a problem please contact us on gitter.

Basic Commandline Usage

Basic usage is: standardese [options] inputs, see standardese --help for available options.

The inputs can be both files or directories, in case of directory each file is documented, unless an input option is specified (see below). The tool will currently generate a corresponding Markdown file with the documentation for each file it gets as input.

Note: You only need and should give header files to standardese. The source files are unnecessary.

The options listed under "Generic options:" must be given to the commandline. They include things like getting the version, enabling verbose output (please provide it for issues) or passing an additional configuration file.

The options listed under "Configuration" can be passed both to the commandline and to the config file. They are subdivided into various sections:

  • The input.* options are related to the inputs given to the tool. They can be used to filter, both the files inside a directory and the entities in the source code.

  • The compilation.* options are related to the compilation of the source. You can pass macro definitions and include directories as well as a commands_dir. This is a directory where a compile_commands.json file is located. standardese will pass all the flags of all files to libclang.

This has technical reasons because you give header files whereas the compile commands use only source files.

  • The comment.* options are related to the syntax of the documentation markup. You can set both the leading character and the name for each command, for example.

  • The output.* options are related to the output generation. It contains an option to set the human readable name of a section, for example.

The configuration file you can pass with --config uses an INI style syntax, e.g:

[compilation]
include_dir=foo/
macro_definition=FOO

[input]
blacklist_namespace=detail
extract_private=true

Basic Docker Usage

For CI purposes, the standardese/standardese image provides a standardese binary at /usr/local/bin/standardese.

To process local files with the standardese docker image, you need to mount your headers into the docker container. If you need additional headers to be present, you can mount them into the docker container and make them available to standardese with the -I switch. Note that standardese writes its output files to /home/standardese which you additionally might want to mount an output directory to.

A typical invocation might therefore look like this:

mkdir output
docker run -v `pwd`/headers:/headers:ro -v /my/include:/includes:ro -v `pwd`/output:/home/standardese standardese/standardese standardese /headers -I /includes --compilation.standard=c++17

Basic CMake Usage

To ease the compilation options, you can call standardese from CMake like so:

find_package(standardese REQUIRED) # find standardese after installation

# generates a custom target that will run standardese to generate the documentation
standardese_generate(my_target CONFIG path/to/config_file
                     INCLUDE_DIRECTORY ${my_target_includedirs}
                     INPUT ${headers})

It will use a custom target that runs standardese. You can specify the compilation options and inputs directly in CMake to allow shared variables. All other options must be given in a config file.

If you don't have standardese on the PATH, you can also include it directly:

set(STANDARDESE_TOOL /path/to/standardese/binary)
include(/path/to/standardese/standardese-config.cmake)

# call standardese_generate() like normal

See standardese-config.cmake for a documentation of standardese_generate().

Documentation syntax overview

standardese looks for documentation comments as shown in the following example:

/// A regular C++ style documentation comment.
/// Multiple C++ style comments are merged automatically.
///   This line has *two* leading whitespaces because one is always skipped.

//! A C++ style comment using an exclamation mark.
/// It will also merge with other C++ style comments.
//! But don't worry, also with the exclamation mark styles.

/** A C style documentation commment. */
/** This is a different comment, they aren't merged.
 * But you can be fancy with the star at the beginning of the line.
 * It will ignore all whitespace, the star and the first following whitespace.
 */

/*! You can also use an exclamation mark. */
/// But neither will merge with any other comment.

int x; //< An end-of-line comment.
/// It will merge with C++ style comments.
int y; //< But this is a different end-of-line comment.

A comment corresponds to the entity on the line directly below or on the same line. You can document all entities that way except files (use file command), namespaces (use entity command), and inline entities such as parameters or base classes (use param/tparam/base command or entity command).

Inside the comment you can use arbitrary* Markdown* in the documentation comments and it will be rendered appropriately.

The Markdown flavor used is CommonMark. standardese does not support inline HTML (for obvious reasons) or images. Inline HTML that isn't a raw HTML block will be treated as literal text. This allows writing vector<T> without markup or escaping in the comment, for example.

Note: CommonMark allows hard line breaks with a backslash at the end of the line. But the C preprocessor uses a backslash to combine multiple lines into one. For that reason you cannot use a backslash there, instead you can use a forward slash.

Linking

To link to an entity, use the syntax [link-text](<> "unique-name") (a CommonMark link with empty URL and a title of unique-name). If you don't want a special link-text, this can be shortened to [unique-name]() (a CommonMark link with empty URL and the name of an entity as text). You can also use an URL of the following form [link-text](standardese://unique-name/ "optional-title") (a normal CommonMark link with the standardese:// protocol, the '/' at the end is important). In either case standardese will insert the correct URL by searching for the entity with the given unique-name.

The unique-name of an entity is the name with all scopes, i.e. foo::bar::baz.

  • For templates (but not function templates) you need to append all parameters, i.e. foo<A, B, C>.

  • For functions you need to append the signature (parameter types and cv and ref qualifier), i.e. func(), bar(int,char) or type::foo() const &&. If the signature is (), you can omit it.

  • For (template) parameters it is of the form function-unique-name.parameter-name

  • For base classes it is of the form derived-class::base-class

The unique-name doesn't care about whitespace, so bar(const char*), bar(const char *) and bar (constchar*) are all the same. Because it is sometimes long and ugly, you can override the unique name via the unique_name command (see below).

For example you can override bar(long, list, of, parameters) to bar(). But keep in mind that it must be unique with regard to all overloads etc. Usually numbering would be a good choice, so bar() (1) or similar.

You can also use a short unique-name if there aren't multiple entities resolved to the same short name. The short name is the unique-name but without a signature or template parameters, i.e. for foo<T>::func<U>(int) const, the short name is foo::func.

Name lookup

If you prefix a unique name with * or ?, this will do a name lookup, looking for the entity. This only works inside a comment associated with an entity, not in template files etc.

It does a similar search to the actual name lookup in C++: It starts at the associated entity and appends its scope to the partial unique name given, going to the next higher entity if no matching entity can be found, etc.

For example:

/// a.
struct a {};

namespace ns
{
    /// ns::a.
    struct a {};

    /// [This will link to ::a, no lookup here](standardese://a/).
    /// [This will link to ns::a](standardese://*a/).
    void foo();

    /// b
    template <typename T>
    struct b
    {
        /// c.
        void c();

        /// [This will link to ns::b<T>::c()](standardese://*c/).
        void foo();
    };
}
External links

You can also link to external documentations via the tool option --comment.external_doc prefix=url. All unique-names starting with prefix will be linked to the url. If the url contains two dollar signs $$, they will be replaced by the unique-name. By default the tool supports http://en.cppreference.com/w/ with a prefix of std:: by default.

You can override to a different URL by specifying --comment.external_doc std::=new-url.

Special commands

standardese adds its own sets of special commands. A command is introduced by the command character (a backslash by default) at the beginning of each line in the comment.

There are three kinds of special commands: commands, sections and inlines.


A command is used to control the documentation generation in some way. A text that begins with a command doesn't appear in the output documentation at all.

There are the following commands:

  • verbatim - This command isn't like the other commands. It can happen anywhere in a line — i.e. where CommonMark allows an inline entity like emphasis. The text following the command until an end command or the end of the line will be inserted as-is into the output.

  • end - This command ends the currently active section, see below. This can be used to extend a section to multiple paragraphs.

  • exclude {arg} - Manually excludes an entity or part of it from the documentation. If you don't specify an argument, it won't appear at all, not even in the synopsis. It is as if the entity never existed in the first place. If you specify return as argument, the return type of the function will be hidden in the synopsis. If you specify target as argument, the target of the namespace/type alias or underlying type of the enum will be hidden in the synopsis.

  • unique_name {name} - Overrides the unique name of an entity (e.g. for linking):

    /// Some documentation.
    /// I can now link to `bar()` by writing [foo]().
    ///
    /// \unique_name foo
    void bar(int a, int c);

    Note that if you override the unique name of a parent entity, this will also affect the unique names of child entities. If the unique name starts with '*' or '?', it will be a relative unique name, i.e. the unique name of the parent entity will be prepended to it (with seperator '::' if needed).

  • output_name {name} - Overrides the output name of a file. This will only change the base name, the doc_ prefix and extension are still handled separately. Useful if there are multiple files with the same base name in a project, e.g a .hpp and .h header.

  • synopsis {string} - Overrides the synopsis in the output. You can pass any string that will be rendered instead of the actual synopsis. Use \n to render a newline and use \t to render a tab.

  • synopsis_return {string} - Like synopsis, but only overrides the return type of the function.

  • group <name> [heading] - Add the entity to a member group. A member group consists of multiple entities that are direct members of the same entity (i.e. class, file, namespace,...) which will be grouped together in the output. For example:

    /// \group foo A heading
    /// This is in the group `foo`.
    /// Because this is the first entity in the group, it will be the "master".
    /// the group comment will be this comment, the group unique name will be this unique name, ...
    /// The optional heading (everything after the first whitespace) will be shown as heading in the output.
    void func();
    
    /// \group foo
    /// This entity will be added to the same group.
    /// As it is not the first occurence of the group,
    /// this comment here will be ignored.
    /// But you can still use commands to modify this entity.
    void func(int);
    
    /// This entity is not part of the group.
    void func(char);
    
    /// \group foo
    /// But this one is (again, comment ignored).
    void func(short);

    This will write the synopsis of all group members together and use the documentation text of the first entity. The group name only needs to be unique for one given scope. Note: It will only show inline documentation for children, so don't use it on containers.

  • module {name} - Add the entity to a module. A module is just a way to group entities together, it will be inherited by all children. There is no need to define a module, but if you do, simply use the command in first place of a module and you can add documentation for it:

    /// This is an entity in the module 'bar'.
    /// \module bar
    void foo();
    
    /// \module bar
    /// This is the documentation for the module 'bar',
    /// because the command was the first one.
  • output_section {name} - Generates a little section comment in the synopsis above the entity. This is implictly used for member groups with the group name as output section name, if the option output.show_group_output_section is true (the default). If a member group name starts with '-', it will never be used (the minus won't be shown). Given the following input:

    /// Some int getter.
    /// \output_section Getter functions
    int get_i();
    
    /// Some float getter.
    float get_f();
    
    /// Some int setter.
    /// \output_section Setter functions
    void set_i(int val);
    
    /// Some float setter.
    void set_f(float f);

    It will generate a synopsis like this:

    //=== Getter functions ===//
    int get_i();
    
    float get_f();
    
    //=== Setter functions ===//
    void set_i(int val);
    
    void set_f(float f);
  • entity {unique-name} - If put in the first place of a comment, names the entity to document, this allows "remote" comments:

    void foo();
    
    /// \entity foo
    /// This comment has no corresponding entity.
    /// But the command specifies the entity it will belong to.

    It also mixes with unique_name as you might expect.

  • file - similar to entity, marks a comment that describes this entire file.


A section is the basic way of standardese documentation. It supports all the sections the C++ standard uses, as explained in the example. Those sections will create a paragraph in the output prefixed with a human readable name. There are two special sections, brief and details. They are not labeled in the output.

Unlike for a command text following a section is included in the output. A section is active for the rest of the paragraph, a hard line break or until another special command is encountered. Any brief sections will be merged together automatically.

If you don't specify a section for a paragraph, the first paragraph will be implictly brief, all others implictly details.

/// \brief This text is brief.
///
/// This is implictly details.
/// \effects This is effects.
/// This is still effects.
/// \returns This is returns./
/// Due to the hard break this is details again.
///
/// \notes This is notes.
/// \notes This is a different notes.

A inline is a special kind of command. They are param, tparam and base and used to document (template) parameters and base classes, because you cannot put a corresponding comment there. As such they are shorthands for the \entity unique-name command. They are followed by the name of entity they refer to.

The inline and argument is stripped from the text. The rest of the line will be treated as brief documentation. Like a section, an inline ends when a new special command or hard line break is encountered or a paragraph ends. You can include sections in inlines, however.

For example:

/// Normal documentation for the function.
///
/// \param foo Brief documentation for the parameter `foo`.
/// It continues here with details.
/// \param bar
/// \exclude
///
/// The `\exclude` is part of the documentation for `bar`.
void func(int foo, int bar);

Acknowledgements

This project was started by Jonathan @foonathan Müller who wrote most of the code and maintains the cppast library that we heavily rely on.

Thanks a lot to our contributors and supporters:

  • Manu @Manu343726 Sánchez, as always

  • Jason @jpleau Pleau, for much feedback and requests on Gitter

  • Mark @DarkerStar Gibbs, for feature suggestions

  • Tristan @tcbrindle Brindle, for (better) clang support

  • Marek @mkurdej Kurdej, for (better) MSVC support

  • Victor @vitaut Zverovich, for bugfixes

  • John @johnmcfarlane McFarlane, for issue reporting

  • Filipe @verri Verri, for maintaining the AUR package

  • @topisani, for issue reporting and bugfixes

  • Trim @bresilla Bresilla, for our logo

  • Reiner Eiteljoerge and Sina for having supported development through Patreon.

And everyone else who shares and uses this project!

cppast's People

Contributors

azure-pipelines[bot] avatar bkryza avatar carlosnihelton avatar chibidev avatar firefly35 avatar firodj avatar foonathan avatar grumbel avatar manu343726 avatar metalslime0 avatar minhlu12 avatar nealhow avatar ozars avatar rokups avatar saraedum avatar siennathesane avatar staticintlucas avatar sztomi avatar tobiashienzsch avatar topisani avatar ubsan avatar waitingtocompile avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cppast's Issues

Member class typedefs and weird ast content

cppast version: Manu343726@b58405b
libclang parser
libclang version: 4.0.0
Explanation of the error:

I'm trying to parse and examine the contents of classes declared as:

typdef struct
{
    int a, b, c;
} Foo;

I've written a function that tries to extract the cpp_class entity out of a cpp_type_alias, trying to match my requirements (anonymous struct type alias, struct declared in that same header, etc). If the type alias entity matches, getting the aliased class would be equivalent to:

type_safe::optional_ref<const cppast::cpp_class> class_typedef(index, typedef_entity)
{
    return type_safe::cref(typedef_entity.underlying_type().entity().get(index)[0]);
}

Things get interesting once I put the typedef struct as a class member (Which is my target use case):

struct Class
{
    typedef struct
    {
        int a, b;
    } InnerTypedefClass;

    int a, b;
};

My current AST "scanner" currently handles classes and enums only, so a typedef entity like TypedefClass there is ignored.

If I introduce a case for typedefs as members and apply the typedef struct matching logic described earlier, I successfully find a class declaration node. But also a class declaration node is automagically added as a member of the Class class.

My class members scanning system us just a plain call to visit on the class node (See https://gitlab.com/Manu343726/tinyrefl/blob/master/tool/tool.cpp#L267), and it's from inside that visitor that the typedef check algorithm is run (An extra case for the switch for the typedef):

case cppast::cpp_entity_kind::cpp_type_alias:
    const auto alias = class_typedef(child);
    if(alias) std::cout << " - class typedef " << child.name() << "\n";
    break;

...

With that change only (Note there's nothing done with the alias in the switch side), I see a TypedefClass class declaration appearing as class declaration member of Class, as if already were a child of the class. Note also I get the right class name (from the typedef pov, not an empty class name). Tool output:

    - (class typedef) TypedefStruct
    - (class) TypedefStruct (declaration) [attributes: ] <-- MAGIC

That's fairly weird, but maybe I'm misunderstanding something about how the AST works.

After that, I said "Ok, if a child is automatically added to the class, let's take advantage of that". Now I register typedef classes that are automatically added to my parent class to be scanned later. When I run an scan on TypedefStruct cpp_class entity, I get no members, and parent class members as base classes of TypedefStruct:

 # my_namespace::MyClass [attributes: ]
    - (member) f [attributes: ]
    - (member) str [attributes: ]
    - (enum) Enum [attributes: ]
    - (class) Foo (definition) [attributes: ]
    - (class) InnerClassWithMembers (definition) [attributes: ]
[warning] Found class with empty name at my_namespace::MyClass
    - (class typedef) TypedefStruct
    - (class) TypedefStruct (declaration) [attributes: ]
    - (member) innerClassInstance [attributes: ]
    - (base) my_namespace::BaseClass
    - (base) my_namespace::Foo
 # my_namespace::MyClass::TypedefStruct [attributes: ]
    - (base) my_namespace::MyClass::Foo                                  // WTF ???
    - (base) my_namespace::MyClass::InnerClassWithMembers // WTF ???
    - (base) my_namespace::MyClass::                                        // WTF ??? 
    - (base) my_namespace::MyClass::TypedefStruct                  // WHAAAAT ???
    - (base) my_namespace::MyClass::innerClassInstance         // WTF ???
    - (base) my_namespace::MyClass::private                             // WTF ???
    - (base) my_namespace::MyClass::_private                           // WTF ???

base classes are retrieved with cpp_class::bases().

I will try to get a minimal repo ASAP.

wrong assert for multiple definition for redundant conversion to related types

  • cppast version: 70ac5cf
  • parser: libclang_parser
  • clang version: 4.0

Explanation of the error.
[debug assert] /home/bf/devel/asttoy/cppast/src/cpp_entity_index.cpp:25: Assertion '!value.is_definition' failed - duplicate entity registration.

Input:

#include <memory>

struct A {
  virtual ~A() = default;
};
struct B : A {};

struct M
{
  operator std::unique_ptr<B>() { return nullptr; }
  operator std::unique_ptr<A>() { return nullptr; }
};

Changing the above to raw pointers makes the problem go away.

Input flags: -std=c++14

Output of cppast -v <input>

[preprocessor] [debug] /tmp/t.cpp: parsing include 'memory'
[libclang parser] [debug] A: parsing cursor of type 'StructDecl'
[libclang parser] [debug] ~A(): parsing cursor of type 'CXXDestructor'
[libclang parser] [debug] B: parsing cursor of type 'StructDecl'
[libclang parser] [debug] M: parsing cursor of type 'StructDecl'
[libclang parser] [debug] operator unique_ptr(): parsing cursor of type 'CXXConversion'
[libclang parser] [debug] operator unique_ptr(): parsing cursor of type 'CXXConversion'
[debug assert] /home/bf/devel/asttoy/cppast/src/cpp_entity_index.cpp:25: Assertion '!value.is_definition' failed - duplicate entity registration.

Compilation database parsing

I'm reading a compilation database, and I don't want to use the flags abstractions to supply the flags to the config. I would have to parse the string flags just have cppast put the same string together. So, is there a way to set the directly?

Inconsistency when using C++11 `friend` syntax for types

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 4.0

C++11 introduced a new syntax to mark types as friends, friend foo instead of friend class foo.
When parsing friend foo it will be treated as if friend class foo was written.
But when parsing friend ns::foo, it will be detected properly.

`decltype` expression is always `cpp_unexposed_expression`

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

The expression inside a decltype() will always be a cpp_unexposed_expression and the type of the expression is not exposed either. On a related note, cpp_decltype_auto_type will never be created, decltype(auto) will create a simple cpp_auto_type instead.

Parsing function bodies

I've run the example and it fits exactly what I'm looking for, the only problem I have is that function bodies aren't parsed. Do you have a roadmap of when this might be implemented? Cheers.

Parsing fails on array function arguments

  • cppast version: latest
  • clang version: 5.0.1

test.cpp:

void foo(const char* const items[]);

cppast -v test.cpp:

[libclang parser] [debug] test.cpp:1: parsing cursor of type 'FunctionDecl'
[libclang parser] [error] test.cpp:1: expected '[', got exhausted stream
AST for 'test.cpp':
+-foo (function): `void foo();`

test.cpp.pp:

void foo(const char* const items[]);

Attribute list incorrect with declarators

Thanks for implementing attributes! I was initially the guy requesting them on your blog, so I am super happy! (the readme still says no attributes, so that is why it took me sometime to start testing)

  • cppast version: latest
  • parser: libclang_parser
  • clang version: 5.0

Input:

struct [[reflect]] my_struct{
  [[property1]] int foo;
} [[property2]] bar;

Input flags: -std=c++1z

For this struct, my_struct will have 1 attribute (correct), foo will have 1 attribute (correct) and bar will have 3 attributes [reflect, property1, property2], which I think is incorrect, it should only have 1 attribute (property2). Of course this is easily worked around by moving the declarator.

A possibly separate issue is that attributes after declarators are ignored.

Dependent types are always unexposed

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

The type cpp_depedent_type will never be created, instead a cpp_unexposed_type.

Problems with spaces in paths

This is a very odd issue. I have encountered it on my local windows VM while CI on appveyor does not have this issue. Same code is used in both places.

Using cppast causes application to terminate because clang executable invocation returns non-zero return code. This happens because clang include directory is passed unquoted so -IC:/Program is treated as include directory and Files/LLVM/... is treated as source file which wont be found and cause clang to fail.

I have made a workaround quoting paths that contain spaces: rbfx/rbfx@7f7423c
For some reason quoting all paths caused parsing errors in my project. Given obscurity of the issue i am not sure if this is a right fix. If its good enough - let me know and i will submit a PR. If not - please look into it whenever possible :)

Edit: just realized I quoted path so wrong. Shame on me.

Getting arguments of template instantiation

I am trying to get templated type parameter. This oversimplified example fails:

if (type.kind() == cppast::cpp_type_kind::template_instantiation_t)
{
    const auto& templateType = dynamic_cast<const cppast::cpp_template_instantiation_type&>(type);
    templateType.arguments().value();    // type_safe/tagged_union.hpp:262: Assertion 'cur_type_ == type' failed - different type stored in union.
}

Am i doing something wrong or is this a bug?

Extracting constructor signature

Hi,

I'm trying to generate reflection information of class constructors, and I would like to extract the exact signature of a given cpp_constructor as an string. For example:

struct Foo
{
     Foo(int i, const std::string& str);
};

would return "Foo(int, const std::string&)" for that Foo constructor.

I've found that manipulating the cpp_type hierarchy myself is a bit tedious (handling all the different kinds of types, cross-referencing types thanks to pointers and reference qualifiers, etc), so I was wondering if you already wrote such a functionality. I see that Standardese outputs full signature function names, but I wasn't sure if Standardese just got the displayname from libclang (which is complete iirc) or if it implemented a complex get-function-signature algorithm like what I need.

After checking Standardese sources for 30m I didn't find anything like that, so here I am asking for some pointers in that regard.

Thanks.

Parsing fails at the end of the file with "no tokens available" message

  • cppast version: latest
  • clang version: 5.0.1

In addition to issue explained to the title cppast output also does not show base classes. Could it be related?

Input file: https://github.com/rokups/Urho3D/blob/master/Source/Urho3D/IO/AbstractFile.h
Input flags: -std=c++11

Output of cppast -v -I . -I .. -D URHO3D_API --std c++11 IO/AbstractFile.h:

[preprocessor] [debug] IO/AbstractFile.h:25: parsing include '../IO/Serializer.h'
[preprocessor] [debug] IO/AbstractFile.h:26: parsing include '../IO/Deserializer.h'
[libclang parser] [debug] IO/AbstractFile.h:28: parsing cursor of type 'Namespace'
[libclang parser] [debug] IO/AbstractFile.h:32: parsing cursor of type 'ClassDecl'
[libclang parser] [debug] IO/AbstractFile.h:32: parsing cursor of type 'attribute(visibility)'
[libclang parser] [debug] IO/AbstractFile.h:36: parsing cursor of type 'CXXConstructor'
[libclang parser] [debug] IO/AbstractFile.h:38: parsing cursor of type 'CXXConstructor'
[libclang parser] [debug] IO/AbstractFile.h:40: parsing cursor of type 'CXXDestructor'
[libclang parser] [debug] IO/AbstractFile.h:43: parsing cursor of type 'UnexposedDecl'
[libclang parser] [error] IO/AbstractFile.h:43: no tokens available
AST for 'IO/AbstractFile.h':
|-../IO/Serializer.h (include directive): `#include "../IO/Serializer.h"`
|-../IO/Deserializer.h (include directive): `#include "../IO/Deserializer.h"`
+-Urho3D (namespace)
  +-AbstractFile (class) [definition]: `class AbstractFile;`
    |-public (access specifier): `public:`
    |-AbstractFile (constructor) [definition]: `AbstractFile();`
    |-AbstractFile (constructor) [definition]: `explicit AbstractFile(unsigned int size);`
    +-~AbstractFile (destructor) [definition]: `virtual ~AbstractFile()=default;`

functions with the same name as their return type are misparsed

  • cppast version: latest master
  • clang version: tested with 5.0 and latest svn

If a function has the same name as its return type, it is misparsed as a class declaration it seems.

struct name {};
name name();

Now, this is a weird thing to do, but this is not as weird:

std::string string();

In fact it came up while implementing the filesystem ts, because of filesystem::path::string().

This is what standardese reports:

[libclang parser] [error] test.cpp:4: expected a bracket, got 'name'

std::atoi throws invalid argument exception

  • cppast version: master ca2fae0
  • parser: libclang_parser
  • clang version: 5.0

While parsing a header file with my libclang parser instance, an std::atoi() call throws an std::invalid_argument exception. Seems to be a regression introduced by #32 (My previous working version of cppast was master 24365e8, the issue started after updating my project submodules).

I've set up a branch of my project with the mentioned ca2fae0 cppast commit to reproduce the error, named type_safe_atoi_throws. Here's a link to the latest CI build of that branch. (The project has not been released yet, but I've added your gitlab account as a guest).

For reference, here's the same build in the master branch, which uses the cppast commit 24365e8.

Both builds are run in a docker container with an image named geordiejones/cpp14-build-machine, which provides a minimal libclang-5 ubuntu environment. The issue happens when running my tool with my example header.

Also for reference, here's the commit in the type_safe_atoi_throws branch, the difference from master:

commit 38885f6b8b98ef94176f5127d66a91e3dd659912
Author: Manuel Sanchez <[email protected]>
Date:   Wed Jan 24 09:19:40 2018 +0000

    update cppast version to ca2fae08a2c50c9759433b5abb1345fc78dcfc55

diff --git a/cppast b/cppast
index 24365e8..ca2fae0 160000
--- a/cppast
+++ b/cppast
@@ -1 +1 @@
-Subproject commit 24365e8b8288c8949e9585d0dda4b59c69d0b6b2
+Subproject commit ca2fae08a2c50c9759433b5abb1345fc78dcfc55

How do i tell if cpp_type is enum?

I am generating a c wrapper over api using cppast and i came to need to decide if type is complex or not. Checking cppast source code i noticed that user_defined_t is treated as non-complex. I may not understand what exactly is complex type here because for example user-defined class types are also user_defined_t. So is there a way to figure out if particular cpp_type is backed by a simple data type like enums are backed by integers for example?

cmake build only the static lib

I'm trying to incorporate cppast into another project and so want only to build the static lib, no example, test, etc. when i pass -DCPPAST_BUILD_EXAMPLE=OFF -DCPPAST_BUILD_TEST=OFF -DCPPAST_BUILD_TOOL=OFF to the cmake command it still builds example, test, etc.

I'm not a cmake expert but i think i tracked it down to this statement in CMakeLists.txt:

if(${CPPAST_BUILD_EXAMPLE} OR (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR))

(on line 29).

from the cmake docs:

CMAKE_CURRENT_SOURCE_DIR
this is the directory where the currently processed CMakeLists.txt is located in

CMAKE_SOURCE_DIR
this is the directory which contains the top-level CMakeLists.txt, i.e. the top level source directory

so this will always be true the way i configure:

cd cppast
mkdir build
cmake ..

perhaps i'm configuring incorrectly but i thought this was the accepted cmake way.

thanks

Variable templates are unexposed

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

A C++14 variable template isn't exposed by libclang, so it won't be parsed as a cpp_variable_template but as a cpp_unexposed_entity. Variable template specializations do not even have their own class yet.

Comments in macro parameter lists trigger an error

  • cppast version: 0.0 (1053429)
  • parser: libclang_parser
  • clang version: 3.9.1

Input:

#define ADD(A /* plus */, B) ((A) + (B))

Input flags:

none

Output:

[preprocessor] [error] main.cpp:3: expected comma in macro parameter list
[fatal parsing error] preprocessor: command '/usr/bin/clang -x c++ -I. -E -CC -dD -fno-caret-diagnostics -fno-show-column -fdiagnostics-format=msvc -Wno-pragma-once-outside-header -Wno-pragma-system-header-outside-header -Wno-include-next-outside-header -I/usr/lib64/clang/3.9.1/include -D__cppast__=libclang -D__cppast_version_major__=0 -D__cppast_version_minor__=0 -std=c++14 "main.cpp"' exited with non-zero exit code (1)

Output of cppast -v <input>

(the exact same error as above)

Arguments in a template specialization are not exposed

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

Due to a libclang limitation, the arguments in a template specialization are only available as a string unless the specialization is in a friend declaration.

Input:

template <typename T, int I>
struct foo {};

template <>
struct foo<int, 42> {};

Here, the only information available about the specialization arguments is the string "int, 42".

Fast preprocessing causes file_name here to come up either <built-in> or <command line>

https://github.com/foonathan/cppast/blob/4c34587668ba9958f75bf345b8f68e48f2569c64/src/libclang/libclang_visitor.hpp#L49

Hi there,
I have been using your AST traversing tool to search codebases that I have marked up with attributes, and using those attributes to generate some code that automates the process for me to easily add classes into a scripting runtime (chaiscript).

With the most recent update to master, I was excited about the fast preprocessing option. With one of the codebases I'm loading into the AST parses just fine. The other however, I'm finding that when it is in visit_tu, there is a mismatch of the filenames which causes it to not actually visit the tu, and thus I get none of the information I need. Instead it filename comes out of clang_getPresumedLocation as "'<'built-in'>'" or "'<'command line'>'" instead of actual file names. Because of this, cppast::visit, only looks at the file object and then kicks out as if it were the only entity parsed.

With the one that parses successfully, it has to use fast_preprocessing, otherwise I get unknown token errors. With the other, it works fine if I turn fast_preprocessing off, but not if fast_preprocessing is on. This discrepancy is really confusing to me, and while I could put a flag in to turn it on or off through my command line, I still feel like I should find out what is causing the issue in the first place.

I interface with cppast as such:

cppast::libclang_compile_config config;
cppast::compile_flags flags;

config.fast_preprocessing(true);

config.set_flags(cppast::cpp_standard::cpp_14, flags);

for(auto i : includes) {
  config.add_include_dir(i); //Includes from argv
}
...
cppast::cpp_entity_index idx;
std::vector<std::unique_ptr<cppast::cpp_file>> parsed_files;
cppast::libclang_parser parser;
for(auto f : filenames) { //Filenames from a recursive tinydir search
  auto file = parser.parse(idx, f, config);
  if(parser.error()) {
    std::cout<<"There was a parser error when parsing "<<f<<std::endl;
    parser.reset_error();
  }
  else {
    parsed_files.push_back(std::move(file));
  }
}
...
for(auto& file : parsed_files) {
    cppast::visit(*file, [&](const cppast::cpp_entity& ent, cppast::visitor_info info) {
      if(info.event != cppast::visitor_info::container_entity_exit) {
        if(ent.kind() == cppast::cpp_entity_kind::namespace_t) {
          processNamespace(ent);
        }
        else if(ent.kind() == cppast::cpp_entity_kind::enum_t) {
          processEnum(ent);
        }
        else if(ent.kind() == cppast::cpp_entity_kind::class_t) {
          processModule(ent);
        }
        else if(ent.kind() == cppast::cpp_entity_kind::constructor_t) {
          processConstructor(ent);
        }
        else if(ent.kind() == cppast::cpp_entity_kind::member_function_t) {
          processMemberFunction(ent);
        }
        else if(ent.kind() == cppast::cpp_entity_kind::function_t) {
          processStaticFunction(ent);
        }
      }
      else if(info.event == cppast::visitor_info::container_entity_exit && ent.kind() == cppast::cpp_entity_kind::namespace_t) {
        if(current_namespace.find_last_of("::") == std::string::npos)
          current_namespace.clear();
        else
          current_namespace = current_namespace.substr(0, current_namespace.find_last_of("::") - 1);
      }
      return true;
    });
  }

If you need anymore information from me, let me know. :)

Filtered node visitation

I started playing with the library and I found myself often writing visitor callbacks, that:

  • Filter out "exit" tokens
  • Blacklist-style filter out certain entity types (e.g. file node)
  • Whitelist-style filter for certain node types ("iterate over only enums")

Some form of declarative filtering would be quite useful, e.g.

visit(file, cppast::whitelist(cpp_entity_type::enum_t, cpp_entity_type::class_t), [&](const cpp_entity& e, visitor_info info) {

or

visit(file, cppast::blacklist(cpp_entity_type::enum_value_t, cpp_entity_type::struct_t), [&](const cpp_entity& e, visitor_info info) {

(not sure about the syntax, but you get the idea). As for the enter-exit events, it might even make sense to provide a simple_visit function that only does enter events, since that's a large use-case.

Use of preprocessor values in enum results in "no tokens available" error

  • cppast version: latest
  • clang version: 5.0.1

One enum i have is using macros from external library:

enum MouseButton
{
    MOUSEB_NONE,
    MOUSEB_LEFT = SDL_BUTTON_LMASK,
    MOUSEB_MIDDLE = SDL_BUTTON_MMASK,
    MOUSEB_RIGHT = SDL_BUTTON_RMASK,
    MOUSEB_X1 = SDL_BUTTON_X1MASK,
    MOUSEB_X2 = SDL_BUTTON_X2MASK,
    MOUSEB_ANY = ~0
};

Header includes SDL/SDL_mouse.h where these macros are defined. Parsing fails "no tokens available" for enum elements that are using preprocessor macros as values. Actual InputEvents.h.

Input flags: -fPIC -msse -msse2 -Wno-invalid-offsetof -std=gnu++11

~/src/games/Projects/Urho3D/Source % /home/rk/src/open/cppast/build/tool/cppast -I ThirdParty/SDL/include -I ThirdParty/SDL/include/SDL -I . -I /tmp/Urho3D-debug/Source/ThirdParty/SDL/include/SDL/generated/ Urho3D/Input/InputEvents.h
[libclang parser] [error] Urho3D/Input/InputEvents.h:251: no tokens available
[libclang parser] [error] Urho3D/Input/InputEvents.h:252: no tokens available
[libclang parser] [error] Urho3D/Input/InputEvents.h:253: no tokens available
[libclang parser] [error] Urho3D/Input/InputEvents.h:254: no tokens available
[libclang parser] [error] Urho3D/Input/InputEvents.h:255: no tokens available
AST for 'Urho3D/Input/InputEvents.h':
|-../Core/Object.h (include directive): `#include "../Core/Object.h"`
|-SDL/SDL_joystick.h (include directive): `#include <SDL/SDL_joystick.h>`
|-SDL/SDL_gamecontroller.h (include directive): `#include <SDL/SDL_gamecontroller.h>`
|-SDL/SDL_keycode.h (include directive): `#include <SDL/SDL_keycode.h>`
|-SDL/SDL_mouse.h (include directive): `#include <SDL/SDL_mouse.h>`
+-Urho3D (namespace)
  |-E_MOUSEBUTTONDOWN (variable) [definition]: `static Urho3D::StringHash const E_MOUSEBUTTONDOWN;`
  |-MouseButtonDown (namespace)
  | |-P_BUTTON (variable) [definition]: `static Urho3D::StringHash const P_BUTTON;`
  | |-P_BUTTONS (variable) [definition]: `static Urho3D::StringHash const P_BUTTONS;`
  | +-P_QUALIFIERS (variable) [definition]: `static Urho3D::StringHash const P_QUALIFIERS;`
  |-E_MOUSEBUTTONUP (variable) [definition]: `static Urho3D::StringHash const E_MOUSEBUTTONUP;`
  |-MouseButtonUp (namespace)
  | |-P_BUTTON (variable) [definition]: `static Urho3D::StringHash const P_BUTTON;`
  | |-P_BUTTONS (variable) [definition]: `static Urho3D::StringHash const P_BUTTONS;`
  | +-P_QUALIFIERS (variable) [definition]: `static Urho3D::StringHash const P_QUALIFIERS;`
  |-E_MOUSEMOVE (variable) [definition]: `static Urho3D::StringHash const E_MOUSEMOVE;`
  |-MouseMove (namespace)
  | |-P_X (variable) [definition]: `static Urho3D::StringHash const P_X;`
  | |-P_Y (variable) [definition]: `static Urho3D::StringHash const P_Y;`
  | |-P_DX (variable) [definition]: `static Urho3D::StringHash const P_DX;`
  | |-P_DY (variable) [definition]: `static Urho3D::StringHash const P_DY;`
  | |-P_BUTTONS (variable) [definition]: `static Urho3D::StringHash const P_BUTTONS;`
  | +-P_QUALIFIERS (variable) [definition]: `static Urho3D::StringHash const P_QUALIFIERS;`
  |-E_MOUSEWHEEL (variable) [definition]: `static Urho3D::StringHash const E_MOUSEWHEEL;`
  |-MouseWheel (namespace)
  | |-P_WHEEL (variable) [definition]: `static Urho3D::StringHash const P_WHEEL;`
  | |-P_BUTTONS (variable) [definition]: `static Urho3D::StringHash const P_BUTTONS;`
  | +-P_QUALIFIERS (variable) [definition]: `static Urho3D::StringHash const P_QUALIFIERS;`
  |-E_KEYDOWN (variable) [definition]: `static Urho3D::StringHash const E_KEYDOWN;`
  |-KeyDown (namespace)
  | |-P_KEY (variable) [definition]: `static Urho3D::StringHash const P_KEY;`
  | |-P_SCANCODE (variable) [definition]: `static Urho3D::StringHash const P_SCANCODE;`
  | |-P_BUTTONS (variable) [definition]: `static Urho3D::StringHash const P_BUTTONS;`
  | |-P_QUALIFIERS (variable) [definition]: `static Urho3D::StringHash const P_QUALIFIERS;`
  | +-P_REPEAT (variable) [definition]: `static Urho3D::StringHash const P_REPEAT;`
  |-E_KEYUP (variable) [definition]: `static Urho3D::StringHash const E_KEYUP;`
  |-KeyUp (namespace)
  | |-P_KEY (variable) [definition]: `static Urho3D::StringHash const P_KEY;`
  | |-P_SCANCODE (variable) [definition]: `static Urho3D::StringHash const P_SCANCODE;`
  | |-P_BUTTONS (variable) [definition]: `static Urho3D::StringHash const P_BUTTONS;`
  | +-P_QUALIFIERS (variable) [definition]: `static Urho3D::StringHash const P_QUALIFIERS;`
  |-E_TEXTINPUT (variable) [definition]: `static Urho3D::StringHash const E_TEXTINPUT;`
  |-TextInput (namespace)
  | +-P_TEXT (variable) [definition]: `static Urho3D::StringHash const P_TEXT;`
  |-E_TEXTEDITING (variable) [definition]: `static Urho3D::StringHash const E_TEXTEDITING;`
  |-TextEditing (namespace)
  | |-P_COMPOSITION (variable) [definition]: `static Urho3D::StringHash const P_COMPOSITION;`
  | |-P_CURSOR (variable) [definition]: `static Urho3D::StringHash const P_CURSOR;`
  | +-P_SELECTION_LENGTH (variable) [definition]: `static Urho3D::StringHash const P_SELECTION_LENGTH;`
  |-E_JOYSTICKCONNECTED (variable) [definition]: `static Urho3D::StringHash const E_JOYSTICKCONNECTED;`
  |-JoystickConnected (namespace)
  | +-P_JOYSTICKID (variable) [definition]: `static Urho3D::StringHash const P_JOYSTICKID;`
  |-E_JOYSTICKDISCONNECTED (variable) [definition]: `static Urho3D::StringHash const E_JOYSTICKDISCONNECTED;`
  |-JoystickDisconnected (namespace)
  | +-P_JOYSTICKID (variable) [definition]: `static Urho3D::StringHash const P_JOYSTICKID;`
  |-E_JOYSTICKBUTTONDOWN (variable) [definition]: `static Urho3D::StringHash const E_JOYSTICKBUTTONDOWN;`
  |-JoystickButtonDown (namespace)
  | |-P_JOYSTICKID (variable) [definition]: `static Urho3D::StringHash const P_JOYSTICKID;`
  | +-P_BUTTON (variable) [definition]: `static Urho3D::StringHash const P_BUTTON;`
  |-E_JOYSTICKBUTTONUP (variable) [definition]: `static Urho3D::StringHash const E_JOYSTICKBUTTONUP;`
  |-JoystickButtonUp (namespace)
  | |-P_JOYSTICKID (variable) [definition]: `static Urho3D::StringHash const P_JOYSTICKID;`
  | +-P_BUTTON (variable) [definition]: `static Urho3D::StringHash const P_BUTTON;`
  |-E_JOYSTICKAXISMOVE (variable) [definition]: `static Urho3D::StringHash const E_JOYSTICKAXISMOVE;`
  |-JoystickAxisMove (namespace)
  | |-P_JOYSTICKID (variable) [definition]: `static Urho3D::StringHash const P_JOYSTICKID;`
  | |-P_AXIS (variable) [definition]: `static Urho3D::StringHash const P_AXIS;`
  | +-P_POSITION (variable) [definition]: `static Urho3D::StringHash const P_POSITION;`
  |-E_JOYSTICKHATMOVE (variable) [definition]: `static Urho3D::StringHash const E_JOYSTICKHATMOVE;`
  |-JoystickHatMove (namespace)
  | |-P_JOYSTICKID (variable) [definition]: `static Urho3D::StringHash const P_JOYSTICKID;`
  | |-P_HAT (variable) [definition]: `static Urho3D::StringHash const P_HAT;`
  | +-P_POSITION (variable) [definition]: `static Urho3D::StringHash const P_POSITION;`
  |-E_TOUCHBEGIN (variable) [definition]: `static Urho3D::StringHash const E_TOUCHBEGIN;`
  |-TouchBegin (namespace)
  | |-P_TOUCHID (variable) [definition]: `static Urho3D::StringHash const P_TOUCHID;`
  | |-P_X (variable) [definition]: `static Urho3D::StringHash const P_X;`
  | |-P_Y (variable) [definition]: `static Urho3D::StringHash const P_Y;`
  | +-P_PRESSURE (variable) [definition]: `static Urho3D::StringHash const P_PRESSURE;`
  |-E_TOUCHEND (variable) [definition]: `static Urho3D::StringHash const E_TOUCHEND;`
  |-TouchEnd (namespace)
  | |-P_TOUCHID (variable) [definition]: `static Urho3D::StringHash const P_TOUCHID;`
  | |-P_X (variable) [definition]: `static Urho3D::StringHash const P_X;`
  | +-P_Y (variable) [definition]: `static Urho3D::StringHash const P_Y;`
  |-E_TOUCHMOVE (variable) [definition]: `static Urho3D::StringHash const E_TOUCHMOVE;`
  |-TouchMove (namespace)
  | |-P_TOUCHID (variable) [definition]: `static Urho3D::StringHash const P_TOUCHID;`
  | |-P_X (variable) [definition]: `static Urho3D::StringHash const P_X;`
  | |-P_Y (variable) [definition]: `static Urho3D::StringHash const P_Y;`
  | |-P_DX (variable) [definition]: `static Urho3D::StringHash const P_DX;`
  | |-P_DY (variable) [definition]: `static Urho3D::StringHash const P_DY;`
  | +-P_PRESSURE (variable) [definition]: `static Urho3D::StringHash const P_PRESSURE;`
  |-E_GESTURERECORDED (variable) [definition]: `static Urho3D::StringHash const E_GESTURERECORDED;`
  |-GestureRecorded (namespace)
  | +-P_GESTUREID (variable) [definition]: `static Urho3D::StringHash const P_GESTUREID;`
  |-E_GESTUREINPUT (variable) [definition]: `static Urho3D::StringHash const E_GESTUREINPUT;`
  |-GestureInput (namespace)
  | |-P_GESTUREID (variable) [definition]: `static Urho3D::StringHash const P_GESTUREID;`
  | |-P_CENTERX (variable) [definition]: `static Urho3D::StringHash const P_CENTERX;`
  | |-P_CENTERY (variable) [definition]: `static Urho3D::StringHash const P_CENTERY;`
  | |-P_NUMFINGERS (variable) [definition]: `static Urho3D::StringHash const P_NUMFINGERS;`
  | +-P_ERROR (variable) [definition]: `static Urho3D::StringHash const P_ERROR;`
  |-E_MULTIGESTURE (variable) [definition]: `static Urho3D::StringHash const E_MULTIGESTURE;`
  |-MultiGesture (namespace)
  | |-P_CENTERX (variable) [definition]: `static Urho3D::StringHash const P_CENTERX;`
  | |-P_CENTERY (variable) [definition]: `static Urho3D::StringHash const P_CENTERY;`
  | |-P_NUMFINGERS (variable) [definition]: `static Urho3D::StringHash const P_NUMFINGERS;`
  | |-P_DTHETA (variable) [definition]: `static Urho3D::StringHash const P_DTHETA;`
  | +-P_DDIST (variable) [definition]: `static Urho3D::StringHash const P_DDIST;`
  |-E_DROPFILE (variable) [definition]: `static Urho3D::StringHash const E_DROPFILE;`
  |-DropFile (namespace)
  | +-P_FILENAME (variable) [definition]: `static Urho3D::StringHash const P_FILENAME;`
  |-E_INPUTFOCUS (variable) [definition]: `static Urho3D::StringHash const E_INPUTFOCUS;`
  |-InputFocus (namespace)
  | |-P_FOCUS (variable) [definition]: `static Urho3D::StringHash const P_FOCUS;`
  | +-P_MINIMIZED (variable) [definition]: `static Urho3D::StringHash const P_MINIMIZED;`
  |-E_MOUSEVISIBLECHANGED (variable) [definition]: `static Urho3D::StringHash const E_MOUSEVISIBLECHANGED;`
  |-MouseVisibleChanged (namespace)
  | +-P_VISIBLE (variable) [definition]: `static Urho3D::StringHash const P_VISIBLE;`
  |-E_MOUSEMODECHANGED (variable) [definition]: `static Urho3D::StringHash const E_MOUSEMODECHANGED;`
  |-MouseModeChanged (namespace)
  | |-P_MODE (variable) [definition]: `static Urho3D::StringHash const P_MODE;`
  | +-P_MOUSELOCKED (variable) [definition]: `static Urho3D::StringHash const P_MOUSELOCKED;`
  |-E_EXITREQUESTED (variable) [definition]: `static Urho3D::StringHash const E_EXITREQUESTED;`
  |-ExitRequested (namespace)
  |-E_SDLRAWINPUT (variable) [definition]: `static Urho3D::StringHash const E_SDLRAWINPUT;`
  |-SDLRawInput (namespace)
  | |-P_SDLEVENT (variable) [definition]: `static Urho3D::StringHash const P_SDLEVENT;`
  | +-P_CONSUMED (variable) [definition]: `static Urho3D::StringHash const P_CONSUMED;`
  |-E_INPUTBEGIN (variable) [definition]: `static Urho3D::StringHash const E_INPUTBEGIN;`
  |-InputBegin (namespace)
  |-E_INPUTEND (variable) [definition]: `static Urho3D::StringHash const E_INPUTEND;`
  |-InputEnd (namespace)
  |-MouseButton (enum) [definition]: `enum MouseButton;`
  | |-MOUSEB_NONE (enum value): `MOUSEB_NONE`
  | +-MOUSEB_ANY (enum value): `MOUSEB_ANY=~0`
  |-QUAL_SHIFT (variable) [definition]: `static int const QUAL_SHIFT=1;`
  |-QUAL_CTRL (variable) [definition]: `static int const QUAL_CTRL=2;`
  |-QUAL_ALT (variable) [definition]: `static int const QUAL_ALT=4;`
  |-QUAL_ANY (variable) [definition]: `static int const QUAL_ANY=8;`
  |-KEY_UNKNOWN (variable) [definition]: `static int const KEY_UNKNOWN=SDLK_UNKNOWN;`
  |-KEY_A (variable) [definition]: `static int const KEY_A=SDLK_a;`
  |-KEY_B (variable) [definition]: `static int const KEY_B=SDLK_b;`
  |-KEY_C (variable) [definition]: `static int const KEY_C=SDLK_c;`
  |-KEY_D (variable) [definition]: `static int const KEY_D=SDLK_d;`
  |-KEY_E (variable) [definition]: `static int const KEY_E=SDLK_e;`
  |-KEY_F (variable) [definition]: `static int const KEY_F=SDLK_f;`
  |-KEY_G (variable) [definition]: `static int const KEY_G=SDLK_g;`
  |-KEY_H (variable) [definition]: `static int const KEY_H=SDLK_h;`
  |-KEY_I (variable) [definition]: `static int const KEY_I=SDLK_i;`
  |-KEY_J (variable) [definition]: `static int const KEY_J=SDLK_j;`
  |-KEY_K (variable) [definition]: `static int const KEY_K=SDLK_k;`
  |-KEY_L (variable) [definition]: `static int const KEY_L=SDLK_l;`
  |-KEY_M (variable) [definition]: `static int const KEY_M=SDLK_m;`
  |-KEY_N (variable) [definition]: `static int const KEY_N=SDLK_n;`
  |-KEY_O (variable) [definition]: `static int const KEY_O=SDLK_o;`
  |-KEY_P (variable) [definition]: `static int const KEY_P=SDLK_p;`
  |-KEY_Q (variable) [definition]: `static int const KEY_Q=SDLK_q;`
  |-KEY_R (variable) [definition]: `static int const KEY_R=SDLK_r;`
  |-KEY_S (variable) [definition]: `static int const KEY_S=SDLK_s;`
  |-KEY_T (variable) [definition]: `static int const KEY_T=SDLK_t;`
  |-KEY_U (variable) [definition]: `static int const KEY_U=SDLK_u;`
  |-KEY_V (variable) [definition]: `static int const KEY_V=SDLK_v;`
  |-KEY_W (variable) [definition]: `static int const KEY_W=SDLK_w;`
  |-KEY_X (variable) [definition]: `static int const KEY_X=SDLK_x;`
  |-KEY_Y (variable) [definition]: `static int const KEY_Y=SDLK_y;`
  |-KEY_Z (variable) [definition]: `static int const KEY_Z=SDLK_z;`
  |-KEY_0 (variable) [definition]: `static int const KEY_0=SDLK_0;`
  |-KEY_1 (variable) [definition]: `static int const KEY_1=SDLK_1;`
  |-KEY_2 (variable) [definition]: `static int const KEY_2=SDLK_2;`
  |-KEY_3 (variable) [definition]: `static int const KEY_3=SDLK_3;`
  |-KEY_4 (variable) [definition]: `static int const KEY_4=SDLK_4;`
  |-KEY_5 (variable) [definition]: `static int const KEY_5=SDLK_5;`
  |-KEY_6 (variable) [definition]: `static int const KEY_6=SDLK_6;`
  |-KEY_7 (variable) [definition]: `static int const KEY_7=SDLK_7;`
  |-KEY_8 (variable) [definition]: `static int const KEY_8=SDLK_8;`
  |-KEY_9 (variable) [definition]: `static int const KEY_9=SDLK_9;`
  |-KEY_BACKSPACE (variable) [definition]: `static int const KEY_BACKSPACE=SDLK_BACKSPACE;`
  |-KEY_TAB (variable) [definition]: `static int const KEY_TAB=SDLK_TAB;`
  |-KEY_RETURN (variable) [definition]: `static int const KEY_RETURN=SDLK_RETURN;`
  |-KEY_RETURN2 (variable) [definition]: `static int const KEY_RETURN2=SDLK_RETURN2;`
  |-KEY_KP_ENTER (variable) [definition]: `static int const KEY_KP_ENTER=SDLK_KP_ENTER;`
  |-KEY_SHIFT (variable) [definition]: `static int const KEY_SHIFT=SDLK_LSHIFT;`
  |-KEY_CTRL (variable) [definition]: `static int const KEY_CTRL=SDLK_LCTRL;`
  |-KEY_ALT (variable) [definition]: `static int const KEY_ALT=SDLK_LALT;`
  |-KEY_GUI (variable) [definition]: `static int const KEY_GUI=SDLK_LGUI;`
  |-KEY_PAUSE (variable) [definition]: `static int const KEY_PAUSE=SDLK_PAUSE;`
  |-KEY_CAPSLOCK (variable) [definition]: `static int const KEY_CAPSLOCK=SDLK_CAPSLOCK;`
  |-KEY_ESCAPE (variable) [definition]: `static int const KEY_ESCAPE=SDLK_ESCAPE;`
  |-KEY_SPACE (variable) [definition]: `static int const KEY_SPACE=SDLK_SPACE;`
  |-KEY_PAGEUP (variable) [definition]: `static int const KEY_PAGEUP=SDLK_PAGEUP;`
  |-KEY_PAGEDOWN (variable) [definition]: `static int const KEY_PAGEDOWN=SDLK_PAGEDOWN;`
  |-KEY_END (variable) [definition]: `static int const KEY_END=SDLK_END;`
  |-KEY_HOME (variable) [definition]: `static int const KEY_HOME=SDLK_HOME;`
  |-KEY_LEFT (variable) [definition]: `static int const KEY_LEFT=SDLK_LEFT;`
  |-KEY_UP (variable) [definition]: `static int const KEY_UP=SDLK_UP;`
  |-KEY_RIGHT (variable) [definition]: `static int const KEY_RIGHT=SDLK_RIGHT;`
  |-KEY_DOWN (variable) [definition]: `static int const KEY_DOWN=SDLK_DOWN;`
  |-KEY_SELECT (variable) [definition]: `static int const KEY_SELECT=SDLK_SELECT;`
  |-KEY_PRINTSCREEN (variable) [definition]: `static int const KEY_PRINTSCREEN=SDLK_PRINTSCREEN;`
  |-KEY_INSERT (variable) [definition]: `static int const KEY_INSERT=SDLK_INSERT;`
  |-KEY_DELETE (variable) [definition]: `static int const KEY_DELETE=SDLK_DELETE;`
  |-KEY_LGUI (variable) [definition]: `static int const KEY_LGUI=SDLK_LGUI;`
  |-KEY_RGUI (variable) [definition]: `static int const KEY_RGUI=SDLK_RGUI;`
  |-KEY_APPLICATION (variable) [definition]: `static int const KEY_APPLICATION=SDLK_APPLICATION;`
  |-KEY_KP_0 (variable) [definition]: `static int const KEY_KP_0=SDLK_KP_0;`
  |-KEY_KP_1 (variable) [definition]: `static int const KEY_KP_1=SDLK_KP_1;`
  |-KEY_KP_2 (variable) [definition]: `static int const KEY_KP_2=SDLK_KP_2;`
  |-KEY_KP_3 (variable) [definition]: `static int const KEY_KP_3=SDLK_KP_3;`
  |-KEY_KP_4 (variable) [definition]: `static int const KEY_KP_4=SDLK_KP_4;`
  |-KEY_KP_5 (variable) [definition]: `static int const KEY_KP_5=SDLK_KP_5;`
  |-KEY_KP_6 (variable) [definition]: `static int const KEY_KP_6=SDLK_KP_6;`
  |-KEY_KP_7 (variable) [definition]: `static int const KEY_KP_7=SDLK_KP_7;`
  |-KEY_KP_8 (variable) [definition]: `static int const KEY_KP_8=SDLK_KP_8;`
  |-KEY_KP_9 (variable) [definition]: `static int const KEY_KP_9=SDLK_KP_9;`
  |-KEY_KP_MULTIPLY (variable) [definition]: `static int const KEY_KP_MULTIPLY=SDLK_KP_MULTIPLY;`
  |-KEY_KP_PLUS (variable) [definition]: `static int const KEY_KP_PLUS=SDLK_KP_PLUS;`
  |-KEY_KP_MINUS (variable) [definition]: `static int const KEY_KP_MINUS=SDLK_KP_MINUS;`
  |-KEY_KP_PERIOD (variable) [definition]: `static int const KEY_KP_PERIOD=SDLK_KP_PERIOD;`
  |-KEY_KP_DIVIDE (variable) [definition]: `static int const KEY_KP_DIVIDE=SDLK_KP_DIVIDE;`
  |-KEY_F1 (variable) [definition]: `static int const KEY_F1=SDLK_F1;`
  |-KEY_F2 (variable) [definition]: `static int const KEY_F2=SDLK_F2;`
  |-KEY_F3 (variable) [definition]: `static int const KEY_F3=SDLK_F3;`
  |-KEY_F4 (variable) [definition]: `static int const KEY_F4=SDLK_F4;`
  |-KEY_F5 (variable) [definition]: `static int const KEY_F5=SDLK_F5;`
  |-KEY_F6 (variable) [definition]: `static int const KEY_F6=SDLK_F6;`
  |-KEY_F7 (variable) [definition]: `static int const KEY_F7=SDLK_F7;`
  |-KEY_F8 (variable) [definition]: `static int const KEY_F8=SDLK_F8;`
  |-KEY_F9 (variable) [definition]: `static int const KEY_F9=SDLK_F9;`
  |-KEY_F10 (variable) [definition]: `static int const KEY_F10=SDLK_F10;`
  |-KEY_F11 (variable) [definition]: `static int const KEY_F11=SDLK_F11;`
  |-KEY_F12 (variable) [definition]: `static int const KEY_F12=SDLK_F12;`
  |-KEY_F13 (variable) [definition]: `static int const KEY_F13=SDLK_F13;`
  |-KEY_F14 (variable) [definition]: `static int const KEY_F14=SDLK_F14;`
  |-KEY_F15 (variable) [definition]: `static int const KEY_F15=SDLK_F15;`
  |-KEY_F16 (variable) [definition]: `static int const KEY_F16=SDLK_F16;`
  |-KEY_F17 (variable) [definition]: `static int const KEY_F17=SDLK_F17;`
  |-KEY_F18 (variable) [definition]: `static int const KEY_F18=SDLK_F18;`
  |-KEY_F19 (variable) [definition]: `static int const KEY_F19=SDLK_F19;`
  |-KEY_F20 (variable) [definition]: `static int const KEY_F20=SDLK_F20;`
  |-KEY_F21 (variable) [definition]: `static int const KEY_F21=SDLK_F21;`
  |-KEY_F22 (variable) [definition]: `static int const KEY_F22=SDLK_F22;`
  |-KEY_F23 (variable) [definition]: `static int const KEY_F23=SDLK_F23;`
  |-KEY_F24 (variable) [definition]: `static int const KEY_F24=SDLK_F24;`
  |-KEY_NUMLOCKCLEAR (variable) [definition]: `static int const KEY_NUMLOCKCLEAR=SDLK_NUMLOCKCLEAR;`
  |-KEY_SCROLLLOCK (variable) [definition]: `static int const KEY_SCROLLLOCK=SDLK_SCROLLLOCK;`
  |-KEY_LSHIFT (variable) [definition]: `static int const KEY_LSHIFT=SDLK_LSHIFT;`
  |-KEY_RSHIFT (variable) [definition]: `static int const KEY_RSHIFT=SDLK_RSHIFT;`
  |-KEY_LCTRL (variable) [definition]: `static int const KEY_LCTRL=SDLK_LCTRL;`
  |-KEY_RCTRL (variable) [definition]: `static int const KEY_RCTRL=SDLK_RCTRL;`
  |-KEY_LALT (variable) [definition]: `static int const KEY_LALT=SDLK_LALT;`
  |-KEY_RALT (variable) [definition]: `static int const KEY_RALT=SDLK_RALT;`
  |-KEY_AC_BACK (variable) [definition]: `static int const KEY_AC_BACK=SDLK_AC_BACK;`
  |-KEY_AC_BOOKMARKS (variable) [definition]: `static int const KEY_AC_BOOKMARKS=SDLK_AC_BOOKMARKS;`
  |-KEY_AC_FORWARD (variable) [definition]: `static int const KEY_AC_FORWARD=SDLK_AC_FORWARD;`
  |-KEY_AC_HOME (variable) [definition]: `static int const KEY_AC_HOME=SDLK_AC_HOME;`
  |-KEY_AC_REFRESH (variable) [definition]: `static int const KEY_AC_REFRESH=SDLK_AC_REFRESH;`
  |-KEY_AC_SEARCH (variable) [definition]: `static int const KEY_AC_SEARCH=SDLK_AC_SEARCH;`
  |-KEY_AC_STOP (variable) [definition]: `static int const KEY_AC_STOP=SDLK_AC_STOP;`
  |-KEY_AGAIN (variable) [definition]: `static int const KEY_AGAIN=SDLK_AGAIN;`
  |-KEY_ALTERASE (variable) [definition]: `static int const KEY_ALTERASE=SDLK_ALTERASE;`
  |-KEY_AMPERSAND (variable) [definition]: `static int const KEY_AMPERSAND=SDLK_AMPERSAND;`
  |-KEY_ASTERISK (variable) [definition]: `static int const KEY_ASTERISK=SDLK_ASTERISK;`
  |-KEY_AT (variable) [definition]: `static int const KEY_AT=SDLK_AT;`
  |-KEY_AUDIOMUTE (variable) [definition]: `static int const KEY_AUDIOMUTE=SDLK_AUDIOMUTE;`
  |-KEY_AUDIONEXT (variable) [definition]: `static int const KEY_AUDIONEXT=SDLK_AUDIONEXT;`
  |-KEY_AUDIOPLAY (variable) [definition]: `static int const KEY_AUDIOPLAY=SDLK_AUDIOPLAY;`
  |-KEY_AUDIOPREV (variable) [definition]: `static int const KEY_AUDIOPREV=SDLK_AUDIOPREV;`
  |-KEY_AUDIOSTOP (variable) [definition]: `static int const KEY_AUDIOSTOP=SDLK_AUDIOSTOP;`
  |-KEY_BACKQUOTE (variable) [definition]: `static int const KEY_BACKQUOTE=SDLK_BACKQUOTE;`
  |-KEY_BACKSLASH (variable) [definition]: `static int const KEY_BACKSLASH=SDLK_BACKSLASH;`
  |-KEY_BRIGHTNESSDOWN (variable) [definition]: `static int const KEY_BRIGHTNESSDOWN=SDLK_BRIGHTNESSDOWN;`
  |-KEY_BRIGHTNESSUP (variable) [definition]: `static int const KEY_BRIGHTNESSUP=SDLK_BRIGHTNESSUP;`
  |-KEY_CALCULATOR (variable) [definition]: `static int const KEY_CALCULATOR=SDLK_CALCULATOR;`
  |-KEY_CANCEL (variable) [definition]: `static int const KEY_CANCEL=SDLK_CANCEL;`
  |-KEY_CARET (variable) [definition]: `static int const KEY_CARET=SDLK_CARET;`
  |-KEY_CLEAR (variable) [definition]: `static int const KEY_CLEAR=SDLK_CLEAR;`
  |-KEY_CLEARAGAIN (variable) [definition]: `static int const KEY_CLEARAGAIN=SDLK_CLEARAGAIN;`
  |-KEY_COLON (variable) [definition]: `static int const KEY_COLON=SDLK_COLON;`
  |-KEY_COMMA (variable) [definition]: `static int const KEY_COMMA=SDLK_COMMA;`
  |-KEY_COMPUTER (variable) [definition]: `static int const KEY_COMPUTER=SDLK_COMPUTER;`
  |-KEY_COPY (variable) [definition]: `static int const KEY_COPY=SDLK_COPY;`
  |-KEY_CRSEL (variable) [definition]: `static int const KEY_CRSEL=SDLK_CRSEL;`
  |-KEY_CURRENCYSUBUNIT (variable) [definition]: `static int const KEY_CURRENCYSUBUNIT=SDLK_CURRENCYSUBUNIT;`
  |-KEY_CURRENCYUNIT (variable) [definition]: `static int const KEY_CURRENCYUNIT=SDLK_CURRENCYUNIT;`
  |-KEY_CUT (variable) [definition]: `static int const KEY_CUT=SDLK_CUT;`
  |-KEY_DECIMALSEPARATOR (variable) [definition]: `static int const KEY_DECIMALSEPARATOR=SDLK_DECIMALSEPARATOR;`
  |-KEY_DISPLAYSWITCH (variable) [definition]: `static int const KEY_DISPLAYSWITCH=SDLK_DISPLAYSWITCH;`
  |-KEY_DOLLAR (variable) [definition]: `static int const KEY_DOLLAR=SDLK_DOLLAR;`
  |-KEY_EJECT (variable) [definition]: `static int const KEY_EJECT=SDLK_EJECT;`
  |-KEY_EQUALS (variable) [definition]: `static int const KEY_EQUALS=SDLK_EQUALS;`
  |-KEY_EXCLAIM (variable) [definition]: `static int const KEY_EXCLAIM=SDLK_EXCLAIM;`
  |-KEY_EXSEL (variable) [definition]: `static int const KEY_EXSEL=SDLK_EXSEL;`
  |-KEY_FIND (variable) [definition]: `static int const KEY_FIND=SDLK_FIND;`
  |-KEY_GREATER (variable) [definition]: `static int const KEY_GREATER=SDLK_GREATER;`
  |-KEY_HASH (variable) [definition]: `static int const KEY_HASH=SDLK_HASH;`
  |-KEY_HELP (variable) [definition]: `static int const KEY_HELP=SDLK_HELP;`
  |-KEY_KBDILLUMDOWN (variable) [definition]: `static int const KEY_KBDILLUMDOWN=SDLK_KBDILLUMDOWN;`
  |-KEY_KBDILLUMTOGGLE (variable) [definition]: `static int const KEY_KBDILLUMTOGGLE=SDLK_KBDILLUMTOGGLE;`
  |-KEY_KBDILLUMUP (variable) [definition]: `static int const KEY_KBDILLUMUP=SDLK_KBDILLUMUP;`
  |-KEY_KP_00 (variable) [definition]: `static int const KEY_KP_00=SDLK_KP_00;`
  |-KEY_KP_000 (variable) [definition]: `static int const KEY_KP_000=SDLK_KP_000;`
  |-KEY_KP_A (variable) [definition]: `static int const KEY_KP_A=SDLK_KP_A;`
  |-KEY_KP_AMPERSAND (variable) [definition]: `static int const KEY_KP_AMPERSAND=SDLK_KP_AMPERSAND;`
  |-KEY_KP_AT (variable) [definition]: `static int const KEY_KP_AT=SDLK_KP_AT;`
  |-KEY_KP_B (variable) [definition]: `static int const KEY_KP_B=SDLK_KP_B;`
  |-KEY_KP_BACKSPACE (variable) [definition]: `static int const KEY_KP_BACKSPACE=SDLK_KP_BACKSPACE;`
  |-KEY_KP_BINARY (variable) [definition]: `static int const KEY_KP_BINARY=SDLK_KP_BINARY;`
  |-KEY_KP_C (variable) [definition]: `static int const KEY_KP_C=SDLK_KP_C;`
  |-KEY_KP_CLEAR (variable) [definition]: `static int const KEY_KP_CLEAR=SDLK_KP_CLEAR;`
  |-KEY_KP_CLEARENTRY (variable) [definition]: `static int const KEY_KP_CLEARENTRY=SDLK_KP_CLEARENTRY;`
  |-KEY_KP_COLON (variable) [definition]: `static int const KEY_KP_COLON=SDLK_KP_COLON;`
  |-KEY_KP_COMMA (variable) [definition]: `static int const KEY_KP_COMMA=SDLK_KP_COMMA;`
  |-KEY_KP_D (variable) [definition]: `static int const KEY_KP_D=SDLK_KP_D;`
  |-KEY_KP_DBLAMPERSAND (variable) [definition]: `static int const KEY_KP_DBLAMPERSAND=SDLK_KP_DBLAMPERSAND;`
  |-KEY_KP_DBLVERTICALBAR (variable) [definition]: `static int const KEY_KP_DBLVERTICALBAR=SDLK_KP_DBLVERTICALBAR;`
  |-KEY_KP_DECIMAL (variable) [definition]: `static int const KEY_KP_DECIMAL=SDLK_KP_DECIMAL;`
  |-KEY_KP_E (variable) [definition]: `static int const KEY_KP_E=SDLK_KP_E;`
  |-KEY_KP_EQUALS (variable) [definition]: `static int const KEY_KP_EQUALS=SDLK_KP_EQUALS;`
  |-KEY_KP_EQUALSAS400 (variable) [definition]: `static int const KEY_KP_EQUALSAS400=SDLK_KP_EQUALSAS400;`
  |-KEY_KP_EXCLAM (variable) [definition]: `static int const KEY_KP_EXCLAM=SDLK_KP_EXCLAM;`
  |-KEY_KP_F (variable) [definition]: `static int const KEY_KP_F=SDLK_KP_F;`
  |-KEY_KP_GREATER (variable) [definition]: `static int const KEY_KP_GREATER=SDLK_KP_GREATER;`
  |-KEY_KP_HASH (variable) [definition]: `static int const KEY_KP_HASH=SDLK_KP_HASH;`
  |-KEY_KP_HEXADECIMAL (variable) [definition]: `static int const KEY_KP_HEXADECIMAL=SDLK_KP_HEXADECIMAL;`
  |-KEY_KP_LEFTBRACE (variable) [definition]: `static int const KEY_KP_LEFTBRACE=SDLK_KP_LEFTBRACE;`
  |-KEY_KP_LEFTPAREN (variable) [definition]: `static int const KEY_KP_LEFTPAREN=SDLK_KP_LEFTPAREN;`
  |-KEY_KP_LESS (variable) [definition]: `static int const KEY_KP_LESS=SDLK_KP_LESS;`
  |-KEY_KP_MEMADD (variable) [definition]: `static int const KEY_KP_MEMADD=SDLK_KP_MEMADD;`
  |-KEY_KP_MEMCLEAR (variable) [definition]: `static int const KEY_KP_MEMCLEAR=SDLK_KP_MEMCLEAR;`
  |-KEY_KP_MEMDIVIDE (variable) [definition]: `static int const KEY_KP_MEMDIVIDE=SDLK_KP_MEMDIVIDE;`
  |-KEY_KP_MEMMULTIPLY (variable) [definition]: `static int const KEY_KP_MEMMULTIPLY=SDLK_KP_MEMMULTIPLY;`
  |-KEY_KP_MEMRECALL (variable) [definition]: `static int const KEY_KP_MEMRECALL=SDLK_KP_MEMRECALL;`
  |-KEY_KP_MEMSTORE (variable) [definition]: `static int const KEY_KP_MEMSTORE=SDLK_KP_MEMSTORE;`
  |-KEY_KP_MEMSUBTRACT (variable) [definition]: `static int const KEY_KP_MEMSUBTRACT=SDLK_KP_MEMSUBTRACT;`
  |-KEY_KP_OCTAL (variable) [definition]: `static int const KEY_KP_OCTAL=SDLK_KP_OCTAL;`
  |-KEY_KP_PERCENT (variable) [definition]: `static int const KEY_KP_PERCENT=SDLK_KP_PERCENT;`
  |-KEY_KP_PLUSMINUS (variable) [definition]: `static int const KEY_KP_PLUSMINUS=SDLK_KP_PLUSMINUS;`
  |-KEY_KP_POWER (variable) [definition]: `static int const KEY_KP_POWER=SDLK_KP_POWER;`
  |-KEY_KP_RIGHTBRACE (variable) [definition]: `static int const KEY_KP_RIGHTBRACE=SDLK_KP_RIGHTBRACE;`
  |-KEY_KP_RIGHTPAREN (variable) [definition]: `static int const KEY_KP_RIGHTPAREN=SDLK_KP_RIGHTPAREN;`
  |-KEY_KP_SPACE (variable) [definition]: `static int const KEY_KP_SPACE=SDLK_KP_SPACE;`
  |-KEY_KP_TAB (variable) [definition]: `static int const KEY_KP_TAB=SDLK_KP_TAB;`
  |-KEY_KP_VERTICALBAR (variable) [definition]: `static int const KEY_KP_VERTICALBAR=SDLK_KP_VERTICALBAR;`
  |-KEY_KP_XOR (variable) [definition]: `static int const KEY_KP_XOR=SDLK_KP_XOR;`
  |-KEY_LEFTBRACKET (variable) [definition]: `static int const KEY_LEFTBRACKET=SDLK_LEFTBRACKET;`
  |-KEY_LEFTPAREN (variable) [definition]: `static int const KEY_LEFTPAREN=SDLK_LEFTPAREN;`
  |-KEY_LESS (variable) [definition]: `static int const KEY_LESS=SDLK_LESS;`
  |-KEY_MAIL (variable) [definition]: `static int const KEY_MAIL=SDLK_MAIL;`
  |-KEY_MEDIASELECT (variable) [definition]: `static int const KEY_MEDIASELECT=SDLK_MEDIASELECT;`
  |-KEY_MENU (variable) [definition]: `static int const KEY_MENU=SDLK_MENU;`
  |-KEY_MINUS (variable) [definition]: `static int const KEY_MINUS=SDLK_MINUS;`
  |-KEY_MODE (variable) [definition]: `static int const KEY_MODE=SDLK_MODE;`
  |-KEY_MUTE (variable) [definition]: `static int const KEY_MUTE=SDLK_MUTE;`
  |-KEY_OPER (variable) [definition]: `static int const KEY_OPER=SDLK_OPER;`
  |-KEY_OUT (variable) [definition]: `static int const KEY_OUT=SDLK_OUT;`
  |-KEY_PASTE (variable) [definition]: `static int const KEY_PASTE=SDLK_PASTE;`
  |-KEY_PERCENT (variable) [definition]: `static int const KEY_PERCENT=SDLK_PERCENT;`
  |-KEY_PERIOD (variable) [definition]: `static int const KEY_PERIOD=SDLK_PERIOD;`
  |-KEY_PLUS (variable) [definition]: `static int const KEY_PLUS=SDLK_PLUS;`
  |-KEY_POWER (variable) [definition]: `static int const KEY_POWER=SDLK_POWER;`
  |-KEY_PRIOR (variable) [definition]: `static int const KEY_PRIOR=SDLK_PRIOR;`
  |-KEY_QUESTION (variable) [definition]: `static int const KEY_QUESTION=SDLK_QUESTION;`
  |-KEY_QUOTE (variable) [definition]: `static int const KEY_QUOTE=SDLK_QUOTE;`
  |-KEY_QUOTEDBL (variable) [definition]: `static int const KEY_QUOTEDBL=SDLK_QUOTEDBL;`
  |-KEY_RIGHTBRACKET (variable) [definition]: `static int const KEY_RIGHTBRACKET=SDLK_RIGHTBRACKET;`
  |-KEY_RIGHTPAREN (variable) [definition]: `static int const KEY_RIGHTPAREN=SDLK_RIGHTPAREN;`
  |-KEY_SEMICOLON (variable) [definition]: `static int const KEY_SEMICOLON=SDLK_SEMICOLON;`
  |-KEY_SEPARATOR (variable) [definition]: `static int const KEY_SEPARATOR=SDLK_SEPARATOR;`
  |-KEY_SLASH (variable) [definition]: `static int const KEY_SLASH=SDLK_SLASH;`
  |-KEY_SLEEP (variable) [definition]: `static int const KEY_SLEEP=SDLK_SLEEP;`
  |-KEY_STOP (variable) [definition]: `static int const KEY_STOP=SDLK_STOP;`
  |-KEY_SYSREQ (variable) [definition]: `static int const KEY_SYSREQ=SDLK_SYSREQ;`
  |-KEY_THOUSANDSSEPARATOR (variable) [definition]: `static int const KEY_THOUSANDSSEPARATOR=SDLK_THOUSANDSSEPARATOR;`
  |-KEY_UNDERSCORE (variable) [definition]: `static int const KEY_UNDERSCORE=SDLK_UNDERSCORE;`
  |-KEY_UNDO (variable) [definition]: `static int const KEY_UNDO=SDLK_UNDO;`
  |-KEY_VOLUMEDOWN (variable) [definition]: `static int const KEY_VOLUMEDOWN=SDLK_VOLUMEDOWN;`
  |-KEY_VOLUMEUP (variable) [definition]: `static int const KEY_VOLUMEUP=SDLK_VOLUMEUP;`
  |-KEY_WWW (variable) [definition]: `static int const KEY_WWW=SDLK_WWW;`
  |-SCANCODE_UNKNOWN (variable) [definition]: `static int const SCANCODE_UNKNOWN=SDL_SCANCODE_UNKNOWN;`
  |-SCANCODE_CTRL (variable) [definition]: `static int const SCANCODE_CTRL=SDL_SCANCODE_LCTRL;`
  |-SCANCODE_SHIFT (variable) [definition]: `static int const SCANCODE_SHIFT=SDL_SCANCODE_LSHIFT;`
  |-SCANCODE_ALT (variable) [definition]: `static int const SCANCODE_ALT=SDL_SCANCODE_LALT;`
  |-SCANCODE_GUI (variable) [definition]: `static int const SCANCODE_GUI=SDL_SCANCODE_LGUI;`
  |-SCANCODE_A (variable) [definition]: `static int const SCANCODE_A=SDL_SCANCODE_A;`
  |-SCANCODE_B (variable) [definition]: `static int const SCANCODE_B=SDL_SCANCODE_B;`
  |-SCANCODE_C (variable) [definition]: `static int const SCANCODE_C=SDL_SCANCODE_C;`
  |-SCANCODE_D (variable) [definition]: `static int const SCANCODE_D=SDL_SCANCODE_D;`
  |-SCANCODE_E (variable) [definition]: `static int const SCANCODE_E=SDL_SCANCODE_E;`
  |-SCANCODE_F (variable) [definition]: `static int const SCANCODE_F=SDL_SCANCODE_F;`
  |-SCANCODE_G (variable) [definition]: `static int const SCANCODE_G=SDL_SCANCODE_G;`
  |-SCANCODE_H (variable) [definition]: `static int const SCANCODE_H=SDL_SCANCODE_H;`
  |-SCANCODE_I (variable) [definition]: `static int const SCANCODE_I=SDL_SCANCODE_I;`
  |-SCANCODE_J (variable) [definition]: `static int const SCANCODE_J=SDL_SCANCODE_J;`
  |-SCANCODE_K (variable) [definition]: `static int const SCANCODE_K=SDL_SCANCODE_K;`
  |-SCANCODE_L (variable) [definition]: `static int const SCANCODE_L=SDL_SCANCODE_L;`
  |-SCANCODE_M (variable) [definition]: `static int const SCANCODE_M=SDL_SCANCODE_M;`
  |-SCANCODE_N (variable) [definition]: `static int const SCANCODE_N=SDL_SCANCODE_N;`
  |-SCANCODE_O (variable) [definition]: `static int const SCANCODE_O=SDL_SCANCODE_O;`
  |-SCANCODE_P (variable) [definition]: `static int const SCANCODE_P=SDL_SCANCODE_P;`
  |-SCANCODE_Q (variable) [definition]: `static int const SCANCODE_Q=SDL_SCANCODE_Q;`
  |-SCANCODE_R (variable) [definition]: `static int const SCANCODE_R=SDL_SCANCODE_R;`
  |-SCANCODE_S (variable) [definition]: `static int const SCANCODE_S=SDL_SCANCODE_S;`
  |-SCANCODE_T (variable) [definition]: `static int const SCANCODE_T=SDL_SCANCODE_T;`
  |-SCANCODE_U (variable) [definition]: `static int const SCANCODE_U=SDL_SCANCODE_U;`
  |-SCANCODE_V (variable) [definition]: `static int const SCANCODE_V=SDL_SCANCODE_V;`
  |-SCANCODE_W (variable) [definition]: `static int const SCANCODE_W=SDL_SCANCODE_W;`
  |-SCANCODE_X (variable) [definition]: `static int const SCANCODE_X=SDL_SCANCODE_X;`
  |-SCANCODE_Y (variable) [definition]: `static int const SCANCODE_Y=SDL_SCANCODE_Y;`
  |-SCANCODE_Z (variable) [definition]: `static int const SCANCODE_Z=SDL_SCANCODE_Z;`
  |-SCANCODE_1 (variable) [definition]: `static int const SCANCODE_1=SDL_SCANCODE_1;`
  |-SCANCODE_2 (variable) [definition]: `static int const SCANCODE_2=SDL_SCANCODE_2;`
  |-SCANCODE_3 (variable) [definition]: `static int const SCANCODE_3=SDL_SCANCODE_3;`
  |-SCANCODE_4 (variable) [definition]: `static int const SCANCODE_4=SDL_SCANCODE_4;`
  |-SCANCODE_5 (variable) [definition]: `static int const SCANCODE_5=SDL_SCANCODE_5;`
  |-SCANCODE_6 (variable) [definition]: `static int const SCANCODE_6=SDL_SCANCODE_6;`
  |-SCANCODE_7 (variable) [definition]: `static int const SCANCODE_7=SDL_SCANCODE_7;`
  |-SCANCODE_8 (variable) [definition]: `static int const SCANCODE_8=SDL_SCANCODE_8;`
  |-SCANCODE_9 (variable) [definition]: `static int const SCANCODE_9=SDL_SCANCODE_9;`
  |-SCANCODE_0 (variable) [definition]: `static int const SCANCODE_0=SDL_SCANCODE_0;`
  |-SCANCODE_RETURN (variable) [definition]: `static int const SCANCODE_RETURN=SDL_SCANCODE_RETURN;`
  |-SCANCODE_ESCAPE (variable) [definition]: `static int const SCANCODE_ESCAPE=SDL_SCANCODE_ESCAPE;`
  |-SCANCODE_BACKSPACE (variable) [definition]: `static int const SCANCODE_BACKSPACE=SDL_SCANCODE_BACKSPACE;`
  |-SCANCODE_TAB (variable) [definition]: `static int const SCANCODE_TAB=SDL_SCANCODE_TAB;`
  |-SCANCODE_SPACE (variable) [definition]: `static int const SCANCODE_SPACE=SDL_SCANCODE_SPACE;`
  |-SCANCODE_MINUS (variable) [definition]: `static int const SCANCODE_MINUS=SDL_SCANCODE_MINUS;`
  |-SCANCODE_EQUALS (variable) [definition]: `static int const SCANCODE_EQUALS=SDL_SCANCODE_EQUALS;`
  |-SCANCODE_LEFTBRACKET (variable) [definition]: `static int const SCANCODE_LEFTBRACKET=SDL_SCANCODE_LEFTBRACKET;`
  |-SCANCODE_RIGHTBRACKET (variable) [definition]: `static int const SCANCODE_RIGHTBRACKET=SDL_SCANCODE_RIGHTBRACKET;`
  |-SCANCODE_BACKSLASH (variable) [definition]: `static int const SCANCODE_BACKSLASH=SDL_SCANCODE_BACKSLASH;`
  |-SCANCODE_NONUSHASH (variable) [definition]: `static int const SCANCODE_NONUSHASH=SDL_SCANCODE_NONUSHASH;`
  |-SCANCODE_SEMICOLON (variable) [definition]: `static int const SCANCODE_SEMICOLON=SDL_SCANCODE_SEMICOLON;`
  |-SCANCODE_APOSTROPHE (variable) [definition]: `static int const SCANCODE_APOSTROPHE=SDL_SCANCODE_APOSTROPHE;`
  |-SCANCODE_GRAVE (variable) [definition]: `static int const SCANCODE_GRAVE=SDL_SCANCODE_GRAVE;`
  |-SCANCODE_COMMA (variable) [definition]: `static int const SCANCODE_COMMA=SDL_SCANCODE_COMMA;`
  |-SCANCODE_PERIOD (variable) [definition]: `static int const SCANCODE_PERIOD=SDL_SCANCODE_PERIOD;`
  |-SCANCODE_SLASH (variable) [definition]: `static int const SCANCODE_SLASH=SDL_SCANCODE_SLASH;`
  |-SCANCODE_CAPSLOCK (variable) [definition]: `static int const SCANCODE_CAPSLOCK=SDL_SCANCODE_CAPSLOCK;`
  |-SCANCODE_F1 (variable) [definition]: `static int const SCANCODE_F1=SDL_SCANCODE_F1;`
  |-SCANCODE_F2 (variable) [definition]: `static int const SCANCODE_F2=SDL_SCANCODE_F2;`
  |-SCANCODE_F3 (variable) [definition]: `static int const SCANCODE_F3=SDL_SCANCODE_F3;`
  |-SCANCODE_F4 (variable) [definition]: `static int const SCANCODE_F4=SDL_SCANCODE_F4;`
  |-SCANCODE_F5 (variable) [definition]: `static int const SCANCODE_F5=SDL_SCANCODE_F5;`
  |-SCANCODE_F6 (variable) [definition]: `static int const SCANCODE_F6=SDL_SCANCODE_F6;`
  |-SCANCODE_F7 (variable) [definition]: `static int const SCANCODE_F7=SDL_SCANCODE_F7;`
  |-SCANCODE_F8 (variable) [definition]: `static int const SCANCODE_F8=SDL_SCANCODE_F8;`
  |-SCANCODE_F9 (variable) [definition]: `static int const SCANCODE_F9=SDL_SCANCODE_F9;`
  |-SCANCODE_F10 (variable) [definition]: `static int const SCANCODE_F10=SDL_SCANCODE_F10;`
  |-SCANCODE_F11 (variable) [definition]: `static int const SCANCODE_F11=SDL_SCANCODE_F11;`
  |-SCANCODE_F12 (variable) [definition]: `static int const SCANCODE_F12=SDL_SCANCODE_F12;`
  |-SCANCODE_PRINTSCREEN (variable) [definition]: `static int const SCANCODE_PRINTSCREEN=SDL_SCANCODE_PRINTSCREEN;`
  |-SCANCODE_SCROLLLOCK (variable) [definition]: `static int const SCANCODE_SCROLLLOCK=SDL_SCANCODE_SCROLLLOCK;`
  |-SCANCODE_PAUSE (variable) [definition]: `static int const SCANCODE_PAUSE=SDL_SCANCODE_PAUSE;`
  |-SCANCODE_INSERT (variable) [definition]: `static int const SCANCODE_INSERT=SDL_SCANCODE_INSERT;`
  |-SCANCODE_HOME (variable) [definition]: `static int const SCANCODE_HOME=SDL_SCANCODE_HOME;`
  |-SCANCODE_PAGEUP (variable) [definition]: `static int const SCANCODE_PAGEUP=SDL_SCANCODE_PAGEUP;`
  |-SCANCODE_DELETE (variable) [definition]: `static int const SCANCODE_DELETE=SDL_SCANCODE_DELETE;`
  |-SCANCODE_END (variable) [definition]: `static int const SCANCODE_END=SDL_SCANCODE_END;`
  |-SCANCODE_PAGEDOWN (variable) [definition]: `static int const SCANCODE_PAGEDOWN=SDL_SCANCODE_PAGEDOWN;`
  |-SCANCODE_RIGHT (variable) [definition]: `static int const SCANCODE_RIGHT=SDL_SCANCODE_RIGHT;`
  |-SCANCODE_LEFT (variable) [definition]: `static int const SCANCODE_LEFT=SDL_SCANCODE_LEFT;`
  |-SCANCODE_DOWN (variable) [definition]: `static int const SCANCODE_DOWN=SDL_SCANCODE_DOWN;`
  |-SCANCODE_UP (variable) [definition]: `static int const SCANCODE_UP=SDL_SCANCODE_UP;`
  |-SCANCODE_NUMLOCKCLEAR (variable) [definition]: `static int const SCANCODE_NUMLOCKCLEAR=SDL_SCANCODE_NUMLOCKCLEAR;`
  |-SCANCODE_KP_DIVIDE (variable) [definition]: `static int const SCANCODE_KP_DIVIDE=SDL_SCANCODE_KP_DIVIDE;`
  |-SCANCODE_KP_MULTIPLY (variable) [definition]: `static int const SCANCODE_KP_MULTIPLY=SDL_SCANCODE_KP_MULTIPLY;`
  |-SCANCODE_KP_MINUS (variable) [definition]: `static int const SCANCODE_KP_MINUS=SDL_SCANCODE_KP_MINUS;`
  |-SCANCODE_KP_PLUS (variable) [definition]: `static int const SCANCODE_KP_PLUS=SDL_SCANCODE_KP_PLUS;`
  |-SCANCODE_KP_ENTER (variable) [definition]: `static int const SCANCODE_KP_ENTER=SDL_SCANCODE_KP_ENTER;`
  |-SCANCODE_KP_1 (variable) [definition]: `static int const SCANCODE_KP_1=SDL_SCANCODE_KP_1;`
  |-SCANCODE_KP_2 (variable) [definition]: `static int const SCANCODE_KP_2=SDL_SCANCODE_KP_2;`
  |-SCANCODE_KP_3 (variable) [definition]: `static int const SCANCODE_KP_3=SDL_SCANCODE_KP_3;`
  |-SCANCODE_KP_4 (variable) [definition]: `static int const SCANCODE_KP_4=SDL_SCANCODE_KP_4;`
  |-SCANCODE_KP_5 (variable) [definition]: `static int const SCANCODE_KP_5=SDL_SCANCODE_KP_5;`
  |-SCANCODE_KP_6 (variable) [definition]: `static int const SCANCODE_KP_6=SDL_SCANCODE_KP_6;`
  |-SCANCODE_KP_7 (variable) [definition]: `static int const SCANCODE_KP_7=SDL_SCANCODE_KP_7;`
  |-SCANCODE_KP_8 (variable) [definition]: `static int const SCANCODE_KP_8=SDL_SCANCODE_KP_8;`
  |-SCANCODE_KP_9 (variable) [definition]: `static int const SCANCODE_KP_9=SDL_SCANCODE_KP_9;`
  |-SCANCODE_KP_0 (variable) [definition]: `static int const SCANCODE_KP_0=SDL_SCANCODE_KP_0;`
  |-SCANCODE_KP_PERIOD (variable) [definition]: `static int const SCANCODE_KP_PERIOD=SDL_SCANCODE_KP_PERIOD;`
  |-SCANCODE_NONUSBACKSLASH (variable) [definition]: `static int const SCANCODE_NONUSBACKSLASH=SDL_SCANCODE_NONUSBACKSLASH;`
  |-SCANCODE_APPLICATION (variable) [definition]: `static int const SCANCODE_APPLICATION=SDL_SCANCODE_APPLICATION;`
  |-SCANCODE_POWER (variable) [definition]: `static int const SCANCODE_POWER=SDL_SCANCODE_POWER;`
  |-SCANCODE_KP_EQUALS (variable) [definition]: `static int const SCANCODE_KP_EQUALS=SDL_SCANCODE_KP_EQUALS;`
  |-SCANCODE_F13 (variable) [definition]: `static int const SCANCODE_F13=SDL_SCANCODE_F13;`
  |-SCANCODE_F14 (variable) [definition]: `static int const SCANCODE_F14=SDL_SCANCODE_F14;`
  |-SCANCODE_F15 (variable) [definition]: `static int const SCANCODE_F15=SDL_SCANCODE_F15;`
  |-SCANCODE_F16 (variable) [definition]: `static int const SCANCODE_F16=SDL_SCANCODE_F16;`
  |-SCANCODE_F17 (variable) [definition]: `static int const SCANCODE_F17=SDL_SCANCODE_F17;`
  |-SCANCODE_F18 (variable) [definition]: `static int const SCANCODE_F18=SDL_SCANCODE_F18;`
  |-SCANCODE_F19 (variable) [definition]: `static int const SCANCODE_F19=SDL_SCANCODE_F19;`
  |-SCANCODE_F20 (variable) [definition]: `static int const SCANCODE_F20=SDL_SCANCODE_F20;`
  |-SCANCODE_F21 (variable) [definition]: `static int const SCANCODE_F21=SDL_SCANCODE_F21;`
  |-SCANCODE_F22 (variable) [definition]: `static int const SCANCODE_F22=SDL_SCANCODE_F22;`
  |-SCANCODE_F23 (variable) [definition]: `static int const SCANCODE_F23=SDL_SCANCODE_F23;`
  |-SCANCODE_F24 (variable) [definition]: `static int const SCANCODE_F24=SDL_SCANCODE_F24;`
  |-SCANCODE_EXECUTE (variable) [definition]: `static int const SCANCODE_EXECUTE=SDL_SCANCODE_EXECUTE;`
  |-SCANCODE_HELP (variable) [definition]: `static int const SCANCODE_HELP=SDL_SCANCODE_HELP;`
  |-SCANCODE_MENU (variable) [definition]: `static int const SCANCODE_MENU=SDL_SCANCODE_MENU;`
  |-SCANCODE_SELECT (variable) [definition]: `static int const SCANCODE_SELECT=SDL_SCANCODE_SELECT;`
  |-SCANCODE_STOP (variable) [definition]: `static int const SCANCODE_STOP=SDL_SCANCODE_STOP;`
  |-SCANCODE_AGAIN (variable) [definition]: `static int const SCANCODE_AGAIN=SDL_SCANCODE_AGAIN;`
  |-SCANCODE_UNDO (variable) [definition]: `static int const SCANCODE_UNDO=SDL_SCANCODE_UNDO;`
  |-SCANCODE_CUT (variable) [definition]: `static int const SCANCODE_CUT=SDL_SCANCODE_CUT;`
  |-SCANCODE_COPY (variable) [definition]: `static int const SCANCODE_COPY=SDL_SCANCODE_COPY;`
  |-SCANCODE_PASTE (variable) [definition]: `static int const SCANCODE_PASTE=SDL_SCANCODE_PASTE;`
  |-SCANCODE_FIND (variable) [definition]: `static int const SCANCODE_FIND=SDL_SCANCODE_FIND;`
  |-SCANCODE_MUTE (variable) [definition]: `static int const SCANCODE_MUTE=SDL_SCANCODE_MUTE;`
  |-SCANCODE_VOLUMEUP (variable) [definition]: `static int const SCANCODE_VOLUMEUP=SDL_SCANCODE_VOLUMEUP;`
  |-SCANCODE_VOLUMEDOWN (variable) [definition]: `static int const SCANCODE_VOLUMEDOWN=SDL_SCANCODE_VOLUMEDOWN;`
  |-SCANCODE_KP_COMMA (variable) [definition]: `static int const SCANCODE_KP_COMMA=SDL_SCANCODE_KP_COMMA;`
  |-SCANCODE_KP_EQUALSAS400 (variable) [definition]: `static int const SCANCODE_KP_EQUALSAS400=SDL_SCANCODE_KP_EQUALSAS400;`
  |-SCANCODE_INTERNATIONAL1 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL1=SDL_SCANCODE_INTERNATIONAL1;`
  |-SCANCODE_INTERNATIONAL2 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL2=SDL_SCANCODE_INTERNATIONAL2;`
  |-SCANCODE_INTERNATIONAL3 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL3=SDL_SCANCODE_INTERNATIONAL3;`
  |-SCANCODE_INTERNATIONAL4 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL4=SDL_SCANCODE_INTERNATIONAL4;`
  |-SCANCODE_INTERNATIONAL5 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL5=SDL_SCANCODE_INTERNATIONAL5;`
  |-SCANCODE_INTERNATIONAL6 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL6=SDL_SCANCODE_INTERNATIONAL6;`
  |-SCANCODE_INTERNATIONAL7 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL7=SDL_SCANCODE_INTERNATIONAL7;`
  |-SCANCODE_INTERNATIONAL8 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL8=SDL_SCANCODE_INTERNATIONAL8;`
  |-SCANCODE_INTERNATIONAL9 (variable) [definition]: `static int const SCANCODE_INTERNATIONAL9=SDL_SCANCODE_INTERNATIONAL9;`
  |-SCANCODE_LANG1 (variable) [definition]: `static int const SCANCODE_LANG1=SDL_SCANCODE_LANG1;`
  |-SCANCODE_LANG2 (variable) [definition]: `static int const SCANCODE_LANG2=SDL_SCANCODE_LANG2;`
  |-SCANCODE_LANG3 (variable) [definition]: `static int const SCANCODE_LANG3=SDL_SCANCODE_LANG3;`
  |-SCANCODE_LANG4 (variable) [definition]: `static int const SCANCODE_LANG4=SDL_SCANCODE_LANG4;`
  |-SCANCODE_LANG5 (variable) [definition]: `static int const SCANCODE_LANG5=SDL_SCANCODE_LANG5;`
  |-SCANCODE_LANG6 (variable) [definition]: `static int const SCANCODE_LANG6=SDL_SCANCODE_LANG6;`
  |-SCANCODE_LANG7 (variable) [definition]: `static int const SCANCODE_LANG7=SDL_SCANCODE_LANG7;`
  |-SCANCODE_LANG8 (variable) [definition]: `static int const SCANCODE_LANG8=SDL_SCANCODE_LANG8;`
  |-SCANCODE_LANG9 (variable) [definition]: `static int const SCANCODE_LANG9=SDL_SCANCODE_LANG9;`
  |-SCANCODE_ALTERASE (variable) [definition]: `static int const SCANCODE_ALTERASE=SDL_SCANCODE_ALTERASE;`
  |-SCANCODE_SYSREQ (variable) [definition]: `static int const SCANCODE_SYSREQ=SDL_SCANCODE_SYSREQ;`
  |-SCANCODE_CANCEL (variable) [definition]: `static int const SCANCODE_CANCEL=SDL_SCANCODE_CANCEL;`
  |-SCANCODE_CLEAR (variable) [definition]: `static int const SCANCODE_CLEAR=SDL_SCANCODE_CLEAR;`
  |-SCANCODE_PRIOR (variable) [definition]: `static int const SCANCODE_PRIOR=SDL_SCANCODE_PRIOR;`
  |-SCANCODE_RETURN2 (variable) [definition]: `static int const SCANCODE_RETURN2=SDL_SCANCODE_RETURN2;`
  |-SCANCODE_SEPARATOR (variable) [definition]: `static int const SCANCODE_SEPARATOR=SDL_SCANCODE_SEPARATOR;`
  |-SCANCODE_OUT (variable) [definition]: `static int const SCANCODE_OUT=SDL_SCANCODE_OUT;`
  |-SCANCODE_OPER (variable) [definition]: `static int const SCANCODE_OPER=SDL_SCANCODE_OPER;`
  |-SCANCODE_CLEARAGAIN (variable) [definition]: `static int const SCANCODE_CLEARAGAIN=SDL_SCANCODE_CLEARAGAIN;`
  |-SCANCODE_CRSEL (variable) [definition]: `static int const SCANCODE_CRSEL=SDL_SCANCODE_CRSEL;`
  |-SCANCODE_EXSEL (variable) [definition]: `static int const SCANCODE_EXSEL=SDL_SCANCODE_EXSEL;`
  |-SCANCODE_KP_00 (variable) [definition]: `static int const SCANCODE_KP_00=SDL_SCANCODE_KP_00;`
  |-SCANCODE_KP_000 (variable) [definition]: `static int const SCANCODE_KP_000=SDL_SCANCODE_KP_000;`
  |-SCANCODE_THOUSANDSSEPARATOR (variable) [definition]: `static int const SCANCODE_THOUSANDSSEPARATOR=SDL_SCANCODE_THOUSANDSSEPARATOR;`
  |-SCANCODE_DECIMALSEPARATOR (variable) [definition]: `static int const SCANCODE_DECIMALSEPARATOR=SDL_SCANCODE_DECIMALSEPARATOR;`
  |-SCANCODE_CURRENCYUNIT (variable) [definition]: `static int const SCANCODE_CURRENCYUNIT=SDL_SCANCODE_CURRENCYUNIT;`
  |-SCANCODE_CURRENCYSUBUNIT (variable) [definition]: `static int const SCANCODE_CURRENCYSUBUNIT=SDL_SCANCODE_CURRENCYSUBUNIT;`
  |-SCANCODE_KP_LEFTPAREN (variable) [definition]: `static int const SCANCODE_KP_LEFTPAREN=SDL_SCANCODE_KP_LEFTPAREN;`
  |-SCANCODE_KP_RIGHTPAREN (variable) [definition]: `static int const SCANCODE_KP_RIGHTPAREN=SDL_SCANCODE_KP_RIGHTPAREN;`
  |-SCANCODE_KP_LEFTBRACE (variable) [definition]: `static int const SCANCODE_KP_LEFTBRACE=SDL_SCANCODE_KP_LEFTBRACE;`
  |-SCANCODE_KP_RIGHTBRACE (variable) [definition]: `static int const SCANCODE_KP_RIGHTBRACE=SDL_SCANCODE_KP_RIGHTBRACE;`
  |-SCANCODE_KP_TAB (variable) [definition]: `static int const SCANCODE_KP_TAB=SDL_SCANCODE_KP_TAB;`
  |-SCANCODE_KP_BACKSPACE (variable) [definition]: `static int const SCANCODE_KP_BACKSPACE=SDL_SCANCODE_KP_BACKSPACE;`
  |-SCANCODE_KP_A (variable) [definition]: `static int const SCANCODE_KP_A=SDL_SCANCODE_KP_A;`
  |-SCANCODE_KP_B (variable) [definition]: `static int const SCANCODE_KP_B=SDL_SCANCODE_KP_B;`
  |-SCANCODE_KP_C (variable) [definition]: `static int const SCANCODE_KP_C=SDL_SCANCODE_KP_C;`
  |-SCANCODE_KP_D (variable) [definition]: `static int const SCANCODE_KP_D=SDL_SCANCODE_KP_D;`
  |-SCANCODE_KP_E (variable) [definition]: `static int const SCANCODE_KP_E=SDL_SCANCODE_KP_E;`
  |-SCANCODE_KP_F (variable) [definition]: `static int const SCANCODE_KP_F=SDL_SCANCODE_KP_F;`
  |-SCANCODE_KP_XOR (variable) [definition]: `static int const SCANCODE_KP_XOR=SDL_SCANCODE_KP_XOR;`
  |-SCANCODE_KP_POWER (variable) [definition]: `static int const SCANCODE_KP_POWER=SDL_SCANCODE_KP_POWER;`
  |-SCANCODE_KP_PERCENT (variable) [definition]: `static int const SCANCODE_KP_PERCENT=SDL_SCANCODE_KP_PERCENT;`
  |-SCANCODE_KP_LESS (variable) [definition]: `static int const SCANCODE_KP_LESS=SDL_SCANCODE_KP_LESS;`
  |-SCANCODE_KP_GREATER (variable) [definition]: `static int const SCANCODE_KP_GREATER=SDL_SCANCODE_KP_GREATER;`
  |-SCANCODE_KP_AMPERSAND (variable) [definition]: `static int const SCANCODE_KP_AMPERSAND=SDL_SCANCODE_KP_AMPERSAND;`
  |-SCANCODE_KP_DBLAMPERSAND (variable) [definition]: `static int const SCANCODE_KP_DBLAMPERSAND=SDL_SCANCODE_KP_DBLAMPERSAND;`
  |-SCANCODE_KP_VERTICALBAR (variable) [definition]: `static int const SCANCODE_KP_VERTICALBAR=SDL_SCANCODE_KP_VERTICALBAR;`
  |-SCANCODE_KP_DBLVERTICALBAR (variable) [definition]: `static int const SCANCODE_KP_DBLVERTICALBAR=SDL_SCANCODE_KP_DBLVERTICALBAR;`
  |-SCANCODE_KP_COLON (variable) [definition]: `static int const SCANCODE_KP_COLON=SDL_SCANCODE_KP_COLON;`
  |-SCANCODE_KP_HASH (variable) [definition]: `static int const SCANCODE_KP_HASH=SDL_SCANCODE_KP_HASH;`
  |-SCANCODE_KP_SPACE (variable) [definition]: `static int const SCANCODE_KP_SPACE=SDL_SCANCODE_KP_SPACE;`
  |-SCANCODE_KP_AT (variable) [definition]: `static int const SCANCODE_KP_AT=SDL_SCANCODE_KP_AT;`
  |-SCANCODE_KP_EXCLAM (variable) [definition]: `static int const SCANCODE_KP_EXCLAM=SDL_SCANCODE_KP_EXCLAM;`
  |-SCANCODE_KP_MEMSTORE (variable) [definition]: `static int const SCANCODE_KP_MEMSTORE=SDL_SCANCODE_KP_MEMSTORE;`
  |-SCANCODE_KP_MEMRECALL (variable) [definition]: `static int const SCANCODE_KP_MEMRECALL=SDL_SCANCODE_KP_MEMRECALL;`
  |-SCANCODE_KP_MEMCLEAR (variable) [definition]: `static int const SCANCODE_KP_MEMCLEAR=SDL_SCANCODE_KP_MEMCLEAR;`
  |-SCANCODE_KP_MEMADD (variable) [definition]: `static int const SCANCODE_KP_MEMADD=SDL_SCANCODE_KP_MEMADD;`
  |-SCANCODE_KP_MEMSUBTRACT (variable) [definition]: `static int const SCANCODE_KP_MEMSUBTRACT=SDL_SCANCODE_KP_MEMSUBTRACT;`
  |-SCANCODE_KP_MEMMULTIPLY (variable) [definition]: `static int const SCANCODE_KP_MEMMULTIPLY=SDL_SCANCODE_KP_MEMMULTIPLY;`
  |-SCANCODE_KP_MEMDIVIDE (variable) [definition]: `static int const SCANCODE_KP_MEMDIVIDE=SDL_SCANCODE_KP_MEMDIVIDE;`
  |-SCANCODE_KP_PLUSMINUS (variable) [definition]: `static int const SCANCODE_KP_PLUSMINUS=SDL_SCANCODE_KP_PLUSMINUS;`
  |-SCANCODE_KP_CLEAR (variable) [definition]: `static int const SCANCODE_KP_CLEAR=SDL_SCANCODE_KP_CLEAR;`
  |-SCANCODE_KP_CLEARENTRY (variable) [definition]: `static int const SCANCODE_KP_CLEARENTRY=SDL_SCANCODE_KP_CLEARENTRY;`
  |-SCANCODE_KP_BINARY (variable) [definition]: `static int const SCANCODE_KP_BINARY=SDL_SCANCODE_KP_BINARY;`
  |-SCANCODE_KP_OCTAL (variable) [definition]: `static int const SCANCODE_KP_OCTAL=SDL_SCANCODE_KP_OCTAL;`
  |-SCANCODE_KP_DECIMAL (variable) [definition]: `static int const SCANCODE_KP_DECIMAL=SDL_SCANCODE_KP_DECIMAL;`
  |-SCANCODE_KP_HEXADECIMAL (variable) [definition]: `static int const SCANCODE_KP_HEXADECIMAL=SDL_SCANCODE_KP_HEXADECIMAL;`
  |-SCANCODE_LCTRL (variable) [definition]: `static int const SCANCODE_LCTRL=SDL_SCANCODE_LCTRL;`
  |-SCANCODE_LSHIFT (variable) [definition]: `static int const SCANCODE_LSHIFT=SDL_SCANCODE_LSHIFT;`
  |-SCANCODE_LALT (variable) [definition]: `static int const SCANCODE_LALT=SDL_SCANCODE_LALT;`
  |-SCANCODE_LGUI (variable) [definition]: `static int const SCANCODE_LGUI=SDL_SCANCODE_LGUI;`
  |-SCANCODE_RCTRL (variable) [definition]: `static int const SCANCODE_RCTRL=SDL_SCANCODE_RCTRL;`
  |-SCANCODE_RSHIFT (variable) [definition]: `static int const SCANCODE_RSHIFT=SDL_SCANCODE_RSHIFT;`
  |-SCANCODE_RALT (variable) [definition]: `static int const SCANCODE_RALT=SDL_SCANCODE_RALT;`
  |-SCANCODE_RGUI (variable) [definition]: `static int const SCANCODE_RGUI=SDL_SCANCODE_RGUI;`
  |-SCANCODE_MODE (variable) [definition]: `static int const SCANCODE_MODE=SDL_SCANCODE_MODE;`
  |-SCANCODE_AUDIONEXT (variable) [definition]: `static int const SCANCODE_AUDIONEXT=SDL_SCANCODE_AUDIONEXT;`
  |-SCANCODE_AUDIOPREV (variable) [definition]: `static int const SCANCODE_AUDIOPREV=SDL_SCANCODE_AUDIOPREV;`
  |-SCANCODE_AUDIOSTOP (variable) [definition]: `static int const SCANCODE_AUDIOSTOP=SDL_SCANCODE_AUDIOSTOP;`
  |-SCANCODE_AUDIOPLAY (variable) [definition]: `static int const SCANCODE_AUDIOPLAY=SDL_SCANCODE_AUDIOPLAY;`
  |-SCANCODE_AUDIOMUTE (variable) [definition]: `static int const SCANCODE_AUDIOMUTE=SDL_SCANCODE_AUDIOMUTE;`
  |-SCANCODE_MEDIASELECT (variable) [definition]: `static int const SCANCODE_MEDIASELECT=SDL_SCANCODE_MEDIASELECT;`
  |-SCANCODE_WWW (variable) [definition]: `static int const SCANCODE_WWW=SDL_SCANCODE_WWW;`
  |-SCANCODE_MAIL (variable) [definition]: `static int const SCANCODE_MAIL=SDL_SCANCODE_MAIL;`
  |-SCANCODE_CALCULATOR (variable) [definition]: `static int const SCANCODE_CALCULATOR=SDL_SCANCODE_CALCULATOR;`
  |-SCANCODE_COMPUTER (variable) [definition]: `static int const SCANCODE_COMPUTER=SDL_SCANCODE_COMPUTER;`
  |-SCANCODE_AC_SEARCH (variable) [definition]: `static int const SCANCODE_AC_SEARCH=SDL_SCANCODE_AC_SEARCH;`
  |-SCANCODE_AC_HOME (variable) [definition]: `static int const SCANCODE_AC_HOME=SDL_SCANCODE_AC_HOME;`
  |-SCANCODE_AC_BACK (variable) [definition]: `static int const SCANCODE_AC_BACK=SDL_SCANCODE_AC_BACK;`
  |-SCANCODE_AC_FORWARD (variable) [definition]: `static int const SCANCODE_AC_FORWARD=SDL_SCANCODE_AC_FORWARD;`
  |-SCANCODE_AC_STOP (variable) [definition]: `static int const SCANCODE_AC_STOP=SDL_SCANCODE_AC_STOP;`
  |-SCANCODE_AC_REFRESH (variable) [definition]: `static int const SCANCODE_AC_REFRESH=SDL_SCANCODE_AC_REFRESH;`
  |-SCANCODE_AC_BOOKMARKS (variable) [definition]: `static int const SCANCODE_AC_BOOKMARKS=SDL_SCANCODE_AC_BOOKMARKS;`
  |-SCANCODE_BRIGHTNESSDOWN (variable) [definition]: `static int const SCANCODE_BRIGHTNESSDOWN=SDL_SCANCODE_BRIGHTNESSDOWN;`
  |-SCANCODE_BRIGHTNESSUP (variable) [definition]: `static int const SCANCODE_BRIGHTNESSUP=SDL_SCANCODE_BRIGHTNESSUP;`
  |-SCANCODE_DISPLAYSWITCH (variable) [definition]: `static int const SCANCODE_DISPLAYSWITCH=SDL_SCANCODE_DISPLAYSWITCH;`
  |-SCANCODE_KBDILLUMTOGGLE (variable) [definition]: `static int const SCANCODE_KBDILLUMTOGGLE=SDL_SCANCODE_KBDILLUMTOGGLE;`
  |-SCANCODE_KBDILLUMDOWN (variable) [definition]: `static int const SCANCODE_KBDILLUMDOWN=SDL_SCANCODE_KBDILLUMDOWN;`
  |-SCANCODE_KBDILLUMUP (variable) [definition]: `static int const SCANCODE_KBDILLUMUP=SDL_SCANCODE_KBDILLUMUP;`
  |-SCANCODE_EJECT (variable) [definition]: `static int const SCANCODE_EJECT=SDL_SCANCODE_EJECT;`
  |-SCANCODE_SLEEP (variable) [definition]: `static int const SCANCODE_SLEEP=SDL_SCANCODE_SLEEP;`
  |-SCANCODE_APP1 (variable) [definition]: `static int const SCANCODE_APP1=SDL_SCANCODE_APP1;`
  |-SCANCODE_APP2 (variable) [definition]: `static int const SCANCODE_APP2=SDL_SCANCODE_APP2;`
  |-HAT_CENTER (variable) [definition]: `static int const HAT_CENTER=SDL_HAT_CENTERED;`
  |-HAT_UP (variable) [definition]: `static int const HAT_UP=SDL_HAT_UP;`
  |-HAT_RIGHT (variable) [definition]: `static int const HAT_RIGHT=SDL_HAT_RIGHT;`
  |-HAT_DOWN (variable) [definition]: `static int const HAT_DOWN=SDL_HAT_DOWN;`
  |-HAT_LEFT (variable) [definition]: `static int const HAT_LEFT=SDL_HAT_LEFT;`
  |-CONTROLLER_BUTTON_A (variable) [definition]: `static int const CONTROLLER_BUTTON_A=SDL_CONTROLLER_BUTTON_A;`
  |-CONTROLLER_BUTTON_B (variable) [definition]: `static int const CONTROLLER_BUTTON_B=SDL_CONTROLLER_BUTTON_B;`
  |-CONTROLLER_BUTTON_X (variable) [definition]: `static int const CONTROLLER_BUTTON_X=SDL_CONTROLLER_BUTTON_X;`
  |-CONTROLLER_BUTTON_Y (variable) [definition]: `static int const CONTROLLER_BUTTON_Y=SDL_CONTROLLER_BUTTON_Y;`
  |-CONTROLLER_BUTTON_BACK (variable) [definition]: `static int const CONTROLLER_BUTTON_BACK=SDL_CONTROLLER_BUTTON_BACK;`
  |-CONTROLLER_BUTTON_GUIDE (variable) [definition]: `static int const CONTROLLER_BUTTON_GUIDE=SDL_CONTROLLER_BUTTON_GUIDE;`
  |-CONTROLLER_BUTTON_START (variable) [definition]: `static int const CONTROLLER_BUTTON_START=SDL_CONTROLLER_BUTTON_START;`
  |-CONTROLLER_BUTTON_LEFTSTICK (variable) [definition]: `static int const CONTROLLER_BUTTON_LEFTSTICK=SDL_CONTROLLER_BUTTON_LEFTSTICK;`
  |-CONTROLLER_BUTTON_RIGHTSTICK (variable) [definition]: `static int const CONTROLLER_BUTTON_RIGHTSTICK=SDL_CONTROLLER_BUTTON_RIGHTSTICK;`
  |-CONTROLLER_BUTTON_LEFTSHOULDER (variable) [definition]: `static int const CONTROLLER_BUTTON_LEFTSHOULDER=SDL_CONTROLLER_BUTTON_LEFTSHOULDER;`
  |-CONTROLLER_BUTTON_RIGHTSHOULDER (variable) [definition]: `static int const CONTROLLER_BUTTON_RIGHTSHOULDER=SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;`
  |-CONTROLLER_BUTTON_DPAD_UP (variable) [definition]: `static int const CONTROLLER_BUTTON_DPAD_UP=SDL_CONTROLLER_BUTTON_DPAD_UP;`
  |-CONTROLLER_BUTTON_DPAD_DOWN (variable) [definition]: `static int const CONTROLLER_BUTTON_DPAD_DOWN=SDL_CONTROLLER_BUTTON_DPAD_DOWN;`
  |-CONTROLLER_BUTTON_DPAD_LEFT (variable) [definition]: `static int const CONTROLLER_BUTTON_DPAD_LEFT=SDL_CONTROLLER_BUTTON_DPAD_LEFT;`
  |-CONTROLLER_BUTTON_DPAD_RIGHT (variable) [definition]: `static int const CONTROLLER_BUTTON_DPAD_RIGHT=SDL_CONTROLLER_BUTTON_DPAD_RIGHT;`
  |-CONTROLLER_AXIS_LEFTX (variable) [definition]: `static int const CONTROLLER_AXIS_LEFTX=SDL_CONTROLLER_AXIS_LEFTX;`
  |-CONTROLLER_AXIS_LEFTY (variable) [definition]: `static int const CONTROLLER_AXIS_LEFTY=SDL_CONTROLLER_AXIS_LEFTY;`
  |-CONTROLLER_AXIS_RIGHTX (variable) [definition]: `static int const CONTROLLER_AXIS_RIGHTX=SDL_CONTROLLER_AXIS_RIGHTX;`
  |-CONTROLLER_AXIS_RIGHTY (variable) [definition]: `static int const CONTROLLER_AXIS_RIGHTY=SDL_CONTROLLER_AXIS_RIGHTY;`
  |-CONTROLLER_AXIS_TRIGGERLEFT (variable) [definition]: `static int const CONTROLLER_AXIS_TRIGGERLEFT=SDL_CONTROLLER_AXIS_TRIGGERLEFT;`
  +-CONTROLLER_AXIS_TRIGGERRIGHT (variable) [definition]: `static int const CONTROLLER_AXIS_TRIGGERRIGHT=SDL_CONTROLLER_AXIS_TRIGGERRIGHT;`

Typedefs of element type in pointer/reference to array are ignored

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

When having a pointer/reference to an array, the element type of the array will ignore typedefs and return the underlying type as element type instead. This is due to a libclang workaround that requires a call to clang_getCanonicalType() on the array type returned by a call to clang_getPointeeType(); otherwise clang_getElementType() won't work. But clang_getCanonicalType() strips away all typedefs, so they can't be exposed.

Input:

using foo = int;
using type = foo(&)[10];

Element type of the array will be a plain int, not foo.

LIBCLANG_LIBRARY-NOTFOUND.lib

  • cppast version:
  • parser: libclang_parser
  • clang version: <4.0.1>

compile error:
1>------ 已启动生成: 项目: cppast_test, 配置: Debug Win32 ------
2>------ 已启动生成: 项目: cppast_tool, 配置: Debug Win32 ------
2>LINK : fatal error LNK1104: 无法打开文件“LIBCLANG_LIBRARY-NOTFOUND.lib”
1>LINK : fatal error LNK1104: 无法打开文件“LIBCLANG_LIBRARY-NOTFOUND.lib”

I can't find the library in clang or llvm project.
I don't understand why the library name.

Constructor attributes are not captured when they precede the name.

  • cppast version: latest
  • parser: libclang_parser
  • clang version: 6.0

Attributes in constructors are captured only if they appear after constructor's name.

Input:

// this works:
struct X
{
    X [[my_ctor]]] () {}
};

// but this doesn't work as I would expect it to:
struct Y
{
    [[my_ctor]]
    Y() {}
};

Input flags: same as for unit tests.

Any chance for examples of common usage?

Right now it's hard to see where to get started, what are the main "entry points" from the library users' perspective. Examples of extracting member functions, attributes, enums etc. would be great.

Example using cpp_entity_index

Hey is it possible to use cpp_entity_index for our own purposes? I cant really see how.

What i am trying to do

As you know i am writing c# bindings generator. Part of the process is to drop certain parts of API that contain unknown types. Consider Texture* GetTexture() method. cpp_member_function pointing to GetTexture() provides return type Texture* as cpp_type. Is there any way to look into cpp_entity_index and see if there is class Texture defined? I did some debugging of cppast and i see that ids are like "c:@N@Urho3D@S@Texture". I probably should not go around trying to guess them manually myself..

Integer promotion issue in 32 bit builds

It seems that std::size_t is not unsigned long long in 32 bit builds. I would change the hash type to std::uin64_t or unsigned long long.

/home/conan/build/cppast-src/src/../include/cppast/cpp_entity_index.hpp:26:43: error: large integer implicitly truncated to unsigned type [-Werror=overflow]
         constexpr std::size_t fnv_basis = 14695981039346656037ull;       
                                           ^                       
/home/conan/build/cppast-src/src/../include/cppast/cpp_entity_index.hpp:27:43: error: large integer implicitly truncated to unsigned type [-Werror=overflow]
         constexpr std::size_t fnv_prime = 1099511628211ull; 

Unexposed expression string representation is not complete

  • cppast version: latest
  • clang version: 5.0.1

In some rare cases string representation of unexposed expression is incomplete. Happened to me exactly once, last character is missing in this case.

Input:

void SetEventFrame(float time, const StringHash& eventType, const VariantMap& eventData = VariantMap());

Output:
dynamic_cast<const cppast::cpp_unexposed_expression&>(expression).expression().as_string() returns VariantMap(.

AST for 'Scene/ValueAnimation.h':
|-../Core/Variant.h (include directive): `#include "../Core/Variant.h"`
|-../Resource/Resource.h (include directive): `#include "../Resource/Resource.h"`
+-Urho3D (namespace)
  +-ValueAnimation (class) [definition]: `class ValueAnimation;`
    |-public (access specifier): `public:`
    |-ClassName (type alias): `using ClassName=Urho3D::ValueAnimation;`
    |-BaseClassName (type alias): `using BaseClassName=Urho3D::Resource;`
    |-SetEventFrame (member function): `void SetEventFrame(float time,Urho3D::StringHash const& eventType,Urho3D::VariantMap const& eventData=VariantMap();`

`extern` template are treated as class template specializations

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

An extern template will be treated as a (full) class template specialization.

Input:

template <typename T>
struct foo {};

template <>
extern struct foo<int>;

Output:

AST for 'file.cpp':
|-foo (class template) [definition]: `template<typename T> struct foo;`
+-foo (class template specialization): `template<> struct foo<int>;`

Walking a template specialization

Consider std::vector<std::string> used as return type somewhere. Is there a way to somehow use that return type and walk instantiation of class std::vector<std::string> so that methods of std::vector have std::string type inserted where appropriate? Or do i have to resolve these template types manually somehow?

P.S. I hope i am not getting annoying with spamming issue tracker with random questions. If there is a better place to ask these things please let me know.
P.P.S. Thank you for the help with other issues, i greatly appreciate swift response. Just never posted "thanks" messages to save you some spam in the mailbox :)

Visual Studio Support

I'm guessing this does not support windows or visual studio, because it depends on clang, but I was wondering if there was a chance, or similar tool that does support windows/visual studio. Thanks!

Variable type of pointer to member variable is unexposed

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

If you have a pointer to a member variable, you'll correctly get a cpp_pointer_type to a cpp_member_object_type but the type returned by object_type() is always a cpp_unexposed_type.
This is due to an issue with libclang's clang_getPointeeType() returning an invalid type for pointers to member variable (works fine with pointers to member functions).

Input:

struct foo {};

using type = int(foo::*);

Missing identifiers in global namespace

  • cppast version: fork (Current cppast master + two commits, see diff in the link).
  • libclang version: 3.9.1

Hi,

I'm sure this issue is not a cppast bug, but since I'm clueless right now I'm approaching you for help...

I've found that my parser is giving errors about undeclared entities in the global namespace, like std in std::string foo;, or tinyrefl in tinyrefl::foobar foo();

I think the issue is not related to missing include directories (there are no warnings/errors about missing headers), but just in case I've added the gcc/clang search include directories to the set of include directories of the parser. That doesn't fix the issue though.

Here is an example of the error, from a CI build. The tool parser setup is as follows:

bool reflect_file(const std::string& filepath, const std::string& cpp_standard, const std::vector<std::string>& include_dirs)
{
    using parser_t = cppast::simple_file_parser<cppast::libclang_parser>;

    if(!is_outdated_file(filepath))
    {
        std::cout << "file " << filepath << " metadata is up to date, skipping\n";
        return true;
    }

    cppast::cpp_entity_index index;
    parser_t parser{type_safe::ref(index)};
    parser_t::config config;
    config.set_flags(get_cpp_standard(cpp_standard));
    config.add_flag("-fPIC");

    std::cout << "parsing file " << filepath << " -std=c++"
        << cpp_standard << " ";

    for(const std::string& include_dir : include_dirs)
    {
        std::cout << "-I" << include_dir << " ";
        config.add_include_dir(include_dir);
    }

    std::cout << " ...\n";

    try
    {
        auto file = parser.parse(filepath, config);
        ...

as you can see the parser is fed with the C++ standard and set of include directories given as command line arguments to the tool.

error: invalid filename for #line directive on windows

  • cppast version: latest
  • clang version: 5.0.1 / 6.0.0
  • MSVC 19.12.25834.0 (vs 2017)

Input cpp file:

#include <type_traits>
void foo() { }

Output:

cppast.exe --msvc_extensions --msvc_compatibility test.cpp
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2518):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:70: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2544):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:69: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2548):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:70: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2552):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:69: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2563):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:69: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2567):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:70: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2571):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:69: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2583):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:69: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2587):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:70: note: expanded from here
[preprocessor] [error] In file included from ..\test.cpp: 1:
[preprocessor] [error] C: \Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.12.25827\include\type_traits(2591):  error: invalid filename for #line directive
[preprocessor] [error] <scratch space>:69: note: expanded from here
[fatal parsing error] preprocessor: command 'C:/LLVM/bin/clang++.exe -x c++ -E -CC -dD -Xclang -dI -fno-caret-diagnostics -fno-show-column -fdiagnostics-format=msvc -Wno-macro-redefined -Wno-pragma-once-outside-header -Wno-pragma-system-header-outside-header -Wno-include-next-outside-header -IC:/LLVM -D__cppast__="libclang" -D__cppast_version_major__="0" -D__cppast_version_minor__="0" -std=c++14 -fms-compatibility -fms-extensions "test.cpp"' exited with non-zero exit code (1)
``

Support for custom llvm binary download URL

Hi,

To have reliable builds I'm thinking about patching external/external.cmake to allow passing a custom LLVM download URL (Say an internal binary server instead of pulling directly from LLVM releases). I would like to know your opinion on this.

Thanks in advance.

Mangled names

Would it be possible to expose mangled names? It could be very helpful when generating API wrappers for foreign languages.

Why can't read multiple attributes?

  • cppast version: last one
  • parser: libclang_parser
  • clang version: 6.0.0

Explanation of the error.

Input:

[[gnu::always_inline]] [[gnu::hot]] [[gnu::const]] [[nodiscard]]
inline int f(); // declare f with four attributes.
//this is ok,but cppast only read last attribute(nodiscard)
//https://en.cppreference.com/w/cpp/language/attributes

Input flags:

Output:

Output of `cppast -v <input>`

How to selectively parse a header file

I want to parse a header file and run through the AST. I'm using the Tool code as a base.
My code layout is like this:

// MyCppFile.cpp
#include "DataXYZ.h"
#include "MyHeader.h" // makes use of things in DataXYZ.h

If I parse just MyHeader.h, it cannot see DataXYZ, (as expected), and so there are unknown types. So I want to parse MyCppFile.cpp, run through the AST and only pay attention to the entries once I hit MyHeader.h

I thought I could achieve this by parsing MyCppFile.cpp, then visiting the AST until I get to the relevant include_directive_t and then parsing everything inside that, but the AST does not seem to include anything outside of the original source file.

I've tried a few other approaches too, with no luck, and I feel like I'm missing something simple.
Can you clarify how I should be approaching this please?

Expose __attribute__ and __declspec attributes

I found myself in need of these attributes. When generating bindings it is useful to know if certain type is exported from dll or not. These attributes are used for exactly this purpose and it would be extremely handy to get info. I myself hacked a sort of working solution: rokups/Urho3DNet@50babf2. If you think it is good enough i can submit a PR. If not - this is a feature request then :)

Expression of default values is always `cpp_unexposed_expression`

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

The default value of a function parameter, template non type parameter and the initializer of a (member) variable is not exposed.
This is due to an ambiguity when parsing the children of the libclang cursor, there is no way to distinguish between the expression in the array size and the expression of the initializer.

Also see #7.

Function parameters are not visited

I think this is because member_function_t is not treated as a container in detail::visit, and simply the callback is called instead of recursive visitation. I'd assume standardese would need to parse function paramters, wouldn't it?

  • cppast version: 2be20f6
  • parser: libclang_parser
  • clang version: 4.0

Explanation of the error.

Input:

    auto code = R"(
          class foo {
            void f(int a, int b){};
          };
    )";

    cpp_entity_index idx;
    auto file = parse(idx, "cpp_class.cpp", code);
    unsigned filtered_count = 0;
    auto visitor_callback = [&](const cpp_entity &e, cppast::visitor_info info) {
      if (info.event == cppast::visitor_info::container_entity_exit)
        return true;
      std::cout << e.name() << " : " << cppast::to_string(e.kind()) << "\n";
    };

    cppast::visit(*file, visitor_callback);

Output:

cpp_class.cpp : file
foo : class
f : member function

I would expect the function parameters a and b to be visible in the output.

Policies regarding project dependencies

I would like to open a discussion regarding how dependencies (and especially updating dependencies) should be handled in this project.

Please note I'm not talking about dependency managers or using a dependency manager

After some weeks working with the lib I found myself experimenting (Suffering, actually :P) the following scenario multiple times:

  • A dependency of a cppast dependency causes an issue.
  • Fix the issue
  • Update the cppast dependency to include the dependency of dependency fix
  • Update cppast to include the latest version of its dependency

This is exacerbated by the fact git submodules are a pain to work with (I'm at a 4th level in the dependency tree, with cppast being a submodule of my project). Maybe it's just me...

Anyway, I'm here because I think most of this issues would not be so if we write down some policies regarding cppast dependencies. Some ideas/questions:

  • Should cppast master include the latest master type_safe available?
  • What about type_safe and debug_assert? Same "always-up-to-date" policy as above?

Properly versioning the library(ies) would fix this situation ("cppast v1.3 uses type_safe v0.5, which uses debug_assert v1.0", but since all the three are under active development versioning is not a complete solution (In the case of stable releases the same issues would arise during development on the active branches).
Also, this same policies would make much more clear to me how to package the libraries.

Regarding versioning, maybe you could adopt a release train strategy, where you use cppast development (And Standardese) as locomotives of the train, releasing new versions of your libs every two months or so, including all master changes since the last release. In that case, I'm sure 90% of the time the release would be something like this:

  • debug_assert: Fixes, if any. Increase fix number
  • type_safe: Fixes, if any. Increase fix number. Reference debug_assert release above. A change whose sole purpose is to update to a non-breaking fix release of debug_assert is considered a fix. Updating to debug_assert minors (Like you developed a non-breaking debug_assert feature you find interesting for type_safe) is up to you. Else is major.
  • cppast: Features and/or fixes. Increase fix or minor number. Reference type_safe above. Same policies regarding dependencies described above.

Just some ideas, I would love to hear your opinion.

Thanks in advance.

Default type of template type parameter is unexposed

  • cppast version: latest one
  • parser: libclang_parser
  • clang version: 3.9.1+

The default type of a template type parameter is always unexposed, as there is no way to retrieve them from libclang.

Input:

template <typename T = int>
void foo();

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.