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