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