18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/StringSwitch.h"
25 #include "clang/AST/CommentHTMLTagsProperties.inc"
31 Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
32 PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr),
33 HeaderfileCommand(nullptr) {
40 ThisDeclInfo =
new (Allocator)
DeclInfo;
91 diag::warn_doc_param_not_attached_to_a_function_decl)
105 case CommandTraits::KCI_function:
108 case CommandTraits::KCI_functiongroup:
111 case CommandTraits::KCI_method:
114 case CommandTraits::KCI_methodgroup:
117 case CommandTraits::KCI_callback:
125 Diag(Comment->
getLocation(), diag::warn_doc_function_method_decl_mismatch)
127 << (DiagSelect-1) << (DiagSelect-1)
137 case CommandTraits::KCI_class:
145 case CommandTraits::KCI_interface:
148 case CommandTraits::KCI_protocol:
151 case CommandTraits::KCI_struct:
154 case CommandTraits::KCI_union:
162 Diag(Comment->
getLocation(), diag::warn_doc_api_container_decl_mismatch)
164 << (DiagSelect-1) << (DiagSelect-1)
174 case CommandTraits::KCI_classdesign:
177 case CommandTraits::KCI_coclass:
180 case CommandTraits::KCI_dependency:
183 case CommandTraits::KCI_helper:
186 case CommandTraits::KCI_helperclass:
189 case CommandTraits::KCI_helps:
192 case CommandTraits::KCI_instancesize:
195 case CommandTraits::KCI_ownership:
198 case CommandTraits::KCI_performance:
201 case CommandTraits::KCI_security:
204 case CommandTraits::KCI_superclass:
212 Diag(Comment->
getLocation(), diag::warn_doc_container_decl_mismatch)
221 return llvm::StringSwitch<int>(Arg)
232 std::string ArgLower = Arg.lower();
235 if (Direction == -1) {
243 if (Direction != -1) {
246 Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction)
249 Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange;
269 Argument *A =
new (Allocator) Argument(
SourceRange(ArgLocBegin,
272 Command->
setArgs(llvm::makeArrayRef(A, 1));
292 diag::warn_doc_tparam_not_attached_to_a_template_decl)
307 Argument *A =
new (Allocator) Argument(
SourceRange(ArgLocBegin,
310 Command->
setArgs(llvm::makeArrayRef(A, 1));
325 Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
327 Diag(PrevCommand->
getLocation(), diag::note_doc_tparam_previous)
330 PrevCommand = Command;
335 Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
338 if (!TemplateParameters || TemplateParameters->
size() == 0)
341 StringRef CorrectedName;
342 if (TemplateParameters->
size() == 1) {
351 if (!CorrectedName.empty()) {
352 Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
366 unsigned CommandID) {
384 Argument *A =
new (Allocator) Argument(
SourceRange(ArgLocBegin,
394 llvm::makeArrayRef(A, 1));
399 StringRef CommandName) {
406 unsigned CommandID) {
409 LocBegin, LocEnd, CommandID,
417 return new (Allocator)
TextComment(LocBegin, LocEnd, Text);
421 unsigned CommandID) {
467 bool IsSelfClosing) {
472 else if (!isHTMLEndTagForbidden(Tag->
getTagName()))
473 HTMLOpenTags.push_back(Tag);
481 if (isHTMLEndTagForbidden(TagName)) {
482 Diag(HET->
getLocation(), diag::warn_doc_html_end_forbidden)
488 bool FoundOpen =
false;
490 I = HTMLOpenTags.rbegin(),
E = HTMLOpenTags.rend();
492 if ((*I)->getTagName() == TagName) {
498 Diag(HET->
getLocation(), diag::warn_doc_html_end_unbalanced)
504 while (!HTMLOpenTags.empty()) {
506 StringRef LastNotClosedTagName = HST->
getTagName();
507 if (LastNotClosedTagName == TagName) {
514 if (isHTMLEndTagOptional(LastNotClosedTagName))
517 bool OpenLineInvalid;
521 bool CloseLineInvalid;
526 if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) {
527 Diag(HST->
getLocation(), diag::warn_doc_html_start_end_mismatch)
532 Diag(HST->
getLocation(), diag::warn_doc_html_start_end_mismatch)
535 Diag(HET->
getLocation(), diag::note_doc_html_end_tag)
550 while (!HTMLOpenTags.empty()) {
555 Diag(HST->
getLocation(), diag::warn_doc_html_missing_end_tag)
574 Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
585 assert(ThisDeclInfo &&
"should not call this check on a bare comment");
597 case Decl::CXXConstructor:
600 case Decl::CXXDestructor:
605 diag::warn_doc_returns_attached_to_a_void_function)
617 diag::warn_doc_returns_not_attached_to_a_function_decl)
628 BriefCommand = Command;
631 PrevCommand = BriefCommand;
633 if (!HeaderfileCommand) {
634 HeaderfileCommand = Command;
637 PrevCommand = HeaderfileCommand;
644 Diag(Command->
getLocation(), diag::warn_doc_block_command_duplicate)
648 if (CommandName == PrevCommandName)
649 Diag(PrevCommand->
getLocation(), diag::note_doc_block_command_previous)
655 diag::note_doc_block_command_previous_alias)
665 assert(ThisDeclInfo &&
"should not call this check on a bare comment");
671 if (D->hasAttr<DeprecatedAttr>() ||
672 D->hasAttr<AvailabilityAttr>() ||
673 D->hasAttr<UnavailableAttr>())
677 diag::warn_doc_deprecated_not_sync)
681 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
686 FD->doesThisDeclarationHaveABody())
689 StringRef AttributeSpelling =
"__attribute__((deprecated))";
692 tok::kw___attribute, tok::l_paren, tok::l_paren,
694 tok::r_paren, tok::r_paren
698 if (!MacroName.empty())
699 AttributeSpelling = MacroName;
703 TextToInsert += AttributeSpelling;
704 Diag(FD->getLocEnd(),
705 diag::note_add_deprecation_attr)
725 ParamVarDocs.resize(ParamVars.size(),
nullptr);
743 UnresolvedParamCommands.push_back(PCC);
747 if (ParamVarDocs[ResolvedParamIndex]) {
749 Diag(ArgRange.
getBegin(), diag::warn_doc_param_duplicate)
750 << ParamName << ArgRange;
752 Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
753 << PrevCommand->getParamNameRange();
755 ParamVarDocs[ResolvedParamIndex] = PCC;
760 for (
unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
761 if (!ParamVarDocs[i])
762 OrphanedParamDecls.push_back(ParamVars[i]);
768 for (
unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
773 Diag(ArgRange.
getBegin(), diag::warn_doc_param_not_found)
774 << ParamName << ArgRange;
777 if (OrphanedParamDecls.size() == 0)
781 if (OrphanedParamDecls.size() == 1) {
784 CorrectedParamIndex = 0;
791 const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
793 Diag(ArgRange.
getBegin(), diag::note_doc_param_name_suggestion)
794 << CorrectedII->getName()
818 return FD->isVariadic();
820 dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->
CurrentDecl))
821 return FTD->getTemplatedDecl()->isVariadic();
823 dyn_cast<ObjCMethodDecl>(ThisDeclInfo->
CurrentDecl))
824 return MD->isVariadic();
852 return ThisDeclInfo->
CurrentDecl->getKind() == Decl::ObjCProperty;
878 dyn_cast_or_null<RecordDecl>(ThisDeclInfo->
CurrentDecl))
879 return RD->isUnion();
899 (isa<ClassTemplateDecl>(ThisDeclInfo->
CurrentDecl));
908 (isa<FunctionTemplateDecl>(ThisDeclInfo->
CurrentDecl));
936 ThisDeclInfo->
fill();
941 for (
unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
952 class SimpleTypoCorrector {
962 SimpleTypoCorrector(StringRef
Typo) :
968 void addDecl(
const NamedDecl *ND);
970 const NamedDecl *getBestDecl()
const {
977 unsigned getBestDeclIndex()
const {
978 assert(getBestDecl());
983 void SimpleTypoCorrector::addDecl(
const NamedDecl *ND) {
986 const IdentifierInfo *II = ND->getIdentifier();
991 unsigned MinPossibleEditDistance =
abs((
int)Name.size() - (int)
Typo.size());
992 if (MinPossibleEditDistance > 0 &&
993 Typo.size() / MinPossibleEditDistance < 3)
1008 SimpleTypoCorrector Corrector(Typo);
1009 for (
unsigned i = 0, e = ParamVars.size(); i != e; ++i)
1010 Corrector.addDecl(ParamVars[i]);
1011 if (Corrector.getBestDecl())
1012 return Corrector.getBestDeclIndex();
1018 bool ResolveTParamReferenceHelper(
1022 for (
unsigned i = 0, e = TemplateParameters->
size(); i != e; ++i) {
1026 Position->push_back(i);
1031 dyn_cast<TemplateTemplateParmDecl>(Param)) {
1032 Position->push_back(i);
1033 if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
1036 Position->pop_back();
1048 if (!TemplateParameters)
1051 return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
1055 void CorrectTypoInTParamReferenceHelper(
1057 SimpleTypoCorrector &Corrector) {
1058 for (
unsigned i = 0, e = TemplateParameters->
size(); i != e; ++i) {
1060 Corrector.addDecl(Param);
1063 dyn_cast<TemplateTemplateParmDecl>(Param))
1064 CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
1073 SimpleTypoCorrector Corrector(Typo);
1074 CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
1075 if (
const NamedDecl *ND = Corrector.getBestDecl()) {
1077 assert(II &&
"SimpleTypoCorrector should not return this decl");
1087 return llvm::StringSwitch<InlineCommandComment::RenderKind>(
Name)
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
SourceLocation getEnd() const
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
A (possibly-)qualified type.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
static LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t', '\f', '\v', '\n', '\r'.
Defines the SourceManager interface.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
__DEVICE__ long long abs(long long __n)
Defines the C++ template declaration subclasses.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
NamedDecl * getParam(unsigned Idx)
VarDecl - An instance of this class is created to represent a variable declaration or definition...
ObjCMethodDecl - Represents an instance or class method declaration.
Stores a list of template parameters for a TemplateDecl and its derived classes.
ParmVarDecl - Represents a parameter to a function.
RecordDecl - Represents a struct/union/class.
One of these records is kept for each identifier that is lexed.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
Concrete class used by the front-end to report problems and issues.
detail::InMemoryDirectory::const_iterator I
bool isFunctionPointerType() const
StringRef getName() const
Return the actual identifier string.
Defines the clang::Preprocessor interface.
Stores token information for comparing actual tokens with predefined values.
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
ArrayRef< FormatToken * > Tokens
SourceLocation getBegin() const
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
detail::InMemoryDirectory::const_iterator E
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
A trivial tuple used to represent a source range.
NamedDecl - This represents a decl with a name.
This class handles loading and caching of source files into memory.
Declaration of a template function.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.