From ebe66d9b6b695792bb030d21384e2d4345468c2f Mon Sep 17 00:00:00 2001 From: CuriousTama Date: Sun, 5 May 2024 15:11:32 +0200 Subject: [PATCH] Memory leak fix A lot of missing dispose(); --- src/CppAst/CXUtil.cs | 175 ++++++++++++++++++++++++++++++++++ src/CppAst/CppModelBuilder.cs | 109 +++++++++++---------- src/CppAst/CppParser.cs | 95 +++++++++--------- src/CppAst/CppTokenUtil.cs | 39 +++++--- 4 files changed, 301 insertions(+), 117 deletions(-) create mode 100644 src/CppAst/CXUtil.cs diff --git a/src/CppAst/CXUtil.cs b/src/CppAst/CXUtil.cs new file mode 100644 index 0000000..1f100ba --- /dev/null +++ b/src/CppAst/CXUtil.cs @@ -0,0 +1,175 @@ +using ClangSharp.Interop; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace CppAst +{ + static internal unsafe class CXUtil + { + #region Cursor + public static string GetCursorSpelling(CXCursor cursor) + { + var cursorSpelling = cursor.Spelling; + string cursorSpellingStr = cursorSpelling.ToString(); + cursorSpelling.Dispose(); + return cursorSpellingStr; + } + + public static string GetCursorUsrString(CXCursor cursor) + { + var cursorUsr = cursor.Usr; + string cursorUsrStr = cursorUsr.ToString(); + cursorUsr.Dispose(); + return cursorUsrStr; + } + + public static string GetCursorDisplayName(CXCursor cursor) + { + var cursorDisplayName = cursor.DisplayName; + string cursorDisplayNameStr = cursorDisplayName.ToString(); + cursorDisplayName.Dispose(); + return cursorDisplayNameStr; + } + #endregion Cursor + + #region Comment + public static string GetComment_TextComment_Text(CXComment comment) + { + var textComment_Text = comment.TextComment_Text; + string textComment_TextStr = textComment_Text.ToString(); + textComment_Text.Dispose(); + return textComment_TextStr; + } + + public static string GetComment_InlineCommandComment_CommandName(CXComment comment) + { + var inlineCommandComment_CommandName = comment.InlineCommandComment_CommandName; + string inlineCommandComment_CommandNameStr = inlineCommandComment_CommandName.ToString(); + inlineCommandComment_CommandName.Dispose(); + return inlineCommandComment_CommandNameStr; + } + + public static string GetComment_InlineCommandComment_ArgText(CXComment comment, uint index) + { + var inlineCommandComment_ArgText = comment.InlineCommandComment_GetArgText(index); + string inlineCommandComment_ArgTextStr = inlineCommandComment_ArgText.ToString(); + inlineCommandComment_ArgText.Dispose(); + return inlineCommandComment_ArgTextStr; + } + + public static string GetComment_HtmlTagComment_TagName(CXComment comment) + { + var htmlTagComment_TagName = comment.HtmlTagComment_TagName; + string htmlTagComment_TagNameStr = htmlTagComment_TagName.ToString(); + htmlTagComment_TagName.Dispose(); + return htmlTagComment_TagNameStr; + } + + public static string GetComment_HtmlStartTag_AttrName(CXComment comment, uint index) + { + var htmlStartTag_AttrName = comment.HtmlStartTag_GetAttrName(index); + string htmlStartTag_AttrNameStr = htmlStartTag_AttrName.ToString(); + htmlStartTag_AttrName.Dispose(); + return htmlStartTag_AttrNameStr; + } + + public static string GetComment_HtmlStartTag_AttrValue(CXComment comment, uint index) + { + var htmlStartTag_AttrValue = comment.HtmlStartTag_GetAttrValue(index); + string htmlStartTag_AttrValueStr = htmlStartTag_AttrValue.ToString(); + htmlStartTag_AttrValue.Dispose(); + return htmlStartTag_AttrValueStr; + } + + public static string GetComment_BlockCommandComment_CommandName(CXComment comment) + { + var blockCommandComment_CommandName = comment.BlockCommandComment_CommandName; + string blockCommandComment_CommandNameStr = blockCommandComment_CommandName.ToString(); + blockCommandComment_CommandName.Dispose(); + return blockCommandComment_CommandNameStr; + } + + public static string GetComment_BlockCommandComment_ArgText(CXComment comment, uint index) + { + var blockCommandComment_ArgText = comment.BlockCommandComment_GetArgText(index); + string blockCommandComment_ArgTextStr = blockCommandComment_ArgText.ToString(); + blockCommandComment_ArgText.Dispose(); + return blockCommandComment_ArgTextStr; + } + + public static string GetComment_ParamCommandComment_ParamName(CXComment comment) + { + var paramCommandComment_ParamName = comment.ParamCommandComment_ParamName; + string paramCommandComment_ParamNameStr = paramCommandComment_ParamName.ToString(); + paramCommandComment_ParamName.Dispose(); + return paramCommandComment_ParamNameStr; + } + + public static string GetComment_TParamCommandComment_ParamName(CXComment comment) + { + var tParamCommandComment_ParamName = comment.TParamCommandComment_ParamName; + string tParamCommandComment_ParamNameStr = tParamCommandComment_ParamName.ToString(); + tParamCommandComment_ParamName.Dispose(); + return tParamCommandComment_ParamNameStr; + } + + public static string GetComment_VerbatimBlockLineComment_Text(CXComment comment) + { + var verbatimBlockLineComment_Text = comment.VerbatimBlockLineComment_Text; + string verbatimBlockLineComment_TextStr = verbatimBlockLineComment_Text.ToString(); + verbatimBlockLineComment_Text.Dispose(); + return verbatimBlockLineComment_TextStr; + } + + public static string GetComment_VerbatimLineComment_Text(CXComment comment) + { + var verbatimLineComment_Text = comment.VerbatimLineComment_Text; + string verbatimLineComment_TextStr = verbatimLineComment_Text.ToString(); + verbatimLineComment_Text.Dispose(); + return verbatimLineComment_TextStr; + } + #endregion Comment + + #region Token + public static string GetTokenSpelling(CXToken token, CXTranslationUnit tu) + { + var tokenSpelling = token.GetSpelling(tu); + string tokenSpellingStr = tokenSpelling.ToString(); + tokenSpelling.Dispose(); + return tokenSpellingStr; + } + #endregion Token + + #region File + public static string GetFileName(CXFile file) + { + var fileName = file.Name; + string fileNameStr = fileName.ToString(); + fileName.Dispose(); + return fileNameStr; + } + #endregion File + + #region Type + public static string GetTypeKindSpelling(CXType type) + { + var kindSpelling= type.KindSpelling; + string kindSpellingStr = kindSpelling.ToString(); + kindSpelling.Dispose(); + return kindSpellingStr; + } + + public static string GetTypeSpelling(CXType type) + { + var spelling = type.Spelling; + string spellingStr = spelling.ToString(); + spelling.Dispose(); + return spellingStr; + } + #endregion Type + } +} diff --git a/src/CppAst/CppModelBuilder.cs b/src/CppAst/CppModelBuilder.cs index 8307f44..d9e441f 100644 --- a/src/CppAst/CppModelBuilder.cs +++ b/src/CppAst/CppModelBuilder.cs @@ -59,7 +59,7 @@ private CppType TryToCreateTemplateParameters(CXCursor cursor, void* data) { case CXCursorKind.CXCursor_TemplateTypeParameter: { - var parameterTypeName = new CppTemplateParameterType(GetCursorSpelling(cursor)); + var parameterTypeName = new CppTemplateParameterType(CXUtil.GetCursorSpelling(cursor)); return parameterTypeName; } case CXCursorKind.CXCursor_NonTypeTemplateParameter: @@ -67,7 +67,7 @@ private CppType TryToCreateTemplateParameters(CXCursor cursor, void* data) //Just use low level ClangSharp object to do the logic var tmptype = cursor.Type; var tmpcpptype = GetCppType(tmptype.Declaration, tmptype, cursor, data); - var tmpname = cursor.Spelling.ToString(); + var tmpname = CXUtil.GetCursorSpelling(cursor); var noneTypeParam = new CppTemplateParameterNonType(tmpname, tmpcpptype); return noneTypeParam; @@ -76,7 +76,7 @@ private CppType TryToCreateTemplateParameters(CXCursor cursor, void* data) { //ToDo: add template template parameter support here~~ Debug.WriteLine("[Warning] template template parameter maybe not handle right here!"); - var tmplparam = new CppTemplateParameterType(GetCursorSpelling(cursor)); + var tmplparam = new CppTemplateParameterType(CXUtil.GetCursorSpelling(cursor)); return tmplparam; } } @@ -86,10 +86,10 @@ private CppType TryToCreateTemplateParameters(CXCursor cursor, void* data) private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, void* data) { - var typeAsCString = clang.getCursorUSR(cursor).CString.ToString(); + var typeAsCString = CXUtil.GetCursorUsrString(cursor); if (string.IsNullOrEmpty(typeAsCString)) { - typeAsCString = clang.getCursorDisplayName(cursor).ToString(); + typeAsCString = CXUtil.GetCursorDisplayName(cursor); } // Try to workaround anonymous types var typeKey = $"{cursor.Kind}:{typeAsCString}{(cursor.IsAnonymous ? "/" + cursor.Hash : string.Empty)}"; @@ -114,7 +114,7 @@ private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, voi { case CXCursorKind.CXCursor_Namespace: Debug.Assert(parentGlobalDeclarationContainer != null); - var ns = new CppNamespace(GetCursorSpelling(cursor)); + var ns = new CppNamespace(CXUtil.GetCursorSpelling(cursor)); symbol = ns; ns.IsInlineNamespace = cursor.IsInlineNamespace; defaultContainerVisibility = CppVisibility.Default; @@ -123,7 +123,7 @@ private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, voi case CXCursorKind.CXCursor_EnumDecl: Debug.Assert(parent != null); - var cppEnum = new CppEnum(GetCursorSpelling(cursor)) + var cppEnum = new CppEnum(CXUtil.GetCursorSpelling(cursor)) { IsAnonymous = cursor.IsAnonymous, Visibility = GetVisibility(cursor.CXXAccessSpecifier) @@ -138,7 +138,7 @@ private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, voi case CXCursorKind.CXCursor_StructDecl: case CXCursorKind.CXCursor_UnionDecl: Debug.Assert(parent != null); - var cppClass = new CppClass(GetCursorSpelling(cursor)); + var cppClass = new CppClass(CXUtil.GetCursorSpelling(cursor)); parentDeclarationContainer.Classes.Add(cppClass); symbol = cppClass; cppClass.IsAnonymous = cursor.IsAnonymous; @@ -220,12 +220,12 @@ private CppContainerContext GetOrCreateDeclarationContainer(CXCursor cursor, voi break; default: { - Debug.WriteLine($"[Warning]template argument in class:{cppClass.FullName} with type: {arg.kind.ToString()} do not handle right now!"); + Debug.WriteLine($"[Warning]template argument in class:{cppClass.FullName} with type: {arg.kind} do not handle right now!"); cppClass.TemplateSpecializedArguments.Add(new CppTemplateArgument(tempParams[(int)i], arg.ToString())); } break; } - + arg.Dispose(); } } else @@ -305,7 +305,7 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d { var containerContext = GetOrCreateDeclarationContainer(parent, data); var cppEnum = (CppEnum)containerContext.Container; - var enumItem = new CppEnumItem(GetCursorSpelling(cursor), cursor.EnumConstantDeclValue); + var enumItem = new CppEnumItem(CXUtil.GetCursorSpelling(cursor), cursor.EnumConstantDeclValue); ParseAttributes(cursor, enumItem, true); VisitInitValue(cursor, data, out var enumItemExpression, out var enumValue); @@ -483,13 +483,13 @@ private CppComment GetComment(CXComment cxComment) case CppCommentKind.Text: cppComment = new CppCommentText() { - Text = cxComment.TextComment_Text.ToString()?.TrimStart() + Text = CXUtil.GetComment_TextComment_Text(cxComment)?.TrimStart() }; break; case CppCommentKind.InlineCommand: var inline = new CppCommentInlineCommand(); - inline.CommandName = cxComment.InlineCommandComment_CommandName.ToString(); + inline.CommandName = CXUtil.GetComment_InlineCommandComment_CommandName(cxComment); cppComment = inline; switch (cxComment.InlineCommandComment_RenderKind) { @@ -509,19 +509,19 @@ private CppComment GetComment(CXComment cxComment) for (uint i = 0; i < cxComment.InlineCommandComment_NumArgs; i++) { - inline.Arguments.Add(cxComment.InlineCommandComment_GetArgText(i).ToString()); + inline.Arguments.Add(CXUtil.GetComment_InlineCommandComment_ArgText(cxComment, i)); } break; case CppCommentKind.HtmlStartTag: var htmlStartTag = new CppCommentHtmlStartTag(); - htmlStartTag.TagName = cxComment.HtmlTagComment_TagName.ToString(); + htmlStartTag.TagName = CXUtil.GetComment_HtmlTagComment_TagName(cxComment); htmlStartTag.IsSelfClosing = cxComment.HtmlStartTagComment_IsSelfClosing; for (uint i = 0; i < cxComment.HtmlStartTag_NumAttrs; i++) { htmlStartTag.Attributes.Add(new KeyValuePair( - cxComment.HtmlStartTag_GetAttrName(i).ToString(), - cxComment.HtmlStartTag_GetAttrValue(i).ToString() + CXUtil.GetComment_HtmlStartTag_AttrName(cxComment, i), + CXUtil.GetComment_HtmlStartTag_AttrValue(cxComment, i) )); } cppComment = htmlStartTag; @@ -529,7 +529,7 @@ private CppComment GetComment(CXComment cxComment) case CppCommentKind.HtmlEndTag: var htmlEndTag = new CppCommentHtmlEndTag(); - htmlEndTag.TagName = cxComment.HtmlTagComment_TagName.ToString(); + htmlEndTag.TagName = CXUtil.GetComment_HtmlTagComment_TagName(cxComment); cppComment = htmlEndTag; break; @@ -539,10 +539,10 @@ private CppComment GetComment(CXComment cxComment) case CppCommentKind.BlockCommand: var blockComment = new CppCommentBlockCommand(); - blockComment.CommandName = cxComment.BlockCommandComment_CommandName.ToString(); + blockComment.CommandName = CXUtil.GetComment_BlockCommandComment_CommandName(cxComment); for (uint i = 0; i < cxComment.BlockCommandComment_NumArgs; i++) { - blockComment.Arguments.Add(cxComment.BlockCommandComment_GetArgText(i).ToString()); + blockComment.Arguments.Add(CXUtil.GetComment_BlockCommandComment_ArgText(cxComment, i)); } removeTrailingEmptyText = true; @@ -552,7 +552,7 @@ private CppComment GetComment(CXComment cxComment) case CppCommentKind.ParamCommand: var paramComment = new CppCommentParamCommand(); paramComment.CommandName = "param"; - paramComment.ParamName = cxComment.ParamCommandComment_ParamName.ToString(); + paramComment.ParamName = CXUtil.GetComment_ParamCommandComment_ParamName(cxComment); paramComment.IsDirectionExplicit = cxComment.ParamCommandComment_IsDirectionExplicit; paramComment.IsParamIndexValid = cxComment.ParamCommandComment_IsParamIndexValid; paramComment.ParamIndex = (int)cxComment.ParamCommandComment_ParamIndex; @@ -576,7 +576,7 @@ private CppComment GetComment(CXComment cxComment) case CppCommentKind.TemplateParamCommand: var tParamComment = new CppCommentTemplateParamCommand(); tParamComment.CommandName = "tparam"; - tParamComment.ParamName = cxComment.TParamCommandComment_ParamName.ToString(); + tParamComment.ParamName = CXUtil.GetComment_TParamCommandComment_ParamName(cxComment); tParamComment.Depth = (int)cxComment.TParamCommandComment_Depth; // TODO: index tParamComment.IsPositionValid = cxComment.TParamCommandComment_IsParamPositionValid; @@ -586,15 +586,15 @@ private CppComment GetComment(CXComment cxComment) break; case CppCommentKind.VerbatimBlockCommand: var verbatimBlock = new CppCommentVerbatimBlockCommand(); - verbatimBlock.CommandName = cxComment.BlockCommandComment_CommandName.ToString(); + verbatimBlock.CommandName = CXUtil.GetComment_BlockCommandComment_CommandName(cxComment); for (uint i = 0; i < cxComment.BlockCommandComment_NumArgs; i++) { - verbatimBlock.Arguments.Add(cxComment.BlockCommandComment_GetArgText(i).ToString()); + verbatimBlock.Arguments.Add(CXUtil.GetComment_BlockCommandComment_ArgText(cxComment, i)); } cppComment = verbatimBlock; break; case CppCommentKind.VerbatimBlockLine: - var text = cxComment.VerbatimBlockLineComment_Text.ToString(); + var text = CXUtil.GetComment_VerbatimBlockLineComment_Text(cxComment); // For some reason, VerbatimBlockLineComment_Text can return the rest of the file instead of just the line // So we explicitly trim the line here @@ -612,7 +612,7 @@ private CppComment GetComment(CXComment cxComment) case CppCommentKind.VerbatimLine: cppComment = new CppCommentVerbatimLine() { - Text = cxComment.VerbatimLineComment_Text.ToString() + Text = CXUtil.GetComment_VerbatimLineComment_Text(cxComment) }; break; case CppCommentKind.Full: @@ -716,10 +716,11 @@ private CppMacro ParseMacro(CXCursor cursor) var tokens = tu.Tokenize(range); - var name = GetCursorSpelling(cursor); + var name = CXUtil.GetCursorSpelling(cursor); if (name.StartsWith("__cppast")) { //cppast system macros, just ignore here + tu.DisposeTokens(tokens); return null; } @@ -741,7 +742,7 @@ private CppMacro ParseMacro(CXCursor cursor) { break; } - var tokenStr = token.GetSpelling(tu).CString; + var tokenStr = CXUtil.GetTokenSpelling(token, tu); // If we are parsing the token right after the MACRO name token // if the `(` is right after the name without @@ -805,6 +806,7 @@ private CppMacro ParseMacro(CXCursor cursor) var globalContainer = (CppGlobalDeclarationContainer)_rootContainerContext.DeclarationContainer; globalContainer.Macros.Add(cppMacro); + tu.DisposeTokens(tokens); return cppMacro; } @@ -834,12 +836,13 @@ private static void AssignSourceSpan(CXCursor cursor, CppElement element) public static CppSourceLocation GetSourceLocation(CXSourceLocation start) { start.GetFileLocation(out var file, out var line, out var column, out var offset); - return new CppSourceLocation(file.Name.CString, (int)offset, (int)line, (int)column); + var fileNameStr = CXUtil.GetFileName(file); + return new CppSourceLocation(fileNameStr, (int)offset, (int)line, (int)column); } private CppField VisitFieldOrVariable(CppContainerContext containerContext, CXCursor cursor, void* data) { - var fieldName = GetCursorSpelling(cursor); + var fieldName = CXUtil.GetCursorSpelling(cursor); var type = GetCppType(cursor.Type.Declaration, cursor.Type, cursor, data); var previousField = containerContext.DeclarationContainer.Fields.Count > 0 ? containerContext.DeclarationContainer.Fields[containerContext.DeclarationContainer.Fields.Count - 1] : null; @@ -905,8 +908,8 @@ private void VisitInitValue(CXCursor cursor, void* data, out CppExpression expre return CXChildVisitResult.CXChildVisit_Continue; }, new CXClientData((IntPtr)data)); - // Still tries to extract the compiled value - var resultEval = new CXEvalResult((IntPtr)clang.Cursor_Evaluate(cursor)); + // Still tries to extract the compiled value + CXEvalResult resultEval = cursor.Evaluate; switch (resultEval.Kind) { @@ -924,12 +927,13 @@ private void VisitInitValue(CXCursor cursor, void* data, out CppExpression expre case CXEvalResultKind.CXEval_UnExposed: break; default: - RootCompilation.Diagnostics.Warning($"Not supported field default value {cursor}", GetSourceLocation(cursor.Location)); + RootCompilation.Diagnostics.Warning($"Not supported field default value {CXUtil.GetCursorSpelling(cursor)}", GetSourceLocation(cursor.Location)); break; } expression = localExpression; value = localValue; + resultEval.Dispose(); } private static bool IsExpression(CXCursor cursor) @@ -1226,7 +1230,7 @@ private CppFunction VisitFunctionDecl(CXCursor cursor, CXCursor parent, void* da return null; } - var functionName = GetCursorSpelling(cursor); + var functionName = CXUtil.GetCursorSpelling(cursor); //We need ignore the function define out in the class definition here(Otherwise it will has two same functions here~)! var semKind = cursor.SemanticParent.Kind; @@ -1336,7 +1340,7 @@ private CppFunction VisitFunctionDecl(CXCursor cursor, CXCursor parent, void* da switch (argCursor.Kind) { case CXCursorKind.CXCursor_ParmDecl: - var argName = GetCursorSpelling(argCursor); + var argName = CXUtil.GetCursorSpelling(argCursor); var parameter = new CppParameter(GetCppType(argCursor.Type.Declaration, argCursor.Type, functionCursor, clientData), argName); @@ -1440,14 +1444,14 @@ private List ParseSystemAndAnnotateAttributeInCursor(CXCursor curs cursor.VisitChildren((argCursor, parentCursor, clientData) => { var sourceSpan = new CppSourceSpan(GetSourceLocation(argCursor.SourceRange.Start), GetSourceLocation(argCursor.SourceRange.End)); - var meta = argCursor.Spelling.CString; + var meta = CXUtil.GetCursorSpelling(argCursor); switch (argCursor.Kind) { case CXCursorKind.CXCursor_VisibilityAttr: { CppAttribute attribute = new CppAttribute("visibility", AttributeKind.CxxSystemAttribute); AssignSourceSpan(argCursor, attribute); - attribute.Arguments = string.Format("\"{0}\"", argCursor.DisplayName.ToString()); + attribute.Arguments = string.Format("\"{0}\"", CXUtil.GetCursorDisplayName(argCursor)); collectAttributes.Add(attribute); } break; @@ -1646,7 +1650,7 @@ private void ParseTypedefAttribute(CXCursor cursor, CppType type, CppType underl private CppType VisitTypeAliasDecl(CXCursor cursor, void* data) { - var fulltypeDefName = clang.getCursorUSR(cursor).CString; + var fulltypeDefName = CXUtil.GetCursorUsrString(cursor); if (_typedefs.TryGetValue(fulltypeDefName, out var type)) { return type; @@ -1663,7 +1667,7 @@ private CppType VisitTypeAliasDecl(CXCursor cursor, void* data) } var underlyingTypeDefType = GetCppType(usedCursor.TypedefDeclUnderlyingType.Declaration, usedCursor.TypedefDeclUnderlyingType, usedCursor, data); - var typedefName = GetCursorSpelling(usedCursor); + var typedefName = CXUtil.GetCursorSpelling(usedCursor); if (AutoSquashTypedef && underlyingTypeDefType is ICppMember cppMember && (string.IsNullOrEmpty(cppMember.Name) || typedefName == cppMember.Name)) { @@ -1693,7 +1697,7 @@ private CppType VisitTypeAliasDecl(CXCursor cursor, void* data) private CppType VisitTypeDefDecl(CXCursor cursor, void* data) { - var fulltypeDefName = clang.getCursorUSR(cursor).CString; + var fulltypeDefName = CXUtil.GetCursorUsrString(cursor); if (_typedefs.TryGetValue(fulltypeDefName, out var type)) { return type; @@ -1701,8 +1705,8 @@ private CppType VisitTypeDefDecl(CXCursor cursor, void* data) var contextContainer = GetOrCreateDeclarationContainer(cursor.SemanticParent, data); var underlyingTypeDefType = GetCppType(cursor.TypedefDeclUnderlyingType.Declaration, cursor.TypedefDeclUnderlyingType, cursor, data); - - var typedefName = GetCursorSpelling(cursor); + + var typedefName = CXUtil.GetCursorSpelling(cursor); if (AutoSquashTypedef && underlyingTypeDefType is ICppMember cppMember && (string.IsNullOrEmpty(cppMember.Name) || typedefName == cppMember.Name)) { @@ -1732,8 +1736,9 @@ private CppType VisitTypeDefDecl(CXCursor cursor, void* data) private CppType VisitElaboratedDecl(CXCursor cursor, CXType type, CXCursor parent, void* data) { - var fulltypeDefName = clang.getCursorUSR(cursor).CString; - if (_typedefs.TryGetValue(fulltypeDefName, out var typeRef)) { + var fulltypeDefName = CXUtil.GetCursorUsrString(cursor); + if (_typedefs.TryGetValue(fulltypeDefName, out var typeRef)) + { return typeRef; } @@ -1763,8 +1768,6 @@ private string GetCursorAsTextBetweenOffset(CXCursor cursor, int startOffset, in return builder.ToString(); } - private string GetCursorSpelling(CXCursor cursor) => cursor.Spelling.ToString(); - private CppType GetCppType(CXCursor cursor, CXType type, CXCursor parent, void* data) { var cppType = GetCppTypeInternal(cursor, type, parent, data); @@ -1879,7 +1882,7 @@ private CppType GetCppTypeInternal(CXCursor cursor, CXType type, CXCursor parent case CXTypeKind.CXType_DependentSizedArray: { // TODO: this is not yet supported - RootCompilation.Diagnostics.Warning($"Dependent sized arrays `{type}` from `{parent}` is not supported", GetSourceLocation(parent.Location)); + RootCompilation.Diagnostics.Warning($"Dependent sized arrays `{CXUtil.GetTypeSpelling(type)}` from `{CXUtil.GetCursorSpelling(parent)}` is not supported", GetSourceLocation(parent.Location)); var elementType = GetCppType(type.ArrayElementType.Declaration, type.ArrayElementType, parent, data); return new CppArrayType(elementType, (int)type.ArraySize); } @@ -1893,7 +1896,7 @@ private CppType GetCppTypeInternal(CXCursor cursor, CXType type, CXCursor parent return GetCppType(type.Declaration, type.Declaration.Type, parent, data); } - var cppUnexposedType = new CppUnexposedType(type.ToString()) { SizeOf = (int)type.SizeOf }; + var cppUnexposedType = new CppUnexposedType(CXUtil.GetTypeSpelling(type)) { SizeOf = (int)type.SizeOf }; var templateParameters = ParseTemplateSpecializedArguments(cursor, type, new CXClientData((IntPtr)data)); if (templateParameters != null) { @@ -1911,7 +1914,7 @@ private CppType GetCppTypeInternal(CXCursor cursor, CXType type, CXCursor parent default: { WarningUnhandled(cursor, parent, type); - return new CppUnexposedType(type.ToString()) { SizeOf = (int)type.SizeOf }; + return new CppUnexposedType(CXUtil.GetTypeSpelling(type)) { SizeOf = (int)type.SizeOf }; } } } @@ -1940,7 +1943,7 @@ private CppFunctionType VisitFunctionType(CXCursor cursor, CXType type, CXCursor { if (cxCursor.Kind == CXCursorKind.CXCursor_ParmDecl) { - var name = GetCursorSpelling(cxCursor); + var name = CXUtil.GetCursorSpelling(cxCursor); var parameterType = GetCppType(cxCursor.Type.Declaration, cxCursor.Type, cxCursor, data); cppFunction.Parameters.Add(new CppParameter(parameterType, name)); @@ -1955,7 +1958,7 @@ private CppFunctionType VisitFunctionType(CXCursor cursor, CXType type, CXCursor private void Unhandled(CXCursor cursor) { var cppLocation = GetSourceLocation(cursor.Location); - RootCompilation.Diagnostics.Warning($"Unhandled declaration: {cursor.Kind}/{cursor}.", cppLocation); + RootCompilation.Diagnostics.Warning($"Unhandled declaration: {cursor.Kind}/{CXUtil.GetCursorSpelling(cursor)}.", cppLocation); } private void WarningUnhandled(CXCursor cursor, CXCursor parent, CXType type) @@ -1965,7 +1968,7 @@ private void WarningUnhandled(CXCursor cursor, CXCursor parent, CXType type) { cppLocation = GetSourceLocation(parent.Location); } - RootCompilation.Diagnostics.Warning($"The type {cursor.Kind}/`{type}` of kind `{type.KindSpelling}` is not supported in `{parent}`", cppLocation); + RootCompilation.Diagnostics.Warning($"The type {cursor.Kind}/`{CXUtil.GetTypeSpelling(type)}` of kind `{CXUtil.GetTypeKindSpelling(type)}` is not supported in `{CXUtil.GetCursorSpelling(parent)}`", cppLocation); } protected void WarningUnhandled(CXCursor cursor, CXCursor parent) @@ -1975,7 +1978,7 @@ protected void WarningUnhandled(CXCursor cursor, CXCursor parent) { cppLocation = GetSourceLocation(parent.Location); } - RootCompilation.Diagnostics.Warning($"Unhandled declaration: {cursor.Kind}/{cursor} in {parent}.", cppLocation); + RootCompilation.Diagnostics.Warning($"Unhandled declaration: {cursor.Kind}/{CXUtil.GetCursorSpelling(cursor)} in {CXUtil.GetCursorSpelling(parent)}.", cppLocation); } private List ParseTemplateSpecializedArguments(CXCursor cursor, CXType type, CXClientData data) diff --git a/src/CppAst/CppParser.cs b/src/CppAst/CppParser.cs index 68fb40d..744c615 100644 --- a/src/CppAst/CppParser.cs +++ b/src/CppAst/CppParser.cs @@ -164,71 +164,63 @@ private static unsafe CppCompilation ParseInternal(List cppFile // TODO: Add debug rootFileContent = tempBuilder.ToString(); - var rootFileContentUTF8 = Encoding.UTF8.GetBytes(rootFileContent); compilation.InputText = rootFileContent; - fixed (void* rootFileContentUTF8Ptr = rootFileContentUTF8) + CXTranslationUnit translationUnit; + using (CXUnsavedFile unsavedFile = CXUnsavedFile.Create(rootFileName, rootFileContent)) { - CXTranslationUnit translationUnit; + ReadOnlySpan unsavedFiles = stackalloc CXUnsavedFile[] { unsavedFile }; - var rootFileNameUTF8 = Marshal.StringToHGlobalAnsi(rootFileName); - - translationUnit = CXTranslationUnit.Parse(createIndex, rootFileName, argumentsArray,new CXUnsavedFile[] - { - new CXUnsavedFile() - { - Contents = (sbyte*) rootFileContentUTF8Ptr, - Filename = (sbyte*) rootFileNameUTF8, - Length = new UIntPtr((uint)rootFileContentUTF8.Length) - - } - }, translationFlags); + translationUnit = CXTranslationUnit.Parse(createIndex + , rootFileName + , argumentsArray + , unsavedFiles + , translationFlags); + } - bool skipProcessing = false; + bool skipProcessing = false; - if (translationUnit.NumDiagnostics != 0) + if (translationUnit.NumDiagnostics != 0) + { + for (uint i = 0; i < translationUnit.NumDiagnostics; ++i) { - for (uint i = 0; i < translationUnit.NumDiagnostics; ++i) + using (var diagnostic = translationUnit.GetDiagnostic(i)) { - using (var diagnostic = translationUnit.GetDiagnostic(i)) + var message = GetMessageAndLocation(rootFileContent, diagnostic, out var location); + + switch (diagnostic.Severity) { - var message = GetMessageAndLocation(rootFileContent, diagnostic, out var location); - - switch (diagnostic.Severity) - { - case CXDiagnosticSeverity.CXDiagnostic_Ignored: - case CXDiagnosticSeverity.CXDiagnostic_Note: - compilation.Diagnostics.Info(message, location); - break; - case CXDiagnosticSeverity.CXDiagnostic_Warning: - // Avoid warning from clang (0, 0): warning: argument unused during compilation: '-fsyntax-only' - if (!message.Contains("-fsyntax-only")) - { - compilation.Diagnostics.Warning(message, location); - } - break; - case CXDiagnosticSeverity.CXDiagnostic_Error: - case CXDiagnosticSeverity.CXDiagnostic_Fatal: - compilation.Diagnostics.Error(message, location); - skipProcessing = true; - break; - } + case CXDiagnosticSeverity.CXDiagnostic_Ignored: + case CXDiagnosticSeverity.CXDiagnostic_Note: + compilation.Diagnostics.Info(message, location); + break; + case CXDiagnosticSeverity.CXDiagnostic_Warning: + // Avoid warning from clang (0, 0): warning: argument unused during compilation: '-fsyntax-only' + if (!message.Contains("-fsyntax-only")) + { + compilation.Diagnostics.Warning(message, location); + } + break; + case CXDiagnosticSeverity.CXDiagnostic_Error: + case CXDiagnosticSeverity.CXDiagnostic_Fatal: + compilation.Diagnostics.Error(message, location); + skipProcessing = true; + break; } } } + } - if (skipProcessing) - { - compilation.Diagnostics.Warning($"Compilation aborted due to one or more errors listed above.", new CppSourceLocation(rootFileName, 0, 1, 1)); - } - else - { - using (translationUnit) - { - translationUnit.Cursor.VisitChildren(builder.VisitTranslationUnit, clientData: default); - } - } + if (skipProcessing) + { + compilation.Diagnostics.Warning($"Compilation aborted due to one or more errors listed above.", new CppSourceLocation(rootFileName, 0, 1, 1)); } + else + { + translationUnit.Cursor.VisitChildren(builder.VisitTranslationUnit, clientData: default); + } + + translationUnit.Dispose(); return compilation; } @@ -263,6 +255,7 @@ private static string GetMessageAndLocation(string rootContent, CXDiagnostic dia } } + diagnostic.Dispose(); return builder.ToString(); } diff --git a/src/CppAst/CppTokenUtil.cs b/src/CppAst/CppTokenUtil.cs index 1a930f7..56b1017 100644 --- a/src/CppAst/CppTokenUtil.cs +++ b/src/CppAst/CppTokenUtil.cs @@ -439,21 +439,20 @@ public string PeekText() [DebuggerTypeProxy(typeof(TokenizerDebuggerType))] internal class Tokenizer { - private readonly CXToken[] _tokens; + private readonly CXSourceRange _range; private CppToken[] _cppTokens; protected readonly CXTranslationUnit _tu; public Tokenizer(CXCursor cursor) { _tu = cursor.TranslationUnit; - var range = GetRange(cursor); - _tokens = _tu.Tokenize(range).ToArray(); + _range = GetRange(cursor); } public Tokenizer(CXTranslationUnit tu, CXSourceRange range) { _tu = tu; - _tokens = _tu.Tokenize(range).ToArray(); + _range = range; } public virtual CXSourceRange GetRange(CXCursor cursor) @@ -461,7 +460,16 @@ public virtual CXSourceRange GetRange(CXCursor cursor) return cursor.Extent; } - public int Count => _tokens?.Length ?? 0; + public int Count + { + get + { + var tokens = _tu.Tokenize(_range); + int length = tokens.Length; + _tu.DisposeTokens(tokens); + return length; + } + } public CppToken this[int i] { @@ -470,7 +478,7 @@ public CppToken this[int i] // Only create a tokenizer if necessary if (_cppTokens == null) { - _cppTokens = new CppToken[_tokens.Length]; + _cppTokens = new CppToken[Count]; } ref var cppToken = ref _cppTokens[i]; @@ -478,8 +486,9 @@ public CppToken this[int i] { return cppToken; } + var tokens = _tu.Tokenize(_range); + var token = tokens[i]; - var token = _tokens[i]; CppTokenKind cppTokenKind = 0; switch (token.Kind) { @@ -502,7 +511,7 @@ public CppToken this[int i] break; } - var tokenStr = token.GetSpelling(_tu).CString; + var tokenStr = CXUtil.GetTokenSpelling(token, _tu); var tokenLocation = token.GetLocation(_tu); var tokenRange = token.GetExtent(_tu); @@ -510,26 +519,30 @@ public CppToken this[int i] { Span = new CppSourceSpan(CppModelBuilder.GetSourceLocation(tokenRange.Start), CppModelBuilder.GetSourceLocation(tokenRange.End)) }; + _tu.DisposeTokens(tokens); return cppToken; } } public string GetString(int i) { - var token = _tokens[i]; - return token.GetSpelling(_tu).CString; + var tokens = _tu.Tokenize(_range); + var TokenSpelling = CXUtil.GetTokenSpelling(tokens[i], _tu); + _tu.DisposeTokens(tokens); + return TokenSpelling; } public string TokensToString() { - if (_tokens == null) + int length = Count; + if (length <= 0) { return null; } - var tokens = new List(_tokens.Length); + var tokens = new List(length); - for (int i = 0; i < _tokens.Length; i++) + for (int i = 0; i < length; i++) { tokens.Add(this[i]); }