From 0c3e1b4e82dfd62dbe991f471d212867a2f605bd Mon Sep 17 00:00:00 2001 From: Lewis Jordan Date: Thu, 7 Sep 2023 15:27:14 +0100 Subject: [PATCH] Synced our CppSharp fork with main (#8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Incorrect build instructions on Windows (#1701) * Fix incorrect build instructions for Windows * Add link to Visual Studio installer * Refine building instructions for VS2019+ (cherry picked from commit c4a24b0ccec322e4c8eb00be14bcc5415f5316f8) * Misc changes (#1710) * Minor code refactoring for re-use. * Add Class.FindVariable helper method. * Upgrade to .NET 6. (cherry picked from commit db7949b263e90158c0e8cb388bf243b0f80de4cb) * Add C++ WebAssembly ABI (#1711) * Minor code refactorings. * Fix debug assert issue with vtable methods. * Add support for WebAssembly C++ ABI to parser and AST converter. (cherry picked from commit 9b06e7bc01d6eba151b2cc5cd6c7f6ec91cbbd9e) * Add initial Emscripten generator. (#1712) (cherry picked from commit 117567d61f1cdd1b97b6baf302decc3569a355c0) * Code cleanups and improvements (#1713) * Code cleanups. * Run GetterSetterToPropertyPass for more generators. * Fixed compile warning when compiling parser bindings. * Cleanup driver code. * Remove dead 32-bit code. * Reduce verbosity when Options.Quiet is set. * Remove test compile-time warnings. * Move .NET tests to tests/dotnet. * Remove unused AST viewer code and premake-qt submodule. * Move tests2/ contents to tests/. (cherry picked from commit 4417dd987ade1392ef1e1d164c25f40f10ce2b48) * Publish package to nuget.org when a version tag is created (cherry picked from commit 5715df5a72574f65c30795b5ebb3d90eff4a855b) * Allow passing a `-target-framework` option to `build.sh` (#1718) Closes https://github.com/mono/CppSharp/issues/1717. (cherry picked from commit 8cf6e3f2805babe78b1b30b1d719d6c62c0cbaac) * Remove unused LLVM build flags. (cherry picked from commit 84b7276114e1b2a36edb8887772063a1d508e87c) * Update LLVM workflow to latest Action images. (cherry picked from commit 3d32fc7d87f107d00e966da847489669fb9b1eb4) * Update LLVM Windows workflow to latest Action images. (cherry picked from commit f9f9e9c2bc410b028711dab20b5c4d05684e7171) * Update action steps to latest to fix Node.js deprecation warnings. (cherry picked from commit 7d6decd8b7fb48770035c7ae8b36bded1e605f5b) * Update LLVM build script for Visual Studio 2022. (cherry picked from commit b8a16a45b1666a91506f9630c4cc7d2ff05a15ae) * Workaround Directory.Build.props getting picked up when building LLVM. This is to workaround MSBuild CMake step from LLVM build in Windows picking this up. (cherry picked from commit 25e2c7c0aa86ccd20dc36cb542e39f91fb585506) * Added variation of https://github.com/mono/CppSharp/pull/1736 * Workaround parsing GNU system headers with GCC 11.0 version. (#1737) Closes https://github.com/mono/CppSharp/issues/1703. Upstream bugs: https://github.com/llvm/llvm-project/issues/51607 https://github.com/llvm/llvm-project/issues/53152 (cherry picked from commit 02725320fd14bf1d236f75c7f6ad8b6217b71a9e) * CppSharp.AST.Declaration - fix return QualifiedOriginalName, QualifiedLogicalOriginalName (#1740) Fixed properties getters of QualifiedOriginalName, QualifiedLogicalOriginalName and methods GetQualifiedName(), GatherNamespaces. (cherry picked from commit 9923d79617e8ae24851f9d86c195fb3b5ef82224) * CSharpExpressionPrinter: Wrap expression in parenthesis (#1741) Wrap default parameter expressions in parentheses to ensure whole expressions are casted instead of only the first operand. (cherry picked from commit 169f8686a932d2269be97fdf123d66761039f15e) * Update README.md Remove Gitter since the link is 404 and we have not been using it anyway. (cherry picked from commit 160efb469a6afbcf94082d9d55a07482344a8e2d) * CSharpExpressionPrinter: Recurse into operands (#1745) * CSharpExpressionPrinter: Recurse into operands Recursively call `VisitExpression` on the LHS and RHS of a binary operator expression. This fixes the generation for complex default parameters involving things other than two enumeration members. * CSharpSources: Use `const` when possible Generate `const` instead of `static` members when possible. This allows generated members to be used when compile-time constants are required, such as default parameters. (cherry picked from commit 1ce9cb7e7fff2dae3bdce05a6a2231b1919b4cab) * CSharp: More default parameter fixes (#1747) - Expression generation for `ConstructorReference` now also recursively calls `VisitExpression` for the argument if only one argument is detected. This allows correct overload generation for functions taking a variable as the default parameter value. - Default parameters of pointer-to-enumeration types are now correctly generated similar to primitive types. (cherry picked from commit add3aba684c367091d67129d1a2b0ed196025ad2) * Add type parameter to non-type template parameter decls. (#1749) (cherry picked from commit bb31bd616b278061d38b00eec9fe825e316bc7d9) * Update parser example to latest API. (cherry picked from commit 8c1fa18ccb1c13f052bb185345da0c5359eb8918) * Fixed debugging printing when type printing delegate is not initialized. (cherry picked from commit 9f3ce76261f3e4a25440b2d33194dee865c5e99c) * Array marshalling (#1748) * Generator: Customization for const char[] Allow the user to choose whether `const char[]` should be marshalled as `string` or a normal `char` array in C#. A new option `MarshalConstCharArrayAsString` is added, and is `true` by default. This helps in situations where the original C++ API distinguishes between C-strings and char arrays using the two different notations. * CSharpMarshal: Fix unknown length array marshal For unknown length arrays, also run a conversion loop if the primitive type encountered needs conversion (e.g. `char` to `sbyte`). * CSharpTypePrinter: Fix for boolean arrays (cherry picked from commit 357efec91bb2eeccc013c22ed70ba21a2279ed39) * Add qualified template name to GetCXXRecordDeclFromBaseType. (#1751) (cherry picked from commit 626a362698aa3a290857b1d3421254da1a8a4a6c) * SymbolResolver: Use filename when path cannot be found (#1752) Uses bare filename to pass to `dlopen` when the full path cannot be detected. This helps on systems where library paths are not the same as $PATH. (cherry picked from commit 3978fb3be9257209b5757c91fde546d9088f45a5) * CSharpSources: Dereference pointer variables (#1753) Dereference pointers when generating getters for pointer variables. Otherwise, the managed instance would point to the pointer itself rather than the object at the native instance's address. (cherry picked from commit ce3d04abd7a80102fe2a6253c3aee2e803aa58a1) * Use TypePrinter.IntPtrType in CSharpSources.cs code from previous commit. (cherry picked from commit 3c31179db1e8a4a2f008612fb005124b946cc793) --------- Co-authored-by: aybe Co-authored-by: João Matos Co-authored-by: josetr <37419832+josetr@users.noreply.github.com> Co-authored-by: stachu99 Co-authored-by: Trung Nguyen <57174311+trungnt2910@users.noreply.github.com> --- .github/workflows/llvm-win.yml | 10 +- .github/workflows/llvm.yml | 10 +- .github/workflows/main.yml | 10 +- .gitmodules | 3 - Directory.Build.props | 2 +- README.md | 2 - build/Helpers.lua | 19 +- build/build.sh | 12 +- build/llvm/Directory.Build.props | 3 + build/llvm/LLVM.lua | 12 +- build/modules/premake-qt | 1 - build/premake5.lua | 2 +- docs/GettingStarted.md | 27 +- docs/UsersManual.md | 1 + examples/Parser/Parser.cs | 11 +- src/AST/ASTContext.cs | 3 +- src/AST/Class.cs | 5 + src/AST/ClassLayout.cs | 9 +- src/AST/Declaration.cs | 21 +- src/AST/Property.cs | 111 +- src/AST/Template.cs | 2 + src/AST/Type.cs | 2 +- src/AST/TypeExtensions.cs | 19 + src/ASTViewer/AstModel.cpp | 141 -- src/ASTViewer/AstModel.h | 35 - src/ASTViewer/AstReader.cpp | 543 ------ src/ASTViewer/AstReader.h | 60 - .../ClangUtilities/StringLiteralExtractor.cpp | 304 --- .../ClangUtilities/StringLiteralExtractor.h | 46 - .../ClangUtilities/TemplateUtilities.cpp | 287 --- .../ClangUtilities/TemplateUtilities.h | 27 - src/ASTViewer/CommandLineSplitter.cpp | 90 - src/ASTViewer/CommandLineSplitter.h | 6 - src/ASTViewer/Highlighter.cpp | 143 -- src/ASTViewer/Highlighter.h | 84 - src/ASTViewer/LICENSE | 165 -- src/ASTViewer/MainWindow.cpp | 169 -- src/ASTViewer/MainWindow.h | 27 - src/ASTViewer/MainWindow.ui | 151 -- src/ASTViewer/README.md | 7 - src/ASTViewer/main.cpp | 14 - src/ASTViewer/premake5.lua | 32 - src/CLI/CLI.cs | 39 +- src/CLI/Generator.cs | 92 +- src/CLI/Options.cs | 4 +- src/Core/Platform.cs | 3 +- src/CppParser/AST.cpp | 1 + src/CppParser/Bindings/CLI/Decl.cpp | 12 + src/CppParser/Bindings/CLI/Decl.h | 9 +- .../CSharp/CppSharp.Parser.CSharp.csproj | 1 + .../CppSharp.CppParser.cs | 19 +- .../i686-pc-win32-msvc/CppSharp.CppParser.cs | 19 +- .../CppSharp.CppParser.cs | 19 +- .../CppSharp.CppParser.cs | 19 +- .../x86_64-linux-gnu/CppSharp.CppParser.cs | 19 +- .../CppSharp.CppParser.cs | 19 +- src/CppParser/Decl.h | 1651 +++++++++-------- src/CppParser/Parser.cpp | 26 +- src/Generator.Tests/GeneratorTest.cs | 23 +- src/Generator/AST/VTables.cs | 1 + src/Generator/Driver.cs | 228 +-- src/Generator/Generator.cs | 1 + src/Generator/Generators/C/CppTypePrinter.cs | 6 +- src/Generator/Generators/CLI/CLIMarshal.cs | 3 +- .../Generators/CLI/CLITypePrinter.cs | 3 +- .../CSharp/CSharpExpressionPrinter.cs | 19 +- .../Generators/CSharp/CSharpMarshal.cs | 10 +- .../Generators/CSharp/CSharpSources.cs | 69 +- .../Generators/CSharp/CSharpTypePrinter.cs | 10 +- src/Generator/Generators/CodeGenerator.cs | 6 +- .../Emscripten/EmscriptenGenerator.cs | 73 + .../Emscripten/EmscriptenHeaders.cs | 48 + .../Emscripten/EmscriptenMarshal.cs | 21 + .../Generators/Emscripten/EmscriptenModule.cs | 89 + .../Emscripten/EmscriptenSources.cs | 202 ++ .../Emscripten/EmscriptenTypePrinter.cs | 11 + src/Generator/Generators/NAPI/NAPIHelpers.cs | 32 +- src/Generator/Generators/NAPI/NAPISources.cs | 9 - .../Generators/QuickJS/QuickJSSources.cs | 2 +- src/Generator/Options.cs | 5 +- .../Passes/CheckAmbiguousFunctions.cs | 2 +- .../Passes/CheckDuplicatedNamesPass.cs | 4 + src/Generator/Passes/CleanUnitPass.cs | 5 + src/Generator/Passes/FieldToPropertyPass.cs | 3 +- .../Passes/GetterSetterToPropertyPass.cs | 65 +- src/Generator/Types/Std/Stdlib.CSharp.cs | 2 - src/Generator/Utils/Options.cs | 1 - src/Parser/ASTConverter.cs | 3 + src/Parser/Parser.cs | 2 +- src/Parser/ParserOptions.cs | 64 +- src/Runtime/SymbolResolver.cs | 10 +- {tests2 => tests}/Builtins.h | 3 + {tests2 => tests}/Classes.h | 0 {tests2 => tests}/Classes2.h | 0 {tests2 => tests}/Delegates.h | 0 {tests2 => tests}/Enums.h | 0 tests/NamespacesBase/premake4.lua | 11 - {tests2 => tests}/Overloads.h | 0 tests/{ => dotnet}/CLI/CLI.Gen.cs | 0 tests/{ => dotnet}/CLI/CLI.Gen.csproj | 0 tests/{ => dotnet}/CLI/CLI.Tests.CLI.csproj | 0 tests/{ => dotnet}/CLI/CLI.Tests.cs | 0 tests/{ => dotnet}/CLI/CLI.cpp | 0 tests/{ => dotnet}/CLI/CLI.h | 0 .../ClassWithNestedEnum.cpp | 0 .../ClassWithNestedEnum.h | 0 .../NestedEnumConsumer.cpp | 0 .../NestedEnumConsumer.h | 0 .../Employee.cpp | 0 .../Employee.h | 0 .../EmployeeForwardDecl.h | 0 .../EmployeeOrg.cpp | 0 .../EmployeeOrg.h | 0 .../IgnoredClassTemplateForEmployee.h | 0 tests/{ => dotnet}/CLI/premake4.lua | 0 tests/{ => dotnet}/CSharp/AnonTypes.h | 0 tests/{ => dotnet}/CSharp/AnotherUnit.cpp | 0 tests/{ => dotnet}/CSharp/AnotherUnit.h | 0 .../{ => dotnet}/CSharp/CSharp.CSharp.csproj | 3 + tests/{ => dotnet}/CSharp/CSharp.Gen.cs | 0 tests/{ => dotnet}/CSharp/CSharp.Gen.csproj | 0 .../CSharp/CSharp.Tests.CSharp.csproj | 0 tests/{ => dotnet}/CSharp/CSharp.Tests.cs | 11 + tests/{ => dotnet}/CSharp/CSharp.cpp | 58 +- tests/{ => dotnet}/CSharp/CSharp.h | 36 +- .../CSharp/CSharpPartialMethods.cs | 0 tests/{ => dotnet}/CSharp/CSharpTemplates.cpp | 0 tests/{ => dotnet}/CSharp/CSharpTemplates.h | 0 tests/{ => dotnet}/CSharp/ExcludedUnit.hpp | 0 tests/{ => dotnet}/CSharp/premake4.lua | 0 tests/{ => dotnet}/Common/AnotherUnit.cpp | 0 tests/{ => dotnet}/Common/AnotherUnit.h | 0 .../{ => dotnet}/Common/Common.CSharp.csproj | 0 tests/{ => dotnet}/Common/Common.Gen.cs | 0 tests/{ => dotnet}/Common/Common.Gen.csproj | 0 .../Common/Common.Tests.CLI.csproj | 0 .../Common/Common.Tests.CSharp.csproj | 0 tests/{ => dotnet}/Common/Common.Tests.cs | 0 tests/{ => dotnet}/Common/Common.cpp | 2 +- tests/{ => dotnet}/Common/Common.h | 0 tests/{ => dotnet}/Common/interface.h | 0 tests/{ => dotnet}/Common/premake4.lua | 0 tests/{ => dotnet}/Directory.Build.props | 2 +- tests/{ => dotnet}/Empty/Empty.Gen.cs | 0 tests/{ => dotnet}/Empty/Empty.Tests.cs | 0 tests/{ => dotnet}/Empty/Empty.cpp | 0 tests/{ => dotnet}/Empty/Empty.h | 0 tests/{ => dotnet}/Empty/premake4.lua | 0 .../Encodings/Encodings.CSharp.csproj | 0 tests/{ => dotnet}/Encodings/Encodings.Gen.cs | 0 .../Encodings/Encodings.Gen.csproj | 0 .../Encodings/Encodings.Tests.CSharp.csproj | 0 .../{ => dotnet}/Encodings/Encodings.Tests.cs | 0 tests/{ => dotnet}/Encodings/Encodings.cpp | 0 tests/{ => dotnet}/Encodings/Encodings.h | 0 tests/{ => dotnet}/Encodings/premake4.lua | 0 .../NamespacesBase/NamespacesBase.cpp | 0 .../NamespacesBase/NamespacesBase.h | 0 tests/dotnet/NamespacesBase/premake4.lua | 3 + tests/{ => dotnet}/NamespacesBase/test.cs | 0 .../NamespacesDerived/Independent.h | 0 .../NamespacesDerived.Gen.cs | 0 .../NamespacesDerived.Gen.csproj | 0 .../NamespacesDerived.Tests.CSharp.csproj | 4 +- .../NamespacesDerived.Tests.cs | 0 .../NamespacesDerived/NamespacesDerived.cpp | 0 .../NamespacesDerived/NamespacesDerived.h | 0 .../NamespacesDerived/premake4.lua | 0 tests/{ => dotnet}/Native/AST.h | 0 tests/{ => dotnet}/Native/ASTExtensions.h | 0 tests/{ => dotnet}/Native/Enums.h | 0 tests/{ => dotnet}/Native/Passes.h | 0 tests/{ => dotnet}/Native/Templates.h | 0 tests/{ => dotnet}/Native/linux/libexpat.so.0 | Bin .../{ => dotnet}/Native/macos/libexpat.dylib | Bin .../{ => dotnet}/Native/windows/libexpat.dll | Bin .../StandardLib/StandardLib.Gen.cs | 0 .../StandardLib/StandardLib.Gen.csproj | 0 .../StandardLib/StandardLib.Tests.CLI.csproj | 0 .../StandardLib/StandardLib.Tests.cs | 0 .../{ => dotnet}/StandardLib/StandardLib.cpp | 0 tests/{ => dotnet}/StandardLib/StandardLib.h | 0 tests/{ => dotnet}/StandardLib/premake4.lua | 0 tests/{ => dotnet}/Test.Bindings.props | 0 tests/{ => dotnet}/Test.Common.props | 0 tests/{ => dotnet}/Test.Generator.props | 0 tests/{ => dotnet}/Test.props | 0 tests/{ => dotnet}/Tests.h | 0 .../VTables/VTables.CSharp.csproj | 0 tests/{ => dotnet}/VTables/VTables.Gen.cs | 0 tests/{ => dotnet}/VTables/VTables.Gen.csproj | 0 .../VTables/VTables.Tests.CSharp.csproj | 0 tests/{ => dotnet}/VTables/VTables.Tests.cs | 0 tests/{ => dotnet}/VTables/VTables.cpp | 0 tests/{ => dotnet}/VTables/VTables.h | 0 tests/{ => dotnet}/VTables/premake4.lua | 0 .../quickjs => tests/emscripten}/.gitignore | 0 tests/emscripten/premake5.lua | 21 + tests/emscripten/test.mjs | 114 ++ tests/emscripten/test.sh | 30 + tests/emscripten/utils.mjs | 21 + {tests2 => tests}/napi/.gitignore | 0 {tests2 => tests}/napi/premake5.lua | 0 {tests2 => tests}/napi/test.js | 0 {tests2 => tests}/napi/test.sh | 0 tests/quickjs/.gitignore | 4 + {tests2 => tests}/quickjs/premake5.lua | 0 {tests2 => tests}/quickjs/test-prop.js | 0 {tests2 => tests}/quickjs/test.js | 0 {tests2 => tests}/quickjs/test.sh | 0 {tests2 => tests}/test.sh | 1 + {tests2 => tests}/ts/.gitignore | 0 {tests2 => tests}/ts/test.sh | 0 {tests2 => tests}/ts/test.ts | 0 {tests2 => tests}/ts/tsconfig.json | 0 215 files changed, 2284 insertions(+), 3652 deletions(-) create mode 100644 build/llvm/Directory.Build.props delete mode 160000 build/modules/premake-qt delete mode 100644 src/ASTViewer/AstModel.cpp delete mode 100644 src/ASTViewer/AstModel.h delete mode 100644 src/ASTViewer/AstReader.cpp delete mode 100644 src/ASTViewer/AstReader.h delete mode 100644 src/ASTViewer/ClangUtilities/StringLiteralExtractor.cpp delete mode 100644 src/ASTViewer/ClangUtilities/StringLiteralExtractor.h delete mode 100644 src/ASTViewer/ClangUtilities/TemplateUtilities.cpp delete mode 100644 src/ASTViewer/ClangUtilities/TemplateUtilities.h delete mode 100644 src/ASTViewer/CommandLineSplitter.cpp delete mode 100644 src/ASTViewer/CommandLineSplitter.h delete mode 100644 src/ASTViewer/Highlighter.cpp delete mode 100644 src/ASTViewer/Highlighter.h delete mode 100644 src/ASTViewer/LICENSE delete mode 100644 src/ASTViewer/MainWindow.cpp delete mode 100644 src/ASTViewer/MainWindow.h delete mode 100644 src/ASTViewer/MainWindow.ui delete mode 100644 src/ASTViewer/README.md delete mode 100644 src/ASTViewer/main.cpp delete mode 100644 src/ASTViewer/premake5.lua create mode 100644 src/Generator/Generators/Emscripten/EmscriptenGenerator.cs create mode 100644 src/Generator/Generators/Emscripten/EmscriptenHeaders.cs create mode 100644 src/Generator/Generators/Emscripten/EmscriptenMarshal.cs create mode 100644 src/Generator/Generators/Emscripten/EmscriptenModule.cs create mode 100644 src/Generator/Generators/Emscripten/EmscriptenSources.cs create mode 100644 src/Generator/Generators/Emscripten/EmscriptenTypePrinter.cs rename {tests2 => tests}/Builtins.h (97%) rename {tests2 => tests}/Classes.h (100%) rename {tests2 => tests}/Classes2.h (100%) rename {tests2 => tests}/Delegates.h (100%) rename {tests2 => tests}/Enums.h (100%) delete mode 100644 tests/NamespacesBase/premake4.lua rename {tests2 => tests}/Overloads.h (100%) rename tests/{ => dotnet}/CLI/CLI.Gen.cs (100%) rename tests/{ => dotnet}/CLI/CLI.Gen.csproj (100%) rename tests/{ => dotnet}/CLI/CLI.Tests.CLI.csproj (100%) rename tests/{ => dotnet}/CLI/CLI.Tests.cs (100%) rename tests/{ => dotnet}/CLI/CLI.cpp (100%) rename tests/{ => dotnet}/CLI/CLI.h (100%) rename tests/{ => dotnet}/CLI/NestedEnumInClassTest/ClassWithNestedEnum.cpp (100%) rename tests/{ => dotnet}/CLI/NestedEnumInClassTest/ClassWithNestedEnum.h (100%) rename tests/{ => dotnet}/CLI/NestedEnumInClassTest/NestedEnumConsumer.cpp (100%) rename tests/{ => dotnet}/CLI/NestedEnumInClassTest/NestedEnumConsumer.h (100%) rename tests/{ => dotnet}/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.cpp (100%) rename tests/{ => dotnet}/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.h (100%) rename tests/{ => dotnet}/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeForwardDecl.h (100%) rename tests/{ => dotnet}/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.cpp (100%) rename tests/{ => dotnet}/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h (100%) rename tests/{ => dotnet}/CLI/UseTemplateTypeFromIgnoredClassTemplate/IgnoredClassTemplateForEmployee.h (100%) rename tests/{ => dotnet}/CLI/premake4.lua (100%) rename tests/{ => dotnet}/CSharp/AnonTypes.h (100%) rename tests/{ => dotnet}/CSharp/AnotherUnit.cpp (100%) rename tests/{ => dotnet}/CSharp/AnotherUnit.h (100%) rename tests/{ => dotnet}/CSharp/CSharp.CSharp.csproj (65%) rename tests/{ => dotnet}/CSharp/CSharp.Gen.cs (100%) rename tests/{ => dotnet}/CSharp/CSharp.Gen.csproj (100%) rename tests/{ => dotnet}/CSharp/CSharp.Tests.CSharp.csproj (100%) rename tests/{ => dotnet}/CSharp/CSharp.Tests.cs (99%) rename tests/{ => dotnet}/CSharp/CSharp.cpp (96%) rename tests/{ => dotnet}/CSharp/CSharp.h (97%) rename tests/{ => dotnet}/CSharp/CSharpPartialMethods.cs (100%) rename tests/{ => dotnet}/CSharp/CSharpTemplates.cpp (100%) rename tests/{ => dotnet}/CSharp/CSharpTemplates.h (100%) rename tests/{ => dotnet}/CSharp/ExcludedUnit.hpp (100%) rename tests/{ => dotnet}/CSharp/premake4.lua (100%) rename tests/{ => dotnet}/Common/AnotherUnit.cpp (100%) rename tests/{ => dotnet}/Common/AnotherUnit.h (100%) rename tests/{ => dotnet}/Common/Common.CSharp.csproj (100%) rename tests/{ => dotnet}/Common/Common.Gen.cs (100%) rename tests/{ => dotnet}/Common/Common.Gen.csproj (100%) rename tests/{ => dotnet}/Common/Common.Tests.CLI.csproj (100%) rename tests/{ => dotnet}/Common/Common.Tests.CSharp.csproj (100%) rename tests/{ => dotnet}/Common/Common.Tests.cs (100%) rename tests/{ => dotnet}/Common/Common.cpp (99%) rename tests/{ => dotnet}/Common/Common.h (100%) rename tests/{ => dotnet}/Common/interface.h (100%) rename tests/{ => dotnet}/Common/premake4.lua (100%) rename tests/{ => dotnet}/Directory.Build.props (83%) rename tests/{ => dotnet}/Empty/Empty.Gen.cs (100%) rename tests/{ => dotnet}/Empty/Empty.Tests.cs (100%) rename tests/{ => dotnet}/Empty/Empty.cpp (100%) rename tests/{ => dotnet}/Empty/Empty.h (100%) rename tests/{ => dotnet}/Empty/premake4.lua (100%) rename tests/{ => dotnet}/Encodings/Encodings.CSharp.csproj (100%) rename tests/{ => dotnet}/Encodings/Encodings.Gen.cs (100%) rename tests/{ => dotnet}/Encodings/Encodings.Gen.csproj (100%) rename tests/{ => dotnet}/Encodings/Encodings.Tests.CSharp.csproj (100%) rename tests/{ => dotnet}/Encodings/Encodings.Tests.cs (100%) rename tests/{ => dotnet}/Encodings/Encodings.cpp (100%) rename tests/{ => dotnet}/Encodings/Encodings.h (100%) rename tests/{ => dotnet}/Encodings/premake4.lua (100%) rename tests/{ => dotnet}/NamespacesBase/NamespacesBase.cpp (100%) rename tests/{ => dotnet}/NamespacesBase/NamespacesBase.h (100%) create mode 100644 tests/dotnet/NamespacesBase/premake4.lua rename tests/{ => dotnet}/NamespacesBase/test.cs (100%) rename tests/{ => dotnet}/NamespacesDerived/Independent.h (100%) rename tests/{ => dotnet}/NamespacesDerived/NamespacesDerived.Gen.cs (100%) rename tests/{ => dotnet}/NamespacesDerived/NamespacesDerived.Gen.csproj (100%) rename tests/{ => dotnet}/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj (65%) rename tests/{ => dotnet}/NamespacesDerived/NamespacesDerived.Tests.cs (100%) rename tests/{ => dotnet}/NamespacesDerived/NamespacesDerived.cpp (100%) rename tests/{ => dotnet}/NamespacesDerived/NamespacesDerived.h (100%) rename tests/{ => dotnet}/NamespacesDerived/premake4.lua (100%) rename tests/{ => dotnet}/Native/AST.h (100%) rename tests/{ => dotnet}/Native/ASTExtensions.h (100%) rename tests/{ => dotnet}/Native/Enums.h (100%) rename tests/{ => dotnet}/Native/Passes.h (100%) rename tests/{ => dotnet}/Native/Templates.h (100%) rename tests/{ => dotnet}/Native/linux/libexpat.so.0 (100%) rename tests/{ => dotnet}/Native/macos/libexpat.dylib (100%) rename tests/{ => dotnet}/Native/windows/libexpat.dll (100%) rename tests/{ => dotnet}/StandardLib/StandardLib.Gen.cs (100%) rename tests/{ => dotnet}/StandardLib/StandardLib.Gen.csproj (100%) rename tests/{ => dotnet}/StandardLib/StandardLib.Tests.CLI.csproj (100%) rename tests/{ => dotnet}/StandardLib/StandardLib.Tests.cs (100%) rename tests/{ => dotnet}/StandardLib/StandardLib.cpp (100%) rename tests/{ => dotnet}/StandardLib/StandardLib.h (100%) rename tests/{ => dotnet}/StandardLib/premake4.lua (100%) rename tests/{ => dotnet}/Test.Bindings.props (100%) rename tests/{ => dotnet}/Test.Common.props (100%) rename tests/{ => dotnet}/Test.Generator.props (100%) rename tests/{ => dotnet}/Test.props (100%) rename tests/{ => dotnet}/Tests.h (100%) rename tests/{ => dotnet}/VTables/VTables.CSharp.csproj (100%) rename tests/{ => dotnet}/VTables/VTables.Gen.cs (100%) rename tests/{ => dotnet}/VTables/VTables.Gen.csproj (100%) rename tests/{ => dotnet}/VTables/VTables.Tests.CSharp.csproj (100%) rename tests/{ => dotnet}/VTables/VTables.Tests.cs (100%) rename tests/{ => dotnet}/VTables/VTables.cpp (100%) rename tests/{ => dotnet}/VTables/VTables.h (100%) rename tests/{ => dotnet}/VTables/premake4.lua (100%) rename {tests2/quickjs => tests/emscripten}/.gitignore (100%) create mode 100644 tests/emscripten/premake5.lua create mode 100644 tests/emscripten/test.mjs create mode 100755 tests/emscripten/test.sh create mode 100644 tests/emscripten/utils.mjs rename {tests2 => tests}/napi/.gitignore (100%) rename {tests2 => tests}/napi/premake5.lua (100%) rename {tests2 => tests}/napi/test.js (100%) rename {tests2 => tests}/napi/test.sh (100%) create mode 100644 tests/quickjs/.gitignore rename {tests2 => tests}/quickjs/premake5.lua (100%) rename {tests2 => tests}/quickjs/test-prop.js (100%) rename {tests2 => tests}/quickjs/test.js (100%) rename {tests2 => tests}/quickjs/test.sh (100%) rename {tests2 => tests}/test.sh (80%) rename {tests2 => tests}/ts/.gitignore (100%) rename {tests2 => tests}/ts/test.sh (100%) rename {tests2 => tests}/ts/test.ts (100%) rename {tests2 => tests}/ts/tsconfig.json (100%) diff --git a/.github/workflows/llvm-win.yml b/.github/workflows/llvm-win.yml index 6bf9e8c0e5..455c4f4dcf 100644 --- a/.github/workflows/llvm-win.yml +++ b/.github/workflows/llvm-win.yml @@ -9,8 +9,8 @@ jobs: fail-fast: false matrix: config: - - { os: windows-2019, platform: x86, vs: 2019 } - - { os: windows-2019, platform: x64, vs: 2019 } + - { os: windows-2022, platform: x86, vs: 2022 } + - { os: windows-2022, platform: x64, vs: 2022 } runs-on: ${{ matrix.config.os }} @@ -23,7 +23,7 @@ jobs: steps: - name: Inject slug/short variables - uses: rlespinasse/github-slug-action@v3.x + uses: rlespinasse/github-slug-action@v4 - name: Check out shell: cmd @@ -35,7 +35,7 @@ jobs: - name: Environment shell: cmd run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\%VS_VERSION%\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" %PLATFORM% + call "C:\Program Files\Microsoft Visual Studio\%VS_VERSION%\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" %PLATFORM% :: Loop over all environment variables and make them global using set-env. :: See: https://stackoverflow.com/a/39184941 setlocal @@ -60,7 +60,7 @@ jobs: working-directory: C:\CppSharp - name: 'Upload Artifact' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: llvm path: C:\CppSharp\build\llvm\llvm-*-*.* \ No newline at end of file diff --git a/.github/workflows/llvm.yml b/.github/workflows/llvm.yml index aa3ffe278e..d8b3f10b82 100644 --- a/.github/workflows/llvm.yml +++ b/.github/workflows/llvm.yml @@ -9,9 +9,9 @@ jobs: fail-fast: false matrix: config: - - { os: ubuntu-20.04, platform: x64, cxx: g++-9, cc: gcc-9 } - - { os: ubuntu-20.04, platform: x64, cxx: g++-10, cc: gcc-10 } - - { os: macos-10.15, platform: x64, cxx: clang++, cc: clang } + - { os: ubuntu-22.04, platform: x64, cxx: g++-11, cc: gcc-11 } + - { os: macos-11, platform: x64, cxx: clang++, cc: clang } + - { os: macos-12, platform: x64, cxx: clang++, cc: clang } runs-on: ${{ matrix.config.os }} @@ -22,7 +22,7 @@ jobs: ACTIONS_ALLOW_UNSECURE_COMMANDS: true steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: lukka/get-cmake@latest - name: Clone LLVM @@ -38,7 +38,7 @@ jobs: run: build/build.sh package_llvm -platform $PLATFORM - name: 'Upload Artifact' - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: llvm path: build/llvm/llvm-*-*.* \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ae538fd464..6756de7613 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -73,8 +73,8 @@ jobs: runs-on: windows-2019 needs: build if: | - (github.event_name == 'push' && (github.ref == 'refs/heads/main' || contains(github.ref, 'nuget'))) || - (github.event.pull_request.head.repo.full_name != github.repository && contains(github.event.pull_request.head.ref, 'nuget')) + (github.event_name == 'push' && (github.ref == 'refs/heads/main' || contains(github.ref, 'nuget') || startsWith(github.ref, 'refs/tags/v'))) || + (github.event.pull_request.head.repo.full_name != github.repository && (contains(github.event.pull_request.head.ref, 'nuget') || startsWith(github.event.pull_request.head.ref, 'refs/tags/v'))) env: DOTNET_NOLOGO: true @@ -111,3 +111,9 @@ jobs: run: | cd artifacts dotnet nuget push "*.nupkg" --api-key ${{ secrets.GITHUB_TOKEN }} --source "https://nuget.pkg.github.com/mono/index.json" --skip-duplicate + + - name: Publish package to nuget.org + if: startsWith(github.ref, 'refs/tags/v') + run: | + cd artifacts + dotnet nuget push "*.nupkg" --api-key ${{ secrets.NUGET_API_KEY }} --source "https://api.nuget.org/v3/index.json" --skip-duplicate diff --git a/.gitmodules b/.gitmodules index cababe3d56..e69de29bb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "build/modules/premake-qt"] - path = build/modules/premake-qt - url = https://github.com/dcourtois/premake-qt.git diff --git a/Directory.Build.props b/Directory.Build.props index 69c39a4e28..3fe84b36b1 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -34,7 +34,7 @@ dll "$(MSBuildProgramFiles32)\dotnet\dotnet.exe" "$(ProgramW6432)\dotnet\dotnet.exe" - win + win linux osx $(RID)-$(PlatformTarget) diff --git a/README.md b/README.md index 259d97b950..b3b3a9495c 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,6 @@ Please see the following resources for more information: Feel free to open up issues on Github for any problems you find. -You can also join us at our [#managed-interop](https://gitter.im/managed-interop) Gitter discussion channel. - ## Support For building wrappers and priority support please write to cppsharp@protonmail.com. diff --git a/build/Helpers.lua b/build/Helpers.lua index b68da9a261..68c4c91d3e 100644 --- a/build/Helpers.lua +++ b/build/Helpers.lua @@ -43,11 +43,16 @@ newoption { description = "Only generate configuration file", } +newoption { + trigger = "target-framework", + description = ".NET target framework version", +} + rootdir = path.getabsolute("../") srcdir = path.join(rootdir, "src"); incdir = path.join(rootdir, "include"); examplesdir = path.join(rootdir, "examples"); -testsdir = path.join(rootdir, "tests"); +testsdir = path.join(rootdir, "tests/dotnet"); builddir = path.join(rootdir, "build") bindir = path.join(rootdir, "bin") objsdir = path.join(builddir, "obj"); @@ -61,7 +66,17 @@ msvc_cpp_defines = { } default_gcc_version = "9.0.0" generate_build_config = true premake.path = premake.path .. ";" .. path.join(builddir, "modules") -targetframework = "netcoreapp3.1" + +function string.isempty(s) + return s == nil or s == '' +end + +local function target_framework() + local value = _OPTIONS["target-framework"] + return string.isempty(value) and "net6.0" or value +end + +targetframework = target_framework() function string.starts(str, start) if str == nil then return end diff --git a/build/build.sh b/build/build.sh index de1368dc90..6f7a086fee 100755 --- a/build/build.sh +++ b/build/build.sh @@ -6,6 +6,7 @@ vs=vs2019 configuration=Release build_only=false ci=false +target_framework= verbosity=minimal rootdir="$builddir/.." bindir="$rootdir/bin" @@ -46,7 +47,7 @@ build() generate_config() { - "$builddir/premake.sh" --file="$builddir/premake5.lua" $vs --os=$os --arch=$platform --configuration=$configuration --config_only + "$builddir/premake.sh" --file="$builddir/premake5.lua" $vs --os=$os --arch=$platform --configuration=$configuration --target-framework=$target_framework --config_only } generate() @@ -54,10 +55,10 @@ generate() download_llvm if [ "$os" = "linux" ] || [ "$os" = "macosx" ]; then - "$builddir/premake.sh" --file="$builddir/premake5.lua" gmake2 --os=$os --arch=$platform --configuration=$configuration "$@" + "$builddir/premake.sh" --file="$builddir/premake5.lua" gmake2 --os=$os --arch=$platform --configuration=$configuration --target-framework=$target_framework "$@" fi - "$builddir/premake.sh" --file="$builddir/premake5.lua" $vs --os=$os --arch=$platform --configuration=$configuration + "$builddir/premake.sh" --file="$builddir/premake5.lua" $vs --os=$os --arch=$platform --configuration=$configuration --target-framework=$target_framework } restore() @@ -194,6 +195,11 @@ while [[ $# > 0 ]]; do os=$2 shift ;; + -target-framework) + target_framework=$2 + echo $target_framework + shift + ;; -ci) ci=true export CI=true diff --git a/build/llvm/Directory.Build.props b/build/llvm/Directory.Build.props new file mode 100644 index 0000000000..8d7621c6b0 --- /dev/null +++ b/build/llvm/Directory.Build.props @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/build/llvm/LLVM.lua b/build/llvm/LLVM.lua index fc15650167..30a3943314 100644 --- a/build/llvm/LLVM.lua +++ b/build/llvm/LLVM.lua @@ -53,13 +53,15 @@ end function get_vs_version() local function map_msvc_to_vs_version(major, minor) - if major == "19" and minor >= "20" then return "vs2019" + if major == "19" and minor >= "30" then return "vs2022" + elseif major == "19" and minor >= "20" then return "vs2019" elseif major == "19" and minor >= "10" then return "vs2017" end end local function map_msbuild_to_vs_version(major, minor) - if major == "16" then return "vs2019" + if major == "17" then return "vs2022" + elseif major == "16" then return "vs2019" elseif major == "15" then return "vs2017" end end @@ -379,8 +381,6 @@ function cmake(gen, conf, builddir, options) .. ' -DCLANG_TOOL_C_INDEX_TEST_BUILD=false' .. ' -DCLANG_TOOL_DIAGTOOL_BUILD=false' .. ' -DCLANG_TOOL_DRIVER_BUILD=false' - .. ' -DCLANG_TOOL_HANDLE_CXX_BUILD=false' - .. ' -DCLANG_TOOL_HANDLE_LLVM_BUILD=false' .. ' -DCLANG_TOOL_LIBCLANG_BUILD=false' .. ' -DCLANG_TOOL_SCAN_BUILD_BUILD=false' .. ' -DCLANG_TOOL_SCAN_BUILD_PY_BUILD=false' @@ -399,7 +399,9 @@ end function get_cmake_generator() local vsver = get_vs_version() - if vsver == "vs2019" then + if vsver == "vs2022" then + return "Visual Studio 17 2022", (target_architecture() == "x86") and "-A Win32" or nil + elseif vsver == "vs2019" then return "Visual Studio 16 2019", (target_architecture() == "x86") and "-A Win32" or nil elseif vsver == "vs2017" then return "Visual Studio 15 2017" .. (target_architecture() == "x64" and " Win64" or ""), nil diff --git a/build/modules/premake-qt b/build/modules/premake-qt deleted file mode 160000 index 0ddc49715c..0000000000 --- a/build/modules/premake-qt +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0ddc49715c7892211774d4b5e705a7c5559aeed4 diff --git a/build/premake5.lua b/build/premake5.lua index 7139ba02cd..f7b10fc24d 100644 --- a/build/premake5.lua +++ b/build/premake5.lua @@ -44,7 +44,7 @@ workspace "CppSharp" workspacefiles(path.join(builddir, "premake5.lua")) workspacefiles(path.join(builddir, "*.sh")) workspacefiles(path.join(rootdir, ".github/workflows/*.yml")) - workspacefiles(path.join(rootdir, "tests/Test*.props")) + workspacefiles(path.join(testsdir, "Test*.props")) group "Libraries" if EnableNativeProjects() then diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index ff8017b4a3..a6711727f0 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -35,27 +35,46 @@ make sure those are installed on your system. ## Compiling on Windows/Visual Studio +The following steps should be called from the VS developer command prompt. + 1. Generate the VS solution ```shell cd \build - ./build.sh generate -configuration Release -platform x64 + build.sh generate -configuration Release -platform x64 ``` +> :information_source: You can use the `-target-framework` option to target any valid .NET target framework. + 2. Compile the VS projects You can open `CppSharp.sln` and hit F5 or compile via the command line: ``` - ./build.sh -configuration Release -platform x64 + build.sh -configuration Release -platform x64 ``` Building in *Release* is recommended because else we will use the Clang parser debug configuration, which will be too slow for practical use beyond debugging. +The solution generated will be for Visual Studio 2019. + +If you have a more recent version of Visual Studio, you can either: +- install Visual Studio 2019 +- install Visual Studio 2019 build tools, from [Visual Studio Installer](https://visualstudio.microsoft.com/downloads/) + - select the payload *MSVC v142 - VS 2019 C++ x64/x86 build tools (v14.29-16.11)* + +Please note that Windows isn't natively able to run sh scripts, to remediate this, you can either: + +- use the one from Visual Studio if present + - e.g. `C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\Git\usr\bin\sh.exe` +- use the one from [Git for Windows](https://gitforwindows.org/) + - e.g. `C:\Program Files\Git\bin\sh.exe` + +When opening the solution for the first time on a more recent version than Visual Studio 2019, you will be prompted to retarget projects to one of the platform toolset available on your system. + ## Compiling on macOS or Linux -The following steps should be called from the VS developer command prompt. 1. Generate the VS solution and makefiles @@ -65,6 +84,8 @@ The following steps should be called from the VS developer command prompt. ./build.sh generate -configuration Release -platform x64 ``` +> :information_source: You can use the `-target-framework` option to target any valid .NET target framework. + 2. Compile the csproj files and makefiles ``` diff --git a/docs/UsersManual.md b/docs/UsersManual.md index bd4865f93d..0c45a91acb 100644 --- a/docs/UsersManual.md +++ b/docs/UsersManual.md @@ -39,6 +39,7 @@ There is also experimental support for these JavaScript-related targets: - N-API (Node.js) - QuickJS - TypeScript +- Emscripten # 3. Native Targets diff --git a/examples/Parser/Parser.cs b/examples/Parser/Parser.cs index a39518cdd2..bbad7b6ce7 100644 --- a/examples/Parser/Parser.cs +++ b/examples/Parser/Parser.cs @@ -23,12 +23,12 @@ public static void Main(string[] args) ParseSourceFile(file); } - public static bool ParseSourceFile(string file) + private static bool ParseSourceFile(string file) { // Lets setup the options for parsing the file. var parserOptions = new ParserOptions { - LanguageVersion = LanguageVersion.CPP11, + LanguageVersion = LanguageVersion.CPP20_GNU, // Verbose here will make sure the parser outputs some extra debugging // information regarding include directories, which can be helpful when @@ -37,13 +37,10 @@ public static bool ParseSourceFile(string file) }; // This will setup the necessary system include paths and arguments for parsing. - // It will probe into the registry (on Windows) and filesystem to find the paths - // of the system toolchains and necessary include directories. - parserOptions.Setup(); + parserOptions.Setup(Platform.Host); // We create the Clang parser and parse the source code. - var parser = new ClangParser(); - var parserResult = parser.ParseSourceFile(file, parserOptions); + var parserResult = ClangParser.ParseSourceFile(file, parserOptions); // If there was some kind of error parsing, then lets print some diagnostics. if (parserResult.Kind != ParserResultKind.Success) diff --git a/src/AST/ASTContext.cs b/src/AST/ASTContext.cs index 9aafd38a23..827ce261f4 100644 --- a/src/AST/ASTContext.cs +++ b/src/AST/ASTContext.cs @@ -11,7 +11,8 @@ public enum CppAbi Microsoft, ARM, iOS, - iOS64 + iOS64, + WebAssembly } /// diff --git a/src/AST/Class.cs b/src/AST/Class.cs index 2b1206a7ff..535236e350 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -291,6 +291,11 @@ public Method FindMethodByUSR(string usr) .FirstOrDefault(m => m.USR == usr); } + public Variable FindVariable(string name) + { + return Variables.FirstOrDefault(m => m.Name == name); + } + public override T Visit(IDeclVisitor visitor) { return visitor.VisitClassDecl(this); diff --git a/src/AST/ClassLayout.cs b/src/AST/ClassLayout.cs index f22a278d92..06d97e47c8 100644 --- a/src/AST/ClassLayout.cs +++ b/src/AST/ClassLayout.cs @@ -31,14 +31,7 @@ public struct VTableComponent public Declaration Declaration; /// Method declaration (if Kind == FunctionPointer). - public Method Method - { - get - { - Debug.Assert(Kind == VTableComponentKind.FunctionPointer); - return Declaration as Method; - } - } + public Method Method => Declaration as Method; } /// diff --git a/src/AST/Declaration.cs b/src/AST/Declaration.cs index 02176d6a87..2fc50d3122 100644 --- a/src/AST/Declaration.cs +++ b/src/AST/Declaration.cs @@ -189,15 +189,16 @@ public virtual string Name public static string QualifiedNameSeparator = "::"; public string GetQualifiedName(Func getName, - Func getNamespace) + Func getNamespace, bool getOriginal) { - if (Namespace == null) + DeclarationContext @namespace = getNamespace(this); + if (@namespace == null) return getName(this); - if (Namespace.IsRoot) + if (@namespace.IsRoot) return getName(this); - var namespaces = GatherNamespaces(getNamespace(this)); + var namespaces = GatherNamespaces(@namespace, getOriginal); var names = namespaces.Select(getName).ToList(); names.Add(getName(this)); @@ -206,7 +207,7 @@ public string GetQualifiedName(Func getName, return string.Join(QualifiedNameSeparator, names); } - public static IEnumerable GatherNamespaces(DeclarationContext @namespace) + public static IEnumerable GatherNamespaces(DeclarationContext @namespace, bool getOriginal) { var namespaces = new Stack(); @@ -216,7 +217,7 @@ public static IEnumerable GatherNamespaces(DeclarationContext @name var isInlineNamespace = currentNamespace is Namespace { IsInline: true }; if (!isInlineNamespace) namespaces.Push(currentNamespace); - currentNamespace = currentNamespace.Namespace; + currentNamespace = getOriginal ? currentNamespace.OriginalNamespace : currentNamespace.Namespace; } return namespaces; @@ -226,7 +227,7 @@ public string QualifiedName { get { - return GetQualifiedName(decl => GetDeclName(decl, decl.Name), decl => decl.Namespace); + return GetQualifiedName(decl => GetDeclName(decl, decl.Name), decl => decl.Namespace, false); } } @@ -235,7 +236,7 @@ public string QualifiedOriginalName get { return GetQualifiedName( - decl => GetDeclName(decl, decl.OriginalName), decl => decl.OriginalNamespace); + decl => GetDeclName(decl, decl.OriginalName), decl => decl.OriginalNamespace, true); } } @@ -244,7 +245,7 @@ public string QualifiedLogicalName get { return GetQualifiedName( - decl => GetDeclName(decl, decl.LogicalName), decl => decl.Namespace); + decl => GetDeclName(decl, decl.LogicalName), decl => decl.Namespace, false); } } @@ -253,7 +254,7 @@ public string QualifiedLogicalOriginalName get { return GetQualifiedName( - decl => GetDeclName(decl, decl.LogicalOriginalName), decl => decl.OriginalNamespace); + decl => GetDeclName(decl, decl.LogicalOriginalName), decl => decl.OriginalNamespace, true); } } diff --git a/src/AST/Property.cs b/src/AST/Property.cs index 9b78ea7dee..f0c469a3cb 100644 --- a/src/AST/Property.cs +++ b/src/AST/Property.cs @@ -22,109 +22,62 @@ public Property(Property property) parameters.AddRange(property.Parameters); } - public Type Type - { - get { return QualifiedType.Type; } - } + public Type Type => QualifiedType.Type; public QualifiedType QualifiedType { get; set; } - public bool IsStatic - { - get - { - return (GetMethod != null && GetMethod.IsStatic) || - (SetMethod != null && SetMethod.IsStatic); - } - } + public bool IsStatic => + GetMethod is {IsStatic: true} || + SetMethod is {IsStatic: true}; - public bool IsPure - { - get - { - return (GetMethod != null && GetMethod.IsPure) || - (SetMethod != null && SetMethod.IsPure); - } - } + public bool IsPure => + GetMethod is {IsPure: true} || + SetMethod is {IsPure: true}; - public bool IsVirtual - { - get - { - return (GetMethod != null && GetMethod.IsVirtual) || - (SetMethod != null && SetMethod.IsVirtual); - } - } + public bool IsVirtual => + GetMethod is {IsVirtual: true} || + SetMethod is {IsVirtual: true}; - public bool IsOverride - { - get - { - return (GetMethod != null && GetMethod.IsOverride) || - (SetMethod != null && SetMethod.IsOverride); - } - } + public bool IsOverride => + GetMethod is {IsOverride: true} || + SetMethod is {IsOverride: true}; public Method GetMethod { get; set; } public Method SetMethod { get; set; } - public bool HasGetter - { - get - { - return (GetMethod != null && - GetMethod.GenerationKind != GenerationKind.None) || - (Field != null && - Field.GenerationKind != GenerationKind.None); - } - } + public bool HasGetter => + (GetMethod != null && + GetMethod.GenerationKind != GenerationKind.None) || + (Field != null && + Field.GenerationKind != GenerationKind.None); - public bool HasSetter - { - get - { - return (SetMethod != null && - SetMethod.GenerationKind != GenerationKind.None) || - (Field != null && - (!Field.QualifiedType.IsConst() || - Field.Type.IsConstCharString()) && - Field.GenerationKind != GenerationKind.None); - } - } + public bool HasSetter => + (SetMethod != null && + SetMethod.GenerationKind != GenerationKind.None) || + (Field != null && + (!Field.QualifiedType.IsConst() || + Field.Type.IsConstCharString()) && + Field.GenerationKind != GenerationKind.None); // The field that should be get and set by this property public Field Field { get; set; } public Class ExplicitInterfaceImpl { get; set; } - private readonly List parameters = new List(); + private readonly List parameters = new(); /// /// Only applicable to index ([]) properties. /// - public List Parameters - { - get { return parameters; } - } + public List Parameters => parameters; - public bool IsIndexer - { - get - { - return GetMethod != null && - GetMethod.OperatorKind == CXXOperatorKind.Subscript; - } - } + public bool IsIndexer => + GetMethod is {OperatorKind: CXXOperatorKind.Subscript}; - public bool IsSynthetized - { - get - { - return (GetMethod != null && GetMethod.IsSynthetized) || - (SetMethod != null && SetMethod.IsSynthetized); - } - } + public bool IsSynthetized => + (GetMethod != null && GetMethod.IsSynthetized) || + (SetMethod != null && SetMethod.IsSynthetized); public override T Visit(IDeclVisitor visitor) { diff --git a/src/AST/Template.cs b/src/AST/Template.cs index 062254ee80..e71ee5b815 100644 --- a/src/AST/Template.cs +++ b/src/AST/Template.cs @@ -124,6 +124,8 @@ public class NonTypeTemplateParameter : Declaration /// public bool IsExpandedParameterPack { get; set; } + public QualifiedType Type { get; set; } + public override T Visit(IDeclVisitor visitor) { return visitor.VisitNonTypeTemplateParameterDecl(this); diff --git a/src/AST/Type.cs b/src/AST/Type.cs index 831b9f677b..d686f5d9a3 100644 --- a/src/AST/Type.cs +++ b/src/AST/Type.cs @@ -30,7 +30,7 @@ public abstract T Visit(ITypeVisitor visitor, TypeQualifiers quals public override string ToString() { - return TypePrinterDelegate(this); + return TypePrinterDelegate == null ? base.ToString() : TypePrinterDelegate(this); } public abstract object Clone(); diff --git a/src/AST/TypeExtensions.cs b/src/AST/TypeExtensions.cs index eb447d09fa..32333d6e6b 100644 --- a/src/AST/TypeExtensions.cs +++ b/src/AST/TypeExtensions.cs @@ -92,6 +92,25 @@ public static bool IsPointerToPrimitiveType(this Type t, PrimitiveType primitive return ptr.Pointee.IsPrimitiveType(primitive); } + public static bool IsPointerToEnum(this Type t) + { + var ptr = t as PointerType; + if (ptr == null) + return false; + return ptr.Pointee.IsEnumType(); + } + + public static bool IsPointerToEnum(this Type t, out Enumeration @enum) + { + var ptr = t as PointerType; + if (ptr == null) + { + @enum = null; + return false; + } + return ptr.Pointee.TryGetEnum(out @enum); + } + public static bool IsPointerTo(this Type t, out T type) where T : Type { var pointee = t.GetPointee(); diff --git a/src/ASTViewer/AstModel.cpp b/src/ASTViewer/AstModel.cpp deleted file mode 100644 index e0d8a388d9..0000000000 --- a/src/ASTViewer/AstModel.cpp +++ /dev/null @@ -1,141 +0,0 @@ -#include "AstModel.h" -#include - - -AstModel::AstModel(GenericAstNode *data, QObject *parent): - QAbstractItemModel(parent), - rootItem(data) -{ -} - -AstModel::~AstModel() -{ -} - -int AstModel::columnCount(const QModelIndex &parent) const -{ - return 1; -} - -QVariant AstModel::data(const QModelIndex &index, int role) const -{ - if (!index.isValid()) - return QVariant(); - - if (role != Qt::DisplayRole && role != Qt::ForegroundRole && role != Qt::NodeRole) - return QVariant(); - - auto item = static_cast(index.internalPointer()); - switch (role) - { - case Qt::DisplayRole: - return QVariant(QString::fromStdString(item->name)); - case Qt::ForegroundRole: - switch (item->getColor()) - { - case 0: - return QVariant(QBrush(Qt::GlobalColor::darkBlue)); - case 1: - return QVariant(QBrush(Qt::GlobalColor::darkGreen)); - default: - return QVariant(QBrush(Qt::GlobalColor::black)); - } - case Qt::NodeRole: - return QVariant::fromValue(item); - } - return QVariant(QString::fromStdString(item->name)); -} - -Qt::ItemFlags AstModel::flags(const QModelIndex &index) const -{ - if (!index.isValid()) - return 0; - - return QAbstractItemModel::flags(index); -} - -QVariant AstModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - if (orientation == Qt::Horizontal && role == Qt::DisplayRole) - return QVariant("Test"); - - return QVariant(); -} - -QModelIndex AstModel::index(int row, int column, const QModelIndex &parent) const -{ - if (!hasIndex(row, column, parent)) - return QModelIndex(); - - - if (!parent.isValid()) - { - return rootIndex(); - } - - auto parentItem = static_cast(parent.internalPointer()); - auto &childItem = parentItem->myChidren[row]; - if (childItem) - return createIndex(row, column, childItem.get()); - else - return QModelIndex(); -} - -QModelIndex AstModel::rootIndex() const -{ - return createIndex(0, 0, rootItem); -} - -QModelIndex AstModel::parent(const QModelIndex &index) const -{ - if (!index.isValid()) - return QModelIndex(); - - GenericAstNode *childItem = static_cast(index.internalPointer()); - if (childItem == rootItem || childItem->myParent == nullptr) - return QModelIndex(); - - GenericAstNode *parentItem = childItem->myParent; - - if (parentItem == rootItem) - return rootIndex(); - auto grandFather = parentItem->myParent; - auto parentRow = grandFather == nullptr ? - 0 : - grandFather->findChildIndex(parentItem); - - return createIndex(parentRow, 0, parentItem); -} - -int AstModel::rowCount(const QModelIndex &parent) const -{ - GenericAstNode *parentItem; - if (parent.column() > 0) - return 0; - - if (parent.isValid()) - { - parentItem = static_cast(parent.internalPointer()); - return parentItem->myChidren.size(); - } - else - { - return 1; - } -} - -bool AstModel::hasChildren(const QModelIndex &parent) const -{ - GenericAstNode *parentItem; - if (parent.column() > 0) - return false; - - if (parent.isValid()) - parentItem = static_cast(parent.internalPointer()); - else - parentItem = rootItem; - - return !parentItem->myChidren.empty(); - -} - diff --git a/src/ASTViewer/AstModel.h b/src/ASTViewer/AstModel.h deleted file mode 100644 index 3c6c46a56b..0000000000 --- a/src/ASTViewer/AstModel.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include "AstReader.h" - -namespace Qt -{ -int const NodeRole = UserRole + 1; -} - -Q_DECLARE_METATYPE(GenericAstNode*) - -class AstModel : public QAbstractItemModel -{ - Q_OBJECT - -public: - explicit AstModel(GenericAstNode *data, QObject *parent = 0); - ~AstModel(); - - QVariant data(const QModelIndex &index, int role) const override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex &index) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QModelIndex rootIndex() const; - bool hasChildren(const QModelIndex &parent = QModelIndex()) const override; - -private: - void setupModelData(const QStringList &lines, GenericAstNode *parent); - - GenericAstNode *rootItem; -}; \ No newline at end of file diff --git a/src/ASTViewer/AstReader.cpp b/src/ASTViewer/AstReader.cpp deleted file mode 100644 index 4b07a8edad..0000000000 --- a/src/ASTViewer/AstReader.cpp +++ /dev/null @@ -1,543 +0,0 @@ -#include "AstReader.h" -#include -#include "CommandLineSplitter.h" -#include -#include "ClangUtilities/StringLiteralExtractor.h" -#include "ClangUtilities/TemplateUtilities.h" - - -#pragma warning (push) -#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#pragma warning (pop) - -using namespace clang; - -namespace props -{ - std::string const Name = "Name"; - std::string const Mangling = "Mangling"; - std::string const Referenced = "Referenced name"; - std::string const Resolved = "Resolved name"; - std::string const Value = "Value"; - std::string const InterpretedValue = "Interpreted value"; - std::string const IsTemplateDecl = "Is template declaration"; - std::string const IsGenerated = "Generated"; - std::string const Type = "Type"; -} - - -CFG::BuildOptions getCFGBuildOptions() -{ - CFG::BuildOptions cfgBuildOptions; // TODO: Initialize it correctly - cfgBuildOptions.AddImplicitDtors = true; - cfgBuildOptions.AddTemporaryDtors = true; - cfgBuildOptions.AddCXXDefaultInitExprInCtors = true; - cfgBuildOptions.AddInitializers = true; - return cfgBuildOptions; -} - -std::string getCFG(clang::FunctionDecl const *FD) -{ - try - { - auto& astContext = FD->getASTContext(); - auto cfgBuildOptions = getCFGBuildOptions(); - auto cfg = CFG::buildCFG(FD, FD->getBody(), &astContext, cfgBuildOptions); - if (!cfg) - return ""; - std::string dumpBuf; - llvm::raw_string_ostream dumpBufOS(dumpBuf); - - cfg->print(dumpBufOS, astContext.getLangOpts(), false); - auto dumped = dumpBufOS.str(); - return dumped; - } - catch (std::exception &e) - { - return std::string(""; - } -} - - - -GenericAstNode::GenericAstNode() : -myParent(nullptr), hasDetails(false) -{ - -} - -int GenericAstNode::findChildIndex(GenericAstNode *node) -{ - auto it = std::find_if(myChidren.begin(), myChidren.end(), [node](std::unique_ptr const & n){return n.get() == node; }); - return it == myChidren.end() ? - -1 : - it - myChidren.begin(); -} - -void GenericAstNode::attach(std::unique_ptr child) -{ - child->myParent = this; - myChidren.push_back(std::move(child)); -} - -//struct SourceRangeVisitor : boost::static_visitor -//{ -// template -// SourceRange operator()(T const *t) const -// { -// if (t == nullptr) -// return SourceRange(); -// return t->getSourceRange(); -// } -//}; - -SourceRange GenericAstNode::getRange() -{ - //return boost::apply_visitor(SourceRangeVisitor(), myAstNode); - return SourceRange(); -} - -bool GenericAstNode::getRangeInMainFile(std::pair &result, clang::SourceManager const &manager, clang::ASTContext &context) -{ - auto range = getRange(); - if (range.isInvalid()) - { - return false; - } - auto start = manager.getDecomposedSpellingLoc(range.getBegin()); - auto end = manager.getDecomposedSpellingLoc(clang::Lexer::getLocForEndOfToken(range.getEnd(), 0, manager, context.getLangOpts())); - if (start.first != end.first || start.first != manager.getMainFileID()) - { - //Not in the same file, or not in the main file (probably #included) - return false; - } - result = std::make_pair(start.second, end.second); - return true; -} - - -//struct NodeColorVisitor : boost::static_visitor -//{ -// int operator()(Decl const *) const -// { -// return 0; -// } -// int operator()(Stmt const *) const -// { -// return 1; -// } -//}; - -int GenericAstNode::getColor() -{ - //return boost::apply_visitor(NodeColorVisitor(), myAstNode); - return 0; -} - - -void GenericAstNode::setProperty(std::string const &propertyName, std::string const &value) -{ - myProperties[propertyName] = value; -} - -GenericAstNode::Properties const &GenericAstNode::getProperties() const -{ - return myProperties; -} - - - - -class AstDumpVisitor : public RecursiveASTVisitor -{ -public: - using PARENT = clang::RecursiveASTVisitor; - AstDumpVisitor(clang::ASTContext &context, GenericAstNode *rootNode) : - myRootNode(rootNode), - myAstContext(context) - { - myStack.push_back(myRootNode); - } - - bool shouldVisitTemplateInstantiations() const - { - return true; - } - - bool shouldVisitImplicitCode() const - { - return true; - } - - std::string getMangling(clang::NamedDecl const *ND) - { - if (auto funcContext = dyn_cast(ND->getDeclContext())) - { - if (funcContext->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) - { - return ""; - } - } - - std::vector containers; - auto currentElement = dyn_cast(ND->getDeclContext()); - while (currentElement) - { - containers.push_back(currentElement); - currentElement = dyn_cast(currentElement->getDeclContext()); - } - for (auto tag : containers) - { - if (auto partialSpe = dyn_cast(tag)) - { - return "getNameAsString() + ": " + ND->getNameAsString() + ">"; - } - else if (auto recContext = dyn_cast(tag)) - { - if (recContext->getDescribedClassTemplate() != nullptr) - { - return "getNameAsString() + ": " + ND->getNameAsString() + ">"; - } - } - } - - auto mangleContext = std::unique_ptr{ND->getASTContext().createMangleContext()}; - std::string FrontendBuf; - llvm::raw_string_ostream FrontendBufOS(FrontendBuf); - - if (auto ctor = dyn_cast(ND)) - { - mangleContext->mangleCXXCtor(ctor, CXXCtorType::Ctor_Complete, FrontendBufOS); - } - else if (auto dtor = dyn_cast(ND)) - { - mangleContext->mangleCXXDtor(dtor, CXXDtorType::Dtor_Complete, FrontendBufOS); - } - else if (mangleContext->shouldMangleDeclName(ND) && !isa(ND)) - { - mangleContext->mangleName(ND, FrontendBufOS); - } - else - { - return ND->getNameAsString(); - } - return FrontendBufOS.str(); - } - - - bool TraverseDecl(clang::Decl *decl) - { - if (decl == nullptr) - { - return PARENT::TraverseDecl(decl); - } - auto node = std::make_unique(); - node->myAstNode = decl; - node->name = decl->getDeclKindName() + std::string("Decl"); // Try to mimick clang default dump - if (auto *FD = dyn_cast(decl)) - { -#ifndef NDEBUG - auto &mngr = FD->getASTContext().getSourceManager(); - auto fileName = mngr.getFilename(FD->getLocation()).str(); - bool invalid; - auto startingLine = mngr.getExpansionLineNumber(FD->getLocation(), &invalid); - - std::string FrontendBuf; - llvm::raw_string_ostream FrontendBufOS(FrontendBuf); - clang::PrintingPolicy policyForDebug(FD->getASTContext().getLangOpts()); - FD->getNameForDiagnostic(FrontendBufOS, policyForDebug, true); - auto debugName = FrontendBufOS.str(); - - RecordDecl const*containingClass = nullptr; - if (FD->isCXXClassMember()) - { - auto methodDecl = cast(FD); - containingClass = cast(methodDecl->getDeclContext()); - } -#endif - - node->name += " " + clang_utilities::getFunctionPrototype(FD, false); - if (FD->getTemplatedKind() != FunctionDecl::TK_FunctionTemplate) - { - node->setProperty(props::Mangling, getMangling(FD)); - } - node->setProperty(props::Name, clang_utilities::getFunctionPrototype(FD, true)); - if (auto *MD = dyn_cast(FD)) - { - node->setProperty(props::IsGenerated, MD->isUserProvided() ? "False" : "True"); - - } - node->hasDetails = true; - node->detailsTitle = "Control flow graph"; - node->detailsComputer = [FD]() {return getCFG(FD); }; - } - else if (auto *PVD = dyn_cast(decl)) - { - if (auto *PFD = dyn_cast_or_null(decl->getParentFunctionOrMethod())) - { - if (PFD->getTemplatedKind() != FunctionDecl::TK_FunctionTemplate) - { - node->setProperty(props::Mangling, getMangling(PFD)); - } - } - else - { - node->setProperty(props::Mangling, getMangling(PVD)); - } - node->setProperty(props::Name, PVD->getNameAsString()); - } - else if (auto *VD = dyn_cast(decl)) - { - //node->setProperty(props::Mangling, getMangling(VD)); - node->setProperty(props::Name, VD->getNameAsString()); - node->setProperty(props::Type, clang_utilities::getTypeName(VD->getType(), true)); - } - else if (auto *ECD = dyn_cast(decl)) - { - node->setProperty(props::Name, ECD->getNameAsString()); - node->setProperty(props::Value, ECD->getInitVal().toString(10)); - } - else if (auto *tag = dyn_cast(decl)) - { - std::string nameBuf; - llvm::raw_string_ostream os(nameBuf); - - if (TypedefNameDecl *Typedef = tag->getTypedefNameForAnonDecl()) - os << Typedef->getIdentifier()->getName(); - else if (tag->getIdentifier()) - os << tag->getIdentifier()->getName(); - else - os << "No name"; - - if (auto templateInstance = dyn_cast(tag)) - { - clang::PrintingPolicy policy(templateInstance->getASTContext().getLangOpts()); - clang_utilities::printTemplateArguments(os, policy, &templateInstance->getTemplateArgs(), false); - } - node->name += " " + tag->getNameAsString(); - node->setProperty(props::Name, os.str()); - } - else if (auto *ND = dyn_cast(decl)) - { - - - node->name += " " + ND->getNameAsString(); - node->setProperty(props::Name, ND->getNameAsString()); - } - - auto nodePtr = node.get(); - myStack.back()->attach(std::move(node)); - myStack.push_back(nodePtr); - auto res = PARENT::TraverseDecl(decl); - myStack.pop_back(); - return res; - } - - bool TraverseStmt(clang::Stmt *stmt) - { - if (stmt == nullptr) - { - return PARENT::TraverseStmt(stmt); - } - auto node = std::make_unique(); - node->myAstNode = stmt; - node->name = stmt->getStmtClassName(); - auto nodePtr = node.get(); - myStack.back()->attach(std::move(node)); - myStack.push_back(nodePtr); - auto res = PARENT::TraverseStmt(stmt); - myStack.pop_back(); - return res; - } - - bool VisitStringLiteral(clang::StringLiteral *s) - { - myStack.back()->name += (" " + s->getBytes()).str(); - myStack.back()->setProperty(props::InterpretedValue, s->getBytes()); - auto parts = clang_utilities::splitStringLiteral(s, myAstContext.getSourceManager(), myAstContext.getLangOpts(), myAstContext.getTargetInfo()); - if (parts.size() == 1) - { - myStack.back()->setProperty(props::Value, parts[0]); - - } - else - { - int i = 0; - for (auto &part : parts) - { - ++i; - myStack.back()->setProperty(props::Value + " " + std::to_string(i), part); - - } - } - return true; - } - - bool VisitIntegerLiteral(clang::IntegerLiteral *i) - { - bool isSigned = i->getType()->isSignedIntegerType(); - myStack.back()->setProperty(props::Value, i->getValue().toString(10, isSigned)); - return true; - } - - bool VisitCharacterLiteral(clang::CharacterLiteral *c) - { - myStack.back()->setProperty(props::Value, std::string(1, c->getValue())); - return true; - } - - bool VisitFloatingLiteral(clang::FloatingLiteral *f) - { - myStack.back()->setProperty(props::Value, std::to_string(f->getValueAsApproximateDouble())); - return true; - } - - bool VisitCXXRecordDecl(clang::CXXRecordDecl *r) - { - myStack.back()->setProperty(props::IsTemplateDecl, std::to_string(r->getDescribedClassTemplate() != nullptr)); - return true; - } - - - void addReference(GenericAstNode *node, clang::NamedDecl *referenced, std::string const &label) - { - auto funcDecl = dyn_cast(referenced); - myStack.back()->setProperty(label, funcDecl == nullptr ? - referenced->getNameAsString() : - clang_utilities::getFunctionPrototype(funcDecl, false)); - } - - bool VisitDeclRefExpr(clang::DeclRefExpr *ref) - { - addReference(myStack.back(), ref->getDecl(), props::Referenced); - addReference(myStack.back(), ref->getFoundDecl(), props::Resolved); - - return true; - } - - bool TraverseType(clang::QualType type) - { - if (type.isNull()) - { - return PARENT::TraverseType(type); - } - auto node = std::make_unique(); - //node->myType = d; - node->name = type->getTypeClassName(); - auto nodePtr = node.get(); - myStack.back()->attach(std::move(node)); - myStack.push_back(nodePtr); - auto res = PARENT::TraverseType(type); - myStack.pop_back(); - return res; - } - -private: - std::vector myStack; - GenericAstNode *myRootNode; - ASTContext &myAstContext; -}; - - -AstReader::AstReader() : isReady(false) -{ -} - -clang::SourceManager &AstReader::getManager() -{ - return myAst->getSourceManager(); -} - -clang::ASTContext &AstReader::getContext() -{ - return myAst->getASTContext(); -} - -GenericAstNode *AstReader::getRealRoot() -{ - return myArtificialRoot->myChidren.front().get(); -} - -GenericAstNode *AstReader::findPosInChildren(std::vector> const &candidates, int position) -{ - for (auto &candidate : candidates) - { - std::pair location; - if (!candidate->getRangeInMainFile(location, getManager(), getContext())) - { - continue; - } - if (location.first <= position && position <= location.second) - { - return candidate.get(); - } - } - return nullptr; -} - -std::vector AstReader::getBestNodeMatchingPosition(int position) -{ - std::vector result; - auto currentNode = getRealRoot(); - result.push_back(currentNode); - currentNode = currentNode->myChidren[0].get(); - result.push_back(currentNode); // Translation unit does not have position - while (true) - { - auto bestChild = findPosInChildren(currentNode->myChidren, position); - if (bestChild == nullptr) - { - return result; - } - result.push_back(bestChild); - currentNode = bestChild; - } -} - -GenericAstNode *AstReader::readAst(std::string const &sourceCode, std::string const &options) -{ - mySourceCode = sourceCode; - myArtificialRoot = std::make_unique(); - auto root = std::make_unique(); - root->name = "AST"; - myArtificialRoot->attach(std::move(root)); - - auto args = splitCommandLine(options); - - std::cout << "Launching Clang to create AST" << std::endl; - //myAst = clang::tooling::buildASTFromCodeWithArgs(mySourceCode, args); - myAst = nullptr; - if (myAst != nullptr) - { - for (auto it = myAst->top_level_begin(); it != myAst->top_level_end(); ++it) - { - //(*it)->dumpColor(); - } - std::cout << "Visiting AST and creating Qt Tree" << std::endl; - auto visitor = AstDumpVisitor{ myAst->getASTContext(), getRealRoot() }; - visitor.TraverseDecl(myAst->getASTContext().getTranslationUnitDecl()); - } - isReady = true; - return myArtificialRoot.get(); -} - -bool AstReader::ready() -{ - return isReady; -} - -void AstReader::dirty() -{ - isReady = false; -} - diff --git a/src/ASTViewer/AstReader.h b/src/ASTViewer/AstReader.h deleted file mode 100644 index 3796aa9b22..0000000000 --- a/src/ASTViewer/AstReader.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once - -#pragma warning (push) -#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996) -#include "clang/Frontend/TextDiagnosticBuffer.h" -#include "clang/Tooling/CommonOptionsParser.h" -#include "clang/Tooling/Tooling.h" -#include "llvm/Support/CommandLine.h" -#include "clang/Basic/SourceLocation.h" -#pragma warning(pop) -#include -#include - - -class GenericAstNode -{ -public: - GenericAstNode(); - int findChildIndex(GenericAstNode *node); // Return -1 if not found - void attach(std::unique_ptr child); - std::string name; - std::vector> myChidren; - bool getRangeInMainFile(std::pair &result, clang::SourceManager const &manager, clang::ASTContext &context); // Return false if the range is not fully in the main file - clang::SourceRange getRange(); - int getColor(); // Will return a color identifier How this is linked to the real color is up to the user - using Properties = std::map; - void setProperty(std::string const &propertyName, std::string const &value); - Properties const &getProperties() const; - std::variant myAstNode; - GenericAstNode *myParent; - - bool hasDetails; - std::string detailsTitle; - std::string details; - std::function detailsComputer; - -private: - Properties myProperties; -}; - -class AstReader -{ -public: - AstReader(); - GenericAstNode *readAst(std::string const &sourceCode, std::string const &options); - clang::SourceManager &getManager(); - clang::ASTContext &getContext(); - GenericAstNode *getRealRoot(); - std::vector getBestNodeMatchingPosition(int position); // Return the path from root to the node - bool ready(); - void dirty(); // Ready will be false until the reader is run again -private: - GenericAstNode *findPosInChildren(std::vector> const &candidates, int position); - std::string args; - std::string mySourceCode; // Needs to stay alive while we navigate the tree - std::unique_ptr myAst; - std::unique_ptr myArtificialRoot; // We need an artificial root on top of the real root, because the root is not displayed by Qt - bool isReady; -}; - diff --git a/src/ASTViewer/ClangUtilities/StringLiteralExtractor.cpp b/src/ASTViewer/ClangUtilities/StringLiteralExtractor.cpp deleted file mode 100644 index 70f601270d..0000000000 --- a/src/ASTViewer/ClangUtilities/StringLiteralExtractor.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#include "StringLiteralExtractor.h" - -#pragma warning (push) -#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996 4146) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#pragma warning (pop) - -using namespace llvm; -using namespace clang; - -namespace clang_utilities { - -// This function is an direct adaptation from ProcessCharEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part) -unsigned ProcessCharEscape(const char *ThisTokBegin, - const char *&ThisTokBuf, - const char *ThisTokEnd, bool &HadError, - FullSourceLoc Loc, unsigned CharWidth, - const LangOptions &Features) -{ - // Skip the '\' char. - ++ThisTokBuf; - - // We know that this character can't be off the end of the buffer, because - // that would have been \", which would not have been the end of string. - unsigned ResultChar = *ThisTokBuf++; - switch (ResultChar) { - // These map to themselves. - case '\\': case '\'': case '"': case '?': break; - - // These have fixed mappings. - case 'a': - // TODO: K&R: the meaning of '\\a' is different in traditional C - ResultChar = 7; - break; - case 'b': - ResultChar = 8; - break; - case 'e': - ResultChar = 27; - break; - case 'E': - ResultChar = 27; - break; - case 'f': - ResultChar = 12; - break; - case 'n': - ResultChar = 10; - break; - case 'r': - ResultChar = 13; - break; - case 't': - ResultChar = 9; - break; - case 'v': - ResultChar = 11; - break; - case 'x': { // Hex escape. - ResultChar = 0; - if (ThisTokBuf == ThisTokEnd || !isHexDigit(*ThisTokBuf)) { - HadError = 1; - break; - } - - // Hex escapes are a maximal series of hex digits. - bool Overflow = false; - for (; ThisTokBuf != ThisTokEnd; ++ThisTokBuf) { - int CharVal = llvm::hexDigitValue(ThisTokBuf[0]); - if (CharVal == -1) break; - // About to shift out a digit? - if (ResultChar & 0xF0000000) - Overflow = true; - ResultChar <<= 4; - ResultChar |= CharVal; - } - - // See if any bits will be truncated when evaluated as a character. - if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) { - Overflow = true; - ResultChar &= ~0U >> (32 - CharWidth); - } - - // Check for overflow. - break; - } - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': { - // Octal escapes. - --ThisTokBuf; - ResultChar = 0; - - // Octal escapes are a series of octal digits with maximum length 3. - // "\0123" is a two digit sequence equal to "\012" "3". - unsigned NumDigits = 0; - do { - ResultChar <<= 3; - ResultChar |= *ThisTokBuf++ - '0'; - ++NumDigits; - } while (ThisTokBuf != ThisTokEnd && NumDigits < 3 && - ThisTokBuf[0] >= '0' && ThisTokBuf[0] <= '7'); - - // Check for overflow. Reject '\777', but not L'\777'. - if (CharWidth != 32 && (ResultChar >> CharWidth) != 0) { - ResultChar &= ~0U >> (32 - CharWidth); - } - break; - } - - // Otherwise, these are not valid escapes. - case '(': case '{': case '[': case '%': - // GCC accepts these as extensions. We warn about them as such though. - break; - default: - break; - } - return ResultChar; -} - - -// This function is an direct adaptation from ProcessUCNEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part) -bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, - const char *ThisTokEnd, - uint32_t &UcnVal, unsigned short &UcnLen, - FullSourceLoc Loc, - const LangOptions &Features, - bool in_char_string_literal) { - const char *UcnBegin = ThisTokBuf; - - // Skip the '\u' char's. - ThisTokBuf += 2; - - if (ThisTokBuf == ThisTokEnd || !isHexDigit(*ThisTokBuf)) { - return false; - } - UcnLen = (ThisTokBuf[-1] == 'u' ? 4 : 8); - unsigned short UcnLenSave = UcnLen; - for (; ThisTokBuf != ThisTokEnd && UcnLenSave; ++ThisTokBuf, UcnLenSave--) { - int CharVal = llvm::hexDigitValue(ThisTokBuf[0]); - if (CharVal == -1) break; - UcnVal <<= 4; - UcnVal |= CharVal; - } - // If we didn't consume the proper number of digits, there is a problem. - if (UcnLenSave) { - return false; - } - - // Check UCN constraints (C99 6.4.3p2) [C++11 lex.charset p2] - if ((0xD800 <= UcnVal && UcnVal <= 0xDFFF) || // surrogate codepoints - UcnVal > 0x10FFFF) { // maximum legal UTF32 value - return false; - } - - // C++11 allows UCNs that refer to control characters and basic source - // characters inside character and string literals - if (UcnVal < 0xa0 && - (UcnVal != 0x24 && UcnVal != 0x40 && UcnVal != 0x60)) { // $, @, ` - bool IsError = (!Features.CPlusPlus11 || !in_char_string_literal); - if (IsError) - return false; - } - return true; -} - -// This function is an direct adaptation from ProcessUCNEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part) -int MeasureUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, - const char *ThisTokEnd, unsigned CharByteWidth, - const LangOptions &Features, bool &HadError) { - // UTF-32: 4 bytes per escape. - if (CharByteWidth == 4) - return 4; - - uint32_t UcnVal = 0; - unsigned short UcnLen = 0; - FullSourceLoc Loc; - - if (!ProcessUCNEscape(ThisTokBegin, ThisTokBuf, ThisTokEnd, UcnVal, - UcnLen, Loc, Features, true)) { - HadError = true; - return 0; - } - - // UTF-16: 2 bytes for BMP, 4 bytes otherwise. - if (CharByteWidth == 2) - return UcnVal <= 0xFFFF ? 2 : 4; - - // UTF-8. - if (UcnVal < 0x80) - return 1; - if (UcnVal < 0x800) - return 2; - if (UcnVal < 0x10000) - return 3; - return 4; -} - - - -// This function is just the same as convertUTF16ToUTF8String, but adapted to UTF32, since it did not exist in clang -bool convertUTF32ToUTF8String(ArrayRef SrcBytes, std::string &Out) { - assert(Out.empty()); - - // Error out on an uneven byte count. - if (SrcBytes.size() % 4) - return false; - - // Avoid OOB by returning early on empty input. - if (SrcBytes.empty()) - return true; - - const UTF32 *Src = reinterpret_cast(SrcBytes.begin()); - const UTF32 *SrcEnd = reinterpret_cast(SrcBytes.end()); - - // Byteswap if necessary. - // Ignore any potential BOM: We won't have the here... - - // Just allocate enough space up front. We'll shrink it later. Allocate - // enough that we can fit a null terminator without reallocating. - Out.resize(SrcBytes.size() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1); - UTF8 *Dst = reinterpret_cast(&Out[0]); - UTF8 *DstEnd = Dst + Out.size(); - - ConversionResult CR = - ConvertUTF32toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion); - assert(CR != targetExhausted); - - if (CR != conversionOK) { - Out.clear(); - return false; - } - - Out.resize(reinterpret_cast(Dst)-&Out[0]); - Out.push_back(0); - Out.pop_back(); - return true; -} - - -// This function is an adaptation from StringLiteral::getLocationOfByte in llvm-3.7.1\src\tools\clang\lib\AST\Expr.cpp -std::vector -splitStringLiteral(clang::StringLiteral *S, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target) -{ - // Loop over all of the tokens in this string until we find the one that - // contains the byte we're looking for. - unsigned TokNo = 0; - - std::vector result; - for (TokNo = 0; TokNo < S->getNumConcatenated(); ++TokNo) - { - SourceLocation StrTokLoc = S->getStrTokenLoc(TokNo); - - // Get the spelling of the string so that we can get the data that makes up - // the string literal, not the identifier for the macro it is potentially - // expanded through. - SourceLocation StrTokSpellingLoc = SM.getSpellingLoc(StrTokLoc); - - // Re-lex the token to get its length and original spelling. - std::pair LocInfo = SM.getDecomposedLoc(StrTokSpellingLoc); - bool Invalid = false; - StringRef Buffer = SM.getBufferData(LocInfo.first, &Invalid); - if (Invalid) - continue; // We ignore this part - - const char *StrData = Buffer.data() + LocInfo.second; - - // Create a lexer starting at the beginning of this token. - Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), Features, - Buffer.begin(), StrData, Buffer.end()); - Token TheTok; - TheLexer.LexFromRawLexer(TheTok); - if (TheTok.isAnyIdentifier()) - { - // It should not be, since we are parsing inside a string literal, but it can happen with special macros such as __func__ - // of __PRETTY_FUNCTION__ that are not resolved at this time. In that case, we just ignore them... - continue; - } - // Get the spelling of the token. - SmallString<32> SpellingBuffer; - SpellingBuffer.resize(TheTok.getLength()); - - bool StringInvalid = false; - const char *SpellingPtr = &SpellingBuffer[0]; - unsigned TokLen = Lexer::getSpelling(TheTok, SpellingPtr, SM, Features, &StringInvalid); - if (StringInvalid) - continue; - - const char *SpellingStart = SpellingPtr; - const char *SpellingEnd = SpellingPtr + TokLen; - result.push_back(std::string(SpellingStart, SpellingEnd)); - - } - return result; -} - -} // namespace clang_utilities diff --git a/src/ASTViewer/ClangUtilities/StringLiteralExtractor.h b/src/ASTViewer/ClangUtilities/StringLiteralExtractor.h deleted file mode 100644 index 72d7ca264c..0000000000 --- a/src/ASTViewer/ClangUtilities/StringLiteralExtractor.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include -#pragma warning (push) -#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996 4146) -#include -#include -#include -#include -#include -#pragma warning (pop) - - -namespace clang_utilities { - -// This function is an direct adaptation from ProcessCharEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part) -unsigned ProcessCharEscape(const char *ThisTokBegin, - const char *&ThisTokBuf, - const char *ThisTokEnd, bool &HadError, - clang::FullSourceLoc Loc, unsigned CharWidth, - const clang::LangOptions &Features); - -// This function is an direct adaptation from ProcessUCNEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part) -bool ProcessUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, - const char *ThisTokEnd, - uint32_t &UcnVal, unsigned short &UcnLen, - clang::FullSourceLoc Loc, - const clang::LangOptions &Features, - bool in_char_string_literal = false); - - -// This function is an direct adaptation from ProcessUCNEscape in llvm-3.7.1\src\tools\clang\lib\Lex\LiteralSupport.cpp (just removed the diag part) -int MeasureUCNEscape(const char *ThisTokBegin, const char *&ThisTokBuf, - const char *ThisTokEnd, unsigned CharByteWidth, - const clang::LangOptions &Features, bool &HadError); - - -bool convertUTF32ToUTF8String(llvm::ArrayRef SrcBytes, std::string &Out); - - -std::vector -splitStringLiteral(clang::StringLiteral *S, const clang::SourceManager &SM, const clang::LangOptions &Features, const clang::TargetInfo &Target); - -} // namespace clang_utilities - diff --git a/src/ASTViewer/ClangUtilities/TemplateUtilities.cpp b/src/ASTViewer/ClangUtilities/TemplateUtilities.cpp deleted file mode 100644 index 1aa554994f..0000000000 --- a/src/ASTViewer/ClangUtilities/TemplateUtilities.cpp +++ /dev/null @@ -1,287 +0,0 @@ -#include "TemplateUtilities.h" - -#pragma warning (push) -#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996) -#include -#include -#include -#include -#include -#include -#include -#include -#pragma warning (pop) - -using namespace clang; -namespace clang_utilities { - - -void printDeclType(raw_ostream &out, PrintingPolicy const &policy, QualType T, StringRef DeclName, bool Pack) { - // Normally, a PackExpansionType is written as T[3]... (for instance, as a - // template argument), but if it is the type of a declaration, the ellipsis - // is placed before the name being declared. - if (auto *PET = T->getAs()) { - Pack = true; - T = PET->getPattern(); - } - T.print(out, policy, (Pack ? "..." : "") + DeclName); -} - -void printTemplateParameters(raw_ostream &out, PrintingPolicy const &policy, TemplateParameterList const *params) -{ - if (params == nullptr) - { - return; - } - - out << "<"; - for (unsigned i = 0, e = params->size(); i != e; ++i) { - if (i != 0) - out << ", "; - - auto param = params->getParam(i); - printTemplateParameter(out, policy, param); - } - out << ">"; - -} - -// Adapted from tools\clang\lib\AST\DeclPrinter.cpp DeclPrinter::PrintTemplateParameters -void printTemplateParameter(raw_ostream &out, PrintingPolicy const &policy, NamedDecl const *param) -{ - if (const TemplateTypeParmDecl *TTP = - dyn_cast(param)) { - - if (TTP->wasDeclaredWithTypename()) - out << "typename "; - else - out << "class "; - - if (TTP->isParameterPack()) - out << "..."; - - out << *TTP; - - if (TTP->hasDefaultArgument()) { - out << " = "; - out << TTP->getDefaultArgument().getAsString(policy); - }; - } - else if (const NonTypeTemplateParmDecl *NTTP = - dyn_cast(param)) { - StringRef Name; - if (IdentifierInfo *II = NTTP->getIdentifier()) - Name = II->getName(); - printDeclType(out, policy, NTTP->getType(), Name, NTTP->isParameterPack()); - - if (NTTP->hasDefaultArgument()) { - out << " = "; - NTTP->getDefaultArgument()->printPretty(out, nullptr, policy, 0); - } - } - else if (const TemplateTemplateParmDecl *TTPD = - dyn_cast(param)) { - out << "template"; - printTemplateParameters(out, policy, TTPD->getTemplateParameters()); - out << " class " << TTPD->getNameAsString(); - //VisitTemplateDecl(TTPD); - // FIXME: print the default argument, if present. - } -} - - -static void printIntegral(const TemplateArgument &TemplArg, - raw_ostream &out, const PrintingPolicy& policy) { - const ::clang::Type *T = TemplArg.getIntegralType().getTypePtr(); - const llvm::APSInt &Val = TemplArg.getAsIntegral(); - - if (const EnumType *ET = T->getAs()) { - for (const EnumConstantDecl* ECD : ET->getDecl()->enumerators()) { - // In Sema::CheckTemplateArugment, enum template arguments value are - // extended to the size of the integer underlying the enum type. This - // may create a size difference between the enum value and template - // argument value, requiring isSameValue here instead of operator==. - if (llvm::APSInt::isSameValue(ECD->getInitVal(), Val)) { - ECD->printQualifiedName(out, policy); - return; - } - } - } - - if (T->isBooleanType()) { - out << (Val.getBoolValue() ? "true" : "false"); - } - else if (T->isCharType()) { - const char Ch = Val.getZExtValue(); - out << ((Ch == '\'') ? "'\\" : "'"); - out.write_escaped(StringRef(&Ch, 1), /*UseHexEscapes=*/ true); - out << "'"; - } - else { - out << Val; - } -} - -void printTemplateName(raw_ostream &OS, const PrintingPolicy &policy, TemplateName const &name, bool qualifyNames = false) -{ - if (auto Template = name.getAsTemplateDecl()) - OS << (qualifyNames ? Template->getQualifiedNameAsString() : Template->getNameAsString()); - else if (auto QTN = name.getAsQualifiedTemplateName()) { - OS << (qualifyNames ? QTN->getDecl()->getQualifiedNameAsString() : QTN->getDecl()->getNameAsString()); - } - else if (auto DTN = name.getAsDependentTemplateName()) { - if (qualifyNames && DTN->getQualifier()) - DTN->getQualifier()->print(OS, policy); - OS << "template "; - - if (DTN->isIdentifier()) - OS << DTN->getIdentifier()->getName(); - else - OS << "operator " << getOperatorSpelling(DTN->getOperator()); - } - else if (auto subst = name.getAsSubstTemplateTemplateParm()) { - subst->getReplacement().print(OS, policy, !qualifyNames); - } - else if (auto SubstPack = name.getAsSubstTemplateTemplateParmPack()) - OS << *SubstPack->getParameterPack(); - else { - auto OTS = name.getAsOverloadedTemplate(); - (*OTS->begin())->printName(OS); - } -} - - - -// Adapted from tools\clang\lib\AST\TemplateBase.cpp TemplateArgument::print -void printTemplateArgument(raw_ostream &out, const PrintingPolicy &policy, TemplateArgument const &arg, bool qualifyNames) -{ - switch (arg.getKind()) { - case TemplateArgument::Null: - out << "(no value)"; - break; - - case TemplateArgument::Type: { - PrintingPolicy SubPolicy(policy); - SubPolicy.SuppressStrongLifetime = true; - arg.getAsType().print(out, SubPolicy); - break; - } - - case TemplateArgument::Declaration: { - NamedDecl *ND = cast(arg.getAsDecl()); - out << '&'; - if (ND->getDeclName()) { - // FIXME: distinguish between pointer and reference args? - ND->printQualifiedName(out); - } - else { - out << "(anonymous)"; - } - break; - } - - case TemplateArgument::NullPtr: - out << "nullptr"; - break; - - case TemplateArgument::Template: - // Orig: arg.getAsTemplate().print(out, policy); - { - auto templateName = arg.getAsTemplate(); - printTemplateName(out, policy, templateName, qualifyNames); - break; - } - - case TemplateArgument::TemplateExpansion: - arg.getAsTemplateOrTemplatePattern().print(out, policy); - out << "..."; - break; - - case TemplateArgument::Integral: { - printIntegral(arg, out, policy); - break; - } - - case TemplateArgument::Expression: - arg.getAsExpr()->printPretty(out, nullptr, policy); - break; - - case TemplateArgument::Pack: - out << "<"; - bool First = true; - for (const auto &P : arg.pack_elements()) { - if (First) - First = false; - else - out << ", "; - - P.print(policy, out); - } - out << ">"; - break; - } -} - -void printTemplateArguments(raw_ostream &out, const PrintingPolicy &policy, TemplateArgumentList const *args, bool qualifyNames) -{ - if (args == nullptr) - { - return; - } - out << "<"; - for (unsigned i = 0, e = args->size(); i != e; ++i) { - if (i != 0) - out << ", "; - - auto arg = args->get(i); - printTemplateArgument(out, policy, arg, qualifyNames); - } - out << ">"; - -} - -std::string getTypeName(QualType qualType, bool qualifyNames) -{ - auto langOptions = clang::LangOptions{}; - auto printPolicy = PrintingPolicy{ langOptions }; - printPolicy.SuppressSpecifiers = false; - printPolicy.ConstantArraySizeAsWritten = false; - return qualType.getAsString(printPolicy); - -} - -std::string getFunctionPrototype(FunctionDecl *f, bool qualifyNames) -{ - std::string prototypeBuf; - llvm::raw_string_ostream os(prototypeBuf); - PrintingPolicy policy(f->getASTContext().getLangOpts()); - policy.TerseOutput = false; - os << getTypeName(f->getReturnType(), qualifyNames) << ' ' << f->getNameAsString(); - if (f->getTemplatedKind() == FunctionDecl::TK_FunctionTemplateSpecialization || - // f->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || - f->getTemplatedKind() == FunctionDecl::TK_DependentFunctionTemplateSpecialization) - { - printTemplateArguments(os, policy, f->getTemplateSpecializationArgs(), qualifyNames); - } - if (f->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) - { - printTemplateParameters(os, policy, f->getDescribedFunctionTemplate()->getTemplateParameters()); - } - os << '('; - bool first = true; - for (auto param : f->parameters()) - { - if (!first) - { - os << ", "; - } - first = false; - - os << getTypeName(param->getType(), qualifyNames) << ' ' << param->getNameAsString(); - } - os << ')'; - return os.str(); -} - - -} // namespace clang_utilities diff --git a/src/ASTViewer/ClangUtilities/TemplateUtilities.h b/src/ASTViewer/ClangUtilities/TemplateUtilities.h deleted file mode 100644 index 60b4fb113f..0000000000 --- a/src/ASTViewer/ClangUtilities/TemplateUtilities.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#pragma warning (push) -#pragma warning (disable:4100 4127 4800 4512 4245 4291 4510 4610 4324 4267 4244 4996) -#include -#include -#include -#include -#pragma warning (pop) - -namespace clang_utilities { - -// Adapted from tools\clang\lib\AST\DeclPrinter.cpp DeclPrinter::PrintTemplateParameters -void printTemplateParameters(llvm::raw_ostream &out, clang::PrintingPolicy const &policy, const clang::TemplateParameterList *params); -void printTemplateParameter(llvm::raw_ostream &out, clang::PrintingPolicy const &policy, clang::NamedDecl const *param); - - -void printTemplateArguments(llvm::raw_ostream &out, const clang::PrintingPolicy &policy, clang::TemplateArgumentList const *args, bool qualifyNames); -// Adapted from tools\clang\lib\AST\TemplateBase.cpp TemplateArgument::print -void printTemplateArgument(llvm::raw_ostream &out, const clang::PrintingPolicy &policy, clang::TemplateArgument const &arg, bool qualifyNames); - -std::string getFunctionPrototype(clang::FunctionDecl *f, bool qualifyNames); -std::string getTypeName(clang::QualType qualType, bool qualifyNames); - - -} // namespace clang_utilities - diff --git a/src/ASTViewer/CommandLineSplitter.cpp b/src/ASTViewer/CommandLineSplitter.cpp deleted file mode 100644 index a0ea6ccc58..0000000000 --- a/src/ASTViewer/CommandLineSplitter.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifdef _WIN32 -#include -#else -#include -#endif - -#include -#include -#include - -std::vector splitCommandLine(std::string const &cmdline) -{ - int i; - char **argv = NULL; - int argc; - std::vector result; - // Posix. -#ifndef _WIN32 - { - wordexp_t p; - - // Note! This expands shell variables. - if (wordexp(cmdline.c_str(), &p, 0)) - { - return result; - } - - argc = p.we_wordc; - - if (!(argv = (char**) calloc(argc, sizeof(char *)))) - { - goto fail; - } - - for (i = 0; i < p.we_wordc; i++) - { - result.push_back(p.we_wordv[i]); - } - - wordfree(&p); - - return result; - fail: - wordfree(&p); - return result; - } -#else // WIN32 - { - wchar_t **wargs = NULL; - size_t needed = 0; - wchar_t *cmdlinew = NULL; - size_t len = cmdline.size() + 1; - - if (!(cmdlinew = static_cast(calloc(len, sizeof(wchar_t))))) - goto fail; - - if (!MultiByteToWideChar(CP_ACP, 0, cmdline.c_str(), -1, cmdlinew, len)) - goto fail; - - if (!(wargs = CommandLineToArgvW(cmdlinew, &argc))) - goto fail; - - // Convert from wchar_t * to ANSI char * - for (i = 0; i < argc; i++) - { - // Get the size needed for the target buffer. - // CP_ACP = Ansi Codepage. - needed = WideCharToMultiByte(CP_ACP, 0, wargs[i], -1, - NULL, 0, NULL, NULL); - char *argv; - if (!(argv = static_cast(malloc(needed)))) - goto fail; - - // Do the conversion. - needed = WideCharToMultiByte(CP_ACP, 0, wargs[i], -1, - argv, needed, NULL, NULL); - result.push_back(argv); - free(argv); - } - - if (wargs) LocalFree(wargs); - if (cmdlinew) free(cmdlinew); - return result; - - fail: - if (wargs) LocalFree(wargs); - if (cmdlinew) free(cmdlinew); - } -#endif // WIN32 -} \ No newline at end of file diff --git a/src/ASTViewer/CommandLineSplitter.h b/src/ASTViewer/CommandLineSplitter.h deleted file mode 100644 index 0f59566b18..0000000000 --- a/src/ASTViewer/CommandLineSplitter.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include -#include - -std::vector splitCommandLine(std::string const &cmdline); diff --git a/src/ASTViewer/Highlighter.cpp b/src/ASTViewer/Highlighter.cpp deleted file mode 100644 index a225857811..0000000000 --- a/src/ASTViewer/Highlighter.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "Highlighter.h" - -//! [0] -Highlighter::Highlighter(QTextDocument *parent) - : QSyntaxHighlighter(parent) -{ - HighlightingRule rule; - - keywordFormat.setForeground(Qt::darkBlue); - QStringList keywordPatterns; - keywordPatterns << "\\bchar\\b" << "\\bclass\\b" << "\\bconst\\b" - << "\\bdouble\\b" << "\\benum\\b" << "\\bexplicit\\b" - << "\\bfriend\\b" << "\\binline\\b" << "\\bint\\b" - << "\\blong\\b" << "\\bnamespace\\b" << "\\boperator\\b" - << "\\bprivate\\b" << "\\bprotected\\b" << "\\bpublic\\b" - << "\\bshort\\b" << "\\bsignals\\b" << "\\bsigned\\b" - << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b" - << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b" - << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b" - << "\\bvoid\\b" << "\\bvolatile\\b"; - foreach (const QString &pattern, keywordPatterns) { - rule.pattern = QRegExp(pattern); - rule.format = keywordFormat; - highlightingRules.append(rule); -//! [0] //! [1] - } -//! [1] - -//! [2] - classFormat.setFontWeight(QFont::Bold); - classFormat.setForeground(Qt::darkMagenta); - rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b"); - rule.format = classFormat; - highlightingRules.append(rule); -//! [2] - -//! [3] - singleLineCommentFormat.setForeground(Qt::darkGreen); - rule.pattern = QRegExp("//[^\n]*"); - rule.format = singleLineCommentFormat; - highlightingRules.append(rule); - - multiLineCommentFormat.setForeground(Qt::darkGreen); -//! [3] - -//! [4] - quotationFormat.setForeground(Qt::darkMagenta); - rule.pattern = QRegExp("\".*\""); - rule.format = quotationFormat; - highlightingRules.append(rule); -//! [4] - -//! [5] - functionFormat.setForeground(Qt::blue); - rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); - rule.format = functionFormat; - highlightingRules.append(rule); -//! [5] - -//! [6] - commentStartExpression = QRegExp("/\\*"); - commentEndExpression = QRegExp("\\*/"); -} -//! [6] - -//! [7] -void Highlighter::highlightBlock(const QString &text) -{ - foreach (const HighlightingRule &rule, highlightingRules) { - QRegExp expression(rule.pattern); - int index = expression.indexIn(text); - while (index >= 0) { - int length = expression.matchedLength(); - setFormat(index, length, rule.format); - index = expression.indexIn(text, index + length); - } - } -//! [7] //! [8] - setCurrentBlockState(0); -//! [8] - -//! [9] - int startIndex = 0; - if (previousBlockState() != 1) - startIndex = commentStartExpression.indexIn(text); - -//! [9] //! [10] - while (startIndex >= 0) { -//! [10] //! [11] - int endIndex = commentEndExpression.indexIn(text, startIndex); - int commentLength; - if (endIndex == -1) { - setCurrentBlockState(1); - commentLength = text.length() - startIndex; - } else { - commentLength = endIndex - startIndex - + commentEndExpression.matchedLength(); - } - setFormat(startIndex, commentLength, multiLineCommentFormat); - startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); - } -} -//! [11] diff --git a/src/ASTViewer/Highlighter.h b/src/ASTViewer/Highlighter.h deleted file mode 100644 index a034194dff..0000000000 --- a/src/ASTViewer/Highlighter.h +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the examples of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HIGHLIGHTER_H -#define HIGHLIGHTER_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QTextDocument; -QT_END_NAMESPACE - -//! [0] -class Highlighter : public QSyntaxHighlighter -{ - Q_OBJECT - -public: - Highlighter(QTextDocument *parent = 0); - -protected: - void highlightBlock(const QString &text) Q_DECL_OVERRIDE; - -private: - struct HighlightingRule - { - QRegExp pattern; - QTextCharFormat format; - }; - QVector highlightingRules; - - QRegExp commentStartExpression; - QRegExp commentEndExpression; - - QTextCharFormat keywordFormat; - QTextCharFormat classFormat; - QTextCharFormat singleLineCommentFormat; - QTextCharFormat multiLineCommentFormat; - QTextCharFormat quotationFormat; - QTextCharFormat functionFormat; -}; -//! [0] - -#endif // HIGHLIGHTER_H diff --git a/src/ASTViewer/LICENSE b/src/ASTViewer/LICENSE deleted file mode 100644 index 65c5ca88a6..0000000000 --- a/src/ASTViewer/LICENSE +++ /dev/null @@ -1,165 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - - This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - - 0. Additional Definitions. - - As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the GNU -General Public License. - - "The Library" refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - - The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - - 1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - - 2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort to - ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - - 3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that the - Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this license - document. - - 4. Combined Works. - - You may convey a Combined Work under terms of your choice that, -taken together, effectively do not restrict modification of the -portions of the Library contained in the Combined Work and reverse -engineering for debugging such modifications, if you also do each of -the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this license - document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of this - License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (a) uses at run time - a copy of the Library already present on the user's computer - system, and (b) will operate properly with a modified version - of the Library that is interface-compatible with the Linked - Version. - - e) Provide Installation Information, but only if you would otherwise - be required to provide such information under section 6 of the - GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the - Application with a modified version of the Linked Version. (If - you use option 4d0, the Installation Information must accompany - the Minimal Corresponding Source and Corresponding Application - Code. If you use option 4d1, you must provide the Installation - Information in the manner specified by section 6 of the GNU GPL - for conveying Corresponding Source.) - - 5. Combined Libraries. - - You may place library facilities that are a work based on the -Library side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work based - on the Library, uncombined with any other library facilities, - conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - - 6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - - Each version is given a distinguishing version number. If the -Library as you received it specifies that a certain numbered version -of the GNU Lesser General Public License "or any later version" -applies to it, you have the option of following the terms and -conditions either of that published version or of any later version -published by the Free Software Foundation. If the Library as you -received it does not specify a version number of the GNU Lesser -General Public License, you may choose any version of the GNU Lesser -General Public License ever published by the Free Software Foundation. - - If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. diff --git a/src/ASTViewer/MainWindow.cpp b/src/ASTViewer/MainWindow.cpp deleted file mode 100644 index a9c489921d..0000000000 --- a/src/ASTViewer/MainWindow.cpp +++ /dev/null @@ -1,169 +0,0 @@ -#include "MainWindow.h" -#include -#include -#include -#include -#include "AstModel.h" - -class UpdateLock -{ -public: - UpdateLock(bool &lock) : myLock(lock) - { - myLock = true; - } - ~UpdateLock() - { - myLock = false; - } - bool & myLock; -}; - -MainWindow::MainWindow(QWidget *parent) : - QMainWindow(parent), - isUpdateInProgress(false) -{ - myUi.setupUi(this); - - connect(myUi.actionRefresh, &QAction::triggered, this, &MainWindow::RefreshAst); - - myHighlighter = new Highlighter(myUi.codeViewer->document()); - myUi.nodeProperties->setHeaderLabels({ "Property", "Value" }); - connect(myUi.codeViewer, &QTextEdit::cursorPositionChanged, this, &MainWindow::HighlightNodeMatchingCode); - connect(myUi.codeViewer, &QTextEdit::textChanged, this, &MainWindow::OnCodeChange); - connect(myUi.showDetails, &QPushButton::clicked, this, &MainWindow::ShowNodeDetails); -} - -void MainWindow::RefreshAst() -{ - auto ast = myReader.readAst(myUi.codeViewer->document()->toPlainText().toStdString(), - myUi.commandLineArgs->document()->toPlainText().toStdString()); - auto model = new AstModel(std::move(ast)); - - myUi.astTreeView->setModel(model); - myUi.astTreeView->setRootIndex(model->rootIndex()); - connect(myUi.astTreeView->selectionModel(), &QItemSelectionModel::currentChanged, - this, &MainWindow::HighlightCodeMatchingNode); - connect(myUi.astTreeView->selectionModel(), &QItemSelectionModel::currentChanged, - this, &MainWindow::DisplayNodeProperties); - myUi.astTreeView->setEnabled(myReader.ready()); -} - -void MainWindow::HighlightCodeMatchingNode(const QModelIndex &newNode, const QModelIndex &previousNode) -{ - if (isUpdateInProgress) - { - return; - } - auto lock = UpdateLock{ isUpdateInProgress }; - auto node = myUi.astTreeView->model()->data(newNode, Qt::NodeRole).value(); - auto &manager = myReader.getManager(); - std::pair location; - if (!node->getRangeInMainFile(location, manager, myReader.getContext())) - { - return; - } - auto cursor = myUi.codeViewer->textCursor(); - cursor.setPosition(location.first); - cursor.setPosition(location.second, QTextCursor::KeepAnchor); - myUi.codeViewer->setTextCursor(cursor); -} - -void MainWindow::DisplayNodeProperties(const QModelIndex &newNode, const QModelIndex &previousNode) -{ - myUi.nodeProperties->clear(); - auto node = myUi.astTreeView->model()->data(newNode, Qt::NodeRole).value(); - for (auto &prop : node->getProperties()) - { - new QTreeWidgetItem(myUi.nodeProperties, QStringList{ QString::fromStdString(prop.first), QString::fromStdString(prop.second) }); - } - myUi.showDetails->setVisible(node->hasDetails); -} - -void MainWindow::HighlightNodeMatchingCode() -{ - if (isUpdateInProgress || !myReader.ready()) - { - return; - } - auto lock = UpdateLock{ isUpdateInProgress }; - auto cursorPosition = myUi.codeViewer->textCursor().position(); - auto nodePath = myReader.getBestNodeMatchingPosition(cursorPosition); - auto model = myUi.astTreeView->model(); - if (!nodePath.empty()) - { - auto currentIndex = model->index(0, 0); // Returns the root - currentIndex = model->index(0, 0, currentIndex); // Returns the AST node - auto currentNode = nodePath.front(); - bool first = true; - for (auto node : nodePath) - { - if (first) - { - first = false; - } - else - { - auto index = currentNode->findChildIndex(node); - if (index == -1) - { - // Something wrong, just silently return - return; - } - currentIndex = model->index(index, 0, currentIndex); - currentNode = node; - } - } - myUi.astTreeView->scrollTo(currentIndex, QAbstractItemView::EnsureVisible); - auto selectionModel = myUi.astTreeView->selectionModel(); -// selectionModel->select(currentIndex, QItemSelectionModel::ClearAndSelect); - selectionModel->setCurrentIndex(currentIndex, QItemSelectionModel::ClearAndSelect); - DisplayNodeProperties(currentIndex, currentIndex); // Since we won't use the previous node, it's not an issue if it is wrong... - } -} - -void MainWindow::ShowNodeDetails() -{ - auto selectionModel = myUi.astTreeView->selectionModel(); - auto model = myUi.astTreeView->model(); - auto node = myUi.astTreeView->model()->data(selectionModel->currentIndex(), Qt::NodeRole).value(); - if (! node || !node->hasDetails) - { - QMessageBox::warning(this, windowTitle() + " - Error in details", - "The currently selected node does not have details", QMessageBox::Ok); - return; - } - if (node->details.empty()) - { - node->details = node->detailsComputer(); - } - - auto win = new QDialog(this); - win->setLayout(new QGridLayout()); - win->resize(size()); - win->move(pos()); - win->setWindowTitle(windowTitle() + " - " + QString::fromStdString(node->name) + " - " + QString::fromStdString(node->detailsTitle)); - auto edit = new QTextEdit(win); - win->layout()->addWidget(edit); - edit->setText(QString::fromStdString(node->details)); - edit->setReadOnly(true); - myDetailWindows.push_back(win); - win->show(); -} - - -void MainWindow::closeEvent(QCloseEvent *event) -{ - for (auto win : myDetailWindows) - { - win->close(); - } - event->accept(); -} - -void MainWindow::OnCodeChange() -{ - myUi.astTreeView->setEnabled(false); - myReader.dirty(); -} - diff --git a/src/ASTViewer/MainWindow.h b/src/ASTViewer/MainWindow.h deleted file mode 100644 index ed076e2504..0000000000 --- a/src/ASTViewer/MainWindow.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include "ui_MainWindow.h" -#include "Highlighter.h" -#include "AstReader.h" - - -class MainWindow : public QMainWindow -{ - Q_OBJECT -public: - MainWindow(QWidget *parent = nullptr); -public slots: - void RefreshAst(); - void HighlightCodeMatchingNode(const QModelIndex &newNode, const QModelIndex &previousNode); - void DisplayNodeProperties(const QModelIndex &newNode, const QModelIndex &previousNode); - void HighlightNodeMatchingCode(); - void ShowNodeDetails(); - void OnCodeChange(); - void closeEvent(QCloseEvent *event) override; -private: - Ui::MainWindow myUi; - Highlighter *myHighlighter; // No need to delete, since is will have a parent that will take care of that - AstReader myReader; - std::vector myDetailWindows; - bool isUpdateInProgress; -}; diff --git a/src/ASTViewer/MainWindow.ui b/src/ASTViewer/MainWindow.ui deleted file mode 100644 index eb716cc7f6..0000000000 --- a/src/ASTViewer/MainWindow.ui +++ /dev/null @@ -1,151 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 800 - 600 - - - - Clang AST viewer - - - - - - - - Consolas - 10 - - - - selection-background-color: rgb(170, 85, 255); -selection-color: white - - - 25 - - - - - - - - - 0 - 0 - 800 - 21 - - - - - - - Clang AST - - - 2 - - - - - - - false - - - QTreeView::item:selected { color:white; background:rgb(170, 85, 255); } - - - 10 - - - true - - - - - - - - - toolBar - - - TopToolBarArea - - - false - - - - - - Command line arguments - - - 8 - - - - - - - -std=c++14 "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include" -I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.10150.0\ucrt" -fcxx-exceptions -fms-compatibility -fdelayed-template-parsing - - - - - - - - - Properties - - - 2 - - - - - - - 2 - - - - 1 - - - - - 2 - - - - - - - - Show details - - - - - - - - - Refresh - - - - - - diff --git a/src/ASTViewer/README.md b/src/ASTViewer/README.md deleted file mode 100644 index faa3af271f..0000000000 --- a/src/ASTViewer/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Clang-ast-viewer -## Introduction - -Fork of [https://github.com/CAST-projects/Clang-ast-viewer](https://github.com/CAST-projects/Clang-ast-viewer). - -## License -This product is provided under LGPL. See the `LICENCE` file for more information. \ No newline at end of file diff --git a/src/ASTViewer/main.cpp b/src/ASTViewer/main.cpp deleted file mode 100644 index 14dfa7f717..0000000000 --- a/src/ASTViewer/main.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include "MainWindow.h" - -int main(int argc, char **argv) -{ - QApplication app (argc, argv); - - MainWindow mainWindow; - mainWindow.show(); - - return app.exec(); -} - diff --git a/src/ASTViewer/premake5.lua b/src/ASTViewer/premake5.lua deleted file mode 100644 index f27afaa992..0000000000 --- a/src/ASTViewer/premake5.lua +++ /dev/null @@ -1,32 +0,0 @@ -require("premake-qt/qt") -local qt = premake.extensions.qt - -project "CppSharp.ASTViewer" - SetupNativeProject() - kind "ConsoleApp" - systemversion("latest") - cppdialect "C++17" - - qt.enable() - - filter { "system:linux" } - buildoptions { "-fPIC" } - links { "pthread" } - qtincludepath "/usr/include/x86_64-linux-gnu/qt5" - qtlibpath "/usr/lib/x86_64-linux-gnu" - qtbinpath "/usr/lib/qt5/bin" - - filter { "system:windows" } - qtpath "C:\\Qt\\5.12.0\\msvc2017" - - filter {} - - qtmodules { "core", "gui", "widgets" } - qtprefix "Qt5" - files { "**.h", "**.cpp", "**.ui", "**.qrc" } - - SetupLLVMIncludes() - SetupLLVMLibs() - - filter { "toolset:msc*" } - buildoptions { "/wd4141", "/wd4146", "/wd4996" } diff --git a/src/CLI/CLI.cs b/src/CLI/CLI.cs index 54b2ed6c5d..44889307cb 100644 --- a/src/CLI/CLI.cs +++ b/src/CLI/CLI.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using CppSharp.Generators; using Mono.Options; namespace CppSharp @@ -15,11 +16,11 @@ static bool ParseCommandLineArgs(string[] args, List errorMessages, ref { var showHelp = false; - optionSet.Add("I=", "the {PATH} of a folder to search for include files", (i) => { AddIncludeDirs(i, errorMessages); }); + optionSet.Add("I=", "the {PATH} of a folder to search for include files", i => { AddIncludeDirs(i, errorMessages); }); optionSet.Add("l=", "{LIBRARY} that that contains the symbols of the generated code", l => options.Libraries.Add(l)); optionSet.Add("L=", "the {PATH} of a folder to search for additional libraries", l => options.LibraryDirs.Add(l)); optionSet.Add("D:", "additional define with (optional) value to add to be used while parsing the given header files", (n, v) => AddDefine(n, v, errorMessages)); - optionSet.Add("A=", "additional Clang arguments to pass to the compiler while parsing the given header files", (v) => AddArgument(v, errorMessages)); + optionSet.Add("A=", "additional Clang arguments to pass to the compiler while parsing the given header files", v => AddArgument(v, errorMessages)); optionSet.Add("o=|output=", "the {PATH} for the generated bindings file (doesn't need the extension since it will depend on the generator)", v => HandleOutputArg(v, errorMessages)); optionSet.Add("on=|outputnamespace=", "the {NAMESPACE} that will be used for the generated code", on => options.OutputNamespace = on); @@ -30,8 +31,8 @@ static bool ParseCommandLineArgs(string[] args, List errorMessages, ref optionSet.Add("d|debug", "enables debug mode which generates more verbose code to aid debugging", v => options.Debug = true); optionSet.Add("c|compile", "enables automatic compilation of the generated code", v => options.Compile = true); optionSet.Add("g=|gen=|generator=", "the {TYPE} of generated code: 'csharp' or 'cli' ('cli' supported only for Windows)", g => { GetGeneratorKind(g, errorMessages); }); - optionSet.Add("p=|platform=", "the {PLATFORM} that the generated code will target: 'win', 'osx' or 'linux'", p => { GetDestinationPlatform(p, errorMessages); }); - optionSet.Add("a=|arch=", "the {ARCHITECTURE} that the generated code will target: 'x86' or 'x64'", a => { GetDestinationArchitecture(a, errorMessages); }); + optionSet.Add("p=|platform=", "the {PLATFORM} that the generated code will target: 'win', 'osx' or 'linux' or 'emscripten'", p => { GetDestinationPlatform(p, errorMessages); }); + optionSet.Add("a=|arch=", "the {ARCHITECTURE} that the generated code will target: 'x86' or 'x64' or 'wasm32' or 'wasm64'", a => { GetDestinationArchitecture(a, errorMessages); }); optionSet.Add("prefix=", "sets a string prefix to the names of generated files", a => { options.Prefix = a; }); optionSet.Add("exceptions", "enables support for C++ exceptions in the parser", v => { options.EnableExceptions = true; }); @@ -208,26 +209,29 @@ static void GetGeneratorKind(string generator, List errorMessages) switch (generator.ToLower()) { case "csharp": - options.Kind = CppSharp.Generators.GeneratorKind.CSharp; + options.Kind = GeneratorKind.CSharp; return; case "cli": - options.Kind = CppSharp.Generators.GeneratorKind.CLI; + options.Kind = GeneratorKind.CLI; return; case "c": - options.Kind = CppSharp.Generators.GeneratorKind.C; + options.Kind = GeneratorKind.C; return; case "cpp": - options.Kind = CppSharp.Generators.GeneratorKind.CPlusPlus; + options.Kind = GeneratorKind.CPlusPlus; return; case "napi": - options.Kind = CppSharp.Generators.GeneratorKind.NAPI; + options.Kind = GeneratorKind.NAPI; return; case "qjs": - options.Kind = CppSharp.Generators.GeneratorKind.QuickJS; + options.Kind = GeneratorKind.QuickJS; return; case "ts": case "typescript": - options.Kind = CppSharp.Generators.GeneratorKind.TypeScript; + options.Kind = GeneratorKind.TypeScript; + return; + case "emscripten": + options.Kind = GeneratorKind.Emscripten; return; } @@ -247,6 +251,9 @@ static void GetDestinationPlatform(string platform, List errorMessages) case "linux": options.Platform = TargetPlatform.Linux; return; + case "emscripten": + options.Platform = TargetPlatform.Emscripten; + return; } errorMessages.Add($"Unknown target platform: {platform}. Defaulting to {options.Platform}"); @@ -262,6 +269,12 @@ static void GetDestinationArchitecture(string architecture, List errorMe case "x64": options.Architecture = TargetArchitecture.x64; return; + case "wasm32": + options.Architecture = TargetArchitecture.WASM32; + return; + case "wasm64": + options.Architecture = TargetArchitecture.WASM64; + return; } errorMessages.Add($"Unknown target architecture: {architecture}. Defaulting to {options.Architecture}"); @@ -286,9 +299,9 @@ static void Main(string[] args) return; } - Generator gen = new Generator(options); + var gen = new Generator(options); - bool validOptions = gen.ValidateOptions(errorMessages); + var validOptions = gen.ValidateOptions(errorMessages); PrintErrorMessages(errorMessages); if (errorMessages.Any() || !validOptions) diff --git a/src/CLI/Generator.cs b/src/CLI/Generator.cs index 5c6f72be77..58db9ac72d 100644 --- a/src/CLI/Generator.cs +++ b/src/CLI/Generator.cs @@ -13,58 +13,64 @@ namespace CppSharp { class Generator : ILibrary { - private Options options = null; + private readonly Options options; private string triple = ""; private CppAbi abi = CppAbi.Microsoft; public Generator(Options options) { - if (options == null) - throw new ArgumentNullException(nameof(options)); - - this.options = options; - } - - static TargetPlatform GetCurrentPlatform() - { - if (Platform.IsWindows) - return TargetPlatform.Windows; - - if (Platform.IsMacOS) - return TargetPlatform.MacOS; - - if (Platform.IsLinux) - return TargetPlatform.Linux; - - throw new System.NotImplementedException("Unknown host platform"); + this.options = options ?? throw new ArgumentNullException(nameof(options)); } void SetupTargetTriple() { var tripleBuilder = new StringBuilder(); - if (options.Architecture == TargetArchitecture.x64) - tripleBuilder.Append("x86_64-"); - else if (options.Architecture == TargetArchitecture.x86) - tripleBuilder.Append("i686-"); - - if (options.Platform == TargetPlatform.Windows) - { - tripleBuilder.Append("pc-win32-msvc"); - abi = CppAbi.Microsoft; - } - else if (options.Platform == TargetPlatform.MacOS) + switch (options.Architecture) { - tripleBuilder.Append("apple-darwin12.4.0"); - abi = CppAbi.Itanium; + case TargetArchitecture.x64: + tripleBuilder.Append("x86_64-"); + break; + case TargetArchitecture.x86: + tripleBuilder.Append("i686-"); + break; + case TargetArchitecture.WASM32: + tripleBuilder.Append("wasm32-"); + break; + case TargetArchitecture.WASM64: + tripleBuilder.Append("wasm64-"); + break; } - else if (options.Platform == TargetPlatform.Linux) - { - tripleBuilder.Append("linux-gnu"); - abi = CppAbi.Itanium; - if (options.Cpp11ABI) - tripleBuilder.Append("-cxx11abi"); + switch (options.Platform) + { + case TargetPlatform.Windows: + tripleBuilder.Append("pc-win32-msvc"); + abi = CppAbi.Microsoft; + break; + case TargetPlatform.MacOS: + tripleBuilder.Append("apple-darwin12.4.0"); + abi = CppAbi.Itanium; + break; + case TargetPlatform.Linux: + { + tripleBuilder.Append("linux-gnu"); + abi = CppAbi.Itanium; + + if (options.Cpp11ABI) + tripleBuilder.Append("-cxx11abi"); + break; + } + case TargetPlatform.Emscripten: + { + if (options.Architecture != TargetArchitecture.WASM32 && + options.Architecture != TargetArchitecture.WASM64) + throw new Exception("Emscripten target is only compatible with WASM architectures"); + + tripleBuilder.Append("unknown-emscripten"); + abi = CppAbi.Itanium; + break; + } } triple = tripleBuilder.ToString(); @@ -78,8 +84,7 @@ public bool ValidateOptions(List messages) return false; } - if (!options.Platform.HasValue) - options.Platform = GetCurrentPlatform(); + options.Platform ??= Platform.Host; if (string.IsNullOrEmpty(options.OutputDir)) { @@ -103,6 +108,9 @@ public bool ValidateOptions(List messages) if (string.IsNullOrEmpty(options.OutputNamespace)) options.OutputNamespace = moduleName; + if (options.IncludeDirs.Count == 0) + options.IncludeDirs.Add(Path.GetDirectoryName(options.HeaderFiles.First())); + SetupTargetTriple(); return true; @@ -133,7 +141,7 @@ public void Setup(Driver driver) parserOptions.UnityBuild = options.UnityBuild; parserOptions.EnableRTTI = options.EnableRTTI; - parserOptions.Setup(); + parserOptions.Setup(options.Platform ?? Platform.Host); if (triple.Contains("linux")) SetupLinuxOptions(parserOptions); @@ -189,7 +197,7 @@ public void Postprocess(Driver driver, ASTContext ctx) public void Run() { - StringBuilder messageBuilder = new StringBuilder(); + var messageBuilder = new StringBuilder(); messageBuilder.Append($"Generating {GetGeneratorKindName(options.Kind)}"); messageBuilder.Append($" bindings for {GetPlatformName(options.Platform)} {options.Architecture}"); diff --git a/src/CLI/Options.cs b/src/CLI/Options.cs index f679287c0f..bbcb2f3894 100644 --- a/src/CLI/Options.cs +++ b/src/CLI/Options.cs @@ -6,7 +6,9 @@ namespace CppSharp enum TargetArchitecture { x86, - x64 + x64, + WASM32, + WASM64 } class Options diff --git a/src/Core/Platform.cs b/src/Core/Platform.cs index d0500f290f..90740dfc66 100644 --- a/src/Core/Platform.cs +++ b/src/Core/Platform.cs @@ -11,7 +11,8 @@ public enum TargetPlatform MacOS, iOS, WatchOS, - TVOS + TVOS, + Emscripten, } public static class Platform diff --git a/src/CppParser/AST.cpp b/src/CppParser/AST.cpp index d0442df015..ae9e176360 100644 --- a/src/CppParser/AST.cpp +++ b/src/CppParser/AST.cpp @@ -164,6 +164,7 @@ NonTypeTemplateParameter::NonTypeTemplateParameter(const NonTypeTemplateParamete , position(rhs.position) , isPackExpansion(rhs.isPackExpansion) , isExpandedParameterPack(rhs.isExpandedParameterPack) + , type(rhs.type) { } diff --git a/src/CppParser/Bindings/CLI/Decl.cpp b/src/CppParser/Bindings/CLI/Decl.cpp index 2465c7ef4e..3de0e48dec 100644 --- a/src/CppParser/Bindings/CLI/Decl.cpp +++ b/src/CppParser/Bindings/CLI/Decl.cpp @@ -4224,6 +4224,18 @@ void CppSharp::Parser::AST::NonTypeTemplateParameter::IsExpandedParameterPack::s ((class ::CppSharp::CppParser::AST::NonTypeTemplateParameter*)NativePtr)->isExpandedParameterPack = value; } +CppSharp::Parser::AST::QualifiedType^ CppSharp::Parser::AST::NonTypeTemplateParameter::Type::get() +{ + return (&((class ::CppSharp::CppParser::AST::NonTypeTemplateParameter*)NativePtr)->type == nullptr) ? nullptr : gcnew ::CppSharp::Parser::AST::QualifiedType((struct ::CppSharp::CppParser::AST::QualifiedType*)&((class ::CppSharp::CppParser::AST::NonTypeTemplateParameter*)NativePtr)->type); +} + +void CppSharp::Parser::AST::NonTypeTemplateParameter::Type::set(CppSharp::Parser::AST::QualifiedType^ value) +{ + if (ReferenceEquals(value, nullptr)) + throw gcnew ::System::ArgumentNullException("value", "Cannot be null because it is passed by value."); + ((class ::CppSharp::CppParser::AST::NonTypeTemplateParameter*)NativePtr)->type = *(struct ::CppSharp::CppParser::AST::QualifiedType*)value->NativePtr; +} + CppSharp::Parser::AST::ClassTemplate::ClassTemplate(class ::CppSharp::CppParser::AST::ClassTemplate* native) : CppSharp::Parser::AST::Template((::CppSharp::CppParser::AST::Template*)native) { diff --git a/src/CppParser/Bindings/CLI/Decl.h b/src/CppParser/Bindings/CLI/Decl.h index a96a160c8a..8c9044c774 100644 --- a/src/CppParser/Bindings/CLI/Decl.h +++ b/src/CppParser/Bindings/CLI/Decl.h @@ -256,7 +256,8 @@ namespace CppSharp Microsoft = 1, ARM = 2, iOS = 3, - iOS64 = 4 + iOS64 = 4, + WebAssembly = 5 }; public enum class RecordArgABI @@ -2097,6 +2098,12 @@ namespace CppSharp bool get(); void set(bool); } + + property CppSharp::Parser::AST::QualifiedType^ Type + { + CppSharp::Parser::AST::QualifiedType^ get(); + void set(CppSharp::Parser::AST::QualifiedType^); + } }; public ref class ClassTemplate : CppSharp::Parser::AST::Template diff --git a/src/CppParser/Bindings/CSharp/CppSharp.Parser.CSharp.csproj b/src/CppParser/Bindings/CSharp/CppSharp.Parser.CSharp.csproj index b026b257be..cb09d65642 100644 --- a/src/CppParser/Bindings/CSharp/CppSharp.Parser.CSharp.csproj +++ b/src/CppParser/Bindings/CSharp/CppSharp.Parser.CSharp.csproj @@ -5,6 +5,7 @@ true true true + 0109 x86_64-pc-win32-msvc x86_64-linux-gnu-cxx11abi x86_64-linux-gnu diff --git a/src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/CppSharp.CppParser.cs b/src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/CppSharp.CppParser.cs index f12e2fa508..5fcdfc4ebd 100644 --- a/src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/CppSharp.CppParser.cs +++ b/src/CppParser/Bindings/CSharp/i686-apple-darwin12.4.0/CppSharp.CppParser.cs @@ -6301,7 +6301,8 @@ public enum CppAbi Microsoft = 1, ARM = 2, iOS = 3, - iOS64 = 4 + iOS64 = 4, + WebAssembly = 5 } public enum RecordArgABI @@ -13016,6 +13017,7 @@ public unsafe partial class NonTypeTemplateParameter : global::CppSharp.Parser.A internal uint position; internal byte isPackExpansion; internal byte isExpandedParameterPack; + internal global::CppSharp.Parser.AST.QualifiedType.__Internal type; [SuppressUnmanagedCodeSecurity, DllImport("CppSharp.CppParser", EntryPoint = "_ZN8CppSharp9CppParser3AST24NonTypeTemplateParameterC2Ev", CallingConvention = __CallingConvention.Cdecl)] internal static extern void ctor(__IntPtr __instance); @@ -13170,6 +13172,21 @@ public bool IsExpandedParameterPack ((__Internal*)__Instance)->isExpandedParameterPack = (byte) (value ? 1 : 0); } } + + public global::CppSharp.Parser.AST.QualifiedType Type + { + get + { + return global::CppSharp.Parser.AST.QualifiedType.__CreateInstance(new __IntPtr(&((__Internal*)__Instance)->type)); + } + + set + { + if (ReferenceEquals(value, null)) + throw new global::System.ArgumentNullException("value", "Cannot be null because it is passed by value."); + ((__Internal*)__Instance)->type = *(global::CppSharp.Parser.AST.QualifiedType.__Internal*) value.__Instance; + } + } } public unsafe partial class ClassTemplate : global::CppSharp.Parser.AST.Template, IDisposable diff --git a/src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/CppSharp.CppParser.cs b/src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/CppSharp.CppParser.cs index e6d43d9596..de89c3f760 100644 --- a/src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/CppSharp.CppParser.cs +++ b/src/CppParser/Bindings/CSharp/i686-pc-win32-msvc/CppSharp.CppParser.cs @@ -6301,7 +6301,8 @@ public enum CppAbi Microsoft = 1, ARM = 2, iOS = 3, - iOS64 = 4 + iOS64 = 4, + WebAssembly = 5 } public enum RecordArgABI @@ -13016,6 +13017,7 @@ public unsafe partial class NonTypeTemplateParameter : global::CppSharp.Parser.A internal uint position; internal byte isPackExpansion; internal byte isExpandedParameterPack; + internal global::CppSharp.Parser.AST.QualifiedType.__Internal type; [SuppressUnmanagedCodeSecurity, DllImport("CppSharp.CppParser.dll", EntryPoint = "??0NonTypeTemplateParameter@AST@CppParser@CppSharp@@QAE@XZ", CallingConvention = __CallingConvention.ThisCall)] internal static extern __IntPtr ctor(__IntPtr __instance); @@ -13170,6 +13172,21 @@ public bool IsExpandedParameterPack ((__Internal*)__Instance)->isExpandedParameterPack = (byte) (value ? 1 : 0); } } + + public global::CppSharp.Parser.AST.QualifiedType Type + { + get + { + return global::CppSharp.Parser.AST.QualifiedType.__CreateInstance(new __IntPtr(&((__Internal*)__Instance)->type)); + } + + set + { + if (ReferenceEquals(value, null)) + throw new global::System.ArgumentNullException("value", "Cannot be null because it is passed by value."); + ((__Internal*)__Instance)->type = *(global::CppSharp.Parser.AST.QualifiedType.__Internal*) value.__Instance; + } + } } public unsafe partial class ClassTemplate : global::CppSharp.Parser.AST.Template, IDisposable diff --git a/src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/CppSharp.CppParser.cs b/src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/CppSharp.CppParser.cs index 4ce7bfff71..576edd3c17 100644 --- a/src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/CppSharp.CppParser.cs +++ b/src/CppParser/Bindings/CSharp/x86_64-apple-darwin12.4.0/CppSharp.CppParser.cs @@ -6301,7 +6301,8 @@ public enum CppAbi Microsoft = 1, ARM = 2, iOS = 3, - iOS64 = 4 + iOS64 = 4, + WebAssembly = 5 } public enum RecordArgABI @@ -13015,6 +13016,7 @@ public unsafe partial class NonTypeTemplateParameter : global::CppSharp.Parser.A internal uint position; internal byte isPackExpansion; internal byte isExpandedParameterPack; + internal global::CppSharp.Parser.AST.QualifiedType.__Internal type; [SuppressUnmanagedCodeSecurity, DllImport("CppSharp.CppParser", EntryPoint = "_ZN8CppSharp9CppParser3AST24NonTypeTemplateParameterC2Ev", CallingConvention = __CallingConvention.Cdecl)] internal static extern void ctor(__IntPtr __instance); @@ -13169,6 +13171,21 @@ public bool IsExpandedParameterPack ((__Internal*)__Instance)->isExpandedParameterPack = (byte) (value ? 1 : 0); } } + + public global::CppSharp.Parser.AST.QualifiedType Type + { + get + { + return global::CppSharp.Parser.AST.QualifiedType.__CreateInstance(new __IntPtr(&((__Internal*)__Instance)->type)); + } + + set + { + if (ReferenceEquals(value, null)) + throw new global::System.ArgumentNullException("value", "Cannot be null because it is passed by value."); + ((__Internal*)__Instance)->type = *(global::CppSharp.Parser.AST.QualifiedType.__Internal*) value.__Instance; + } + } } public unsafe partial class ClassTemplate : global::CppSharp.Parser.AST.Template, IDisposable diff --git a/src/CppParser/Bindings/CSharp/x86_64-linux-gnu-cxx11abi/CppSharp.CppParser.cs b/src/CppParser/Bindings/CSharp/x86_64-linux-gnu-cxx11abi/CppSharp.CppParser.cs index 82844c1059..4c6201974c 100644 --- a/src/CppParser/Bindings/CSharp/x86_64-linux-gnu-cxx11abi/CppSharp.CppParser.cs +++ b/src/CppParser/Bindings/CSharp/x86_64-linux-gnu-cxx11abi/CppSharp.CppParser.cs @@ -6301,7 +6301,8 @@ public enum CppAbi Microsoft = 1, ARM = 2, iOS = 3, - iOS64 = 4 + iOS64 = 4, + WebAssembly = 5 } public enum RecordArgABI @@ -13015,6 +13016,7 @@ public unsafe partial class NonTypeTemplateParameter : global::CppSharp.Parser.A internal uint position; internal byte isPackExpansion; internal byte isExpandedParameterPack; + internal global::CppSharp.Parser.AST.QualifiedType.__Internal type; [SuppressUnmanagedCodeSecurity, DllImport("CppSharp.CppParser", EntryPoint = "_ZN8CppSharp9CppParser3AST24NonTypeTemplateParameterC2Ev", CallingConvention = __CallingConvention.Cdecl)] internal static extern void ctor(__IntPtr __instance); @@ -13169,6 +13171,21 @@ public bool IsExpandedParameterPack ((__Internal*)__Instance)->isExpandedParameterPack = (byte) (value ? 1 : 0); } } + + public global::CppSharp.Parser.AST.QualifiedType Type + { + get + { + return global::CppSharp.Parser.AST.QualifiedType.__CreateInstance(new __IntPtr(&((__Internal*)__Instance)->type)); + } + + set + { + if (ReferenceEquals(value, null)) + throw new global::System.ArgumentNullException("value", "Cannot be null because it is passed by value."); + ((__Internal*)__Instance)->type = *(global::CppSharp.Parser.AST.QualifiedType.__Internal*) value.__Instance; + } + } } public unsafe partial class ClassTemplate : global::CppSharp.Parser.AST.Template, IDisposable diff --git a/src/CppParser/Bindings/CSharp/x86_64-linux-gnu/CppSharp.CppParser.cs b/src/CppParser/Bindings/CSharp/x86_64-linux-gnu/CppSharp.CppParser.cs index 612f1f207f..2b7e1e837c 100644 --- a/src/CppParser/Bindings/CSharp/x86_64-linux-gnu/CppSharp.CppParser.cs +++ b/src/CppParser/Bindings/CSharp/x86_64-linux-gnu/CppSharp.CppParser.cs @@ -6301,7 +6301,8 @@ public enum CppAbi Microsoft = 1, ARM = 2, iOS = 3, - iOS64 = 4 + iOS64 = 4, + WebAssembly = 5 } public enum RecordArgABI @@ -13015,6 +13016,7 @@ public unsafe partial class NonTypeTemplateParameter : global::CppSharp.Parser.A internal uint position; internal byte isPackExpansion; internal byte isExpandedParameterPack; + internal global::CppSharp.Parser.AST.QualifiedType.__Internal type; [SuppressUnmanagedCodeSecurity, DllImport("CppSharp.CppParser", EntryPoint = "_ZN8CppSharp9CppParser3AST24NonTypeTemplateParameterC2Ev", CallingConvention = __CallingConvention.Cdecl)] internal static extern void ctor(__IntPtr __instance); @@ -13169,6 +13171,21 @@ public bool IsExpandedParameterPack ((__Internal*)__Instance)->isExpandedParameterPack = (byte) (value ? 1 : 0); } } + + public global::CppSharp.Parser.AST.QualifiedType Type + { + get + { + return global::CppSharp.Parser.AST.QualifiedType.__CreateInstance(new __IntPtr(&((__Internal*)__Instance)->type)); + } + + set + { + if (ReferenceEquals(value, null)) + throw new global::System.ArgumentNullException("value", "Cannot be null because it is passed by value."); + ((__Internal*)__Instance)->type = *(global::CppSharp.Parser.AST.QualifiedType.__Internal*) value.__Instance; + } + } } public unsafe partial class ClassTemplate : global::CppSharp.Parser.AST.Template, IDisposable diff --git a/src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/CppSharp.CppParser.cs b/src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/CppSharp.CppParser.cs index 85846584a7..5c6dadc5fe 100644 --- a/src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/CppSharp.CppParser.cs +++ b/src/CppParser/Bindings/CSharp/x86_64-pc-win32-msvc/CppSharp.CppParser.cs @@ -6301,7 +6301,8 @@ public enum CppAbi Microsoft = 1, ARM = 2, iOS = 3, - iOS64 = 4 + iOS64 = 4, + WebAssembly = 5 } public enum RecordArgABI @@ -13017,6 +13018,7 @@ public unsafe partial class NonTypeTemplateParameter : global::CppSharp.Parser.A internal uint position; internal byte isPackExpansion; internal byte isExpandedParameterPack; + internal global::CppSharp.Parser.AST.QualifiedType.__Internal type; [SuppressUnmanagedCodeSecurity, DllImport("CppSharp.CppParser.dll", EntryPoint = "??0NonTypeTemplateParameter@AST@CppParser@CppSharp@@QEAA@XZ", CallingConvention = __CallingConvention.Cdecl)] internal static extern __IntPtr ctor(__IntPtr __instance); @@ -13171,6 +13173,21 @@ public bool IsExpandedParameterPack ((__Internal*)__Instance)->isExpandedParameterPack = (byte) (value ? 1 : 0); } } + + public global::CppSharp.Parser.AST.QualifiedType Type + { + get + { + return global::CppSharp.Parser.AST.QualifiedType.__CreateInstance(new __IntPtr(&((__Internal*)__Instance)->type)); + } + + set + { + if (ReferenceEquals(value, null)) + throw new global::System.ArgumentNullException("value", "Cannot be null because it is passed by value."); + ((__Internal*)__Instance)->type = *(global::CppSharp.Parser.AST.QualifiedType.__Internal*) value.__Instance; + } + } } public unsafe partial class ClassTemplate : global::CppSharp.Parser.AST.Template, IDisposable diff --git a/src/CppParser/Decl.h b/src/CppParser/Decl.h index 7132a11080..b51929c45d 100644 --- a/src/CppParser/Decl.h +++ b/src/CppParser/Decl.h @@ -1,9 +1,9 @@ /************************************************************************ -* -* CppSharp -* Licensed under the MIT license. -* -************************************************************************/ + * + * CppSharp + * Licensed under the MIT license. + * + ************************************************************************/ #pragma once @@ -12,823 +12,834 @@ #include "Types.h" #include -namespace CppSharp { namespace CppParser { namespace AST { - -enum class DeclarationKind +namespace CppSharp { - DeclarationContext, - Typedef, - TypeAlias, - Parameter, - Function, - Method, - Enumeration, - EnumerationItem, - Variable, - Field, - AccessSpecifier, - Class, - Template, - TypeAliasTemplate, - ClassTemplate, - ClassTemplateSpecialization, - ClassTemplatePartialSpecialization, - FunctionTemplate, - Namespace, - PreprocessedEntity, - MacroDefinition, - MacroExpansion, - TranslationUnit, - Friend, - TemplateTemplateParm, - TemplateTypeParm, - NonTypeTemplateParm, - VarTemplate, - VarTemplateSpecialization, - VarTemplatePartialSpecialization, - UnresolvedUsingTypename, -}; + namespace CppParser + { + namespace AST + { + + enum class DeclarationKind + { + DeclarationContext, + Typedef, + TypeAlias, + Parameter, + Function, + Method, + Enumeration, + EnumerationItem, + Variable, + Field, + AccessSpecifier, + Class, + Template, + TypeAliasTemplate, + ClassTemplate, + ClassTemplateSpecialization, + ClassTemplatePartialSpecialization, + FunctionTemplate, + Namespace, + PreprocessedEntity, + MacroDefinition, + MacroExpansion, + TranslationUnit, + Friend, + TemplateTemplateParm, + TemplateTypeParm, + NonTypeTemplateParm, + VarTemplate, + VarTemplateSpecialization, + VarTemplatePartialSpecialization, + UnresolvedUsingTypename, + }; #define DECLARE_DECL_KIND(klass, kind) \ klass(); -enum class AccessSpecifier -{ - Private, - Protected, - Public -}; - -class DeclarationContext; -class RawComment; -class PreprocessedEntity; - -class ExpressionObsolete; -class CS_API Declaration -{ -public: - Declaration(DeclarationKind kind); - Declaration(const Declaration&); - ~Declaration(); - - DeclarationKind kind; - int alignAs; - int maxFieldAlignment; - AccessSpecifier access; - DeclarationContext* _namespace; - SourceLocation location; - int lineNumberStart; - int lineNumberEnd; - std::string name; - std::string USR; - std::string debugText; - bool isIncomplete; - bool isDependent; - bool isImplicit; - bool isInvalid; - bool isDeprecated; - Declaration* completeDeclaration; - unsigned definitionOrder; - VECTOR(PreprocessedEntity*, PreprocessedEntities) - VECTOR(Declaration*, Redeclarations) - void* originalPtr; - RawComment* comment; -}; - -class Class; -class Enumeration; -class Function; -class TypedefDecl; -class TypeAlias; -class Namespace; -class Template; -class TypeAliasTemplate; -class ClassTemplate; -class FunctionTemplate; -class Variable; -class Friend; - -class CS_API DeclarationContext : public Declaration -{ -public: - DeclarationContext(DeclarationKind kind); - - CS_IGNORE Declaration* FindAnonymous(const std::string& USR); - - CS_IGNORE Namespace* FindNamespace(const std::string& Name); - CS_IGNORE Namespace* FindNamespace(const std::vector&); - CS_IGNORE Namespace* FindCreateNamespace(const std::string& Name); - - CS_IGNORE Class* CreateClass(const std::string& Name, bool IsComplete); - CS_IGNORE Class* FindClass(const void* OriginalPtr, const std::string& Name, bool IsComplete); - CS_IGNORE Class* FindClass(const void* OriginalPtr, const std::string& Name, bool IsComplete, - bool Create); - - CS_IGNORE template T* FindTemplate(const std::string& USR); - - CS_IGNORE Enumeration* FindEnum(const void* OriginalPtr); - CS_IGNORE Enumeration* FindEnum(const std::string& Name, bool Create = false); - CS_IGNORE Enumeration* FindEnumWithItem(const std::string& Name); - - CS_IGNORE Function* FindFunction(const std::string& USR); - - CS_IGNORE TypedefDecl* FindTypedef(const std::string& Name, bool Create = false); - - CS_IGNORE TypeAlias* FindTypeAlias(const std::string& Name, bool Create = false); - - CS_IGNORE Variable* FindVariable(const std::string& USR); - - CS_IGNORE Friend* FindFriend(const std::string& USR); - - VECTOR(Namespace*, Namespaces) - VECTOR(Enumeration*, Enums) - VECTOR(Function*, Functions) - VECTOR(Class*, Classes) - VECTOR(Template*, Templates) - VECTOR(TypedefDecl*, Typedefs) - VECTOR(TypeAlias*, TypeAliases) - VECTOR(Variable*, Variables) - VECTOR(Friend*, Friends) - - std::map anonymous; - - bool isAnonymous; -}; - -class CS_API TypedefNameDecl : public Declaration -{ -public: - TypedefNameDecl(DeclarationKind kind); - ~TypedefNameDecl(); - QualifiedType qualifiedType; -}; - -class CS_API TypedefDecl : public TypedefNameDecl -{ -public: - DECLARE_DECL_KIND(TypedefDecl, Typedef) - ~TypedefDecl(); -}; - -class CS_API TypeAlias : public TypedefNameDecl -{ -public: - TypeAlias(); - ~TypeAlias(); - TypeAliasTemplate* describedAliasTemplate; -}; - -class CS_API Friend : public Declaration -{ -public: - DECLARE_DECL_KIND(Friend, Friend) - ~Friend(); - Declaration* declaration; -}; - -enum class StatementClassObsolete -{ - Any, - BinaryOperator, - CallExprClass, - DeclRefExprClass, - CXXConstructExprClass, - CXXOperatorCallExpr, - ImplicitCastExpr, - ExplicitCastExpr, -}; - -class CS_API StatementObsolete -{ -public: - StatementObsolete(const std::string& str, StatementClassObsolete Class = StatementClassObsolete::Any, Declaration* decl = 0); - StatementClassObsolete _class; - Declaration* decl; - std::string string; -}; - -class CS_API ExpressionObsolete : public StatementObsolete -{ -public: - ExpressionObsolete(const std::string& str, StatementClassObsolete Class = StatementClassObsolete::Any, Declaration* decl = 0); -}; - -class Expr; - -class CS_API BinaryOperatorObsolete : public ExpressionObsolete -{ -public: - BinaryOperatorObsolete(const std::string& str, ExpressionObsolete* lhs, ExpressionObsolete* rhs, const std::string& opcodeStr); - ~BinaryOperatorObsolete(); - ExpressionObsolete* LHS; - ExpressionObsolete* RHS; - std::string opcodeStr; -}; - -class CS_API CallExprObsolete : public ExpressionObsolete -{ -public: - CallExprObsolete(const std::string& str, Declaration* decl); - ~CallExprObsolete(); - VECTOR(ExpressionObsolete*, Arguments) -}; - -class CS_API CXXConstructExprObsolete : public ExpressionObsolete -{ -public: - CXXConstructExprObsolete(const std::string& str, Declaration* decl = 0); - ~CXXConstructExprObsolete(); - VECTOR(ExpressionObsolete*, Arguments) -}; - -class CS_API Parameter : public Declaration -{ -public: - Parameter(); - ~Parameter(); - - QualifiedType qualifiedType; - bool isIndirect; - bool hasDefaultValue; - unsigned int index; - ExpressionObsolete* defaultArgument; - Expr* defaultValue; -}; - -enum class CXXMethodKind -{ - Normal, - Constructor, - Destructor, - Conversion, - Operator, - UsingDirective -}; - -enum class CXXOperatorKind -{ - None, - New, - Delete, - Array_New, - Array_Delete, - Plus, - Minus, - Star, - Slash, - Percent, - Caret, - Amp, - Pipe, - Tilde, - Exclaim, - Equal, - Less, - Greater, - PlusEqual, - MinusEqual, - StarEqual, - SlashEqual, - PercentEqual, - CaretEqual, - AmpEqual, - PipeEqual, - LessLess, - GreaterGreater, - LessLessEqual, - GreaterGreaterEqual, - EqualEqual, - ExclaimEqual, - LessEqual, - GreaterEqual, - Spaceship, - AmpAmp, - PipePipe, - PlusPlus, - MinusMinus, - Comma, - ArrowStar, - Arrow, - Call, - Subscript, - Conditional, - Coawait -}; - -class FunctionTemplateSpecialization; - -enum class FriendKind -{ - None, - Declared, - Undeclared -}; - -class Stmt; - -class CS_API Function : public DeclarationContext -{ -public: - Function(); - ~Function(); - - QualifiedType returnType; - bool isReturnIndirect; - bool hasThisReturn; - - bool isConstExpr; - bool isVariadic; - bool isInline; - bool isPure; - bool isDeleted; - bool isDefaulted; - FriendKind friendKind; - CXXOperatorKind operatorKind; - std::string mangled; - std::string signature; - std::string body; - Stmt* bodyStmt; - CallingConvention callingConvention; - VECTOR(Parameter*, Parameters) - FunctionTemplateSpecialization* specializationInfo; - Function* instantiatedFrom; - QualifiedType qualifiedType; -}; - -class AccessSpecifierDecl; - -enum class RefQualifierKind -{ - None, - LValue, - RValue -}; - -class CS_API Method : public Function -{ -public: - Method(); - ~Method(); - - bool isVirtual; - bool isStatic; - bool isConst; - bool isExplicit; - - CXXMethodKind methodKind; - - bool isDefaultConstructor; - bool isCopyConstructor; - bool isMoveConstructor; - - QualifiedType conversionType; - RefQualifierKind refQualifier; - VECTOR(Method*, OverriddenMethods) -}; - -class CS_API Enumeration : public DeclarationContext -{ -public: - DECLARE_DECL_KIND(Enumeration, Enumeration) - ~Enumeration(); - - class CS_API Item : public Declaration - { - public: - DECLARE_DECL_KIND(Item, EnumerationItem) - Item(const Item&); - ~Item(); - std::string expression; - uint64_t value; - }; - - enum class CS_FLAGS EnumModifiers - { - Anonymous = 1 << 0, - Scoped = 1 << 1, - Flags = 1 << 2, - }; - - EnumModifiers modifiers; - Type* type; - BuiltinType* builtinType; - VECTOR(Item*, Items) - - Item* FindItemByName(const std::string& Name); -}; - -class CS_API Variable : public Declaration -{ -public: - DECLARE_DECL_KIND(Variable, Variable) - ~Variable(); - bool isConstExpr; - std::string mangled; - QualifiedType qualifiedType; - ExpressionObsolete* initializer; -}; - -class PreprocessedEntity; - -struct CS_API BaseClassSpecifier -{ - BaseClassSpecifier(); - AccessSpecifier access; - bool isVirtual; - Type* type; - int offset; -}; - -class Class; - -class CS_API Field : public Declaration -{ -public: - DECLARE_DECL_KIND(Field, Field) - ~Field(); - QualifiedType qualifiedType; - Class* _class; - bool isBitField; - unsigned bitWidth; -}; - -class CS_API AccessSpecifierDecl : public Declaration -{ -public: - DECLARE_DECL_KIND(AccessSpecifierDecl, AccessSpecifier) - ~AccessSpecifierDecl(); -}; - -enum class CppAbi -{ - Itanium, - Microsoft, - ARM, - iOS, - iOS64 -}; - -enum class VTableComponentKind -{ - VCallOffset, - VBaseOffset, - OffsetToTop, - RTTI, - FunctionPointer, - CompleteDtorPointer, - DeletingDtorPointer, - UnusedFunctionPointer, -}; - -struct CS_API VTableComponent -{ - VTableComponent(); - VTableComponentKind kind; - unsigned offset; - Declaration* declaration; -}; - -struct CS_API VTableLayout -{ - VTableLayout(); - VTableLayout(const VTableLayout&); - ~VTableLayout(); - VECTOR(VTableComponent, Components) -}; - -struct CS_API VFTableInfo -{ - VFTableInfo(); - VFTableInfo(const VFTableInfo&); - uint64_t VBTableIndex; - uint32_t VFPtrOffset; - uint32_t VFPtrFullOffset; - VTableLayout layout; -}; - -class CS_API LayoutField -{ -public: - LayoutField(); - LayoutField(const LayoutField& other); - ~LayoutField(); - unsigned offset; - std::string name; - QualifiedType qualifiedType; - void* fieldPtr; -}; - -class Class; - -class CS_API LayoutBase -{ -public: - LayoutBase(); - LayoutBase(const LayoutBase& other); - ~LayoutBase(); - unsigned offset; - Class* _class; -}; - -enum class RecordArgABI -{ - /// Pass it using the normal C aggregate rules for the ABI, - /// potentially introducing extra copies and passing some - /// or all of it in registers. - Default = 0, - /// Pass it on the stack using its defined layout. - /// The argument must be evaluated directly into the correct - /// stack position in the arguments area, and the call machinery - /// must not move it or introduce extra copies. - DirectInMemory, - /// Pass it as a pointer to temporary memory. - Indirect -}; - -struct CS_API ClassLayout -{ - ClassLayout(); - CppAbi ABI; - RecordArgABI argABI; - VECTOR(VFTableInfo, VFTables) - VTableLayout layout; - bool hasOwnVFPtr; - long VBPtrOffset; - int alignment; - int size; - int dataSize; - VECTOR(LayoutField, Fields) - VECTOR(LayoutBase, Bases) -}; - -enum class TagKind -{ - Struct, - Interface, - Union, - Class, - Enum -}; - -class CS_API Class : public DeclarationContext -{ -public: - Class(); - ~Class(); - - VECTOR(BaseClassSpecifier*, Bases) - VECTOR(Field*, Fields) - VECTOR(Method*, Methods) - VECTOR(AccessSpecifierDecl*, Specifiers) - - bool isPOD; - bool isAbstract; - bool isUnion; - bool isDynamic; - bool isPolymorphic; - bool hasNonTrivialDefaultConstructor; - bool hasNonTrivialCopyConstructor; - bool hasNonTrivialDestructor; - bool isExternCContext; - bool isInjected; - TagKind tagKind; - - ClassLayout* layout; -}; - -class CS_API Template : public Declaration -{ -public: - Template(DeclarationKind kind); - DECLARE_DECL_KIND(Template, Template) - Declaration* TemplatedDecl; - VECTOR(Declaration*, Parameters) -}; - -template -T* DeclarationContext::FindTemplate(const std::string& USR) -{ - auto foundTemplate = std::find_if(Templates.begin(), Templates.end(), - [&](Template* t) { return t->USR == USR; }); - - if (foundTemplate != Templates.end()) - return static_cast(*foundTemplate); - - return nullptr; -} - -class CS_API TypeAliasTemplate : public Template -{ -public: - TypeAliasTemplate(); - ~TypeAliasTemplate(); -}; - -class CS_API TemplateParameter : public Declaration -{ -public: - TemplateParameter(DeclarationKind kind); - ~TemplateParameter(); - unsigned int depth; - unsigned int index; - bool isParameterPack; -}; - -class CS_API TemplateTemplateParameter : public Template -{ -public: - TemplateTemplateParameter(); - ~TemplateTemplateParameter(); - - bool isParameterPack; - bool isPackExpansion; - bool isExpandedParameterPack; -}; - -class CS_API TypeTemplateParameter : public TemplateParameter -{ -public: - TypeTemplateParameter(); - TypeTemplateParameter(const TypeTemplateParameter&); - ~TypeTemplateParameter(); - - QualifiedType defaultArgument; -}; - -class CS_API NonTypeTemplateParameter : public TemplateParameter -{ -public: - NonTypeTemplateParameter(); - NonTypeTemplateParameter(const NonTypeTemplateParameter&); - ~NonTypeTemplateParameter(); - ExpressionObsolete* defaultArgument; - Expr* defaultArgumentNew; - unsigned int position; - bool isPackExpansion; - bool isExpandedParameterPack; -}; - -class ClassTemplateSpecialization; -class ClassTemplatePartialSpecialization; - -class CS_API ClassTemplate : public Template -{ -public: - ClassTemplate(); - ~ClassTemplate(); - VECTOR(ClassTemplateSpecialization*, Specializations) - ClassTemplateSpecialization* FindSpecialization(const std::string& usr); - ClassTemplatePartialSpecialization* FindPartialSpecialization(const std::string& usr); -}; - -enum class TemplateSpecializationKind -{ - Undeclared, - ImplicitInstantiation, - ExplicitSpecialization, - ExplicitInstantiationDeclaration, - ExplicitInstantiationDefinition -}; - -class CS_API ClassTemplateSpecialization : public Class -{ -public: - ClassTemplateSpecialization(); - ~ClassTemplateSpecialization(); - ClassTemplate* templatedDecl; - VECTOR(TemplateArgument, Arguments) - TemplateSpecializationKind specializationKind; -}; - -class CS_API ClassTemplatePartialSpecialization : public ClassTemplateSpecialization -{ -public: - ClassTemplatePartialSpecialization(); - ~ClassTemplatePartialSpecialization(); -}; - -class CS_API FunctionTemplate : public Template -{ -public: - FunctionTemplate(); - ~FunctionTemplate(); - VECTOR(FunctionTemplateSpecialization*, Specializations) - FunctionTemplateSpecialization* FindSpecialization(const std::string& usr); -}; - -class CS_API FunctionTemplateSpecialization -{ -public: - FunctionTemplateSpecialization(); - ~FunctionTemplateSpecialization(); - FunctionTemplate* _template; - VECTOR(TemplateArgument, Arguments) - Function* specializedFunction; - TemplateSpecializationKind specializationKind; -}; - -class VarTemplateSpecialization; -class VarTemplatePartialSpecialization; - -class CS_API VarTemplate : public Template -{ -public: - VarTemplate(); - ~VarTemplate(); - VECTOR(VarTemplateSpecialization*, Specializations) - VarTemplateSpecialization* FindSpecialization(const std::string& usr); - VarTemplatePartialSpecialization* FindPartialSpecialization(const std::string& usr); -}; - -class CS_API VarTemplateSpecialization : public Variable -{ -public: - VarTemplateSpecialization(); - ~VarTemplateSpecialization(); - VarTemplate* templatedDecl; - VECTOR(TemplateArgument, Arguments) - TemplateSpecializationKind specializationKind; -}; - -class CS_API VarTemplatePartialSpecialization : public VarTemplateSpecialization -{ -public: - VarTemplatePartialSpecialization(); - ~VarTemplatePartialSpecialization(); -}; - -class CS_API UnresolvedUsingTypename : public Declaration -{ -public: - UnresolvedUsingTypename(); - ~UnresolvedUsingTypename(); -}; - -class CS_API Namespace : public DeclarationContext -{ -public: - Namespace(); - ~Namespace(); - bool isInline; -}; - -enum class MacroLocation -{ - Unknown, - ClassHead, - ClassBody, - FunctionHead, - FunctionParameters, - FunctionBody, -}; - -class CS_API PreprocessedEntity -{ -public: - PreprocessedEntity(); - MacroLocation macroLocation; - void* originalPtr; - DeclarationKind kind; -}; - -class CS_API MacroDefinition : public PreprocessedEntity -{ -public: - MacroDefinition(); - ~MacroDefinition(); - std::string name; - std::string expression; - int lineNumberStart; - int lineNumberEnd; -}; - -class CS_API MacroExpansion : public PreprocessedEntity -{ -public: - MacroExpansion(); - ~MacroExpansion(); - std::string name; - std::string text; - MacroDefinition* definition; -}; - -class CS_API TranslationUnit : public Namespace -{ -public: - TranslationUnit(); - ~TranslationUnit(); - std::string fileName; - bool isSystemHeader; - VECTOR(MacroDefinition*, Macros) -}; - -class CS_API ASTContext -{ -public: - ASTContext(); - ~ASTContext(); - TranslationUnit* FindOrCreateModule(std::string File); - VECTOR(TranslationUnit*, TranslationUnits) -}; - -} } } \ No newline at end of file + enum class AccessSpecifier + { + Private, + Protected, + Public + }; + + class DeclarationContext; + class RawComment; + class PreprocessedEntity; + + class ExpressionObsolete; + class CS_API Declaration + { + public: + Declaration(DeclarationKind kind); + Declaration(const Declaration &); + ~Declaration(); + + DeclarationKind kind; + int alignAs; + int maxFieldAlignment; + AccessSpecifier access; + DeclarationContext *_namespace; + SourceLocation location; + int lineNumberStart; + int lineNumberEnd; + std::string name; + std::string USR; + std::string debugText; + bool isIncomplete; + bool isDependent; + bool isImplicit; + bool isInvalid; + bool isDeprecated; + Declaration *completeDeclaration; + unsigned definitionOrder; + VECTOR(PreprocessedEntity *, PreprocessedEntities) + VECTOR(Declaration *, Redeclarations) + void *originalPtr; + RawComment *comment; + }; + + class Class; + class Enumeration; + class Function; + class TypedefDecl; + class TypeAlias; + class Namespace; + class Template; + class TypeAliasTemplate; + class ClassTemplate; + class FunctionTemplate; + class Variable; + class Friend; + + class CS_API DeclarationContext : public Declaration + { + public: + DeclarationContext(DeclarationKind kind); + + CS_IGNORE Declaration *FindAnonymous(const std::string &USR); + + CS_IGNORE Namespace *FindNamespace(const std::string &Name); + CS_IGNORE Namespace *FindNamespace(const std::vector &); + CS_IGNORE Namespace *FindCreateNamespace(const std::string &Name); + + CS_IGNORE Class *CreateClass(const std::string &Name, bool IsComplete); + CS_IGNORE Class *FindClass(const void *OriginalPtr, const std::string &Name, bool IsComplete); + CS_IGNORE Class *FindClass(const void *OriginalPtr, const std::string &Name, bool IsComplete, + bool Create); + + CS_IGNORE template + T *FindTemplate(const std::string &USR); + + CS_IGNORE Enumeration *FindEnum(const void *OriginalPtr); + CS_IGNORE Enumeration *FindEnum(const std::string &Name, bool Create = false); + CS_IGNORE Enumeration *FindEnumWithItem(const std::string &Name); + + CS_IGNORE Function *FindFunction(const std::string &USR); + + CS_IGNORE TypedefDecl *FindTypedef(const std::string &Name, bool Create = false); + + CS_IGNORE TypeAlias *FindTypeAlias(const std::string &Name, bool Create = false); + + CS_IGNORE Variable *FindVariable(const std::string &USR); + + CS_IGNORE Friend *FindFriend(const std::string &USR); + + VECTOR(Namespace *, Namespaces) + VECTOR(Enumeration *, Enums) + VECTOR(Function *, Functions) + VECTOR(Class *, Classes) + VECTOR(Template *, Templates) + VECTOR(TypedefDecl *, Typedefs) + VECTOR(TypeAlias *, TypeAliases) + VECTOR(Variable *, Variables) + VECTOR(Friend *, Friends) + + std::map anonymous; + + bool isAnonymous; + }; + + class CS_API TypedefNameDecl : public Declaration + { + public: + TypedefNameDecl(DeclarationKind kind); + ~TypedefNameDecl(); + QualifiedType qualifiedType; + }; + + class CS_API TypedefDecl : public TypedefNameDecl + { + public: + DECLARE_DECL_KIND(TypedefDecl, Typedef) + ~TypedefDecl(); + }; + + class CS_API TypeAlias : public TypedefNameDecl + { + public: + TypeAlias(); + ~TypeAlias(); + TypeAliasTemplate *describedAliasTemplate; + }; + + class CS_API Friend : public Declaration + { + public: + DECLARE_DECL_KIND(Friend, Friend) + ~Friend(); + Declaration *declaration; + }; + + enum class StatementClassObsolete + { + Any, + BinaryOperator, + CallExprClass, + DeclRefExprClass, + CXXConstructExprClass, + CXXOperatorCallExpr, + ImplicitCastExpr, + ExplicitCastExpr, + }; + + class CS_API StatementObsolete + { + public: + StatementObsolete(const std::string &str, StatementClassObsolete Class = StatementClassObsolete::Any, Declaration *decl = 0); + StatementClassObsolete _class; + Declaration *decl; + std::string string; + }; + + class CS_API ExpressionObsolete : public StatementObsolete + { + public: + ExpressionObsolete(const std::string &str, StatementClassObsolete Class = StatementClassObsolete::Any, Declaration *decl = 0); + }; + + class Expr; + + class CS_API BinaryOperatorObsolete : public ExpressionObsolete + { + public: + BinaryOperatorObsolete(const std::string &str, ExpressionObsolete *lhs, ExpressionObsolete *rhs, const std::string &opcodeStr); + ~BinaryOperatorObsolete(); + ExpressionObsolete *LHS; + ExpressionObsolete *RHS; + std::string opcodeStr; + }; + + class CS_API CallExprObsolete : public ExpressionObsolete + { + public: + CallExprObsolete(const std::string &str, Declaration *decl); + ~CallExprObsolete(); + VECTOR(ExpressionObsolete *, Arguments) + }; + + class CS_API CXXConstructExprObsolete : public ExpressionObsolete + { + public: + CXXConstructExprObsolete(const std::string &str, Declaration *decl = 0); + ~CXXConstructExprObsolete(); + VECTOR(ExpressionObsolete *, Arguments) + }; + + class CS_API Parameter : public Declaration + { + public: + Parameter(); + ~Parameter(); + + QualifiedType qualifiedType; + bool isIndirect; + bool hasDefaultValue; + unsigned int index; + ExpressionObsolete *defaultArgument; + Expr *defaultValue; + }; + + enum class CXXMethodKind + { + Normal, + Constructor, + Destructor, + Conversion, + Operator, + UsingDirective + }; + + enum class CXXOperatorKind + { + None, + New, + Delete, + Array_New, + Array_Delete, + Plus, + Minus, + Star, + Slash, + Percent, + Caret, + Amp, + Pipe, + Tilde, + Exclaim, + Equal, + Less, + Greater, + PlusEqual, + MinusEqual, + StarEqual, + SlashEqual, + PercentEqual, + CaretEqual, + AmpEqual, + PipeEqual, + LessLess, + GreaterGreater, + LessLessEqual, + GreaterGreaterEqual, + EqualEqual, + ExclaimEqual, + LessEqual, + GreaterEqual, + Spaceship, + AmpAmp, + PipePipe, + PlusPlus, + MinusMinus, + Comma, + ArrowStar, + Arrow, + Call, + Subscript, + Conditional, + Coawait + }; + + class FunctionTemplateSpecialization; + + enum class FriendKind + { + None, + Declared, + Undeclared + }; + + class Stmt; + + class CS_API Function : public DeclarationContext + { + public: + Function(); + ~Function(); + + QualifiedType returnType; + bool isReturnIndirect; + bool hasThisReturn; + + bool isConstExpr; + bool isVariadic; + bool isInline; + bool isPure; + bool isDeleted; + bool isDefaulted; + FriendKind friendKind; + CXXOperatorKind operatorKind; + std::string mangled; + std::string signature; + std::string body; + Stmt *bodyStmt; + CallingConvention callingConvention; + VECTOR(Parameter *, Parameters) + FunctionTemplateSpecialization *specializationInfo; + Function *instantiatedFrom; + QualifiedType qualifiedType; + }; + + class AccessSpecifierDecl; + + enum class RefQualifierKind + { + None, + LValue, + RValue + }; + + class CS_API Method : public Function + { + public: + Method(); + ~Method(); + + bool isVirtual; + bool isStatic; + bool isConst; + bool isExplicit; + + CXXMethodKind methodKind; + + bool isDefaultConstructor; + bool isCopyConstructor; + bool isMoveConstructor; + + QualifiedType conversionType; + RefQualifierKind refQualifier; + VECTOR(Method *, OverriddenMethods) + }; + + class CS_API Enumeration : public DeclarationContext + { + public: + DECLARE_DECL_KIND(Enumeration, Enumeration) + ~Enumeration(); + + class CS_API Item : public Declaration + { + public: + DECLARE_DECL_KIND(Item, EnumerationItem) + Item(const Item &); + ~Item(); + std::string expression; + uint64_t value; + }; + + enum class CS_FLAGS EnumModifiers + { + Anonymous = 1 << 0, + Scoped = 1 << 1, + Flags = 1 << 2, + }; + + EnumModifiers modifiers; + Type *type; + BuiltinType *builtinType; + VECTOR(Item *, Items) + + Item *FindItemByName(const std::string &Name); + }; + + class CS_API Variable : public Declaration + { + public: + DECLARE_DECL_KIND(Variable, Variable) + ~Variable(); + bool isConstExpr; + std::string mangled; + QualifiedType qualifiedType; + ExpressionObsolete *initializer; + }; + + class PreprocessedEntity; + + struct CS_API BaseClassSpecifier + { + BaseClassSpecifier(); + AccessSpecifier access; + bool isVirtual; + Type *type; + int offset; + }; + + class Class; + + class CS_API Field : public Declaration + { + public: + DECLARE_DECL_KIND(Field, Field) + ~Field(); + QualifiedType qualifiedType; + Class *_class; + bool isBitField; + unsigned bitWidth; + }; + + class CS_API AccessSpecifierDecl : public Declaration + { + public: + DECLARE_DECL_KIND(AccessSpecifierDecl, AccessSpecifier) + ~AccessSpecifierDecl(); + }; + + enum class CppAbi + { + Itanium, + Microsoft, + ARM, + iOS, + iOS64, + WebAssembly + }; + + enum class VTableComponentKind + { + VCallOffset, + VBaseOffset, + OffsetToTop, + RTTI, + FunctionPointer, + CompleteDtorPointer, + DeletingDtorPointer, + UnusedFunctionPointer, + }; + + struct CS_API VTableComponent + { + VTableComponent(); + VTableComponentKind kind; + unsigned offset; + Declaration *declaration; + }; + + struct CS_API VTableLayout + { + VTableLayout(); + VTableLayout(const VTableLayout &); + ~VTableLayout(); + VECTOR(VTableComponent, Components) + }; + + struct CS_API VFTableInfo + { + VFTableInfo(); + VFTableInfo(const VFTableInfo &); + uint64_t VBTableIndex; + uint32_t VFPtrOffset; + uint32_t VFPtrFullOffset; + VTableLayout layout; + }; + + class CS_API LayoutField + { + public: + LayoutField(); + LayoutField(const LayoutField &other); + ~LayoutField(); + unsigned offset; + std::string name; + QualifiedType qualifiedType; + void *fieldPtr; + }; + + class Class; + + class CS_API LayoutBase + { + public: + LayoutBase(); + LayoutBase(const LayoutBase &other); + ~LayoutBase(); + unsigned offset; + Class *_class; + }; + + enum class RecordArgABI + { + /// Pass it using the normal C aggregate rules for the ABI, + /// potentially introducing extra copies and passing some + /// or all of it in registers. + Default = 0, + /// Pass it on the stack using its defined layout. + /// The argument must be evaluated directly into the correct + /// stack position in the arguments area, and the call machinery + /// must not move it or introduce extra copies. + DirectInMemory, + /// Pass it as a pointer to temporary memory. + Indirect + }; + + struct CS_API ClassLayout + { + ClassLayout(); + CppAbi ABI; + RecordArgABI argABI; + VECTOR(VFTableInfo, VFTables) + VTableLayout layout; + bool hasOwnVFPtr; + long VBPtrOffset; + int alignment; + int size; + int dataSize; + VECTOR(LayoutField, Fields) + VECTOR(LayoutBase, Bases) + }; + + enum class TagKind + { + Struct, + Interface, + Union, + Class, + Enum + }; + + class CS_API Class : public DeclarationContext + { + public: + Class(); + ~Class(); + + VECTOR(BaseClassSpecifier *, Bases) + VECTOR(Field *, Fields) + VECTOR(Method *, Methods) + VECTOR(AccessSpecifierDecl *, Specifiers) + + bool isPOD; + bool isAbstract; + bool isUnion; + bool isDynamic; + bool isPolymorphic; + bool hasNonTrivialDefaultConstructor; + bool hasNonTrivialCopyConstructor; + bool hasNonTrivialDestructor; + bool isExternCContext; + bool isInjected; + TagKind tagKind; + + ClassLayout *layout; + }; + + class CS_API Template : public Declaration + { + public: + Template(DeclarationKind kind); + DECLARE_DECL_KIND(Template, Template) + Declaration *TemplatedDecl; + VECTOR(Declaration *, Parameters) + }; + + template + T *DeclarationContext::FindTemplate(const std::string &USR) + { + auto foundTemplate = std::find_if(Templates.begin(), Templates.end(), + [&](Template *t) + { return t->USR == USR; }); + + if (foundTemplate != Templates.end()) + return static_cast(*foundTemplate); + + return nullptr; + } + + class CS_API TypeAliasTemplate : public Template + { + public: + TypeAliasTemplate(); + ~TypeAliasTemplate(); + }; + + class CS_API TemplateParameter : public Declaration + { + public: + TemplateParameter(DeclarationKind kind); + ~TemplateParameter(); + unsigned int depth; + unsigned int index; + bool isParameterPack; + }; + + class CS_API TemplateTemplateParameter : public Template + { + public: + TemplateTemplateParameter(); + ~TemplateTemplateParameter(); + + bool isParameterPack; + bool isPackExpansion; + bool isExpandedParameterPack; + }; + + class CS_API TypeTemplateParameter : public TemplateParameter + { + public: + TypeTemplateParameter(); + TypeTemplateParameter(const TypeTemplateParameter &); + ~TypeTemplateParameter(); + + QualifiedType defaultArgument; + }; + + class CS_API NonTypeTemplateParameter : public TemplateParameter + { + public: + NonTypeTemplateParameter(); + NonTypeTemplateParameter(const NonTypeTemplateParameter &); + ~NonTypeTemplateParameter(); + ExpressionObsolete *defaultArgument; + Expr *defaultArgumentNew; + unsigned int position; + bool isPackExpansion; + bool isExpandedParameterPack; + QualifiedType type; + }; + + class ClassTemplateSpecialization; + class ClassTemplatePartialSpecialization; + + class CS_API ClassTemplate : public Template + { + public: + ClassTemplate(); + ~ClassTemplate(); + VECTOR(ClassTemplateSpecialization *, Specializations) + ClassTemplateSpecialization *FindSpecialization(const std::string &usr); + ClassTemplatePartialSpecialization *FindPartialSpecialization(const std::string &usr); + }; + + enum class TemplateSpecializationKind + { + Undeclared, + ImplicitInstantiation, + ExplicitSpecialization, + ExplicitInstantiationDeclaration, + ExplicitInstantiationDefinition + }; + + class CS_API ClassTemplateSpecialization : public Class + { + public: + ClassTemplateSpecialization(); + ~ClassTemplateSpecialization(); + ClassTemplate *templatedDecl; + VECTOR(TemplateArgument, Arguments) + TemplateSpecializationKind specializationKind; + }; + + class CS_API ClassTemplatePartialSpecialization : public ClassTemplateSpecialization + { + public: + ClassTemplatePartialSpecialization(); + ~ClassTemplatePartialSpecialization(); + }; + + class CS_API FunctionTemplate : public Template + { + public: + FunctionTemplate(); + ~FunctionTemplate(); + VECTOR(FunctionTemplateSpecialization *, Specializations) + FunctionTemplateSpecialization *FindSpecialization(const std::string &usr); + }; + + class CS_API FunctionTemplateSpecialization + { + public: + FunctionTemplateSpecialization(); + ~FunctionTemplateSpecialization(); + FunctionTemplate *_template; + VECTOR(TemplateArgument, Arguments) + Function *specializedFunction; + TemplateSpecializationKind specializationKind; + }; + + class VarTemplateSpecialization; + class VarTemplatePartialSpecialization; + + class CS_API VarTemplate : public Template + { + public: + VarTemplate(); + ~VarTemplate(); + VECTOR(VarTemplateSpecialization *, Specializations) + VarTemplateSpecialization *FindSpecialization(const std::string &usr); + VarTemplatePartialSpecialization *FindPartialSpecialization(const std::string &usr); + }; + + class CS_API VarTemplateSpecialization : public Variable + { + public: + VarTemplateSpecialization(); + ~VarTemplateSpecialization(); + VarTemplate *templatedDecl; + VECTOR(TemplateArgument, Arguments) + TemplateSpecializationKind specializationKind; + }; + + class CS_API VarTemplatePartialSpecialization : public VarTemplateSpecialization + { + public: + VarTemplatePartialSpecialization(); + ~VarTemplatePartialSpecialization(); + }; + + class CS_API UnresolvedUsingTypename : public Declaration + { + public: + UnresolvedUsingTypename(); + ~UnresolvedUsingTypename(); + }; + + class CS_API Namespace : public DeclarationContext + { + public: + Namespace(); + ~Namespace(); + bool isInline; + }; + + enum class MacroLocation + { + Unknown, + ClassHead, + ClassBody, + FunctionHead, + FunctionParameters, + FunctionBody, + }; + + class CS_API PreprocessedEntity + { + public: + PreprocessedEntity(); + MacroLocation macroLocation; + void *originalPtr; + DeclarationKind kind; + }; + + class CS_API MacroDefinition : public PreprocessedEntity + { + public: + MacroDefinition(); + ~MacroDefinition(); + std::string name; + std::string expression; + int lineNumberStart; + int lineNumberEnd; + }; + + class CS_API MacroExpansion : public PreprocessedEntity + { + public: + MacroExpansion(); + ~MacroExpansion(); + std::string name; + std::string text; + MacroDefinition *definition; + }; + + class CS_API TranslationUnit : public Namespace + { + public: + TranslationUnit(); + ~TranslationUnit(); + std::string fileName; + bool isSystemHeader; + VECTOR(MacroDefinition *, Macros) + }; + + class CS_API ASTContext + { + public: + ASTContext(); + ~ASTContext(); + TranslationUnit *FindOrCreateModule(std::string File); + VECTOR(TranslationUnit *, TranslationUnits) + }; + + } + } +} \ No newline at end of file diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index a64b091c95..97d7736643 100644 --- a/src/CppParser/Parser.cpp +++ b/src/CppParser/Parser.cpp @@ -104,6 +104,8 @@ static CppAbi GetClassLayoutAbi(clang::TargetCXXABI::Kind abi) return CppAbi::iOS; case clang::TargetCXXABI::AppleARM64: return CppAbi::iOS64; + case clang::TargetCXXABI::WebAssembly: + return CppAbi::WebAssembly; default: llvm_unreachable("Unsupported C++ ABI kind"); } @@ -872,14 +874,31 @@ static bool IsRecordValid(const clang::RecordDecl* RC) return IsRecordValid(RC, Visited); } -static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::QualType& Ty) { +static clang::CXXRecordDecl* GetCXXRecordDeclFromTemplateName(const clang::TemplateName& Name) +{ + using namespace clang; + + switch (Name.getKind()) { + case clang::TemplateName::Template: + return dyn_cast( + Name.getAsTemplateDecl()->getTemplatedDecl()); + case clang::TemplateName::QualifiedTemplate: + return dyn_cast( + Name.getAsQualifiedTemplateName()->getTemplateDecl()->getTemplatedDecl()); + default: + assert(0 && "Unknown template name kind"); + return nullptr; + } +} + +static clang::CXXRecordDecl* GetCXXRecordDeclFromBaseType(const clang::QualType& Ty) +{ using namespace clang; if (auto RT = Ty->getAs()) return dyn_cast(RT->getDecl()); else if (auto TST = Ty->getAs()) - return dyn_cast( - TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl()); + return GetCXXRecordDeclFromTemplateName(TST->getTemplateName()); else if (auto Injected = Ty->getAs()) return Injected->getDecl(); @@ -1428,6 +1447,7 @@ NonTypeTemplateParameter* Parser::WalkNonTypeTemplateParameter(const clang::NonT HandleDeclaration(NTTPD, NTP); if (NTTPD->hasDefaultArgument()) NTP->defaultArgument = WalkExpressionObsolete(NTTPD->getDefaultArgument()); + NTP->type = GetQualifiedType(NTTPD->getType()); NTP->depth = NTTPD->getDepth(); NTP->index = NTTPD->getIndex(); NTP->isParameterPack = NTTPD->isParameterPack(); diff --git a/src/Generator.Tests/GeneratorTest.cs b/src/Generator.Tests/GeneratorTest.cs index feff986fb8..3805353ad7 100644 --- a/src/Generator.Tests/GeneratorTest.cs +++ b/src/Generator.Tests/GeneratorTest.cs @@ -35,23 +35,21 @@ public virtual void Setup(Driver driver) testModule.LibraryName, options.GeneratorKind.ToString()); if (Platform.IsMacOS) - driver.ParserOptions.TargetTriple = Environment.Is64BitProcess ? - "x86_64-apple-darwin" : "i686-apple-darwin"; + driver.ParserOptions.TargetTriple = "x86_64-apple-darwin"; var path = Path.GetFullPath(GetTestsDirectory(name)); testModule.IncludeDirs.Add(path); testModule.LibraryDirs.Add(options.OutputDir); testModule.Libraries.Add($"{name}.Native"); - Diagnostics.Message("Looking for tests in: {0}", path); var files = Directory.EnumerateFiles(path, "*.h", SearchOption.AllDirectories); foreach (var file in files) { - string includeDir = Path.GetDirectoryName(file); + var includeDir = Path.GetDirectoryName(file); + if (!testModule.IncludeDirs.Contains(includeDir)) - { testModule.IncludeDirs.Add(includeDir); - } + testModule.Headers.Add(Path.GetFileName(file)); } } @@ -72,16 +70,16 @@ public virtual void SetupPasses(Driver driver) public static string GetTestsDirectory(string name) { var directory = new DirectoryInfo( - Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty); while (directory != null) { - var path = Path.Combine(directory.FullName, "tests", name); + var path = Path.Combine(directory.FullName, "tests", "dotnet", name); if (Directory.Exists(path)) return path; - path = Path.Combine(directory.FullName, "external", "CppSharp", "tests", name); + path = Path.Combine(directory.FullName, "external", "CppSharp", "tests", "dotnet", name); if (Directory.Exists(path)) return path; @@ -89,15 +87,12 @@ public static string GetTestsDirectory(string name) directory = directory.Parent; } - throw new Exception(string.Format( - "Tests directory for project '{0}' was not found", name)); + throw new Exception($"Tests directory for project '{name}' was not found"); } static string GetOutputDirectory() { - string exePath = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath; - var directory = Directory.GetParent(exePath); - + var directory = Directory.GetParent(Assembly.GetExecutingAssembly().Location); while (directory != null) { var path = Path.Combine(directory.FullName, "build"); diff --git a/src/Generator/AST/VTables.cs b/src/Generator/AST/VTables.cs index 13add5b8fc..93e59ed9dc 100644 --- a/src/Generator/AST/VTables.cs +++ b/src/Generator/AST/VTables.cs @@ -34,6 +34,7 @@ private static List GatherVTableMethodEntries(VTableLayout layo where component.Kind != VTableComponentKind.CompleteDtorPointer && component.Kind != VTableComponentKind.RTTI && component.Kind != VTableComponentKind.UnusedFunctionPointer && + component.Kind != VTableComponentKind.OffsetToTop && component.Method != null select component); diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 3f9a847ec5..82780bfa2c 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -8,6 +8,7 @@ using CppSharp.Generators.CLI; using CppSharp.Generators.Cpp; using CppSharp.Generators.CSharp; +using CppSharp.Generators.Emscripten; using CppSharp.Generators.TS; using CppSharp.Parser; using CppSharp.Passes; @@ -43,6 +44,8 @@ Generator CreateGeneratorFromKind(GeneratorKind kind) return new CLIGenerator(Context); case GeneratorKind.CSharp: return new CSharpGenerator(Context); + case GeneratorKind.Emscripten: + return new EmscriptenGenerator(Context); case GeneratorKind.QuickJS: return new QuickJSGenerator(Context); case GeneratorKind.NAPI: @@ -82,7 +85,7 @@ void ValidateOptions() public void Setup() { ValidateOptions(); - ParserOptions.Setup(); + ParserOptions.Setup(Platform.Host); Context = new BindingContext(Options, ParserOptions); Context.LinkerOptions.Setup(ParserOptions.TargetTriple, ParserOptions.LanguageVersion); Generator = CreateGeneratorFromKind(Options.GeneratorKind); @@ -109,7 +112,8 @@ void OnFileParsed(IEnumerable files, ParserResult result) switch (result.Kind) { case ParserResultKind.Success: - Diagnostics.Message("Parsed '{0}'", string.Join(", ", files)); + if (!Options.Quiet) + Diagnostics.Message("Parsed '{0}'", string.Join(", ", files)); break; case ParserResultKind.Error: Diagnostics.Error("Error parsing '{0}'", string.Join(", ", files)); @@ -180,27 +184,22 @@ public bool ParseLibraries() ClangParser.LibraryParsed += OnFileParsed; foreach (var module in Options.Modules) { - using (var linkerOptions = new LinkerOptions(Context.LinkerOptions)) + using var linkerOptions = new LinkerOptions(Context.LinkerOptions); + foreach (var libraryDir in module.LibraryDirs) + linkerOptions.AddLibraryDirs(libraryDir); + + foreach (var library in module.Libraries.Where(library => + Context.Symbols.Libraries.All(l => l.FileName != library))) { - foreach (var libraryDir in module.LibraryDirs) - linkerOptions.AddLibraryDirs(libraryDir); - - foreach (string library in module.Libraries) - { - if (Context.Symbols.Libraries.Any(l => l.FileName == library)) - continue; - linkerOptions.AddLibraries(library); - } - - using (var res = ClangParser.ParseLibrary(linkerOptions)) - { - if (res.Kind != ParserResultKind.Success) - continue; - - for (uint i = 0; i < res.LibrariesCount; i++) - Context.Symbols.Libraries.Add(ClangParser.ConvertLibrary(res.GetLibraries(i))); - } + linkerOptions.AddLibraries(library); } + + using var res = ClangParser.ParseLibrary(linkerOptions); + if (res.Kind != ParserResultKind.Success) + continue; + + for (uint i = 0; i < res.LibrariesCount; i++) + Context.Symbols.Libraries.Add(ClangParser.ConvertLibrary(res.GetLibraries(i))); } ClangParser.LibraryParsed -= OnFileParsed; @@ -212,95 +211,99 @@ public bool ParseLibraries() public void SetupPasses(ILibrary library) { - var TranslationUnitPasses = Context.TranslationUnitPasses; + var passes = Context.TranslationUnitPasses; - TranslationUnitPasses.AddPass(new ResolveIncompleteDeclsPass()); - TranslationUnitPasses.AddPass(new IgnoreSystemDeclarationsPass()); - TranslationUnitPasses.AddPass(new MatchParamNamesWithInstantiatedFromPass()); + passes.AddPass(new ResolveIncompleteDeclsPass()); + passes.AddPass(new IgnoreSystemDeclarationsPass()); + passes.AddPass(new MatchParamNamesWithInstantiatedFromPass()); if (Options.IsCSharpGenerator) - TranslationUnitPasses.AddPass(new EqualiseAccessOfOverrideAndBasePass()); + passes.AddPass(new EqualiseAccessOfOverrideAndBasePass()); - TranslationUnitPasses.AddPass(new FlattenAnonymousTypesToFields()); - TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass()); - TranslationUnitPasses.AddPass(new MarkUsedClassInternalsPass()); + passes.AddPass(new FlattenAnonymousTypesToFields()); + passes.AddPass(new CheckIgnoredDeclsPass()); + passes.AddPass(new MarkUsedClassInternalsPass()); if (Options.IsCSharpGenerator) { - TranslationUnitPasses.AddPass(new TrimSpecializationsPass()); - TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions()); - TranslationUnitPasses.AddPass(new GenerateSymbolsPass()); - TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass()); + passes.AddPass(new TrimSpecializationsPass()); + passes.AddPass(new CheckAmbiguousFunctions()); + passes.AddPass(new GenerateSymbolsPass()); + passes.AddPass(new CheckIgnoredDeclsPass()); } if (Options.IsCLIGenerator || Options.IsCSharpGenerator) { - TranslationUnitPasses.AddPass(new MoveFunctionToClassPass()); - TranslationUnitPasses.AddPass(new ValidateOperatorsPass()); + passes.AddPass(new MoveFunctionToClassPass()); + passes.AddPass(new ValidateOperatorsPass()); } library.SetupPasses(this); - TranslationUnitPasses.AddPass(new FindSymbolsPass()); - TranslationUnitPasses.AddPass(new CheckMacroPass()); - TranslationUnitPasses.AddPass(new CheckStaticClass()); + passes.AddPass(new FindSymbolsPass()); + passes.AddPass(new CheckMacroPass()); + passes.AddPass(new CheckStaticClass()); if (Options.IsCLIGenerator || Options.IsCSharpGenerator || Options.IsCppGenerator) { - TranslationUnitPasses.AddPass(new CheckAmbiguousFunctions()); + passes.AddPass(new CheckAmbiguousFunctions()); } - TranslationUnitPasses.AddPass(new ConstructorToConversionOperatorPass()); - TranslationUnitPasses.AddPass(new MarshalPrimitivePointersAsRefTypePass()); + passes.AddPass(new ConstructorToConversionOperatorPass()); + passes.AddPass(new MarshalPrimitivePointersAsRefTypePass()); if (Options.IsCLIGenerator || Options.IsCSharpGenerator) { - TranslationUnitPasses.AddPass(new CheckOperatorsOverloadsPass()); + passes.AddPass(new CheckOperatorsOverloadsPass()); } - TranslationUnitPasses.AddPass(new CheckVirtualOverrideReturnCovariance()); - TranslationUnitPasses.AddPass(new CleanCommentsPass()); + passes.AddPass(new CheckVirtualOverrideReturnCovariance()); + passes.AddPass(new CleanCommentsPass()); Generator.SetupPasses(); - TranslationUnitPasses.AddPass(new CleanInvalidDeclNamesPass()); - TranslationUnitPasses.AddPass(new FastDelegateToDelegatesPass()); - TranslationUnitPasses.AddPass(new FieldToPropertyPass()); - TranslationUnitPasses.AddPass(new CheckIgnoredDeclsPass()); - TranslationUnitPasses.AddPass(new CheckFlagEnumsPass()); - TranslationUnitPasses.AddPass(new MakeProtectedNestedTypesPublicPass()); + passes.AddPass(new CleanInvalidDeclNamesPass()); + passes.AddPass(new FastDelegateToDelegatesPass()); + passes.AddPass(new FieldToPropertyPass()); + passes.AddPass(new CheckIgnoredDeclsPass()); + passes.AddPass(new CheckFlagEnumsPass()); + passes.AddPass(new MakeProtectedNestedTypesPublicPass()); if (Options.IsCSharpGenerator) { - TranslationUnitPasses.AddPass(new GenerateAbstractImplementationsPass()); - TranslationUnitPasses.AddPass(new MultipleInheritancePass()); + passes.AddPass(new GenerateAbstractImplementationsPass()); + passes.AddPass(new MultipleInheritancePass()); } if (Options.IsCLIGenerator || Options.IsCSharpGenerator) { - TranslationUnitPasses.AddPass(new DelegatesPass()); - TranslationUnitPasses.AddPass(new GetterSetterToPropertyPass()); + passes.AddPass(new DelegatesPass()); } - TranslationUnitPasses.AddPass(new StripUnusedSystemTypesPass()); + if (Options.GeneratorKind != GeneratorKind.C) + { + passes.AddPass(new GetterSetterToPropertyPass()); + } + + passes.AddPass(new StripUnusedSystemTypesPass()); if (Options.IsCSharpGenerator) { - TranslationUnitPasses.AddPass(new SpecializationMethodsWithDependentPointersPass()); - TranslationUnitPasses.AddPass(new ParamTypeToInterfacePass()); + passes.AddPass(new SpecializationMethodsWithDependentPointersPass()); + passes.AddPass(new ParamTypeToInterfacePass()); } - TranslationUnitPasses.AddPass(new CheckDuplicatedNamesPass()); + passes.AddPass(new CheckDuplicatedNamesPass()); if (Options.IsCLIGenerator || Options.IsCSharpGenerator) { - TranslationUnitPasses.RenameDeclsUpperCase(RenameTargets.Any & ~RenameTargets.Parameter); - TranslationUnitPasses.AddPass(new CheckKeywordNamesPass()); + passes.RenameDeclsUpperCase(RenameTargets.Any & ~RenameTargets.Parameter); + passes.AddPass(new CheckKeywordNamesPass()); } - Context.TranslationUnitPasses.AddPass(new HandleVariableInitializerPass()); + passes.AddPass(new HandleVariableInitializerPass()); - TranslationUnitPasses.AddPass(new MarkEventsWithUniqueIdPass()); + passes.AddPass(new MarkEventsWithUniqueIdPass()); } public void ProcessCode() @@ -342,10 +345,10 @@ public void SaveCode(IEnumerable outputs) var file = Path.Combine(outputPath, fileRelativePath); WriteGeneratedCodeToFile(file, template.Generate()); - if (output.TranslationUnit.Module != null) - output.TranslationUnit.Module.CodeFiles.Add(file); + output.TranslationUnit.Module?.CodeFiles.Add(file); - Diagnostics.Message("Generated '{0}'", fileRelativePath); + if (!Options.Quiet) + Diagnostics.Message("Generated '{0}'", fileRelativePath); } } } @@ -364,7 +367,7 @@ private void WriteGeneratedCodeToFile(string file, string generatedCode) public bool CompileCode(Module module) { - var msBuildGenerator = new MSBuildGenerator(Context, module, libraryMappings); + var msBuildGenerator = new MSBuildGenerator(Context, module, LibraryMappings); msBuildGenerator.Process(); string csproj = Path.Combine(Options.OutputDir, $"{module.LibraryName}.{msBuildGenerator.FileExtension}"); @@ -375,7 +378,7 @@ public bool CompileCode(Module module) if (error == 0) { Diagnostics.Message($@"Compilation succeeded: { - libraryMappings[module] = Path.Combine( + LibraryMappings[module] = Path.Combine( Options.OutputDir, $"{module.LibraryName}.dll")}."); return true; } @@ -404,7 +407,7 @@ public void Dispose() } private bool hasParsingErrors; - private static readonly Dictionary libraryMappings = new Dictionary(); + private static readonly Dictionary LibraryMappings = new(); } public static class ConsoleDriver @@ -412,67 +415,68 @@ public static class ConsoleDriver public static void Run(ILibrary library) { var options = new DriverOptions(); - using (var driver = new Driver(options)) - { - library.Setup(driver); + using var driver = new Driver(options); + library.Setup(driver); - driver.Setup(); + driver.Setup(); - if (driver.Options.Verbose) - Diagnostics.Level = DiagnosticKind.Debug; + if (driver.Options.Verbose) + Diagnostics.Level = DiagnosticKind.Debug; - if (!options.Quiet) - Diagnostics.Message("Parsing libraries..."); + if (!options.Quiet) + Diagnostics.Message("Parsing libraries..."); - if (!driver.ParseLibraries()) - return; + if (!driver.ParseLibraries()) + return; - if (!options.Quiet) - Diagnostics.Message("Parsing code..."); + if (!options.Quiet) + Diagnostics.Message("Parsing code..."); - if (!driver.ParseCode()) - { - Diagnostics.Error("CppSharp has encountered an error while parsing code."); - return; - } + if (!driver.ParseCode()) + { + Diagnostics.Error("CppSharp has encountered an error while parsing code."); + return; + } - new CleanUnitPass { Context = driver.Context }.VisitASTContext(driver.Context.ASTContext); - options.Modules.RemoveAll(m => m != options.SystemModule && !m.Units.GetGenerated().Any()); + new CleanUnitPass { Context = driver.Context }.VisitASTContext(driver.Context.ASTContext); + foreach (var module in options.Modules.Where( + m => m != options.SystemModule && !m.Units.GetGenerated().Any())) + { + Diagnostics.Message($"Removing module {module} because no translation units are generated..."); + options.Modules.Remove(module); + } - if (!options.Quiet) - Diagnostics.Message("Processing code..."); + if (!options.Quiet) + Diagnostics.Message("Processing code..."); - driver.SetupPasses(library); - driver.SetupTypeMaps(); - driver.SetupDeclMaps(); + driver.SetupPasses(library); + driver.SetupTypeMaps(); + driver.SetupDeclMaps(); - library.Preprocess(driver, driver.Context.ASTContext); + library.Preprocess(driver, driver.Context.ASTContext); - driver.ProcessCode(); - library.Postprocess(driver, driver.Context.ASTContext); + driver.ProcessCode(); + library.Postprocess(driver, driver.Context.ASTContext); - if (!options.Quiet) - Diagnostics.Message("Generating code..."); + if (!options.Quiet) + Diagnostics.Message("Generating code..."); - if (!options.DryRun) - { - var outputs = driver.GenerateCode(); + if (options.DryRun) + return; - library.GenerateCode(driver, outputs); + var outputs = driver.GenerateCode(); - foreach (var output in outputs) - { - foreach (var pass in driver.Context.GeneratorOutputPasses.Passes) - { - pass.VisitGeneratorOutput(output); - } - } + library.GenerateCode(driver, outputs); - driver.SaveCode(outputs); - if (driver.Options.IsCSharpGenerator && driver.Options.CompileCode) - driver.Options.Modules.Any(m => !driver.CompileCode(m)); - } + foreach (var output in outputs) + { + foreach (var pass in driver.Context.GeneratorOutputPasses.Passes) + pass.VisitGeneratorOutput(output); } + + driver.SaveCode(outputs); + if (driver.Options.IsCSharpGenerator && driver.Options.CompileCode) + driver.Options.Modules.Any(m => !driver.CompileCode(m)); } } } diff --git a/src/Generator/Generator.cs b/src/Generator/Generator.cs index e9bcc3e818..cf414b4823 100644 --- a/src/Generator/Generator.cs +++ b/src/Generator/Generator.cs @@ -14,6 +14,7 @@ public enum GeneratorKind CSharp = 2, C, CPlusPlus, + Emscripten, ObjectiveC, Java, Swift, diff --git a/src/Generator/Generators/C/CppTypePrinter.cs b/src/Generator/Generators/C/CppTypePrinter.cs index 8acd62c7cf..f289705f76 100644 --- a/src/Generator/Generators/C/CppTypePrinter.cs +++ b/src/Generator/Generators/C/CppTypePrinter.cs @@ -584,7 +584,8 @@ public override TypePrinterResult VisitClassTemplateSpecializationDecl( args.Add(arg.Type.Visit(this)); break; case TemplateArgument.ArgumentKind.Declaration: - args.Add(arg.Declaration.Visit(this)); + if (arg.Declaration != null) + args.Add(arg.Declaration.Visit(this)); break; case TemplateArgument.ArgumentKind.Integral: ClassTemplate template = specialization.TemplatedDecl; @@ -596,6 +597,7 @@ public override TypePrinterResult VisitClassTemplateSpecializationDecl( { args.Add(arg.Integral.ToString(CultureInfo.InvariantCulture)); } + break; } } @@ -634,7 +636,7 @@ public override TypePrinterResult VisitFunctionDecl(Function function) CppSharp.AST.Type desugared = function.FunctionType.Type.Desugar(); if (!desugared.IsPointerTo(out functionType)) functionType = (FunctionType)desugared; - string exceptionType = Print(functionType.ExceptionSpecType); + string exceptionType = functionType != null ? Print(functionType.ExceptionSpecType) : ""; var @return = function.OriginalReturnType.Visit(this); @return.Name = @class + name; diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 1376592c92..c641651754 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -61,7 +61,8 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals) break; case ArrayType.ArraySize.Incomplete: // const char* and const char[] are the same so we can use a string - if (array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && + if (Context.Context.Options.MarshalConstCharArrayAsString && + array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) { var pointer = new PointerType { QualifiedPointee = array.QualifiedType }; diff --git a/src/Generator/Generators/CLI/CLITypePrinter.cs b/src/Generator/Generators/CLI/CLITypePrinter.cs index 50ff8d46d4..69077affe2 100644 --- a/src/Generator/Generators/CLI/CLITypePrinter.cs +++ b/src/Generator/Generators/CLI/CLITypePrinter.cs @@ -35,7 +35,8 @@ public override TypePrinterResult VisitArrayType(ArrayType array, TypeQualifiers quals) { // const char* and const char[] are the same so we can use a string - if (array.SizeType == ArrayType.ArraySize.Incomplete && + if (Context.Options.MarshalConstCharArrayAsString && + array.SizeType == ArrayType.ArraySize.Incomplete && array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) return VisitCILType(new CILType(typeof(string)), quals); diff --git a/src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs b/src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs index c4c2f1d5d7..3884d1694c 100644 --- a/src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs @@ -27,11 +27,11 @@ public string VisitParameter(Parameter parameter) if (desugared.IsPrimitiveType() && (parameter.DefaultArgument.Declaration != null || parameter.DefaultArgument.Class == StatementClass.BinaryOperator)) - return $"({desugared.Visit(typePrinter)}) {expression}"; + return $"({desugared.Visit(typePrinter)}) ({expression})"; var finalType = (desugared.GetFinalPointee() ?? desugared).Desugar(); if (finalType.TryGetClass(out var @class) && @class.IsInterface) return $@"({@class.Visit(typePrinter)}) ({ - @class.OriginalClass.Visit(typePrinter)}) {expression}"; + @class.OriginalClass.Visit(typePrinter)}) ({expression})"; return expression; } @@ -61,20 +61,15 @@ public string VisitExpression(ExpressionObsolete expr) case StatementClass.BinaryOperator: var binaryOperator = (BinaryOperatorObsolete)expr; - var lhsResult = binaryOperator.LHS.String; - if (binaryOperator.LHS.Declaration is Enumeration.Item) - lhsResult = binaryOperator.LHS.Declaration.Visit(typePrinter).Type; - - var rhsResult = binaryOperator.RHS.String; - if (binaryOperator.RHS.Declaration is Enumeration.Item) - rhsResult = binaryOperator.RHS.Declaration.Visit(typePrinter).Type; + var lhsResult = VisitExpression(binaryOperator.LHS); + var rhsResult = VisitExpression(binaryOperator.RHS); return $"{lhsResult} {binaryOperator.OpcodeStr} {rhsResult}"; case StatementClass.ConstructorReference: var constructorExpr = (CXXConstructExprObsolete)expr; if (constructorExpr.Arguments.Count == 1 && - constructorExpr.Arguments[0].Declaration is Enumeration.Item) - return constructorExpr.Arguments[0].Declaration.Visit(typePrinter).Type; + constructorExpr.Arguments[0].Class != StatementClass.Any) + return VisitExpression(constructorExpr.Arguments[0]); goto default; default: return expr.String; @@ -88,4 +83,4 @@ public string ToString(Type type) private readonly TypePrinter typePrinter; } -} \ No newline at end of file +} diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 8f64f72b27..21d7279ca7 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -116,7 +116,8 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals) break; case ArrayType.ArraySize.Incomplete: // const char* and const char[] are the same so we can use a string - if (array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && + if (Context.Context.Options.MarshalConstCharArrayAsString && + array.Type.Desugar().IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) { var pointer = new PointerType { QualifiedPointee = array.QualifiedType }; @@ -906,7 +907,8 @@ private void MarshalArray(ArrayType arrayType) var elementType = arrayType.Type.Desugar(); - if (elementType.IsPrimitiveType() || + if ((elementType.IsPrimitiveType() && + !(elementType.IsPrimitiveType(PrimitiveType.Char) && Context.Context.Options.MarshalCharAsManagedChar)) || elementType.IsPointerToPrimitiveType()) { if (Context.Context.Options.UseSpan && !elementType.IsConstCharString()) @@ -948,6 +950,10 @@ private void MarshalArray(ArrayType arrayType) Context.Before.WriteLine($@"{intermediateArray}[i] = { element} is null ? {intPtrZero} : {element}.{Helpers.InstanceIdentifier};"); } + else if (elementType.IsPrimitiveType(PrimitiveType.Char) && + Context.Context.Options.MarshalCharAsManagedChar) + Context.Before.WriteLine($@"{intermediateArray}[i] = global::System.Convert.ToSByte({ + element});"); else Context.Before.WriteLine($@"{intermediateArray}[i] = { element} is null ? new {intermediateArrayType}() : *({ diff --git a/src/Generator/Generators/CSharp/CSharpSources.cs b/src/Generator/Generators/CSharp/CSharpSources.cs index d9da8b46c6..3ee9104b1a 100644 --- a/src/Generator/Generators/CSharp/CSharpSources.cs +++ b/src/Generator/Generators/CSharp/CSharpSources.cs @@ -256,9 +256,9 @@ public virtual void GenerateNamespaceFunctionsAndVariables(DeclarationContext co .Any(); using (PushWriteBlock(BlockKind.Functions, $"public unsafe partial {(isStruct ? "struct" : "class")} {parentName}", NewLineKind.BeforeNextBlock)) - { + { using (PushWriteBlock(BlockKind.InternalsClass, GetClassInternalHead(new Class { Name = parentName }), NewLineKind.BeforeNextBlock)) - { + { // Generate all the internal function declarations. foreach (var function in context.Functions) { @@ -301,7 +301,7 @@ template.OriginalNamespace is Class && template.Name); using (PushWriteBlock(BlockKind.Namespace, namespaceName, NewLineKind.BeforeNextBlock)) - { + { var generated = GetGeneratedClasses(template, specializations); foreach (var nestedTemplate in template.Classes.Where( @@ -972,7 +972,7 @@ private string GeneratePointerTo(Variable var) string ptr = Generator.GeneratedIdentifier("ptr"); if (arrayType != null) { - if (arrayType.Type.IsPrimitiveType(PrimitiveType.Char) && arrayType.SizeType != ArrayType.ArraySize.Constant) + if (Context.Options.MarshalConstCharArrayAsString && arrayType.Type.IsPrimitiveType(PrimitiveType.Char) && arrayType.SizeType != ArrayType.ArraySize.Constant) WriteLine($"var {ptr} = {location};"); else WriteLine($"var {ptr} = ({arrayType.Type.Visit(TypePrinter)}*){location};"); @@ -1310,6 +1310,17 @@ private bool GenerateVariableGetter(Variable var) }; ctx.PushMarshalKind(MarshalKind.ReturnVariableArray); + if (var.Type.Desugar().IsPointer()) + { + var pointerType = var.Type.Desugar() as PointerType; + while (pointerType != null && !pointerType.Pointee.Desugar().IsPrimitiveType(PrimitiveType.Char)) + { + ptr = $"*{ptr}"; + pointerType = pointerType.Pointee.Desugar() as PointerType; + } + ptr = $"({TypePrinter.IntPtrType}*)({ptr})"; + } + var arrayType = var.Type.Desugar() as ArrayType; var isRefTypeArray = arrayType != null && var.Namespace is Class context && context.IsRefType; var elementType = arrayType?.Type.Desugar(); @@ -1645,19 +1656,27 @@ private void GenerateVariable(Class @class, Variable variable) var variableType = variable.Type.Visit(TypePrinter); TypePrinter.PopMarshalKind(); - var signature = $"public static {variableType} {variable.Name}"; + bool hasInitializer = variable.Initializer != null && !string.IsNullOrWhiteSpace(variable.Initializer.String); - if (variable.Initializer != null && !string.IsNullOrWhiteSpace(variable.Initializer.String)) - GeneratePropertyGetterForVariableWithInitializer(variable, signature); + if (hasInitializer && variable.QualifiedType.Qualifiers.IsConst && + (variable.Type.Desugar() is BuiltinType || variableType.ToString() == "string")) + Write($"public const {variableType} {variable.Name} = {variable.Initializer.String};"); else { - using (WriteBlock(signature)) + var signature = $"public static {variableType} {variable.Name}"; + + if (hasInitializer) + GeneratePropertyGetterForVariableWithInitializer(variable, signature); + else { - GeneratePropertyGetter(variable, @class); + using (WriteBlock(signature)) + { + GeneratePropertyGetter(variable, @class); - if (!variable.QualifiedType.Qualifiers.IsConst && - !(variable.Type.Desugar() is ArrayType)) - GeneratePropertySetter(variable, @class); + if (!variable.QualifiedType.Qualifiers.IsConst && + !(variable.Type.Desugar() is ArrayType)) + GeneratePropertySetter(variable, @class); + } } } @@ -1810,7 +1829,7 @@ public void GenerateVTable(Class @class) return __vtables; }} - set {{ + set {{ __vtables = value; }}", trimIndentation: true); } @@ -2326,13 +2345,13 @@ private void GenerateDisposeMethods(Class @class) // Normally, calling the native dtor should be controlled by whether or not we // we own the underlying instance. (i.e. Helpers.OwnsNativeInstanceIdentifier). // However, there are 2 situations when the caller needs to have direct control - // + // // 1. When we have a virtual dtor on the native side we detour the vtable entry // even when we don't own the underlying native instance. I think we do this // so that the managed side can null out the __Instance pointer and remove the // instance from the NativeToManagedMap. Of course, this is somewhat half-hearted // since we can't/don't do this when there's no virtual dtor available to detour. - // Anyway, we must be able to call the native dtor in this case even if we don't + // Anyway, we must be able to call the native dtor in this case even if we don't /// own the underlying native instance. // // 2. When we we pass a disposable object to a function "by value" then the callee @@ -2343,7 +2362,7 @@ private void GenerateDisposeMethods(Class @class) // .... // compiler generates call to f.dtor() at the end of function // } - // + // // IDisposable.Dispose() and Object.Finalize() set callNativeDtor = Helpers.OwnsNativeInstanceIdentifier WriteLine("if (callNativeDtor)"); if (@class.IsDependent || dtor.IsVirtual) @@ -2364,7 +2383,7 @@ c is ClassTemplateSpecialization ? } // If we have any fields holding references to unmanaged memory allocated here, free the - // referenced memory. Don't rely on testing if the field's IntPtr is IntPtr.Zero since + // referenced memory. Don't rely on testing if the field's IntPtr is IntPtr.Zero since // unmanaged memory isn't always initialized and/or a reference may be owned by the // native side. // @@ -2616,7 +2635,7 @@ private void Generate__CopyValue(Class @class, string @internal) using (WriteBlock($"private static void* __CopyValue({@internal} native)")) { var copyCtorMethod = @class.Methods.FirstOrDefault(method => method.IsCopyConstructor); - + if (@class.HasNonTrivialCopyConstructor && copyCtorMethod != null && copyCtorMethod.IsGenerated) { // Allocate memory for a new native object and call the ctor. @@ -2851,7 +2870,7 @@ private bool GenerateMethodBody(Class @class, Method method, private string OverloadParamNameWithDefValue(Parameter p, ref int index) { - return p.Type.IsPointerToPrimitiveType() && p.Usage == ParameterUsage.InOut && p.HasDefaultValue + return (p.Type.IsPointerToPrimitiveType() || p.Type.IsPointerToEnum()) && p.Usage == ParameterUsage.InOut && p.HasDefaultValue ? "ref param" + index++ : ExpressionPrinter.VisitParameter(p); } @@ -2870,13 +2889,15 @@ private void GenerateOverloadCall(Function function) for (int i = 0, j = 0; i < function.Parameters.Count; i++) { var parameter = function.Parameters[i]; - PrimitiveType primitiveType; + PrimitiveType primitiveType = PrimitiveType.Null; + Enumeration enumeration = null; if (parameter.Kind == ParameterKind.Regular && parameter.Ignore && - parameter.Type.IsPointerToPrimitiveType(out primitiveType) && + (parameter.Type.IsPointerToPrimitiveType(out primitiveType) || + parameter.Type.IsPointerToEnum(out enumeration)) && parameter.Usage == ParameterUsage.InOut && parameter.HasDefaultValue) { var pointeeType = ((PointerType)parameter.Type).Pointee.ToString(); - WriteLine($@"{pointeeType} param{j++} = {(primitiveType == PrimitiveType.Bool ? "false" : "0")};"); + WriteLine($@"{pointeeType} param{j++} = {(primitiveType == PrimitiveType.Bool ? "false" : $"({pointeeType})0")};"); } } @@ -2924,7 +2945,7 @@ private void GenerateEquals(Class @class) private void GenerateGetHashCode(Class @class) { using (WriteBlock("public override int GetHashCode()")) - { + { if (!@class.IsRefType) WriteLine($"return {Helpers.InstanceIdentifier}.GetHashCode();"); else @@ -3075,7 +3096,7 @@ private void GenerateClassConstructor(Method method, Class @class) // Copy any string references owned by the source to the new instance so we // don't have to ref count them. // If there is no property or no setter then this instance can never own the native - // memory. Worry about the case where there's only a setter (write-only) when we + // memory. Worry about the case where there's only a setter (write-only) when we // understand the use case and how it can occur. foreach (var prop in @class.GetConstCharFieldProperties()) { diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index c31a0df833..7271179569 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -111,7 +111,8 @@ public override TypePrinterResult VisitArrayType(ArrayType array, } // const char* and const char[] are the same so we can use a string - if (array.SizeType == ArrayType.ArraySize.Incomplete && + if (Context.Options.MarshalConstCharArrayAsString && + array.SizeType == ArrayType.ArraySize.Incomplete && arrayType.IsPrimitiveType(PrimitiveType.Char) && array.QualifiedType.Qualifiers.IsConst) return "string"; @@ -123,6 +124,13 @@ public override TypePrinterResult VisitArrayType(ArrayType array, return $"{prefix}string[]"; } + if (arrayType.IsPrimitiveType(PrimitiveType.Bool)) + { + var prefix = ContextKind == TypePrinterContextKind.Managed ? string.Empty : + "[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1)] "; + return $"{prefix}bool[]"; + } + if (Context.Options.UseSpan && !(array.SizeType != ArrayType.ArraySize.Constant && MarshalKind == MarshalKind.ReturnVariableArray)) { diff --git a/src/Generator/Generators/CodeGenerator.cs b/src/Generator/Generators/CodeGenerator.cs index 39eb7e4984..e0057a13d1 100644 --- a/src/Generator/Generators/CodeGenerator.cs +++ b/src/Generator/Generators/CodeGenerator.cs @@ -316,7 +316,7 @@ public virtual bool VisitClassDeclContext(Class @class) property.Visit(this); } - VisitClassConstructors(@class); + VisitClassConstructors(@class.Constructors.Where(c => !ASTUtils.CheckIgnoreMethod(c))); VisitClassMethods(@class); return true; @@ -333,9 +333,9 @@ public virtual void VisitClassMethods(Class @class) } } - public virtual void VisitClassConstructors(Class @class) + public virtual void VisitClassConstructors(IEnumerable constructors) { - foreach (var ctor in @class.Constructors.Where(c => !ASTUtils.CheckIgnoreMethod(c))) + foreach (var ctor in constructors) { ctor.Visit(this); } diff --git a/src/Generator/Generators/Emscripten/EmscriptenGenerator.cs b/src/Generator/Generators/Emscripten/EmscriptenGenerator.cs new file mode 100644 index 0000000000..f2f7e71a14 --- /dev/null +++ b/src/Generator/Generators/Emscripten/EmscriptenGenerator.cs @@ -0,0 +1,73 @@ +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; +using CppSharp.Generators.Cpp; + +namespace CppSharp.Generators.Emscripten +{ + /// + /// Emscripten generator responsible for driving the generation of binding files. + /// Embind documentation: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html + /// + public class EmscriptenGenerator : CppGenerator + { + public EmscriptenGenerator(BindingContext context) : base(context) + { + } + + public override List Generate() + { + var outputs = base.Generate(); + + foreach (var module in Context.Options.Modules) + { + if (module == Context.Options.SystemModule) + continue; + + var output = GenerateModule(module); + if (output != null) + { + OnUnitGenerated(output); + outputs.Add(output); + } + } + + return outputs; + } + + public override List Generate(IEnumerable units) + { + var outputs = new List(); + + var header = new EmscriptenHeaders(Context, units); + outputs.Add(header); + + var source = new EmscriptenSources(Context, units); + outputs.Add(source); + + return outputs; + } + + public override GeneratorOutput GenerateModule(Module module) + { + if (module == Context.Options.SystemModule) + return null; + + var moduleGen = new EmscriptenModule(Context, module); + + var output = new GeneratorOutput + { + TranslationUnit = new TranslationUnit + { + FilePath = $"{module.LibraryName}_embind_module.cpp", + Module = module + }, + Outputs = new List { moduleGen } + }; + + output.Outputs[0].Process(); + + return output; + } + } +} diff --git a/src/Generator/Generators/Emscripten/EmscriptenHeaders.cs b/src/Generator/Generators/Emscripten/EmscriptenHeaders.cs new file mode 100644 index 0000000000..2cd8a3e400 --- /dev/null +++ b/src/Generator/Generators/Emscripten/EmscriptenHeaders.cs @@ -0,0 +1,48 @@ +using System.Collections.Generic; +using CppSharp.AST; + +namespace CppSharp.Generators.Emscripten +{ + /// + /// Generates Emscripten Embind C/C++ header files. + /// Embind documentation: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html + /// + public sealed class EmscriptenHeaders : EmscriptenCodeGenerator + { + public EmscriptenHeaders(BindingContext context, IEnumerable units) + : base(context, units) + { + CTypePrinter.PushContext(TypePrinterContextKind.Managed); + } + + //public override bool ShouldGenerateNamespaces => false; + + public override void Process() + { + GenerateFilePreamble(CommentKind.BCPL); + + PushBlock(BlockKind.Includes); + WriteLine("#pragma once"); + NewLine(); + PopBlock(); + + var name = GetTranslationUnitName(TranslationUnit); + WriteLine($"extern \"C\" void embind_init_{name}();"); + } + + public override bool VisitClassDecl(Class @class) + { + return true; + } + + public override bool VisitEvent(Event @event) + { + return true; + } + + public override bool VisitFieldDecl(Field field) + { + return true; + } + } +} diff --git a/src/Generator/Generators/Emscripten/EmscriptenMarshal.cs b/src/Generator/Generators/Emscripten/EmscriptenMarshal.cs new file mode 100644 index 0000000000..0e05a74042 --- /dev/null +++ b/src/Generator/Generators/Emscripten/EmscriptenMarshal.cs @@ -0,0 +1,21 @@ +using CppSharp.Generators.C; + +namespace CppSharp.Generators.Emscripten +{ + public class EmscriptenMarshalNativeToManagedPrinter : MarshalPrinter + { + public EmscriptenMarshalNativeToManagedPrinter(MarshalContext marshalContext) + : base(marshalContext) + { + } + } + + public class EmscriptenMarshalManagedToNativePrinter : MarshalPrinter + { + public EmscriptenMarshalManagedToNativePrinter(MarshalContext ctx) + : base(ctx) + { + Context.MarshalToNative = this; + } + } +} diff --git a/src/Generator/Generators/Emscripten/EmscriptenModule.cs b/src/Generator/Generators/Emscripten/EmscriptenModule.cs new file mode 100644 index 0000000000..e92c4bcf7c --- /dev/null +++ b/src/Generator/Generators/Emscripten/EmscriptenModule.cs @@ -0,0 +1,89 @@ +using System.IO; +using System.Linq; +using CppSharp.AST; +using CppSharp.Generators.C; + +namespace CppSharp.Generators.Emscripten +{ + /// + /// Generates Emscripten module init files. + /// Embind documentation: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html + /// + public class EmscriptenModule : EmscriptenCodeGenerator + { + private readonly Module module; + + public EmscriptenModule(BindingContext context, Module module) + : base(context, module.Units.GetGenerated()) + { + this.module = module; + } + + public override string FileExtension { get; } = "cpp"; + + public override void Process() + { + GenerateFilePreamble(CommentKind.BCPL); + NewLine(); + + PushBlock(BlockKind.Includes); + { + WriteInclude(new CInclude() + { + File = "emscripten/bind.h", + Kind = CInclude.IncludeKind.Angled + }); + + foreach (var unit in TranslationUnits) + WriteInclude(GetIncludeFileName(Context, unit), CInclude.IncludeKind.Quoted); + } + PopBlock(NewLineKind.Always); + + WriteLine("extern \"C\" {"); + NewLine(); + + PushBlock(BlockKind.ForwardReferences); + { + foreach (var unit in TranslationUnits.Where(unit => unit.IsGenerated)) + { + var name = GetTranslationUnitName(unit); + WriteLine($"void embind_init_{name}();"); + } + } + PopBlock(NewLineKind.Always); + + var moduleName = module.LibraryName; + WriteLine($"void embind_init_{moduleName}()"); + WriteOpenBraceAndIndent(); + + foreach (var unit in TranslationUnits) + { + var name = GetTranslationUnitName(unit); + WriteLine($"embind_init_{name}();"); + } + + UnindentAndWriteCloseBrace(); + + NewLine(); + WriteLine("}"); + NewLine(); + + WriteLine($"static struct EmBindInit_{moduleName} : emscripten::internal::InitFunc {{"); + WriteLineIndent($"EmBindInit_{moduleName}() : InitFunc(embind_init_{moduleName}) {{}}"); + WriteLine($"}} EmBindInit_{moduleName}_instance;"); + } + + public static string GetIncludeFileName(BindingContext context, TranslationUnit unit) + { + // TODO: Replace with GetIncludePath + string file; + if (context.Options.GenerateName != null) + file = context.Options.GenerateName(unit); + else + file = Path.GetFileNameWithoutExtension(unit.FileName) + .Replace('\\', '/'); + + return $"{file}.h"; + } + } +} diff --git a/src/Generator/Generators/Emscripten/EmscriptenSources.cs b/src/Generator/Generators/Emscripten/EmscriptenSources.cs new file mode 100644 index 0000000000..4e786b0400 --- /dev/null +++ b/src/Generator/Generators/Emscripten/EmscriptenSources.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; +using CppSharp.AST.Extensions; +using CppSharp.Generators.C; +using CppSharp.Generators.Cpp; + +namespace CppSharp.Generators.Emscripten +{ + public class EmscriptenCodeGenerator : MethodGroupCodeGenerator + { + protected EmscriptenCodeGenerator(BindingContext context, IEnumerable units) + : base(context, units) + { + } + + public virtual MarshalPrinter GetMarshalManagedToNativePrinter(MarshalContext ctx) + { + return new EmscriptenMarshalManagedToNativePrinter(ctx); + } + + public virtual MarshalPrinter GetMarshalNativeToManagedPrinter(MarshalContext ctx) + { + return new EmscriptenMarshalNativeToManagedPrinter(ctx); + } + + public override bool VisitClassTemplateDecl(ClassTemplate template) + { + return true; + } + + public override bool VisitFunctionTemplateDecl(FunctionTemplate template) + { + return true; + } + } + + /// + /// Generates Emscripten C/C++ source files. + /// Embind documentation: https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html + /// + public class EmscriptenSources : EmscriptenCodeGenerator + { + public override string FileExtension => "cpp"; + + public EmscriptenSources(BindingContext context, IEnumerable units) + : base(context, units) + { + } + + public override void Process() + { + GenerateFilePreamble(CommentKind.BCPL); + + PushBlock(BlockKind.Includes); + { + WriteInclude(new CInclude() + { + File = "emscripten/bind.h", + Kind = CInclude.IncludeKind.Angled + }); + + foreach (var unit in TranslationUnits) + { + WriteInclude(unit.IncludePath, CInclude.IncludeKind.Angled); + } + } + PopBlock(NewLineKind.Always); + + var name = GetTranslationUnitName(TranslationUnit); + WriteLine($"extern \"C\" void embind_init_{name}()"); + WriteOpenBraceAndIndent(); + VisitNamespace(TranslationUnit); + UnindentAndWriteCloseBrace(); + } + + public override bool VisitClassDecl(Class @class) + { + if (@class.IsIncomplete) + return true; + + PushBlock(); + Write($"emscripten::class_<{@class.QualifiedOriginalName}"); + if (@class.HasBaseClass) + Write($", emscripten::base<{@class.BaseClass.QualifiedOriginalName}>"); + WriteLine($">(\"{@class.Name}\")"); + + VisitClassDeclContext(@class); + + WriteLineIndent(";"); + PopBlock(NewLineKind.BeforeNextBlock); + return true; + } + + public override void VisitClassConstructors(IEnumerable ctors) + { + var overloadCheck = new HashSet(); + foreach (var ctor in ctors) + { + if (overloadCheck.Contains(ctor.Parameters.Count)) + { + Console.WriteLine($"Ignoring overloaded ctor: {ctor.QualifiedOriginalName}"); + continue; + } + + var cppTypePrinter = new CppTypePrinter(Context) + { + PrintFlavorKind = CppTypePrintFlavorKind.Cpp + }; + cppTypePrinter.PushContext(TypePrinterContextKind.Native); + + var parameters = ctor.Parameters.Select(p => p.Type.Visit(cppTypePrinter).Type); + WriteLineIndent($".constructor<{string.Join(", ", parameters)}>()"); + + overloadCheck.Add(ctor.Parameters.Count); + } + } + + public override bool VisitMethodDecl(Method method) + { + Indent(); + var ret = VisitFunctionDecl(method); + Unindent(); + return ret; + } + + public override bool VisitFieldDecl(Field field) + { + WriteLineIndent($".field(\"{field.Name}\", &{field.Class.QualifiedOriginalName}::{field.OriginalName})"); + return true; + } + + public override void GenerateMethodGroup(List @group) + { + if (@group.Count > 1) + { + Console.WriteLine($"Ignoring method group: {@group.First().QualifiedOriginalName}"); + return; + } + + base.GenerateMethodGroup(@group); + } + + public override void GenerateFunctionGroup(List @group) + { + if (@group.Count > 1) + { + Console.WriteLine($"Ignoring function group: {@group.First().QualifiedOriginalName}"); + return; + } + + base.GenerateFunctionGroup(@group); + } + + public override void VisitDeclContextFunctions(DeclarationContext context) + { + PushBlock(); + base.VisitDeclContextFunctions(context); + PopBlock(NewLineKind.BeforeNextBlock); + } + + public override bool VisitFunctionDecl(Function function) + { + var prefix = function is Method ? ".function" : "emscripten::function"; + Write($"{prefix}(\"{function.Name}\", &{function.QualifiedOriginalName}"); + + var hasPointers = function.ReturnType.Type.IsPointer() || + function.Parameters.Any(p => p.Type.IsPointer()); + if (hasPointers) + Write(", emscripten::allow_raw_pointers()"); + + WriteLine(function is not Method ? ");" : $")"); + return true; + } + + public override bool VisitEnumDecl(Enumeration @enum) + { + if (@enum.IsIncomplete) + return false; + + PushBlock(); + + WriteLine($"emscripten::enum_<{@enum.Name}>(\"{@enum.QualifiedOriginalName}\")"); + foreach (var item in @enum.Items) + { + WriteLineIndent(@enum.IsScoped + ? $".value(\"{item.Name}\", {@enum.QualifiedOriginalName}::{item.OriginalName})" + : $".value(\"{item.Name}\", {item.QualifiedOriginalName})"); + } + WriteLineIndent(";"); + + PopBlock(NewLineKind.BeforeNextBlock); + return true; + } + + public override bool VisitTypedefDecl(TypedefDecl typedef) + { + return true; + } + } +} diff --git a/src/Generator/Generators/Emscripten/EmscriptenTypePrinter.cs b/src/Generator/Generators/Emscripten/EmscriptenTypePrinter.cs new file mode 100644 index 0000000000..b5d5cd8816 --- /dev/null +++ b/src/Generator/Generators/Emscripten/EmscriptenTypePrinter.cs @@ -0,0 +1,11 @@ +using CppSharp.Generators.C; + +namespace CppSharp.Generators.Emscripten +{ + public class EmscriptenTypePrinter : CppTypePrinter + { + public EmscriptenTypePrinter(BindingContext context) : base(context) + { + } + } +} diff --git a/src/Generator/Generators/NAPI/NAPIHelpers.cs b/src/Generator/Generators/NAPI/NAPIHelpers.cs index a1f4b93971..858c488cea 100644 --- a/src/Generator/Generators/NAPI/NAPIHelpers.cs +++ b/src/Generator/Generators/NAPI/NAPIHelpers.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using CppSharp.AST; using CppSharp.AST.Extensions; @@ -9,11 +10,9 @@ namespace CppSharp.Generators.Cpp { - public class NAPICodeGenerator : CCodeGenerator + public class MethodGroupCodeGenerator : CCodeGenerator { - public override string FileExtension => "cpp"; - - public NAPICodeGenerator(BindingContext context, IEnumerable units) + protected MethodGroupCodeGenerator(BindingContext context, IEnumerable units) : base(context, units) { } @@ -43,9 +42,9 @@ public override bool VisitClassDecl(Class @class) return VisitClassDeclContext(@class); } - public override void VisitClassConstructors(Class @class) + public override void VisitClassConstructors(IEnumerable ctors) { - var constructors = @class.Constructors.Where(c => c.IsGenerated && !c.IsCopyConstructor) + var constructors = ctors.Where(c => c.IsGenerated && !c.IsCopyConstructor) .ToList(); if (!constructors.Any()) @@ -59,7 +58,7 @@ public static bool ShouldGenerate(Function function) if (!function.IsGenerated) return false; - if (!(function is Method method)) + if (function is not Method method) return true; if (method.IsConstructor || method.IsDestructor) @@ -88,10 +87,27 @@ public virtual void GenerateMethodGroup(List @group) foreach (var method in @group) { method.Visit(this); - return; } } + public static string GetTranslationUnitName(TranslationUnit unit) + { + var paths = unit.FileRelativePath.Split('/').ToList(); + paths = paths.Select(p => Path.GetFileNameWithoutExtension(p.ToLowerInvariant())).ToList(); + var name = string.Join('_', paths); + return name; + } + } + + public class NAPICodeGenerator : MethodGroupCodeGenerator + { + public override string FileExtension => "cpp"; + + public NAPICodeGenerator(BindingContext context, IEnumerable units) + : base(context, units) + { + } + public virtual MarshalPrinter GetMarshalManagedToNativePrinter(MarshalContext ctx) { return new NAPIMarshalManagedToNativePrinter(ctx); diff --git a/src/Generator/Generators/NAPI/NAPISources.cs b/src/Generator/Generators/NAPI/NAPISources.cs index b6676f8b11..a78d2948b4 100644 --- a/src/Generator/Generators/NAPI/NAPISources.cs +++ b/src/Generator/Generators/NAPI/NAPISources.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using CppSharp.AST; @@ -24,14 +23,6 @@ public NAPISources(BindingContext context, IEnumerable units) { } - public static string GetTranslationUnitName(TranslationUnit unit) - { - var paths = unit.FileRelativePath.Split('/').ToList(); - paths = paths.Select(p => Path.GetFileNameWithoutExtension(p.ToLowerInvariant())).ToList(); - var name = string.Join('_', paths); - return name; - } - public override void Process() { GenerateFilePreamble(CommentKind.BCPL); diff --git a/src/Generator/Generators/QuickJS/QuickJSSources.cs b/src/Generator/Generators/QuickJS/QuickJSSources.cs index 3facf63fd1..7f98a8017a 100644 --- a/src/Generator/Generators/QuickJS/QuickJSSources.cs +++ b/src/Generator/Generators/QuickJS/QuickJSSources.cs @@ -198,7 +198,7 @@ public QuickJSClassFuncDef(BindingContext context) : base(context, null) { } - public override void VisitClassConstructors(Class @class) + public override void VisitClassConstructors(IEnumerable ctors) { } diff --git a/src/Generator/Options.cs b/src/Generator/Options.cs index 0f0bc25790..df924b86f3 100644 --- a/src/Generator/Options.cs +++ b/src/Generator/Options.cs @@ -115,7 +115,7 @@ public bool DoAllModulesHaveLibraries() => /// /// Enable this option to enable generation of finalizers. Works in both CLI and - /// C# backends. + /// C# backends. /// /// /// Use to specify a filter so that @@ -125,7 +125,7 @@ public bool DoAllModulesHaveLibraries() => /// /// A filter that can restrict the classes for which finalizers are generated when - /// is true. + /// is true. /// /// /// The default filter performs no filtering so that whenever public readonly List DependentNameSpaces = new List(); public bool MarshalCharAsManagedChar { get; set; } + public bool MarshalConstCharArrayAsString { get; set; } = true; /// /// Use Span Struct instead of Managed Array diff --git a/src/Generator/Passes/CheckAmbiguousFunctions.cs b/src/Generator/Passes/CheckAmbiguousFunctions.cs index 964a12c694..a2001c0a7c 100644 --- a/src/Generator/Passes/CheckAmbiguousFunctions.cs +++ b/src/Generator/Passes/CheckAmbiguousFunctions.cs @@ -62,7 +62,7 @@ public override bool VisitFunctionDecl(AST.Function function) } if (function.IsAmbiguous) - Diagnostics.Message($"Found ambiguous overload: {function.QualifiedOriginalName}"); + Diagnostics.Debug($"Found ambiguous overload: {function.QualifiedOriginalName}"); return true; } diff --git a/src/Generator/Passes/CheckDuplicatedNamesPass.cs b/src/Generator/Passes/CheckDuplicatedNamesPass.cs index 1ccefa4261..0a2d7622ab 100644 --- a/src/Generator/Passes/CheckDuplicatedNamesPass.cs +++ b/src/Generator/Passes/CheckDuplicatedNamesPass.cs @@ -7,6 +7,7 @@ using CppSharp.Generators.C; using CppSharp.Generators.CLI; using CppSharp.Generators.CSharp; +using CppSharp.Generators.Emscripten; using CppSharp.Types; namespace CppSharp.Passes @@ -204,6 +205,9 @@ private TypePrinter GetTypePrinter(GeneratorKind kind, BindingContext context) case GeneratorKind.C: typePrinter = new CppTypePrinter(Context) { PrintFlavorKind = CppTypePrintFlavorKind.C }; break; + case GeneratorKind.Emscripten: + typePrinter = new EmscriptenTypePrinter(Context); + break;; case GeneratorKind.CPlusPlus: case GeneratorKind.QuickJS: case GeneratorKind.NAPI: diff --git a/src/Generator/Passes/CleanUnitPass.cs b/src/Generator/Passes/CleanUnitPass.cs index 4d1b3750d4..3afaa028fd 100644 --- a/src/Generator/Passes/CleanUnitPass.cs +++ b/src/Generator/Passes/CleanUnitPass.cs @@ -31,6 +31,11 @@ private Module GetModule(TranslationUnit unit) includeDir = "."; includeDir = Path.GetFullPath(includeDir); + // Added in https://github.com/mono/CppSharp/pull/1736, but causes us issues. + // return Options.Modules.FirstOrDefault( + // m => m.IncludeDirs.Any(i => Path.GetFullPath(i) == includeDir)) ?? + // Options.Modules[1]; + Module module = Options.Modules.Find( m => m.IncludeDirs.Any(i => Path.GetFullPath(i) == includeDir)); if (module == null) diff --git a/src/Generator/Passes/FieldToPropertyPass.cs b/src/Generator/Passes/FieldToPropertyPass.cs index d94adebb68..9b90a431b8 100644 --- a/src/Generator/Passes/FieldToPropertyPass.cs +++ b/src/Generator/Passes/FieldToPropertyPass.cs @@ -33,8 +33,7 @@ public override bool VisitFieldDecl(Field field) return false; } - var @class = field.Namespace as Class; - if (@class == null) + if (field.Namespace is not Class @class) return false; // Check if we already have a synthetized property. diff --git a/src/Generator/Passes/GetterSetterToPropertyPass.cs b/src/Generator/Passes/GetterSetterToPropertyPass.cs index 62640744f0..4d49a4a4ab 100644 --- a/src/Generator/Passes/GetterSetterToPropertyPass.cs +++ b/src/Generator/Passes/GetterSetterToPropertyPass.cs @@ -21,19 +21,16 @@ static GetterSetterToPropertyPass() private static void LoadVerbs() { var assembly = Assembly.GetAssembly(typeof(GetterSetterToPropertyPass)); - using (var resourceStream = GetResourceStream(assembly)) - { - using (var streamReader = new StreamReader(resourceStream)) - while (!streamReader.EndOfStream) - verbs.Add(streamReader.ReadLine()); - } + using var resourceStream = GetResourceStream(assembly); + using var streamReader = new StreamReader(resourceStream); + while (!streamReader.EndOfStream) + Verbs.Add(streamReader.ReadLine()); } private static Stream GetResourceStream(Assembly assembly) { var resources = assembly.GetManifestResourceNames(); - - if (resources.Count() == 0) + if (!resources.Any()) throw new Exception("Cannot find embedded verbs data resource."); // We are relying on this fact that there is only one resource embedded. @@ -54,13 +51,12 @@ public override bool VisitClassDecl(Class @class) return false; } - protected virtual List GetProperties(Class @class) => - new List(); + protected virtual List GetProperties() => new(); protected IEnumerable GenerateProperties(Class @class) { - List properties = GetProperties(@class); - foreach (Method method in @class.Methods.Where( + var properties = GetProperties(); + foreach (var method in @class.Methods.Where( m => !m.IsConstructor && !m.IsDestructor && !m.IsOperator && m.IsGenerated && (properties.All(p => p.GetMethod != m && p.SetMethod != m) || m.OriginalFunction != null) && @@ -72,15 +68,16 @@ protected IEnumerable GenerateProperties(Class @class) if (IsGetter(method)) { string name = GetPropertyName(method.Name); - GetProperty(properties, method, name, method.OriginalReturnType); + CreateOrUpdateProperty(properties, method, name, method.OriginalReturnType); continue; } + if (IsSetter(method)) { string name = GetPropertyNameFromSetter(method.Name); QualifiedType type = method.Parameters.First( p => p.Kind == ParameterKind.Regular).QualifiedType; - GetProperty(properties, method, name, type, true); + CreateOrUpdateProperty(properties, method, name, type, true); } } @@ -104,7 +101,7 @@ private IEnumerable CleanUp(Class @class, List properties) continue; if (Match(firstWord, new[] { "to", "new", "on" }) || - verbs.Contains(firstWord)) + Verbs.Contains(firstWord)) { property.GetMethod.GenerationKind = GenerationKind.Generate; @class.Properties.Remove(property); @@ -115,12 +112,10 @@ private IEnumerable CleanUp(Class @class, List properties) return properties; } - private static void GetProperty(List properties, Method method, + private static void CreateOrUpdateProperty(List properties, Method method, string name, QualifiedType type, bool isSetter = false) { Type underlyingType = GetUnderlyingType(type); - Class @class = (Class)method.Namespace; - Property property = properties.Find( p => p.Field == null && ((!isSetter && p.SetMethod?.IsStatic == method.IsStatic) || @@ -255,14 +250,13 @@ private static void RenameConflictingMethods(Class @class, Property property) private static Type GetUnderlyingType(QualifiedType type) { - TagType tagType = type.Type as TagType; - if (tagType != null) + if (type.Type is TagType) return type.Type; + // TODO: we should normally check pointer types for const; // however, there's some bug, probably in the parser, that returns IsConst = false for "const Type& arg" // so skip the check for the time being - PointerType pointerType = type.Type as PointerType; - return pointerType != null ? pointerType.Pointee : type.Type; + return type.Type is PointerType pointerType ? pointerType.Pointee : type.Type; } private static void CombineComments(Property property) @@ -277,6 +271,7 @@ private static void CombineComments(Property property) BriefText = getter.Comment.BriefText, Text = getter.Comment.Text }; + if (getter.Comment.FullComment != null) { comment.FullComment = new FullComment(); @@ -295,20 +290,18 @@ private static void CombineComments(Property property) private static string GetPropertyName(string name) { var firstWord = GetFirstWord(name); - if (Match(firstWord, new[] { "get" }) && - (string.Compare(name, firstWord, StringComparison.InvariantCultureIgnoreCase) != 0) && - !char.IsNumber(name[3])) + if (!Match(firstWord, new[] {"get"}) || + (string.Compare(name, firstWord, StringComparison.InvariantCultureIgnoreCase) == 0) || + char.IsNumber(name[3])) return name; + + if (name.Length == 4) { - if (name.Length == 4) - { - return char.ToLowerInvariant( - name[3]).ToString(CultureInfo.InvariantCulture); - } return char.ToLowerInvariant( - name[3]).ToString(CultureInfo.InvariantCulture) + - name.Substring(4); + name[3]).ToString(CultureInfo.InvariantCulture); } - return name; + + return string.Concat(char.ToLowerInvariant( + name[3]).ToString(CultureInfo.InvariantCulture), name.AsSpan(4)); } private static string GetPropertyNameFromSetter(string name) @@ -327,8 +320,8 @@ private static string GetPropertyNameFromSetter(string name) private bool IsGetter(Method method) => !method.IsDestructor && - !method.OriginalReturnType.Type.IsPrimitiveType(PrimitiveType.Void) && - !method.Parameters.Any(p => p.Kind != ParameterKind.IndirectReturnType); + !method.OriginalReturnType.Type.IsPrimitiveType(PrimitiveType.Void) && + method.Parameters.All(p => p.Kind == ParameterKind.IndirectReturnType); private static bool IsSetter(Method method) { @@ -365,6 +358,6 @@ private static string GetFirstWord(string name) return new string(firstWord.ToArray()); } - private static readonly HashSet verbs = new HashSet(); + private static readonly HashSet Verbs = new(); } } diff --git a/src/Generator/Types/Std/Stdlib.CSharp.cs b/src/Generator/Types/Std/Stdlib.CSharp.cs index 9f46125c00..83df7b1cd2 100644 --- a/src/Generator/Types/Std/Stdlib.CSharp.cs +++ b/src/Generator/Types/Std/Stdlib.CSharp.cs @@ -227,8 +227,6 @@ public override void CSharpMarshalToManaged(CSharpMarshalContext ctx) return (Context.Options.Encoding, nameof(Encoding.ASCII)); if (Context.Options.Encoding == Encoding.UTF8) return (Context.Options.Encoding, nameof(Encoding.UTF8)); - if (Context.Options.Encoding == Encoding.UTF7) - return (Context.Options.Encoding, nameof(Encoding.UTF7)); if (Context.Options.Encoding == Encoding.BigEndianUnicode) return (Context.Options.Encoding, nameof(Encoding.BigEndianUnicode)); if (Context.Options.Encoding == Encoding.Unicode) diff --git a/src/Generator/Utils/Options.cs b/src/Generator/Utils/Options.cs index f5740700f9..845c41db0a 100644 --- a/src/Generator/Utils/Options.cs +++ b/src/Generator/Utils/Options.cs @@ -710,7 +710,6 @@ public string OptionName get { return this.option; } } - [SecurityPermission(SecurityAction.LinkDemand, SerializationFormatter = true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); diff --git a/src/Parser/ASTConverter.cs b/src/Parser/ASTConverter.cs index 5e682d4971..f32f63c75b 100644 --- a/src/Parser/ASTConverter.cs +++ b/src/Parser/ASTConverter.cs @@ -1719,6 +1719,8 @@ AST.CppAbi VisitCppAbi(CppAbi abi) return AST.CppAbi.iOS; case CppAbi.iOS64: return AST.CppAbi.iOS64; + case CppAbi.WebAssembly: + return AST.CppAbi.WebAssembly; default: throw new ArgumentOutOfRangeException("abi"); } @@ -2081,6 +2083,7 @@ public override AST.Declaration VisitNonTypeTemplateParameter(NonTypeTemplatePar nonTypeTemplateParameter.IsParameterPack = decl.IsParameterPack; nonTypeTemplateParameter.IsPackExpansion = decl.IsPackExpansion; nonTypeTemplateParameter.IsExpandedParameterPack = decl.IsExpandedParameterPack; + nonTypeTemplateParameter.Type = typeConverter.VisitQualified(decl.Type); return nonTypeTemplateParameter; } diff --git a/src/Parser/Parser.cs b/src/Parser/Parser.cs index fa1a889b65..66d5daceaa 100644 --- a/src/Parser/Parser.cs +++ b/src/Parser/Parser.cs @@ -59,7 +59,7 @@ public static ParserResult ParseLibrary(LinkerOptions options) /// /// Converts a native parser AST to a managed AST. /// - static public AST.ASTContext ConvertASTContext(ASTContext context) + public static AST.ASTContext ConvertASTContext(ASTContext context) { var converter = new ASTConverter(context); return converter.Convert(); diff --git a/src/Parser/ParserOptions.cs b/src/Parser/ParserOptions.cs index 41dffa66d3..7cda0375e3 100644 --- a/src/Parser/ParserOptions.cs +++ b/src/Parser/ParserOptions.cs @@ -5,9 +5,7 @@ using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.InteropServices; using System.Text.RegularExpressions; -using LanguageVersion = CppSharp.Parser.LanguageVersion; namespace CppSharp.Parser { @@ -200,20 +198,22 @@ private void GetUnixCompilerInfo(string headersPath, out string compiler, var versions = Directory.EnumerateDirectories(Path.Combine(headersPath, "usr", "include", "c++")); - if (versions.Count() == 0) + if (!versions.Any()) throw new Exception("No valid GCC version found on system include paths"); - string gccVersionPath = versions.First(); + var gccVersionPath = versions.First(); longVersion = shortVersion = gccVersionPath.Substring( gccVersionPath.LastIndexOf(Path.DirectorySeparatorChar) + 1); return; } - var info = new ProcessStartInfo(Environment.GetEnvironmentVariable("CXX") ?? "gcc", "-v"); - info.RedirectStandardError = true; - info.CreateNoWindow = true; - info.UseShellExecute = false; + var info = new ProcessStartInfo(Environment.GetEnvironmentVariable("CXX") ?? "gcc", "-v") + { + RedirectStandardError = true, + CreateNoWindow = true, + UseShellExecute = false + }; var process = Process.Start(info); if (process == null) @@ -237,13 +237,14 @@ public void SetupLinux(string headersPath = "") NoBuiltinIncludes = true; NoStandardIncludes = true; - string compiler, longVersion, shortVersion; - GetUnixCompilerInfo(headersPath, out compiler, out longVersion, out shortVersion); + GetUnixCompilerInfo(headersPath, out var compiler, out var longVersion, out var shortVersion); AddSystemIncludeDirs(BuiltinsDir); - AddArguments($"-fgnuc-version={longVersion}"); - string majorVersion = shortVersion.Split('.')[0]; + var majorVersion = shortVersion.Split('.')[0]; + // Workaround https://github.com/llvm/llvm-project/issues/53152, remove once bug is fixed. + AddArguments(int.Parse(majorVersion) >= 11 ? $"-fgnuc-version=10.1" : $"-fgnuc-version={longVersion}"); + string[] versions = { longVersion, shortVersion, majorVersion }; string[] triples = { "x86_64-linux-gnu", "x86_64-pc-linux-gnu" }; if (compiler == "gcc") @@ -277,19 +278,23 @@ public void SetupLinux(string headersPath = "") AddSystemIncludeDirs($"{headersPath}/usr/include/linux"); } - public void Setup() + private bool setupDone; + + public void Setup(TargetPlatform targetPlatform) { - SetupArguments(); + if (setupDone) return; + + SetupArguments(targetPlatform); if (!NoBuiltinIncludes) - SetupIncludes(); + SetupIncludes(targetPlatform); + + setupDone = true; } - private void SetupArguments() + private void SetupArguments(TargetPlatform targetPlatform) { - // do not remove the CppSharp prefix becase the Mono C# compiler breaks - if (!LanguageVersion.HasValue) - LanguageVersion = CppSharp.Parser.LanguageVersion.CPP14_GNU; + LanguageVersion ??= CppSharp.Parser.LanguageVersion.CPP14_GNU; // As of Clang revision 5e866e411caa we are required to pass "-fgnuc-version=" // to get the __GNUC__ symbol defined. macOS and Linux system headers require @@ -299,7 +304,7 @@ private void SetupArguments() // setup methods, below is generic fallback in case that logic was disabled. if (NoBuiltinIncludes) { - switch (Platform.Host) + switch (targetPlatform) { case TargetPlatform.MacOS: case TargetPlatform.Linux: @@ -373,18 +378,21 @@ public string BuiltinsDir { get { - var assemblyDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + var assemblyDir = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); + if (assemblyDir == null) + throw new InvalidOperationException(); + return Path.Combine(assemblyDir, "lib", "clang", ClangVersion, "include"); } } - private void SetupIncludes() + private void SetupIncludes(TargetPlatform targetPlatform) { // Check that the builtin includes folder exists. if (!Directory.Exists(BuiltinsDir)) throw new Exception($"Clang resource folder 'lib/clang/{ClangVersion}/include' was not found."); - switch (Platform.Host) + switch (targetPlatform) { case TargetPlatform.Windows: SetupMSVC(); @@ -395,6 +403,16 @@ private void SetupIncludes() case TargetPlatform.Linux: SetupLinux(); break; + case TargetPlatform.Android: + throw new NotImplementedException(); + case TargetPlatform.iOS: + case TargetPlatform.WatchOS: + case TargetPlatform.TVOS: + throw new NotImplementedException(); + case TargetPlatform.Emscripten: + break; + default: + throw new ArgumentOutOfRangeException(); } } } diff --git a/src/Runtime/SymbolResolver.cs b/src/Runtime/SymbolResolver.cs index cc2c3680eb..19e1645bc2 100644 --- a/src/Runtime/SymbolResolver.cs +++ b/src/Runtime/SymbolResolver.cs @@ -1,5 +1,5 @@ /* Copyright (c) 2013 Xamarin, Inc and contributors - * + * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including @@ -7,10 +7,10 @@ * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: - * + * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -80,8 +80,8 @@ public static IntPtr LoadImage(ref string name) break; } } - if (!File.Exists(attempted)) - continue; + if (attempted == null) + attempted = filename; var ptr = loadImage(attempted); diff --git a/tests2/Builtins.h b/tests/Builtins.h similarity index 97% rename from tests2/Builtins.h rename to tests/Builtins.h index 3aa8015cbf..9b270e5385 100644 --- a/tests2/Builtins.h +++ b/tests/Builtins.h @@ -1,3 +1,4 @@ +#include #include void ReturnsVoid () { } @@ -40,8 +41,10 @@ int16_t ReturnsInt16 () { return -5; } uint16_t ReturnsUInt16 () { return 5; } int32_t ReturnsInt32 () { return -5; } uint32_t ReturnsUInt32 () { return 5; } +#if !defined(__EMSCRIPTEN__) int64_t ReturnsInt64 () { return -5; } uint64_t ReturnsUInt64 () { return 5; } +#endif int8_t PassAndReturnsInt8 (int8_t v) { return v; } uint8_t PassAndReturnsUInt8 (uint8_t v) { return v; } diff --git a/tests2/Classes.h b/tests/Classes.h similarity index 100% rename from tests2/Classes.h rename to tests/Classes.h diff --git a/tests2/Classes2.h b/tests/Classes2.h similarity index 100% rename from tests2/Classes2.h rename to tests/Classes2.h diff --git a/tests2/Delegates.h b/tests/Delegates.h similarity index 100% rename from tests2/Delegates.h rename to tests/Delegates.h diff --git a/tests2/Enums.h b/tests/Enums.h similarity index 100% rename from tests2/Enums.h rename to tests/Enums.h diff --git a/tests/NamespacesBase/premake4.lua b/tests/NamespacesBase/premake4.lua deleted file mode 100644 index 0c46c42af1..0000000000 --- a/tests/NamespacesBase/premake4.lua +++ /dev/null @@ -1,11 +0,0 @@ -function SetupWrapper(name) - if not EnabledManagedProjects() then - return - end - - SetupExternalManagedTestProject(name .. ".CSharp") -end - -group "Tests/Namespaces" - SetupTestNativeProject("NamespacesBase") - targetdir (path.join(gendir, "NamespacesDerived")) \ No newline at end of file diff --git a/tests2/Overloads.h b/tests/Overloads.h similarity index 100% rename from tests2/Overloads.h rename to tests/Overloads.h diff --git a/tests/CLI/CLI.Gen.cs b/tests/dotnet/CLI/CLI.Gen.cs similarity index 100% rename from tests/CLI/CLI.Gen.cs rename to tests/dotnet/CLI/CLI.Gen.cs diff --git a/tests/CLI/CLI.Gen.csproj b/tests/dotnet/CLI/CLI.Gen.csproj similarity index 100% rename from tests/CLI/CLI.Gen.csproj rename to tests/dotnet/CLI/CLI.Gen.csproj diff --git a/tests/CLI/CLI.Tests.CLI.csproj b/tests/dotnet/CLI/CLI.Tests.CLI.csproj similarity index 100% rename from tests/CLI/CLI.Tests.CLI.csproj rename to tests/dotnet/CLI/CLI.Tests.CLI.csproj diff --git a/tests/CLI/CLI.Tests.cs b/tests/dotnet/CLI/CLI.Tests.cs similarity index 100% rename from tests/CLI/CLI.Tests.cs rename to tests/dotnet/CLI/CLI.Tests.cs diff --git a/tests/CLI/CLI.cpp b/tests/dotnet/CLI/CLI.cpp similarity index 100% rename from tests/CLI/CLI.cpp rename to tests/dotnet/CLI/CLI.cpp diff --git a/tests/CLI/CLI.h b/tests/dotnet/CLI/CLI.h similarity index 100% rename from tests/CLI/CLI.h rename to tests/dotnet/CLI/CLI.h diff --git a/tests/CLI/NestedEnumInClassTest/ClassWithNestedEnum.cpp b/tests/dotnet/CLI/NestedEnumInClassTest/ClassWithNestedEnum.cpp similarity index 100% rename from tests/CLI/NestedEnumInClassTest/ClassWithNestedEnum.cpp rename to tests/dotnet/CLI/NestedEnumInClassTest/ClassWithNestedEnum.cpp diff --git a/tests/CLI/NestedEnumInClassTest/ClassWithNestedEnum.h b/tests/dotnet/CLI/NestedEnumInClassTest/ClassWithNestedEnum.h similarity index 100% rename from tests/CLI/NestedEnumInClassTest/ClassWithNestedEnum.h rename to tests/dotnet/CLI/NestedEnumInClassTest/ClassWithNestedEnum.h diff --git a/tests/CLI/NestedEnumInClassTest/NestedEnumConsumer.cpp b/tests/dotnet/CLI/NestedEnumInClassTest/NestedEnumConsumer.cpp similarity index 100% rename from tests/CLI/NestedEnumInClassTest/NestedEnumConsumer.cpp rename to tests/dotnet/CLI/NestedEnumInClassTest/NestedEnumConsumer.cpp diff --git a/tests/CLI/NestedEnumInClassTest/NestedEnumConsumer.h b/tests/dotnet/CLI/NestedEnumInClassTest/NestedEnumConsumer.h similarity index 100% rename from tests/CLI/NestedEnumInClassTest/NestedEnumConsumer.h rename to tests/dotnet/CLI/NestedEnumInClassTest/NestedEnumConsumer.h diff --git a/tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.cpp b/tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.cpp similarity index 100% rename from tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.cpp rename to tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.cpp diff --git a/tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.h b/tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.h similarity index 100% rename from tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.h rename to tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/Employee.h diff --git a/tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeForwardDecl.h b/tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeForwardDecl.h similarity index 100% rename from tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeForwardDecl.h rename to tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeForwardDecl.h diff --git a/tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.cpp b/tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.cpp similarity index 100% rename from tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.cpp rename to tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.cpp diff --git a/tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h b/tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h similarity index 100% rename from tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h rename to tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/EmployeeOrg.h diff --git a/tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/IgnoredClassTemplateForEmployee.h b/tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/IgnoredClassTemplateForEmployee.h similarity index 100% rename from tests/CLI/UseTemplateTypeFromIgnoredClassTemplate/IgnoredClassTemplateForEmployee.h rename to tests/dotnet/CLI/UseTemplateTypeFromIgnoredClassTemplate/IgnoredClassTemplateForEmployee.h diff --git a/tests/CLI/premake4.lua b/tests/dotnet/CLI/premake4.lua similarity index 100% rename from tests/CLI/premake4.lua rename to tests/dotnet/CLI/premake4.lua diff --git a/tests/CSharp/AnonTypes.h b/tests/dotnet/CSharp/AnonTypes.h similarity index 100% rename from tests/CSharp/AnonTypes.h rename to tests/dotnet/CSharp/AnonTypes.h diff --git a/tests/CSharp/AnotherUnit.cpp b/tests/dotnet/CSharp/AnotherUnit.cpp similarity index 100% rename from tests/CSharp/AnotherUnit.cpp rename to tests/dotnet/CSharp/AnotherUnit.cpp diff --git a/tests/CSharp/AnotherUnit.h b/tests/dotnet/CSharp/AnotherUnit.h similarity index 100% rename from tests/CSharp/AnotherUnit.h rename to tests/dotnet/CSharp/AnotherUnit.h diff --git a/tests/CSharp/CSharp.CSharp.csproj b/tests/dotnet/CSharp/CSharp.CSharp.csproj similarity index 65% rename from tests/CSharp/CSharp.CSharp.csproj rename to tests/dotnet/CSharp/CSharp.CSharp.csproj index a253523095..6a6c4bf76a 100644 --- a/tests/CSharp/CSharp.CSharp.csproj +++ b/tests/dotnet/CSharp/CSharp.CSharp.csproj @@ -1,4 +1,7 @@  + + 0108 + diff --git a/tests/CSharp/CSharp.Gen.cs b/tests/dotnet/CSharp/CSharp.Gen.cs similarity index 100% rename from tests/CSharp/CSharp.Gen.cs rename to tests/dotnet/CSharp/CSharp.Gen.cs diff --git a/tests/CSharp/CSharp.Gen.csproj b/tests/dotnet/CSharp/CSharp.Gen.csproj similarity index 100% rename from tests/CSharp/CSharp.Gen.csproj rename to tests/dotnet/CSharp/CSharp.Gen.csproj diff --git a/tests/CSharp/CSharp.Tests.CSharp.csproj b/tests/dotnet/CSharp/CSharp.Tests.CSharp.csproj similarity index 100% rename from tests/CSharp/CSharp.Tests.CSharp.csproj rename to tests/dotnet/CSharp/CSharp.Tests.CSharp.csproj diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/dotnet/CSharp/CSharp.Tests.cs similarity index 99% rename from tests/CSharp/CSharp.Tests.cs rename to tests/dotnet/CSharp/CSharp.Tests.cs index 185c1d518a..7050fa744c 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/dotnet/CSharp/CSharp.Tests.cs @@ -346,6 +346,10 @@ public void TestDefaultArguments() methodsWithDefaultValues.DefaultWithSpecialization(); methodsWithDefaultValues.DefaultOverloadedImplicitCtor(); methodsWithDefaultValues.DefaultWithParamNamedSameAsMethod(5); + Assert.That(methodsWithDefaultValues.DefaultIntAssignedAnEnumWithBinaryOperatorAndFlags(), Is.EqualTo((int)(Bar.Items.Item1 | Bar.Items.Item2))); + Assert.That(methodsWithDefaultValues.DefaultWithConstantFlags(), Is.EqualTo(CSharp.CSharp.ConstFlag1 | CSharp.CSharp.ConstFlag2 | CSharp.CSharp.ConstFlag3)); + Assert.IsTrue(methodsWithDefaultValues.DefaultWithPointerToEnum()); + Assert.AreEqual(CSharp.CSharp.DefaultSmallPODInstance.__Instance, methodsWithDefaultValues.DefaultWithNonPrimitiveType().__Instance); } } @@ -1999,4 +2003,11 @@ public void TestCallByValueCopyConstructor() Assert.That(CallByValueCopyConstructor.CopyConstructorCalls, Is.EqualTo(1)); Assert.That(CallByValueCopyConstructor.DestructorCalls, Is.EqualTo(2)); } + + [Test] + public void TestPointerToClass() + { + Assert.IsTrue(CSharp.CSharp.PointerToClass.IsDefaultInstance); + Assert.IsTrue(CSharp.CSharp.PointerToClass.IsValid); + } } diff --git a/tests/CSharp/CSharp.cpp b/tests/dotnet/CSharp/CSharp.cpp similarity index 96% rename from tests/CSharp/CSharp.cpp rename to tests/dotnet/CSharp/CSharp.cpp index 33ff64b040..8d1d091260 100644 --- a/tests/CSharp/CSharp.cpp +++ b/tests/dotnet/CSharp/CSharp.cpp @@ -568,6 +568,8 @@ MethodsWithDefaultValues::QMargins::QMargins(int left, int top, int right, int b { } +struct SmallPOD DefaultSmallPODInstance; + const char* MethodsWithDefaultValues::stringConstant = "test"; int MethodsWithDefaultValues::intConstant = 5; @@ -808,6 +810,26 @@ int MethodsWithDefaultValues::DefaultWithParamNamedSameAsMethod(int DefaultWithP return 1; } +int MethodsWithDefaultValues::defaultIntAssignedAnEnumWithBinaryOperatorAndFlags(int f) +{ + return f; +} + +int MethodsWithDefaultValues::defaultWithConstantFlags(int f) +{ + return f; +} + +bool MethodsWithDefaultValues::defaultWithPointerToEnum(UntypedFlags* f1, int* f2) +{ + return (f1 == NULL || *f1 == (UntypedFlags)0) && (f2 == NULL || *f2 == 0); +} + +SmallPOD* MethodsWithDefaultValues::defaultWithNonPrimitiveType(SmallPOD& pod) +{ + return &pod; +} + int MethodsWithDefaultValues::getA() { return m_foo.A; @@ -1299,7 +1321,7 @@ TestString::TestString() : unicodeConst(L"ქართული ენა"), uni { } -TestChar32String::TestChar32String() : +TestChar32String::TestChar32String() : thirtyTwoBitConst(U"ქართული ენა") { static std::u32string nonConst = U"Test String"; @@ -1307,8 +1329,8 @@ TestChar32String::TestChar32String() : } TestChar32String::~TestChar32String() {} -void TestChar32String::UpdateString(const char32_t* s) -{ +void TestChar32String::UpdateString(const char32_t* s) +{ static std::u32string nativeOwnedMemory = s; thirtyTwoBitConst = nativeOwnedMemory.data(); } @@ -1316,8 +1338,8 @@ void TestChar32String::UpdateString(const char32_t* s) const char32_t* TestChar32String::RetrieveString() { return thirtyTwoBitConst; } void TestChar32String::functionPointerUTF32(void(*ptr)(const char32_t*)) {} -TestChar16String::TestChar16String() : - sixteenBitConst(u"ქართული ენა") +TestChar16String::TestChar16String() : + sixteenBitConst(u"ქართული ენა") { static std::u16string nonConst = u"Test String"; sixteenBitNonConst = &nonConst[0]; @@ -1325,10 +1347,10 @@ TestChar16String::TestChar16String() : TestChar16String::~TestChar16String() {} -void TestChar16String::UpdateString(const char16_t* s) -{ +void TestChar16String::UpdateString(const char16_t* s) +{ static std::u16string nativeOwnedMemory = s; - sixteenBitConst = nativeOwnedMemory.data(); + sixteenBitConst = nativeOwnedMemory.data(); } const char16_t* TestChar16String::RetrieveString() { return sixteenBitConst; } @@ -1667,7 +1689,7 @@ const unsigned ClassCustomTypeAlignmentOffsets[5] offsetof(ClassCustomTypeAlignment, align8), }; -const unsigned ClassCustomObjectAlignmentOffsets[2] { +const unsigned ClassCustomObjectAlignmentOffsets[2] { offsetof(ClassCustomObjectAlignment, boolean), offsetof(ClassCustomObjectAlignment, charAligned8), }; @@ -1776,3 +1798,21 @@ void CallByValueCopyConstructorFunction(CallByValueCopyConstructor s) { s.a = 99999; } +static PointerTester internalPointerTesterInstance; + +PointerTester::PointerTester() +{ + a = 0; +} + +bool PointerTester::IsDefaultInstance() +{ + return this == &internalPointerTesterInstance; +} + +bool PointerTester::IsValid() +{ + return a == 0; +} + +PointerTester* PointerToClass = &internalPointerTesterInstance; diff --git a/tests/CSharp/CSharp.h b/tests/dotnet/CSharp/CSharp.h similarity index 97% rename from tests/CSharp/CSharp.h rename to tests/dotnet/CSharp/CSharp.h index 6bd021b68f..7986dbe14f 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/dotnet/CSharp/CSharp.h @@ -405,6 +405,12 @@ enum class Empty : unsigned long long int class _ClassWithLeadingUnderscore { }; +const int ConstFlag1 = 1; +const int ConstFlag2 = 2; +const int ConstFlag3 = 4; + +extern DLL_API struct SmallPOD DefaultSmallPODInstance; + class DLL_API MethodsWithDefaultValues : public Quux { public: @@ -480,6 +486,10 @@ class DLL_API MethodsWithDefaultValues : public Quux void defaultWithSpecialization(IndependentFields specialization = IndependentFields()); void defaultOverloadedImplicitCtor(P p); void defaultOverloadedImplicitCtor(Qux q = Qux()); + int defaultIntAssignedAnEnumWithBinaryOperatorAndFlags(int f = Bar::Item1 | Bar::Item2); + int defaultWithConstantFlags(int f = ConstFlag1 | ConstFlag2 | ConstFlag3); + bool defaultWithPointerToEnum(UntypedFlags* f1 = NULL, int* f2 = NULL); + SmallPOD* defaultWithNonPrimitiveType(SmallPOD& pod = DefaultSmallPODInstance); int DefaultWithParamNamedSameAsMethod(int DefaultWithParamNamedSameAsMethod, const Foo& defaultArg = Foo()); int getA(); private: @@ -1082,9 +1092,9 @@ class DLL_API VariablesWithInitializer { static constexpr const char* StringArray1[1] { "Str" "F,\"or" }; static constexpr const char* StringArray3[3] { "Str" "F,\"or", "C#", String }; static constexpr const char* StringArray30[30] { - "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", - "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", - "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", + "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", + "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", + "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", "Str", }; static constexpr const char* StringArray3EmptyInitList[3] { }; static constexpr const wchar_t* WideStringArray[2] { L"Str", L"C#" }; @@ -1278,7 +1288,7 @@ struct StructTestArrayTypeFromTypedef #define MY_MACRO_TEST2_4 (1 << 3) #define MY_MACRO_TEST2_ALL (1 << 4) - 1 -#define SIGNED_MACRO_VALUES_TO_ENUM_TEST_1 1 << 5 +#define SIGNED_MACRO_VALUES_TO_ENUM_TEST_1 1 << 5 #define SIGNED_MACRO_VALUES_TO_ENUM_TEST_2 1 << 22 #define SIGNED_MACRO_VALUES_TO_ENUM_TEST_3 1L << 32 #define SIGNED_MACRO_VALUES_TO_ENUM_TEST_4 -1 @@ -1465,9 +1475,9 @@ struct DLL_API ConversionFunctions short field = 100; }; -struct DLL_API ClassCustomTypeAlignment +struct DLL_API ClassCustomTypeAlignment { - struct alignas(1) Align1 { }; + struct alignas(1) Align1 { }; struct alignas(8) Align8 { }; struct alignas(16) Align16 { double a; @@ -1476,7 +1486,7 @@ struct DLL_API ClassCustomTypeAlignment bool boolean; Align16 align16; - Align1 align1; + Align1 align1; double dbl; Align8 align8; }; @@ -1524,7 +1534,7 @@ DLL_API extern const unsigned StructWithEmbeddedArrayOfStructObjectAlignmentOffs DLL_API const char* TestCSharpString(const char* in, CS_OUT const char** out); DLL_API const wchar_t* TestCSharpStringWide(const wchar_t* in, CS_OUT const wchar_t** out); -DLL_API const char16_t* TestCSharpString16(const char16_t* in, CS_OUT const char16_t** out); +DLL_API const char16_t* TestCSharpString16(const char16_t* in, CS_OUT const char16_t** out); DLL_API const char32_t* TestCSharpString32(const char32_t* in, CS_OUT const char32_t** out); struct DLL_API FTIStruct { int a; }; @@ -1595,3 +1605,13 @@ struct DLL_API CallByValueCopyConstructor { }; DLL_API void CallByValueCopyConstructorFunction(CallByValueCopyConstructor s); +class DLL_API PointerTester +{ + int a; +public: + PointerTester(); + bool IsDefaultInstance(); + bool IsValid(); +}; + +DLL_API extern PointerTester* PointerToClass; diff --git a/tests/CSharp/CSharpPartialMethods.cs b/tests/dotnet/CSharp/CSharpPartialMethods.cs similarity index 100% rename from tests/CSharp/CSharpPartialMethods.cs rename to tests/dotnet/CSharp/CSharpPartialMethods.cs diff --git a/tests/CSharp/CSharpTemplates.cpp b/tests/dotnet/CSharp/CSharpTemplates.cpp similarity index 100% rename from tests/CSharp/CSharpTemplates.cpp rename to tests/dotnet/CSharp/CSharpTemplates.cpp diff --git a/tests/CSharp/CSharpTemplates.h b/tests/dotnet/CSharp/CSharpTemplates.h similarity index 100% rename from tests/CSharp/CSharpTemplates.h rename to tests/dotnet/CSharp/CSharpTemplates.h diff --git a/tests/CSharp/ExcludedUnit.hpp b/tests/dotnet/CSharp/ExcludedUnit.hpp similarity index 100% rename from tests/CSharp/ExcludedUnit.hpp rename to tests/dotnet/CSharp/ExcludedUnit.hpp diff --git a/tests/CSharp/premake4.lua b/tests/dotnet/CSharp/premake4.lua similarity index 100% rename from tests/CSharp/premake4.lua rename to tests/dotnet/CSharp/premake4.lua diff --git a/tests/Common/AnotherUnit.cpp b/tests/dotnet/Common/AnotherUnit.cpp similarity index 100% rename from tests/Common/AnotherUnit.cpp rename to tests/dotnet/Common/AnotherUnit.cpp diff --git a/tests/Common/AnotherUnit.h b/tests/dotnet/Common/AnotherUnit.h similarity index 100% rename from tests/Common/AnotherUnit.h rename to tests/dotnet/Common/AnotherUnit.h diff --git a/tests/Common/Common.CSharp.csproj b/tests/dotnet/Common/Common.CSharp.csproj similarity index 100% rename from tests/Common/Common.CSharp.csproj rename to tests/dotnet/Common/Common.CSharp.csproj diff --git a/tests/Common/Common.Gen.cs b/tests/dotnet/Common/Common.Gen.cs similarity index 100% rename from tests/Common/Common.Gen.cs rename to tests/dotnet/Common/Common.Gen.cs diff --git a/tests/Common/Common.Gen.csproj b/tests/dotnet/Common/Common.Gen.csproj similarity index 100% rename from tests/Common/Common.Gen.csproj rename to tests/dotnet/Common/Common.Gen.csproj diff --git a/tests/Common/Common.Tests.CLI.csproj b/tests/dotnet/Common/Common.Tests.CLI.csproj similarity index 100% rename from tests/Common/Common.Tests.CLI.csproj rename to tests/dotnet/Common/Common.Tests.CLI.csproj diff --git a/tests/Common/Common.Tests.CSharp.csproj b/tests/dotnet/Common/Common.Tests.CSharp.csproj similarity index 100% rename from tests/Common/Common.Tests.CSharp.csproj rename to tests/dotnet/Common/Common.Tests.CSharp.csproj diff --git a/tests/Common/Common.Tests.cs b/tests/dotnet/Common/Common.Tests.cs similarity index 100% rename from tests/Common/Common.Tests.cs rename to tests/dotnet/Common/Common.Tests.cs diff --git a/tests/Common/Common.cpp b/tests/dotnet/Common/Common.cpp similarity index 99% rename from tests/Common/Common.cpp rename to tests/dotnet/Common/Common.cpp index 04d63cdd09..47076a023d 100644 --- a/tests/Common/Common.cpp +++ b/tests/dotnet/Common/Common.cpp @@ -1273,4 +1273,4 @@ extern "C" s.field2 = 10; return s; } -} // extern "C" \ No newline at end of file +} // extern "C" diff --git a/tests/Common/Common.h b/tests/dotnet/Common/Common.h similarity index 100% rename from tests/Common/Common.h rename to tests/dotnet/Common/Common.h diff --git a/tests/Common/interface.h b/tests/dotnet/Common/interface.h similarity index 100% rename from tests/Common/interface.h rename to tests/dotnet/Common/interface.h diff --git a/tests/Common/premake4.lua b/tests/dotnet/Common/premake4.lua similarity index 100% rename from tests/Common/premake4.lua rename to tests/dotnet/Common/premake4.lua diff --git a/tests/Directory.Build.props b/tests/dotnet/Directory.Build.props similarity index 83% rename from tests/Directory.Build.props rename to tests/dotnet/Directory.Build.props index 9b32f3ecd5..5402b2c443 100644 --- a/tests/Directory.Build.props +++ b/tests/dotnet/Directory.Build.props @@ -1,5 +1,5 @@ - + diff --git a/tests/Empty/Empty.Gen.cs b/tests/dotnet/Empty/Empty.Gen.cs similarity index 100% rename from tests/Empty/Empty.Gen.cs rename to tests/dotnet/Empty/Empty.Gen.cs diff --git a/tests/Empty/Empty.Tests.cs b/tests/dotnet/Empty/Empty.Tests.cs similarity index 100% rename from tests/Empty/Empty.Tests.cs rename to tests/dotnet/Empty/Empty.Tests.cs diff --git a/tests/Empty/Empty.cpp b/tests/dotnet/Empty/Empty.cpp similarity index 100% rename from tests/Empty/Empty.cpp rename to tests/dotnet/Empty/Empty.cpp diff --git a/tests/Empty/Empty.h b/tests/dotnet/Empty/Empty.h similarity index 100% rename from tests/Empty/Empty.h rename to tests/dotnet/Empty/Empty.h diff --git a/tests/Empty/premake4.lua b/tests/dotnet/Empty/premake4.lua similarity index 100% rename from tests/Empty/premake4.lua rename to tests/dotnet/Empty/premake4.lua diff --git a/tests/Encodings/Encodings.CSharp.csproj b/tests/dotnet/Encodings/Encodings.CSharp.csproj similarity index 100% rename from tests/Encodings/Encodings.CSharp.csproj rename to tests/dotnet/Encodings/Encodings.CSharp.csproj diff --git a/tests/Encodings/Encodings.Gen.cs b/tests/dotnet/Encodings/Encodings.Gen.cs similarity index 100% rename from tests/Encodings/Encodings.Gen.cs rename to tests/dotnet/Encodings/Encodings.Gen.cs diff --git a/tests/Encodings/Encodings.Gen.csproj b/tests/dotnet/Encodings/Encodings.Gen.csproj similarity index 100% rename from tests/Encodings/Encodings.Gen.csproj rename to tests/dotnet/Encodings/Encodings.Gen.csproj diff --git a/tests/Encodings/Encodings.Tests.CSharp.csproj b/tests/dotnet/Encodings/Encodings.Tests.CSharp.csproj similarity index 100% rename from tests/Encodings/Encodings.Tests.CSharp.csproj rename to tests/dotnet/Encodings/Encodings.Tests.CSharp.csproj diff --git a/tests/Encodings/Encodings.Tests.cs b/tests/dotnet/Encodings/Encodings.Tests.cs similarity index 100% rename from tests/Encodings/Encodings.Tests.cs rename to tests/dotnet/Encodings/Encodings.Tests.cs diff --git a/tests/Encodings/Encodings.cpp b/tests/dotnet/Encodings/Encodings.cpp similarity index 100% rename from tests/Encodings/Encodings.cpp rename to tests/dotnet/Encodings/Encodings.cpp diff --git a/tests/Encodings/Encodings.h b/tests/dotnet/Encodings/Encodings.h similarity index 100% rename from tests/Encodings/Encodings.h rename to tests/dotnet/Encodings/Encodings.h diff --git a/tests/Encodings/premake4.lua b/tests/dotnet/Encodings/premake4.lua similarity index 100% rename from tests/Encodings/premake4.lua rename to tests/dotnet/Encodings/premake4.lua diff --git a/tests/NamespacesBase/NamespacesBase.cpp b/tests/dotnet/NamespacesBase/NamespacesBase.cpp similarity index 100% rename from tests/NamespacesBase/NamespacesBase.cpp rename to tests/dotnet/NamespacesBase/NamespacesBase.cpp diff --git a/tests/NamespacesBase/NamespacesBase.h b/tests/dotnet/NamespacesBase/NamespacesBase.h similarity index 100% rename from tests/NamespacesBase/NamespacesBase.h rename to tests/dotnet/NamespacesBase/NamespacesBase.h diff --git a/tests/dotnet/NamespacesBase/premake4.lua b/tests/dotnet/NamespacesBase/premake4.lua new file mode 100644 index 0000000000..632b1083a9 --- /dev/null +++ b/tests/dotnet/NamespacesBase/premake4.lua @@ -0,0 +1,3 @@ +group "Tests/Namespaces" + SetupTestNativeProject("NamespacesBase") + targetdir (path.join(gendir, "NamespacesDerived")) \ No newline at end of file diff --git a/tests/NamespacesBase/test.cs b/tests/dotnet/NamespacesBase/test.cs similarity index 100% rename from tests/NamespacesBase/test.cs rename to tests/dotnet/NamespacesBase/test.cs diff --git a/tests/NamespacesDerived/Independent.h b/tests/dotnet/NamespacesDerived/Independent.h similarity index 100% rename from tests/NamespacesDerived/Independent.h rename to tests/dotnet/NamespacesDerived/Independent.h diff --git a/tests/NamespacesDerived/NamespacesDerived.Gen.cs b/tests/dotnet/NamespacesDerived/NamespacesDerived.Gen.cs similarity index 100% rename from tests/NamespacesDerived/NamespacesDerived.Gen.cs rename to tests/dotnet/NamespacesDerived/NamespacesDerived.Gen.cs diff --git a/tests/NamespacesDerived/NamespacesDerived.Gen.csproj b/tests/dotnet/NamespacesDerived/NamespacesDerived.Gen.csproj similarity index 100% rename from tests/NamespacesDerived/NamespacesDerived.Gen.csproj rename to tests/dotnet/NamespacesDerived/NamespacesDerived.Gen.csproj diff --git a/tests/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj b/tests/dotnet/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj similarity index 65% rename from tests/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj rename to tests/dotnet/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj index b6509a70d3..d1aefe5089 100644 --- a/tests/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj +++ b/tests/dotnet/NamespacesDerived/NamespacesDerived.Tests.CSharp.csproj @@ -4,10 +4,10 @@ - ..\..\build\gen\NamespacesDerived\NamespacesBase.dll + ..\..\..\build\gen\NamespacesDerived\NamespacesBase.dll - ..\..\build\gen\NamespacesDerived\NamespacesDerived.dll + ..\..\..\build\gen\NamespacesDerived\NamespacesDerived.dll \ No newline at end of file diff --git a/tests/NamespacesDerived/NamespacesDerived.Tests.cs b/tests/dotnet/NamespacesDerived/NamespacesDerived.Tests.cs similarity index 100% rename from tests/NamespacesDerived/NamespacesDerived.Tests.cs rename to tests/dotnet/NamespacesDerived/NamespacesDerived.Tests.cs diff --git a/tests/NamespacesDerived/NamespacesDerived.cpp b/tests/dotnet/NamespacesDerived/NamespacesDerived.cpp similarity index 100% rename from tests/NamespacesDerived/NamespacesDerived.cpp rename to tests/dotnet/NamespacesDerived/NamespacesDerived.cpp diff --git a/tests/NamespacesDerived/NamespacesDerived.h b/tests/dotnet/NamespacesDerived/NamespacesDerived.h similarity index 100% rename from tests/NamespacesDerived/NamespacesDerived.h rename to tests/dotnet/NamespacesDerived/NamespacesDerived.h diff --git a/tests/NamespacesDerived/premake4.lua b/tests/dotnet/NamespacesDerived/premake4.lua similarity index 100% rename from tests/NamespacesDerived/premake4.lua rename to tests/dotnet/NamespacesDerived/premake4.lua diff --git a/tests/Native/AST.h b/tests/dotnet/Native/AST.h similarity index 100% rename from tests/Native/AST.h rename to tests/dotnet/Native/AST.h diff --git a/tests/Native/ASTExtensions.h b/tests/dotnet/Native/ASTExtensions.h similarity index 100% rename from tests/Native/ASTExtensions.h rename to tests/dotnet/Native/ASTExtensions.h diff --git a/tests/Native/Enums.h b/tests/dotnet/Native/Enums.h similarity index 100% rename from tests/Native/Enums.h rename to tests/dotnet/Native/Enums.h diff --git a/tests/Native/Passes.h b/tests/dotnet/Native/Passes.h similarity index 100% rename from tests/Native/Passes.h rename to tests/dotnet/Native/Passes.h diff --git a/tests/Native/Templates.h b/tests/dotnet/Native/Templates.h similarity index 100% rename from tests/Native/Templates.h rename to tests/dotnet/Native/Templates.h diff --git a/tests/Native/linux/libexpat.so.0 b/tests/dotnet/Native/linux/libexpat.so.0 similarity index 100% rename from tests/Native/linux/libexpat.so.0 rename to tests/dotnet/Native/linux/libexpat.so.0 diff --git a/tests/Native/macos/libexpat.dylib b/tests/dotnet/Native/macos/libexpat.dylib similarity index 100% rename from tests/Native/macos/libexpat.dylib rename to tests/dotnet/Native/macos/libexpat.dylib diff --git a/tests/Native/windows/libexpat.dll b/tests/dotnet/Native/windows/libexpat.dll similarity index 100% rename from tests/Native/windows/libexpat.dll rename to tests/dotnet/Native/windows/libexpat.dll diff --git a/tests/StandardLib/StandardLib.Gen.cs b/tests/dotnet/StandardLib/StandardLib.Gen.cs similarity index 100% rename from tests/StandardLib/StandardLib.Gen.cs rename to tests/dotnet/StandardLib/StandardLib.Gen.cs diff --git a/tests/StandardLib/StandardLib.Gen.csproj b/tests/dotnet/StandardLib/StandardLib.Gen.csproj similarity index 100% rename from tests/StandardLib/StandardLib.Gen.csproj rename to tests/dotnet/StandardLib/StandardLib.Gen.csproj diff --git a/tests/StandardLib/StandardLib.Tests.CLI.csproj b/tests/dotnet/StandardLib/StandardLib.Tests.CLI.csproj similarity index 100% rename from tests/StandardLib/StandardLib.Tests.CLI.csproj rename to tests/dotnet/StandardLib/StandardLib.Tests.CLI.csproj diff --git a/tests/StandardLib/StandardLib.Tests.cs b/tests/dotnet/StandardLib/StandardLib.Tests.cs similarity index 100% rename from tests/StandardLib/StandardLib.Tests.cs rename to tests/dotnet/StandardLib/StandardLib.Tests.cs diff --git a/tests/StandardLib/StandardLib.cpp b/tests/dotnet/StandardLib/StandardLib.cpp similarity index 100% rename from tests/StandardLib/StandardLib.cpp rename to tests/dotnet/StandardLib/StandardLib.cpp diff --git a/tests/StandardLib/StandardLib.h b/tests/dotnet/StandardLib/StandardLib.h similarity index 100% rename from tests/StandardLib/StandardLib.h rename to tests/dotnet/StandardLib/StandardLib.h diff --git a/tests/StandardLib/premake4.lua b/tests/dotnet/StandardLib/premake4.lua similarity index 100% rename from tests/StandardLib/premake4.lua rename to tests/dotnet/StandardLib/premake4.lua diff --git a/tests/Test.Bindings.props b/tests/dotnet/Test.Bindings.props similarity index 100% rename from tests/Test.Bindings.props rename to tests/dotnet/Test.Bindings.props diff --git a/tests/Test.Common.props b/tests/dotnet/Test.Common.props similarity index 100% rename from tests/Test.Common.props rename to tests/dotnet/Test.Common.props diff --git a/tests/Test.Generator.props b/tests/dotnet/Test.Generator.props similarity index 100% rename from tests/Test.Generator.props rename to tests/dotnet/Test.Generator.props diff --git a/tests/Test.props b/tests/dotnet/Test.props similarity index 100% rename from tests/Test.props rename to tests/dotnet/Test.props diff --git a/tests/Tests.h b/tests/dotnet/Tests.h similarity index 100% rename from tests/Tests.h rename to tests/dotnet/Tests.h diff --git a/tests/VTables/VTables.CSharp.csproj b/tests/dotnet/VTables/VTables.CSharp.csproj similarity index 100% rename from tests/VTables/VTables.CSharp.csproj rename to tests/dotnet/VTables/VTables.CSharp.csproj diff --git a/tests/VTables/VTables.Gen.cs b/tests/dotnet/VTables/VTables.Gen.cs similarity index 100% rename from tests/VTables/VTables.Gen.cs rename to tests/dotnet/VTables/VTables.Gen.cs diff --git a/tests/VTables/VTables.Gen.csproj b/tests/dotnet/VTables/VTables.Gen.csproj similarity index 100% rename from tests/VTables/VTables.Gen.csproj rename to tests/dotnet/VTables/VTables.Gen.csproj diff --git a/tests/VTables/VTables.Tests.CSharp.csproj b/tests/dotnet/VTables/VTables.Tests.CSharp.csproj similarity index 100% rename from tests/VTables/VTables.Tests.CSharp.csproj rename to tests/dotnet/VTables/VTables.Tests.CSharp.csproj diff --git a/tests/VTables/VTables.Tests.cs b/tests/dotnet/VTables/VTables.Tests.cs similarity index 100% rename from tests/VTables/VTables.Tests.cs rename to tests/dotnet/VTables/VTables.Tests.cs diff --git a/tests/VTables/VTables.cpp b/tests/dotnet/VTables/VTables.cpp similarity index 100% rename from tests/VTables/VTables.cpp rename to tests/dotnet/VTables/VTables.cpp diff --git a/tests/VTables/VTables.h b/tests/dotnet/VTables/VTables.h similarity index 100% rename from tests/VTables/VTables.h rename to tests/dotnet/VTables/VTables.h diff --git a/tests/VTables/premake4.lua b/tests/dotnet/VTables/premake4.lua similarity index 100% rename from tests/VTables/premake4.lua rename to tests/dotnet/VTables/premake4.lua diff --git a/tests2/quickjs/.gitignore b/tests/emscripten/.gitignore similarity index 100% rename from tests2/quickjs/.gitignore rename to tests/emscripten/.gitignore diff --git a/tests/emscripten/premake5.lua b/tests/emscripten/premake5.lua new file mode 100644 index 0000000000..8fa7a73885 --- /dev/null +++ b/tests/emscripten/premake5.lua @@ -0,0 +1,21 @@ + +workspace "emscripten" + configurations { "debug", "release" } + location "gen" + symbols "On" + optimize "Off" + + project "test" + kind "SharedLib" + language "C++" + files + { + "gen/**.cpp", + } + includedirs + { + "..", + "../../include" + } + linkoptions { "--bind -sENVIRONMENT=node -sMODULARIZE=1 -sEXPORT_ALL -sEXPORT_ES6=1 -sUSE_ES6_IMPORT_META=1" } + targetextension ".mjs" \ No newline at end of file diff --git a/tests/emscripten/test.mjs b/tests/emscripten/test.mjs new file mode 100644 index 0000000000..95b8b0bf0b --- /dev/null +++ b/tests/emscripten/test.mjs @@ -0,0 +1,114 @@ +import wasmModule from "./gen/bin/debug/libtest.mjs"; +import { eq, ascii, floateq } from "./utils.mjs" + +const test = await wasmModule({ + onRuntimeInitialized() { + + } +}); + +function builtins() { + eq(test.ReturnsVoid(), undefined) + + eq(test.ReturnsBool(), true) + eq(test.PassAndReturnsBool(false), false) + + eq(test.ReturnsNullptr(), null) + eq(test.PassAndReturnsNullptr(null), null) + + eq(test.ReturnsChar(), ascii('a')); + eq(test.ReturnsSChar(), ascii('a')); + eq(test.ReturnsUChar(), ascii('a')); + + eq(test.PassAndReturnsChar(ascii('a')), ascii('a')); + eq(test.PassAndReturnsSChar(ascii('b')), ascii('b')); + eq(test.PassAndReturnsUChar(ascii('c')), ascii('c')); + + // TODO: add wchar_t tests + + eq(test.ReturnsFloat(), 5.0); + eq(test.ReturnsDouble(), -5.0); + //eq(test.ReturnsLongDouble(), -5.0); + + floateq(test.PassAndReturnsFloat(1.32), 1.32); + floateq(test.PassAndReturnsDouble(1.32), 1.32); + //float(test.PassAndReturnsLongDouble(1.32), 1.32); + + eq(test.ReturnsInt8(), -5); + eq(test.ReturnsUInt8(), 5); + eq(test.ReturnsInt16(), -5); + eq(test.ReturnsUInt16(), 5); + eq(test.ReturnsInt32(), -5); + eq(test.ReturnsUInt32(), 5); + + // TODO: + // https://github.com/WebAssembly/proposals/issues/7 + // https://github.com/emscripten-core/emscripten/issues/11140 + //eq(test.ReturnsInt64(), -5n); + //eq(test.ReturnsUInt64(), 5n); + + const int8 = { min: -(2 ** 7), max: (2 ** 7) - 1 }; + eq(test.PassAndReturnsInt8(int8.min), int8.min); + eq(test.PassAndReturnsInt8(int8.max), int8.max); + + const uint8 = { min: 0, max: (2 ** 8) - 1 }; + eq(test.PassAndReturnsUInt8(uint8.min), uint8.min); + eq(test.PassAndReturnsUInt8(uint8.max), uint8.max); + + const int16 = { min: -(2 ** 15), max: (2 ** 15) - 1 }; + eq(test.PassAndReturnsInt16(int16.min), int16.min); + eq(test.PassAndReturnsInt16(int16.max), int16.max); + + const uint16 = { min: 0, max: (2 ** 16) - 1 }; + eq(test.PassAndReturnsUInt16(uint16.min), uint16.min); + eq(test.PassAndReturnsUInt16(uint16.max), uint16.max); + + const int32 = { min: -(2 ** 31), max: (2 ** 31) - 1 }; + eq(test.PassAndReturnsInt32(int32.min), int32.min); + eq(test.PassAndReturnsInt32(int32.max), int32.max); + + const uint32 = { min: 0, max: (2 ** 32) - 1 }; + eq(test.PassAndReturnsUInt32(uint32.min), uint32.min); + eq(test.PassAndReturnsUInt32(uint32.max), uint32.max); + + //const int64 = { min: BigInt(2 ** 63) * -1n, max: BigInt(2 ** 63) - 1n }; + //eq(test.PassAndReturnsInt64(int64.min), int64.min); + //eq(test.PassAndReturnsInt64(int64.max), int64.max); + + //const uint64 = { min: BigInt(0), max: BigInt(2 ** 64) - 1n }; + //eq(test.PassAndReturnsUInt64(uint64.min), uint64.min); + //eq(test.PassAndReturnsUInt64(uint64.max), uint64.max); +} + +function enums() { + eq(test.Enum0.Item0.value, 0); + eq(test.Enum0.Item1.value, 1); + eq(test.Enum0.Item2.value, 5); + + eq(test.ReturnsEnum(), test.Enum0.Item0); + eq(test.PassAndReturnsEnum(test.Enum0.Item1), test.Enum0.Item1); +} + +function classes() { + var c = new test.Class(); + eq(typeof (c), "object") + eq(c.ReturnsVoid(), undefined) + eq(c.ReturnsInt(), 0) + eq(c.PassAndReturnsClassPtr(null), null) + + var c1 = new test.ClassWithSingleInheritance(); + eq(c1.__proto__.constructor.name, 'ClassWithSingleInheritance') + eq(c1.__proto__.__proto__.constructor.name, 'Class') + eq(c1.ReturnsVoid(), undefined); + eq(c1.ReturnsInt(), 0); + eq(c1.ChildMethod(), 2); + + var classWithField = new test.ClassWithField(); + eq(classWithField.ReturnsField(), 10); + eq(classWithField.Field, 10); +} + + +builtins(); +enums(); +classes(); \ No newline at end of file diff --git a/tests/emscripten/test.sh b/tests/emscripten/test.sh new file mode 100755 index 0000000000..52807e87dd --- /dev/null +++ b/tests/emscripten/test.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -e +dir=$(cd "$(dirname "$0")"; pwd) +rootdir="$dir/../.." +dotnet_configuration=Release +configuration=debug +platform=x64 +jsinterp=node + +red=`tput setaf 1` +green=`tput setaf 2` +reset=`tput sgr0` + +generate=true + +if [ $generate = true ]; then + echo "${green}Generating bindings${reset}" + dotnet $rootdir/bin/${dotnet_configuration}_${platform}/CppSharp.CLI.dll \ + --gen=emscripten --platform=emscripten --arch=wasm32 \ + -I$dir/.. -I$rootdir/include -o $dir/gen -m tests $dir/../*.h +fi + +echo "${green}Building generated binding files${reset}" +premake=$rootdir/build/premake.sh +config=$configuration $premake --file=$dir/premake5.lua gmake +emmake make -C $dir/gen +echo + +echo "${green}Executing JS tests with Node${reset}" +$jsinterp $dir/test.mjs \ No newline at end of file diff --git a/tests/emscripten/utils.mjs b/tests/emscripten/utils.mjs new file mode 100644 index 0000000000..fb0eb6c73d --- /dev/null +++ b/tests/emscripten/utils.mjs @@ -0,0 +1,21 @@ +export function assert(actual, expected, message) { + if (arguments.length == 1) + expected = true; + + if (actual === expected) + return; + + if (actual !== null && expected !== null + && typeof actual == 'object' && typeof expected == 'object' + && actual.toString() === expected.toString()) + return; + + throw Error("assertion failed: got |" + actual + "|" + + ", expected |" + expected + "|" + + (message ? " (" + message + ")" : "")); +} + +export const eq = assert; +export const floateq = (actual, expected) => { assert(Math.abs(actual - expected) < 0.01) } + +export const ascii = v => v.charCodeAt(0) diff --git a/tests2/napi/.gitignore b/tests/napi/.gitignore similarity index 100% rename from tests2/napi/.gitignore rename to tests/napi/.gitignore diff --git a/tests2/napi/premake5.lua b/tests/napi/premake5.lua similarity index 100% rename from tests2/napi/premake5.lua rename to tests/napi/premake5.lua diff --git a/tests2/napi/test.js b/tests/napi/test.js similarity index 100% rename from tests2/napi/test.js rename to tests/napi/test.js diff --git a/tests2/napi/test.sh b/tests/napi/test.sh similarity index 100% rename from tests2/napi/test.sh rename to tests/napi/test.sh diff --git a/tests/quickjs/.gitignore b/tests/quickjs/.gitignore new file mode 100644 index 0000000000..36316b019c --- /dev/null +++ b/tests/quickjs/.gitignore @@ -0,0 +1,4 @@ +gen +*.so +*.dylib +*.dll diff --git a/tests2/quickjs/premake5.lua b/tests/quickjs/premake5.lua similarity index 100% rename from tests2/quickjs/premake5.lua rename to tests/quickjs/premake5.lua diff --git a/tests2/quickjs/test-prop.js b/tests/quickjs/test-prop.js similarity index 100% rename from tests2/quickjs/test-prop.js rename to tests/quickjs/test-prop.js diff --git a/tests2/quickjs/test.js b/tests/quickjs/test.js similarity index 100% rename from tests2/quickjs/test.js rename to tests/quickjs/test.js diff --git a/tests2/quickjs/test.sh b/tests/quickjs/test.sh similarity index 100% rename from tests2/quickjs/test.sh rename to tests/quickjs/test.sh diff --git a/tests2/test.sh b/tests/test.sh similarity index 80% rename from tests2/test.sh rename to tests/test.sh index 622401efcf..f5abc712b9 100755 --- a/tests2/test.sh +++ b/tests/test.sh @@ -4,3 +4,4 @@ dir=$(cd "$(dirname "$0")"; pwd) $dir/napi/test.sh $dir/quickjs/test.sh +$dir/emscripten/test.sh diff --git a/tests2/ts/.gitignore b/tests/ts/.gitignore similarity index 100% rename from tests2/ts/.gitignore rename to tests/ts/.gitignore diff --git a/tests2/ts/test.sh b/tests/ts/test.sh similarity index 100% rename from tests2/ts/test.sh rename to tests/ts/test.sh diff --git a/tests2/ts/test.ts b/tests/ts/test.ts similarity index 100% rename from tests2/ts/test.ts rename to tests/ts/test.ts diff --git a/tests2/ts/tsconfig.json b/tests/ts/tsconfig.json similarity index 100% rename from tests2/ts/tsconfig.json rename to tests/ts/tsconfig.json