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