Skip to content

Commit 9f39ac3

Browse files
committed
[clang-doc] document-concepts
1 parent 8d8b900 commit 9f39ac3

File tree

10 files changed

+273
-7
lines changed

10 files changed

+273
-7
lines changed

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

Lines changed: 72 additions & 1 deletion
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();
@@ -369,7 +371,6 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
369371

370372
static llvm::Error parseRecord(const Record &R, unsigned ID,
371373
llvm::StringRef Blob, TemplateInfo *I) {
372-
// Currently there are no child records of TemplateInfo (only child blocks).
373374
return llvm::createStringError(llvm::inconvertibleErrorCode(),
374375
"invalid field for TemplateParamInfo");
375376
}
@@ -391,6 +392,29 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
391392
"invalid field for TemplateParamInfo");
392393
}
393394

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

456+
template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
457+
return &I->Description.emplace_back();
458+
}
459+
432460
// When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
433461
// the parent block to set it. The template specializations define what to do
434462
// for each supported parent block.
@@ -584,6 +612,18 @@ template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
584612
}
585613
}
586614

615+
template <>
616+
llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F) {
617+
switch (F) {
618+
case FieldId::F_concept:
619+
I->ConceptRef = std::move(R);
620+
return llvm::Error::success();
621+
default:
622+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
623+
"invalid type cannot contain Reference");
624+
}
625+
}
626+
587627
template <typename T, typename ChildInfoType>
588628
static void addChild(T I, ChildInfoType &&R) {
589629
llvm::errs() << "invalid child type for info";
@@ -600,6 +640,9 @@ template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
600640
template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
601641
I->Children.Typedefs.emplace_back(std::move(R));
602642
}
643+
template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) {
644+
I->Children.Concepts.emplace_back(std::move(R));
645+
}
603646

604647
// Record children:
605648
template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
@@ -649,6 +692,9 @@ template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
649692
template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
650693
I->Template.emplace(std::move(P));
651694
}
695+
template <> void addTemplate(ConceptInfo *I, TemplateInfo &&P) {
696+
I->Template = std::move(P);
697+
}
652698

653699
// Template specializations go only into template records.
654700
template <typename T>
@@ -662,6 +708,14 @@ void addTemplateSpecialization(TemplateInfo *I,
662708
I->Specialization.emplace(std::move(TSI));
663709
}
664710

711+
template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {
712+
llvm::errs() << "invalid container for constraint info";
713+
exit(1);
714+
}
715+
template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) {
716+
I->Constraints.emplace_back(std::move(C));
717+
}
718+
665719
// Read records from bitcode into a given info.
666720
template <typename T>
667721
llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
@@ -817,6 +871,20 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
817871
addChild(I, std::move(TI));
818872
return llvm::Error::success();
819873
}
874+
case BI_CONSTRAINT_BLOCK_ID: {
875+
ConstraintInfo CI;
876+
if (auto Err = readBlock(ID, &CI))
877+
return Err;
878+
addConstraint(I, std::move(CI));
879+
return llvm::Error::success();
880+
}
881+
case BI_CONCEPT_BLOCK_ID: {
882+
ConceptInfo CI;
883+
if (auto Err = readBlock(ID, &CI))
884+
return Err;
885+
addChild(I, std::move(CI));
886+
return llvm::Error::success();
887+
}
820888
default:
821889
return llvm::createStringError(llvm::inconvertibleErrorCode(),
822890
"invalid subblock type");
@@ -922,6 +990,8 @@ ClangDocBitcodeReader::readBlockToInfo(unsigned ID) {
922990
return createInfo<EnumInfo>(ID);
923991
case BI_TYPEDEF_BLOCK_ID:
924992
return createInfo<TypedefInfo>(ID);
993+
case BI_CONCEPT_BLOCK_ID:
994+
return createInfo<ConceptInfo>(ID);
925995
case BI_FUNCTION_BLOCK_ID:
926996
return createInfo<FunctionInfo>(ID);
927997
default:
@@ -962,6 +1032,7 @@ ClangDocBitcodeReader::readBitcode() {
9621032
case BI_RECORD_BLOCK_ID:
9631033
case BI_ENUM_BLOCK_ID:
9641034
case BI_TYPEDEF_BLOCK_ID:
1035+
case BI_CONCEPT_BLOCK_ID:
9651036
case BI_FUNCTION_BLOCK_ID: {
9661037
auto InfoOrErr = readBlockToInfo(ID);
9671038
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)