Comment.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. //===--- Comment.cpp - Comment AST node implementation --------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/AST/Comment.h"
  11. #include "clang/AST/Decl.h"
  12. #include "clang/AST/DeclObjC.h"
  13. #include "clang/AST/DeclTemplate.h"
  14. #include "llvm/Support/ErrorHandling.h"
  15. #include "llvm/Support/raw_ostream.h"
  16. namespace clang {
  17. namespace comments {
  18. const char *Comment::getCommentKindName() const {
  19. switch (getCommentKind()) {
  20. case NoCommentKind: return "NoCommentKind";
  21. #define ABSTRACT_COMMENT(COMMENT)
  22. #define COMMENT(CLASS, PARENT) \
  23. case CLASS##Kind: \
  24. return #CLASS;
  25. #include "clang/AST/CommentNodes.inc"
  26. #undef COMMENT
  27. #undef ABSTRACT_COMMENT
  28. }
  29. llvm_unreachable("Unknown comment kind!");
  30. }
  31. namespace {
  32. struct good {};
  33. struct bad {};
  34. template <typename T>
  35. good implements_child_begin_end(Comment::child_iterator (T::*)() const) {
  36. return good();
  37. }
  38. static inline bad implements_child_begin_end(
  39. Comment::child_iterator (Comment::*)() const) {
  40. return bad();
  41. }
  42. #define ASSERT_IMPLEMENTS_child_begin(function) \
  43. (void) sizeof(good(implements_child_begin_end(function)))
  44. static inline void CheckCommentASTNodes() {
  45. #define ABSTRACT_COMMENT(COMMENT)
  46. #define COMMENT(CLASS, PARENT) \
  47. ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \
  48. ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end);
  49. #include "clang/AST/CommentNodes.inc"
  50. #undef COMMENT
  51. #undef ABSTRACT_COMMENT
  52. }
  53. #undef ASSERT_IMPLEMENTS_child_begin
  54. } // end unnamed namespace
  55. Comment::child_iterator Comment::child_begin() const {
  56. switch (getCommentKind()) {
  57. case NoCommentKind: llvm_unreachable("comment without a kind");
  58. #define ABSTRACT_COMMENT(COMMENT)
  59. #define COMMENT(CLASS, PARENT) \
  60. case CLASS##Kind: \
  61. return static_cast<const CLASS *>(this)->child_begin();
  62. #include "clang/AST/CommentNodes.inc"
  63. #undef COMMENT
  64. #undef ABSTRACT_COMMENT
  65. }
  66. llvm_unreachable("Unknown comment kind!");
  67. }
  68. Comment::child_iterator Comment::child_end() const {
  69. switch (getCommentKind()) {
  70. case NoCommentKind: llvm_unreachable("comment without a kind");
  71. #define ABSTRACT_COMMENT(COMMENT)
  72. #define COMMENT(CLASS, PARENT) \
  73. case CLASS##Kind: \
  74. return static_cast<const CLASS *>(this)->child_end();
  75. #include "clang/AST/CommentNodes.inc"
  76. #undef COMMENT
  77. #undef ABSTRACT_COMMENT
  78. }
  79. llvm_unreachable("Unknown comment kind!");
  80. }
  81. bool TextComment::isWhitespaceNoCache() const {
  82. for (StringRef::const_iterator I = Text.begin(), E = Text.end();
  83. I != E; ++I) {
  84. const char C = *I;
  85. if (C != ' ' && C != '\n' && C != '\r' &&
  86. C != '\t' && C != '\f' && C != '\v')
  87. return false;
  88. }
  89. return true;
  90. }
  91. bool ParagraphComment::isWhitespaceNoCache() const {
  92. for (child_iterator I = child_begin(), E = child_end(); I != E; ++I) {
  93. if (const TextComment *TC = dyn_cast<TextComment>(*I)) {
  94. if (!TC->isWhitespace())
  95. return false;
  96. } else
  97. return false;
  98. }
  99. return true;
  100. }
  101. const char *ParamCommandComment::getDirectionAsString(PassDirection D) {
  102. switch (D) {
  103. case ParamCommandComment::In:
  104. return "[in]";
  105. case ParamCommandComment::Out:
  106. return "[out]";
  107. case ParamCommandComment::InOut:
  108. return "[in,out]";
  109. }
  110. llvm_unreachable("unknown PassDirection");
  111. }
  112. void DeclInfo::fill() {
  113. assert(!IsFilled);
  114. // Set defaults.
  115. Kind = OtherKind;
  116. TemplateKind = NotTemplate;
  117. IsObjCMethod = false;
  118. IsInstanceMethod = false;
  119. IsClassMethod = false;
  120. ParamVars = None;
  121. TemplateParameters = NULL;
  122. if (!CommentDecl) {
  123. // If there is no declaration, the defaults is our only guess.
  124. IsFilled = true;
  125. return;
  126. }
  127. CurrentDecl = CommentDecl;
  128. Decl::Kind K = CommentDecl->getKind();
  129. switch (K) {
  130. default:
  131. // Defaults are should be good for declarations we don't handle explicitly.
  132. break;
  133. case Decl::Function:
  134. case Decl::CXXMethod:
  135. case Decl::CXXConstructor:
  136. case Decl::CXXDestructor:
  137. case Decl::CXXConversion: {
  138. const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl);
  139. Kind = FunctionKind;
  140. ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
  141. FD->getNumParams());
  142. ResultType = FD->getResultType();
  143. unsigned NumLists = FD->getNumTemplateParameterLists();
  144. if (NumLists != 0) {
  145. TemplateKind = TemplateSpecialization;
  146. TemplateParameters =
  147. FD->getTemplateParameterList(NumLists - 1);
  148. }
  149. if (K == Decl::CXXMethod || K == Decl::CXXConstructor ||
  150. K == Decl::CXXDestructor || K == Decl::CXXConversion) {
  151. const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl);
  152. IsInstanceMethod = MD->isInstance();
  153. IsClassMethod = !IsInstanceMethod;
  154. }
  155. break;
  156. }
  157. case Decl::ObjCMethod: {
  158. const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl);
  159. Kind = FunctionKind;
  160. ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(),
  161. MD->param_size());
  162. ResultType = MD->getResultType();
  163. IsObjCMethod = true;
  164. IsInstanceMethod = MD->isInstanceMethod();
  165. IsClassMethod = !IsInstanceMethod;
  166. break;
  167. }
  168. case Decl::FunctionTemplate: {
  169. const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl);
  170. Kind = FunctionKind;
  171. TemplateKind = Template;
  172. const FunctionDecl *FD = FTD->getTemplatedDecl();
  173. ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(),
  174. FD->getNumParams());
  175. ResultType = FD->getResultType();
  176. TemplateParameters = FTD->getTemplateParameters();
  177. break;
  178. }
  179. case Decl::ClassTemplate: {
  180. const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl);
  181. Kind = ClassKind;
  182. TemplateKind = Template;
  183. TemplateParameters = CTD->getTemplateParameters();
  184. break;
  185. }
  186. case Decl::ClassTemplatePartialSpecialization: {
  187. const ClassTemplatePartialSpecializationDecl *CTPSD =
  188. cast<ClassTemplatePartialSpecializationDecl>(CommentDecl);
  189. Kind = ClassKind;
  190. TemplateKind = TemplatePartialSpecialization;
  191. TemplateParameters = CTPSD->getTemplateParameters();
  192. break;
  193. }
  194. case Decl::ClassTemplateSpecialization:
  195. Kind = ClassKind;
  196. TemplateKind = TemplateSpecialization;
  197. break;
  198. case Decl::Record:
  199. case Decl::CXXRecord:
  200. Kind = ClassKind;
  201. break;
  202. case Decl::Var:
  203. case Decl::Field:
  204. case Decl::EnumConstant:
  205. case Decl::ObjCIvar:
  206. case Decl::ObjCAtDefsField:
  207. Kind = VariableKind;
  208. break;
  209. case Decl::Namespace:
  210. Kind = NamespaceKind;
  211. break;
  212. case Decl::Typedef: {
  213. Kind = TypedefKind;
  214. // If this is a typedef to something we consider a function, extract
  215. // arguments and return type.
  216. const TypedefDecl *TD = cast<TypedefDecl>(CommentDecl);
  217. const TypeSourceInfo *TSI = TD->getTypeSourceInfo();
  218. if (!TSI)
  219. break;
  220. TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
  221. while (true) {
  222. TL = TL.IgnoreParens();
  223. // Look through qualified types.
  224. if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
  225. TL = QualifiedTL.getUnqualifiedLoc();
  226. continue;
  227. }
  228. // Look through pointer types.
  229. if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>()) {
  230. TL = PointerTL.getPointeeLoc().getUnqualifiedLoc();
  231. continue;
  232. }
  233. if (BlockPointerTypeLoc BlockPointerTL =
  234. TL.getAs<BlockPointerTypeLoc>()) {
  235. TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
  236. continue;
  237. }
  238. if (MemberPointerTypeLoc MemberPointerTL =
  239. TL.getAs<MemberPointerTypeLoc>()) {
  240. TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
  241. continue;
  242. }
  243. // Is this a typedef for a function type?
  244. if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
  245. Kind = FunctionKind;
  246. ArrayRef<ParmVarDecl *> Params = FTL.getParams();
  247. ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(),
  248. Params.size());
  249. ResultType = FTL.getResultLoc().getType();
  250. break;
  251. }
  252. break;
  253. }
  254. break;
  255. }
  256. case Decl::TypeAlias:
  257. Kind = TypedefKind;
  258. break;
  259. case Decl::TypeAliasTemplate: {
  260. const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl);
  261. Kind = TypedefKind;
  262. TemplateKind = Template;
  263. TemplateParameters = TAT->getTemplateParameters();
  264. break;
  265. }
  266. case Decl::Enum:
  267. Kind = EnumKind;
  268. break;
  269. }
  270. IsFilled = true;
  271. }
  272. StringRef ParamCommandComment::getParamName(const FullComment *FC) const {
  273. assert(isParamIndexValid());
  274. if (isVarArgParam())
  275. return "...";
  276. return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName();
  277. }
  278. StringRef TParamCommandComment::getParamName(const FullComment *FC) const {
  279. assert(isPositionValid());
  280. const TemplateParameterList *TPL = FC->getDeclInfo()->TemplateParameters;
  281. for (unsigned i = 0, e = getDepth(); i != e; ++i) {
  282. if (i == e-1)
  283. return TPL->getParam(getIndex(i))->getName();
  284. const NamedDecl *Param = TPL->getParam(getIndex(i));
  285. if (const TemplateTemplateParmDecl *TTP =
  286. dyn_cast<TemplateTemplateParmDecl>(Param))
  287. TPL = TTP->getTemplateParameters();
  288. }
  289. return "";
  290. }
  291. } // end namespace comments
  292. } // end namespace clang