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