Example #1
0
        public void BasicWrapper(string name)
        {
            // Create a unique directory
            var dir = Path.GetRandomFileName();

            _ = Directory.CreateDirectory(dir);

            try
            {
                // Create a file with the right name
                var file = new FileInfo(Path.Combine(dir, name + ".c"));
                File.WriteAllText(file.FullName, "int main() { return 0; }");

                var index               = CXIndex.Create();
                var translationUnit     = CXTranslationUnit.Parse(index, file.FullName, Array.Empty <string>(), Array.Empty <CXUnsavedFile>(), CXTranslationUnit_Flags.CXTranslationUnit_None);
                var clangFile           = translationUnit.GetFile(file.FullName);
                var clangFileName       = clangFile.Name;
                var clangFileNameString = clangFileName.CString;

                Assert.Equal(file.FullName, clangFileNameString);
            }
            finally
            {
                Directory.Delete(dir, true);
            }
        }
Example #2
0
        public void Parse()
        {
            s_Root = new Node();
            CXIndex index = clang.createIndex(0, 0);

            string[] arr = { "-std=c++17", "-ast-dump" };
            // -ast-dump
            // OnlyLocalDecls
            CXUnsavedFile     unsavedFile;
            CXTranslationUnit translationUnit;
            // TODO: grab errors and warnings
            //var translationUnitError = clang.parseTranslationUnit2(index, "C:\\Users\\Alex\\source\\repos\\clang_test\\clang_test\\test.cpp", arr, 2, out unsavedFile, 0, 0, out translationUnit);
            var translationUnitError = clang.parseTranslationUnit2(index, m_url, arr, 2, out unsavedFile, 0, 0, out translationUnit);

            if (translationUnitError != CXErrorCode.CXError_Success)
            {
                Console.WriteLine("Error: " + translationUnitError);
                var numDiagnostics = clang.getNumDiagnostics(translationUnit);

                for (uint i = 0; i < numDiagnostics; ++i)
                {
                    var diagnostic = clang.getDiagnostic(translationUnit, i);
                    Console.WriteLine(clang.getDiagnosticSpelling(diagnostic).ToString());
                    clang.disposeDiagnostic(diagnostic);
                }
            }
            else
            {
                traverse(translationUnit);
                clang.disposeTranslationUnit(translationUnit);
            }
            clang.disposeIndex(index);
        }
Example #3
0
        protected static TranslationUnit CreateTranslationUnit(string inputContents)
        {
            Assert.True(File.Exists(DefaultInputFileName));

            using var unsavedFile = CXUnsavedFile.Create(DefaultInputFileName, inputContents);
            var unsavedFiles = new CXUnsavedFile[] { unsavedFile };

            var index           = CXIndex.Create();
            var translationUnit = CXTranslationUnit.Parse(index, DefaultInputFileName, DefaultClangCommandLineArgs, unsavedFiles, DefaultTranslationUnitFlags);

            if (translationUnit.NumDiagnostics != 0)
            {
                var errorDiagnostics = new StringBuilder();
                _ = errorDiagnostics.AppendLine($"The provided {nameof(CXTranslationUnit)} has the following diagnostics which prevent its use:");
                var invalidTranslationUnitHandle = false;

                for (uint i = 0; i < translationUnit.NumDiagnostics; ++i)
                {
                    using var diagnostic = translationUnit.GetDiagnostic(i);

                    if (diagnostic.Severity is CXDiagnosticSeverity.CXDiagnostic_Error or CXDiagnosticSeverity.CXDiagnostic_Fatal)
                    {
                        invalidTranslationUnitHandle = true;
                        _ = errorDiagnostics.Append(' ', 4);
                        _ = errorDiagnostics.AppendLine(diagnostic.Format(CXDiagnosticDisplayOptions.CXDiagnostic_DisplayOption).ToString());
                    }
                }

                Assert.False(invalidTranslationUnitHandle, errorDiagnostics.ToString());
            }

            return(TranslationUnit.GetOrCreate(translationUnit));
        }
