clang  14.0.0git
CommentSema.cpp
Go to the documentation of this file.
1 //===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===//
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 
10 #include "clang/AST/Attr.h"
13 #include "clang/AST/Decl.h"
14 #include "clang/AST/DeclTemplate.h"
15 #include "clang/Basic/LLVM.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/StringSwitch.h"
20 
21 namespace clang {
22 namespace comments {
23 
24 namespace {
25 #include "clang/AST/CommentHTMLTagsProperties.inc"
26 } // end anonymous namespace
27 
28 Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
29  DiagnosticsEngine &Diags, CommandTraits &Traits,
30  const Preprocessor *PP) :
31  Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
32  PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr),
33  HeaderfileCommand(nullptr) {
34 }
35 
36 void Sema::setDecl(const Decl *D) {
37  if (!D)
38  return;
39 
40  ThisDeclInfo = new (Allocator) DeclInfo;
41  ThisDeclInfo->CommentDecl = D;
42  ThisDeclInfo->IsFilled = false;
43 }
44 
47  return new (Allocator) ParagraphComment(Content);
48 }
49 
51  SourceLocation LocBegin,
52  SourceLocation LocEnd,
53  unsigned CommandID,
54  CommandMarkerKind CommandMarker) {
55  BlockCommandComment *BC = new (Allocator) BlockCommandComment(LocBegin, LocEnd,
56  CommandID,
57  CommandMarker);
59  return BC;
60 }
61 
64  Command->setArgs(Args);
65 }
66 
68  ParagraphComment *Paragraph) {
69  Command->setParagraph(Paragraph);
72  if (ThisDeclInfo) {
73  // These checks only make sense if the comment is attached to a
74  // declaration.
75  checkReturnsCommand(Command);
76  checkDeprecatedCommand(Command);
77  }
78 }
79 
81  SourceLocation LocBegin,
82  SourceLocation LocEnd,
83  unsigned CommandID,
84  CommandMarkerKind CommandMarker) {
85  ParamCommandComment *Command =
86  new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID,
87  CommandMarker);
88 
90  Diag(Command->getLocation(),
91  diag::warn_doc_param_not_attached_to_a_function_decl)
92  << CommandMarker
93  << Command->getCommandNameRange(Traits);
94 
95  return Command;
96 }
97 
99  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
100  if (!Info->IsFunctionDeclarationCommand)
101  return;
102 
103  unsigned DiagSelect;
104  switch (Comment->getCommandID()) {
105  case CommandTraits::KCI_function:
106  DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 1 : 0;
107  break;
108  case CommandTraits::KCI_functiongroup:
109  DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 2 : 0;
110  break;
111  case CommandTraits::KCI_method:
112  DiagSelect = !isObjCMethodDecl() ? 3 : 0;
113  break;
114  case CommandTraits::KCI_methodgroup:
115  DiagSelect = !isObjCMethodDecl() ? 4 : 0;
116  break;
117  case CommandTraits::KCI_callback:
118  DiagSelect = !isFunctionPointerVarDecl() ? 5 : 0;
119  break;
120  default:
121  DiagSelect = 0;
122  break;
123  }
124  if (DiagSelect)
125  Diag(Comment->getLocation(), diag::warn_doc_function_method_decl_mismatch)
126  << Comment->getCommandMarker()
127  << (DiagSelect-1) << (DiagSelect-1)
128  << Comment->getSourceRange();
129 }
130 
132  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
134  return;
135  unsigned DiagSelect;
136  switch (Comment->getCommandID()) {
137  case CommandTraits::KCI_class:
138  DiagSelect =
140  : 0;
141  // Allow @class command on @interface declarations.
142  // FIXME. Currently, \class and @class are indistinguishable. So,
143  // \class is also allowed on an @interface declaration
144  if (DiagSelect && Comment->getCommandMarker() && isObjCInterfaceDecl())
145  DiagSelect = 0;
146  break;
147  case CommandTraits::KCI_interface:
148  DiagSelect = !isObjCInterfaceDecl() ? 2 : 0;
149  break;
150  case CommandTraits::KCI_protocol:
151  DiagSelect = !isObjCProtocolDecl() ? 3 : 0;
152  break;
153  case CommandTraits::KCI_struct:
154  DiagSelect = !isClassOrStructOrTagTypedefDecl() ? 4 : 0;
155  break;
156  case CommandTraits::KCI_union:
157  DiagSelect = !isUnionDecl() ? 5 : 0;
158  break;
159  default:
160  DiagSelect = 0;
161  break;
162  }
163  if (DiagSelect)
164  Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch)
165  << Comment->getCommandMarker()
166  << (DiagSelect-1) << (DiagSelect-1)
167  << Comment->getSourceRange();
168 }
169 
171  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
173  return;
174  unsigned DiagSelect;
175  switch (Comment->getCommandID()) {
176  case CommandTraits::KCI_classdesign:
177  DiagSelect = 1;
178  break;
179  case CommandTraits::KCI_coclass:
180  DiagSelect = 2;
181  break;
182  case CommandTraits::KCI_dependency:
183  DiagSelect = 3;
184  break;
185  case CommandTraits::KCI_helper:
186  DiagSelect = 4;
187  break;
188  case CommandTraits::KCI_helperclass:
189  DiagSelect = 5;
190  break;
191  case CommandTraits::KCI_helps:
192  DiagSelect = 6;
193  break;
194  case CommandTraits::KCI_instancesize:
195  DiagSelect = 7;
196  break;
197  case CommandTraits::KCI_ownership:
198  DiagSelect = 8;
199  break;
200  case CommandTraits::KCI_performance:
201  DiagSelect = 9;
202  break;
203  case CommandTraits::KCI_security:
204  DiagSelect = 10;
205  break;
206  case CommandTraits::KCI_superclass:
207  DiagSelect = 11;
208  break;
209  default:
210  DiagSelect = 0;
211  break;
212  }
213  if (DiagSelect)
214  Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch)
215  << Comment->getCommandMarker()
216  << (DiagSelect-1)
217  << Comment->getSourceRange();
218 }
219 
220 /// Turn a string into the corresponding PassDirection or -1 if it's not
221 /// valid.
222 static int getParamPassDirection(StringRef Arg) {
223  return llvm::StringSwitch<int>(Arg)
224  .Case("[in]", ParamCommandComment::In)
225  .Case("[out]", ParamCommandComment::Out)
226  .Cases("[in,out]", "[out,in]", ParamCommandComment::InOut)
227  .Default(-1);
228 }
229 
231  SourceLocation ArgLocBegin,
232  SourceLocation ArgLocEnd,
233  StringRef Arg) {
234  std::string ArgLower = Arg.lower();
235  int Direction = getParamPassDirection(ArgLower);
236 
237  if (Direction == -1) {
238  // Try again with whitespace removed.
239  llvm::erase_if(ArgLower, clang::isWhitespace);
240  Direction = getParamPassDirection(ArgLower);
241 
242  SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
243  if (Direction != -1) {
244  const char *FixedName = ParamCommandComment::getDirectionAsString(
246  Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction)
247  << ArgRange << FixItHint::CreateReplacement(ArgRange, FixedName);
248  } else {
249  Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange;
250  Direction = ParamCommandComment::In; // Sane fall back.
251  }
252  }
254  /*Explicit=*/true);
255 }
256 
258  SourceLocation ArgLocBegin,
259  SourceLocation ArgLocEnd,
260  StringRef Arg) {
261  // Parser will not feed us more arguments than needed.
262  assert(Command->getNumArgs() == 0);
263 
264  if (!Command->isDirectionExplicit()) {
265  // User didn't provide a direction argument.
266  Command->setDirection(ParamCommandComment::In, /* Explicit = */ false);
267  }
268  typedef BlockCommandComment::Argument Argument;
269  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
270  ArgLocEnd),
271  Arg);
272  Command->setArgs(llvm::makeArrayRef(A, 1));
273 }
274 
276  ParagraphComment *Paragraph) {
277  Command->setParagraph(Paragraph);
279 }
280 
282  SourceLocation LocBegin,
283  SourceLocation LocEnd,
284  unsigned CommandID,
285  CommandMarkerKind CommandMarker) {
286  TParamCommandComment *Command =
287  new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID,
288  CommandMarker);
289 
291  Diag(Command->getLocation(),
292  diag::warn_doc_tparam_not_attached_to_a_template_decl)
293  << CommandMarker
294  << Command->getCommandNameRange(Traits);
295 
296  return Command;
297 }
298 
300  SourceLocation ArgLocBegin,
301  SourceLocation ArgLocEnd,
302  StringRef Arg) {
303  // Parser will not feed us more arguments than needed.
304  assert(Command->getNumArgs() == 0);
305 
306  typedef BlockCommandComment::Argument Argument;
307  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
308  ArgLocEnd),
309  Arg);
310  Command->setArgs(llvm::makeArrayRef(A, 1));
311 
313  // We already warned that this \\tparam is not attached to a template decl.
314  return;
315  }
316 
317  const TemplateParameterList *TemplateParameters =
318  ThisDeclInfo->TemplateParameters;
319  SmallVector<unsigned, 2> Position;
320  if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
321  Command->setPosition(copyArray(llvm::makeArrayRef(Position)));
322  TParamCommandComment *&PrevCommand = TemplateParameterDocs[Arg];
323  if (PrevCommand) {
324  SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
325  Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
326  << Arg << ArgRange;
327  Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous)
328  << PrevCommand->getParamNameRange();
329  }
330  PrevCommand = Command;
331  return;
332  }
333 
334  SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
335  Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
336  << Arg << ArgRange;
337 
338  if (!TemplateParameters || TemplateParameters->size() == 0)
339  return;
340 
341  StringRef CorrectedName;
342  if (TemplateParameters->size() == 1) {
343  const NamedDecl *Param = TemplateParameters->getParam(0);
344  const IdentifierInfo *II = Param->getIdentifier();
345  if (II)
346  CorrectedName = II->getName();
347  } else {
348  CorrectedName = correctTypoInTParamReference(Arg, TemplateParameters);
349  }
350 
351  if (!CorrectedName.empty()) {
352  Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
353  << CorrectedName
354  << FixItHint::CreateReplacement(ArgRange, CorrectedName);
355  }
356 }
357 
359  ParagraphComment *Paragraph) {
360  Command->setParagraph(Paragraph);
362 }
363 
365  SourceLocation CommandLocEnd,
366  unsigned CommandID) {
368  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
369  return new (Allocator) InlineCommandComment(
370  CommandLocBegin,
371  CommandLocEnd,
372  CommandID,
373  getInlineCommandRenderKind(CommandName),
374  Args);
375 }
376 
378  SourceLocation CommandLocEnd,
379  unsigned CommandID,
380  SourceLocation ArgLocBegin,
381  SourceLocation ArgLocEnd,
382  StringRef Arg) {
383  typedef InlineCommandComment::Argument Argument;
384  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
385  ArgLocEnd),
386  Arg);
387  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
388 
389  return new (Allocator) InlineCommandComment(
390  CommandLocBegin,
391  CommandLocEnd,
392  CommandID,
393  getInlineCommandRenderKind(CommandName),
394  llvm::makeArrayRef(A, 1));
395 }
396 
398  SourceLocation LocEnd,
399  StringRef CommandName) {
400  unsigned CommandID = Traits.registerUnknownCommand(CommandName)->getID();
401  return actOnUnknownCommand(LocBegin, LocEnd, CommandID);
402 }
403 
405  SourceLocation LocEnd,
406  unsigned CommandID) {
408  return new (Allocator) InlineCommandComment(
409  LocBegin, LocEnd, CommandID,
411  Args);
412 }
413 
415  SourceLocation LocEnd,
416  StringRef Text) {
417  return new (Allocator) TextComment(LocBegin, LocEnd, Text);
418 }
419 
421  unsigned CommandID) {
422  StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
423  return new (Allocator) VerbatimBlockComment(
424  Loc,
425  Loc.getLocWithOffset(1 + CommandName.size()),
426  CommandID);
427 }
428 
430  StringRef Text) {
431  return new (Allocator) VerbatimBlockLineComment(Loc, Text);
432 }
433 
435  VerbatimBlockComment *Block,
436  SourceLocation CloseNameLocBegin,
437  StringRef CloseName,
439  Block->setCloseName(CloseName, CloseNameLocBegin);
440  Block->setLines(Lines);
441 }
442 
444  unsigned CommandID,
445  SourceLocation TextBegin,
446  StringRef Text) {
447  VerbatimLineComment *VL = new (Allocator) VerbatimLineComment(
448  LocBegin,
449  TextBegin.getLocWithOffset(Text.size()),
450  CommandID,
451  TextBegin,
452  Text);
455  return VL;
456 }
457 
459  StringRef TagName) {
460  return new (Allocator) HTMLStartTagComment(LocBegin, TagName);
461 }
462 
464  HTMLStartTagComment *Tag,
466  SourceLocation GreaterLoc,
467  bool IsSelfClosing) {
468  Tag->setAttrs(Attrs);
469  Tag->setGreaterLoc(GreaterLoc);
470  if (IsSelfClosing)
471  Tag->setSelfClosing();
472  else if (!isHTMLEndTagForbidden(Tag->getTagName()))
473  HTMLOpenTags.push_back(Tag);
474 }
475 
477  SourceLocation LocEnd,
478  StringRef TagName) {
479  HTMLEndTagComment *HET =
480  new (Allocator) HTMLEndTagComment(LocBegin, LocEnd, TagName);
481  if (isHTMLEndTagForbidden(TagName)) {
482  Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden)
483  << TagName << HET->getSourceRange();
484  HET->setIsMalformed();
485  return HET;
486  }
487 
488  bool FoundOpen = false;
490  I = HTMLOpenTags.rbegin(), E = HTMLOpenTags.rend();
491  I != E; ++I) {
492  if ((*I)->getTagName() == TagName) {
493  FoundOpen = true;
494  break;
495  }
496  }
497  if (!FoundOpen) {
498  Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced)
499  << HET->getSourceRange();
500  HET->setIsMalformed();
501  return HET;
502  }
503 
504  while (!HTMLOpenTags.empty()) {
505  HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
506  StringRef LastNotClosedTagName = HST->getTagName();
507  if (LastNotClosedTagName == TagName) {
508  // If the start tag is malformed, end tag is malformed as well.
509  if (HST->isMalformed())
510  HET->setIsMalformed();
511  break;
512  }
513 
514  if (isHTMLEndTagOptional(LastNotClosedTagName))
515  continue;
516 
517  bool OpenLineInvalid;
518  const unsigned OpenLine = SourceMgr.getPresumedLineNumber(
519  HST->getLocation(),
520  &OpenLineInvalid);
521  bool CloseLineInvalid;
522  const unsigned CloseLine = SourceMgr.getPresumedLineNumber(
523  HET->getLocation(),
524  &CloseLineInvalid);
525 
526  if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) {
527  Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
528  << HST->getTagName() << HET->getTagName()
529  << HST->getSourceRange() << HET->getSourceRange();
530  HST->setIsMalformed();
531  } else {
532  Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
533  << HST->getTagName() << HET->getTagName()
534  << HST->getSourceRange();
535  Diag(HET->getLocation(), diag::note_doc_html_end_tag)
536  << HET->getSourceRange();
537  HST->setIsMalformed();
538  }
539  }
540 
541  return HET;
542 }
543 
546  FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
548 
549  // Complain about HTML tags that are not closed.
550  while (!HTMLOpenTags.empty()) {
551  HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
552  if (isHTMLEndTagOptional(HST->getTagName()))
553  continue;
554 
555  Diag(HST->getLocation(), diag::warn_doc_html_missing_end_tag)
556  << HST->getTagName() << HST->getSourceRange();
557  HST->setIsMalformed();
558  }
559 
560  return FC;
561 }
562 
564  if (Traits.getCommandInfo(Command->getCommandID())->IsEmptyParagraphAllowed)
565  return;
566 
567  ParagraphComment *Paragraph = Command->getParagraph();
568  if (Paragraph->isWhitespace()) {
569  SourceLocation DiagLoc;
570  if (Command->getNumArgs() > 0)
571  DiagLoc = Command->getArgRange(Command->getNumArgs() - 1).getEnd();
572  if (!DiagLoc.isValid())
573  DiagLoc = Command->getCommandNameRange(Traits).getEnd();
574  Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
575  << Command->getCommandMarker()
576  << Command->getCommandName(Traits)
577  << Command->getSourceRange();
578  }
579 }
580 
582  if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand)
583  return;
584 
585  assert(ThisDeclInfo && "should not call this check on a bare comment");
586 
587  // We allow the return command for all @properties because it can be used
588  // to document the value that the property getter returns.
589  if (isObjCPropertyDecl())
590  return;
592  assert(!ThisDeclInfo->ReturnType.isNull() &&
593  "should have a valid return type");
594  if (ThisDeclInfo->ReturnType->isVoidType()) {
595  unsigned DiagKind;
596  switch (ThisDeclInfo->CommentDecl->getKind()) {
597  default:
598  if (ThisDeclInfo->IsObjCMethod)
599  DiagKind = 3;
600  else
601  DiagKind = 0;
602  break;
603  case Decl::CXXConstructor:
604  DiagKind = 1;
605  break;
606  case Decl::CXXDestructor:
607  DiagKind = 2;
608  break;
609  }
610  Diag(Command->getLocation(),
611  diag::warn_doc_returns_attached_to_a_void_function)
612  << Command->getCommandMarker()
613  << Command->getCommandName(Traits)
614  << DiagKind
615  << Command->getSourceRange();
616  }
617  return;
618  }
619 
620  Diag(Command->getLocation(),
621  diag::warn_doc_returns_not_attached_to_a_function_decl)
622  << Command->getCommandMarker()
623  << Command->getCommandName(Traits)
624  << Command->getSourceRange();
625 }
626 
628  const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
629  const BlockCommandComment *PrevCommand = nullptr;
630  if (Info->IsBriefCommand) {
631  if (!BriefCommand) {
632  BriefCommand = Command;
633  return;
634  }
635  PrevCommand = BriefCommand;
636  } else if (Info->IsHeaderfileCommand) {
637  if (!HeaderfileCommand) {
638  HeaderfileCommand = Command;
639  return;
640  }
641  PrevCommand = HeaderfileCommand;
642  } else {
643  // We don't want to check this command for duplicates.
644  return;
645  }
646  StringRef CommandName = Command->getCommandName(Traits);
647  StringRef PrevCommandName = PrevCommand->getCommandName(Traits);
648  Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
649  << Command->getCommandMarker()
650  << CommandName
651  << Command->getSourceRange();
652  if (CommandName == PrevCommandName)
653  Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
654  << PrevCommand->getCommandMarker()
655  << PrevCommandName
656  << PrevCommand->getSourceRange();
657  else
658  Diag(PrevCommand->getLocation(),
659  diag::note_doc_block_command_previous_alias)
660  << PrevCommand->getCommandMarker()
661  << PrevCommandName
662  << CommandName;
663 }
664 
666  if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand)
667  return;
668 
669  assert(ThisDeclInfo && "should not call this check on a bare comment");
670 
671  const Decl *D = ThisDeclInfo->CommentDecl;
672  if (!D)
673  return;
674 
675  if (D->hasAttr<DeprecatedAttr>() ||
676  D->hasAttr<AvailabilityAttr>() ||
677  D->hasAttr<UnavailableAttr>())
678  return;
679 
680  Diag(Command->getLocation(), diag::warn_doc_deprecated_not_sync)
681  << Command->getSourceRange() << Command->getCommandMarker();
682 
683  // Try to emit a fixit with a deprecation attribute.
684  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
685  // Don't emit a Fix-It for non-member function definitions. GCC does not
686  // accept attributes on them.
687  const DeclContext *Ctx = FD->getDeclContext();
688  if ((!Ctx || !Ctx->isRecord()) &&
689  FD->doesThisDeclarationHaveABody())
690  return;
691 
692  const LangOptions &LO = FD->getLangOpts();
693  const bool DoubleSquareBracket = LO.CPlusPlus14 || LO.C2x;
694  StringRef AttributeSpelling =
695  DoubleSquareBracket ? "[[deprecated]]" : "__attribute__((deprecated))";
696  if (PP) {
697  // Try to find a replacement macro:
698  // - In C2x/C++14 we prefer [[deprecated]].
699  // - If not found or an older C/C++ look for __attribute__((deprecated)).
700  StringRef MacroName;
701  if (DoubleSquareBracket) {
702  TokenValue Tokens[] = {tok::l_square, tok::l_square,
703  PP->getIdentifierInfo("deprecated"),
704  tok::r_square, tok::r_square};
705  MacroName = PP->getLastMacroWithSpelling(FD->getLocation(), Tokens);
706  if (!MacroName.empty())
707  AttributeSpelling = MacroName;
708  }
709 
710  if (MacroName.empty()) {
711  TokenValue Tokens[] = {
712  tok::kw___attribute, tok::l_paren,
713  tok::l_paren, PP->getIdentifierInfo("deprecated"),
714  tok::r_paren, tok::r_paren};
715  StringRef MacroName =
716  PP->getLastMacroWithSpelling(FD->getLocation(), Tokens);
717  if (!MacroName.empty())
718  AttributeSpelling = MacroName;
719  }
720  }
721 
722  SmallString<64> TextToInsert = AttributeSpelling;
723  TextToInsert += " ";
724  SourceLocation Loc = FD->getSourceRange().getBegin();
725  Diag(Loc, diag::note_add_deprecation_attr)
726  << FixItHint::CreateInsertion(Loc, TextToInsert);
727  }
728 }
729 
731  if (!isFunctionDecl()) {
732  // We already warned that \\param commands are not attached to a function
733  // decl.
734  return;
735  }
736 
737  SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;
738 
739  // Comment AST nodes that correspond to \c ParamVars for which we have
740  // found a \\param command or NULL if no documentation was found so far.
742 
744  ParamVarDocs.resize(ParamVars.size(), nullptr);
745 
746  // First pass over all \\param commands: resolve all parameter names.
747  for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
748  I != E; ++I) {
749  ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
750  if (!PCC || !PCC->hasParamName())
751  continue;
752  StringRef ParamName = PCC->getParamNameAsWritten();
753 
754  // Check that referenced parameter name is in the function decl.
755  const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,
756  ParamVars);
757  if (ResolvedParamIndex == ParamCommandComment::VarArgParamIndex) {
758  PCC->setIsVarArgParam();
759  continue;
760  }
761  if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) {
762  UnresolvedParamCommands.push_back(PCC);
763  continue;
764  }
765  PCC->setParamIndex(ResolvedParamIndex);
766  if (ParamVarDocs[ResolvedParamIndex]) {
767  SourceRange ArgRange = PCC->getParamNameRange();
768  Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)
769  << ParamName << ArgRange;
770  ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
771  Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
772  << PrevCommand->getParamNameRange();
773  }
774  ParamVarDocs[ResolvedParamIndex] = PCC;
775  }
776 
777  // Find parameter declarations that have no corresponding \\param.
778  SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;
779  for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
780  if (!ParamVarDocs[i])
781  OrphanedParamDecls.push_back(ParamVars[i]);
782  }
783 
784  // Second pass over unresolved \\param commands: do typo correction.
785  // Suggest corrections from a set of parameter declarations that have no
786  // corresponding \\param.
787  for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
788  const ParamCommandComment *PCC = UnresolvedParamCommands[i];
789 
790  SourceRange ArgRange = PCC->getParamNameRange();
791  StringRef ParamName = PCC->getParamNameAsWritten();
792  Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)
793  << ParamName << ArgRange;
794 
795  // All parameters documented -- can't suggest a correction.
796  if (OrphanedParamDecls.size() == 0)
797  continue;
798 
799  unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
800  if (OrphanedParamDecls.size() == 1) {
801  // If one parameter is not documented then that parameter is the only
802  // possible suggestion.
803  CorrectedParamIndex = 0;
804  } else {
805  // Do typo correction.
806  CorrectedParamIndex = correctTypoInParmVarReference(ParamName,
807  OrphanedParamDecls);
808  }
809  if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
810  const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
811  if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
812  Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)
813  << CorrectedII->getName()
814  << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
815  }
816  }
817 }
818 
820  if (!ThisDeclInfo)
821  return false;
822  if (!ThisDeclInfo->IsFilled)
823  inspectThisDecl();
824  return ThisDeclInfo->getKind() == DeclInfo::FunctionKind;
825 }
826 
828  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
829  isa<FunctionDecl>(ThisDeclInfo->CurrentDecl);
830 }
831 
833  if (!isFunctionDecl() || !ThisDeclInfo->CurrentDecl)
834  return false;
835  if (const FunctionDecl *FD =
836  dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl))
837  return FD->isVariadic();
838  if (const FunctionTemplateDecl *FTD =
839  dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl))
840  return FTD->getTemplatedDecl()->isVariadic();
841  if (const ObjCMethodDecl *MD =
842  dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl))
843  return MD->isVariadic();
844  if (const TypedefNameDecl *TD =
845  dyn_cast<TypedefNameDecl>(ThisDeclInfo->CurrentDecl)) {
846  QualType Type = TD->getUnderlyingType();
848  Type = Type->getPointeeType();
849  if (const auto *FT = Type->getAs<FunctionProtoType>())
850  return FT->isVariadic();
851  }
852  return false;
853 }
854 
856  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
857  isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl);
858 }
859 
861  if (!ThisDeclInfo)
862  return false;
863  if (!ThisDeclInfo->IsFilled)
864  inspectThisDecl();
865  if (ThisDeclInfo->getKind() == DeclInfo::VariableKind) {
866  if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDeclInfo->CurrentDecl)) {
867  QualType QT = VD->getType();
868  return QT->isFunctionPointerType();
869  }
870  }
871  return false;
872 }
873 
875  if (!ThisDeclInfo)
876  return false;
877  if (!ThisDeclInfo->IsFilled)
878  inspectThisDecl();
879  if (ThisDeclInfo->getKind() != DeclInfo::VariableKind ||
880  !ThisDeclInfo->CurrentDecl)
881  return false;
882  QualType QT;
883  if (const auto *VD = dyn_cast<DeclaratorDecl>(ThisDeclInfo->CurrentDecl))
884  QT = VD->getType();
885  else if (const auto *PD =
886  dyn_cast<ObjCPropertyDecl>(ThisDeclInfo->CurrentDecl))
887  QT = PD->getType();
888  else
889  return false;
890  // We would like to warn about the 'returns'/'param' commands for
891  // variables that don't directly specify the function type, so type aliases
892  // can be ignored.
893  if (QT->getAs<TypedefType>())
894  return false;
895  if (const auto *P = QT->getAs<PointerType>())
896  if (P->getPointeeType()->getAs<TypedefType>())
897  return false;
898  if (const auto *P = QT->getAs<BlockPointerType>())
899  if (P->getPointeeType()->getAs<TypedefType>())
900  return false;
901  return QT->isFunctionPointerType() || QT->isBlockPointerType();
902 }
903 
905  if (!ThisDeclInfo)
906  return false;
907  if (!ThisDeclInfo->IsFilled)
908  inspectThisDecl();
909  return ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty;
910 }
911 
913  if (!ThisDeclInfo)
914  return false;
915  if (!ThisDeclInfo->IsFilled)
916  inspectThisDecl();
917  return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate;
918 }
919 
921  if (!ThisDeclInfo)
922  return false;
923  if (!ThisDeclInfo->IsFilled)
924  inspectThisDecl();
927 }
928 
930  if (!ThisDeclInfo)
931  return false;
932  if (!ThisDeclInfo->IsFilled)
933  inspectThisDecl();
934  if (const RecordDecl *RD =
935  dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl))
936  return RD->isUnion();
937  return false;
938 }
939 static bool isClassOrStructDeclImpl(const Decl *D) {
940  if (auto *record = dyn_cast_or_null<RecordDecl>(D))
941  return !record->isUnion();
942 
943  return false;
944 }
945 
947  if (!ThisDeclInfo)
948  return false;
949  if (!ThisDeclInfo->IsFilled)
950  inspectThisDecl();
951 
952  if (!ThisDeclInfo->CurrentDecl)
953  return false;
954 
955  return isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl);
956 }
957 
959  if (!ThisDeclInfo)
960  return false;
961  if (!ThisDeclInfo->IsFilled)
962  inspectThisDecl();
963 
964  if (!ThisDeclInfo->CurrentDecl)
965  return false;
966 
967  if (isClassOrStructDeclImpl(ThisDeclInfo->CurrentDecl))
968  return true;
969 
970  if (auto *ThisTypedefDecl = dyn_cast<TypedefDecl>(ThisDeclInfo->CurrentDecl)) {
971  auto UnderlyingType = ThisTypedefDecl->getUnderlyingType();
972  if (auto ThisElaboratedType = dyn_cast<ElaboratedType>(UnderlyingType)) {
973  auto DesugaredType = ThisElaboratedType->desugar();
974  if (auto *DesugaredTypePtr = DesugaredType.getTypePtrOrNull()) {
975  if (auto *ThisRecordType = dyn_cast<RecordType>(DesugaredTypePtr)) {
976  return isClassOrStructDeclImpl(ThisRecordType->getAsRecordDecl());
977  }
978  }
979  }
980  }
981 
982  return false;
983 }
984 
986  if (!ThisDeclInfo)
987  return false;
988  if (!ThisDeclInfo->IsFilled)
989  inspectThisDecl();
990  return ThisDeclInfo->CurrentDecl &&
991  (isa<ClassTemplateDecl>(ThisDeclInfo->CurrentDecl));
992 }
993 
995  if (!ThisDeclInfo)
996  return false;
997  if (!ThisDeclInfo->IsFilled)
998  inspectThisDecl();
999  return ThisDeclInfo->CurrentDecl &&
1000  (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl));
1001 }
1002 
1004  if (!ThisDeclInfo)
1005  return false;
1006  if (!ThisDeclInfo->IsFilled)
1007  inspectThisDecl();
1008  return ThisDeclInfo->CurrentDecl &&
1009  isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl);
1010 }
1011 
1013  if (!ThisDeclInfo)
1014  return false;
1015  if (!ThisDeclInfo->IsFilled)
1016  inspectThisDecl();
1017  return ThisDeclInfo->CurrentDecl &&
1018  isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl);
1019 }
1020 
1022  if (!ThisDeclInfo->IsFilled)
1023  inspectThisDecl();
1024  return ThisDeclInfo->ParamVars;
1025 }
1026 
1028  ThisDeclInfo->fill();
1029 }
1030 
1031 unsigned Sema::resolveParmVarReference(StringRef Name,
1032  ArrayRef<const ParmVarDecl *> ParamVars) {
1033  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
1034  const IdentifierInfo *II = ParamVars[i]->getIdentifier();
1035  if (II && II->getName() == Name)
1036  return i;
1037  }
1038  if (Name == "..." && isFunctionOrMethodVariadic())
1041 }
1042 
1043 namespace {
1044 class SimpleTypoCorrector {
1045  const NamedDecl *BestDecl;
1046 
1047  StringRef Typo;
1048  const unsigned MaxEditDistance;
1049 
1050  unsigned BestEditDistance;
1051  unsigned BestIndex;
1052  unsigned NextIndex;
1053 
1054 public:
1055  explicit SimpleTypoCorrector(StringRef Typo)
1056  : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
1057  BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}
1058 
1059  void addDecl(const NamedDecl *ND);
1060 
1061  const NamedDecl *getBestDecl() const {
1062  if (BestEditDistance > MaxEditDistance)
1063  return nullptr;
1064 
1065  return BestDecl;
1066  }
1067 
1068  unsigned getBestDeclIndex() const {
1069  assert(getBestDecl());
1070  return BestIndex;
1071  }
1072 };
1073 
1074 void SimpleTypoCorrector::addDecl(const NamedDecl *ND) {
1075  unsigned CurrIndex = NextIndex++;
1076 
1077  const IdentifierInfo *II = ND->getIdentifier();
1078  if (!II)
1079  return;
1080 
1081  StringRef Name = II->getName();
1082  unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
1083  if (MinPossibleEditDistance > 0 &&
1084  Typo.size() / MinPossibleEditDistance < 3)
1085  return;
1086 
1087  unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
1088  if (EditDistance < BestEditDistance) {
1089  BestEditDistance = EditDistance;
1090  BestDecl = ND;
1091  BestIndex = CurrIndex;
1092  }
1093 }
1094 } // end anonymous namespace
1095 
1097  StringRef Typo,
1098  ArrayRef<const ParmVarDecl *> ParamVars) {
1099  SimpleTypoCorrector Corrector(Typo);
1100  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i)
1101  Corrector.addDecl(ParamVars[i]);
1102  if (Corrector.getBestDecl())
1103  return Corrector.getBestDeclIndex();
1104  else
1106 }
1107 
1108 namespace {
1109 bool ResolveTParamReferenceHelper(
1110  StringRef Name,
1111  const TemplateParameterList *TemplateParameters,
1112  SmallVectorImpl<unsigned> *Position) {
1113  for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
1114  const NamedDecl *Param = TemplateParameters->getParam(i);
1115  const IdentifierInfo *II = Param->getIdentifier();
1116  if (II && II->getName() == Name) {
1117  Position->push_back(i);
1118  return true;
1119  }
1120 
1121  if (const TemplateTemplateParmDecl *TTP =
1122  dyn_cast<TemplateTemplateParmDecl>(Param)) {
1123  Position->push_back(i);
1124  if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
1125  Position))
1126  return true;
1127  Position->pop_back();
1128  }
1129  }
1130  return false;
1131 }
1132 } // end anonymous namespace
1133 
1135  StringRef Name,
1136  const TemplateParameterList *TemplateParameters,
1137  SmallVectorImpl<unsigned> *Position) {
1138  Position->clear();
1139  if (!TemplateParameters)
1140  return false;
1141 
1142  return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
1143 }
1144 
1145 namespace {
1146 void CorrectTypoInTParamReferenceHelper(
1147  const TemplateParameterList *TemplateParameters,
1148  SimpleTypoCorrector &Corrector) {
1149  for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
1150  const NamedDecl *Param = TemplateParameters->getParam(i);
1151  Corrector.addDecl(Param);
1152 
1153  if (const TemplateTemplateParmDecl *TTP =
1154  dyn_cast<TemplateTemplateParmDecl>(Param))
1155  CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
1156  Corrector);
1157  }
1158 }
1159 } // end anonymous namespace
1160 
1162  StringRef Typo,
1163  const TemplateParameterList *TemplateParameters) {
1164  SimpleTypoCorrector Corrector(Typo);
1165  CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
1166  if (const NamedDecl *ND = Corrector.getBestDecl()) {
1167  const IdentifierInfo *II = ND->getIdentifier();
1168  assert(II && "SimpleTypoCorrector should not return this decl");
1169  return II->getName();
1170  }
1171  return StringRef();
1172 }
1173 
1175 Sema::getInlineCommandRenderKind(StringRef Name) const {
1176  assert(Traits.getCommandInfo(Name)->IsInlineCommand);
1177 
1178  return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
1180  .Cases("c", "p", InlineCommandComment::RenderMonospaced)
1181  .Cases("a", "e", "em", InlineCommandComment::RenderEmphasized)
1182  .Case("anchor", InlineCommandComment::RenderAnchor)
1184 }
1185 
1186 } // end namespace comments
1187 } // end namespace clang
clang::comments::ParamCommandComment::getDirectionAsString
static const char * getDirectionAsString(PassDirection D)
Definition: Comment.cpp:192
clang::comments::Sema::checkContainerDecl
void checkContainerDecl(const BlockCommandComment *Comment)
Definition: CommentSema.cpp:170
clang::comments::isClassOrStructDeclImpl
static bool isClassOrStructDeclImpl(const Decl *D)
Definition: CommentSema.cpp:939
clang::comments::CommandInfo::IsEmptyParagraphAllowed
unsigned IsEmptyParagraphAllowed
True if we don't want to warn about this command being passed an empty paragraph.
Definition: CommentCommandTraits.h:84
clang::TokenValue
Stores token information for comparing actual tokens with predefined values.
Definition: Preprocessor.h:91
clang::comments::Sema::actOnVerbatimLine
VerbatimLineComment * actOnVerbatimLine(SourceLocation LocBegin, unsigned CommandID, SourceLocation TextBegin, StringRef Text)
Definition: CommentSema.cpp:443
clang::comments::VerbatimLineComment
A verbatim line command.
Definition: Comment.h:943
clang::comments::Sema::isFunctionOrBlockPointerVarLikeDecl
bool isFunctionOrBlockPointerVarLikeDecl()
Definition: CommentSema.cpp:874
clang::comments::Sema::actOnParamCommandStart
ParamCommandComment * actOnParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:80
clang::comments::Sema::inspectThisDecl
void inspectThisDecl()
Extract all important semantic information from ThisDeclInfo->ThisDecl into ThisDeclInfo members.
Definition: CommentSema.cpp:1027
clang::comments::Sema::actOnTParamCommandFinish
void actOnTParamCommandFinish(TParamCommandComment *Command, ParagraphComment *Paragraph)
Definition: CommentSema.cpp:358
clang::Type::isBlockPointerType
bool isBlockPointerType() const
Definition: Type.h:6681
clang::comments::ParamCommandComment::Out
@ Out
Definition: Comment.h:739
clang::comments::InlineCommandComment::RenderEmphasized
@ RenderEmphasized
Definition: Comment.h:312
clang::comments::CommandInfo::IsRecordLikeDeclarationCommand
unsigned IsRecordLikeDeclarationCommand
True if block command is a container API; such as @interface.
Definition: CommentCommandTraits.h:118
clang::comments::ParamCommandComment::isDirectionExplicit
bool isDirectionExplicit() const LLVM_READONLY
Definition: Comment.h:749
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:212
clang::comments::ParamCommandComment::getParamNameRange
SourceRange getParamNameRange() const
Definition: Comment.h:768
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::DeclContext
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1347
clang::Decl::hasAttr
bool hasAttr() const
Definition: DeclBase.h:547
clang::Preprocessor::getLastMacroWithSpelling
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
Definition: Preprocessor.cpp:351
clang::comments::BlockCommandComment::setArgs
void setArgs(ArrayRef< Argument > A)
Definition: Comment.h:680
clang::FixItHint::CreateInsertion
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition: Diagnostic.h:96
clang::comments::DeclInfo::ParamVars
ArrayRef< const ParmVarDecl * > ParamVars
Parameters that can be referenced by \param if CommentDecl is something that we consider a "function"...
Definition: Comment.h:997
llvm::SmallVector
Definition: LLVM.h:38
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
clang::SourceLocation::getLocWithOffset
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
Definition: SourceLocation.h:136
clang::NamedDecl
This represents a decl that may have a name.
Definition: Decl.h:249
clang::SourceRange::getBegin
SourceLocation getBegin() const
Definition: SourceLocation.h:221
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:673
Attr.h
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:191
clang::comments::BlockCommandComment::getCommandID
unsigned getCommandID() const
Definition: Comment.h:650
clang::comments::Sema::getInlineCommandRenderKind
InlineCommandComment::RenderKind getInlineCommandRenderKind(StringRef Name) const
Definition: CommentSema.cpp:1175
clang::ParmVarDecl
Represents a parameter to a function.
Definition: Decl.h:1665
clang::comments::BlockCommandComment::getParagraph
ParagraphComment * getParagraph() const LLVM_READONLY
Definition: Comment.h:689
clang::comments::BlockCommandComment::getArgRange
SourceRange getArgRange(unsigned Idx) const
Definition: Comment.h:676
clang::comments::Sema::actOnParagraphComment
ParagraphComment * actOnParagraphComment(ArrayRef< InlineContentComment * > Content)
Definition: CommentSema.cpp:45
clang::comments::Sema::checkDeprecatedCommand
void checkDeprecatedCommand(const BlockCommandComment *Comment)
Definition: CommentSema.cpp:665
clang::comments::DeclInfo::IsFilled
unsigned IsFilled
If false, only CommentDecl is valid.
Definition: Comment.h:1058
clang::comments::Sema::isAnyFunctionDecl
bool isAnyFunctionDecl()
Definition: CommentSema.cpp:827
SourceManager.h
clang::Type::isVoidType
bool isVoidType() const
Definition: Type.h:6956
clang::comments::Sema::isObjCProtocolDecl
bool isObjCProtocolDecl()
Definition: CommentSema.cpp:1012
clang::comments::CommandInfo::IsDeprecatedCommand
unsigned IsDeprecatedCommand
True if this command is \deprecated or an alias.
Definition: CommentCommandTraits.h:77
clang::comments::HTMLEndTagComment
A closing HTML tag.
Definition: Comment.h:507
clang::comments::CommandInfo
Information about a single command.
Definition: CommentCommandTraits.h:32
clang::comments::InlineContentComment
Inline content (contained within a block).
Definition: Comment.h:236
clang::comments::ParamCommandComment::setParamIndex
void setParamIndex(unsigned Index)
Definition: Comment.h:791
clang::comments::InlineCommandComment::RenderMonospaced
@ RenderMonospaced
Definition: Comment.h:311
clang::comments::Sema::isClassOrStructOrTagTypedefDecl
bool isClassOrStructOrTagTypedefDecl()
Definition: CommentSema.cpp:958
clang::comments::Sema::isUnionDecl
bool isUnionDecl()
Definition: CommentSema.cpp:929
clang::comments::DeclInfo::CommentDecl
const Decl * CommentDecl
Declaration the comment is actually attached to (in the source).
Definition: Comment.h:983
clang::comments::Sema::actOnTParamCommandParamNameArg
void actOnTParamCommandParamNameArg(TParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
Definition: CommentSema.cpp:299
clang::comments::Sema::actOnFullComment
FullComment * actOnFullComment(ArrayRef< BlockContentComment * > Blocks)
Definition: CommentSema.cpp:544
clang::SourceManager
This class handles loading and caching of source files into memory.
Definition: SourceManager.h:626
clang::Type
The base class of the type hierarchy.
Definition: Type.h:1490
Preprocessor.h
clang::comments::ParamCommandComment::InvalidParamIndex
@ InvalidParamIndex
Definition: Comment.h:718
clang::comments::Sema::setDecl
void setDecl(const Decl *D)
Definition: CommentSema.cpp:36
clang::comments::CommandTraits::getCommandInfo
const CommandInfo * getCommandInfo(StringRef Name) const
Definition: CommentCommandTraits.h:145
clang::comments::InlineCommandComment
A command with word-like arguments that is considered inline content.
Definition: Comment.h:297
Decl.h
clang::TypedefType
Definition: Type.h:4371
clang::comments::DeclInfo::CurrentDecl
const Decl * CurrentDecl
CurrentDecl is the declaration with which the FullComment is associated.
Definition: Comment.h:993
clang::comments::TParamCommandComment::getParamNameRange
SourceRange getParamNameRange() const
Definition: Comment.h:838
clang::comments::InlineCommandComment::RenderBold
@ RenderBold
Definition: Comment.h:310
clang::comments::VerbatimBlockLineComment
A line of text contained in a verbatim block.
Definition: Comment.h:863
clang::comments::ParamCommandComment
Doxygen \param command.
Definition: Comment.h:711
clang::FunctionTemplateDecl
Declaration of a template function.
Definition: DeclTemplate.h:978
clang::comments::Comment
Any part of the comment.
Definition: Comment.h:52
clang::comments::Sema::actOnBlockCommandStart
BlockCommandComment * actOnBlockCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:50
clang::comments::Sema::isRecordLikeDecl
bool isRecordLikeDecl()
Definition: CommentSema.cpp:920
clang::comments::Sema::actOnInlineCommand
InlineCommandComment * actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, unsigned CommandID)
Definition: CommentSema.cpp:364
clang::TemplateParameterList::getParam
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:138
DeclTemplate.h
clang::Decl::getKind
Kind getKind() const
Definition: DeclBase.h:433
clang::comments::Sema::actOnParamCommandParamNameArg
void actOnParamCommandParamNameArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
Definition: CommentSema.cpp:257
clang::comments::ParamCommandComment::getParamNameAsWritten
StringRef getParamNameAsWritten() const
Definition: Comment.h:764
clang::comments::ParamCommandComment::setIsVarArgParam
void setIsVarArgParam()
Definition: Comment.h:780
clang::SourceRange::getEnd
SourceLocation getEnd() const
Definition: SourceLocation.h:222
clang::comments::Sema::actOnHTMLEndTag
HTMLEndTagComment * actOnHTMLEndTag(SourceLocation LocBegin, SourceLocation LocEnd, StringRef TagName)
Definition: CommentSema.cpp:476
clang::Type::isFunctionPointerType
bool isFunctionPointerType() const
Definition: Type.h:6707
clang::comments::HTMLTagComment::setIsMalformed
void setIsMalformed()
Definition: Comment.h:407
clang::comments::Sema::resolveParmVarReference
unsigned resolveParmVarReference(StringRef Name, ArrayRef< const ParmVarDecl * > ParamVars)
Returns index of a function parameter with a given name.
Definition: CommentSema.cpp:1031
clang::comments::Sema::resolveParamCommandIndexes
void resolveParamCommandIndexes(const FullComment *FC)
Resolve parameter names to parameter indexes in function declaration.
Definition: CommentSema.cpp:730
clang::comments::HTMLStartTagComment::setGreaterLoc
void setGreaterLoc(SourceLocation GreaterLoc)
Definition: Comment.h:493
clang::Type::getAs
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7162
clang::comments::ParamCommandComment::In
@ In
Definition: Comment.h:738
clang::comments::Sema::actOnParamCommandFinish
void actOnParamCommandFinish(ParamCommandComment *Command, ParagraphComment *Paragraph)
Definition: CommentSema.cpp:275
clang::comments::TParamCommandComment::setPosition
void setPosition(ArrayRef< unsigned > NewPosition)
Definition: Comment.h:856
clang::comments::BlockCommandComment::getNumArgs
unsigned getNumArgs() const
Definition: Comment.h:668
clang::comments::Sema::correctTypoInTParamReference
StringRef correctTypoInTParamReference(StringRef Typo, const TemplateParameterList *TemplateParameters)
Definition: CommentSema.cpp:1161
clang::comments::CommandInfo::IsRecordLikeDetailCommand
unsigned IsRecordLikeDetailCommand
True if block command is further describing a container API; such as @coclass, @classdesign,...
Definition: CommentCommandTraits.h:115
clang::comments::DeclInfo::getKind
DeclKind getKind() const LLVM_READONLY
Definition: Comment.h:1081
clang::comments::CommandInfo::IsBriefCommand
unsigned IsBriefCommand
True if this command is introducing a brief documentation paragraph (\or an alias).
Definition: CommentCommandTraits.h:60
clang::comments::getParamPassDirection
static int getParamPassDirection(StringRef Arg)
Turn a string into the corresponding PassDirection or -1 if it's not valid.
Definition: CommentSema.cpp:222
clang::comments::Sema::actOnVerbatimBlockFinish
void actOnVerbatimBlockFinish(VerbatimBlockComment *Block, SourceLocation CloseNameLocBegin, StringRef CloseName, ArrayRef< VerbatimBlockLineComment * > Lines)
Definition: CommentSema.cpp:434
clang::comments::CommandInfo::Name
const char * Name
Definition: CommentCommandTraits.h:37
clang::comments::FullComment
A full comment attached to a declaration, contains block content.
Definition: Comment.h:1091
clang::comments::Sema::isObjCInterfaceDecl
bool isObjCInterfaceDecl()
Definition: CommentSema.cpp:1003
CommentSema.h
llvm::SmallString
Definition: LLVM.h:37
clang::TemplateTemplateParmDecl
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
Definition: DeclTemplate.h:1601
clang::comments::CommandMarkerKind
CommandMarkerKind
Describes the syntax that was used in a documentation command.
Definition: Comment.h:36
clang::comments::Sema::isFunctionTemplateDecl
bool isFunctionTemplateDecl()
Definition: CommentSema.cpp:994
clang::VarDecl
Represents a variable declaration or definition.
Definition: Decl.h:876
clang::comments::DeclInfo::TemplateParameters
const TemplateParameterList * TemplateParameters
Template parameters that can be referenced by \tparam if CommentDecl is a template (IsTemplateDecl or...
Definition: Comment.h:1006
clang::comments::BlockCommandComment
A command that has zero or more word-like arguments (number of word-like arguments depends on command...
Definition: Comment.h:596
clang::Type::getPointeeType
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:625
clang::comments::DeclInfo::FunctionKind
@ FunctionKind
Something that we consider a "function":
Definition: Comment.h:1024
clang::TemplateParameterList
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:69
clang::comments::Sema::actOnHTMLStartTagFinish
void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag, ArrayRef< HTMLStartTagComment::Attribute > Attrs, SourceLocation GreaterLoc, bool IsSelfClosing)
Definition: CommentSema.cpp:463
clang::comments::DeclInfo::fill
void fill()
Definition: Comment.cpp:204
clang::comments::ParamCommandComment::InOut
@ InOut
Definition: Comment.h:740
clang::DeclContext::isRecord
bool isRecord() const
Definition: DeclBase.h:1939
clang::comments::CommandTraits::registerUnknownCommand
const CommandInfo * registerUnknownCommand(StringRef CommandName)
Definition: CommentCommandTraits.cpp:103
clang::BlockPointerType
Pointer to a block type.
Definition: Type.h:2720
clang::comments::Sema::actOnVerbatimBlockStart
VerbatimBlockComment * actOnVerbatimBlockStart(SourceLocation Loc, unsigned CommandID)
Definition: CommentSema.cpp:420
clang::comments::BlockCommandComment::Argument
Definition: Comment.h:598
clang::comments::DeclInfo::IsObjCMethod
unsigned IsObjCMethod
Is CommentDecl an ObjCMethodDecl.
Definition: Comment.h:1067
clang::comments::Sema::correctTypoInParmVarReference
unsigned correctTypoInParmVarReference(StringRef Typo, ArrayRef< const ParmVarDecl * > ParamVars)
Returns index of a function parameter with the name closest to a given typo.
Definition: CommentSema.cpp:1096
clang::comments::ParamCommandComment::setDirection
void setDirection(PassDirection Direction, bool Explicit)
Definition: Comment.h:753
clang::comments::HTMLStartTagComment
An opening HTML tag with attributes.
Definition: Comment.h:413
clang::comments::BlockCommandComment::getCommandName
StringRef getCommandName(const CommandTraits &Traits) const
Definition: Comment.h:654
clang::comments::ParamCommandComment::hasParamName
bool hasParamName() const
Definition: Comment.h:758
clang::comments::Sema::actOnParamCommandDirectionArg
void actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
Definition: CommentSema.cpp:230
clang::isWhitespace
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t',...
Definition: CharInfo.h:92
P
StringRef P
Definition: ASTMatchersInternal.cpp:563
clang::comments::FullComment::child_begin
child_iterator child_begin() const
Definition: Comment.h:1111
clang::comments::DeclInfo::VariableKind
@ VariableKind
Something that we consider a "variable":
Definition: Comment.h:1036
clang::NamedDecl::getIdentifier
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
clang::comments::Sema::getParamVars
ArrayRef< const ParmVarDecl * > getParamVars()
Definition: CommentSema.cpp:1021
clang::comments::DeclInfo
Information about the declaration, useful to clients of FullComment.
Definition: Comment.h:980
clang::FunctionProtoType
Represents a prototype with parameter type info, e.g.
Definition: Type.h:3885
clang::comments::Sema::isClassTemplateDecl
bool isClassTemplateDecl()
Definition: CommentSema.cpp:985
clang::comments::Sema::checkBlockCommandEmptyParagraph
void checkBlockCommandEmptyParagraph(BlockCommandComment *Command)
Definition: CommentSema.cpp:563
clang::QualType::isNull
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:738
clang::comments::TParamCommandComment
Doxygen \tparam command, describes a template parameter.
Definition: Comment.h:799
llvm::ArrayRef
Definition: LLVM.h:34
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:89
clang::comments::HTMLTagComment::isMalformed
bool isMalformed() const
Definition: Comment.h:403
clang::comments::Sema::isFunctionOrMethodVariadic
bool isFunctionOrMethodVariadic()
Definition: CommentSema.cpp:832
clang::comments::BlockCommandComment::setParagraph
void setParagraph(ParagraphComment *PC)
Definition: Comment.h:697
LLVM.h
clang::comments::Sema::actOnText
TextComment * actOnText(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Text)
Definition: CommentSema.cpp:414
clang::comments::CommandInfo::IsHeaderfileCommand
unsigned IsHeaderfileCommand
True if this is a \headerfile-like command.
Definition: CommentCommandTraits.h:80
clang::comments::BlockCommandComment::getCommandNameRange
SourceRange getCommandNameRange(const CommandTraits &Traits) const
Definition: Comment.h:662
clang::comments::Sema::isClassOrStructDecl
bool isClassOrStructDecl()
Definition: CommentSema.cpp:946
clang::TemplateParameterList::size
unsigned size() const
Definition: DeclTemplate.h:129
clang::IdentifierInfo
One of these records is kept for each identifier that is lexed.
Definition: IdentifierTable.h:84
clang::comments::BlockCommandComment::getCommandMarker
CommandMarkerKind getCommandMarker() const LLVM_READONLY
Definition: Comment.h:704
clang::comments::Sema::checkReturnsCommand
void checkReturnsCommand(const BlockCommandComment *Command)
Definition: CommentSema.cpp:581
clang::comments::Sema::isFunctionPointerVarDecl
bool isFunctionPointerVarDecl()
Definition: CommentSema.cpp:860
clang::comments::ParamCommandComment::PassDirection
PassDirection
Definition: Comment.h:737
clang::LangOptions
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:58
clang::comments::Sema::actOnHTMLStartTagStart
HTMLStartTagComment * actOnHTMLStartTagStart(SourceLocation LocBegin, StringRef TagName)
Definition: CommentSema.cpp:458
clang::comments::Sema::actOnBlockCommandArgs
void actOnBlockCommandArgs(BlockCommandComment *Command, ArrayRef< BlockCommandComment::Argument > Args)
Definition: CommentSema.cpp:62
clang::ObjCMethodDecl
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
clang::comments::CommandInfo::IsFunctionDeclarationCommand
unsigned IsFunctionDeclarationCommand
True if verbatim-like line command is a function declaration.
Definition: CommentCommandTraits.h:111
clang::PointerType
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2640
clang::comments::TextComment
Plain text.
Definition: Comment.h:261
clang::comments::Sema::checkContainerDeclVerbatimLine
void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment)
Definition: CommentSema.cpp:131
clang::IdentifierInfo::getName
StringRef getName() const
Return the actual identifier string.
Definition: IdentifierTable.h:195
clang::comments::InlineCommandComment::RenderKind
RenderKind
The most appropriate rendering mode for this command, chosen on command semantics in Doxygen.
Definition: Comment.h:308
clang
Definition: CalledOnceCheck.h:17
clang::comments::Sema::checkBlockCommandDuplicate
void checkBlockCommandDuplicate(const BlockCommandComment *Command)
Emit diagnostics about duplicate block commands that should be used only once per comment,...
Definition: CommentSema.cpp:627
Text
StringRef Text
Definition: Format.cpp:2334
clang::comments::Comment::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
Definition: Comment.h:214
clang::comments::HTMLTagComment::getTagName
StringRef getTagName() const LLVM_READONLY
Definition: Comment.h:395
clang::DeclaratorContext::Block
@ Block
clang::comments::VerbatimBlockComment
A verbatim block command (e.
Definition: Comment.h:891
clang::comments::Sema::isTemplateOrSpecialization
bool isTemplateOrSpecialization()
Definition: CommentSema.cpp:912
clang::comments::InlineCommandComment::Argument
Definition: Comment.h:299
clang::comments::Sema::resolveTParamReference
bool resolveTParamReference(StringRef Name, const TemplateParameterList *TemplateParameters, SmallVectorImpl< unsigned > *Position)
Definition: CommentSema.cpp:1134
clang::SourceLocation::isValid
bool isValid() const
Return true if this is a valid SourceLocation object.
Definition: SourceLocation.h:112
clang::comments::Comment::getLocation
SourceLocation getLocation() const LLVM_READONLY
Definition: Comment.h:220
clang::comments::DeclInfo::getTemplateKind
TemplateDeclKind getTemplateKind() const LLVM_READONLY
Definition: Comment.h:1085
clang::comments::Sema::isObjCMethodDecl
bool isObjCMethodDecl()
Definition: CommentSema.cpp:855
clang::TypedefNameDecl
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:3180
clang::comments::HTMLStartTagComment::setSelfClosing
void setSelfClosing()
Definition: Comment.h:501
clang::comments::DeclInfo::ReturnType
QualType ReturnType
Function return type if CommentDecl is something that we consider a "function".
Definition: Comment.h:1001
clang::comments::FullComment::child_end
child_iterator child_end() const
Definition: Comment.h:1115
clang::comments::InlineCommandComment::RenderNormal
@ RenderNormal
Definition: Comment.h:309
clang::comments::CommandInfo::IsReturnsCommand
unsigned IsReturnsCommand
True if this command is \returns or an alias.
Definition: CommentCommandTraits.h:63
clang::comments::Comment::child_iterator
Comment *const * child_iterator
Definition: Comment.h:222
llvm::SmallVectorImpl
Definition: LLVM.h:39
clang::comments::ParamCommandComment::VarArgParamIndex
@ VarArgParamIndex
Definition: Comment.h:719
clang::comments::CommandTraits
This class provides information about commands that can be used in comments.
Definition: CommentCommandTraits.h:127
clang::Preprocessor
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:130
clang::comments::Sema::actOnVerbatimBlockLine
VerbatimBlockLineComment * actOnVerbatimBlockLine(SourceLocation Loc, StringRef Text)
Definition: CommentSema.cpp:429
clang::comments::InlineCommandComment::RenderAnchor
@ RenderAnchor
Definition: Comment.h:313
clang::comments::Sema::actOnUnknownCommand
InlineContentComment * actOnUnknownCommand(SourceLocation LocBegin, SourceLocation LocEnd, StringRef CommandName)
Definition: CommentSema.cpp:397
CommentCommandTraits.h
CommentDiagnostic.h
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1856
clang::RecordDecl
Represents a struct/union/class.
Definition: Decl.h:3859
clang::comments::Sema::checkFunctionDeclVerbatimLine
void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment)
Definition: CommentSema.cpp:98
clang::comments::CommandInfo::getID
unsigned getID() const
Definition: CommentCommandTraits.h:33
clang::comments::CommandInfo::IsInlineCommand
unsigned IsInlineCommand
True if this command is a inline command (of any kind).
Definition: CommentCommandTraits.h:53
clang::comments::Sema::isObjCPropertyDecl
bool isObjCPropertyDecl()
Definition: CommentSema.cpp:904
clang::Preprocessor::getIdentifierInfo
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
Definition: Preprocessor.h:1243
clang::comments::Sema::copyArray
ArrayRef< T > copyArray(ArrayRef< T > Source)
Returns a copy of array, owned by Sema's allocator.
Definition: CommentSema.h:80
clang::FixItHint::CreateReplacement
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition: Diagnostic.h:133
clang::comments::Sema::actOnTParamCommandStart
TParamCommandComment * actOnTParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:281
clang::comments::Sema::actOnBlockCommandFinish
void actOnBlockCommandFinish(BlockCommandComment *Command, ParagraphComment *Paragraph)
Definition: CommentSema.cpp:67
clang::comments::Sema::isFunctionDecl
bool isFunctionDecl()
Definition: CommentSema.cpp:819
abs
__DEVICE__ long long abs(long long __n)
Definition: __clang_cuda_cmath.h:41
clang::comments::HTMLStartTagComment::setAttrs
void setAttrs(ArrayRef< Attribute > Attrs)
Definition: Comment.h:480
clang::SourceManager::getPresumedLineNumber
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
Definition: SourceManager.cpp:1456
clang::comments::ParagraphComment::isWhitespace
bool isWhitespace() const
Definition: Comment.h:580
clang::comments::ParagraphComment
A single paragraph that contains inline content.
Definition: Comment.h:546
clang::comments::DeclInfo::NotTemplate
@ NotTemplate
Definition: Comment.h:1051