Skip to content

Commit ab20818

Browse files
committed
[clang-doc] document-concepts
1 parent b602047 commit ab20818

File tree

13 files changed

+315
-48
lines changed

13 files changed

+315
-48
lines changed

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

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ static llvm::Error decodeRecord(const Record &R, InfoType &Field,
9292
case InfoType::IT_default:
9393
case InfoType::IT_enum:
9494
case InfoType::IT_typedef:
95+
case InfoType::IT_concept:
9596
Field = IT;
9697
return llvm::Error::success();
9798
}
@@ -108,6 +109,7 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field,
108109
case FieldId::F_type:
109110
case FieldId::F_child_namespace:
110111
case FieldId::F_child_record:
112+
case FieldId::F_concept:
111113
case FieldId::F_default:
112114
Field = F;
113115
return llvm::Error::success();
@@ -391,6 +393,29 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
391393
"invalid field for TemplateParamInfo");
392394
}
393395

396+
static llvm::Error parseRecord(const Record &R, unsigned ID,
397+
llvm::StringRef Blob, ConceptInfo *I) {
398+
switch (ID) {
399+
case CONCEPT_USR:
400+
return decodeRecord(R, I->USR, Blob);
401+
case CONCEPT_NAME:
402+
return decodeRecord(R, I->Name, Blob);
403+
case CONCEPT_IS_TYPE:
404+
return decodeRecord(R, I->IsType, Blob);
405+
case CONCEPT_CONSTRAINT_EXPRESSION:
406+
return decodeRecord(R, I->ConstraintExpression, Blob);
407+
}
408+
llvm_unreachable("invalid field for ConceptInfo");
409+
}
410+
411+
static llvm::Error parseRecord(const Record &R, unsigned ID,
412+
llvm::StringRef Blob, ConstraintInfo *I) {
413+
if (ID == CONSTRAINT_EXPRESSION)
414+
return decodeRecord(R, I->Expression, Blob);
415+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
416+
"invalid field for ConstraintInfo");
417+
}
418+
394419
template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
395420
return llvm::createStringError(llvm::inconvertibleErrorCode(),
396421
"invalid type cannot contain CommentInfo");
@@ -429,6 +454,10 @@ template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) {
429454
return I->Children.back().get();
430455
}
431456

457+
template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
458+
return &I->Description.emplace_back();
459+
}
460+
432461
// When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
433462
// the parent block to set it. The template specializations define what to do
434463
// for each supported parent block.
@@ -584,6 +613,18 @@ template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
584613
}
585614
}
586615

616+
template <>
617+
llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F) {
618+
switch (F) {
619+
case FieldId::F_concept:
620+
I->ConceptRef = std::move(R);
621+
return llvm::Error::success();
622+
default:
623+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
624+
"invalid type cannot contain Reference");
625+
}
626+
}
627+
587628
template <typename T, typename ChildInfoType>
588629
static void addChild(T I, ChildInfoType &&R) {
589630
llvm::errs() << "invalid child type for info";
@@ -600,6 +641,9 @@ template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
600641
template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
601642
I->Children.Typedefs.emplace_back(std::move(R));
602643
}
644+
template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) {
645+
I->Children.Concepts.emplace_back(std::move(R));
646+
}
603647

604648
// Record children:
605649
template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
@@ -649,6 +693,9 @@ template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
649693
template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
650694
I->Template.emplace(std::move(P));
651695
}
696+
template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {
697+
I->Template = std::move(P);
698+
}
652699

653700
// Template specializations go only into template records.
654701
template <typename T>
@@ -662,6 +709,14 @@ void addTemplateSpecialization(TemplateInfo *I,
662709
I->Specialization.emplace(std::move(TSI));
663710
}
664711

