10b57cec5SDimitry Andric //===--- Comment.cpp - Comment AST node implementation --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "clang/AST/Comment.h"
100b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
110b57cec5SDimitry Andric #include "clang/AST/Decl.h"
120b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
130b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
140b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
150b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
16a7dea167SDimitry Andric #include <type_traits>
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric namespace clang {
190b57cec5SDimitry Andric namespace comments {
200b57cec5SDimitry Andric
21a7dea167SDimitry Andric // Check that no comment class has a non-trival destructor. They are allocated
22a7dea167SDimitry Andric // with a BumpPtrAllocator and therefore their destructor is not executed.
23a7dea167SDimitry Andric #define ABSTRACT_COMMENT(COMMENT)
24a7dea167SDimitry Andric #define COMMENT(CLASS, PARENT) \
25a7dea167SDimitry Andric static_assert(std::is_trivially_destructible<CLASS>::value, \
26a7dea167SDimitry Andric #CLASS " should be trivially destructible!");
27a7dea167SDimitry Andric #include "clang/AST/CommentNodes.inc"
28a7dea167SDimitry Andric #undef COMMENT
29a7dea167SDimitry Andric #undef ABSTRACT_COMMENT
30a7dea167SDimitry Andric
31a7dea167SDimitry Andric // DeclInfo is also allocated with a BumpPtrAllocator.
32bdd1243dSDimitry Andric static_assert(std::is_trivially_destructible_v<DeclInfo>,
33a7dea167SDimitry Andric "DeclInfo should be trivially destructible!");
34a7dea167SDimitry Andric
getCommentKindName() const350b57cec5SDimitry Andric const char *Comment::getCommentKindName() const {
360b57cec5SDimitry Andric switch (getCommentKind()) {
37*5f757f3fSDimitry Andric case CommentKind::None:
38*5f757f3fSDimitry Andric return "None";
390b57cec5SDimitry Andric #define ABSTRACT_COMMENT(COMMENT)
400b57cec5SDimitry Andric #define COMMENT(CLASS, PARENT) \
41*5f757f3fSDimitry Andric case CommentKind::CLASS: \
420b57cec5SDimitry Andric return #CLASS;
430b57cec5SDimitry Andric #include "clang/AST/CommentNodes.inc"
440b57cec5SDimitry Andric #undef COMMENT
450b57cec5SDimitry Andric #undef ABSTRACT_COMMENT
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric llvm_unreachable("Unknown comment kind!");
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric namespace {
510b57cec5SDimitry Andric struct good {};
520b57cec5SDimitry Andric struct bad {};
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric template <typename T>
implements_child_begin_end(Comment::child_iterator (T::*)()const)550b57cec5SDimitry Andric good implements_child_begin_end(Comment::child_iterator (T::*)() const) {
560b57cec5SDimitry Andric return good();
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
590b57cec5SDimitry Andric LLVM_ATTRIBUTE_UNUSED
implements_child_begin_end(Comment::child_iterator (Comment::*)()const)600b57cec5SDimitry Andric static inline bad implements_child_begin_end(
610b57cec5SDimitry Andric Comment::child_iterator (Comment::*)() const) {
620b57cec5SDimitry Andric return bad();
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric #define ASSERT_IMPLEMENTS_child_begin(function) \
660b57cec5SDimitry Andric (void) good(implements_child_begin_end(function))
670b57cec5SDimitry Andric
680b57cec5SDimitry Andric LLVM_ATTRIBUTE_UNUSED
CheckCommentASTNodes()690b57cec5SDimitry Andric static inline void CheckCommentASTNodes() {
700b57cec5SDimitry Andric #define ABSTRACT_COMMENT(COMMENT)
710b57cec5SDimitry Andric #define COMMENT(CLASS, PARENT) \
720b57cec5SDimitry Andric ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \
730b57cec5SDimitry Andric ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end);
740b57cec5SDimitry Andric #include "clang/AST/CommentNodes.inc"
750b57cec5SDimitry Andric #undef COMMENT
760b57cec5SDimitry Andric #undef ABSTRACT_COMMENT
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric
790b57cec5SDimitry Andric #undef ASSERT_IMPLEMENTS_child_begin
800b57cec5SDimitry Andric
810b57cec5SDimitry Andric } // end unnamed namespace
820b57cec5SDimitry Andric
child_begin() const830b57cec5SDimitry Andric Comment::child_iterator Comment::child_begin() const {
840b57cec5SDimitry Andric switch (getCommentKind()) {
85*5f757f3fSDimitry Andric case CommentKind::None:
86*5f757f3fSDimitry Andric llvm_unreachable("comment without a kind");
870b57cec5SDimitry Andric #define ABSTRACT_COMMENT(COMMENT)
880b57cec5SDimitry Andric #define COMMENT(CLASS, PARENT) \
89*5f757f3fSDimitry Andric case CommentKind::CLASS: \
900b57cec5SDimitry Andric return static_cast<const CLASS *>(this)->child_begin();
910b57cec5SDimitry Andric #include "clang/AST/CommentNodes.inc"
920b57cec5SDimitry Andric #undef COMMENT
930b57cec5SDimitry Andric #undef ABSTRACT_COMMENT
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric llvm_unreachable("Unknown comment kind!");
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
child_end() const980b57cec5SDimitry Andric Comment::child_iterator Comment::child_end() const {
990b57cec5SDimitry Andric switch (getCommentKind()) {
100*5f757f3fSDimitry Andric case CommentKind::None:
101*5f757f3fSDimitry Andric llvm_unreachable("comment without a kind");
1020b57cec5SDimitry Andric #define ABSTRACT_COMMENT(COMMENT)
1030b57cec5SDimitry Andric #define COMMENT(CLASS, PARENT) \
104*5f757f3fSDimitry Andric case CommentKind::CLASS: \
1050b57cec5SDimitry Andric return static_cast<const CLASS *>(this)->child_end();
1060b57cec5SDimitry Andric #include "clang/AST/CommentNodes.inc"
1070b57cec5SDimitry Andric #undef COMMENT
1080b57cec5SDimitry Andric #undef ABSTRACT_COMMENT
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric llvm_unreachable("Unknown comment kind!");
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric
isWhitespaceNoCache() const1130b57cec5SDimitry Andric bool TextComment::isWhitespaceNoCache() const {
1140eae32dcSDimitry Andric return llvm::all_of(Text, clang::isWhitespace);
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric
isWhitespaceNoCache() const1170b57cec5SDimitry Andric bool ParagraphComment::isWhitespaceNoCache() const {
1180b57cec5SDimitry Andric for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) {
1190b57cec5SDimitry Andric if (const TextComment *TC = dyn_cast<TextComment>(*I)) {
1200b57cec5SDimitry Andric if (!TC->isWhitespace())
1210b57cec5SDimitry Andric return false;
1220b57cec5SDimitry Andric } else
1230b57cec5SDimitry Andric return false;
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric return true;
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric
lookThroughTypedefOrTypeAliasLocs(TypeLoc & SrcTL)1280b57cec5SDimitry Andric static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) {
1290b57cec5SDimitry Andric TypeLoc TL = SrcTL.IgnoreParens();
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric // Look through attribute types.
1320b57cec5SDimitry Andric if (AttributedTypeLoc AttributeTL = TL.getAs<AttributedTypeLoc>())
1330b57cec5SDimitry Andric return AttributeTL.getModifiedLoc();
1340b57cec5SDimitry Andric // Look through qualified types.
1350b57cec5SDimitry Andric if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>())
1360b57cec5SDimitry Andric return QualifiedTL.getUnqualifiedLoc();
1370b57cec5SDimitry Andric // Look through pointer types.
1380b57cec5SDimitry Andric if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>())
1390b57cec5SDimitry Andric return PointerTL.getPointeeLoc().getUnqualifiedLoc();
1400b57cec5SDimitry Andric // Look through reference types.
1410b57cec5SDimitry Andric if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>())
1420b57cec5SDimitry Andric return ReferenceTL.getPointeeLoc().getUnqualifiedLoc();
1430b57cec5SDimitry Andric // Look through adjusted types.
1440b57cec5SDimitry Andric if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>())
1450b57cec5SDimitry Andric return ATL.getOriginalLoc();
1460b57cec5SDimitry Andric if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>())
1470b57cec5SDimitry Andric return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
1480b57cec5SDimitry Andric if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>())
1490b57cec5SDimitry Andric return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
1500b57cec5SDimitry Andric if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>())
1510b57cec5SDimitry Andric return ETL.getNamedTypeLoc();
1520b57cec5SDimitry Andric
1530b57cec5SDimitry Andric return TL;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
getFunctionTypeLoc(TypeLoc TL,FunctionTypeLoc & ResFTL)1560b57cec5SDimitry Andric static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) {
1570b57cec5SDimitry Andric TypeLoc PrevTL;
1580b57cec5SDimitry Andric while (PrevTL != TL) {
1590b57cec5SDimitry Andric PrevTL = TL;
1600b57cec5SDimitry Andric TL = lookThroughTypedefOrTypeAliasLocs(TL);
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric
1630b57cec5SDimitry Andric if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
1640b57cec5SDimitry Andric ResFTL = FTL;
1650b57cec5SDimitry Andric return true;
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric if (TemplateSpecializationTypeLoc STL =
1690b57cec5SDimitry Andric TL.getAs<TemplateSpecializationTypeLoc>()) {
1700b57cec5SDimitry Andric // If we have a typedef to a template specialization with exactly one
1710b57cec5SDimitry Andric // template argument of a function type, this looks like std::function,
1720b57cec5SDimitry Andric // boost::function, or other function wrapper. Treat these typedefs as
1730b57cec5SDimitry Andric // functions.
1740b57cec5SDimitry Andric if (STL.getNumArgs() != 1)
1750b57cec5SDimitry Andric return false;
1760b57cec5SDimitry Andric TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0);
1770b57cec5SDimitry Andric if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type)
1780b57cec5SDimitry Andric return false;
1790b57cec5SDimitry Andric TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo();
1800b57cec5SDimitry Andric TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc();
1810b57cec5SDimitry Andric if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
1820b57cec5SDimitry Andric ResFTL = FTL;
1830b57cec5SDimitry Andric return true;
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric return false;
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric
190*5f757f3fSDimitry Andric const char *
getDirectionAsString(ParamCommandPassDirection D)191*5f757f3fSDimitry Andric ParamCommandComment::getDirectionAsString(ParamCommandPassDirection D) {
1920b57cec5SDimitry Andric switch (D) {
193*5f757f3fSDimitry Andric case ParamCommandPassDirection::In:
1940b57cec5SDimitry Andric return "[in]";
195*5f757f3fSDimitry Andric case ParamCommandPassDirection::Out:
1960b57cec5SDimitry Andric return "[out]";
197*5f757f3fSDimitry Andric case ParamCommandPassDirection::InOut:
1980b57cec5SDimitry Andric return "[in,out]";
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric llvm_unreachable("unknown PassDirection");
2010b57cec5SDimitry Andric }
2020b57cec5SDimitry Andric
fill()2030b57cec5SDimitry Andric void DeclInfo::fill() {
2040b57cec5SDimitry Andric assert(!IsFilled);
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric // Set defaults.
2070b57cec5SDimitry Andric Kind = OtherKind;
2080b57cec5SDimitry Andric TemplateKind = NotTemplate;
2090b57cec5SDimitry Andric IsObjCMethod = false;
2100b57cec5SDimitry Andric IsInstanceMethod = false;
2110b57cec5SDimitry Andric IsClassMethod = false;
212349cc55cSDimitry Andric IsVariadic = false;
213bdd1243dSDimitry Andric ParamVars = std::nullopt;
2140b57cec5SDimitry Andric TemplateParameters = nullptr;
2150b57cec5SDimitry Andric
2160b57cec5SDimitry Andric if (!CommentDecl) {
2170b57cec5SDimitry Andric // If there is no declaration, the defaults is our only guess.
2180b57cec5SDimitry Andric IsFilled = true;
2190b57cec5SDimitry Andric return;
2200b57cec5SDimitry Andric }
2210b57cec5SDimitry Andric CurrentDecl = CommentDecl;
2220b57cec5SDimitry Andric
2230b57cec5SDimitry Andric Decl::Kind K = CommentDecl->getKind();
224349cc55cSDimitry Andric const TypeSourceInfo *TSI = nullptr;
2250b57cec5SDimitry Andric switch (K) {
2260b57cec5SDimitry Andric default:
2270b57cec5SDimitry Andric // Defaults are should be good for declarations we don't handle explicitly.
2280b57cec5SDimitry Andric break;
2290b57cec5SDimitry Andric case Decl::Function:
2300b57cec5SDimitry Andric case Decl::CXXMethod:
2310b57cec5SDimitry Andric case Decl::CXXConstructor:
2320b57cec5SDimitry Andric case Decl::CXXDestructor:
2330b57cec5SDimitry Andric case Decl::CXXConversion: {
2340b57cec5SDimitry Andric const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl);
2350b57cec5SDimitry Andric Kind = FunctionKind;
2360b57cec5SDimitry Andric ParamVars = FD->parameters();
2370b57cec5SDimitry Andric ReturnType = FD->getReturnType();
2380b57cec5SDimitry Andric unsigned NumLists = FD->getNumTemplateParameterLists();
2390b57cec5SDimitry Andric if (NumLists != 0) {
2400b57cec5SDimitry Andric TemplateKind = TemplateSpecialization;
2410b57cec5SDimitry Andric TemplateParameters =
2420b57cec5SDimitry Andric FD->getTemplateParameterList(NumLists - 1);
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric if (K == Decl::CXXMethod || K == Decl::CXXConstructor ||
2460b57cec5SDimitry Andric K == Decl::CXXDestructor || K == Decl::CXXConversion) {
2470b57cec5SDimitry Andric const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl);
2480b57cec5SDimitry Andric IsInstanceMethod = MD->isInstance();
2490b57cec5SDimitry Andric IsClassMethod = !IsInstanceMethod;
2500b57cec5SDimitry Andric }
251349cc55cSDimitry Andric IsVariadic = FD->isVariadic();
252349cc55cSDimitry Andric assert(involvesFunctionType());
2530b57cec5SDimitry Andric break;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric case Decl::ObjCMethod: {
2560b57cec5SDimitry Andric const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl);
2570b57cec5SDimitry Andric Kind = FunctionKind;
2580b57cec5SDimitry Andric ParamVars = MD->parameters();
2590b57cec5SDimitry Andric ReturnType = MD->getReturnType();
2600b57cec5SDimitry Andric IsObjCMethod = true;
2610b57cec5SDimitry Andric IsInstanceMethod = MD->isInstanceMethod();
2620b57cec5SDimitry Andric IsClassMethod = !IsInstanceMethod;
263349cc55cSDimitry Andric IsVariadic = MD->isVariadic();
264349cc55cSDimitry Andric assert(involvesFunctionType());
2650b57cec5SDimitry Andric break;
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric case Decl::FunctionTemplate: {
2680b57cec5SDimitry Andric const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl);
2690b57cec5SDimitry Andric Kind = FunctionKind;
2700b57cec5SDimitry Andric TemplateKind = Template;
2710b57cec5SDimitry Andric const FunctionDecl *FD = FTD->getTemplatedDecl();
2720b57cec5SDimitry Andric ParamVars = FD->parameters();
2730b57cec5SDimitry Andric ReturnType = FD->getReturnType();
2740b57cec5SDimitry Andric TemplateParameters = FTD->getTemplateParameters();
275349cc55cSDimitry Andric IsVariadic = FD->isVariadic();
276349cc55cSDimitry Andric assert(involvesFunctionType());
2770b57cec5SDimitry Andric break;
2780b57cec5SDimitry Andric }
2790b57cec5SDimitry Andric case Decl::ClassTemplate: {
2800b57cec5SDimitry Andric const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl);
2810b57cec5SDimitry Andric Kind = ClassKind;
2820b57cec5SDimitry Andric TemplateKind = Template;
2830b57cec5SDimitry Andric TemplateParameters = CTD->getTemplateParameters();
2840b57cec5SDimitry Andric break;
2850b57cec5SDimitry Andric }
2860b57cec5SDimitry Andric case Decl::ClassTemplatePartialSpecialization: {
2870b57cec5SDimitry Andric const ClassTemplatePartialSpecializationDecl *CTPSD =
2880b57cec5SDimitry Andric cast<ClassTemplatePartialSpecializationDecl>(CommentDecl);
2890b57cec5SDimitry Andric Kind = ClassKind;
2900b57cec5SDimitry Andric TemplateKind = TemplatePartialSpecialization;
2910b57cec5SDimitry Andric TemplateParameters = CTPSD->getTemplateParameters();
2920b57cec5SDimitry Andric break;
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric case Decl::ClassTemplateSpecialization:
2950b57cec5SDimitry Andric Kind = ClassKind;
2960b57cec5SDimitry Andric TemplateKind = TemplateSpecialization;
2970b57cec5SDimitry Andric break;
2980b57cec5SDimitry Andric case Decl::Record:
2990b57cec5SDimitry Andric case Decl::CXXRecord:
3000b57cec5SDimitry Andric Kind = ClassKind;
3010b57cec5SDimitry Andric break;
3020b57cec5SDimitry Andric case Decl::Var:
303349cc55cSDimitry Andric if (const VarTemplateDecl *VTD =
304349cc55cSDimitry Andric cast<VarDecl>(CommentDecl)->getDescribedVarTemplate()) {
305349cc55cSDimitry Andric TemplateKind = TemplateSpecialization;
306349cc55cSDimitry Andric TemplateParameters = VTD->getTemplateParameters();
307349cc55cSDimitry Andric }
308bdd1243dSDimitry Andric [[fallthrough]];
3090b57cec5SDimitry Andric case Decl::Field:
3100b57cec5SDimitry Andric case Decl::EnumConstant:
3110b57cec5SDimitry Andric case Decl::ObjCIvar:
3120b57cec5SDimitry Andric case Decl::ObjCAtDefsField:
313349cc55cSDimitry Andric case Decl::ObjCProperty:
3140b57cec5SDimitry Andric if (const auto *VD = dyn_cast<DeclaratorDecl>(CommentDecl))
3150b57cec5SDimitry Andric TSI = VD->getTypeSourceInfo();
3160b57cec5SDimitry Andric else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(CommentDecl))
3170b57cec5SDimitry Andric TSI = PD->getTypeSourceInfo();
3180b57cec5SDimitry Andric Kind = VariableKind;
3190b57cec5SDimitry Andric break;
320349cc55cSDimitry Andric case Decl::VarTemplate: {
321349cc55cSDimitry Andric const VarTemplateDecl *VTD = cast<VarTemplateDecl>(CommentDecl);
322349cc55cSDimitry Andric Kind = VariableKind;
323349cc55cSDimitry Andric TemplateKind = Template;
324349cc55cSDimitry Andric TemplateParameters = VTD->getTemplateParameters();
325349cc55cSDimitry Andric if (const VarDecl *VD = VTD->getTemplatedDecl())
326349cc55cSDimitry Andric TSI = VD->getTypeSourceInfo();
327349cc55cSDimitry Andric break;
3280b57cec5SDimitry Andric }
3290b57cec5SDimitry Andric case Decl::Namespace:
3300b57cec5SDimitry Andric Kind = NamespaceKind;
3310b57cec5SDimitry Andric break;
3320b57cec5SDimitry Andric case Decl::TypeAlias:
333349cc55cSDimitry Andric case Decl::Typedef:
3340b57cec5SDimitry Andric Kind = TypedefKind;
335349cc55cSDimitry Andric TSI = cast<TypedefNameDecl>(CommentDecl)->getTypeSourceInfo();
3360b57cec5SDimitry Andric break;
3370b57cec5SDimitry Andric case Decl::TypeAliasTemplate: {
3380b57cec5SDimitry Andric const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl);
3390b57cec5SDimitry Andric Kind = TypedefKind;
3400b57cec5SDimitry Andric TemplateKind = Template;
3410b57cec5SDimitry Andric TemplateParameters = TAT->getTemplateParameters();
342349cc55cSDimitry Andric if (TypeAliasDecl *TAD = TAT->getTemplatedDecl())
343349cc55cSDimitry Andric TSI = TAD->getTypeSourceInfo();
3440b57cec5SDimitry Andric break;
3450b57cec5SDimitry Andric }
3460b57cec5SDimitry Andric case Decl::Enum:
3470b57cec5SDimitry Andric Kind = EnumKind;
3480b57cec5SDimitry Andric break;
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric
351349cc55cSDimitry Andric // If the type is a typedef / using to something we consider a function,
352349cc55cSDimitry Andric // extract arguments and return type.
353349cc55cSDimitry Andric if (TSI) {
354349cc55cSDimitry Andric TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
355349cc55cSDimitry Andric FunctionTypeLoc FTL;
356349cc55cSDimitry Andric if (getFunctionTypeLoc(TL, FTL)) {
357349cc55cSDimitry Andric ParamVars = FTL.getParams();
358349cc55cSDimitry Andric ReturnType = FTL.getReturnLoc().getType();
359349cc55cSDimitry Andric if (const auto *FPT = dyn_cast<FunctionProtoType>(FTL.getTypePtr()))
360349cc55cSDimitry Andric IsVariadic = FPT->isVariadic();
361349cc55cSDimitry Andric assert(involvesFunctionType());
362349cc55cSDimitry Andric }
363349cc55cSDimitry Andric }
364349cc55cSDimitry Andric
3650b57cec5SDimitry Andric IsFilled = true;
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric
getParamName(const FullComment * FC) const3680b57cec5SDimitry Andric StringRef ParamCommandComment::getParamName(const FullComment *FC) const {
3690b57cec5SDimitry Andric assert(isParamIndexValid());
3700b57cec5SDimitry Andric if (isVarArgParam())
3710b57cec5SDimitry Andric return "...";
3720b57cec5SDimitry Andric return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName();
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric
getParamName(const FullComment * FC) const3750b57cec5SDimitry Andric StringRef TParamCommandComment::getParamName(const FullComment *FC) const {
3760b57cec5SDimitry Andric assert(isPositionValid());
3770b57cec5SDimitry Andric const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters;
3780b57cec5SDimitry Andric for (unsigned i = 0, e = getDepth(); i != e; ++i) {
379480093f4SDimitry Andric assert(TPL && "Unknown TemplateParameterList");
3800b57cec5SDimitry Andric if (i == e - 1)
3810b57cec5SDimitry Andric return TPL->getParam(getIndex(i))->getName();
3820b57cec5SDimitry Andric const NamedDecl *Param = TPL->getParam(getIndex(i));
383480093f4SDimitry Andric if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param))
3840b57cec5SDimitry Andric TPL = TTP->getTemplateParameters();
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric return "";
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andric } // end namespace comments
3900b57cec5SDimitry Andric } // end namespace clang
3910b57cec5SDimitry Andric
392