diff options
author | Dmitri Gribenko <gribozavr@gmail.com> | 2012-08-22 17:44:32 +0000 |
---|---|---|
committer | Dmitri Gribenko <gribozavr@gmail.com> | 2012-08-22 17:44:32 +0000 |
commit | 2125c9010e259548a8c476fa998a561889555c95 (patch) | |
tree | d881497ce9688000d19da19f7846af1779cbfc48 /lib/AST/ASTContext.cpp | |
parent | f01ef105f16a03bee7ea899e4e2ce6d0feee7801 (diff) |
Attaching comments to declarations: when documentation is requested for an
implicit instantiation, look for documentation attached to the template.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162371 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 67 |
1 files changed, 62 insertions, 5 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7c685cf59a..adb06147fa 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -214,15 +214,72 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { namespace { /// If we have a 'templated' declaration for a template, adjust 'D' to /// refer to the actual template. +/// If we have an implicit instantiation, adjust 'D' to refer to template. const Decl *adjustDeclToTemplate(const Decl *D) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // Is this function declaration part of a function template? if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) - D = FTD; - } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - if (const ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) - D = CTD; + return FTD; + + // Nothing to do if function is not an implicit instantiation. + if (FD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) + return D; + + // Function is an implicit instantiation of a function template? + if (const FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) + return FTD; + + // Function is instantiated from a member definition of a class template? + if (const FunctionDecl *MemberDecl = + FD->getInstantiatedFromMemberFunction()) + return MemberDecl; + + return D; + } + if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + // Static data member is instantiated from a member definition of a class + // template? + if (VD->isStaticDataMember()) + if (const VarDecl *MemberDecl = VD->getInstantiatedFromStaticDataMember()) + return MemberDecl; + + return D; + } + if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { + // Is this class declaration part of a class template? + if (const ClassTemplateDecl *CTD = CRD->getDescribedClassTemplate()) + return CTD; + + // Class is an implicit instantiation of a class template or partial + // specialization? + if (const ClassTemplateSpecializationDecl *CTSD = + dyn_cast<ClassTemplateSpecializationDecl>(CRD)) { + if (CTSD->getSpecializationKind() != TSK_ImplicitInstantiation) + return D; + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + PU = CTSD->getSpecializedTemplateOrPartial(); + return PU.is<ClassTemplateDecl*>() ? + static_cast<const Decl*>(PU.get<ClassTemplateDecl *>()) : + static_cast<const Decl*>( + PU.get<ClassTemplatePartialSpecializationDecl *>()); + } + + // Class is instantiated from a member definition of a class template? + if (const MemberSpecializationInfo *Info = + CRD->getMemberSpecializationInfo()) + return Info->getInstantiatedFrom(); + + return D; + } + if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { + // Enum is instantiated from a member definition of a class template? + if (const EnumDecl *MemberDecl = ED->getInstantiatedFromMemberEnum()) + return MemberDecl; + + return D; } - // FIXME: Alias templates? + // FIXME: Adjust alias templates? return D; } } // unnamed namespace |