diff --git a/include/cppast/libclang_parser.hpp b/include/cppast/libclang_parser.hpp new file mode 100644 index 0000000..df56294 --- /dev/null +++ b/include/cppast/libclang_parser.hpp @@ -0,0 +1,44 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#ifndef CPPAST_LIBCLANG_PARSER_HPP_INCLUDED +#define CPPAST_LIBCLANG_PARSER_HPP_INCLUDED + +#include + +namespace cppast +{ + /// Compilation config for the [cppast::libclang_parser](). + class libclang_compile_config final : public compile_config + { + public: + libclang_compile_config(); + + private: + void do_set_flags(cpp_standard standard, type_safe::flag_set flags) override; + + void do_add_include_dir(std::string path) override; + + void do_add_macro_definition(std::string name, std::string definition) override; + + void do_remove_macro_definition(std::string name) override; + }; + + /// A parser that uses libclang. + class libclang_parser final : public parser + { + public: + libclang_parser(); + ~libclang_parser() noexcept override; + + private: + std::unique_ptr do_parse(const cpp_entity_index& idx, const std::string& path, + const compile_config& config) const override; + + struct impl; + std::unique_ptr pimpl_; + }; +} // namespace cppast + +#endif // CPPAST_LIBCLANG_PARSER_HPP_INCLUDED diff --git a/src/libclang/libclang_parser.cpp b/src/libclang/libclang_parser.cpp new file mode 100644 index 0000000..d031815 --- /dev/null +++ b/src/libclang/libclang_parser.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#include + +#include "raii_wrapper.hpp" + +using namespace cppast; + +libclang_compile_config::libclang_compile_config() : compile_config({}) +{ +} + +void libclang_compile_config::do_set_flags(cpp_standard standard, + type_safe::flag_set flags) +{ + switch (standard) + { + case cpp_standard::cpp_98: + if (flags & compile_flag::gnu_extensions) + add_flag("-std=gnu++98"); + else + add_flag("-std=c++98"); + break; + case cpp_standard::cpp_03: + if (flags & compile_flag::gnu_extensions) + add_flag("-std=gnu++03"); + else + add_flag("-std=c++03"); + break; + case cpp_standard::cpp_11: + if (flags & compile_flag::gnu_extensions) + add_flag("-std=gnu++11"); + else + add_flag("-std=c++11"); + break; + case cpp_standard::cpp_14: + if (flags & compile_flag::gnu_extensions) + add_flag("-std=gnu++14"); + else + add_flag("-std=c++14"); + break; + } + + if (flags & compile_flag::ms_compatibility) + add_flag("-fms-compatibility"); + if (flags & compile_flag::ms_extensions) + add_flag("-fms-extensions"); +} + +void libclang_compile_config::do_add_include_dir(std::string path) +{ + add_flag("-I" + std::move(path)); +} + +void libclang_compile_config::do_add_macro_definition(std::string name, std::string definition) +{ + auto str = "-D" + std::move(name); + if (!definition.empty()) + str += "=" + std::move(definition); + add_flag(std::move(str)); +} + +void libclang_compile_config::do_remove_macro_definition(std::string name) +{ + add_flag("-U" + std::move(name)); +} + +struct libclang_parser::impl +{ + detail::cxindex index; + + impl() : index(clang_createIndex(1, 1)) + { + } +}; + +libclang_parser::libclang_parser() +{ +} + +libclang_parser::~libclang_parser() noexcept +{ +} + +std::unique_ptr libclang_parser::do_parse(const cpp_entity_index& idx, + const std::string& path, + const compile_config& config) const +{ + return nullptr; +} diff --git a/src/libclang/raii_wrapper.hpp b/src/libclang/raii_wrapper.hpp new file mode 100644 index 0000000..3f6277b --- /dev/null +++ b/src/libclang/raii_wrapper.hpp @@ -0,0 +1,89 @@ +// Copyright (C) 2017 Jonathan Müller +// This file is subject to the license terms in the LICENSE file +// found in the top-level directory of this distribution. + +#ifndef CPPAST_RAII_WRAPPER_HPP_INCLUDED +#define CPPAST_RAII_WRAPPER_HPP_INCLUDED + +#include + +#include + +#include + +namespace cppast +{ + namespace detail + { + template + class raii_wrapper : Deleter + { + static_assert(std::is_pointer::value, ""); + + public: + raii_wrapper() noexcept : obj_(nullptr) + { + } + + raii_wrapper(T obj) noexcept : obj_(obj) + { + DEBUG_ASSERT(obj_, detail::assert_handler{}); + } + + raii_wrapper(raii_wrapper&& other) noexcept : obj_(other.obj_) + { + DEBUG_ASSERT(obj_, detail::assert_handler{}); + other.obj_ = nullptr; + } + + ~raii_wrapper() noexcept + { + if (obj_) + static_cast (*this)(obj_); + } + + raii_wrapper& operator=(raii_wrapper&& other) noexcept + { + raii_wrapper tmp(std::move(other)); + swap(*this, tmp); + return *this; + } + + friend void swap(raii_wrapper& a, raii_wrapper& b) noexcept + { + std::swap(a.obj_, b.obj_); + } + + T get() const noexcept + { + DEBUG_ASSERT(obj_, detail::assert_handler{}); + return obj_; + } + + private: + T obj_; + }; + + struct cxindex_deleter + { + void operator()(CXIndex idx) noexcept + { + clang_disposeIndex(idx); + } + }; + + using cxindex = raii_wrapper; + + struct cxtranslation_unit_deleter + { + void operator()(CXTranslationUnit unit) noexcept + { + clang_disposeTranslationUnit(unit); + } + }; + + using cxtranslation_unit = raii_wrapper; + } +} // namespace cppast::detail + +#endif // CPPAST_RAII_WRAPPER_HPP_INCLUDED