712+
template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {
713+
llvm::errs() << "invalid container for constraint info";
714+
exit(1);
715+
}
716+
template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) {
717+
I->Constraints.emplace_back(std::move(C));
718+
}
719+
665720
// Read records from bitcode into a given info.
666721
template <typename T>
667722
llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
@@ -817,6 +872,20 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
817872
addChild(I, std::move(TI));
818873
return llvm::Error::success();
819874
}
875+
case BI_CONSTRAINT_BLOCK_ID: {
876+
ConstraintInfo CI;
877+
if (auto Err = readBlock(ID, &CI))
878+
return Err;
879+
addConstraint(I, std::move(CI));
880+
return llvm::Error::success();
881+
}
882+
case BI_CONCEPT_BLOCK_ID: {
883+
ConceptInfo CI;
884+
if (auto Err = readBlock(ID, &CI))
885+
return Err;
886+
addChild(I, std::move(CI));
887+
return llvm::Error::success();
888+
}
820889
default:
821890
return llvm::createStringError(llvm::inconvertibleErrorCode(),
822891
"invalid subblock type");
@@ -922,6 +991,8 @@ ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
922991
return createInfo<EnumInfo>(ID);
923992
case BI_TYPEDEF_BLOCK_ID:
924993
return createInfo<TypedefInfo>(ID);
994+
case BI_CONCEPT_BLOCK_ID:
995+
return createInfo<ConceptInfo>(ID);
925996
case BI_FUNCTION_BLOCK_ID:
926997
return createInfo<FunctionInfo>(ID);
927998
default:
@@ -962,6 +1033,7 @@ ClangDocBitcodeReader::readBitcode() {
9621033
case BI_RECORD_BLOCK_ID:
9631034
case BI_ENUM_BLOCK_ID:
9641035
case BI_TYPEDEF_BLOCK_ID:
1036+
case BI_CONCEPT_BLOCK_ID:
9651037
case BI_FUNCTION_BLOCK_ID: {
9661038
auto InfoOrErr = readBlockToInfo(ID);
9671039
if (!InfoOrErr)

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

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,9 @@ static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
128128
{BI_REFERENCE_BLOCK_ID, "ReferenceBlock"},
129129
{BI_TEMPLATE_BLOCK_ID, "TemplateBlock"},
130130
{BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, "TemplateSpecializationBlock"},
131-
{BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"}};
131+
{BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"},
132+
{BI_CONSTRAINT_BLOCK_ID, "ConstraintBlock"},
133+
{BI_CONCEPT_BLOCK_ID, "ConceptBlock"}};
132134
assert(Inits.size() == BlockIdCount);
133135
for (const auto &Init : Inits)
134136
BlockIdNameMap[Init.first] = Init.second;
@@ -205,7 +207,13 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
205207
{TYPEDEF_USR, {"USR", &genSymbolIdAbbrev}},
206208
{TYPEDEF_NAME, {"Name", &genStringAbbrev}},
207209
{TYPEDEF_DEFLOCATION, {"DefLocation", &genLocationAbbrev}},
208-
{TYPEDEF_IS_USING, {"IsUsing", &genBoolAbbrev}}};
210+
{TYPEDEF_IS_USING, {"IsUsing", &genBoolAbbrev}},
211+
{CONCEPT_USR, {"USR", &genSymbolIdAbbrev}},
212+
{CONCEPT_NAME, {"Name", &genStringAbbrev}},
213+
{CONCEPT_IS_TYPE, {"IsType", &genBoolAbbrev}},
214+
{CONCEPT_CONSTRAINT_EXPRESSION,
215+
{"ConstraintExpression", &genStringAbbrev}},
216+
{CONSTRAINT_EXPRESSION, {"Expression", &genStringAbbrev}}};
209217
assert(Inits.size() == RecordIdCount);
210218
for (const auto &Init : Inits) {
211219
RecordIdNameMap[Init.first] = Init.second;
@@ -263,7 +271,13 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
263271
// Template Blocks.
264272
{BI_TEMPLATE_BLOCK_ID, {}},
265273
{BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},
266-
{BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, {TEMPLATE_SPECIALIZATION_OF}}};
274+
{BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, {TEMPLATE_SPECIALIZATION_OF}},
275+
// Concept Block
276+
{BI_CONCEPT_BLOCK_ID,
277+
{CONCEPT_USR, CONCEPT_NAME, CONCEPT_IS_TYPE,
278+
CONCEPT_CONSTRAINT_EXPRESSION}},
279+
// Constraint Block
280+
{BI_CONSTRAINT_BLOCK_ID, {CONSTRAINT_EXPRESSION}}};
267281

268282
// AbbreviationMap
269283

@@ -524,6 +538,8 @@ void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) {
524538
emitBlock(C);
525539
for (const auto &C : I.Children.Typedefs)
526540
emitBlock(C);
541+
for (const auto &C : I.Children.Concepts)
542+
emitBlock(C);
527543
}
528544

