28#include "llvm/ADT/StringRef.h"
35 const AvailabilityAttr *AA) {
38 if (!IIEnvironment || Environment == llvm::Triple::UnknownEnvironment)
41 llvm::Triple::EnvironmentType ET =
42 AvailabilityAttr::getEnvironmentType(IIEnvironment->
getName());
43 return Environment == ET;
48 AvailabilityAttr
const *PartialMatch =
nullptr;
54 if (
const auto *FTD = dyn_cast<FunctionTemplateDecl>(
D))
55 D = FTD->getTemplatedDecl();
56 for (
const auto *A :
D->
attrs()) {
57 if (
const auto *Avail = dyn_cast<AvailabilityAttr>(A)) {
63 StringRef ActualPlatform = Avail->getPlatform()->getName();
64 StringRef RealizedPlatform = ActualPlatform;
66 size_t suffix = RealizedPlatform.rfind(
"_app_extension");
67 if (suffix != StringRef::npos)
68 RealizedPlatform = RealizedPlatform.slice(0, suffix);
74 if (RealizedPlatform == TargetPlatform) {
93std::pair<AvailabilityResult, const NamedDecl *>
100 while (
const auto *TD = dyn_cast<TypedefNameDecl>(
D)) {
103 for (
const Type *
T = TD->getUnderlyingType().getTypePtr(); ; ) {
104 if (
auto *TT = dyn_cast<TagType>(
T)) {
105 D = TT->getOriginalDecl()->getDefinitionOrSelf();
106 }
else if (isa<SubstTemplateTypeParmType>(
T)) {
125 if (
const auto *ADecl = dyn_cast<TypeAliasTemplateDecl>(
D)) {
126 D = ADecl->getTemplatedDecl();
131 if (
const auto *IDecl = dyn_cast<ObjCInterfaceDecl>(
D)) {
132 if (IDecl->getDefinition()) {
133 D = IDecl->getDefinition();
138 if (
const auto *ECD = dyn_cast<EnumConstantDecl>(
D))
141 if (
const auto *TheEnumDecl = dyn_cast<EnumDecl>(DC)) {
142 Result = TheEnumDecl->getAvailability(Message);
148 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(
D)) {
149 if (
ObjC().NSAPIObj && ClassReceiver) {
151 ObjC().NSAPIObj->getInitSelector());
153 MD->getSelector() ==
ObjC().NSAPIObj->getNewSelector() &&
170 assert(K !=
AR_Available &&
"Expected an unavailable declaration here!");
173 auto DeclLoc = Ctx->getBeginLoc();
175 if (DeclLoc.isMacroID() && S.
getLangOpts().CPlusPlus &&
176 isa<TypedefDecl>(OffendingDecl)) {
178 if (MacroName ==
"CF_OPTIONS" || MacroName ==
"OBJC_OPTIONS" ||
179 MacroName ==
"SWIFT_OPTIONS" || MacroName ==
"NS_OPTIONS") {
192 (DeclEnv !=
nullptr &&
194 llvm::Triple::EnvironmentType::Library))
199 if (
const auto *VD = dyn_cast<VarDecl>(OffendingDecl))
200 if (VD->isLocalVarDeclOrParm() && VD->isDeprecated())
205 auto CheckContext = [&](
const Decl *
C) {
208 if (AA->getIntroduced() >= DeclVersion &&
209 AA->getEnvironment() == DeclEnv)
212 if (
C->isDeprecated())
218 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(OffendingDecl)) {
219 if (
const auto *Impl = dyn_cast<ObjCImplDecl>(
C)) {
220 if (MD->getClassInterface() == Impl->getClassInterface())
226 if (
C->isUnavailable())
232 if (CheckContext(Ctx))
237 if (
const auto *MethodD = dyn_cast<ObjCMethodDecl>(Ctx))
238 if (MethodD->isClassMethod() &&
239 MethodD->getSelector().getAsString() ==
"load")
242 if (
const auto *CatOrImpl = dyn_cast<ObjCImplDecl>(Ctx)) {
248 else if (
const auto *CatD = dyn_cast<ObjCCategoryDecl>(Ctx))
252 }
while ((Ctx = cast_or_null<Decl>(Ctx->getDeclContext())));
258 const ASTContext &Context,
const VersionTuple &DeploymentVersion,
259 const VersionTuple &DeclVersion,
bool HasMatchingEnv) {
261 VersionTuple ForceAvailabilityFromVersion;
262 switch (Triple.getOS()) {
267 case llvm::Triple::IOS:
268 case llvm::Triple::TvOS:
269 ForceAvailabilityFromVersion = VersionTuple(11);
271 case llvm::Triple::WatchOS:
272 ForceAvailabilityFromVersion = VersionTuple(4);
274 case llvm::Triple::Darwin:
275 case llvm::Triple::MacOSX:
276 ForceAvailabilityFromVersion = VersionTuple(10, 13);
282 case llvm::Triple::ShaderModel:
283 return HasMatchingEnv ? diag::warn_hlsl_availability
284 : diag::warn_hlsl_availability_unavailable;
287 ForceAvailabilityFromVersion =
288 (Triple.getVendor() == llvm::Triple::Apple)
290 : VersionTuple((
unsigned)-1, (
unsigned)-1);
292 if (DeploymentVersion >= ForceAvailabilityFromVersion ||
293 DeclVersion >= ForceAvailabilityFromVersion)
294 return HasMatchingEnv ? diag::warn_unguarded_availability_new
295 : diag::warn_unguarded_availability_unavailable_new;
296 return HasMatchingEnv ? diag::warn_unguarded_availability
297 : diag::warn_unguarded_availability_unavailable;
301 for (
Decl *Ctx = OrigCtx; Ctx;
302 Ctx = cast_or_null<Decl>(Ctx->getDeclContext())) {
303 if (isa<TagDecl>(Ctx) || isa<FunctionDecl>(Ctx) || isa<ObjCMethodDecl>(Ctx))
304 return cast<NamedDecl>(Ctx);
305 if (
auto *CD = dyn_cast<ObjCContainerDecl>(Ctx)) {
306 if (
auto *Imp = dyn_cast<ObjCImplDecl>(Ctx))
307 return Imp->getClassInterface();
312 return dyn_cast<NamedDecl>(OrigCtx);
317struct AttributeInsertion {
322 static AttributeInsertion createInsertionAfter(
const NamedDecl *
D) {
326 return {
" ",
Loc,
""};
328 static AttributeInsertion createInsertionBefore(
const NamedDecl *
D) {
343static std::optional<unsigned>
347 if (!Name.empty() && (Name.front() ==
'-' || Name.front() ==
'+'))
348 Name = Name.drop_front(1);
351 Name.split(SlotNames,
':');
353 if (Name.back() ==
':') {
355 SlotNames.pop_back();
356 NumParams = SlotNames.size();
358 if (SlotNames.size() != 1)
364 bool AllowDollar = LangOpts.DollarIdents;
365 for (StringRef S : SlotNames) {
376static std::optional<AttributeInsertion>
379 if (isa<ObjCPropertyDecl>(
D))
380 return AttributeInsertion::createInsertionAfter(
D);
381 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(
D)) {
384 return AttributeInsertion::createInsertionAfter(
D);
386 if (
const auto *TD = dyn_cast<TagDecl>(
D)) {
392 return AttributeInsertion::createInsertionAfter(
Loc);
394 return AttributeInsertion::createInsertionBefore(
D);
414 bool ObjCPropertyAccess) {
416 unsigned diag, diag_message, diag_fwdclass_message;
417 unsigned diag_available_here = diag::note_availability_specified_here;
421 unsigned property_note_select;
424 unsigned available_here_select_kind;
426 VersionTuple DeclVersion;
430 DeclVersion = AA->getIntroduced();
431 IIEnv = AA->getEnvironment();
442 if (AA && AA->isInherited()) {
445 const AvailabilityAttr *AForRedecl =
447 if (AForRedecl && !AForRedecl->isInherited()) {
450 NoteLocation = Redecl->getLocation();
462 assert(AA !=
nullptr &&
"expecting valid availability attribute");
463 VersionTuple Introduced = AA->getIntroduced();
464 bool EnvironmentMatchesOrNone =
468 std::string PlatformName(
470 llvm::StringRef TargetEnvironment(
471 llvm::Triple::getEnvironmentTypeName(TI.
getTriple().getEnvironment()));
472 llvm::StringRef AttrEnvironment =
473 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
474 bool UseEnvironment =
475 (!AttrEnvironment.empty() && !TargetEnvironment.empty());
479 Introduced, EnvironmentMatchesOrNone);
481 S.
Diag(
Loc, DiagKind) << OffendingDecl << PlatformName
482 << Introduced.getAsString() << UseEnvironment
483 << TargetEnvironment;
486 diag::note_partial_availability_specified_here)
487 << OffendingDecl << PlatformName << Introduced.getAsString()
489 << UseEnvironment << AttrEnvironment << TargetEnvironment;
496 if (
const auto *TD = dyn_cast<TagDecl>(Enclosing))
497 if (TD->getDeclName().isEmpty()) {
498 S.
Diag(TD->getLocation(),
499 diag::note_decl_unguarded_availability_silence)
500 << 1 << TD->getKindName();
504 S.
Diag(Enclosing->getLocation(),
505 diag::note_decl_unguarded_availability_silence)
508 if (Enclosing->hasAttr<AvailabilityAttr>())
517 StringRef PlatformName =
530 std::vector<StringRef> EquivalentPlatforms =
531 AvailabilityAttr::equivalentPlatformNames(PlatformName);
532 llvm::Twine MacroPrefix =
"__API_AVAILABLE_PLATFORM_";
533 auto AvailablePlatform =
534 llvm::find_if(EquivalentPlatforms, [&](StringRef EquivalentPlatform) {
535 return PP.
isMacroDefined((MacroPrefix + EquivalentPlatform).str());
537 if (AvailablePlatform == EquivalentPlatforms.end())
539 std::string Introduced =
543 (llvm::Twine(Insertion->Prefix) +
"API_AVAILABLE(" +
544 *AvailablePlatform +
"(" + Introduced +
"))" + Insertion->Suffix)
553 FD && FD->isImplicit())
556 if (ObjCPropertyAccess)
557 diag = diag::warn_property_method_deprecated;
559 diag = diag::warn_deprecated_switch_case;
561 diag = diag::warn_deprecated;
563 diag_message = diag::warn_deprecated_message;
564 diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
565 property_note_select = 0;
566 available_here_select_kind = 2;
567 if (
const auto *AL = OffendingDecl->
getAttr<DeprecatedAttr>())
568 NoteLocation = AL->getLocation();
572 diag = !ObjCPropertyAccess ? diag::err_unavailable
573 : diag::err_property_method_unavailable;
574 diag_message = diag::err_unavailable_message;
575 diag_fwdclass_message = diag::warn_unavailable_fwdclass_message;
576 property_note_select = 1;
577 available_here_select_kind = 0;
579 if (
auto AL = OffendingDecl->
getAttr<UnavailableAttr>()) {
580 if (AL->isImplicit() && AL->getImplicitReason()) {
583 auto flagARCError = [&] {
587 diag = diag::err_unavailable_in_arc;
590 switch (AL->getImplicitReason()) {
591 case UnavailableAttr::IR_None:
break;
593 case UnavailableAttr::IR_ARCForbiddenType:
595 diag_available_here = diag::note_arc_forbidden_type;
598 case UnavailableAttr::IR_ForbiddenWeak:
600 diag_available_here = diag::note_arc_weak_disabled;
602 diag_available_here = diag::note_arc_weak_no_runtime;
605 case UnavailableAttr::IR_ARCForbiddenConversion:
607 diag_available_here = diag::note_performs_forbidden_arc_conversion;
610 case UnavailableAttr::IR_ARCInitReturnsUnrelated:
612 diag_available_here = diag::note_arc_init_returns_unrelated;
615 case UnavailableAttr::IR_ARCFieldWithOwnership:
617 diag_available_here = diag::note_arc_field_with_ownership;
625 llvm_unreachable(
"Warning for availability of available declaration?");
630 StringRef Replacement;
631 if (
auto AL = OffendingDecl->
getAttr<DeprecatedAttr>())
632 Replacement = AL->getReplacement();
634 Replacement = AL->getReplacement();
637 if (!Replacement.empty())
641 if (
const auto *MethodDecl = dyn_cast<ObjCMethodDecl>(ReferringDecl)) {
642 Selector Sel = MethodDecl->getSelector();
646 if (NumParams && *NumParams == Sel.
getNumArgs()) {
647 assert(SelectorSlotNames.size() == Locs.size());
648 for (
unsigned I = 0; I < Locs.size(); ++I) {
653 NameRange, SelectorSlotNames[I]));
671 bool ShouldAllowWarningInSystemHeader =
672 InstantiationLoc !=
Loc &&
674 struct AllowWarningInSystemHeaders {
676 bool AllowWarningInSystemHeaders)
677 : Engine(
E), Prev(
E.getSuppressSystemWarnings()) {
678 E.setSuppressSystemWarnings(!AllowWarningInSystemHeaders);
680 ~AllowWarningInSystemHeaders() { Engine.setSuppressSystemWarnings(Prev); }
686 ShouldAllowWarningInSystemHeader);
688 if (!Message.empty()) {
689 S.
Diag(
Loc, diag_message) << ReferringDecl << Message << FixIts;
692 << ObjCProperty->
getDeclName() << property_note_select;
693 }
else if (!UnknownObjCClass) {
694 S.
Diag(
Loc, diag) << ReferringDecl << FixIts;
697 << ObjCProperty->
getDeclName() << property_note_select;
699 S.
Diag(
Loc, diag_fwdclass_message) << ReferringDecl << FixIts;
703 S.
Diag(NoteLocation, diag_available_here)
704 << OffendingDecl << available_here_select_kind;
709 "Expected an availability diagnostic here");
726 bool ObjCPropertyAccess) {
731 AR, Locs, ReferringDecl, OffendingDecl, UnknownObjCClass,
732 ObjCProperty, Message, ObjCPropertyAccess));
738 Message, Locs, UnknownObjCClass, ObjCProperty,
746 switch (
Parent->getStmtClass()) {
747 case Stmt::IfStmtClass:
748 return cast<IfStmt>(
Parent)->getThen() == S ||
749 cast<IfStmt>(
Parent)->getElse() == S;
750 case Stmt::WhileStmtClass:
751 return cast<WhileStmt>(
Parent)->getBody() == S;
752 case Stmt::DoStmtClass:
753 return cast<DoStmt>(
Parent)->getBody() == S;
754 case Stmt::ForStmtClass:
755 return cast<ForStmt>(
Parent)->getBody() == S;
756 case Stmt::CXXForRangeStmtClass:
757 return cast<CXXForRangeStmt>(
Parent)->getBody() == S;
758 case Stmt::ObjCForCollectionStmtClass:
759 return cast<ObjCForCollectionStmt>(
Parent)->getBody() == S;
760 case Stmt::CaseStmtClass:
761 case Stmt::DefaultStmtClass:
762 return cast<SwitchCase>(
Parent)->getSubStmt() == S;
772 bool VisitStmt(
Stmt *S)
override {
return S !=
Target; }
776 StmtUSEFinder Visitor;
778 return !Visitor.TraverseDecl(
const_cast<Decl *
>(
D));
794 static const Stmt *findLastStmtThatUsesDecl(
const Decl *
D,
796 LastDeclUSEFinder Visitor;
798 for (
const Stmt *S : llvm::reverse(
Scope->body())) {
799 if (!Visitor.TraverseStmt(
const_cast<Stmt *
>(S)))
824 DiagnoseUnguardedAvailability(
Sema &SemaRef,
Decl *Ctx)
825 : SemaRef(SemaRef), Ctx(Ctx) {
826 AvailabilityStack.push_back(
830 bool TraverseStmt(
Stmt *S)
override {
833 StmtStack.push_back(S);
835 StmtStack.pop_back();
839 void IssueDiagnostics(
Stmt *S) { TraverseStmt(S); }
841 bool TraverseIfStmt(
IfStmt *
If)
override;
845 bool TraverseCaseStmt(
CaseStmt *CS)
override {
856 DiagnoseDeclAvailability(
863 DiagnoseDeclAvailability(DRE->
getDecl(),
868 bool VisitMemberExpr(
MemberExpr *ME)
override {
880 bool VisitTypeLoc(
TypeLoc Ty)
override;
883void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
887 std::tie(
Result, OffendingDecl) =
895 const AvailabilityAttr *AA =
897 assert(AA !=
nullptr &&
"expecting valid availability attribute");
898 bool EnvironmentMatchesOrNone =
900 VersionTuple Introduced = AA->getIntroduced();
902 if (EnvironmentMatchesOrNone && AvailabilityStack.back() >= Introduced)
908 AA->getEnvironment(), Ctx,
913 std::string PlatformName(
915 llvm::StringRef TargetEnvironment(TI.
getTriple().getEnvironmentName());
916 llvm::StringRef AttrEnvironment =
917 AA->getEnvironment() ? AA->getEnvironment()->getName() :
"";
918 bool UseEnvironment =
919 (!AttrEnvironment.empty() && !TargetEnvironment.empty());
924 EnvironmentMatchesOrNone);
927 <<
Range <<
D << PlatformName << Introduced.getAsString()
928 << UseEnvironment << TargetEnvironment;
931 diag::note_partial_availability_specified_here)
932 << OffendingDecl << PlatformName << Introduced.getAsString()
934 << UseEnvironment << AttrEnvironment << TargetEnvironment;
947 if (StmtStack.empty())
949 const Stmt *StmtOfUse = StmtStack.back();
951 for (
const Stmt *S : llvm::reverse(StmtStack)) {
952 if (
const auto *CS = dyn_cast<CompoundStmt>(S)) {
956 if (isBodyLikeChildStmt(StmtOfUse, S)) {
964 const Stmt *LastStmtOfUse =
nullptr;
965 if (isa<DeclStmt>(StmtOfUse) &&
Scope) {
966 for (
const Decl *
D : cast<DeclStmt>(StmtOfUse)->decls()) {
967 if (StmtUSEFinder::isContained(StmtStack.back(),
D)) {
968 LastStmtOfUse = LastDeclUSEFinder::findLastStmtThatUsesDecl(
D,
Scope);
978 SM.getExpansionRange(
979 (LastStmtOfUse ? LastStmtOfUse : StmtOfUse)->getEndLoc())
981 if (
SM.getFileID(IfInsertionLoc) !=
SM.getFileID(StmtEndLoc))
985 const char *ExtraIndentation =
" ";
986 std::string FixItString;
987 llvm::raw_string_ostream FixItOS(FixItString);
988 FixItOS <<
"if (" << (SemaRef.
getLangOpts().ObjC ?
"@available"
989 :
"__builtin_available")
991 << AvailabilityAttr::getPlatformNameSourceSpelling(
993 <<
" " << Introduced.getAsString() <<
", *)) {\n"
994 << Indentation << ExtraIndentation;
1002 FixItOS.str().clear();
1004 << Indentation <<
"} else {\n"
1005 << Indentation << ExtraIndentation
1006 <<
"// Fallback on earlier versions\n"
1007 << Indentation <<
"}";
1012bool DiagnoseUnguardedAvailability::VisitTypeLoc(
TypeLoc Ty) {
1019 if (
const auto *TT = dyn_cast<TagType>(TyPtr)) {
1021 DiagnoseDeclAvailability(TD,
Range);
1023 }
else if (
const auto *TD = dyn_cast<TypedefType>(TyPtr)) {
1025 DiagnoseDeclAvailability(
D,
Range);
1027 }
else if (
const auto *ObjCO = dyn_cast<ObjCObjectType>(TyPtr)) {
1029 DiagnoseDeclAvailability(
D,
Range);
1035struct ExtractedAvailabilityExpr {
1037 bool isNegated =
false;
1040ExtractedAvailabilityExpr extractAvailabilityExpr(
const Expr *IfCond) {
1041 const auto *
E = IfCond;
1042 bool IsNegated =
false;
1045 if (
const auto *AE = dyn_cast<ObjCAvailabilityCheckExpr>(
E)) {
1046 return ExtractedAvailabilityExpr{AE, IsNegated};
1049 const auto *UO = dyn_cast<UnaryOperator>(
E);
1050 if (!UO || UO->getOpcode() != UO_LNot) {
1051 return ExtractedAvailabilityExpr{};
1053 E = UO->getSubExpr();
1054 IsNegated = !IsNegated;
1058bool DiagnoseUnguardedAvailability::TraverseIfStmt(
IfStmt *
If) {
1059 ExtractedAvailabilityExpr IfCond = extractAvailabilityExpr(
If->getCond());
1062 return DynamicRecursiveASTVisitor::TraverseIfStmt(
If);
1065 VersionTuple CondVersion = IfCond.E->getVersion();
1068 if (CondVersion.empty() || CondVersion <= AvailabilityStack.back()) {
1069 return TraverseStmt(
If->getThen()) && TraverseStmt(
If->getElse());
1072 auto *Guarded =
If->getThen();
1073 auto *Unguarded =
If->getElse();
1074 if (IfCond.isNegated) {
1075 std::swap(Guarded, Unguarded);
1078 AvailabilityStack.push_back(CondVersion);
1079 bool ShouldContinue = TraverseStmt(Guarded);
1080 AvailabilityStack.pop_back();
1082 return ShouldContinue && TraverseStmt(Unguarded);
1088 Stmt *Body =
nullptr;
1091 Body = FD->getBody();
1093 if (
auto *CD = dyn_cast<CXXConstructorDecl>(FD))
1095 DiagnoseUnguardedAvailability(*
this,
D).IssueDiagnostics(CI->getInit());
1097 }
else if (
auto *MD = dyn_cast<ObjCMethodDecl>(
D))
1098 Body = MD->getBody();
1099 else if (
auto *BD = dyn_cast<BlockDecl>(
D))
1100 Body = BD->getBody();
1102 assert(Body &&
"Need a body here!");
1104 DiagnoseUnguardedAvailability(*
this,
D).IssueDiagnostics(Body);
1121 bool ObjCPropertyAccess,
1122 bool AvoidPartialAvailabilityChecks,
1125 std::string Message;
1129 std::tie(
Result, OffendingDecl) =
1135 if (AvoidPartialAvailabilityChecks)
1142 Context->HasPotentialAvailabilityViolations =
true;
1148 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(
D)) {
1151 if (PDeclResult ==
Result)
1157 UnknownObjCClass, ObjCPDecl, ObjCPropertyAccess);
Defines the C++ template declaration subclasses.
Defines the classes clang::DelayedDiagnostic and clang::AccessedEntity.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
llvm::MachO::Target Target
Defines the clang::Preprocessor interface.
static unsigned getAvailabilityDiagnosticKind(const ASTContext &Context, const VersionTuple &DeploymentVersion, const VersionTuple &DeclVersion, bool HasMatchingEnv)
static bool hasMatchingEnvironmentOrNone(const ASTContext &Context, const AvailabilityAttr *AA)
static std::optional< AttributeInsertion > createAttributeInsertion(const NamedDecl *D, const SourceManager &SM, const LangOptions &LangOpts)
Returns a source location in which it's appropriate to insert a new attribute for the given declarati...
static void EmitAvailabilityWarning(Sema &S, AvailabilityResult AR, const NamedDecl *ReferringDecl, const NamedDecl *OffendingDecl, StringRef Message, ArrayRef< SourceLocation > Locs, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess)
static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K, Decl *Ctx, const NamedDecl *ReferringDecl, const NamedDecl *OffendingDecl, StringRef Message, ArrayRef< SourceLocation > Locs, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess)
Actually emit an availability diagnostic for a reference to an unavailable decl.
static NamedDecl * findEnclosingDeclToAnnotate(Decl *OrigCtx)
static std::optional< unsigned > tryParseObjCMethodName(StringRef Name, SmallVectorImpl< StringRef > &SlotNames, const LangOptions &LangOpts)
Tries to parse a string as ObjC method name.
static const AvailabilityAttr * getAttrForPlatform(ASTContext &Context, const Decl *D)
static bool ShouldDiagnoseAvailabilityInContext(Sema &S, AvailabilityResult K, VersionTuple DeclVersion, const IdentifierInfo *DeclEnv, Decl *Ctx, const NamedDecl *OffendingDecl)
whether we should emit a diagnostic for K and DeclVersion in the context of Ctx.
This file declares semantic analysis for Objective-C.
Defines the Objective-C statement AST node classes.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const LangOptions & getLangOpts() const
const TargetInfo & getTargetInfo() const
Represents a C++ base or member initializer.
CaseStmt - Represent a case statement.
Represents a character-granular source range.
static CharSourceRange getCharRange(SourceRange R)
CompoundStmt - This represents a group of statements like { stmt stmt }.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
A reference to a declared variable, function, enum, etc.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const
Decl - This represents one declaration (or definition), e.g.
Decl * getPreviousDecl()
Retrieve the previous declaration that declares the same entity as this declaration,...
SourceLocation getEndLoc() const LLVM_READONLY
AvailabilityResult getAvailability(std::string *Message=nullptr, VersionTuple EnclosingVersion=VersionTuple(), StringRef *RealizedPlatform=nullptr) const
Determine the availability of the given declaration.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
VersionTuple getVersionIntroduced() const
Retrieve the version of the target platform in which this declaration was introduced.
Concrete class used by the front-end to report problems and issues.
Recursive AST visitor that supports extension via dynamic dispatch.
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
Recursively visit a statement or expression, by dispatching to Traverse*() based on the argument's dy...
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
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.
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
IfStmt - This represents an if/then/else.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static SourceLocation findLocationAfterToken(SourceLocation loc, tok::TokenKind TKind, const SourceManager &SM, const LangOptions &LangOpts, bool SkipTrailingWhitespaceAndNewLine)
Checks that the given token is the first token that occurs after the given location (this excludes co...
static StringRef getIndentationForLine(SourceLocation Loc, const SourceManager &SM)
Returns the leading whitespace for line that corresponds to the given location Loc.
static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)
Computes the source location just past the end of the token at this source location.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
This represents a decl that may have a name.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
NamedDecl * getMostRecentDecl()
A runtime availability query.
Represents an ObjC class declaration.
ObjCMethodDecl * lookupInstanceMethod(Selector Sel) const
Lookup an instance method for a given selector.
An expression that sends a message to the given Objective-C object or class.
QualType getClassReceiver() const
Returns the type of a class message send, or NULL if the message is not a class message.
const ObjCMethodDecl * getMethodDecl() const
SourceLocation getEndLoc() const LLVM_READONLY
SourceLocation getSelectorStartLoc() const
ObjCMethodDecl - Represents an instance or class method declaration.
ObjCInterfaceDecl * getInterface() const
Gets the interface declaration for this object type, if the base type really is an interface.
Represents one property declaration in an Objective-C interface.
static ObjCPropertyDecl * findPropertyDecl(const DeclContext *DC, const IdentifierInfo *propertyID, ObjCPropertyQueryKind queryKind)
Lookup a property by name in the specified DeclContext.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
bool isMacroDefined(StringRef Id)
StringRef getImmediateMacroName(SourceLocation Loc)
Retrieve the name of the immediate macro expansion.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Scope - A scope is a transient data structure that is used while parsing the program.
Smart pointer class that efficiently represents Objective-C method names.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
unsigned getNumArgs() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
bool shouldDelayDiagnostics()
Determines whether diagnostics should be delayed.
void add(const sema::DelayedDiagnostic &diag)
Adds a delayed diagnostic.
Sema - This implements semantic analysis and AST building for C.
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Preprocessor & getPreprocessor() const
const ExpressionEvaluationContextRecord & currentEvaluationContext() const
class clang::Sema::DelayedDiagnostics DelayedDiagnostics
FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const
Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...
DiagnosticsEngine & getDiagnostics() const
ASTContext & getASTContext() const
void DiagnoseUnguardedAvailabilityViolations(Decl *FD)
Issue any -Wunguarded-availability warnings in FD.
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Calls Lexer::getLocForEndOfToken()
const LangOptions & getLangOpts() const
DeclContext * getCurLexicalContext() const
SourceManager & getSourceManager() const
void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef< SourceLocation > Locs, const ObjCInterfaceDecl *UnknownObjCClass, bool ObjCPropertyAccess, bool AvoidPartialAvailabilityChecks, ObjCInterfaceDecl *ClassReceiver)
std::pair< AvailabilityResult, const NamedDecl * > ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message, ObjCInterfaceDecl *ClassReceiver)
The diagnostic we should emit for D, and the declaration that originated it, or AR_Available.
sema::FunctionScopeInfo * getCurFunctionAvailabilityContext()
Retrieve the current function, if any, that should be analyzed for potential availability violations.
SourceLocation getTopMostPointOfInstantiation(const NamedDecl *) const
Returns the top most location responsible for the definition of N.
void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx)
Encodes a location in the source.
This class handles loading and caching of source files into memory.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Represents the declaration of a struct/union/class/enum.
TagDecl * getDefinitionOrSelf() const
Exposes information about the current target.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getPlatformName() const
Retrieve the name of the platform as it is used in the availability attribute.
VersionTuple getPlatformMinVersion() const
Retrieve the minimum desired version of the platform, to which the program should be compiled.
Base wrapper for a particular "section" of type source info.
SourceLocation getEndLoc() const
Get the end source location.
SourceLocation getBeginLoc() const
Get the begin source location.
const Type * getTypePtr() const
The base class of the type hierarchy.
QualType getLocallyUnqualifiedSingleStepDesugaredType() const
Pull a single level of sugar off of this locally-unqualified type.
const ObjCObjectType * getAsObjCInterfaceType() const
Base class for declarations which introduce a typedef-name.
A diagnostic message which has been conditionally emitted pending the complete parsing of the current...
static DelayedDiagnostic makeAvailability(AvailabilityResult AR, ArrayRef< SourceLocation > Locs, const NamedDecl *ReferringDecl, const NamedDecl *OffendingDecl, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, StringRef Msg, bool ObjCPropertyAccess)
const ObjCInterfaceDecl * getUnknownObjCClass() const
const NamedDecl * getAvailabilityOffendingDecl() const
const ObjCPropertyDecl * getObjCProperty() const
StringRef getAvailabilityMessage() const
ArrayRef< SourceLocation > getAvailabilitySelectorLocs() const
AvailabilityResult getAvailabilityResult() const
const NamedDecl * getAvailabilityReferringDecl() const
Retains information about a function, method, or block that is currently being parsed.
Defines the clang::TargetInfo interface.
The JSON file list parser is used to communicate input to InstallAPI.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
LLVM_READONLY bool isValidAsciiIdentifier(StringRef S, bool AllowDollar=false)
Return true if this is a valid ASCII identifier.
@ Result
The result type of a method or function.
AvailabilityResult
Captures the result of checking the availability of a declaration.
const FunctionProtoType * T
@ Interface
The "__interface" keyword introduces the elaborated-type-specifier.
bool IsCaseExpr
Whether evaluating an expression for a switch case label.