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