[clang-doc] Use LangOpts when printing types (#120308)

The implementation in the clang-doc serializer failed to take in the
LangOpts from the declaration. As a result, we'd do things like print
`_Bool` instead of `bool`, even in C++ code.

Fixes #62970
This commit is contained in:
Paul Kirth 2024-12-18 08:39:19 -08:00 committed by GitHub
parent 72e58e00c2
commit 2b932bc111
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 26 additions and 19 deletions

View File

@ -236,10 +236,10 @@ static RecordDecl *getRecordDeclForType(const QualType &T) {
return nullptr;
}
TypeInfo getTypeInfoForType(const QualType &T) {
TypeInfo getTypeInfoForType(const QualType &T, const PrintingPolicy &Policy) {
const TagDecl *TD = getTagDeclForType(T);
if (!TD)
return TypeInfo(Reference(SymbolID(), T.getAsString()));
return TypeInfo(Reference(SymbolID(), T.getAsString(Policy)));
InfoType IT;
if (dyn_cast<EnumDecl>(TD)) {
@ -250,7 +250,7 @@ TypeInfo getTypeInfoForType(const QualType &T) {
IT = InfoType::IT_default;
}
return TypeInfo(Reference(getUSRForDecl(TD), TD->getNameAsString(), IT,
T.getAsString(), getInfoRelativePath(TD)));
T.getAsString(Policy), getInfoRelativePath(TD)));
}
static bool isPublic(const clang::AccessSpecifier AS,
@ -379,10 +379,11 @@ static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly,
if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F))
continue;
auto &LO = F->getLangOpts();
// Use getAccessUnsafe so that we just get the default AS_none if it's not
// valid, as opposed to an assert.
MemberTypeInfo &NewMember = I.Members.emplace_back(
getTypeInfoForType(F->getTypeSourceInfo()->getType()),
getTypeInfoForType(F->getTypeSourceInfo()->getType(), LO),
F->getNameAsString(),
getFinalAccessSpecifier(Access, F->getAccessUnsafe()));
populateMemberTypeInfo(NewMember, F);
@ -412,9 +413,10 @@ static void parseEnumerators(EnumInfo &I, const EnumDecl *D) {
}
static void parseParameters(FunctionInfo &I, const FunctionDecl *D) {
auto &LO = D->getLangOpts();
for (const ParmVarDecl *P : D->parameters()) {
FieldTypeInfo &FieldInfo = I.Params.emplace_back(
getTypeInfoForType(P->getOriginalType()), P->getNameAsString());
getTypeInfoForType(P->getOriginalType(), LO), P->getNameAsString());
FieldInfo.DefaultValue = getSourceCode(D, P->getDefaultArgRange());
}
}
@ -541,7 +543,8 @@ static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
bool &IsInAnonymousNamespace) {
populateSymbolInfo(I, D, FC, LineNumber, Filename, IsFileInRootDir,
IsInAnonymousNamespace);
I.ReturnType = getTypeInfoForType(D->getReturnType());
auto &LO = D->getLangOpts();
I.ReturnType = getTypeInfoForType(D->getReturnType(), LO);
parseParameters(I, D);
PopulateTemplateParameters(I.Template, D);
@ -783,7 +786,8 @@ emitInfo(const TypedefDecl *D, const FullComment *FC, int LineNumber,
return {};
Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir);
Info.Underlying = getTypeInfoForType(D->getUnderlyingType());
auto &LO = D->getLangOpts();
Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
if (Info.Underlying.Type.Name.empty()) {
// Typedef for an unnamed type. This is like "typedef struct { } Foo;"
// The record serializer explicitly checks for this syntax and constructs
@ -809,7 +813,8 @@ emitInfo(const TypeAliasDecl *D, const FullComment *FC, int LineNumber,
return {};
Info.DefLoc.emplace(LineNumber, File, IsFileInRootDir);
Info.Underlying = getTypeInfoForType(D->getUnderlyingType());
auto &LO = D->getLangOpts();
Info.Underlying = getTypeInfoForType(D->getUnderlyingType(), LO);
Info.IsUsing = true;
// Info is wrapped in its parent scope so is returned in the second position.

View File

@ -23,11 +23,11 @@ extern bool b();
// YAML-NEXT: Filename: '{{.*}}'
// YAML-NEXT: ReturnType:
// YAML-NEXT: Type:
// YAML-NEXT: Name: '_Bool'
// YAML-NEXT: QualName: '_Bool'
// YAML-NEXT: Name: 'bool'
// YAML-NEXT: QualName: 'bool'
// MD: ### b
// MD: *_Bool b()*
// MD: *bool b()*
char c();

View File

@ -80,8 +80,8 @@ void function<bool, 0>(bool x) {}
// YAML-NEXT: Filename: '{{.*}}'
// YAML-NEXT: Params:
// YAML-NEXT: - Type:
// YAML-NEXT: Name: '_Bool'
// YAML-NEXT: QualName: '_Bool'
// YAML-NEXT: Name: 'bool'
// YAML-NEXT: QualName: 'bool'
// YAML-NEXT: Name: 'x'
// YAML-NEXT: ReturnType:
// YAML-NEXT: Type:
@ -95,7 +95,7 @@ void function<bool, 0>(bool x) {}
// YAML-NEXT: - Contents: '0'
// MD: ### function
// MD: *void function(_Bool x)*
// MD: *void function(bool x)*
// MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 26]]*
/// A Tuple type
@ -136,7 +136,7 @@ tuple<int,int,bool> func_with_tuple_param(tuple<int,int,bool> t){ return t;}
// YAML-NEXT: - Type:
// YAML-NEXT: Type: Record
// YAML-NEXT: Name: 'tuple'
// YAML-NEXT: QualName: 'tuple<int, int, _Bool>'
// YAML-NEXT: QualName: 'tuple<int, int, bool>'
// YAML-NEXT: USR: '{{([0-9A-F]{40})}}'
// YAML-NEXT: Path: 'GlobalNamespace'
// YAML-NEXT: Name: 't'
@ -144,13 +144,13 @@ tuple<int,int,bool> func_with_tuple_param(tuple<int,int,bool> t){ return t;}
// YAML-NEXT: Type:
// YAML-NEXT: Type: Record
// YAML-NEXT: Name: 'tuple'
// YAML-NEXT: QualName: 'tuple<int, int, _Bool>'
// YAML-NEXT: QualName: 'tuple<int, int, bool>'
// YAML-NEXT: USR: '{{([0-9A-F]{40})}}'
// YAML-NEXT: Path: 'GlobalNamespace'
// YAML-NEXT: ...
// MD: ### func_with_tuple_param
// MD: *tuple<int, int, _Bool> func_with_tuple_param(tuple<int, int, _Bool> t)*
// MD: *tuple<int, int, bool> func_with_tuple_param(tuple<int, int, bool> t)*
// MD: *Defined at {{.*}}templates.cpp#[[# @LINE - 44]]*
// MD: A function with a tuple parameter
// MD: **t** The input to func_with_tuple_param

View File

@ -631,8 +631,8 @@ TEST(SerializeTests, emitTypedefs) {
TEST(SerializeTests, emitFunctionTemplate) {
EmittedInfoList Infos;
// A template and a specialization.
ExtractInfosFromCode("template<typename T = int> void GetFoo(T);\n"
"template<> void GetFoo<bool>(bool);",
ExtractInfosFromCode("template<typename T = int> bool GetFoo(T);\n"
"template<> bool GetFoo<bool>(bool);",
2,
/*Public=*/false, Infos);
@ -666,6 +666,8 @@ TEST(SerializeTests, emitFunctionTemplate) {
ASSERT_EQ(1u, Func2.Template->Specialization->Params.size());
EXPECT_EQ("bool", Func2.Template->Specialization->Params[0].Contents);
EXPECT_EQ(Func1.USR, Func2.Template->Specialization->SpecializationOf);
EXPECT_EQ("bool", Func2.ReturnType.Type.Name);
}
TEST(SerializeTests, emitClassTemplate) {