18 #include "llvm/ADT/SmallString.h" 19 #include "llvm/ADT/StringSwitch.h" 25 #include "clang/AST/CommentHTMLTagsProperties.inc" 28 Sema::Sema(llvm::BumpPtrAllocator &Allocator,
const SourceManager &SourceMgr,
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");
601 case Decl::CXXConstructor:
604 case Decl::CXXDestructor:
609 diag::warn_doc_returns_attached_to_a_void_function)
619 diag::warn_doc_returns_not_attached_to_a_function_decl)
630 BriefCommand = Command;
633 PrevCommand = BriefCommand;
635 if (!HeaderfileCommand) {
636 HeaderfileCommand = Command;
639 PrevCommand = HeaderfileCommand;
646 Diag(Command->
getLocation(), diag::warn_doc_block_command_duplicate)
650 if (CommandName == PrevCommandName)
651 Diag(PrevCommand->
getLocation(), diag::note_doc_block_command_previous)
657 diag::note_doc_block_command_previous_alias)
667 assert(ThisDeclInfo &&
"should not call this check on a bare comment");
673 if (D->
hasAttr<DeprecatedAttr>() ||
674 D->
hasAttr<AvailabilityAttr>() ||
679 diag::warn_doc_deprecated_not_sync)
683 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
688 FD->doesThisDeclarationHaveABody())
691 StringRef AttributeSpelling =
"__attribute__((deprecated))";
694 tok::kw___attribute, tok::l_paren, tok::l_paren,
696 tok::r_paren, tok::r_paren
700 if (!MacroName.empty())
701 AttributeSpelling = MacroName;
705 TextToInsert += AttributeSpelling;
706 Diag(FD->getLocEnd(),
707 diag::note_add_deprecation_attr)
727 ParamVarDocs.resize(ParamVars.size(),
nullptr);
745 UnresolvedParamCommands.push_back(PCC);
749 if (ParamVarDocs[ResolvedParamIndex]) {
751 Diag(ArgRange.
getBegin(), diag::warn_doc_param_duplicate)
752 << ParamName << ArgRange;
754 Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
755 << PrevCommand->getParamNameRange();
757 ParamVarDocs[ResolvedParamIndex] = PCC;
762 for (
unsigned i = 0, e = ParamVarDocs.size(); i != e; ++i) {
763 if (!ParamVarDocs[i])
764 OrphanedParamDecls.push_back(ParamVars[i]);
770 for (
unsigned i = 0, e = UnresolvedParamCommands.size(); i != e; ++i) {
775 Diag(ArgRange.
getBegin(), diag::warn_doc_param_not_found)
776 << ParamName << ArgRange;
779 if (OrphanedParamDecls.size() == 0)
783 if (OrphanedParamDecls.size() == 1) {
786 CorrectedParamIndex = 0;
793 const ParmVarDecl *CorrectedPVD = OrphanedParamDecls[CorrectedParamIndex];
795 Diag(ArgRange.
getBegin(), diag::note_doc_param_name_suggestion)
796 << CorrectedII->getName()
820 return FD->isVariadic();
822 dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->
CurrentDecl))
823 return FTD->getTemplatedDecl()->isVariadic();
825 dyn_cast<ObjCMethodDecl>(ThisDeclInfo->
CurrentDecl))
826 return MD->isVariadic();
828 dyn_cast<TypedefNameDecl>(ThisDeclInfo->
CurrentDecl)) {
833 return FT->isVariadic();
866 if (
const auto *VD = dyn_cast<DeclaratorDecl>(ThisDeclInfo->
CurrentDecl))
868 else if (
const auto *PD =
869 dyn_cast<ObjCPropertyDecl>(ThisDeclInfo->
CurrentDecl))
912 dyn_cast_or_null<RecordDecl>(ThisDeclInfo->
CurrentDecl))
913 return RD->isUnion();
933 (isa<ClassTemplateDecl>(ThisDeclInfo->
CurrentDecl));
942 (isa<FunctionTemplateDecl>(ThisDeclInfo->
CurrentDecl));
970 ThisDeclInfo->
fill();
975 for (
unsigned i = 0, e = ParamVars.size(); i != e; ++i) {
977 if (II && II->
getName() == Name)
986 class SimpleTypoCorrector {
990 const unsigned MaxEditDistance;
992 unsigned BestEditDistance;
997 explicit SimpleTypoCorrector(StringRef Typo)
998 : BestDecl(
nullptr), Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3),
999 BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) {}
1004 if (BestEditDistance > MaxEditDistance)
1010 unsigned getBestDeclIndex()
const {
1011 assert(getBestDecl());
1016 void SimpleTypoCorrector::addDecl(
const NamedDecl *ND) {
1017 unsigned CurrIndex = NextIndex++;
1023 StringRef Name = II->
getName();
1024 unsigned MinPossibleEditDistance =
abs((
int)Name.size() - (int)Typo.size());
1025 if (MinPossibleEditDistance > 0 &&
1026 Typo.size() / MinPossibleEditDistance < 3)
1029 unsigned EditDistance = Typo.edit_distance(Name,
true, MaxEditDistance);
1030 if (EditDistance < BestEditDistance) {
1031 BestEditDistance = EditDistance;
1033 BestIndex = CurrIndex;
1041 SimpleTypoCorrector Corrector(Typo);
1042 for (
unsigned i = 0, e = ParamVars.size(); i != e; ++i)
1043 Corrector.addDecl(ParamVars[i]);
1044 if (Corrector.getBestDecl())
1045 return Corrector.getBestDeclIndex();
1051 bool ResolveTParamReferenceHelper(
1055 for (
unsigned i = 0, e = TemplateParameters->
size(); i != e; ++i) {
1058 if (II && II->
getName() == Name) {
1059 Position->push_back(i);
1064 dyn_cast<TemplateTemplateParmDecl>(Param)) {
1065 Position->push_back(i);
1066 if (ResolveTParamReferenceHelper(Name, TTP->getTemplateParameters(),
1069 Position->pop_back();
1081 if (!TemplateParameters)
1084 return ResolveTParamReferenceHelper(Name, TemplateParameters, Position);
1088 void CorrectTypoInTParamReferenceHelper(
1090 SimpleTypoCorrector &Corrector) {
1091 for (
unsigned i = 0, e = TemplateParameters->
size(); i != e; ++i) {
1093 Corrector.addDecl(Param);
1096 dyn_cast<TemplateTemplateParmDecl>(Param))
1097 CorrectTypoInTParamReferenceHelper(TTP->getTemplateParameters(),
1106 SimpleTypoCorrector Corrector(Typo);
1107 CorrectTypoInTParamReferenceHelper(TemplateParameters, Corrector);
1108 if (
const NamedDecl *ND = Corrector.getBestDecl()) {
1110 assert(II &&
"SimpleTypoCorrector should not return this decl");
1118 assert(Traits.getCommandInfo(Name)->IsInlineCommand);
1120 return llvm::StringSwitch<InlineCommandComment::RenderKind>(Name)
An instance of this class is created to represent a function declaration or definition.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
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)
VarDecl - An instance of this class is created to represent 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.
ParmVarDecl - Represents a parameter to a function.
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
RecordDecl - Represents a struct/union/class.
One of these records is kept for each identifier that is lexed.
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
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.
NamedDecl - This represents a decl with 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.