From e595195c13deab3b1bdb98d11299ee282b471854 Mon Sep 17 00:00:00 2001 From: alandefreitas Date: Mon, 27 Jan 2025 15:32:51 -0300 Subject: [PATCH] populate overloads use explicit types #perf --- include/mrdocs/Metadata/Info.hpp | 5 +- include/mrdocs/Metadata/Info/Concept.hpp | 1 - include/mrdocs/Metadata/Info/Enum.hpp | 1 - include/mrdocs/Metadata/Info/EnumConstant.hpp | 1 - include/mrdocs/Metadata/Info/Field.hpp | 1 - include/mrdocs/Metadata/Info/Friend.hpp | 1 - include/mrdocs/Metadata/Info/Function.hpp | 24 +- include/mrdocs/Metadata/Info/Guide.hpp | 1 - .../mrdocs/Metadata/Info/NamespaceAlias.hpp | 1 - include/mrdocs/Metadata/Info/Record.hpp | 1 - include/mrdocs/Metadata/Info/Typedef.hpp | 17 +- include/mrdocs/Metadata/Info/Variable.hpp | 1 - include/mrdocs/Metadata/Source.hpp | 4 +- include/mrdocs/Metadata/Using.hpp | 3 +- src/lib/AST/ASTVisitor.cpp | 274 ++++++++++-------- src/lib/AST/ASTVisitor.hpp | 32 +- src/lib/AST/ClangHelpers.hpp | 68 ++++- 17 files changed, 262 insertions(+), 174 deletions(-) diff --git a/include/mrdocs/Metadata/Info.hpp b/include/mrdocs/Metadata/Info.hpp index 30826f9c9..4a022321d 100644 --- a/include/mrdocs/Metadata/Info.hpp +++ b/include/mrdocs/Metadata/Info.hpp @@ -20,9 +20,11 @@ #include #include #include +#include #include #include + namespace clang::mrdocs { /* Forward declarations @@ -59,8 +61,7 @@ tag_invoke( /** Base class with common properties of all symbols */ -struct MRDOCS_VISIBLE - Info +struct MRDOCS_VISIBLE Info : SourceInfo { /** The unique identifier for this symbol. */ diff --git a/include/mrdocs/Metadata/Info/Concept.hpp b/include/mrdocs/Metadata/Info/Concept.hpp index abe14ab37..5651efa1b 100644 --- a/include/mrdocs/Metadata/Info/Concept.hpp +++ b/include/mrdocs/Metadata/Info/Concept.hpp @@ -22,7 +22,6 @@ namespace clang::mrdocs { */ struct ConceptInfo final : InfoCommonBase - , SourceInfo { /** The concepts template parameters */ diff --git a/include/mrdocs/Metadata/Info/Enum.hpp b/include/mrdocs/Metadata/Info/Enum.hpp index cfda1d96a..37ddc9e6a 100644 --- a/include/mrdocs/Metadata/Info/Enum.hpp +++ b/include/mrdocs/Metadata/Info/Enum.hpp @@ -22,7 +22,6 @@ namespace clang::mrdocs { struct EnumInfo final : InfoCommonBase - , SourceInfo , ScopeInfo { // Indicates whether this enum is scoped (e.g. enum class). diff --git a/include/mrdocs/Metadata/Info/EnumConstant.hpp b/include/mrdocs/Metadata/Info/EnumConstant.hpp index 8a24bd25b..9625de237 100644 --- a/include/mrdocs/Metadata/Info/EnumConstant.hpp +++ b/include/mrdocs/Metadata/Info/EnumConstant.hpp @@ -21,7 +21,6 @@ namespace clang::mrdocs { */ struct EnumConstantInfo final : InfoCommonBase - , SourceInfo { /** The initializer expression, if any */ diff --git a/include/mrdocs/Metadata/Info/Field.hpp b/include/mrdocs/Metadata/Info/Field.hpp index 946aa5789..875dad105 100644 --- a/include/mrdocs/Metadata/Info/Field.hpp +++ b/include/mrdocs/Metadata/Info/Field.hpp @@ -27,7 +27,6 @@ namespace clang::mrdocs { */ struct FieldInfo final : InfoCommonBase - , SourceInfo { /** Type of the field */ PolymorphicValue Type; diff --git a/include/mrdocs/Metadata/Info/Friend.hpp b/include/mrdocs/Metadata/Info/Friend.hpp index 926e78bcf..488988555 100644 --- a/include/mrdocs/Metadata/Info/Friend.hpp +++ b/include/mrdocs/Metadata/Info/Friend.hpp @@ -21,7 +21,6 @@ namespace clang::mrdocs { */ struct FriendInfo final : InfoCommonBase - , SourceInfo { /** Befriended symbol. */ diff --git a/include/mrdocs/Metadata/Info/Function.hpp b/include/mrdocs/Metadata/Info/Function.hpp index 9b21eae44..86d298a9d 100644 --- a/include/mrdocs/Metadata/Info/Function.hpp +++ b/include/mrdocs/Metadata/Info/Function.hpp @@ -126,7 +126,6 @@ tag_invoke( // Info for functions. struct FunctionInfo final : InfoCommonBase - , SourceInfo { /// Info about the return type of this function. PolymorphicValue ReturnType; @@ -141,15 +140,8 @@ struct FunctionInfo final FunctionClass Class = FunctionClass::Normal; NoexceptInfo Noexcept; - - ExplicitInfo Explicit; - ExprInfo Requires; - bool IsVariadic = false; - bool IsVirtual = false; - bool IsVirtualAsWritten = false; - bool IsPure = false; bool IsDefaulted = false; bool IsExplicitlyDefaulted = false; bool IsDeleted = false; @@ -157,19 +149,23 @@ struct FunctionInfo final bool IsNoReturn = false; bool HasOverrideAttr = false; bool HasTrailingReturn = false; - bool IsConst = false; - bool IsVolatile = false; - bool IsFinal = false; bool IsNodiscard = false; bool IsExplicitObjectMemberFunction = false; - ConstexprKind Constexpr = ConstexprKind::None; OperatorKind OverloadedOperator = OperatorKind::None; StorageClassKind StorageClass = StorageClassKind::None; - ReferenceKind RefQualifier = ReferenceKind::None; - std::vector Attributes; + // CXXMethodDecl + bool IsVirtual = false; + bool IsVirtualAsWritten = false; + bool IsPure = false; + bool IsConst = false; + bool IsVolatile = false; + bool IsFinal = false; + ReferenceKind RefQualifier = ReferenceKind::None; + ExplicitInfo Explicit; + //-------------------------------------------- explicit FunctionInfo(SymbolID const& ID) noexcept diff --git a/include/mrdocs/Metadata/Info/Guide.hpp b/include/mrdocs/Metadata/Info/Guide.hpp index ba2b77991..58481d042 100644 --- a/include/mrdocs/Metadata/Info/Guide.hpp +++ b/include/mrdocs/Metadata/Info/Guide.hpp @@ -23,7 +23,6 @@ namespace clang::mrdocs { */ struct GuideInfo final : InfoCommonBase - , SourceInfo { /** The pattern for the deduced specialization. diff --git a/include/mrdocs/Metadata/Info/NamespaceAlias.hpp b/include/mrdocs/Metadata/Info/NamespaceAlias.hpp index 8d0e20a59..632ec7c08 100644 --- a/include/mrdocs/Metadata/Info/NamespaceAlias.hpp +++ b/include/mrdocs/Metadata/Info/NamespaceAlias.hpp @@ -20,7 +20,6 @@ namespace clang::mrdocs { */ struct NamespaceAliasInfo final : InfoCommonBase - , SourceInfo { /** The aliased symbol. */ PolymorphicValue AliasedSymbol; diff --git a/include/mrdocs/Metadata/Info/Record.hpp b/include/mrdocs/Metadata/Info/Record.hpp index 0c6058471..1aded0677 100644 --- a/include/mrdocs/Metadata/Info/Record.hpp +++ b/include/mrdocs/Metadata/Info/Record.hpp @@ -75,7 +75,6 @@ tag_invoke( */ struct RecordInfo final : InfoCommonBase - , SourceInfo , ScopeInfo { /** Kind of record this is (class, struct, or union). diff --git a/include/mrdocs/Metadata/Info/Typedef.hpp b/include/mrdocs/Metadata/Info/Typedef.hpp index 84684036a..3623e5acd 100644 --- a/include/mrdocs/Metadata/Info/Typedef.hpp +++ b/include/mrdocs/Metadata/Info/Typedef.hpp @@ -22,14 +22,21 @@ namespace clang::mrdocs { // Info for typedef and using statements. struct TypedefInfo final : InfoCommonBase - , SourceInfo { PolymorphicValue Type; - // Indicates if this is a new C++ "using"-style typedef: - // using MyVector = std::vector - // False means it's a C-style typedef: - // typedef std::vector MyVector; + /** Indicates if this is a new C++ "using"-style typedef + + @code + using MyVector = std::vector + @endcode + + False means it's a C-style typedef: + + @code + typedef std::vector MyVector; + @endcode + */ bool IsUsing = false; std::optional Template; diff --git a/include/mrdocs/Metadata/Info/Variable.hpp b/include/mrdocs/Metadata/Info/Variable.hpp index b4b3486d5..73959930d 100644 --- a/include/mrdocs/Metadata/Info/Variable.hpp +++ b/include/mrdocs/Metadata/Info/Variable.hpp @@ -26,7 +26,6 @@ namespace clang::mrdocs { */ struct VariableInfo final : InfoCommonBase - , SourceInfo { /** The type of the variable */ PolymorphicValue Type; diff --git a/include/mrdocs/Metadata/Source.hpp b/include/mrdocs/Metadata/Source.hpp index 27b6f4fa4..95e825455 100644 --- a/include/mrdocs/Metadata/Source.hpp +++ b/include/mrdocs/Metadata/Source.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include #include namespace clang::mrdocs { @@ -118,7 +118,7 @@ struct MRDOCS_DECL */ OptionalLocation DefLoc; - /** Locations where the entity was declared, + /** Locations where the entity was declared. This does not include the definition. */ diff --git a/include/mrdocs/Metadata/Using.hpp b/include/mrdocs/Metadata/Using.hpp index bb3aeaa45..90b201967 100644 --- a/include/mrdocs/Metadata/Using.hpp +++ b/include/mrdocs/Metadata/Using.hpp @@ -56,8 +56,7 @@ tag_invoke( /** Info for using declarations. */ struct UsingInfo final - : InfoCommonBase, - SourceInfo + : InfoCommonBase { /** The kind of using declaration. */ diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index d79731a5e..f23260021 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -112,7 +112,6 @@ traverse(DeclTy* D) using R = std::conditional_t< std::same_as, InfoTypeFor_t, - InfoTy>; auto exp = upsert(D); @@ -122,7 +121,7 @@ traverse(DeclTy* D) // Populate the base classes with the necessary information. // Even when the object is new, we want to update the source locations // and the documentation status. - populateInfoBases(I, isNew, D); + populate(dynamic_cast(I), isNew, D); // Populate the derived Info object with the necessary information // when the object is new. If the object already exists, this @@ -506,36 +505,42 @@ generateID(const Decl* D) const return id; } -template InfoTy, class DeclTy> +namespace +{ +template +bool +isDefinition(DeclTy* D) +{ + if constexpr (requires {D->isThisDeclarationADefinition();}) + { + return D->isThisDeclarationADefinition(); + } + else + { + return false; + } +} +} + +template DeclTy> void ASTVisitor:: -populateInfoBases(InfoTy& I, bool const isNew, DeclTy* D) +populate(Info& I, bool const isNew, DeclTy* D) { // Populate the documentation bool const isDocumented = generateJavadoc(I.javadoc, D); // Populate the source info - if constexpr (std::derived_from) + clang::SourceLocation Loc = D->getBeginLoc(); + if (Loc.isInvalid()) { - bool const isDefinition = [&]() { - if constexpr (requires {D->isThisDeclarationADefinition();}) - { - return D->isThisDeclarationADefinition(); - } - else - { - return false; - } - }(); - clang::SourceLocation Loc = D->getBeginLoc(); - if (Loc.isInvalid()) - { - Loc = D->getLocation(); - } - if (Loc.isValid()) - { - populate(I, Loc, isDefinition, isDocumented); - } + Loc = D->getLocation(); + } + if (Loc.isValid()) + { + populate( + dynamic_cast(I), + Loc, isDefinition(D), isDocumented); } // All other information is redundant if the symbol is not new @@ -545,30 +550,7 @@ populateInfoBases(InfoTy& I, bool const isNew, DeclTy* D) MRDOCS_ASSERT(I.id); MRDOCS_ASSERT(I.Kind != InfoKind::None); - if constexpr (std::same_as) - { - I.Name = extractName(D->getDeducedTemplate()); - } - else if constexpr (std::derived_from) - { - if (auto* FD = D->getFriendDecl()) - { - I.Name = extractName(D->getFriendDecl()); - } - else if (TypeSourceInfo const* FT = D->getFriendType()) - { - llvm::raw_string_ostream os(I.Name); - FT->getType().print(os, context_.getPrintingPolicy()); - } - } - else if constexpr (std::derived_from) - { - I.Name = extractName(D->getNominatedNamespace()); - } - else if constexpr (std::derived_from) - { - I.Name = extractName(D); - } + I.Name = extractName(D); } void @@ -700,12 +682,11 @@ populate(RecordInfo& I, ClassTemplateSpecializationDecl* D) populate(I, cast(D)); } -template DeclTy> void ASTVisitor:: populate( FunctionInfo& I, - DeclTy* D) + FunctionDecl* D) { MRDOCS_SYMBOL_TRACE(D, context_); @@ -719,8 +700,9 @@ populate( if (auto* FTSI = D->getTemplateSpecializationInfo()) { - generateID(getInstantiatedFrom( - FTSI->getTemplate()), I.Template->Primary); + generateID( + getInstantiatedFrom(FTSI->getTemplate()), + I.Template->Primary); // TemplateArguments is used instead of TemplateArgumentsAsWritten // because explicit specializations of function templates may have @@ -756,76 +738,30 @@ populate( I.HasTrailingReturn |= FPT->hasTrailingReturn(); } - // - // FunctionDecl - // - FunctionDecl const* FD = D; - I.OverloadedOperator = toOperatorKind(FD->getOverloadedOperator()); - I.IsVariadic |= FD->isVariadic(); - I.IsDefaulted |= FD->isDefaulted(); - I.IsExplicitlyDefaulted |= FD->isExplicitlyDefaulted(); - I.IsDeleted |= FD->isDeleted(); - I.IsDeletedAsWritten |= FD->isDeletedAsWritten(); - I.IsNoReturn |= FD->isNoReturn(); - I.HasOverrideAttr |= FD->hasAttr(); - - if (ConstexprSpecKind const CSK = FD->getConstexprKind(); + I.OverloadedOperator = toOperatorKind(D->getOverloadedOperator()); + I.IsVariadic |= D->isVariadic(); + I.IsDefaulted |= D->isDefaulted(); + I.IsExplicitlyDefaulted |= D->isExplicitlyDefaulted(); + I.IsDeleted |= D->isDeleted(); + I.IsDeletedAsWritten |= D->isDeletedAsWritten(); + I.IsNoReturn |= D->isNoReturn(); + I.HasOverrideAttr |= D->hasAttr(); + + if (ConstexprSpecKind const CSK = D->getConstexprKind(); CSK != ConstexprSpecKind::Unspecified) { I.Constexpr = toConstexprKind(CSK); } - if (StorageClass const SC = FD->getStorageClass()) + if (StorageClass const SC = D->getStorageClass()) { I.StorageClass = toStorageClassKind(SC); } - I.IsNodiscard |= FD->hasAttr(); - I.IsExplicitObjectMemberFunction |= FD->hasCXXExplicitFunctionObjectParameter(); - - // - // CXXMethodDecl - // - if constexpr(std::derived_from) - { - CXXMethodDecl const* MD = D; - I.IsVirtual |= MD->isVirtual(); - I.IsVirtualAsWritten |= MD->isVirtualAsWritten(); - I.IsPure |= MD->isPureVirtual(); - I.IsConst |= MD->isConst(); - I.IsVolatile |= MD->isVolatile(); - I.RefQualifier = toReferenceKind(MD->getRefQualifier()); - I.IsFinal |= MD->hasAttr(); - //MD->isCopyAssignmentOperator() - //MD->isMoveAssignmentOperator() - //MD->isOverloadedOperator(); - //MD->isStaticOverloadedOperator(); - - // - // CXXDestructorDecl - // - // if constexpr(std::derived_from) - // { - // } - - // - // CXXConstructorDecl - // - if constexpr(std::derived_from) - { - populate(I.Explicit, D->getExplicitSpecifier()); - } - - // - // CXXConversionDecl - // - if constexpr(std::derived_from) - { - populate(I.Explicit, D->getExplicitSpecifier()); - } - } + I.IsNodiscard |= D->hasAttr(); + I.IsExplicitObjectMemberFunction |= D->hasCXXExplicitFunctionObjectParameter(); - ArrayRef const params = FD->parameters(); + ArrayRef const params = D->parameters(); I.Params.resize(params.size()); for (std::size_t i = 0; i < params.size(); ++i) { @@ -858,16 +794,16 @@ populate( } } - I.Class = toFunctionClass(FD->getDeclKind()); + I.Class = toFunctionClass(D->getDeclKind()); // extract the return type in direct dependency mode // if it contains a placeholder type which is // deduceded as a local class type - QualType const RT = FD->getReturnType(); + QualType const RT = D->getReturnType(); MRDOCS_SYMBOL_TRACE(RT, context_); I.ReturnType = toTypeInfo(RT); - if (auto* TRC = FD->getTrailingRequiresClause()) + if (auto* TRC = D->getTrailingRequiresClause()) { populate(I.Requires, TRC); } @@ -922,6 +858,48 @@ populate(FunctionInfo& I, FunctionTemplateDecl* D) populate(I, TD); } +void +ASTVisitor:: +populate(FunctionInfo& I, CXXMethodDecl* D) +{ + FunctionDecl* FD = D; + populate(I, FD); + I.IsVirtual |= D->isVirtual(); + I.IsVirtualAsWritten |= D->isVirtualAsWritten(); + I.IsPure |= D->isPureVirtual(); + I.IsConst |= D->isConst(); + I.IsVolatile |= D->isVolatile(); + I.RefQualifier = toReferenceKind(D->getRefQualifier()); + I.IsFinal |= D->hasAttr(); +} + +void +ASTVisitor:: +populate(FunctionInfo& I, CXXConstructorDecl* D) +{ + CXXMethodDecl* FD = D; + populate(I, FD); + populate(I.Explicit, D->getExplicitSpecifier()); +} + +void +ASTVisitor:: +populate(FunctionInfo& I, CXXDestructorDecl* D) +{ + CXXMethodDecl* FD = D; + populate(I, FD); +} + +void +ASTVisitor:: +populate(FunctionInfo& I, CXXConversionDecl* D) +{ + CXXMethodDecl* FD = D; + populate(I, FD); + populate(I.Explicit, D->getExplicitSpecifier()); +} + + void ASTVisitor:: populate( @@ -948,27 +926,45 @@ populate( D->getInitVal()); } -template TypedefNameDeclTy> void ASTVisitor:: -populate( - TypedefInfo& I, - TypedefNameDeclTy* D) +populate(TypedefInfo& I, TypedefNameDecl* D) { - I.IsUsing = isa(D); QualType const QT = D->getUnderlyingType(); I.Type = toTypeInfo(QT); } +void +ASTVisitor:: +populate(TypedefInfo& I, TypedefDecl* D) +{ + populate(I, cast(D)); +} + +void +ASTVisitor:: +populate(TypedefInfo& I, TypeAliasDecl* D) +{ + I.IsUsing = isa(D); + populate(I, cast(D)); +} + void ASTVisitor:: populate(TypedefInfo& I, TypeAliasTemplateDecl* D) { populate(I.Template, D->getTemplatedDecl(), D); - populate(I, D->getTemplatedDecl()); + if (auto* TD = D->getTemplatedDecl(); + isa(TD)) + { + populate(I, cast(TD)); + } + else + { + populate(I, TD); + } } - void ASTVisitor:: populate( @@ -1569,6 +1565,40 @@ populateAttributes(InfoTy& I, const Decl* D) } } +template DeclTy> +std::string +ASTVisitor:: +extractName(DeclTy const* D) +{ + if constexpr (std::same_as) + { + return extractName(D->getDeducedTemplate()); + } + else if constexpr (std::derived_from) + { + if (auto* FD = D->getFriendDecl()) + { + return extractName(D->getFriendDecl()); + } + if (TypeSourceInfo const* FT = D->getFriendType()) + { + std::string Name; + llvm::raw_string_ostream os(Name); + FT->getType().print(os, context_.getPrintingPolicy()); + return Name; + } + } + else if constexpr (std::derived_from) + { + return extractName(D->getNominatedNamespace()); + } + else if constexpr (std::derived_from) + { + return extractName(cast(D)); + } + return {}; +} + std::string ASTVisitor:: extractName(NamedDecl const* D) diff --git a/src/lib/AST/ASTVisitor.hpp b/src/lib/AST/ASTVisitor.hpp index 8bd645cdf..f0943d225 100644 --- a/src/lib/AST/ASTVisitor.hpp +++ b/src/lib/AST/ASTVisitor.hpp @@ -444,9 +444,9 @@ class ASTVisitor // ================================================= // Populate functions // ================================================= - template InfoTy, class DeclTy> + template DeclTy> void - populateInfoBases(InfoTy& I, bool isNew, DeclTy* D); + populate(Info& I, bool isNew, DeclTy* D); void populate(SourceInfo& I, clang::SourceLocation loc, bool definition, bool documented); @@ -467,22 +467,38 @@ class ASTVisitor void populate(RecordInfo& I, ClassTemplateSpecializationDecl* D); - template DeclTy> void - populate(FunctionInfo& I, DeclTy* D); + populate(FunctionInfo& I, FunctionDecl* D); void populate(FunctionInfo& I, FunctionTemplateDecl* D); + void + populate(FunctionInfo& I, CXXMethodDecl* D); + + void + populate(FunctionInfo& I, CXXConstructorDecl* D); + + void + populate(FunctionInfo& I, CXXDestructorDecl* D); + + void + populate(FunctionInfo& I, CXXConversionDecl* D); + void populate(EnumInfo& I, EnumDecl* D); void populate(EnumConstantInfo& I, EnumConstantDecl* D); - template TypedefNameDeclTy> void - populate(TypedefInfo& I, TypedefNameDeclTy* D); + populate(TypedefInfo& I, TypedefNameDecl* D); + + void + populate(TypedefInfo& I, TypedefDecl* D); + + void + populate(TypedefInfo& I, TypeAliasDecl* D); void populate(TypedefInfo& I, TypeAliasTemplateDecl* D); @@ -638,6 +654,10 @@ class ASTVisitor // ================================================= // Populate function helpers // ================================================= + template DeclTy> + std::string + extractName(DeclTy const* D); + // Extract the name of a declaration std::string extractName(NamedDecl const* D); diff --git a/src/lib/AST/ClangHelpers.hpp b/src/lib/AST/ClangHelpers.hpp index 27b5fa812..c65027195 100644 --- a/src/lib/AST/ClangHelpers.hpp +++ b/src/lib/AST/ClangHelpers.hpp @@ -79,8 +79,16 @@ struct InfoTypeFor // Extract RecordInfo from anything derived from CXXRecordDecl // and ClassTemplateDecl. Decls derived from CXXRecordDecl // include class specializations. -template DeclType> -struct InfoTypeFor +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor : std::type_identity {}; template <> @@ -88,9 +96,24 @@ struct InfoTypeFor : std::type_identity {}; // Extract FunctionInfo from anything derived from FunctionDecl -template FunctionTy> -requires (!std::same_as) -struct InfoTypeFor +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor : std::type_identity {}; template <> @@ -108,8 +131,16 @@ struct InfoTypeFor : std::type_identity {}; // Extract TypedefInfo from anything derived from TypedefNameDecl -template TypedefNameTy> -struct InfoTypeFor +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor : std::type_identity {}; template <> @@ -118,8 +149,16 @@ struct InfoTypeFor // Extract VariableInfo from anything derived from VarDecl // and VarTemplateDecl. -template VarTy> -struct InfoTypeFor +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor + : std::type_identity {}; + +template <> +struct InfoTypeFor : std::type_identity {}; template <> @@ -657,9 +696,14 @@ TypeLocToKind() /** Get the user-written `Decl` for a `Decl` Given a `Decl` `D`, `getInstantiatedFrom` will return the - user-written `Decl` corresponding to `D`. For specializations - which were implicitly instantiated, this will be whichever `Decl` - was used as the pattern for instantiation. + user-written `Decl` corresponding to `D`. + + For specializations which were implicitly instantiated, + this will be whichever `Decl` was used as the pattern + for instantiation. + + For instance, if `D` represents `std::vector`, the + user-written `Decl` will be the `std::vector` template. */ template DeclTy*