| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 1 | //===--- Comment.cpp - Comment AST node implementation --------------------===// | 
|  | 2 | // | 
| Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 +0000 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | 4 | // See https://llvm.org/LICENSE.txt for license information. | 
|  | 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 |  | 
|  | 9 | #include "clang/AST/Comment.h" | 
| Mehdi Amini | 9670f84 | 2016-07-18 19:02:11 +0000 | [diff] [blame] | 10 | #include "clang/AST/ASTContext.h" | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 11 | #include "clang/AST/Decl.h" | 
|  | 12 | #include "clang/AST/DeclObjC.h" | 
|  | 13 | #include "clang/AST/DeclTemplate.h" | 
| Dmitri Gribenko | db6adab | 2013-08-23 17:45:43 +0000 | [diff] [blame] | 14 | #include "clang/Basic/CharInfo.h" | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 15 | #include "llvm/Support/ErrorHandling.h" | 
| Bruno Ricci | 2535f04 | 2019-08-27 11:21:00 +0000 | [diff] [blame] | 16 | #include <type_traits> | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 17 |  | 
|  | 18 | namespace clang { | 
|  | 19 | namespace comments { | 
|  | 20 |  | 
| Bruno Ricci | 2535f04 | 2019-08-27 11:21:00 +0000 | [diff] [blame] | 21 | // Check that no comment class has a non-trival destructor. They are allocated | 
|  | 22 | // with a BumpPtrAllocator and therefore their destructor is not executed. | 
|  | 23 | #define ABSTRACT_COMMENT(COMMENT) | 
|  | 24 | #define COMMENT(CLASS, PARENT)                                                 \ | 
|  | 25 | static_assert(std::is_trivially_destructible<CLASS>::value,                  \ | 
|  | 26 | #CLASS " should be trivially destructible!"); | 
|  | 27 | #include "clang/AST/CommentNodes.inc" | 
|  | 28 | #undef COMMENT | 
|  | 29 | #undef ABSTRACT_COMMENT | 
|  | 30 |  | 
|  | 31 | // DeclInfo is also allocated with a BumpPtrAllocator. | 
|  | 32 | static_assert(std::is_trivially_destructible<DeclInfo>::value, | 
|  | 33 | "DeclInfo should be trivially destructible!"); | 
|  | 34 |  | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 35 | const char *Comment::getCommentKindName() const { | 
|  | 36 | switch (getCommentKind()) { | 
|  | 37 | case NoCommentKind: return "NoCommentKind"; | 
|  | 38 | #define ABSTRACT_COMMENT(COMMENT) | 
|  | 39 | #define COMMENT(CLASS, PARENT) \ | 
|  | 40 | case CLASS##Kind: \ | 
|  | 41 | return #CLASS; | 
|  | 42 | #include "clang/AST/CommentNodes.inc" | 
|  | 43 | #undef COMMENT | 
|  | 44 | #undef ABSTRACT_COMMENT | 
|  | 45 | } | 
|  | 46 | llvm_unreachable("Unknown comment kind!"); | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | namespace { | 
|  | 50 | struct good {}; | 
|  | 51 | struct bad {}; | 
|  | 52 |  | 
|  | 53 | template <typename T> | 
|  | 54 | good implements_child_begin_end(Comment::child_iterator (T::*)() const) { | 
|  | 55 | return good(); | 
|  | 56 | } | 
|  | 57 |  | 
| Eli Friedman | dc41d79 | 2013-09-10 22:57:15 +0000 | [diff] [blame] | 58 | LLVM_ATTRIBUTE_UNUSED | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 59 | static inline bad implements_child_begin_end( | 
|  | 60 | Comment::child_iterator (Comment::*)() const) { | 
|  | 61 | return bad(); | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | #define ASSERT_IMPLEMENTS_child_begin(function) \ | 
| Eli Friedman | dc41d79 | 2013-09-10 22:57:15 +0000 | [diff] [blame] | 65 | (void) good(implements_child_begin_end(function)) | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 66 |  | 
| Eli Friedman | dc41d79 | 2013-09-10 22:57:15 +0000 | [diff] [blame] | 67 | LLVM_ATTRIBUTE_UNUSED | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 68 | static inline void CheckCommentASTNodes() { | 
|  | 69 | #define ABSTRACT_COMMENT(COMMENT) | 
|  | 70 | #define COMMENT(CLASS, PARENT) \ | 
|  | 71 | ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \ | 
|  | 72 | ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end); | 
|  | 73 | #include "clang/AST/CommentNodes.inc" | 
|  | 74 | #undef COMMENT | 
|  | 75 | #undef ABSTRACT_COMMENT | 
|  | 76 | } | 
|  | 77 |  | 
|  | 78 | #undef ASSERT_IMPLEMENTS_child_begin | 
|  | 79 |  | 
|  | 80 | } // end unnamed namespace | 
|  | 81 |  | 
|  | 82 | Comment::child_iterator Comment::child_begin() const { | 
|  | 83 | switch (getCommentKind()) { | 
|  | 84 | case NoCommentKind: llvm_unreachable("comment without a kind"); | 
|  | 85 | #define ABSTRACT_COMMENT(COMMENT) | 
|  | 86 | #define COMMENT(CLASS, PARENT) \ | 
|  | 87 | case CLASS##Kind: \ | 
|  | 88 | return static_cast<const CLASS *>(this)->child_begin(); | 
|  | 89 | #include "clang/AST/CommentNodes.inc" | 
|  | 90 | #undef COMMENT | 
|  | 91 | #undef ABSTRACT_COMMENT | 
|  | 92 | } | 
| Matt Beaumont-Gay | 4106ea3 | 2012-07-06 21:13:09 +0000 | [diff] [blame] | 93 | llvm_unreachable("Unknown comment kind!"); | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 94 | } | 
|  | 95 |  | 
|  | 96 | Comment::child_iterator Comment::child_end() const { | 
|  | 97 | switch (getCommentKind()) { | 
|  | 98 | case NoCommentKind: llvm_unreachable("comment without a kind"); | 
|  | 99 | #define ABSTRACT_COMMENT(COMMENT) | 
|  | 100 | #define COMMENT(CLASS, PARENT) \ | 
|  | 101 | case CLASS##Kind: \ | 
|  | 102 | return static_cast<const CLASS *>(this)->child_end(); | 
|  | 103 | #include "clang/AST/CommentNodes.inc" | 
|  | 104 | #undef COMMENT | 
|  | 105 | #undef ABSTRACT_COMMENT | 
|  | 106 | } | 
| Matt Beaumont-Gay | 4106ea3 | 2012-07-06 21:13:09 +0000 | [diff] [blame] | 107 | llvm_unreachable("Unknown comment kind!"); | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 108 | } | 
|  | 109 |  | 
| Dmitri Gribenko | 05c3c75 | 2012-07-18 20:54:32 +0000 | [diff] [blame] | 110 | bool TextComment::isWhitespaceNoCache() const { | 
| Dmitri Gribenko | f26054f | 2012-07-11 21:38:39 +0000 | [diff] [blame] | 111 | for (StringRef::const_iterator I = Text.begin(), E = Text.end(); | 
|  | 112 | I != E; ++I) { | 
| Dmitri Gribenko | db6adab | 2013-08-23 17:45:43 +0000 | [diff] [blame] | 113 | if (!clang::isWhitespace(*I)) | 
| Dmitri Gribenko | f26054f | 2012-07-11 21:38:39 +0000 | [diff] [blame] | 114 | return false; | 
|  | 115 | } | 
|  | 116 | return true; | 
|  | 117 | } | 
|  | 118 |  | 
| Dmitri Gribenko | 05c3c75 | 2012-07-18 20:54:32 +0000 | [diff] [blame] | 119 | bool ParagraphComment::isWhitespaceNoCache() const { | 
| Dmitri Gribenko | f26054f | 2012-07-11 21:38:39 +0000 | [diff] [blame] | 120 | for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) { | 
|  | 121 | if (const TextComment *TC = dyn_cast<TextComment>(*I)) { | 
|  | 122 | if (!TC->isWhitespace()) | 
|  | 123 | return false; | 
| Dmitri Gribenko | 7b2ca3e | 2012-07-19 00:01:56 +0000 | [diff] [blame] | 124 | } else | 
|  | 125 | return false; | 
| Dmitri Gribenko | f26054f | 2012-07-11 21:38:39 +0000 | [diff] [blame] | 126 | } | 
|  | 127 | return true; | 
|  | 128 | } | 
|  | 129 |  | 
| Bruno Cardoso Lopes | 72ae62c | 2016-08-25 00:22:08 +0000 | [diff] [blame] | 130 | static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL) { | 
|  | 131 | TypeLoc TL = SrcTL.IgnoreParens(); | 
|  | 132 |  | 
| Alex Lorenz | 6246cc6 | 2017-04-26 12:46:27 +0000 | [diff] [blame] | 133 | // Look through attribute types. | 
|  | 134 | if (AttributedTypeLoc AttributeTL = TL.getAs<AttributedTypeLoc>()) | 
|  | 135 | return AttributeTL.getModifiedLoc(); | 
| Bruno Cardoso Lopes | 72ae62c | 2016-08-25 00:22:08 +0000 | [diff] [blame] | 136 | // Look through qualified types. | 
|  | 137 | if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) | 
|  | 138 | return QualifiedTL.getUnqualifiedLoc(); | 
|  | 139 | // Look through pointer types. | 
|  | 140 | if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) | 
|  | 141 | return PointerTL.getPointeeLoc().getUnqualifiedLoc(); | 
|  | 142 | // Look through reference types. | 
|  | 143 | if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) | 
|  | 144 | return ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); | 
|  | 145 | // Look through adjusted types. | 
|  | 146 | if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) | 
|  | 147 | return ATL.getOriginalLoc(); | 
|  | 148 | if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>()) | 
|  | 149 | return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); | 
|  | 150 | if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>()) | 
|  | 151 | return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); | 
|  | 152 | if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) | 
|  | 153 | return ETL.getNamedTypeLoc(); | 
|  | 154 |  | 
|  | 155 | return TL; | 
|  | 156 | } | 
|  | 157 |  | 
|  | 158 | static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) { | 
|  | 159 | TypeLoc PrevTL; | 
|  | 160 | while (PrevTL != TL) { | 
|  | 161 | PrevTL = TL; | 
|  | 162 | TL = lookThroughTypedefOrTypeAliasLocs(TL); | 
|  | 163 | } | 
|  | 164 |  | 
|  | 165 | if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { | 
|  | 166 | ResFTL = FTL; | 
|  | 167 | return true; | 
|  | 168 | } | 
|  | 169 |  | 
|  | 170 | if (TemplateSpecializationTypeLoc STL = | 
|  | 171 | TL.getAs<TemplateSpecializationTypeLoc>()) { | 
|  | 172 | // If we have a typedef to a template specialization with exactly one | 
|  | 173 | // template argument of a function type, this looks like std::function, | 
|  | 174 | // boost::function, or other function wrapper.  Treat these typedefs as | 
|  | 175 | // functions. | 
|  | 176 | if (STL.getNumArgs() != 1) | 
|  | 177 | return false; | 
|  | 178 | TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); | 
|  | 179 | if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) | 
|  | 180 | return false; | 
|  | 181 | TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); | 
|  | 182 | TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); | 
|  | 183 | if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { | 
|  | 184 | ResFTL = FTL; | 
|  | 185 | return true; | 
|  | 186 | } | 
|  | 187 | } | 
|  | 188 |  | 
|  | 189 | return false; | 
|  | 190 | } | 
|  | 191 |  | 
| Dmitri Gribenko | f26054f | 2012-07-11 21:38:39 +0000 | [diff] [blame] | 192 | const char *ParamCommandComment::getDirectionAsString(PassDirection D) { | 
|  | 193 | switch (D) { | 
|  | 194 | case ParamCommandComment::In: | 
|  | 195 | return "[in]"; | 
|  | 196 | case ParamCommandComment::Out: | 
|  | 197 | return "[out]"; | 
|  | 198 | case ParamCommandComment::InOut: | 
|  | 199 | return "[in,out]"; | 
|  | 200 | } | 
|  | 201 | llvm_unreachable("unknown PassDirection"); | 
|  | 202 | } | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 203 |  | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 204 | void DeclInfo::fill() { | 
|  | 205 | assert(!IsFilled); | 
|  | 206 |  | 
|  | 207 | // Set defaults. | 
| Dmitri Gribenko | 6430583 | 2012-08-03 21:15:32 +0000 | [diff] [blame] | 208 | Kind = OtherKind; | 
| Dmitri Gribenko | 8e5d5f1 | 2012-08-06 21:31:15 +0000 | [diff] [blame] | 209 | TemplateKind = NotTemplate; | 
| Dmitri Gribenko | 558babc | 2012-08-06 16:29:26 +0000 | [diff] [blame] | 210 | IsObjCMethod = false; | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 211 | IsInstanceMethod = false; | 
|  | 212 | IsClassMethod = false; | 
| Dmitri Gribenko | 44ebbd5 | 2013-05-05 00:41:58 +0000 | [diff] [blame] | 213 | ParamVars = None; | 
| Craig Topper | 36250ad | 2014-05-12 05:36:57 +0000 | [diff] [blame] | 214 | TemplateParameters = nullptr; | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 215 |  | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 216 | if (!CommentDecl) { | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 217 | // If there is no declaration, the defaults is our only guess. | 
|  | 218 | IsFilled = true; | 
|  | 219 | return; | 
|  | 220 | } | 
| Fariborz Jahanian | a7d76d2 | 2012-10-17 21:58:03 +0000 | [diff] [blame] | 221 | CurrentDecl = CommentDecl; | 
| Fangrui Song | 6907ce2 | 2018-07-30 19:24:48 +0000 | [diff] [blame] | 222 |  | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 223 | Decl::Kind K = CommentDecl->getKind(); | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 224 | switch (K) { | 
|  | 225 | default: | 
|  | 226 | // Defaults are should be good for declarations we don't handle explicitly. | 
|  | 227 | break; | 
|  | 228 | case Decl::Function: | 
|  | 229 | case Decl::CXXMethod: | 
|  | 230 | case Decl::CXXConstructor: | 
|  | 231 | case Decl::CXXDestructor: | 
|  | 232 | case Decl::CXXConversion: { | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 233 | const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl); | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 234 | Kind = FunctionKind; | 
| David Majnemer | 59f7792 | 2016-06-24 04:05:48 +0000 | [diff] [blame] | 235 | ParamVars = FD->parameters(); | 
| Alp Toker | 314cc81 | 2014-01-25 16:55:45 +0000 | [diff] [blame] | 236 | ReturnType = FD->getReturnType(); | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 237 | unsigned NumLists = FD->getNumTemplateParameterLists(); | 
|  | 238 | if (NumLists != 0) { | 
| Dmitri Gribenko | 8e5d5f1 | 2012-08-06 21:31:15 +0000 | [diff] [blame] | 239 | TemplateKind = TemplateSpecialization; | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 240 | TemplateParameters = | 
|  | 241 | FD->getTemplateParameterList(NumLists - 1); | 
|  | 242 | } | 
|  | 243 |  | 
| Dmitri Gribenko | 6430583 | 2012-08-03 21:15:32 +0000 | [diff] [blame] | 244 | if (K == Decl::CXXMethod || K == Decl::CXXConstructor || | 
|  | 245 | K == Decl::CXXDestructor || K == Decl::CXXConversion) { | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 246 | const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl); | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 247 | IsInstanceMethod = MD->isInstance(); | 
|  | 248 | IsClassMethod = !IsInstanceMethod; | 
|  | 249 | } | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 250 | break; | 
|  | 251 | } | 
|  | 252 | case Decl::ObjCMethod: { | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 253 | const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl); | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 254 | Kind = FunctionKind; | 
| David Majnemer | 59f7792 | 2016-06-24 04:05:48 +0000 | [diff] [blame] | 255 | ParamVars = MD->parameters(); | 
| Alp Toker | 314cc81 | 2014-01-25 16:55:45 +0000 | [diff] [blame] | 256 | ReturnType = MD->getReturnType(); | 
| Dmitri Gribenko | 558babc | 2012-08-06 16:29:26 +0000 | [diff] [blame] | 257 | IsObjCMethod = true; | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 258 | IsInstanceMethod = MD->isInstanceMethod(); | 
|  | 259 | IsClassMethod = !IsInstanceMethod; | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 260 | break; | 
|  | 261 | } | 
|  | 262 | case Decl::FunctionTemplate: { | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 263 | const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl); | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 264 | Kind = FunctionKind; | 
| Dmitri Gribenko | 8e5d5f1 | 2012-08-06 21:31:15 +0000 | [diff] [blame] | 265 | TemplateKind = Template; | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 266 | const FunctionDecl *FD = FTD->getTemplatedDecl(); | 
| David Majnemer | 59f7792 | 2016-06-24 04:05:48 +0000 | [diff] [blame] | 267 | ParamVars = FD->parameters(); | 
| Alp Toker | 314cc81 | 2014-01-25 16:55:45 +0000 | [diff] [blame] | 268 | ReturnType = FD->getReturnType(); | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 269 | TemplateParameters = FTD->getTemplateParameters(); | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 270 | break; | 
|  | 271 | } | 
|  | 272 | case Decl::ClassTemplate: { | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 273 | const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl); | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 274 | Kind = ClassKind; | 
| Dmitri Gribenko | 8e5d5f1 | 2012-08-06 21:31:15 +0000 | [diff] [blame] | 275 | TemplateKind = Template; | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 276 | TemplateParameters = CTD->getTemplateParameters(); | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 277 | break; | 
|  | 278 | } | 
|  | 279 | case Decl::ClassTemplatePartialSpecialization: { | 
|  | 280 | const ClassTemplatePartialSpecializationDecl *CTPSD = | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 281 | cast<ClassTemplatePartialSpecializationDecl>(CommentDecl); | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 282 | Kind = ClassKind; | 
| Dmitri Gribenko | 8e5d5f1 | 2012-08-06 21:31:15 +0000 | [diff] [blame] | 283 | TemplateKind = TemplatePartialSpecialization; | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 284 | TemplateParameters = CTPSD->getTemplateParameters(); | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 285 | break; | 
|  | 286 | } | 
|  | 287 | case Decl::ClassTemplateSpecialization: | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 288 | Kind = ClassKind; | 
| Dmitri Gribenko | 8e5d5f1 | 2012-08-06 21:31:15 +0000 | [diff] [blame] | 289 | TemplateKind = TemplateSpecialization; | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 290 | break; | 
|  | 291 | case Decl::Record: | 
| Dmitri Gribenko | 6430583 | 2012-08-03 21:15:32 +0000 | [diff] [blame] | 292 | case Decl::CXXRecord: | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 293 | Kind = ClassKind; | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 294 | break; | 
|  | 295 | case Decl::Var: | 
|  | 296 | case Decl::Field: | 
| Dmitri Gribenko | 94ef635 | 2012-08-07 18:12:22 +0000 | [diff] [blame] | 297 | case Decl::EnumConstant: | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 298 | case Decl::ObjCIvar: | 
|  | 299 | case Decl::ObjCAtDefsField: | 
| Alex Lorenz | 6b82a75 | 2017-04-21 14:17:49 +0000 | [diff] [blame] | 300 | case Decl::ObjCProperty: { | 
|  | 301 | const TypeSourceInfo *TSI; | 
|  | 302 | if (const auto *VD = dyn_cast<DeclaratorDecl>(CommentDecl)) | 
|  | 303 | TSI = VD->getTypeSourceInfo(); | 
|  | 304 | else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(CommentDecl)) | 
|  | 305 | TSI = PD->getTypeSourceInfo(); | 
|  | 306 | else | 
|  | 307 | TSI = nullptr; | 
|  | 308 | if (TSI) { | 
|  | 309 | TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); | 
|  | 310 | FunctionTypeLoc FTL; | 
|  | 311 | if (getFunctionTypeLoc(TL, FTL)) { | 
|  | 312 | ParamVars = FTL.getParams(); | 
|  | 313 | ReturnType = FTL.getReturnLoc().getType(); | 
|  | 314 | } | 
|  | 315 | } | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 316 | Kind = VariableKind; | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 317 | break; | 
| Alex Lorenz | 6b82a75 | 2017-04-21 14:17:49 +0000 | [diff] [blame] | 318 | } | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 319 | case Decl::Namespace: | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 320 | Kind = NamespaceKind; | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 321 | break; | 
| Bruno Cardoso Lopes | b09db22 | 2016-08-24 21:11:43 +0000 | [diff] [blame] | 322 | case Decl::TypeAlias: | 
| Dmitri Gribenko | 907f6b8 | 2012-08-24 00:05:30 +0000 | [diff] [blame] | 323 | case Decl::Typedef: { | 
|  | 324 | Kind = TypedefKind; | 
| Bruno Cardoso Lopes | b09db22 | 2016-08-24 21:11:43 +0000 | [diff] [blame] | 325 | // If this is a typedef / using to something we consider a function, extract | 
| Dmitri Gribenko | 907f6b8 | 2012-08-24 00:05:30 +0000 | [diff] [blame] | 326 | // arguments and return type. | 
| Bruno Cardoso Lopes | b09db22 | 2016-08-24 21:11:43 +0000 | [diff] [blame] | 327 | const TypeSourceInfo *TSI = | 
|  | 328 | K == Decl::Typedef | 
|  | 329 | ? cast<TypedefDecl>(CommentDecl)->getTypeSourceInfo() | 
|  | 330 | : cast<TypeAliasDecl>(CommentDecl)->getTypeSourceInfo(); | 
| Dmitri Gribenko | 907f6b8 | 2012-08-24 00:05:30 +0000 | [diff] [blame] | 331 | if (!TSI) | 
|  | 332 | break; | 
|  | 333 | TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); | 
| Bruno Cardoso Lopes | 72ae62c | 2016-08-25 00:22:08 +0000 | [diff] [blame] | 334 | FunctionTypeLoc FTL; | 
|  | 335 | if (getFunctionTypeLoc(TL, FTL)) { | 
|  | 336 | Kind = FunctionKind; | 
|  | 337 | ParamVars = FTL.getParams(); | 
|  | 338 | ReturnType = FTL.getReturnLoc().getType(); | 
| Dmitri Gribenko | 907f6b8 | 2012-08-24 00:05:30 +0000 | [diff] [blame] | 339 | } | 
|  | 340 | break; | 
|  | 341 | } | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 342 | case Decl::TypeAliasTemplate: { | 
| Fariborz Jahanian | 1c883b9 | 2012-10-10 18:34:52 +0000 | [diff] [blame] | 343 | const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl); | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 344 | Kind = TypedefKind; | 
| Dmitri Gribenko | 8e5d5f1 | 2012-08-06 21:31:15 +0000 | [diff] [blame] | 345 | TemplateKind = Template; | 
| Dmitri Gribenko | baeb60e | 2012-08-02 21:36:57 +0000 | [diff] [blame] | 346 | TemplateParameters = TAT->getTemplateParameters(); | 
| Bruno Cardoso Lopes | 6080bdb | 2016-08-25 17:09:33 +0000 | [diff] [blame] | 347 | TypeAliasDecl *TAD = TAT->getTemplatedDecl(); | 
|  | 348 | if (!TAD) | 
|  | 349 | break; | 
|  | 350 |  | 
|  | 351 | const TypeSourceInfo *TSI = TAD->getTypeSourceInfo(); | 
|  | 352 | if (!TSI) | 
|  | 353 | break; | 
|  | 354 | TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc(); | 
|  | 355 | FunctionTypeLoc FTL; | 
|  | 356 | if (getFunctionTypeLoc(TL, FTL)) { | 
|  | 357 | Kind = FunctionKind; | 
|  | 358 | ParamVars = FTL.getParams(); | 
|  | 359 | ReturnType = FTL.getReturnLoc().getType(); | 
|  | 360 | } | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 361 | break; | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 362 | } | 
| Dmitri Gribenko | 168d234 | 2012-08-07 18:59:04 +0000 | [diff] [blame] | 363 | case Decl::Enum: | 
|  | 364 | Kind = EnumKind; | 
|  | 365 | break; | 
| Dmitri Gribenko | 0567de8 | 2012-08-03 00:01:01 +0000 | [diff] [blame] | 366 | } | 
|  | 367 |  | 
| Dmitri Gribenko | 527ab21 | 2012-08-01 23:08:09 +0000 | [diff] [blame] | 368 | IsFilled = true; | 
|  | 369 | } | 
|  | 370 |  | 
| Dmitri Gribenko | 923f305 | 2012-10-19 16:51:38 +0000 | [diff] [blame] | 371 | StringRef ParamCommandComment::getParamName(const FullComment *FC) const { | 
| Fariborz Jahanian | 9d2f1e7 | 2012-10-18 21:42:42 +0000 | [diff] [blame] | 372 | assert(isParamIndexValid()); | 
| Dmitri Gribenko | 02489eb | 2013-06-24 04:41:32 +0000 | [diff] [blame] | 373 | if (isVarArgParam()) | 
|  | 374 | return "..."; | 
| Fariborz Jahanian | e405569 | 2013-07-05 23:20:55 +0000 | [diff] [blame] | 375 | return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName(); | 
| Fariborz Jahanian | 42e3132 | 2012-10-11 23:52:50 +0000 | [diff] [blame] | 376 | } | 
|  | 377 |  | 
| Dmitri Gribenko | 923f305 | 2012-10-19 16:51:38 +0000 | [diff] [blame] | 378 | StringRef TParamCommandComment::getParamName(const FullComment *FC) const { | 
| Fariborz Jahanian | 9d2f1e7 | 2012-10-18 21:42:42 +0000 | [diff] [blame] | 379 | assert(isPositionValid()); | 
| Fariborz Jahanian | e405569 | 2013-07-05 23:20:55 +0000 | [diff] [blame] | 380 | const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters; | 
| Fariborz Jahanian | 9d2f1e7 | 2012-10-18 21:42:42 +0000 | [diff] [blame] | 381 | for (unsigned i = 0, e = getDepth(); i != e; ++i) { | 
| Simon Pilgrim | 3b417b7 | 2020-01-07 13:37:48 +0000 | [diff] [blame] | 382 | assert(TPL && "Unknown TemplateParameterList"); | 
|  | 383 | if (i == e - 1) | 
| Fariborz Jahanian | 9d2f1e7 | 2012-10-18 21:42:42 +0000 | [diff] [blame] | 384 | return TPL->getParam(getIndex(i))->getName(); | 
|  | 385 | const NamedDecl *Param = TPL->getParam(getIndex(i)); | 
| Simon Pilgrim | 3b417b7 | 2020-01-07 13:37:48 +0000 | [diff] [blame] | 386 | if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param)) | 
| Fariborz Jahanian | 9d2f1e7 | 2012-10-18 21:42:42 +0000 | [diff] [blame] | 387 | TPL = TTP->getTemplateParameters(); | 
| Fariborz Jahanian | 14ec3f3 | 2012-10-15 18:58:50 +0000 | [diff] [blame] | 388 | } | 
| Fariborz Jahanian | 9d2f1e7 | 2012-10-18 21:42:42 +0000 | [diff] [blame] | 389 | return ""; | 
| Fariborz Jahanian | 14ec3f3 | 2012-10-15 18:58:50 +0000 | [diff] [blame] | 390 | } | 
| Dmitri Gribenko | 923f305 | 2012-10-19 16:51:38 +0000 | [diff] [blame] | 391 |  | 
| Dmitri Gribenko | ec92531 | 2012-07-06 00:28:32 +0000 | [diff] [blame] | 392 | } // end namespace comments | 
|  | 393 | } // end namespace clang | 
| Dmitri Gribenko | 37a7faf | 2012-08-02 21:45:39 +0000 | [diff] [blame] | 394 |  |