xoofx/CppAst.NET

how to parse __declspec attribute?

srxqds opened this issue · 16 comments

I found it can't pase __declspec attribute, how can I make it work?

xoofx commented

It depends. It is supported for some constructs (see TestAttributes.cs), it might not be supported in some places.

Do you have a simple example where this is not working?

@xoofx I test the code

            string text = @"
#ifdef WIN32
#define EXPORT_API __declspec(dllexport)
#else
#define EXPORT_API __attribute__((visibility(""default"")))
#endif
EXPORT_API int function0();
int function1();
class EXPORT_API TestClass
{};

EXPORT_API class TestClass1
{};
";

the class attribute can't be parsed.
image

you can test with it
thank you.

xoofx commented

But the tests are checking exactly this and they are working, so you might have setup this differently. Could you post the exact code you are using for this, including the initialization of the parser?

you can replace the text with above, it can found the function has the attribute but class not.

hi, @xoofx ,
I found if i write the attribute directly before class name, it can parsed,

string text = @"
#ifdef WIN32
#define EXPORT_API __declspec(dllexport)
#else
#define EXPORT_API __attribute__((visibility(""default"")))
#endif
EXPORT_API int function0();
int function1();
class EXPORT_API TestClass
{};

class __declspec(dllexport) TestClass1
{};
";

the TestClass have n't attribute, the TestClass1 have attribute.

may you fixed it or
how can I try fixed it?

thank you.

xoofx commented

By default, attributes are not parsed, are you sure you are passing new CppParserOptions() { ParseAttributes = true } as in the tests?

By default, attributes are not parsed, are you sure you are passing new CppParserOptions() { ParseAttributes = true } as in the tests?

yeah ,I set the ParseAttributes = true

xoofx commented

I believe that this particular attribute __attribute__((visibility(""default""))) is translated by clang to the property .Visibility = Default, not by an attached attribute, at least for the class.

xoofx commented

But it could be a bug, I don't know, don't have time to investigate this more.

the detail of options and result:
image

image

hi, @xoofx I found that the

bool CursorIsFunction(CXCursorKind inKind)

AttributeTokenizer don't handle for CXCursorKind.CXCursor_ClassDecl kind ,so if it is a maco it will wrong.

may you help fixed it?

xoofx commented

AttributeTokenizer don't handle for CXCursorKind.CXCursor_ClassDecl kind ,so if it is a maco it will wrong.
may you help fixed it?

You maybe found the problem, so the fix might be easy. Could you try?

but I could not found where is the function get the macro extension.

I think it is the clang or clangcsharp's bug.

hi, @xoofx
It is becase if we define the attribute macro in the class. the libclang will directly parsed it as CXCursor_VisibilityAttr, CXCursor_DLLExport and CXCursor_DLLImport.

you can add below code into VisitMember function in CppModelBuilder.cs

case CXCursorKind.CXCursor_VisibilityAttr:
                    {
                        var containerContext = GetOrCreateDeclarationContainer(parent, data).Container;
                        var cppClass = containerContext as CppClass;
                        if (cppClass != null)
                        {
                            CppAttribute attribute = new CppAttribute("visibility");
                            attribute.Arguments = cursor.DisplayName.ToString();
                            cppClass.Attributes.Add(attribute);
                        }
                    }
                    break;
                case CXCursorKind.CXCursor_DLLImport:
                    {
                        var containerContext = GetOrCreateDeclarationContainer(parent, data).Container;
                        var cppClass = containerContext as CppClass;
                        if (cppClass != null)
                        {
                            cppClass.Attributes.Add(new CppAttribute("dllimport"));
                        }
                    }
                    break;
                case CXCursorKind.CXCursor_DLLExport:
                    {
                        var containerContext = GetOrCreateDeclarationContainer(parent, data).Container;
                        var cppClass = containerContext as CppClass;
                        if (cppClass != null)
                        {
                            cppClass.Attributes.Add(new CppAttribute("dllexport"));
                        }
                    }
                    break;