├── CPP2D ├── CustomPrinters.h ├── CustomPrinters.cpp ├── CustomPrinters │ ├── boost_port.cpp │ ├── c_stdlib_port.cpp │ └── cpp_stdlib_port.cpp ├── Options.cpp ├── Spliter.h ├── Options.h ├── CPP2DFrontendAction.h ├── CPP2DFrontendAction.cpp ├── CPP2DConsumer.h ├── CPP2DTools.h ├── CMakeLists.txt ├── CPP2DConsumer.cpp ├── CPP2DTools.cpp ├── CPP2D.vcxproj.user ├── CPP2D.cpp ├── CPP2DPPHandling.h ├── CPP2D.vcxproj.filters ├── MatchContainer.h ├── MatchContainer.cpp ├── CPP2DPPHandling.cpp ├── CPP2D.vcxproj └── DPrinter.h ├── CPP2D_UT_CPP ├── CMakeLists.txt ├── stdlib_testsuite.h ├── template_testsuite.h ├── CPP2D_UT_CPP.vcxproj.user ├── test.h ├── main.cpp ├── framework.cpp ├── framework.h ├── comment.cpp ├── CPP2D_UT_CPP.vcxproj.filters ├── template_testsuite.cpp ├── CPP2D_UT_CPP.vcxproj ├── stdlib_testsuite.cpp └── test.cpp ├── CMakeLists.txt ├── .gitignore ├── LICENSE_1_0.txt ├── .travis.yml ├── appveyor.yml ├── CPP2D.sln ├── cpp_std.d └── README.md /CPP2D/CustomPrinters.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lhamot/CPP2D/HEAD/CPP2D/CustomPrinters.h -------------------------------------------------------------------------------- /CPP2D/CustomPrinters.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lhamot/CPP2D/HEAD/CPP2D/CustomPrinters.cpp -------------------------------------------------------------------------------- /CPP2D_UT_CPP/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lhamot/CPP2D/HEAD/CPP2D_UT_CPP/CMakeLists.txt -------------------------------------------------------------------------------- /CPP2D_UT_CPP/stdlib_testsuite.h: -------------------------------------------------------------------------------- 1 | #include "framework.h" 2 | 3 | void stdlib_register(TestFrameWork& tf); -------------------------------------------------------------------------------- /CPP2D/CustomPrinters/boost_port.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lhamot/CPP2D/HEAD/CPP2D/CustomPrinters/boost_port.cpp -------------------------------------------------------------------------------- /CPP2D_UT_CPP/template_testsuite.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lhamot/CPP2D/HEAD/CPP2D_UT_CPP/template_testsuite.h -------------------------------------------------------------------------------- /CPP2D/CustomPrinters/c_stdlib_port.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lhamot/CPP2D/HEAD/CPP2D/CustomPrinters/c_stdlib_port.cpp -------------------------------------------------------------------------------- /CPP2D/CustomPrinters/cpp_stdlib_port.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lhamot/CPP2D/HEAD/CPP2D/CustomPrinters/cpp_stdlib_port.cpp -------------------------------------------------------------------------------- /CPP2D/Options.cpp: -------------------------------------------------------------------------------- 1 | #include "Options.h" 2 | 3 | Options& Options::getInstance() 4 | { 5 | static Options instance; 6 | return instance; 7 | } 8 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/CPP2D_UT_CPP.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/test.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #pragma once 8 | 9 | #include "framework.h" 10 | 11 | void test_register(TestFrameWork& tf); 12 | -------------------------------------------------------------------------------- /CPP2D/Spliter.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "DPrinter.h" 3 | 4 | struct Spliter 5 | { 6 | DPrinter& printer; 7 | std::string const str; 8 | bool first = true; 9 | 10 | Spliter(DPrinter& pr, std::string const& s) : printer(pr), str(s) {} 11 | 12 | void split() 13 | { 14 | if(first) 15 | first = false; 16 | else 17 | printer.stream() << str; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | project(cpp2d) 4 | 5 | if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -fno-rtti") 7 | endif() 8 | 9 | find_package(LLVM 6 REQUIRED) 10 | include_directories(${LLVM_INCLUDE_DIRS}) 11 | link_directories(${LLVM_LIBRARY_DIRS}) 12 | 13 | add_subdirectory(CPP2D) 14 | add_subdirectory(CPP2D_UT_CPP) 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | /CPP2D/x64/Debug 3 | /CPP2D/x64/Release 4 | *.patch 5 | /x64/Debug 6 | /x64/Release 7 | /AStyle.exe 8 | *.opensdf 9 | *.sdf 10 | /format.bat 11 | /todo.txt 12 | /CPP2D_UT_CPP/x64/Debug 13 | /CPP2D_UT_CPP/x64/Release 14 | /doc 15 | /*.vsp 16 | /*.psess 17 | /compile_commands.json 18 | /CPP2D_UT_CPP/*.tmp 19 | /garbage 20 | /CPP2D.VC.db 21 | /*.opendb 22 | /CPP2D_UT_CPP/compile_commands.json 23 | /build 24 | /CPP2D_UT_D 25 | -------------------------------------------------------------------------------- /CPP2D/Options.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct TypeOptions 7 | { 8 | //! Semantic of an object (Value or Reference) 9 | enum Semantic 10 | { 11 | Value, //!< Like **D** struct and everything in C++ 12 | Reference, //!< Garbage collected like **D** class 13 | AssocArray, //!< Special case for hashmap. Created without new, but reference semantic. 14 | }; 15 | 16 | std::string name; 17 | Semantic semantic; 18 | }; 19 | 20 | struct Options 21 | { 22 | std::unordered_map types; 23 | 24 | static Options& getInstance(); 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/main.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #include "framework.h" 8 | #include "test.h" 9 | #include "stdlib_testsuite.h" 10 | #include "template_testsuite.h" 11 | 12 | int main( 13 | int argc, char** argv 14 | ) 15 | { 16 | int argvCount = argc; 17 | CHECK(argvCount > 0); 18 | CHECK(argv[0] != nullptr); 19 | 20 | TestFrameWork testFrameWork; 21 | test_register(testFrameWork); 22 | stdlib_register(testFrameWork); 23 | template_register(testFrameWork); 24 | testFrameWork.run(); 25 | 26 | testFrameWork.print_results(); 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /CPP2D/CPP2DFrontendAction.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #pragma once 8 | 9 | #include 10 | 11 | #pragma warning(push, 0) 12 | #include "clang/Frontend/FrontendActions.h" 13 | #pragma warning(pop) 14 | 15 | namespace clang 16 | { 17 | class CompilerInstance; 18 | } 19 | 20 | class CPP2DPPHandling; 21 | 22 | //! Implement clang::ASTFrontendAction to create the CPP2DConsumer 23 | class CPP2DFrontendAction : public clang::ASTFrontendAction 24 | { 25 | public: 26 | //! Create the CPP2DConsumer 27 | std::unique_ptr CreateASTConsumer( 28 | clang::CompilerInstance& Compiler, 29 | llvm::StringRef InFile 30 | ) override; 31 | 32 | //! Add the CPP2DPPHandling (PPCallbacks) to the Preprocessor 33 | bool BeginSourceFileAction(clang::CompilerInstance& ci) override; 34 | 35 | private: 36 | CPP2DPPHandling* ppHandlingPtr = nullptr; 37 | }; 38 | -------------------------------------------------------------------------------- /CPP2D/CPP2DFrontendAction.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #include "CPP2DFrontendAction.h" 9 | 10 | #include 11 | 12 | #pragma warning(push, 0) 13 | #include 14 | #include 15 | #pragma warning(pop) 16 | 17 | #include "CPP2DConsumer.h" 18 | #include "CPP2DPPHandling.h" 19 | 20 | using namespace clang; 21 | 22 | std::unique_ptr CPP2DFrontendAction::CreateASTConsumer( 23 | clang::CompilerInstance& Compiler, 24 | llvm::StringRef InFile 25 | ) 26 | { 27 | auto consumer = std::make_unique(Compiler, InFile); 28 | consumer->setPPCallBack(ppHandlingPtr); 29 | return std::move(consumer); 30 | } 31 | 32 | bool CPP2DFrontendAction::BeginSourceFileAction(CompilerInstance& ci) 33 | { 34 | Preprocessor& pp = ci.getPreprocessor(); 35 | auto ppHandling = std::make_unique(pp.getSourceManager(), pp, getCurrentFile()); 36 | ppHandlingPtr = ppHandling.get(); 37 | pp.addPPCallbacks(std::move(ppHandling)); 38 | return true; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/framework.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #include 8 | #include "framework.h" 9 | 10 | unsigned int testCount = 0; 11 | 12 | void check(bool ok, char const* message, int line, char const* file) 13 | { 14 | ++testCount; 15 | if (!ok) 16 | { 17 | //printf(message); 18 | printf("%s ->Failed at line %u, in file %s\n", message, line, file); 19 | } 20 | } 21 | 22 | void TestSuite::run() const noexcept 23 | { 24 | for (TestCase const& testcase : testCases) 25 | { 26 | try 27 | { 28 | testcase(); 29 | } 30 | catch (std::exception& ex) 31 | { 32 | printf("%s", ex.what()); 33 | } 34 | } 35 | } 36 | 37 | void TestSuite::addTestCase(TestCase testCase) 38 | { 39 | testCases.push_back(testCase); 40 | } 41 | 42 | void TestFrameWork::run() const noexcept 43 | { 44 | for (std::unique_ptr const& suite : testSuites) 45 | suite->run(); 46 | } 47 | 48 | void TestFrameWork::print_results() 49 | { 50 | printf("%u tests\n", testCount); 51 | } 52 | 53 | void TestFrameWork::addTestSuite(std::unique_ptr&& testSuite) 54 | { 55 | testSuites.emplace_back(std::move(testSuite)); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /CPP2D/CPP2DConsumer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #pragma once 8 | 9 | #pragma warning(push, 0) 10 | #include 11 | #pragma warning(disable: 4265) 12 | #include 13 | #pragma warning(pop) 14 | 15 | #include "MatchContainer.h" 16 | #include "DPrinter.h" 17 | 18 | namespace clang 19 | { 20 | class CompilerInstance; 21 | } 22 | 23 | class CPP2DPPHandling; 24 | 25 | //! Implement clang::ASTConsumer to call the DPrinter 26 | class CPP2DConsumer : public clang::ASTConsumer 27 | { 28 | public: 29 | explicit CPP2DConsumer( 30 | clang::CompilerInstance& compiler, 31 | llvm::StringRef inFile 32 | ); 33 | 34 | //! Print imports, mixins, and finaly call the DPrinter on the translationUnit 35 | void HandleTranslationUnit(clang::ASTContext& context) override; 36 | 37 | void setPPCallBack(CPP2DPPHandling* cb) 38 | { 39 | ppcallbackPtr = cb; 40 | } 41 | 42 | private: 43 | clang::CompilerInstance& compiler; 44 | MatchContainer receiver; 45 | clang::ast_matchers::MatchFinder finder; 46 | std::unique_ptr finderConsumer; 47 | std::string inFile; 48 | DPrinter visitor; 49 | CPP2DPPHandling* ppcallbackPtr = nullptr; 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /LICENSE_1_0.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: C++ 2 | sudo: false 3 | dist: trusty 4 | addons: 5 | apt: 6 | update: true 7 | sources: 8 | - llvm-toolchain-trusty-6.0 9 | - ubuntu-toolchain-r-test 10 | packages: 11 | - cmake 12 | - libclang-6.0-dev 13 | - llvm-6.0-dev 14 | - gcc-4.9 15 | - g++-4.9 16 | - curl 17 | 18 | install: 19 | - curl -fsS https://dlang.org/install.sh | bash -s ldc 20 | - source ~/dlang/ldc-1.12.0/activate 21 | - export CC="gcc-4.9" 22 | - export CPP="g++-4.9" 23 | - export CXX="g++-4.9" 24 | - export LD="g++-4.9" 25 | 26 | script: 27 | - mkdir -p build 28 | - cd build 29 | - cmake .. -DCMAKE_PREFIX_PATH=/usr/lib/llvm-6.0 -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF 30 | - make 31 | - cmake .. -DCMAKE_PREFIX_PATH=/usr/lib/llvm-6.0 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 32 | - ln -s $PWD/compile_commands.json ../CPP2D_UT_CPP 33 | - cd ../CPP2D_UT_CPP 34 | - ../build/CPP2D/cpp2d stdlib_testsuite.cpp template_testsuite.cpp test.cpp framework.cpp main.cpp comment.cpp -macro-expr=UT_MACRO_EXPR/nn -macro-expr=CHECK/e -macro-expr=CHECK_EQUAL/ee -macro-expr=UT_MACRO/eee -macro-stmt=UT_MACRO_STMT -macro-stmt=UT_MACRO_STMT_CLASS/ntne 35 | - mkdir ../CPP2D_UT_D 36 | - cp ../build/CPP2D_UT_CPP/*.d ../CPP2D_UT_D 37 | - cd ../CPP2D_UT_D 38 | - ldc2 -m64 -ofCPP2D_UT_D ../cpp_std.d template_testsuite.d main.d framework.d test.d stdlib_testsuite.d comment.d 39 | - ../build/CPP2D_UT_CPP/CPP2D_UT_CPP 40 | - ./CPP2D_UT_D 41 | -------------------------------------------------------------------------------- /CPP2D/CPP2DTools.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #pragma once 8 | #include 9 | 10 | namespace clang 11 | { 12 | class ASTContext; 13 | class Stmt; 14 | class Decl; 15 | class SourceLocation; 16 | } 17 | 18 | namespace CPP2DTools 19 | { 20 | //! Get the name of the file pointed by sl 21 | const char* getFile(clang::SourceManager const& sourceManager, clang::SourceLocation const& sl); 22 | //! Get the name of the file pointed by s 23 | const char* getFile(clang::SourceManager const& sourceManager, clang::Stmt const* s); 24 | //! Get the name of the file pointed by d 25 | const char* getFile(clang::SourceManager const& sourceManager, clang::Decl const* d); 26 | //! @return true if the file is the header of the module (the matching header of the cpp) 27 | bool checkFilename(std::string const& modulename, char const* filepath_str); 28 | //! @return true if the file of d is in the header of the module 29 | bool checkFilename(clang::SourceManager const& sourceManager, 30 | std::string const& modulename, 31 | clang::Decl const* d); 32 | 33 | //! @brief Replace the ocurances of search in subject, by replace 34 | //! @return subject with the replaced strings. 35 | std::string replaceString(std::string subject, 36 | const std::string& search, 37 | const std::string& replace); 38 | 39 | } -------------------------------------------------------------------------------- /CPP2D/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | project(cpp2d) 4 | 5 | # Executable declaration 6 | add_executable( 7 | cpp2d 8 | CPP2D.cpp 9 | CPP2DConsumer.cpp 10 | CPP2DFrontendAction.cpp 11 | CPP2DPPHandling.cpp 12 | CPP2DTools.cpp 13 | DPrinter.cpp 14 | MatchContainer.cpp 15 | CustomPrinters.cpp 16 | Options.cpp 17 | CustomPrinters/boost_port.cpp 18 | CustomPrinters/c_stdlib_port.cpp 19 | CustomPrinters/cpp_stdlib_port.cpp 20 | ) 21 | 22 | target_link_libraries(cpp2d 23 | clangFrontend 24 | clangSerialization 25 | clangDriver 26 | clangParse 27 | clangSema 28 | clangAnalysis 29 | clangAST 30 | clangBasic 31 | clangEdit 32 | clangLex 33 | clangTooling 34 | clangASTMatchers 35 | ) 36 | 37 | target_link_libraries(cpp2d 38 | LLVMX86AsmParser # MC, MCParser, Support, X86Desc, X86Info 39 | LLVMX86Desc # MC, Support, X86AsmPrinter, X86Info 40 | LLVMX86AsmPrinter # MC, Support, X86Utils 41 | LLVMX86Info # MC, Support, Target 42 | LLVMX86Utils # Core, Support 43 | LLVMipo 44 | LLVMScalarOpts 45 | LLVMInstCombine 46 | LLVMTransformUtils 47 | LLVMAnalysis 48 | LLVMTarget 49 | LLVMOption # Support 50 | LLVMMCParser # MC, Support 51 | LLVMMC # Object, Support 52 | LLVMObject # BitReader, Core, Support 53 | LLVMBitReader # Core, Support 54 | LLVMCore # Support 55 | LLVMProfileData 56 | LLVMSupport 57 | LLVMDemangle 58 | LLVMBinaryFormat # Needed under windows 59 | ) 60 | 61 | if(CMAKE_COMPILER_IS_GNUCXX) 62 | target_link_libraries(cpp2d rt dl tinfo pthread z m) 63 | endif() 64 | 65 | if(CMAKE_SYSTEM_NAME MATCHES "Windows") 66 | target_link_libraries(cpp2d 67 | version.lib 68 | ) 69 | endif() 70 | -------------------------------------------------------------------------------- /CPP2D/CPP2DConsumer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #include "CPP2DConsumer.h" 9 | #include "CPP2DPPHandling.h" 10 | 11 | #include 12 | #include 13 | 14 | #pragma warning(push, 0) 15 | #include 16 | #include 17 | #include 18 | #pragma warning(pop) 19 | 20 | CPP2DConsumer::CPP2DConsumer( 21 | clang::CompilerInstance& compiler, 22 | llvm::StringRef inFile 23 | ) 24 | : compiler(compiler) 25 | , finder(receiver.getMatcher()) 26 | , finderConsumer(finder.newASTConsumer()) 27 | , inFile(inFile.str()) 28 | , visitor(&compiler.getASTContext(), receiver, inFile) 29 | { 30 | } 31 | 32 | void CPP2DConsumer::HandleTranslationUnit(clang::ASTContext& context) 33 | { 34 | //Find_Includes 35 | CPP2DPPHandling& ppcallback = *ppcallbackPtr; 36 | auto& incs = ppcallback.getIncludes(); 37 | 38 | finderConsumer->HandleTranslationUnit(context); 39 | visitor.setIncludes(incs); 40 | visitor.TraverseTranslationUnitDecl(context.getTranslationUnitDecl()); 41 | 42 | std::string modulename = llvm::sys::path::stem(inFile).str(); 43 | std::ofstream file(modulename + ".d"); 44 | std::string new_modulename; 45 | std::replace_copy(std::begin(modulename), std::end(modulename), 46 | std::back_inserter(new_modulename), '-', '_'); //Replace illegal characters 47 | if(new_modulename != modulename) // When filename has some illegal characters 48 | file << "module " << new_modulename << ';'; 49 | for(auto const& import : visitor.getExternIncludes()) 50 | { 51 | file << "import " << import.first << "; //"; 52 | for(auto const& type : import.second) 53 | file << type << " "; 54 | file << std::endl; 55 | } 56 | file << "\n\n"; 57 | for(auto const& code : ppcallback.getInsertedBeforeDecls()) 58 | file << code << '\n'; 59 | file << visitor.getDCode(); 60 | } 61 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/framework.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | extern unsigned int testCount; 16 | 17 | void check(bool ok, char const* message, int line, char const* file); 18 | 19 | template 20 | void check_equal(A a, B b, char const* astr, char const* bstr, int line, char const* file) 21 | { 22 | ++testCount; 23 | if (a != b) 24 | { 25 | std::cout << astr << " == " << bstr << " ->Failed at line " << line << ", in file " << file 26 | << ", because " << a << " != " << b << '\n'; 27 | } 28 | } 29 | 30 | #define CHECK(COND) check(COND, #COND, __LINE__, __FILE__) 31 | #define CHECK_EQUAL(A, B) check_equal(A, B, #A, #B, __LINE__, __FILE__) 32 | 33 | typedef void(*TestCase)(); //!< One small test independant of others 34 | 35 | //! Store some related test cases, and run them 36 | class TestSuite 37 | { 38 | TestSuite(TestSuite const&) = delete; 39 | TestSuite& operator=(TestSuite const&) = delete; 40 | 41 | std::vector testCases; 42 | 43 | public: 44 | TestSuite() = default; 45 | 46 | //! Run all test cases 47 | void run() const noexcept; 48 | 49 | //! @brief Add a test cases 50 | //! @pre TestCase != nullptr 51 | void addTestCase(TestCase testCase); 52 | }; 53 | 54 | //! Store all test suites, and run them 55 | class TestFrameWork 56 | { 57 | TestFrameWork(TestFrameWork const&) = delete; 58 | TestFrameWork& operator=(TestFrameWork const&) = delete; 59 | 60 | std::vector > testSuites; 61 | 62 | public: 63 | TestFrameWork() = default; 64 | 65 | //! Run all test suites 66 | void run() const noexcept; 67 | 68 | //! @brief Print a report to std output 69 | //! @pre TestFrameWork::run has been called 70 | void print_results(); 71 | 72 | //! @brief Add a test suite 73 | //! @pre testSuite != nullptr 74 | void addTestSuite(std::unique_ptr&& testSuite); 75 | }; 76 | 77 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | install: 2 | # Install curl 3 | - PATH=C:\Program Files\Git\mingw64\bin;%PATH% 4 | - cd %APPVEYOR_BUILD_FOLDER% 5 | - cd .. 6 | - mkdir deps 7 | - cd deps 8 | # Install llvm 9 | - curl -o llvm-6.0.1.7z http://www.nogane.net/owncloud/index.php/s/qdUscYbcXtHQTqG/download 10 | - 7z x llvm-6.0.1.7z 11 | # Install dmd 12 | - curl -o dmd.2.081.1.windows.7z http://downloads.dlang.org/releases/2018/dmd.2.081.1.windows.7z 13 | - 7z x dmd.2.081.1.windows.7z 14 | - PATH=%APPVEYOR_BUILD_FOLDER%/../deps/dmd2/windows/bin;%PATH% 15 | # Build CPP2D 16 | - cd %APPVEYOR_BUILD_FOLDER% 17 | - mkdir -p build 18 | - cd build 19 | - cmake -G "Visual Studio 14 2015 Win64" .. -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_PREFIX_PATH=%APPVEYOR_BUILD_FOLDER%/../deps/llvm-6.0.1 -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF 20 | 21 | platform: x64 22 | 23 | configuration: Release 24 | 25 | build: 26 | project: build/CPP2D.sln 27 | parallel: true 28 | 29 | test_script: 30 | - cd ..\CPP2D_UT_CPP 31 | - ..\build\CPP2D\Release\cpp2d.exe stdlib_testsuite.cpp template_testsuite.cpp test.cpp framework.cpp main.cpp comment.cpp -macro-expr=UT_MACRO_EXPR/nn -macro-expr=CHECK/e -macro-expr=CHECK_EQUAL/ee -macro-expr=UT_MACRO/eee -macro-stmt=UT_MACRO_STMT -macro-stmt=UT_MACRO_STMT_CLASS/ntne 32 | - mkdir ..\CPP2D_UT_D 33 | - copy *.d ..\CPP2D_UT_D 34 | - cd ..\CPP2D_UT_D 35 | - dmd -ofCPP2D_UT_D ../cpp_std.d template_testsuite.d main.d framework.d test.d stdlib_testsuite.d comment.d 36 | - ..\build\CPP2D_UT_CPP\Release\CPP2D_UT_CPP 37 | - .\CPP2D_UT_D 38 | 39 | artifacts: 40 | - path: build\CPP2D\Release\cpp2d.exe 41 | name: cpp2d 42 | 43 | before_deploy: 44 | - cd %APPVEYOR_BUILD_FOLDER% 45 | - cd .. 46 | - mkdir export 47 | - copy %APPVEYOR_BUILD_FOLDER%\build\CPP2D\Release\cpp2d.exe export 48 | 49 | deploy: 50 | provider: GitHub 51 | name: production 52 | artifact: build\CPP2D\Release\cpp2d.exe 53 | draft: true 54 | prerelease: false 55 | auth_token: 56 | secure: shGtrmloOL+jiGtSauloOo4irhao45Ei0THf2VPepuIkqLxMpS0P5PEu4lsm8b/5 57 | on: 58 | branch: master # release from master branch only 59 | appveyor_repo_tag: false # deploy on tag push only 60 | 61 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/comment.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | // Check for #ifdef #endif 9 | 10 | #define MULTI_LINE \ 11 | int i = 45; \ 12 | int j = 72; 13 | 14 | #define FEATURE_A 15 | 16 | #ifdef FEATURE_A 17 | const int FeatureA = 1; 18 | #else 19 | const int FeatureA = 0; 20 | #endif 21 | 22 | static_assert(FeatureA == 1, "FEATURE_A is not defined??"); 23 | 24 | // Check for #if 25 | 26 | #define FEATURE_B 27 | 28 | #if defined(FEATURE_B) 29 | const int FeatureB = 1; 30 | #else 31 | const int FeatureB = 0; 32 | #endif 33 | 34 | static_assert(FeatureB, "FEATURE_B is not defined??"); 35 | 36 | // Check for #else 37 | 38 | #if defined(FEATURE_C) 39 | const int FeatureC = 1; 40 | #else 41 | const int FeatureC = 0; 42 | #endif 43 | 44 | static_assert(FeatureC == 0, "FEATURE_C is defined??"); 45 | 46 | // Check for #elif 47 | 48 | #if defined(FEATURE_D) 49 | const int FeatureD = 1; 50 | #elif defined(FEATURE_B) 51 | const int FeatureD = 2; 52 | #else 53 | const int FeatureD = 3; 54 | #endif 55 | 56 | static_assert(FeatureD == 2, "FEATURE_D is defined??"); 57 | 58 | void func4845( 59 | int aaaa 60 | , int bbbb //hhhh! 61 | , int cccc = 45 //iii! 62 | , char const* dddd = "ffffgggg" //jjjj! 63 | , char const* uuuu = "ojftfs", //xkdtrt! 64 | int eeee = 13 65 | ) 66 | { 67 | } 68 | 69 | int func2(int asdflkhds, int bateau) 70 | { 71 | /* 72 | gdf 73 | dslksdgfjn 74 | gdfg 75 | */ 76 | int a = asdflkhds; 77 | /* 78 | sdgfdfhfgj 79 | */ 80 | return a; 81 | /* 82 | - 1: 83 | - 2 84 | - 3 85 | */ 86 | } 87 | 88 | // Comment! 89 | int func3() 90 | { 91 | //ABCDEF1 92 | int a = 0; 93 | //ABCDEF2 94 | return a; 95 | //ABCDEF3 96 | } 97 | 98 | // Comment! 99 | int func4() 100 | { 101 | #ifdef ABCDEF4 102 | assert(false); 103 | #endif 104 | int a = 0; 105 | #ifdef ABCDEF5 106 | assert(false); 107 | #endif 108 | return a; 109 | #ifdef ABCDEF6 110 | assert(false); 111 | #endif 112 | } 113 | 114 | /* 115 | Flub 116 | */ -------------------------------------------------------------------------------- /CPP2D_UT_CPP/CPP2D_UT_CPP.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Fichiers sources 23 | 24 | 25 | Fichiers sources 26 | 27 | 28 | Fichiers sources 29 | 30 | 31 | Fichiers sources 32 | 33 | 34 | Fichiers sources 35 | 36 | 37 | Fichiers sources 38 | 39 | 40 | 41 | 42 | Fichiers d%27en-tête 43 | 44 | 45 | Fichiers sources 46 | 47 | 48 | Fichiers d%27en-tête 49 | 50 | 51 | Fichiers d%27en-tête 52 | 53 | 54 | -------------------------------------------------------------------------------- /CPP2D.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPP2D", "CPP2D\CPP2D.vcxproj", "{F60FFC9A-3941-4F21-81E0-7E23E54E8F93}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CPP2D_UT_CPP", "CPP2D_UT_CPP\CPP2D_UT_CPP.vcxproj", "{1981F516-28E6-4905-B4E8-BD38982CBCE8}" 9 | EndProject 10 | Global 11 | GlobalSection(Performance) = preSolution 12 | HasPerformanceSessions = true 13 | EndGlobalSection 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|x64 = Debug|x64 16 | Debug|x86 = Debug|x86 17 | Release|x64 = Release|x64 18 | Release|x86 = Release|x86 19 | EndGlobalSection 20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 21 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93}.Debug|x64.ActiveCfg = Debug|x64 22 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93}.Debug|x64.Build.0 = Debug|x64 23 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93}.Debug|x86.ActiveCfg = Debug|Win32 24 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93}.Debug|x86.Build.0 = Debug|Win32 25 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93}.Release|x64.ActiveCfg = Release|x64 26 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93}.Release|x64.Build.0 = Release|x64 27 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93}.Release|x86.ActiveCfg = Release|Win32 28 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93}.Release|x86.Build.0 = Release|Win32 29 | {1981F516-28E6-4905-B4E8-BD38982CBCE8}.Debug|x64.ActiveCfg = Debug|x64 30 | {1981F516-28E6-4905-B4E8-BD38982CBCE8}.Debug|x64.Build.0 = Debug|x64 31 | {1981F516-28E6-4905-B4E8-BD38982CBCE8}.Debug|x86.ActiveCfg = Debug|Win32 32 | {1981F516-28E6-4905-B4E8-BD38982CBCE8}.Debug|x86.Build.0 = Debug|Win32 33 | {1981F516-28E6-4905-B4E8-BD38982CBCE8}.Release|x64.ActiveCfg = Release|x64 34 | {1981F516-28E6-4905-B4E8-BD38982CBCE8}.Release|x64.Build.0 = Release|x64 35 | {1981F516-28E6-4905-B4E8-BD38982CBCE8}.Release|x86.ActiveCfg = Release|Win32 36 | {1981F516-28E6-4905-B4E8-BD38982CBCE8}.Release|x86.Build.0 = Release|Win32 37 | EndGlobalSection 38 | GlobalSection(SolutionProperties) = preSolution 39 | HideSolutionNode = FALSE 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/template_testsuite.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | // 8 | // Copyright (c) 2016 Loïc HAMOT 9 | // 10 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 11 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 12 | // 13 | #include "framework.h" 14 | #include 15 | #include 16 | 17 | template 18 | auto sum(T value) 19 | { 20 | return value; 21 | } 22 | 23 | template 24 | auto sum(T const& value, Args const&... args) 25 | { 26 | return value + sum(args...); 27 | } 28 | 29 | 30 | void check_variadic_tmpl() 31 | { 32 | CHECK(sum(1, 0.5f, 0.25) == 1.75); 33 | } 34 | 35 | struct S 36 | { 37 | int val; 38 | }; 39 | 40 | static S StatStruct = { 42 }; 41 | 42 | S const& ret_ref() 43 | { 44 | return StatStruct; 45 | } 46 | 47 | template 48 | S const& ret_ref_tmpl() 49 | { 50 | return StatStruct; 51 | } 52 | 53 | template 54 | void check_return_ref_tmpl() 55 | { 56 | auto const& a = ret_ref_tmpl(); 57 | CHECK_EQUAL(a.val, 43); 58 | StatStruct.val = 44; 59 | CHECK_EQUAL(a.val, 44); 60 | 61 | CHECK(std::min(2, 3) == 2); 62 | CHECK(std::min(T(2), T(3)) == 2); 63 | } 64 | 65 | void check_return_ref() 66 | { 67 | auto const& a = ret_ref(); 68 | CHECK_EQUAL(a.val, 42); 69 | StatStruct.val = 43; 70 | CHECK_EQUAL(a.val, 43); 71 | } 72 | 73 | struct QA 74 | { 75 | struct B 76 | { 77 | 78 | }; 79 | }; 80 | 81 | template 82 | struct QC; 83 | 84 | template<> 85 | struct QC 86 | { 87 | static const int U = 18; 88 | }; 89 | 90 | void check_qualifier() 91 | { 92 | CHECK_EQUAL(QC::U, 18); 93 | } 94 | 95 | 96 | void template_register(TestFrameWork& tf) 97 | { 98 | auto ts = std::make_unique(); 99 | 100 | ts->addTestCase(check_variadic_tmpl); 101 | 102 | ts->addTestCase(check_return_ref); 103 | 104 | ts->addTestCase(check_qualifier); 105 | 106 | ts->addTestCase(check_return_ref_tmpl); 107 | 108 | tf.addTestSuite(std::move(ts)); 109 | } -------------------------------------------------------------------------------- /CPP2D/CPP2DTools.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #pragma warning(push, 0) 9 | #pragma warning(disable: 4548) 10 | #include 11 | #include 12 | #pragma warning(pop) 13 | 14 | using namespace llvm; 15 | using namespace clang; 16 | 17 | 18 | namespace CPP2DTools 19 | { 20 | 21 | const char* getFile(clang::SourceManager const& sourceManager, clang::SourceLocation const& sl) 22 | { 23 | if(sl.isValid() == false) 24 | return ""; 25 | clang::FullSourceLoc fsl = FullSourceLoc(sl, sourceManager).getExpansionLoc(); 26 | auto& mgr = fsl.getManager(); 27 | if(clang::FileEntry const* f = mgr.getFileEntryForID(fsl.getFileID())) 28 | return f->getName().data(); 29 | else 30 | return nullptr; 31 | } 32 | 33 | 34 | const char* getFile(clang::SourceManager const& sourceManager, Stmt const* d) 35 | { 36 | return getFile(sourceManager, d->getLocStart()); 37 | } 38 | 39 | const char* getFile(clang::SourceManager const& sourceManager, Decl const* d) 40 | { 41 | return getFile(sourceManager, d->getLocation()); 42 | } 43 | 44 | bool checkFilename(std::string const& modulename, char const* filepath_str) 45 | { 46 | if(filepath_str == nullptr) 47 | return false; 48 | std::string filepath = filepath_str; 49 | if(filepath.size() < 12) 50 | return false; 51 | else 52 | { 53 | StringRef const filename = llvm::sys::path::filename(filepath); 54 | static char const* exts[] = { ".h", ".hpp", ".cpp", ".cxx", ".c" }; 55 | auto iter = std::find_if(std::begin(exts), std::end(exts), [&](auto && ext) 56 | { 57 | return filename == (modulename + ext); 58 | }); 59 | return iter != std::end(exts); 60 | } 61 | } 62 | 63 | bool checkFilename(clang::SourceManager const& sourceManager, 64 | std::string const& modulename, 65 | clang::Decl const* d) 66 | { 67 | return checkFilename(modulename, getFile(sourceManager, d)); 68 | } 69 | 70 | std::string replaceString(std::string subject, 71 | const std::string& search, 72 | const std::string& replace) 73 | { 74 | size_t pos = 0; 75 | while((pos = subject.find(search, pos)) != std::string::npos) 76 | { 77 | subject.replace(pos, search.length(), replace); 78 | pos += replace.length(); 79 | } 80 | return subject; 81 | } 82 | 83 | } //CPP2DTools -------------------------------------------------------------------------------- /CPP2D/CPP2D.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | I:\C\CPP2D\CPP2D_UT_CPP\main.cpp I:\C\CPP2D\CPP2D_UT_CPP\framework.cpp I:\C\CPP2D\CPP2D_UT_CPP\test.cpp -macro-expr=UT_MACRO_EXPR/nn -macro-expr=CHECK/e -macro-expr=UT_MACRO/eee -macro-stmt=UT_MACRO_STMT -macro-stmt=UT_MACRO_STMT_CLASS/ntne -- -fms-extensions -fms-compatibility 5 | WindowsLocalDebugger 6 | I:\C\CPP2D_UT_D\CPP2D_UT_D 7 | 8 | 9 | I:\C\CPP2D\CPP2D_UT_CPP\main.cpp I:\C\CPP2D\CPP2D_UT_CPP\framework.cpp I:\C\CPP2D\CPP2D_UT_CPP\test.cpp -macro-expr=UT_MACRO_EXPR/nn -macro-expr=CHECK/e -macro-expr=UT_MACRO/eee -macro-stmt=UT_MACRO_STMT -macro-stmt=UT_MACRO_STMT_CLASS/ntne -- -fms-extensions -fms-compatibility 10 | WindowsLocalDebugger 11 | I:\C\CPP2D_UT_D\CPP2D_UT_D 12 | 13 | 14 | C:\C\CPP2D\CPP2D_UT_CPP\comment.cpp C:\C\CPP2D\CPP2D_UT_CPP\framework.cpp C:\C\CPP2D\CPP2D_UT_CPP\main.cpp C:\C\CPP2D\CPP2D_UT_CPP\template_testsuite.cpp C:\C\CPP2D\CPP2D_UT_CPP\stdlib_testsuite.cpp C:\C\CPP2D\CPP2D_UT_CPP\test.cpp -macro-expr=UT_MACRO_EXPR/nn -macro-expr=CHECK/e -macro-expr=CHECK_EQUAL/ee -macro-expr=UT_MACRO/eee -macro-stmt=UT_MACRO_STMT -macro-stmt=UT_MACRO_STMT_CLASS/ntne -- -fms-extensions -fms-compatibility 15 | WindowsLocalDebugger 16 | C:\C\CPP2D_UT_D\source 17 | 18 | 19 | C:\C\CPP2D\CPP2D_UT_CPP\comment.cpp C:\C\CPP2D\CPP2D_UT_CPP\framework.cpp C:\C\CPP2D\CPP2D_UT_CPP\main.cpp C:\C\CPP2D\CPP2D_UT_CPP\template_testsuite.cpp C:\C\CPP2D\CPP2D_UT_CPP\stdlib_testsuite.cpp C:\C\CPP2D\CPP2D_UT_CPP\test.cpp -macro-expr=UT_MACRO_EXPR/nn -macro-expr=CHECK/e -macro-expr=CHECK_EQUAL/ee -macro-expr=UT_MACRO/eee -macro-stmt=UT_MACRO_STMT -macro-stmt=UT_MACRO_STMT_CLASS/ntne -- -fms-extensions -fms-compatibility 20 | WindowsLocalDebugger 21 | C:\C\CPP2D_UT_D\source 22 | 23 | -------------------------------------------------------------------------------- /CPP2D/CPP2D.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #pragma warning(push, 0) 9 | #pragma warning(disable: 4548) 10 | #include "clang/Tooling/CommonOptionsParser.h" 11 | #include "clang/Tooling/Tooling.h" 12 | #pragma warning(pop) 13 | 14 | #include 15 | #include 16 | 17 | #include "CPP2DFrontendAction.h" 18 | 19 | using namespace clang::tooling; 20 | using namespace llvm; 21 | using namespace clang; 22 | 23 | cl::OptionCategory cpp2dCategory("cpp2d options"); 24 | 25 | cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); 26 | 27 | cl::list MacroAsExpr( 28 | "macro-expr", 29 | cl::desc("This macro will not be expanded and will be migrated expecting an expression"), 30 | cl::cat(cpp2dCategory), 31 | cl::ZeroOrMore); 32 | 33 | cl::list MacroAsStmt( 34 | "macro-stmt", 35 | cl::desc("This macro will not be expanded and will be migrated expecting statments"), 36 | cl::cat(cpp2dCategory), 37 | cl::ZeroOrMore); 38 | 39 | 40 | //! Used to add fake options to the compiler 41 | //! - For example : -fno-delayed-template-parsing 42 | class CPP2DCompilationDatabase : public clang::tooling::CompilationDatabase 43 | { 44 | clang::tooling::CompilationDatabase& sourceCDB; 45 | 46 | public: 47 | CPP2DCompilationDatabase(clang::tooling::CompilationDatabase& sourceCDB_) 48 | : sourceCDB(sourceCDB_) 49 | { 50 | } 51 | 52 | std::vector getCompileCommands(StringRef FilePath) const override 53 | { 54 | std::vector result = sourceCDB.getCompileCommands(FilePath); 55 | for(CompileCommand& cc : result) 56 | { 57 | cc.CommandLine.push_back("-fno-delayed-template-parsing"); 58 | cc.CommandLine.push_back("-ferror-limit=999999"); 59 | cc.CommandLine.push_back("-Wno-builtin-macro-redefined"); 60 | cc.CommandLine.push_back("-Wno-unused-value"); 61 | cc.CommandLine.push_back("-DCPP2D"); 62 | } 63 | return result; 64 | } 65 | 66 | std::vector getAllFiles() const override { return sourceCDB.getAllFiles(); } 67 | 68 | std::vector getAllCompileCommands() const override 69 | { 70 | assert(false && "Unexpected call to function CPP2DCompilationDatabase::getAllCompileCommands"); 71 | return sourceCDB.getAllCompileCommands(); 72 | } 73 | }; 74 | 75 | int main(int argc, char const** argv) 76 | { 77 | std::vector argv_vect; 78 | std::copy(argv, argv + static_cast(argc), std::back_inserter(argv_vect)); 79 | argv_vect.insert(std::begin(argv_vect) + 1, "-macro-expr=assert/e"); 80 | argc = static_cast(argv_vect.size()); 81 | CommonOptionsParser OptionsParser(argc, argv_vect.data(), cpp2dCategory); 82 | CPP2DCompilationDatabase compilationDatabase(OptionsParser.getCompilations()); 83 | ClangTool Tool( 84 | compilationDatabase, 85 | OptionsParser.getSourcePathList()); 86 | return Tool.run(newFrontendActionFactory().get()); 87 | } 88 | -------------------------------------------------------------------------------- /CPP2D/CPP2DPPHandling.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #pragma once 8 | 9 | #pragma warning(push, 0) 10 | #include 11 | #include 12 | #pragma warning(pop) 13 | 14 | #include 15 | 16 | namespace clang 17 | { 18 | class ASTContext; 19 | } 20 | 21 | //! Extract includes and transform macros 22 | class CPP2DPPHandling : public clang::PPCallbacks 23 | { 24 | public: 25 | CPP2DPPHandling(clang::SourceManager& sourceManager, 26 | clang::Preprocessor& pp, 27 | llvm::StringRef inFile); 28 | 29 | //! Fill the list of included files (includes_in_file) 30 | void InclusionDirective( 31 | clang::SourceLocation, //hash_loc, 32 | const clang::Token&, //include_token, 33 | llvm::StringRef file_name, 34 | bool, //is_angled, 35 | clang::CharSourceRange, //filename_range, 36 | const clang::FileEntry*, //file, 37 | llvm::StringRef, //search_path, 38 | llvm::StringRef, //relative_path, 39 | const clang::Module* //imported 40 | ) override; 41 | 42 | //! Transform macro definition by calling TransformMacroExpr or TransformMacroStmt 43 | void MacroDefined(const clang::Token& MacroNameTok, const clang::MacroDirective* MD) override; 44 | 45 | //! Get include list 46 | std::set const& getIncludes() const; 47 | //! Get macros to add in the D code 48 | std::set const& getInsertedBeforeDecls() const; 49 | 50 | private: 51 | //! Add or replace a macro definition in the clang::Preprocessor 52 | void inject_macro( 53 | clang::MacroDirective const* MD, 54 | std::string const& name, 55 | std::string const& new_macro); 56 | 57 | //! Options passed by the user about a specific macro 58 | struct MacroInfo 59 | { 60 | std::string name; //!< Macro name 61 | std::string argType; //!< e:expression n:name t:type 62 | std::string cppReplace; //!< override the macro, in C++ code 63 | }; 64 | //! @brief Transform macro definition if tagged by -macro-expr option 65 | //! + Add the D mixin version in the list add_before_decl 66 | void TransformMacroExpr(clang::Token const& MacroNameTok, 67 | clang::MacroDirective const* MD, 68 | CPP2DPPHandling::MacroInfo const& args); 69 | //! @brief Transform macro definition if tagged by -macro-stmt option 70 | //! + Add the D mixin version in the list add_before_decl 71 | void TransformMacroStmt(clang::Token const& MacroNameTok, 72 | clang::MacroDirective const* MD, 73 | CPP2DPPHandling::MacroInfo const& args); 74 | 75 | clang::SourceManager& sourceManager; 76 | clang::Preprocessor& pp; 77 | llvm::StringRef inFile; 78 | llvm::StringRef modulename; 79 | std::map macro_expr; 80 | std::map macro_stmt; 81 | 82 | std::set includes_in_file; 83 | std::set add_before_decl; 84 | 85 | std::string predefines; 86 | std::set new_macros; 87 | }; -------------------------------------------------------------------------------- /CPP2D/CPP2D.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {c9043405-1f6f-43e7-9a06-6f2f16c20117} 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Fichiers sources 26 | 27 | 28 | Fichiers sources 29 | 30 | 31 | Fichiers sources 32 | 33 | 34 | Fichiers sources 35 | 36 | 37 | Fichiers sources 38 | 39 | 40 | Fichiers sources 41 | 42 | 43 | Fichiers sources 44 | 45 | 46 | Fichiers sources 47 | 48 | 49 | Fichiers sources\CustomPrinters 50 | 51 | 52 | Fichiers sources\CustomPrinters 53 | 54 | 55 | Fichiers sources\CustomPrinters 56 | 57 | 58 | Fichiers sources 59 | 60 | 61 | 62 | 63 | Fichiers d%27en-tête 64 | 65 | 66 | Fichiers d%27en-tête 67 | 68 | 69 | Fichiers d%27en-tête 70 | 71 | 72 | Fichiers d%27en-tête 73 | 74 | 75 | Fichiers d%27en-tête 76 | 77 | 78 | Fichiers d%27en-tête 79 | 80 | 81 | Fichiers d%27en-tête 82 | 83 | 84 | Fichiers d%27en-tête 85 | 86 | 87 | Fichiers d%27en-tête 88 | 89 | 90 | -------------------------------------------------------------------------------- /cpp_std.d: -------------------------------------------------------------------------------- 1 | import std.container.rbtree; 2 | import std.container.array; 3 | import std.typecons; 4 | import std.stdio; 5 | import std.conv; 6 | 7 | //****************************** map ***************************************** 8 | alias pair(K, V) = Tuple!(K, "key", V, "value"); 9 | alias map(K, V, alias less = "a[0] < b[0]") = RedBlackTree!(pair!(K, V), less, false); 10 | alias multimap(K, V, alias less = "a < b") = RedBlackTree!(pair!(K, V), less, true); 11 | 12 | 13 | //************************** boost::serialization **************************** 14 | 15 | template class_version(T) 16 | { 17 | immutable(int) class_version = 0; 18 | } 19 | 20 | template class_version(T: double) 21 | { 22 | immutable(int) class_version = 6; 23 | } 24 | 25 | //************************** std::vector ************************************** 26 | 27 | struct allocator(T){} 28 | 29 | alias vector(T, A = allocator!T) = Array!T; 30 | 31 | //************************** std::set ************************************** 32 | 33 | struct set(T, alias less = "a < b", A = allocator!T) 34 | { 35 | RedBlackTree!(T, less) data = new RedBlackTree!(T, less); 36 | 37 | auto length() {return data.length;} 38 | 39 | this()(auto this) 40 | { 41 | data = data.dup; 42 | } 43 | } 44 | 45 | 46 | //************************** unordered_map ************************************** 47 | 48 | struct unordered_map(K, V) 49 | { 50 | V[K] ptr; 51 | } 52 | 53 | //************************* cpp-like lambda helper **************************** 54 | 55 | struct toFunctor(alias F) 56 | { 57 | this(int){} 58 | auto ref opCall(Args...)(auto ref Args args) 59 | { 60 | return F(args); 61 | } 62 | } 63 | 64 | //************************* default ctor helper **************************** 65 | 66 | struct DefaultCtorArgType{}; 67 | static DefaultCtorArgType DefaultCtorArg; 68 | 69 | // ********************** std::move **************************************** 70 | 71 | auto move(T)(auto ref T ptr) if(is(T == struct)) 72 | { 73 | auto newPtr = ptr; 74 | ptr = T.init; 75 | return newPtr; 76 | } 77 | 78 | auto move(T)(auto ref T ptr) if(is(T == class)) 79 | { 80 | auto newPtr = ptr; 81 | ptr = null; 82 | return newPtr; 83 | } 84 | 85 | // ******************************** ********************************* 86 | 87 | auto make_pair(A, B)(auto ref A a, auto ref B b) 88 | { 89 | //return Tuple!(A, "key", B, "value")(a, b); 90 | return pair!(A, B)(a, b); 91 | } 92 | 93 | // ******************************* other ************************************** 94 | 95 | struct Ref(T) 96 | { 97 | T* ptr; 98 | 99 | this(U)(auto ref U other) 100 | { 101 | ptr = &other; 102 | } 103 | 104 | ref T opCast() 105 | { 106 | return *ptr; 107 | } 108 | 109 | bool opBinary(string op, U)(auto ref U other) 110 | { 111 | return mixin("*ptr" ~ op ~ "other"); 112 | } 113 | 114 | bool opBinary(string op, U = Ref!U)(auto ref Ref!U other) 115 | { 116 | return mixin("*ptr" ~ op ~ "*other.ptr"); 117 | } 118 | 119 | alias ptr this; 120 | } 121 | 122 | auto makeRef(T)(ref auto T val) 123 | { 124 | return Ref!T(val); 125 | } 126 | 127 | //************************* iostream ****************************************** 128 | 129 | struct OStream 130 | { 131 | File file; 132 | 133 | ref OStream opBinary(string op = "<<", T)(auto ref T arg) 134 | { 135 | file.write(arg); 136 | return this; 137 | } 138 | } 139 | 140 | 141 | enum ios_base 142 | { 143 | in_ = 1, 144 | out_ = 2 145 | } 146 | 147 | struct Stringstream 148 | { 149 | string data; 150 | 151 | this(ios_base mode){} 152 | 153 | this(string str, int mode = 3){data = str;} 154 | 155 | ref Stringstream opBinary(string op = "<<", T)(auto ref T arg) 156 | { 157 | data ~= to!string(arg); 158 | return this; 159 | } 160 | 161 | string str() 162 | { 163 | return data; 164 | } 165 | } 166 | 167 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CPP2D 2 | (Clang based) C++ to D language converter 3 | 4 | ## Objective 5 | The goal is to take a C++ project and convert all the source code to D language. 6 | 7 | ## License 8 | 9 | Copyright Loïc HAMOT, 2016 10 | 11 | Distributed under the Boost Software License, Version 1.0. 12 | 13 | See ./LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt 14 | 15 | ## Continuous integration 16 | 17 | * Ubuntu 18 | 19 | [![Build Status](https://travis-ci.org/lhamot/CPP2D.svg?branch=master)](https://travis-ci.org/lhamot/CPP2D) 20 | 21 | * Windows 22 | 23 | [![Build Status](https://ci.appveyor.com/api/projects/status/github/lhamot/cpp2d?svg=true)](https://ci.appveyor.com/project/lhamot/cpp2d) 24 | 25 | ## Already handled C++ features 26 | 27 | Majority of C++ code is already convertible to D. 28 | 29 | A not exhaustive list: 30 | * class 31 | * constructor/destructor 32 | * virtual 33 | * abstract 34 | * override 35 | * initialization list 36 | * call base constructor 37 | * Operator overloading 38 | * member 39 | * free 40 | * left or right 41 | * Template 42 | * function 43 | * function specialization 44 | * class 45 | * class/struct specialization 46 | * class/struct partial specialization 47 | * arrays 48 | * static 49 | * dynamic 50 | * std::vector (partially) 51 | * std::array (partially) 52 | * preprocessor 53 | * function-like macro 54 | * declaration-like macro 55 | * simple #ifdef/else/endif 56 | 57 | Some samples here : https://github.com/lhamot/CPP2D/wiki/Conversion-samples 58 | 59 | ## Requirements 60 | * cmake >= 2.6 61 | * Tested with **gcc** 4.8.4 (**Ubuntu** 14.04.3), **Visual Studio** 2015 (**Windows** 7 & 10), and **clang** (**macOS** 10.14) 62 | * Tested with **LLVM/clang** **6.0.1** 63 | 64 | ## How to install it? 65 | 1. Install **clang** : http://clang.llvm.org/get_started.html 66 | 2. Check out **CPP2D** from : https://github.com/lhamot/CPP2D.git 67 | 3. Run **cmake** in the root directory of **CPP2D** 68 | 1. Set the build type if needed (Debug;Release;MinSizeRel;RelWithDebInfo) 69 | 2. Set the path to **LLVM** using **CMAKE_PREFIX_PATH**. 70 | 4. Generate 71 | 4. Run **make** 72 | 73 | ## How to use it? 74 | **Be aware than this project is far to be finished. Do not expect a fully working D project immediately. That you can expect is a great help to the conversion of your project, doing all the simple repetitive job, which is not so bad.** 75 | 76 | CPP2D work like any clang tools. This could help you: 77 | - http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html 78 | 79 | There is two way to use CPP2D: 80 | 81 | ### 1. Without compilation database 82 | 1. Go to the destination directory (D project) 83 | 2. Call ```CPP2D.exe [options] [... ] -- [compiler options]``` 84 | - The double dashes are needed to inform cpp2d you don't need a compilation database 85 | - `````` are C++ source files 86 | - [compiler options] are options forwarded to the compiler, like includes path, preprocessor definitions and so on. 87 | - [options] can be **-macro-stmt** and **-macro-exec** which are for macro handling 88 | 89 | ### 2. With compilation database 90 | It seems to be impossible to generate a compilation database under windows... 91 | 92 | If you are not under windows, and you are using cmake to compile your project: 93 | - Add this code in your(s) CMakeFiles.txt 94 | ```cmake 95 | if(CMAKE_EXPORT_COMPILE_COMMANDS STREQUAL "ON") 96 | include_directories(${LLVM_PATH}/lib/clang/3.9.0/include) 97 | endif() 98 | ``` 99 | ```sh 100 | # Go to project build directory 101 | $ cd project/build/directory 102 | # Run cmake, asking it to generate a compilation database 103 | $ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON path/to/project/sources 104 | # You will obtain a compilation database 105 | # Link it to the source project 106 | $ ln -s $PWD/compile_commands.json path/to/project/source/ 107 | # Convert files, calling cpp2d 108 | $ cd path/to/project/source 109 | $ project/build/directory/CPP2D/cpp2d source1.cpp source2.cpp source3.cpp 110 | # You will find D files in the project/build/directory 111 | # You also need to copy the cpp_std.d file to your D source directory 112 | $ cp project/build/directory/CPP2D/cpp_std.d dproject/source 113 | ``` 114 | 115 | Need for more documentation? You can search here : 116 | - http://eli.thegreenplace.net/2014/05/21/compilation-databases-for-clang-based-tools 117 | 118 | ## Future of the project? 119 | Small C++ project are almost fully convertible to **D**, but many things have to be done for the bigger ones. 120 | 121 | ### Main missing features are: 122 | * Better macro handling 123 | * Namespace/Module handling 124 | * External library handling, and specifically the stdlib 125 | * Variadic template 126 | * Not tried to do yet 127 | * Better conservation of comments 128 | * Porting constness 129 | * Hard because **D** containers seem to not be const correct 130 | * Handling const ref function argument 131 | * Hard because, unlike in **C++**, in **D** we can't pass a rvalue to a const ref parameter 132 | 133 | ### Other possible enhancements 134 | 135 | * CMake : Create a cmake to compile a project linked to **LLVM**/**clang** in a cross-platform way seems to be not straightforward. If you can enhance my CMakeLists, please do it! 136 | * Clang integration : Maybe there is a better way to integrate **CPP2D** with **clang**, like make it a real clang tool, in clang/tools, or clang/tools/extra. 137 | 138 | ## Want to try? 139 | - http://nogane.net/cpp2d 140 | 141 | ## Want to help? 142 | I would be happy to get some help on this project. If you are interested, do not hesitate to : 143 | - Reach us on the mailing list: https://groups.google.com/forum/#!forum/cpp2d 144 | - Contact me at loic.hamot@yahoo.fr 145 | - Or just checkout and enjoy ;) 146 | -------------------------------------------------------------------------------- /CPP2D/MatchContainer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #pragma once 8 | 9 | #include 10 | #include 11 | 12 | #pragma warning(push, 0) 13 | #pragma warning(disable: 4265) 14 | #include 15 | #pragma warning(pop) 16 | 17 | class DPrinter; 18 | 19 | namespace clang 20 | { 21 | class Stmt; 22 | class Decl; 23 | class Type; 24 | } 25 | 26 | //! Store matchers and receive the callbacks when the are find 27 | //! 28 | //! Find some paterns in the source which are hard to finc while parsing 29 | //! Permit the excecution of custom matcher and custom printer in order to 30 | //! translate external library usages 31 | class MatchContainer : public clang::ast_matchers::MatchFinder::MatchCallback 32 | { 33 | public: 34 | //! Generate all ASTMatchers 35 | clang::ast_matchers::MatchFinder getMatcher(); 36 | 37 | //! Hash traits (std::hash) of this record. [recordname] -> method 38 | std::unordered_map hashTraits; 39 | //! @brief Free operators (left) of this record. [recordname] -> operator 40 | //! @remark The record appear on the left side 41 | std::unordered_multimap freeOperator; 42 | //! @brief Free operators (right) of this record. [recordname] -> operator 43 | //! @remark The record appear on the right side 44 | std::unordered_multimap freeOperatorRight; 45 | 46 | typedef std::function StmtPrinter; //!< Custom Stmt printer 47 | typedef std::function DeclPrinter; //!< Custom Decl printer 48 | typedef std::function TypePrinter; //!< Custom Type printer 49 | 50 | 51 | StmtPrinter getPrinter(clang::Stmt const*) const; //!< Get the custom printer for this statment 52 | DeclPrinter getPrinter(clang::Decl const*) const; //!< Get the custom printer for this decl 53 | TypePrinter getPrinter(clang::Type const*) const; //!< Get the custom printer for this type 54 | 55 | //! Get the nth template argument of type tmplType 56 | static clang::TemplateArgument const* getTemplateTypeArgument( 57 | clang::Expr const* tmplType, 58 | size_t nth); 59 | 60 | //! Change the name of a C++ type 61 | void rewriteType( 62 | clang::ast_matchers::MatchFinder& finder, 63 | std::string const& oldName, //!< Old type name in C++ (no regex) 64 | std::string const& newName, //!< New type name in D 65 | std::string const& newImport //!< import to get this type in **D** 66 | ); 67 | 68 | //! Custom print a method call 69 | void methodPrinter( 70 | std::string const& className, //!< Class of this method (no regex) 71 | std::string const& methodName, //!< Metod name (no regex) 72 | StmtPrinter const& printer //!< Custom printer 73 | ); 74 | 75 | //! Custom print a global function call 76 | void globalFuncPrinter( 77 | std::string const& funcName, //!< Function name (regex) 78 | StmtPrinter const& printer //!< Custom printer 79 | ); 80 | 81 | //! Custom print a template type 82 | void tmplTypePrinter( 83 | std::string const& name, //!< Type name (regex) 84 | DeclPrinter const& printMapDecl //!< Custom printer 85 | ); 86 | 87 | //! Custom print a member call 88 | void memberPrinter( 89 | clang::ast_matchers::MatchFinder& finder, 90 | std::string const& regexpr, //!< Fully qualified member name (regex) 91 | StmtPrinter const& printer //!< Custom printer 92 | ); 93 | 94 | //! Custom print an operator call 95 | void operatorCallPrinter( 96 | clang::ast_matchers::MatchFinder& finder, 97 | std::string const& classRegexpr, //!< class name (regex) 98 | std::string const& op, //!< operator (like "==") 99 | StmtPrinter const& printer //!< Custom printer 100 | ); 101 | 102 | //! Port a C standard library function to D 103 | void cFuncPrinter( 104 | std::string const& lib, //!< include name 105 | std::string const& func //!< function name (no regex) 106 | ); 107 | 108 | //! clang::Stmt which match. [clang::Stmt] -> matchername 109 | std::unordered_multimap stmtTags; 110 | //! clang::Stmt which match. [clang::Decl] -> matchername 111 | std::unordered_multimap declTags; 112 | //! clang::Stmt which match. [clang::Type] -> matchername 113 | std::unordered_multimap typeTags; 114 | 115 | typedef std::unordered_map ClassPrinter; 116 | //! How to print a call to this method. methodPrinters[method_name][class_name] => printer 117 | std::unordered_map methodPrinters; 118 | 119 | std::unordered_map globalFuncPrinters; 120 | 121 | std::unordered_map customTypePrinters; 122 | 123 | //! Custom printer for clang::Type matchers. [matchername] -> printer 124 | std::unordered_map typePrinters; 125 | //! Custom printer for clang::Stmt matchers. [matchername] -> printer 126 | std::unordered_map stmtPrinters; 127 | //! Custom printer for clang::Decl matchers. [matchername] -> printer 128 | std::unordered_map declPrinters; 129 | 130 | //! Function excecuted when a clang::Stmt match. [matchername] -> function 131 | std::unordered_map> onStmtMatch; 132 | //! Function excecuted when a clang::Decl match. [matchername] -> function 133 | std::unordered_map> onDeclMatch; 134 | //! Function excecuted when a clang::Type match. [matchername] -> function 135 | std::unordered_map> onTypeMatch; 136 | 137 | private: 138 | //! When match is find, excecute on*Match or add the node to *Tags 139 | void run(clang::ast_matchers::MatchFinder::MatchResult const& Result) override; 140 | }; -------------------------------------------------------------------------------- /CPP2D_UT_CPP/CPP2D_UT_CPP.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {1981F516-28E6-4905-B4E8-BD38982CBCE8} 23 | Win32Proj 24 | CPP2D_UT_CPP 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | 4996;4702;4714; 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | 4996;4702;4714; 106 | 107 | 108 | Console 109 | true 110 | 111 | 112 | 113 | 114 | Level3 115 | 116 | 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | 4996;4702;4714; 122 | 123 | 124 | Console 125 | true 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | Level3 133 | 134 | 135 | MaxSpeed 136 | true 137 | true 138 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | 4996;4702;4714; 140 | 141 | 142 | Console 143 | true 144 | true 145 | true 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/stdlib_testsuite.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "framework.h" 12 | #include 13 | #include "math.h" 14 | #include 15 | 16 | template 17 | struct TestType {}; 18 | 19 | void check_std_map() 20 | { 21 | /*std::map m1; 22 | m1[36] = 78; 23 | CHECK_EQUAL(m1[36], 78); 24 | 25 | auto m2 = m1; 26 | m2[36] = 581; 27 | CHECK_EQUAL(m2[36], 581); 28 | CHECK_EQUAL(m1[36], 78);*/ 29 | 30 | //auto lmbd = [](std::map toto) {}; 31 | //auto lmbd2 = [](std::map::value_type toto) {}; 32 | 33 | //TestType toto; 34 | //TestType> tata; 35 | std::map tutu; 36 | std::map::value_type titi; 37 | TestType>> tata; 38 | } 39 | 40 | struct ContainHashMap 41 | { 42 | std::unordered_map m1; 43 | }; 44 | 45 | struct ContainHashMap2 46 | { 47 | std::unordered_map m1; 48 | 49 | ContainHashMap2() = default; 50 | 51 | ContainHashMap2(ContainHashMap2 const& other) 52 | : m1(other.m1) 53 | { 54 | } 55 | }; 56 | 57 | struct ContainHashMap3 58 | { 59 | std::unordered_map m1; 60 | 61 | ContainHashMap3() = default; 62 | 63 | ContainHashMap3(ContainHashMap3 const& other) 64 | { 65 | m1 = other.m1; 66 | } 67 | }; 68 | 69 | void check_cmath() 70 | { 71 | CHECK(std::sqrt(4.) == 2.); 72 | CHECK(pow(2, 2) == 4); 73 | } 74 | 75 | void check_std_unordered_map() 76 | { 77 | std::unordered_map m1; 78 | m1[36] = 78; 79 | CHECK(m1[36] == 78); 80 | 81 | std::vector v1; 82 | std::vector v2; 83 | for (auto i : m1) 84 | { 85 | v1.push_back(i.first); 86 | v2.push_back(i.second); 87 | } 88 | CHECK(v1[0] == 36); 89 | CHECK(v2[0] == 78); 90 | 91 | { 92 | ContainHashMap c1; 93 | c1.m1[15] = 98; 94 | auto c2 = c1; 95 | c1.m1[15] = 6; 96 | CHECK(c2.m1[15] == 98); 97 | c2 = c1; 98 | c1.m1[15] = 7; 99 | CHECK(c2.m1[15] == 6); 100 | } 101 | 102 | { 103 | ContainHashMap2 c1; 104 | c1.m1[15] = 98; 105 | auto c2 = c1; 106 | c1.m1[15] = 6; 107 | CHECK(c2.m1[15] == 98); 108 | c2 = c1; 109 | c1.m1[15] = 7; 110 | CHECK(c2.m1[15] == 6); 111 | } 112 | 113 | { 114 | ContainHashMap3 c1; 115 | c1.m1[15] = 98; 116 | auto c2 = c1; 117 | c1.m1[15] = 6; 118 | CHECK(c2.m1[15] == 98); 119 | c2 = c1; 120 | c1.m1[15] = 7; 121 | CHECK(c2.m1[15] == 6); 122 | } 123 | } 124 | 125 | class Class781 126 | { 127 | public: 128 | int i = 0; 129 | Class781() {}; 130 | Class781(int u) :i(u) {}; 131 | }; 132 | 133 | struct Struct781 134 | { 135 | int i = 0; 136 | Struct781() = default; 137 | Struct781(int u) :i(u) {}; 138 | }; 139 | 140 | void check_shared_ptr() 141 | { 142 | std::shared_ptr classptr1; //default ctor 143 | CHECK(classptr1 == nullptr); 144 | classptr1.reset(new Class781()); 145 | CHECK(classptr1 != nullptr); 146 | std::shared_ptr classptr2 = classptr1; //copy ctor 147 | CHECK(classptr1 == classptr2); 148 | //std::shared_ptr classptr3(new Class781()); //Use make_shared!! 149 | //CHECK(classptr3 != nullptr); 150 | std::shared_ptr classptr4 = std::make_shared(); //make_shared ctor 151 | CHECK(classptr4 != nullptr); 152 | classptr4 = std::make_shared(); //assign make_shared 153 | CHECK(classptr4 != nullptr); 154 | classptr4 = classptr2; //assign 155 | CHECK(classptr4 == classptr2); 156 | 157 | std::shared_ptr structptr1; //default ctor 158 | CHECK(structptr1 == nullptr); 159 | structptr1 = std::make_shared(); //assign make_shared 160 | CHECK(structptr1 != nullptr); 161 | //structptr1.reset(new Struct781()); //Use make_shared!! 162 | //CHECK(structptr1 != nullptr); 163 | std::shared_ptr structptr2 = structptr1; //copy stor 164 | CHECK(structptr2 == structptr1); 165 | //std::shared_ptr structptr3(new Struct781()); //Use make_shared!! 166 | //CHECK(structptr2 != nullptr); 167 | std::shared_ptr structptr4 = std::make_shared(); //make_shared ctor 168 | CHECK(structptr4 != nullptr); 169 | structptr4 = structptr1; //assign 170 | CHECK(structptr4 == structptr1); 171 | return; 172 | } 173 | 174 | void check_unique_ptr() 175 | { 176 | std::unique_ptr classptr1; //default ctor 177 | CHECK(classptr1 == nullptr); 178 | classptr1.reset(new Class781()); 179 | CHECK(classptr1 != nullptr); 180 | std::unique_ptr classptr2 = std::move(classptr1); //move copy 181 | CHECK(classptr2 != nullptr); 182 | CHECK(classptr1 == nullptr); 183 | //std::unique_ptrd_ptr classptr3(new Class781()); //Use make_shared!! 184 | //CHECK(classptr3 != nullptr); 185 | std::unique_ptr classptr4 = std::make_unique(); //make_shared ctor 186 | (*classptr4).i = 78; 187 | CHECK_EQUAL((*classptr4).i, 78); 188 | CHECK(classptr4 != nullptr); 189 | classptr4 = std::make_unique(); //assign make_shared 190 | CHECK(classptr4 != nullptr); 191 | classptr4 = std::move(classptr2); //move assign 192 | CHECK(classptr4 != nullptr); 193 | CHECK(classptr2 == nullptr); 194 | 195 | std::unique_ptr structptr1; //default ctor 196 | CHECK(structptr1 == nullptr); 197 | structptr1 = std::make_unique(); //assign make_shared 198 | (*structptr1).i = 78; 199 | CHECK_EQUAL((*structptr1).i, 78); 200 | CHECK(structptr1 != nullptr); 201 | //structptr1.reset(new Struct781()); //Use make_shared!! 202 | //CHECK(structptr1 != nullptr); 203 | std::unique_ptr structptr2 = std::move(structptr1); //move copy 204 | CHECK(structptr2 != nullptr); 205 | CHECK(structptr1 == nullptr); 206 | //std::unique_ptr structptr3(new Struct781()); //Use make_shared!! 207 | //CHECK(structptr2 != nullptr); 208 | std::unique_ptr structptr4 = std::make_unique(); //make_shared ctor 209 | CHECK(structptr4 != nullptr); 210 | structptr4 = std::move(structptr2); //assign 211 | CHECK(structptr4 != nullptr); 212 | CHECK(structptr2 == nullptr); 213 | return; 214 | } 215 | 216 | void check_stdarray() 217 | { 218 | std::array a; 219 | a.fill(2); 220 | CHECK(a[3] == 2); 221 | std::array b = {0, 1, 2, 3}; 222 | CHECK(b[1] == 1); 223 | } 224 | 225 | void check_stdpair() 226 | { 227 | std::pair p1; 228 | p1.first = 3; 229 | p1.second = 3.141f; 230 | CHECK(p1.first == 3); 231 | CHECK(p1.second == 3.141f); 232 | auto p2 = std::pair(4, 4.44444f); 233 | CHECK(p2.first == 4); 234 | auto p3 = std::make_pair(6, 6.66666f); 235 | CHECK(p3.first == 6); 236 | 237 | std::get<0>(p1) = 7; 238 | CHECK(std::get<0>(p1) == 7); 239 | } 240 | 241 | class Class783 : public Class781 242 | { 243 | public: 244 | Class783() { i = 12; } 245 | }; 246 | 247 | void check_vector() 248 | { 249 | std::vector a; 250 | a.push_back(2); 251 | CHECK_EQUAL(a[0], 2); 252 | CHECK_EQUAL(static_cast(a.size()), 1); 253 | 254 | enum Blu 255 | { 256 | A1, 257 | }; 258 | std::vector b; 259 | b.push_back(A1); 260 | CHECK_EQUAL(b[0], A1); 261 | CHECK_EQUAL(static_cast(b.size()), 1); 262 | 263 | std::vector> c; 264 | c.push_back(std::make_shared()); 265 | CHECK_EQUAL(c[0]->i, 0); 266 | CHECK_EQUAL(static_cast(c.size()), 1); 267 | 268 | std::vector> d; 269 | d.push_back(std::make_shared()); 270 | CHECK_EQUAL(d[0]->i, 0); 271 | CHECK_EQUAL(static_cast(d.size()), 1); 272 | 273 | d.push_back(std::make_shared()); 274 | CHECK_EQUAL(d[1]->i, 12); 275 | CHECK_EQUAL(d.at(1)->i, 12); 276 | CHECK_EQUAL(static_cast(d.size()), 2); 277 | 278 | std::cout << std::endl; 279 | } 280 | 281 | void check_tuple() 282 | { 283 | typedef std::tuple > sdgdfh; 284 | typedef std::tuple Tutu; 285 | Tutu tutu(42, "azer"); 286 | CHECK_EQUAL(std::get<0>(tutu), 42); 287 | CHECK_EQUAL(std::get<1>(tutu), "azer"); 288 | 289 | typedef std::tuple TutuR; 290 | //TutuR tutuR(std::get<0>(tutu), std::get<1>(tutu)); 291 | //CHECK_EQUAL(std::get<0>(tutuR), 42); 292 | //CHECK_EQUAL(std::get<1>(tutuR), "azer"); 293 | } 294 | 295 | void check_stringstream() 296 | { 297 | std::stringstream ss; 298 | ss << "abc" << " " << 42; 299 | CHECK(ss.str() == "abc 42"); 300 | std::stringstream& ss2 = ss; 301 | CHECK(ss2.str() == "abc 42"); 302 | 303 | std::stringstream ss3("dfgdfgfh"); 304 | CHECK(ss3.str() == "dfgdfgfh"); 305 | } 306 | 307 | void stdlib_register(TestFrameWork& tf) 308 | { 309 | auto ts = std::make_unique(); 310 | 311 | ts->addTestCase(check_stringstream); 312 | 313 | ts->addTestCase(check_std_map); 314 | 315 | ts->addTestCase(check_vector); 316 | 317 | ts->addTestCase(check_cmath); 318 | 319 | ts->addTestCase(check_std_unordered_map); 320 | 321 | ts->addTestCase(check_shared_ptr); 322 | 323 | ts->addTestCase(check_unique_ptr); 324 | 325 | ts->addTestCase(check_stdarray); 326 | 327 | ts->addTestCase(check_stdpair); 328 | 329 | ts->addTestCase(check_tuple); 330 | 331 | tf.addTestSuite(std::move(ts)); 332 | } -------------------------------------------------------------------------------- /CPP2D/MatchContainer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #include "MatchContainer.h" 9 | #include "DPrinter.h" 10 | #include 11 | #include 12 | #include "CustomPrinters.h" 13 | #include "Spliter.h" 14 | 15 | 16 | 17 | using namespace clang; 18 | using namespace clang::ast_matchers; 19 | 20 | TemplateArgument const* MatchContainer::getTemplateTypeArgument(Expr const* e, size_t tmplArgIndex) 21 | { 22 | if(auto* cast = dyn_cast(e)) 23 | { 24 | if(auto* ref = dyn_cast(cast->getSubExpr())) 25 | { 26 | TemplateArgumentLoc const* tmpArgs = ref->getTemplateArgs(); 27 | if(tmpArgs) 28 | { 29 | assert(ref->getNumTemplateArgs() > tmplArgIndex); 30 | return &tmpArgs[tmplArgIndex].getArgument(); 31 | } 32 | else 33 | { 34 | if(auto elType = dyn_cast(ref->getType())) 35 | { 36 | if(auto* TSType = dyn_cast(elType->getNamedType())) 37 | { 38 | assert(TSType->getNumArgs() > tmplArgIndex); 39 | return &TSType->getArg((unsigned int)tmplArgIndex); 40 | } 41 | else 42 | return nullptr; 43 | } 44 | else 45 | return nullptr; 46 | } 47 | } 48 | else 49 | return nullptr; 50 | } 51 | else 52 | return nullptr; 53 | }; 54 | 55 | void MatchContainer::rewriteType(clang::ast_matchers::MatchFinder& finder, 56 | std::string const& oldName, 57 | std::string const& newName, 58 | std::string const& newImport) 59 | { 60 | using namespace clang::ast_matchers; 61 | finder.addMatcher(recordType(hasDeclaration(namedDecl(hasName(oldName)))) 62 | .bind(oldName), this); 63 | typePrinters.emplace(oldName, [newName, newImport](DPrinter & pr, Type*) 64 | { 65 | pr.stream() << newName; 66 | if(not newImport.empty()) 67 | pr.addExternInclude(newImport, newName); 68 | }); 69 | }; 70 | 71 | void MatchContainer::methodPrinter(std::string const& className, 72 | std::string const& methodName, 73 | StmtPrinter const& printer) 74 | { 75 | methodPrinters[methodName].emplace(className, printer); 76 | }; 77 | 78 | void MatchContainer::globalFuncPrinter( 79 | std::string const& funcName, 80 | StmtPrinter const& printer 81 | ) 82 | { 83 | globalFuncPrinters[funcName] = printer; 84 | }; 85 | 86 | void MatchContainer::tmplTypePrinter(std::string const& name, 87 | DeclPrinter const& printMapDecl) 88 | { 89 | customTypePrinters.emplace(name, printMapDecl); 90 | }; 91 | 92 | void MatchContainer::memberPrinter(clang::ast_matchers::MatchFinder& finder, 93 | std::string const& memberName, 94 | StmtPrinter const& printer) 95 | { 96 | std::string const tag = "memberPrinter_" + memberName; 97 | finder.addMatcher(memberExpr(member(matchesName(memberName))).bind(tag), this); 98 | stmtPrinters.emplace(tag, printer); 99 | }; 100 | 101 | void MatchContainer::operatorCallPrinter( 102 | clang::ast_matchers::MatchFinder& finder, 103 | std::string const& classRegexpr, 104 | std::string const& op, 105 | StmtPrinter const& printer) 106 | { 107 | std::string const tag = "operatorCallPrinter_" + classRegexpr + op; 108 | finder.addMatcher(cxxOperatorCallExpr( 109 | hasArgument(0, hasType(cxxRecordDecl(isSameOrDerivedFrom(matchesName(classRegexpr))))), 110 | hasOverloadedOperatorName(op) 111 | ).bind(tag), this); 112 | stmtPrinters.emplace(tag, printer); 113 | }; 114 | 115 | void MatchContainer::cFuncPrinter( 116 | std::string const& lib, 117 | std::string const& func) 118 | { 119 | globalFuncPrinter("^(::std)?::" + func + "(<|$)", [lib, func](DPrinter & pr, Stmt * s) 120 | { 121 | if(auto* call = dyn_cast(s)) 122 | { 123 | pr.stream() << "core.stdc." << lib << "." << func; 124 | pr.stream() << "("; 125 | Spliter spliter(pr, ", "); 126 | for(Expr* arg : call->arguments()) 127 | { 128 | if(arg->getStmtClass() == Stmt::StmtClass::CXXDefaultArgExprClass) 129 | break; 130 | spliter.split(); 131 | 132 | std::string const argType = arg->getType().getAsString(); 133 | bool const passCString = (argType == "const char *" || argType == "char *"); 134 | if(passCString) 135 | { 136 | pr.addExternInclude("std.string", "std.string.toStringz"); 137 | pr.stream() << "std.string.toStringz("; 138 | } 139 | pr.TraverseStmt(arg); 140 | if(passCString) 141 | pr.stream() << ")"; 142 | } 143 | pr.stream() << ")"; 144 | 145 | pr.addExternInclude("core.stdc." + lib, "core.stdc." + lib + "." + func); 146 | } 147 | }); 148 | }; 149 | 150 | 151 | clang::ast_matchers::MatchFinder MatchContainer::getMatcher() 152 | { 153 | MatchFinder finder; 154 | 155 | // Some debug bind slot 156 | onStmtMatch.emplace("dump", [](Stmt const * d) {d->dump(); }); 157 | onTypeMatch.emplace("dump", [](Type const * d) {d->dump(); }); 158 | onDeclMatch.emplace("dump", [](Decl const * d) {d->dump(); }); 159 | onDeclMatch.emplace("print_name", [](Decl const * d) 160 | { 161 | if(auto* nd = dyn_cast(d)) 162 | llvm::errs() << nd->getNameAsString() << "\n"; 163 | }); 164 | 165 | //free operators 166 | DeclarationMatcher out_stream_op = 167 | functionDecl( 168 | unless(hasDeclContext(recordDecl())), 169 | matchesName("operator[\\+-\\*\\^\\[\\(\\!\\&\\|\\~\\=\\/\\%\\<\\>]") 170 | ).bind("free_operator"); 171 | finder.addMatcher(out_stream_op, this); 172 | declPrinters.emplace("free_operator", [](DPrinter&, Decl*) {}); 173 | onDeclMatch.emplace("free_operator", [this](Decl const * d) 174 | { 175 | if(auto* funcDecl = dyn_cast(d)) 176 | { 177 | auto getParamTypeName = [](ParmVarDecl const * typeParam) 178 | { 179 | QualType canType = typeParam->getType().getCanonicalType() 180 | .getUnqualifiedType().getNonReferenceType(); 181 | canType.removeLocalConst(); 182 | return canType.getAsString(); 183 | }; 184 | 185 | if(funcDecl->getNumParams() > 0) 186 | { 187 | std::string const left_name = getParamTypeName(funcDecl->getParamDecl(0)); 188 | freeOperator.emplace(left_name, funcDecl); 189 | if(funcDecl->getNumParams() > 1) 190 | { 191 | std::string const right_name = getParamTypeName(funcDecl->getParamDecl(1)); 192 | if(right_name != left_name) 193 | freeOperatorRight.emplace(right_name, funcDecl); 194 | } 195 | } 196 | } 197 | }); 198 | 199 | for(auto printerRegisterers : CustomPrinters::getInstance().getRegisterers()) 200 | printerRegisterers(*this, finder); 201 | 202 | return finder; 203 | } 204 | 205 | void MatchContainer::run(const ast_matchers::MatchFinder::MatchResult& Result) 206 | { 207 | // To call printers during the D print 208 | for(auto const& tag_n_func : typePrinters) 209 | { 210 | if(auto* t = Result.Nodes.getNodeAs(tag_n_func.first)) 211 | typeTags.emplace(t, tag_n_func.first); 212 | } 213 | for(auto const& tag_n_func : stmtPrinters) 214 | { 215 | if(auto* s = Result.Nodes.getNodeAs(tag_n_func.first)) 216 | stmtTags.emplace(s, tag_n_func.first); 217 | } 218 | for(auto const& tag_n_func : declPrinters) 219 | { 220 | if(auto* d = Result.Nodes.getNodeAs(tag_n_func.first)) 221 | declTags.emplace(d, tag_n_func.first); 222 | } 223 | 224 | // To call a special handling now 225 | for(auto const& name_n_func : onDeclMatch) 226 | { 227 | if(auto* d = Result.Nodes.getNodeAs(name_n_func.first)) 228 | name_n_func.second(d); 229 | } 230 | for(auto const& name_n_func : onStmtMatch) 231 | { 232 | if(auto* s = Result.Nodes.getNodeAs(name_n_func.first)) 233 | name_n_func.second(s); 234 | } 235 | for(auto const& name_n_func : onTypeMatch) 236 | { 237 | if(auto* t = Result.Nodes.getNodeAs(name_n_func.first)) 238 | name_n_func.second(t); 239 | } 240 | } 241 | 242 | 243 | std::function 244 | MatchContainer::getPrinter(clang::Stmt const* node) const 245 | { 246 | auto iter_pair = stmtTags.equal_range(node); 247 | if(iter_pair.first != iter_pair.second) 248 | { 249 | auto iter2 = stmtPrinters.find(iter_pair.first->second); 250 | if(iter2 != stmtPrinters.end()) 251 | return iter2->second; 252 | } 253 | 254 | return std::function(); 255 | } 256 | 257 | std::function 258 | MatchContainer::getPrinter(clang::Decl const* node) const 259 | { 260 | auto iter_pair = declTags.equal_range(node); 261 | if(iter_pair.first != iter_pair.second) 262 | { 263 | auto iter2 = declPrinters.find(iter_pair.first->second); 264 | if(iter2 != declPrinters.end()) 265 | return iter2->second; 266 | } 267 | 268 | return std::function(); 269 | } 270 | 271 | std::function 272 | MatchContainer::getPrinter(clang::Type const* node) const 273 | { 274 | auto iter_pair = typeTags.equal_range(node); 275 | if(iter_pair.first != iter_pair.second) 276 | { 277 | auto iter2 = typePrinters.find(iter_pair.first->second); 278 | if(iter2 != typePrinters.end()) 279 | return iter2->second; 280 | } 281 | 282 | return std::function(); 283 | } 284 | -------------------------------------------------------------------------------- /CPP2D/CPP2DPPHandling.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | 8 | #include "CPP2DPPHandling.h" 9 | 10 | #pragma warning(push, 0) 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #pragma warning(pop) 18 | 19 | #include 20 | #include "CPP2DTools.h" 21 | 22 | using namespace clang; 23 | using namespace llvm; 24 | 25 | extern cl::list MacroAsExpr; 26 | extern cl::list MacroAsStmt; 27 | 28 | CPP2DPPHandling::CPP2DPPHandling(clang::SourceManager& sourceManager_, 29 | Preprocessor& pp_, 30 | StringRef inFile_) 31 | : sourceManager(sourceManager_) 32 | , pp(pp_) 33 | , inFile(inFile_) 34 | , modulename(llvm::sys::path::stem(inFile_)) 35 | { 36 | auto split = [](std::string name) 37 | { 38 | std::string args, cppReplace; 39 | size_t arg_pos = name.find("/"); 40 | if(arg_pos != std::string::npos) 41 | { 42 | args = name.substr(arg_pos + 1); 43 | name = name.substr(0, arg_pos); 44 | } 45 | arg_pos = args.find("/"); 46 | if(arg_pos != std::string::npos) 47 | { 48 | cppReplace = args.substr(arg_pos + 1); 49 | args = args.substr(0, arg_pos); 50 | } 51 | return std::make_tuple(name, args, cppReplace); 52 | }; 53 | for(std::string const& macro_options : MacroAsExpr) 54 | { 55 | std::string name, args, cppReplace; 56 | std::tie(name, args, cppReplace) = split(macro_options); 57 | macro_expr.emplace(name, MacroInfo{ name, args, cppReplace }); 58 | } 59 | for(std::string const& macro_options : MacroAsStmt) 60 | { 61 | std::string name, args, cppReplace; 62 | std::tie(name, args, cppReplace) = split(macro_options); 63 | macro_stmt.emplace(name, MacroInfo{ name, args, cppReplace }); 64 | } 65 | 66 | // TODO : Find a better way if it exists 67 | predefines = pp_.getPredefines() + 68 | "\ntemplate int cpp2d_dummy_variadic(Args&&...){}\n" 69 | "template int cpp2d_type();\n" 70 | "int cpp2d_name(char const*);\n" 71 | "#define CPP2D_ADD2(A, B) A##B\n" 72 | "#define CPP2D_ADD(A, B) CPP2D_ADD2(A, B)\n"; 73 | pp_.setPredefines(predefines); 74 | } 75 | 76 | void CPP2DPPHandling::InclusionDirective( 77 | SourceLocation, //hash_loc, 78 | const Token&, //include_token, 79 | StringRef file_name, 80 | bool, //is_angled, 81 | CharSourceRange, //filename_range, 82 | const FileEntry*, //file, 83 | StringRef, //search_path, 84 | StringRef, //relative_path, 85 | const clang::Module* //imported 86 | ) 87 | { 88 | includes_in_file.insert(file_name); 89 | } 90 | 91 | //! Print arguments of the macro MI into a std::stringstream, for a normal macro declaration 92 | auto print_macro_args(MacroInfo const* MI, 93 | std::stringstream& new_macro, 94 | char const* prefix = nullptr) 95 | { 96 | new_macro << '('; 97 | bool first = true; 98 | for(IdentifierInfo const* arg : MI->params()) 99 | { 100 | if(first) 101 | first = false; 102 | else 103 | new_macro << ", "; 104 | if(prefix) 105 | new_macro << prefix; 106 | new_macro << arg->getName().str(); 107 | } 108 | new_macro << ')'; 109 | } 110 | 111 | //! Print arguments of the macro MI into a std::stringstream, 112 | //! in a way they are compilable in C++, and convertible to D 113 | void print_macro_args_expand(MacroInfo const* MI, 114 | std::stringstream& new_macro, 115 | std::string args) 116 | { 117 | new_macro << '('; 118 | bool first = true; 119 | args.resize(MI->getNumParams(), 'n'); 120 | auto arg_type_iter = std::begin(args); 121 | for(IdentifierInfo const* arg : MI->params()) 122 | { 123 | if(first) 124 | first = false; 125 | else 126 | new_macro << ", "; 127 | switch(*arg_type_iter) 128 | { 129 | case 't': 130 | new_macro << "cpp2d_type<" << arg->getName().str() << ">()"; 131 | break; 132 | case 'e': 133 | new_macro << arg->getName().str(); 134 | break; 135 | case 'n': default: 136 | new_macro << "cpp2d_name(#" << arg->getName().str() << ")"; 137 | } 138 | ++arg_type_iter; 139 | } 140 | new_macro << ')'; 141 | } 142 | 143 | //! Print the macro, as a C macro 144 | std::string print_macro(MacroInfo const* MI) 145 | { 146 | std::string new_macro; 147 | bool first = true; 148 | for(Token const& Tok : MI->tokens()) 149 | { 150 | if(first || Tok.hasLeadingSpace()) 151 | new_macro += " "; 152 | first = false; 153 | 154 | if(const char* Punc = tok::getPunctuatorSpelling(Tok.getKind())) 155 | new_macro += Punc; 156 | else if(Tok.isLiteral() && Tok.getLiteralData()) 157 | new_macro.append(Tok.getLiteralData(), Tok.getLength()); 158 | else if(auto* II = Tok.getIdentifierInfo()) 159 | new_macro += II->getName(); 160 | else 161 | new_macro += Tok.getName(); 162 | } 163 | return new_macro; 164 | } 165 | 166 | //! Print the macro as a D mixin 167 | std::string make_d_macro(MacroInfo const* MI, std::string const& name) 168 | { 169 | std::set arg_names; 170 | for(IdentifierInfo const* arg : MI->params()) 171 | arg_names.insert(arg->getName()); 172 | 173 | std::stringstream d_templ; 174 | d_templ << "template " + name; 175 | if(MI->isFunctionLike()) 176 | print_macro_args(MI, d_templ, "string "); 177 | else 178 | d_templ << "()"; 179 | d_templ << "\n{\n"; 180 | d_templ << " const char[] " + name + " = "; 181 | bool first = true; 182 | bool next_is_str = false; 183 | bool next_is_pasted = false; 184 | for(Token const& Tok : MI->tokens()) 185 | { 186 | if(!first && Tok.hasLeadingSpace()) 187 | d_templ << "\" \""; 188 | first = false; 189 | 190 | if(const char* Punc = tok::getPunctuatorSpelling(Tok.getKind())) 191 | { 192 | if(Punc == std::string("#")) 193 | next_is_str = true; 194 | else if(Punc == std::string("##")) 195 | next_is_pasted = true; 196 | else 197 | d_templ << std::string(1, '"') + Punc + '"'; 198 | } 199 | else if(Tok.isLiteral() && Tok.getLiteralData()) 200 | { 201 | std::string const literal = 202 | CPP2DTools::replaceString( 203 | std::string(Tok.getLiteralData(), Tok.getLength()), "\"", "\\\""); 204 | d_templ << '"' + literal + '"'; 205 | } 206 | else if(auto* II = Tok.getIdentifierInfo()) 207 | { 208 | std::string const identifierName = 209 | CPP2DTools::replaceString(II->getName(), "\"", "\\\""); 210 | if(arg_names.count(identifierName)) 211 | { 212 | if(next_is_str) 213 | { 214 | d_templ << "\"q{\" ~ " + identifierName + " ~ \"}\""; 215 | next_is_str = false; 216 | } 217 | else if(next_is_pasted) 218 | { 219 | d_templ << " ~ " + identifierName + " ~ "; 220 | next_is_pasted = false; 221 | } 222 | else 223 | d_templ << "\" \" ~ " + identifierName + " ~ \" \""; 224 | } 225 | else 226 | d_templ << '"' + identifierName + '"'; 227 | } 228 | else 229 | d_templ << std::string(1, '"') + Tok.getName() + '"'; 230 | } 231 | d_templ << ";\n"; 232 | d_templ << "}\n"; 233 | 234 | std::string d_templ_str = d_templ.str(); 235 | size_t pos = std::string::npos; 236 | while((pos = d_templ_str.find("\"\"")) != std::string::npos) 237 | d_templ_str = d_templ_str.substr(0, pos) + d_templ_str.substr(pos + 2); 238 | return d_templ_str; 239 | } 240 | 241 | namespace 242 | { 243 | static std::string const MemFileSuffix = "_MemFileSuffix"; 244 | } 245 | 246 | void CPP2DPPHandling::inject_macro( 247 | MacroDirective const* MD, 248 | std::string const& name, 249 | std::string const& new_macro) 250 | { 251 | // TODO : Find a better way if it exists 252 | auto iter_inserted = new_macros.insert(new_macro); 253 | std::unique_ptr membuf = 254 | MemoryBuffer::getMemBuffer(*iter_inserted.first, "<" + name + MemFileSuffix + ">"); 255 | assert(membuf); 256 | FileID fileID = pp.getSourceManager().createFileID( 257 | std::move(membuf), clang::SrcMgr::C_User, 0, 0, MD->getLocation()); 258 | 259 | pp.EnterSourceFile(fileID, pp.GetCurDirLookup(), MD->getMacroInfo()->getDefinitionEndLoc()); 260 | 261 | char const* filename = CPP2DTools::getFile(sourceManager, MD->getLocation()); 262 | if(CPP2DTools::checkFilename(modulename, filename)) 263 | add_before_decl.insert(make_d_macro(MD->getMacroInfo(), name)); 264 | } 265 | 266 | void CPP2DPPHandling::TransformMacroExpr( 267 | Token const& MacroNameTok, 268 | MacroDirective const* MD, 269 | CPP2DPPHandling::MacroInfo const& macro_options) 270 | { 271 | clang::MacroInfo const* MI = MD->getMacroInfo(); 272 | 273 | std::stringstream new_macro; 274 | new_macro << "\n#define " + macro_options.name; 275 | 276 | if(MI->isFunctionLike()) 277 | print_macro_args(MI, new_macro); 278 | new_macro << " (\"CPP2D_MACRO_EXPR\", ((\"" + macro_options.name + "\", cpp2d_dummy_variadic"; 279 | if(MI->isFunctionLike()) 280 | print_macro_args_expand(MI, new_macro, macro_options.argType); 281 | else 282 | new_macro << "()"; 283 | new_macro << "), "; 284 | if(macro_options.cppReplace.empty()) 285 | new_macro << print_macro(MI); 286 | else 287 | new_macro << macro_options.cppReplace; 288 | new_macro << + "))\n"; 289 | 290 | SourceLocation const location = MacroNameTok.getLocation(); 291 | if(location.printToString(sourceManager).find(MemFileSuffix) != std::string::npos) 292 | return; 293 | 294 | pp.appendMacroDirective(MacroNameTok.getIdentifierInfo(), new UndefMacroDirective(location)); 295 | 296 | inject_macro(MD, macro_options.name, new_macro.str()); 297 | } 298 | 299 | void CPP2DPPHandling::TransformMacroStmt( 300 | Token const& MacroNameTok, 301 | MacroDirective const* MD, 302 | CPP2DPPHandling::MacroInfo const& macro_options) 303 | { 304 | clang:: MacroInfo const* MI = MD->getMacroInfo(); 305 | 306 | std::stringstream new_macro; 307 | new_macro << "\n#define " + macro_options.name; 308 | 309 | if(MI->isFunctionLike()) 310 | print_macro_args(MI, new_macro); 311 | new_macro << " int CPP2D_ADD(CPP2D_MACRO_STMT, __COUNTER__) = (\"" 312 | << macro_options.name << "\", cpp2d_dummy_variadic"; 313 | if(MI->isFunctionLike()) 314 | print_macro_args_expand(MI, new_macro, macro_options.argType); 315 | else 316 | new_macro << "()"; 317 | new_macro << ");\\\n"; 318 | 319 | new_macro << print_macro(MI) << "\\\n"; 320 | new_macro << "int CPP2D_ADD(CPP2D_MACRO_STMT_END, __COUNTER__) = 0;"; 321 | 322 | SourceLocation const location = MacroNameTok.getLocation(); 323 | if(location.printToString(sourceManager).find(MemFileSuffix) != std::string::npos) 324 | return; 325 | 326 | pp.appendMacroDirective(MacroNameTok.getIdentifierInfo(), new UndefMacroDirective(location)); 327 | 328 | inject_macro(MD, macro_options.name, new_macro.str()); 329 | } 330 | 331 | 332 | void CPP2DPPHandling::MacroDefined(const Token& MacroNameTok, const MacroDirective* MD) 333 | { 334 | std::string const& name = MacroNameTok.getIdentifierInfo()->getName(); 335 | clang::MacroInfo const* MI = MD->getMacroInfo(); 336 | if(MI->isBuiltinMacro()) 337 | return; 338 | auto macro_expr_iter = macro_expr.find(name); 339 | if(macro_expr_iter != macro_expr.end()) 340 | TransformMacroExpr(MacroNameTok, MD, macro_expr_iter->second); 341 | else 342 | { 343 | auto macro_stmt_iter = macro_stmt.find(name); 344 | if(macro_stmt_iter != macro_stmt.end()) 345 | TransformMacroStmt(MacroNameTok, MD, macro_stmt_iter->second); 346 | } 347 | } 348 | 349 | std::set const& CPP2DPPHandling::getIncludes() const 350 | { 351 | return includes_in_file; 352 | } 353 | 354 | std::set const& CPP2DPPHandling::getInsertedBeforeDecls() const 355 | { 356 | return add_before_decl; 357 | } 358 | -------------------------------------------------------------------------------- /CPP2D/CPP2D.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {F60FFC9A-3941-4F21-81E0-7E23E54E8F93} 23 | Win32Proj 24 | clangAST_test 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | EnableAllWarnings 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | I:\C_libs\llvm_bin\include;I:\C_libs\llvm\include;I:\C_libs\llvm\tools\clang\include;I:\C_libs\llvm_bin\tools\clang\include;%(AdditionalIncludeDirectories) 92 | ProgramDatabase 93 | true 94 | 4820;4371;4710;4514;5027;4626;5026;4625;4996;4702;4714;4711 95 | true 96 | 97 | 98 | Console 99 | true 100 | I:/C_libs/llvm_bin/$(Configuration)/lib 101 | clangFrontend.lib;clangDriver.lib;clangSerialization.lib;clangParse.lib;clangSema.lib;clangAnalysis.lib;clangEdit.lib;clangAST.lib;clangASTMatchers.lib;clangLex.lib;clangBasic.lib;clangTooling.lib;I:\C_libs\llvm_bin\Release\lib\LLVMOption.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBitReader.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSupport.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64CodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64AsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64AsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64Desc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64Info.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64Disassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBPFCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBPFAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBPFDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBPFInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMCppBackendCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMCppBackendInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMSP430CodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMSP430AsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMSP430Desc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMSP430Info.lib;I:\C_libs\llvm_bin\Release\lib\LLVMNVPTXCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMNVPTXAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMNVPTXDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMNVPTXInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86CodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86AsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86AsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86Desc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86Info.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86Disassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64Utils.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUUtils.lib;I:\C_libs\llvm_bin\Release\lib\LLVMipo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMIRReader.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMLinker.lib;I:\C_libs\llvm_bin\Release\lib\LLVMVectorize.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86Utils.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMDebugInfoCodeView.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSelectionDAG.lib;I:\C_libs\llvm_bin\Release\lib\LLVMCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMScalarOpts.lib;I:\C_libs\llvm_bin\Release\lib\LLVMInstCombine.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBitWriter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMInstrumentation.lib;I:\C_libs\llvm_bin\Release\lib\LLVMProfileData.lib;I:\C_libs\llvm_bin\Release\lib\LLVMObject.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMCParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMTarget.lib;I:\C_libs\llvm_bin\Release\lib\LLVMTransformUtils.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAnalysis.lib;I:\C_libs\llvm_bin\Release\lib\LLVMCore.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMCDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMC.lib;%(AdditionalDependencies) 102 | 103 | 104 | 105 | 106 | 107 | 108 | EnableAllWarnings 109 | Disabled 110 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 111 | I:\C_libs\llvm-4.0.1_VS2015\include;I:\C_libs\llvm-4.0.1\include;I:\C_libs\llvm-4.0.1\tools\clang\include;I:\C_libs\llvm-4.0.1_VS2015\tools\clang\include;%(AdditionalIncludeDirectories) 112 | ProgramDatabase 113 | true 114 | 4571;4548;4503;4820;4371;4710;4514;5027;4626;5026;4625;4996;4702;4714;4711;4464;4061;4062 115 | true 116 | 117 | 118 | Console 119 | true 120 | I:\C_libs\llvm-4.0.1_VS2015/$(Configuration)/lib 121 | Version.lib;clangFrontend.lib;clangDriver.lib;clangSerialization.lib;clangParse.lib;clangSema.lib;clangAnalysis.lib;clangEdit.lib;clangAST.lib;clangASTMatchers.lib;clangLex.lib;clangBasic.lib;clangTooling.lib;LLVMX86AsmParser.lib;LLVMX86Desc.lib;LLVMX86AsmPrinter.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMipo.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMAnalysis.lib;LLVMTarget.lib;LLVMOption.lib;LLVMMCParser.lib;LLVMMC.lib;LLVMObject.lib;LLVMBitReader.lib;LLVMCore.lib;LLVMProfileData.lib;LLVMSupport.lib;LLVMBinaryFormat.lib;Mincore.lib;%(AdditionalDependencies) 122 | 123 | 124 | 125 | 126 | EnableAllWarnings 127 | 128 | 129 | Disabled 130 | true 131 | true 132 | NDEBUG;_CONSOLE;WIN32;%(PreprocessorDefinitions) 133 | I:\C_libs\llvm_bin\include;I:\C_libs\llvm\include;I:\C_libs\llvm\tools\clang\include;I:\C_libs\llvm_bin\tools\clang\include;%(AdditionalIncludeDirectories) 134 | true 135 | 4820;4371;4710;4514;5027;4626;5026;4625;4996;4702;4714;4711 136 | true 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | I:/C_libs/llvm_bin/$(Configuration)/lib 144 | clangFrontend.lib;clangDriver.lib;clangSerialization.lib;clangParse.lib;clangSema.lib;clangAnalysis.lib;clangEdit.lib;clangAST.lib;clangASTMatchers.lib;clangLex.lib;clangBasic.lib;clangTooling.lib;I:\C_libs\llvm_bin\Release\lib\LLVMOption.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBitReader.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSupport.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64CodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64AsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64AsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64Desc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64Info.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64Disassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMARMDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBPFCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBPFAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBPFDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBPFInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMCppBackendCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMCppBackendInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMHexagonDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMipsDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMSP430CodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMSP430AsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMSP430Desc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMSP430Info.lib;I:\C_libs\llvm_bin\Release\lib\LLVMNVPTXCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMNVPTXAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMNVPTXDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMNVPTXInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMPowerPCDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSparcDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSystemZDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86CodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86AsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86AsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86Desc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86Info.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86Disassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreDesc.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreInfo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMXCoreDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAArch64Utils.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAMDGPUUtils.lib;I:\C_libs\llvm_bin\Release\lib\LLVMipo.lib;I:\C_libs\llvm_bin\Release\lib\LLVMIRReader.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAsmParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMLinker.lib;I:\C_libs\llvm_bin\Release\lib\LLVMVectorize.lib;I:\C_libs\llvm_bin\Release\lib\LLVMX86Utils.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAsmPrinter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMDebugInfoCodeView.lib;I:\C_libs\llvm_bin\Release\lib\LLVMSelectionDAG.lib;I:\C_libs\llvm_bin\Release\lib\LLVMCodeGen.lib;I:\C_libs\llvm_bin\Release\lib\LLVMScalarOpts.lib;I:\C_libs\llvm_bin\Release\lib\LLVMInstCombine.lib;I:\C_libs\llvm_bin\Release\lib\LLVMBitWriter.lib;I:\C_libs\llvm_bin\Release\lib\LLVMInstrumentation.lib;I:\C_libs\llvm_bin\Release\lib\LLVMProfileData.lib;I:\C_libs\llvm_bin\Release\lib\LLVMObject.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMCParser.lib;I:\C_libs\llvm_bin\Release\lib\LLVMTarget.lib;I:\C_libs\llvm_bin\Release\lib\LLVMTransformUtils.lib;I:\C_libs\llvm_bin\Release\lib\LLVMAnalysis.lib;I:\C_libs\llvm_bin\Release\lib\LLVMCore.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMCDisassembler.lib;I:\C_libs\llvm_bin\Release\lib\LLVMMC.lib;%(AdditionalDependencies) 145 | 146 | 147 | 148 | 149 | EnableAllWarnings 150 | 151 | 152 | Disabled 153 | true 154 | true 155 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 156 | C:\Program Files\LLVM\include;%(AdditionalIncludeDirectories) 157 | true 158 | 4571;4548;4503;4820;4371;4710;4514;5027;4626;5026;4625;4996;4702;4714;4711;4464;4061;4062 159 | true 160 | Speed 161 | 162 | 163 | Console 164 | true 165 | true 166 | true 167 | C:\Program Files\LLVM\lib 168 | Version.lib;clangFrontend.lib;clangDriver.lib;clangSerialization.lib;clangParse.lib;clangSema.lib;clangAnalysis.lib;clangEdit.lib;clangAST.lib;clangASTMatchers.lib;clangLex.lib;clangBasic.lib;clangTooling.lib;LLVMX86AsmParser.lib;LLVMX86Desc.lib;LLVMX86AsmPrinter.lib;LLVMX86Info.lib;LLVMX86Utils.lib;LLVMipo.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMAnalysis.lib;LLVMTarget.lib;LLVMOption.lib;LLVMMCParser.lib;LLVMMC.lib;LLVMObject.lib;LLVMBitReader.lib;LLVMCore.lib;LLVMProfileData.lib;LLVMSupport.lib;LLVMBinaryFormat.lib;Mincore.lib;%(AdditionalDependencies) 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /CPP2D/DPrinter.h: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #pragma once 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #pragma warning(push, 0) 15 | #pragma warning(disable: 4265) 16 | #include 17 | #include 18 | #pragma warning(pop) 19 | 20 | #include "Options.h" 21 | 22 | class MatchContainer; 23 | 24 | //! Visit all the AST and print the compilation unit into **D** language file 25 | class DPrinter : public clang::RecursiveASTVisitor 26 | { 27 | typedef RecursiveASTVisitor Base; 28 | 29 | public: 30 | explicit DPrinter( 31 | clang::ASTContext* Context, 32 | MatchContainer const& receiver, 33 | llvm::StringRef file); 34 | 35 | //! Set the list if #include found in the C++ source 36 | void setIncludes(std::set const& includes); 37 | 38 | //! Get indentation string for a new line in **D** code 39 | std::string indentStr() const; 40 | 41 | //! Print in **dlang** the base class part of a class declaration. Like class A : B 42 | void printBasesClass(clang::CXXRecordDecl* decl); 43 | 44 | //! Print in **dlang** the template argument of a template func/type. Like A!(B) 45 | void printTmpArgList(std::string const& tmpArgListStr); 46 | 47 | //! Print in **dlang** the common part of RecordDecl, CXXRecordDecl, and template records 48 | template 49 | void traverseCXXRecordDeclImpl( 50 | clang::RecordDecl* decl, 51 | TmpSpecFunc traverseTmpSpecs, //!< A callable printing the template parameters. Like struct A(C, int) 52 | PrintBasesClass printBasesClass //!< A callable printing the base classes. Like class A : B 53 | ); 54 | 55 | //! Print the template parameters of a struct/func declaration. Like struct A(C, int) 56 | void printTemplateParameterList( 57 | clang::TemplateParameterList* tmpParams, 58 | std::string const& prevTmplParmsStr); 59 | 60 | //! Print a clang::CompoundStmt with an optional function for print an initialization list 61 | template 62 | void traverseCompoundStmtImpl( 63 | clang::CompoundStmt* Stmt, //!< The clang::CompoundStmt to print 64 | InitList initList, //!< A callable printing somthing a the begining of the scope 65 | AddBeforeEnd addBeforEnd //!< A callable printing somthing a the end of the scope 66 | ); 67 | 68 | //! Print a clang::CXXTryStmt with an optional function for print an initialization list 69 | template 70 | void traverseCXXTryStmtImpl( 71 | clang::CXXTryStmt* Stmt, //!< The clang::CXXTryStmt to print 72 | InitList initList //!< A callable printing somthing a the begining of the scope 73 | ); 74 | 75 | //! Get TemplateParameterList* of Decl if Decl is a clang::ClassTemplatePartialSpecializationDecl 76 | clang::TemplateParameterList* getTemplateParameters( 77 | clang::ClassTemplateSpecializationDecl* Decl); 78 | 79 | //! Get TemplateParameterList* of Decl if Decl is a clang::ClassTemplatePartialSpecializationDecl 80 | clang::TemplateParameterList* getTemplateParameters( 81 | clang::ClassTemplatePartialSpecializationDecl* Decl); 82 | 83 | //! Print to **dlang** the clang::TemplateArgument ta 84 | void printTemplateArgument(clang::TemplateArgument const& ta); 85 | 86 | //! Print the template part a of tmpl specialization. Like class A(B = int, int = 2, C) 87 | void printTemplateSpec_TmpArgsAndParms( 88 | clang::TemplateParameterList& primaryTmpParams, //!< Tmpl params of the specialized template 89 | clang::TemplateArgumentList const& tmpArgs, //!< Tmpl arguments of the specialization 90 | const clang::ASTTemplateArgumentListInfo* tmpArgsInfo, //!< Tmpl arguments of the specialization 91 | clang::TemplateParameterList* newTmpParams, //!< [optional] Tmpl params of the specialization 92 | std::string const& prevTmplParmsStr //!< String to add before the first param 93 | ); 94 | 95 | //! Print to **dlang** the construction expr in this way ```Type(arg1, arg2)``` 96 | void printCXXConstructExprParams(clang::CXXConstructExpr* Init); 97 | 98 | //! Print a type name to **dlang** 99 | void printType(clang::QualType const& type); 100 | 101 | //! Trait printing the initialization list of the clang::FunctionDecl (nothing) 102 | void startCtorBody(clang::FunctionDecl*); 103 | 104 | //! Trait printing the initialization list of the clang::CXXConstructorDecl 105 | void startCtorBody(clang::CXXConstructorDecl* Decl); 106 | 107 | //! Trait printing the const keyword (nothing) at the end of the clang::FunctionDecl prototype 108 | void printFuncEnd(clang::FunctionDecl* decl); 109 | 110 | //! Trait printing the const keyword at the end of the clang::CXXMethodDecl prototype 111 | void printFuncEnd(clang::CXXMethodDecl* Decl); 112 | 113 | //! Print keywords of a method. Like **static**, **abstract**, **override**, **final** 114 | void printSpecialMethodAttribute(clang::CXXMethodDecl* Decl); 115 | 116 | //! @brief Print the return type and name of a function. Like **rtype func_name**(arg1, arg2) 117 | //! @return true if this Decl has to be printed, else false 118 | bool printFuncBegin( 119 | clang::FunctionDecl* Decl, 120 | std::string& tmpParams, 121 | int thisArgIndex 122 | ); 123 | 124 | //! @brief Print the return type and name of a method. Like **rtype method_name**(arg1, arg2) 125 | //! @overload bool DPrinter::printFuncBegin(clang::FunctionDecl* Decl, std::string& tmpParams, int thisArgIndex) 126 | bool printFuncBegin(clang::CXXMethodDecl* Decl, std::string& tmpParams, int thisArgIndex); 127 | 128 | //! @brief Print the return type and name of a function. Like **T opCast**(T)() 129 | //! @overload bool DPrinter::printFuncBegin(clang::FunctionDecl* Decl, std::string& tmpParams, int thisArgIndex) 130 | bool printFuncBegin(clang::CXXConversionDecl* Decl, std::string& tmpParams, int thisArgIndex); 131 | 132 | //! @brief Print the return type and name of ctor. Like **this**(arg1) 133 | //! @overload bool DPrinter::printFuncBegin(clang::FunctionDecl* Decl, std::string& tmpParams, int thisArgIndex) 134 | bool printFuncBegin(clang::CXXConstructorDecl* Decl, 135 | std::string& tmpParams, 136 | int thisArgIndex); 137 | 138 | //! @brief Print the return type and name of dtor. Like ~this() 139 | //! @overload bool DPrinter::printFuncBegin(clang::FunctionDecl* Decl, std::string& tmpParams, int thisArgIndex) 140 | bool printFuncBegin(clang::CXXDestructorDecl*, std::string& tmpParams, int thisArgIndex); 141 | 142 | //! @brief Common function to print function 143 | //! @param Decl FunctionDel to print 144 | //! @param thisArgIndex This parameter will be "this".\n 145 | //! Usefull to put free operators inside, because one operand become "this".\n 146 | //! -1 mean no parameter is changed. 147 | template 148 | void traverseFunctionDeclImpl(D* Decl, int thisArgIndex = -1); 149 | 150 | //! Get the semantic of the passed type 151 | static TypeOptions::Semantic getSemantic(clang::QualType qt); 152 | 153 | //! Is this type a pointer, or a smart pointer 154 | static bool isPointer(clang::QualType const&); 155 | 156 | //! @brief Print a C++ pointer type to **D** 157 | //! Pointer to TypeOptions::Value become T[], and Semantic::Reference become just T. 158 | template 159 | void traversePointerTypeImpl(PType* Type); 160 | 161 | //! Common printing code for TraverseClassTemplate(Partial)SpecializationDecl 162 | template 163 | void traverseClassTemplateSpecializationDeclImpl( 164 | D* Decl, 165 | const clang::ASTTemplateArgumentListInfo* tmpArgsInfo //!< Optional 166 | ); 167 | 168 | //! Is this clang::QualType a std::array or a boost::array ? 169 | static bool isStdArray(clang::QualType const& type); 170 | 171 | //! Is this clang::QualType a std::unordered_map or a boost::unordered_map ? 172 | static bool isStdUnorderedMap(clang::QualType const& type); 173 | 174 | //! @brief Print the template args for (DependentScope)DeclRefExpr and UnresolvedLookupExpr 175 | //! Example : func!(T1, T2) 176 | template 177 | void traverseDeclRefExprImpl(ME* Expr); 178 | 179 | //! Print a (CXXDependentScope)MemberExpr 180 | template 181 | bool traverseMemberExprImpl(ME* Stmt); 182 | 183 | //! Get the list of all **import** to print in **D** 184 | std::map> const& getExternIncludes() const; 185 | 186 | //! Get the printer **D** code 187 | std::string getDCode() const; 188 | 189 | //! Get the std::ostream where print **D** code. 190 | std::ostream& stream(); 191 | 192 | //! Insert this include to the needed imports 193 | void addExternInclude( 194 | std::string const& include, //!< Modulename to import 195 | std::string const& typeName //!< Hint to known why this module is imported 196 | ); 197 | 198 | //! Print arguments of (CXXMember)CallExpr 199 | void printCallExprArgument(clang::CallExpr* Stmt); 200 | 201 | //! Print clang::VarDecl, also in CXXForRangeStmt and catch 202 | void traverseVarDeclImpl(clang::VarDecl* Decl); 203 | 204 | //! Print a statment which can be a compound one, a normal one, or a NullStmt (printed to {}) 205 | void traverseCompoundStmtOrNot(clang::Stmt* Stmt); 206 | 207 | //! Check if decl is the type named baseName, or inherit from it directly or indirectly 208 | static bool isA(clang::CXXRecordDecl* decl, std::string const& baseName); 209 | 210 | // ******************** Function called by RecursiveASTVisitor ******************************* 211 | bool shouldVisitImplicitCode() const; 212 | 213 | //! @pre setIncludes has already been called before 214 | bool TraverseTranslationUnitDecl(clang::TranslationUnitDecl* Decl); 215 | 216 | bool TraverseTypedefDecl(clang::TypedefDecl* Decl); 217 | 218 | bool TraverseTypeAliasDecl(clang::TypeAliasDecl* Decl); 219 | 220 | bool TraverseTypeAliasTemplateDecl(clang::TypeAliasTemplateDecl* Decl); 221 | 222 | bool TraverseFieldDecl(clang::FieldDecl* Decl); 223 | 224 | bool TraverseDependentNameType(clang::DependentNameType* Type); 225 | 226 | bool TraverseAttributedType(clang::AttributedType* Type); 227 | 228 | bool TraverseDecayedType(clang::DecayedType* Type); 229 | 230 | bool TraverseElaboratedType(clang::ElaboratedType* Type); 231 | 232 | bool TraverseInjectedClassNameType(clang::InjectedClassNameType* Type); 233 | 234 | bool TraverseSubstTemplateTypeParmType(clang::SubstTemplateTypeParmType*); 235 | 236 | bool TraverseNestedNameSpecifier(clang::NestedNameSpecifier* NNS); 237 | 238 | bool TraverseTemplateSpecializationType(clang::TemplateSpecializationType* Type); 239 | 240 | bool TraverseTypedefType(clang::TypedefType* Type); 241 | 242 | bool TraverseCompoundStmt(clang::CompoundStmt* Stmt); 243 | 244 | bool TraverseCXXTryStmt(clang::CXXTryStmt* Stmt); 245 | 246 | bool TraverseNamespaceDecl(clang::NamespaceDecl* Decl); 247 | 248 | bool TraverseCXXCatchStmt(clang::CXXCatchStmt* Stmt); 249 | 250 | bool TraverseAccessSpecDecl(clang::AccessSpecDecl* Decl); 251 | 252 | bool TraverseCXXRecordDecl(clang::CXXRecordDecl* decl); 253 | 254 | bool TraverseRecordDecl(clang::RecordDecl* Decl); 255 | 256 | bool TraverseClassTemplateDecl(clang::ClassTemplateDecl* Decl); 257 | 258 | bool TraverseClassTemplatePartialSpecializationDecl( 259 | clang::ClassTemplatePartialSpecializationDecl* Decl); 260 | 261 | bool TraverseClassTemplateSpecializationDecl(clang::ClassTemplateSpecializationDecl* Decl); 262 | 263 | bool TraverseCXXConversionDecl(clang::CXXConversionDecl* Decl); 264 | 265 | bool TraverseCXXConstructorDecl(clang::CXXConstructorDecl* Decl); 266 | 267 | bool TraverseCXXDestructorDecl(clang::CXXDestructorDecl* Decl); 268 | 269 | bool TraverseCXXMethodDecl(clang::CXXMethodDecl* Decl); 270 | 271 | bool TraversePredefinedExpr(clang::PredefinedExpr* expr); 272 | 273 | bool TraverseCXXDefaultArgExpr(clang::CXXDefaultArgExpr* expr); 274 | 275 | bool TraverseCXXUnresolvedConstructExpr(clang::CXXUnresolvedConstructExpr* Expr); 276 | 277 | bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* Expr); 278 | 279 | bool TraverseCXXForRangeStmt(clang::CXXForRangeStmt* Stmt); 280 | 281 | bool TraverseDoStmt(clang::DoStmt* Stmt); 282 | 283 | bool TraverseSwitchStmt(clang::SwitchStmt* Stmt); 284 | 285 | bool TraverseCaseStmt(clang::CaseStmt* Stmt); 286 | 287 | bool TraverseBreakStmt(clang::BreakStmt* Stmt); 288 | 289 | bool TraverseContinueStmt(clang::ContinueStmt* Stmt); 290 | 291 | bool TraverseStaticAssertDecl(clang::StaticAssertDecl* Decl); 292 | 293 | bool TraverseDefaultStmt(clang::DefaultStmt* Stmt); 294 | 295 | bool TraverseCXXDeleteExpr(clang::CXXDeleteExpr* Expr); 296 | 297 | bool TraverseCXXNewExpr(clang::CXXNewExpr* Expr); 298 | 299 | bool TraverseCXXConstructExpr(clang::CXXConstructExpr* Init); 300 | 301 | bool TraverseConstructorInitializer(clang::CXXCtorInitializer* Init); 302 | 303 | bool TraverseUsingDecl(clang::UsingDecl* Decl); 304 | 305 | bool TraverseFunctionDecl(clang::FunctionDecl* Decl); 306 | 307 | bool TraverseUsingDirectiveDecl(clang::UsingDirectiveDecl* Decl); 308 | 309 | bool TraverseFunctionTemplateDecl(clang::FunctionTemplateDecl* Decl); 310 | 311 | bool TraverseBuiltinType(clang::BuiltinType* Type); 312 | 313 | bool TraverseMemberPointerType(clang::MemberPointerType* Type); 314 | 315 | bool TraversePointerType(clang::PointerType* Type); 316 | 317 | bool TraverseCXXNullPtrLiteralExpr(clang::CXXNullPtrLiteralExpr* Expr); 318 | 319 | bool TraverseEnumConstantDecl(clang::EnumConstantDecl* Decl); 320 | 321 | bool TraverseEnumDecl(clang::EnumDecl* Decl); 322 | 323 | bool TraverseEnumType(clang::EnumType* Type); 324 | 325 | bool TraverseIntegerLiteral(clang::IntegerLiteral* Stmt); 326 | 327 | bool TraverseDecltypeType(clang::DecltypeType* Type); 328 | 329 | bool TraverseAutoType(clang::AutoType*); 330 | 331 | bool TraverseLinkageSpecDecl(clang::LinkageSpecDecl* Decl); 332 | 333 | bool TraverseFriendDecl(clang::FriendDecl* Decl); 334 | 335 | bool TraverseParmVarDecl(clang::ParmVarDecl* Decl); 336 | 337 | bool TraverseRValueReferenceType(clang::RValueReferenceType* Type); 338 | 339 | bool TraverseLValueReferenceType(clang::LValueReferenceType* Type); 340 | 341 | bool TraverseTemplateTypeParmType(clang::TemplateTypeParmType* Type); 342 | 343 | bool TraversePackExpansionType(clang::PackExpansionType* Type); 344 | 345 | bool TraversePackExpansionExpr(clang::PackExpansionExpr* expr); 346 | 347 | bool TraverseTemplateTypeParmDecl(clang::TemplateTypeParmDecl* Decl); 348 | 349 | bool TraverseNonTypeTemplateParmDecl(clang::NonTypeTemplateParmDecl* Decl); 350 | 351 | bool TraverseDeclStmt(clang::DeclStmt* Stmt); 352 | 353 | bool TraverseNamespaceAliasDecl(clang::NamespaceAliasDecl* Decl); 354 | 355 | bool TraverseReturnStmt(clang::ReturnStmt* Stmt); 356 | 357 | bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr* Stmt); 358 | 359 | bool TraverseExprWithCleanups(clang::ExprWithCleanups* Stmt); 360 | 361 | bool TraverseArraySubscriptExpr(clang::ArraySubscriptExpr* Expr); 362 | 363 | bool TraverseFloatingLiteral(clang::FloatingLiteral* Expr); 364 | 365 | bool TraverseForStmt(clang::ForStmt* Stmt); 366 | 367 | bool TraverseWhileStmt(clang::WhileStmt* Stmt); 368 | 369 | bool TraverseIfStmt(clang::IfStmt* Stmt); 370 | 371 | bool TraverseCXXBindTemporaryExpr(clang::CXXBindTemporaryExpr* Stmt); 372 | 373 | bool TraverseCXXThrowExpr(clang::CXXThrowExpr* Stmt); 374 | 375 | bool TraverseMaterializeTemporaryExpr(clang::MaterializeTemporaryExpr* Stmt); 376 | 377 | bool TraverseCXXFunctionalCastExpr(clang::CXXFunctionalCastExpr* Stmt); 378 | 379 | bool TraverseParenType(clang::ParenType* Type); 380 | 381 | bool TraverseFunctionProtoType(clang::FunctionProtoType* Type); 382 | 383 | bool TraverseCXXTemporaryObjectExpr(clang::CXXTemporaryObjectExpr* Stmt); 384 | 385 | bool TraverseNullStmt(clang::NullStmt* Stmt); 386 | 387 | bool TraverseCharacterLiteral(clang::CharacterLiteral* Stmt); 388 | 389 | bool TraverseStringLiteral(clang::StringLiteral* Stmt); 390 | 391 | bool TraverseCXXBoolLiteralExpr(clang::CXXBoolLiteralExpr* Stmt); 392 | 393 | bool TraverseUnaryExprOrTypeTraitExpr(clang::UnaryExprOrTypeTraitExpr* Expr); 394 | 395 | bool TraverseEmptyDecl(clang::EmptyDecl* Decl); 396 | 397 | bool TraverseLambdaExpr(clang::LambdaExpr* S); 398 | 399 | bool TraverseCallExpr(clang::CallExpr* Stmt); 400 | 401 | bool TraverseImplicitCastExpr(clang::ImplicitCastExpr* Stmt); 402 | 403 | bool TraverseCXXThisExpr(clang::CXXThisExpr* expr); 404 | 405 | bool TraverseCXXDependentScopeMemberExpr(clang::CXXDependentScopeMemberExpr* expr); 406 | 407 | bool TraverseMemberExpr(clang::MemberExpr* Stmt); 408 | 409 | bool TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr* Stmt); 410 | 411 | bool TraverseCXXStaticCastExpr(clang::CXXStaticCastExpr* Stmt); 412 | 413 | bool TraverseCStyleCastExpr(clang::CStyleCastExpr* Stmt); 414 | 415 | bool TraverseConditionalOperator(clang::ConditionalOperator* op); 416 | 417 | bool TraverseCompoundAssignOperator(clang::CompoundAssignOperator* op); 418 | 419 | bool TraverseBinAddAssign(clang::CompoundAssignOperator* expr); 420 | 421 | #define OPERATOR(NAME) bool TraverseBin##NAME##Assign(clang::CompoundAssignOperator *S); 422 | OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Sub) 423 | OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) 424 | #undef OPERATOR 425 | 426 | bool TraverseSubstNonTypeTemplateParmExpr(clang::SubstNonTypeTemplateParmExpr* Expr); 427 | 428 | bool TraverseBinaryOperator(clang::BinaryOperator* Stmt); 429 | 430 | bool TraverseBinAdd(clang::BinaryOperator* expr); 431 | 432 | #define OPERATOR(NAME) bool TraverseBin##NAME(clang::BinaryOperator* Stmt); 433 | OPERATOR(PtrMemD) OPERATOR(PtrMemI) OPERATOR(Mul) OPERATOR(Div) 434 | OPERATOR(Rem) OPERATOR(Sub) OPERATOR(Shl) OPERATOR(Shr) 435 | OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) OPERATOR(GE) OPERATOR(EQ) 436 | OPERATOR(NE) OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) OPERATOR(LAnd) 437 | OPERATOR(LOr) OPERATOR(Assign) OPERATOR(Comma) 438 | #undef OPERATOR 439 | 440 | bool TraverseUnaryOperator(clang::UnaryOperator* Stmt); 441 | 442 | #define OPERATOR(NAME) bool TraverseUnary##NAME(clang::UnaryOperator* Stmt); 443 | OPERATOR(PostInc) OPERATOR(PostDec) OPERATOR(PreInc) OPERATOR(PreDec) 444 | OPERATOR(AddrOf) OPERATOR(Deref) OPERATOR(Plus) OPERATOR(Minus) 445 | OPERATOR(Not) OPERATOR(LNot) OPERATOR(Real) OPERATOR(Imag) 446 | OPERATOR(Extension) OPERATOR(Coawait) 447 | #undef OPERATOR 448 | 449 | bool TraverseDeclRefExpr(clang::DeclRefExpr* Expr); 450 | 451 | bool TraverseDependentScopeDeclRefExpr(clang::DependentScopeDeclRefExpr* expr); 452 | 453 | bool TraverseRecordType(clang::RecordType* Type); 454 | 455 | bool TraverseConstantArrayType(clang::ConstantArrayType* Type); 456 | 457 | bool TraverseIncompleteArrayType(clang::IncompleteArrayType* Type); 458 | 459 | bool TraverseDependentSizedArrayType(clang::DependentSizedArrayType* Type); 460 | 461 | bool TraverseInitListExpr(clang::InitListExpr* Expr); 462 | 463 | bool TraverseParenExpr(clang::ParenExpr* expr); 464 | 465 | bool TraverseImplicitValueInitExpr(clang::ImplicitValueInitExpr* expr); 466 | 467 | bool TraverseParenListExpr(clang::ParenListExpr* Expr); 468 | 469 | bool TraverseCXXScalarValueInitExpr(clang::CXXScalarValueInitExpr* Expr); 470 | 471 | bool TraverseUnresolvedMemberExpr(clang::UnresolvedMemberExpr* Expr); 472 | 473 | bool TraverseVarDecl(clang::VarDecl* Decl); 474 | 475 | bool TraverseIndirectFieldDecl(clang::IndirectFieldDecl*); 476 | 477 | bool VisitDecl(clang::Decl* Decl); 478 | 479 | bool VisitStmt(clang::Stmt* Stmt); 480 | 481 | bool VisitType(clang::Type* Type); 482 | 483 | std::set dontTakePtr; //!< Avoid to take pointer when implicit FunctionToPointerDecay 484 | 485 | private: 486 | //! Add the import of for this file if it was included in the C++ file 487 | void includeFile(std::string const& inclFile, std::string const& typeName); 488 | 489 | //! Print the context (namespace, class, function) to **D** 490 | void printDeclContext(clang::DeclContext* DC); 491 | 492 | //! Get type name and transform it for **D** printing 493 | std::string printDeclName(clang::NamedDecl* decl); 494 | 495 | //! Print the comment preceding this clang::Decl 496 | void printCommentBefore(clang::Decl* t); 497 | 498 | //! Print the comment after this clang::Decl 499 | void printCommentAfter(clang::Decl* t); 500 | 501 | //! Trim from begin and end 502 | static std::string trim(std::string const& s); 503 | 504 | static std::vector split_lines(std::string const& instr); 505 | 506 | //! Print comment before a clang::Stmt 507 | bool printStmtComment( 508 | clang::SourceLocation& locStart, //!< IN/OUT Comment start (Will become nextStart) 509 | clang::SourceLocation const& locEnd, //!< Comment end (Stmt start) 510 | clang::SourceLocation const& nextStart = clang::SourceLocation(), //!< Stmt end 511 | bool doIndent = false //!< Add indentation before each new line 512 | ); 513 | 514 | //! Call a custom type printer for this type if it exist 515 | //! @return true if a custom printer was called 516 | bool customTypePrinter(clang::NamedDecl* decl); 517 | 518 | //! @brief Print to **D**, arguments of a **cpp2d_dummy_variadic** function call 519 | //! @see https://github.com/lhamot/CPP2D/wiki/Macro-migration 520 | void printMacroArgs(clang::CallExpr* macroArgs //!< Argument of the **cpp2d_dummy_variadic** 521 | ); 522 | 523 | //! @brief Print a "stmt-style" macro 524 | //! @see https://github.com/lhamot/CPP2D/wiki/Macro-migration 525 | void printStmtMacro( 526 | std::string const& varName, //!< CPP2D_MACRO_STMT or CPP2D_MACRO_STMT_END 527 | clang::Expr* init //!< Initialisation of the CPP2D_MACRO_STMT object 528 | ); 529 | 530 | //! Info about the relation between two type 531 | struct RelationInfo 532 | { 533 | bool hasOpEqual = false; //!< If ```a == b``` is valid 534 | bool hasOpLess = false; //!< If ```a < b``` is valid 535 | }; 536 | //! Info about a type 537 | struct ClassInfo 538 | { 539 | std::unordered_map relations; //!< Relation with other types 540 | bool hasOpExclaim = false; //!< If ```!a``` is valid 541 | bool hasBoolConv = false; //!< If has an operator ```operator bool()``` 542 | }; 543 | //!< Using Custom matchers and custom printer (in MatchContainer) decide to custom print or not 544 | bool passDecl(clang::Decl* decl); 545 | //!< Using Custom matchers and custom printer (in MatchContainer) decide to custom print or not 546 | bool passStmt(clang::Stmt* stmt); 547 | //!< Using Custom matchers and custom printer (in MatchContainer) decide to custom print or not 548 | bool passType(clang::Type* type); 549 | 550 | std::set includesInFile; //!< All includes find in the C++ file 551 | std::map > externIncludes; //!< import to do in **D** 552 | std::string modulename; //!< Name of the C++ module 553 | 554 | MatchContainer const& receiver; //!< Custom matchers and custom printers 555 | size_t indent = 0; //!< Indentation level 556 | clang::ASTContext* Context; 557 | size_t isInMacro = 0; //!< Disable printing if inside a macro expantion 558 | 559 | std::map > templateArgsStack; //!< Template argument names 560 | std::unordered_map renamedIdentifiers; //!< Avoid name collision 561 | std::unordered_map classInfoMap; //!< Info about all clang::CXXRecordDecl 562 | bool renameIdentifiers = true; //!< Use renamedIdentifiers ? 563 | bool refAccepted = false; //!< If we are in a **D** place where we can use **ref** 564 | bool inFuncParams = false; //!< We are printing function parameters 565 | bool inForRangeInit = false; //!< If in for-range-base-loop initialization 566 | bool doPrintType = true; //!< Do not re-print type in if multi-decl one line 567 | bool splitMultiLineDecl = true; //!< If split multi line declaration is needed. False in for init. 568 | bool portConst = false; //!< True to port **const** keyword. 569 | bool printDefaultValue = true; 570 | bool isThisFunctionUsefull = false; //!< To keep usefull implicit function 571 | bool inTemplateParamList = false; 572 | std::stack catchedExceptNames; 573 | static clang::PrintingPolicy printingPolicy; //!< Policy for print to C++ (sometimes useful) 574 | }; 575 | -------------------------------------------------------------------------------- /CPP2D_UT_CPP/test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) 2016 Loïc HAMOT 3 | // 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 | // 7 | #include "test.h" 8 | #include "framework.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | class noncopyable 22 | { 23 | noncopyable(noncopyable const&); 24 | noncopyable& operator=(noncopyable const&); 25 | public: 26 | noncopyable() = default; 27 | }; 28 | 29 | class Tata : noncopyable 30 | { 31 | virtual int funcA2() = 0; 32 | 33 | public: 34 | virtual ~Tata() = default; 35 | virtual int funcV() 36 | { 37 | return 1; 38 | } 39 | 40 | int funcF() 41 | { 42 | return 1; 43 | } 44 | 45 | virtual int funcA() = 0; 46 | }; 47 | 48 | class Tata2 : public Tata 49 | { 50 | public: 51 | int value; 52 | 53 | Tata2(int arg = 13) 54 | { 55 | value = arg; 56 | } 57 | 58 | int funcV() override 59 | { 60 | return 2; 61 | } 62 | 63 | int funcF(int i = 0) 64 | { 65 | return 2; 66 | } 67 | 68 | int funcA() override 69 | { 70 | return 4; 71 | } 72 | 73 | int funcA2() override 74 | { 75 | return 5; 76 | } 77 | 78 | Tata2* getThis() 79 | { 80 | return this; 81 | } 82 | 83 | Tata2& getThisRef() 84 | { 85 | return *this; 86 | } 87 | }; 88 | 89 | template 90 | class TmplClass1 91 | { 92 | public: 93 | static int const value = I; 94 | }; 95 | 96 | template 97 | class TmplClass2 : public TmplClass1 {}; 98 | 99 | template<> 100 | class TmplClass2<0> : public TmplClass1<42> {}; 101 | 102 | template 103 | bool fl_equal(T1 v1, T2 v2) 104 | { 105 | int argc = 2; 106 | auto diff = ((v1 - v2) + argc) - argc; 107 | return (diff < 0. ? -diff : diff) < 0.00001; 108 | } 109 | 110 | void check_operators() 111 | { 112 | //**************************** operators ********************************** 113 | // Math 114 | CHECK(45 == 45); 115 | CHECK(11 != 88); 116 | CHECK(3 + 2 == 5); 117 | CHECK(3 - 2 == 1); 118 | CHECK(3 * 2 == 6); 119 | CHECK(6 / 2 == 3); 120 | 121 | int u = 0; 122 | u += 2; 123 | CHECK(u == 2); 124 | u -= 1; 125 | CHECK(u == 1); 126 | u *= 6; 127 | CHECK(u == 6); 128 | u /= 3; 129 | CHECK(u == 2); 130 | 131 | // Bin 132 | CHECK(true && true); 133 | CHECK(true || false); 134 | 135 | // bitwise 136 | CHECK((0x3 & 0x1) == 0x1); 137 | CHECK((0x3 | 0x1) == 0x3); 138 | CHECK((0x3 ^ 0x1) == 0x2); 139 | } 140 | 141 | int func0() { return 3; } 142 | 143 | int func10(int i = 42) { return i; } 144 | 145 | void func12(int& i, int u) { i = 42; u = 43; } 146 | 147 | int z = 45; 148 | 149 | int& func15() { return z; } 150 | 151 | const int& func16() { return z; } 152 | 153 | void check_function() 154 | { 155 | //*********************** Functions *************************************** 156 | CHECK(func0() == 3); 157 | 158 | CHECK(func10(7) == 7); 159 | 160 | CHECK(func10() == 42); 161 | 162 | int a = 0, b = 0; 163 | func12(a, b); 164 | CHECK(a == 42 && b == 0); 165 | 166 | func15() = 98; 167 | CHECK(z == 98); 168 | CHECK(&func15() == &z); 169 | } 170 | 171 | void check_static_array() 172 | { 173 | int tab[3] = { 1, 2, 3 }; 174 | tab[1] = 42; 175 | CHECK(tab[1] == 42); 176 | CHECK(tab[2] == 3); 177 | 178 | int tab3[] = { 4, 5, 6, 7 }; 179 | CHECK(sizeof(tab3) == 4 * sizeof(int)); 180 | 181 | char const* tabStr[] = {"aa", "bb", "cc"}; 182 | CHECK(sizeof(tabStr) == 3 * sizeof(char const*)); 183 | 184 | int tabA[3] = { 1, 2, 3 }; 185 | int tabB[3] = { 1, 2, 3 }; 186 | CHECK(tabA != tabB); // Pointer comparison 187 | 188 | typedef int start[]; 189 | 190 | start bli = { 4, 8, 9 }; 191 | CHECK(bli[2] == 9); 192 | } 193 | 194 | //! To ensure the same function isn't print twice 195 | void check_dynamic_array(); 196 | 197 | void check_dynamic_array() 198 | { 199 | int *tab2 = new int[46]; 200 | tab2[6] = 42; 201 | CHECK(tab2[6] == 42); 202 | delete[] tab2; 203 | tab2 = nullptr; 204 | 205 | int *tabC = new int[3]; 206 | int *tabD = new int[3]; 207 | for (int i = 0; i < 3; ++i) 208 | { 209 | tabC[i] = i - 1; 210 | tabD[i] = i - 1; 211 | } 212 | CHECK(tabD != tabC); // Pointer comparison 213 | 214 | tabD = tabC; // Copy pointer 215 | tabC[1] = 78; 216 | CHECK(tabD == tabC); // Pointer comparison 217 | } 218 | 219 | struct Toto3 220 | { 221 | int a; 222 | float b; 223 | bool c; 224 | static short u; 225 | 226 | int getA() const 227 | { 228 | return a; 229 | } 230 | 231 | void setA(int a_) 232 | { 233 | a = a_; 234 | } 235 | 236 | static int getStatic() 237 | { 238 | return 12; 239 | } 240 | 241 | bool operator==(Toto3 const& other) const 242 | { 243 | return a == other.a && b == other.b && c == other.c; 244 | } 245 | 246 | //virtual void impossible(){} 247 | }; 248 | 249 | short Toto3::u = 36; 250 | 251 | struct MultiplArgsCtorStruct 252 | { 253 | int a; 254 | float b; //!< comment b 255 | bool c; 256 | MultiplArgsCtorStruct(int a_, 257 | float b_, 258 | bool c_ //!< comment c 259 | ) 260 | : a(a_) 261 | , b(b_) 262 | , c(c_) 263 | { 264 | } 265 | }; 266 | 267 | template 268 | struct Toto4 269 | { 270 | T tutu; 271 | Toto4(int a) :tutu(a, 3.3f, true) {} 272 | }; 273 | 274 | //! To ensure the same function isn't print twice 275 | extern "C" { 276 | int a_func_with_c_export(int a, int b, int c); 277 | // Blablabla 278 | } 279 | 280 | // Blablabla2 281 | int a_func_with_c_export(int a, int b, int c) 282 | { 283 | return a + b + c; 284 | } 285 | 286 | void check_struct() 287 | { 288 | //! comment Toto 289 | struct Toto 290 | { 291 | int a; 292 | float b; 293 | bool c; 294 | }; 295 | Toto toto; //defult ctor 296 | toto.a = 6; 297 | // test commment 298 | CHECK(toto.a == 6); 299 | 300 | Toto toto2 = { 7, 8.99f, true }; 301 | CHECK(toto2.a == 7 && fl_equal(toto2.b, 8.99) && toto2.c == true); 302 | 303 | //! comment Toto2 304 | struct Toto2 305 | { 306 | //! comment a 307 | int a; 308 | float b; //!< comment b 309 | bool c; 310 | Toto2(int a_, 311 | float b_, 312 | bool c_ //!< comment c 313 | ) 314 | : a(a_) 315 | , b(b_) 316 | , c(c_) 317 | { 318 | } 319 | 320 | Toto2* getThis() 321 | { 322 | return this; 323 | } 324 | 325 | Toto2& getThisRef() 326 | { 327 | return *this; 328 | } 329 | }; 330 | 331 | Toto2 toto3(18, 12.57f, true); 332 | CHECK(toto3.a == 18 && fl_equal(toto3.b, 12.57) && toto3.c == true); 333 | CHECK(toto3.getThis() == &toto3); 334 | CHECK(&toto3.getThisRef() == &toto3); 335 | 336 | Toto3 t3; 337 | t3.setA(16); 338 | CHECK(t3.getA() == 16); 339 | CHECK(Toto3::getStatic() == 12); 340 | 341 | Toto3 const t4 = { 16 }; 342 | CHECK(t4.getA() == 16); 343 | 344 | Toto3::u = 17; 345 | CHECK(Toto3::u == 17); 346 | 347 | t3.b = 0.00795f; 348 | Toto3 t5 = t3; 349 | CHECK(&t5 != &t3); // Pointer compatison 350 | CHECK(t5 == t3); //Content comparison 351 | 352 | Toto4 tt4(1); 353 | CHECK(tt4.tutu.b == 3.3f); 354 | 355 | struct Toto5 356 | { 357 | Toto2 tutu; 358 | Toto5(int a) :tutu(a, 3.3f, true) {} 359 | }; 360 | Toto5 tt5(1); 361 | CHECK(tt5.tutu.b == 3.3f); 362 | 363 | typedef struct {int x; } c_style_struct_dect; 364 | c_style_struct_dect i; 365 | i.x = 12; 366 | CHECK_EQUAL(i.x, 12); 367 | }; 368 | 369 | // Template type 370 | template 371 | T funcT() 372 | { 373 | return T(I); 374 | } 375 | 376 | // Template type deduction 377 | template 378 | T funcT2(T a, int mult) 379 | { 380 | return a * mult; 381 | } 382 | 383 | template 384 | struct is_same 385 | { 386 | static bool const value = false; 387 | }; 388 | 389 | template 390 | struct is_same 391 | { 392 | static bool const value = true; 393 | }; 394 | 395 | void check_template_struct_specialization() 396 | { 397 | bool b = is_same::value; 398 | CHECK(b); 399 | b = is_same::value; 400 | CHECK(!b); 401 | } 402 | 403 | void check_template_function() 404 | { 405 | auto res1 = funcT(); 406 | const bool isInt = is_same::value; 407 | CHECK(isInt); 408 | CHECK(res1 == 4); 409 | auto res2 = funcT2(3, 2); 410 | CHECK(res2 == 6); 411 | } 412 | 413 | 414 | void check_class() 415 | { 416 | Tata2* t2 = new Tata2(); 417 | CHECK(t2->funcV() == 2); 418 | CHECK(t2->funcF() == 2); 419 | CHECK(t2->funcA() == 4); 420 | CHECK(t2->funcA2() == 5); 421 | Tata* t = t2; 422 | CHECK(t->funcV() == 2); 423 | CHECK(t->funcF() == 1); 424 | CHECK(t2->getThis() == t2); 425 | CHECK(t2 == t); 426 | CHECK(&t2->getThisRef() == t2); 427 | delete t; 428 | t = nullptr; 429 | CHECK(t == nullptr); 430 | 431 | CHECK(TmplClass2<3>::value == 3); 432 | CHECK(TmplClass2<0>::value == 42); 433 | 434 | Tata2 t3; 435 | CHECK(&t3 != nullptr); 436 | CHECK(t3.value == 13); 437 | 438 | Tata2 t4(54); 439 | CHECK(&t4 != nullptr); 440 | CHECK(t4.value == 54); 441 | } 442 | 443 | template 444 | struct same_type; 445 | 446 | template 447 | struct same_type { static bool const value = true; }; 448 | 449 | template struct A { typedef T type; }; 450 | template using Type = typename A::type; 451 | 452 | void check_type_alias() 453 | { 454 | using type = int; 455 | static_assert(same_type::value, "same_type::value"); 456 | 457 | static_assert(same_type, A::type>::value, "same_type::value"); 458 | } 459 | 460 | struct HasBitField 461 | { 462 | unsigned char a : 1, b : 2, c : 3; 463 | }; 464 | 465 | struct HasBitField2 466 | { 467 | int a : 7; 468 | int b : 8; 469 | int c; 470 | }; 471 | 472 | void check_bitfield() 473 | { 474 | static_assert(sizeof(HasBitField) == 1, "sizeof(HasBitField) == 1"); 475 | static_assert(sizeof(HasBitField2) == 8, "sizeof(HasBitField2) == 8"); 476 | 477 | HasBitField bf; // = { 0, 1, 3 }; // Do not work in D 478 | bf.a = 0; 479 | bf.b = 1; 480 | bf.c = 3; 481 | CHECK(bf.a == 0 && bf.b == 1 && bf.c == 3); 482 | bf.a = 1; 483 | CHECK(bf.a == 1 && bf.b == 1 && bf.c == 3); 484 | bf.b = 2; 485 | CHECK(bf.a == 1 && bf.b == 2 && bf.c == 3); 486 | bf.c = 2; 487 | CHECK(bf.a == 1 && bf.b == 2 && bf.c == 2); 488 | } 489 | 490 | int decayed_type_func(int a[2], int b[], int(c)(int)) 491 | { 492 | return c(a[0] + a[1] + b[3]); 493 | } 494 | 495 | int mult2(int val) 496 | { 497 | return val * 2; 498 | } 499 | 500 | void check_decayed_type() 501 | { 502 | int a[2] = { 1, 2 }; 503 | int b[4] = { 0, 1, 2, 4 }; 504 | CHECK(decayed_type_func(a, b, mult2) == 14); 505 | } 506 | 507 | template struct InjectedClassNameType 508 | { 509 | public: 510 | T data = 2; 511 | InjectedClassNameType const& toto(InjectedClassNameType const* a) 512 | { 513 | return *a; 514 | } 515 | }; 516 | 517 | void check_injectedclassnametype() 518 | { 519 | InjectedClassNameType toto; 520 | InjectedClassNameType toto2; 521 | CHECK(&toto.toto(&toto2) == &toto2); 522 | } 523 | 524 | 525 | class ConvertibleClass 526 | { 527 | int a_; 528 | void meth(){} //check private non virtual method 529 | public: 530 | ConvertibleClass(int a) :a_(a) {} 531 | 532 | operator int() 533 | { 534 | return a_; 535 | } 536 | }; 537 | 538 | struct ConvertibleStruct 539 | { 540 | int a_; 541 | 542 | ConvertibleStruct(int a) :a_(a) {} 543 | 544 | operator int() 545 | { 546 | return a_; 547 | } 548 | }; 549 | 550 | void check_convertion_operator() 551 | { 552 | ConvertibleClass a(7); 553 | CHECK(a == 7); 554 | 555 | ConvertibleStruct b(19); 556 | CHECK(b == 19); 557 | } 558 | 559 | class AbsMethClass 560 | { 561 | public: 562 | virtual ~AbsMethClass() {}; 563 | virtual int meth() = 0; 564 | }; 565 | 566 | class AbsMethClass2 : public AbsMethClass 567 | { 568 | int meth() 569 | { 570 | return 12; 571 | } 572 | }; 573 | 574 | void check_abstract_keyword() 575 | { 576 | AbsMethClass* a = new AbsMethClass2(); 577 | CHECK(a->meth() == 12); 578 | delete a; 579 | } 580 | 581 | 582 | void check_struct_opassign() 583 | { 584 | struct S 585 | { 586 | int a; 587 | int b; 588 | 589 | S& operator = (S const& other) 590 | { 591 | a = other.a; 592 | return *this; 593 | } 594 | }; 595 | 596 | S a = { 1, 2 }; 597 | S const b = { 3, 4 }; 598 | a = b; 599 | CHECK(a.a == 3 && a.b == 2); 600 | } 601 | 602 | void check_class_opassign() 603 | { 604 | class S 605 | { 606 | public: 607 | int a; 608 | int b; 609 | S(int a_, int b_) :a(a_), b(b_) {} 610 | 611 | S& operator = (int c) 612 | { 613 | a = c; 614 | return *this; 615 | } 616 | }; 617 | 618 | S a(1, 2); 619 | a = 59; 620 | CHECK(a.a == 59 && a.b == 2); 621 | 622 | S *c = new S(1, 2); 623 | *c = 47; 624 | CHECK(c->a == 47); 625 | CHECK(c->b == 2); 626 | delete c; 627 | } 628 | 629 | 630 | template 631 | bool is_int() 632 | { 633 | return false; 634 | } 635 | 636 | template<> 637 | bool is_int() 638 | { 639 | return true; 640 | } 641 | 642 | template 643 | bool is_float(); 644 | 645 | template 646 | bool is_float() 647 | { 648 | return false; 649 | } 650 | 651 | template<> 652 | bool is_float(); 653 | 654 | template<> 655 | bool is_float() 656 | { 657 | return true; 658 | } 659 | 660 | void check_tmpl_func_spec() 661 | { 662 | struct Blip {}; 663 | CHECK(is_int() == false); 664 | CHECK(is_int() == true); 665 | CHECK(is_float() == true); 666 | } 667 | 668 | void var_func(char* buffer, const char* fmt, ...) 669 | { 670 | //! TODO : Waiting for macro handling 671 | /*va_list args; 672 | va_start(args, fmt); 673 | 674 | while (*fmt != '\0') { 675 | if (*fmt == 'd') { 676 | int i = va_arg(args, int); 677 | buffer += sprintf(buffer, "%d ", i); 678 | } 679 | else if (*fmt == 'c') { 680 | // note automatic conversion to integral type 681 | int c = va_arg(args, int); 682 | buffer += sprintf(buffer, "%c ", c); 683 | } 684 | else if (*fmt == 'f') { 685 | double d = va_arg(args, double); 686 | buffer += sprintf(buffer, "%f ", d); 687 | } 688 | ++fmt; 689 | } 690 | 691 | va_end(args);*/ 692 | return; 693 | } 694 | 695 | 696 | void check_variadic() 697 | { 698 | char buffer[1000]; 699 | var_func(buffer, "dcff", 3, 'a', 1.999, 42.5); 700 | } 701 | 702 | template 703 | struct TmplMethstruct2 704 | { 705 | int a; 706 | }; 707 | 708 | 709 | template 710 | struct TmplMethstruct 711 | { 712 | int a = I; 713 | 714 | TmplMethstruct() = default; 715 | 716 | template 717 | TmplMethstruct(TmplMethstruct const&) : a(I2) {} 718 | 719 | template 720 | operator TmplMethstruct2() 721 | { 722 | TmplMethstruct2 bli = {a}; 723 | return bli; 724 | } 725 | 726 | template 727 | TmplMethstruct& operator = (TmplMethstruct const& ot) 728 | { 729 | a = ot.a; 730 | return *this; 731 | } 732 | 733 | template 734 | TmplMethstruct operator - (TmplMethstruct const& ot) 735 | { 736 | TmplMethstruct res; 737 | res.a = a - ot.a; 738 | return res; 739 | } 740 | 741 | template 742 | bool operator < (TmplMethstruct const& ot) 743 | { 744 | return a < ot.a; 745 | } 746 | 747 | }; 748 | 749 | void check_tmpl_meth() 750 | { 751 | TmplMethstruct<4> a; 752 | TmplMethstruct<7> b(a); 753 | CHECK(a.a == 4); //default ctor 754 | CHECK(b.a == 4); //copy ctor 755 | b.a = 56; 756 | b = a; // copy operator 757 | CHECK(b.a == 4); 758 | b.a = 56; 759 | 760 | TmplMethstruct2<78> c = b; //cast operator 761 | CHECK(c.a == 56); 762 | 763 | auto d = b - a; 764 | CHECK(d.a == 52); // binary operator 765 | 766 | //CHECK(a < d); // comparison 767 | } 768 | 769 | int tata(short a) { return a * 2; } 770 | 771 | int toto(short a) { return a * 4; } 772 | 773 | void check_function_pointer() 774 | { 775 | int(*a)(short) = tata; 776 | int(*b)(short) = toto; 777 | CHECK(a != b); 778 | CHECK(2 * a(2) == b(2)); 779 | a = b; 780 | CHECK(a == b); 781 | } 782 | 783 | 784 | void check_method_pointer() 785 | { 786 | struct MethPointerStruct 787 | { 788 | int tata(short a) { return a * 2; } 789 | int toto(short a) { return a * 2; } 790 | }; 791 | /*MethPointerStruct toto; 792 | int (MethPointerStruct::*a)(short) = &MethPointerStruct::tata; 793 | int (MethPointerStruct::*b)(short) = &MethPointerStruct::toto; 794 | CHECK(a != b); 795 | CHECK((toto.*a)(2) == (toto.*b)(2)); 796 | a = b; 797 | CHECK(a == b); 798 | */ 799 | return; 800 | } 801 | 802 | 803 | void check_member_pointer() 804 | { 805 | struct MemPointerStruct 806 | { 807 | int a = 1; 808 | int b = 2; 809 | } instance; 810 | 811 | /*int MemPointerStruct::* i = &MemPointerStruct::a; 812 | int MemPointerStruct::* j = &MemPointerStruct::b; 813 | CHECK(i != j); 814 | 815 | j = &MemPointerStruct::b; 816 | CHECK((instance.*i) == 1); 817 | CHECK((instance.*j) == 2); 818 | i = j; 819 | CHECK(i == j); 820 | CHECK((instance.*i) == 2);*/ 821 | return; 822 | } 823 | 824 | enum Empty {}; 825 | 826 | struct FriendStruct1; 827 | struct FriendStruct2 828 | { 829 | friend FriendStruct1; 830 | }; 831 | struct FriendStruct1 832 | { 833 | friend FriendStruct2; 834 | }; 835 | 836 | 837 | struct CheckUDAArg 838 | { 839 | typedef int A; 840 | static int const a = 42; 841 | }; 842 | 843 | template 844 | struct CheckUDA 845 | { 846 | typedef typename T::A T_A; 847 | T_A a = T::a; 848 | T_A func(T_A a = T::a) 849 | { 850 | return a; 851 | }; 852 | }; 853 | 854 | void check_uninstantiated_default_arg() 855 | { 856 | CheckUDA a; 857 | CHECK(a.a == 42); 858 | CHECK(a.func() == 42); 859 | } 860 | 861 | void check_class_instantiation() 862 | { 863 | class StackClass 864 | { 865 | public: 866 | int a; 867 | 868 | StackClass(int a_ = 0) : a(a_) {} 869 | }; 870 | StackClass a; 871 | StackClass b(1); 872 | StackClass c = 2; 873 | 874 | StackClass *d = new StackClass; 875 | StackClass *e = new StackClass(1); 876 | CHECK(d->a != e->a); 877 | CHECK(d != e); 878 | delete d; 879 | 880 | d = e; 881 | CHECK(d == e); 882 | delete e; 883 | } 884 | 885 | typedef int incomp_arr[]; 886 | int func_incomp_arr(incomp_arr arr) 887 | { 888 | return arr[3]; 889 | } 890 | 891 | void check_incomplete_array_type() 892 | { 893 | int toto[] = { 0, 1, 2, 3 }; 894 | CHECK(func_incomp_arr(toto) == 3); 895 | } 896 | 897 | 898 | template 899 | struct UninstantiatedStruct 900 | { 901 | template 902 | typename T::A func(typename I::B a) 903 | { 904 | typename I::C c; 905 | typename I::D d; 906 | return c + d.z - I::C::y; 907 | } 908 | }; 909 | 910 | void check_builtin_macro() 911 | { 912 | auto l = __LINE__; 913 | CHECK(strstr(__FILE__, "test") != nullptr); 914 | CHECK(strstr(__FUNCTION__, "check_builtin_macro") != nullptr); 915 | CHECK(strstr(__func__, "check_builtin_macro") != nullptr); 916 | CHECK(__LINE__ == l + 4); 917 | assert(2 * 3 == 6); 918 | } 919 | 920 | void check_incr_pointer() 921 | { 922 | size_t const SIZE = 10; 923 | int tab[SIZE]; 924 | int val = 0; 925 | for (int* ptr = tab; ptr != tab + 10; ++ptr, ++val) // preincr 926 | *ptr = val; 927 | int* ptr = tab; 928 | ptr++; //postincr 929 | ptr += 2; // += 930 | int* ptr2 = ptr + 2; //+ 931 | CHECK(*ptr2 == 5); 932 | } 933 | 934 | template 935 | auto comma4(A const& a, B const& b, C const& c, D const& d) 936 | { 937 | return d; 938 | } 939 | 940 | #define UT_MACRO(expr1, expr2, expr3) \ 941 | comma4(var##expr1 = 42, var2 = #expr2, var3 = expr3, expr1 + expr3) 942 | 943 | #define UT_MACRO_STMT \ 944 | int a = 1; \ 945 | int b = 2; 946 | 947 | #define UT_MACRO_STMT_CLASS(P, T, N, V) P: T N = V; 948 | 949 | class MacroClass 950 | { 951 | UT_MACRO_STMT_CLASS(public, int, a, 1); 952 | UT_MACRO_STMT_CLASS(public, int, b, 2); 953 | }; 954 | 955 | template 956 | struct MPInt {}; 957 | 958 | int forward(int i) 959 | { 960 | return i; 961 | } 962 | 963 | #define UT_MACRO_EXPR(A, B) A + B 964 | 965 | void check_function_macro() 966 | { 967 | int var1(0); 968 | char const* var2 = nullptr; 969 | int var3 = 0; 970 | int var4(UT_MACRO(1, 2, 3)); 971 | 972 | CHECK(var1 == 42); 973 | CHECK(var2[0] == '2'); 974 | CHECK(var3 == 3); 975 | CHECK(var4 == 4); 976 | 977 | UT_MACRO_STMT 978 | 979 | CHECK(a == 1 && b == 2); 980 | 981 | MacroClass* m = new MacroClass(); 982 | CHECK(m->a == 1 && m->b == 2); 983 | delete m; 984 | 985 | CHECK(forward(UT_MACRO_EXPR(4, 3)) == 7); 986 | } 987 | 988 | void check_range_based_for_loop() 989 | { 990 | int tab[] = { 1, 2, 3 }; 991 | int sum = 0; 992 | for (int i : tab) 993 | sum += i; 994 | CHECK(sum == 6); 995 | 996 | sum = 0; 997 | for (auto i : tab) 998 | sum += i; 999 | CHECK(sum == 6); 1000 | 1001 | for (int& i : tab) 1002 | i = i + 1; 1003 | CHECK_EQUAL(tab[0], 2); 1004 | CHECK_EQUAL(tab[1], 3); 1005 | CHECK_EQUAL(tab[2], 4); 1006 | 1007 | for (auto& i : tab) 1008 | i = i + 1; 1009 | CHECK(tab[0] == 3 && tab[1] == 4 && tab[2] == 5); 1010 | 1011 | int ctab[] = { 1, 2, 3 }; 1012 | sum = 0; 1013 | for (auto const& i : ctab) 1014 | sum += i; 1015 | CHECK(sum == 6); 1016 | 1017 | } 1018 | 1019 | struct OverloadOpStuct2 1020 | { 1021 | int value; 1022 | }; 1023 | 1024 | struct OverloadOpStuct 1025 | { 1026 | int value = 0; 1027 | 1028 | explicit OverloadOpStuct(int v) : value(v) {}; 1029 | 1030 | // Unary operators 1031 | OverloadOpStuct operator -() const { return OverloadOpStuct(-value); } 1032 | OverloadOpStuct operator +() const { return OverloadOpStuct(+value); } 1033 | OverloadOpStuct operator *() const { return OverloadOpStuct(value * value); } 1034 | OverloadOpStuct& operator ++() 1035 | { 1036 | ++value; 1037 | return *this; 1038 | } 1039 | OverloadOpStuct& operator --() 1040 | { 1041 | --value; 1042 | return *this; 1043 | } 1044 | OverloadOpStuct operator ++(int) 1045 | { 1046 | OverloadOpStuct tmp(*this); 1047 | ++(*this); 1048 | return tmp; 1049 | } 1050 | OverloadOpStuct operator --(int) 1051 | { 1052 | OverloadOpStuct tmp(*this); 1053 | --(*this); 1054 | return tmp; 1055 | } 1056 | 1057 | // Cast operator 1058 | operator int() const {return 42;} 1059 | 1060 | //*************** Binary operators ************************************************************ 1061 | 1062 | // Arithmetic operators 1063 | 1064 | OverloadOpStuct& operator += (OverloadOpStuct const& other) 1065 | { 1066 | value += other.value; 1067 | return *this; 1068 | } 1069 | 1070 | OverloadOpStuct operator + (OverloadOpStuct const& other) const 1071 | { 1072 | OverloadOpStuct tmp(*this); 1073 | return tmp += other; 1074 | } 1075 | 1076 | OverloadOpStuct& operator -= (OverloadOpStuct const& other) 1077 | { 1078 | value -= other.value; 1079 | return *this; 1080 | } 1081 | 1082 | OverloadOpStuct operator - (OverloadOpStuct const& other) const 1083 | { 1084 | OverloadOpStuct tmp(*this); 1085 | return tmp -= other; 1086 | } 1087 | 1088 | OverloadOpStuct& operator *= (OverloadOpStuct const& other) 1089 | { 1090 | value *= other.value; 1091 | return *this; 1092 | } 1093 | 1094 | OverloadOpStuct operator * (OverloadOpStuct const& other) const 1095 | { 1096 | OverloadOpStuct tmp(*this); 1097 | return tmp *= other; 1098 | } 1099 | 1100 | OverloadOpStuct& operator /= (OverloadOpStuct const& other) 1101 | { 1102 | value /= other.value; 1103 | return *this; 1104 | } 1105 | 1106 | OverloadOpStuct operator / (OverloadOpStuct const& other) const 1107 | { 1108 | OverloadOpStuct tmp(*this); 1109 | return tmp /= other; 1110 | } 1111 | 1112 | // relational operators 1113 | 1114 | bool operator == (OverloadOpStuct const& other) const 1115 | { 1116 | return value == other.value; 1117 | } 1118 | 1119 | bool operator != (OverloadOpStuct const& other) const 1120 | { 1121 | return !(*this == other); 1122 | } 1123 | 1124 | bool operator < (OverloadOpStuct const& other) const 1125 | { 1126 | return (this->value < other.value); 1127 | } 1128 | 1129 | bool operator > (OverloadOpStuct const& other) const 1130 | { 1131 | return (this->value > other.value); 1132 | } 1133 | 1134 | bool operator <= (OverloadOpStuct const& other) const 1135 | { 1136 | return (*this < other) || (*this == other); 1137 | } 1138 | 1139 | bool operator >= (OverloadOpStuct const& other) const 1140 | { 1141 | return (this->value >= other.value); 1142 | } 1143 | 1144 | // asymetric relational operators 1145 | bool operator == (OverloadOpStuct2 const& other) const 1146 | { 1147 | return value == other.value; 1148 | } 1149 | 1150 | bool operator != (OverloadOpStuct2 const& other) const 1151 | { 1152 | return !(*this == other); 1153 | } 1154 | 1155 | bool operator < (OverloadOpStuct2 const& other) const 1156 | { 1157 | return (this->value < other.value); 1158 | } 1159 | 1160 | bool operator > (OverloadOpStuct2 const& other) const 1161 | { 1162 | return (this->value > other.value); 1163 | } 1164 | 1165 | bool operator <= (OverloadOpStuct2 const& other) const 1166 | { 1167 | return (*this < other) || (*this == other); 1168 | } 1169 | 1170 | bool operator >= (OverloadOpStuct2 const& other) const 1171 | { 1172 | return (this->value >= other.value); 1173 | } 1174 | 1175 | //************************ logical operators ************************************************** 1176 | bool operator ! () const 1177 | { 1178 | return this->value == 0; 1179 | } 1180 | 1181 | bool operator && (OverloadOpStuct const& other) const 1182 | { 1183 | return (!!*this) && (!!other); 1184 | } 1185 | 1186 | bool operator || (OverloadOpStuct const& other) const 1187 | { 1188 | return (!!*this) || (!!other); 1189 | } 1190 | 1191 | //************************ Bitwise operators ************************************************** 1192 | OverloadOpStuct operator ~ () const 1193 | { 1194 | return OverloadOpStuct(~(this->value)); 1195 | } 1196 | 1197 | OverloadOpStuct operator & (OverloadOpStuct const& other) const 1198 | { 1199 | return OverloadOpStuct(this->value & other.value); 1200 | } 1201 | 1202 | OverloadOpStuct operator | (OverloadOpStuct const& other) const 1203 | { 1204 | return OverloadOpStuct(this->value | other.value); 1205 | } 1206 | 1207 | OverloadOpStuct operator ^ (OverloadOpStuct const& other) const 1208 | { 1209 | return OverloadOpStuct(this->value ^ other.value); 1210 | } 1211 | 1212 | OverloadOpStuct operator << (int count) const 1213 | { 1214 | return OverloadOpStuct(this->value << count); 1215 | } 1216 | 1217 | OverloadOpStuct operator >> (int count) const 1218 | { 1219 | return OverloadOpStuct(this->value >> count); 1220 | } 1221 | 1222 | // Member and pointer operators 1223 | int operator [] (int arg) const 1224 | { 1225 | return value + arg; 1226 | } 1227 | 1228 | int const* operator & () const 1229 | { 1230 | return &value; 1231 | } 1232 | 1233 | int* operator & () 1234 | { 1235 | return &value; 1236 | } 1237 | 1238 | OverloadOpStuct* operator -> () 1239 | { 1240 | return this; 1241 | } 1242 | 1243 | int operator()(int a, int b) 1244 | { 1245 | return a + b; 1246 | } 1247 | 1248 | int operator,(int a) 1249 | { 1250 | return a * 3; 1251 | } 1252 | }; 1253 | 1254 | void check_overloaded_operator() 1255 | { 1256 | //**************** Unary operators ********************************************************* 1257 | { 1258 | OverloadOpStuct i(18); 1259 | CHECK((-i).value == -18); 1260 | CHECK((+i).value == +18); 1261 | CHECK((~i).value == ~18); 1262 | CHECK((*i).value == 18 * 18); 1263 | // Pre incr and decr 1264 | CHECK((++i).value == 19); 1265 | CHECK(i.value == 19); 1266 | CHECK((--i).value == 18); 1267 | CHECK(i.value == 18); 1268 | // post incr and decr 1269 | CHECK((i++).value == 18); 1270 | CHECK(i.value == 19); 1271 | CHECK((i--).value == 19); 1272 | CHECK(i.value == 18); 1273 | } 1274 | 1275 | //*************************** Cast operator *************************************************** 1276 | { 1277 | OverloadOpStuct i(18); 1278 | CHECK((int)i == 42); 1279 | } 1280 | 1281 | //********************* Binary operators ****************************************************** 1282 | // Arithmetic operators 1283 | { 1284 | OverloadOpStuct a(6); 1285 | OverloadOpStuct b(3); 1286 | 1287 | OverloadOpStuct mu = a * b; 1288 | CHECK(mu.value == 18); 1289 | 1290 | OverloadOpStuct d = a / b; 1291 | CHECK(d.value == 2); 1292 | 1293 | OverloadOpStuct p = a + b; 1294 | CHECK(p.value == 9); 1295 | 1296 | OverloadOpStuct mi = a - b; 1297 | CHECK(mi.value == 3); 1298 | 1299 | mu /= b; 1300 | CHECK(mu.value == a.value); 1301 | 1302 | d *= b; 1303 | CHECK(d.value == a.value); 1304 | 1305 | p -= b; 1306 | CHECK(p.value == a.value); 1307 | 1308 | mi += b; 1309 | CHECK(mi.value == a.value); 1310 | } 1311 | 1312 | // relational operators 1313 | { 1314 | OverloadOpStuct a6(6); 1315 | OverloadOpStuct b6(6); 1316 | OverloadOpStuct c3(3); 1317 | CHECK(b6 == a6); 1318 | CHECK(b6 <= a6); 1319 | CHECK(b6 >= a6); 1320 | CHECK(c3 != a6); 1321 | CHECK(c3 < a6); 1322 | CHECK(c3 <= a6); 1323 | CHECK(a6 > c3); 1324 | CHECK(a6 >= c3); 1325 | } 1326 | 1327 | // Asymetric relational operators 1328 | { 1329 | OverloadOpStuct2 a6 = { 6 }; 1330 | OverloadOpStuct b6(6); 1331 | OverloadOpStuct c3(3); 1332 | OverloadOpStuct d9(9); 1333 | CHECK(b6 == a6); 1334 | CHECK(b6 <= a6); 1335 | CHECK(b6 >= a6); 1336 | CHECK(c3 != a6); 1337 | CHECK(c3 < a6); 1338 | CHECK(c3 <= a6); 1339 | CHECK(d9 > a6); 1340 | CHECK(d9 >= a6); 1341 | } 1342 | 1343 | // Logical operators 1344 | { 1345 | OverloadOpStuct a0(0); 1346 | OverloadOpStuct b0(0); 1347 | OverloadOpStuct c1(48); 1348 | OverloadOpStuct d1(79); 1349 | CHECK(!a0); 1350 | CHECK(!!c1); 1351 | CHECK(!(a0 && b0)); 1352 | CHECK(!(a0 && c1)); 1353 | CHECK(!(c1 && a0)); 1354 | CHECK(c1 && d1); 1355 | CHECK(!(a0 || b0)); 1356 | CHECK(a0 || c1); 1357 | CHECK(c1 || a0); 1358 | CHECK(c1 || d1); 1359 | } 1360 | 1361 | //************************ Bitwise operators ************************************************** 1362 | { 1363 | auto inv = ~decltype(OverloadOpStuct::value)(0); 1364 | OverloadOpStuct a000(0); 1365 | OverloadOpStuct a110(6); 1366 | OverloadOpStuct a011(3); 1367 | CHECK((~a000).value == inv); 1368 | CHECK((a110 & a011) == OverloadOpStuct(2)); 1369 | CHECK((a110 | a011) == OverloadOpStuct(7)); 1370 | CHECK((a110 ^ a011) == OverloadOpStuct(5)); 1371 | CHECK((a110 >> 1) == OverloadOpStuct(3)); 1372 | CHECK((a110 << 1) == OverloadOpStuct(12)); 1373 | } 1374 | 1375 | // Member and pointer operators 1376 | { 1377 | OverloadOpStuct a13(13); 1378 | CHECK(a13[7] == 20); 1379 | //CHECK(&a13 == &a13.value); 1380 | CHECK(a13->value == a13.value); 1381 | } 1382 | 1383 | //********************************* Other operators ******************************************* 1384 | { 1385 | OverloadOpStuct a13(13); 1386 | CHECK(a13(1, 2) == 3); 1387 | //CHECK((a13, 18) == (18 * 3)); //Can't overload , in D 1388 | } 1389 | } 1390 | 1391 | 1392 | struct ExtOverloadOpStuct 1393 | { 1394 | int value = 0; 1395 | 1396 | explicit ExtOverloadOpStuct(int v) : value(v) {}; 1397 | }; 1398 | 1399 | // Unary operators 1400 | ExtOverloadOpStuct operator -(ExtOverloadOpStuct const& self) { return ExtOverloadOpStuct(-self.value); } 1401 | ExtOverloadOpStuct operator +(ExtOverloadOpStuct const& self) { return ExtOverloadOpStuct(+self.value); } 1402 | ExtOverloadOpStuct operator *(ExtOverloadOpStuct const& self) { return ExtOverloadOpStuct(self.value * self.value); } 1403 | ExtOverloadOpStuct& operator ++(ExtOverloadOpStuct& self) 1404 | { 1405 | ++self.value; 1406 | return self; 1407 | } 1408 | ExtOverloadOpStuct& operator --(ExtOverloadOpStuct& self) 1409 | { 1410 | --self.value; 1411 | return self; 1412 | } 1413 | ExtOverloadOpStuct operator ++(ExtOverloadOpStuct& self, int) 1414 | { 1415 | ExtOverloadOpStuct tmp(self); 1416 | ++self; 1417 | return tmp; 1418 | } 1419 | ExtOverloadOpStuct operator --(ExtOverloadOpStuct& self, int) 1420 | { 1421 | ExtOverloadOpStuct tmp(self); 1422 | --self; 1423 | return tmp; 1424 | } 1425 | 1426 | //*************** Binary operators ************************************************************ 1427 | 1428 | // Arithmetic operators 1429 | 1430 | ExtOverloadOpStuct& operator += (ExtOverloadOpStuct& self, ExtOverloadOpStuct const& other) 1431 | { 1432 | self.value += other.value; 1433 | return self; 1434 | } 1435 | 1436 | ExtOverloadOpStuct operator + (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1437 | { 1438 | ExtOverloadOpStuct tmp(self); 1439 | return tmp += other; 1440 | } 1441 | 1442 | ExtOverloadOpStuct& operator -= (ExtOverloadOpStuct& self, ExtOverloadOpStuct const& other) 1443 | { 1444 | self.value -= other.value; 1445 | return self; 1446 | } 1447 | 1448 | ExtOverloadOpStuct operator - (ExtOverloadOpStuct& self, ExtOverloadOpStuct const& other) 1449 | { 1450 | ExtOverloadOpStuct tmp(self); 1451 | return tmp -= other; 1452 | } 1453 | 1454 | ExtOverloadOpStuct& operator *= (ExtOverloadOpStuct& self, ExtOverloadOpStuct const& other) 1455 | { 1456 | self.value *= other.value; 1457 | return self; 1458 | } 1459 | 1460 | ExtOverloadOpStuct operator * (ExtOverloadOpStuct& self, ExtOverloadOpStuct const& other) 1461 | { 1462 | ExtOverloadOpStuct tmp(self); 1463 | return tmp *= other; 1464 | } 1465 | 1466 | ExtOverloadOpStuct& operator /= (ExtOverloadOpStuct& self, ExtOverloadOpStuct const& other) 1467 | { 1468 | self.value /= other.value; 1469 | return self; 1470 | } 1471 | 1472 | ExtOverloadOpStuct operator / (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1473 | { 1474 | ExtOverloadOpStuct tmp(self); 1475 | return tmp /= other; 1476 | } 1477 | 1478 | // relational operators 1479 | 1480 | bool operator == (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1481 | { 1482 | return self.value == other.value; 1483 | } 1484 | 1485 | bool operator != (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1486 | { 1487 | return !(self == other); 1488 | } 1489 | 1490 | bool operator < (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1491 | { 1492 | return (self.value < other.value); 1493 | } 1494 | 1495 | bool operator > (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1496 | { 1497 | return (self.value > other.value); 1498 | } 1499 | 1500 | bool operator <= (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1501 | { 1502 | return (self < other) || (self == other); 1503 | } 1504 | 1505 | bool operator >= (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1506 | { 1507 | return (self.value >= other.value); 1508 | } 1509 | 1510 | // asymetric relational operators 1511 | bool operator == (ExtOverloadOpStuct const& self, OverloadOpStuct2 const& other) 1512 | { 1513 | return self.value == other.value; 1514 | } 1515 | 1516 | bool operator != (ExtOverloadOpStuct const& self, OverloadOpStuct2 const& other) 1517 | { 1518 | return !(self == other); 1519 | } 1520 | 1521 | bool operator < (ExtOverloadOpStuct const& self, OverloadOpStuct2 const& other) 1522 | { 1523 | return (self.value < other.value); 1524 | } 1525 | 1526 | bool operator > (ExtOverloadOpStuct const& self, OverloadOpStuct2 const& other) 1527 | { 1528 | return (self.value > other.value); 1529 | } 1530 | 1531 | bool operator <= (ExtOverloadOpStuct const& self, OverloadOpStuct2 const& other) 1532 | { 1533 | return (self < other) || (self == other); 1534 | } 1535 | 1536 | bool operator >= (ExtOverloadOpStuct const& self, OverloadOpStuct2 const& other) 1537 | { 1538 | return (self.value >= other.value); 1539 | } 1540 | 1541 | //************************ logical operators ************************************************** 1542 | bool operator ! (ExtOverloadOpStuct const& self) 1543 | { 1544 | return self.value == 0; 1545 | } 1546 | 1547 | bool operator && (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1548 | { 1549 | return (!!self) && (!!other); 1550 | } 1551 | 1552 | bool operator || (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1553 | { 1554 | return (!!self) || (!!other); 1555 | } 1556 | 1557 | //************************ Bitwise operators ************************************************** 1558 | ExtOverloadOpStuct operator ~ (ExtOverloadOpStuct const& self) 1559 | { 1560 | return ExtOverloadOpStuct(~(self.value)); 1561 | } 1562 | 1563 | ExtOverloadOpStuct operator & (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1564 | { 1565 | return ExtOverloadOpStuct(self.value & other.value); 1566 | } 1567 | 1568 | ExtOverloadOpStuct operator | (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1569 | { 1570 | return ExtOverloadOpStuct(self.value | other.value); 1571 | } 1572 | 1573 | ExtOverloadOpStuct operator ^ (ExtOverloadOpStuct const& self, ExtOverloadOpStuct const& other) 1574 | { 1575 | return ExtOverloadOpStuct(self.value ^ other.value); 1576 | } 1577 | 1578 | ExtOverloadOpStuct operator << (ExtOverloadOpStuct const& self, int count) 1579 | { 1580 | return ExtOverloadOpStuct(self.value << count); 1581 | } 1582 | 1583 | ExtOverloadOpStuct operator >> (ExtOverloadOpStuct const& self, int count) 1584 | { 1585 | return ExtOverloadOpStuct(self.value >> count); 1586 | } 1587 | 1588 | // Member and pointer operators 1589 | 1590 | int const* operator & (ExtOverloadOpStuct const& self) 1591 | { 1592 | return &self.value; 1593 | } 1594 | 1595 | int* operator & (ExtOverloadOpStuct& self) 1596 | { 1597 | return &self.value; 1598 | } 1599 | 1600 | void check_extern_overloaded_operator() 1601 | { 1602 | //**************** Unary operators ********************************************************* 1603 | { 1604 | ExtOverloadOpStuct i(18); 1605 | CHECK((-i).value == -18); 1606 | CHECK((+i).value == +18); 1607 | CHECK((~i).value == ~18); 1608 | CHECK((*i).value == 18 * 18); 1609 | // Pre incr and decr 1610 | CHECK((++i).value == 19); 1611 | CHECK(i.value == 19); 1612 | CHECK((--i).value == 18); 1613 | CHECK(i.value == 18); 1614 | // post incr and decr 1615 | CHECK((i++).value == 18); 1616 | CHECK(i.value == 19); 1617 | CHECK((i--).value == 19); 1618 | CHECK(i.value == 18); 1619 | } 1620 | 1621 | //********************* Binary operators ****************************************************** 1622 | // Arithmetic operators 1623 | { 1624 | ExtOverloadOpStuct a(6); 1625 | ExtOverloadOpStuct b(3); 1626 | 1627 | ExtOverloadOpStuct mu = a * b; 1628 | CHECK(mu.value == 18); 1629 | 1630 | ExtOverloadOpStuct d = a / b; 1631 | CHECK(d.value == 2); 1632 | 1633 | ExtOverloadOpStuct p = a + b; 1634 | CHECK(p.value == 9); 1635 | 1636 | ExtOverloadOpStuct mi = a - b; 1637 | CHECK(mi.value == 3); 1638 | 1639 | mu /= b; 1640 | CHECK(mu.value == a.value); 1641 | 1642 | d *= b; 1643 | CHECK(d.value == a.value); 1644 | 1645 | p -= b; 1646 | CHECK(p.value == a.value); 1647 | 1648 | mi += b; 1649 | CHECK(mi.value == a.value); 1650 | } 1651 | 1652 | // relational operators 1653 | { 1654 | ExtOverloadOpStuct a6(6); 1655 | ExtOverloadOpStuct b6(6); 1656 | ExtOverloadOpStuct c3(3); 1657 | CHECK(b6 == a6); 1658 | CHECK(b6 <= a6); 1659 | CHECK(b6 >= a6); 1660 | CHECK(c3 != a6); 1661 | CHECK(c3 < a6); 1662 | CHECK(c3 <= a6); 1663 | CHECK(a6 > c3); 1664 | CHECK(a6 >= c3); 1665 | } 1666 | 1667 | // Asymetric relational operators 1668 | { 1669 | OverloadOpStuct2 a6 = { 6 }; 1670 | ExtOverloadOpStuct b6(6); 1671 | ExtOverloadOpStuct c3(3); 1672 | ExtOverloadOpStuct d9(9); 1673 | CHECK(b6 == a6); 1674 | CHECK(b6 <= a6); 1675 | CHECK(b6 >= a6); 1676 | CHECK(c3 != a6); 1677 | CHECK(c3 < a6); 1678 | CHECK(c3 <= a6); 1679 | CHECK(d9 > a6); 1680 | CHECK(d9 >= a6); 1681 | } 1682 | 1683 | // Logical operators 1684 | { 1685 | ExtOverloadOpStuct a0(0); 1686 | ExtOverloadOpStuct b0(0); 1687 | ExtOverloadOpStuct c1(48); 1688 | ExtOverloadOpStuct d1(79); 1689 | CHECK(!a0); 1690 | CHECK(!!c1); 1691 | CHECK(!(a0 && b0)); 1692 | CHECK(!(a0 && c1)); 1693 | CHECK(!(c1 && a0)); 1694 | CHECK(c1 && d1); 1695 | CHECK(!(a0 || b0)); 1696 | CHECK(a0 || c1); 1697 | CHECK(c1 || a0); 1698 | CHECK(c1 || d1); 1699 | } 1700 | 1701 | //************************ Bitwise operators ************************************************** 1702 | { 1703 | auto inv = ~decltype(ExtOverloadOpStuct::value)(0); 1704 | ExtOverloadOpStuct a000(0); 1705 | ExtOverloadOpStuct a110(6); 1706 | ExtOverloadOpStuct a011(3); 1707 | CHECK((~a000).value == inv); 1708 | CHECK((a110 & a011) == ExtOverloadOpStuct(2)); 1709 | CHECK((a110 | a011) == ExtOverloadOpStuct(7)); 1710 | CHECK((a110 ^ a011) == ExtOverloadOpStuct(5)); 1711 | CHECK((a110 >> 1) == ExtOverloadOpStuct(3)); 1712 | CHECK((a110 << 1) == ExtOverloadOpStuct(12)); 1713 | } 1714 | } 1715 | 1716 | void check_lib_porting_pair() 1717 | { 1718 | std::pair toto(3, 6.66); 1719 | CHECK(toto.first == 3); 1720 | CHECK(toto.second == 6.66); 1721 | } 1722 | 1723 | 1724 | void check_union() 1725 | { 1726 | union U 1727 | { 1728 | int i; 1729 | double d; 1730 | bool b; 1731 | } u; 1732 | u.i = 45; 1733 | CHECK(u.i == 45); 1734 | u.d = 6.66; 1735 | CHECK(u.d == 6.66); 1736 | 1737 | struct Foo 1738 | { 1739 | union 1740 | { 1741 | int i; 1742 | double d; 1743 | bool b; 1744 | }; 1745 | Foo(bool b2) : b(b2) {} 1746 | 1747 | } foo(true); 1748 | CHECK(foo.b == true); 1749 | foo.i = 45; 1750 | CHECK(foo.i == 45); 1751 | foo.d = 6.66; 1752 | CHECK(foo.d == 6.66); 1753 | } 1754 | 1755 | template 1756 | auto call_func(F f, A v) //->decltype(F()) 1757 | { 1758 | return f(v); 1759 | } 1760 | 1761 | void check_lambda() 1762 | { 1763 | auto give_1 = []() {return 1; }; 1764 | CHECK(give_1() == 1); 1765 | 1766 | auto give_x = [](int x) {return x; }; 1767 | CHECK(give_x(1) == 1); 1768 | CHECK(call_func(give_x, 2) == 2); 1769 | CHECK(call_func([](int x) {return x; }, 3) == 3); 1770 | 1771 | auto give_tx = [](auto x) {return x; }; 1772 | CHECK(give_tx(1) == 1); 1773 | CHECK(call_func(give_tx, -12) == -12); 1774 | CHECK(call_func([](auto x) {return x; }, 6.66) == 6.66); 1775 | 1776 | auto to_1 = [](int& x) {x = 1; }; 1777 | int x; 1778 | to_1(x); 1779 | CHECK(x == 1); 1780 | 1781 | auto ext_to_2 = [&x]() {x = 2; }; 1782 | ext_to_2(); 1783 | CHECK(x == 2); 1784 | 1785 | auto give_x_or_y = [](bool s, int x, int y) -> int {if (s) return x; else return y; }; 1786 | CHECK(give_x(1) == 1); 1787 | 1788 | auto give_tx_plus_ty = [](auto x, auto y) {return x + y; }; 1789 | CHECK(give_tx_plus_ty(1, 3.33) == 4.33); 1790 | 1791 | auto copy_a_to_b = [](auto a, auto& b) {b = a; }; 1792 | int b = 0; 1793 | copy_a_to_b(958421, b); 1794 | CHECK_EQUAL(b, 958421); 1795 | 1796 | auto copy_42_to_b = [](auto & b) {b = 42; return 18; }; 1797 | CHECK_EQUAL(copy_42_to_b(b), 18); 1798 | CHECK_EQUAL(b, 42); 1799 | 1800 | auto set_string_to_toto = [](std::string& b) {b = "toto"; }; 1801 | std::string toto; 1802 | set_string_to_toto(toto); 1803 | CHECK_EQUAL(toto, "toto"); 1804 | } 1805 | 1806 | struct StructWithDefCtor 1807 | { 1808 | int i = 42; 1809 | }; 1810 | 1811 | struct StructWithoutDefCtor 1812 | { 1813 | int i = 42; 1814 | 1815 | StructWithoutDefCtor(int = 0) 1816 | { 1817 | i = 2; 1818 | } 1819 | }; 1820 | 1821 | void check_struct_default_ctor() 1822 | { 1823 | StructWithDefCtor foo; 1824 | CHECK(foo.i == 42); 1825 | CHECK(StructWithDefCtor().i == 42); 1826 | 1827 | StructWithoutDefCtor foo2; 1828 | CHECK(foo2.i == 2); 1829 | CHECK(StructWithoutDefCtor().i == 2); 1830 | } 1831 | 1832 | struct Struct781 1833 | { 1834 | int i = 0; 1835 | Struct781() = default; 1836 | Struct781(int u) :i(u) {}; 1837 | }; 1838 | 1839 | struct Struct782 1840 | { 1841 | Struct781 toto; 1842 | 1843 | Struct782() = default; 1844 | Struct782(int i) : toto(i) {}; 1845 | Struct782(double) {}; 1846 | }; 1847 | 1848 | int take_struct(Struct781 const& s) 1849 | { 1850 | return s.i; 1851 | } 1852 | 1853 | void check_struct_ctor_call() 1854 | { 1855 | Struct782 tutu; 1856 | CHECK(tutu.toto.i == 0); 1857 | Struct782 tutu2(5); 1858 | CHECK(tutu2.toto.i == 5); 1859 | Struct782 tutu22(5.5); 1860 | CHECK(tutu22.toto.i == 0); 1861 | Struct782 tutu3 = 6; 1862 | CHECK(tutu3.toto.i == 6); 1863 | CHECK(take_struct(Struct781(57)) == 57); 1864 | } 1865 | 1866 | class Class781 1867 | { 1868 | public: 1869 | int i = 0; 1870 | Class781() {}; 1871 | Class781(int u):i(u) {}; 1872 | }; 1873 | 1874 | class Class782 1875 | { 1876 | public: 1877 | Class781 toto; 1878 | Class781* toto2 = nullptr; 1879 | Class781* toto3; 1880 | 1881 | //Class782():toto2(new Class781()) {}; 1882 | Class782() = default; 1883 | Class782(int i) : toto(i), toto2(new Class781(i)) {}; 1884 | Class782(double) : toto2(new Class781(19)) {}; 1885 | 1886 | ~Class782() { delete toto2; } 1887 | }; 1888 | 1889 | Class781 const& take_class_(Class781 const& s) 1890 | { 1891 | return s; 1892 | } 1893 | 1894 | Class781* take_class(Class781* s) 1895 | { 1896 | return s; 1897 | } 1898 | 1899 | class CheckNoCtor 1900 | { 1901 | 1902 | }; 1903 | 1904 | class InheritCheckNoCtor : public CheckNoCtor 1905 | { 1906 | public: 1907 | InheritCheckNoCtor() :CheckNoCtor() 1908 | { 1909 | } 1910 | }; 1911 | 1912 | class CheckWithDefCtor 1913 | { 1914 | public: 1915 | CheckWithDefCtor() {} 1916 | }; 1917 | 1918 | class InheritWithDefCtor : public CheckWithDefCtor 1919 | { 1920 | public: 1921 | InheritWithDefCtor() :CheckWithDefCtor() 1922 | { 1923 | } 1924 | }; 1925 | 1926 | class CheckWithDefDefCtor 1927 | { 1928 | public: 1929 | CheckWithDefDefCtor() {} 1930 | }; 1931 | 1932 | class InheritWithDefDefCtor : public CheckWithDefDefCtor 1933 | { 1934 | public: 1935 | InheritWithDefDefCtor() :CheckWithDefDefCtor() 1936 | { 1937 | } 1938 | }; 1939 | 1940 | class CheckWithCtor 1941 | { 1942 | public: 1943 | int i; 1944 | CheckWithCtor(int u) 1945 | :i(u) 1946 | { 1947 | } 1948 | }; 1949 | 1950 | class InheritCheckWithCtor : public CheckWithCtor 1951 | { 1952 | public: 1953 | InheritCheckWithCtor() :CheckWithCtor(72) 1954 | { 1955 | } 1956 | }; 1957 | 1958 | void check_class_ctor_call() 1959 | { 1960 | Class782 tutu; 1961 | CHECK(tutu.toto.i == 0); 1962 | Class782 tutu2(5); 1963 | CHECK(tutu2.toto.i == 5); 1964 | Class782 tutu22(5.5); 1965 | CHECK(tutu22.toto2->i == 19); 1966 | Class782 tutu3 = 6; 1967 | CHECK(tutu3.toto.i == 6); 1968 | CHECK(take_class_(Class781(57)).i == 57); 1969 | 1970 | Class782* tutu4 = new Class782(); 1971 | CHECK(tutu4->toto.i == 0); 1972 | delete tutu4; 1973 | Class782* tutu5 = new Class782(5); 1974 | CHECK(tutu5->toto.i == 5); 1975 | delete tutu5; 1976 | CHECK(take_class_(Class781(57)).i == 57); 1977 | 1978 | Class781* tutu6 = take_class(new Class781(58)); 1979 | CHECK(tutu6->i == 58); 1980 | tutu6->~Class781(); 1981 | //::operator delete(tutu6); 1982 | 1983 | InheritCheckNoCtor* tutu7 = new InheritCheckNoCtor; 1984 | CheckNoCtor* tutu8 = tutu7; 1985 | CHECK(tutu8 != nullptr); 1986 | 1987 | InheritCheckWithCtor* tutu9 = new InheritCheckWithCtor; 1988 | CheckWithCtor* tutu10 = tutu9; 1989 | CHECK(tutu10 != nullptr); 1990 | CHECK(tutu10->i == 72); 1991 | 1992 | InheritWithDefCtor* tutu11 = new InheritWithDefCtor; 1993 | CheckWithDefCtor* tutu12 = tutu11; 1994 | CHECK(tutu12 != nullptr); 1995 | 1996 | InheritWithDefDefCtor* tutu13 = new InheritWithDefDefCtor; 1997 | CheckWithDefDefCtor* tutu14 = tutu13; 1998 | CHECK(tutu14 != nullptr); 1999 | } 2000 | 2001 | void func_throw_except() 2002 | { 2003 | throw std::runtime_error("error test"); 2004 | } 2005 | /* 2006 | void func_throw_except(std::runtime_error const& ex) 2007 | { 2008 | 2009 | } 2010 | */ 2011 | void check_exception() 2012 | { 2013 | bool catched = false; 2014 | try 2015 | { 2016 | //func_throw_except(std::runtime_error("toto")); 2017 | func_throw_except(); 2018 | } 2019 | catch (std::logic_error&) 2020 | { 2021 | 2022 | } 2023 | catch (std::runtime_error& ex) 2024 | { 2025 | CHECK(strcmp(ex.what(), "error test") == 0); 2026 | catched = true; 2027 | } 2028 | catch (std::exception&) 2029 | { 2030 | 2031 | } 2032 | CHECK(catched); 2033 | } 2034 | 2035 | void check_exception2() 2036 | try 2037 | { 2038 | //func_throw_except(std::runtime_error("toto")); 2039 | func_throw_except(); 2040 | CHECK(false); 2041 | } 2042 | catch (std::logic_error&) 2043 | { 2044 | CHECK(false); 2045 | } 2046 | catch (std::runtime_error& ex) 2047 | { 2048 | CHECK(strcmp(ex.what(), "error test") == 0); 2049 | } 2050 | catch (std::exception&) 2051 | { 2052 | CHECK(false); 2053 | 2054 | } 2055 | 2056 | void check_for_loop() 2057 | { 2058 | for (int x = 0, y = 3; x != y; ++x); 2059 | size_t count = 0; 2060 | for (int i = 0; i < 3; ++i) 2061 | ++count; 2062 | CHECK(count == 3); 2063 | count = 0; 2064 | int i; 2065 | for (i = 0; i < 3; ++i) 2066 | ++count; 2067 | CHECK(count == 3); 2068 | count = 0; 2069 | for (int x = 0, y = 3; x != y; ++x) 2070 | ++count; 2071 | CHECK(count == 3); 2072 | } 2073 | 2074 | void check_while_loop() 2075 | { 2076 | int count = 3; 2077 | while (count != 0) --count; 2078 | CHECK(count == 0); 2079 | count = 3; 2080 | while (--count); 2081 | CHECK(count == 0); 2082 | } 2083 | 2084 | void check_dowhile_loop() 2085 | { 2086 | int count = 3; 2087 | do 2088 | { 2089 | --count; 2090 | } 2091 | while (count != 0); 2092 | CHECK(count == 0); 2093 | count = 3; 2094 | do 2095 | { 2096 | 2097 | } 2098 | while (--count); 2099 | CHECK(count == 0); 2100 | } 2101 | 2102 | 2103 | void check_multidecl_line() 2104 | { 2105 | int i = 2, *u = new int[18], z[12]; 2106 | CHECK(i == 2); 2107 | CHECK(sizeof(z) / sizeof(int) == 12); 2108 | z[3] = 77; 2109 | CHECK(z[3] == 77); 2110 | u[17] = 78; 2111 | CHECK(u[17] == 78); 2112 | } 2113 | 2114 | struct ArrayStruct 2115 | { 2116 | std::array tab = { { 0, 0, 0 } }; 2117 | 2118 | ArrayStruct(int a, int b, int c) 2119 | { 2120 | tab[0] = a; tab[1] = b; tab[2] = c; 2121 | } 2122 | }; 2123 | 2124 | 2125 | struct ArrayArrayStruct 2126 | { 2127 | ArrayStruct tab2 = ArrayStruct(0, 0, 0); 2128 | }; 2129 | 2130 | void check_std_array() 2131 | { 2132 | ArrayStruct tab2(0, 0, 0); 2133 | ArrayArrayStruct toto; 2134 | CHECK(toto.tab2.tab[0] == 0); 2135 | 2136 | std::array tab3 = { { 4, 5, 6 } }; 2137 | tab3.fill(18); 2138 | CHECK(tab3[0] == 18); 2139 | } 2140 | 2141 | 2142 | struct ImplCtorStruct 2143 | { 2144 | int i; 2145 | 2146 | ImplCtorStruct(int u) : i(u) {} 2147 | }; 2148 | 2149 | class ImplCtorClass 2150 | { 2151 | public: 2152 | int i; 2153 | ImplCtorClass(int u) : i(u) {} 2154 | }; 2155 | 2156 | void check_implicit_ctor() 2157 | { 2158 | ImplCtorStruct a = 2; 2159 | CHECK(a.i == 2); 2160 | ImplCtorStruct t[3] = {1, 2, 3}; 2161 | CHECK(t[2].i == 3); 2162 | ImplCtorClass b = 18; 2163 | CHECK(b.i == 18); 2164 | ImplCtorClass y[3] = { 1, 2, 3 }; 2165 | CHECK(y[2].i == 3); 2166 | } 2167 | 2168 | class WithExternBody 2169 | { 2170 | public: 2171 | 2172 | int give42(int i = 1); 2173 | 2174 | int give43() 2175 | { 2176 | return 43; 2177 | } 2178 | }; 2179 | 2180 | int WithExternBody::give42(int tu) 2181 | { 2182 | return 42 * tu; 2183 | } 2184 | 2185 | int give42(int i = 1); 2186 | 2187 | int give42(int tu) 2188 | { 2189 | return 42 * tu; 2190 | } 2191 | 2192 | 2193 | int give43() 2194 | { 2195 | return 43; 2196 | } 2197 | 2198 | void check_extern_methode() 2199 | { 2200 | WithExternBody toto; 2201 | CHECK(toto.give42() == 42); 2202 | CHECK(give42() == 42); 2203 | CHECK(toto.give43() == 43); 2204 | CHECK(give43() == 43); 2205 | } 2206 | 2207 | class SimpleClass 2208 | { 2209 | public: 2210 | int i; 2211 | 2212 | SimpleClass() = default; 2213 | SimpleClass(SimpleClass const&) = default; 2214 | SimpleClass* dup() 2215 | { 2216 | return new SimpleClass(*this); 2217 | } 2218 | }; 2219 | 2220 | struct ContainScopedClass 2221 | { 2222 | SimpleClass m1; 2223 | }; 2224 | 2225 | struct ContainScopedClass2 2226 | { 2227 | SimpleClass m1; 2228 | 2229 | ContainScopedClass2() = default; 2230 | 2231 | ContainScopedClass2(ContainScopedClass2 const& other) 2232 | : m1(other.m1) 2233 | { 2234 | } 2235 | }; 2236 | 2237 | void check_struct_containing_scooped_class() 2238 | { 2239 | { 2240 | ContainScopedClass c1; 2241 | c1.m1.i = 98; 2242 | auto c2 = c1; 2243 | c1.m1.i = 6; 2244 | CHECK(c2.m1.i == 98); 2245 | c2 = c1; 2246 | c1.m1.i = 7; 2247 | CHECK(c2.m1.i == 6); 2248 | } 2249 | 2250 | { 2251 | ContainScopedClass2 c1; 2252 | c1.m1.i = 98; 2253 | auto c2 = c1; 2254 | c1.m1.i = 6; 2255 | CHECK(c2.m1.i == 98); 2256 | c2 = c1; 2257 | c1.m1.i = 7; 2258 | CHECK(c2.m1.i == 6); 2259 | } 2260 | 2261 | } 2262 | 2263 | class CopyDisableClass 2264 | { 2265 | public: 2266 | int i = 3; 2267 | CopyDisableClass(){} 2268 | 2269 | CopyDisableClass(CopyDisableClass const&) = delete; 2270 | CopyDisableClass& operator=(CopyDisableClass const&) = delete; 2271 | }; 2272 | 2273 | class CopyDisableClass2 2274 | { 2275 | CopyDisableClass2(CopyDisableClass2 const&); 2276 | CopyDisableClass2& operator=(CopyDisableClass2 const&); 2277 | 2278 | public: 2279 | int i = 3; 2280 | CopyDisableClass2() {} 2281 | }; 2282 | 2283 | void check_not_copyable_class() 2284 | { 2285 | CopyDisableClass a; 2286 | CHECK(a.i == 3); 2287 | CopyDisableClass2 b; 2288 | CHECK(b.i == 3); 2289 | } 2290 | 2291 | void check_break() 2292 | { 2293 | int i = 0; 2294 | for (; i < 10; ++i) 2295 | { 2296 | if (i == 5) 2297 | break; 2298 | } 2299 | CHECK(i == 5); 2300 | } 2301 | 2302 | void check_continue() 2303 | { 2304 | int i = 0; 2305 | for (; i < 10; ++i) 2306 | { 2307 | if (i == 5) 2308 | continue; 2309 | CHECK(i != 5); 2310 | } 2311 | CHECK(i == 10); 2312 | } 2313 | 2314 | void check_switch() 2315 | { 2316 | auto test = [](int value) 2317 | { 2318 | int res; 2319 | switch (value) 2320 | { 2321 | case 0: return 0; 2322 | case 1: return 1; 2323 | case 2: res = 2; break; 2324 | default: res = 3; 2325 | } 2326 | return res; 2327 | }; 2328 | CHECK(test(0) == 0); 2329 | CHECK(test(1) == 1); 2330 | CHECK(test(2) == 2); 2331 | CHECK(test(3) == 3); 2332 | 2333 | enum EA 2334 | { 2335 | OPT2, 2336 | OPT21 = OPT2, 2337 | OPT3 2338 | }; 2339 | 2340 | auto test_named_enum = [](EA a) 2341 | { 2342 | int result = 0; 2343 | switch (a) 2344 | { 2345 | case OPT2: result = 1; break; 2346 | case OPT3: result = 2; break; 2347 | } 2348 | return result; 2349 | }; 2350 | CHECK(test_named_enum(OPT2) == 1); 2351 | CHECK(test_named_enum(OPT21) == 1); 2352 | CHECK(test_named_enum(OPT3) == 2); 2353 | CHECK(test_named_enum((EA)-1) == 0); 2354 | 2355 | enum class EB 2356 | { 2357 | OPT4, 2358 | OPT41 = OPT4, 2359 | OPT5 2360 | }; 2361 | 2362 | auto test_class_enum = [](EB a) 2363 | { 2364 | int result = 0; 2365 | switch (a) 2366 | { 2367 | case EB::OPT4: result = 1; break; 2368 | case EB::OPT5: result = 2; break; 2369 | } 2370 | return result; 2371 | }; 2372 | CHECK(test_class_enum(EB::OPT4) == 1); 2373 | CHECK(test_class_enum(EB::OPT41) == 1); 2374 | CHECK(test_class_enum(EB::OPT5) == 2); 2375 | CHECK(test_class_enum((EB)-1) == 0); 2376 | 2377 | auto test_enum_fallthrough = [](EB a) 2378 | { 2379 | int result = 0; 2380 | switch (a) 2381 | { 2382 | case EB::OPT4: 2383 | result = 2; 2384 | case EB::OPT5: 2385 | ++result; 2386 | break; 2387 | } 2388 | return result; 2389 | }; 2390 | CHECK(test_enum_fallthrough(EB::OPT4) == 3); 2391 | CHECK(test_enum_fallthrough(EB::OPT41) == 3); 2392 | CHECK(test_enum_fallthrough(EB::OPT5) == 1); 2393 | CHECK(test_enum_fallthrough((EB)-1) == 0); 2394 | } 2395 | 2396 | extern int ext_var; 2397 | 2398 | int ext_var = 18; 2399 | 2400 | void check_ext_vat() 2401 | { 2402 | CHECK(ext_var == 18); 2403 | } 2404 | 2405 | template 2406 | struct TableTraits2; 2407 | 2408 | template 2409 | struct TableTraits2 2410 | { 2411 | static size_t const Size = I; 2412 | }; 2413 | 2414 | template 2415 | struct TableTraits; 2416 | 2417 | template<> 2418 | struct TableTraits 2419 | { 2420 | static size_t const Size = 6; 2421 | }; 2422 | 2423 | 2424 | void check_tmpl_sized_array() 2425 | { 2426 | int tab[] = { 0, 1, 2, 3, 4, 5 }; 2427 | static_assert(TableTraits::Size == 6, ""); 2428 | static_assert(TableTraits2::Size == 6, ""); 2429 | } 2430 | 2431 | void check_rethrow() 2432 | { 2433 | int status = 0; 2434 | try 2435 | { 2436 | try 2437 | { 2438 | try 2439 | { 2440 | throw std::runtime_error("test"); 2441 | } 2442 | catch (std::runtime_error& ex) 2443 | { 2444 | CHECK(status == 0); 2445 | ++status; 2446 | throw; 2447 | } 2448 | } 2449 | catch (std::runtime_error&) 2450 | { 2451 | CHECK(status == 1); 2452 | ++status; 2453 | throw; 2454 | } 2455 | } 2456 | catch (std::runtime_error&) 2457 | { 2458 | CHECK(status == 2); 2459 | ++status; 2460 | } 2461 | CHECK(status == 3); 2462 | 2463 | try 2464 | { 2465 | try 2466 | { 2467 | throw std::runtime_error("test"); 2468 | } 2469 | catch (...) 2470 | { 2471 | ++status; 2472 | throw; 2473 | } 2474 | } 2475 | catch (...) 2476 | { 2477 | CHECK(status == 4); 2478 | ++status; 2479 | } 2480 | CHECK(status == 5); 2481 | } 2482 | 2483 | typedef struct Z Z; 2484 | 2485 | struct Z 2486 | { 2487 | enum Y : char 2488 | { 2489 | A, 2490 | B, 2491 | C 2492 | }; 2493 | }; 2494 | 2495 | void check_enum() 2496 | { 2497 | CHECK_EQUAL(Z::Y::A, 0); 2498 | CHECK_EQUAL(Z::Y::B, 1); 2499 | CHECK_EQUAL(Z::Y::C, 2); 2500 | 2501 | CHECK_EQUAL(Z::A, 0); 2502 | CHECK_EQUAL(Z::B, 1); 2503 | CHECK_EQUAL(Z::C, 2); 2504 | 2505 | Z::Y y = Z::B; 2506 | CHECK_EQUAL(y, Z::B); 2507 | } 2508 | 2509 | void check_cast() 2510 | { 2511 | double d = 3.33; 2512 | int i = int(d); 2513 | CHECK_EQUAL(i, 3); 2514 | } 2515 | 2516 | void check_keyword_convertion() 2517 | { 2518 | int version = 0; 2519 | CHECK_EQUAL(version, 0); 2520 | int out = 0; 2521 | CHECK_EQUAL(out, 0); 2522 | int in = 0; 2523 | CHECK_EQUAL(in, 0); 2524 | int ref = 0; 2525 | CHECK_EQUAL(ref, 0); 2526 | int debug = 0; 2527 | CHECK_EQUAL(debug, 0); 2528 | int function = 0; 2529 | CHECK_EQUAL(function, 0); 2530 | int cast = 0; 2531 | CHECK_EQUAL(cast, 0); 2532 | int align = 0; 2533 | CHECK_EQUAL(align, 0); 2534 | int Exception = 0; 2535 | CHECK_EQUAL(Exception, 0); 2536 | } 2537 | 2538 | enum 2539 | { 2540 | a, 2541 | b, 2542 | c = 32, 2543 | d, 2544 | e = 1, 2545 | f 2546 | }; 2547 | 2548 | void check_anonymous_enum() 2549 | { 2550 | static_assert(a == 0, ""); 2551 | static_assert(b == 1, ""); 2552 | static_assert(c == 32, ""); 2553 | static_assert(d == 33, ""); 2554 | static_assert(e == 1, ""); 2555 | static_assert(f == 2, ""); 2556 | } 2557 | 2558 | void func_with_pointer(Struct781* s, SimpleClass* s2) 2559 | { 2560 | int u = s->i; 2561 | CHECK_EQUAL(u, 5678); 2562 | int v = s2->i; 2563 | CHECK_EQUAL(v, 1234); 2564 | } 2565 | 2566 | void check_not_array_ptr() 2567 | { 2568 | SimpleClass* b = new SimpleClass; 2569 | b->i = 1234; 2570 | 2571 | Struct781 s; 2572 | s.i = 5678; 2573 | func_with_pointer(&s, b); 2574 | delete b; 2575 | } 2576 | 2577 | 2578 | void check_string_literal() 2579 | { 2580 | char a[] = "\x53\x80\xF6\x34"; // Not an utf-8 string 2581 | char b[] = "漢字"; // utf-8 (Need Unicode to be printed) 2582 | } 2583 | 2584 | void test_register(TestFrameWork& tf) 2585 | { 2586 | auto ts = std::make_unique(); 2587 | 2588 | ts->addTestCase(check_string_literal); 2589 | 2590 | ts->addTestCase(check_cast); 2591 | 2592 | ts->addTestCase(check_enum); 2593 | 2594 | ts->addTestCase(check_operators); 2595 | 2596 | ts->addTestCase(check_function); 2597 | 2598 | ts->addTestCase(check_static_array); 2599 | 2600 | ts->addTestCase(check_dynamic_array); 2601 | 2602 | ts->addTestCase(check_struct); 2603 | 2604 | ts->addTestCase(check_template_struct_specialization); 2605 | 2606 | ts->addTestCase(check_template_function); 2607 | 2608 | ts->addTestCase(check_class); 2609 | 2610 | ts->addTestCase(check_type_alias); 2611 | 2612 | ts->addTestCase(check_bitfield); 2613 | 2614 | ts->addTestCase(check_decayed_type); 2615 | 2616 | ts->addTestCase(check_injectedclassnametype); 2617 | 2618 | ts->addTestCase(check_convertion_operator); 2619 | 2620 | ts->addTestCase(check_abstract_keyword); 2621 | 2622 | ts->addTestCase(check_class_opassign); 2623 | 2624 | ts->addTestCase(check_tmpl_func_spec); 2625 | 2626 | ts->addTestCase(check_variadic); 2627 | 2628 | ts->addTestCase(check_tmpl_meth); 2629 | 2630 | ts->addTestCase(check_function_pointer); 2631 | 2632 | ts->addTestCase(check_method_pointer); 2633 | 2634 | ts->addTestCase(check_member_pointer); 2635 | 2636 | ts->addTestCase(check_uninstantiated_default_arg); 2637 | 2638 | ts->addTestCase(check_class_instantiation); 2639 | 2640 | ts->addTestCase(check_incomplete_array_type); 2641 | 2642 | ts->addTestCase(check_builtin_macro); 2643 | 2644 | ts->addTestCase(check_incr_pointer); 2645 | 2646 | ts->addTestCase(check_function_macro); 2647 | 2648 | ts->addTestCase(check_range_based_for_loop); 2649 | 2650 | ts->addTestCase(check_overloaded_operator); 2651 | 2652 | ts->addTestCase(check_extern_overloaded_operator); 2653 | 2654 | ts->addTestCase(check_lib_porting_pair); 2655 | 2656 | ts->addTestCase(check_union); 2657 | 2658 | ts->addTestCase(check_lambda); 2659 | 2660 | ts->addTestCase(check_struct_default_ctor); 2661 | 2662 | ts->addTestCase(check_struct_ctor_call); 2663 | 2664 | ts->addTestCase(check_class_ctor_call); 2665 | 2666 | ts->addTestCase(check_exception); 2667 | 2668 | ts->addTestCase(check_exception2); 2669 | 2670 | ts->addTestCase(check_for_loop); 2671 | 2672 | ts->addTestCase(check_while_loop); 2673 | 2674 | ts->addTestCase(check_dowhile_loop); 2675 | 2676 | ts->addTestCase(check_multidecl_line); 2677 | 2678 | ts->addTestCase(check_std_array); 2679 | 2680 | ts->addTestCase(check_implicit_ctor); 2681 | 2682 | ts->addTestCase(check_extern_methode); 2683 | 2684 | ts->addTestCase(check_struct_containing_scooped_class); 2685 | 2686 | ts->addTestCase(check_not_copyable_class); 2687 | 2688 | ts->addTestCase(check_break); 2689 | 2690 | ts->addTestCase(check_continue); 2691 | 2692 | ts->addTestCase(check_switch); 2693 | 2694 | ts->addTestCase(check_ext_vat); 2695 | 2696 | ts->addTestCase(check_tmpl_sized_array); 2697 | 2698 | ts->addTestCase(check_rethrow); 2699 | 2700 | ts->addTestCase(check_keyword_convertion); 2701 | 2702 | ts->addTestCase(check_anonymous_enum); 2703 | 2704 | ts->addTestCase(check_not_array_ptr); 2705 | 2706 | tf.addTestSuite(std::move(ts)); 2707 | } --------------------------------------------------------------------------------