Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fatal error at GetCXXRecordDclFromBaseType in Parser.cpp #1750

Open
r-schmitt opened this issue Jul 17, 2023 · 26 comments
Open

fatal error at GetCXXRecordDclFromBaseType in Parser.cpp #1750

r-schmitt opened this issue Jul 17, 2023 · 26 comments

Comments

@r-schmitt
Copy link

r-schmitt commented Jul 17, 2023

Brief Description

We are attempting to use CppSharp to bind Pixar's USD library to C# to hopefully enable a great development environment for USD in C#

On first pass, we got about a 50% success rate, almost all the failures were here:
Parser.cpp line 884

These fatal parsing errors prevent us from generating any output, but I have unable to identify what specifically is breaking at this point. Any help identifying how we can avoid this error would be awesome! I've been very happy with what we've been able to generate successfully...

OS: Windows 10

Used headers

pxr/usd/sdf/path.h
pxr/usd/usd/prim.h
pxr/usd/usd/stage.h

these are three examples, representing a lot of core USD functionality

Used settings

DriverOptions options = driver.Options;
options.GeneratorKind = GeneratorKind.CSharp;
options.Verbose = true;
options.GenerationOutputMode = GenerationOutputMode.FilePerUnit;

Other settings
USD was exported with the cmake flag set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) which is important for getting all the mangled names exported for bindings, but not needed for these parsing errors

@tritao
Copy link
Collaborator

tritao commented Jul 17, 2023

Sounds like an interesting bindings.

Don't have time right now to properly repro and test this, but based on looking where the code fails, I've pushed some changes that hopefully will help with the crash: #1751

Let me know how it goes with the new version.

@r-schmitt
Copy link
Author

thanks, unfortunately that has just pushed the error to a new location:

Exception thrown: read access violation.
*(clang::TemplateName::getAsTemplateDecl(...)) was nullptr.

at Parser.cpp line 901

@tritao
Copy link
Collaborator

tritao commented Jul 18, 2023

thanks, unfortunately that has just pushed the error to a new location:

Exception thrown: read access violation. *(clang::TemplateName::getAsTemplateDecl(...)) was nullptr.

at Parser.cpp line 901

Can you try making the following changes to Parser.cpp:GetCXXRecordDeclFromTemplateName:

First try adding Name.dump(); to the start of the function, hopefully when you run it it will give you the offending piece of code that makes it crash and we can take a look at what's going on.

Then try replacing the case clang::TemplateName::Template case:

    case clang::TemplateName::Template:
    {
        if (auto TD = Name.getAsTemplateDecl())
            return dyn_cast<clang::CXXRecordDecl>(TD->getTemplatedDecl());
        else
            return nullptr;
    }

Hopefully that works around it / fixes it.

@r-schmitt
Copy link
Author

r-schmitt commented Jul 18, 2023

Name.dump() was helpful, it looks like its coming from std::enable_if which is being used for several template functions. is there a way to ignore functions that use std::enable_if or ignore all template functions?

still hitting the error though with the code change

@r-schmitt
Copy link
Author

update, after trying to bind std::optional which hits the same error, it looks like the error is actually during the parsing of Allocator

@r-schmitt
Copy link
Author

@tritao do you have any updates? we're blocked at the moment due to this, but would still very much like to use this if we can

@tritao
Copy link
Collaborator

tritao commented Aug 1, 2023

@tritao do you have any updates? we're blocked at the moment due to this, but would still very much like to use this if we can

No updates on my side, I can try to take a look next time I got some free time, but I need a test case. It would really help if you can help get me an isolated test case that can trigger this issue.

@r-schmitt
Copy link
Author

thanks, any of the three headers listed in my fist post will trigger it

@tritao
Copy link
Collaborator

tritao commented Aug 1, 2023

Ok, those are not self contained tests, ideally we have something that is only a dozen lines or so and can be included in the test suite. Usually we would start with a self-contained header (after using the preprocessing option on the compiler, so no further includes are needed), then start removing code until we as minimal repro as possible.

@r-schmitt
Copy link
Author

r-schmitt commented Aug 1, 2023

float getOptionalFloat(std::optional<float> optionalFloat)
{
    if(optionalFloat.has_value())
    {
        return optionalFloat.value();
    }
    else
    {
        return 0.0f;
    }
}

that should trigger it

also if we cannot fix the error, any guidance on ignoring template functions during parsing would be great

@tritao
Copy link
Collaborator

tritao commented Aug 1, 2023

Ok cool, thanks, I will try to repro that later.

@tritao
Copy link
Collaborator

tritao commented Aug 1, 2023

@r-schmitt Btw which VS version are you using?

@r-schmitt
Copy link
Author

i built cppsharp with 2019, but im running the bindings in 2022

@tritao
Copy link
Collaborator

tritao commented Aug 8, 2023

