Skip to content

Commit b18b454

Browse files
Revert "[clang][ExtractAPI] Stop dropping fields of nested anonymous record types when they aren't attached to variable declaration (#104600)"
This reverts commit c60da1a.
1 parent 7dd6340 commit b18b454

File tree

5 files changed

+27
-110
lines changed

5 files changed

+27
-110
lines changed

clang/include/clang/ExtractAPI/API.h

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,21 @@
1919
#define LLVM_CLANG_EXTRACTAPI_API_H
2020

2121
#include "clang/AST/Availability.h"
22+
#include "clang/AST/Decl.h"
2223
#include "clang/AST/DeclBase.h"
24+
#include "clang/AST/DeclObjC.h"
2325
#include "clang/AST/RawCommentList.h"
2426
#include "clang/Basic/SourceLocation.h"
27+
#include "clang/Basic/Specifiers.h"
2528
#include "clang/ExtractAPI/DeclarationFragments.h"
26-
#include "llvm/ADT/SmallPtrSet.h"
29+
#include "llvm/ADT/ArrayRef.h"
30+
#include "llvm/ADT/MapVector.h"
31+
#include "llvm/ADT/StringRef.h"
2732
#include "llvm/Support/Allocator.h"
2833
#include "llvm/Support/Casting.h"
34+
#include "llvm/Support/Compiler.h"
35+
#include "llvm/Support/ErrorHandling.h"
36+
#include "llvm/Support/raw_ostream.h"
2937
#include "llvm/TargetParser/Triple.h"
3038
#include <cstddef>
3139
#include <iterator>
@@ -320,8 +328,6 @@ class RecordContext {
320328
/// chain.
321329
void stealRecordChain(RecordContext &Other);
322330

323-
void removeFromRecordChain(APIRecord *Record);
324-
325331
APIRecord::RecordKind getKind() const { return Kind; }
326332

327333
struct record_iterator {
@@ -1420,15 +1426,10 @@ class APISet {
14201426
typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
14211427
createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs);
14221428

1423-
auto getTopLevelRecords() const {
1424-
return llvm::iterator_range<decltype(TopLevelRecords)::iterator>(
1425-
TopLevelRecords);
1429+
ArrayRef<const APIRecord *> getTopLevelRecords() const {
1430+
return TopLevelRecords;
14261431
}
14271432

1428-
void removeRecord(StringRef USR);
1429-
1430-
void removeRecord(APIRecord *Record);
1431-
14321433
APISet(const llvm::Triple &Target, Language Lang,
14331434
const std::string &ProductName)
14341435
: Target(Target), Lang(Lang), ProductName(ProductName) {}
@@ -1455,7 +1456,7 @@ class APISet {
14551456
// lives in the BumpPtrAllocator.
14561457
using APIRecordStoredPtr = std::unique_ptr<APIRecord, APIRecordDeleter>;
14571458
llvm::DenseMap<StringRef, APIRecordStoredPtr> USRBasedLookupTable;
1458-
llvm::SmallPtrSet<const APIRecord *, 32> TopLevelRecords;
1459+
std::vector<const APIRecord *> TopLevelRecords;
14591460

14601461
public:
14611462
const std::string ProductName;
@@ -1481,7 +1482,7 @@ APISet::createRecord(StringRef USR, StringRef Name,
14811482
dyn_cast_if_present<RecordContext>(Record->Parent.Record))
14821483
ParentContext->addToRecordChain(Record);
14831484
else
1484-
TopLevelRecords.insert(Record);
1485+
TopLevelRecords.push_back(Record);
14851486
} else {
14861487
Record = dyn_cast<RecordTy>(Result.first->second.get());
14871488
}

clang/include/clang/ExtractAPI/ExtractAPIVisitor.h

Lines changed: 4 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,13 @@
2323
#include "clang/AST/RecursiveASTVisitor.h"
2424
#include "clang/Basic/LLVM.h"
2525
#include "clang/Basic/Module.h"
26+
#include "clang/Basic/SourceManager.h"
2627
#include "clang/Basic/Specifiers.h"
2728
#include "clang/ExtractAPI/API.h"
2829
#include "clang/ExtractAPI/DeclarationFragments.h"
2930
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
3031
#include "clang/Index/USRGeneration.h"
32+
#include "llvm/ADT/SmallString.h"
3133
#include "llvm/ADT/StringRef.h"
3234
#include "llvm/Support/Casting.h"
3335
#include <type_traits>
@@ -38,8 +40,6 @@ namespace impl {
3840

3941
template <typename Derived>
4042
class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
41-
using Base = RecursiveASTVisitor<Derived>;
42-
4343
protected:
4444
ExtractAPIVisitorBase(ASTContext &Context, APISet &API)
4545
: Context(Context), API(API) {}
@@ -81,10 +81,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
8181

8282
bool VisitNamespaceDecl(const NamespaceDecl *Decl);
8383

84-
bool TraverseRecordDecl(RecordDecl *Decl);
8584
bool VisitRecordDecl(const RecordDecl *Decl);
8685

87-
bool TraverseCXXRecordDecl(CXXRecordDecl *Decl);
8886
bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
8987

9088
bool VisitCXXMethodDecl(const CXXMethodDecl *Decl);
@@ -242,7 +240,7 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
242240

243241
bool isEmbeddedInVarDeclarator(const TagDecl &D) {
244242
return D.getName().empty() && getTypedefName(&D).empty() &&
245-
D.isEmbeddedInDeclarator() && !D.isFreeStanding();
243+
D.isEmbeddedInDeclarator();
246244
}
247245

248246
void maybeMergeWithAnonymousTag(const DeclaratorDecl &D,
@@ -254,10 +252,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
254252
clang::index::generateUSRForDecl(Tag, TagUSR);
255253
if (auto *Record = llvm::dyn_cast_if_present<TagRecord>(
256254
API.findRecordForUSR(TagUSR))) {
257-
if (Record->IsEmbeddedInVarDeclarator) {
255+
if (Record->IsEmbeddedInVarDeclarator)
258256
NewRecordContext->stealRecordChain(*Record);
259-
API.removeRecord(Record);
260-
}
261257
}
262258
}
263259
};
@@ -552,19 +548,6 @@ bool ExtractAPIVisitorBase<Derived>::VisitNamespaceDecl(
552548
return true;
553549
}
554550

555-
template <typename Derived>
556-
bool ExtractAPIVisitorBase<Derived>::TraverseRecordDecl(RecordDecl *Decl) {
557-
bool Ret = Base::TraverseRecordDecl(Decl);
558-
559-
if (!isEmbeddedInVarDeclarator(*Decl) && Decl->isAnonymousStructOrUnion()) {
560-
SmallString<128> USR;
561-
index::generateUSRForDecl(Decl, USR);
562-
API.removeRecord(USR);
563-
}
564-
565-
return Ret;
566-
}
567-
568551
template <typename Derived>
569552
bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
570553
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
@@ -605,20 +588,6 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
605588
return true;
606589
}
607590

608-
template <typename Derived>
609-
bool ExtractAPIVisitorBase<Derived>::TraverseCXXRecordDecl(
610-
CXXRecordDecl *Decl) {
611-
bool Ret = Base::TraverseCXXRecordDecl(Decl);
612-
613-
if (!isEmbeddedInVarDeclarator(*Decl) && Decl->isAnonymousStructOrUnion()) {
614-
SmallString<128> USR;
615-
index::generateUSRForDecl(Decl, USR);
616-
API.removeRecord(USR);
617-
}
618-
619-
return Ret;
620-
}
621-
622591
template <typename Derived>
623592
bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
624593
const CXXRecordDecl *Decl) {

clang/lib/ExtractAPI/API.cpp

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "clang/ExtractAPI/API.h"
16+
#include "clang/AST/RawCommentList.h"
17+
#include "clang/Index/USRGeneration.h"
1618
#include "llvm/ADT/StringRef.h"
1719
#include "llvm/Support/ErrorHandling.h"
1820
#include <memory>
@@ -58,10 +60,6 @@ bool RecordContext::IsWellFormed() const {
5860

5961
void RecordContext::stealRecordChain(RecordContext &Other) {
6062
assert(IsWellFormed());
61-
// Other's record chain is empty, nothing to do
62-
if (Other.First == nullptr && Other.Last == nullptr)
63-
return;
64-
6563
// If we don't have an empty chain append Other's chain into ours.
6664
if (First)
6765
Last->NextInContext = Other.First;
@@ -70,10 +68,6 @@ void RecordContext::stealRecordChain(RecordContext &Other) {
7068

7169
Last = Other.Last;
7270

73-
for (auto *StolenRecord = Other.First; StolenRecord != nullptr;
74-
StolenRecord = StolenRecord->getNextInContext())
75-
StolenRecord->Parent = SymbolReference(cast<APIRecord>(this));
76-
7771
// Delete Other's chain to ensure we don't accidentally traverse it.
7872
Other.First = nullptr;
7973
Other.Last = nullptr;
@@ -91,22 +85,6 @@ void RecordContext::addToRecordChain(APIRecord *Record) const {
9185
Last = Record;
9286
}
9387

94-
void RecordContext::removeFromRecordChain(APIRecord *Record) {
95-
APIRecord *Prev = nullptr;
96-
for (APIRecord *Curr = First; Curr != Record; Curr = Curr->NextInContext)
97-
Prev = Curr;
98-
99-
if (Prev)
100-
Prev->NextInContext = Record->NextInContext;
101-
else
102-
First = Record->NextInContext;
103-
104-
if (Last == Record)
105-
Last = Prev;
106-
107-
Record->NextInContext = nullptr;
108-
}
109-
11088
APIRecord *APISet::findRecordForUSR(StringRef USR) const {
11189
if (USR.empty())
11290
return nullptr;
@@ -136,33 +114,6 @@ SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
136114
return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
137115
}
138116

139-
void APISet::removeRecord(StringRef USR) {
140-
auto Result = USRBasedLookupTable.find(USR);
141-
if (Result != USRBasedLookupTable.end()) {
142-
auto *Record = Result->getSecond().get();
143-
auto &ParentReference = Record->Parent;
144-
auto *ParentRecord = const_cast<APIRecord *>(ParentReference.Record);
145-
if (!ParentRecord)
146-
ParentRecord = findRecordForUSR(ParentReference.USR);
147-
148-
if (auto *ParentCtx = llvm::cast_if_present<RecordContext>(ParentRecord)) {
149-
ParentCtx->removeFromRecordChain(Record);
150-
if (auto *RecordAsCtx = llvm::dyn_cast<RecordContext>(Record))
151-
ParentCtx->stealRecordChain(*RecordAsCtx);
152-
} else {
153-
TopLevelRecords.erase(Record);
154-
if (auto *RecordAsCtx = llvm::dyn_cast<RecordContext>(Record)) {
155-
for (const auto *Child = RecordAsCtx->First; Child != nullptr;
156-
Child = Child->getNextInContext())
157-
TopLevelRecords.insert(Child);
158-
}
159-
}
160-
USRBasedLookupTable.erase(Result);
161-
}
162-
}
163-
164-
void APISet::removeRecord(APIRecord *Record) { removeRecord(Record->USR); }
165-
166117
APIRecord::~APIRecord() {}
167118
TagRecord::~TagRecord() {}
168119
RecordRecord::~RecordRecord() {}

clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,14 @@ bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const {
673673
if (Record->Availability.isUnconditionallyUnavailable())
674674
return true;
675675

676+
// Filter out symbols without a name as we can generate correct symbol graphs
677+
// for them. In practice these are anonymous record types that aren't attached
678+
// to a declaration.
679+
if (auto *Tag = dyn_cast<TagRecord>(Record)) {
680+
if (Tag->IsEmbeddedInVarDeclarator)
681+
return true;
682+
}
683+
676684
// Filter out symbols prefixed with an underscored as they are understood to
677685
// be symbols clients should not use.
678686
if (Record->Name.starts_with("_"))

clang/test/ExtractAPI/anonymous_record_no_typedef.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,16 +163,4 @@ enum {
163163
// GLOBALOTHERCASE-NEXT: "GlobalOtherCase"
164164
// GLOBALOTHERCASE-NEXT: ]
165165

166-
// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix VEC
167-
union Vector {
168-
struct {
169-
float X;
170-
float Y;
171-
};
172-
float Data[2];
173-
};
174-
// VEC-DAG: "!testRelLabel": "memberOf $ c:@U@Vector@FI@Data $ c:@U@Vector"
175-
// VEC-DAG: "!testRelLabel": "memberOf $ c:@U@Vector@Sa@FI@X $ c:@U@Vector"
176-
// VEC-DAG: "!testRelLabel": "memberOf $ c:@U@Vector@Sa@FI@Y $ c:@U@Vector"
177-
178166
// expected-no-diagnostics

0 commit comments

Comments
 (0)