https://github.com/chaitanyav updated https://github.com/llvm/llvm-project/pull/159698
>From c24df2cedb575c76c89ec5ba2604967e3d3e91c5 Mon Sep 17 00:00:00 2001 From: NagaChaitanya Vellanki <pnag...@protonmail.com> Date: Thu, 18 Sep 2025 20:36:53 -0700 Subject: [PATCH] [clang][ExtractAPI] Fix for nested types are not enabled. Recursively extract nested types. Keep anonymous structs/unions embedded in var declarators Fixes #61477 --- .../clang/ExtractAPI/ExtractAPIVisitor.h | 68 +-- .../ExtractAPI/anonymous_record_no_typedef.c | 24 +- clang/test/ExtractAPI/nested_types.cpp | 290 ++++++++++ clang/test/ExtractAPI/nested_types_deep.cpp | 532 ++++++++++++++++++ 4 files changed, 850 insertions(+), 64 deletions(-) create mode 100644 clang/test/ExtractAPI/nested_types.cpp create mode 100644 clang/test/ExtractAPI/nested_types_deep.cpp diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 9ea664f57f828..5f0b8dfcede62 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -250,27 +250,6 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> { return D.getName().empty() && getTypedefName(&D).empty() && D.isEmbeddedInDeclarator() && !D.isFreeStanding(); } - - void maybeMergeWithAnonymousTag(const DeclaratorDecl &D, - RecordContext *NewRecordContext) { - if (!NewRecordContext) - return; - auto *Tag = D.getType()->getAsTagDecl(); - if (!Tag) { - if (const auto *AT = D.getASTContext().getAsArrayType(D.getType())) { - Tag = AT->getElementType()->getAsTagDecl(); - } - } - SmallString<128> TagUSR; - clang::index::generateUSRForDecl(Tag, TagUSR); - if (auto *Record = llvm::dyn_cast_if_present<TagRecord>( - API.findRecordForUSR(TagUSR))) { - if (Record->IsEmbeddedInVarDeclarator) { - NewRecordContext->stealRecordChain(*Record); - API.removeRecord(Record); - } - } - } }; template <typename Derived> @@ -322,14 +301,10 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) { SubHeading, Access, isInSystemHeader(Decl)); } else { // Add the global variable record to the API set. - auto *NewRecord = API.createRecord<GlobalVariableRecord>( + API.createRecord<GlobalVariableRecord>( USR, Name, createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, Comment, Declaration, SubHeading, isInSystemHeader(Decl)); - - // If this global variable has a non typedef'd anonymous tag type let's - // pretend the type's child records are under us in the hierarchy. - maybeMergeWithAnonymousTag(*Decl, NewRecord); } return true; @@ -565,15 +540,7 @@ bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl( template <typename Derived> bool ExtractAPIVisitorBase<Derived>::TraverseRecordDecl(RecordDecl *Decl) { - bool Ret = Base::TraverseRecordDecl(Decl); - - if (!isEmbeddedInVarDeclarator(*Decl) && Decl->isAnonymousStructOrUnion()) { - SmallString<128> USR; - index::generateUSRForDecl(Decl, USR); - API.removeRecord(USR); - } - - return Ret; + return Base::TraverseRecordDecl(Decl); } template <typename Derived> @@ -620,13 +587,7 @@ template <typename Derived> bool ExtractAPIVisitorBase<Derived>::TraverseCXXRecordDecl( CXXRecordDecl *Decl) { bool Ret = Base::TraverseCXXRecordDecl(Decl); - - if (!isEmbeddedInVarDeclarator(*Decl) && Decl->isAnonymousStructOrUnion()) { - SmallString<128> USR; - index::generateUSRForDecl(Decl, USR); - API.removeRecord(USR); - } - + // Keep anonymous structs in the hierarchy to preserve path components return Ret; } @@ -643,6 +604,11 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl( SmallString<128> USR; index::generateUSRForDecl(Decl, USR); + + if (API.findRecordForUSR(USR)) { + return true; + } + PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(Decl->getLocation()); DocComment Comment; @@ -679,6 +645,13 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl( Record->KindForDisplay = getKindForDisplay(Decl); Record->Bases = getBases(Decl); + // Visit nested records + for (const auto *NestedDecl : Decl->decls()) { + if (auto *NestedRecord = dyn_cast<CXXRecordDecl>(NestedDecl)) { + VisitCXXRecordDecl(NestedRecord); + } + } + return true; } @@ -1320,31 +1293,26 @@ bool ExtractAPIVisitorBase<Derived>::VisitFieldDecl(const FieldDecl *Decl) { DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - RecordContext *NewRecord = nullptr; if (isa<CXXRecordDecl>(Decl->getDeclContext())) { AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Decl); - NewRecord = API.createRecord<CXXFieldRecord>( + API.createRecord<CXXFieldRecord>( USR, Name, createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, Access, isInSystemHeader(Decl)); } else if (auto *RD = dyn_cast<RecordDecl>(Decl->getDeclContext())) { if (RD->isUnion()) - NewRecord = API.createRecord<UnionFieldRecord>( + API.createRecord<UnionFieldRecord>( USR, Name, createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, isInSystemHeader(Decl)); else - NewRecord = API.createRecord<StructFieldRecord>( + API.createRecord<StructFieldRecord>( USR, Name, createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, isInSystemHeader(Decl)); } - // If this field has a non typedef'd anonymous tag type let's pretend the - // type's child records are under us in the hierarchy. - maybeMergeWithAnonymousTag(*Decl, NewRecord); - return true; } diff --git a/clang/test/ExtractAPI/anonymous_record_no_typedef.c b/clang/test/ExtractAPI/anonymous_record_no_typedef.c index d278cbb8ec348..f6d8cb7b0f3d4 100644 --- a/clang/test/ExtractAPI/anonymous_record_no_typedef.c +++ b/clang/test/ExtractAPI/anonymous_record_no_typedef.c @@ -43,19 +43,19 @@ struct { char *prefix; char *content; } global; // GLOBAL-NEXT: "global" // GLOBAL-NEXT:] -// PREFIX: "!testRelLabel": "memberOf $ c:@S@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@prefix $ c:@global" +// PREFIX: "!testRelLabel": "memberOf $ c:@S@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@prefix $ c:@S@anonymous_record_no_typedef.c@{{[0-9]+}}" // PREFIX-LABEL: "!testLabel": "c:@S@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@prefix" // PREFIX: "title": "prefix" // PREFIX: "pathComponents": [ -// PREFIX-NEXT: "global", +// PREFIX-NEXT: "", // PREFIX-NEXT: "prefix" // PREFIX-NEXT: ] -// CONTENT: "!testRelLabel": "memberOf $ c:@S@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@content $ c:@global" +// CONTENT: "!testRelLabel": "memberOf $ c:@S@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@content $ c:@S@anonymous_record_no_typedef.c@{{[0-9]+}}" // CONTENT-LABEL: "!testLabel": "c:@S@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@content" // CONTENT: "title": "content" // CONTENT: "pathComponents": [ -// CONTENT-NEXT: "global", +// CONTENT-NEXT: "", // CONTENT-NEXT: "content" // CONTENT-NEXT: ] @@ -139,21 +139,21 @@ struct Vehicle { // INFORMATION: "text": "The information about the vehicle." // INFORMATION: "title": "information" - // WHEELS: "!testRelLabel": "memberOf $ c:@S@Vehicle@U@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@wheels $ c:@S@Vehicle@FI@information" + // WHEELS: "!testRelLabel": "memberOf $ c:@S@Vehicle@U@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@wheels $ c:@S@Vehicle@U@anonymous_record_no_typedef.c@{{[0-9]+}}" // WHEELS-LABEL: "!testLabel": "c:@S@Vehicle@U@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@wheels" // WHEELS: "title": "wheels" // WHEELS: "pathComponents": [ // WHEELS-NEXT: "Vehicle", - // WHEELS-NEXT: "information", + // WHEELS-NEXT: "", // WHEELS-NEXT: "wheels" // WHEELS-NEXT: ] - // NAME: "!testRelLabel": "memberOf $ c:@S@Vehicle@U@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@name $ c:@S@Vehicle@FI@information" + // NAME: "!testRelLabel": "memberOf $ c:@S@Vehicle@U@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@name $ c:@S@Vehicle@U@anonymous_record_no_typedef.c@{{[0-9]+}}" // NAME-LABEL: "!testLabel": "c:@S@Vehicle@U@anonymous_record_no_typedef.c@{{[0-9]+}}@FI@name" // NAME: "title": "name" // NAME: "pathComponents": [ // NAME-NEXT: "Vehicle", - // NAME-NEXT: "information", + // NAME-NEXT: "", // NAME-NEXT: "name" // NAME-NEXT: ] }; @@ -188,11 +188,9 @@ union Vector { float Data[2]; }; // VEC-DAG: "!testRelLabel": "memberOf $ c:@U@Vector@FI@Data $ c:@U@Vector" -// VEC-DAG: "!testRelLabel": "memberOf $ c:@U@Vector@Sa@FI@X $ c:@U@Vector" -// VEC-DAG: "!testRelLabel": "memberOf $ c:@U@Vector@Sa@FI@Y $ c:@U@Vector" +// VEC-DAG: "!testRelLabel": "memberOf $ c:@U@Vector@Sa@FI@X $ c:@U@Vector@Sa" +// VEC-DAG: "!testRelLabel": "memberOf $ c:@U@Vector@Sa@FI@Y $ c:@U@Vector@Sa" -// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix MYSTRUCT -// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix MYSTRUCT // RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix COUNTS // RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix COUNTS struct MyStruct { @@ -200,8 +198,6 @@ struct MyStruct { int count; } counts[1]; }; -// MYSTRUCT-NOT: "spelling": "" -// MYSTRUCT-NOT: "title": "" // COUNTS-LABEL: "!testLabel": "c:@S@MyStruct@FI@counts" // COUNTS: "declarationFragments": [ diff --git a/clang/test/ExtractAPI/nested_types.cpp b/clang/test/ExtractAPI/nested_types.cpp new file mode 100644 index 0000000000000..88d709a2c0772 --- /dev/null +++ b/clang/test/ExtractAPI/nested_types.cpp @@ -0,0 +1,290 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ +// RUN: %t/reference.output.json.in >> %t/reference.output.json +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ +// RUN: -x c++-header %t/input.h -o %t/output.json -verify + +// Generator version is not consistent across test runs, normalize it. +// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ +// RUN: %t/output.json >> %t/output-normalized.json +// RUN: diff %t/reference.output.json %t/output-normalized.json + +//--- input.h +struct MyStruct { + struct { + int count; + } counts[1]; +}; + +/// expected-no-diagnostics + +//--- reference.output.json.in +{ + "metadata": { + "formatVersion": { + "major": 0, + "minor": 5, + "patch": 3 + }, + "generator": "?" + }, + "module": { + "name": "", + "platform": { + "architecture": "arm64", + "operatingSystem": { + "minimumVersion": { + "major": 11, + "minor": 0, + "patch": 0 + }, + "name": "macosx" + }, + "vendor": "apple" + } + }, + "relationships": [ + { + "kind": "memberOf", + "source": "c:@S@MyStruct@S@input.h@22", + "target": "c:@S@MyStruct", + "targetFallback": "MyStruct" + }, + { + "kind": "memberOf", + "source": "c:@S@MyStruct@S@input.h@22@FI@count", + "target": "c:@S@MyStruct@S@input.h@22", + "targetFallback": "" + }, + { + "kind": "memberOf", + "source": "c:@S@MyStruct@FI@counts", + "target": "c:@S@MyStruct", + "targetFallback": "MyStruct" + } + ], + "symbols": [ + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "struct" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "MyStruct" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@MyStruct" + }, + "kind": { + "displayName": "Structure", + "identifier": "c++.struct" + }, + "location": { + "position": { + "character": 7, + "line": 0 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "MyStruct" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "MyStruct" + } + ], + "title": "MyStruct" + }, + "pathComponents": [ + "MyStruct" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "struct" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@MyStruct@S@input.h@22" + }, + "kind": { + "displayName": "Structure", + "identifier": "c++.struct" + }, + "location": { + "position": { + "character": 4, + "line": 1 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "" + } + ], + "title": "" + }, + "pathComponents": [ + "MyStruct", + "" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:I", + "spelling": "int" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "count" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@MyStruct@S@input.h@22@FI@count" + }, + "kind": { + "displayName": "Instance Property", + "identifier": "c++.property" + }, + "location": { + "position": { + "character": 12, + "line": 2 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "count" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "count" + } + ], + "title": "count" + }, + "pathComponents": [ + "MyStruct", + "", + "count" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "struct" + }, + { + "kind": "text", + "spelling": " { ... } " + }, + { + "kind": "identifier", + "spelling": "counts" + }, + { + "kind": "text", + "spelling": "[" + }, + { + "kind": "number", + "spelling": "1" + }, + { + "kind": "text", + "spelling": "];" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@MyStruct@FI@counts" + }, + "kind": { + "displayName": "Instance Property", + "identifier": "c++.property" + }, + "location": { + "position": { + "character": 6, + "line": 3 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "counts" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "counts" + } + ], + "title": "counts" + }, + "pathComponents": [ + "MyStruct", + "counts" + ] + } + ] +} diff --git a/clang/test/ExtractAPI/nested_types_deep.cpp b/clang/test/ExtractAPI/nested_types_deep.cpp new file mode 100644 index 0000000000000..4ef85734fe7c2 --- /dev/null +++ b/clang/test/ExtractAPI/nested_types_deep.cpp @@ -0,0 +1,532 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t +// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ +// RUN: %t/reference.output.json.in >> %t/reference.output.json +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-macosx \ +// RUN: -x c++-header %t/input.h -o %t/output.json -verify + +// Generator version is not consistent across test runs, normalize it. +// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ +// RUN: %t/output.json >> %t/output-normalized.json +// RUN: diff %t/reference.output.json %t/output-normalized.json + +//--- input.h +class Outer { + class Inner1 { + class DeeplyNested { + int value; + }; + }; + + struct Inner2 { + enum Status { READY, PENDING }; + }; +}; + +/// expected-no-diagnostics + +//--- reference.output.json.in +{ + "metadata": { + "formatVersion": { + "major": 0, + "minor": 5, + "patch": 3 + }, + "generator": "?" + }, + "module": { + "name": "", + "platform": { + "architecture": "arm64", + "operatingSystem": { + "minimumVersion": { + "major": 11, + "minor": 0, + "patch": 0 + }, + "name": "macosx" + }, + "vendor": "apple" + } + }, + "relationships": [ + { + "kind": "memberOf", + "source": "c:@S@Outer@S@Inner1", + "target": "c:@S@Outer", + "targetFallback": "Outer" + }, + { + "kind": "memberOf", + "source": "c:@S@Outer@S@Inner1@S@DeeplyNested", + "target": "c:@S@Outer@S@Inner1", + "targetFallback": "Inner1" + }, + { + "kind": "memberOf", + "source": "c:@S@Outer@S@Inner1@S@DeeplyNested@FI@value", + "target": "c:@S@Outer@S@Inner1@S@DeeplyNested", + "targetFallback": "DeeplyNested" + }, + { + "kind": "memberOf", + "source": "c:@S@Outer@S@Inner2", + "target": "c:@S@Outer", + "targetFallback": "Outer" + }, + { + "kind": "memberOf", + "source": "c:@S@Outer@S@Inner2@E@Status", + "target": "c:@S@Outer@S@Inner2", + "targetFallback": "Inner2" + }, + { + "kind": "memberOf", + "source": "c:@S@Outer@S@Inner2@E@Status@READY", + "target": "c:@S@Outer@S@Inner2@E@Status", + "targetFallback": "Status" + }, + { + "kind": "memberOf", + "source": "c:@S@Outer@S@Inner2@E@Status@PENDING", + "target": "c:@S@Outer@S@Inner2@E@Status", + "targetFallback": "Status" + } + ], + "symbols": [ + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "class" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Outer" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@Outer" + }, + "kind": { + "displayName": "Class", + "identifier": "c++.class" + }, + "location": { + "position": { + "character": 6, + "line": 0 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Outer" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Outer" + } + ], + "title": "Outer" + }, + "pathComponents": [ + "Outer" + ] + }, + { + "accessLevel": "private", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "class" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Inner1" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@Outer@S@Inner1" + }, + "kind": { + "displayName": "Class", + "identifier": "c++.class" + }, + "location": { + "position": { + "character": 8, + "line": 1 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Inner1" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Inner1" + } + ], + "title": "Inner1" + }, + "pathComponents": [ + "Outer", + "Inner1" + ] + }, + { + "accessLevel": "private", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "class" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "DeeplyNested" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@Outer@S@Inner1@S@DeeplyNested" + }, + "kind": { + "displayName": "Class", + "identifier": "c++.class" + }, + "location": { + "position": { + "character": 10, + "line": 2 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "DeeplyNested" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "DeeplyNested" + } + ], + "title": "DeeplyNested" + }, + "pathComponents": [ + "Outer", + "Inner1", + "DeeplyNested" + ] + }, + { + "accessLevel": "private", + "declarationFragments": [ + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:I", + "spelling": "int" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "value" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@Outer@S@Inner1@S@DeeplyNested@FI@value" + }, + "kind": { + "displayName": "Instance Property", + "identifier": "c++.property" + }, + "location": { + "position": { + "character": 10, + "line": 3 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "value" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "value" + } + ], + "title": "value" + }, + "pathComponents": [ + "Outer", + "Inner1", + "DeeplyNested", + "value" + ] + }, + { + "accessLevel": "private", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "struct" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Inner2" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@Outer@S@Inner2" + }, + "kind": { + "displayName": "Structure", + "identifier": "c++.struct" + }, + "location": { + "position": { + "character": 9, + "line": 7 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Inner2" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Inner2" + } + ], + "title": "Inner2" + }, + "pathComponents": [ + "Outer", + "Inner2" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "keyword", + "spelling": "enum" + }, + { + "kind": "text", + "spelling": " " + }, + { + "kind": "identifier", + "spelling": "Status" + }, + { + "kind": "text", + "spelling": " : " + }, + { + "kind": "typeIdentifier", + "preciseIdentifier": "c:i", + "spelling": "unsigned int" + }, + { + "kind": "text", + "spelling": ";" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@Outer@S@Inner2@E@Status" + }, + "kind": { + "displayName": "Enumeration", + "identifier": "c++.enum" + }, + "location": { + "position": { + "character": 9, + "line": 8 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "Status" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "Status" + } + ], + "title": "Status" + }, + "pathComponents": [ + "Outer", + "Inner2", + "Status" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "READY" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@Outer@S@Inner2@E@Status@READY" + }, + "kind": { + "displayName": "Enumeration Case", + "identifier": "c++.enum.case" + }, + "location": { + "position": { + "character": 18, + "line": 8 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "READY" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "READY" + } + ], + "title": "READY" + }, + "pathComponents": [ + "Outer", + "Inner2", + "Status", + "READY" + ] + }, + { + "accessLevel": "public", + "declarationFragments": [ + { + "kind": "identifier", + "spelling": "PENDING" + } + ], + "identifier": { + "interfaceLanguage": "c++", + "precise": "c:@S@Outer@S@Inner2@E@Status@PENDING" + }, + "kind": { + "displayName": "Enumeration Case", + "identifier": "c++.enum.case" + }, + "location": { + "position": { + "character": 25, + "line": 8 + }, + "uri": "file://INPUT_DIR/input.h" + }, + "names": { + "navigator": [ + { + "kind": "identifier", + "spelling": "PENDING" + } + ], + "subHeading": [ + { + "kind": "identifier", + "spelling": "PENDING" + } + ], + "title": "PENDING" + }, + "pathComponents": [ + "Outer", + "Inner2", + "Status", + "PENDING" + ] + } + ] +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits