xoofx / xoofx/CppAst.NET

CppContainerList throws "The item belongs already to a container" when parsing VTK 9.5 headers Body

Open
#122 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
620
Forks
79
Avg merge
14h 27m
Merged PRs (30d)
1

Description

Description

When parsing VTK 9.5 headers with CppParser.ParseFile, an ArgumentException is thrown:

System.ArgumentException: The item belongs already to a container
   at CppAst.CppContainerList`1.Add(TElement item)
   at CppAst.CppContainerList`1.AddRange(IEnumerable`1 collection)
   at CppAst.CppModelBuilder.GetCppTypeInternal(CXCursor cursor, CXType type, CXCursor parent, Void* data)

Reproduction

var options = new CppParserOptions();
options.ConfigureForWindowsMsvc(CppTargetCpu.X86_64, CppVisualStudioVersion.VS2022);
options.IncludeFolders.Add(@"C:\Program Files\VTK\include\vtk-9.5");
var compilation = CppParser.ParseFile(@"C:\Program Files\VTK\include\vtk-9.5\vtkActor.h", options);

Environment: VTK 9.5 headers, CppAst 0.25.0, ClangSharp 21.1.8.3, Windows x64.

Root Cause

The problem is in CppContainerList<T>.Add() — it enforces strict single-parent ownership:

public void Add(TElement item)
{
    if (item.Parent != null)
        throw new ArgumentException("The item belongs already to a container");
    ...
}

During GetCppTypeInternalCXType_Unexposed handling, ParseTemplateSpecializedArguments resolves template arguments that return type instances already belonging to a container (e.g., a CppClass that was added to compilation.Classes). When these same instances are added to CppUnexposedType.TemplateParameters via AddRange, the strict check fails.

The stack trace consistently points to:

GetCppTypeInternal → VisitElaboratedDecl → GetCppType → GetCppTypeInternal → VisitFunctionDecl → CppContainerList.AddRange

Suggested Fix

Relax Add and Insert to allow re-parenting. Skip duplicates in the same container, otherwise allow the element to move:

public void Add(TElement item)
{
    if (item.Parent == Container)
        return; // Already in this container
    item.Parent = Container;
    _elements.Add(item);
}

public void Insert(int index, TElement item)
{
    if (item.Parent == Container)
        return; // Already in this container
    item.Parent = Container;
    _elements.Insert(index, item);
}

This is the same approach taken by XML DOM implementations — a node can be moved from one parent to another without error.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with CppContainerList.Add and Insert, then trace CppModelBuilder.GetCppTypeInternal through CXType_Unexposed and ParseTemplateSpecializedArguments. Reproduce the failure by parsing vtkActor.h from VTK 9.5 with the shown options. Done means the header parses without the container ownership exception while duplicate and parent behavior remains covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, csharp
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.