Skip to content

Commit 0f6dbb5

Browse files
committed
[clang-doc] Add template support.
Reads template information from the AST and adds template parameters and specialization information to the corresponding clang-doc structures. Add a "QualName" to the Reference struct which includes the full qualified type name. The Reference object represents a link in the HTML/MD generators so is based on the unqualified name. But this does not encode C-V qualifiers or template information that decorate the name. The new QualName member encodes all of this information and also makes it easier for the generators or downsteam YAML consumers to generate the full name (before they had to process the "Path"). In test code that was changed, remove made-up paths to built-in types like "int". In addition to slightnly cleaning up the code, these types do not have paths in real execution, and generating incorrect references to nonexistant data may complicate future changes in the generators. Differential Revision: https://reviews.llvm.org/D139154
1 parent 538f69f commit 0f6dbb5

13 files changed

+587
-80
lines changed

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

+85
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,8 @@ llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
351351
return decodeRecord(R, I->USR, Blob);
352352
case REFERENCE_NAME:
353353
return decodeRecord(R, I->Name, Blob);
354+
case REFERENCE_QUAL_NAME:
355+
return decodeRecord(R, I->QualName, Blob);
354356
case REFERENCE_TYPE:
355357
return decodeRecord(R, I->RefType, Blob);
356358
case REFERENCE_PATH:
@@ -363,6 +365,29 @@ llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
363365
}
364366
}
365367

368+
llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
369+
TemplateInfo *I) {
370+
// Currently there are no child records of TemplateInfo (only child blocks).
371+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
372+
"invalid field for TemplateParamInfo");
373+
}
374+
375+
llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
376+
TemplateSpecializationInfo *I) {
377+
if (ID == TEMPLATE_SPECIALIZATION_OF)
378+
return decodeRecord(R, I->SpecializationOf, Blob);
379+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
380+
"invalid field for TemplateParamInfo");
381+
}
382+
383+
llvm::Error parseRecord(const Record &R, unsigned ID, llvm::StringRef Blob,
384+
TemplateParamInfo *I) {
385+
if (ID == TEMPLATE_PARAM_CONTENTS)
386+
return decodeRecord(R, I->Contents, Blob);
387+
return llvm::createStringError(llvm::inconvertibleErrorCode(),
388+
"invalid field for TemplateParamInfo");
389+
}
390+
366391
template <typename T> llvm::Expected<CommentInfo *> getCommentInfo(T I) {
367392
return llvm::createStringError(llvm::inconvertibleErrorCode(),
368393
"invalid type cannot contain CommentInfo");
@@ -595,6 +620,45 @@ template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
595620
I->Children.Functions.emplace_back(std::move(R));
596621
}
597622

