Skip to content

Commit 4042f3c

Browse files
committedJul 5, 2017
[Sema] Don't allow -Wunguarded-availability to be silenced with redecls
Differential revision: https://reviews.llvm.org/D33816 llvm-svn: 307175
1 parent aa5a6a1 commit 4042f3c

13 files changed

+220
-148
lines changed
 

‎clang/include/clang/Basic/DiagnosticSemaKinds.td

+1-1
Original file line numberDiff line numberDiff line change
@@ -2880,7 +2880,7 @@ def warn_partial_availability : Warning<"%0 is only available conditionally">,
28802880
def warn_partial_availability_new : Warning<warn_partial_availability.Text>,
28812881
InGroup<UnguardedAvailabilityNew>;
28822882
def note_partial_availability_silence : Note<
2883-
"explicitly redeclare %0 to silence this warning">;
2883+
"annotate %select{%1|anonymous %1}0 with an availability attribute to silence">;
28842884
def note_unguarded_available_silence : Note<
28852885
"enclose %0 in %select{an @available|a __builtin_available}1 check to silence"
28862886
" this warning">;

‎clang/include/clang/Sema/DelayedDiagnostic.h

+10-4
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ class DelayedDiagnostic {
124124

125125
static DelayedDiagnostic makeAvailability(AvailabilityResult AR,
126126
SourceLocation Loc,
127-
const NamedDecl *D,
127+
const NamedDecl *ReferringDecl,
128+
const NamedDecl *OffendingDecl,
128129
const ObjCInterfaceDecl *UnknownObjCClass,
129130
const ObjCPropertyDecl *ObjCProperty,
130131
StringRef Msg,
@@ -164,9 +165,13 @@ class DelayedDiagnostic {
164165
return *reinterpret_cast<const AccessedEntity*>(AccessData);
165166
}
166167

167-
const NamedDecl *getAvailabilityDecl() const {
168+
const NamedDecl *getAvailabilityReferringDecl() const {
168169
assert(Kind == Availability && "Not an availability diagnostic.");
169-
return AvailabilityData.Decl;
170+
return AvailabilityData.ReferringDecl;
171+
}
172+
173+
const NamedDecl *getAvailabilityOffendingDecl() const {
174+
return AvailabilityData.OffendingDecl;
170175
}
171176

172177
StringRef getAvailabilityMessage() const {
@@ -213,7 +218,8 @@ class DelayedDiagnostic {
213218
private:
214219

215220
struct AD {
216-
const NamedDecl *Decl;
221+
const NamedDecl *ReferringDecl;
222+
const NamedDecl *OffendingDecl;
217223
const ObjCInterfaceDecl *UnknownObjCClass;
218224
const ObjCPropertyDecl *ObjCProperty;
219225
const char *Message;

‎clang/include/clang/Sema/Sema.h

+8-8
Original file line numberDiff line numberDiff line change
@@ -3881,7 +3881,9 @@ class Sema {
38813881

38823882
void redelayDiagnostics(sema::DelayedDiagnosticPool &pool);
38833883

3884-
void EmitAvailabilityWarning(AvailabilityResult AR, NamedDecl *D,
3884+
void EmitAvailabilityWarning(AvailabilityResult AR,
3885+
const NamedDecl *ReferringDecl,
3886+
const NamedDecl *OffendingDecl,
38853887
StringRef Message, SourceLocation Loc,
38863888
const ObjCInterfaceDecl *UnknownObjCClass,
38873889
const ObjCPropertyDecl *ObjCProperty,
@@ -10413,16 +10415,14 @@ class Sema {
1041310415
return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
1041410416
}
1041510417

10416-
/// \brief The diagnostic we should emit for \c D, or \c AR_Available.
10417-
///
10418-
/// \param D The declaration to check. Note that this may be altered to point
10419-
/// to another declaration that \c D gets it's availability from. i.e., we
10420-
/// walk the list of typedefs to find an availability attribute.
10418+
/// The diagnostic we should emit for \c D, and the declaration that
10419+
/// originated it, or \c AR_Available.
1042110420
///
10421+
/// \param D The declaration to check.
1042210422
/// \param Message If non-null, this will be populated with the message from
1042310423
/// the availability attribute that is selected.
10424-
AvailabilityResult ShouldDiagnoseAvailabilityOfDecl(NamedDecl *&D,
10425-
std::string *Message);
10424+
std::pair<AvailabilityResult, const NamedDecl *>
10425+
ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message);
1042610426

1042710427
const DeclContext *getCurObjCLexicalContext() const {
1042810428
const DeclContext *DC = getCurLexicalContext();

‎clang/lib/Sema/DelayedDiagnostic.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ using namespace sema;
2222
DelayedDiagnostic
2323
DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
2424
SourceLocation Loc,
25-
const NamedDecl *D,
25+
const NamedDecl *ReferringDecl,
26+
const NamedDecl *OffendingDecl,
2627
const ObjCInterfaceDecl *UnknownObjCClass,
2728
const ObjCPropertyDecl *ObjCProperty,
2829
StringRef Msg,
@@ -31,7 +32,8 @@ DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
3132
DD.Kind = Availability;
3233
DD.Triggered = false;
3334
DD.Loc = Loc;
34-
DD.AvailabilityData.Decl = D;
35+
DD.AvailabilityData.ReferringDecl = ReferringDecl;
36+
DD.AvailabilityData.OffendingDecl = OffendingDecl;
3537
DD.AvailabilityData.UnknownObjCClass = UnknownObjCClass;
3638
DD.AvailabilityData.ObjCProperty = ObjCProperty;
3739
char *MessageData = nullptr;

‎clang/lib/Sema/SemaDeclAttr.cpp

+79-36
Original file line numberDiff line numberDiff line change
@@ -6929,16 +6929,42 @@ shouldDiagnoseAvailabilityByDefault(const ASTContext &Context,
69296929
DeclVersion >= ForceAvailabilityFromVersion;
69306930
}
69316931

6932+
static NamedDecl *findEnclosingDeclToAnnotate(Decl *OrigCtx) {
6933+
for (Decl *Ctx = OrigCtx; Ctx;
6934+
Ctx = cast_or_null<Decl>(Ctx->getDeclContext())) {
6935+
if (isa<TagDecl>(Ctx) || isa<FunctionDecl>(Ctx) || isa<ObjCMethodDecl>(Ctx))
6936+
return cast<NamedDecl>(Ctx);
6937+
if (auto *CD = dyn_cast<ObjCContainerDecl>(Ctx)) {
6938+
if (auto *Imp = dyn_cast<ObjCImplDecl>(Ctx))
6939+
return Imp->getClassInterface();
6940+
return CD;
6941+
}
6942+
}
6943+
6944+
return dyn_cast<NamedDecl>(OrigCtx);
6945+
}
6946+
6947+
/// Actually emit an availability diagnostic for a reference to an unavailable
6948+
/// decl.
6949+
///
6950+
/// \param Ctx The context that the reference occurred in
6951+
/// \param ReferringDecl The exact declaration that was referenced.
6952+
/// \param OffendingDecl A related decl to \c ReferringDecl that has an
6953+
/// availability attribute corrisponding to \c K attached to it. Note that this
6954+
/// may not be the same as ReferringDecl, i.e. if an EnumDecl is annotated and
6955+
/// we refer to a member EnumConstantDecl, ReferringDecl is the EnumConstantDecl
6956+
/// and OffendingDecl is the EnumDecl.
69326957
static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
6933-
Decl *Ctx, const NamedDecl *D,
6958+
Decl *Ctx, const NamedDecl *ReferringDecl,
6959+
const NamedDecl *OffendingDecl,
69346960
StringRef Message, SourceLocation Loc,
69356961
const ObjCInterfaceDecl *UnknownObjCClass,
69366962
const ObjCPropertyDecl *ObjCProperty,
69376963
bool ObjCPropertyAccess) {
69386964
// Diagnostics for deprecated or unavailable.
69396965
unsigned diag, diag_message, diag_fwdclass_message;
69406966
unsigned diag_available_here = diag::note_availability_specified_here;
6941-
SourceLocation NoteLocation = D->getLocation();
6967+
SourceLocation NoteLocation = OffendingDecl->getLocation();
69426968

69436969
// Matches 'diag::note_property_attribute' options.
69446970
unsigned property_note_select;
@@ -6947,7 +6973,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
69476973
unsigned available_here_select_kind;
69486974

69496975
VersionTuple DeclVersion;
6950-
if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, D))
6976+
if (const AvailabilityAttr *AA = getAttrForPlatform(S.Context, OffendingDecl))
69516977
DeclVersion = AA->getIntroduced();
69526978

69536979
if (!ShouldDiagnoseAvailabilityInContext(S, K, DeclVersion, Ctx))
@@ -6961,7 +6987,7 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
69616987
diag_fwdclass_message = diag::warn_deprecated_fwdclass_message;
69626988
property_note_select = /* deprecated */ 0;
69636989
available_here_select_kind = /* deprecated */ 2;
6964-
if (const auto *attr = D->getAttr<DeprecatedAttr>())
6990+
if (const auto *attr = OffendingDecl->getAttr<DeprecatedAttr>())
69656991
NoteLocation = attr->getLocation();
69666992
break;
69676993

@@ -6973,13 +6999,14 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
69736999
property_note_select = /* unavailable */ 1;
69747000
available_here_select_kind = /* unavailable */ 0;
69757001

6976-
if (auto attr = D->getAttr<UnavailableAttr>()) {
7002+
if (auto attr = OffendingDecl->getAttr<UnavailableAttr>()) {
69777003
if (attr->isImplicit() && attr->getImplicitReason()) {
69787004
// Most of these failures are due to extra restrictions in ARC;
69797005
// reflect that in the primary diagnostic when applicable.
69807006
auto flagARCError = [&] {
69817007
if (S.getLangOpts().ObjCAutoRefCount &&
6982-
S.getSourceManager().isInSystemHeader(D->getLocation()))
7008+
S.getSourceManager().isInSystemHeader(
7009+
OffendingDecl->getLocation()))
69837010
diag = diag::err_unavailable_in_arc;
69847011
};
69857012

@@ -7022,7 +7049,8 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
70227049
// not specified for deployment targets >= to iOS 11 or equivalent or
70237050
// for declarations that were introduced in iOS 11 (macOS 10.13, ...) or
70247051
// later.
7025-
const AvailabilityAttr *AA = getAttrForPlatform(S.getASTContext(), D);
7052+
const AvailabilityAttr *AA =
7053+
getAttrForPlatform(S.getASTContext(), OffendingDecl);
70267054
VersionTuple Introduced = AA->getIntroduced();
70277055
bool NewWarning = shouldDiagnoseAvailabilityByDefault(
70287056
S.Context, S.Context.getTargetInfo().getPlatformMinVersion(),
@@ -7045,9 +7073,9 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
70457073
CharSourceRange UseRange;
70467074
StringRef Replacement;
70477075
if (K == AR_Deprecated) {
7048-
if (auto attr = D->getAttr<DeprecatedAttr>())
7076+
if (auto attr = OffendingDecl->getAttr<DeprecatedAttr>())
70497077
Replacement = attr->getReplacement();
7050-
if (auto attr = getAttrForPlatform(S.Context, D))
7078+
if (auto attr = getAttrForPlatform(S.Context, OffendingDecl))
70517079
Replacement = attr->getReplacement();
70527080

70537081
if (!Replacement.empty())
@@ -7056,49 +7084,58 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
70567084
}
70577085

70587086
if (!Message.empty()) {
7059-
S.Diag(Loc, diag_message) << D << Message
7087+
S.Diag(Loc, diag_message) << ReferringDecl << Message
70607088
<< (UseRange.isValid() ?
70617089
FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
70627090
if (ObjCProperty)
70637091
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
70647092
<< ObjCProperty->getDeclName() << property_note_select;
70657093
} else if (!UnknownObjCClass) {
7066-
S.Diag(Loc, diag) << D
7094+
S.Diag(Loc, diag) << ReferringDecl
70677095
<< (UseRange.isValid() ?
70687096
FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
70697097
if (ObjCProperty)
70707098
S.Diag(ObjCProperty->getLocation(), diag::note_property_attribute)
70717099
<< ObjCProperty->getDeclName() << property_note_select;
70727100
} else {
7073-
S.Diag(Loc, diag_fwdclass_message) << D
7101+
S.Diag(Loc, diag_fwdclass_message) << ReferringDecl
70747102
<< (UseRange.isValid() ?
70757103
FixItHint::CreateReplacement(UseRange, Replacement) : FixItHint());
70767104
S.Diag(UnknownObjCClass->getLocation(), diag::note_forward_class);
70777105
}
70787106

70797107
// The declaration can have multiple availability attributes, we are looking
70807108
// at one of them.
7081-
const AvailabilityAttr *A = getAttrForPlatform(S.Context, D);
7109+
const AvailabilityAttr *A = getAttrForPlatform(S.Context, OffendingDecl);
70827110
if (A && A->isInherited()) {
7083-
for (const Decl *Redecl = D->getMostRecentDecl(); Redecl;
7111+
for (const Decl *Redecl = OffendingDecl->getMostRecentDecl(); Redecl;
70847112
Redecl = Redecl->getPreviousDecl()) {
70857113
const AvailabilityAttr *AForRedecl = getAttrForPlatform(S.Context,
70867114
Redecl);
70877115
if (AForRedecl && !AForRedecl->isInherited()) {
70887116
// If D is a declaration with inherited attributes, the note should
70897117
// point to the declaration with actual attributes.
7090-
S.Diag(Redecl->getLocation(), diag_available_here) << D
7118+
S.Diag(Redecl->getLocation(), diag_available_here) << OffendingDecl
70917119
<< available_here_select_kind;
70927120
break;
70937121
}
70947122
}
70957123
}
70967124
else
70977125
S.Diag(NoteLocation, diag_available_here)
7098-
<< D << available_here_select_kind;
7126+
<< OffendingDecl << available_here_select_kind;
70997127

71007128
if (K == AR_NotYetIntroduced)
7101-
S.Diag(Loc, diag::note_partial_availability_silence) << D;
7129+
if (const auto *Enclosing = findEnclosingDeclToAnnotate(Ctx)) {
7130+
if (auto *TD = dyn_cast<TagDecl>(Enclosing))
7131+
if (TD->getDeclName().isEmpty()) {
7132+
S.Diag(TD->getLocation(), diag::note_partial_availability_silence)
7133+
<< /*Anonymous*/1 << TD->getKindName();
7134+
return;
7135+
}
7136+
S.Diag(Enclosing->getLocation(), diag::note_partial_availability_silence)
7137+
<< /*Named*/0 << Enclosing;
7138+
}
71027139
}
71037140

71047141
static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
@@ -7108,9 +7145,9 @@ static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
71087145

71097146
DD.Triggered = true;
71107147
DoEmitAvailabilityWarning(
7111-
S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityDecl(),
7112-
DD.getAvailabilityMessage(), DD.Loc, DD.getUnknownObjCClass(),
7113-
DD.getObjCProperty(), false);
7148+
S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityReferringDecl(),
7149+
DD.getAvailabilityOffendingDecl(), DD.getAvailabilityMessage(), DD.Loc,
7150+
DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
71147151
}
71157152

71167153
void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -7169,22 +7206,25 @@ void Sema::redelayDiagnostics(DelayedDiagnosticPool &pool) {
71697206
}
71707207

71717208
void Sema::EmitAvailabilityWarning(AvailabilityResult AR,
7172-
NamedDecl *D, StringRef Message,
7173-
SourceLocation Loc,
7209+
const NamedDecl *ReferringDecl,
7210+
const NamedDecl *OffendingDecl,
7211+
StringRef Message, SourceLocation Loc,
71747212
const ObjCInterfaceDecl *UnknownObjCClass,
7175-
const ObjCPropertyDecl *ObjCProperty,
7213+
const ObjCPropertyDecl *ObjCProperty,
71767214
bool ObjCPropertyAccess) {
71777215
// Delay if we're currently parsing a declaration.
71787216
if (DelayedDiagnostics.shouldDelayDiagnostics()) {
7179-
DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
7180-
AR, Loc, D, UnknownObjCClass, ObjCProperty, Message,
7181-
ObjCPropertyAccess));
7217+
DelayedDiagnostics.add(
7218+
DelayedDiagnostic::makeAvailability(
7219+
AR, Loc, ReferringDecl, OffendingDecl, UnknownObjCClass,
7220+
ObjCProperty, Message, ObjCPropertyAccess));
71827221
return;
71837222
}
71847223

71857224
Decl *Ctx = cast<Decl>(getCurLexicalContext());
7186-
DoEmitAvailabilityWarning(*this, AR, Ctx, D, Message, Loc, UnknownObjCClass,
7187-
ObjCProperty, ObjCPropertyAccess);
7225+
DoEmitAvailabilityWarning(*this, AR, Ctx, ReferringDecl, OffendingDecl,
7226+
Message, Loc, UnknownObjCClass, ObjCProperty,
7227+
ObjCPropertyAccess);
71887228
}
71897229

71907230
namespace {
@@ -7336,19 +7376,21 @@ class DiagnoseUnguardedAvailability
73367376

73377377
void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
73387378
NamedDecl *D, SourceRange Range) {
7339-
7340-
VersionTuple ContextVersion = AvailabilityStack.back();
7341-
if (AvailabilityResult Result =
7342-
SemaRef.ShouldDiagnoseAvailabilityOfDecl(D, nullptr)) {
7379+
AvailabilityResult Result;
7380+
const NamedDecl *OffendingDecl;
7381+
std::tie(Result, OffendingDecl) =
7382+
SemaRef.ShouldDiagnoseAvailabilityOfDecl(D, nullptr);
7383+
if (Result != AR_Available) {
73437384
// All other diagnostic kinds have already been handled in
73447385
// DiagnoseAvailabilityOfDecl.
73457386
if (Result != AR_NotYetIntroduced)
73467387
return;
73477388

7348-
const AvailabilityAttr *AA = getAttrForPlatform(SemaRef.getASTContext(), D);
7389+
const AvailabilityAttr *AA =
7390+
getAttrForPlatform(SemaRef.getASTContext(), OffendingDecl);
73497391
VersionTuple Introduced = AA->getIntroduced();
73507392

7351-
if (ContextVersion >= Introduced)
7393+
if (AvailabilityStack.back() >= Introduced)
73527394
return;
73537395

73547396
// If the context of this function is less available than D, we should not
@@ -7373,8 +7415,9 @@ void DiagnoseUnguardedAvailability::DiagnoseDeclAvailability(
73737415
SemaRef.getASTContext().getTargetInfo().getPlatformName())
73747416
<< Introduced.getAsString();
73757417

7376-
SemaRef.Diag(D->getLocation(), diag::note_availability_specified_here)
7377-
<< D << /* partial */ 3;
7418+
SemaRef.Diag(OffendingDecl->getLocation(),
7419+
diag::note_availability_specified_here)
7420+
<< OffendingDecl << /* partial */ 3;
73787421

73797422
auto FixitDiag =
73807423
SemaRef.Diag(Range.getBegin(), diag::note_unguarded_available_silence)

0 commit comments

Comments
 (0)
Please sign in to comment.