17 #include "llvm/ADT/SmallString.h" 18 #include "llvm/ADT/StringSwitch.h" 24 #include "clang/AST/CommentHTMLTagsProperties.inc" 27 Sema::Sema(llvm::BumpPtrAllocator &Allocator,
const SourceManager &SourceMgr,
30 Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits),
31 PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr),
32 HeaderfileCommand(nullptr) {
39 ThisDeclInfo =
new (Allocator)
DeclInfo;
90 diag::warn_doc_param_not_attached_to_a_function_decl)
104 case CommandTraits::KCI_function:
107 case CommandTraits::KCI_functiongroup:
110 case CommandTraits::KCI_method:
113 case CommandTraits::KCI_methodgroup:
116 case CommandTraits::KCI_callback:
124 Diag(Comment->
getLocation(), diag::warn_doc_function_method_decl_mismatch)
126 << (DiagSelect-1) << (DiagSelect-1)
136 case CommandTraits::KCI_class:
144 case CommandTraits::KCI_interface:
147 case CommandTraits::KCI_protocol:
150 case CommandTraits::KCI_struct:
153 case CommandTraits::KCI_union:
161 Diag(Comment->
getLocation(), diag::warn_doc_api_container_decl_mismatch)
163 << (DiagSelect-1) << (DiagSelect-1)
173 case CommandTraits::KCI_classdesign:
176 case CommandTraits::KCI_coclass:
179 case CommandTraits::KCI_dependency:
182 case CommandTraits::KCI_helper:
185 case CommandTraits::KCI_helperclass:
188 case CommandTraits::KCI_helps:
191 case CommandTraits::KCI_instancesize:
194 case CommandTraits::KCI_ownership:
197 case CommandTraits::KCI_performance:
200 case CommandTraits::KCI_security:
203 case CommandTraits::KCI_superclass:
211 Diag(Comment->
getLocation(), diag::warn_doc_container_decl_mismatch)
220 return llvm::StringSwitch<int>(Arg)
231 std::string ArgLower = Arg.lower();
234 if (Direction == -1) {
242 if (Direction != -1) {
245 Diag(ArgLocBegin, diag::warn_doc_param_spaces_in_direction)
248 Diag(ArgLocBegin, diag::warn_doc_param_invalid_direction) << ArgRange;
268 Argument *A =
new (Allocator) Argument(
SourceRange(ArgLocBegin,
271 Command->
setArgs(llvm::makeArrayRef(A, 1));
291 diag::warn_doc_tparam_not_attached_to_a_template_decl)
306 Argument *A =
new (Allocator) Argument(
SourceRange(ArgLocBegin,
309 Command->
setArgs(llvm::makeArrayRef(A, 1));
324 Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
326 Diag(PrevCommand->
getLocation(), diag::note_doc_tparam_previous)
329 PrevCommand = Command;
334 Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
337 if (!TemplateParameters || TemplateParameters->
size() == 0)
340 StringRef CorrectedName;
341 if (TemplateParameters->
size() == 1) {
350 if (!CorrectedName.empty()) {
351 Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
365 unsigned CommandID) {
383 Argument *A =
new (Allocator) Argument(
SourceRange(ArgLocBegin,
393 llvm::makeArrayRef(A, 1));
398 StringRef CommandName) {
405 unsigned CommandID) {
408 LocBegin, LocEnd, CommandID,
416 return new (Allocator)
TextComment(LocBegin, LocEnd, Text);
420 unsigned CommandID) {
466 bool IsSelfClosing) {
471 else if (!isHTMLEndTagForbidden(Tag->
getTagName()))
472 HTMLOpenTags.push_back(Tag);
480 if (isHTMLEndTagForbidden(TagName)) {
481 Diag(HET->
getLocation(), diag::warn_doc_html_end_forbidden)
487 bool FoundOpen =
false;
489 I = HTMLOpenTags.rbegin(), E = HTMLOpenTags.rend();
491 if ((*I)->getTagName() == TagName) {
497 Diag(HET->
getLocation(), diag::warn_doc_html_end_unbalanced)
503 while (!HTMLOpenTags.empty()) {
505 StringRef LastNotClosedTagName = HST->
getTagName();
506 if (LastNotClosedTagName == TagName) {
513 if (isHTMLEndTagOptional(LastNotClosedTagName))
516 bool OpenLineInvalid;
520 bool CloseLineInvalid;
525 if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) {
526 Diag(HST->
getLocation(), diag::warn_doc_html_start_end_mismatch)
531 Diag(HST->
getLocation(), diag::warn_doc_html_start_end_mismatch)
534 Diag(HET->
getLocation(), diag::note_doc_html_end_tag)
549 while (!HTMLOpenTags.empty()) {
554 Diag(HST->
getLocation(), diag::warn_doc_html_missing_end_tag)
573 Diag(DiagLoc, diag::warn_doc_block_command_empty_paragraph)
584 assert(ThisDeclInfo &&
"should not call this check on a bare comment");
592 "should have a valid return type");
602 case Decl::CXXConstructor:
605 case Decl::CXXDestructor:
610 diag::warn_doc_returns_attached_to_a_void_function)
620 diag::warn_doc_returns_not_attached_to_a_function_decl)
631 BriefCommand = Command;
634 PrevCommand = BriefCommand;
636 if (!HeaderfileCommand) {
637 HeaderfileCommand = Command;
640 PrevCommand = HeaderfileCommand;
647 Diag(Command->
getLocation(), diag::warn_doc_block_command_duplicate)
651 if (CommandName == PrevCommandName)
652 Diag(PrevCommand->
getLocation(), diag::note_doc_block_command_previous)
658 diag::note_doc_block_command_previous_alias)
668 assert(ThisDeclInfo &&
"should not call this check on a bare comment");
674 if (D->
hasAttr<DeprecatedAttr>() ||
675 D->
hasAttr<AvailabilityAttr>() ||
679 Diag(Command->
getLocation(), diag::warn_doc_deprecated_not_sync)
683 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
688 FD->doesThisDeclarationHaveABody())
691 const LangOptions &LO = FD->getASTContext().getLangOpts();
692 const bool DoubleSquareBracket = LO.CPlusPlus14 || LO.C2x;
693 StringRef AttributeSpelling =
694 DoubleSquareBracket ?
"[[deprecated]]" :
"__attribute__((deprecated))";
700 if (DoubleSquareBracket) {
701 TokenValue Tokens[] = {tok::l_square, tok::l_square,
703 tok::r_square, tok::r_square};
705 if (!MacroName.empty())
706 AttributeSpelling = MacroName;
709 if (MacroName.empty()) {
711 tok::kw___attribute, tok::l_paren,
713 tok::r_paren, tok::r_paren};
714 StringRef MacroName =
716 if (!MacroName.empty())
717 AttributeSpelling = MacroName;
724 Diag(Loc, diag::note_add_deprecation_attr)
743 ParamVarDocs.resize(ParamVars.size(),
nullptr);
761 UnresolvedParamCommands.push_back(PCC);
765 if (ParamVarDocs[ResolvedParamIndex]) {
767 Diag(ArgRange.
getBegin(), diag::warn_doc_param_duplicate)
768 << ParamName << ArgRange;
770 Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
771 << PrevCommand->getParamNameRange();
773 ParamVarDocs[ResolvedParamIndex] = PCC;
778 for (
unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
779 if (!ParamVarDocs[i])
780 OrphanedParamDecls.push_back(ParamVars[i]);
786 for (
unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
791 Diag(ArgRange.
getBegin(), diag::warn_doc_param_not_found)
792 << ParamName << ArgRange;
795 if (OrphanedParamDecls.size() == 0)
799 if (OrphanedParamDecls.size() == 1) {
802 CorrectedParamIndex = 0;
809 const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
811 Diag(ArgRange.
getBegin(), diag::note_doc_param_name_suggestion)
812 << CorrectedII->getName()
836 return FD->isVariadic();
838 dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->
CurrentDecl))
839 return FTD->getTemplatedDecl()->isVariadic();
841 dyn_cast<ObjCMethodDecl>(ThisDeclInfo->
CurrentDecl))
842 return MD->isVariadic();
844 dyn_cast<TypedefNameDecl>(ThisDeclInfo->
CurrentDecl)) {
849 return FT->isVariadic();
882 if (
const auto *VD = dyn_cast<DeclaratorDecl>(ThisDeclInfo->
CurrentDecl))
884 else if (
const auto *PD =
885 dyn_cast<ObjCPropertyDecl>(ThisDeclInfo->
CurrentDecl))
934 dyn_cast_or_null<RecordDecl>(ThisDeclInfo->
CurrentDecl))
935 return RD->isUnion();
955 (isa<ClassTemplateDecl>(ThisDeclInfo->
CurrentDecl));
964 (isa<FunctionTemplateDecl>(ThisDeclInfo->
CurrentDecl));
992 ThisDeclInfo->
fill();
997 for (
unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
999 if (II && II->
getName() == Name)
1008 class SimpleTypoCorrector {
1012 const unsigned MaxEditDistance;
1014 unsigned BestEditDistance;
1019 explicit SimpleTypoCorrector(StringRef Typo)
1020 : BestDecl(
nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
1021 BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}
1026 if (BestEditDistance > MaxEditDistance)
1032 unsigned getBestDeclIndex()
const {
1033 assert(getBestDecl());
1038 void SimpleTypoCorrector::addDecl(
const NamedDecl *ND) {
1039 unsigned CurrIndex = NextIndex++;
1045 StringRef Name = II->
getName();
1046 unsigned MinPossibleEditDistance =
abs((
int)Name.size() - (int)Typo.size());
1047 if (MinPossibleEditDistance > 0 &&
1048 Typo.size() / MinPossibleEditDistance < 3)
1051 unsigned EditDistance = Typo.edit_distance(Name,
true, MaxEditDistance);
1052 if (EditDistance < BestEditDistance) {
1053 BestEditDistance = EditDistance;
1055 BestIndex = CurrIndex;
1063 SimpleTypoCorrector Corrector(Typo);
1064 for (
unsigned i = 0, e = ParamVars.size(); i != e; ++i)
1065 Corrector.addDecl(ParamVars[i]);
1066 if (Corrector.getBestDecl())
1067 return Corrector.getBestDeclIndex();
1073 bool ResolveTParamReferenceHelper(
1077 for (
unsigned i = 0, e = TemplateParameters->
size(); i != e; ++i) {
1080 if (II && II->
getName() == Name) {
1081 Position->push_back(i);
1086 dyn_cast<TemplateTemplateParmDecl>(Param)) {
1087 Position->push_back(i);
1088 if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
1091 Position->pop_back();
1103 if (!TemplateParameters)
1106 return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
1110 void CorrectTypoInTParamReferenceHelper(
1112 SimpleTypoCorrector &Corrector) {
1113 for (
unsigned i = 0, e = TemplateParameters->
size(); i != e; ++i) {
1115 Corrector.addDecl(Param);
1118 dyn_cast<TemplateTemplateParmDecl>(Param))
1119 CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
1128 SimpleTypoCorrector Corrector(Typo);
1129 CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
1130 if (
const NamedDecl *ND = Corrector.getBestDecl()) {
1132 assert(II &&
"SimpleTypoCorrector should not return this decl");
1140 assert(Traits.getCommandInfo(Name)->IsInlineCommand);
1142 return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
Represents a function declaration or definition.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isBlockPointerType() const
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
Defines the SourceManager interface.
Decl - This represents one declaration (or definition), e.g.
__DEVICE__ long long abs(long long __n)
Defines the C++ template declaration subclasses.
The base class of the type hierarchy.
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
NamedDecl * getParam(unsigned Idx)
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
ObjCMethodDecl - Represents an instance or class method declaration.
Stores a list of template parameters for a TemplateDecl and its derived classes.
Represents a parameter to a function.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Represents a struct/union/class.
One of these records is kept for each identifier that is lexed.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
LLVM_READONLY bool isWhitespace(unsigned char c)
Return true if this character is horizontal or vertical ASCII whitespace: ' ', '\t', '\f', '\v', '\n', '\r'.
Concrete class used by the front-end to report problems and issues.
Represents a prototype with parameter type info, e.g.
Defines the clang::Preprocessor interface.
Stores token information for comparing actual tokens with predefined values.
SourceLocation getEnd() const
TemplateTemplateParmDecl - Declares a template template parameter, e.g., "T" in.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Encodes a location in the source.
StringRef getName() const
Return the actual identifier string.
Base class for declarations which introduce a typedef-name.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
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.
This represents a decl that may have a name.
bool isFunctionPointerType() const
SourceLocation getBegin() const
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.