623+
// TemplateParam children. These go into either a TemplateInfo (for template
624+
// parameters) or TemplateSpecializationInfo (for the specialization's
625+
// parameters).
626+
template <typename T> void addTemplateParam(T I, TemplateParamInfo &&P) {
627+
llvm::errs() << "invalid container for template parameter";
628+
exit(1);
629+
}
630+
template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) {
631+
I->Params.emplace_back(std::move(P));
632+
}
633+
template <>
634+
void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) {
635+
I->Params.emplace_back(std::move(P));
636+
}
637+
638+
// Template info. These apply to either records or functions.
639+
template <typename T> void addTemplate(T I, TemplateInfo &&P) {
640+
llvm::errs() << "invalid container for template info";
641+
exit(1);
642+
}
643+
template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) {
644+
I->Template.emplace(std::move(P));
645+
}
646+
template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) {
647+
I->Template.emplace(std::move(P));
648+
}
649+
650+
// Template specializations go only into template records.
651+
template <typename T>
652+
void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI) {
653+
llvm::errs() << "invalid container for template specialization info";
654+
exit(1);
655+
}
656+
template <>
657+
void addTemplateSpecialization(TemplateInfo *I,
658+
TemplateSpecializationInfo &&TSI) {
659+
I->Specialization.emplace(std::move(TSI));
660+
}
661+
598662
// Read records from bitcode into a given info.
599663
template <typename T>
600664
llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) {
@@ -719,6 +783,27 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
719783
addChild(I, std::move(EV));
720784
return llvm::Error::success();
721785
}
786+
case BI_TEMPLATE_BLOCK_ID: {
787+
TemplateInfo TI;
788+
if (auto Err = readBlock(ID, &TI))
789+
return Err;
790+
addTemplate(I, std::move(TI));
791+
return llvm::Error::success();
792+
}
793+
case BI_TEMPLATE_SPECIALIZATION_BLOCK_ID: {
794+
TemplateSpecializationInfo TSI;
795+
if (auto Err = readBlock(ID, &TSI))
796+
return Err;
797+
addTemplateSpecialization(I, std::move(TSI));
798+
return llvm::Error::success();
799+
}
800+
case BI_TEMPLATE_PARAM_BLOCK_ID: {
801+
TemplateParamInfo TPI;
802+
if (auto Err = readBlock(ID, &TPI))
803+
return Err;
804+
addTemplateParam(I, std::move(TPI));
805+
return llvm::Error::success();
806+
}
722807
case BI_TYPEDEF_BLOCK_ID: {
723808
TypedefInfo TI;
724809
if (auto Err = readBlock(ID, &TI))

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

+40-3
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,10 @@ static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
121121
{BI_BASE_RECORD_BLOCK_ID, "BaseRecordBlock"},
122122
{BI_FUNCTION_BLOCK_ID, "FunctionBlock"},
123123
{BI_COMMENT_BLOCK_ID, "CommentBlock"},
124-
{BI_REFERENCE_BLOCK_ID, "ReferenceBlock"}};
124+
{BI_REFERENCE_BLOCK_ID, "ReferenceBlock"},
125+
{BI_TEMPLATE_BLOCK_ID, "TemplateBlock"},
126+
{BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, "TemplateSpecializationBlock"},
127+
{BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"}};
125128
assert(Inits.size() == BlockIdCount);
126129
for (const auto &Init : Inits)
127130
BlockIdNameMap[Init.first] = Init.second;
@@ -186,9 +189,12 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
186189
{FUNCTION_IS_METHOD, {"IsMethod", &BoolAbbrev}},
187190
{REFERENCE_USR, {"USR", &SymbolIDAbbrev}},
188191
{REFERENCE_NAME, {"Name", &StringAbbrev}},
192+
{REFERENCE_QUAL_NAME, {"QualName", &StringAbbrev}},
189193
{REFERENCE_TYPE, {"RefType", &IntAbbrev}},
190194
{REFERENCE_PATH, {"Path", &StringAbbrev}},
191195
{REFERENCE_FIELD, {"Field", &IntAbbrev}},
196+
{TEMPLATE_PARAM_CONTENTS, {"Contents", &StringAbbrev}},
197+
{TEMPLATE_SPECIALIZATION_OF, {"SpecializationOf", &SymbolIDAbbrev}},
192198
{TYPEDEF_USR, {"USR", &SymbolIDAbbrev}},
193199
{TYPEDEF_NAME, {"Name", &StringAbbrev}},
194200
{TYPEDEF_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
@@ -244,8 +250,12 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
244250
FUNCTION_ACCESS, FUNCTION_IS_METHOD}},
245251
// Reference Block
246252
{BI_REFERENCE_BLOCK_ID,
247-
{REFERENCE_USR, REFERENCE_NAME, REFERENCE_TYPE, REFERENCE_PATH,
248-
REFERENCE_FIELD}}};
253+
{REFERENCE_USR, REFERENCE_NAME, REFERENCE_QUAL_NAME, REFERENCE_TYPE,
254+
REFERENCE_PATH, REFERENCE_FIELD}},
255+
// Template Blocks.
256+
{BI_TEMPLATE_BLOCK_ID, {}},
257+
{BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},
258+
{BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, {TEMPLATE_SPECIALIZATION_OF}}};
249259

250260
// AbbreviationMap
251261

@@ -378,6 +388,8 @@ void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
378388
Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
379389
}
380390

391+
void ClangDocBitcodeWriter::emitRecord(const TemplateInfo &Templ) {}
392+
381393
bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
382394
assert(RecordIdNameMap[ID] && "Unknown RecordId.");
383395
if (!ShouldEmit)
@@ -416,6 +428,7 @@ void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
416428
StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
417429
emitRecord(R.USR, REFERENCE_USR);
418430
emitRecord(R.Name, REFERENCE_NAME);
431+
emitRecord(R.QualName, REFERENCE_QUAL_NAME);
419432
emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
420433
emitRecord(R.Path, REFERENCE_PATH);
421434
emitRecord((unsigned)Field, REFERENCE_FIELD);
@@ -556,6 +569,8 @@ void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {
556569
emitBlock(C);
557570
for (const auto &C : I.Children.Typedefs)
558571
emitBlock(C);
572+
if (I.Template)
573+
emitBlock(*I.Template);
559574
}
560575

