]> granicus.if.org Git - clang/commitdiff
When using an unavailable/deprecated interface Foo inside Foo's interface/implementation
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 6 Oct 2011 23:23:20 +0000 (23:23 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 6 Oct 2011 23:23:20 +0000 (23:23 +0000)
don't emit unavailable errors.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141334 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
include/clang/Sema/Sema.h
lib/Parse/ParseObjc.cpp
lib/Sema/Sema.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExpr.cpp
test/SemaObjC/attr-deprecated.m
test/SemaObjC/class-unavail-warning.m

index cf9bbbe9dd9b79f26f5693662428f9a9db47db2f..a1f602c72a9e06c2e54843cff6f5050742153391 100644 (file)
@@ -520,11 +520,11 @@ private:
     explicit ObjCDeclContextSwitch(Parser &p) : P(p), 
                DC(p.getObjCDeclContext()) {
       if (DC)
-        P.Actions.ActOnObjCContainerFinishDefinition();
+        P.Actions.ActOnObjCTemporaryExitContainerContext();
     }
     ~ObjCDeclContextSwitch() {
       if (DC)
-        P.Actions.ActOnObjCContainerStartDefinition(DC);
+        P.Actions.ActOnObjCReenterContainerContext();
     }
   };
 
index 4b8bbdc6eab727451cb3473a316b39b1e60a0792..6aee5900e2d6b577289d1d202f759d1b5fce6f0c 100644 (file)
@@ -202,6 +202,10 @@ public:
   /// CurContext - This is the current declaration context of parsing.
   DeclContext *CurContext;
 
+  /// \brief Generally null except when we temporarily switch decl contexts,
+  /// like in \see ActOnObjCTemporaryExitContainerContext.
+  DeclContext *OriginalLexicalContext;
+
   /// VAListTagName - The declaration name corresponding to __va_list_tag.
   /// This is used as part of a hack to omit that class from ADL results.
   DeclarationName VAListTagName;
@@ -1224,7 +1228,7 @@ public:
   /// struct, or union).
   void ActOnTagStartDefinition(Scope *S, Decl *TagDecl);
 
-  void ActOnObjCContainerStartDefinition(Decl *IDecl);
+  Decl *ActOnObjCContainerStartDefinition(Decl *IDecl);
 
   /// ActOnStartCXXMemberDeclarations - Invoked when we have parsed a
   /// C++ record definition's base-specifiers clause and are starting its
@@ -1240,6 +1244,13 @@ public:
 
   void ActOnObjCContainerFinishDefinition();
 
+  /// \brief Invoked when we must temporarily exit the objective-c container
+  /// scope for parsing/looking-up C constructs.
+  ///
+  /// Must be followed by a call to \see ActOnObjCReenterContainerContext
+  void ActOnObjCTemporaryExitContainerContext();
+  void ActOnObjCReenterContainerContext();
+
   /// ActOnTagDefinitionError - Invoked when there was an unrecoverable
   /// error parsing the definition of a tag.
   void ActOnTagDefinitionError(Scope *S, Decl *TagDecl);
@@ -6150,6 +6161,10 @@ public:
   Scope *getCurScope() const { return CurScope; }
     
   Decl *getObjCDeclContext() const;
+
+  DeclContext *getCurLexicalContext() const {
+    return OriginalLexicalContext ? OriginalLexicalContext : CurContext;
+  }
 };
 
 /// \brief RAII object that enters a new expression evaluation context.
index 1b48225837342eede43e71d9612cc6b8b5858ece..78c6b87715f95e416c6fc1e4daea8e85c1815df5 100644 (file)
@@ -336,7 +336,6 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
 
   SourceRange AtEnd;
-  Actions.ActOnObjCContainerStartDefinition(CDecl);
     
   while (1) {
     // If this is a method prototype, parse it.
@@ -1195,6 +1194,7 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
   SmallVector<Decl *, 32> AllIvarDecls;
     
   ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
+  ObjCDeclContextSwitch ObjCDC(*this);
 
   SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
 
@@ -1441,7 +1441,6 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
                                     atLoc, nameId, nameLoc, categoryId,
                                     categoryLoc);
 
-    Actions.ActOnObjCContainerStartDefinition(ImplCatType);
     ObjCImpDecl = ImplCatType;
     PendingObjCImpDecl.push_back(ObjCImpDecl);
     return 0;
