Skip to content

Commit 786f5e8

Browse files
committed
Merge branch 'main' into jroelofs/lower-matrix-extract
2 parents 53098ce + 1f1c725 commit 786f5e8

File tree

1,112 files changed

+28975
-21316
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,112 files changed

+28975
-21316
lines changed

.github/new-prs-labeler.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,10 @@ mlgo:
703703
- llvm/test/CodeGen/MLRegAlloc/**
704704
- llvm/utils/mlgo-utils/**
705705
- llvm/docs/MLGO.rst
706+
- llvm/include/llvm/Analysis/IR2Vec.h
707+
- llvm/lib/Analysis/IR2Vec.cpp
708+
- llvm/lib/Analysis/models/**
709+
- llvm/test/Analysis/IR2Vec/**
706710

707711
tools:llvm-exegesis:
708712
- llvm/tools/llvm-exegesis/**

clang-tools-extra/clang-doc/Representation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ struct TypeInfo {
164164
bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
165165

166166
Reference Type; // Referenced type in this info.
167+
168+
bool IsTemplate = false;
169+
bool IsBuiltIn = false;
167170
};
168171

169172
// Represents one template parameter.
@@ -363,6 +366,9 @@ struct FunctionInfo : public SymbolInfo {
363366
// specializations.
364367
SmallString<16> FullName;
365368

369+
// Function Prototype
370+
SmallString<256> Prototype;
371+
366372
// When present, this function is a template or specialization.
367373
std::optional<TemplateInfo> Template;
368374
};

clang-tools-extra/clang-doc/Serialize.cpp

Lines changed: 222 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88

99
#include "Serialize.h"
1010
#include "BitcodeWriter.h"
11+
#include "clang/AST/Attr.h"
1112
#include "clang/AST/Comment.h"
1213
#include "clang/Index/USRGeneration.h"
1314
#include "clang/Lex/Lexer.h"
14-
#include "llvm/ADT/Hashing.h"
1515
#include "llvm/ADT/StringExtras.h"
1616
#include "llvm/Support/SHA1.h"
1717

@@ -35,6 +35,184 @@ static void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
3535
const DeclaratorDecl *D,
3636
bool IsStatic = false);
3737

38+
static void getTemplateParameters(const TemplateParameterList *TemplateParams,
39+
llvm::raw_ostream &Stream) {
40+
Stream << "template <";
41+
42+
for (unsigned i = 0; i < TemplateParams->size(); ++i) {
43+
if (i > 0)
44+
Stream << ", ";
45+
46+
const NamedDecl *Param = TemplateParams->getParam(i);
47+
if (const auto *TTP = llvm::dyn_cast<TemplateTypeParmDecl>(Param)) {
48+
if (TTP->wasDeclaredWithTypename())
49+
Stream << "typename";
50+
else
51+
Stream << "class";
52+
if (TTP->isParameterPack())
53+
Stream << "...";
54+
Stream << " " << TTP->getNameAsString();
55+
56+
// We need to also handle type constraints for code like:
57+
// template <class T = void>
58+
// class C {};
59+
if (TTP->hasTypeConstraint()) {
60+
Stream << " = ";
61+
TTP->getTypeConstraint()->print(
62+
Stream, TTP->getASTContext().getPrintingPolicy());
63+
}
64+
} else if (const auto *NTTP =
65+
llvm::dyn_cast<NonTypeTemplateParmDecl>(Param)) {
66+
NTTP->getType().print(Stream, NTTP->getASTContext().getPrintingPolicy());
67+
if (NTTP->isParameterPack())
68+
Stream << "...";
69+
Stream << " " << NTTP->getNameAsString();
70+
} else if (const auto *TTPD =
71+
llvm::dyn_cast<TemplateTemplateParmDecl>(Param)) {
72+
Stream << "template <";
73+
getTemplateParameters(TTPD->getTemplateParameters(), Stream);
74+
Stream << "> class " << TTPD->getNameAsString();
75+
}
76+
}
77+
78+
Stream << "> ";
79+
}
80+
81+
// Extract the full function prototype from a FunctionDecl including
82+
// Full Decl
83+
static llvm::SmallString<256>
84+
getFunctionPrototype(const FunctionDecl *FuncDecl) {
85+
llvm::SmallString<256> Result;
86+
llvm::raw_svector_ostream Stream(Result);
87+
const ASTContext &Ctx = FuncDecl->getASTContext();
88+
const auto *Method = llvm::dyn_cast<CXXMethodDecl>(FuncDecl);
89+
// If it's a templated function, handle the template parameters
90+
if (const auto *TmplDecl = FuncDecl->getDescribedTemplate())
91+
getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
92+
93+
// If it's a virtual method
94+
if (Method && Method->isVirtual())
95+
Stream << "virtual ";
96+
97+
// Print return type
98+
FuncDecl->getReturnType().print(Stream, Ctx.getPrintingPolicy());
99+
100+
// Print function name
101+
Stream << " " << FuncDecl->getNameAsString() << "(";
102+
103+
// Print parameter list with types, names, and default values
104+
for (unsigned I = 0; I < FuncDecl->getNumParams(); ++I) {
105+
if (I > 0)
106+
Stream << ", ";
107+
const ParmVarDecl *ParamDecl = FuncDecl->getParamDecl(I);
108+
QualType ParamType = ParamDecl->getType();
109+
ParamType.print(Stream, Ctx.getPrintingPolicy());
110+
111+
// Print parameter name if it has one
112+
if (!ParamDecl->getName().empty())
113+
Stream << " " << ParamDecl->getNameAsString();
114+
115+
// Print default argument if it exists
116+
if (ParamDecl->hasDefaultArg()) {
117+
const Expr *DefaultArg = ParamDecl->getDefaultArg();
118+
if (DefaultArg) {
119+
Stream << " = ";
120+
DefaultArg->printPretty(Stream, nullptr, Ctx.getPrintingPolicy());
121+
}
122+
}
123+
}
124+
125+
// If it is a variadic function, add '...'
126+
if (FuncDecl->isVariadic()) {
127+
if (FuncDecl->getNumParams() > 0)
128+
Stream << ", ";
129+
Stream << "...";
130+
}
131+
132+
Stream << ")";
133+
134+
// If it's a const method, add 'const' qualifier
135+
if (Method) {
136+
if (Method->isDeleted())
137+
Stream << " = delete";
138+
if (Method->size_overridden_methods())
139+
Stream << " override";
140+
if (Method->hasAttr<clang::FinalAttr>())
141+
Stream << " final";
142+
if (Method->isConst())
143+
Stream << " const";
144+
if (Method->isPureVirtual())
145+
Stream << " = 0";
146+
}
147+
148+
if (auto ExceptionSpecType = FuncDecl->getExceptionSpecType())
149+
Stream << " " << ExceptionSpecType;
150+
151+
return Result; // Convert SmallString to std::string for return
152+
}
153+
154+
static llvm::SmallString<16> getTypeAlias(const TypeAliasDecl *Alias) {
155+
llvm::SmallString<16> Result;
156+
llvm::raw_svector_ostream Stream(Result);
157+
const ASTContext &Ctx = Alias->getASTContext();
158+
if (const auto *TmplDecl = Alias->getDescribedTemplate())
159+
getTemplateParameters(TmplDecl->getTemplateParameters(), Stream);
160+
Stream << "using " << Alias->getNameAsString() << " = ";
161+
QualType Q = Alias->getUnderlyingType();
162+
Q.print(Stream, Ctx.getPrintingPolicy());
163+
164+
return Result;
165+
}
166+
167+
// extract full syntax for record declaration
168+
static llvm::SmallString<16> getRecordPrototype(const CXXRecordDecl *CXXRD) {
169+
llvm::SmallString<16> Result;
170+
LangOptions LangOpts;
171+
PrintingPolicy Policy(LangOpts);
172+
Policy.SuppressTagKeyword = false;
173+
Policy.FullyQualifiedName = true;
174+
Policy.IncludeNewlines = false;
175+
llvm::raw_svector_ostream OS(Result);
176+
if (const auto *TD = CXXRD->getDescribedClassTemplate()) {
177+
OS << "template <";
178+
bool FirstParam = true;
179+
for (const auto *Param : *TD->getTemplateParameters()) {
180+
if (!FirstParam)
181+
OS << ", ";
182+
Param->print(OS, Policy);
183+
FirstParam = false;
184+
}
185+
OS << ">\n";
186+
}
187+
188+
if (CXXRD->isStruct())
189+
OS << "struct ";
190+
else if (CXXRD->isClass())
191+
OS << "class ";
192+
else if (CXXRD->isUnion())
193+
OS << "union ";
194+
195+
OS << CXXRD->getNameAsString();
196+
197+
// We need to make sure we have a good enough declaration to check. In the
198+
// case where the class is a forward declaration, we'll fail assertions in
199+
// DeclCXX.
200+
if (CXXRD->isCompleteDefinition() && CXXRD->getNumBases() > 0) {
201+
OS << " : ";
202+
bool FirstBase = true;
203+
for (const auto &Base : CXXRD->bases()) {
204+
if (!FirstBase)
205+
OS << ", ";
206+
if (Base.isVirtual())
207+
OS << "virtual ";
208+
OS << getAccessSpelling(Base.getAccessSpecifier()) << " ";
209+
OS << Base.getType().getAsString(Policy);
210+
FirstBase = false;
211+
}
212+
}
213+
return Result;
214+
}
215+
38216
// A function to extract the appropriate relative path for a given info's
39217
// documentation. The path returned is a composite of the parent namespaces.
40218
//
@@ -242,9 +420,12 @@ static RecordDecl *getRecordDeclForType(const QualType &T) {
242420
static TypeInfo getTypeInfoForType(const QualType &T,
243421
const PrintingPolicy &Policy) {
244422
const TagDecl *TD = getTagDeclForType(T);
245-
if (!TD)
246-
return TypeInfo(Reference(SymbolID(), T.getAsString(Policy)));
247-
423+
if (!TD) {
424+
TypeInfo TI = TypeInfo(Reference(SymbolID(), T.getAsString(Policy)));
425+
TI.IsBuiltIn = T->isBuiltinType();
426+
TI.IsTemplate = T->isTemplateTypeParmType();
427+
return TI;
428+
}
248429
InfoType IT;
249430
if (isa<EnumDecl>(TD)) {
250431
IT = InfoType::IT_enum;
@@ -253,8 +434,12 @@ static TypeInfo getTypeInfoForType(const QualType &T,
253434
} else {
254435
IT = InfoType::IT_default;
255436
}
256-
return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
257-
T.getAsString(Policy), getInfoRelativePath(TD)));
437+
Reference R = Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
438+
T.getAsString(Policy), getInfoRelativePath(TD));
439+
TypeInfo TI = TypeInfo(R);
440+
TI.IsBuiltIn = T->isBuiltinType();
441+
TI.IsTemplate = T->isTemplateTypeParmType();
442+
return TI;
258443
}
259444

260445
static bool isPublic(const clang::AccessSpecifier AS,
@@ -408,7 +593,6 @@ static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
408593
ASTContext &Context = E->getASTContext();
409594
if (RawComment *Comment =
410595
E->getASTContext().getRawCommentForDeclNoCache(E)) {
411-
CommentInfo CInfo;
412596
Comment->setAttached();
413597
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, E)) {
414598
EnumValueInfo &Member = I.Members.back();
@@ -434,6 +618,7 @@ static void parseBases(RecordInfo &I, const CXXRecordDecl *D) {
434618
// Don't parse bases if this isn't a definition.
435619
if (!D->isThisDeclarationADefinition())
436620
return;
621+
437622
for (const CXXBaseSpecifier &B : D->bases()) {
438623
if (B.isVirtual())
439624
continue;
@@ -555,6 +740,7 @@ static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
555740
populateSymbolInfo(I, D, FC, Loc, IsInAnonymousNamespace);
556741
auto &LO = D->getLangOpts();
557742
I.ReturnType = getTypeInfoForType(D->getReturnType(), LO);
743+
I.Prototype = getFunctionPrototype(D);
558744
parseParameters(I, D);
559745

560746
populateTemplateParameters(I.Template, D);
@@ -686,15 +872,19 @@ emitInfo(const NamespaceDecl *D, const FullComment *FC, Location Loc,
686872
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
687873
emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
688874
bool PublicOnly) {
875+
689876
auto RI = std::make_unique<RecordInfo>();
690877
bool IsInAnonymousNamespace = false;
878+
691879
populateSymbolInfo(*RI, D, FC, Loc, IsInAnonymousNamespace);
692880
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
693881
return {};
694882

695883
RI->TagType = D->getTagKind();
696884
parseFields(*RI, D, PublicOnly);
885+
697886
if (const auto *C = dyn_cast<CXXRecordDecl>(D)) {
887+
RI->FullName = getRecordPrototype(C);
698888
if (const TypedefNameDecl *TD = C->getTypedefNameForAnonDecl()) {
699889
RI->Name = TD->getNameAsString();
700890
RI->IsTypeDef = true;
@@ -716,11 +906,11 @@ emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
716906

717907
// What this is a specialization of.
718908
auto SpecOf = CTSD->getSpecializedTemplateOrPartial();
719-
if (auto *CTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
720-
Specialization.SpecializationOf = getUSRForDecl(CTD);
721-
else if (auto *CTPSD =
909+
if (auto *SpecTD = dyn_cast<ClassTemplateDecl *>(SpecOf))
910+
Specialization.SpecializationOf = getUSRForDecl(SpecTD);
911+
else if (auto *SpecTD =
722912
dyn_cast<ClassTemplatePartialSpecializationDecl *>(SpecOf))
723-
Specialization.SpecializationOf = getUSRForDecl(CTPSD);
913+
Specialization.SpecializationOf = getUSRForDecl(SpecTD);
724914

725915
// Parameters to the specialization. For partial specializations, get the
726916
// parameters "as written" from the ClassTemplatePartialSpecializationDecl
@@ -792,25 +982,42 @@ emitInfo(const CXXMethodDecl *D, const FullComment *FC, Location Loc,
792982
return {nullptr, makeAndInsertIntoParent<FunctionInfo &&>(std::move(Func))};
793983
}
794984

985+
static void extractCommentFromDecl(const Decl *D, TypedefInfo &Info) {
986+
assert(D && "Invalid Decl when extracting comment");
987+
ASTContext &Context = D->getASTContext();
988+
RawComment *Comment = Context.getRawCommentForDeclNoCache(D);
989+
if (!Comment)
990+
return;
991+
992+
Comment->setAttached();
993+
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
994+
Info.Description.emplace_back();
995+
parseFullComment(Fc, Info.Description.back());
996+
}
997+
}
998+
795999
std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
7961000
emitInfo(const TypedefDecl *D, const FullComment *FC, Location Loc,
7971001
bool PublicOnly) {
7981002
TypedefInfo Info;
7991003
bool IsInAnonymousNamespace = false;
8001004
populateInfo(Info, D, FC, IsInAnonymousNamespace);
1005+
8011006
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
8021007
return {};
8031008

8041009
Info.DefLoc = Loc;
8051010
auto &LO = D->getLangOpts();
8061011
Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1012+
8071013
if (Info.Underlying.Type.Name.empty()) {
8081014
// Typedef for an unnamed type. This is like "typedef struct { } Foo;"
8091015
// The record serializer explicitly checks for this syntax and constructs
8101016
// a record with that name, so we don't want to emit a duplicate here.
8111017
return {};
8121018
}
8131019
Info.IsUsing = false;
1020+
extractCommentFromDecl(D, Info);
8141021

8151022
// Info is wrapped in its parent scope so is returned in the second position.
8161023
return {nullptr, makeAndInsertIntoParent<TypedefInfo &&>(std::move(Info))};
@@ -822,17 +1029,19 @@ std::pair<std::unique_ptr<Info>, std::unique_ptr<Info>>
8221029
emitInfo(const TypeAliasDecl *D, const FullComment *FC, Location Loc,
8231030
bool PublicOnly) {
8241031
TypedefInfo Info;
825-
8261032
bool IsInAnonymousNamespace = false;
8271033
populateInfo(Info, D, FC, IsInAnonymousNamespace);
8281034
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
8291035
return {};
8301036

8311037
Info.DefLoc = Loc;
832-
auto &LO = D->getLangOpts();
1038+
const LangOptions &LO = D->getLangOpts();
8331039
Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
1040+
Info.TypeDeclaration = getTypeAlias(D);
8341041
Info.IsUsing = true;
8351042

1043+
extractCommentFromDecl(D, Info);
1044+
8361045
// Info is wrapped in its parent scope so is returned in the second position.
8371046
return {nullptr, makeAndInsertIntoParent<TypedefInfo &&>(std::move(Info))};
8381047
}

clang-tools-extra/clang-doc/tool/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ clang_target_link_libraries(clang-doc
99
clangAST
1010
clangASTMatchers
1111
clangBasic
12+
clangDocSupport
1213
clangFrontend
1314
clangTooling
1415
clangToolingCore

0 commit comments

Comments
 (0)