forked from OSchip/llvm-project
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. llvm-svn: 62091
This commit is contained in:
parent
5daa1abf25
commit
45a33ecce1
|
@ -848,7 +848,7 @@ void Parser::ParseObjCClassInstanceVariables(DeclTy *interfaceDecl,
|
|||
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 "{"
|
||||
|
||||
|
|
|
@ -506,6 +506,8 @@ public:
|
|||
// 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,
|
||||
|
|
|
@ -251,6 +251,38 @@ MaybeConstructOverloadSet(ASTContext &Context,
|
|||
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 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
|
|||
// 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 @@ CreateNewDecl:
|
|||
|
||||
// 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 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
|
|||
|
||||
// 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.
|
||||
|
|
|
@ -35,3 +35,31 @@ int test_struct_scope_3(struct S4 * s4) { // expected-warning{{declaration of 's
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
|
||||
@protocol NSObject
|
||||
- (BOOL)isEqual:(id)object;
|
||||
- (BOOL)respondsToSelector:(SEL)aSelector;
|
||||
@end
|
||||
@protocol NSCopying
|
||||
- (id)copyWithZone:(NSZone *)zone;
|
||||
@end
|
||||
@protocol NSMutableCopying
|
||||
- (id)mutableCopyWithZone:(NSZone *)zone;
|
||||
@end
|
||||
@protocol NSCoding
|
||||
- (void)encodeWithCoder:(NSCoder *)aCoder;
|
||||
@end
|
||||
@interface NSObject <NSObject> {}
|
||||
@end
|
||||
@class NSString, NSData;
|
||||
typedef struct _NSPoint {}
|
||||
NSRange;
|
||||
@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
|
||||
- (NSUInteger)length;
|
||||
@end
|
||||
@interface NSMutableString : NSString
|
||||
- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)aString;
|
||||
@end
|
||||
@class NSArray, NSDictionary, NSMapTable;
|
||||
@interface NSResponder : NSObject <NSCoding> {}
|
||||
@end
|
||||
@protocol NSAnimatablePropertyContainer
|
||||
- (id)animator;
|
||||
@end
|
||||
extern NSString *NSAnimationTriggerOrderIn ;
|
||||
@interface NSView : NSResponder <NSAnimatablePropertyContainer> {
|
||||
struct __VFlags2 {} _vFlags2;
|
||||
}
|
||||
@end
|
||||
@class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView;
|
||||
@interface FooiagramView : NSView {
|
||||
id _delegate;
|
||||
}
|
||||
@end
|
||||
@class FooiagramView;
|
||||
@interface _FooiagramViewReserved : NSObject {
|
||||
@public
|
||||
NSMutableString *_typeToSelectString;
|
||||
struct _FooiagramViewFlags {
|
||||
unsigned int delegateRespondsToPrintInfoForBarView : 1;
|
||||
} _dvFlags;
|
||||
}
|
||||
@end
|
||||
extern _FooiagramViewReserved *_FooiagramViewBarViewReserved(FooiagramView *BarView);
|
||||
@interface FooiagramView (FooiagramViewPrivate)
|
||||
+ (Class)_defaultBarToolManagerClass;
|
||||
@end
|
||||
@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:)];
|
||||
}
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
// <rdar://problem/6487684>
|
||||
@interface WizKing_MIKeep {
|
||||
struct __LoreStuffNode *_historyStuff;
|
||||
}
|
||||
@end
|
||||
typedef struct __LoreStuffNode {} LoreStuffNode;
|
||||
@implementation WizKing_MIKeep
|
||||
- init {
|
||||
LoreStuffNode *node;
|
||||
node = &(_historyStuff[1]);
|
||||
}
|
||||
@end
|
||||
|
||||
// <rdar://problem/6487702>
|
||||
typedef long unsigned int __darwin_size_t;
|
||||
typedef __darwin_size_t size_t;
|
||||
void *memset(void *, int, size_t);
|
||||
@class NSString, NSURL, NSError;
|
||||
@interface OingoWerdnaPeon : NSObject {}
|
||||
@end typedef enum {
|
||||
OingoPT_SmashOK, OingoPT_NoSuchFile, }
|
||||
OingoWerdnaPeonIOMethod;
|
||||
@interface OingoWerdnaPeonSmashDrivel : NSObject <NSCopying> {}
|
||||
@end
|
||||
@interface OingoBoingoContraptionPeon : OingoWerdnaPeon {
|
||||
struct _OingoBoingoContraptionPeonFlags {}
|
||||
_nfttFlags;
|
||||
}
|
||||
@end
|
||||
@implementation OingoBoingoContraptionPeon
|
||||
+ (void)initialize {}
|
||||
- (id)initWithSmashDrivel:(OingoWerdnaPeonSmashDrivel *)info {
|
||||
if (self != ((void *)0)) {
|
||||
(void)memset(&_nfttFlags, 0, sizeof(struct _OingoBoingoContraptionPeonFlags));
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
@interface Blah {
|
||||
struct X {
|
||||
int x;
|
||||
} value;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation Blah
|
||||
- (int)getValue {
|
||||
struct X *xp = &value;
|
||||
return xp->x;
|
||||
}
|
||||
@end
|
Loading…
Reference in New Issue