561576
void ClangDocBitcodeWriter::emitBlock(const BaseRecordInfo &I) {
@@ -591,6 +606,28 @@ void ClangDocBitcodeWriter::emitBlock(const FunctionInfo &I) {
591606
emitBlock(I.ReturnType);
592607
for (const auto &N : I.Params)
593608
emitBlock(N);
609+
if (I.Template)
610+
emitBlock(*I.Template);
611+
}
612+
613+
void ClangDocBitcodeWriter::emitBlock(const TemplateInfo &T) {
614+
StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);
615+
for (const auto &P : T.Params)
616+
emitBlock(P);
617+
if (T.Specialization)
618+
emitBlock(*T.Specialization);
619+
}
620+
621+
void ClangDocBitcodeWriter::emitBlock(const TemplateSpecializationInfo &T) {
622+
StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);
623+
emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);
624+
for (const auto &P : T.Params)
625+
emitBlock(P);
626+
}
627+
628+
void ClangDocBitcodeWriter::emitBlock(const TemplateParamInfo &T) {
629+
StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID);
630+
emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);
594631
}
595632

596633
bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {

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

+10-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
#include "Representation.h"
1919
#include "clang/AST/AST.h"
20-
#include "llvm/ADT/APSInt.h"
2120
#include "llvm/ADT/DenseMap.h"
2221
#include "llvm/ADT/SmallVector.h"
2322
#include "llvm/ADT/StringRef.h"
@@ -64,6 +63,9 @@ enum BlockId {
6463
BI_FUNCTION_BLOCK_ID,
6564
BI_COMMENT_BLOCK_ID,
6665
BI_REFERENCE_BLOCK_ID,
66+
BI_TEMPLATE_BLOCK_ID,
67+
BI_TEMPLATE_SPECIALIZATION_BLOCK_ID,
68+
BI_TEMPLATE_PARAM_BLOCK_ID,
6769
BI_TYPEDEF_BLOCK_ID,
6870
BI_LAST,
6971
BI_FIRST = BI_VERSION_BLOCK_ID
@@ -121,9 +123,12 @@ enum RecordId {
121123
BASE_RECORD_IS_PARENT,
122124
REFERENCE_USR,
123125
REFERENCE_NAME,
126+
REFERENCE_QUAL_NAME,
124127
REFERENCE_TYPE,
125128
REFERENCE_PATH,
126129
REFERENCE_FIELD,
130+
TEMPLATE_PARAM_CONTENTS,
131+
TEMPLATE_SPECIALIZATION_OF,
127132
TYPEDEF_USR,
128133
TYPEDEF_NAME,
129134
TYPEDEF_DEFLOCATION,
@@ -169,6 +174,9 @@ class ClangDocBitcodeWriter {
169174
void emitBlock(const FieldTypeInfo &B);
170175
void emitBlock(const MemberTypeInfo &T);
171176
void emitBlock(const CommentInfo &B);
177+
void emitBlock(const TemplateInfo &T);
178+
void emitBlock(const TemplateSpecializationInfo &T);
179+
void emitBlock(const TemplateParamInfo &T);
172180
void emitBlock(const Reference &B, FieldId F);
173181

174182
private:
@@ -215,7 +223,7 @@ class ClangDocBitcodeWriter {
215223
void emitRecord(bool Value, RecordId ID);
216224
void emitRecord(int Value, RecordId ID);
217225
void emitRecord(unsigned Value, RecordId ID);
218-
void emitRecord(llvm::APSInt Value, RecordId ID);
226+
void emitRecord(const TemplateInfo &Templ);
219227
bool prepRecordData(RecordId ID, bool ShouldEmit = true);
220228

221229
// Emission of appropriate abbreviation type.

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

+4
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ void RecordInfo::merge(RecordInfo &&Other) {
250250
reduceChildren(Children.Enums, std::move(Other.Children.Enums));
251251
reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs));
252252
SymbolInfo::merge(std::move(Other));
253+
if (!Template)
254+
Template = Other.Template;
253255
}
254256

255257
void EnumInfo::merge(EnumInfo &&Other) {
@@ -274,6 +276,8 @@ void FunctionInfo::merge(FunctionInfo &&Other) {
274276
if (Params.empty())
275277
Params = std::move(Other.Params);
276278
SymbolInfo::merge(std::move(Other));
279+
if (!Template)
280+
Template = Other.Template;
277281
}
278282

279283
void TypedefInfo::merge(TypedefInfo &&Other) {

0 commit comments

Comments
 (0)