diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -795,6 +795,10 @@ ``clang_Cursor_getTemplateArgumentType``, ``clang_Cursor_getTemplateArgumentValue`` and ``clang_Cursor_getTemplateArgumentUnsignedValue`` now work on struct, class, and partial template specialization cursors in addition to function cursors. +- Added ``CXType_SubstTemplateTypeParm`` to ``CXTypeKind``, which identifies a type that + is a replacement for a template type parameter (previously reported a ``CXType_Unexposed``). +- Introduced the new function ``clang_Type_getReplacementType`` which gets the type replacing + the template type parameter when type kind is ``CXType_SubstTemplateTypeParm``. Static Analyzer --------------- diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h --- a/clang/include/clang-c/Index.h +++ b/clang/include/clang-c/Index.h @@ -2789,7 +2789,9 @@ CXType_ExtVector = 176, CXType_Atomic = 177, - CXType_BTFTagAttributed = 178 + CXType_BTFTagAttributed = 178, + /* Represents a type that has been substituted for a template type parameter. */ + CXType_SubstTemplateTypeParm = 179 }; /** @@ -3447,6 +3449,13 @@ */ CINDEX_LINKAGE CXType clang_Type_getValueType(CXType CT); +/** + * Gets the replacement type for a SubstTemplateTypeParm type. + * + * If any other type kind is passed in, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getReplacementType(CXType CT); + /** * Return the offset of the field represented by the Cursor. * diff --git a/clang/test/Index/print-type.cpp b/clang/test/Index/print-type.cpp --- a/clang/test/Index/print-type.cpp +++ b/clang/test/Index/print-type.cpp @@ -171,7 +171,7 @@ // CHECK: VarDecl=autoI:54:6 (Definition) [type=int] [typekind=Auto] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1] // CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1] // CHECK: VarDecl=autoTbar:55:6 (Definition) [type=int] [typekind=Auto] [canonicaltype=int] [canonicaltypekind=Int] [isPOD=1] -// CHECK: CallExpr=tbar:36:3 [type=int] [typekind=Unexposed] [canonicaltype=int] [canonicaltypekind=Int] [args= [int] [Int]] [isPOD=1] +// CHECK: CallExpr=tbar:36:3 [type=int] [typekind=SubstTemplateTypeParm] [canonicaltype=int] [canonicaltypekind=Int] [args= [int] [Int]] [isPOD=1] // CHECK: UnexposedExpr=tbar:36:3 [type=int (*)(int)] [typekind=Pointer] [canonicaltype=int (*)(int)] [canonicaltypekind=Pointer] [isPOD=1] [pointeetype=int (int)] [pointeekind=FunctionProto] // CHECK: DeclRefExpr=tbar:36:3 RefName=[55:17 - 55:21] RefName=[55:21 - 55:26] [type=int (int)] [typekind=FunctionProto] [canonicaltype=int (int)] [canonicaltypekind=FunctionProto] [isPOD=0] // CHECK: IntegerLiteral= [type=int] [typekind=Int] [isPOD=1] diff --git a/clang/tools/libclang/CXType.cpp b/clang/tools/libclang/CXType.cpp --- a/clang/tools/libclang/CXType.cpp +++ b/clang/tools/libclang/CXType.cpp @@ -118,13 +118,13 @@ TKCASE(Attributed); TKCASE(BTFTagAttributed); TKCASE(Atomic); + TKCASE(SubstTemplateTypeParm); default: return CXType_Unexposed; } #undef TKCASE } - CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) { CXTypeKind TK = CXType_Invalid; @@ -635,6 +635,7 @@ TKIND(OCLQueue); TKIND(OCLReserveID); TKIND(Atomic); + TKIND(SubstTemplateTypeParm); } #undef TKIND return cxstring::createRef(s); @@ -1355,3 +1356,11 @@ const auto *AT = T->castAs(); return MakeCXType(AT->getValueType(), GetTU(CT)); } + +CXType clang_Type_getReplacementType(CXType CT) { + QualType T = GetQualType(CT); + + const auto *ST = + !T.isNull() ? T->getAs() : nullptr; + return MakeCXType(ST ? ST->getReplacementType() : QualType(), GetTU(CT)); +} diff --git a/clang/tools/libclang/libclang.map b/clang/tools/libclang/libclang.map --- a/clang/tools/libclang/libclang.map +++ b/clang/tools/libclang/libclang.map @@ -164,6 +164,7 @@ clang_Type_getObjCProtocolDecl; clang_Type_getObjCTypeArg; clang_Type_getOffsetOf; + clang_Type_getReplacementType; clang_Type_getSizeOf; clang_Type_getTemplateArgumentAsType; clang_Type_getValueType;