Example #4
0
        private static bool TryParseTranslationUnit(
            string filePath,
            ImmutableArray <string> commandLineArgs,
            out CXTranslationUnit translationUnit)
        {
            // ReSharper disable BitwiseOperatorOnEnumWithoutFlags
            var flags = CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes |
                        CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes |
                        CXTranslationUnit_Flags.CXTranslationUnit_IgnoreNonErrorsFromIncludedFiles |
                        CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies;

            var index     = CXIndex.Create();
            var errorCode = CXTranslationUnit.TryParse(
                index,
                filePath,
                commandLineArgs.AsSpan(),
                Array.Empty <CXUnsavedFile>(),
                flags,
                out translationUnit);

            if (errorCode == CXErrorCode.CXError_Success)
            {
                return(translationUnit != null);
            }

            translationUnit = null !;
            return(false);
        }
Example #5
0
 public ClangWrapper(string filePath, CXIndex index, CXTranslationUnit translationUnit, CXCursor cursor)
 {
     FilePath        = filePath;
     Index           = index;
     TranslationUnit = translationUnit;
     Cursor          = cursor;
 }
Example #6
0
 internal static extern ErrorCode clang_parseTranslationUnit2FullArgv(CXIndex index, string source_filename,
                                                                      [MarshalAs(UnmanagedType.LPArray)] string[] command_line_args,
                                                                      int num_command_line_args,
                                                                      [MarshalAs(UnmanagedType.LPArray)] CXUnsavedFile[] unsaved_files,
                                                                      uint num_unsaved_files,
                                                                      TranslationUnitFlags options,
                                                                      out CXTranslationUnit out_tu);
Example #7
0
 public static extern CXErrorCode parseTranslationUnit2(CXIndex @CIdx,
                                                        [MarshalAs(UnmanagedType.LPStr)] string @source_filename,
                                                        string[] @command_line_args,
                                                        int @num_command_line_args,
                                                        [MarshalAs(UnmanagedType.LPArray)] CXUnsavedFile[] @unsaved_files,
                                                        uint @num_unsaved_files,
                                                        uint @options,
                                                        out CXTranslationUnit @out_TU);
Example #8
0
 public ParseClang(DeepEnds.Core.Parser parser, TextWriter logger)
 {
     this.parser      = parser;
     this.logger      = logger;
     this.createIndex = clang.createIndex(0, 0);
     this.leaves      = new Dictionary <string, DeepEnds.Core.Dependency>();
     this.links       = new Dictionary <DeepEnds.Core.Dependency, HashSet <string> >();
 }
Example #9
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="proj">
 /// A <see cref="CProject"/> reference: project which the manager manages
 /// </param>
 public CLangManager(CProject proj)
 {
     project          = proj;
     index            = clang.createIndex(0, 0);
     SerManager       = new SerializationManager(project, this, index);
     translationUnits = new Dictionary <string, CXTranslationUnit> ();
     Loaded           = new Dictionary <string, bool> ();
     project.DefaultConfigurationChanged += HandleDefaultConfigurationChange;
     project.FileAddedToProject          += HandleAddition;
     project.FileChangedInProject        += HandleChange;
     project.FileRemovedFromProject      += HandleRemoval;
     project.FileRenamedInProject        += HandleRename;
 }
Example #10
0
 /// <inheritDoc />
 public BIR.BIR Produce(Configuration config)
 {
     using (var index = CXIndex.Create())
     {
         using (var tu = BuildClangAST(config, index))
         {
             if (tu != null)
             {
                 return(TransformClangASTtoBIR(config, index, tu));
             }
         }
     }
     return(null);
 }
Example #11
0
        /// <summary>
        /// Transform the Clang AST to BIR
        /// </summary>
        private BIR.BIR TransformClangASTtoBIR(Configuration config, CXIndex index, TranslationUnit tu)
        {
            BIR.BIR bir = null;
            using (var section = CreateSection("Transforming Clang AST to BIR"))
            {
                using (var parser = new ClangParser(Context, index, tu))
                {
                    bir = parser.ProduceBIR(config);
                }

                if (bir != null)
                {
                    section.Done();
                }
            }
            return(bir);
        }
