]> granicus.if.org Git - clang/commitdiff
Tweak availability checking to look through typedef declarations.
authorTed Kremenek <kremenek@apple.com>
Thu, 14 May 2015 22:07:25 +0000 (22:07 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 14 May 2015 22:07:25 +0000 (22:07 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@237396 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/SemaObjC/attr-availability.m

index 8dee0eebc5158ecb1f8743da1c56dfec6ac75638..0c5c23a3e2a6536b36add74b48a60629229ec8a8 100644 (file)
@@ -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<TypedefNameDecl>(D)) {
+    if (Result == AR_Available) {
+      if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
+        D = TT->getDecl();
+        Result = D->getAvailability(&Message);
+        continue;
+      }
+    }
+    break;
+  }
     
   // Forward class declarations get their attributes from their definition.
   if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(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<EnumConstantDecl>(D))
     if (Result == AR_Available) {
       const DeclContext *DC = ECD->getDeclContext();
index bac4be2d1dfcc63277959fa7d4a96ca0ecdbae1c..ea97e0e472d312bbd1dbc6d5f1f6b27c8dabd789 100644 (file)
@@ -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; 
+}