[clang] [clang][ExtractAPI] Fix up casting from CXXClassRecord (PR #110983)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/110983 `RecordRecord::classOfKind` and `TagRecord::classofKind` didn't correctly capture `RK_CXXClass` and derived variants, e.g. `RK_ClassTemplate`. This materialized by anonymous C++ tag types not being correctly detected when they need to be merged with another record. >From 0d94b2e151a3d2abde1139841100aef2e141ff94 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 3 Oct 2024 11:52:34 +0100 Subject: [PATCH] [clang][ExtractAPI] Fix up casting from CXXClassRecord `RecordRecord::classOfKind` and `TagRecord::classofKind` didn't correctly capture `RK_CXXClass` and derived variants, e.g. `RK_ClassTemplate`. This materialized by anonymous C++ tag types not being correctly detected when they need to be merged with another record. --- clang/include/clang/ExtractAPI/API.h | 37 +++- .../ExtractAPI/anonymous_record_no_typedef.c | 44 +-- .../ExtractAPI/typedef_anonymous_record.c | 27 +++- 3 files changed, 82 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index 4f34fcc575e807..c30e6fac66d6ba 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -26,6 +26,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" #include "llvm/TargetParser/Triple.h" #include #include @@ -615,7 +616,24 @@ struct TagRecord : APIRecord, RecordContext { return classofKind(Record->getKind()); } static bool classofKind(RecordKind K) { -return K == RK_Struct || K == RK_Union || K == RK_Enum; +switch (K) { +case RK_Enum: + LLVM_FALLTHROUGH; +case RK_Struct: + LLVM_FALLTHROUGH; +case RK_Union: + LLVM_FALLTHROUGH; +case RK_CXXClass: + LLVM_FALLTHROUGH; +case RK_ClassTemplate: + LLVM_FALLTHROUGH; +case RK_ClassTemplateSpecialization: + LLVM_FALLTHROUGH; +case RK_ClassTemplatePartialSpecialization: + return true; +default: + return false; +} } bool IsEmbeddedInVarDeclarator; @@ -684,7 +702,22 @@ struct RecordRecord : TagRecord { return classofKind(Record->getKind()); } static bool classofKind(RecordKind K) { -return K == RK_Struct || K == RK_Union; +switch (K) { +case RK_Struct: + LLVM_FALLTHROUGH; +case RK_Union: + LLVM_FALLTHROUGH; +case RK_CXXClass: + LLVM_FALLTHROUGH; +case RK_ClassTemplate: + LLVM_FALLTHROUGH; +case RK_ClassTemplateSpecialization: + LLVM_FALLTHROUGH; +case RK_ClassTemplatePartialSpecialization: + return true; +default: + return false; +} } bool isAnonymousWithNoTypedef() { return Name.empty(); } diff --git a/clang/test/ExtractAPI/anonymous_record_no_typedef.c b/clang/test/ExtractAPI/anonymous_record_no_typedef.c index 064c223ad56e73..c0c76ef1f06b57 100644 --- a/clang/test/ExtractAPI/anonymous_record_no_typedef.c +++ b/clang/test/ExtractAPI/anonymous_record_no_typedef.c @@ -1,11 +1,18 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ // RUN: -triple arm64-apple-macosx -isystem %S -fretain-comments-from-system-headers \ -// RUN: -x c-header %s -o %t/output.symbols.json -verify +// RUN: -x c-header %s -o %t/output-c.symbols.json -verify +// +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -isystem %S -fretain-comments-from-system-headers \ +// RUN: -x c++-header %s -o %t/output-cxx.symbols.json -verify -// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix GLOBAL -// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix PREFIX -// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix CONTENT +// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix GLOBAL +// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix PREFIX +// RUN: FileCheck %s --input-file %t/output-c.symbols.json --check-prefix CONTENT +// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix GLOBAL +// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix PREFIX +// RUN: FileCheck %s --input-file %t/output-cxx.symbols.json --check-prefix CONTENT /// A global variable with an anonymous struct type. struct { char *prefix; char *content; } global; // GLOBAL-LABEL: "!testLabel": "c:@global" @@ -30,7 +37,7 @@ struct { char *prefix; char *content; } global; // GLOBAL: "text": "A global variable with an anonymous struct type." // GLOBAL: "kind": { // GLOBAL-NEXT: "displayName": "Global Variable", -// GLOBAL-NEXT: "identifier": "c.var" +// GLOBAL-NEXT: "identifier": "c{{(\+\+)?}}.var" // GLOBAL: "title": "global" // GLOBAL:
[clang] [clang][ExtractAPI] Generate subheading for typedef'd anonymous types (PR #110689)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/110689 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Generate subheading for typedef'd anonymous types (PR #110689)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/110689 >From 30e06bed5b8ba378b2b43f0706617f6978f4be6c Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 1 Oct 2024 16:29:30 +0100 Subject: [PATCH] [clang][ExtractAPI] Generate subheading for typedef'd anonymous types When an anonymous type has a typedef we normally use the typedef's name in places where we expect a named identifier in the symbol graph. This extends this logic to apply to subheadings. rdar://136690614 --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 3 ++ .../ExtractAPI/typedef_anonymous_record.c | 32 +-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 9cb45c8fbf9cbc..66c03863293c2f 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1621,6 +1621,9 @@ DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { cast(Decl)->isOverloadedOperator()) { Fragments.append(Decl->getNameAsString(), DeclarationFragments::FragmentKind::Identifier); + } else if (isa(Decl) && + cast(Decl)->getTypedefNameForAnonDecl()) { +return getSubHeading(cast(Decl)->getTypedefNameForAnonDecl()); } else if (Decl->getIdentifier()) { Fragments.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); diff --git a/clang/test/ExtractAPI/typedef_anonymous_record.c b/clang/test/ExtractAPI/typedef_anonymous_record.c index 9c03e9e190ed6b..8e298f8d9ce829 100644 --- a/clang/test/ExtractAPI/typedef_anonymous_record.c +++ b/clang/test/ExtractAPI/typedef_anonymous_record.c @@ -35,7 +35,21 @@ typedef struct { } MyStruct; // MYSTRUCT: "kind": { // MYSTRUCT-NEXT: "displayName": "Structure", // MYSTRUCT-NEXT: "identifier": "c.struct" -// MYSTRUCT: "title": "MyStruct" +// MYSTRUCT: "names": { +// MYSTRUCT-NEXT:"navigator": [ +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT:"kind": "identifier", +// MYSTRUCT-NEXT:"spelling": "MyStruct" +// MYSTRUCT-NEXT: } +// MYSTRUCT-NEXT:], +// MYSTRUCT-NEXT:"subHeading": [ +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT:"kind": "identifier", +// MYSTRUCT-NEXT:"spelling": "MyStruct" +// MYSTRUCT-NEXT: } +// MYSTRUCT-NEXT:], +// MYSTRUCT-NEXT:"title": "MyStruct" +// MYSTRUCT-NEXT: }, // MYSTRUCT: "pathComponents": [ // MYSTRUCT-NEXT:"MyStruct" // MYSTRUCT-NEXT: ] @@ -111,7 +125,21 @@ typedef enum { Case } MyEnum; // MYENUM: "kind": { // MYENUM-NEXT: "displayName": "Enumeration", // MYENUM-NEXT: "identifier": "c.enum" -// MYENUM: "title": "MyEnum" +// MYENUM: "names": { +// MYENUM-NEXT:"navigator": [ +// MYENUM-NEXT: { +// MYENUM-NEXT:"kind": "identifier", +// MYENUM-NEXT:"spelling": "MyEnum" +// MYENUM-NEXT: } +// MYENUM-NEXT:], +// MYENUM-NEXT:"subHeading": [ +// MYENUM-NEXT: { +// MYENUM-NEXT:"kind": "identifier", +// MYENUM-NEXT:"spelling": "MyEnum" +// MYENUM-NEXT: } +// MYENUM-NEXT:], +// MYENUM-NEXT:"title": "MyEnum" +// MYENUM-NEXT: }, // CASE-LABEL: "!testLabel": "c:@EA@MyEnum@Case" // CASE: "pathComponents": [ ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Generate subheading for typedef'd anonymous types (PR #110689)
@@ -1621,6 +1621,9 @@ DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { cast(Decl)->isOverloadedOperator()) { Fragments.append(Decl->getNameAsString(), DeclarationFragments::FragmentKind::Identifier); + } else if (dyn_cast(Decl) && daniel-grumberg wrote: absolutely https://github.com/llvm/llvm-project/pull/110689 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Generate subheading for typedef'd anonymous types (PR #110689)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/110689 When an anonymous type has a typedef we normally use the typedef's name in places where we expect a named identifier in the symbol graph. This extends this logic to apply to subheadings. rdar://136690614 >From 03b790809bbf3d59d031ff99886ac015c7f0864f Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 1 Oct 2024 16:29:30 +0100 Subject: [PATCH] [clang][ExtractAPI] Generate subheading for typedef'd anonymous types When an anonymous type has a typedef we normally use the typedef's name in places where we expect a named identifier in the symbol graph. This extends this logic to apply to subheadings. rdar://136690614 --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 3 ++ .../ExtractAPI/typedef_anonymous_record.c | 32 +-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 9cb45c8fbf9cbc..f2d4c905664560 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1621,6 +1621,9 @@ DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) { cast(Decl)->isOverloadedOperator()) { Fragments.append(Decl->getNameAsString(), DeclarationFragments::FragmentKind::Identifier); + } else if (dyn_cast(Decl) && + cast(Decl)->getTypedefNameForAnonDecl()) { +return getSubHeading(cast(Decl)->getTypedefNameForAnonDecl()); } else if (Decl->getIdentifier()) { Fragments.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier); diff --git a/clang/test/ExtractAPI/typedef_anonymous_record.c b/clang/test/ExtractAPI/typedef_anonymous_record.c index 9c03e9e190ed6b..8e298f8d9ce829 100644 --- a/clang/test/ExtractAPI/typedef_anonymous_record.c +++ b/clang/test/ExtractAPI/typedef_anonymous_record.c @@ -35,7 +35,21 @@ typedef struct { } MyStruct; // MYSTRUCT: "kind": { // MYSTRUCT-NEXT: "displayName": "Structure", // MYSTRUCT-NEXT: "identifier": "c.struct" -// MYSTRUCT: "title": "MyStruct" +// MYSTRUCT: "names": { +// MYSTRUCT-NEXT:"navigator": [ +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT:"kind": "identifier", +// MYSTRUCT-NEXT:"spelling": "MyStruct" +// MYSTRUCT-NEXT: } +// MYSTRUCT-NEXT:], +// MYSTRUCT-NEXT:"subHeading": [ +// MYSTRUCT-NEXT: { +// MYSTRUCT-NEXT:"kind": "identifier", +// MYSTRUCT-NEXT:"spelling": "MyStruct" +// MYSTRUCT-NEXT: } +// MYSTRUCT-NEXT:], +// MYSTRUCT-NEXT:"title": "MyStruct" +// MYSTRUCT-NEXT: }, // MYSTRUCT: "pathComponents": [ // MYSTRUCT-NEXT:"MyStruct" // MYSTRUCT-NEXT: ] @@ -111,7 +125,21 @@ typedef enum { Case } MyEnum; // MYENUM: "kind": { // MYENUM-NEXT: "displayName": "Enumeration", // MYENUM-NEXT: "identifier": "c.enum" -// MYENUM: "title": "MyEnum" +// MYENUM: "names": { +// MYENUM-NEXT:"navigator": [ +// MYENUM-NEXT: { +// MYENUM-NEXT:"kind": "identifier", +// MYENUM-NEXT:"spelling": "MyEnum" +// MYENUM-NEXT: } +// MYENUM-NEXT:], +// MYENUM-NEXT:"subHeading": [ +// MYENUM-NEXT: { +// MYENUM-NEXT:"kind": "identifier", +// MYENUM-NEXT:"spelling": "MyEnum" +// MYENUM-NEXT: } +// MYENUM-NEXT:], +// MYENUM-NEXT:"title": "MyEnum" +// MYENUM-NEXT: }, // CASE-LABEL: "!testLabel": "c:@EA@MyEnum@Case" // CASE: "pathComponents": [ ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Handle AttributedType fragments transparently (PR #107262)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/107262 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Handle AttributedType fragments transparently (PR #107262)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/107262 >From 17a956e118879df9ce1431c41f580108b92b6784 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 3 Sep 2024 16:27:36 +0100 Subject: [PATCH] [clang][ExtractAPI] Handle AttributedType fragments transparently rdar://131958623 --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 13 ++ clang/test/ExtractAPI/attributed-typedef.m| 24 +++ 2 files changed, 37 insertions(+) create mode 100644 clang/test/ExtractAPI/attributed-typedef.m diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index d77bb1d424f7cf..06ce5ed6a64756 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -276,6 +276,19 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( DeclarationFragments Fragments; + if (const MacroQualifiedType *MQT = dyn_cast(T)) { +Fragments.append( +getFragmentsForType(MQT->getUnderlyingType(), Context, After)); +return Fragments; + } + + if (const AttributedType *AT = dyn_cast(T)) { +// FIXME: Serialize Attributes correctly +Fragments.append( +getFragmentsForType(AT->getModifiedType(), Context, After)); +return Fragments; + } + // An ElaboratedType is a sugar for types that are referred to using an // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a // qualified name, e.g., `N::M::type`, or both. diff --git a/clang/test/ExtractAPI/attributed-typedef.m b/clang/test/ExtractAPI/attributed-typedef.m new file mode 100644 index 00..c948c873ab759c --- /dev/null +++ b/clang/test/ExtractAPI/attributed-typedef.m @@ -0,0 +1,24 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json + +_Pragma("clang assume_nonnull begin") + +struct Foo { int a; }; +typedef struct Foo *Bar; +// RUN: FileCheck %s -input-file %t/output.symbols.json --check-prefix FUNC +void func(Bar b); +// FUNC-LABEL: "!testLabel": "c:@F@func", +// CHECK-NOT: Foo +// CHECK: "pathComponents" + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix THING +#define SWIFT_NAME(_name) __attribute__((swift_name(#_name))) +extern Bar const thing SWIFT_NAME(swiftThing); +// THING-LABEL: "!testLabel": "c:@thing" +// THING-NOT: Foo +// THING: "pathComponents" + +_Pragma("clang assume_nonnull end") + +// expected-no-diagnostics ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Handle AttributedType fragments transparently (PR #107262)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/107262 rdar://131958623 >From 71011c910b218c4817872dee91499e60bd771e07 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 3 Sep 2024 16:27:36 +0100 Subject: [PATCH] [clang][ExtractAPI] Handle AttributedType fragments transparently rdar://131958623 --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 11 + clang/test/ExtractAPI/attributed-typedef.m| 24 +++ 2 files changed, 35 insertions(+) create mode 100644 clang/test/ExtractAPI/attributed-typedef.m diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index d77bb1d424f7cf..a95ab06534b737 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -276,6 +276,17 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( DeclarationFragments Fragments; + if (const MacroQualifiedType *MQT = dyn_cast(T)) { +Fragments.append(getFragmentsForType(MQT->getUnderlyingType(), Context, After)); +return Fragments; + } + + if (const AttributedType *AT = dyn_cast(T)) { +// FIXME: Serialize Attributes correctly +Fragments.append(getFragmentsForType(AT->getModifiedType(), Context, After)); +return Fragments; + } + // An ElaboratedType is a sugar for types that are referred to using an // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a // qualified name, e.g., `N::M::type`, or both. diff --git a/clang/test/ExtractAPI/attributed-typedef.m b/clang/test/ExtractAPI/attributed-typedef.m new file mode 100644 index 00..c948c873ab759c --- /dev/null +++ b/clang/test/ExtractAPI/attributed-typedef.m @@ -0,0 +1,24 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -x objective-c-header %s -o %t/output.symbols.json + +_Pragma("clang assume_nonnull begin") + +struct Foo { int a; }; +typedef struct Foo *Bar; +// RUN: FileCheck %s -input-file %t/output.symbols.json --check-prefix FUNC +void func(Bar b); +// FUNC-LABEL: "!testLabel": "c:@F@func", +// CHECK-NOT: Foo +// CHECK: "pathComponents" + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix THING +#define SWIFT_NAME(_name) __attribute__((swift_name(#_name))) +extern Bar const thing SWIFT_NAME(swiftThing); +// THING-LABEL: "!testLabel": "c:@thing" +// THING-NOT: Foo +// THING: "pathComponents" + +_Pragma("clang assume_nonnull end") + +// expected-no-diagnostics ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Remove erroneous module name check in MacroCallbacks (PR #107059)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/107059 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Remove erroneous module name check in MacroCallbacks (PR #107059)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/107059 rdar://135044923 >From caf560529093f80b5b6e6220ec19e244f57779d3 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 2 Sep 2024 18:47:40 +0100 Subject: [PATCH] [clang][ExtractAPI] Remove erroneous module name check in MacroCallbacks rdar://135044923 --- clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index 0adc23280fd6c0..75c2dec22400b9 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -350,7 +350,7 @@ class APIMacroCallback : public MacroCallback { bool shouldMacroBeIncluded(const SourceLocation &MacroLoc, StringRef ModuleName) override { // Do not include macros from external files -return LCF(MacroLoc) || API.ProductName == ModuleName; +return LCF(MacroLoc); } private: ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix iteration order of TopLevelRecords (PR #106411)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/106411 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix iteration order of TopLevelRecords (PR #106411)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/106411 Fixes #106355 >From 5b47537dd49e79e102f7a809b434c18086274b4b Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Wed, 28 Aug 2024 17:03:22 +0100 Subject: [PATCH] [clang][ExtractAPI] Fix iteration order of TopLevelRecords --- clang/include/clang/ExtractAPI/API.h | 11 +-- clang/lib/ExtractAPI/API.cpp | 6 -- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index 188e35b72117b5..4f34fcc575e807 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -23,7 +23,7 @@ #include "clang/AST/RawCommentList.h" #include "clang/Basic/SourceLocation.h" #include "clang/ExtractAPI/DeclarationFragments.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" #include "llvm/TargetParser/Triple.h" @@ -1420,9 +1420,8 @@ class APISet { typename std::enable_if_t, RecordTy> * createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs); - auto getTopLevelRecords() const { -return llvm::iterator_range( -TopLevelRecords); + ArrayRef getTopLevelRecords() const { +return TopLevelRecords; } void removeRecord(StringRef USR); @@ -1455,7 +1454,7 @@ class APISet { // lives in the BumpPtrAllocator. using APIRecordStoredPtr = std::unique_ptr; llvm::DenseMap USRBasedLookupTable; - llvm::SmallPtrSet TopLevelRecords; + llvm::SmallVector TopLevelRecords; public: const std::string ProductName; @@ -1481,7 +1480,7 @@ APISet::createRecord(StringRef USR, StringRef Name, dyn_cast_if_present(Record->Parent.Record)) ParentContext->addToRecordChain(Record); else - TopLevelRecords.insert(Record); + TopLevelRecords.push_back(Record); } else { Record = dyn_cast(Result.first->second.get()); } diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp index 9dbc023885c37f..a6ca0ae8d0d51d 100644 --- a/clang/lib/ExtractAPI/API.cpp +++ b/clang/lib/ExtractAPI/API.cpp @@ -150,11 +150,13 @@ void APISet::removeRecord(StringRef USR) { if (auto *RecordAsCtx = llvm::dyn_cast(Record)) ParentCtx->stealRecordChain(*RecordAsCtx); } else { - TopLevelRecords.erase(Record); + auto *It = llvm::find(TopLevelRecords, Record); + if (It != TopLevelRecords.end()) +TopLevelRecords.erase(It); if (auto *RecordAsCtx = llvm::dyn_cast(Record)) { for (const auto *Child = RecordAsCtx->First; Child != nullptr; Child = Child->getNextInContext()) - TopLevelRecords.insert(Child); + TopLevelRecords.push_back(Child); } } USRBasedLookupTable.erase(Result); ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix quirks in interaction with submodules (PR #105868)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/105868 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix quirks in interaction with submodules (PR #105868)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/105868 >From b687c9512b748ee593eedd5e06d04d2a40197ec3 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Fri, 23 Aug 2024 10:02:42 +0100 Subject: [PATCH 1/5] [clang][ExtractAPI] Use top level module name for tracking which module a symbol came from rdar://123020565 --- clang/include/clang/ExtractAPI/ExtractAPIVisitor.h | 2 +- clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 67659f5a25037c..b09b8b44d9abaa 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -213,7 +213,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { StringRef getOwningModuleName(const Decl &D) { if (auto *OwningModule = D.getImportedOwningModule()) - return OwningModule->Name; + return OwningModule->getTopLevelModule()->Name; return {}; } diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 1bce9c59b19791..54124ddbb2f58a 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -928,8 +928,8 @@ bool SymbolGraphSerializer::traverseObjCCategoryRecord( return true; auto *CurrentModule = ModuleForCurrentSymbol; - if (Record->isExtendingExternalModule()) -ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source]; + if (auto ModuleExtendedByRecord= Record->getExtendedExternalModule()) +ModuleForCurrentSymbol = &ExtendedModules[*ModuleExtendedByRecord]; if (!walkUpFromObjCCategoryRecord(Record)) return false; >From dc061de96ede86df0afdb01bde797c3965760ebb Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Fri, 23 Aug 2024 18:16:50 +0100 Subject: [PATCH 2/5] [clang][ExtractAPI] Fix macro detection code to work with modules enabled Change macro detection from using `MacroDefined` callback to iterating over all visible macros in `EndOfMainFile` callback. This way macros that came from an ASTFile are taken into account. --- .../clang/ExtractAPI/DeclarationFragments.h | 4 +- clang/lib/ExtractAPI/DeclarationFragments.cpp | 4 +- clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 84 +- clang/test/ExtractAPI/macros.c| 756 -- 4 files changed, 382 insertions(+), 466 deletions(-) diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h index 535da90b98284b..4ac744459031eb 100644 --- a/clang/include/clang/ExtractAPI/DeclarationFragments.h +++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -411,9 +411,9 @@ class DeclarationFragmentsBuilder { /// Build DeclarationFragments for a macro. /// /// \param Name name of the macro. - /// \param MD the associated MacroDirective. + /// \param MI the associated MacroInfo. static DeclarationFragments getFragmentsForMacro(StringRef Name, - const MacroDirective *MD); + const MacroInfo *MI); /// Build DeclarationFragments for a typedef \p TypedefNameDecl. static DeclarationFragments diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 6b85c7db90349e..d77bb1d424f7cf 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1327,14 +1327,12 @@ DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, - const MacroDirective *MD) { + const MacroInfo *MI) { DeclarationFragments Fragments; Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) .appendSpace(); Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); - auto *MI = MD->getMacroInfo(); - if (MI->isFunctionLike()) { Fragments.append("(", DeclarationFragments::FragmentKind::Text); unsigned numParameters = MI->getNumParams(); diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index d6335854cbf262..b23a62267651c8 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -286,78 +286,54 @@ class MacroCallback : public PPCallbacks { MacroCallback(const SourceManager &SM, APISet &API, Preprocessor &PP) : SM(SM), API(API), PP(PP) {} - void MacroDefined(const Token &MacroNameToken, -const Macr
[clang] [clang][ExtractAPI] Fix quirks in interaction with submodules (PR #105868)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/105868 Extension SGFs require the module system to be enabled in order to discover which module defines the extended external type. This patch ensures the following: - Associate symbols with their top level module name, - Ensure we don't drop macro definitions that came from a submodule but that should be included in the SGF output. >From b687c9512b748ee593eedd5e06d04d2a40197ec3 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Fri, 23 Aug 2024 10:02:42 +0100 Subject: [PATCH 1/4] [clang][ExtractAPI] Use top level module name for tracking which module a symbol came from rdar://123020565 --- clang/include/clang/ExtractAPI/ExtractAPIVisitor.h | 2 +- clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 67659f5a25037c..b09b8b44d9abaa 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -213,7 +213,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { StringRef getOwningModuleName(const Decl &D) { if (auto *OwningModule = D.getImportedOwningModule()) - return OwningModule->Name; + return OwningModule->getTopLevelModule()->Name; return {}; } diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 1bce9c59b19791..54124ddbb2f58a 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -928,8 +928,8 @@ bool SymbolGraphSerializer::traverseObjCCategoryRecord( return true; auto *CurrentModule = ModuleForCurrentSymbol; - if (Record->isExtendingExternalModule()) -ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source]; + if (auto ModuleExtendedByRecord= Record->getExtendedExternalModule()) +ModuleForCurrentSymbol = &ExtendedModules[*ModuleExtendedByRecord]; if (!walkUpFromObjCCategoryRecord(Record)) return false; >From dc061de96ede86df0afdb01bde797c3965760ebb Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Fri, 23 Aug 2024 18:16:50 +0100 Subject: [PATCH 2/4] [clang][ExtractAPI] Fix macro detection code to work with modules enabled Change macro detection from using `MacroDefined` callback to iterating over all visible macros in `EndOfMainFile` callback. This way macros that came from an ASTFile are taken into account. --- .../clang/ExtractAPI/DeclarationFragments.h | 4 +- clang/lib/ExtractAPI/DeclarationFragments.cpp | 4 +- clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 84 +- clang/test/ExtractAPI/macros.c| 756 -- 4 files changed, 382 insertions(+), 466 deletions(-) diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h index 535da90b98284b..4ac744459031eb 100644 --- a/clang/include/clang/ExtractAPI/DeclarationFragments.h +++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -411,9 +411,9 @@ class DeclarationFragmentsBuilder { /// Build DeclarationFragments for a macro. /// /// \param Name name of the macro. - /// \param MD the associated MacroDirective. + /// \param MI the associated MacroInfo. static DeclarationFragments getFragmentsForMacro(StringRef Name, - const MacroDirective *MD); + const MacroInfo *MI); /// Build DeclarationFragments for a typedef \p TypedefNameDecl. static DeclarationFragments diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 6b85c7db90349e..d77bb1d424f7cf 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1327,14 +1327,12 @@ DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization( DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name, - const MacroDirective *MD) { + const MacroInfo *MI) { DeclarationFragments Fragments; Fragments.append("#define", DeclarationFragments::FragmentKind::Keyword) .appendSpace(); Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier); - auto *MI = MD->getMacroInfo(); - if (MI->isFunctionLike()) { Fragments.append("(", DeclarationFragments::FragmentKind::Text); unsigned numParameters = MI->getNumParams(); diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index d6335854cbf262..b23a62267651c8 100644 --- a/clang/lib/ExtractAPI/
[clang] Reenable anon structs (PR #104922)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/104922 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] b18b454 - Revert "[clang][ExtractAPI] Stop dropping fields of nested anonymous record types when they aren't attached to variable declaration (#104600)"
Author: Daniel Grumberg Date: 2024-08-19T16:06:43+01:00 New Revision: b18b4547f1bfaf6da37b29440a96176e807c2e6c URL: https://github.com/llvm/llvm-project/commit/b18b4547f1bfaf6da37b29440a96176e807c2e6c DIFF: https://github.com/llvm/llvm-project/commit/b18b4547f1bfaf6da37b29440a96176e807c2e6c.diff LOG: Revert "[clang][ExtractAPI] Stop dropping fields of nested anonymous record types when they aren't attached to variable declaration (#104600)" This reverts commit c60da1a271a6bb271e7703b2f7c71fbece67ab78. Added: Modified: clang/include/clang/ExtractAPI/API.h clang/include/clang/ExtractAPI/ExtractAPIVisitor.h clang/lib/ExtractAPI/API.cpp clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp clang/test/ExtractAPI/anonymous_record_no_typedef.c Removed: diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index 188e35b72117b5..bf291074fd0614 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -19,13 +19,21 @@ #define LLVM_CLANG_EXTRACTAPI_API_H #include "clang/AST/Availability.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclObjC.h" #include "clang/AST/RawCommentList.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "clang/ExtractAPI/DeclarationFragments.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" #include #include @@ -320,8 +328,6 @@ class RecordContext { /// chain. void stealRecordChain(RecordContext &Other); - void removeFromRecordChain(APIRecord *Record); - APIRecord::RecordKind getKind() const { return Kind; } struct record_iterator { @@ -1420,15 +1426,10 @@ class APISet { typename std::enable_if_t, RecordTy> * createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs); - auto getTopLevelRecords() const { -return llvm::iterator_range( -TopLevelRecords); + ArrayRef getTopLevelRecords() const { +return TopLevelRecords; } - void removeRecord(StringRef USR); - - void removeRecord(APIRecord *Record); - APISet(const llvm::Triple &Target, Language Lang, const std::string &ProductName) : Target(Target), Lang(Lang), ProductName(ProductName) {} @@ -1455,7 +1456,7 @@ class APISet { // lives in the BumpPtrAllocator. using APIRecordStoredPtr = std::unique_ptr; llvm::DenseMap USRBasedLookupTable; - llvm::SmallPtrSet TopLevelRecords; + std::vector TopLevelRecords; public: const std::string ProductName; @@ -1481,7 +1482,7 @@ APISet::createRecord(StringRef USR, StringRef Name, dyn_cast_if_present(Record->Parent.Record)) ParentContext->addToRecordChain(Record); else - TopLevelRecords.insert(Record); + TopLevelRecords.push_back(Record); } else { Record = dyn_cast(Result.first->second.get()); } diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 8d9ac062034511..1b27027621666a 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -23,11 +23,13 @@ #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "clang/ExtractAPI/API.h" #include "clang/ExtractAPI/DeclarationFragments.h" #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Casting.h" #include @@ -38,8 +40,6 @@ namespace impl { template class ExtractAPIVisitorBase : public RecursiveASTVisitor { - using Base = RecursiveASTVisitor; - protected: ExtractAPIVisitorBase(ASTContext &Context, APISet &API) : Context(Context), API(API) {} @@ -81,10 +81,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { bool VisitNamespaceDecl(const NamespaceDecl *Decl); - bool TraverseRecordDecl(RecordDecl *Decl); bool VisitRecordDecl(const RecordDecl *Decl); - bool TraverseCXXRecordDecl(CXXRecordDecl *Decl); bool VisitCXXRecordDecl(const CXXRecordDecl *Decl); bool VisitCXXMethodDecl(const CXXMethodDecl *Decl); @@ -242,7 +240,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { bool isEmbeddedInVarDeclarator(const TagDecl &D) { return D.getName().empty() && getTypedefName(&D).empty() && - D.isEmbeddedInDeclarator() && !D.isFreeStanding(); +
[clang] [clang][ExtractAPI] Stop dropping fields of nested anonymous record types when they aren't attached to variable declaration (PR #104600)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/104600 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Stop dropping fields of nested anonymous record types when they aren't attached to variable declaration (PR #104600)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/104600 >From 8e3909ecb1bfe6aec6344cd89cbe1798d6cde7da Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 15 Aug 2024 17:42:02 +0100 Subject: [PATCH 1/4] [clang][ExtractAPI] Implement Record removal from APISet rdar://128092236 --- clang/include/clang/ExtractAPI/API.h | 24 ++-- clang/lib/ExtractAPI/API.cpp | 57 +++- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index bf291074fd0614..3b36dfe0325b9b 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -19,21 +19,13 @@ #define LLVM_CLANG_EXTRACTAPI_API_H #include "clang/AST/Availability.h" -#include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/RawCommentList.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/Specifiers.h" #include "clang/ExtractAPI/DeclarationFragments.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" #include #include @@ -328,6 +320,8 @@ class RecordContext { /// chain. void stealRecordChain(RecordContext &Other); + void removeFromRecordChain(APIRecord *Record); + APIRecord::RecordKind getKind() const { return Kind; } struct record_iterator { @@ -1426,10 +1420,14 @@ class APISet { typename std::enable_if_t, RecordTy> * createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs); - ArrayRef getTopLevelRecords() const { -return TopLevelRecords; + auto getTopLevelRecords() const { +return llvm::iterator_range(TopLevelRecords); } + void removeRecord(StringRef USR); + + void removeRecord(APIRecord *Record); + APISet(const llvm::Triple &Target, Language Lang, const std::string &ProductName) : Target(Target), Lang(Lang), ProductName(ProductName) {} @@ -1456,7 +1454,7 @@ class APISet { // lives in the BumpPtrAllocator. using APIRecordStoredPtr = std::unique_ptr; llvm::DenseMap USRBasedLookupTable; - std::vector TopLevelRecords; + llvm::SmallPtrSet TopLevelRecords; public: const std::string ProductName; @@ -1482,7 +1480,7 @@ APISet::createRecord(StringRef USR, StringRef Name, dyn_cast_if_present(Record->Parent.Record)) ParentContext->addToRecordChain(Record); else - TopLevelRecords.push_back(Record); + TopLevelRecords.insert(Record); } else { Record = dyn_cast(Result.first->second.get()); } diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp index ab1108f663deac..48d8bb7f600630 100644 --- a/clang/lib/ExtractAPI/API.cpp +++ b/clang/lib/ExtractAPI/API.cpp @@ -13,8 +13,6 @@ //===--===// #include "clang/ExtractAPI/API.h" -#include "clang/AST/RawCommentList.h" -#include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include @@ -60,6 +58,10 @@ bool RecordContext::IsWellFormed() const { void RecordContext::stealRecordChain(RecordContext &Other) { assert(IsWellFormed()); + // Other's record chain is empty, nothing to do + if (Other.First == nullptr && Other.Last == nullptr) +return; + // If we don't have an empty chain append Other's chain into ours. if (First) Last->NextInContext = Other.First; @@ -68,6 +70,9 @@ void RecordContext::stealRecordChain(RecordContext &Other) { Last = Other.Last; + for (auto *StolenRecord = Other.First; StolenRecord != nullptr; StolenRecord = StolenRecord->getNextInContext()) +StolenRecord->Parent = SymbolReference(cast(this)); + // Delete Other's chain to ensure we don't accidentally traverse it. Other.First = nullptr; Other.Last = nullptr; @@ -85,6 +90,22 @@ void RecordContext::addToRecordChain(APIRecord *Record) const { Last = Record; } +void RecordContext::removeFromRecordChain(APIRecord *Record) { + APIRecord *Prev = nullptr; + for (APIRecord *Curr = First; Curr != Record; Curr = Curr->NextInContext) +Prev = Curr; + + if (Prev) +Prev->NextInContext = Record->NextInContext; + else +First = Record->NextInContext; + + if (Last == Record) +Last = Prev; + + Record->NextInContext = nullptr; +} + APIRecord *APISet::findRecordForUSR(StringRef USR) const { if (USR.empty()) return nullptr; @@ -114,6 +135,38 @@ SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR, return SymbolReference(copyString(Name), copyString(USR), copyString(Source)); } + +void APISet::removeRecord
[clang] [clang][ExtractAPI] Stop dropping fields of nested anonymous record types when they aren't attached to variable declaration (PR #104600)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/104600 >From 61b8014d418867e0108bf4513227d9a8fdad63f8 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 15 Aug 2024 17:42:02 +0100 Subject: [PATCH 1/4] [clang][ExtractAPI] Implement Record removal from APISet rdar://128092236 --- clang/include/clang/ExtractAPI/API.h | 24 ++-- clang/lib/ExtractAPI/API.cpp | 57 +++- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index bf291074fd0614..3b36dfe0325b9b 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -19,21 +19,13 @@ #define LLVM_CLANG_EXTRACTAPI_API_H #include "clang/AST/Availability.h" -#include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/RawCommentList.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/Specifiers.h" #include "clang/ExtractAPI/DeclarationFragments.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" #include #include @@ -328,6 +320,8 @@ class RecordContext { /// chain. void stealRecordChain(RecordContext &Other); + void removeFromRecordChain(APIRecord *Record); + APIRecord::RecordKind getKind() const { return Kind; } struct record_iterator { @@ -1426,10 +1420,14 @@ class APISet { typename std::enable_if_t, RecordTy> * createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs); - ArrayRef getTopLevelRecords() const { -return TopLevelRecords; + auto getTopLevelRecords() const { +return llvm::iterator_range(TopLevelRecords); } + void removeRecord(StringRef USR); + + void removeRecord(APIRecord *Record); + APISet(const llvm::Triple &Target, Language Lang, const std::string &ProductName) : Target(Target), Lang(Lang), ProductName(ProductName) {} @@ -1456,7 +1454,7 @@ class APISet { // lives in the BumpPtrAllocator. using APIRecordStoredPtr = std::unique_ptr; llvm::DenseMap USRBasedLookupTable; - std::vector TopLevelRecords; + llvm::SmallPtrSet TopLevelRecords; public: const std::string ProductName; @@ -1482,7 +1480,7 @@ APISet::createRecord(StringRef USR, StringRef Name, dyn_cast_if_present(Record->Parent.Record)) ParentContext->addToRecordChain(Record); else - TopLevelRecords.push_back(Record); + TopLevelRecords.insert(Record); } else { Record = dyn_cast(Result.first->second.get()); } diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp index ab1108f663deac..48d8bb7f600630 100644 --- a/clang/lib/ExtractAPI/API.cpp +++ b/clang/lib/ExtractAPI/API.cpp @@ -13,8 +13,6 @@ //===--===// #include "clang/ExtractAPI/API.h" -#include "clang/AST/RawCommentList.h" -#include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include @@ -60,6 +58,10 @@ bool RecordContext::IsWellFormed() const { void RecordContext::stealRecordChain(RecordContext &Other) { assert(IsWellFormed()); + // Other's record chain is empty, nothing to do + if (Other.First == nullptr && Other.Last == nullptr) +return; + // If we don't have an empty chain append Other's chain into ours. if (First) Last->NextInContext = Other.First; @@ -68,6 +70,9 @@ void RecordContext::stealRecordChain(RecordContext &Other) { Last = Other.Last; + for (auto *StolenRecord = Other.First; StolenRecord != nullptr; StolenRecord = StolenRecord->getNextInContext()) +StolenRecord->Parent = SymbolReference(cast(this)); + // Delete Other's chain to ensure we don't accidentally traverse it. Other.First = nullptr; Other.Last = nullptr; @@ -85,6 +90,22 @@ void RecordContext::addToRecordChain(APIRecord *Record) const { Last = Record; } +void RecordContext::removeFromRecordChain(APIRecord *Record) { + APIRecord *Prev = nullptr; + for (APIRecord *Curr = First; Curr != Record; Curr = Curr->NextInContext) +Prev = Curr; + + if (Prev) +Prev->NextInContext = Record->NextInContext; + else +First = Record->NextInContext; + + if (Last == Record) +Last = Prev; + + Record->NextInContext = nullptr; +} + APIRecord *APISet::findRecordForUSR(StringRef USR) const { if (USR.empty()) return nullptr; @@ -114,6 +135,38 @@ SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR, return SymbolReference(copyString(Name), copyString(USR), copyString(Source)); } + +void APISet::removeRecord
[clang] [clang][ExtractAPI] Stop dropping fields of nested anonymous record types when they aren't attached to variable declaration (PR #104600)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/104600 - Introduce primitives for removing records from `APISet` and managing the record chain of `RecordContext` - Detect nested anonymous record types and remove them from the `APISet` after they have been fully traversed and transfer ownership of child records to the parent context (if any) >From 61b8014d418867e0108bf4513227d9a8fdad63f8 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 15 Aug 2024 17:42:02 +0100 Subject: [PATCH 1/3] [clang][ExtractAPI] Implement Record removal from APISet rdar://128092236 --- clang/include/clang/ExtractAPI/API.h | 24 ++-- clang/lib/ExtractAPI/API.cpp | 57 +++- 2 files changed, 66 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index bf291074fd0614..3b36dfe0325b9b 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -19,21 +19,13 @@ #define LLVM_CLANG_EXTRACTAPI_API_H #include "clang/AST/Availability.h" -#include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" -#include "clang/AST/DeclObjC.h" #include "clang/AST/RawCommentList.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/Specifiers.h" #include "clang/ExtractAPI/DeclarationFragments.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" #include #include @@ -328,6 +320,8 @@ class RecordContext { /// chain. void stealRecordChain(RecordContext &Other); + void removeFromRecordChain(APIRecord *Record); + APIRecord::RecordKind getKind() const { return Kind; } struct record_iterator { @@ -1426,10 +1420,14 @@ class APISet { typename std::enable_if_t, RecordTy> * createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs); - ArrayRef getTopLevelRecords() const { -return TopLevelRecords; + auto getTopLevelRecords() const { +return llvm::iterator_range(TopLevelRecords); } + void removeRecord(StringRef USR); + + void removeRecord(APIRecord *Record); + APISet(const llvm::Triple &Target, Language Lang, const std::string &ProductName) : Target(Target), Lang(Lang), ProductName(ProductName) {} @@ -1456,7 +1454,7 @@ class APISet { // lives in the BumpPtrAllocator. using APIRecordStoredPtr = std::unique_ptr; llvm::DenseMap USRBasedLookupTable; - std::vector TopLevelRecords; + llvm::SmallPtrSet TopLevelRecords; public: const std::string ProductName; @@ -1482,7 +1480,7 @@ APISet::createRecord(StringRef USR, StringRef Name, dyn_cast_if_present(Record->Parent.Record)) ParentContext->addToRecordChain(Record); else - TopLevelRecords.push_back(Record); + TopLevelRecords.insert(Record); } else { Record = dyn_cast(Result.first->second.get()); } diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp index ab1108f663deac..48d8bb7f600630 100644 --- a/clang/lib/ExtractAPI/API.cpp +++ b/clang/lib/ExtractAPI/API.cpp @@ -13,8 +13,6 @@ //===--===// #include "clang/ExtractAPI/API.h" -#include "clang/AST/RawCommentList.h" -#include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include @@ -60,6 +58,10 @@ bool RecordContext::IsWellFormed() const { void RecordContext::stealRecordChain(RecordContext &Other) { assert(IsWellFormed()); + // Other's record chain is empty, nothing to do + if (Other.First == nullptr && Other.Last == nullptr) +return; + // If we don't have an empty chain append Other's chain into ours. if (First) Last->NextInContext = Other.First; @@ -68,6 +70,9 @@ void RecordContext::stealRecordChain(RecordContext &Other) { Last = Other.Last; + for (auto *StolenRecord = Other.First; StolenRecord != nullptr; StolenRecord = StolenRecord->getNextInContext()) +StolenRecord->Parent = SymbolReference(cast(this)); + // Delete Other's chain to ensure we don't accidentally traverse it. Other.First = nullptr; Other.Last = nullptr; @@ -85,6 +90,22 @@ void RecordContext::addToRecordChain(APIRecord *Record) const { Last = Record; } +void RecordContext::removeFromRecordChain(APIRecord *Record) { + APIRecord *Prev = nullptr; + for (APIRecord *Curr = First; Curr != Record; Curr = Curr->NextInContext) +Prev = Curr; + + if (Prev) +Prev->NextInContext = Record->NextInContext; + else +First = Record->NextInContext; + + if (Last == Record) +Last = Prev; + + Record->NextInContext = nullptr; +} + APIRecord *APISet::find
[clang] [clang][ExtractAPI] Emit environment component of target triple in SGF (PR #103273)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/103273 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Compute inherited availability information (PR #103040)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/103040 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Compute inherited availability information (PR #103040)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/103040 >From cd38c476336ea90e4d080638d028dda203b52ac4 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 13 Aug 2024 11:30:18 +0100 Subject: [PATCH 1/5] [clang][ExtractAPI] Compute inherited availability information Additionally this computes availability information for all platforms ahead of possibly introducing a flag to enable this behavior. rdar://123513706 --- clang/include/clang/AST/Availability.h| 4 + clang/lib/AST/Availability.cpp| 100 ++-- .../Serialization/SymbolGraphSerializer.cpp | 31 ++-- .../test/ExtractAPI/inherited_availability.m | 149 ++ 4 files changed, 254 insertions(+), 30 deletions(-) create mode 100644 clang/test/ExtractAPI/inherited_availability.m diff --git a/clang/include/clang/AST/Availability.h b/clang/include/clang/AST/Availability.h index 26ae622e5b4496..60ca1383f0a44e 100644 --- a/clang/include/clang/AST/Availability.h +++ b/clang/include/clang/AST/Availability.h @@ -97,6 +97,10 @@ struct AvailabilityInfo { return UnconditionallyUnavailable; } + /// Augments the existing information with additional constraints provided by + /// \c Other. + void mergeWith(AvailabilityInfo Other); + AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D, VersionTuple O, bool U, bool UD, bool UU) : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O), diff --git a/clang/lib/AST/Availability.cpp b/clang/lib/AST/Availability.cpp index 238359a2dedfcf..376a625b41817a 100644 --- a/clang/lib/AST/Availability.cpp +++ b/clang/lib/AST/Availability.cpp @@ -16,33 +16,101 @@ #include "clang/AST/Decl.h" #include "clang/Basic/TargetInfo.h" -namespace clang { +namespace { + +struct AvailabilitySet { + llvm::SmallVector Availabilities; + bool UnconditionallyDeprecated = false; + bool UnconditionallyUnavailable = false; -AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *Decl) { - ASTContext &Context = Decl->getASTContext(); - StringRef PlatformName = Context.getTargetInfo().getPlatformName(); - AvailabilityInfo Availability; + void insert(clang::AvailabilityInfo &&Availability) { +auto *Found = getForPlatform(Availability.Domain); +if (Found) + Found->mergeWith(std::move(Availability)); +else + Availabilities.emplace_back(std::move(Availability)); + } + + clang::AvailabilityInfo *getForPlatform(llvm::StringRef Domain) { +auto *It = llvm::find_if(Availabilities, + [Domain](const clang::AvailabilityInfo &Info) { + return Domain.compare(Info.Domain) == 0; + }); +return It == Availabilities.end() ? nullptr : It; + } +}; +static void createInfoForDecl(const clang::Decl *Decl, + AvailabilitySet &Availabilities) { // Collect availability attributes from all redeclarations. for (const auto *RD : Decl->redecls()) { -for (const auto *A : RD->specific_attrs()) { - if (A->getPlatform()->getName() != PlatformName) -continue; - Availability = AvailabilityInfo( +for (const auto *A : RD->specific_attrs()) { + Availabilities.insert(clang::AvailabilityInfo( A->getPlatform()->getName(), A->getIntroduced(), A->getDeprecated(), - A->getObsoleted(), A->getUnavailable(), false, false); - break; + A->getObsoleted(), A->getUnavailable(), false, false)); } -if (const auto *A = RD->getAttr()) +if (const auto *A = RD->getAttr()) if (!A->isImplicit()) -Availability.UnconditionallyUnavailable = true; +Availabilities.UnconditionallyUnavailable = true; -if (const auto *A = RD->getAttr()) +if (const auto *A = RD->getAttr()) if (!A->isImplicit()) -Availability.UnconditionallyDeprecated = true; +Availabilities.UnconditionallyDeprecated = true; + } +} + +} // namespace + +namespace clang { + +void AvailabilityInfo::mergeWith(AvailabilityInfo Other) { + if (isDefault() && Other.isDefault()) +return; + + if (Domain.empty()) +Domain = Other.Domain; + + UnconditionallyUnavailable |= Other.UnconditionallyUnavailable; + UnconditionallyDeprecated |= Other.UnconditionallyDeprecated; + Unavailable |= Other.Unavailable; + + Introduced = std::max(Introduced, Other.Introduced); + + // Default VersionTuple is 0.0.0 so if both are non default let's pick the + // smallest version number, otherwise select the one that is non-zero if there + // is one. + if (!Deprecated.empty() && !Other.Deprecated.empty()) +Deprecated = std::min(Deprecated, Other.Deprecated); + else +Deprecated = std::max(Deprecated, Other.Deprecated); + + if (!Obsoleted.empty() && !Other.Obsoleted.empty()) +Obsoleted = std::min(Obsoleted, Other.Obsoleted); + else +Obsoleted = std::max(Obsoleted, Other.Obsoleted); +} + +Availabili
[clang] [clang][ExtractAPI] Compute inherited availability information (PR #103040)
@@ -16,33 +16,101 @@ #include "clang/AST/Decl.h" #include "clang/Basic/TargetInfo.h" -namespace clang { +namespace { + +struct AvailabilitySet { + llvm::SmallVector Availabilities; + bool UnconditionallyDeprecated = false; + bool UnconditionallyUnavailable = false; -AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *Decl) { - ASTContext &Context = Decl->getASTContext(); - StringRef PlatformName = Context.getTargetInfo().getPlatformName(); - AvailabilityInfo Availability; + void insert(clang::AvailabilityInfo &&Availability) { +auto *Found = getForPlatform(Availability.Domain); +if (Found) + Found->mergeWith(std::move(Availability)); +else + Availabilities.emplace_back(std::move(Availability)); + } + + clang::AvailabilityInfo *getForPlatform(llvm::StringRef Domain) { daniel-grumberg wrote: The semantic is that you get a reference of the thing inside the Availabilities vector if it exist (this method is used by `insert` and not just `AvailabilityInfo::createFromDecl`), to express that with `std::optional` which doesn't exist. https://github.com/llvm/llvm-project/pull/103040 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Compute inherited availability information (PR #103040)
@@ -0,0 +1,149 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing -triple arm64-apple-macosx \ +// RUN: -x objective-c-header %s -o %t/output.symbols.json -verify + + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix A +__attribute__((availability(macos, introduced=9.0, deprecated=12.0, obsoleted=20.0))) +@interface A daniel-grumberg wrote: It walks DeclContext's upwards to find one to compute the most restrictive information. If the are no other annotations for that platform walking upwards then it is just the one in the availability annotation. I realized that the existing availability test case doesn't cover this, thanks for pointing it out I will add a test to validate this behavior. https://github.com/llvm/llvm-project/pull/103040 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Compute inherited availability information (PR #103040)
daniel-grumberg wrote: > > Additionally this computes availability information for all platforms ahead > > Can you add a test for this? The behavior is not exposed yet so I can't add a test, will do when I start exposing the behavior. https://github.com/llvm/llvm-project/pull/103040 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Emit environment component of target triple in SGF (PR #103273)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/103273 rdar://133533830 >From 6c9fdf64b14c14db00fbf4ba8ec4103b14ddb72d Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 13 Aug 2024 16:09:58 +0100 Subject: [PATCH] [clang][ExtractAPI] Emit environment component of target triple in SGF rdar://133533830 --- .../Serialization/SymbolGraphSerializer.cpp | 4 .../test/ExtractAPI/platform-serialization.c | 20 +++ 2 files changed, 24 insertions(+) create mode 100644 clang/test/ExtractAPI/platform-serialization.c diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 6e56ee5b573f66..647c8659639f35 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -104,6 +104,10 @@ Object serializePlatform(const Triple &T) { Object Platform; Platform["architecture"] = T.getArchName(); Platform["vendor"] = T.getVendorName(); + + if (!T.getEnvironmentName().empty()) +Platform["environment"] = T.getEnvironmentName(); + Platform["operatingSystem"] = serializeOperatingSystem(T); return Platform; } diff --git a/clang/test/ExtractAPI/platform-serialization.c b/clang/test/ExtractAPI/platform-serialization.c new file mode 100644 index 00..6d6a13f085cd9d --- /dev/null +++ b/clang/test/ExtractAPI/platform-serialization.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -extract-api --pretty-sgf -triple arm64-apple-ios17.1-macabi \ +// RUN: -x c-header %s -verify -o - | FileCheck %s + +int a; + +// CHECK: "platform": { +// CHECK-NEXT: "architecture": "arm64", +// CHECK-NEXT: "environment": "macabi", +// CHECK-NEXT: "operatingSystem": { +// CHECK-NEXT: "minimumVersion": { +// CHECK-NEXT: "major": 14, +// CHECK-NEXT: "minor": 0, +// CHECK-NEXT: "patch": 0 +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "ios" +// CHECK-NEXT: }, +// CHECK-NEXT: "vendor": "apple" +// CHECK-NEXT: } + +// expected-no-diagnostics ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Compute inherited availability information (PR #103040)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/103040 Additionally this computes availability information for all platforms ahead of possibly introducing a flag to enable this behavior. rdar://123513706 >From cd38c476336ea90e4d080638d028dda203b52ac4 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 13 Aug 2024 11:30:18 +0100 Subject: [PATCH] [clang][ExtractAPI] Compute inherited availability information Additionally this computes availability information for all platforms ahead of possibly introducing a flag to enable this behavior. rdar://123513706 --- clang/include/clang/AST/Availability.h| 4 + clang/lib/AST/Availability.cpp| 100 ++-- .../Serialization/SymbolGraphSerializer.cpp | 31 ++-- .../test/ExtractAPI/inherited_availability.m | 149 ++ 4 files changed, 254 insertions(+), 30 deletions(-) create mode 100644 clang/test/ExtractAPI/inherited_availability.m diff --git a/clang/include/clang/AST/Availability.h b/clang/include/clang/AST/Availability.h index 26ae622e5b4496..60ca1383f0a44e 100644 --- a/clang/include/clang/AST/Availability.h +++ b/clang/include/clang/AST/Availability.h @@ -97,6 +97,10 @@ struct AvailabilityInfo { return UnconditionallyUnavailable; } + /// Augments the existing information with additional constraints provided by + /// \c Other. + void mergeWith(AvailabilityInfo Other); + AvailabilityInfo(StringRef Domain, VersionTuple I, VersionTuple D, VersionTuple O, bool U, bool UD, bool UU) : Domain(Domain), Introduced(I), Deprecated(D), Obsoleted(O), diff --git a/clang/lib/AST/Availability.cpp b/clang/lib/AST/Availability.cpp index 238359a2dedfcf..376a625b41817a 100644 --- a/clang/lib/AST/Availability.cpp +++ b/clang/lib/AST/Availability.cpp @@ -16,33 +16,101 @@ #include "clang/AST/Decl.h" #include "clang/Basic/TargetInfo.h" -namespace clang { +namespace { + +struct AvailabilitySet { + llvm::SmallVector Availabilities; + bool UnconditionallyDeprecated = false; + bool UnconditionallyUnavailable = false; -AvailabilityInfo AvailabilityInfo::createFromDecl(const Decl *Decl) { - ASTContext &Context = Decl->getASTContext(); - StringRef PlatformName = Context.getTargetInfo().getPlatformName(); - AvailabilityInfo Availability; + void insert(clang::AvailabilityInfo &&Availability) { +auto *Found = getForPlatform(Availability.Domain); +if (Found) + Found->mergeWith(std::move(Availability)); +else + Availabilities.emplace_back(std::move(Availability)); + } + + clang::AvailabilityInfo *getForPlatform(llvm::StringRef Domain) { +auto *It = llvm::find_if(Availabilities, + [Domain](const clang::AvailabilityInfo &Info) { + return Domain.compare(Info.Domain) == 0; + }); +return It == Availabilities.end() ? nullptr : It; + } +}; +static void createInfoForDecl(const clang::Decl *Decl, + AvailabilitySet &Availabilities) { // Collect availability attributes from all redeclarations. for (const auto *RD : Decl->redecls()) { -for (const auto *A : RD->specific_attrs()) { - if (A->getPlatform()->getName() != PlatformName) -continue; - Availability = AvailabilityInfo( +for (const auto *A : RD->specific_attrs()) { + Availabilities.insert(clang::AvailabilityInfo( A->getPlatform()->getName(), A->getIntroduced(), A->getDeprecated(), - A->getObsoleted(), A->getUnavailable(), false, false); - break; + A->getObsoleted(), A->getUnavailable(), false, false)); } -if (const auto *A = RD->getAttr()) +if (const auto *A = RD->getAttr()) if (!A->isImplicit()) -Availability.UnconditionallyUnavailable = true; +Availabilities.UnconditionallyUnavailable = true; -if (const auto *A = RD->getAttr()) +if (const auto *A = RD->getAttr()) if (!A->isImplicit()) -Availability.UnconditionallyDeprecated = true; +Availabilities.UnconditionallyDeprecated = true; + } +} + +} // namespace + +namespace clang { + +void AvailabilityInfo::mergeWith(AvailabilityInfo Other) { + if (isDefault() && Other.isDefault()) +return; + + if (Domain.empty()) +Domain = Other.Domain; + + UnconditionallyUnavailable |= Other.UnconditionallyUnavailable; + UnconditionallyDeprecated |= Other.UnconditionallyDeprecated; + Unavailable |= Other.Unavailable; + + Introduced = std::max(Introduced, Other.Introduced); + + // Default VersionTuple is 0.0.0 so if both are non default let's pick the + // smallest version number, otherwise select the one that is non-zero if there + // is one. + if (!Deprecated.empty() && !Other.Deprecated.empty()) +Deprecated = std::min(Deprecated, Other.Deprecated); + else +Deprecated = std::max(Deprecated, Other.Deprecated); + + if (!Obsoleted.empty() && !Other.Obsol
[clang] [clang][ExtractAPI][NFC] Remove some nullptr dereference problems (PR #98914)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/98914 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI][NFC] Remove some nullptr dereference problems (PR #98914)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/98914 A places try to get a NamedDecl's name using getName when it isn't a simple identifier, migrate these areas to getNameAsString. rdar://125315602 >From 20a72b3170d284f1f984d1dc7c868fe5632df510 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 9 Jul 2024 17:40:10 +0100 Subject: [PATCH] [clang][ExtractAPI][NFC] Remove some nullptr dereference problems A places try to get a NamedDecl's name using getName when it isn't a simple identifier, migrate these areas to getNameAsString. rdar://125315602 --- .../clang/ExtractAPI/ExtractAPIVisitor.h | 51 ++- clang/lib/ExtractAPI/DeclarationFragments.cpp | 8 ++- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 76d7fd798bed3..1b27027621666 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -175,22 +175,25 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { // skip classes not inherited as public if (BaseSpecifier.getAccessSpecifier() != AccessSpecifier::AS_public) continue; - SymbolReference BaseClass; - if (BaseSpecifier.getType().getTypePtr()->isTemplateTypeParmType()) { -BaseClass.Name = API.copyString(BaseSpecifier.getType().getAsString()); -if (auto *TTPTD = BaseSpecifier.getType() - ->getAs() - ->getDecl()) { - SmallString<128> USR; - index::generateUSRForDecl(TTPTD, USR); - BaseClass.USR = API.copyString(USR); - BaseClass.Source = API.copyString(getOwningModuleName(*TTPTD)); -} + if (auto *BaseDecl = BaseSpecifier.getType()->getAsTagDecl()) { +Bases.emplace_back(createSymbolReferenceForDecl(*BaseDecl)); } else { -BaseClass = createSymbolReferenceForDecl( -*BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl()); +SymbolReference BaseClass; +BaseClass.Name = API.copyString(BaseSpecifier.getType().getAsString( +Decl->getASTContext().getPrintingPolicy())); + +if (BaseSpecifier.getType().getTypePtr()->isTemplateTypeParmType()) { + if (auto *TTPTD = BaseSpecifier.getType() +->getAs() +->getDecl()) { +SmallString<128> USR; +index::generateUSRForDecl(TTPTD, USR); +BaseClass.USR = API.copyString(USR); +BaseClass.Source = API.copyString(getOwningModuleName(*TTPTD)); + } +} +Bases.emplace_back(BaseClass); } - Bases.emplace_back(BaseClass); } return Bases; } @@ -352,7 +355,7 @@ bool ExtractAPIVisitorBase::VisitFunctionDecl( return true; // Collect symbol information. - StringRef Name = Decl->getName(); + auto Name = Decl->getNameAsString(); SmallString<128> USR; index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = @@ -666,8 +669,8 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl( if (FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate()) { API.createRecord( -USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc, -AvailabilityInfo::createFromDecl(Decl), Comment, +USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), +Loc, AvailabilityInfo::createFromDecl(Decl), Comment, DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate( TemplateDecl), SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl), @@ -675,8 +678,8 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl( Template(TemplateDecl), isInSystemHeader(Decl)); } else if (Decl->getTemplateSpecializationInfo()) API.createRecord( -USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc, -AvailabilityInfo::createFromDecl(Decl), Comment, +USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), +Loc, AvailabilityInfo::createFromDecl(Decl), Comment, DeclarationFragmentsBuilder:: getFragmentsForFunctionTemplateSpecialization(Decl), SubHeading, Signature, Access, isInSystemHeader(Decl)); @@ -688,14 +691,14 @@ bool ExtractAPIVisitorBase::VisitCXXMethodDecl( SubHeading, Signature, Access, isInSystemHeader(Decl)); else if (Decl->isStatic()) API.createRecord( -USR, Decl->getName(), createHierarchyInformationForDecl(*Decl), Loc, -AvailabilityInfo::createFromDecl(Decl), Comment, +USR, Decl->getNameAsString(), createHierarchyInformationForDecl(*Decl), +Loc, AvailabilityInfo::createFromDecl(Decl), Comment, DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Decl), SubHeadi
[clang] [clang][ExtractAPI][NFC] pass params by const reference (PR #94820)
daniel-grumberg wrote: Thanks for looking at these, I think it would be best to try and leverage move semantics where possible if we are going to change this code. https://github.com/llvm/llvm-project/pull/94820 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI][NFC] pass params by const reference (PR #94820)
@@ -240,7 +241,7 @@ class DeclarationFragments { class AccessControl { public: - AccessControl(std::string Access) : Access(Access) {} daniel-grumberg wrote: Again I would prefer if we kept the value semantic ones and use `std::move` https://github.com/llvm/llvm-project/pull/94820 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI][NFC] pass params by const reference (PR #94820)
@@ -199,7 +199,8 @@ class DeclarationFragments { return *this; } - DeclarationFragments &replace(std::string NewSpelling, unsigned Position) { daniel-grumberg wrote: I would prefer to keep the value semantics version and instead move assign the value, that way callers can move the string in and avoid any copies. https://github.com/llvm/llvm-project/pull/94820 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Flatten all enum cases from anonymous enums at top level (PR #93559)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/93559 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Flatten all enum cases from anonymous enums at top level (PR #93559)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/93559 >From 5c8258fb2bcc102d431af9f3ae41cf72ecc335b6 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 28 May 2024 15:43:45 +0100 Subject: [PATCH] [clang][ExtractAPI] Flatten all enum cases from anonymous enums at top level rdar://128863241 --- .../clang/ExtractAPI/ExtractAPIVisitor.h | 65 +- .../ExtractAPI/anonymous_record_no_typedef.c | 42 ++- clang/test/ExtractAPI/enum.c | 112 -- clang/tools/libclang/CXExtractAPI.cpp | 3 + 4 files changed, 54 insertions(+), 168 deletions(-) diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 8ccebe457ed53..76d7fd798bed3 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -21,6 +21,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ParentMapContext.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" @@ -127,7 +128,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { protected: /// Collect API information for the enum constants and associate with the /// parent enum. - void recordEnumConstants(EnumRecord *EnumRecord, + void recordEnumConstants(SymbolReference Container, const EnumDecl::enumerator_range Constants); /// Collect API information for the Objective-C methods and associate with the @@ -248,12 +249,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { clang::index::generateUSRForDecl(Tag, TagUSR); if (auto *Record = llvm::dyn_cast_if_present( API.findRecordForUSR(TagUSR))) { - if (Record->IsEmbeddedInVarDeclarator) { + if (Record->IsEmbeddedInVarDeclarator) NewRecordContext->stealRecordChain(*Record); -auto *NewRecord = cast(NewRecordContext); -if (NewRecord->Comment.empty()) - NewRecord->Comment = Record->Comment; - } } } }; @@ -394,17 +391,6 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) return true; - SmallString<128> QualifiedNameBuffer; - // Collect symbol information. - StringRef Name = Decl->getName(); - if (Name.empty()) -Name = getTypedefName(Decl); - if (Name.empty()) { -llvm::raw_svector_ostream OS(QualifiedNameBuffer); -Decl->printQualifiedName(OS); -Name = QualifiedNameBuffer; - } - SmallString<128> USR; index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = @@ -420,13 +406,29 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { DeclarationFragmentsBuilder::getFragmentsForEnum(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - auto *ER = API.createRecord( - USR, Name, createHierarchyInformationForDecl(*Decl), Loc, - AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, - isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); + + // Collect symbol information. + SymbolReference ParentContainer; + + if (Decl->hasNameForLinkage()) { +StringRef Name = Decl->getName(); +if (Name.empty()) + Name = getTypedefName(Decl); + +auto *ER = API.createRecord( +USR, Name, createHierarchyInformationForDecl(*Decl), Loc, +AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, +SubHeading, isInSystemHeader(Decl), false); +ParentContainer = SymbolReference(ER); + } else { +// If this an anonymous enum then the parent scope of the constants is the +// top level namespace. +ParentContainer = {}; + } // Now collect information about the enumerators in this enum. - getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators()); + getDerivedExtractAPIVisitor().recordEnumConstants(ParentContainer, +Decl->enumerators()); return true; } @@ -1197,7 +1199,7 @@ bool ExtractAPIVisitorBase::VisitObjCCategoryDecl( /// parent enum. template void ExtractAPIVisitorBase::recordEnumConstants( -EnumRecord *EnumRecord, const EnumDecl::enumerator_range Constants) { +SymbolReference Container, const EnumDecl::enumerator_range Constants) { for (const auto *Constant : Constants) { // Collect symbol information. StringRef Name = Constant->getName(); @@ -1218,9 +1220,8 @@ void ExtractAPIVisitorBase::recordEnumConstants( DeclarationFragmentsBuilder::getSubHeading(Constant); API.createRecord( -USR, Name, createHierarchyInformationForDecl(*Constant), Loc, -AvailabilityInfo::createFromDecl(Constant), Comment, Declaration, -SubHeading, isInSystemHeader(Constan
[clang] [clang][ExtractAPI] Flatten all enum cases from anonymous enums at top level (PR #93559)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/93559 rdar://128863241 >From d453e5b21d369d8c2b1d06c640887ec81ace Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 28 May 2024 15:43:45 +0100 Subject: [PATCH] [clang][ExtractAPI] Flatten all enum cases from anonymous enums at top level rdar://128863241 --- .../clang/ExtractAPI/ExtractAPIVisitor.h | 57 + .../ExtractAPI/anonymous_record_no_typedef.c | 42 ++- clang/test/ExtractAPI/enum.c | 112 -- clang/tools/libclang/CXExtractAPI.cpp | 3 + 4 files changed, 50 insertions(+), 164 deletions(-) diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 8ccebe457ed53..9df5138a223da 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -21,6 +21,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ParentMapContext.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" @@ -127,7 +128,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { protected: /// Collect API information for the enum constants and associate with the /// parent enum. - void recordEnumConstants(EnumRecord *EnumRecord, + void recordEnumConstants(SymbolReference Container, const EnumDecl::enumerator_range Constants); /// Collect API information for the Objective-C methods and associate with the @@ -248,12 +249,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { clang::index::generateUSRForDecl(Tag, TagUSR); if (auto *Record = llvm::dyn_cast_if_present( API.findRecordForUSR(TagUSR))) { - if (Record->IsEmbeddedInVarDeclarator) { + if (Record->IsEmbeddedInVarDeclarator) NewRecordContext->stealRecordChain(*Record); -auto *NewRecord = cast(NewRecordContext); -if (NewRecord->Comment.empty()) - NewRecord->Comment = Record->Comment; - } } } }; @@ -394,17 +391,6 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl)) return true; - SmallString<128> QualifiedNameBuffer; - // Collect symbol information. - StringRef Name = Decl->getName(); - if (Name.empty()) -Name = getTypedefName(Decl); - if (Name.empty()) { -llvm::raw_svector_ostream OS(QualifiedNameBuffer); -Decl->printQualifiedName(OS); -Name = QualifiedNameBuffer; - } - SmallString<128> USR; index::generateUSRForDecl(Decl, USR); PresumedLoc Loc = @@ -420,13 +406,27 @@ bool ExtractAPIVisitorBase::VisitEnumDecl(const EnumDecl *Decl) { DeclarationFragmentsBuilder::getFragmentsForEnum(Decl); DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - auto *ER = API.createRecord( + + // Collect symbol information. + SymbolReference ParentContainer; + + if (Decl->hasNameForLinkage()) { +StringRef Name = Decl->getName(); +if (Name.empty()) + Name = getTypedefName(Decl); + +auto *ER = API.createRecord( USR, Name, createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, - isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); + isInSystemHeader(Decl), false); +ParentContainer = SymbolReference(ER); + } else { +// If this an anonymous enum then the parent scope of the constants is the top level namespace. +ParentContainer = {}; + } // Now collect information about the enumerators in this enum. - getDerivedExtractAPIVisitor().recordEnumConstants(ER, Decl->enumerators()); + getDerivedExtractAPIVisitor().recordEnumConstants(ParentContainer, Decl->enumerators()); return true; } @@ -1197,7 +1197,7 @@ bool ExtractAPIVisitorBase::VisitObjCCategoryDecl( /// parent enum. template void ExtractAPIVisitorBase::recordEnumConstants( -EnumRecord *EnumRecord, const EnumDecl::enumerator_range Constants) { +SymbolReference Container, const EnumDecl::enumerator_range Constants) { for (const auto *Constant : Constants) { // Collect symbol information. StringRef Name = Constant->getName(); @@ -1218,7 +1218,7 @@ void ExtractAPIVisitorBase::recordEnumConstants( DeclarationFragmentsBuilder::getSubHeading(Constant); API.createRecord( -USR, Name, createHierarchyInformationForDecl(*Constant), Loc, +USR, Name, Container, Loc, AvailabilityInfo::createFromDecl(Constant), Comment, Declaration, SubHeading, isInSystemHeader(Constant)); } @@ -1469,7 +1469,18 @@ class ExtractAPIVisitor bool shouldDeclBeIncluded(const Decl *D) const { return true; } const RawComment *fetchRawCom
[clang] [clang][ExtractAPI] Ensure TemplateArgumentLocations are only accessed if available (PR #93205)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/93205 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Ensure TemplateArgumentLocations are only accessed if available (PR #93205)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/93205 None >From d4e7e838fcbdf1645e5e31cefb462d53e59361d4 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 23 May 2024 15:24:53 +0100 Subject: [PATCH] [clang][ExtractAPI] Ensure TemplateArgumentLocations are only accessed if available --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 32 +- clang/test/ExtractAPI/non_type_template.cpp | 44 +++ 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 904b9315f26ef..8c7c0f8a14726 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1084,12 +1084,22 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( if (StringRef(ArgumentFragment.begin()->Spelling) .starts_with("type-parameter")) { -std::string ProperArgName = TemplateArgumentLocs.value()[i] -.getTypeSourceInfo() -->getType() -.getAsString(); -ArgumentFragment.begin()->Spelling.swap(ProperArgName); +if (TemplateArgumentLocs.has_value() && +TemplateArgumentLocs->size() > i) { + std::string ProperArgName = TemplateArgumentLocs.value()[i] + .getTypeSourceInfo() + ->getType() + .getAsString(); + ArgumentFragment.begin()->Spelling.swap(ProperArgName); +} else { + auto &Spelling = ArgumentFragment.begin()->Spelling; + Spelling.clear(); + raw_string_ostream OutStream(Spelling); + CTA.print(Context.getPrintingPolicy(), OutStream, false); + OutStream.flush(); +} } + Fragments.append(std::move(ArgumentFragment)); break; } @@ -1212,9 +1222,9 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( cast(Decl))) .pop_back() // there is an extra semicolon now .append("<", DeclarationFragments::FragmentKind::Text) - .append( - getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), - Decl->getASTContext(), std::nullopt)) + .append(getFragmentsForTemplateArguments( + Decl->getTemplateArgs().asArray(), Decl->getASTContext(), + Decl->getTemplateArgsAsWritten()->arguments())) .append(">", DeclarationFragments::FragmentKind::Text) .appendSemicolon(); } @@ -1255,9 +1265,9 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) .pop_back() // there is an extra semicolon now .append("<", DeclarationFragments::FragmentKind::Text) - .append( - getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), - Decl->getASTContext(), std::nullopt)) + .append(getFragmentsForTemplateArguments( + Decl->getTemplateArgs().asArray(), Decl->getASTContext(), + Decl->getTemplateArgsAsWritten()->arguments())) .append(">", DeclarationFragments::FragmentKind::Text) .appendSemicolon(); } diff --git a/clang/test/ExtractAPI/non_type_template.cpp b/clang/test/ExtractAPI/non_type_template.cpp index 4e65eb790ca11..85f38e39c82bc 100644 --- a/clang/test/ExtractAPI/non_type_template.cpp +++ b/clang/test/ExtractAPI/non_type_template.cpp @@ -310,4 +310,48 @@ NestedTemplateTemplateParamPack var; // VAR-NEXT: } // VAR-NEXT: ] +template +class TypeContainer { + public: +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TYPE +typedef Foo Type; +// TYPE-LABEL: "!testLabel": "c:non_type_template.cpp@ST>1#T@TypeContainer@T@Type", +// TYPE: "declarationFragments": [ +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "keyword", +// TYPE-NEXT: "spelling": "typedef" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "text", +// TYPE-NEXT: "spelling": " " +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "typeIdentifier", +// TYPE-NEXT: "preciseIdentifier": "c:@ST>2#T#NI@Foo", +// TYPE-NEXT: "spelling": "Foo" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "text", +// TYPE-NEXT: "spelling": "<" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "typeIdentifier", +// TYPE-NEXT: "preciseIdentifier": "c:t0.0", +// TYPE-NEXT: "spelling": "T" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "text", +// TYPE-NEXT: "spelling": "> " +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "identifier", +// TYPE-NEXT: "spelling": "Type" +// TYPE-
[clang] [clang][ExtractAPI] Remove symbols defined in categories to external types unless requested (PR #92522)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/92522 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Remove symbols defined in categories to external types unless requested (PR #92522)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/92522 rdar://128259890 >From 7650c18c883bb14e5a4b17d6b6d61297f2fa3c44 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Fri, 17 May 2024 11:58:18 +0100 Subject: [PATCH] [clang][ExtractAPI] Remove symbols defined in categories to external types unless requested rdar://128259890 --- .../Serialization/SymbolGraphSerializer.h | 9 +++-- .../Serialization/SymbolGraphSerializer.cpp| 11 +-- clang/test/ExtractAPI/objc_external_category.m | 18 +- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h index 724b087f7aea9..27e9167ca1ad0 100644 --- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h +++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h @@ -102,6 +102,8 @@ class SymbolGraphSerializer : public APISetVisitor { const bool EmitSymbolLabelsForTesting = false; + const bool SkipSymbolsInCategoriesToExternalTypes = false; + /// The object instantiated by the last call to serializeAPIRecord. Object *CurrentSymbol = nullptr; @@ -271,10 +273,13 @@ class SymbolGraphSerializer : public APISetVisitor { SymbolGraphSerializer(const APISet &API, const APIIgnoresList &IgnoresList, bool EmitSymbolLabelsForTesting = false, -bool ForceEmitToMainModule = false) +bool ForceEmitToMainModule = false, +bool SkipSymbolsInCategoriesToExternalTypes = false) : Base(API), ForceEmitToMainModule(ForceEmitToMainModule), IgnoresList(IgnoresList), -EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting) {} +EmitSymbolLabelsForTesting(EmitSymbolLabelsForTesting), +SkipSymbolsInCategoriesToExternalTypes( +SkipSymbolsInCategoriesToExternalTypes) {} }; } // namespace extractapi diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index c16d4623f115d..08e711cafae28 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -925,6 +925,10 @@ bool SymbolGraphSerializer::visitObjCInterfaceRecord( bool SymbolGraphSerializer::traverseObjCCategoryRecord( const ObjCCategoryRecord *Record) { + if (SkipSymbolsInCategoriesToExternalTypes && + !API.findRecordForUSR(Record->Interface.USR)) +return true; + auto *CurrentModule = ModuleForCurrentSymbol; if (Record->isExtendingExternalModule()) ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source]; @@ -1040,8 +1044,11 @@ void SymbolGraphSerializer::serializeGraphToStream( void SymbolGraphSerializer::serializeMainSymbolGraph( raw_ostream &OS, const APISet &API, const APIIgnoresList &IgnoresList, SymbolGraphSerializerOption Options) { - SymbolGraphSerializer Serializer(API, IgnoresList, - Options.EmitSymbolLabelsForTesting); + SymbolGraphSerializer Serializer( + API, IgnoresList, Options.EmitSymbolLabelsForTesting, + /*ForceEmitToMainModule=*/true, + /*SkipSymbolsInCategoriesToExternalTypes=*/true); + Serializer.traverseAPISet(); Serializer.serializeGraphToStream(OS, Options, API.ProductName, std::move(Serializer.MainModule)); diff --git a/clang/test/ExtractAPI/objc_external_category.m b/clang/test/ExtractAPI/objc_external_category.m index 47e699cb91c0e..8afc92489f28b 100644 --- a/clang/test/ExtractAPI/objc_external_category.m +++ b/clang/test/ExtractAPI/objc_external_category.m @@ -4,6 +4,9 @@ // RUN: --emit-extension-symbol-graphs --symbol-graph-dir=%t/symbols \ // RUN: --product-name=Module -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/modules-cache \ // RUN: -triple arm64-apple-macosx -x objective-c-header %t/input.h -verify +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: --product-name=Module -o %t/ModuleNoExt.symbols.json -triple arm64-apple-macosx \ +// RUN: -x objective-c-header %t/input.h //--- input.h #include "ExternalModule.h" @@ -28,15 +31,20 @@ @interface ExtInterface header "ExternalModule.h" } +// Main symbol graph from the build with extension SGFs // RUN: FileCheck %s --input-file %t/symbols/Module.symbols.json --check-prefix MOD + // MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(py)Property $ c:objc(cs)ExtInterface" // MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(im)InstanceMethod $ c:objc(cs)ExtInterface" // MOD-NOT: "!testRelLabel": "memberOf $ c:objc(cs)ExtInterface(cm)ClassMethod $ c:objc(cs)ExtInterface" -// MOD-NOT: "!testLabel": "c:objc(cs)ExtInterface(py)P
[clang] [clang][ExtractAPI] Correctly generate declaration fragments for non-type template parameters (PR #91958)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/91958 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [ExtractAPI,test] fix filecheck annotation (PR #92231)
https://github.com/daniel-grumberg approved this pull request. LGTM! Thanks for doing this! https://github.com/llvm/llvm-project/pull/92231 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Correctly generate declaration fragments for non-type template parameters (PR #91958)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/91958 Previously we only generated declaration fragments for template type parameters/arguments, this adds supports for most other possible template parameters/arguments. rdar://127732598 >From d86e4256da57451a08d580b8eecd5525bd1642c6 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Wed, 8 May 2024 12:22:47 +0100 Subject: [PATCH] [clang][ExtractAPI] Correctly generate declaration fragments for non-type template parameters. Previously we only generated declaration fragments for template type paramters/arguments, this adds supports for most other possible template parameters/arguments. rdar://127732598 --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 226 ++--- clang/test/ExtractAPI/class_template.cpp | 2 +- .../class_template_param_inheritance.cpp | 2 +- .../class_template_partial_spec.cpp | 4 +- clang/test/ExtractAPI/class_template_spec.cpp | 4 +- clang/test/ExtractAPI/concept.cpp | 2 +- clang/test/ExtractAPI/field_template.cpp | 2 +- .../test/ExtractAPI/global_func_template.cpp | 4 +- .../ExtractAPI/global_func_template_spec.cpp | 4 +- clang/test/ExtractAPI/global_var_template.cpp | 2 +- .../global_var_template_partial_spec.cpp | 4 +- .../ExtractAPI/global_var_template_spec.cpp | 4 +- clang/test/ExtractAPI/method_template.cpp | 2 +- .../test/ExtractAPI/method_template_spec.cpp | 4 +- clang/test/ExtractAPI/non_type_template.cpp | 313 ++ 15 files changed, 522 insertions(+), 57 deletions(-) create mode 100644 clang/test/ExtractAPI/non_type_template.cpp diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 9bf7950888dbb..98b9343924a83 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -12,13 +12,19 @@ //===--===// #include "clang/ExtractAPI/DeclarationFragments.h" +#include "clang/AST/ASTFwd.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include using namespace clang::extractapi; using namespace llvm; @@ -386,6 +392,25 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( getFragmentsForType(AT->getElementType(), Context, After)); } + if (const TemplateSpecializationType *TemplSpecTy = + dyn_cast(T)) { +const auto TemplName = TemplSpecTy->getTemplateName(); +std::string Str; +raw_string_ostream Stream(Str); +TemplName.print(Stream, Context.getPrintingPolicy(), +TemplateName::Qualified::AsWritten); +SmallString<64> USR(""); +if (const auto *TemplDecl = TemplName.getAsTemplateDecl()) + index::generateUSRForDecl(TemplDecl, USR); + +return Fragments +.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR) +.append("<", DeclarationFragments::FragmentKind::Text) +.append(getFragmentsForTemplateArguments( +TemplSpecTy->template_arguments(), Context, std::nullopt)) +.append(">", DeclarationFragments::FragmentKind::Text); + } + // Everything we care about has been handled now, reduce to the canonical // unqualified base type. QualType Base = T->getCanonicalTypeUnqualified(); @@ -650,7 +675,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock( DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) { DeclarationFragments Fragments; - // FIXME: Handle template specialization switch (Func->getStorageClass()) { case SC_None: case SC_PrivateExtern: @@ -952,27 +976,84 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( Fragments.append(",", DeclarationFragments::FragmentKind::Text) .appendSpace(); -const auto *TemplateParam = -dyn_cast(ParameterArray[i]); -if (!TemplateParam) - continue; -if (TemplateParam->hasTypeConstraint()) - Fragments.append(TemplateParam->getTypeConstraint() - ->getNamedConcept() - ->getName() - .str(), - DeclarationFragments::FragmentKind::TypeIdentifier); -else if (TemplateParam->wasDeclaredWithTypename()) - Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword); -else - Fragments.append("class", DeclarationFragments::FragmentKind::Keyword); - -if (TemplateParam->isParam
[clang] [clang][ExtractAPI] Distinguish between record kind for display and for RTTI (PR #91466)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/91466 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-tools-extra] [flang] [llvm] [mlir] [polly] [test]: fix filecheck annotation typos (PR #91854)
https://github.com/daniel-grumberg approved this pull request. LGTM to me for the ExtractAPI one. https://github.com/llvm/llvm-project/pull/91854 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Distinguish between record kind for display and for RTTI (PR #91466)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/91466 >From a8c7763ed5f36e4faeba5eece2827b2dec010734 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Wed, 8 May 2024 11:55:15 +0100 Subject: [PATCH] [clang][ExtractAPI] Distinguish between record kind for display and for RTTI rdar://127732562 --- clang/include/clang/ExtractAPI/API.h | 7 -- .../clang/ExtractAPI/ExtractAPIVisitor.h | 25 +++ .../Serialization/SymbolGraphSerializer.cpp | 6 ++--- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index d323e1668a72..bf291074fd06 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -266,6 +266,8 @@ struct APIRecord { AccessControl Access; + RecordKind KindForDisplay; + private: const RecordKind Kind; friend class RecordContext; @@ -277,6 +279,7 @@ struct APIRecord { APIRecord *getNextInContext() const { return NextInContext; } RecordKind getKind() const { return Kind; } + RecordKind getKindForDisplay() const { return KindForDisplay; } static APIRecord *castFromRecordContext(const RecordContext *Ctx); static RecordContext *castToRecordContext(const APIRecord *Record); @@ -293,10 +296,10 @@ struct APIRecord { Availability(std::move(Availability)), Linkage(Linkage), Comment(Comment), Declaration(Declaration), SubHeading(SubHeading), IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)), -Kind(Kind) {} +KindForDisplay(Kind), Kind(Kind) {} APIRecord(RecordKind Kind, StringRef USR, StringRef Name) - : USR(USR), Name(Name), Kind(Kind) {} + : USR(USR), Name(Name), KindForDisplay(Kind), Kind(Kind) {} // Pure virtual destructor to make APIRecord abstract virtual ~APIRecord() = 0; diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 97cc457ea2a9..8ccebe457ed5 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -194,6 +194,15 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { return Bases; } + APIRecord::RecordKind getKindForDisplay(const CXXRecordDecl *Decl) { +if (Decl->isUnion()) + return APIRecord::RK_Union; +if (Decl->isStruct()) + return APIRecord::RK_Struct; + +return APIRecord::RK_CXXClass; + } + StringRef getOwningModuleName(const Decl &D) { if (auto *OwningModule = D.getImportedOwningModule()) return OwningModule->Name; @@ -599,13 +608,6 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - APIRecord::RecordKind Kind; - if (Decl->isUnion()) -Kind = APIRecord::RecordKind::RK_Union; - else if (Decl->isStruct()) -Kind = APIRecord::RecordKind::RK_Struct; - else -Kind = APIRecord::RecordKind::RK_CXXClass; auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); CXXClassRecord *Record; @@ -619,13 +621,15 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl( AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, Template(Decl->getDescribedClassTemplate()), Access, isInSystemHeader(Decl)); - } else + } else { Record = API.createRecord( USR, Name, createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, -SubHeading, Kind, Access, isInSystemHeader(Decl), -isEmbeddedInVarDeclarator(*Decl)); +SubHeading, APIRecord::RecordKind::RK_CXXClass, Access, +isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); + } + Record->KindForDisplay = getKindForDisplay(Decl); Record->Bases = getBases(Decl); return true; @@ -849,6 +853,7 @@ bool ExtractAPIVisitorBase:: Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl), isInSystemHeader(Decl)); + CTPSR->KindForDisplay = getKindForDisplay(Decl); CTPSR->Bases = getBases(Decl); return true; diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 34278b5d40c4..c16d4623f115 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -514,7 +514,7 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { /// which is prefixed by the source language name, useful for tooling to parse /// the kind, and a \c displayName for rendering human-readable names. Object serializeSymbolKind(const APIRecord &Record, Language Lang) { - return serializeSymbolKind(Record.getKind(), Lang); + return serializeSymbolKind(Record.KindForDisplay, Lang); } /// Serialize the f
[clang] [clang][ExtractAPI] Distinguish between record kind for display and for RTTI (PR #91466)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/91466 rdar://127732562 >From d1118a8552d84e044cd0f22cd8b46e5e65b43cae Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Wed, 8 May 2024 11:55:15 +0100 Subject: [PATCH] [clang][ExtractAPI] Distinguish between record kind for display and for RTTI --- clang/include/clang/ExtractAPI/API.h | 6 +++-- .../clang/ExtractAPI/ExtractAPIVisitor.h | 23 +++ .../Serialization/SymbolGraphSerializer.cpp | 4 ++-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index d323e1668a72b..d2341f004c52f 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -266,6 +266,7 @@ struct APIRecord { AccessControl Access; + RecordKind KindForDisplay; private: const RecordKind Kind; friend class RecordContext; @@ -277,6 +278,7 @@ struct APIRecord { APIRecord *getNextInContext() const { return NextInContext; } RecordKind getKind() const { return Kind; } + RecordKind getKindForDisplay() const { return KindForDisplay; } static APIRecord *castFromRecordContext(const RecordContext *Ctx); static RecordContext *castToRecordContext(const APIRecord *Record); @@ -293,10 +295,10 @@ struct APIRecord { Availability(std::move(Availability)), Linkage(Linkage), Comment(Comment), Declaration(Declaration), SubHeading(SubHeading), IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)), -Kind(Kind) {} +KindForDisplay(Kind), Kind(Kind) {} APIRecord(RecordKind Kind, StringRef USR, StringRef Name) - : USR(USR), Name(Name), Kind(Kind) {} + : USR(USR), Name(Name), KindForDisplay(Kind), Kind(Kind) {} // Pure virtual destructor to make APIRecord abstract virtual ~APIRecord() = 0; diff --git a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h index 97cc457ea2a92..482a81f750a76 100644 --- a/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h +++ b/clang/include/clang/ExtractAPI/ExtractAPIVisitor.h @@ -194,6 +194,15 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor { return Bases; } + APIRecord::RecordKind getKindForDisplay(const CXXRecordDecl *Decl) { +if (Decl->isUnion()) + return APIRecord::RK_Union; +if (Decl->isStruct()) + return APIRecord::RK_Struct; + +return APIRecord::RK_CXXClass; + } + StringRef getOwningModuleName(const Decl &D) { if (auto *OwningModule = D.getImportedOwningModule()) return OwningModule->Name; @@ -599,13 +608,6 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl( DeclarationFragments SubHeading = DeclarationFragmentsBuilder::getSubHeading(Decl); - APIRecord::RecordKind Kind; - if (Decl->isUnion()) -Kind = APIRecord::RecordKind::RK_Union; - else if (Decl->isStruct()) -Kind = APIRecord::RecordKind::RK_Struct; - else -Kind = APIRecord::RecordKind::RK_CXXClass; auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl); CXXClassRecord *Record; @@ -619,13 +621,15 @@ bool ExtractAPIVisitorBase::VisitCXXRecordDecl( AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, SubHeading, Template(Decl->getDescribedClassTemplate()), Access, isInSystemHeader(Decl)); - } else + } else { Record = API.createRecord( USR, Name, createHierarchyInformationForDecl(*Decl), Loc, AvailabilityInfo::createFromDecl(Decl), Comment, Declaration, -SubHeading, Kind, Access, isInSystemHeader(Decl), +SubHeading, APIRecord::RecordKind::RK_CXXClass, Access, isInSystemHeader(Decl), isEmbeddedInVarDeclarator(*Decl)); + } + Record->KindForDisplay = getKindForDisplay(Decl); Record->Bases = getBases(Decl); return true; @@ -849,6 +853,7 @@ bool ExtractAPIVisitorBase:: Template(Decl), DeclarationFragmentsBuilder::getAccessControl(Decl), isInSystemHeader(Decl)); + CTPSR->KindForDisplay = getKindForDisplay(Decl); CTPSR->Bases = getBases(Decl); return true; diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 34278b5d40c42..952deccded07d 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -514,7 +514,7 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) { /// which is prefixed by the source language name, useful for tooling to parse /// the kind, and a \c displayName for rendering human-readable names. Object serializeSymbolKind(const APIRecord &Record, Language Lang) { - return serializeSymbolKind(Record.getKind(), Lang); + return serializeSymbolKind(Record.KindForDisplay, Lang); } /// Serialize the function signature field, as specified by
[clang] [clang][ExtractAPI] Fix handling of anonymous TagDecls (PR #87772)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/87772 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix handling of anonymous TagDecls (PR #87772)
@@ -54,6 +54,20 @@ RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) { } } +void RecordContext::stealRecordChain(RecordContext &Other) { + // If we don't have an empty chain append Other's chain into ours. + if (First) +Last->NextInContext = Other.First; daniel-grumberg wrote: Documented the invariant that `First` being non-null implies that `Last` is also non-null in an assert above. https://github.com/llvm/llvm-project/pull/87772 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix handling of anonymous TagDecls (PR #87772)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/87772 >From 18912352db31406c7c5b530d6e22f77e775fbf38 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 4 Apr 2024 18:33:25 +0100 Subject: [PATCH 1/3] [clang][ExtractAPI] Fix handling of anonymous TagDecls This changes the handling of anonymous TagDecls to the following rules: - If the TagDecl is embedded in the declaration for some VarDecl (this is the only possibility for RecordDecls), then pretend the child decls belong to the VarDecl - If it's an EnumDecl proceed as we did previously, i.e., embed it in the enclosing DeclContext. Additionally this fixes a few issues with declaration fragments not consistently including "{ ... }" for anonymous TagDecls. To make testing these additions easier this patch fixes some text declaration fragments merging issues and updates tests accordingly. --- clang/include/clang/ExtractAPI/API.h | 132 ++-- clang/include/clang/ExtractAPI/APIRecords.inc | 16 +- .../clang/ExtractAPI/DeclarationFragments.h | 84 ++- .../clang/ExtractAPI/ExtractAPIVisitor.h | 76 ++- clang/lib/ExtractAPI/API.cpp | 8 + clang/lib/ExtractAPI/DeclarationFragments.cpp | 17 +- .../Serialization/SymbolGraphSerializer.cpp | 8 + .../ExtractAPI/anonymous_record_no_typedef.c | 565 +- clang/test/ExtractAPI/enum.c | 12 +- clang/test/ExtractAPI/function_noexcepts.cpp | 18 +- clang/test/ExtractAPI/methods.cpp | 6 +- clang/test/ExtractAPI/objc_block.m| 48 +- .../ExtractAPI/typedef_anonymous_record.c | 4 +- clang/test/ExtractAPI/typedef_struct_enum.c | 2 +- 14 files changed, 427 insertions(+), 569 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index 92cacf65c7d64e..05cfabd072a560 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -208,20 +208,20 @@ struct APIRecord { RK_ClassTemplate, RK_ClassTemplateSpecialization, RK_ClassTemplatePartialSpecialization, -RK_LastRecordContext, -RK_GlobalFunction, -RK_GlobalFunctionTemplate, -RK_GlobalFunctionTemplateSpecialization, +RK_StructField, +RK_UnionField, +RK_CXXField, +RK_StaticField, +RK_CXXFieldTemplate, RK_GlobalVariable, RK_GlobalVariableTemplate, RK_GlobalVariableTemplateSpecialization, RK_GlobalVariableTemplatePartialSpecialization, +RK_LastRecordContext, +RK_GlobalFunction, +RK_GlobalFunctionTemplate, +RK_GlobalFunctionTemplateSpecialization, RK_EnumConstant, -RK_StructField, -RK_UnionField, -RK_StaticField, -RK_CXXField, -RK_CXXFieldTemplate, RK_Concept, RK_CXXStaticMethod, RK_CXXInstanceMethod, @@ -321,6 +321,8 @@ class RecordContext { RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {} + void stealRecordChain(RecordContext &Other); + APIRecord::RecordKind getKind() const { return Kind; } struct record_iterator { @@ -475,7 +477,7 @@ struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord { }; /// This holds information associated with global functions. -struct GlobalVariableRecord : APIRecord { +struct GlobalVariableRecord : APIRecord, RecordContext { GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, @@ -483,23 +485,28 @@ struct GlobalVariableRecord : APIRecord { DeclarationFragments SubHeading, bool IsFromSystemHeader) : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, - SubHeading, IsFromSystemHeader) {} + SubHeading, IsFromSystemHeader), +RecordContext(RK_GlobalVariable) {} GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name, - SymbolReference Parent, - - PresumedLoc Loc, AvailabilityInfo Availability, - LinkageInfo Linkage, const DocComment &Comment, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, LinkageInfo Linkage, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading, - IsFromSystemHeader) {} + IsFromSystemHeader), +RecordContext(Kind) {} static bool classof(const APIRecord *Record) { return classofKind(Record->getKind()); } - static bool classofKind(RecordK
[clang] [clang][ExtractAPI] Fix handling of anonymous TagDecls (PR #87772)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/87772 >From 18912352db31406c7c5b530d6e22f77e775fbf38 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 4 Apr 2024 18:33:25 +0100 Subject: [PATCH 1/2] [clang][ExtractAPI] Fix handling of anonymous TagDecls This changes the handling of anonymous TagDecls to the following rules: - If the TagDecl is embedded in the declaration for some VarDecl (this is the only possibility for RecordDecls), then pretend the child decls belong to the VarDecl - If it's an EnumDecl proceed as we did previously, i.e., embed it in the enclosing DeclContext. Additionally this fixes a few issues with declaration fragments not consistently including "{ ... }" for anonymous TagDecls. To make testing these additions easier this patch fixes some text declaration fragments merging issues and updates tests accordingly. --- clang/include/clang/ExtractAPI/API.h | 132 ++-- clang/include/clang/ExtractAPI/APIRecords.inc | 16 +- .../clang/ExtractAPI/DeclarationFragments.h | 84 ++- .../clang/ExtractAPI/ExtractAPIVisitor.h | 76 ++- clang/lib/ExtractAPI/API.cpp | 8 + clang/lib/ExtractAPI/DeclarationFragments.cpp | 17 +- .../Serialization/SymbolGraphSerializer.cpp | 8 + .../ExtractAPI/anonymous_record_no_typedef.c | 565 +- clang/test/ExtractAPI/enum.c | 12 +- clang/test/ExtractAPI/function_noexcepts.cpp | 18 +- clang/test/ExtractAPI/methods.cpp | 6 +- clang/test/ExtractAPI/objc_block.m| 48 +- .../ExtractAPI/typedef_anonymous_record.c | 4 +- clang/test/ExtractAPI/typedef_struct_enum.c | 2 +- 14 files changed, 427 insertions(+), 569 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index 92cacf65c7d64e..05cfabd072a560 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -208,20 +208,20 @@ struct APIRecord { RK_ClassTemplate, RK_ClassTemplateSpecialization, RK_ClassTemplatePartialSpecialization, -RK_LastRecordContext, -RK_GlobalFunction, -RK_GlobalFunctionTemplate, -RK_GlobalFunctionTemplateSpecialization, +RK_StructField, +RK_UnionField, +RK_CXXField, +RK_StaticField, +RK_CXXFieldTemplate, RK_GlobalVariable, RK_GlobalVariableTemplate, RK_GlobalVariableTemplateSpecialization, RK_GlobalVariableTemplatePartialSpecialization, +RK_LastRecordContext, +RK_GlobalFunction, +RK_GlobalFunctionTemplate, +RK_GlobalFunctionTemplateSpecialization, RK_EnumConstant, -RK_StructField, -RK_UnionField, -RK_StaticField, -RK_CXXField, -RK_CXXFieldTemplate, RK_Concept, RK_CXXStaticMethod, RK_CXXInstanceMethod, @@ -321,6 +321,8 @@ class RecordContext { RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {} + void stealRecordChain(RecordContext &Other); + APIRecord::RecordKind getKind() const { return Kind; } struct record_iterator { @@ -475,7 +477,7 @@ struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord { }; /// This holds information associated with global functions. -struct GlobalVariableRecord : APIRecord { +struct GlobalVariableRecord : APIRecord, RecordContext { GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, @@ -483,23 +485,28 @@ struct GlobalVariableRecord : APIRecord { DeclarationFragments SubHeading, bool IsFromSystemHeader) : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, - SubHeading, IsFromSystemHeader) {} + SubHeading, IsFromSystemHeader), +RecordContext(RK_GlobalVariable) {} GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name, - SymbolReference Parent, - - PresumedLoc Loc, AvailabilityInfo Availability, - LinkageInfo Linkage, const DocComment &Comment, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, LinkageInfo Linkage, + const DocComment &Comment, DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader) : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading, - IsFromSystemHeader) {} + IsFromSystemHeader), +RecordContext(Kind) {} static bool classof(const APIRecord *Record) { return classofKind(Record->getKind()); } - static bool classofKind(RecordK
[clang] [clang][ExtractAPI] Serialize platform specific unavailable attribute in symbol graphs (PR #89277)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/89277 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix handling of anonymous TagDecls (PR #87772)
@@ -54,6 +54,13 @@ RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) { } } +void RecordContext::stealRecordChain(RecordContext &Other) { + First = Other.First; + Last = Other.Last; + Other.First = nullptr; + Other.Last = nullptr; +} daniel-grumberg wrote: There is no harm in "stealing" an empty record chain, and it's not necessarily even semantically wrong, all it indicates is that the current RecordContext won't have any children during any traversals. Semantic problems would still be caught by having a test. https://github.com/llvm/llvm-project/pull/87772 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Update ExtractAPIConsumer.cpp (PR #88285)
https://github.com/daniel-grumberg approved this pull request. LGTM! https://github.com/llvm/llvm-project/pull/88285 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix handling of anonymous TagDecls (PR #87772)
@@ -54,6 +54,13 @@ RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) { } } +void RecordContext::stealRecordChain(RecordContext &Other) { + First = Other.First; + Last = Other.Last; + Other.First = nullptr; + Other.Last = nullptr; +} daniel-grumberg wrote: Maybe a better name for this would be `transferRecordChain`? https://github.com/llvm/llvm-project/pull/87772 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Fix handling of anonymous TagDecls (PR #87772)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/87772 This changes the handling of anonymous TagDecls to the following rules: - If the TagDecl is embedded in the declaration for some VarDecl (this is the only possibility for RecordDecls), then pretend the child decls belong to the VarDecl - If it's an EnumDecl proceed as we did previously, i.e., embed it in the enclosing DeclContext. Additionally this fixes a few issues with declaration fragments not consistently including "{ ... }" for anonymous TagDecls. To make testing these additions easier this patch fixes some text declaration fragments merging issues and updates tests accordingly. >From f2755070ead054c56f7e9f9a2084ec40c10968bf Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 4 Apr 2024 18:33:25 +0100 Subject: [PATCH] [clang][ExtractAPI] Fix handling of anonymous TagDecls This changes the handling of anonymous TagDecls to the following rules: - If the TagDecl is embedded in the declaration for some VarDecl (this is the only possibility for RecordDecls), then pretend the child decls belong to the VarDecl - If it's an EnumDecl proceed as we did previously, i.e., embed it in the enclosing DeclContext. Additionally this fixes a few issues with declaration fragments not consistently including "{ ... }" for anonymous TagDecls. To make testing these additions easier this patch fixes some text declaration fragments merging issues and updates tests accordingly. --- clang/include/clang/ExtractAPI/API.h | 132 ++-- clang/include/clang/ExtractAPI/APIRecords.inc | 16 +- .../clang/ExtractAPI/DeclarationFragments.h | 84 ++- .../clang/ExtractAPI/ExtractAPIVisitor.h | 76 ++- clang/lib/ExtractAPI/API.cpp | 8 + clang/lib/ExtractAPI/DeclarationFragments.cpp | 17 +- .../Serialization/SymbolGraphSerializer.cpp | 8 + .../ExtractAPI/anonymous_record_no_typedef.c | 565 +- clang/test/ExtractAPI/enum.c | 12 +- clang/test/ExtractAPI/function_noexcepts.cpp | 18 +- clang/test/ExtractAPI/methods.cpp | 6 +- clang/test/ExtractAPI/objc_block.m| 48 +- .../ExtractAPI/typedef_anonymous_record.c | 4 +- clang/test/ExtractAPI/typedef_struct_enum.c | 2 +- 14 files changed, 427 insertions(+), 569 deletions(-) diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index 92cacf65c7d64e..05cfabd072a560 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -208,20 +208,20 @@ struct APIRecord { RK_ClassTemplate, RK_ClassTemplateSpecialization, RK_ClassTemplatePartialSpecialization, -RK_LastRecordContext, -RK_GlobalFunction, -RK_GlobalFunctionTemplate, -RK_GlobalFunctionTemplateSpecialization, +RK_StructField, +RK_UnionField, +RK_CXXField, +RK_StaticField, +RK_CXXFieldTemplate, RK_GlobalVariable, RK_GlobalVariableTemplate, RK_GlobalVariableTemplateSpecialization, RK_GlobalVariableTemplatePartialSpecialization, +RK_LastRecordContext, +RK_GlobalFunction, +RK_GlobalFunctionTemplate, +RK_GlobalFunctionTemplateSpecialization, RK_EnumConstant, -RK_StructField, -RK_UnionField, -RK_StaticField, -RK_CXXField, -RK_CXXFieldTemplate, RK_Concept, RK_CXXStaticMethod, RK_CXXInstanceMethod, @@ -321,6 +321,8 @@ class RecordContext { RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {} + void stealRecordChain(RecordContext &Other); + APIRecord::RecordKind getKind() const { return Kind; } struct record_iterator { @@ -475,7 +477,7 @@ struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord { }; /// This holds information associated with global functions. -struct GlobalVariableRecord : APIRecord { +struct GlobalVariableRecord : APIRecord, RecordContext { GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, AvailabilityInfo Availability, LinkageInfo Linkage, const DocComment &Comment, @@ -483,23 +485,28 @@ struct GlobalVariableRecord : APIRecord { DeclarationFragments SubHeading, bool IsFromSystemHeader) : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc, std::move(Availability), Linkage, Comment, Declaration, - SubHeading, IsFromSystemHeader) {} + SubHeading, IsFromSystemHeader), +RecordContext(RK_GlobalVariable) {} GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name, - SymbolReference Parent, - - PresumedLoc Loc, AvailabilityInfo Availability, - LinkageInfo Linkage, const DocComment &Comment, + SymbolReference Parent, PresumedLoc Loc, + AvailabilityInfo Availability, Li
[clang] [clang][ExtractAPI] Add ability to create multiple symbol graphs (PR #86676)
daniel-grumberg wrote: Just reverted this due to buildbot failures in `Misc/warning-flags.c` will reenable shortly. https://github.com/llvm/llvm-project/pull/86676 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] improve template argument name deduction (PR #77716)
https://github.com/daniel-grumberg approved this pull request. https://github.com/llvm/llvm-project/pull/77716 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add ability to create multiple symbol graphs (PR #86676)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/86676 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add ability to create multiple symbol graphs (PR #86676)
https://github.com/daniel-grumberg deleted https://github.com/llvm/llvm-project/pull/86676 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add ability to create multiple symbol graphs (PR #86676)
@@ -119,20 +78,12 @@ static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor, break; #include "clang/AST/DeclNodes.inc" } - - for (auto *Parent = D->getDeclContext(); Parent != nullptr; - Parent = Parent->getParent()) { -if (WalkupParentContext(Parent, Visitor)) daniel-grumberg wrote: Restore this logic for objc types? https://github.com/llvm/llvm-project/pull/86676 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add ability to create multiple symbol graphs (PR #86676)
@@ -54,63 +55,21 @@ struct LibClangExtractAPIVisitor if (!shouldDeclBeIncluded(Decl)) return true; -const ObjCInterfaceDecl *Interface = Decl->getClassInterface(); -StringRef Name = Interface->getName(); -StringRef USR = API.recordUSR(Decl); -PresumedLoc Loc = -Context.getSourceManager().getPresumedLoc(Decl->getLocation()); -LinkageInfo Linkage = Decl->getLinkageAndVisibility(); -DocComment Comment; -if (auto *RawComment = fetchRawCommentForDecl(Interface)) - Comment = RawComment->getFormattedLines(Context.getSourceManager(), - Context.getDiagnostics()); - -// Build declaration fragments and sub-heading by generating them for the -// interface. -DeclarationFragments Declaration = -DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Interface); -DeclarationFragments SubHeading = -DeclarationFragmentsBuilder::getSubHeading(Decl); - -// Collect super class information. -SymbolReference SuperClass; -if (const auto *SuperClassDecl = Decl->getSuperClass()) { - SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString(); - SuperClass.USR = API.recordUSR(SuperClassDecl); -} - -ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface( -Name, USR, Loc, AvailabilityInfo::createFromDecl(Decl), Linkage, -Comment, Declaration, SubHeading, SuperClass, isInSystemHeader(Decl)); - -// Record all methods (selectors). This doesn't include automatically -// synthesized property methods. -recordObjCMethods(ObjCInterfaceRecord, Decl->methods()); -recordObjCProperties(ObjCInterfaceRecord, Decl->properties()); -recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars()); - -return true; +return VisitObjCInterfaceDecl(Decl->getClassInterface()); daniel-grumberg wrote: Restore logic to grab symbols defined only in the implementation. First visit the interface and then add the things only defined in the implementation block to the interface record. https://github.com/llvm/llvm-project/pull/86676 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add ability to create multiple symbol graphs (PR #86676)
@@ -50,17 +51,20 @@ TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type, SmallString<128> TypeUSR; const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type); const TypedefType *TypedefTy = Type->getAs(); + StringRef OwningModuleName; if (TypeDecl) { if (!TypedefTy) TypeName = TypeDecl->getName().str(); clang::index::generateUSRForDecl(TypeDecl, TypeUSR); +if (auto *OwningModule = TypeDecl->getImportedOwningModule()) + OwningModuleName = API.copyString(OwningModule->Name); } else { clang::index::generateUSRForType(Type, Context, TypeUSR); } - return {API.copyString(TypeName), API.copyString(TypeUSR)}; + return {API.copyString(TypeName), API.copyString(TypeUSR), OwningModuleName}; daniel-grumberg wrote: TODO: Can this be expressed as APISet.createSymbolReference https://github.com/llvm/llvm-project/pull/86676 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] improve template argument name deduction (PR #77716)
@@ -1127,7 +1096,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization( .append("<", DeclarationFragments::FragmentKind::Text) .append(getFragmentsForTemplateArguments( Decl->getTemplateArgs().asArray(), Decl->getASTContext(), - Decl->getTemplateParameters()->asArray())) + Decl->getTemplateArgsAsWritten()->arguments())) daniel-grumberg wrote: Looks like the right thing to me! https://github.com/llvm/llvm-project/pull/77716 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Ensure typedef to pointer types are preserved (PR #78584)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/78584 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add support C unions in non C++ parsing mode (PR #77451)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/77451 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add support C unions in non C++ parsing mode (PR #77451)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/77451 >From 8ff189e707a909f5228bce2042812a45a98d1e6c Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 9 Jan 2024 12:06:14 + Subject: [PATCH] [clang][ExtractAPI] Add support C unions in non C++ parsing mode Ensure that we generate correct symbol kinds and declaration fragments for unions in C and Objective-C parsing modes. rdar://120544091 --- clang/include/clang/ExtractAPI/API.h | 48 +-- .../clang/ExtractAPI/DeclarationFragments.h | 5 +- .../clang/ExtractAPI/ExtractAPIVisitor.h | 42 ++- .../ExtractAPI/Serialization/SerializerBase.h | 12 +- .../Serialization/SymbolGraphSerializer.h | 4 +- clang/lib/ExtractAPI/API.cpp | 35 ++- clang/lib/ExtractAPI/DeclarationFragments.cpp | 9 +- .../Serialization/SymbolGraphSerializer.cpp | 18 +- clang/test/ExtractAPI/union.c | 281 ++ 9 files changed, 380 insertions(+), 74 deletions(-) create mode 100644 clang/test/ExtractAPI/union.c diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index f4a6374161685e2..0a0f1bd1e95f7fe 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -169,6 +169,7 @@ struct APIRecord { RK_Enum, RK_StructField, RK_Struct, +RK_UnionField, RK_Union, RK_StaticField, RK_CXXField, @@ -478,17 +479,19 @@ struct EnumRecord : APIRecord { }; /// This holds information associated with struct fields. -struct StructFieldRecord : APIRecord { - StructFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, +struct RecordFieldRecord : APIRecord { + RecordFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, -DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_StructField, USR, Name, Loc, std::move(Availability), +DeclarationFragments SubHeading, RecordKind Kind, +bool IsFromSystemHeader) + : APIRecord(Kind, USR, Name, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { -return Record->getKind() == RK_StructField; +return Record->getKind() == RK_StructField || + Record->getKind() == RK_UnionField; } private: @@ -496,19 +499,20 @@ struct StructFieldRecord : APIRecord { }; /// This holds information associated with structs. -struct StructRecord : APIRecord { - SmallVector> Fields; +struct RecordRecord : APIRecord { + SmallVector> Fields; - StructRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + RecordRecord(StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_Struct, USR, Name, Loc, std::move(Availability), + DeclarationFragments SubHeading, RecordKind Kind, + bool IsFromSystemHeader) + : APIRecord(Kind, USR, Name, Loc, std::move(Availability), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { -return Record->getKind() == RK_Struct; +return Record->getKind() == RK_Struct || Record->getKind() == RK_Union; } private: @@ -1266,30 +1270,31 @@ class APISet { DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader); - /// Create and add a struct field record into the API set. + /// Create and add a record field record into the API set. /// /// Note: the caller is responsible for keeping the StringRef \p Name and /// \p USR alive. APISet::copyString provides a way to copy strings into /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method /// to generate the USR for \c D and keep it alive in APISet. - StructFieldRecord * - addStructField(StructRecord *Struct, StringRef Name, StringRef USR, + RecordFieldRecord * + addRecordField(RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader); + DeclarationFragments SubHeading, APIRecord::RecordKind Kind, + bool IsFromSystemHeader); - /// Create and add a struct record into the API set. + /// Create and add a record record into the API set. /// /// Note: the
[clang] [clang][ExtractAPI] Record availability information only for the target platform (PR #76823)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/76823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Ensure typedef to pointer types are preserved (PR #78584)
daniel-grumberg wrote: That and the typedef case before the pointer case. The pointer check would lead to extraneous desugaring in the fragments, i.e. you would get something like `struct Bar * value`, because the typedefs are also pointer types and therefore the typedef name would get bypassed in favor of the form "PointeeType *" https://github.com/llvm/llvm-project/pull/78584 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Ensure typedef to pointer types are preserved (PR #78584)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/78584 When generating declaration fragments for types that use typedefs to pointer types ensure that we keep the user-defined typedef form instead of desugaring the typedef. rdar://102137655 >From d3c4ca8092fcec8c8ebea26826cdf7e724edf7a7 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 18 Jan 2024 13:13:13 + Subject: [PATCH] [clang][ExtractAPI] Ensure typedef to pointer types are preserved When generating declaration fragments for types that use typedefs to pointer types ensure that we keep the user-defined typedef form instead of desugaring the typedef. rdar://102137655 --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 80 ++--- clang/test/ExtractAPI/typedef.c | 280 ++ 2 files changed, 320 insertions(+), 40 deletions(-) diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index eb6eea0aaf5465..ae6b2eff5c8a29 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -252,6 +252,46 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( DeclarationFragments Fragments; + // An ElaboratedType is a sugar for types that are referred to using an + // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a + // qualified name, e.g., `N::M::type`, or both. + if (const ElaboratedType *ET = dyn_cast(T)) { +ElaboratedTypeKeyword Keyword = ET->getKeyword(); +if (Keyword != ElaboratedTypeKeyword::None) { + Fragments + .append(ElaboratedType::getKeywordName(Keyword), + DeclarationFragments::FragmentKind::Keyword) + .appendSpace(); +} + +if (const NestedNameSpecifier *NNS = ET->getQualifier()) + Fragments.append(getFragmentsForNNS(NNS, Context, After)); + +// After handling the elaborated keyword or qualified name, build +// declaration fragments for the desugared underlying type. +return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); + } + + // If the type is a typedefed type, get the underlying TypedefNameDecl for a + // direct reference to the typedef instead of the wrapped type. + + // 'id' type is a typedef for an ObjCObjectPointerType + // we treat it as a typedef + if (const TypedefType *TypedefTy = dyn_cast(T)) { +const TypedefNameDecl *Decl = TypedefTy->getDecl(); +TypedefUnderlyingTypeResolver TypedefResolver(Context); +std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); + +if (T->isObjCIdType()) { + return Fragments.append(Decl->getName(), + DeclarationFragments::FragmentKind::Keyword); +} + +return Fragments.append( +Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, +USR, TypedefResolver.getUnderlyingTypeDecl(QualType(T, 0))); + } + // Declaration fragments of a pointer type is the declaration fragments of // the pointee type followed by a `*`, if (T->isPointerType() && !T->isFunctionPointerType()) @@ -328,46 +368,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( getFragmentsForType(AT->getElementType(), Context, After)); } - // An ElaboratedType is a sugar for types that are referred to using an - // elaborated keyword, e.g., `struct S`, `enum E`, or (in C++) via a - // qualified name, e.g., `N::M::type`, or both. - if (const ElaboratedType *ET = dyn_cast(T)) { -ElaboratedTypeKeyword Keyword = ET->getKeyword(); -if (Keyword != ElaboratedTypeKeyword::None) { - Fragments - .append(ElaboratedType::getKeywordName(Keyword), - DeclarationFragments::FragmentKind::Keyword) - .appendSpace(); -} - -if (const NestedNameSpecifier *NNS = ET->getQualifier()) - Fragments.append(getFragmentsForNNS(NNS, Context, After)); - -// After handling the elaborated keyword or qualified name, build -// declaration fragments for the desugared underlying type. -return Fragments.append(getFragmentsForType(ET->desugar(), Context, After)); - } - - // If the type is a typedefed type, get the underlying TypedefNameDecl for a - // direct reference to the typedef instead of the wrapped type. - - // 'id' type is a typedef for an ObjCObjectPointerType - // we treat it as a typedef - if (const TypedefType *TypedefTy = dyn_cast(T)) { -const TypedefNameDecl *Decl = TypedefTy->getDecl(); -TypedefUnderlyingTypeResolver TypedefResolver(Context); -std::string USR = TypedefResolver.getUSRForType(QualType(T, 0)); - -if (T->isObjCIdType()) { - return Fragments.append(Decl->getName(), - DeclarationFragments::FragmentKind::Keyword); -} - -return Fragments.append( -Decl->getName(), DeclarationFragments::FragmentKind::TypeIdentifier, -USR, TypedefResolver.g
[clang] [clang][ExtractAPI] Record availability information only for the target platform (PR #76823)
https://github.com/daniel-grumberg approved this pull request. https://github.com/llvm/llvm-project/pull/76823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Record availability information only for the target platform (PR #76823)
@@ -16,67 +16,61 @@ #define LLVM_CLANG_EXTRACTAPI_AVAILABILITY_INFO_H #include "clang/AST/Decl.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Error.h" #include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" - -using llvm::VersionTuple; +#include daniel-grumberg wrote: I don't think this is needed? https://github.com/llvm/llvm-project/pull/76823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add support C unions in non C++ parsing mode (PR #77451)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/77451 >From 9ed6ab49d39df12b95c65d48d065e82672dba48f Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 9 Jan 2024 12:06:14 + Subject: [PATCH] [clang][ExtractAPI] Add support C unions in non C++ parsing mode Ensure that we generate correct symbol kinds and declaration fragments for unions in C and Objective-C parsing modes. rdar://120544091 --- clang/include/clang/ExtractAPI/API.h | 48 +-- .../clang/ExtractAPI/DeclarationFragments.h | 5 +- .../clang/ExtractAPI/ExtractAPIVisitor.h | 39 ++- .../ExtractAPI/Serialization/SerializerBase.h | 12 +- .../Serialization/SymbolGraphSerializer.h | 4 +- clang/lib/ExtractAPI/API.cpp | 35 ++- clang/lib/ExtractAPI/DeclarationFragments.cpp | 9 +- .../Serialization/SymbolGraphSerializer.cpp | 18 +- clang/test/ExtractAPI/union.c | 281 ++ 9 files changed, 378 insertions(+), 73 deletions(-) create mode 100644 clang/test/ExtractAPI/union.c diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index b4c0e0ad39cdf2..a86654dd64bec5 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -169,6 +169,7 @@ struct APIRecord { RK_Enum, RK_StructField, RK_Struct, +RK_UnionField, RK_Union, RK_StaticField, RK_CXXField, @@ -478,17 +479,19 @@ struct EnumRecord : APIRecord { }; /// This holds information associated with struct fields. -struct StructFieldRecord : APIRecord { - StructFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, +struct RecordFieldRecord : APIRecord { + RecordFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, -DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_StructField, USR, Name, Loc, std::move(Availabilities), +DeclarationFragments SubHeading, RecordKind Kind, +bool IsFromSystemHeader) + : APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { -return Record->getKind() == RK_StructField; +return Record->getKind() == RK_StructField || + Record->getKind() == RK_UnionField; } private: @@ -496,19 +499,20 @@ struct StructFieldRecord : APIRecord { }; /// This holds information associated with structs. -struct StructRecord : APIRecord { - SmallVector> Fields; +struct RecordRecord : APIRecord { + SmallVector> Fields; - StructRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + RecordRecord(StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_Struct, USR, Name, Loc, std::move(Availabilities), + DeclarationFragments SubHeading, RecordKind Kind, + bool IsFromSystemHeader) + : APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { -return Record->getKind() == RK_Struct; +return Record->getKind() == RK_Struct || Record->getKind() == RK_Union; } private: @@ -1267,30 +1271,31 @@ class APISet { DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader); - /// Create and add a struct field record into the API set. + /// Create and add a record field record into the API set. /// /// Note: the caller is responsible for keeping the StringRef \p Name and /// \p USR alive. APISet::copyString provides a way to copy strings into /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method /// to generate the USR for \c D and keep it alive in APISet. - StructFieldRecord * - addStructField(StructRecord *Struct, StringRef Name, StringRef USR, + RecordFieldRecord * + addRecordField(RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader); + DeclarationFragments SubHeading, APIRecord::RecordKind Kind, + bool IsFromSystemHeader); - /// Create and add a struct record into the API set. + /// Create and add a record record into the API set. /// /// No
[clang] [clang][ExtractAPI] improve template argument name deduction (PR #77716)
@@ -196,8 +196,7 @@ template class Foo {}; "spelling": "<" }, { - "kind": "typeIdentifier", - "preciseIdentifier": "c:t0.0", + "kind": "genericArgument", daniel-grumberg wrote: might be best to leave these as generic text fragments https://github.com/llvm/llvm-project/pull/77716 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Record availability information only for the target platform (PR #76823)
@@ -1,50 +1,33 @@ #include "clang/ExtractAPI/AvailabilityInfo.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/Basic/TargetInfo.h" #include "llvm/ADT/STLExtras.h" using namespace clang; using namespace extractapi; -AvailabilitySet::AvailabilitySet(const Decl *Decl) { - // Collect availability attributes from all redeclrations. - for (const auto *RD : Decl->redecls()) { -if (const auto *A = RD->getAttr()) { - if (!A->isImplicit()) { -this->Availabilities.clear(); -UnconditionallyUnavailable = true; - } -} +AvailabilityInfo::AvailabilityInfo(const Decl *Decl) { daniel-grumberg wrote: I would prefer if this wasn't a constructor but rather a static type method of with signature: ```c++ AvailabilityInfo createFromDecl(const Decl *D); ``` that way you don't have to do line 19-21 in that way. https://github.com/llvm/llvm-project/pull/76823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add support C unions in non C++ parsing mode (PR #77451)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/77451 Ensure that we generate correct symbol kinds and declaration fragments for unions in C and Objective-C parsing modes. rdar://120544091 >From 23d0713ba8003731cf03d2226c2cb3000411554f Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Tue, 9 Jan 2024 12:06:14 + Subject: [PATCH] [clang][ExtractAPI] Add support C unions in non C++ parsing mode Ensure that we generate correct symbol kinds and declaration fragments for unions in C and Objective-C parsing modes. rdar://120544091 --- clang/include/clang/ExtractAPI/API.h | 46 +-- .../clang/ExtractAPI/DeclarationFragments.h | 5 +- .../clang/ExtractAPI/ExtractAPIVisitor.h | 39 ++- .../ExtractAPI/Serialization/SerializerBase.h | 12 +- .../Serialization/SymbolGraphSerializer.h | 4 +- clang/lib/ExtractAPI/API.cpp | 35 ++- clang/lib/ExtractAPI/DeclarationFragments.cpp | 9 +- .../Serialization/SymbolGraphSerializer.cpp | 18 +- clang/test/ExtractAPI/union.c | 281 ++ 9 files changed, 377 insertions(+), 72 deletions(-) create mode 100644 clang/test/ExtractAPI/union.c diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index b4c0e0ad39cdf2..3bd3162da89a82 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -169,6 +169,7 @@ struct APIRecord { RK_Enum, RK_StructField, RK_Struct, +RK_UnionField, RK_Union, RK_StaticField, RK_CXXField, @@ -478,17 +479,19 @@ struct EnumRecord : APIRecord { }; /// This holds information associated with struct fields. -struct StructFieldRecord : APIRecord { - StructFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, +struct RecordFieldRecord : APIRecord { + RecordFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, -DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_StructField, USR, Name, Loc, std::move(Availabilities), +DeclarationFragments SubHeading, RecordKind Kind, +bool IsFromSystemHeader) + : APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { -return Record->getKind() == RK_StructField; +return Record->getKind() == RK_StructField || + Record->getKind() == RK_UnionField; } private: @@ -496,19 +499,20 @@ struct StructFieldRecord : APIRecord { }; /// This holds information associated with structs. -struct StructRecord : APIRecord { - SmallVector> Fields; +struct RecordRecord : APIRecord { + SmallVector> Fields; - StructRecord(StringRef USR, StringRef Name, PresumedLoc Loc, + RecordRecord(StringRef USR, StringRef Name, PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader) - : APIRecord(RK_Struct, USR, Name, Loc, std::move(Availabilities), + DeclarationFragments SubHeading, RecordKind Kind, + bool IsFromSystemHeader) + : APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), LinkageInfo::none(), Comment, Declaration, SubHeading, IsFromSystemHeader) {} static bool classof(const APIRecord *Record) { -return Record->getKind() == RK_Struct; +return Record->getKind() == RK_Struct || Record->getKind() == RK_Union; } private: @@ -1267,17 +1271,18 @@ class APISet { DeclarationFragments Declaration, DeclarationFragments SubHeading, bool IsFromSystemHeader); - /// Create and add a struct field record into the API set. + /// Create and add a record field record into the API set. /// /// Note: the caller is responsible for keeping the StringRef \p Name and /// \p USR alive. APISet::copyString provides a way to copy strings into /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method /// to generate the USR for \c D and keep it alive in APISet. - StructFieldRecord * - addStructField(StructRecord *Struct, StringRef Name, StringRef USR, + RecordFieldRecord * + addRecordField(RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment, DeclarationFragments Declaration, - DeclarationFragments SubHeading, bool IsFromSystemHeader); + DeclarationFragments SubHeading, APIRecord::RecordKind Kind, + bool IsFromSystemH
[clang] [clang][ExtractAPI] Record availability information only for the target platform (PR #76823)
@@ -256,14 +256,14 @@ struct APIRecord { APIRecord() = delete; APIRecord(RecordKind Kind, StringRef USR, StringRef Name, -PresumedLoc Location, AvailabilitySet Availabilities, +PresumedLoc Location, const AvailabilityInfo &Availability, daniel-grumberg wrote: Can you keep this as a value and bring back the `std::move` below, this allows to prevent unnecessary copies. https://github.com/llvm/llvm-project/pull/76823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Record availability information only for the target platform (PR #76823)
@@ -61,17 +61,17 @@ APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR, GlobalVariableRecord * APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc, - AvailabilitySet Availabilities, LinkageInfo Linkage, + const AvailabilityInfo &Availability, LinkageInfo Linkage, const DocComment &Comment, DeclarationFragments Fragments, DeclarationFragments SubHeading, bool IsFromSystemHeader) { return addTopLevelRecord(USRBasedLookupTable, GlobalVariables, USR, Name, Loc, - std::move(Availabilities), Linkage, Comment, - Fragments, SubHeading, IsFromSystemHeader); + Availability, Linkage, Comment, Fragments, daniel-grumberg wrote: Can you make sure that all of Availabilities are `std::move` https://github.com/llvm/llvm-project/pull/76823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Record availability information only for the target platform (PR #76823)
@@ -45,7 +45,7 @@ RecordTy *addTopLevelRecord(DenseMap &USRLookupTable, NamespaceRecord * APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR, - PresumedLoc Loc, AvailabilitySet Availability, + PresumedLoc Loc, const AvailabilityInfo &Availability, daniel-grumberg wrote: Can we keep these as plain values (i.e. just `AvailabilityInfo Availability`), this prevents the move operation below and leads to a copy. Additionally, this prevents copy ellision with how we pass the parameters in. https://github.com/llvm/llvm-project/pull/76823 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Allow serialization for ObjC++ headers (PR #74733)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/74733 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Allow serialization for ObjC++ headers (PR #74733)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/74733 rdar://79874441 >From 87d6b0fca621bae69102161fa4c3ebc003ae27bc Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Thu, 7 Dec 2023 14:52:47 + Subject: [PATCH] [clang][ExtractAPI] Allow serialization for ObjC++ headers rdar://79874441 --- .../Serialization/SymbolGraphSerializer.cpp | 3 +- clang/test/ExtractAPI/language.c | 101 +- 2 files changed, 101 insertions(+), 3 deletions(-) diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 931933b2bd1ac..d9675b0c94de3 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -199,9 +199,10 @@ StringRef getLanguageName(Language Lang) { return "objective-c"; case Language::CXX: return "c++"; + case Language::ObjCXX: +return "objective-c++"; // Unsupported language currently - case Language::ObjCXX: case Language::OpenCL: case Language::OpenCLCXX: case Language::CUDA: diff --git a/clang/test/ExtractAPI/language.c b/clang/test/ExtractAPI/language.c index 6facd18f5d981..fe98626c84613 100644 --- a/clang/test/ExtractAPI/language.c +++ b/clang/test/ExtractAPI/language.c @@ -4,29 +4,42 @@ // RUN: %t/c.reference.output.json.in >> %t/c.reference.output.json // RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ // RUN: %t/objc.reference.output.json.in >> %t/objc.reference.output.json +// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \ +// RUN: %t/objcpp.reference.output.json.in >> %t/objcpp.reference.output.json -// RUN: %clang -extract-api -x c-header -target arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api -x c-header -triple arm64-apple-macosx \ // RUN: %t/c.h -o %t/c.output.json | FileCheck -allow-empty %s -// RUN: %clang -extract-api -x objective-c-header -target arm64-apple-macosx \ +// RUN: %clang_cc1 -extract-api -x objective-c-header -triple arm64-apple-macosx \ // RUN: %t/objc.h -o %t/objc.output.json | FileCheck -allow-empty %s +// RUN: %clang_cc1 -extract-api -x objective-c++-header -triple arm64-apple-macosx \ +// RUN: %t/objcpp.h -o %t/objcpp.output.json | FileCheck -allow-empty %s // Generator version is not consistent across test runs, normalize it. // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ // RUN: %t/c.output.json >> %t/c.output-normalized.json // RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ // RUN: %t/objc.output.json >> %t/objc.output-normalized.json +// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \ +// RUN: %t/objcpp.output.json >> %t/objcpp.output-normalized.json // RUN: diff %t/c.reference.output.json %t/c.output-normalized.json // RUN: diff %t/objc.reference.output.json %t/objc.output-normalized.json +// RUN: diff %t/objcpp.reference.output.json %t/objcpp.output-normalized.json // CHECK-NOT: error: // CHECK-NOT: warning: //--- c.h char c; +///expected-no-diagnostics //--- objc.h char objc; +///expected-no-diagnostics + +//--- objcpp.h +char objcpp; +///expected-no-diagnostics //--- c.reference.output.json.in { @@ -196,3 +209,87 @@ char objc; } ] } +//--- objcpp.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": [], + "symbols": [ +{ + "accessLevel": "public", + "declarationFragments": [ +{ + "kind": "typeIdentifier", + "preciseIdentifier": "c:C", + "spelling": "char" +}, +{ + "kind": "text", + "spelling": " " +}, +{ + "kind": "identifier", + "spelling": "objcpp" +}, +{ + "kind": "text", + "spelling": ";" +} + ], + "identifier": { +"interfaceLanguage": "objective-c++", +"precise": "c:@objcpp" + }, + "kind": { +"displayName": "Global Variable", +"identifier": "objective-c++.var" + }, + "location": { +"position": { + "character": 5, + "line": 0 +}, +"uri": "file://INPUT_DIR/objcpp.h" + }, + "names": { +"navigator": [ + { +"kind": "identifier", +"spelling": "objcpp" + } +], +"subHeading": [ + { +"kind": "identifier", +"spelling": "objcpp" + } +], +"title": "objcpp" + }, + "pathCompon
[clang] [clang][ExtractAPI] Ensure LocationFileChecker doesn't try to traverse VFS when determining file path (PR #74071)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/74071 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Ensure LocationFileChecker doesn't try to traverse VFS when determining file path (PR #74071)
daniel-grumberg wrote: Awesome! Let me know if you need any clarification as the semantic is now different from what it was originally and what it was after your patch. https://github.com/llvm/llvm-project/pull/74071 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Ensure LocationFileChecker doesn't try to traverse VFS when determining file path (PR #74071)
daniel-grumberg wrote: Adding @compnerd since he committed (on behalf of someone else) the patch that caused this subtle problem in the first place. Do you know the original authors handle on GitHub? https://github.com/llvm/llvm-project/pull/74071 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Ensure LocationFileChecker doesn't try to traverse VFS when determining file path (PR #74071)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/74071 As part of https://reviews.llvm.org/D154130 the logic of LocationFileChecker changed slightly to try and get the absolute external file path instead of the name as requested when the file was openened which would be before VFS mappings in our usage. Ensure that we only check against the name as requested instead of trying to generate the external canonical file path. rdar://115195433 >From 93f1bb149011be424ea2383ea21c99ba1ed595c8 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Fri, 1 Dec 2023 12:19:38 + Subject: [PATCH] [clang][ExtractAPI] Ensure LocationFileChecker doesn't try to traverse VFS when determining file path As part of https://reviews.llvm.org/D154130 the logic of LocationFileChecker changed slightly to try and get the absolute external file path instead of the name as requested when the file was openened which would be before VFS mappings in our usage. Ensure that we only check against the name as requested instead of trying to generate the external canonical file path. rdar://115195433 --- clang/lib/ExtractAPI/ExtractAPIConsumer.cpp | 11 +- .../test/ExtractAPI/vfs_redirected_include.m | 211 ++ 2 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 clang/test/ExtractAPI/vfs_redirected_include.m diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp index 3aba3bf44547cf6..fe282dfb19e8aa7 100644 --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -17,6 +17,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" #include "clang/Basic/DiagnosticFrontend.h" +#include "clang/Basic/FileEntry.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -167,6 +168,12 @@ std::optional getRelativeIncludeName(const CompilerInstance &CI, return std::nullopt; } +std::optional getRelativeIncludeName(const CompilerInstance &CI, + FileEntryRef FE, + bool *IsQuoted = nullptr) { + return getRelativeIncludeName(CI, FE.getNameAsRequested(), IsQuoted); +} + struct LocationFileChecker { bool operator()(SourceLocation Loc) { // If the loc refers to a macro expansion we need to first get the file @@ -187,11 +194,9 @@ struct LocationFileChecker { if (ExternalFileEntries.count(*File)) return false; -StringRef FileName = SM.getFileManager().getCanonicalName(*File); - // Try to reduce the include name the same way we tried to include it. bool IsQuoted = false; -if (auto IncludeName = getRelativeIncludeName(CI, FileName, &IsQuoted)) +if (auto IncludeName = getRelativeIncludeName(CI, *File, &IsQuoted)) if (llvm::any_of(KnownFiles, [&IsQuoted, &IncludeName](const auto &KnownFile) { return KnownFile.first.equals(*IncludeName) && diff --git a/clang/test/ExtractAPI/vfs_redirected_include.m b/clang/test/ExtractAPI/vfs_redirected_include.m new file mode 100644 index 000..9ba7e1dedb601eb --- /dev/null +++ b/clang/test/ExtractAPI/vfs_redirected_include.m @@ -0,0 +1,211 @@ +// RUN: rm -rf %t +// RUN: split-file %s %t + +// Setup framework root +// RUN: mkdir -p %t/Frameworks/MyFramework.framework/Headers +// RUN: cp %t/MyFramework.h %t/Frameworks/MyFramework.framework/Headers/ +// RUN: cp %t/MyHeader.h %t/Frameworks/MyFramework.framework/Headers/ + +// RUN: sed -e "s@SRCROOT@%{/t:regex_replacement}@g" \ +// RUN: %t/reference.output.json.in >> %t/reference.output.json + +// Create VFS overlay from framework headers to SRCROOT +// RUN: sed -e "s@SRCROOT@%{/t:regex_replacement}@g" -e "s@DSTROOT@%{/t:regex_replacement}@g" \ +// RUN: %t/vfsoverlay.yaml.in >> %t/vfsoverlay.yaml + +// Input headers use paths to the framework root/DSTROOT +// RUN: %clang_cc1 -extract-api -v --product-name=MyFramework \ +// RUN: -triple arm64-apple-macosx \ +// RUN: -iquote%t -ivfsoverlay %t/vfsoverlay.yaml -F%t/Frameworks \ +// RUN: -x objective-c-header \ +// RUN: %t/Frameworks/MyFramework.framework/Headers/MyFramework.h \ +// RUN: %t/Frameworks/MyFramework.framework/Headers/MyHeader.h \ +// RUN: %t/QuotedHeader.h \ +// RUN: -o %t/output.json 2>&1 -verify | FileCheck -allow-empty %s + +// 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 + +// CHECK: : +// CHECK-NEXT: #import +// CHECK-NEXT: #import +// CHECK-NEXT: #import "QuotedHeader.h" + +//--- vfsoverlay.yaml.in +{ +"case-sensitive": "false", +"roots": [ +{ +"contents": [ +{ +"external-
[clang] [clang][ExtractAPI] Add support for blocks in declaration fragments (PR #73369)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/73369 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Add support for blocks in declaration fragments (PR #73369)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/73369 Ensure that block types get represented correctly in declaration fragments, as block parameter names are important for documentation clients we need a separate system from getFragmentsForType in order to have access to full ParmVarDecls for the parameters. rdar://118257401 >From e0a9db8aa5e511e81836b5f8e59853c0b498cadf Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Fri, 24 Nov 2023 20:34:49 + Subject: [PATCH] [clang][ExtractAPI] Add support for blocks in declaration fragments Ensure that block types get represented correctly in declaration fragments, as block parameter names are important for documentation clients we need a separate system from getFragmentsForType in order to have access to full ParmVarDecls for the parameters. rdar://118257401 --- .../clang/ExtractAPI/DeclarationFragments.h | 6 + clang/lib/ExtractAPI/DeclarationFragments.cpp | 176 +++- clang/test/ExtractAPI/objc_block.m| 965 ++ clang/test/ExtractAPI/objc_category.m | 4 + clang/test/ExtractAPI/objc_id_protocol.m | 8 + clang/test/ExtractAPI/objc_interface.m| 4 + clang/test/ExtractAPI/objc_property.m | 24 + 7 files changed, 1159 insertions(+), 28 deletions(-) create mode 100644 clang/test/ExtractAPI/objc_block.m diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h index 316d83df13e9359..d719196b9a43ecb 100644 --- a/clang/include/clang/ExtractAPI/DeclarationFragments.h +++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h @@ -24,6 +24,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/MacroInfo.h" #include "llvm/ADT/SmallVector.h" @@ -410,6 +411,11 @@ class DeclarationFragmentsBuilder { /// Build DeclarationFragments for a parameter variable declaration /// ParmVarDecl. static DeclarationFragments getFragmentsForParam(const ParmVarDecl *); + + static DeclarationFragments + getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block, + FunctionProtoTypeLoc &BlockProto, + DeclarationFragments &After); }; template diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 02fa6cd6119ecac..eb6eea0aaf54655 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -15,6 +15,8 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/QualTypeNames.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/OperatorKinds.h" #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h" #include "clang/Index/USRGeneration.h" @@ -24,6 +26,40 @@ using namespace clang::extractapi; using namespace llvm; +namespace { + +void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo, + clang::FunctionTypeLoc &Block, + clang::FunctionProtoTypeLoc &BlockProto) { + if (!TSInfo) +return; + + clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); + while (true) { +// Look through qualified types +if (auto QualifiedTL = TL.getAs()) { + TL = QualifiedTL.getUnqualifiedLoc(); + continue; +} + +if (auto AttrTL = TL.getAs()) { + TL = AttrTL.getModifiedLoc(); + continue; +} + +// Try to get the function prototype behind the block pointer type, +// then we're done. +if (auto BlockPtr = TL.getAs()) { + TL = BlockPtr.getPointeeLoc().IgnoreParens(); + Block = TL.getAs(); + BlockProto = TL.getAs(); +} +break; + } +} + +} // namespace + DeclarationFragments &DeclarationFragments::appendSpace() { if (!Fragments.empty()) { Fragment &Last = Fragments.back(); @@ -218,7 +254,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType( // Declaration fragments of a pointer type is the declaration fragments of // the pointee type followed by a `*`, - if (T->isPointerType()) + if (T->isPointerType() && !T->isFunctionPointerType()) return Fragments .append(getFragmentsForType(T->getPointeeType(), Context, After)) .append(" *", DeclarationFragments::FragmentKind::Text); @@ -449,10 +485,6 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) { .append(VarDecl::getStorageClassSpecifierString(SC), DeclarationFragments::FragmentKind::Keyword) .appendSpace(); - QualType T = - Var->getTypeSourceInfo() - ? Var->getTypeSourceInfo()->getType() - : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType()); // Capture potential fragments that needs to be placed
[clang] ExtractAPI: use zero-based indices for line/column in symbol graph (PR #71753)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/71753 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] ExtractAPI: use zero-based indices for line/column in symbol graph (PR #71753)
https://github.com/daniel-grumberg approved this pull request. LGTM! https://github.com/llvm/llvm-project/pull/71753 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Update availability serialization in SGF (PR #71418)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/71418 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Update availability serialization in SGF (PR #71418)
https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/71418 The prevailiing symbol graph parsing library expects availability attributes to just be "introduced" instead of "introducedVersion" rdar://117823923 >From ad0c6afb7c728b2ea8ad83be22d670808d319783 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Mon, 6 Nov 2023 16:51:35 + Subject: [PATCH] [clang][ExtractAPI] Update availability serialization in SGF The prevailiing symbol graph parsing library expects availability attributes to just be "introduced" instead of "introducedVersion" rdar://117823923 --- .../Serialization/SymbolGraphSerializer.cpp | 6 +++--- clang/test/ExtractAPI/availability.c | 20 +-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 3c8668d26c60b76..f757522ef8e49db 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -177,11 +177,11 @@ serializeAvailability(const AvailabilitySet &Availabilities) { if (AvailInfo.Unavailable) Availability["isUnconditionallyUnavailable"] = true; else { - serializeObject(Availability, "introducedVersion", + serializeObject(Availability, "introduced", serializeSemanticVersion(AvailInfo.Introduced)); - serializeObject(Availability, "deprecatedVersion", + serializeObject(Availability, "deprecated", serializeSemanticVersion(AvailInfo.Deprecated)); - serializeObject(Availability, "obsoletedVersion", + serializeObject(Availability, "obsoleted", serializeSemanticVersion(AvailInfo.Obsoleted)); } AvailabilityArray.emplace_back(std::move(Availability)); diff --git a/clang/test/ExtractAPI/availability.c b/clang/test/ExtractAPI/availability.c index 0c8cd3629f3fdee..5e3890df83563d4 100644 --- a/clang/test/ExtractAPI/availability.c +++ b/clang/test/ExtractAPI/availability.c @@ -127,7 +127,7 @@ void e(void) __attribute__((availability(tvos, unavailable))); "availability": [ { "domain": "macos", - "introducedVersion": { + "introduced": { "major": 12, "minor": 0, "patch": 0 @@ -200,18 +200,18 @@ void e(void) __attribute__((availability(tvos, unavailable))); "accessLevel": "public", "availability": [ { - "deprecatedVersion": { + "deprecated": { "major": 12, "minor": 0, "patch": 0 }, "domain": "macos", - "introducedVersion": { + "introduced": { "major": 11, "minor": 0, "patch": 0 }, - "obsoletedVersion": { + "obsoleted": { "major": 20, "minor": 0, "patch": 0 @@ -284,18 +284,18 @@ void e(void) __attribute__((availability(tvos, unavailable))); "accessLevel": "public", "availability": [ { - "deprecatedVersion": { + "deprecated": { "major": 12, "minor": 0, "patch": 0 }, "domain": "macos", - "introducedVersion": { + "introduced": { "major": 11, "minor": 0, "patch": 0 }, - "obsoletedVersion": { + "obsoleted": { "major": 20, "minor": 0, "patch": 0 @@ -303,7 +303,7 @@ void e(void) __attribute__((availability(tvos, unavailable))); }, { "domain": "ios", - "introducedVersion": { + "introduced": { "major": 13, "minor": 0, "patch": 0 @@ -311,7 +311,7 @@ void e(void) __attribute__((availability(tvos, unavailable))); }, { "domain": "tvos", - "introducedVersion": { + "introduced": { "major": 15, "minor": 0, "patch": 0 @@ -389,7 +389,7 @@ void e(void) __attribute__((availability(tvos, unavailable))); }, { "domain": "macos", - "introducedVersion": { + "introduced": { "major": 11, "minor": 0, "patch": 0 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Prioritze decl comments from macro expansion site (PR #65481)
https://github.com/daniel-grumberg closed https://github.com/llvm/llvm-project/pull/65481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Prioritze decl comments from macro expansion site (PR #65481)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/65481 >From d5054bcc53dad87232a4969e1a1f978b8d5a593d Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Wed, 6 Sep 2023 12:20:30 +0100 Subject: [PATCH] [clang] Prioritze decl comments from macro expansion site For declarations declared inside a macro, e.g.: ``` `#define MAKE_FUNC(suffix) \ /// Not selected doc comment \ void func_##suffix(void) { } /// Doc comment foo MAKE_FUNC(foo) /// Doc comment bar MAKE_FUNC(bar) Prefer the doc comment at the expansion site instead of the one defined in the macro. rdar://113995729 --- clang/lib/AST/ASTContext.cpp | 197 - clang/test/Index/annotate-comments-objc.m | 48 +++-- clang/unittests/Tooling/SourceCodeTest.cpp | 8 +- 3 files changed, 102 insertions(+), 151 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 27a675b83211775..72faea11349b48c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -112,10 +112,10 @@ enum FloatingRank { Ibm128Rank }; -/// \returns location that is relevant when searching for Doc comments related -/// to \p D. -static SourceLocation getDeclLocForCommentSearch(const Decl *D, - SourceManager &SourceMgr) { +/// \returns The locations that are relevant when searching for Doc comments +/// related to \p D. +static SmallVector +getDeclLocsForCommentSearch(const Decl *D, SourceManager &SourceMgr) { assert(D); // User can not attach documentation to implicit declarations. @@ -167,115 +167,48 @@ static SourceLocation getDeclLocForCommentSearch(const Decl *D, isa(D)) return {}; + SmallVector Locations; // Find declaration location. // For Objective-C declarations we generally don't expect to have multiple // declarators, thus use declaration starting location as the "declaration // location". // For all other declarations multiple declarators are used quite frequently, // so we use the location of the identifier as the "declaration location". + SourceLocation BaseLocation; if (isa(D) || isa(D) || - isa(D) || - isa(D) || + isa(D) || isa(D) || isa(D) || // Allow association with Y across {} in `typedef struct X {} Y`. isa(D)) -return D->getBeginLoc(); +BaseLocation = D->getBeginLoc(); + else +BaseLocation = D->getLocation(); - const SourceLocation DeclLoc = D->getLocation(); - if (DeclLoc.isMacroID()) { -// There are (at least) three types of macros we care about here. -// -// 1. Macros that are used in the definition of a type outside the macro, -//with a comment attached at the macro call site. -//``` -//#define MAKE_NAME(Foo) Name##Foo -// -///// Comment is here, where we use the macro. -//struct MAKE_NAME(Foo) { -//int a; -//int b; -//}; -//``` -// 2. Macros that define whole things along with the comment. -//``` -//#define MAKE_METHOD(name) \ -// /** Comment is here, inside the macro. */ \ -// void name() {} -// -//struct S { -// MAKE_METHOD(f) -//} -//``` -// 3. Macros that both declare a type and name a decl outside the macro. -//``` -///// Comment is here, where we use the macro. -//typedef NS_ENUM(NSInteger, Size) { -//SizeWidth, -//SizeHeight -//}; -//``` -//In this case NS_ENUM declares am enum type, and uses the same name for -//the typedef declaration that appears outside the macro. The comment -//here should be applied to both declarations inside and outside the -//macro. -// -// We have found a Decl name that comes from inside a macro, but -// Decl::getLocation() returns the place where the macro is being called. -// If the declaration (and not just the name) resides inside the macro, -// then we want to map Decl::getLocation() into the macro to where the -// declaration and its attached comment (if any) were written. -// -// This mapping into the macro is done by mapping the location to its -// spelling location, however even if the declaration is inside a macro, -// the name's spelling can come from a macro argument (case 2 above). In -// this case mapping the location to the spelling location finds the -// argument's position (at `f` in MAKE_METHOD(`f`) above), which is not -// where the declaration and its comment are located. -// -// To avoid this issue, we make use of Decl::getBeginLocation() instead. -// While the declaration's position is where the name is written, the -// comment is always attached to the begining of the declaration, not to -// the name. -// -// In the first case, the begin location of the
[clang] [clang] Prioritze decl comments from macro expansion site (PR #65481)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/65481 >From e9be513c357d7bb01a3acf69871e2e9889cb2079 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Wed, 6 Sep 2023 12:20:30 +0100 Subject: [PATCH] [clang] Prioritze decl comments from macro expansion site For declarations declared inside a macro, e.g.: ``` `#define MAKE_FUNC(suffix) \ /// Not selected doc comment \ void func_##suffix(void) { } /// Doc comment foo MAKE_FUNC(foo) /// Doc comment bar MAKE_FUNC(bar) Prefer the doc comment at the expansion site instead of the one defined in the macro. rdar://113995729 --- clang/lib/AST/ASTContext.cpp | 197 - clang/test/Index/annotate-comments-objc.m | 41 +++-- clang/unittests/Tooling/SourceCodeTest.cpp | 8 +- 3 files changed, 95 insertions(+), 151 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 27a675b83211775..72faea11349b48c 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -112,10 +112,10 @@ enum FloatingRank { Ibm128Rank }; -/// \returns location that is relevant when searching for Doc comments related -/// to \p D. -static SourceLocation getDeclLocForCommentSearch(const Decl *D, - SourceManager &SourceMgr) { +/// \returns The locations that are relevant when searching for Doc comments +/// related to \p D. +static SmallVector +getDeclLocsForCommentSearch(const Decl *D, SourceManager &SourceMgr) { assert(D); // User can not attach documentation to implicit declarations. @@ -167,115 +167,48 @@ static SourceLocation getDeclLocForCommentSearch(const Decl *D, isa(D)) return {}; + SmallVector Locations; // Find declaration location. // For Objective-C declarations we generally don't expect to have multiple // declarators, thus use declaration starting location as the "declaration // location". // For all other declarations multiple declarators are used quite frequently, // so we use the location of the identifier as the "declaration location". + SourceLocation BaseLocation; if (isa(D) || isa(D) || - isa(D) || - isa(D) || + isa(D) || isa(D) || isa(D) || // Allow association with Y across {} in `typedef struct X {} Y`. isa(D)) -return D->getBeginLoc(); +BaseLocation = D->getBeginLoc(); + else +BaseLocation = D->getLocation(); - const SourceLocation DeclLoc = D->getLocation(); - if (DeclLoc.isMacroID()) { -// There are (at least) three types of macros we care about here. -// -// 1. Macros that are used in the definition of a type outside the macro, -//with a comment attached at the macro call site. -//``` -//#define MAKE_NAME(Foo) Name##Foo -// -///// Comment is here, where we use the macro. -//struct MAKE_NAME(Foo) { -//int a; -//int b; -//}; -//``` -// 2. Macros that define whole things along with the comment. -//``` -//#define MAKE_METHOD(name) \ -// /** Comment is here, inside the macro. */ \ -// void name() {} -// -//struct S { -// MAKE_METHOD(f) -//} -//``` -// 3. Macros that both declare a type and name a decl outside the macro. -//``` -///// Comment is here, where we use the macro. -//typedef NS_ENUM(NSInteger, Size) { -//SizeWidth, -//SizeHeight -//}; -//``` -//In this case NS_ENUM declares am enum type, and uses the same name for -//the typedef declaration that appears outside the macro. The comment -//here should be applied to both declarations inside and outside the -//macro. -// -// We have found a Decl name that comes from inside a macro, but -// Decl::getLocation() returns the place where the macro is being called. -// If the declaration (and not just the name) resides inside the macro, -// then we want to map Decl::getLocation() into the macro to where the -// declaration and its attached comment (if any) were written. -// -// This mapping into the macro is done by mapping the location to its -// spelling location, however even if the declaration is inside a macro, -// the name's spelling can come from a macro argument (case 2 above). In -// this case mapping the location to the spelling location finds the -// argument's position (at `f` in MAKE_METHOD(`f`) above), which is not -// where the declaration and its comment are located. -// -// To avoid this issue, we make use of Decl::getBeginLocation() instead. -// While the declaration's position is where the name is written, the -// comment is always attached to the begining of the declaration, not to -// the name. -// -// In the first case, the begin location of the
[clang] [clang] Prioritze decl comments from macro expansion site (PR #65481)
https://github.com/daniel-grumberg updated https://github.com/llvm/llvm-project/pull/65481 >From 32155e8b5ac01242c3e16968f9a7c821d16b7007 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Wed, 6 Sep 2023 12:20:30 +0100 Subject: [PATCH 1/2] [clang] Prioritze decl comments from macro expansion site For declarations declared inside a macro, e.g.: ``` `#define MAKE_FUNC(suffix) \ /// Not selected doc comment \ void func_##suffix(void) { } /// Doc comment foo MAKE_FUNC(foo) /// Doc comment bar MAKE_FUNC(bar) Prefer the doc comment at the expansion site instead of the one defined in the macro. rdar://113995729 --- clang/lib/AST/ASTContext.cpp | 191 +++-- clang/test/Index/annotate-comments-objc.m | 12 +- clang/unittests/Tooling/SourceCodeTest.cpp | 5 +- 3 files changed, 70 insertions(+), 138 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4b1d9e86797b778..074f59bd5a50411 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -112,10 +112,10 @@ enum FloatingRank { Ibm128Rank }; -/// \returns location that is relevant when searching for Doc comments related -/// to \p D. -static SourceLocation getDeclLocForCommentSearch(const Decl *D, - SourceManager &SourceMgr) { +/// \returns The locations that are relevant when searching for Doc comments +/// related to \p D. +static SmallVector +getDeclLocsForCommentSearch(const Decl *D, SourceManager &SourceMgr) { assert(D); // User can not attach documentation to implicit declarations. @@ -167,115 +167,41 @@ static SourceLocation getDeclLocForCommentSearch(const Decl *D, isa(D)) return {}; + SmallVector Locations; // Find declaration location. // For Objective-C declarations we generally don't expect to have multiple // declarators, thus use declaration starting location as the "declaration // location". // For all other declarations multiple declarators are used quite frequently, // so we use the location of the identifier as the "declaration location". + SourceLocation BaseLocation; if (isa(D) || isa(D) || - isa(D) || - isa(D) || + isa(D) || isa(D) || isa(D) || // Allow association with Y across {} in `typedef struct X {} Y`. isa(D)) -return D->getBeginLoc(); +BaseLocation = D->getBeginLoc(); + else +BaseLocation = D->getLocation(); - const SourceLocation DeclLoc = D->getLocation(); - if (DeclLoc.isMacroID()) { -// There are (at least) three types of macros we care about here. -// -// 1. Macros that are used in the definition of a type outside the macro, -//with a comment attached at the macro call site. -//``` -//#define MAKE_NAME(Foo) Name##Foo -// -///// Comment is here, where we use the macro. -//struct MAKE_NAME(Foo) { -//int a; -//int b; -//}; -//``` -// 2. Macros that define whole things along with the comment. -//``` -//#define MAKE_METHOD(name) \ -// /** Comment is here, inside the macro. */ \ -// void name() {} -// -//struct S { -// MAKE_METHOD(f) -//} -//``` -// 3. Macros that both declare a type and name a decl outside the macro. -//``` -///// Comment is here, where we use the macro. -//typedef NS_ENUM(NSInteger, Size) { -//SizeWidth, -//SizeHeight -//}; -//``` -//In this case NS_ENUM declares am enum type, and uses the same name for -//the typedef declaration that appears outside the macro. The comment -//here should be applied to both declarations inside and outside the -//macro. -// -// We have found a Decl name that comes from inside a macro, but -// Decl::getLocation() returns the place where the macro is being called. -// If the declaration (and not just the name) resides inside the macro, -// then we want to map Decl::getLocation() into the macro to where the -// declaration and its attached comment (if any) were written. -// -// This mapping into the macro is done by mapping the location to its -// spelling location, however even if the declaration is inside a macro, -// the name's spelling can come from a macro argument (case 2 above). In -// this case mapping the location to the spelling location finds the -// argument's position (at `f` in MAKE_METHOD(`f`) above), which is not -// where the declaration and its comment are located. -// -// To avoid this issue, we make use of Decl::getBeginLocation() instead. -// While the declaration's position is where the name is written, the -// comment is always attached to the begining of the declaration, not to -// the name. -// -// In the first case, the begin location of the
[clang] [clang] Prioritze decl comments from macro expansion site (PR #65481)
https://github.com/daniel-grumberg edited https://github.com/llvm/llvm-project/pull/65481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Prioritze decl comments from macro expansion site (PR #65481)
@@ -374,11 +374,10 @@ TEST(SourceCodeTest, getAssociatedRangeWithComments) { // Does not include comments when only the decl or the comment come from a // macro. daniel-grumberg wrote: Good spot, can't believe I removed the FIXME and not the comment explaining the FIXME 😵💫 https://github.com/llvm/llvm-project/pull/65481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Prioritze decl comments from macro expansion site (PR #65481)
https://github.com/daniel-grumberg review_requested https://github.com/llvm/llvm-project/pull/65481 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ExtractAPI] Remove test with system header (PR #65646)
https://github.com/daniel-grumberg approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/65646 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits