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