clang  6.0.0svn
CommentSema.cpp
Go to the documentation of this file.
1 //===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "clang/AST/CommentSema.h"
11 #include "clang/AST/Attr.h"
14 #include "clang/AST/Decl.h"
15 #include "clang/AST/DeclTemplate.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 = (!isClassOrStructDecl() && !isClassTemplateDecl()) ? 1 : 0;
139  // Allow @class command on @interface declarations.
140  // FIXME. Currently, \class and @class are indistinguishable. So,
141  // \class is also allowed on an @interface declaration
142  if (DiagSelect && Comment->getCommandMarker() && isObjCInterfaceDecl())
143  DiagSelect = 0;
144  break;
145  case CommandTraits::KCI_interface:
146  DiagSelect = !isObjCInterfaceDecl() ? 2 : 0;
147  break;
148  case CommandTraits::KCI_protocol:
149  DiagSelect = !isObjCProtocolDecl() ? 3 : 0;
150  break;
151  case CommandTraits::KCI_struct:
152  DiagSelect = !isClassOrStructDecl() ? 4 : 0;
153  break;
154  case CommandTraits::KCI_union:
155  DiagSelect = !isUnionDecl() ? 5 : 0;
156  break;
157  default:
158  DiagSelect = 0;
159  break;
160  }
161  if (DiagSelect)
162  Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch)
163  << Comment->getCommandMarker()
164  << (DiagSelect-1) << (DiagSelect-1)
165  << Comment->getSourceRange();
166 }
167 
169  const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
171  return;
172  unsigned DiagSelect;
173  switch (Comment->getCommandID()) {
174  case CommandTraits::KCI_classdesign:
175  DiagSelect = 1;
176  break;
177  case CommandTraits::KCI_coclass:
178  DiagSelect = 2;
179  break;
180  case CommandTraits::KCI_dependency:
181  DiagSelect = 3;
182  break;
183  case CommandTraits::KCI_helper:
184  DiagSelect = 4;
185  break;
186  case CommandTraits::KCI_helperclass:
187  DiagSelect = 5;
188  break;
189  case CommandTraits::KCI_helps:
190  DiagSelect = 6;
191  break;
192  case CommandTraits::KCI_instancesize:
193  DiagSelect = 7;
194  break;
195  case CommandTraits::KCI_ownership:
196  DiagSelect = 8;
197  break;
198  case CommandTraits::KCI_performance:
199  DiagSelect = 9;
200  break;
201  case CommandTraits::KCI_security:
202  DiagSelect = 10;
203  break;
204  case CommandTraits::KCI_superclass:
205  DiagSelect = 11;
206  break;
207  default:
208  DiagSelect = 0;
209  break;
210  }
211  if (DiagSelect)
212  Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch)
213  << Comment->getCommandMarker()
214  << (DiagSelect-1)
215  << Comment->getSourceRange();
216 }
217 
218 /// \brief Turn a string into the corresponding PassDirection or -1 if it's not
219 /// valid.
220 static int getParamPassDirection(StringRef Arg) {
221  return llvm::StringSwitch<int>(Arg)
222  .Case("[in]", ParamCommandComment::In)
223  .Case("[out]", ParamCommandComment::Out)
224  .Cases("[in,out]", "[out,in]", ParamCommandComment::InOut)
225  .Default(-1);
226 }
227 
229  SourceLocation ArgLocBegin,
230  SourceLocation ArgLocEnd,
231  StringRef Arg) {
232  std::string ArgLower = Arg.lower();
233  int Direction = getParamPassDirection(ArgLower);
234 
235  if (Direction == -1) {
236  // Try again with whitespace removed.
237  ArgLower.erase(
238  std::remove_if(ArgLower.begin(), ArgLower.end(), clang::isWhitespace),
239  ArgLower.end());
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  if (ThisDeclInfo->ReturnType->isVoidType()) {
593  unsigned DiagKind;
594  switch (ThisDeclInfo->CommentDecl->getKind()) {
595  default:
596  if (ThisDeclInfo->IsObjCMethod)
597  DiagKind = 3;
598  else
599  DiagKind = 0;
600  break;
601  case Decl::CXXConstructor:
602  DiagKind = 1;
603  break;
604  case Decl::CXXDestructor:
605  DiagKind = 2;
606  break;
607  }
608  Diag(Command->getLocation(),
609  diag::warn_doc_returns_attached_to_a_void_function)
610  << Command->getCommandMarker()
611  << Command->getCommandName(Traits)
612  << DiagKind
613  << Command->getSourceRange();
614  }
615  return;
616  }
617 
618  Diag(Command->getLocation(),
619  diag::warn_doc_returns_not_attached_to_a_function_decl)
620  << Command->getCommandMarker()
621  << Command->getCommandName(Traits)
622  << Command->getSourceRange();
623 }
624 
626  const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
627  const BlockCommandComment *PrevCommand = nullptr;
628  if (Info->IsBriefCommand) {
629  if (!BriefCommand) {
630  BriefCommand = Command;
631  return;
632  }
633  PrevCommand = BriefCommand;
634  } else if (Info->IsHeaderfileCommand) {
635  if (!HeaderfileCommand) {
636  HeaderfileCommand = Command;
637  return;
638  }
639  PrevCommand = HeaderfileCommand;
640  } else {
641  // We don't want to check this command for duplicates.
642  return;
643  }
644  StringRef CommandName = Command->getCommandName(Traits);
645  StringRef PrevCommandName = PrevCommand->getCommandName(Traits);
646  Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
647  << Command->getCommandMarker()
648  << CommandName
649  << Command->getSourceRange();
650  if (CommandName == PrevCommandName)
651  Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
652  << PrevCommand->getCommandMarker()
653  << PrevCommandName
654  << PrevCommand->getSourceRange();
655  else
656  Diag(PrevCommand->getLocation(),
657  diag::note_doc_block_command_previous_alias)
658  << PrevCommand->getCommandMarker()
659  << PrevCommandName
660  << CommandName;
661 }
662 
664  if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand)
665  return;
666 
667  assert(ThisDeclInfo && "should not call this check on a bare comment");
668 
669  const Decl *D = ThisDeclInfo->CommentDecl;
670  if (!D)
671  return;
672 
673  if (D->hasAttr<DeprecatedAttr>() ||
674  D->hasAttr<AvailabilityAttr>() ||
675  D->hasAttr<UnavailableAttr>())
676  return;
677 
678  Diag(Command->getLocation(),
679  diag::warn_doc_deprecated_not_sync)
680  << Command->getSourceRange();
681 
682  // Try to emit a fixit with a deprecation attribute.
683  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
684  // Don't emit a Fix-It for non-member function definitions. GCC does not
685  // accept attributes on them.
686  const DeclContext *Ctx = FD->getDeclContext();
687  if ((!Ctx || !Ctx->isRecord()) &&
688  FD->doesThisDeclarationHaveABody())
689  return;
690 
691  StringRef AttributeSpelling = "__attribute__((deprecated))";
692  if (PP) {
693  TokenValue Tokens[] = {
694  tok::kw___attribute, tok::l_paren, tok::l_paren,
695  PP->getIdentifierInfo("deprecated"),
696  tok::r_paren, tok::r_paren
697  };
698  StringRef MacroName = PP->getLastMacroWithSpelling(FD->getLocation(),
699  Tokens);
700  if (!MacroName.empty())
701  AttributeSpelling = MacroName;
702  }
703 
704  SmallString<64> TextToInsert(" ");
705  TextToInsert += AttributeSpelling;
706  Diag(FD->getLocEnd(),
707  diag::note_add_deprecation_attr)
708  << FixItHint::CreateInsertion(FD->getLocEnd().getLocWithOffset(1),
709  TextToInsert);
710  }
711 }
712 
714  if (!isFunctionDecl()) {
715  // We already warned that \\param commands are not attached to a function
716  // decl.
717  return;
718  }
719 
720  SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;
721 
722  // Comment AST nodes that correspond to \c ParamVars for which we have
723  // found a \\param command or NULL if no documentation was found so far.
725 
727  ParamVarDocs.resize(ParamVars.size(), nullptr);
728 
729  // First pass over all \\param commands: resolve all parameter names.
730  for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
731  I != E; ++I) {
732  ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
733  if (!PCC || !PCC->hasParamName())
734  continue;
735  StringRef ParamName = PCC->getParamNameAsWritten();
736 
737  // Check that referenced parameter name is in the function decl.
738  const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,
739  ParamVars);
740  if (ResolvedParamIndex == ParamCommandComment::VarArgParamIndex) {
741  PCC->setIsVarArgParam();
742  continue;
743  }
744  if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) {
745  UnresolvedParamCommands.push_back(PCC);
746  continue;
747  }
748  PCC->setParamIndex(ResolvedParamIndex);
749  if (ParamVarDocs[ResolvedParamIndex]) {
750  SourceRange ArgRange = PCC->getParamNameRange();
751  Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)
752  << ParamName << ArgRange;
753  ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
754  Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
755  << PrevCommand->getParamNameRange();
756  }
757  ParamVarDocs[ResolvedParamIndex] = PCC;
758  }
759 
760  // Find parameter declarations that have no corresponding \\param.
761  SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;
762  for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
763  if (!ParamVarDocs[i])
764  OrphanedParamDecls.push_back(ParamVars[i]);
765  }
766 
767  // Second pass over unresolved \\param commands: do typo correction.
768  // Suggest corrections from a set of parameter declarations that have no
769  // corresponding \\param.
770  for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
771  const ParamCommandComment *PCC = UnresolvedParamCommands[i];
772 
773  SourceRange ArgRange = PCC->getParamNameRange();
774  StringRef ParamName = PCC->getParamNameAsWritten();
775  Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)
776  << ParamName << ArgRange;
777 
778  // All parameters documented -- can't suggest a correction.
779  if (OrphanedParamDecls.size() == 0)
780  continue;
781 
782  unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
783  if (OrphanedParamDecls.size() == 1) {
784  // If one parameter is not documented then that parameter is the only
785  // possible suggestion.
786  CorrectedParamIndex = 0;
787  } else {
788  // Do typo correction.
789  CorrectedParamIndex = correctTypoInParmVarReference(ParamName,
790  OrphanedParamDecls);
791  }
792  if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
793  const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
794  if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
795  Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)
796  << CorrectedII->getName()
797  << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
798  }
799  }
800 }
801 
803  if (!ThisDeclInfo)
804  return false;
805  if (!ThisDeclInfo->IsFilled)
806  inspectThisDecl();
807  return ThisDeclInfo->getKind() == DeclInfo::FunctionKind;
808 }
809 
811  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
812  isa<FunctionDecl>(ThisDeclInfo->CurrentDecl);
813 }
814 
816  if (!isFunctionDecl() || !ThisDeclInfo->CurrentDecl)
817  return false;
818  if (const FunctionDecl *FD =
819  dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl))
820  return FD->isVariadic();
821  if (const FunctionTemplateDecl *FTD =
822  dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl))
823  return FTD->getTemplatedDecl()->isVariadic();
824  if (const ObjCMethodDecl *MD =
825  dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl))
826  return MD->isVariadic();
827  if (const TypedefNameDecl *TD =
828  dyn_cast<TypedefNameDecl>(ThisDeclInfo->CurrentDecl)) {
829  QualType Type = TD->getUnderlyingType();
830  if (Type->isFunctionPointerType() || Type->isBlockPointerType())
831  Type = Type->getPointeeType();
832  if (const auto *FT = Type->getAs<FunctionProtoType>())
833  return FT->isVariadic();
834  }
835  return false;
836 }
837 
839  return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
840  isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl);
841 }
842 
844  if (!ThisDeclInfo)
845  return false;
846  if (!ThisDeclInfo->IsFilled)
847  inspectThisDecl();
848  if (ThisDeclInfo->getKind() == DeclInfo::VariableKind) {
849  if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDeclInfo->CurrentDecl)) {
850  QualType QT = VD->getType();
851  return QT->isFunctionPointerType();
852  }
853  }
854  return false;
855 }
856 
858  if (!ThisDeclInfo)
859  return false;
860  if (!ThisDeclInfo->IsFilled)
861  inspectThisDecl();
862  if (ThisDeclInfo->getKind() != DeclInfo::VariableKind ||
863  !ThisDeclInfo->CurrentDecl)
864  return false;
865  QualType QT;
866  if (const auto *VD = dyn_cast<DeclaratorDecl>(ThisDeclInfo->CurrentDecl))
867  QT = VD->getType();
868  else if (const auto *PD =
869  dyn_cast<ObjCPropertyDecl>(ThisDeclInfo->CurrentDecl))
870  QT = PD->getType();
871  else
872  return false;
873  // We would like to warn about the 'returns'/'param' commands for
874  // variables that don't directly specify the function type, so type aliases
875  // can be ignored.
876  if (QT->getAs<TypedefType>())
877  return false;
878  return QT->isFunctionPointerType() || QT->isBlockPointerType();
879 }
880 
882  if (!ThisDeclInfo)
883  return false;
884  if (!ThisDeclInfo->IsFilled)
885  inspectThisDecl();
886  return ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty;
887 }
888 
890  if (!ThisDeclInfo)
891  return false;
892  if (!ThisDeclInfo->IsFilled)
893  inspectThisDecl();
894  return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate;
895 }
896 
898  if (!ThisDeclInfo)
899  return false;
900  if (!ThisDeclInfo->IsFilled)
901  inspectThisDecl();
904 }
905 
907  if (!ThisDeclInfo)
908  return false;
909  if (!ThisDeclInfo->IsFilled)
910  inspectThisDecl();
911  if (const RecordDecl *RD =
912  dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl))
913  return RD->isUnion();
914  return false;
915 }
916 
918  if (!ThisDeclInfo)
919  return false;
920  if (!ThisDeclInfo->IsFilled)
921  inspectThisDecl();
922  return ThisDeclInfo->CurrentDecl &&
923  isa<RecordDecl>(ThisDeclInfo->CurrentDecl) &&
924  !isUnionDecl();
925 }
926 
928  if (!ThisDeclInfo)
929  return false;
930  if (!ThisDeclInfo->IsFilled)
931  inspectThisDecl();
932  return ThisDeclInfo->CurrentDecl &&
933  (isa<ClassTemplateDecl>(ThisDeclInfo->CurrentDecl));
934 }
935 
937  if (!ThisDeclInfo)
938  return false;
939  if (!ThisDeclInfo->IsFilled)
940  inspectThisDecl();
941  return ThisDeclInfo->CurrentDecl &&
942  (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl));
943 }
944 
946  if (!ThisDeclInfo)
947  return false;
948  if (!ThisDeclInfo->IsFilled)
949  inspectThisDecl();
950  return ThisDeclInfo->CurrentDecl &&
951  isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl);
952 }
953 
955  if (!ThisDeclInfo)
956  return false;
957  if (!ThisDeclInfo->IsFilled)
958  inspectThisDecl();
959  return ThisDeclInfo->CurrentDecl &&
960  isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl);
961 }
962 
964  if (!ThisDeclInfo->IsFilled)
965  inspectThisDecl();
966  return ThisDeclInfo->ParamVars;
967 }
968 
970  ThisDeclInfo->fill();
971 }
972 
973 unsigned Sema::resolveParmVarReference(StringRef Name,
974  ArrayRef<const ParmVarDecl *> ParamVars) {
975  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
976  const IdentifierInfo *II = ParamVars[i]->getIdentifier();
977  if (II && II->getName() == Name)
978  return i;
979  }
980  if (Name == "..." && isFunctionOrMethodVariadic())
983 }
984 
985 namespace {
986 class SimpleTypoCorrector {
987  const NamedDecl *BestDecl;
988 
989  StringRef Typo;
990  const unsigned MaxEditDistance;
991 
992  unsigned BestEditDistance;
993  unsigned BestIndex;
994  unsigned NextIndex;
995 
996 public:
997  explicit SimpleTypoCorrector(StringRef Typo)
998  : BestDecl(nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
999  BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}
1000 
1001  void addDecl(const NamedDecl *ND);
1002 
1003  const NamedDecl *getBestDecl() const {
1004  if (BestEditDistance > MaxEditDistance)
1005  return nullptr;
1006 
1007  return BestDecl;
1008  }
1009 
1010  unsigned getBestDeclIndex() const {
1011  assert(getBestDecl());
1012  return BestIndex;
1013  }
1014 };
1015 
1016 void SimpleTypoCorrector::addDecl(const NamedDecl *ND) {
1017  unsigned CurrIndex = NextIndex++;
1018 
1019  const IdentifierInfo *II = ND->getIdentifier();
1020  if (!II)
1021  return;
1022 
1023  StringRef Name = II->getName();
1024  unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
1025  if (MinPossibleEditDistance > 0 &&
1026  Typo.size() / MinPossibleEditDistance < 3)
1027  return;
1028 
1029  unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
1030  if (EditDistance < BestEditDistance) {
1031  BestEditDistance = EditDistance;
1032  BestDecl = ND;
1033  BestIndex = CurrIndex;
1034  }
1035 }
1036 } // end anonymous namespace
1037 
1039  StringRef Typo,
1040  ArrayRef<const ParmVarDecl *> ParamVars) {
1041  SimpleTypoCorrector Corrector(Typo);
1042  for (unsigned i = 0, e = ParamVars.size(); i != e; ++i)
1043  Corrector.addDecl(ParamVars[i]);
1044  if (Corrector.getBestDecl())
1045  return Corrector.getBestDeclIndex();
1046  else
1048 }
1049 
1050 namespace {
1051 bool ResolveTParamReferenceHelper(
1052  StringRef Name,
1053  const TemplateParameterList *TemplateParameters,
1054  SmallVectorImpl<unsigned> *Position) {
1055  for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
1056  const NamedDecl *Param = TemplateParameters->getParam(i);
1057  const IdentifierInfo *II = Param->getIdentifier();
1058  if (II && II->getName() == Name) {
1059  Position->push_back(i);
1060  return true;
1061  }
1062 
1063  if (const TemplateTemplateParmDecl *TTP =
1064  dyn_cast<TemplateTemplateParmDecl>(Param)) {
1065  Position->push_back(i);
1066  if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
1067  Position))
1068  return true;
1069  Position->pop_back();
1070  }
1071  }
1072  return false;
1073 }
1074 } // end anonymous namespace
1075 
1077  StringRef Name,
1078  const TemplateParameterList *TemplateParameters,
1079  SmallVectorImpl<unsigned> *Position) {
1080  Position->clear();
1081  if (!TemplateParameters)
1082  return false;
1083 
1084  return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
1085 }
1086 
1087 namespace {
1088 void CorrectTypoInTParamReferenceHelper(
1089  const TemplateParameterList *TemplateParameters,
1090  SimpleTypoCorrector &Corrector) {
1091  for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
1092  const NamedDecl *Param = TemplateParameters->getParam(i);
1093  Corrector.addDecl(Param);
1094 
1095  if (const TemplateTemplateParmDecl *TTP =
1096  dyn_cast<TemplateTemplateParmDecl>(Param))
1097  CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
1098  Corrector);
1099  }
1100 }
1101 } // end anonymous namespace
1102 
1104  StringRef Typo,
1105  const TemplateParameterList *TemplateParameters) {
1106  SimpleTypoCorrector Corrector(Typo);
1107  CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
1108  if (const NamedDecl *ND = Corrector.getBestDecl()) {
1109  const IdentifierInfo *II = ND->getIdentifier();
1110  assert(II && "SimpleTypoCorrector should not return this decl");
1111  return II->getName();
1112  }
1113  return StringRef();
1114 }
1115 
1117 Sema::getInlineCommandRenderKind(StringRef Name) const {
1118  assert(Traits.getCommandInfo(Name)->IsInlineCommand);
1119 
1120  return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
1122  .Cases("c", "p", InlineCommandComment::RenderMonospaced)
1123  .Cases("a", "e", "em", InlineCommandComment::RenderEmphasized)
1125 }
1126 
1127 } // end namespace comments
1128 } // end namespace clang
void actOnParamCommandFinish(ParamCommandComment *Command, ParagraphComment *Paragraph)
void setDirection(PassDirection Direction, bool Explicit)
Definition: Comment.h:759
StringRef correctTypoInTParamReference(StringRef Typo, const TemplateParameterList *TemplateParameters)
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
Definition: Decl.h:1698
unsigned IsRecordLikeDeclarationCommand
True if block command is a container API; such as @interface.
const Decl * CommentDecl
Declaration the comment is actually attached to (in the source).
Definition: Comment.h:989
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
A (possibly-)qualified type.
Definition: Type.h:653
bool isBlockPointerType() const
Definition: Type.h:5952
ArrayRef< const ParmVarDecl * > getParamVars()
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
void setLines(ArrayRef< VerbatimBlockLineComment *> L)
Definition: Comment.h:929
void checkBlockCommandEmptyParagraph(BlockCommandComment *Command)
void actOnHTMLStartTagFinish(HTMLStartTagComment *Tag, ArrayRef< HTMLStartTagComment::Attribute > Attrs, SourceLocation GreaterLoc, bool IsSelfClosing)
unsigned IsObjCMethod
Is CommentDecl an ObjCMethodDecl.
Definition: Comment.h:1073
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Definition: Type.cpp:456
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
__DEVICE__ long long abs(long long __n)
Defines the C++ template declaration subclasses.
SourceLocation getLocation() const LLVM_READONLY
Definition: Comment.h:226
ParagraphComment * actOnParagraphComment(ArrayRef< InlineContentComment *> Content)
Definition: CommentSema.cpp:45
The base class of the type hierarchy.
Definition: Type.h:1353
VerbatimBlockComment * actOnVerbatimBlockStart(SourceLocation Loc, unsigned CommandID)
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:133
unsigned correctTypoInParmVarReference(StringRef Typo, ArrayRef< const ParmVarDecl *> ParamVars)
Returns index of a function parameter with the name closest to a given typo.
HTMLStartTagComment * actOnHTMLStartTagStart(SourceLocation LocBegin, StringRef TagName)
VarDecl - An instance of this class is created to represent a variable declaration or definition...
Definition: Decl.h:807
void actOnBlockCommandArgs(BlockCommandComment *Command, ArrayRef< BlockCommandComment::Argument > Args)
Definition: CommentSema.cpp:62
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6307
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
void checkContainerDeclVerbatimLine(const BlockCommandComment *Comment)
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:68
Something that we consider a "variable":
Definition: Comment.h:1042
Something that we consider a "function":
Definition: Comment.h:1030
ParmVarDecl - Represents a parameter to a function.
Definition: Decl.h:1514
void checkBlockCommandDuplicate(const BlockCommandComment *Command)
Emit diagnostics about duplicate block commands that should be used only once per comment...
Information about a single command.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
Definition: Decl.h:265
ParagraphComment * getParagraph() const LLVM_READONLY
Definition: Comment.h:695
RecordDecl - Represents a struct/union/class.
Definition: Decl.h:3482
StringRef getCommandName(const CommandTraits &Traits) const
Definition: Comment.h:660
One of these records is kept for each identifier that is lexed.
child_iterator child_end() const
Definition: Comment.h:1121
void actOnVerbatimBlockFinish(VerbatimBlockComment *Block, SourceLocation CloseNameLocBegin, StringRef CloseName, ArrayRef< VerbatimBlockLineComment *> Lines)
const Decl * CurrentDecl
CurrentDecl is the declaration with which the FullComment is associated.
Definition: Comment.h:999
unsigned IsFilled
If false, only CommentDecl is valid.
Definition: Comment.h:1064
SourceRange getParamNameRange() const
Definition: Comment.h:844
TextComment * actOnText(SourceLocation LocBegin, SourceLocation LocEnd, StringRef Text)
A command with word-like arguments that is considered inline content.
Definition: Comment.h:303
A line of text contained in a verbatim block.
Definition: Comment.h:869
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: &#39; &#39;, &#39;\t&#39;, &#39;\f&#39;, &#39;\v&#39;, &#39;\n&#39;, &#39;\r&#39;.
Definition: CharInfo.h:88
A verbatim line command.
Definition: Comment.h:949
void checkReturnsCommand(const BlockCommandComment *Command)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:147
InlineContentComment * actOnUnknownCommand(SourceLocation LocBegin, SourceLocation LocEnd, StringRef CommandName)
FullComment * actOnFullComment(ArrayRef< BlockContentComment *> Blocks)
Any part of the comment.
Definition: Comment.h:53
Inline content (contained within a block).
Definition: Comment.h:242
RenderKind
The most appropriate rendering mode for this command, chosen on command semantics in Doxygen...
Definition: Comment.h:314
ArrayRef< T > copyArray(ArrayRef< T > Source)
Returns a copy of array, owned by Sema&#39;s allocator.
Definition: CommentSema.h:81
A verbatim block command (e.
Definition: Comment.h:897
bool hasAttr() const
Definition: DeclBase.h:535
bool resolveTParamReference(StringRef Name, const TemplateParameterList *TemplateParameters, SmallVectorImpl< unsigned > *Position)
Represents a prototype with parameter type info, e.g.
Definition: Type.h:3270
void setAttrs(ArrayRef< Attribute > Attrs)
Definition: Comment.h:486
void inspectThisDecl()
Extract all important semantic information from ThisDeclInfo->ThisDecl into ThisDeclInfo members...
void actOnTParamCommandFinish(TParamCommandComment *Command, ParagraphComment *Paragraph)
void setPosition(ArrayRef< unsigned > NewPosition)
Definition: Comment.h:862
unsigned IsBriefCommand
True if this command is introducing a brief documentation paragraph (\brief or an alias)...
QualType ReturnType
Function return type if CommentDecl is something that we consider a "function".
Definition: Comment.h:1007
child_iterator child_begin() const
Definition: Comment.h:1117
Defines the clang::Preprocessor interface.
CommandMarkerKind
Describes the syntax that was used in a documentation command.
Definition: Comment.h:37
A command that has zero or more word-like arguments (number of word-like arguments depends on command...
Definition: Comment.h:602
Stores token information for comparing actual tokens with predefined values.
Definition: Preprocessor.h:88
CommandMarkerKind getCommandMarker() const LLVM_READONLY
Definition: Comment.h:710
VerbatimBlockLineComment * actOnVerbatimBlockLine(SourceLocation Loc, StringRef Text)
const TemplateParameterList * TemplateParameters
Template parameters that can be referenced by \tparam if CommentDecl is a template (IsTemplateDecl or...
Definition: Comment.h:1012
bool isDirectionExplicit() const LLVM_READONLY
Definition: Comment.h:755
SourceRange getParamNameRange() const
Definition: Comment.h:774
unsigned resolveParmVarReference(StringRef Name, ArrayRef< const ParmVarDecl *> ParamVars)
Returns index of a function parameter with a given name.
SourceLocation getEnd() const
An opening HTML tag with attributes.
Definition: Comment.h:419
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
void checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment)
Definition: CommentSema.cpp:98
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
static const char * getDirectionAsString(PassDirection D)
Definition: Comment.cpp:178
TParamCommandComment * actOnTParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
void actOnBlockCommandFinish(BlockCommandComment *Command, ParagraphComment *Paragraph)
Definition: CommentSema.cpp:67
This class provides information about commands that can be used in comments.
InlineCommandComment::RenderKind getInlineCommandRenderKind(StringRef Name) const
unsigned IsRecordLikeDetailCommand
True if block command is further describing a container API; such as @coclass, @classdesign, etc.
void setCloseName(StringRef Name, SourceLocation LocBegin)
Definition: Comment.h:924
void checkDeprecatedCommand(const BlockCommandComment *Comment)
void checkContainerDecl(const BlockCommandComment *Comment)
Encodes a location in the source.
VerbatimLineComment * actOnVerbatimLine(SourceLocation LocBegin, unsigned CommandID, SourceLocation TextBegin, StringRef Text)
bool isFunctionOrBlockPointerVarLikeDecl()
SourceRange getSourceRange() const LLVM_READONLY
Definition: Comment.h:216
ParamCommandComment * actOnParamCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:80
const CommandInfo * getCommandInfo(StringRef Name) const
TemplateDeclKind getTemplateKind() const LLVM_READONLY
Definition: Comment.h:1091
static int getParamPassDirection(StringRef Arg)
Turn a string into the corresponding PassDirection or -1 if it&#39;s not valid.
Comment *const * child_iterator
Definition: Comment.h:228
SourceRange getCommandNameRange(const CommandTraits &Traits) const
Definition: Comment.h:668
A closing HTML tag.
Definition: Comment.h:513
Doxygen \tparam command, describes a template parameter.
Definition: Comment.h:805
StringRef getName() const
Return the actual identifier string.
Base class for declarations which introduce a typedef-name.
Definition: Decl.h:2796
unsigned IsFunctionDeclarationCommand
True if verbatim-like line command is a function declaration.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1252
BlockCommandComment * actOnBlockCommandStart(SourceLocation LocBegin, SourceLocation LocEnd, unsigned CommandID, CommandMarkerKind CommandMarker)
Definition: CommentSema.cpp:50
unsigned IsHeaderfileCommand
True if this is a \headerfile-like command.
bool isRecord() const
Definition: DeclBase.h:1405
Kind getKind() const
Definition: DeclBase.h:419
Information about the declaration, useful to clients of FullComment.
Definition: Comment.h:986
A single paragraph that contains inline content.
Definition: Comment.h:552
DeclKind getKind() const LLVM_READONLY
Definition: Comment.h:1087
HTMLEndTagComment * actOnHTMLEndTag(SourceLocation LocBegin, SourceLocation LocEnd, StringRef TagName)
StringRef getTagName() const LLVM_READONLY
Definition: Comment.h:401
void setParamIndex(unsigned Index)
Definition: Comment.h:797
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:90
void setParagraph(ParagraphComment *PC)
Definition: Comment.h:703
void actOnTParamCommandParamNameArg(TParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
const CommandInfo * registerUnknownCommand(StringRef CommandName)
void setDecl(const Decl *D)
Definition: CommentSema.cpp:36
bool isVoidType() const
Definition: Type.h:6171
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:127
StringRef getParamNameAsWritten() const
Definition: Comment.h:770
InlineCommandComment * actOnInlineCommand(SourceLocation CommandLocBegin, SourceLocation CommandLocEnd, unsigned CommandID)
void setArgs(ArrayRef< Argument > A)
Definition: Comment.h:686
Doxygen \param command.
Definition: Comment.h:717
StringRef Text
Definition: Format.cpp:1346
ArrayRef< const ParmVarDecl * > ParamVars
Parameters that can be referenced by \param if CommentDecl is something that we consider a "function"...
Definition: Comment.h:1003
A trivial tuple used to represent a source range.
NamedDecl - This represents a decl with a name.
Definition: Decl.h:245
void setGreaterLoc(SourceLocation GreaterLoc)
Definition: Comment.h:499
void actOnParamCommandParamNameArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
SourceRange getArgRange(unsigned Idx) const
Definition: Comment.h:682
bool isFunctionPointerType() const
Definition: Type.h:5968
SourceLocation getBegin() const
void resolveParamCommandIndexes(const FullComment *FC)
Resolve parameter names to parameter indexes in function declaration.
This class handles loading and caching of source files into memory.
Declaration of a template function.
Definition: DeclTemplate.h:967
void actOnParamCommandDirectionArg(ParamCommandComment *Command, SourceLocation ArgLocBegin, SourceLocation ArgLocEnd, StringRef Arg)
A full comment attached to a declaration, contains block content.
Definition: Comment.h:1097
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:127