clang API Documentation

CommentSema.cpp
Go to the documentation of this file.
00001 //===--- CommentSema.cpp - Doxygen comment semantic analysis --------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "clang/AST/CommentSema.h"
00011 #include "clang/AST/Attr.h"
00012 #include "clang/AST/CommentCommandTraits.h"
00013 #include "clang/AST/CommentDiagnostic.h"
00014 #include "clang/AST/Decl.h"
00015 #include "clang/AST/DeclTemplate.h"
00016 #include "clang/Basic/SourceManager.h"
00017 #include "clang/Lex/Preprocessor.h"
00018 #include "llvm/ADT/SmallString.h"
00019 #include "llvm/ADT/StringSwitch.h"
00020 
00021 namespace clang {
00022 namespace comments {
00023 
00024 namespace {
00025 #include "clang/AST/CommentHTMLTagsProperties.inc"
00026 } // unnamed namespace
00027 
00028 Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr,
00029            DiagnosticsEngine &Diags, CommandTraits &Traits,
00030            const Preprocessor *PP) :
00031     Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
00032     PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr),
00033     HeaderfileCommand(nullptr) {
00034 }
00035 
00036 void Sema::setDecl(const Decl *D) {
00037   if (!D)
00038     return;
00039 
00040   ThisDeclInfo = new (Allocator) DeclInfo;
00041   ThisDeclInfo->CommentDecl = D;
00042   ThisDeclInfo->IsFilled = false;
00043 }
00044 
00045 ParagraphComment *Sema::actOnParagraphComment(
00046                               ArrayRef<InlineContentComment *> Content) {
00047   return new (Allocator) ParagraphComment(Content);
00048 }
00049 
00050 BlockCommandComment *Sema::actOnBlockCommandStart(
00051                                       SourceLocation LocBegin,
00052                                       SourceLocation LocEnd,
00053                                       unsigned CommandID,
00054                                       CommandMarkerKind CommandMarker) {
00055   BlockCommandComment *BC = new (Allocator) BlockCommandComment(LocBegin, LocEnd,
00056                                                                 CommandID,
00057                                                                 CommandMarker);
00058   checkContainerDecl(BC);
00059   return BC;
00060 }
00061 
00062 void Sema::actOnBlockCommandArgs(BlockCommandComment *Command,
00063                                  ArrayRef<BlockCommandComment::Argument> Args) {
00064   Command->setArgs(Args);
00065 }
00066 
00067 void Sema::actOnBlockCommandFinish(BlockCommandComment *Command,
00068                                    ParagraphComment *Paragraph) {
00069   Command->setParagraph(Paragraph);
00070   checkBlockCommandEmptyParagraph(Command);
00071   checkBlockCommandDuplicate(Command);
00072   if (ThisDeclInfo) {
00073     // These checks only make sense if the comment is attached to a
00074     // declaration.
00075     checkReturnsCommand(Command);
00076     checkDeprecatedCommand(Command);
00077   }
00078 }
00079 
00080 ParamCommandComment *Sema::actOnParamCommandStart(
00081                                       SourceLocation LocBegin,
00082                                       SourceLocation LocEnd,
00083                                       unsigned CommandID,
00084                                       CommandMarkerKind CommandMarker) {
00085   ParamCommandComment *Command =
00086       new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID,
00087                                           CommandMarker);
00088 
00089   if (!isFunctionDecl())
00090     Diag(Command->getLocation(),
00091          diag::warn_doc_param_not_attached_to_a_function_decl)
00092       << CommandMarker
00093       << Command->getCommandNameRange(Traits);
00094 
00095   return Command;
00096 }
00097 
00098 void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) {
00099   const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
00100   if (!Info->IsFunctionDeclarationCommand)
00101     return;
00102 
00103   unsigned DiagSelect;
00104   switch (Comment->getCommandID()) {
00105     case CommandTraits::KCI_function:
00106       DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 1 : 0;
00107       break;
00108     case CommandTraits::KCI_functiongroup:
00109       DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 2 : 0;
00110       break;
00111     case CommandTraits::KCI_method:
00112       DiagSelect = !isObjCMethodDecl() ? 3 : 0;
00113       break;
00114     case CommandTraits::KCI_methodgroup:
00115       DiagSelect = !isObjCMethodDecl() ? 4 : 0;
00116       break;
00117     case CommandTraits::KCI_callback:
00118       DiagSelect = !isFunctionPointerVarDecl() ? 5 : 0;
00119       break;
00120     default:
00121       DiagSelect = 0;
00122       break;
00123   }
00124   if (DiagSelect)
00125     Diag(Comment->getLocation(), diag::warn_doc_function_method_decl_mismatch)
00126     << Comment->getCommandMarker()
00127     << (DiagSelect-1) << (DiagSelect-1)
00128     << Comment->getSourceRange();
00129 }
00130 
00131 void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
00132   const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
00133   if (!Info->IsRecordLikeDeclarationCommand)
00134     return;
00135   unsigned DiagSelect;
00136   switch (Comment->getCommandID()) {
00137     case CommandTraits::KCI_class:
00138       DiagSelect = (!isClassOrStructDecl() && !isClassTemplateDecl()) ? 1 : 0;
00139       // Allow @class command on @interface declarations.
00140       // FIXME. Currently, \class and @class are indistinguishable. So,
00141       // \class is also allowed on an @interface declaration
00142       if (DiagSelect && Comment->getCommandMarker() && isObjCInterfaceDecl())
00143         DiagSelect = 0;
00144       break;
00145     case CommandTraits::KCI_interface:
00146       DiagSelect = !isObjCInterfaceDecl() ? 2 : 0;
00147       break;
00148     case CommandTraits::KCI_protocol:
00149       DiagSelect = !isObjCProtocolDecl() ? 3 : 0;
00150       break;
00151     case CommandTraits::KCI_struct:
00152       DiagSelect = !isClassOrStructDecl() ? 4 : 0;
00153       break;
00154     case CommandTraits::KCI_union:
00155       DiagSelect = !isUnionDecl() ? 5 : 0;
00156       break;
00157     default:
00158       DiagSelect = 0;
00159       break;
00160   }
00161   if (DiagSelect)
00162     Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch)
00163     << Comment->getCommandMarker()
00164     << (DiagSelect-1) << (DiagSelect-1)
00165     << Comment->getSourceRange();
00166 }
00167 
00168 void Sema::checkContainerDecl(const BlockCommandComment *Comment) {
00169   const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
00170   if (!Info->IsRecordLikeDetailCommand || isRecordLikeDecl())
00171     return;
00172   unsigned DiagSelect;
00173   switch (Comment->getCommandID()) {
00174     case CommandTraits::KCI_classdesign:
00175       DiagSelect = 1;
00176       break;
00177     case CommandTraits::KCI_coclass:
00178       DiagSelect = 2;
00179       break;
00180     case CommandTraits::KCI_dependency:
00181       DiagSelect = 3;
00182       break;
00183     case CommandTraits::KCI_helper:
00184       DiagSelect = 4;
00185       break;
00186     case CommandTraits::KCI_helperclass:
00187       DiagSelect = 5;
00188       break;
00189     case CommandTraits::KCI_helps:
00190       DiagSelect = 6;
00191       break;
00192     case CommandTraits::KCI_instancesize:
00193       DiagSelect = 7;
00194       break;
00195     case CommandTraits::KCI_ownership:
00196       DiagSelect = 8;
00197       break;
00198     case CommandTraits::KCI_performance:
00199       DiagSelect = 9;
00200       break;
00201     case CommandTraits::KCI_security:
00202       DiagSelect = 10;
00203       break;
00204     case CommandTraits::KCI_superclass:
00205       DiagSelect = 11;
00206       break;
00207     default:
00208       DiagSelect = 0;
00209       break;
00210   }
00211   if (DiagSelect)
00212     Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch)
00213     << Comment->getCommandMarker()
00214     << (DiagSelect-1)
00215     << Comment->getSourceRange();
00216 }
00217 
00218 /// \brief Turn a string into the corresponding PassDirection or -1 if it's not
00219 /// valid.
00220 static int getParamPassDirection(StringRef Arg) {
00221   return llvm::StringSwitch<int>(Arg)
00222       .Case("[in]", ParamCommandComment::In)
00223       .Case("[out]", ParamCommandComment::Out)
00224       .Cases("[in,out]", "[out,in]", ParamCommandComment::InOut)
00225       .Default(-1);
00226 }
00227 
00228 void Sema::actOnParamCommandDirectionArg(ParamCommandComment *Command,
00229                                          SourceLocation ArgLocBegin,
00230                                          SourceLocation ArgLocEnd,
00231                                          StringRef Arg) {
00232   std::string ArgLower = Arg.lower();
00233   int Direction = getParamPassDirection(ArgLower);
00234 
00235   if (Direction == -1) {
00236     // Try again with whitespace removed.
00237     ArgLower.erase(
00238         std::remove_if(ArgLower.begin(), ArgLower.end(), clang::isWhitespace),
00239         ArgLower.end());
00240     Direction = getParamPassDirection(ArgLower);
00241 
00242     SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
00243     if (Direction != -1) {
00244       const char *FixedName = ParamCommandComment::getDirectionAsString(
00245           (ParamCommandComment::PassDirection)Direction);
00246       Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction)
00247           << ArgRange << FixItHint::CreateReplacement(ArgRange, FixedName);
00248     } else {
00249       Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange;
00250       Direction = ParamCommandComment::In; // Sane fall back.
00251     }
00252   }
00253   Command->setDirection((ParamCommandComment::PassDirection)Direction,
00254                         /*Explicit=*/true);
00255 }
00256 
00257 void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command,
00258                                          SourceLocation ArgLocBegin,
00259                                          SourceLocation ArgLocEnd,
00260                                          StringRef Arg) {
00261   // Parser will not feed us more arguments than needed.
00262   assert(Command->getNumArgs() == 0);
00263 
00264   if (!Command->isDirectionExplicit()) {
00265     // User didn't provide a direction argument.
00266     Command->setDirection(ParamCommandComment::In, /* Explicit = */ false);
00267   }
00268   typedef BlockCommandComment::Argument Argument;
00269   Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
00270                                                      ArgLocEnd),
00271                                          Arg);
00272   Command->setArgs(llvm::makeArrayRef(A, 1));
00273 }
00274 
00275 void Sema::actOnParamCommandFinish(ParamCommandComment *Command,
00276                                    ParagraphComment *Paragraph) {
00277   Command->setParagraph(Paragraph);
00278   checkBlockCommandEmptyParagraph(Command);
00279 }
00280 
00281 TParamCommandComment *Sema::actOnTParamCommandStart(
00282                                       SourceLocation LocBegin,
00283                                       SourceLocation LocEnd,
00284                                       unsigned CommandID,
00285                                       CommandMarkerKind CommandMarker) {
00286   TParamCommandComment *Command =
00287       new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID,
00288                                            CommandMarker);
00289 
00290   if (!isTemplateOrSpecialization())
00291     Diag(Command->getLocation(),
00292          diag::warn_doc_tparam_not_attached_to_a_template_decl)
00293       << CommandMarker
00294       << Command->getCommandNameRange(Traits);
00295 
00296   return Command;
00297 }
00298 
00299 void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command,
00300                                           SourceLocation ArgLocBegin,
00301                                           SourceLocation ArgLocEnd,
00302                                           StringRef Arg) {
00303   // Parser will not feed us more arguments than needed.
00304   assert(Command->getNumArgs() == 0);
00305 
00306   typedef BlockCommandComment::Argument Argument;
00307   Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
00308                                                      ArgLocEnd),
00309                                          Arg);
00310   Command->setArgs(llvm::makeArrayRef(A, 1));
00311 
00312   if (!isTemplateOrSpecialization()) {
00313     // We already warned that this \\tparam is not attached to a template decl.
00314     return;
00315   }
00316 
00317   const TemplateParameterList *TemplateParameters =
00318       ThisDeclInfo->TemplateParameters;
00319   SmallVector<unsigned, 2> Position;
00320   if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
00321     Command->setPosition(copyArray(llvm::makeArrayRef(Position)));
00322     TParamCommandComment *&PrevCommand = TemplateParameterDocs[Arg];
00323     if (PrevCommand) {
00324       SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
00325       Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
00326         << Arg << ArgRange;
00327       Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous)
00328         << PrevCommand->getParamNameRange();
00329     }
00330     PrevCommand = Command;
00331     return;
00332   }
00333 
00334   SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
00335   Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
00336     << Arg << ArgRange;
00337 
00338   if (!TemplateParameters || TemplateParameters->size() == 0)
00339     return;
00340 
00341   StringRef CorrectedName;
00342   if (TemplateParameters->size() == 1) {
00343     const NamedDecl *Param = TemplateParameters->getParam(0);
00344     const IdentifierInfo *II = Param->getIdentifier();
00345     if (II)
00346       CorrectedName = II->getName();
00347   } else {
00348     CorrectedName = correctTypoInTParamReference(Arg, TemplateParameters);
00349   }
00350 
00351   if (!CorrectedName.empty()) {
00352     Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
00353       << CorrectedName
00354       << FixItHint::CreateReplacement(ArgRange, CorrectedName);
00355   }
00356 
00357   return;
00358 }
00359 
00360 void Sema::actOnTParamCommandFinish(TParamCommandComment *Command,
00361                                     ParagraphComment *Paragraph) {
00362   Command->setParagraph(Paragraph);
00363   checkBlockCommandEmptyParagraph(Command);
00364 }
00365 
00366 InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
00367                                                SourceLocation CommandLocEnd,
00368                                                unsigned CommandID) {
00369   ArrayRef<InlineCommandComment::Argument> Args;
00370   StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
00371   return new (Allocator) InlineCommandComment(
00372                                   CommandLocBegin,
00373                                   CommandLocEnd,
00374                                   CommandID,
00375                                   getInlineCommandRenderKind(CommandName),
00376                                   Args);
00377 }
00378 
00379 InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
00380                                                SourceLocation CommandLocEnd,
00381                                                unsigned CommandID,
00382                                                SourceLocation ArgLocBegin,
00383                                                SourceLocation ArgLocEnd,
00384                                                StringRef Arg) {
00385   typedef InlineCommandComment::Argument Argument;
00386   Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
00387                                                      ArgLocEnd),
00388                                          Arg);
00389   StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
00390 
00391   return new (Allocator) InlineCommandComment(
00392                                   CommandLocBegin,
00393                                   CommandLocEnd,
00394                                   CommandID,
00395                                   getInlineCommandRenderKind(CommandName),
00396                                   llvm::makeArrayRef(A, 1));
00397 }
00398 
00399 InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
00400                                                 SourceLocation LocEnd,
00401                                                 StringRef CommandName) {
00402   unsigned CommandID = Traits.registerUnknownCommand(CommandName)->getID();
00403   return actOnUnknownCommand(LocBegin, LocEnd, CommandID);
00404 }
00405 
00406 InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
00407                                                 SourceLocation LocEnd,
00408                                                 unsigned CommandID) {
00409   ArrayRef<InlineCommandComment::Argument> Args;
00410   return new (Allocator) InlineCommandComment(
00411                                   LocBegin, LocEnd, CommandID,
00412                                   InlineCommandComment::RenderNormal,
00413                                   Args);
00414 }
00415 
00416 TextComment *Sema::actOnText(SourceLocation LocBegin,
00417                              SourceLocation LocEnd,
00418                              StringRef Text) {
00419   return new (Allocator) TextComment(LocBegin, LocEnd, Text);
00420 }
00421 
00422 VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc,
00423                                                     unsigned CommandID) {
00424   StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
00425   return new (Allocator) VerbatimBlockComment(
00426                                   Loc,
00427                                   Loc.getLocWithOffset(1 + CommandName.size()),
00428                                   CommandID);
00429 }
00430 
00431 VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc,
00432                                                        StringRef Text) {
00433   return new (Allocator) VerbatimBlockLineComment(Loc, Text);
00434 }
00435 
00436 void Sema::actOnVerbatimBlockFinish(
00437                             VerbatimBlockComment *Block,
00438                             SourceLocation CloseNameLocBegin,
00439                             StringRef CloseName,
00440                             ArrayRef<VerbatimBlockLineComment *> Lines) {
00441   Block->setCloseName(CloseName, CloseNameLocBegin);
00442   Block->setLines(Lines);
00443 }
00444 
00445 VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin,
00446                                              unsigned CommandID,
00447                                              SourceLocation TextBegin,
00448                                              StringRef Text) {
00449   VerbatimLineComment *VL = new (Allocator) VerbatimLineComment(
00450                               LocBegin,
00451                               TextBegin.getLocWithOffset(Text.size()),
00452                               CommandID,
00453                               TextBegin,
00454                               Text);
00455   checkFunctionDeclVerbatimLine(VL);
00456   checkContainerDeclVerbatimLine(VL);
00457   return VL;
00458 }
00459 
00460 HTMLStartTagComment *Sema::actOnHTMLStartTagStart(SourceLocation LocBegin,
00461                                                   StringRef TagName) {
00462   return new (Allocator) HTMLStartTagComment(LocBegin, TagName);
00463 }
00464 
00465 void Sema::actOnHTMLStartTagFinish(
00466                               HTMLStartTagComment *Tag,
00467                               ArrayRef<HTMLStartTagComment::Attribute> Attrs,
00468                               SourceLocation GreaterLoc,
00469                               bool IsSelfClosing) {
00470   Tag->setAttrs(Attrs);
00471   Tag->setGreaterLoc(GreaterLoc);
00472   if (IsSelfClosing)
00473     Tag->setSelfClosing();
00474   else if (!isHTMLEndTagForbidden(Tag->getTagName()))
00475     HTMLOpenTags.push_back(Tag);
00476 }
00477 
00478 HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin,
00479                                          SourceLocation LocEnd,
00480                                          StringRef TagName) {
00481   HTMLEndTagComment *HET =
00482       new (Allocator) HTMLEndTagComment(LocBegin, LocEnd, TagName);
00483   if (isHTMLEndTagForbidden(TagName)) {
00484     Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden)
00485       << TagName << HET->getSourceRange();
00486     HET->setIsMalformed();
00487     return HET;
00488   }
00489 
00490   bool FoundOpen = false;
00491   for (SmallVectorImpl<HTMLStartTagComment *>::const_reverse_iterator
00492        I = HTMLOpenTags.rbegin(), E = HTMLOpenTags.rend();
00493        I != E; ++I) {
00494     if ((*I)->getTagName() == TagName) {
00495       FoundOpen = true;
00496       break;
00497     }
00498   }
00499   if (!FoundOpen) {
00500     Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced)
00501       << HET->getSourceRange();
00502     HET->setIsMalformed();
00503     return HET;
00504   }
00505 
00506   while (!HTMLOpenTags.empty()) {
00507     HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
00508     StringRef LastNotClosedTagName = HST->getTagName();
00509     if (LastNotClosedTagName == TagName) {
00510       // If the start tag is malformed, end tag is malformed as well.
00511       if (HST->isMalformed())
00512         HET->setIsMalformed();
00513       break;
00514     }
00515 
00516     if (isHTMLEndTagOptional(LastNotClosedTagName))
00517       continue;
00518 
00519     bool OpenLineInvalid;
00520     const unsigned OpenLine = SourceMgr.getPresumedLineNumber(
00521                                                 HST->getLocation(),
00522                                                 &OpenLineInvalid);
00523     bool CloseLineInvalid;
00524     const unsigned CloseLine = SourceMgr.getPresumedLineNumber(
00525                                                 HET->getLocation(),
00526                                                 &CloseLineInvalid);
00527 
00528     if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) {
00529       Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
00530         << HST->getTagName() << HET->getTagName()
00531         << HST->getSourceRange() << HET->getSourceRange();
00532       HST->setIsMalformed();
00533     } else {
00534       Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
00535         << HST->getTagName() << HET->getTagName()
00536         << HST->getSourceRange();
00537       Diag(HET->getLocation(), diag::note_doc_html_end_tag)
00538         << HET->getSourceRange();
00539       HST->setIsMalformed();
00540     }
00541   }
00542 
00543   return HET;
00544 }
00545 
00546 FullComment *Sema::actOnFullComment(
00547                               ArrayRef<BlockContentComment *> Blocks) {
00548   FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
00549   resolveParamCommandIndexes(FC);
00550 
00551   // Complain about HTML tags that are not closed.
00552   while (!HTMLOpenTags.empty()) {
00553     HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
00554     if (isHTMLEndTagOptional(HST->getTagName()))
00555       continue;
00556 
00557     Diag(HST->getLocation(), diag::warn_doc_html_missing_end_tag)
00558       << HST->getTagName() << HST->getSourceRange();
00559     HST->setIsMalformed();
00560   }
00561 
00562   return FC;
00563 }
00564 
00565 void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
00566   if (Traits.getCommandInfo(Command->getCommandID())->IsEmptyParagraphAllowed)
00567     return;
00568 
00569   ParagraphComment *Paragraph = Command->getParagraph();
00570   if (Paragraph->isWhitespace()) {
00571     SourceLocation DiagLoc;
00572     if (Command->getNumArgs() > 0)
00573       DiagLoc = Command->getArgRange(Command->getNumArgs() - 1).getEnd();
00574     if (!DiagLoc.isValid())
00575       DiagLoc = Command->getCommandNameRange(Traits).getEnd();
00576     Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
00577       << Command->getCommandMarker()
00578       << Command->getCommandName(Traits)
00579       << Command->getSourceRange();
00580   }
00581 }
00582 
00583 void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
00584   if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand)
00585     return;
00586 
00587   assert(ThisDeclInfo && "should not call this check on a bare comment");
00588 
00589   if (isFunctionDecl()) {
00590     if (ThisDeclInfo->ReturnType->isVoidType()) {
00591       unsigned DiagKind;
00592       switch (ThisDeclInfo->CommentDecl->getKind()) {
00593       default:
00594         if (ThisDeclInfo->IsObjCMethod)
00595           DiagKind = 3;
00596         else
00597           DiagKind = 0;
00598         break;
00599       case Decl::CXXConstructor:
00600         DiagKind = 1;
00601         break;
00602       case Decl::CXXDestructor:
00603         DiagKind = 2;
00604         break;
00605       }
00606       Diag(Command->getLocation(),
00607            diag::warn_doc_returns_attached_to_a_void_function)
00608         << Command->getCommandMarker()
00609         << Command->getCommandName(Traits)
00610         << DiagKind
00611         << Command->getSourceRange();
00612     }
00613     return;
00614   }
00615   else if (isObjCPropertyDecl())
00616     return;
00617 
00618   Diag(Command->getLocation(),
00619        diag::warn_doc_returns_not_attached_to_a_function_decl)
00620     << Command->getCommandMarker()
00621     << Command->getCommandName(Traits)
00622     << Command->getSourceRange();
00623 }
00624 
00625 void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
00626   const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
00627   const BlockCommandComment *PrevCommand = nullptr;
00628   if (Info->IsBriefCommand) {
00629     if (!BriefCommand) {
00630       BriefCommand = Command;
00631       return;
00632     }
00633     PrevCommand = BriefCommand;
00634   } else if (Info->IsHeaderfileCommand) {
00635     if (!HeaderfileCommand) {
00636       HeaderfileCommand = Command;
00637       return;
00638     }
00639     PrevCommand = HeaderfileCommand;
00640   } else {
00641     // We don't want to check this command for duplicates.
00642     return;
00643   }
00644   StringRef CommandName = Command->getCommandName(Traits);
00645   StringRef PrevCommandName = PrevCommand->getCommandName(Traits);
00646   Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
00647       << Command->getCommandMarker()
00648       << CommandName
00649       << Command->getSourceRange();
00650   if (CommandName == PrevCommandName)
00651     Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
00652         << PrevCommand->getCommandMarker()
00653         << PrevCommandName
00654         << PrevCommand->getSourceRange();
00655   else
00656     Diag(PrevCommand->getLocation(),
00657          diag::note_doc_block_command_previous_alias)
00658         << PrevCommand->getCommandMarker()
00659         << PrevCommandName
00660         << CommandName;
00661 }
00662 
00663 void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {
00664   if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand)
00665     return;
00666 
00667   assert(ThisDeclInfo && "should not call this check on a bare comment");
00668 
00669   const Decl *D = ThisDeclInfo->CommentDecl;
00670   if (!D)
00671     return;
00672 
00673   if (D->hasAttr<DeprecatedAttr>() ||
00674       D->hasAttr<AvailabilityAttr>() ||
00675       D->hasAttr<UnavailableAttr>())
00676     return;
00677 
00678   Diag(Command->getLocation(),
00679        diag::warn_doc_deprecated_not_sync)
00680     << Command->getSourceRange();
00681 
00682   // Try to emit a fixit with a deprecation attribute.
00683   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
00684     // Don't emit a Fix-It for non-member function definitions.  GCC does not
00685     // accept attributes on them.
00686     const DeclContext *Ctx = FD->getDeclContext();
00687     if ((!Ctx || !Ctx->isRecord()) &&
00688         FD->doesThisDeclarationHaveABody())
00689       return;
00690 
00691     StringRef AttributeSpelling = "__attribute__((deprecated))";
00692     if (PP) {
00693       TokenValue Tokens[] = {
00694         tok::kw___attribute, tok::l_paren, tok::l_paren,
00695         PP->getIdentifierInfo("deprecated"),
00696         tok::r_paren, tok::r_paren
00697       };
00698       StringRef MacroName = PP->getLastMacroWithSpelling(FD->getLocation(),
00699                                                          Tokens);
00700       if (!MacroName.empty())
00701         AttributeSpelling = MacroName;
00702     }
00703 
00704     SmallString<64> TextToInsert(" ");
00705     TextToInsert += AttributeSpelling;
00706     Diag(FD->getLocEnd(),
00707          diag::note_add_deprecation_attr)
00708       << FixItHint::CreateInsertion(FD->getLocEnd().getLocWithOffset(1),
00709                                     TextToInsert);
00710   }
00711 }
00712 
00713 void Sema::resolveParamCommandIndexes(const FullComment *FC) {
00714   if (!isFunctionDecl()) {
00715     // We already warned that \\param commands are not attached to a function
00716     // decl.
00717     return;
00718   }
00719 
00720   SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;
00721 
00722   // Comment AST nodes that correspond to \c ParamVars for which we have
00723   // found a \\param command or NULL if no documentation was found so far.
00724   SmallVector<ParamCommandComment *, 8> ParamVarDocs;
00725 
00726   ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
00727   ParamVarDocs.resize(ParamVars.size(), nullptr);
00728 
00729   // First pass over all \\param commands: resolve all parameter names.
00730   for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
00731        I != E; ++I) {
00732     ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
00733     if (!PCC || !PCC->hasParamName())
00734       continue;
00735     StringRef ParamName = PCC->getParamNameAsWritten();
00736 
00737     // Check that referenced parameter name is in the function decl.
00738     const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,
00739                                                                 ParamVars);
00740     if (ResolvedParamIndex == ParamCommandComment::VarArgParamIndex) {
00741       PCC->setIsVarArgParam();
00742       continue;
00743     }
00744     if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) {
00745       UnresolvedParamCommands.push_back(PCC);
00746       continue;
00747     }
00748     PCC->setParamIndex(ResolvedParamIndex);
00749     if (ParamVarDocs[ResolvedParamIndex]) {
00750       SourceRange ArgRange = PCC->getParamNameRange();
00751       Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)
00752         << ParamName << ArgRange;
00753       ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
00754       Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
00755         << PrevCommand->getParamNameRange();
00756     }
00757     ParamVarDocs[ResolvedParamIndex] = PCC;
00758   }
00759 
00760   // Find parameter declarations that have no corresponding \\param.
00761   SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;
00762   for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
00763     if (!ParamVarDocs[i])
00764       OrphanedParamDecls.push_back(ParamVars[i]);
00765   }
00766 
00767   // Second pass over unresolved \\param commands: do typo correction.
00768   // Suggest corrections from a set of parameter declarations that have no
00769   // corresponding \\param.
00770   for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
00771     const ParamCommandComment *PCC = UnresolvedParamCommands[i];
00772 
00773     SourceRange ArgRange = PCC->getParamNameRange();
00774     StringRef ParamName = PCC->getParamNameAsWritten();
00775     Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)
00776       << ParamName << ArgRange;
00777 
00778     // All parameters documented -- can't suggest a correction.
00779     if (OrphanedParamDecls.size() == 0)
00780       continue;
00781 
00782     unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
00783     if (OrphanedParamDecls.size() == 1) {
00784       // If one parameter is not documented then that parameter is the only
00785       // possible suggestion.
00786       CorrectedParamIndex = 0;
00787     } else {
00788       // Do typo correction.
00789       CorrectedParamIndex = correctTypoInParmVarReference(ParamName,
00790                                                           OrphanedParamDecls);
00791     }
00792     if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
00793       const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
00794       if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
00795         Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)
00796           << CorrectedII->getName()
00797           << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
00798     }
00799   }
00800 }
00801 
00802 bool Sema::isFunctionDecl() {
00803   if (!ThisDeclInfo)
00804     return false;
00805   if (!ThisDeclInfo->IsFilled)
00806     inspectThisDecl();
00807   return ThisDeclInfo->getKind() == DeclInfo::FunctionKind;
00808 }
00809 
00810 bool Sema::isAnyFunctionDecl() {
00811   return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
00812          isa<FunctionDecl>(ThisDeclInfo->CurrentDecl);
00813 }
00814 
00815 bool Sema::isFunctionOrMethodVariadic() {
00816   if (!isAnyFunctionDecl() && !isObjCMethodDecl() && !isFunctionTemplateDecl())
00817     return false;
00818   if (const FunctionDecl *FD =
00819         dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl))
00820     return FD->isVariadic();
00821   if (const FunctionTemplateDecl *FTD =
00822         dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl))
00823     return FTD->getTemplatedDecl()->isVariadic();
00824   if (const ObjCMethodDecl *MD =
00825         dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl))
00826     return MD->isVariadic();
00827   return false;
00828 }
00829 
00830 bool Sema::isObjCMethodDecl() {
00831   return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
00832          isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl);
00833 }
00834 
00835 bool Sema::isFunctionPointerVarDecl() {
00836   if (!ThisDeclInfo)
00837     return false;
00838   if (!ThisDeclInfo->IsFilled)
00839     inspectThisDecl();
00840   if (ThisDeclInfo->getKind() == DeclInfo::VariableKind) {
00841     if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDeclInfo->CurrentDecl)) {
00842       QualType QT = VD->getType();
00843       return QT->isFunctionPointerType();
00844     }
00845   }
00846   return false;
00847 }
00848 
00849 bool Sema::isObjCPropertyDecl() {
00850   if (!ThisDeclInfo)
00851     return false;
00852   if (!ThisDeclInfo->IsFilled)
00853     inspectThisDecl();
00854   return ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty;
00855 }
00856 
00857 bool Sema::isTemplateOrSpecialization() {
00858   if (!ThisDeclInfo)
00859     return false;
00860   if (!ThisDeclInfo->IsFilled)
00861     inspectThisDecl();
00862   return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate;
00863 }
00864 
00865 bool Sema::isRecordLikeDecl() {
00866   if (!ThisDeclInfo)
00867     return false;
00868   if (!ThisDeclInfo->IsFilled)
00869     inspectThisDecl();
00870   return isUnionDecl() || isClassOrStructDecl() || isObjCInterfaceDecl() ||
00871          isObjCProtocolDecl();
00872 }
00873 
00874 bool Sema::isUnionDecl() {
00875   if (!ThisDeclInfo)
00876     return false;
00877   if (!ThisDeclInfo->IsFilled)
00878     inspectThisDecl();
00879   if (const RecordDecl *RD =
00880         dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl))
00881     return RD->isUnion();
00882   return false;
00883 }
00884 
00885 bool Sema::isClassOrStructDecl() {
00886   if (!ThisDeclInfo)
00887     return false;
00888   if (!ThisDeclInfo->IsFilled)
00889     inspectThisDecl();
00890   return ThisDeclInfo->CurrentDecl &&
00891          isa<RecordDecl>(ThisDeclInfo->CurrentDecl) &&
00892          !isUnionDecl();
00893 }
00894 
00895 bool Sema::isClassTemplateDecl() {
00896   if (!ThisDeclInfo)
00897     return false;
00898   if (!ThisDeclInfo->IsFilled)
00899     inspectThisDecl();
00900   return ThisDeclInfo->CurrentDecl &&
00901           (isa<ClassTemplateDecl>(ThisDeclInfo->CurrentDecl));
00902 }
00903 
00904 bool Sema::isFunctionTemplateDecl() {
00905   if (!ThisDeclInfo)
00906     return false;
00907   if (!ThisDeclInfo->IsFilled)
00908     inspectThisDecl();
00909   return ThisDeclInfo->CurrentDecl &&
00910          (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl));
00911 }
00912 
00913 bool Sema::isObjCInterfaceDecl() {
00914   if (!ThisDeclInfo)
00915     return false;
00916   if (!ThisDeclInfo->IsFilled)
00917     inspectThisDecl();
00918   return ThisDeclInfo->CurrentDecl &&
00919          isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl);
00920 }
00921 
00922 bool Sema::isObjCProtocolDecl() {
00923   if (!ThisDeclInfo)
00924     return false;
00925   if (!ThisDeclInfo->IsFilled)
00926     inspectThisDecl();
00927   return ThisDeclInfo->CurrentDecl &&
00928          isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl);
00929 }
00930 
00931 ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
00932   if (!ThisDeclInfo->IsFilled)
00933     inspectThisDecl();
00934   return ThisDeclInfo->ParamVars;
00935 }
00936 
00937 void Sema::inspectThisDecl() {
00938   ThisDeclInfo->fill();
00939 }
00940 
00941 unsigned Sema::resolveParmVarReference(StringRef Name,
00942                                        ArrayRef<const ParmVarDecl *> ParamVars) {
00943   for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
00944     const IdentifierInfo *II = ParamVars[i]->getIdentifier();
00945     if (II && II->getName() == Name)
00946       return i;
00947   }
00948   if (Name == "..." && isFunctionOrMethodVariadic())
00949     return ParamCommandComment::VarArgParamIndex;
00950   return ParamCommandComment::InvalidParamIndex;
00951 }
00952 
00953 namespace {
00954 class SimpleTypoCorrector {
00955   StringRef Typo;
00956   const unsigned MaxEditDistance;
00957 
00958   const NamedDecl *BestDecl;
00959   unsigned BestEditDistance;
00960   unsigned BestIndex;
00961   unsigned NextIndex;
00962 
00963 public:
00964   SimpleTypoCorrector(StringRef Typo) :
00965       Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
00966       BestDecl(nullptr), BestEditDistance(MaxEditDistance + 1),
00967       BestIndex(0), NextIndex(0)
00968   { }
00969 
00970   void addDecl(const NamedDecl *ND);
00971 
00972   const NamedDecl *getBestDecl() const {
00973     if (BestEditDistance > MaxEditDistance)
00974       return nullptr;
00975 
00976     return BestDecl;
00977   }
00978 
00979   unsigned getBestDeclIndex() const {
00980     assert(getBestDecl());
00981     return BestIndex;
00982   }
00983 };
00984 
00985 void SimpleTypoCorrector::addDecl(const NamedDecl *ND) {
00986   unsigned CurrIndex = NextIndex++;
00987 
00988   const IdentifierInfo *II = ND->getIdentifier();
00989   if (!II)
00990     return;
00991 
00992   StringRef Name = II->getName();
00993   unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
00994   if (MinPossibleEditDistance > 0 &&
00995       Typo.size() / MinPossibleEditDistance < 3)
00996     return;
00997 
00998   unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
00999   if (EditDistance < BestEditDistance) {
01000     BestEditDistance = EditDistance;
01001     BestDecl = ND;
01002     BestIndex = CurrIndex;
01003   }
01004 }
01005 } // unnamed namespace
01006 
01007 unsigned Sema::correctTypoInParmVarReference(
01008                                     StringRef Typo,
01009                                     ArrayRef<const ParmVarDecl *> ParamVars) {
01010   SimpleTypoCorrector Corrector(Typo);
01011   for (unsigned i = 0, e = ParamVars.size(); i != e; ++i)
01012     Corrector.addDecl(ParamVars[i]);
01013   if (Corrector.getBestDecl())
01014     return Corrector.getBestDeclIndex();
01015   else
01016     return ParamCommandComment::InvalidParamIndex;
01017 }
01018 
01019 namespace {
01020 bool ResolveTParamReferenceHelper(
01021                             StringRef Name,
01022                             const TemplateParameterList *TemplateParameters,
01023                             SmallVectorImpl<unsigned> *Position) {
01024   for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
01025     const NamedDecl *Param = TemplateParameters->getParam(i);
01026     const IdentifierInfo *II = Param->getIdentifier();
01027     if (II && II->getName() == Name) {
01028       Position->push_back(i);
01029       return true;
01030     }
01031 
01032     if (const TemplateTemplateParmDecl *TTP =
01033             dyn_cast<TemplateTemplateParmDecl>(Param)) {
01034       Position->push_back(i);
01035       if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
01036                                        Position))
01037         return true;
01038       Position->pop_back();
01039     }
01040   }
01041   return false;
01042 }
01043 } // unnamed namespace
01044 
01045 bool Sema::resolveTParamReference(
01046                             StringRef Name,
01047                             const TemplateParameterList *TemplateParameters,
01048                             SmallVectorImpl<unsigned> *Position) {
01049   Position->clear();
01050   if (!TemplateParameters)
01051     return false;
01052 
01053   return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
01054 }
01055 
01056 namespace {
01057 void CorrectTypoInTParamReferenceHelper(
01058                             const TemplateParameterList *TemplateParameters,
01059                             SimpleTypoCorrector &Corrector) {
01060   for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
01061     const NamedDecl *Param = TemplateParameters->getParam(i);
01062     Corrector.addDecl(Param);
01063 
01064     if (const TemplateTemplateParmDecl *TTP =
01065             dyn_cast<TemplateTemplateParmDecl>(Param))
01066       CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
01067                                          Corrector);
01068   }
01069 }
01070 } // unnamed namespace
01071 
01072 StringRef Sema::correctTypoInTParamReference(
01073                             StringRef Typo,
01074                             const TemplateParameterList *TemplateParameters) {
01075   SimpleTypoCorrector Corrector(Typo);
01076   CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
01077   if (const NamedDecl *ND = Corrector.getBestDecl()) {
01078     const IdentifierInfo *II = ND->getIdentifier();
01079     assert(II && "SimpleTypoCorrector should not return this decl");
01080     return II->getName();
01081   }
01082   return StringRef();
01083 }
01084 
01085 InlineCommandComment::RenderKind
01086 Sema::getInlineCommandRenderKind(StringRef Name) const {
01087   assert(Traits.getCommandInfo(Name)->IsInlineCommand);
01088 
01089   return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
01090       .Case("b", InlineCommandComment::RenderBold)
01091       .Cases("c", "p", InlineCommandComment::RenderMonospaced)
01092       .Cases("a", "e", "em", InlineCommandComment::RenderEmphasized)
01093       .Default(InlineCommandComment::RenderNormal);
01094 }
01095 
01096 } // end namespace comments
01097 } // end namespace clang
01098