Example #12
0
        public AST ParseWithClangArgs(CppConfig config)
        {
            if (config.Sources.Count == 0)
            {
                Console.WriteLine("No input sources or includes");
                return(null);
            }

            // the index object
            CXIndex Index = clang.createIndex(0, 0);

            // prepare some vars for parse
            uint option = clang.defaultEditingTranslationUnitOptions()
                          | (uint)CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies;
            CXUnsavedFile unsavedFile = new CXUnsavedFile();

            CXTranslationUnit TU;
            var error = clang.parseTranslationUnit2(Index, config.Sources[0], config.Extras, config.Extras.Length, out unsavedFile, 0,
                                                    option, out TU);

            if (error != CXErrorCode.CXError_Success)
            {
                Console.WriteLine("Failed to parse Translation Unit!");
                return(null);
            }

            bool fatal          = false;
            var  numDiagnostics = clang.getNumDiagnostics(TU);

            for (uint loop = 0; loop < numDiagnostics; ++loop)
            {
                fatal |= DealingWithDiagnostic(clang.getDiagnostic(TU, loop));
            }
            if (fatal)
            {
                return(null);
            }

            ASTVisitor visitor = new ASTVisitor();
            AST        ast     = visitor.Visit(TU);

            clang.disposeIndex(Index);
            return(ast);
        }
Example #13
0
        public void AugmentSignatureHelpSession(ISignatureHelpSession session, IList <ISignature> signatures)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var snapshot      = _textBuffer.CurrentSnapshot;
            var triggerPoint  = session.GetTriggerPoint(_textBuffer);
            var snapshotPoint = triggerPoint.GetPoint(snapshot);
            var position      = triggerPoint.GetPosition(snapshot);

            var applicableToSpan = _textBuffer.CurrentSnapshot.CreateTrackingSpan(new Span(position, 0), SpanTrackingMode.EdgeInclusive, TrackingFidelityMode.Forward);

            // Parse the entire document into an AST
            var index = CXIndex.Create(false, false);

            if ((_dte.ActiveDocument, snapshot).TryParseDocument(index, out var translationUnit, out _))
            {
                var visitor = new EmplacingVisitor(_dte.ActiveDocument.FullName, snapshotPoint.GetContainingLine().LineNumber);
                visitor.CtorFound += (templateParameters, parameters) =>
                {
                    // TODO: eliminate this stupid back-and-forth string handling

                    var signatureBuilder = new StringBuilder("emplace");
                    signatureBuilder.Append('(');
                    foreach (var parameter in parameters)
                    {
                        signatureBuilder.Append(parameter.Type).Append(' ').Append(parameter.Name).Append(", ");
                    }

                    if (parameters.Count > 0)
                    {
                        signatureBuilder.Length -= 2;
                    }
                    signatureBuilder.Append(')');

                    signatures.Add(CreateSignature(_textBuffer, signatureBuilder.ToString(), applicableToSpan));
                };

                visitor.Visit(translationUnit);
            }
        }
Example #14
0
 public SerializationManager(CProject proj, CLangManager man, CXIndex ind)
 {
     Manager = man;
     project = proj;
     Index   = ind;
 }
Example #15
0
        /// <summary>
        /// Build the Clang AST
        /// </summary>
        private TranslationUnit BuildClangAST(Configuration config, CXIndex index)
        {
            CXTranslationUnit tu = null;

            using (var section = CreateSection("Building Clang AST"))
            {
                // Assemble the arguments
                var clangArgs = new List <string>()
                {
                    "-Wno-pragma-once-outside-header"
                };

                switch (config.Clang.Language)
                {
                case LanguageEnum.C99:
                    clangArgs.Add("-xc");
                    clangArgs.Add("-std=c99");
                    break;

                case LanguageEnum.Cpp11:
                    clangArgs.Add("-xc++");
                    clangArgs.Add("-std=c++11");
                    break;

                case LanguageEnum.Cpp14:
                    clangArgs.Add("-xc++");
                    clangArgs.Add("-std=c++14");
                    break;

                case LanguageEnum.Cpp17:
                    clangArgs.Add("-xc++");
                    clangArgs.Add("-std=c++17");
                    break;

                default:
                    throw new Exception($"unknown language {config.Clang.Language}");
                }

                clangArgs.AddRange(GetWinSDKDIncludeArgs(config));
                clangArgs.AddRange(GetCxxSTLIncludeArgs(config));

                clangArgs.AddRange(config.Clang.Includes.Select(i => MakeIncludeArg(i)));
                clangArgs.AddRange(config.Clang.Defines.Select((m, v) => $"-D{m}=\"{v}\""));
                clangArgs.AddRange(config.Clang.Arguments.Split(" "));

                var tuFlags = CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies;

                // Create the TU source file
                var sourceFiles = new HashSet <string>();
                config.Hook.Descriptions.Values.ToList().ForEach(hook => hook.Input.ForEach(source => sourceFiles.Add(source)));

                var tuFilename = Path.GetFileNameWithoutExtension(string.IsNullOrEmpty(config.Plugin.Name) ? Path.GetTempFileName() : config.Plugin.Name) + ".cpp";
                Logger.Debug($"Clang TU filename: {tuFilename}");

                var tuSource = "#include <" + string.Join(">\n#include <", sourceFiles) + ">";

                Logger.Debug($"Clang TU source:\n  {tuSource.Replace("\n", "\n  ")}");
                using (var tuSourceFile = CXUnsavedFile.Create(tuFilename, tuSource))
                {
                    // Invoke clang to get the TU
                    Logger.Debug($"Clang args: {string.Join(" ", clangArgs)}");
                    var tuError = CXTranslationUnit.TryParse(index, tuSourceFile.FilenameString, clangArgs.ToArray(), new CXUnsavedFile[] { tuSourceFile }, tuFlags, out tu);
                    if (tuError != CXErrorCode.CXError_Success)
                    {
                        throw new Exception($"clang error: failed to generate tanslation unit: {tuError}");
                    }
                }
                section.Done();
            }
            if (tu == null)
            {
                return(null);
            }
            return(TranslationUnit.GetOrCreate(tu));
        }