float getOptionalFloat(std::optional<float> optionalFloat)
{
    if(optionalFloat.has_value())
    {
        return optionalFloat.value();
    }
    else
    {
        return 0.0f;
    }
}

that should trigger it

also if we cannot fix the error, any guidance on ignoring template functions during parsing would be great

Just tried to parse this with latest CppSharp in VS2019 and can't repro it.

@r-schmitt
Copy link
Author

r-schmitt commented Aug 8, 2023

could you outline your build process/MSVC version/LLVM version and cppsharp settings/.net version? i still get this error, so maybe its a mis-configuration somwhere in my build process

@tritao
Copy link
Collaborator

tritao commented Aug 8, 2023

could you outline your build process/MSVC version/LLVM version and cppsharp settings? i still get this error, so maybe its a mis-configuration somwhere in my build process

I've changed the C++ version in parser options to C++17, added the above code, including #include <optional> to the test suite (VTables.Native/VTables.h specifically, just out of convenience), ran VTables.Gen and can see all of above types parsed in the AST (added a breakpoint to Preprocess and just manually expanded the variables in the debugging windows).

@r-schmitt
Copy link
Author

sorry, how can i change the c++ version for the parser? i don't see an option for that

@tritao
Copy link
Collaborator

tritao commented Aug 8, 2023

driver.ParserOptions.LanguageVersion = Parser.LanguageVersion.CPP17;

@r-schmitt
Copy link
Author

thanks, still getting the same errors, will try rebuilding from scratch again

@tritao
Copy link
Collaborator

tritao commented Aug 8, 2023

Cool, if that doesn't work, try adding driver.ParserOptions.Verbose = true; and paste the output of your include paths.

Mine are:

#include "..." search starts here:
#include <...> search starts here:
 C:\dev\CppSharp\tests\dotnet\VTables
 lib\clang\14.0.0\include
 C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.28.29910\include
 C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt
 C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared
 C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um
 C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\winrt

Maybe your C++ standard library is more recent and that causes issues.

@tritao
Copy link
Collaborator

tritao commented Aug 16, 2023

If this is still an issue, might be worth testing with the new Clang branch that comes with a newer Clang version and supports VS 2022: #1724

@r-schmitt
Copy link
Author

thanks, i've been able to test this out again and am hitting two issues

  1. no option for Verbose in ParserOptions
  2. vs2022 built with clang 18, but the parser setup is trying to find lib/clang/14/include and failing

@tritao
Copy link
Collaborator

tritao commented Aug 23, 2023

thanks, i've been able to test this out again and am hitting two issues

  1. no option for Verbose in ParserOptions

It definitely exists:

Verbose = true

Something wrong with auto-complete maybe? Dunno.

  1. vs2022 built with clang 18, but the parser setup is trying to find lib/clang/14/include and failing

Sounds like your CppSharp.CppParser.dll might be outdated, re-compile it and make sure the new copy is in the same folder as the managed program executable.

@r-schmitt
Copy link
Author

trying to set Verbose explicitly causes a compilation error for me and rebuilding CppParser.CppParser.dll still has the error pointing to clang 14 when run.

Clearly something is misconfigured, but I cannot tell what. for this branch what are the generate and build commands you recommend?

I am using the OTB ones from getting started:

sh build.sh generate -configuration Release -platform x64
sh build.sh -configuration Release -platform x64

@tritao
Copy link
Collaborator

tritao commented Aug 28, 2023

@deadlocklogic
Copy link
Contributor

static clang::CXXRecordDecl* GetCXXRecordDeclFromTemplateName(const clang::TemplateName& Name)
{
using namespace clang;
switch (Name.getKind()) {
case clang::TemplateName::Template:
return dyn_cast<clang::CXXRecordDecl>(Name.getAsTemplateDecl()->getTemplatedDecl());
case clang::TemplateName::QualifiedTemplate:
return GetCXXRecordDeclFromTemplateName(Name.getAsQualifiedTemplateName()->getUnderlyingTemplate());
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<clang::RecordType>())
return dyn_cast<clang::CXXRecordDecl>(RT->getDecl());
else if (auto TST = Ty->getAs<clang::TemplateSpecializationType>())
return GetCXXRecordDeclFromTemplateName(TST->getTemplateName());
else if (auto Injected = Ty->getAs<clang::InjectedClassNameType>())
return Injected->getDecl();
assert(0 && "Could not get base CXX record from type");
return nullptr;
}

We should remove the assertion in both functions.
If you are running in release mode, they won't bother anyway. But in debug mode they are buggy when you try to resolve a template parameter or a dependent type.
The main purpose of these functions is to resolve the base classes of a struct/class in order to calculate the layout.
In the case of a dependent type as base classes, this won't make any sense because the type can't be resolved.
Check #1819, in the future layout calculation should be done on the managed side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants