summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2016-10-28 21:39:27 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2016-10-28 21:39:27 +0000
commitb5328fc64ee57c6058515459d82025c7ecbdc410 (patch)
tree4289090b07a4d4738c793a88b3a45b7203a53cb1
parentc57ace48d79470adc64e1dfd0c50a86148da3a6a (diff)
downloadclang-b5328fc64ee57c6058515459d82025c7ecbdc410.tar.gz
[Sema] Delay partial availability diagnostics, just like deprecated
This is done so that the following compiles with no warnings: int fn(type_10_12) __attribute__((availability(macos, introduced=10.12))); Differential revision: https://reviews.llvm.org/D25284 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285457 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/DelayedDiagnostic.h42
-rw-r--r--lib/Sema/DelayedDiagnostic.cpp33
-rw-r--r--lib/Sema/SemaDeclAttr.cpp22
-rw-r--r--test/SemaObjC/unguarded-availability.m5
4 files changed, 44 insertions, 58 deletions
diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h
index 1d184fb928..b73ec0868f 100644
--- a/include/clang/Sema/DelayedDiagnostic.h
+++ b/include/clang/Sema/DelayedDiagnostic.h
@@ -113,9 +113,9 @@ private:
/// the complete parsing of the current declaration.
class DelayedDiagnostic {
public:
- enum DDKind { Deprecation, Unavailable, Access, ForbiddenType };
+ enum DDKind : unsigned char { Availability, Access, ForbiddenType };
- unsigned char Kind; // actually a DDKind
+ DDKind Kind;
bool Triggered;
SourceLocation Loc;
@@ -164,17 +164,19 @@ public:
return *reinterpret_cast<const AccessedEntity*>(AccessData);
}
- const NamedDecl *getDeprecationDecl() const {
- assert((Kind == Deprecation || Kind == Unavailable) &&
- "Not a deprecation diagnostic.");
- return DeprecationData.Decl;
+ const NamedDecl *getAvailabilityDecl() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return AvailabilityData.Decl;
}
- StringRef getDeprecationMessage() const {
- assert((Kind == Deprecation || Kind == Unavailable) &&
- "Not a deprecation diagnostic.");
- return StringRef(DeprecationData.Message,
- DeprecationData.MessageLen);
+ StringRef getAvailabilityMessage() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return StringRef(AvailabilityData.Message, AvailabilityData.MessageLen);
+ }
+
+ AvailabilityResult getAvailabilityResult() const {
+ assert(Kind == Availability && "Not an availability diagnostic.");
+ return AvailabilityData.AR;
}
/// The diagnostic ID to emit. Used like so:
@@ -195,27 +197,28 @@ public:
assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType);
}
-
+
const ObjCInterfaceDecl *getUnknownObjCClass() const {
- return DeprecationData.UnknownObjCClass;
+ return AvailabilityData.UnknownObjCClass;
}
const ObjCPropertyDecl *getObjCProperty() const {
- return DeprecationData.ObjCProperty;
+ return AvailabilityData.ObjCProperty;
}
-
+
bool getObjCPropertyAccess() const {
- return DeprecationData.ObjCPropertyAccess;
+ return AvailabilityData.ObjCPropertyAccess;
}
-
+
private:
- struct DD {
+ struct AD {
const NamedDecl *Decl;
const ObjCInterfaceDecl *UnknownObjCClass;
const ObjCPropertyDecl *ObjCProperty;
const char *Message;
size_t MessageLen;
+ AvailabilityResult AR;
bool ObjCPropertyAccess;
};
@@ -226,8 +229,7 @@ private:
};
union {
- /// Deprecation
- struct DD DeprecationData;
+ struct AD AvailabilityData;
struct FTD ForbiddenTypeData;
/// Access control.
diff --git a/lib/Sema/DelayedDiagnostic.cpp b/lib/Sema/DelayedDiagnostic.cpp
index f6950301a1..2fa5718d4e 100644
--- a/lib/Sema/DelayedDiagnostic.cpp
+++ b/lib/Sema/DelayedDiagnostic.cpp
@@ -20,7 +20,7 @@ using namespace clang;
using namespace sema;
DelayedDiagnostic
-DelayedDiagnostic::makeAvailability(AvailabilityResult AD,
+DelayedDiagnostic::makeAvailability(AvailabilityResult AR,
SourceLocation Loc,
const NamedDecl *D,
const ObjCInterfaceDecl *UnknownObjCClass,
@@ -28,42 +28,33 @@ DelayedDiagnostic::makeAvailability(AvailabilityResult AD,
StringRef Msg,
bool ObjCPropertyAccess) {
DelayedDiagnostic DD;
- switch (AD) {
- case AR_Deprecated:
- DD.Kind = Deprecation;
- break;
- case AR_Unavailable:
- DD.Kind = Unavailable;
- break;
- default:
- llvm_unreachable("partial diags should not be delayed");
- }
+ DD.Kind = Availability;
DD.Triggered = false;
DD.Loc = Loc;
- DD.DeprecationData.Decl = D;
- DD.DeprecationData.UnknownObjCClass = UnknownObjCClass;
- DD.DeprecationData.ObjCProperty = ObjCProperty;
+ DD.AvailabilityData.Decl = D;
+ DD.AvailabilityData.UnknownObjCClass = UnknownObjCClass;
+ DD.AvailabilityData.ObjCProperty = ObjCProperty;
char *MessageData = nullptr;
if (Msg.size()) {
MessageData = new char [Msg.size()];
memcpy(MessageData, Msg.data(), Msg.size());
}
- DD.DeprecationData.Message = MessageData;
- DD.DeprecationData.MessageLen = Msg.size();
- DD.DeprecationData.ObjCPropertyAccess = ObjCPropertyAccess;
+ DD.AvailabilityData.Message = MessageData;
+ DD.AvailabilityData.MessageLen = Msg.size();
+ DD.AvailabilityData.AR = AR;
+ DD.AvailabilityData.ObjCPropertyAccess = ObjCPropertyAccess;
return DD;
}
void DelayedDiagnostic::Destroy() {
- switch (static_cast<DDKind>(Kind)) {
+ switch (Kind) {
case Access:
getAccessData().~AccessedEntity();
break;
- case Deprecation:
- case Unavailable:
- delete [] DeprecationData.Message;
+ case Availability:
+ delete[] AvailabilityData.Message;
break;
case ForbiddenType:
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 936c29767d..df5720fc2c 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -6510,9 +6510,6 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
break;
case AR_NotYetIntroduced:
- assert(!S.getCurFunctionOrMethodDecl() &&
- "Function-level partial availablity should not be diagnosed here!");
-
diag = diag::warn_partial_availability;
diag_message = diag::warn_partial_message;
diag_fwdclass_message = diag::warn_partial_fwdclass_message;
@@ -6585,15 +6582,14 @@ static void DoEmitAvailabilityWarning(Sema &S, AvailabilityResult K,
static void handleDelayedAvailabilityCheck(Sema &S, DelayedDiagnostic &DD,
Decl *Ctx) {
- assert(DD.Kind == DelayedDiagnostic::Deprecation ||
- DD.Kind == DelayedDiagnostic::Unavailable);
- AvailabilityResult AR = DD.Kind == DelayedDiagnostic::Deprecation
- ? AR_Deprecated
- : AR_Unavailable;
+ assert(DD.Kind == DelayedDiagnostic::Availability &&
+ "Expected an availability diagnostic here");
+
DD.Triggered = true;
DoEmitAvailabilityWarning(
- S, AR, Ctx, DD.getDeprecationDecl(), DD.getDeprecationMessage(), DD.Loc,
- DD.getUnknownObjCClass(), DD.getObjCProperty(), false);
+ S, DD.getAvailabilityResult(), Ctx, DD.getAvailabilityDecl(),
+ DD.getAvailabilityMessage(), DD.Loc, DD.getUnknownObjCClass(),
+ DD.getObjCProperty(), false);
}
void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
@@ -6623,8 +6619,7 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) {
continue;
switch (diag.Kind) {
- case DelayedDiagnostic::Deprecation:
- case DelayedDiagnostic::Unavailable:
+ case DelayedDiagnostic::Availability:
// Don't bother giving deprecation/unavailable diagnostics if
// the decl is invalid.
if (!decl->isInvalidDecl())
@@ -6659,8 +6654,7 @@ void Sema::EmitAvailabilityWarning(AvailabilityResult AR,
const ObjCPropertyDecl *ObjCProperty,
bool ObjCPropertyAccess) {
// Delay if we're currently parsing a declaration.
- if (DelayedDiagnostics.shouldDelayDiagnostics() &&
- AR != AR_NotYetIntroduced) {
+ if (DelayedDiagnostics.shouldDelayDiagnostics()) {
DelayedDiagnostics.add(DelayedDiagnostic::makeAvailability(
AR, Loc, D, UnknownObjCClass, ObjCProperty, Message,
ObjCPropertyAccess));
diff --git a/test/SemaObjC/unguarded-availability.m b/test/SemaObjC/unguarded-availability.m
index fe25c8bb14..4369a0e329 100644
--- a/test/SemaObjC/unguarded-availability.m
+++ b/test/SemaObjC/unguarded-availability.m
@@ -63,7 +63,7 @@ typedef int int_10_11 AVAILABLE_10_11; // expected-note {{'int_10_11' has been e
#ifdef OBJCPP
// expected-note@+2 {{marked partial here}}
#endif
-typedef int int_10_12 AVAILABLE_10_12; // expected-note 3 {{'int_10_12' has been explicitly marked partial here}}
+typedef int int_10_12 AVAILABLE_10_12; // expected-note 2 {{'int_10_12' has been explicitly marked partial here}}
void use_typedef() {
int_10_11 x; // expected-warning{{'int_10_11' is only available on macOS 10.11 or newer}} expected-note{{enclose 'int_10_11' in an @available check to silence this warning}}
@@ -127,8 +127,7 @@ void test_blocks() {
void test_params(int_10_12 x); // expected-warning {{'int_10_12' is partial: introduced in macOS 10.12}} expected-note{{redeclare}}
-// FIXME: This should be fine!
-void test_params2(int_10_12 x) AVAILABLE_10_12; // expected-warning {{'int_10_12' is partial: introduced in macOS 10.12}} expected-note{{redeclare}}
+void test_params2(int_10_12 x) AVAILABLE_10_12; // no warn
#ifdef OBJCPP