From f63ef87a0dcbc12b4cbb6ded142fe0dbd4303367 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 14 May 2015 22:07:25 +0000 Subject: [PATCH] Tweak availability checking to look through typedef declarations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@237396 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 20 ++++++++++++++++++-- test/SemaObjC/attr-availability.m | 16 ++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 8dee0eebc5..0c5c23a3e2 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -104,13 +104,29 @@ DiagnoseAvailabilityOfDecl(Sema &S, NamedDecl *D, SourceLocation Loc, bool ObjCPropertyAccess) { // See if this declaration is unavailable or deprecated. std::string Message; + AvailabilityResult Result = D->getAvailability(&Message); + + // For typedefs, if the typedef declaration appears available look + // to the underlying type to see if it is more restrictive. + while (const TypedefNameDecl *TD = TD = dyn_cast(D)) { + if (Result == AR_Available) { + if (const TagType *TT = TD->getUnderlyingType()->getAs()) { + D = TT->getDecl(); + Result = D->getAvailability(&Message); + continue; + } + } + break; + } // Forward class declarations get their attributes from their definition. if (ObjCInterfaceDecl *IDecl = dyn_cast(D)) { - if (IDecl->getDefinition()) + if (IDecl->getDefinition()) { D = IDecl->getDefinition(); + Result = D->getAvailability(&Message); + } } - AvailabilityResult Result = D->getAvailability(&Message); + if (const EnumConstantDecl *ECD = dyn_cast(D)) if (Result == AR_Available) { const DeclContext *DC = ECD->getDeclContext(); diff --git a/test/SemaObjC/attr-availability.m b/test/SemaObjC/attr-availability.m index bac4be2d1d..ea97e0e472 100644 --- a/test/SemaObjC/attr-availability.m +++ b/test/SemaObjC/attr-availability.m @@ -190,3 +190,19 @@ void partialinter1(PartialI2* p) { void partialinter2(PartialI2* p) { // no warning } + + +// Test that both the use of the 'typedef' and the enum constant +// produces an error. rdar://problem/20903588 +#define UNAVAILABLE __attribute__((unavailable("not available"))) + +typedef enum MyEnum : int MyEnum; +enum MyEnum : int { // expected-note {{'MyEnum' has been explicitly marked unavailable here}} + MyEnum_Blah UNAVAILABLE, // expected-note {{'MyEnum_Blah' has been explicitly marked unavailable here}} +} UNAVAILABLE; + +void use_myEnum() { + // expected-error@+2 {{'MyEnum' is unavailable: not available}} + // expected-error@+1 {{MyEnum_Blah' is unavailable: not available}} + MyEnum e = MyEnum_Blah; +} -- 2.40.0