Example #16
0
 internal static extern CXIndexAction clang_IndexAction_create(CXIndex index);
Example #17
0
 internal static extern void clang_disposeIndex(CXIndex index);
Example #18
0
 internal static extern CXTranslationUnit clang_createTranslationUnit(CXIndex index, string ast_filename);
Example #19
0
        /// <summary>
        /// Private method parsing file or content.
        /// </summary>
        /// <param name="cppFiles">A list of path to C/C++ header files on the disk to parse</param>
        /// <param name="options">Options used for parsing this file (e.g include folders...)</param>
        /// <returns>The result of the compilation</returns>
        private static unsafe CppCompilation ParseInternal(List <CppFileOrString> cppFiles, CppParserOptions options = null)
        {
            if (cppFiles == null)
            {
                throw new ArgumentNullException(nameof(cppFiles));
            }

            options = options ?? new CppParserOptions();

            var arguments = new List <string>();

            // Make sure that paths are absolute
            var normalizedIncludePaths = new List <string>();

            normalizedIncludePaths.AddRange(options.IncludeFolders.Select(x => Path.Combine(Environment.CurrentDirectory, x)));

            var normalizedSystemIncludePaths = new List <string>();

            normalizedSystemIncludePaths.AddRange(options.SystemIncludeFolders.Select(x => Path.Combine(Environment.CurrentDirectory, x)));

            arguments.AddRange(options.AdditionalArguments);
            arguments.AddRange(normalizedIncludePaths.Select(x => $"-I{x}"));
            arguments.AddRange(normalizedSystemIncludePaths.Select(x => $"-isystem{x}"));
            arguments.AddRange(options.Defines.Select(x => $"-D{x}"));

            arguments.Add("-dM");
            arguments.Add("-E");

            if (options.ParseAsCpp && !arguments.Contains("-xc++"))
            {
                arguments.Add("-xc++");
            }

            if (!arguments.Any(x => x.StartsWith("--target=")))
            {
                arguments.Add($"--target={GetTripleFromOptions(options)}");
            }

            if (options.ParseComments)
            {
                arguments.Add("-fparse-all-comments");
            }

            var translationFlags = CXTranslationUnit_Flags.CXTranslationUnit_None;

            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies;                   // Don't traverse function bodies
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes;               // Include attributed types in CXType
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes;              // Implicit attributes should be visited

            if (options.ParseMacros)
            {
                translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord;
            }
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord;

            var argumentsArray = arguments.ToArray();

            using (var createIndex = CXIndex.Create())
            {
                var builder = new CppModelBuilder
                {
                    AutoSquashTypedef     = options.AutoSquashTypedef,
                    ParseSystemIncludes   = options.ParseSystemIncludes,
                    ParseAttributeEnabled = options.ParseAttributes,
                };
                var compilation = builder.RootCompilation;

                string rootFileName    = CppAstRootFileName;
                string rootFileContent = null;

                // Creates a fake 'header.hpp' that includes all the files we passed, so they are parsed all at once

                // Build the root input source file
                var tempBuilder = new StringBuilder();
                if (options.PreHeaderText != null)
                {
                    tempBuilder.AppendLine(options.PreHeaderText);
                }

                foreach (var file in cppFiles)
                {
                    if (file.Content != null)
                    {
                        tempBuilder.AppendLine(file.Content);
                    }
                    else
                    {
                        var filePath = Path.Combine(Environment.CurrentDirectory, file.Filename);
                        tempBuilder.AppendLine($"#include \"{filePath}\"");
                    }
                }

                if (options.PostHeaderText != null)
                {
                    tempBuilder.AppendLine(options.PostHeaderText);
                }

                // TODO: Add debug
                rootFileContent = tempBuilder.ToString();

                var rootFileContentUTF8 = Encoding.UTF8.GetBytes(rootFileContent);
                compilation.InputText = rootFileContent;

                fixed(void *rootFileContentUTF8Ptr = rootFileContentUTF8)
                {
                    CXTranslationUnit translationUnit;

                    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);

                    // Skips the processing of the file if 1 error is raised
                    // We don't want that, so remove that part

                    //bool skipProcessing = false;

                    //if (translationUnit.NumDiagnostics != 0)
                    //{
                    //    for (uint i = 0; i < translationUnit.NumDiagnostics; ++i)
                    //    {
                    //        using (var diagnostic = translationUnit.GetDiagnostic(i))
                    //        {
                    //            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:
                    //                    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);
                    }
                    //}
                }

                return(compilation);
            }
        }
