[cfe-commits] r62091 - in /cfe/trunk: lib/Parse/ParseObjc.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp test/Sema/type-spec-struct-union.c test/SemaObjC/interface-scope-2.m

Douglas Gregor dgregor at apple.com
Mon Jan 12 10:45:56 PST 2009


Author: dgregor
Date: Mon Jan 12 12:45:55 2009
New Revision: 62091

URL: http://llvm.org/viewvc/llvm-project?rev=62091&view=rev
Log:
Properly set the scope of non-fields declared within a struct, union,
or enum to be outside that struct, union, or enum. Fixes several
regressions: 

  <rdar://problem/6487662>
  <rdar://problem/6487669>
  <rdar://problem/6487684>
  <rdar://problem/6487702>
  PR clang/3305
  PR clang/3312

There is still some work to do in Objective-C++, but this requires
that each of the Objective-C entities (interfaces, implementations,
etc.) to be introduced into the context stack with
PushDeclContext/PopDeclContext. This will be a separate fix, later.


Added:
    cfe/trunk/test/SemaObjC/interface-scope-2.m
Modified:
    cfe/trunk/lib/Parse/ParseObjc.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/type-spec-struct-union.c

Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=62091&r1=62090&r2=62091&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Mon Jan 12 12:45:55 2009
@@ -848,7 +848,7 @@
   llvm::SmallVector<DeclTy*, 32> AllIvarDecls;
   llvm::SmallVector<FieldDeclarator, 8> FieldDeclarators;
 
-  ParseScope ClassScope(this, Scope::DeclScope);
+  ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
 
   SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
   

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=62091&r1=62090&r2=62091&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jan 12 12:45:55 2009
@@ -506,6 +506,8 @@
   // we will need a better way to specify lookup criteria for things
   // like template specializations, explicit template instantiations, etc.
 
+  Scope *getNonFieldDeclScope(Scope *S);
+
   /// More parsing and symbol table subroutines.
   Decl *LookupDecl(DeclarationName Name, unsigned NSI, Scope *S,
                    const DeclContext *LookupCtx = 0,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=62091&r1=62090&r2=62091&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jan 12 12:45:55 2009
@@ -251,6 +251,38 @@
   return *I;
 }
 
+/// getNonFieldDeclScope - Retrieves the innermost scope, starting
+/// from S, where a non-field would be declared. This routine copes
+/// with the difference between C and C++ scoping rules in structs and
+/// unions. For example, the following code is well-formed in C but
+/// ill-formed in C++:
+/// @code
+/// struct S6 {
+///   enum { BAR } e;
+/// };
+/// 
+/// void test_S6() {
+///   struct S6 a;
+///   a.e = BAR;
+/// }
+/// @endcode
+/// For the declaration of BAR, this routine will return a different
+/// scope. The scope S will be the scope of the unnamed enumeration
+/// within S6. In C++, this routine will return the scope associated
+/// with S6, because the enumeration's scope is a transparent
+/// context but structures can contain non-field names. In C, this
+/// routine will return the translation unit scope, since the
+/// enumeration's scope is a transparent context and structures cannot
+/// contain non-field names.
+Scope *Sema::getNonFieldDeclScope(Scope *S) {
+  while (((S->getFlags() & Scope::DeclScope) == 0) ||
+         (S->getEntity() && 
+          ((DeclContext *)S->getEntity())->isTransparentContext()) ||
+         (S->isClassScope() && !getLangOptions().CPlusPlus))
+    S = S->getParent();
+  return S;
+}
+
 /// LookupDecl - Look up the inner-most declaration in the specified
 /// namespace. NamespaceNameOnly - during lookup only namespace names
 /// are considered as required in C++ [basic.lookup.udir] 3.4.6.p1
@@ -2999,7 +3031,9 @@
     // Find the scope where we'll be declaring the tag.
     while (S->isClassScope() || 
            (getLangOptions().CPlusPlus && S->isFunctionPrototypeScope()) ||
-           ((S->getFlags() & Scope::DeclScope) == 0))
+           ((S->getFlags() & Scope::DeclScope) == 0) ||
+           (S->getEntity() && 
+            ((DeclContext *)S->getEntity())->isTransparentContext()))
       S = S->getParent();
   }
 