@@ -1466,7 +1465,6 @@ Decl *Parser::ParseObjCAtImplementationDeclaration(
   if (Tok.is(tok::l_brace)) // we have ivars
     ParseObjCClassInstanceVariables(ImplClsType, tok::objc_private, atLoc);
 
-  Actions.ActOnObjCContainerStartDefinition(ImplClsType);
   ObjCImpDecl = ImplClsType;
   PendingObjCImpDecl.push_back(ObjCImpDecl);
   return 0;
index 679d4f658936a19d1526584fce6f625137bc8271..3f47986367c7afbcdb0ffa1e57d65ea3e18d82a6 100644 (file)
@@ -95,7 +95,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
     LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer),
     Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
     CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter),
-    CurContext(0), PackContext(0), MSStructPragmaOn(false), VisContext(0),
+    CurContext(0), OriginalLexicalContext(0),
+    PackContext(0), MSStructPragmaOn(false), VisContext(0),
     ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0),
     IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0),
     GlobalNewDeleteDeclared(false), 
index 534cd488e7595cbca171c960bab53429c782baba..4a4862bec4ce4e5fddf4a424f6a0ce82c8220e78 100644 (file)
@@ -8004,13 +8004,14 @@ void Sema::ActOnTagStartDefinition(Scope *S, Decl *TagD) {
   PushDeclContext(S, Tag);
 }
 
-void Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
+Decl *Sema::ActOnObjCContainerStartDefinition(Decl *IDecl) {
   assert(isa<ObjCContainerDecl>(IDecl) && 
          "ActOnObjCContainerStartDefinition - Not ObjCContainerDecl");
   DeclContext *OCD = cast<DeclContext>(IDecl);
   assert(getContainingDC(OCD) == CurContext &&
       "The next DeclContext should be lexically contained in the current one.");
   CurContext = OCD;
+  return IDecl;
 }
 
 void Sema::ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagD,
@@ -8068,7 +8069,17 @@ void Sema::ActOnObjCContainerFinishDefinition() {
   // Exit this scope of this interface definition.
   PopDeclContext();
 }
-                                          
+
+void Sema::ActOnObjCTemporaryExitContainerContext() {
+  OriginalLexicalContext = CurContext;
+  ActOnObjCContainerFinishDefinition();
+}
+
+void Sema::ActOnObjCReenterContainerContext() {
+  ActOnObjCContainerStartDefinition(cast<Decl>(OriginalLexicalContext));
+  OriginalLexicalContext = 0;
+}
+
 void Sema::ActOnTagDefinitionError(Scope *S, Decl *TagD) {
   AdjustDeclIfTemplate(TagD);
   TagDecl *Tag = cast<TagDecl>(TagD);
index 940f5a86a61e98657cf21add183785a8763ef314..e5ea1610ad587a70cd3360cad066bb71a5a60708 100644 (file)
@@ -4031,7 +4031,7 @@ void Sema::EmitDeprecationWarning(NamedDecl *D, StringRef Message,
   }
 
   // Otherwise, don't warn if our current context is deprecated.
-  if (isDeclDeprecated(cast<Decl>(CurContext)))
+  if (isDeclDeprecated(cast<Decl>(getCurLexicalContext())))
     return;
   if (!Message.empty())
     Diag(Loc, diag::warn_deprecated_message) << D->getDeclName() 
index de48de15d77c405549078c89b02a4670ca2be5b2..1a1ac2eccf134b9d869ecbf288f2159c8ab26b2d 100644 (file)
@@ -374,7 +374,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
 
       // Return the previous class interface.
       // FIXME: don't leak the objects passed in!
-      return IDecl;
+      return ActOnObjCContainerStartDefinition(IDecl);
     } else {
       IDecl->setLocation(ClassLoc);
       IDecl->setForwardDecl(false);
@@ -482,7 +482,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
   }
 
   CheckObjCDeclScope(IDecl);
-  return IDecl;
+  return ActOnObjCContainerStartDefinition(IDecl);
 }
 
 /// ActOnCompatiblityAlias - this action is called after complete parsing of
@@ -578,7 +578,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
       Diag(PDecl->getLocation(), diag::note_previous_definition);
       // Just return the protocol we already had.
       // FIXME: don't leak the objects passed in!