Example #20
0
 internal static extern GlobalOptionFlags clang_CXIndex_getGlobalOptions(CXIndex index);
Example #21
0
 internal static extern CXIndexAction clang_IndexAction_create(CXIndex index);
Example #22
0
 internal static extern void clang_IndexAction_dispose(CXIndex index);
Example #23
0
 internal static extern void clang_CXIndex_setGlobalOptions(CXIndex index, GlobalOptionFlags options);
Example #24
0
 internal static extern CXTranslationUnit clang_createTranslationUnitFromSourceFile(CXIndex index, string sourceFilename,
     int numClangCommandLineArgs, string[] clangCommandLineArgs, uint numUnsavedFiles, UnsavedFile[] unsavedFiles);
Example #25
0
 public ClangParser(string root)
 {
     Root  = root;
     index = clang.createIndex(0, 0);
 }
Example #26
0
 internal static extern CXTranslationUnit clang_createTranslationUnitFromSourceFile(CXIndex index, string source_filename,
                                                                                    int num_clang_command_line_args,
                                                                                    [MarshalAs(UnmanagedType.LPArray)] string[] clang_command_line_ags,
                                                                                    uint num_unsaved_files,
                                                                                    [MarshalAs(UnmanagedType.LPArray)] CXUnsavedFile[] unsaved_files);