@@ -3065,10 +3099,7 @@
   
   // If this has an identifier, add it to the scope stack.
   if (Name) {
-    // The scope passed in may not be a decl scope.  Zip up the scope tree until
-    // we find one that is.
-    while ((S->getFlags() & Scope::DeclScope) == 0)
-      S = S->getParent();
+    S = getNonFieldDeclScope(S);
     
     // Add it to the decl chain.
     if (LexicalContext != CurContext) {
@@ -3509,8 +3540,7 @@
 
   // The scope passed in may not be a decl scope.  Zip up the scope tree until
   // we find one that is.
-  while ((S->getFlags() & Scope::DeclScope) == 0)
-    S = S->getParent();
+  S = getNonFieldDeclScope(S);
   
   // Verify that there isn't already something declared with this name in this
   // scope.

Modified: cfe/trunk/test/Sema/type-spec-struct-union.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/type-spec-struct-union.c?rev=62091&r1=62090&r2=62091&view=diff

==============================================================================
--- cfe/trunk/test/Sema/type-spec-struct-union.c (original)
+++ cfe/trunk/test/Sema/type-spec-struct-union.c Mon Jan 12 12:45:55 2009
@@ -35,3 +35,31 @@
 }
 
 void f(struct S5 { int y; } s5); // expected-warning{{declaration of 'struct S5' will not be visible outside of this function}}
+
+// PR clang/3312
+struct S6 {
+        enum { BAR } e;
+};
+
+void test_S6() {
+        struct S6 a;
+        a.e = BAR;
+}
+
+// <rdar://problem/6487669>
+typedef struct z_foo_s {
+  struct bar_baz *baz;
+} z_foo;
+typedef z_foo *z_foop;
+struct bar_baz {
+  enum {
+    SQUAT, FLAG, DICT4, DICT3, DICT2, DICT1, DICT0, HOP, CHECK4, CHECK3, CHECK2, CHECK1, DONE, BAD
+  } mode;
+  int             nowrap;
+};
+int 
+wizbiz_quxPoof(z)
+  z_foop       z;
+{
+  z->baz->mode = z->baz->nowrap ? HOP : SQUAT;
+}

Added: cfe/trunk/test/SemaObjC/interface-scope-2.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/interface-scope-2.m?rev=62091&view=auto

==============================================================================
--- cfe/trunk/test/SemaObjC/interface-scope-2.m (added)
+++ cfe/trunk/test/SemaObjC/interface-scope-2.m Mon Jan 12 12:45:55 2009
@@ -0,0 +1,126 @@
+// RUN: clang -fsyntax-only -verify %s
+// FIXME: must also compile as Objective-C++ 
+
+// <rdar://problem/6487662>
+typedef struct objc_selector *SEL;
+typedef signed char BOOL;
+typedef unsigned int NSUInteger;
+typedef struct _NSZone NSZone;
+ at class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
+ at protocol NSObject
+- (BOOL)isEqual:(id)object;
+- (BOOL)respondsToSelector:(SEL)aSelector;
+ at end
+ at protocol NSCopying
+- (id)copyWithZone:(NSZone *)zone;
+ at end
+ at protocol NSMutableCopying
+- (id)mutableCopyWithZone:(NSZone *)zone;
+ at end
+ at protocol NSCoding
+- (void)encodeWithCoder:(NSCoder *)aCoder;
+ at end
+ at interface NSObject <NSObject> {}
+ at end
+ at class NSString, NSData;
+typedef struct _NSPoint {}
+NSRange;
+ at interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
+- (NSUInteger)length;
+ at end
+ at interface NSMutableString : NSString
+- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)aString;
+ at end
+ at class NSArray, NSDictionary, NSMapTable;
+ at interface NSResponder : NSObject <NSCoding> {}
+ at end
+ at protocol NSAnimatablePropertyContainer
+- (id)animator;
+ at end
+extern NSString *NSAnimationTriggerOrderIn ;
+ at interface NSView : NSResponder  <NSAnimatablePropertyContainer>  {
+  struct __VFlags2 {} _vFlags2;
+}
+ at end
+ at class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView;
+ at interface FooiagramView : NSView {
+id _delegate;
+}
+ at end
+ at class FooiagramView;
+ at interface _FooiagramViewReserved : NSObject {
+ at public
+  NSMutableString *_typeToSelectString;
+  struct _FooiagramViewFlags {
+      unsigned int delegateRespondsToPrintInfoForBarView : 1;
+  } _dvFlags;
+}
+ at end
+extern _FooiagramViewReserved *_FooiagramViewBarViewReserved(FooiagramView *BarView);
+ at interface FooiagramView (FooiagramViewPrivate)
++ (Class)_defaultBarToolManagerClass;
+ at end
+ at implementation FooiagramView
+static NSMapTable *_defaultMenuForClass = 0;
+- (void)setDelegate:(id)delegate {
+  if (_delegate != delegate) {
+    struct _FooiagramViewFlags *dvFlags =
+      &_FooiagramViewBarViewReserved(self)->_dvFlags;
+    if (_delegate != ((void *)0)) {
+      dvFlags->delegateRespondsToPrintInfoForBarView = [_delegate respondsToSelector:@selector(printInfoForBarView:)];
+    }
+  }
+}
+ at end
+
+// <rdar://problem/6487684>
+ at interface WizKing_MIKeep {
+struct __LoreStuffNode *_historyStuff;
+}
+ at end
+typedef struct __LoreStuffNode {} LoreStuffNode;
+ at implementation WizKing_MIKeep
+- init {
+  LoreStuffNode *node;
+  node = &(_historyStuff[1]);
+}
+ at end
+
+// <rdar://problem/6487702>
+typedef long unsigned int __darwin_size_t;
+typedef __darwin_size_t size_t;
+void *memset(void *, int, size_t);
+ at class NSString, NSURL, NSError;
+ at interface OingoWerdnaPeon : NSObject {}
+ at end        typedef enum {
+OingoPT_SmashOK,     OingoPT_NoSuchFile, }
+OingoWerdnaPeonIOMethod;
+ at interface OingoWerdnaPeonSmashDrivel : NSObject <NSCopying> {}
+ at end
+ at interface OingoBoingoContraptionPeon : OingoWerdnaPeon {
+struct _OingoBoingoContraptionPeonFlags {}
+_nfttFlags;
+}
+ at end
+ at implementation OingoBoingoContraptionPeon
++ (void)initialize {}
+- (id)initWithSmashDrivel:(OingoWerdnaPeonSmashDrivel *)info {
+  if (self != ((void *)0)) {
+    (void)memset(&_nfttFlags, 0, sizeof(struct _OingoBoingoContraptionPeonFlags));
+  }
+}
+ at end
+
+ at interface Blah {
+  struct X {
+    int x;
+  } value;
+}
+ at end
+
+ at implementation Blah
+- (int)getValue {
+  struct X *xp = &value;
+  return xp->x;
+}
+ at end





More information about the cfe-commits mailing list