@@ -17,7 +17,9 @@ namespace CppAst
1717 /// </summary>
1818 internal unsafe class CppModelBuilder
1919 {
20- private readonly CppContainerContext _rootContainerContext ;
20+ private readonly CppContainerContext _userRootContainerContext ;
21+ private readonly CppContainerContext _systemRootContainerContext ;
22+ private CppContainerContext _rootContainerContext ;
2123 private readonly Dictionary < string , CppContainerContext > _containers ;
2224 private readonly Dictionary < string , CppType > _typedefs ;
2325 private CppClass _currentClassBeingVisited ;
@@ -27,7 +29,14 @@ public CppModelBuilder()
2729 _containers = new Dictionary < string , CppContainerContext > ( ) ;
2830 RootCompilation = new CppCompilation ( ) ;
2931 _typedefs = new Dictionary < string , CppType > ( ) ;
30- _rootContainerContext = new CppContainerContext ( RootCompilation ) ;
32+ _userRootContainerContext = new CppContainerContext ( RootCompilation )
33+ {
34+ NameContext = "user"
35+ } ;
36+ _systemRootContainerContext = new CppContainerContext ( RootCompilation . System )
37+ {
38+ NameContext = "system"
39+ } ;
3140 }
3241
3342 public bool AutoSquashTypedef { get ; set ; }
@@ -42,15 +51,6 @@ public CppModelBuilder()
4251
4352 public CXChildVisitResult VisitTranslationUnit ( CXCursor cursor , CXCursor parent , void * data )
4453 {
45- _rootContainerContext . Container = RootCompilation ;
46-
47-
48- if ( cursor . Location . IsInSystemHeader )
49- {
50- if ( ! ParseSystemIncludes ) return CXChildVisitResult . CXChildVisit_Continue ;
51-
52- _rootContainerContext . Container = RootCompilation . System ;
53- }
5454 return VisitMember ( cursor , parent , data ) ;
5555 }
5656
@@ -98,7 +98,7 @@ private bool TryGetDeclarationContainer(CXCursor cursor, void* data, out string
9898 typeAsCString = CXUtil . GetCursorDisplayName ( cursor ) ;
9999 }
100100 // Try to workaround anonymous types
101- typeKey = $ "{ typeAsCString } { ( cursor . IsAnonymous ? "/" + cursor . Hash : string . Empty ) } ";
101+ typeKey = $ "{ _rootContainerContext . NameContext } / { typeAsCString } { ( cursor . IsAnonymous ? "/" + cursor . Hash : string . Empty ) } ";
102102 return _containers . TryGetValue ( typeKey , out containerContext ) ;
103103 }
104104
@@ -116,6 +116,11 @@ private CppContainerContext GetDeclarationContainer(CXCursor cursor, void* data)
116116
117117 private CppContainerContext GetOrCreateDeclarationContainer ( CXCursor cursor , void * data )
118118 {
119+ while ( cursor . Kind == CXCursorKind . CXCursor_LinkageSpec )
120+ {
121+ cursor = cursor . SemanticParent ;
122+ }
123+
119124 if ( TryGetDeclarationContainer ( cursor , data , out string typeKey , out var containerContext ) )
120125 {
121126 return containerContext ;
@@ -383,30 +388,54 @@ private CppClass VisitClassDecl(CXCursor cursor, void* data)
383388 private CXChildVisitResult VisitMember ( CXCursor cursor , CXCursor parent , void * data )
384389 {
385390 CppElement element = null ;
391+
392+ // Only set the root container when we know the location
393+ // Otherwise assume that it hasn't changed
394+ // We expect it to be always set
395+ if ( cursor . Location != CXSourceLocation . Null )
396+ {
397+ if ( cursor . Location . IsInSystemHeader )
398+ {
399+ if ( ! ParseSystemIncludes ) return CXChildVisitResult . CXChildVisit_Continue ;
400+
401+ _rootContainerContext = _systemRootContainerContext ;
402+ }
403+ else
404+ {
405+ _rootContainerContext = _userRootContainerContext ;
406+ }
407+ }
408+
409+ if ( _rootContainerContext is null )
410+ {
411+ RootCompilation . Diagnostics . Error ( $ "Unexpected error with cursor location. Cannot determine Root Compilation context.") ;
412+ return CXChildVisitResult . CXChildVisit_Continue ;
413+ }
414+
386415 switch ( cursor . Kind )
387416 {
388417 case CXCursorKind . CXCursor_FieldDecl :
389418 case CXCursorKind . CXCursor_VarDecl :
390- {
391- var containerContext = GetOrCreateDeclarationContainer ( parent , data ) ;
392- element = VisitFieldOrVariable ( containerContext , cursor , data ) ;
393- break ;
394- }
419+ {
420+ var containerContext = GetOrCreateDeclarationContainer ( parent , data ) ;
421+ element = VisitFieldOrVariable ( containerContext , cursor , data ) ;
422+ break ;
423+ }
395424
396425 case CXCursorKind . CXCursor_EnumConstantDecl :
397- {
398- var containerContext = GetOrCreateDeclarationContainer ( parent , data ) ;
399- var cppEnum = ( CppEnum ) containerContext . Container ;
400- var enumItem = new CppEnumItem ( CXUtil . GetCursorSpelling ( cursor ) , cursor . EnumConstantDeclValue ) ;
401- ParseAttributes ( cursor , enumItem , true ) ;
426+ {
427+ var containerContext = GetOrCreateDeclarationContainer ( parent , data ) ;
428+ var cppEnum = ( CppEnum ) containerContext . Container ;
429+ var enumItem = new CppEnumItem ( CXUtil . GetCursorSpelling ( cursor ) , cursor . EnumConstantDeclValue ) ;
430+ ParseAttributes ( cursor , enumItem , true ) ;
402431
403- VisitInitValue ( cursor , data , out var enumItemExpression , out var enumValue ) ;
404- enumItem . ValueExpression = enumItemExpression ;
432+ VisitInitValue ( cursor , data , out var enumItemExpression , out var enumValue ) ;
433+ enumItem . ValueExpression = enumItemExpression ;
405434
406- cppEnum . Items . Add ( enumItem ) ;
407- element = enumItem ;
408- break ;
409- }
435+ cppEnum . Items . Add ( enumItem ) ;
436+ element = enumItem ;
437+ break ;
438+ }
410439
411440 case CXCursorKind . CXCursor_Namespace :
412441 element = VisitNamespace ( cursor , data ) ;
@@ -419,47 +448,48 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
419448 case CXCursorKind . CXCursor_ObjCInterfaceDecl :
420449 case CXCursorKind . CXCursor_ObjCProtocolDecl :
421450 case CXCursorKind . CXCursor_ObjCCategoryDecl :
451+ {
452+ bool isAnonymous = cursor . IsAnonymous ;
453+ var cppClass = VisitClassDecl ( cursor , data ) ;
454+ var containerContext = GetOrCreateDeclarationContainer ( parent , data ) ;
455+ // Empty struct/class/union declaration are considered as fields
456+ if ( isAnonymous )
422457 {
423- bool isAnonymous = cursor . IsAnonymous ;
424- var cppClass = VisitClassDecl ( cursor , data ) ;
425- var containerContext = GetOrCreateDeclarationContainer ( parent , data ) ;
426- // Empty struct/class/union declaration are considered as fields
427- if ( isAnonymous )
458+ cppClass . Name = string . Empty ;
459+ Debug . Assert ( string . IsNullOrEmpty ( cppClass . Name ) ) ;
460+
461+ // We try to recover the offset from the previous field
462+ // Might not be always correct (with alignment rules),
463+ // but not sure how to recover the offset without recalculating the entire offsets
464+ var offset = 0 ;
465+ var cppClassContainer = containerContext . Container as CppClass ;
466+ if ( cppClassContainer is object && cppClassContainer . Fields . Count > 0 )
428467 {
429- cppClass . Name = string . Empty ;
430- Debug . Assert ( string . IsNullOrEmpty ( cppClass . Name ) ) ;
431-
432- // We try to recover the offset from the previous field
433- // Might not be always correct (with alignment rules),
434- // but not sure how to recover the offset without recalculating the entire offsets
435- var offset = 0 ;
436- var cppClassContainer = containerContext . Container as CppClass ;
437- if ( cppClassContainer is object && cppClassContainer . Fields . Count > 0 )
438- {
439- var lastField = cppClassContainer . Fields [ cppClassContainer . Fields . Count - 1 ] ;
440- offset = ( int ) lastField . Offset + lastField . Type . SizeOf ;
441- }
442-
443- // Create an anonymous field for the type
444- var cppField = new CppField ( cppClass , string . Empty )
445- {
446- Visibility = containerContext . CurrentVisibility ,
447- StorageQualifier = GetStorageQualifier ( cursor ) ,
448- IsAnonymous = true ,
449- Offset = offset ,
450- } ;
451- ParseAttributes ( cursor , cppField , true ) ;
452- containerContext . DeclarationContainer . Fields . Add ( cppField ) ;
453- element = cppField ;
468+ var lastField = cppClassContainer . Fields [ cppClassContainer . Fields . Count - 1 ] ;
469+ offset = ( int ) lastField . Offset + lastField . Type . SizeOf ;
454470 }
455- else
471+
472+ // Create an anonymous field for the type
473+ var cppField = new CppField ( cppClass , string . Empty )
456474 {
457- cppClass . Visibility = containerContext . CurrentVisibility ;
458- element = cppClass ;
459- }
460- break ;
475+ Visibility = containerContext . CurrentVisibility ,
476+ StorageQualifier = GetStorageQualifier ( cursor ) ,
477+ IsAnonymous = true ,
478+ Offset = offset ,
479+ } ;
480+ ParseAttributes ( cursor , cppField , true ) ;
481+ containerContext . DeclarationContainer . Fields . Add ( cppField ) ;
482+ element = cppField ;
483+ }
484+ else
485+ {
486+ cppClass . Visibility = containerContext . CurrentVisibility ;
487+ element = cppClass ;
461488 }
462489
490+ break ;
491+ }
492+
463493 case CXCursorKind . CXCursor_EnumDecl :
464494 element = VisitEnumDecl ( cursor , data ) ;
465495 break ;
@@ -495,7 +525,7 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
495525 break ;
496526 case CXCursorKind . CXCursor_UnexposedDecl :
497527 return CXChildVisitResult . CXChildVisit_Recurse ;
498-
528+
499529 case CXCursorKind . CXCursor_ObjCClassRef :
500530 case CXCursorKind . CXCursor_ObjCProtocolRef :
501531 {
@@ -513,6 +543,7 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
513543 cppClass . ObjCImplementedProtocols . Add ( referencedType ) ;
514544 }
515545 }
546+
516547 break ;
517548 }
518549 case CXCursorKind . CXCursor_TypeRef :
@@ -523,43 +554,40 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
523554 var type = GetCppType ( cursor . Referenced , cursor . Type , cursor , data ) ;
524555 genericType . GenericArguments . Add ( type ) ;
525556 }
557+
526558 break ;
527-
528-
559+
560+
529561 case CXCursorKind . CXCursor_CXXBaseSpecifier :
562+ {
563+ var cppClass = ( CppClass ) GetOrCreateDeclarationContainer ( parent , data ) . Container ;
564+ var baseType = GetCppType ( cursor . Type . Declaration , cursor . Type , cursor , data ) ;
565+ var cppBaseType = new CppBaseType ( baseType )
530566 {
531- var cppClass = ( CppClass ) GetOrCreateDeclarationContainer ( parent , data ) . Container ;
532- var baseType = GetCppType ( cursor . Type . Declaration , cursor . Type , cursor , data ) ;
533- var cppBaseType = new CppBaseType ( baseType )
534- {
535- Visibility = GetVisibility ( cursor . CXXAccessSpecifier ) ,
536- IsVirtual = cursor . IsVirtualBase
537- } ;
538- cppClass . BaseTypes . Add ( cppBaseType ) ;
539- break ;
540- }
567+ Visibility = GetVisibility ( cursor . CXXAccessSpecifier ) ,
568+ IsVirtual = cursor . IsVirtualBase
569+ } ;
570+ cppClass . BaseTypes . Add ( cppBaseType ) ;
571+ break ;
572+ }
541573
542574 case CXCursorKind . CXCursor_CXXAccessSpecifier :
543- {
544- var containerContext = GetOrCreateDeclarationContainer ( parent , data ) ;
545- containerContext . CurrentVisibility = GetVisibility ( cursor . CXXAccessSpecifier ) ;
546- }
575+ {
576+ var containerContext = GetOrCreateDeclarationContainer ( parent , data ) ;
577+ containerContext . CurrentVisibility = GetVisibility ( cursor . CXXAccessSpecifier ) ;
578+ }
547579
548580 break ;
549581
550582 case CXCursorKind . CXCursor_MacroDefinition :
551583 element = ParseMacro ( cursor ) ;
552584 break ;
553-
585+
554586 case CXCursorKind . CXCursor_MacroExpansion :
555587 case CXCursorKind . CXCursor_InclusionDirective :
556- case CXCursorKind . CXCursor_FirstRef :
588+ case CXCursorKind . CXCursor_FirstRef :
557589 case CXCursorKind . CXCursor_ObjCIvarDecl :
558590 case CXCursorKind . CXCursor_TemplateTypeParameter :
559- if ( cursor . IsAttribute )
560- {
561- System . Diagnostics . Debugger . Break ( ) ;
562- }
563591 break ;
564592
565593 case CXCursorKind . CXCursor_LinkageSpec :
@@ -572,19 +600,21 @@ private CXChildVisitResult VisitMember(CXCursor cursor, CXCursor parent, void* d
572600 element = VisitProperty ( containerContext , cursor , data ) ;
573601 break ;
574602 }
575-
603+
576604 default :
577605 if ( ! cursor . IsAttribute )
578606 {
579607 WarningUnhandled ( cursor , parent ) ;
580608 }
609+
581610 break ;
582611 }
583612
584613 if ( element != null )
585614 {
586615 bool isForwardDeclaration = ( element is CppClass || element is CppEnum ) && ! cursor . IsDefinition ;
587- if ( ! isForwardDeclaration ) {
616+ if ( ! isForwardDeclaration )
617+ {
588618 AssignSourceSpan ( cursor , element ) ;
589619 }
590620 }
@@ -2271,6 +2301,11 @@ public CppContainerContext(ICppContainer container)
22712301
22722302 public CppVisibility CurrentVisibility ;
22732303
2304+ /// <summary>
2305+ /// Either "system" (include) or user.
2306+ /// </summary>
2307+ public string ? NameContext { get ; init ; }
2308+
22742309 public bool IsChildrenVisited ;
22752310 }
22762311 }
0 commit comments