529545
void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) {
@@ -627,12 +643,25 @@ void ClangDocBitcodeWriter::emitBlock(const FunctionInfo &I) {
627643
emitBlock(*I.Template);
628644
}
629645

646+
void ClangDocBitcodeWriter::emitBlock(const ConceptInfo &I) {
647+
StreamSubBlockGuard Block(Stream, BI_CONCEPT_BLOCK_ID);
648+
emitRecord(I.USR, CONCEPT_USR);
649+
emitRecord(I.Name, CONCEPT_NAME);
650+
for (const auto &CI : I.Description)
651+
emitBlock(CI);
652+
emitRecord(I.IsType, CONCEPT_IS_TYPE);
653+
emitRecord(I.ConstraintExpression, CONCEPT_CONSTRAINT_EXPRESSION);
654+
emitBlock(I.Template);
655+
}
656+
630657
void ClangDocBitcodeWriter::emitBlock(const TemplateInfo &T) {
631658
StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);
632659
for (const auto &P : T.Params)
633660
emitBlock(P);
634661
if (T.Specialization)
635662
emitBlock(*T.Specialization);
663+
for (const auto &C : T.Constraints)
664+
emitBlock(C);
636665
}
637666

638667
void ClangDocBitcodeWriter::emitBlock(const TemplateSpecializationInfo &T) {
@@ -647,6 +676,12 @@ void ClangDocBitcodeWriter::emitBlock(const TemplateParamInfo &T) {
647676
emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);
648677
}
649678

