]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/clang/lib/AST/CommentSema.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / clang / lib / AST / CommentSema.cpp
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"
12 #include "clang/AST/CommentCommandTraits.h"
13 #include "clang/AST/CommentDiagnostic.h"
14 #include "clang/AST/Decl.h"
15 #include "clang/AST/DeclTemplate.h"
16 #include "clang/Basic/SourceManager.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 } // unnamed 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(NULL), BriefCommand(NULL), HeaderfileCommand(NULL) {
33 }
34
35 void Sema::setDecl(const Decl *D) {
36   if (!D)
37     return;
38
39   ThisDeclInfo = new (Allocator) DeclInfo;
40   ThisDeclInfo->CommentDecl = D;
41   ThisDeclInfo->IsFilled = false;
42 }
43
44 ParagraphComment *Sema::actOnParagraphComment(
45                               ArrayRef<InlineContentComment *> Content) {
46   return new (Allocator) ParagraphComment(Content);
47 }
48
49 BlockCommandComment *Sema::actOnBlockCommandStart(
50                                       SourceLocation LocBegin,
51                                       SourceLocation LocEnd,
52                                       unsigned CommandID,
53                                       CommandMarkerKind CommandMarker) {
54   BlockCommandComment *BC = new (Allocator) BlockCommandComment(LocBegin, LocEnd,
55                                                                 CommandID,
56                                                                 CommandMarker);
57   checkContainerDecl(BC);
58   return BC;
59 }
60
61 void Sema::actOnBlockCommandArgs(BlockCommandComment *Command,
62                                  ArrayRef<BlockCommandComment::Argument> Args) {
63   Command->setArgs(Args);
64 }
65
66 void Sema::actOnBlockCommandFinish(BlockCommandComment *Command,
67                                    ParagraphComment *Paragraph) {
68   Command->setParagraph(Paragraph);
69   checkBlockCommandEmptyParagraph(Command);
70   checkBlockCommandDuplicate(Command);
71   checkReturnsCommand(Command);
72   checkDeprecatedCommand(Command);
73 }
74
75 ParamCommandComment *Sema::actOnParamCommandStart(
76                                       SourceLocation LocBegin,
77                                       SourceLocation LocEnd,
78                                       unsigned CommandID,
79                                       CommandMarkerKind CommandMarker) {
80   ParamCommandComment *Command =
81       new (Allocator) ParamCommandComment(LocBegin, LocEnd, CommandID,
82                                           CommandMarker);
83
84   if (!isFunctionDecl())
85     Diag(Command->getLocation(),
86          diag::warn_doc_param_not_attached_to_a_function_decl)
87       << CommandMarker
88       << Command->getCommandNameRange(Traits);
89
90   return Command;
91 }
92
93 void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) {
94   const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
95   if (!Info->IsFunctionDeclarationCommand)
96     return;
97
98   unsigned DiagSelect;
99   switch (Comment->getCommandID()) {
100     case CommandTraits::KCI_function:
101       DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 1 : 0;
102       break;
103     case CommandTraits::KCI_functiongroup:
104       DiagSelect = (!isAnyFunctionDecl() && !isFunctionTemplateDecl())? 2 : 0;
105       break;
106     case CommandTraits::KCI_method:
107       DiagSelect = !isObjCMethodDecl() ? 3 : 0;
108       break;
109     case CommandTraits::KCI_methodgroup:
110       DiagSelect = !isObjCMethodDecl() ? 4 : 0;
111       break;
112     case CommandTraits::KCI_callback:
113       DiagSelect = !isFunctionPointerVarDecl() ? 5 : 0;
114       break;
115     default:
116       DiagSelect = 0;
117       break;
118   }
119   if (DiagSelect)
120     Diag(Comment->getLocation(), diag::warn_doc_function_method_decl_mismatch)
121     << Comment->getCommandMarker()
122     << (DiagSelect-1) << (DiagSelect-1)
123     << Comment->getSourceRange();
124 }
125   
126 void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) {
127   const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
128   if (!Info->IsRecordLikeDeclarationCommand)
129     return;
130   unsigned DiagSelect;
131   switch (Comment->getCommandID()) {
132     case CommandTraits::KCI_class:
133       DiagSelect = (!isClassOrStructDecl() && !isClassTemplateDecl()) ? 1 : 0;
134       // Allow @class command on @interface declarations.
135       // FIXME. Currently, \class and @class are indistinguishable. So,
136       // \class is also allowed on an @interface declaration
137       if (DiagSelect && Comment->getCommandMarker() && isObjCInterfaceDecl())
138         DiagSelect = 0;
139       break;
140     case CommandTraits::KCI_interface:
141       DiagSelect = !isObjCInterfaceDecl() ? 2 : 0;
142       break;
143     case CommandTraits::KCI_protocol:
144       DiagSelect = !isObjCProtocolDecl() ? 3 : 0;
145       break;
146     case CommandTraits::KCI_struct:
147       DiagSelect = !isClassOrStructDecl() ? 4 : 0;
148       break;
149     case CommandTraits::KCI_union:
150       DiagSelect = !isUnionDecl() ? 5 : 0;
151       break;
152     default:
153       DiagSelect = 0;
154       break;
155   }
156   if (DiagSelect)
157     Diag(Comment->getLocation(), diag::warn_doc_api_container_decl_mismatch)
158     << Comment->getCommandMarker()
159     << (DiagSelect-1) << (DiagSelect-1)
160     << Comment->getSourceRange();
161 }
162
163 void Sema::checkContainerDecl(const BlockCommandComment *Comment) {
164   const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID());
165   if (!Info->IsRecordLikeDetailCommand || isRecordLikeDecl())
166     return;
167   unsigned DiagSelect;
168   switch (Comment->getCommandID()) {
169     case CommandTraits::KCI_classdesign:
170       DiagSelect = 1;
171       break;
172     case CommandTraits::KCI_coclass:
173       DiagSelect = 2;
174       break;
175     case CommandTraits::KCI_dependency:
176       DiagSelect = 3;
177       break;
178     case CommandTraits::KCI_helper:
179       DiagSelect = 4;
180       break;
181     case CommandTraits::KCI_helperclass:
182       DiagSelect = 5;
183       break;
184     case CommandTraits::KCI_helps:
185       DiagSelect = 6;
186       break;
187     case CommandTraits::KCI_instancesize:
188       DiagSelect = 7;
189       break;
190     case CommandTraits::KCI_ownership:
191       DiagSelect = 8;
192       break;
193     case CommandTraits::KCI_performance:
194       DiagSelect = 9;
195       break;
196     case CommandTraits::KCI_security:
197       DiagSelect = 10;
198       break;
199     case CommandTraits::KCI_superclass:
200       DiagSelect = 11;
201       break;
202     default:
203       DiagSelect = 0;
204       break;
205   }
206   if (DiagSelect)
207     Diag(Comment->getLocation(), diag::warn_doc_container_decl_mismatch)
208     << Comment->getCommandMarker()
209     << (DiagSelect-1)
210     << Comment->getSourceRange();
211 }
212
213 /// \brief Turn a string into the corresponding PassDirection or -1 if it's not
214 /// valid.
215 static int getParamPassDirection(StringRef Arg) {
216   return llvm::StringSwitch<int>(Arg)
217       .Case("[in]", ParamCommandComment::In)
218       .Case("[out]", ParamCommandComment::Out)
219       .Cases("[in,out]", "[out,in]", ParamCommandComment::InOut)
220       .Default(-1);
221 }
222
223 void Sema::actOnParamCommandDirectionArg(ParamCommandComment *Command,
224                                          SourceLocation ArgLocBegin,
225                                          SourceLocation ArgLocEnd,
226                                          StringRef Arg) {
227   std::string ArgLower = Arg.lower();
228   int Direction = getParamPassDirection(ArgLower);
229
230   if (Direction == -1) {
231     // Try again with whitespace removed.
232     ArgLower.erase(
233         std::remove_if(ArgLower.begin(), ArgLower.end(), clang::isWhitespace),
234         ArgLower.end());
235     Direction = getParamPassDirection(ArgLower);
236
237     SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
238     if (Direction != -1) {
239       const char *FixedName = ParamCommandComment::getDirectionAsString(
240           (ParamCommandComment::PassDirection)Direction);
241       Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction)
242           << ArgRange << FixItHint::CreateReplacement(ArgRange, FixedName);
243     } else {
244       Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange;
245       Direction = ParamCommandComment::In; // Sane fall back.
246     }
247   }
248   Command->setDirection((ParamCommandComment::PassDirection)Direction,
249                         /*Explicit=*/true);
250 }
251
252 void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command,
253                                          SourceLocation ArgLocBegin,
254                                          SourceLocation ArgLocEnd,
255                                          StringRef Arg) {
256   // Parser will not feed us more arguments than needed.
257   assert(Command->getNumArgs() == 0);
258
259   if (!Command->isDirectionExplicit()) {
260     // User didn't provide a direction argument.
261     Command->setDirection(ParamCommandComment::In, /* Explicit = */ false);
262   }
263   typedef BlockCommandComment::Argument Argument;
264   Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
265                                                      ArgLocEnd),
266                                          Arg);
267   Command->setArgs(llvm::makeArrayRef(A, 1));
268 }
269
270 void Sema::actOnParamCommandFinish(ParamCommandComment *Command,
271                                    ParagraphComment *Paragraph) {
272   Command->setParagraph(Paragraph);
273   checkBlockCommandEmptyParagraph(Command);
274 }
275
276 TParamCommandComment *Sema::actOnTParamCommandStart(
277                                       SourceLocation LocBegin,
278                                       SourceLocation LocEnd,
279                                       unsigned CommandID,
280                                       CommandMarkerKind CommandMarker) {
281   TParamCommandComment *Command =
282       new (Allocator) TParamCommandComment(LocBegin, LocEnd, CommandID,
283                                            CommandMarker);
284
285   if (!isTemplateOrSpecialization())
286     Diag(Command->getLocation(),
287          diag::warn_doc_tparam_not_attached_to_a_template_decl)
288       << CommandMarker
289       << Command->getCommandNameRange(Traits);
290
291   return Command;
292 }
293
294 void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command,
295                                           SourceLocation ArgLocBegin,
296                                           SourceLocation ArgLocEnd,
297                                           StringRef Arg) {
298   // Parser will not feed us more arguments than needed.
299   assert(Command->getNumArgs() == 0);
300
301   typedef BlockCommandComment::Argument Argument;
302   Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
303                                                      ArgLocEnd),
304                                          Arg);
305   Command->setArgs(llvm::makeArrayRef(A, 1));
306
307   if (!isTemplateOrSpecialization()) {
308     // We already warned that this \\tparam is not attached to a template decl.
309     return;
310   }
311
312   const TemplateParameterList *TemplateParameters =
313       ThisDeclInfo->TemplateParameters;
314   SmallVector<unsigned, 2> Position;
315   if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
316     Command->setPosition(copyArray(llvm::makeArrayRef(Position)));
317     TParamCommandComment *&PrevCommand = TemplateParameterDocs[Arg];
318     if (PrevCommand) {
319       SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
320       Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
321         << Arg << ArgRange;
322       Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous)
323         << PrevCommand->getParamNameRange();
324     }
325     PrevCommand = Command;
326     return;
327   }
328
329   SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
330   Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
331     << Arg << ArgRange;
332
333   if (!TemplateParameters || TemplateParameters->size() == 0)
334     return;
335
336   StringRef CorrectedName;
337   if (TemplateParameters->size() == 1) {
338     const NamedDecl *Param = TemplateParameters->getParam(0);
339     const IdentifierInfo *II = Param->getIdentifier();
340     if (II)
341       CorrectedName = II->getName();
342   } else {
343     CorrectedName = correctTypoInTParamReference(Arg, TemplateParameters);
344   }
345
346   if (!CorrectedName.empty()) {
347     Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
348       << CorrectedName
349       << FixItHint::CreateReplacement(ArgRange, CorrectedName);
350   }
351
352   return;
353 }
354
355 void Sema::actOnTParamCommandFinish(TParamCommandComment *Command,
356                                     ParagraphComment *Paragraph) {
357   Command->setParagraph(Paragraph);
358   checkBlockCommandEmptyParagraph(Command);
359 }
360
361 InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
362                                                SourceLocation CommandLocEnd,
363                                                unsigned CommandID) {
364   ArrayRef<InlineCommandComment::Argument> Args;
365   StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
366   return new (Allocator) InlineCommandComment(
367                                   CommandLocBegin,
368                                   CommandLocEnd,
369                                   CommandID,
370                                   getInlineCommandRenderKind(CommandName),
371                                   Args);
372 }
373
374 InlineCommandComment *Sema::actOnInlineCommand(SourceLocation CommandLocBegin,
375                                                SourceLocation CommandLocEnd,
376                                                unsigned CommandID,
377                                                SourceLocation ArgLocBegin,
378                                                SourceLocation ArgLocEnd,
379                                                StringRef Arg) {
380   typedef InlineCommandComment::Argument Argument;
381   Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
382                                                      ArgLocEnd),
383                                          Arg);
384   StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
385
386   return new (Allocator) InlineCommandComment(
387                                   CommandLocBegin,
388                                   CommandLocEnd,
389                                   CommandID,
390                                   getInlineCommandRenderKind(CommandName),
391                                   llvm::makeArrayRef(A, 1));
392 }
393
394 InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
395                                                 SourceLocation LocEnd,
396                                                 StringRef CommandName) {
397   unsigned CommandID = Traits.registerUnknownCommand(CommandName)->getID();
398   return actOnUnknownCommand(LocBegin, LocEnd, CommandID);
399 }
400
401 InlineContentComment *Sema::actOnUnknownCommand(SourceLocation LocBegin,
402                                                 SourceLocation LocEnd,
403                                                 unsigned CommandID) {
404   ArrayRef<InlineCommandComment::Argument> Args;
405   return new (Allocator) InlineCommandComment(
406                                   LocBegin, LocEnd, CommandID,
407                                   InlineCommandComment::RenderNormal,
408                                   Args);
409 }
410
411 TextComment *Sema::actOnText(SourceLocation LocBegin,
412                              SourceLocation LocEnd,
413                              StringRef Text) {
414   return new (Allocator) TextComment(LocBegin, LocEnd, Text);
415 }
416
417 VerbatimBlockComment *Sema::actOnVerbatimBlockStart(SourceLocation Loc,
418                                                     unsigned CommandID) {
419   StringRef CommandName = Traits.getCommandInfo(CommandID)->Name;
420   return new (Allocator) VerbatimBlockComment(
421                                   Loc,
422                                   Loc.getLocWithOffset(1 + CommandName.size()),
423                                   CommandID);
424 }
425
426 VerbatimBlockLineComment *Sema::actOnVerbatimBlockLine(SourceLocation Loc,
427                                                        StringRef Text) {
428   return new (Allocator) VerbatimBlockLineComment(Loc, Text);
429 }
430
431 void Sema::actOnVerbatimBlockFinish(
432                             VerbatimBlockComment *Block,
433                             SourceLocation CloseNameLocBegin,
434                             StringRef CloseName,
435                             ArrayRef<VerbatimBlockLineComment *> Lines) {
436   Block->setCloseName(CloseName, CloseNameLocBegin);
437   Block->setLines(Lines);
438 }
439
440 VerbatimLineComment *Sema::actOnVerbatimLine(SourceLocation LocBegin,
441                                              unsigned CommandID,
442                                              SourceLocation TextBegin,
443                                              StringRef Text) {
444   VerbatimLineComment *VL = new (Allocator) VerbatimLineComment(
445                               LocBegin,
446                               TextBegin.getLocWithOffset(Text.size()),
447                               CommandID,
448                               TextBegin,
449                               Text);
450   checkFunctionDeclVerbatimLine(VL);
451   checkContainerDeclVerbatimLine(VL);
452   return VL;
453 }
454
455 HTMLStartTagComment *Sema::actOnHTMLStartTagStart(SourceLocation LocBegin,
456                                                   StringRef TagName) {
457   return new (Allocator) HTMLStartTagComment(LocBegin, TagName);
458 }
459
460 void Sema::actOnHTMLStartTagFinish(
461                               HTMLStartTagComment *Tag,
462                               ArrayRef<HTMLStartTagComment::Attribute> Attrs,
463                               SourceLocation GreaterLoc,
464                               bool IsSelfClosing) {
465   Tag->setAttrs(Attrs);
466   Tag->setGreaterLoc(GreaterLoc);
467   if (IsSelfClosing)
468     Tag->setSelfClosing();
469   else if (!isHTMLEndTagForbidden(Tag->getTagName()))
470     HTMLOpenTags.push_back(Tag);
471 }
472
473 HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin,
474                                          SourceLocation LocEnd,
475                                          StringRef TagName) {
476   HTMLEndTagComment *HET =
477       new (Allocator) HTMLEndTagComment(LocBegin, LocEnd, TagName);
478   if (isHTMLEndTagForbidden(TagName)) {
479     Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden)
480       << TagName << HET->getSourceRange();
481     return HET;
482   }
483
484   bool FoundOpen = false;
485   for (SmallVectorImpl<HTMLStartTagComment *>::const_reverse_iterator
486        I = HTMLOpenTags.rbegin(), E = HTMLOpenTags.rend();
487        I != E; ++I) {
488     if ((*I)->getTagName() == TagName) {
489       FoundOpen = true;
490       break;
491     }
492   }
493   if (!FoundOpen) {
494     Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced)
495       << HET->getSourceRange();
496     return HET;
497   }
498
499   while (!HTMLOpenTags.empty()) {
500     const HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val();
501     StringRef LastNotClosedTagName = HST->getTagName();
502     if (LastNotClosedTagName == TagName)
503       break;
504
505     if (isHTMLEndTagOptional(LastNotClosedTagName))
506       continue;
507
508     bool OpenLineInvalid;
509     const unsigned OpenLine = SourceMgr.getPresumedLineNumber(
510                                                 HST->getLocation(),
511                                                 &OpenLineInvalid);
512     bool CloseLineInvalid;
513     const unsigned CloseLine = SourceMgr.getPresumedLineNumber(
514                                                 HET->getLocation(),
515                                                 &CloseLineInvalid);
516
517     if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine)
518       Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
519         << HST->getTagName() << HET->getTagName()
520         << HST->getSourceRange() << HET->getSourceRange();
521     else {
522       Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch)
523         << HST->getTagName() << HET->getTagName()
524         << HST->getSourceRange();
525       Diag(HET->getLocation(), diag::note_doc_html_end_tag)
526         << HET->getSourceRange();
527     }
528   }
529
530   return HET;
531 }
532
533 FullComment *Sema::actOnFullComment(
534                               ArrayRef<BlockContentComment *> Blocks) {
535   FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo);
536   resolveParamCommandIndexes(FC);
537   return FC;
538 }
539
540 void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) {
541   if (Traits.getCommandInfo(Command->getCommandID())->IsEmptyParagraphAllowed)
542     return;
543
544   ParagraphComment *Paragraph = Command->getParagraph();
545   if (Paragraph->isWhitespace()) {
546     SourceLocation DiagLoc;
547     if (Command->getNumArgs() > 0)
548       DiagLoc = Command->getArgRange(Command->getNumArgs() - 1).getEnd();
549     if (!DiagLoc.isValid())
550       DiagLoc = Command->getCommandNameRange(Traits).getEnd();
551     Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
552       << Command->getCommandMarker()
553       << Command->getCommandName(Traits)
554       << Command->getSourceRange();
555   }
556 }
557
558 void Sema::checkReturnsCommand(const BlockCommandComment *Command) {
559   if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand)
560     return;
561   if (isFunctionDecl()) {
562     if (ThisDeclInfo->ResultType->isVoidType()) {
563       unsigned DiagKind;
564       switch (ThisDeclInfo->CommentDecl->getKind()) {
565       default:
566         if (ThisDeclInfo->IsObjCMethod)
567           DiagKind = 3;
568         else
569           DiagKind = 0;
570         break;
571       case Decl::CXXConstructor:
572         DiagKind = 1;
573         break;
574       case Decl::CXXDestructor:
575         DiagKind = 2;
576         break;
577       }
578       Diag(Command->getLocation(),
579            diag::warn_doc_returns_attached_to_a_void_function)
580         << Command->getCommandMarker()
581         << Command->getCommandName(Traits)
582         << DiagKind
583         << Command->getSourceRange();
584     }
585     return;
586   }
587   else if (isObjCPropertyDecl())
588     return;
589   
590   Diag(Command->getLocation(),
591        diag::warn_doc_returns_not_attached_to_a_function_decl)
592     << Command->getCommandMarker()
593     << Command->getCommandName(Traits)
594     << Command->getSourceRange();
595 }
596
597 void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) {
598   const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID());
599   const BlockCommandComment *PrevCommand = NULL;
600   if (Info->IsBriefCommand) {
601     if (!BriefCommand) {
602       BriefCommand = Command;
603       return;
604     }
605     PrevCommand = BriefCommand;
606   } else if (Info->IsHeaderfileCommand) {
607     if (!HeaderfileCommand) {
608       HeaderfileCommand = Command;
609       return;
610     }
611     PrevCommand = HeaderfileCommand;
612   } else {
613     // We don't want to check this command for duplicates.
614     return;
615   }
616   StringRef CommandName = Command->getCommandName(Traits);
617   StringRef PrevCommandName = PrevCommand->getCommandName(Traits);
618   Diag(Command->getLocation(), diag::warn_doc_block_command_duplicate)
619       << Command->getCommandMarker()
620       << CommandName
621       << Command->getSourceRange();
622   if (CommandName == PrevCommandName)
623     Diag(PrevCommand->getLocation(), diag::note_doc_block_command_previous)
624         << PrevCommand->getCommandMarker()
625         << PrevCommandName
626         << PrevCommand->getSourceRange();
627   else
628     Diag(PrevCommand->getLocation(),
629          diag::note_doc_block_command_previous_alias)
630         << PrevCommand->getCommandMarker()
631         << PrevCommandName
632         << CommandName;
633 }
634
635 void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) {
636   if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand)
637     return;
638
639   const Decl *D = ThisDeclInfo->CommentDecl;
640   if (!D)
641     return;
642
643   if (D->hasAttr<DeprecatedAttr>() ||
644       D->hasAttr<AvailabilityAttr>() ||
645       D->hasAttr<UnavailableAttr>())
646     return;
647
648   Diag(Command->getLocation(),
649        diag::warn_doc_deprecated_not_sync)
650     << Command->getSourceRange();
651
652   // Try to emit a fixit with a deprecation attribute.
653   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
654     // Don't emit a Fix-It for non-member function definitions.  GCC does not
655     // accept attributes on them.
656     const DeclContext *Ctx = FD->getDeclContext();
657     if ((!Ctx || !Ctx->isRecord()) &&
658         FD->doesThisDeclarationHaveABody())
659       return;
660
661     StringRef AttributeSpelling = "__attribute__((deprecated))";
662     if (PP) {
663       TokenValue Tokens[] = {
664         tok::kw___attribute, tok::l_paren, tok::l_paren,
665         PP->getIdentifierInfo("deprecated"),
666         tok::r_paren, tok::r_paren
667       };
668       StringRef MacroName = PP->getLastMacroWithSpelling(FD->getLocation(),
669                                                          Tokens);
670       if (!MacroName.empty())
671         AttributeSpelling = MacroName;
672     }
673
674     SmallString<64> TextToInsert(" ");
675     TextToInsert += AttributeSpelling;
676     Diag(FD->getLocEnd(),
677          diag::note_add_deprecation_attr)
678       << FixItHint::CreateInsertion(FD->getLocEnd().getLocWithOffset(1),
679                                     TextToInsert);
680   }
681 }
682
683 void Sema::resolveParamCommandIndexes(const FullComment *FC) {
684   if (!isFunctionDecl()) {
685     // We already warned that \\param commands are not attached to a function
686     // decl.
687     return;
688   }
689
690   SmallVector<ParamCommandComment *, 8> UnresolvedParamCommands;
691
692   // Comment AST nodes that correspond to \c ParamVars for which we have
693   // found a \\param command or NULL if no documentation was found so far.
694   SmallVector<ParamCommandComment *, 8> ParamVarDocs;
695
696   ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();
697   ParamVarDocs.resize(ParamVars.size(), NULL);
698
699   // First pass over all \\param commands: resolve all parameter names.
700   for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end();
701        I != E; ++I) {
702     ParamCommandComment *PCC = dyn_cast<ParamCommandComment>(*I);
703     if (!PCC || !PCC->hasParamName())
704       continue;
705     StringRef ParamName = PCC->getParamNameAsWritten();
706
707     // Check that referenced parameter name is in the function decl.
708     const unsigned ResolvedParamIndex = resolveParmVarReference(ParamName,
709                                                                 ParamVars);
710     if (ResolvedParamIndex == ParamCommandComment::VarArgParamIndex) {
711       PCC->setIsVarArgParam();
712       continue;
713     }
714     if (ResolvedParamIndex == ParamCommandComment::InvalidParamIndex) {
715       UnresolvedParamCommands.push_back(PCC);
716       continue;
717     }
718     PCC->setParamIndex(ResolvedParamIndex);
719     if (ParamVarDocs[ResolvedParamIndex]) {
720       SourceRange ArgRange = PCC->getParamNameRange();
721       Diag(ArgRange.getBegin(), diag::warn_doc_param_duplicate)
722         << ParamName << ArgRange;
723       ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
724       Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
725         << PrevCommand->getParamNameRange();
726     }
727     ParamVarDocs[ResolvedParamIndex] = PCC;
728   }
729
730   // Find parameter declarations that have no corresponding \\param.
731   SmallVector<const ParmVarDecl *, 8> OrphanedParamDecls;
732   for (unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
733     if (!ParamVarDocs[i])
734       OrphanedParamDecls.push_back(ParamVars[i]);
735   }
736
737   // Second pass over unresolved \\param commands: do typo correction.
738   // Suggest corrections from a set of parameter declarations that have no
739   // corresponding \\param.
740   for (unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
741     const ParamCommandComment *PCC = UnresolvedParamCommands[i];
742
743     SourceRange ArgRange = PCC->getParamNameRange();
744     StringRef ParamName = PCC->getParamNameAsWritten();
745     Diag(ArgRange.getBegin(), diag::warn_doc_param_not_found)
746       << ParamName << ArgRange;
747
748     // All parameters documented -- can't suggest a correction.
749     if (OrphanedParamDecls.size() == 0)
750       continue;
751
752     unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
753     if (OrphanedParamDecls.size() == 1) {
754       // If one parameter is not documented then that parameter is the only
755       // possible suggestion.
756       CorrectedParamIndex = 0;
757     } else {
758       // Do typo correction.
759       CorrectedParamIndex = correctTypoInParmVarReference(ParamName,
760                                                           OrphanedParamDecls);
761     }
762     if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
763       const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
764       if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
765         Diag(ArgRange.getBegin(), diag::note_doc_param_name_suggestion)
766           << CorrectedII->getName()
767           << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
768     }
769   }
770 }
771
772 bool Sema::isFunctionDecl() {
773   if (!ThisDeclInfo)
774     return false;
775   if (!ThisDeclInfo->IsFilled)
776     inspectThisDecl();
777   return ThisDeclInfo->getKind() == DeclInfo::FunctionKind;
778 }
779
780 bool Sema::isAnyFunctionDecl() {
781   return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
782          isa<FunctionDecl>(ThisDeclInfo->CurrentDecl);
783 }
784
785 bool Sema::isFunctionOrMethodVariadic() {
786   if (!isAnyFunctionDecl() && !isObjCMethodDecl())
787     return false;
788   if (const FunctionDecl *FD =
789         dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl))
790     return FD->isVariadic();
791   if (const ObjCMethodDecl *MD =
792         dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl))
793     return MD->isVariadic();
794   return false;
795 }
796
797 bool Sema::isObjCMethodDecl() {
798   return isFunctionDecl() && ThisDeclInfo->CurrentDecl &&
799          isa<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl);
800 }
801
802 bool Sema::isFunctionPointerVarDecl() {
803   if (!ThisDeclInfo)
804     return false;
805   if (!ThisDeclInfo->IsFilled)
806     inspectThisDecl();
807   if (ThisDeclInfo->getKind() == DeclInfo::VariableKind) {
808     if (const VarDecl *VD = dyn_cast_or_null<VarDecl>(ThisDeclInfo->CurrentDecl)) {
809       QualType QT = VD->getType();
810       return QT->isFunctionPointerType();
811     }
812   }
813   return false;
814 }
815   
816 bool Sema::isObjCPropertyDecl() {
817   if (!ThisDeclInfo)
818     return false;
819   if (!ThisDeclInfo->IsFilled)
820     inspectThisDecl();
821   return ThisDeclInfo->CurrentDecl->getKind() == Decl::ObjCProperty;
822 }
823
824 bool Sema::isTemplateOrSpecialization() {
825   if (!ThisDeclInfo)
826     return false;
827   if (!ThisDeclInfo->IsFilled)
828     inspectThisDecl();
829   return ThisDeclInfo->getTemplateKind() != DeclInfo::NotTemplate;
830 }
831
832 bool Sema::isRecordLikeDecl() {
833   if (!ThisDeclInfo)
834     return false;
835   if (!ThisDeclInfo->IsFilled)
836     inspectThisDecl();
837   return isUnionDecl() || isClassOrStructDecl() 
838          || isObjCInterfaceDecl() || isObjCProtocolDecl();
839 }
840
841 bool Sema::isUnionDecl() {
842   if (!ThisDeclInfo)
843     return false;
844   if (!ThisDeclInfo->IsFilled)
845     inspectThisDecl();
846   if (const RecordDecl *RD =
847         dyn_cast_or_null<RecordDecl>(ThisDeclInfo->CurrentDecl))
848     return RD->isUnion();
849   return false;
850 }
851   
852 bool Sema::isClassOrStructDecl() {
853   if (!ThisDeclInfo)
854     return false;
855   if (!ThisDeclInfo->IsFilled)
856     inspectThisDecl();
857   return ThisDeclInfo->CurrentDecl &&
858          isa<RecordDecl>(ThisDeclInfo->CurrentDecl) &&
859          !isUnionDecl();
860 }
861   
862 bool Sema::isClassTemplateDecl() {
863   if (!ThisDeclInfo)
864     return false;
865   if (!ThisDeclInfo->IsFilled)
866     inspectThisDecl();
867   return ThisDeclInfo->CurrentDecl &&
868           (isa<ClassTemplateDecl>(ThisDeclInfo->CurrentDecl));
869 }
870
871 bool Sema::isFunctionTemplateDecl() {
872   if (!ThisDeclInfo)
873     return false;
874   if (!ThisDeclInfo->IsFilled)
875     inspectThisDecl();
876   return ThisDeclInfo->CurrentDecl &&
877   (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl));
878 }
879
880 bool Sema::isObjCInterfaceDecl() {
881   if (!ThisDeclInfo)
882     return false;
883   if (!ThisDeclInfo->IsFilled)
884     inspectThisDecl();
885   return ThisDeclInfo->CurrentDecl &&
886          isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl);
887 }
888   
889 bool Sema::isObjCProtocolDecl() {
890   if (!ThisDeclInfo)
891     return false;
892   if (!ThisDeclInfo->IsFilled)
893     inspectThisDecl();
894   return ThisDeclInfo->CurrentDecl &&
895          isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl);
896 }
897   
898 ArrayRef<const ParmVarDecl *> Sema::getParamVars() {
899   if (!ThisDeclInfo->IsFilled)
900     inspectThisDecl();
901   return ThisDeclInfo->ParamVars;
902 }
903
904 void Sema::inspectThisDecl() {
905   ThisDeclInfo->fill();
906 }
907
908 unsigned Sema::resolveParmVarReference(StringRef Name,
909                                        ArrayRef<const ParmVarDecl *> ParamVars) {
910   for (unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
911     const IdentifierInfo *II = ParamVars[i]->getIdentifier();
912     if (II && II->getName() == Name)
913       return i;
914   }
915   if (Name == "..." && isFunctionOrMethodVariadic())
916     return ParamCommandComment::VarArgParamIndex;
917   return ParamCommandComment::InvalidParamIndex;
918 }
919
920 namespace {
921 class SimpleTypoCorrector {
922   StringRef Typo;
923   const unsigned MaxEditDistance;
924
925   const NamedDecl *BestDecl;
926   unsigned BestEditDistance;
927   unsigned BestIndex;
928   unsigned NextIndex;
929
930 public:
931   SimpleTypoCorrector(StringRef Typo) :
932       Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
933       BestDecl(NULL), BestEditDistance(MaxEditDistance + 1),
934       BestIndex(0), NextIndex(0)
935   { }
936
937   void addDecl(const NamedDecl *ND);
938
939   const NamedDecl *getBestDecl() const {
940     if (BestEditDistance > MaxEditDistance)
941       return NULL;
942
943     return BestDecl;
944   }
945
946   unsigned getBestDeclIndex() const {
947     assert(getBestDecl());
948     return BestIndex;
949   }
950 };
951
952 void SimpleTypoCorrector::addDecl(const NamedDecl *ND) {
953   unsigned CurrIndex = NextIndex++;
954
955   const IdentifierInfo *II = ND->getIdentifier();
956   if (!II)
957     return;
958
959   StringRef Name = II->getName();
960   unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size());
961   if (MinPossibleEditDistance > 0 &&
962       Typo.size() / MinPossibleEditDistance < 3)
963     return;
964
965   unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance);
966   if (EditDistance < BestEditDistance) {
967     BestEditDistance = EditDistance;
968     BestDecl = ND;
969     BestIndex = CurrIndex;
970   }
971 }
972 } // unnamed namespace
973
974 unsigned Sema::correctTypoInParmVarReference(
975                                     StringRef Typo,
976                                     ArrayRef<const ParmVarDecl *> ParamVars) {
977   SimpleTypoCorrector Corrector(Typo);
978   for (unsigned i = 0, e = ParamVars.size(); i != e; ++i)
979     Corrector.addDecl(ParamVars[i]);
980   if (Corrector.getBestDecl())
981     return Corrector.getBestDeclIndex();
982   else
983     return ParamCommandComment::InvalidParamIndex;
984 }
985
986 namespace {
987 bool ResolveTParamReferenceHelper(
988                             StringRef Name,
989                             const TemplateParameterList *TemplateParameters,
990                             SmallVectorImpl<unsigned> *Position) {
991   for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
992     const NamedDecl *Param = TemplateParameters->getParam(i);
993     const IdentifierInfo *II = Param->getIdentifier();
994     if (II && II->getName() == Name) {
995       Position->push_back(i);
996       return true;
997     }
998
999     if (const TemplateTemplateParmDecl *TTP =
1000             dyn_cast<TemplateTemplateParmDecl>(Param)) {
1001       Position->push_back(i);
1002       if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
1003                                        Position))
1004         return true;
1005       Position->pop_back();
1006     }
1007   }
1008   return false;
1009 }
1010 } // unnamed namespace
1011
1012 bool Sema::resolveTParamReference(
1013                             StringRef Name,
1014                             const TemplateParameterList *TemplateParameters,
1015                             SmallVectorImpl<unsigned> *Position) {
1016   Position->clear();
1017   if (!TemplateParameters)
1018     return false;
1019
1020   return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
1021 }
1022
1023 namespace {
1024 void CorrectTypoInTParamReferenceHelper(
1025                             const TemplateParameterList *TemplateParameters,
1026                             SimpleTypoCorrector &Corrector) {
1027   for (unsigned i = 0, e = TemplateParameters->size(); i != e; ++i) {
1028     const NamedDecl *Param = TemplateParameters->getParam(i);
1029     Corrector.addDecl(Param);
1030
1031     if (const TemplateTemplateParmDecl *TTP =
1032             dyn_cast<TemplateTemplateParmDecl>(Param))
1033       CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
1034                                          Corrector);
1035   }
1036 }
1037 } // unnamed namespace
1038
1039 StringRef Sema::correctTypoInTParamReference(
1040                             StringRef Typo,
1041                             const TemplateParameterList *TemplateParameters) {
1042   SimpleTypoCorrector Corrector(Typo);
1043   CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
1044   if (const NamedDecl *ND = Corrector.getBestDecl()) {
1045     const IdentifierInfo *II = ND->getIdentifier();
1046     assert(II && "SimpleTypoCorrector should not return this decl");
1047     return II->getName();
1048   }
1049   return StringRef();
1050 }
1051
1052 InlineCommandComment::RenderKind
1053 Sema::getInlineCommandRenderKind(StringRef Name) const {
1054   assert(Traits.getCommandInfo(Name)->IsInlineCommand);
1055
1056   return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
1057       .Case("b", InlineCommandComment::RenderBold)
1058       .Cases("c", "p", InlineCommandComment::RenderMonospaced)
1059       .Cases("a", "e", "em", InlineCommandComment::RenderEmphasized)
1060       .Default(InlineCommandComment::RenderNormal);
1061 }
1062
1063 } // end namespace comments
1064 } // end namespace clang
1065