Example #27
0
        /// <summary>
        /// Private method parsing file or content.
        /// </summary>
        /// <param name="cppFiles">A list of path to C/C++ header files on the disk to parse</param>
        /// <param name="options">Options used for parsing this file (e.g include folders...)</param>
        /// <returns>The result of the compilation</returns>
        private static CppCompilation ParseInternal(List <CppFileOrString> cppFiles, CppParserOptions options = null)
        {
            if (cppFiles == null)
            {
                throw new ArgumentNullException(nameof(cppFiles));
            }

            options = options ?? new CppParserOptions();

            var arguments = new List <string>();

            // Make sure that paths are absolute
            var normalizedIncludePaths = new List <string>();

            normalizedIncludePaths.AddRange(options.IncludeFolders.Select(x => Path.Combine(Environment.CurrentDirectory, x)));

            var normalizedSystemIncludePaths = new List <string>();

            normalizedSystemIncludePaths.AddRange(options.SystemIncludeFolders.Select(x => Path.Combine(Environment.CurrentDirectory, x)));

            arguments.AddRange(options.AdditionalArguments);
            arguments.AddRange(normalizedIncludePaths.Select(x => $"-I{x}"));
            arguments.AddRange(normalizedSystemIncludePaths.Select(x => $"-isystem{x}"));
            arguments.AddRange(options.Defines.Select(x => $"-D{x}"));

            if (options.ParseAsCpp && !arguments.Contains("-xc++"))
            {
                arguments.Add("-xc++");
            }

            if (!arguments.Any(x => x.StartsWith("--target=")))
            {
                arguments.Add($"--target={GetTripleFromOptions(options)}");
            }

            if (options.ParseComments)
            {
                arguments.Add("-fparse-all-comments");
            }

            var translationFlags = CXTranslationUnit_Flags.CXTranslationUnit_None;

            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies;                   // Don't traverse function bodies
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes;               // Include attributed types in CXType
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes;              // Implicit attributes should be visited

            if (options.ParseMacros)
            {
                translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord;
            }

            var argumentsArray = arguments.ToArray();

            using (var createIndex = CXIndex.Create())
            {
                var builder = new CppModelBuilder {
                    AutoSquashTypedef = options.AutoSquashTypedef
                };
                var compilation = builder.RootCompilation;

                string rootFileName    = CppAstRootFileName;
                string rootFileContent = null;

                // Build the root input source file
                var tempBuilder = new StringBuilder();
                if (options.PreHeaderText != null)
                {
                    tempBuilder.AppendLine(options.PreHeaderText);
                }

                foreach (var file in cppFiles)
                {
                    if (file.Content != null)
                    {
                        tempBuilder.AppendLine(file.Content);
                    }
                    else
                    {
                        var filePath = Path.Combine(Environment.CurrentDirectory, file.Filename);
                        tempBuilder.AppendLine($"#include \"{filePath}\"");
                    }
                }

                if (options.PostHeaderText != null)
                {
                    tempBuilder.AppendLine(options.PostHeaderText);
                }

                // TODO: Add debug
                rootFileContent = tempBuilder.ToString();

                compilation.InputText = rootFileContent;

                {
                    CXTranslationUnit translationUnit;
                    CXErrorCode       translationUnitError;

                    translationUnitError = CXTranslationUnit.Parse(createIndex, rootFileName, argumentsArray, new CXUnsavedFile[] { new CXUnsavedFile()
                                                                                                                                    {
                                                                                                                                        Contents = rootFileContent,
                                                                                                                                        Filename = rootFileName,
                                                                                                                                        Length   = (uint)Encoding.UTF8.GetByteCount(rootFileContent)
                                                                                                                                    } }, translationFlags, out translationUnit);

                    bool skipProcessing = false;

                    if (translationUnitError != CXErrorCode.CXError_Success)
                    {
                        compilation.Diagnostics.Error($"Parsing failed due to '{translationUnitError}'", new CppSourceLocation(rootFileName, 0, 1, 1));
                        skipProcessing = true;
                    }
                    else if (translationUnit.NumDiagnostics != 0)
                    {
                        for (uint i = 0; i < translationUnit.NumDiagnostics; ++i)
                        {
                            using (var diagnostic = translationUnit.GetDiagnostic(i))
                            {
                                CppSourceLocation location;
                                var message = GetMessageAndLocation(rootFileContent, diagnostic, out location);

                                switch (diagnostic.Severity)
                                {
                                case CXDiagnosticSeverity.CXDiagnostic_Ignored:
                                case CXDiagnosticSeverity.CXDiagnostic_Note:
                                    compilation.Diagnostics.Info(message, location);
                                    break;

                                case CXDiagnosticSeverity.CXDiagnostic_Warning:
                                    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);
                        }
                    }
                }

                return(compilation);
            }
        }
Example #28
0
 public ClangCodeParser()
 {
     _index = CXIndex.Create();
 }
Example #29
0
        public static int Run(InvocationContext context)
        {
            var additionalArgs = context.ParseResult.ValueForOption <string[]>("additional");
            var config         = new ConfigurationOptions(context.ParseResult.ValueForOption <string[]>("config"))
            {
                ExcludedFunctions   = context.ParseResult.ValueForOption <string[]>("excludeFunction"),
                LibraryPath         = context.ParseResult.ValueForOption <string>("libraryPath"),
                MethodClassName     = context.ParseResult.ValueForOption <string>("methodClassName"),
                Namespace           = context.ParseResult.ValueForOption <string>("namespace"),
                OutputLocation      = context.ParseResult.ValueForOption <string>("output"),
                MethodPrefixToStrip = context.ParseResult.ValueForOption <string>("prefixStrip"),
            };
            var defines     = context.ParseResult.ValueForOption <string[]>("define");
            var files       = context.ParseResult.ValueForOption <string[]>("file");
            var includeDirs = context.ParseResult.ValueForOption <string[]>("include");

            var errorList = new List <string>();

            if (!files.Any())
            {
                errorList.Add("Error: No input C/C++ files provided. Use --file or -f");
            }

            if (string.IsNullOrWhiteSpace(config.Namespace))
            {
                errorList.Add("Error: No namespace provided. Use --namespace or -n");
            }

            if (string.IsNullOrWhiteSpace(config.OutputLocation))
            {
                errorList.Add("Error: No output file location provided. Use --output or -o");
            }

            if (string.IsNullOrWhiteSpace(config.LibraryPath))
            {
                errorList.Add("Error: No library path location provided. Use --libraryPath or -l");
            }

            if (errorList.Any())
            {
                foreach (var error in errorList)
                {
                    context.Console.Error.WriteLine(error);
                }
                context.Console.Error.WriteLine();

                new HelpBuilder(context.Console).Write(s_rootCommand);
                return(-1);
            }

            var arr = new string[]
            {
                "-xc++",                                // The input files are C++
                "-Wno-pragma-once-outside-header"       // We are processing files which may be header files
            };

            arr = arr.Concat(includeDirs.Select(x => "-I" + x)).ToArray();
            arr = arr.Concat(defines.Select(x => "-D" + x)).ToArray();
            arr = arr.Concat(additionalArgs).ToArray();

            var translationFlags = CXTranslationUnit_Flags.CXTranslationUnit_None;

            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies;                   // Don't traverse function bodies
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes;               // Include attributed types in CXType
            translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes;              // Implicit attributes should be visited

            using (var createIndex = CXIndex.Create())
                using (var cursorWriter = new CursorWriter(config))
                {
                    foreach (var file in files)
                    {
                        var  translationUnitError = CXTranslationUnit.Parse(createIndex, file, arr, Array.Empty <CXUnsavedFile>(), translationFlags, out CXTranslationUnit translationUnitHandle);
                        bool skipProcessing       = false;

                        if (translationUnitError != CXErrorCode.CXError_Success)
                        {
                            Console.WriteLine($"Error: Parsing failed for '{file}' due to '{translationUnitError}'.");
                            skipProcessing = true;
                        }
                        else if (translationUnitHandle.NumDiagnostics != 0)
                        {
                            Console.WriteLine($"Diagnostics for '{file}':");

                            for (uint i = 0; i < translationUnitHandle.NumDiagnostics; ++i)
                            {
                                using (var diagnostic = translationUnitHandle.GetDiagnostic(i))
                                {
                                    Console.Write("    ");
                                    Console.WriteLine(diagnostic.Format(CXDiagnosticDisplayOptions.CXDiagnostic_DisplayOption).ToString());

                                    skipProcessing |= (diagnostic.Severity == CXDiagnosticSeverity.CXDiagnostic_Error);
                                    skipProcessing |= (diagnostic.Severity == CXDiagnosticSeverity.CXDiagnostic_Fatal);
                                }
                            }
                        }

                        if (skipProcessing)
                        {
                            Console.WriteLine($"Skipping '{file}' due to one or more errors listed above.");
                            Console.WriteLine();
                            continue;
                        }

                        using (translationUnitHandle)
                        {
                            var translationUnit = new TranslationUnit(translationUnitHandle.Cursor);
                            translationUnit.Visit(clientData: default);
Example #30
0
 public CodeCParser()
 {
     _index = CXIndex.Create();
 }
Example #31
0
 internal static extern void clang_disposeIndex(CXIndex index);
Example #32
0
 internal static extern ErrorCode clang_createTranslationUnit2(CXIndex index, string ast_filename, out CXTranslationUnit out_tu);
Example #33
0
 internal static extern void clang_CXIndex_setInvocationEmissionPathOption(CXIndex index, string path);
Example #34
0
 public ClangParser(CompilerContext ctx, CXIndex index, TranslationUnit tu) : base(ctx)
 {
     Index = index;
     TU    = tu;
 }