From 71de29790e83b97232b1ed085ca363092fd17143 Mon Sep 17 00:00:00 2001 From: triton Date: Thu, 31 Oct 2013 22:25:19 +0000 Subject: [PATCH] Added a new pass to check for duplicated vtable components. This helps workaround some Clang's work-in-progress vftable layouting implementation. --- src/Generator/Driver.cs | 2 + .../Passes/CheckVTableComponentsPass.cs | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/Generator/Passes/CheckVTableComponentsPass.cs diff --git a/src/Generator/Driver.cs b/src/Generator/Driver.cs index 86d6cdfb..70a9cb85 100644 --- a/src/Generator/Driver.cs +++ b/src/Generator/Driver.cs @@ -213,6 +213,8 @@ namespace CppSharp TranslationUnitPasses.AddPass(new MultipleInheritancePass()); TranslationUnitPasses.AddPass(new ParamTypeToInterfacePass()); } + if (Options.GenerateVirtualTables) + TranslationUnitPasses.AddPass(new CheckVTableComponentsPass()); if (Options.GenerateProperties) TranslationUnitPasses.AddPass(new GetterSetterToPropertyAdvancedPass()); } diff --git a/src/Generator/Passes/CheckVTableComponentsPass.cs b/src/Generator/Passes/CheckVTableComponentsPass.cs new file mode 100644 index 00000000..eac5278e --- /dev/null +++ b/src/Generator/Passes/CheckVTableComponentsPass.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Linq; +using CppSharp.AST; +using CppSharp.Utils; + +namespace CppSharp.Passes +{ + /// + /// This pass checks for vftable entries with duplicated components. + /// This might happen because of bugs in Clang vftable layouting. + /// + public class CheckVTableComponentsPass : TranslationUnitPass + { + public override bool VisitClassDecl(AST.Class @class) + { + if (AlreadyVisited(@class)) + return false; + + foreach (var vfptr in @class.Layout.VFTables) + { + var uniqueEntries = new OrderedSet(); + foreach (var entry in vfptr.Layout.Components) + uniqueEntries.Add(entry); + + // The vftable does not have duplicated components. + if (vfptr.Layout.Components.Count == uniqueEntries.Count) + continue; + + Driver.Diagnostics.EmitWarning( + "Class '{0}' found with duplicated vftable components", + @class.Name); + vfptr.Layout.Components = uniqueEntries.ToList(); + } + + return base.VisitClassDecl(@class); + } + } +}