[clang-tools-extra] [clang-doc] refactor JSON for better Mustache compatibility (PR #149588)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 18 14:11:10 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
Author: Erick Velez (evelez7)
<details>
<summary>Changes</summary>
This patch contains changes for the JSON generator that will enable compatibility with Mustache templates, like booleans to check for the existence and bounds of arrays to avoid duplication.
---
Patch is 28.25 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/149588.diff
17 Files Affected:
- (modified) clang-tools-extra/clang-doc/BitcodeReader.cpp (+2)
- (modified) clang-tools-extra/clang-doc/BitcodeWriter.cpp (+3-1)
- (modified) clang-tools-extra/clang-doc/BitcodeWriter.h (+1)
- (modified) clang-tools-extra/clang-doc/JSONGenerator.cpp (+49-10)
- (modified) clang-tools-extra/clang-doc/Representation.cpp (+2)
- (modified) clang-tools-extra/clang-doc/Representation.h (+10)
- (modified) clang-tools-extra/clang-doc/Serialize.cpp (+6-2)
- (modified) clang-tools-extra/test/clang-doc/json/class-requires.cpp (+1)
- (modified) clang-tools-extra/test/clang-doc/json/class-template.cpp (+1)
- (modified) clang-tools-extra/test/clang-doc/json/class.cpp (+18)
- (modified) clang-tools-extra/test/clang-doc/json/compound-constraints.cpp (+4)
- (modified) clang-tools-extra/test/clang-doc/json/concept.cpp (+2)
- (modified) clang-tools-extra/test/clang-doc/json/function-requires.cpp (+7)
- (modified) clang-tools-extra/test/clang-doc/json/method-template.cpp (+2)
- (modified) clang-tools-extra/test/clang-doc/json/namespace.cpp (+17)
- (modified) clang-tools-extra/test/clang-doc/json/nested-namespace.cpp (+4)
- (modified) clang-tools-extra/unittests/clang-doc/JSONGeneratorTest.cpp (+25)
``````````diff
diff --git a/clang-tools-extra/clang-doc/BitcodeReader.cpp b/clang-tools-extra/clang-doc/BitcodeReader.cpp
index dce34a8434ff8..4efbbd34730cf 100644
--- a/clang-tools-extra/clang-doc/BitcodeReader.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeReader.cpp
@@ -384,6 +384,8 @@ static llvm::Error parseRecord(const Record &R, unsigned ID,
return decodeRecord(R, I->Path, Blob);
case REFERENCE_FIELD:
return decodeRecord(R, F, Blob);
+ case REFERENCE_FILE:
+ return decodeRecord(R, I->DocumentationFileName, Blob);
default:
return llvm::createStringError(llvm::inconvertibleErrorCode(),
"invalid field for Reference");
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.cpp b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
index eed23726e17bf..e23511bf63690 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.cpp
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.cpp
@@ -210,6 +210,7 @@ static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
{REFERENCE_TYPE, {"RefType", &genIntAbbrev}},
{REFERENCE_PATH, {"Path", &genStringAbbrev}},
{REFERENCE_FIELD, {"Field", &genIntAbbrev}},
+ {REFERENCE_FILE, {"File", &genStringAbbrev}},
{TEMPLATE_PARAM_CONTENTS, {"Contents", &genStringAbbrev}},
{TEMPLATE_SPECIALIZATION_OF,
{"SpecializationOf", &genSymbolIdAbbrev}},
@@ -286,7 +287,7 @@ static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
// Reference Block
{BI_REFERENCE_BLOCK_ID,
{REFERENCE_USR, REFERENCE_NAME, REFERENCE_QUAL_NAME, REFERENCE_TYPE,
- REFERENCE_PATH, REFERENCE_FIELD}},
+ REFERENCE_PATH, REFERENCE_FIELD, REFERENCE_FILE}},
// Template Blocks.
{BI_TEMPLATE_BLOCK_ID, {}},
{BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},
@@ -479,6 +480,7 @@ void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
emitRecord(R.Path, REFERENCE_PATH);
emitRecord((unsigned)Field, REFERENCE_FIELD);
+ emitRecord(R.DocumentationFileName, REFERENCE_FILE);
}
void ClangDocBitcodeWriter::emitBlock(const FriendInfo &R) {
diff --git a/clang-tools-extra/clang-doc/BitcodeWriter.h b/clang-tools-extra/clang-doc/BitcodeWriter.h
index 501af12582a8e..688f886b45308 100644
--- a/clang-tools-extra/clang-doc/BitcodeWriter.h
+++ b/clang-tools-extra/clang-doc/BitcodeWriter.h
@@ -140,6 +140,7 @@ enum RecordId {
REFERENCE_TYPE,
REFERENCE_PATH,
REFERENCE_FIELD,
+ REFERENCE_FILE,
TEMPLATE_PARAM_CONTENTS,
TEMPLATE_SPECIALIZATION_OF,
TYPEDEF_USR,
diff --git a/clang-tools-extra/clang-doc/JSONGenerator.cpp b/clang-tools-extra/clang-doc/JSONGenerator.cpp
index cc4c68346ec53..908e23d24d079 100644
--- a/clang-tools-extra/clang-doc/JSONGenerator.cpp
+++ b/clang-tools-extra/clang-doc/JSONGenerator.cpp
@@ -43,6 +43,30 @@ static auto SerializeReferenceLambda = [](const auto &Ref, Object &Object) {
serializeReference(Ref, Object);
};
+static std::string infoTypeToString(InfoType IT) {
+ switch (IT) {
+ case InfoType::IT_default:
+ return "default";
+ case InfoType::IT_namespace:
+ return "namespace";
+ case InfoType::IT_record:
+ return "record";
+ case InfoType::IT_function:
+ return "function";
+ case InfoType::IT_enum:
+ return "enum";
+ case InfoType::IT_typedef:
+ return "typedef";
+ case InfoType::IT_concept:
+ return "concept";
+ case InfoType::IT_variable:
+ return "variable";
+ case InfoType::IT_friend:
+ return "friend";
+ }
+ llvm_unreachable("Unknown InfoType encountered.");
+}
+
static json::Object
serializeLocation(const Location &Loc,
const std::optional<StringRef> RepositoryUrl) {
@@ -172,6 +196,9 @@ serializeCommonAttributes(const Info &I, json::Object &Obj,
const std::optional<StringRef> RepositoryUrl) {
Obj["Name"] = I.Name;
Obj["USR"] = toHex(toStringRef(I.USR));
+ Obj["InfoType"] = infoTypeToString(I.IT);
+ if (!I.DocumentationFileName.empty())
+ Obj["DocumentationFileName"] = I.DocumentationFileName;
if (!I.Path.empty())
Obj["Path"] = I.Path;
@@ -205,6 +232,8 @@ static void serializeReference(const Reference &Ref, Object &ReferenceObj) {
ReferenceObj["Name"] = Ref.Name;
ReferenceObj["QualName"] = Ref.QualName;
ReferenceObj["USR"] = toHex(toStringRef(Ref.USR));
+ if (!Ref.DocumentationFileName.empty())
+ ReferenceObj["DocumentationFileName"] = Ref.DocumentationFileName;
}
// Although namespaces and records both have ScopeChildren, they serialize them
@@ -217,14 +246,18 @@ serializeCommonChildren(const ScopeChildren &Children, json::Object &Obj,
serializeInfo(Info, Object, RepositoryUrl);
};
- if (!Children.Enums.empty())
+ if (!Children.Enums.empty()) {
serializeArray(Children.Enums, Obj, "Enums", SerializeInfo);
+ Obj["HasEnums"] = true;
+ }
if (!Children.Typedefs.empty())
serializeArray(Children.Typedefs, Obj, "Typedefs", SerializeInfo);
- if (!Children.Records.empty())
+ if (!Children.Records.empty()) {
serializeArray(Children.Records, Obj, "Records", SerializeReferenceLambda);
+ Obj["HasRecords"] = true;
+ }
}
template <typename Container, typename SerializationFunc>
@@ -234,10 +267,12 @@ static void serializeArray(const Container &Records, Object &Obj,
json::Value RecordsArray = Array();
auto &RecordsArrayRef = *RecordsArray.getAsArray();
RecordsArrayRef.reserve(Records.size());
- for (const auto &Item : Records) {
+ for (size_t Index = 0; Index < Records.size(); ++Index) {
json::Value ItemVal = Object();
auto &ItemObj = *ItemVal.getAsObject();
- SerializeInfo(Item, ItemObj);
+ SerializeInfo(Records[Index], ItemObj);
+ if (Index == Records.size() - 1)
+ ItemObj["End"] = true;
RecordsArrayRef.push_back(ItemVal);
}
Obj[Key] = RecordsArray;
@@ -405,8 +440,10 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
ProtFunctionsArrayRef.push_back(FunctionVal);
}
- if (!PubFunctionsArrayRef.empty())
+ if (!PubFunctionsArrayRef.empty()) {
Obj["PublicFunctions"] = PubFunctionsArray;
+ Obj["HasPublicFunctions"] = true;
+ }
if (!ProtFunctionsArrayRef.empty())
Obj["ProtectedFunctions"] = ProtFunctionsArray;
}
@@ -429,8 +466,10 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
ProtMembersArrayRef.push_back(MemberVal);
}
- if (!PubMembersArrayRef.empty())
+ if (!PubMembersArrayRef.empty()) {
Obj["PublicMembers"] = PublicMembersArray;
+ Obj["HasPublicMembers"] = true;
+ }
if (!ProtMembersArrayRef.empty())
Obj["ProtectedMembers"] = ProtectedMembersArray;
}
@@ -496,10 +535,7 @@ static SmallString<16> determineFileName(Info *I, SmallString<128> &Path) {
SmallString<16> FileName;
if (I->IT == InfoType::IT_record) {
auto *RecordSymbolInfo = static_cast<SymbolInfo *>(I);
- if (RecordSymbolInfo->MangledName.size() < 255)
- FileName = RecordSymbolInfo->MangledName;
- else
- FileName = toStringRef(toHex(RecordSymbolInfo->USR));
+ FileName = RecordSymbolInfo->MangledName;
} else if (I->IT == InfoType::IT_namespace && I->Name != "")
// Serialize the global namespace as index.json
FileName = I->Name;
@@ -527,7 +563,10 @@ Error JSONGenerator::generateDocs(
}
SmallString<16> FileName = determineFileName(Info, Path);
+ if (FileToInfos.contains(Path))
+ continue;
FileToInfos[Path].push_back(Info);
+ Info->DocumentationFileName = FileName;
}
for (const auto &Group : FileToInfos) {
diff --git a/clang-tools-extra/clang-doc/Representation.cpp b/clang-tools-extra/clang-doc/Representation.cpp
index beaf314a04ae1..79850e1f90253 100644
--- a/clang-tools-extra/clang-doc/Representation.cpp
+++ b/clang-tools-extra/clang-doc/Representation.cpp
@@ -247,6 +247,8 @@ void Reference::merge(Reference &&Other) {
Name = Other.Name;
if (Path.empty())
Path = Other.Path;
+ if (DocumentationFileName.empty())
+ DocumentationFileName = Other.DocumentationFileName;
}
bool FriendInfo::mergeable(const FriendInfo &Other) {
diff --git a/clang-tools-extra/clang-doc/Representation.h b/clang-tools-extra/clang-doc/Representation.h
index 23f0e90daa27f..2a75f89696b7d 100644
--- a/clang-tools-extra/clang-doc/Representation.h
+++ b/clang-tools-extra/clang-doc/Representation.h
@@ -121,6 +121,10 @@ struct Reference {
Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName,
StringRef Path = StringRef())
: USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path) {}
+ Reference(SymbolID USR, StringRef Name, InfoType IT, StringRef QualName,
+ StringRef Path, SmallString<16> DocumentationFileName)
+ : USR(USR), Name(Name), QualName(QualName), RefType(IT), Path(Path),
+ DocumentationFileName(DocumentationFileName) {}
bool operator==(const Reference &Other) const {
return std::tie(USR, Name, QualName, RefType) ==
@@ -155,6 +159,7 @@ struct Reference {
// Path of directory where the clang-doc generated file will be saved
// (possibly unresolved)
llvm::SmallString<128> Path;
+ SmallString<16> DocumentationFileName;
};
// Holds the children of a record or namespace.
@@ -331,6 +336,11 @@ struct Info {
llvm::SmallString<128> Path; // Path of directory where the clang-doc
// generated file will be saved
+ // The name used for the file that this info is documented in.
+ // In the JSON generator, infos are documented in files with mangled names.
+ // Thus, we keep track of the physical filename for linking purposes.
+ SmallString<16> DocumentationFileName;
+
void mergeBase(Info &&I);
bool mergeable(const Info &Other);
diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp
index 7a0e00c6d9c2d..3e0e54bf53419 100644
--- a/clang-tools-extra/clang-doc/Serialize.cpp
+++ b/clang-tools-extra/clang-doc/Serialize.cpp
@@ -495,7 +495,8 @@ static void InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) {
static void InsertChild(ScopeChildren &Scope, const RecordInfo &Info) {
Scope.Records.emplace_back(Info.USR, Info.Name, InfoType::IT_record,
- Info.Name, getInfoRelativePath(Info.Namespace));
+ Info.Name, getInfoRelativePath(Info.Namespace),
+ Info.MangledName);
}
static void InsertChild(ScopeChildren &Scope, EnumInfo Info) {
@@ -777,7 +778,10 @@ static void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
Mangler->mangleCXXVTable(CXXD, MangledStream);
else
MangledStream << D->getNameAsString();
- I.MangledName = MangledName;
+ if (MangledName.size() > 255)
+ I.MangledName = llvm::toStringRef(llvm::toHex(I.USR));
+ else
+ I.MangledName = MangledName;
delete Mangler;
}
diff --git a/clang-tools-extra/test/clang-doc/json/class-requires.cpp b/clang-tools-extra/test/clang-doc/json/class-requires.cpp
index 213da93a1adfa..bf6c889849a70 100644
--- a/clang-tools-extra/test/clang-doc/json/class-requires.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class-requires.cpp
@@ -20,6 +20,7 @@ struct MyClass;
// CHECK-NEXT: "Template": {
// CHECK-NEXT: "Constraints": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Addable<T>",
// CHECK-NEXT: "Name": "Addable",
// CHECK-NEXT: "Path": "",
diff --git a/clang-tools-extra/test/clang-doc/json/class-template.cpp b/clang-tools-extra/test/clang-doc/json/class-template.cpp
index 6cdc3e9175278..149248c772055 100644
--- a/clang-tools-extra/test/clang-doc/json/class-template.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class-template.cpp
@@ -11,6 +11,7 @@ template<typename T> struct MyClass {
// CHECK: "Name": "method",
// CHECK: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "Param",
// CHECK-NEXT: "Type": "T"
// CHECK-NEXT: }
diff --git a/clang-tools-extra/test/clang-doc/json/class.cpp b/clang-tools-extra/test/clang-doc/json/class.cpp
index d8317eafea91a..a36358982b019 100644
--- a/clang-tools-extra/test/clang-doc/json/class.cpp
+++ b/clang-tools-extra/test/clang-doc/json/class.cpp
@@ -60,8 +60,11 @@ struct MyClass {
// CHECK-NEXT: "TextComment": " This is a brief description."
// CHECK-NEXT: }
// CHECK: "Command": "brief"
+// CHECK: "DocumentationFileName": "_ZTV7MyClass",
// CHECK: "Enums": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "enum",
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}class.cpp",
// CHECK-NEXT: "LineNumber": 17
@@ -76,6 +79,7 @@ struct MyClass {
// CHECK-NEXT: "Value": "1"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "BLUE",
// CHECK-NEXT: "ValueExpr": "5"
// CHECK-NEXT: }
@@ -94,6 +98,7 @@ struct MyClass {
// CHECK-NEXT: "IsClass": false,
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "",
// CHECK-NEXT: "Type": "int"
// CHECK-NEXT: }
@@ -118,6 +123,7 @@ struct MyClass {
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "IsClass": true,
// CHECK-NEXT: "Reference": {
// CHECK-NEXT: "Name": "Foo",
@@ -129,6 +135,11 @@ struct MyClass {
// CHECK-NEXT: ],
// COM: FIXME: FullName is not emitted correctly.
// CHECK-NEXT: "FullName": "",
+// CHECK-NEXT: "HasEnums": true,
+// CHECK-NEXT: "HasPublicFunctions": true,
+// CHECK-NEXT: "HasPublicMembers": true,
+// CHECK-NEXT: "HasRecords": true,
+// CHECK-NEXT: "InfoType": "record",
// CHECK-NEXT: "IsTypedef": false,
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}class.cpp",
@@ -142,6 +153,7 @@ struct MyClass {
// CHECK-NEXT: "Path": "GlobalNamespace",
// CHECK-NEXT: "ProtectedFunctions": [
// CHECK-NEXT: {
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "protectedMethod",
// CHECK-NEXT: "Namespace": [
@@ -166,6 +178,7 @@ struct MyClass {
// CHECK-NEXT: ],
// CHECK-NEXT: "PublicFunctions": [
// CHECK-NEXT: {
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "myMethod",
// CHECK-NEXT: "Namespace": [
@@ -174,6 +187,7 @@ struct MyClass {
// CHECK-NEXT: ],
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "MyParam",
// CHECK-NEXT: "Type": "int"
// CHECK-NEXT: }
@@ -204,6 +218,8 @@ struct MyClass {
// CHECK-NEXT: ],
// CHECK-NEXT: "Records": [
// CHECK-NEXT: {
+// CHECK-NEXT: "DocumentationFileName": "_ZTVN7MyClass11NestedClassE",
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "NestedClass",
// CHECK-NEXT: "Path": "GlobalNamespace{{[\/]+}}MyClass",
// CHECK-NEXT: "QualName": "NestedClass",
@@ -213,6 +229,8 @@ struct MyClass {
// CHECK-NEXT: "TagType": "struct",
// CHECK-NEXT: "Typedefs": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "typedef",
// CHECK-NEXT: "IsUsing": false,
// CHECK-NEXT: "Location": {
// CHECK-NEXT: "Filename": "{{.*}}class.cpp",
diff --git a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
index 34acb6808409d..bb2b4ca770fc0 100644
--- a/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
+++ b/clang-tools-extra/test/clang-doc/json/compound-constraints.cpp
@@ -37,6 +37,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Decrementable<T>",
// CHECK-NEXT: "Name": "Decrementable",
// CHECK-NEXT: "Path": "",
@@ -55,6 +56,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Decrementable<T>",
// CHECK-NEXT: "Name": "Decrementable",
// CHECK-NEXT: "Path": "",
@@ -87,6 +89,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "PreDecrementable<T>",
// CHECK-NEXT: "Name": "PreDecrementable",
// CHECK-NEXT: "Path": "",
@@ -112,6 +115,7 @@ template<typename T> requires (Incrementable<T> && Decrementable<T>) || PreIncre
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "PreIncrementable<T>",
// CHECK-NEXT: "Name": "PreIncrementable",
// CHECK-NEXT: "Path": "",
diff --git a/clang-tools-extra/test/clang-doc/json/concept.cpp b/clang-tools-extra/test/clang-doc/json/concept.cpp
index b946393274c85..766415bbbeecd 100644
--- a/clang-tools-extra/test/clang-doc/json/concept.cpp
+++ b/clang-tools-extra/test/clang-doc/json/concept.cpp
@@ -23,6 +23,8 @@ concept Incrementable = requires(T x) {
// CHECK-NEXT: {
// CHECK-NEXT: "TextComment": " Requires that T suports post and pre-incrementing."
// CHECK: ],
+// CHECK: "End": true,
+// CHECK-NEXT: "InfoType": "concept",
// CHECK-NEXT: "IsType": true,
// CHECK-NEXT: "Name": "Incrementable",
// CHECK-NEXT: "Template": {
diff --git a/clang-tools-extra/test/clang-doc/json/function-requires.cpp b/clang-tools-extra/test/clang-doc/json/function-requires.cpp
index 08ac4c7ed2ca3..59ed39ee61fda 100644
--- a/clang-tools-extra/test/clang-doc/json/function-requires.cpp
+++ b/clang-tools-extra/test/clang-doc/json/function-requires.cpp
@@ -14,10 +14,12 @@ template<Incrementable T> Incrementable auto incrementTwo(T t);
// CHECK: "Functions": [
// CHECK-NEXT: {
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "increment",
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "t",
// CHECK-NEXT: "Type": "T"
// CHECK-NEXT: }
@@ -32,6 +34,7 @@ template<Incrementable T> Incrementable auto incrementTwo(T t);
// CHECK-NEXT: "Template": {
// CHECK-NEXT: "Constraints": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Expression": "Incrementable<T>",
// CHECK-NEXT: "Name": "Incrementable",
// CHECK-NEXT: "Path": "",
@@ -46,10 +49,13 @@ template<Incrementable T> Incrementable auto incrementTwo(T t);
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
// CHECK-NEXT: },
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
+// CHECK-NEXT: "InfoType": "function",
// CHECK-NEXT: "IsStatic": false,
// CHECK-NEXT: "Name": "incrementTwo",
// CHECK-NEXT: "Params": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: "Name": "t",
// CHECK-NEXT: "Type": "T"
// CHECK-NEXT: }
@@ -64,6 +70,7 @@ template<Incrementable T> Incrementable auto incrementTwo(T t);
// CHECK-NEXT: "Template": {
// CHECK-NEXT: "Constraints": [
// CHECK-NEXT: {
+// CHECK-NEXT: "End": true,
// CHECK-NEXT: ...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/149588
More information about the cfe-commits
mailing list