clang  19.0.0git
Comment.cpp
Go to the documentation of this file.
1 //===--- Comment.cpp - Comment AST node implementation --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/AST/Comment.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/Decl.h"
12 #include "clang/AST/DeclObjC.h"
13 #include "clang/AST/DeclTemplate.h"
14 #include "clang/Basic/CharInfo.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include <type_traits>
17 
18 namespace clang {
19 namespace comments {
20 
21 // Check that no comment class has a non-trival destructor. They are allocated
22 // with a BumpPtrAllocator and therefore their destructor is not executed.
23 #define ABSTRACT_COMMENT(COMMENT)
24 #define COMMENT(CLASS, PARENT) \
25  static_assert(std::is_trivially_destructible<CLASS>::value, \
26  #CLASS " should be trivially destructible!");
27 #include "clang/AST/CommentNodes.inc"
28 #undef COMMENT
29 #undef ABSTRACT_COMMENT
30 
31 // DeclInfo is also allocated with a BumpPtrAllocator.
32 static_assert(std::is_trivially_destructible_v<DeclInfo>,
33  "DeclInfo should be trivially destructible!");
34 
35 const char *Comment::getCommentKindName() const {
36  switch (getCommentKind()) {
37  case CommentKind::None:
38  return "None";
39 #define ABSTRACT_COMMENT(COMMENT)
40 #define COMMENT(CLASS, PARENT) \
41  case CommentKind::CLASS: \
42  return #CLASS;
43 #include "clang/AST/CommentNodes.inc"
44 #undef COMMENT
45 #undef ABSTRACT_COMMENT
46  }
47  llvm_unreachable("Unknown comment kind!");
48 }
49 
50 namespace {
51 struct good {};
52 struct bad {};
53 
54 template <typename T>
55 good implements_child_begin_end(Comment::child_iterator (T::*)() const) {
56  return good();
57 }
58 
59 LLVM_ATTRIBUTE_UNUSED
60 static inline bad implements_child_begin_end(
61  Comment::child_iterator (Comment::*)() const) {
62  return bad();
63 }
64 
65 #define ASSERT_IMPLEMENTS_child_begin(function) \
66  (void) good(implements_child_begin_end(function))
67 
68 LLVM_ATTRIBUTE_UNUSED
69 static inline void CheckCommentASTNodes() {
70 #define ABSTRACT_COMMENT(COMMENT)
71 #define COMMENT(CLASS, PARENT) \
72  ASSERT_IMPLEMENTS_child_begin(&CLASS::child_begin); \
73  ASSERT_IMPLEMENTS_child_begin(&CLASS::child_end);
74 #include "clang/AST/CommentNodes.inc"
75 #undef COMMENT
76 #undef ABSTRACT_COMMENT
77 }
78 
79 #undef ASSERT_IMPLEMENTS_child_begin
80 
81 } // end unnamed namespace
82 
84  switch (getCommentKind()) {
85  case CommentKind::None:
86  llvm_unreachable("comment without a kind");
87 #define ABSTRACT_COMMENT(COMMENT)
88 #define COMMENT(CLASS, PARENT) \
89  case CommentKind::CLASS: \
90  return static_cast<const CLASS *>(this)->child_begin();
91 #include "clang/AST/CommentNodes.inc"
92 #undef COMMENT
93 #undef ABSTRACT_COMMENT
94  }
95  llvm_unreachable("Unknown comment kind!");
96 }
97 
99  switch (getCommentKind()) {
100  case CommentKind::None:
101  llvm_unreachable("comment without a kind");
102 #define ABSTRACT_COMMENT(COMMENT)
103 #define COMMENT(CLASS, PARENT) \
104  case CommentKind::CLASS: \
105  return static_cast<const CLASS *>(this)->child_end();
106 #include "clang/AST/CommentNodes.inc"
107 #undef COMMENT
108 #undef ABSTRACT_COMMENT
109  }
110  llvm_unreachable("Unknown comment kind!");
111 }
112 
113 bool TextComment::isWhitespaceNoCache() const {
114  return llvm::all_of(Text, clang::isWhitespace);
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 
129  TypeLoc TL = SrcTL.IgnoreParens();
130 
131  // Look through attribute types.
132  if (AttributedTypeLoc AttributeTL = TL.getAs<AttributedTypeLoc>())
133  return AttributeTL.getModifiedLoc();
134  // Look through qualified types.
135  if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>())
136  return QualifiedTL.getUnqualifiedLoc();
137  // Look through pointer types.
138  if (PointerTypeLoc PointerTL = TL.getAs<PointerTypeLoc>())
139  return PointerTL.getPointeeLoc().getUnqualifiedLoc();
140  // Look through reference types.
141  if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>())
142  return ReferenceTL.getPointeeLoc().getUnqualifiedLoc();
143  // Look through adjusted types.
144  if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>())
145  return ATL.getOriginalLoc();
146  if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>())
147  return BlockPointerTL.getPointeeLoc().getUnqualifiedLoc();
148  if (MemberPointerTypeLoc MemberPointerTL = TL.getAs<MemberPointerTypeLoc>())
149  return MemberPointerTL.getPointeeLoc().getUnqualifiedLoc();
150  if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>())
151  return ETL.getNamedTypeLoc();
152 
153  return TL;
154 }
155 
156 static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL) {
157  TypeLoc PrevTL;
158  while (PrevTL != TL) {
159  PrevTL = TL;
161  }
162 
163  if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
164  ResFTL = FTL;
165  return true;
166  }
167 
170  // If we have a typedef to a template specialization with exactly one
171  // template argument of a function type, this looks like std::function,
172  // boost::function, or other function wrapper. Treat these typedefs as
173  // functions.
174  if (STL.getNumArgs() != 1)
175  return false;
176  TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0);
177  if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type)
178  return false;
179  TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo();
180  TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc();
181  if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) {
182  ResFTL = FTL;
183  return true;
184  }
185  }
186 
187  return false;
188 }
189 
190 const char *
192  switch (D) {
194  return "[in]";
196  return "[out]";
198  return "[in,out]";
199  }
200  llvm_unreachable("unknown PassDirection");
201 }
202 
204  assert(!IsFilled);
205 
206  // Set defaults.
207  Kind = OtherKind;
209  IsObjCMethod = false;
210  IsInstanceMethod = false;
211  IsClassMethod = false;
212  IsVariadic = false;
213  ParamVars = std::nullopt;
214  TemplateParameters = nullptr;
215 
216  if (!CommentDecl) {
217  // If there is no declaration, the defaults is our only guess.
218  IsFilled = true;
219  return;
220  }
222 
224  const TypeSourceInfo *TSI = nullptr;
225  switch (K) {
226  default:
227  // Defaults are should be good for declarations we don't handle explicitly.
228  break;
229  case Decl::Function:
230  case Decl::CXXMethod:
231  case Decl::CXXConstructor:
232  case Decl::CXXDestructor:
233  case Decl::CXXConversion: {
234  const FunctionDecl *FD = cast<FunctionDecl>(CommentDecl);
235  Kind = FunctionKind;
236  ParamVars = FD->parameters();
237  ReturnType = FD->getReturnType();
238  unsigned NumLists = FD->getNumTemplateParameterLists();
239  if (NumLists != 0) {
242  FD->getTemplateParameterList(NumLists - 1);
243  }
244 
245  if (K == Decl::CXXMethod || K == Decl::CXXConstructor ||
246  K == Decl::CXXDestructor || K == Decl::CXXConversion) {
247  const CXXMethodDecl *MD = cast<CXXMethodDecl>(CommentDecl);
250  }
251  IsVariadic = FD->isVariadic();
252  assert(involvesFunctionType());
253  break;
254  }
255  case Decl::ObjCMethod: {
256  const ObjCMethodDecl *MD = cast<ObjCMethodDecl>(CommentDecl);
257  Kind = FunctionKind;
258  ParamVars = MD->parameters();
259  ReturnType = MD->getReturnType();
260  IsObjCMethod = true;
263  IsVariadic = MD->isVariadic();
264  assert(involvesFunctionType());
265  break;
266  }
267  case Decl::FunctionTemplate: {
268  const FunctionTemplateDecl *FTD = cast<FunctionTemplateDecl>(CommentDecl);
269  Kind = FunctionKind;
271  const FunctionDecl *FD = FTD->getTemplatedDecl();
272  ParamVars = FD->parameters();
273  ReturnType = FD->getReturnType();
275  IsVariadic = FD->isVariadic();
276  assert(involvesFunctionType());
277  break;
278  }
279  case Decl::ClassTemplate: {
280  const ClassTemplateDecl *CTD = cast<ClassTemplateDecl>(CommentDecl);
281  Kind = ClassKind;
284  break;
285  }
286  case Decl::ClassTemplatePartialSpecialization: {
288  cast<ClassTemplatePartialSpecializationDecl>(CommentDecl);
289  Kind = ClassKind;
292  break;
293  }
294  case Decl::ClassTemplateSpecialization:
295  Kind = ClassKind;
297  break;
298  case Decl::Record:
299  case Decl::CXXRecord:
300  Kind = ClassKind;
301  break;
302  case Decl::Var:
303  if (const VarTemplateDecl *VTD =
304  cast<VarDecl>(CommentDecl)->getDescribedVarTemplate()) {
306  TemplateParameters = VTD->getTemplateParameters();
307  }
308  [[fallthrough]];
309  case Decl::Field:
310  case Decl::EnumConstant:
311  case Decl::ObjCIvar:
312  case Decl::ObjCAtDefsField:
313  case Decl::ObjCProperty:
314  if (const auto *VD = dyn_cast<DeclaratorDecl>(CommentDecl))
315  TSI = VD->getTypeSourceInfo();
316  else if (const auto *PD = dyn_cast<ObjCPropertyDecl>(CommentDecl))
317  TSI = PD->getTypeSourceInfo();
318  Kind = VariableKind;
319  break;
320  case Decl::VarTemplate: {
321  const VarTemplateDecl *VTD = cast<VarTemplateDecl>(CommentDecl);
322  Kind = VariableKind;
325  if (const VarDecl *VD = VTD->getTemplatedDecl())
326  TSI = VD->getTypeSourceInfo();
327  break;
328  }
329  case Decl::Namespace:
331  break;
332  case Decl::TypeAlias:
333  case Decl::Typedef:
334  Kind = TypedefKind;
335  TSI = cast<TypedefNameDecl>(CommentDecl)->getTypeSourceInfo();
336  break;
337  case Decl::TypeAliasTemplate: {
338  const TypeAliasTemplateDecl *TAT = cast<TypeAliasTemplateDecl>(CommentDecl);
339  Kind = TypedefKind;
342  if (TypeAliasDecl *TAD = TAT->getTemplatedDecl())
343  TSI = TAD->getTypeSourceInfo();
344  break;
345  }
346  case Decl::Enum:
347  Kind = EnumKind;
348  break;
349  }
350 
351  // If the type is a typedef / using to something we consider a function,
352  // extract arguments and return type.
353  if (TSI) {
354  TypeLoc TL = TSI->getTypeLoc().getUnqualifiedLoc();
355  FunctionTypeLoc FTL;
356  if (getFunctionTypeLoc(TL, FTL)) {
357  ParamVars = FTL.getParams();
358  ReturnType = FTL.getReturnLoc().getType();
359  if (const auto *FPT = dyn_cast<FunctionProtoType>(FTL.getTypePtr()))
360  IsVariadic = FPT->isVariadic();
361  assert(involvesFunctionType());
362  }
363  }
364 
365  IsFilled = true;
366 }
367 
368 StringRef ParamCommandComment::getParamName(const FullComment *FC) const {
369  assert(isParamIndexValid());
370  if (isVarArgParam())
371  return "...";
372  return FC->getDeclInfo()->ParamVars[getParamIndex()]->getName();
373 }
374 
376  assert(isPositionValid());
378  for (unsigned i = 0, e = getDepth(); i != e; ++i) {
379  assert(TPL && "Unknown TemplateParameterList");
380  if (i == e - 1)
381  return TPL->getParam(getIndex(i))->getName();
382  const NamedDecl *Param = TPL->getParam(getIndex(i));
383  if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Param))
384  TPL = TTP->getTemplateParameters();
385  }
386  return "";
387 }
388 
389 } // end namespace comments
390 } // end namespace clang
391 
Defines the clang::ASTContext interface.
Defines the C++ template declaration subclasses.
llvm::MachO::Record Record
Definition: MachO.h:31
Type source information for an attributed type.
Definition: TypeLoc.h:875
Wrapper for source info for block pointers.
Definition: TypeLoc.h:1314
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2060
bool isInstance() const
Definition: DeclCXX.h:2087
Declaration of a class template.
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
const TypeClass * getTypePtr() const
Definition: TypeLoc.h:421
Kind
Lists the kind of concrete classes of Decl.
Definition: DeclBase.h:89
Kind getKind() const
Definition: DeclBase.h:448
TemplateParameterList * getTemplateParameterList(unsigned index) const
Definition: Decl.h:863
unsigned getNumTemplateParameterLists() const
Definition: Decl.h:859
Represents a function declaration or definition.
Definition: Decl.h:1972
QualType getReturnType() const
Definition: Decl.h:2757
bool isVariadic() const
Whether this function is variadic.
Definition: Decl.cpp:3093
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2686
Declaration of a template function.
Definition: DeclTemplate.h:957
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
Wrapper for source info for functions.
Definition: TypeLoc.h:1428
ArrayRef< ParmVarDecl * > getParams() const
Definition: TypeLoc.h:1491
TypeLoc getReturnLoc() const
Definition: TypeLoc.h:1509
Wrapper for source info for member pointers.
Definition: TypeLoc.h:1332
This represents a decl that may have a name.
Definition: Decl.h:249
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:140
bool isVariadic() const
Definition: DeclObjC.h:431
bool isInstanceMethod() const
Definition: DeclObjC.h:426
QualType getReturnType() const
Definition: DeclObjC.h:329
ArrayRef< ParmVarDecl * > parameters() const
Definition: DeclObjC.h:373
Wrapper for source info for pointers.
Definition: TypeLoc.h:1301
Wrapper of type source information for a type with non-trivial direct qualifiers.
Definition: TypeLoc.h:289
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:524
TypeSourceInfo * getTypeSourceInfo() const
Definition: TemplateBase.h:578
const TemplateArgument & getArgument() const
Definition: TemplateBase.h:574
@ Type
The template argument is a type.
Definition: TemplateBase.h:70
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:295
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:413
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:73
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:144
Represents the declaration of a typedef-name via a C++11 alias-declaration.
Definition: Decl.h:3558
Declaration of an alias template.
TypeAliasDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:59
UnqualTypeLoc getUnqualifiedLoc() const
Skips past any qualifiers, if this is qualified.
Definition: TypeLoc.h:338
QualType getType() const
Get the type for which this source info wrapper provides information.
Definition: TypeLoc.h:133
T getAs() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
Definition: TypeLoc.h:89
TypeLoc IgnoreParens() const
Definition: TypeLoc.h:1225
A container of type source information.
Definition: Type.h:7342
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
Represents a variable declaration or definition.
Definition: Decl.h:919
Declaration of a variable template.
VarDecl * getTemplatedDecl() const
Get the underlying variable declarations of the template.
Comment *const * child_iterator
Definition: Comment.h:251
child_iterator child_end() const
Definition: Comment.cpp:98
child_iterator child_begin() const
Definition: Comment.cpp:83
const char * getCommentKindName() const
Definition: Comment.cpp:35
CommentKind getCommentKind() const
Definition: Comment.h:233
A full comment attached to a declaration, contains block content.
Definition: Comment.h:1083
const DeclInfo * getDeclInfo() const LLVM_READONLY
Definition: Comment.h:1115
child_iterator child_begin() const
Definition: Comment.h:580
child_iterator child_end() const
Definition: Comment.h:584
unsigned getParamIndex() const LLVM_READONLY
Definition: Comment.h:779
static const char * getDirectionAsString(ParamCommandPassDirection D)
Definition: Comment.cpp:191
StringRef getParamName(const FullComment *FC) const
Definition: Comment.cpp:368
bool isParamIndexValid() const LLVM_READONLY
Definition: Comment.h:766
bool isVarArgParam() const LLVM_READONLY
Definition: Comment.h:770
bool isPositionValid() const LLVM_READONLY
Definition: Comment.h:833
StringRef getParamName(const FullComment *FC) const
Definition: Comment.cpp:375
unsigned getIndex(unsigned Depth) const
Definition: Comment.h:842
ParamCommandPassDirection
Definition: Comment.h:708
static bool getFunctionTypeLoc(TypeLoc TL, FunctionTypeLoc &ResFTL)
Definition: Comment.cpp:156
static TypeLoc lookThroughTypedefOrTypeAliasLocs(TypeLoc &SrcTL)
Definition: Comment.cpp:128
The JSON file list parser is used to communicate input to InstallAPI.
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...
Definition: CharInfo.h:108
const FunctionProtoType * T
unsigned TemplateKind
Is CommentDecl a template declaration.
Definition: Comment.h:1047
unsigned IsClassMethod
Is CommentDecl a static member function of C++ class or class method of ObjC class.
Definition: Comment.h:1063
@ FunctionKind
Something that we consider a "function":
Definition: Comment.h:1004
@ EnumKind
An enumeration or scoped enumeration.
Definition: Comment.h:1026
@ OtherKind
Everything else not explicitly mentioned below.
Definition: Comment.h:994
@ NamespaceKind
A C++ namespace.
Definition: Comment.h:1019
@ VariableKind
Something that we consider a "variable":
Definition: Comment.h:1016
@ ClassKind
Something that we consider a "class":
Definition: Comment.h:1010
@ TypedefKind
A C++ typedef-name (a 'typedef' decl specifier or alias-declaration), see TypedefNameDecl.
Definition: Comment.h:1023
unsigned Kind
Simplified kind of CommentDecl, see DeclKind enum.
Definition: Comment.h:1043
unsigned IsObjCMethod
Is CommentDecl an ObjCMethodDecl.
Definition: Comment.h:1051
const TemplateParameterList * TemplateParameters
Template parameters that can be referenced by \tparam if CommentDecl is a template (IsTemplateDecl or...
Definition: Comment.h:988
ArrayRef< const ParmVarDecl * > ParamVars
Parameters that can be referenced by \param if CommentDecl is something that we consider a "function"...
Definition: Comment.h:979
unsigned IsInstanceMethod
Is CommentDecl a non-static member function of C++ class or instance method of ObjC class.
Definition: Comment.h:1057
bool involvesFunctionType() const
Definition: Comment.h:1079
unsigned IsFilled
If false, only CommentDecl is valid.
Definition: Comment.h:1039
const Decl * CommentDecl
Declaration the comment is actually attached to (in the source).
Definition: Comment.h:965
unsigned IsVariadic
Is CommentDecl something we consider a "function" that's variadic.
Definition: Comment.h:1067
const Decl * CurrentDecl
CurrentDecl is the declaration with which the FullComment is associated.
Definition: Comment.h:975
QualType ReturnType
Function return type if CommentDecl is something that we consider a "function".
Definition: Comment.h:983