679+
void ClangDocBitcodeWriter::emitBlock(const ConstraintInfo &C) {
680+
StreamSubBlockGuard Block(Stream, BI_CONSTRAINT_BLOCK_ID);
681+
emitRecord(C.Expression, CONSTRAINT_EXPRESSION);
682+
emitBlock(C.ConceptRef, FieldId::F_concept);
683+
}
684+
650685
bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
651686
switch (I->IT) {
652687
case InfoType::IT_namespace:
@@ -664,6 +699,9 @@ bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
664699
case InfoType::IT_typedef:
665700
emitBlock(*static_cast<clang::doc::TypedefInfo *>(I));
666701
break;
702+
case InfoType::IT_concept:
703+
emitBlock(*static_cast<clang::doc::ConceptInfo *>(I));
704+
break;
667705
case InfoType::IT_default:
668706
llvm::errs() << "Unexpected info, unable to write.\n";
669707
return true;

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ enum BlockId {
6666
BI_TEMPLATE_BLOCK_ID,
6767
BI_TEMPLATE_SPECIALIZATION_BLOCK_ID,
6868
BI_TEMPLATE_PARAM_BLOCK_ID,
69+
BI_CONSTRAINT_BLOCK_ID,
6970
BI_TYPEDEF_BLOCK_ID,
71+
BI_CONCEPT_BLOCK_ID,
7072
BI_LAST,
7173
BI_FIRST = BI_VERSION_BLOCK_ID
7274
};
@@ -135,6 +137,11 @@ enum RecordId {
135137
TYPEDEF_NAME,
136138
TYPEDEF_DEFLOCATION,
137139
TYPEDEF_IS_USING,
140+
CONCEPT_USR,
141+
CONCEPT_NAME,
142+
CONCEPT_IS_TYPE,
143+
CONCEPT_CONSTRAINT_EXPRESSION,
144+
CONSTRAINT_EXPRESSION,
138145
RI_LAST,
139146
RI_FIRST = VERSION
140147
};
@@ -150,7 +157,8 @@ enum class FieldId {
150157
F_vparent,
151158
F_type,
152159
F_child_namespace,
153-
F_child_record
160+
F_child_record,
161+
F_concept
154162
};
155163

156164
class ClangDocBitcodeWriter {
@@ -179,6 +187,8 @@ class ClangDocBitcodeWriter {
179187
void emitBlock(const TemplateInfo &T);
180188
void emitBlock(const TemplateSpecializationInfo &T);
181189
void emitBlock(const TemplateParamInfo &T);
190+
void emitBlock(const ConceptInfo &T);
191+
void emitBlock(const ConstraintInfo &T);
182192
void emitBlock(const Reference &B, FieldId F);
183193

184194
private:

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ static void serializeCommonChildren(const ScopeChildren &Children,
248248
}
249249
}
250250

251+
static void serializeInfo(const ConstraintInfo &I, Object &Obj) {
252+
serializeReference(I.ConceptRef, Obj);
253+
Obj["Expression"] = I.Expression;
254+
}
255+
251256
static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
252257
json::Value TemplateVal = Object();
253258
auto &TemplateObj = *TemplateVal.getAsObject();
@@ -277,9 +282,30 @@ static void serializeInfo(const TemplateInfo &Template, Object &Obj) {
277282
TemplateObj["Parameters"] = ParamsArray;
278283
}
279284

285+
if (!Template.Constraints.empty()) {
286+
json::Value ConstraintsArray = Array();
287+
auto &ConstraintsArrayRef = *ConstraintsArray.getAsArray();
288+
ConstraintsArrayRef.reserve(Template.Constraints.size());
289+
for (const auto &Constraint : Template.Constraints) {
290+
json::Value ConstraintVal = Object();
291+
auto &ConstraintObj = *ConstraintVal.getAsObject();
292+
serializeInfo(Constraint, ConstraintObj);
293+
ConstraintsArrayRef.push_back(ConstraintVal);
294+
}
295+
TemplateObj["Constraints"] = ConstraintsArray;
296+
}
297+
280298
Obj["Template"] = TemplateVal;
281299
}
282300

301+
static void serializeInfo(const ConceptInfo &I, Object &Obj,
302+
std::optional<StringRef> RepositoryUrl) {
303+
serializeCommonAttributes(I, Obj, RepositoryUrl);
304+
Obj["IsType"] = I.IsType;
305+
Obj["ConstraintExpression"] = I.ConstraintExpression;
306+
serializeInfo(I.Template, Obj);
307+
}
308+
283309
static void serializeInfo(const TypeInfo &I, Object &Obj) {
284310
Obj["Name"] = I.Type.Name;
285311
Obj["QualName"] = I.Type.QualName;
@@ -470,6 +496,19 @@ static void serializeInfo(const NamespaceInfo &I, json::Object &Obj,
470496
Obj["Functions"] = FunctionsArray;
471497
}
472498

499+
if (!I.Children.Concepts.empty()) {
500+
json::Value ConceptsArray = Array();
501+
auto &ConceptsArrayRef = *ConceptsArray.getAsArray();
502+
ConceptsArrayRef.reserve(I.Children.Concepts.size());
503+
for (const auto &Concept : I.Children.Concepts) {
504+
json::Value ConceptVal = Object();
505+
auto &ConceptObj = *ConceptVal.getAsObject();
506+
serializeInfo(Concept, ConceptObj, RepositoryUrl);
507+
ConceptsArrayRef.push_back(ConceptVal);
508+
}
509+
Obj["Concepts"] = ConceptsArray;
510+
}
511+
473512
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
474513
}
475514

@@ -520,6 +559,7 @@ Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
520559
case InfoType::IT_record:
521560
serializeInfo(*static_cast<RecordInfo *>(I), Obj, CDCtx.RepositoryUrl);
522561
break;
562+
case InfoType::IT_concept:
523563
case InfoType::IT_enum:
524564
case InfoType::IT_function:
525565
case InfoType::IT_typedef:

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ bool MapASTVisitor::VisitTypeAliasDecl(const TypeAliasDecl *D) {
134134
return mapDecl(D, /*isDefinition=*/true);
135135
}
136136

137+
bool MapASTVisitor::VisitConceptDecl(const ConceptDecl *D) {
138+
return mapDecl(D, true);
139+
}
140+
137141
comments::FullComment *
138142
MapASTVisitor::getComment(const NamedDecl *D, const ASTContext &Context) const {
139143
RawComment *Comment = Context.getRawCommentForDeclNoCache(D);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>,
4141
bool VisitFunctionDecl(const FunctionDecl *D);
4242
bool VisitTypedefDecl(const TypedefDecl *D);
4343
bool VisitTypeAliasDecl(const TypeAliasDecl *D);
44+
bool VisitConceptDecl(const ConceptDecl *D);
4445

4546
private:
4647
template <typename T> bool mapDecl(const T *D, bool IsDefinition);

0 commit comments

Comments
 (0)