Skip to content

Conversation

@sotteson1
Copy link
Contributor

Some changes required for a project where we use ClangSharp to against Win32 headers so that they can be projected into other languages.

  • Adds 5 new config options:
  1. ExcludeFunctionsWithBody: exclude functions that have a body (code). For projecting to other languages, we want to avoid any functions that include code. We only want DLL import functions.
  2. ExcludeAnonymousFieldHelpers: exclude helper code for anonymous fields.
  3. LogPotentialTypedefRemappings: adds diagnostics to suggest remappings (e.g. tagMyStruct to MyStruct).
  4. GenerateCppAttributes: adds a CppAttributeList attribute for parameters that have C++ attributes on them. We are using this for SAL attributes which help us figure out, for example, if a pointer to a struct is just a single struct or an array.
  5. GenerateNativeInheritanceAttribute: adds an attribute that shows the last base type the struct derived from. We use this to help figure out COM interface inheritance.
  • Fixed a few issues we ran into:
  1. An anonymous struct that wasn't a nested type was getting named "_Anonymous_e__Struct" but then was referenced in a function as the header/location name (e.g. __AnonymousRecord_myheader_L275_C9), so it wouldn't compile. Make sure to only rename to "_Anonymous_e__Struct" if it's a nested type.
  2. This wasn't safe to cast in one case we saw: var functionType = (FunctionType)type; So instead use "is" to make sure it really is of type FunctionType.
  3. When getting the type for an anonymous enum, get its integer type instead of its anonymous type name, since anonymous enum values are emitted as constants and not as constants in an enum type.

Comment on lines +435 to +437
if (type is FunctionType functionType)
{
callConv = functionType.CallConv;
if (callConv == CXCallingConv.CXCallingConv_Invalid)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Simplify the nesting level here

Suggested change
if (type is FunctionType functionType)
{
callConv = functionType.CallConv;
if (callConv == CXCallingConv.CXCallingConv_Invalid)
if ((type is FunctionType functionType) && (callConv == CXCallingConv.CXCallingConv_Invalid))


void VisitAnonymousRecordDeclFields(RecordDecl rootRecordDecl, RecordDecl anonymousRecordDecl, string contextType, string contextName)
{
if (_config.ExcludeAnonymousFieldHelpers)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think this should be a general ExcludeHelpers or that there should be an Exclude*Helper per "helper type" (just to cover any future helper additions)

else if (underlyingType is TagType underlyingTagType)
{
// Nothing to do for tag types
// See if there's a potential typedef remapping we want to log
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Just for consistency, I think this logic should be in a ForTagType local function. It can then early exit with if (!_config.LogPotentialTypedefRemappings)

if (_config.LogPotentialTypedefRemappings)
{
var typedefName = typedefDecl.UnderlyingDecl.Name;
var possibleNamesToRemap = new string[] { "_" + typedefName, "_tag" + typedefName, "tag" + typedefName };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just looking at the Windows bindings I've done for my own project, what about $"{typedefName}_tag", $"{typedefName}_", and $"{typedefName}__"?

_diagnostics.Add(diagnostic);
}

private void AddCppAttributes(ParmVarDecl parmVarDecl, string prefix = null, string postfix = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to confirm. This basically saves all the C++ attributes separated by ^ in a C# style attribute?

return false;
}

if (_config.ExcludeFunctionsWithBody &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IsExcluded is actually one of the "hottest" functions in ClangSharp. It would probably be good to keep this after the IsExcludedByFile check which catches most of the exclusions.

@tannergooding
Copy link
Member

Changes LGTM overall. Just a couple questions/suggestions and I think this can be merged.

@tannergooding
Copy link
Member

Going to take this and will take care of the few nits in a follow up PR.

@tannergooding tannergooding merged commit c10a6db into dotnet:master Jan 8, 2021
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

Successfully merging this pull request may close these issues.

2 participants