-      return PDecl;
+      return ActOnObjCContainerStartDefinition(PDecl);
     }
     ObjCList<ObjCProtocolDecl> PList;
     PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
@@ -611,7 +611,7 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc,
   }
 
   CheckObjCDeclScope(PDecl);
-  return PDecl;
+  return ActOnObjCContainerStartDefinition(PDecl);
 }
 
 /// FindProtocolDeclaration - This routine looks up protocols and
@@ -741,7 +741,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
                                      ClassLoc, CategoryLoc, CategoryName,IDecl);
     CDecl->setInvalidDecl();
     Diag(ClassLoc, diag::err_undef_interface) << ClassName;
-    return CDecl;
+    return ActOnObjCContainerStartDefinition(CDecl);
   }
 
   if (!CategoryName && IDecl->getImplementation()) {
@@ -783,7 +783,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
   }
 
   CheckObjCDeclScope(CDecl);
-  return CDecl;
+  return ActOnObjCContainerStartDefinition(CDecl);
 }
 
 /// ActOnStartCategoryImplementation - Perform semantic checks on the
@@ -836,7 +836,7 @@ Decl *Sema::ActOnStartCategoryImplementation(
   }
 
   CheckObjCDeclScope(CDecl);
-  return CDecl;
+  return ActOnObjCContainerStartDefinition(CDecl);
 }
 
 Decl *Sema::ActOnStartClassImplementation(
@@ -930,7 +930,7 @@ Decl *Sema::ActOnStartClassImplementation(
                                    ClassLoc, AtClassImplLoc);
 
   if (CheckObjCDeclScope(IMPDecl))
-    return IMPDecl;
+    return ActOnObjCContainerStartDefinition(IMPDecl);
 
   // Check that there is no duplicate implementation of this class.
   if (IDecl->getImplementation()) {
@@ -947,7 +947,7 @@ Decl *Sema::ActOnStartClassImplementation(
                                         dyn_cast<NamedDecl>(IDecl), 
                                         IMPDecl->getLocation(), 1);
   }
-  return IMPDecl;
+  return ActOnObjCContainerStartDefinition(IMPDecl);
 }
 
 void Sema::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
index ec71a4e94d19edb005d3b7efc86887397333382a..05b0bb7efc7fa247dd524a7ef7fb163460ba6e3f 100644 (file)
@@ -72,7 +72,8 @@ static AvailabilityResult DiagnoseAvailabilityOfDecl(Sema &S,
       break;
             
     case AR_Unavailable:
-      if (cast<Decl>(S.CurContext)->getAvailability() != AR_Unavailable) {
+      if (cast<Decl>(S.getCurLexicalContext())->getAvailability() !=
+            AR_Unavailable) {
         if (Message.empty()) {
           if (!UnknownObjCClass)
             S.Diag(Loc, diag::err_unavailable) << D->getDeclName();
index 0152aca934ca0687cc822df8d3c61f5dcc4f39fd..be6c51f8c415105bf929638cf14541cd268a9208 100644 (file)
@@ -85,8 +85,10 @@ int t5() {
 __attribute ((deprecated))  
 @interface DEPRECATED {
   @public int ivar; 
+  DEPRECATED *ivar2; // no warning.
 } 
 - (int) instancemethod;
+- (DEPRECATED *) meth; // no warning.
 @property  int prop; 
 @end
 
index 408647ac11c18756de0c33be2ef31aaa7d9151db..a0c2d5588e676d06dbb3fffbc0d5d50f7a9e92d8 100644 (file)
@@ -2,17 +2,25 @@
 // rdar://9092208
 
 __attribute__((unavailable("not available")))
-@interface MyClass { // expected-note 5 {{declaration has been explicitly marked unavailable here}}
+@interface MyClass { // expected-note 7 {{declaration has been explicitly marked unavailable here}}
 @public
     void *_test;
+    MyClass *ivar; // no error.
 }
 
 - (id)self;
 - new;
 + (void)addObject:(id)anObject;
+- (MyClass *)meth; // no error.
 
 @end
 
+@interface Foo {
+  MyClass *ivar; // expected-error {{unavailable}}
+}
+- (MyClass *)meth; // expected-error {{unavailable}}
+@end
+
 int main() {
  [MyClass new]; // expected-error {{'MyClass' is unavailable: not available}}
  [MyClass self]; // expected-error {{'MyClass' is unavailable: not available}}