diff options
author | Ed Schouten <ed@FreeBSD.org> | 2009-06-02 17:58:47 +0000 |
---|---|---|
committer | Ed Schouten <ed@FreeBSD.org> | 2009-06-02 17:58:47 +0000 |
commit | ec2b103c267a06a66e926f62cd96767b280f5cf5 (patch) | |
tree | ce7d964cbb5e39695b71481698f10cb099c23d4a /test | |
download | src-ec2b103c267a06a66e926f62cd96767b280f5cf5.tar.gz src-ec2b103c267a06a66e926f62cd96767b280f5cf5.zip |
Import Clang, at r72732.vendor/clang/clang-r72732
Notes
Notes:
svn path=/vendor/clang/dist/; revision=193326
svn path=/vendor/clang/clang-r72732/; revision=193327; tag=vendor/clang/clang-r72732
Diffstat (limited to 'test')
1257 files changed, 41769 insertions, 0 deletions
diff --git a/test/Analysis/CFDateGC.m b/test/Analysis/CFDateGC.m new file mode 100644 index 000000000000..dfc736627bfc --- /dev/null +++ b/test/Analysis/CFDateGC.m @@ -0,0 +1,87 @@ +// RUN: clang-cc -analyze -checker-cfref -verify -fobjc-gc -analyzer-constraints=basic %s && +// RUN: clang-cc -analyze -checker-cfref -verify -fobjc-gc -analyzer-constraints=range %s && +// RUN: clang-cc -analyze -checker-cfref -verify -fobjc-gc -disable-free %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -fobjc-gc %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -fobjc-gc %s + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from +// Foundation.h and CoreFoundation.h (Mac OS X). +// +// It includes the basic definitions for the test cases below. +// Not directly including [Core]Foundation.h directly makes this test case +// both svelte and portable to non-Mac platforms. +//===----------------------------------------------------------------------===// + +typedef const void * CFTypeRef; +void CFRelease(CFTypeRef cf); +CFTypeRef CFRetain(CFTypeRef cf); +CFTypeRef CFMakeCollectable(CFTypeRef cf); +typedef const struct __CFAllocator * CFAllocatorRef; +typedef double CFTimeInterval; +typedef CFTimeInterval CFAbsoluteTime; +typedef const struct __CFDate * CFDateRef; +extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); +extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); +typedef struct objc_object {} *id; +typedef signed char BOOL; +static __inline__ __attribute__((always_inline)) id NSMakeCollectable(CFTypeRef cf) {} +@protocol NSObject - (BOOL)isEqual:(id)object; +- (oneway void)release; +- (id)retain; +@end +@class NSArray; + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +CFAbsoluteTime f1_use_after_release() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + CFRetain(date); + [NSMakeCollectable(date) release]; + CFDateGetAbsoluteTime(date); // no-warning + CFRelease(date); + t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} + return t; +} + +// The following two test cases verifies that CFMakeCollectable is a no-op +// in non-GC mode and a "release" in GC mode. +CFAbsoluteTime f2_use_after_release() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + CFRetain(date); + [(id) CFMakeCollectable(date) release]; + CFDateGetAbsoluteTime(date); // no-warning + CFRelease(date); + t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} + return t; +} + +CFAbsoluteTime f2_noleak() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + CFRetain(date); + [(id) CFMakeCollectable(date) release]; + CFDateGetAbsoluteTime(date); // no-warning + t = CFDateGetAbsoluteTime(date); // no-warning + CFRelease(date); // no-warning + return t; +} + +void f3_leak_with_gc() { + CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); // expected-warning 2 {{leak}} + [[(id) date retain] release]; +} + +// The following test case verifies that we "stop tracking" a retained object +// when it is passed as an argument to an implicitly defined function. +CFAbsoluteTime f4() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + CFRetain(date); + some_implicitly_defined_function_stop_tracking(date); // no-warning + return t; +} diff --git a/test/Analysis/CFNumber.c b/test/Analysis/CFNumber.c new file mode 100644 index 000000000000..f62d2ab569d4 --- /dev/null +++ b/test/Analysis/CFNumber.c @@ -0,0 +1,31 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s + +typedef signed long CFIndex; +typedef const struct __CFAllocator * CFAllocatorRef; +enum { kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2, + kCFNumberSInt32Type = 3, kCFNumberSInt64Type = 4, + kCFNumberFloat32Type = 5, kCFNumberFloat64Type = 6, + kCFNumberCharType = 7, kCFNumberShortType = 8, + kCFNumberIntType = 9, kCFNumberLongType = 10, + kCFNumberLongLongType = 11, kCFNumberFloatType = 12, + kCFNumberDoubleType = 13, kCFNumberCFIndexType = 14, + kCFNumberNSIntegerType = 15, kCFNumberCGFloatType = 16, + kCFNumberMaxType = 16 }; +typedef CFIndex CFNumberType; +typedef const struct __CFNumber * CFNumberRef; +extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr); + +CFNumberRef f1(unsigned char x) { + return CFNumberCreate(0, kCFNumberSInt16Type, &x); // expected-warning{{An 8 bit integer is used to initialize a CFNumber object that represents a 16 bit integer. 8 bits of the CFNumber value will be garbage.}} +} + +CFNumberRef f2(unsigned short x) { + return CFNumberCreate(0, kCFNumberSInt8Type, &x); // expected-warning{{A 16 bit integer is used to initialize a CFNumber object that represents an 8 bit integer. 8 bits of the input integer will be lost.}} +} + +CFNumberRef f3(unsigned i) { + return CFNumberCreate(0, kCFNumberLongType, &i); // expected-warning{{A 32 bit integer is used to initialize a CFNumber object that represents a 64 bit integer.}} +} diff --git a/test/Analysis/CFRetainRelease_NSAssertionHandler.m b/test/Analysis/CFRetainRelease_NSAssertionHandler.m new file mode 100644 index 000000000000..1ff950725c02 --- /dev/null +++ b/test/Analysis/CFRetainRelease_NSAssertionHandler.m @@ -0,0 +1,67 @@ +// RUN: clang-cc -analyze -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=basic && +// RUN: clang-cc -analyze -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=basic && +// RUN: clang-cc -analyze -checker-cfref -verify %s -analyzer-constraints=basic -analyzer-store=region && +// RUN: clang-cc -analyze -checker-cfref -verify %s -analyzer-constraints=range -analyzer-store=region + +typedef struct objc_selector *SEL; +typedef signed char BOOL; +typedef int NSInteger; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @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> {} - (id)init; @end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> +- (NSUInteger)length; ++ (id)stringWithUTF8String:(const char *)nullTerminatedCString; +@end extern NSString * const NSBundleDidLoadNotification; +@interface NSAssertionHandler : NSObject {} ++ (NSAssertionHandler *)currentHandler; +- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...; +@end +extern NSString * const NSConnectionReplyMode; + +//----------------------------------------------------------------------------// +// The following test case was filed in PR 2593: +// http://llvm.org/bugs/show_bug.cgi?id=2593 +// +// There should be no null dereference flagged by the checker because of +// NSParameterAssert and NSAssert. + + +@interface TestAssert : NSObject {} +@end + +@implementation TestAssert + +- (id)initWithPointer: (int*)x +{ + // Expansion of: NSParameterAssert( x != 0 ); + do { if (!((x != 0))) { [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd object:self file:[NSString stringWithUTF8String:"CFRetainRelease_NSAssertionHandler.m"] lineNumber:21 description:(@"Invalid parameter not satisfying: %s"), ("x != 0"), (0), (0), (0), (0)]; } } while(0); + + if( (self = [super init]) != 0 ) + { + *x = 1; // no-warning + } + + return self; +} + +- (id)initWithPointer2: (int*)x +{ + // Expansion of: NSAssert( x != 0, @"" ); + do { if (!((x != 0))) { [[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd object:self file:[NSString stringWithUTF8String:"CFRetainRelease_NSAssertionHandler.m"] lineNumber:33 description:((@"")), (0), (0), (0), (0), (0)]; } } while(0); + + if( (self = [super init]) != 0 ) + { + *x = 1; // no-warning + } + + return self; +} + +@end diff --git a/test/Analysis/CGColorSpace.c b/test/Analysis/CGColorSpace.c new file mode 100644 index 000000000000..2887d47c5118 --- /dev/null +++ b/test/Analysis/CGColorSpace.c @@ -0,0 +1,21 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s + +typedef struct CGColorSpace *CGColorSpaceRef; +extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void); +extern CGColorSpaceRef CGColorSpaceRetain(CGColorSpaceRef space); +extern void CGColorSpaceRelease(CGColorSpaceRef space); + +void f() { + CGColorSpaceRef X = CGColorSpaceCreateDeviceRGB(); // expected-warning{{leak}} + CGColorSpaceRetain(X); +} + +void fb() { + CGColorSpaceRef X = CGColorSpaceCreateDeviceRGB(); + CGColorSpaceRetain(X); + CGColorSpaceRelease(X); + CGColorSpaceRelease(X); // no-warning +} diff --git a/test/Analysis/CheckNSError.m b/test/Analysis/CheckNSError.m new file mode 100644 index 000000000000..779b865aff8c --- /dev/null +++ b/test/Analysis/CheckNSError.m @@ -0,0 +1,59 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s + + +typedef signed char BOOL; +typedef int NSInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end +@interface NSObject <NSObject> {} @end +@class NSDictionary; +@interface NSError : NSObject <NSCopying, NSCoding> {} ++ (id)errorWithDomain:(NSString *)domain code:(NSInteger)code userInfo:(NSDictionary *)dict; +@end +extern NSString * const NSXMLParserErrorDomain ; + +@interface A +- (void)myMethodWhichMayFail:(NSError **)error; +- (BOOL)myMethodWhichMayFail2:(NSError **)error; +@end + +@implementation A +- (void)myMethodWhichMayFail:(NSError **)error { // expected-warning {{Method accepting NSError** should have a non-void return value to indicate whether or not an error occured.}} + *error = [NSError errorWithDomain:@"domain" code:1 userInfo:0]; // expected-warning {{Potential null dereference.}} +} + +- (BOOL)myMethodWhichMayFail2:(NSError **)error { // no-warning + if (error) *error = [NSError errorWithDomain:@"domain" code:1 userInfo:0]; // no-warning + return 0; +} +@end + +struct __CFError {}; +typedef struct __CFError* CFErrorRef; + +void foo(CFErrorRef* error) { // expected-warning {{Function accepting CFErrorRef* should have a non-void return value to indicate whether or not an error occured.}} + *error = 0; // expected-warning {{Potential null dereference.}} +} + +int f1(CFErrorRef* error) { + if (error) *error = 0; // no-warning + return 0; +} + +int f2(CFErrorRef* error) { + if (0 != error) *error = 0; // no-warning + return 0; +} + +int f3(CFErrorRef* error) { + if (error != 0) *error = 0; // no-warning + return 0; +} + + diff --git a/test/Analysis/MissingDealloc.m b/test/Analysis/MissingDealloc.m new file mode 100644 index 000000000000..41498e56ec1d --- /dev/null +++ b/test/Analysis/MissingDealloc.m @@ -0,0 +1,117 @@ +// RUN: clang-cc -analyze -warn-objc-missing-dealloc '-DIBOutlet=__attribute__((iboutlet))' %s --verify +typedef signed char BOOL; +@protocol NSObject +- (BOOL)isEqual:(id)object; +- (Class)class; +@end + +@interface NSObject <NSObject> {} +- (void)dealloc; +- (id)init; +@end + +typedef struct objc_selector *SEL; + +// <rdar://problem/6380411>: 'myproperty' has kind 'assign' and thus the +// assignment through the setter does not perform a release. + +@interface MyObject : NSObject { + id _myproperty; +} +@property(assign) id myproperty; +@end + +@implementation MyObject +@synthesize myproperty=_myproperty; // no-warning +- (void)dealloc { + self.myproperty = 0; + [super dealloc]; +} +@end + +//===------------------------------------------------------------------------=== +// Don't warn about iVars that are selectors. + +@interface TestSELs : NSObject { + SEL a; + SEL b; +} + +@end + +@implementation TestSELs // no-warning +- (id)init { + if( (self = [super init]) ) { + a = @selector(a); + b = @selector(b); + } + + return self; +} +@end + +//===------------------------------------------------------------------------=== +// Don't warn about iVars that are IBOutlets. + +#ifndef IBOutlet +#define IBOutlet +#endif + +@class NSWindow; + +@interface HasOutlet : NSObject { +IBOutlet NSWindow *window; +} +@end + +@implementation HasOutlet // no-warning +@end + +//===------------------------------------------------------------------------=== +// <rdar://problem/6380411> +// Was bogus warning: "The '_myproperty' instance variable was not retained by a +// synthesized property but was released in 'dealloc'" + +@interface MyObject_rdar6380411 : NSObject { + id _myproperty; +} +@property(assign) id myproperty; +@end + +@implementation MyObject_rdar6380411 +@synthesize myproperty=_myproperty; +- (void)dealloc { + // Don't claim that myproperty is released since it the property + // has the 'assign' attribute. + self.myproperty = 0; // no-warning + [super dealloc]; +} +@end + +//===------------------------------------------------------------------------=== +// PR 3187: http://llvm.org/bugs/show_bug.cgi?id=3187 +// - Disable the missing -dealloc check for classes that subclass SenTestCase + +@class NSString; + +@interface SenTestCase : NSObject {} +@end + +@interface MyClassTest : SenTestCase { + NSString *resourcePath; +} +@end + +@interface NSBundle : NSObject {} ++ (NSBundle *)bundleForClass:(Class)aClass; +- (NSString *)resourcePath; +@end + +@implementation MyClassTest +- (void)setUp { + resourcePath = [[NSBundle bundleForClass:[self class]] resourcePath]; +} +- (void)testXXX { + // do something which uses resourcepath +} +@end diff --git a/test/Analysis/NSPanel.m b/test/Analysis/NSPanel.m new file mode 100644 index 000000000000..c4d4c22540f2 --- /dev/null +++ b/test/Analysis/NSPanel.m @@ -0,0 +1,90 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s + +// BEGIN delta-debugging reduced header stuff + +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; +- (oneway void)release; +@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> {} ++ (id)alloc; +@end +typedef float CGFloat; +typedef struct _NSPoint {} NSRect; +static __inline__ __attribute__((always_inline)) NSRect NSMakeRect(CGFloat x, CGFloat y, CGFloat w, CGFloat h) {} +typedef struct {} NSFastEnumerationState; +@protocol NSFastEnumeration +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end +@class NSString; +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> +- (NSUInteger)count; +@end +@interface NSMutableArray : NSArray +- (void)addObject:(id)anObject; +@end @class NSAppleEventDescriptor; +enum { NSBackingStoreRetained = 0, NSBackingStoreNonretained = 1, NSBackingStoreBuffered = 2 }; +typedef NSUInteger NSBackingStoreType; +@interface NSResponder : NSObject <NSCoding> {} @end +@protocol NSAnimatablePropertyContainer +- (id)animator; +@end +@protocol NSValidatedUserInterfaceItem +- (SEL)action; +@end +@protocol NSUserInterfaceValidations +- (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem; +@end @class NSDate, NSDictionary, NSError, NSException, NSNotification; +enum { NSBorderlessWindowMask = 0, NSTitledWindowMask = 1 << 0, NSClosableWindowMask = 1 << 1, NSMiniaturizableWindowMask = 1 << 2, NSResizableWindowMask = 1 << 3 }; +@interface NSWindow : NSResponder <NSAnimatablePropertyContainer, NSUserInterfaceValidations> {} +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag; +@end +extern NSString *NSWindowDidBecomeKeyNotification; +@interface NSPanel : NSWindow {} +@end +@class NSTableHeaderView; + +// END delta-debugging reduced header stuff + +@interface MyClass +{ + NSMutableArray *panels; +} +- (void)myMethod; +- (void)myMethod2; +@end + +@implementation MyClass // no-warning +- (void)myMethod +{ + NSPanel *panel = [[NSPanel alloc] initWithContentRect:NSMakeRect(0, 0, 200, 200) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:(BOOL)1]; + + [panels addObject:panel]; + + [panel release]; // no-warning +} +- (void)myMethod2 +{ + NSPanel *panel = [[NSPanel alloc] initWithContentRect:NSMakeRect(0, 0, 200, 200) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:(BOOL)1]; // no-warning + + [panels addObject:panel]; +} +@end + diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m new file mode 100644 index 000000000000..b707071990f8 --- /dev/null +++ b/test/Analysis/NSString.m @@ -0,0 +1,335 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s + + +// NOTWORK: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// NOTWORK: clang-cc -triple i386-pc-linux-gnu -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from +// Foundation.h (Mac OS X). +// +// It includes the basic definitions for the test cases below. +// Not directly including Foundation.h directly makes this test case +// both svelte and portable to non-Mac platforms. +//===----------------------------------------------------------------------===// + +typedef int int32_t; +typedef const void * CFTypeRef; +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +extern const CFAllocatorRef kCFAllocatorDefault; +extern CFTypeRef CFRetain(CFTypeRef cf); +void CFRelease(CFTypeRef cf); +typedef const struct __CFDictionary * CFDictionaryRef; +const void *CFDictionaryGetValue(CFDictionaryRef theDict, const void *key); +extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...); +typedef signed char BOOL; +typedef int NSInteger; +typedef unsigned int NSUInteger; +@class NSString, Protocol; +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); +typedef NSInteger NSComparisonResult; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject +- (BOOL)isEqual:(id)object; +- (oneway void)release; +- (id)retain; +- (id)autorelease; +@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> {} +- (id)init; ++ (id)alloc; +@end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +typedef struct {} NSFastEnumerationState; +@protocol NSFastEnumeration +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end +@class NSString; +typedef struct _NSRange {} NSRange; +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> +- (NSUInteger)count; +@end +@interface NSMutableArray : NSArray +- (void)addObject:(id)anObject; +- (id)initWithCapacity:(NSUInteger)numItems; +@end +typedef unsigned short unichar; +@class NSData, NSArray, NSDictionary, NSCharacterSet, NSData, NSURL, NSError, NSLocale; +typedef NSUInteger NSStringCompareOptions; +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; +- (NSComparisonResult)compare:(NSString *)string; +- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask; +- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange; +- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange locale:(id)locale; +- (NSComparisonResult)caseInsensitiveCompare:(NSString *)string; +- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator; ++ (id)stringWithFormat:(NSString *)format, ... __attribute__((format(__NSString__, 1, 2))); +@end +@interface NSSimpleCString : NSString {} @end +@interface NSConstantString : NSSimpleCString @end +extern void *_NSConstantStringClassReference; + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +NSComparisonResult f1(NSString* s) { + NSString *aString = 0; + return [s compare:aString]; // expected-warning {{Argument to 'NSString' method 'compare:' cannot be nil.}} +} + +NSComparisonResult f2(NSString* s) { + NSString *aString = 0; + return [s caseInsensitiveCompare:aString]; // expected-warning {{Argument to 'NSString' method 'caseInsensitiveCompare:' cannot be nil.}} +} + +NSComparisonResult f3(NSString* s, NSStringCompareOptions op) { + NSString *aString = 0; + return [s compare:aString options:op]; // expected-warning {{Argument to 'NSString' method 'compare:options:' cannot be nil.}} +} + +NSComparisonResult f4(NSString* s, NSStringCompareOptions op, NSRange R) { + NSString *aString = 0; + return [s compare:aString options:op range:R]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:' cannot be nil.}} +} + +NSComparisonResult f5(NSString* s, NSStringCompareOptions op, NSRange R) { + NSString *aString = 0; + return [s compare:aString options:op range:R locale:0]; // expected-warning {{Argument to 'NSString' method 'compare:options:range:locale:' cannot be nil.}} +} + +NSArray *f6(NSString* s) { + return [s componentsSeparatedByCharactersInSet:0]; // expected-warning {{Argument to 'NSString' method 'componentsSeparatedByCharactersInSet:' cannot be nil.}} +} + +NSString* f7(NSString* s1, NSString* s2, NSString* s3) { + + NSString* s4 = (NSString*) + CFStringCreateWithFormat(kCFAllocatorDefault, 0, // expected-warning{{leak}} + (CFStringRef) __builtin___CFStringMakeConstantString("%@ %@ (%@)"), + s1, s2, s3); + + CFRetain(s4); + return s4; +} + +NSMutableArray* f8() { + + NSString* s = [[NSString alloc] init]; + NSMutableArray* a = [[NSMutableArray alloc] initWithCapacity:2]; + [a addObject:s]; + [s release]; // no-warning + return a; +} + +void f9() { + + NSString* s = [[NSString alloc] init]; + NSString* q = s; + [s release]; + [q release]; // expected-warning {{used after it is released}} +} + +NSString* f10() { + static NSString* s = 0; + if (!s) s = [[NSString alloc] init]; + return s; // no-warning +} + +// Test case for regression reported in <rdar://problem/6452745>. +// Essentially 's' should not be considered allocated on the false branch. +// This exercises the 'EvalAssume' logic in GRTransferFuncs (CFRefCount.cpp). +NSString* f11(CFDictionaryRef dict, const char* key) { + NSString* s = (NSString*) CFDictionaryGetValue(dict, key); + [s retain]; + if (s) { + [s release]; + } +} + +// Test case for passing a tracked object by-reference to a function we +// don't understand. +void unknown_function_f12(NSString** s); +void f12() { + NSString *string = [[NSString alloc] init]; + unknown_function_f12(&string); // no-warning +} + +// Test double release of CFString (PR 4014). +void f13(void) { + CFStringRef ref = CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); + CFRelease(ref); + CFRelease(ref); // expected-warning{{Reference-counted object is used after it is released}} +} + +// Test regular use of -autorelease +@interface TestAutorelease +-(NSString*) getString; +@end +@implementation TestAutorelease +-(NSString*) getString { + NSString *str = [[NSString alloc] init]; + return [str autorelease]; // no-warning +} +- (void)m1 +{ + NSString *s = [[NSString alloc] init]; // expected-warning{{leak}} + [s retain]; + [s autorelease]; +} +- (void)m2 +{ + NSString *s = [[[NSString alloc] init] autorelease]; // expected-warning{{leak}} + [s retain]; +} +- (void)m3 +{ + NSString *s = [[[NSString alloc] init] autorelease]; + [s retain]; + [s autorelease]; +} +- (void)m4 +{ + NSString *s = [[NSString alloc] init]; // expected-warning{{leak}} + [s retain]; +} +- (void)m5 +{ + NSString *s = [[NSString alloc] init]; + [s autorelease]; +} +@end + +@interface C1 : NSObject {} +- (NSString*) getShared; ++ (C1*) sharedInstance; +@end +@implementation C1 : NSObject {} +- (NSString*) getShared { + static NSString* s = 0; + if (!s) s = [[NSString alloc] init]; + return s; // no-warning +} ++ (C1 *)sharedInstance { + static C1 *sharedInstance = 0; + if (!sharedInstance) { + sharedInstance = [[C1 alloc] init]; + } + return sharedInstance; // no-warning +} +@end + +@interface SharedClass : NSObject ++ (id)sharedInstance; +- (id)notShared; +@end + +@implementation SharedClass + +- (id)_init { + if ((self = [super init])) { + NSLog(@"Bar"); + } + return self; +} + +- (id)notShared { + return [[SharedClass alloc] _init]; // expected-warning{{leak}} +} + ++ (id)sharedInstance { + static SharedClass *_sharedInstance = 0; + if (!_sharedInstance) { + _sharedInstance = [[SharedClass alloc] _init]; + } + return _sharedInstance; // no-warning +} +@end + +id testSharedClassFromFunction() { + return [[SharedClass alloc] _init]; // no-warning +} + +// Test OSCompareAndSwap +_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ); +_Bool OSAtomicCompareAndSwap32Barrier( int32_t __oldValue, int32_t __newValue, volatile int32_t *__theValue ); +extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation); + +void testOSCompareAndSwap() { + NSString *old = 0; + NSString *s = [[NSString alloc] init]; // no-warning + if (!OSAtomicCompareAndSwapPtr(0, s, (void**) &old)) + [s release]; + else + [old release]; +} + +void testOSCompareAndSwap32Barrier() { + NSString *old = 0; + NSString *s = [[NSString alloc] init]; // no-warning + if (!OSAtomicCompareAndSwap32Barrier((int32_t) 0, (int32_t) s, (int32_t*) &old)) + [s release]; + else + [old release]; +} + +void test_objc_atomicCompareAndSwap() { + NSString *old = 0; + NSString *s = [[NSString alloc] init]; // no-warning + if (!objc_atomicCompareAndSwapPtr(0, s, &old)) + [s release]; + else + [old release]; +} + +// Test stringWithFormat (<rdar://problem/6815234>) +void test_stringWithFormat() { + NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain]; + [string release]; + [string release]; // expected-warning{{Incorrect decrement of the reference count}} +} + +// Test isTrackedObjectType(). +typedef NSString* WonkyTypedef; +@interface TestIsTracked ++ (WonkyTypedef)newString; +@end + +void test_isTrackedObjectType(void) { + NSString *str = [TestIsTracked newString]; // expected-warning{{Potential leak}} +} + +// Test isTrackedCFObjectType(). +@interface TestIsCFTracked ++ (CFStringRef) badNewCFString; ++ (CFStringRef) newCFString; +@end + +@implementation TestIsCFTracked ++ (CFStringRef) newCFString { + return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // no-warning +} ++ (CFStringRef) badNewCFString { + return CFStringCreateWithFormat(kCFAllocatorDefault, ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "%d" "")), 100); // expected-warning{{leak}} +} + +// Test @synchronized +void test_synchronized(id x) { + @synchronized(x) { + NSString *string = [[NSString stringWithFormat:@"%ld", (long) 100] retain]; // expected-warning {{leak}} + } +} + + diff --git a/test/Analysis/NSWindow.m b/test/Analysis/NSWindow.m new file mode 100644 index 000000000000..9609c5260f53 --- /dev/null +++ b/test/Analysis/NSWindow.m @@ -0,0 +1,89 @@ +// RUN: clang-cc -analyze -checker-cfref -warn-dead-stores -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -warn-dead-stores -analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref -warn-dead-stores -analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -warn-dead-stores -analyzer-store=region -analyzer-constraints=range -verify %s + +// These declarations were reduced using Delta-Debugging from Foundation.h +// on Mac OS X. The test cases are below. + +typedef struct objc_selector *SEL; +typedef signed char BOOL; +typedef unsigned int NSUInteger; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject +- (BOOL)isEqual:(id)object; +- (id)retain; +@end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; +@end +@interface NSObject <NSObject> {} + + (id)alloc; +@end +typedef float CGFloat; +typedef struct _NSPoint {} NSRect; +NSRect NSMakeRect(CGFloat x, CGFloat y, CGFloat w, CGFloat h); +enum { NSBackingStoreRetained = 0, NSBackingStoreNonretained = 1, NSBackingStoreBuffered = 2 }; +typedef NSUInteger NSBackingStoreType; +@interface NSResponder : NSObject <NSCoding> {} +@end +@protocol NSAnimatablePropertyContainer +- (id)animator; +@end +extern NSString *NSAnimationTriggerOrderIn ; +@class CIFilter, CALayer, NSDictionary, NSScreen, NSShadow, NSTrackingArea; +@interface NSView : NSResponder <NSAnimatablePropertyContainer> {} @end +@protocol NSValidatedUserInterfaceItem - (SEL)action; @end +@protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem; @end @class NSNotification, NSText, NSView, NSMutableSet, NSSet, NSDate; +enum { NSBorderlessWindowMask = 0, NSTitledWindowMask = 1 << 0, NSClosableWindowMask = 1 << 1, NSMiniaturizableWindowMask = 1 << 2, NSResizableWindowMask = 1 << 3 }; +@interface NSWindow : NSResponder <NSAnimatablePropertyContainer, NSUserInterfaceValidations> { + struct __wFlags {} _wFlags; +} +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag; +- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag screen:(NSScreen *)screen; +- (void)orderFrontRegardless; +@end + +extern NSString *NSWindowDidBecomeKeyNotification; + +// Test cases. + +void f1() { + NSWindow *window = [[NSWindow alloc] + initWithContentRect:NSMakeRect(0,0,100,100) + styleMask:NSTitledWindowMask|NSClosableWindowMask + backing:NSBackingStoreBuffered + defer:0]; + + [window orderFrontRegardless]; // no-warning +} + +void f2() { + NSWindow *window = [[NSWindow alloc] + initWithContentRect:NSMakeRect(0,0,100,100) + styleMask:NSTitledWindowMask|NSClosableWindowMask + backing:NSBackingStoreBuffered + defer:0 + screen:0]; + + [window orderFrontRegardless]; // no-warning +} + +void f2b() { + // FIXME: NSWindow doesn't own itself until it is displayed. + NSWindow *window = [[NSWindow alloc] // no-warning + initWithContentRect:NSMakeRect(0,0,100,100) + styleMask:NSTitledWindowMask|NSClosableWindowMask + backing:NSBackingStoreBuffered + defer:0 + screen:0]; + + [window orderFrontRegardless]; + + [window retain]; +} + + +void f3() { + // FIXME: For now we don't track NSWindow. + NSWindow *window = [NSWindow alloc]; // expected-warning{{never read}} +} diff --git a/test/Analysis/NoReturn.m b/test/Analysis/NoReturn.m new file mode 100644 index 000000000000..a43f99bdd79b --- /dev/null +++ b/test/Analysis/NoReturn.m @@ -0,0 +1,82 @@ +// RUN: clang-cc -analyze -checker-simple -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-simple -analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s + +#include <stdarg.h> + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from +// Foundation.h (Mac OS X). +// +// It includes the basic definitions for the test cases below. +// Not directly including Foundation.h directly makes this test case +// both svelte and portable to non-Mac platforms. +//===----------------------------------------------------------------------===// + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +@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 +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> +- (NSUInteger)length; ++ (id)stringWithFormat:(NSString *)format, ...; +@end +@interface NSSimpleCString : NSString {} @end +@interface NSConstantString : NSSimpleCString @end +extern void *_NSConstantStringClassReference; +typedef double NSTimeInterval; +@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate; @end +@class NSString, NSDictionary, NSArray; +@interface NSException : NSObject <NSCopying, NSCoding> {} ++ (NSException *)exceptionWithName:(NSString *)name reason:(NSString *)reason userInfo:(NSDictionary *)userInfo; +- (void)raise; +@end +@interface NSException (NSExceptionRaisingConveniences) ++ (void)raise:(NSString *)name format:(NSString *)format, ...; ++ (void)raise:(NSString *)name format:(NSString *)format arguments:(va_list)argList; +@end + +enum {NSPointerFunctionsStrongMemory = (0 << 0), NSPointerFunctionsZeroingWeakMemory = (1 << 0), NSPointerFunctionsOpaqueMemory = (2 << 0), NSPointerFunctionsMallocMemory = (3 << 0), NSPointerFunctionsMachVirtualMemory = (4 << 0), NSPointerFunctionsObjectPersonality = (0 << 8), NSPointerFunctionsOpaquePersonality = (1 << 8), NSPointerFunctionsObjectPointerPersonality = (2 << 8), NSPointerFunctionsCStringPersonality = (3 << 8), NSPointerFunctionsStructPersonality = (4 << 8), NSPointerFunctionsIntegerPersonality = (5 << 8), NSPointerFunctionsCopyIn = (1 << 16), }; + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +int f1(int *x, NSString* s) { + + if (x) ++x; + + [NSException raise:@"Blah" format:[NSString stringWithFormat:@"Blah %@", s]]; + + return *x; // no-warning +} + +int f2(int *x, ...) { + + if (x) ++x; + va_list alist; + va_start(alist, x); + + [NSException raise:@"Blah" format:@"Blah %@" arguments:alist]; + + return *x; // no-warning +} + +int f3(int* x) { + + if (x) ++x; + + [[NSException exceptionWithName:@"My Exception" reason:@"Want to test exceptions." userInfo:0] raise]; + + return *x; // no-warning +} + diff --git a/test/Analysis/ObjCProperties.m b/test/Analysis/ObjCProperties.m new file mode 100644 index 000000000000..7787a1d6ecdc --- /dev/null +++ b/test/Analysis/ObjCProperties.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -analyze -checker-simple -analyzer-store=basic -analyzer-constraints=basic %s -verify && +// RUN: clang-cc -analyze -checker-simple -analyzer-store=basic -analyzer-constraints=range %s -verify && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic %s -verify && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range %s -verify && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic %s -verify && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range %s -verify + +// The point of this test cases is to exercise properties in the static +// analyzer + +@interface MyClass { +@private + id _X; +} +- (id)initWithY:(id)Y; +@property(copy, readwrite) id X; +@end + +@implementation MyClass +@synthesize X = _X; +- (id)initWithY:(id)Y { + self.X = Y; + return self; +} +@end diff --git a/test/Analysis/ObjCRetSigs.m b/test/Analysis/ObjCRetSigs.m new file mode 100644 index 000000000000..0d699168a551 --- /dev/null +++ b/test/Analysis/ObjCRetSigs.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -analyze -warn-objc-methodsigs -verify %s + +#include <stdio.h> + +@interface MyBase +-(long long)length; +@end + +@interface MySub : MyBase{} +-(double)length; +@end + +@implementation MyBase +-(long long)length{ + printf("Called MyBase -length;\n"); + return 3; +} +@end + +@implementation MySub +-(double)length{ // expected-warning{{types are incompatible}} + printf("Called MySub -length;\n"); + return 3.3; +} +@end diff --git a/test/Analysis/PR2599.m b/test/Analysis/PR2599.m new file mode 100644 index 000000000000..098bfe8e8539 --- /dev/null +++ b/test/Analysis/PR2599.m @@ -0,0 +1,64 @@ +// RUN: clang-cc -analyze -analyzer-constraints=basic -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s && +// RUN: clang-cc -analyze -analyzer-constraints=range -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s && +// RUN: clang-cc -analyze -analyzer-constraints=basic -analyzer-store=basic -checker-cfref -fobjc-gc -verify %s && +// RUN: clang-cc -analyze -analyzer-constraints=range -analyzer-store=region -checker-cfref -fobjc-gc -verify %s + +typedef const void * CFTypeRef; +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +typedef const struct __CFDictionary * CFDictionaryRef; +CFTypeRef CFMakeCollectable(CFTypeRef cf) ; +extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...); +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject +- (BOOL)isEqual:(id)object; +- (id)autorelease; +@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> {} +- (id)init; ++ (id)alloc; +@end +enum { NSASCIIStringEncoding = 1, NSNEXTSTEPStringEncoding = 2, NSJapaneseEUCStringEncoding = 3, NSUTF8StringEncoding = 4, NSISOLatin1StringEncoding = 5, NSSymbolStringEncoding = 6, NSNonLossyASCIIStringEncoding = 7, NSShiftJISStringEncoding = 8, NSISOLatin2StringEncoding = 9, NSUnicodeStringEncoding = 10, NSWindowsCP1251StringEncoding = 11, NSWindowsCP1252StringEncoding = 12, NSWindowsCP1253StringEncoding = 13, NSWindowsCP1254StringEncoding = 14, NSWindowsCP1250StringEncoding = 15, NSISO2022JPStringEncoding = 21, NSMacOSRomanStringEncoding = 30, NSUTF16StringEncoding = NSUnicodeStringEncoding, NSUTF16BigEndianStringEncoding = 0x90000100, NSUTF16LittleEndianStringEncoding = 0x94000100, NSUTF32StringEncoding = 0x8c000100, NSUTF32BigEndianStringEncoding = 0x98000100, NSUTF32LittleEndianStringEncoding = 0x9c000100 }; +typedef NSUInteger NSStringEncoding; +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> +- (NSUInteger)length; +- (id)initWithBytesNoCopy:(void *)bytes length:(NSUInteger)len encoding:(NSStringEncoding)encoding freeWhenDone:(BOOL)freeBuffer; +@end +@interface NSAutoreleasePool : NSObject {} +- (void)drain; +@end +extern NSString * const NSXMLParserErrorDomain ; + +// The actual test case. UTIL_AUTORELEASE_CF_AS_ID is a macro that doesn't +// actually do what it was intended to. + +#define NSSTRINGWRAPPER(bytes,len) \ + [[[NSString alloc] initWithBytesNoCopy: (void*)(bytes) length: (len) encoding: NSUTF8StringEncoding freeWhenDone: (BOOL)0] autorelease] + +#define UTIL_AUTORELEASE_CF_AS_ID(cf) ( (((void*)0) == (cf)) ? ((void*)0) : [(id) CFMakeCollectable( (CFTypeRef) cf) autorelease] ) + +#define UTIL_AUTORELEASE_CF_AS_ID_WITHOUT_TEST(cf) ( [(id) CFMakeCollectable( (CFTypeRef) cf) autorelease] ) + +static char *lorem = "fooBarBaz"; + +int main (int argc, const char * argv[]) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + NSString *tmp1 = NSSTRINGWRAPPER(lorem, 6); // no-warning + NSString *tmp2 = UTIL_AUTORELEASE_CF_AS_ID( CFStringCreateWithFormat(((void*)0), ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "lorem: %@" "")), tmp1) ); // expected-warning 2 {{leak}} + NSString *tmp3 = UTIL_AUTORELEASE_CF_AS_ID_WITHOUT_TEST( CFStringCreateWithFormat(((void*)0), ((void*)0), ((CFStringRef) __builtin___CFStringMakeConstantString ("" "lorem: %@" "")), tmp1) ); + NSLog(@"tmp2: %@ tmp3: %@", tmp2, tmp3); + [pool drain]; + return 0; +} diff --git a/test/Analysis/PR2978.m b/test/Analysis/PR2978.m new file mode 100644 index 000000000000..7bc90b8d03e0 --- /dev/null +++ b/test/Analysis/PR2978.m @@ -0,0 +1,61 @@ +// RUN: clang-cc -analyze -warn-objc-missing-dealloc %s -verify + +// Tests for the checker which checks missing/extra ivar 'release' calls +// in dealloc. + +@interface NSObject +- (void)release; +- dealloc; +@end + +@interface MyClass : NSObject { +@private + id _X; + id _Y; + id _Z; + id _K; + id _N; + id _M; + id _V; + id _W; +} +@property(retain) id X; +@property(retain) id Y; +@property(assign) id Z; +@property(assign) id K; +@property(readonly) id N; +@property(retain) id M; +@property(retain) id V; +@property(retain) id W; +-(id) O; +-(void) setO: (id) arg; +@end + +@implementation MyClass +@synthesize X = _X; +@synthesize Y = _Y; // expected-warning{{The '_Y' instance variable was retained by a synthesized property but wasn't released in 'dealloc'}} +@synthesize Z = _Z; // expected-warning{{The '_Z' instance variable was not retained by a synthesized property but was released in 'dealloc'}} +@synthesize K = _K; +@synthesize N = _N; +@synthesize M = _M; +@synthesize V = _V; +@synthesize W = _W; // expected-warning{{The '_W' instance variable was retained by a synthesized property but wasn't released in 'dealloc'}} + +-(id) O{ return 0; } +-(void) setO:(id)arg { } + +- (id)dealloc +{ + [_X release]; + [_Z release]; + [_N release]; + + self.M = 0; // This will release '_M' + [self setV:0]; // This will release '_V' + [self setW:@"newW"]; // This will release '_W', but retain the new value + self.O = 0; // no-warning + [super dealloc]; +} + +@end + diff --git a/test/Analysis/PR3991.m b/test/Analysis/PR3991.m new file mode 100644 index 000000000000..20d4b5b96059 --- /dev/null +++ b/test/Analysis/PR3991.m @@ -0,0 +1,67 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify -triple x86_64-apple-darwin9 %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify -triple x86_64-apple-darwin9 %s + +//===----------------------------------------------------------------------===// +// Delta-debugging produced forward declarations. +//===----------------------------------------------------------------------===// + +typedef signed char BOOL; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +@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 extern id <NSObject> NSAllocateObject(Class aClass, unsigned extraBytes, NSZone *zone); +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding> - (unsigned)count; +@end @class NSTimer, NSPort, NSArray; +@class NSURLHandle, NSMutableArray, NSMutableData, NSData, NSURL; +@interface NSResponder : NSObject <NSCoding> { +} +@end @class NSBitmapImageRep, NSCursor, NSGraphicsContext, NSImage, NSPasteboard, NSScrollView, NSWindow, NSAttributedString; +@interface NSView : NSResponder { + struct __VFlags2 { + } + _vFlags2; +} +@end @class NSTextField, NSPanel, NSArray, NSWindow, NSImage, NSButton, NSError; +@interface NSBox : NSView { +} +@end @class GDataFeedDocList, GDataServiceTicket, GDataServiceTicket, IHGoogleDocsAdapter; +@protocol IHGoogleDocsAdapterDelegate - (void)googleDocsAdapter:(IHGoogleDocsAdapter*)inGoogleDocsAdapter accountVerifyIsValid:(BOOL)inIsValid error:(NSError *)inError; +@end @interface IHGoogleDocsAdapter : NSObject { +} +- (NSArray *)entries; +@end extern Class const kGDataUseRegisteredClass ; +@interface IHGoogleDocsAdapter () - (GDataFeedDocList *)feedDocList; +- (NSArray *)directoryPathComponents; +- (unsigned int)currentPathComponentIndex; +- (void)setCurrentPathComponentIndex:(unsigned int)aCurrentPathComponentIndex; +- (NSURL *)folderFeedURL; +@end @implementation IHGoogleDocsAdapter - (id)initWithUsername:(NSString *)inUsername password:(NSString *)inPassword owner:(NSObject <IHGoogleDocsAdapterDelegate> *)owner { +} + +//===----------------------------------------------------------------------===// +// Actual test case: +// +// The analyzer currently doesn't reason about ObjCKVCRefExpr. Have both +// GRExprEngine::Visit and GRExprEngine::VisitLValue have such expressions +// evaluate to UnknownVal. +//===----------------------------------------------------------------------===// + +- (void)docListListFetchTicket:(GDataServiceTicket *)ticket finishedWithFeed:(GDataFeedDocList *)feed { + BOOL doGetDir = self.directoryPathComponents != 0 && self.currentPathComponentIndex < [self.directoryPathComponents count]; + if (doGetDir) { + BOOL isDirExisting = [[self.feedDocList entries] count] > 0; + if (isDirExisting) { + if (self.folderFeedURL != 0) { + if (++self.currentPathComponentIndex == [self.directoryPathComponents count]) { + } + } + } + } +} diff --git a/test/Analysis/array-struct.c b/test/Analysis/array-struct.c new file mode 100644 index 000000000000..c0e1d8b7e39f --- /dev/null +++ b/test/Analysis/array-struct.c @@ -0,0 +1,150 @@ +// RUN: clang-cc -analyze -checker-simple -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s + +// RegionStore now has an infinite recursion with this test case. +// NOWORK: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// NOWORK: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s + +struct s { + int data; + int data_array[10]; +}; + +typedef struct { + int data; +} STYPE; + +void g(char *p); +void g1(struct s* p); + +// Array to pointer conversion. Array in the struct field. +void f(void) { + int a[10]; + int (*p)[10]; + p = &a; + (*p)[3] = 1; + + struct s d; + struct s *q; + q = &d; + q->data = 3; + d.data_array[9] = 17; +} + +// StringLiteral in lvalue context and pointer to array type. +// p: ElementRegion, q: StringRegion +void f2() { + char *p = "/usr/local"; + char (*q)[4]; + q = &"abc"; +} + +// Typedef'ed struct definition. +void f3() { + STYPE s; +} + +// Initialize array with InitExprList. +void f4() { + int a[] = { 1, 2, 3}; + int b[3] = { 1, 2 }; + struct s c[] = {{1,{1}}}; +} + +// Struct variable in lvalue context. +// Assign UnknownVal to the whole struct. +void f5() { + struct s data; + g1(&data); +} + +// AllocaRegion test. +void f6() { + char *p; + p = __builtin_alloca(10); + g(p); + char c = *p; + p[1] = 'a'; + // Test if RegionStore::EvalBinOp converts the alloca region to element + // region. + p += 2; +} + +struct s2; + +void g2(struct s2 *p); + +// Incomplete struct pointer used as function argument. +void f7() { + struct s2 *p = __builtin_alloca(10); + g2(p); +} + +// sizeof() is unsigned while -1 is signed in array index. +void f8() { + int a[10]; + a[sizeof(a)/sizeof(int) - 1] = 1; // no-warning +} + +// Initialization of struct array elements. +void f9() { + struct s a[10]; +} + +// Initializing array with string literal. +void f10() { + char a1[4] = "abc"; + char a3[6] = "abc"; +} + +// Retrieve the default value of element/field region. +void f11() { + struct s a; + g1(&a); + if (a.data == 0) // no-warning + a.data = 1; +} + +// Convert unsigned offset to signed when creating ElementRegion from +// SymbolicRegion. +void f12(int *list) { + unsigned i = 0; + list[i] = 1; +} + +struct s1 { + struct s2 { + int d; + } e; +}; + +// The binding of a.e.d should not be removed. Test recursive subregion map +// building: a->e, e->d. Only then 'a' could be added to live region roots. +void f13(double timeout) { + struct s1 a; + a.e.d = (long) timeout; + if (a.e.d == 10) + a.e.d = 4; +} + +struct s3 { + int a[2]; +}; + +static struct s3 opt; + +// Test if the embedded array is retrieved correctly. +void f14() { + struct s3 my_opt = opt; +} + +void bar(int*); + +// Test if the array is correctly invalidated. +void f15() { + int a[10]; + bar(a); + if (a[1]) // no-warning + 1; +} diff --git a/test/Analysis/basicstore_wine_crash.c b/test/Analysis/basicstore_wine_crash.c new file mode 100644 index 000000000000..cb5fac8d2919 --- /dev/null +++ b/test/Analysis/basicstore_wine_crash.c @@ -0,0 +1,11 @@ +// RUN: clang-cc -checker-cfref -analyze -analyzer-store=basic %s + +// Once xfail_regionstore_wine_crash.c passes, move this test case +// into misc-ps.m. + +void foo() { + long x = 0; + char *y = (char *) &x; + if (!*y) + return; +} diff --git a/test/Analysis/casts.c b/test/Analysis/casts.c new file mode 100644 index 000000000000..94a1eac0a316 --- /dev/null +++ b/test/Analysis/casts.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region --verify %s + +// Test if the 'storage' region gets properly initialized after it is cast to +// 'struct sockaddr *'. + +#include <sys/socket.h> +void f(int sock) { + struct sockaddr_storage storage; + struct sockaddr* sockaddr = (struct sockaddr*)&storage; + socklen_t addrlen = sizeof(storage); + getsockname(sock, sockaddr, &addrlen); + switch (sockaddr->sa_family) { // no-warning + default: + ; + } +} diff --git a/test/Analysis/casts.m b/test/Analysis/casts.m new file mode 100644 index 000000000000..82c29fac904f --- /dev/null +++ b/test/Analysis/casts.m @@ -0,0 +1,22 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic --verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region --verify %s + +// Test function pointer casts. Currently we track function addresses using +// loc::FunctionVal. Because casts can be arbitrary, do we need to model +// functions with regions? +typedef void* (*MyFuncTest1)(void); + +MyFuncTest1 test1_aux(void); +void test1(void) { + void *x; + void* (*p)(void); + p = ((void*) test1_aux()); + if (p != ((void*) 0)) x = (*p)(); +} + +// Test casts from void* to function pointers. Same issue as above: +// should we eventually model function pointers using regions? +void* test2(void *p) { + MyFuncTest1 fp = (MyFuncTest1) p; + return (*fp)(); +} diff --git a/test/Analysis/cfref_PR2519.c b/test/Analysis/cfref_PR2519.c new file mode 100644 index 000000000000..695123b53345 --- /dev/null +++ b/test/Analysis/cfref_PR2519.c @@ -0,0 +1,48 @@ +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range -verify %s + +typedef unsigned char Boolean; +typedef signed long CFIndex; +typedef const void * CFTypeRef; +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +extern const CFAllocatorRef kCFAllocatorDefault; +typedef struct {} CFAllocatorContext; +extern void CFRelease(CFTypeRef cf); +typedef struct {} +CFDictionaryKeyCallBacks; +extern const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks; +typedef struct {} +CFDictionaryValueCallBacks; +extern const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks; +typedef const struct __CFDictionary * CFDictionaryRef; +extern CFDictionaryRef CFDictionaryCreate(CFAllocatorRef allocator, const void **keys, const void **values, CFIndex numValues, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks); +enum { kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2, kCFNumberSInt32Type = 3, kCFNumberSInt64Type = 4, kCFNumberFloat32Type = 5, kCFNumberFloat64Type = 6, kCFNumberCharType = 7, kCFNumberShortType = 8, kCFNumberIntType = 9, kCFNumberLongType = 10, kCFNumberLongLongType = 11, kCFNumberFloatType = 12, kCFNumberDoubleType = 13, kCFNumberCFIndexType = 14, kCFNumberNSIntegerType = 15, kCFNumberCGFloatType = 16, kCFNumberMaxType = 16 }; +typedef CFIndex CFNumberType; +typedef const struct __CFNumber * CFNumberRef; +extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr); +typedef struct __CFNotificationCenter * CFNotificationCenterRef; +extern CFNotificationCenterRef CFNotificationCenterGetDistributedCenter(void); +extern void CFNotificationCenterPostNotification(CFNotificationCenterRef center, CFStringRef name, const void *object, CFDictionaryRef userInfo, Boolean deliverImmediately); + +// This test case was reported in PR2519 as a false positive (_value was +// reported as being leaked). + +int main(int argc, char **argv) { + CFStringRef _key = ((CFStringRef) __builtin___CFStringMakeConstantString ("" "Process identifier" "")); + int pid = 42; + + CFNumberRef _value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); + CFDictionaryRef userInfo = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&_key, (const void **)&_value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease(_value); // no-warning + CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), + ((CFStringRef) __builtin___CFStringMakeConstantString ("" "GrowlPreferencesChanged" "")), + ((CFStringRef) __builtin___CFStringMakeConstantString ("" "GrowlUserDefaults" "")), + userInfo, 0); + CFRelease(userInfo); // no-warning + + return 0; +} + diff --git a/test/Analysis/cfref_rdar6080742.c b/test/Analysis/cfref_rdar6080742.c new file mode 100644 index 000000000000..5d957615d0dd --- /dev/null +++ b/test/Analysis/cfref_rdar6080742.c @@ -0,0 +1,58 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s + +// This test case was reported in <rdar:problem/6080742>. +// It tests path-sensitivity with respect to '!(cfstring != 0)' (negation of inequality). + +int printf(const char *restrict,...); +typedef unsigned long UInt32; +typedef signed long SInt32; +typedef SInt32 OSStatus; +typedef unsigned char Boolean; +enum { noErr = 0}; +typedef const void *CFTypeRef; +typedef const struct __CFString *CFStringRef; +typedef const struct __CFAllocator *CFAllocatorRef; +extern void CFRelease(CFTypeRef cf); +typedef UInt32 CFStringEncoding; +enum { kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, + kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, + kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, + kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF, + kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, + kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, + kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100}; +extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); + +enum { memROZWarn = -99, memROZError = -99, memROZErr = -99, memFullErr = -108, + nilHandleErr = -109, memWZErr = -111, memPurErr = -112, memAdrErr = -110, + memAZErr = -113, memPCErr = -114, memBCErr = -115, memSCErr = -116, memLockedErr = -117}; + +#define DEBUG1 + +void DebugStop(const char *format,...); +void DebugTraceIf(unsigned int condition, const char *format,...); +Boolean DebugDisplayOSStatusMsg(OSStatus status, const char *statusStr, const char *fileName, unsigned long lineNumber); + +#define Assert(condition)if (!(condition)) { DebugStop("Assertion failure: %s [File: %s, Line: %lu]", #condition, __FILE__, __LINE__); } +#define AssertMsg(condition, message)if (!(condition)) { DebugStop("Assertion failure: %s (%s) [File: %s, Line: %lu]", #condition, message, __FILE__, __LINE__); } +#define Require(condition)if (!(condition)) { DebugStop("Assertion failure: %s [File: %s, Line: %lu]", #condition, __FILE__, __LINE__); } +#define RequireAction(condition, action)if (!(condition)) { DebugStop("Assertion failure: %s [File: %s, Line: %lu]", #condition, __FILE__, __LINE__); action } +#define RequireActionSilent(condition, action)if (!(condition)) { action } +#define AssertNoErr(err){ DebugDisplayOSStatusMsg((err), #err, __FILE__, __LINE__); } +#define RequireNoErr(err, action){ if( DebugDisplayOSStatusMsg((err), #err, __FILE__, __LINE__) ) { action }} + +void DebugStop(const char *format,...); /* Not an abort function. */ + +int main(int argc, char *argv[]) { + CFStringRef cfString; + OSStatus status = noErr; + cfString = CFStringCreateWithCString(0, "hello", kCFStringEncodingUTF8); + RequireAction(cfString != 0, return memFullErr;) //no - warning + printf("cfstring %p\n", cfString); +Exit: + CFRelease(cfString); + return 0; +} diff --git a/test/Analysis/complex.c b/test/Analysis/complex.c new file mode 100644 index 000000000000..f29fc70c4944 --- /dev/null +++ b/test/Analysis/complex.c @@ -0,0 +1,21 @@ +// RUN: clang-cc -analyze -checker-simple -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s + +#include <stdint.h> + +int f1(int * p) { + + // This branch should be infeasible + // because __imag__ p is 0. + if (!p && __imag__ (intptr_t) p) + *p = 1; // no-warning + + // If p != 0 then this branch is feasible; otherwise it is not. + if (__real__ (intptr_t) p) + *p = 1; // no-warning + + *p = 2; // expected-warning{{Dereference of null pointer}} +} diff --git a/test/Analysis/conditional-op-missing-lhs.c b/test/Analysis/conditional-op-missing-lhs.c new file mode 100644 index 000000000000..bebf155f4640 --- /dev/null +++ b/test/Analysis/conditional-op-missing-lhs.c @@ -0,0 +1,26 @@ +// RUN: clang-cc -analyze -warn-dead-stores -warn-uninit-values -verify %s + +void f1() +{ + int i; + + int j = i ? : 1; // expected-warning{{use of uninitialized variable}} //expected-warning{{Value stored to 'j' during its initialization is never read}} +} + +void *f2(int *i) +{ + return i ? : 0; +} + +void *f3(int *i) +{ + int a; + + return &a ? : i; +} + +void f4() +{ + char c[1 ? : 2]; +} + diff --git a/test/Analysis/dead-stores.c b/test/Analysis/dead-stores.c new file mode 100644 index 000000000000..c100344adf6d --- /dev/null +++ b/test/Analysis/dead-stores.c @@ -0,0 +1,175 @@ +// RUN: clang-cc -analyze -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-simple -analyzer-store=basic -analyzer-constraints=basic -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-simple -analyzer-store=basic -analyzer-constraints=range -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=basic -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -warn-dead-stores -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -warn-dead-stores -verify %s + +void f1() { + int k, y; + int abc=1; + long idx=abc+3*5; // expected-warning {{never read}} +} + +void f2(void *b) { + char *c = (char*)b; // no-warning + char *d = b+1; // expected-warning {{never read}} + printf("%s", c); // expected-warning{{implicitly declaring C library function 'printf' with type 'int (char const *, ...)'}} \ + // expected-note{{please include the header <stdio.h> or explicitly provide a declaration for 'printf'}} +} + +void f3() { + int r; + if ((r = f()) != 0) { // no-warning + int y = r; // no-warning + printf("the error is: %d\n", y); + } +} + +void f4(int k) { + + k = 1; + + if (k) + f1(); + + k = 2; // expected-warning {{never read}} +} + +void f5() { + + int x = 4; // no-warning + int *p = &x; // expected-warning{{never read}} + +} + +int f6() { + + int x = 4; + ++x; // expected-warning{{never read}} + return 1; +} + +int f7(int *p) { + // This is allowed for defensive programming. + p = 0; // no-warning + return 1; +} + +int f8(int *p) { + extern int *baz(); + if (p = baz()) // expected-warning{{Although the value}} + return 1; + return 0; +} + +int f9() { + int x = 4; + x = x + 10; // expected-warning{{never read}} + return 1; +} + +int f10() { + int x = 4; + x = 10 + x; // expected-warning{{never read}} + return 1; +} + +int f11() { + int x = 4; + return x++; // expected-warning{{never read}} +} + +int f11b() { + int x = 4; + return ((((++x)))); // no-warning +} + +int f12a(int y) { + int x = y; // expected-warning{{never read}} + return 1; +} +int f12b(int y) { + int x __attribute__((unused)) = y; // no-warning + return 1; +} + +// Filed with PR 2630. This code should produce no warnings. +int f13(void) +{ + int a = 1; + int b, c = b = a + a; + + if (b > 0) + return (0); + + return (a + b + c); +} + +// Filed with PR 2763. +int f14(int count) { + int index, nextLineIndex; + for (index = 0; index < count; index = nextLineIndex+1) { + nextLineIndex = index+1; // no-warning + continue; + } + return index; +} + +// Test case for <rdar://problem/6248086> +void f15(unsigned x, unsigned y) { + int count = x * y; // no-warning + int z[count]; +} + +int f16(int x) { + x = x * 2; + x = sizeof(int [x = (x || x + 1) * 2]) // expected-warning{{Although the value stored to 'x' is used}} + ? 5 : 8; + return x; +} + +// Self-assignments should not be flagged as dead stores. +int f17() { + int x = 1; + x = x; // no-warning +} + +// <rdar://problem/6506065> +// The values of dead stores are only "consumed" in an enclosing expression +// what that value is actually used. In other words, don't say "Although the value stored to 'x' is used...". +int f18() { + int x = 0; // no-warning + if (1) + x = 10; // expected-warning{{Value stored to 'x' is never read}} + while (1) + x = 10; // expected-warning{{Value stored to 'x' is never read}} + do + x = 10; // expected-warning{{Value stored to 'x' is never read}} + while (1); + + return (x = 10); // expected-warning{{Although the value stored to 'x' is used in the enclosing expression, the value is never actually read from 'x'}} +} + +// PR 3514: false positive `dead initialization` warning for init to global +// http://llvm.org/bugs/show_bug.cgi?id=3514 +extern const int MyConstant; +int f19(void) { + int x = MyConstant; // no-warning + x = 1; + return x; +} + +int f19b(void) { // This case is the same as f19. + const int MyConstant = 0; + int x = MyConstant; // no-warning + x = 1; + return x; +} + +void f20(void) { + int x = 1; // no-warning +#pragma unused(x) +} + diff --git a/test/Analysis/dead-stores.m b/test/Analysis/dead-stores.m new file mode 100644 index 000000000000..218cb4458580 --- /dev/null +++ b/test/Analysis/dead-stores.m @@ -0,0 +1,36 @@ +// RUN: clang-cc -analyze -warn-dead-stores -verify %s + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end +@interface NSObject <NSObject> {} @end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSValue : NSObject <NSCopying, NSCoding> - (void)getValue:(void *)value; @end +typedef float CGFloat; +typedef struct _NSPoint {} NSRange; +@interface NSValue (NSValueRangeExtensions) + (NSValue *)valueWithRange:(NSRange)range; +- (BOOL)containsObject:(id)anObject; +@end +@class NSURLAuthenticationChallenge; +@interface NSResponder : NSObject <NSCoding> {} @end +@class NSArray, NSDictionary, NSString; +@interface NSObject (NSKeyValueBindingCreation) ++ (void)exposeBinding:(NSString *)binding; +- (NSArray *)exposedBindings; +@end +extern NSString *NSAlignmentBinding; + +// This test case was reported as a false positive due to a bug in the +// LiveVariables <-> DeadStores interplay. We should not flag a warning +// here. The test case was reported in: +// http://lists.cs.uiuc.edu/pipermail/cfe-dev/2008-July/002157.html +void DeadStoreTest(NSObject *anObject) { + NSArray *keys; + if ((keys = [anObject exposedBindings]) && // no-warning + ([keys containsObject:@"name"] && [keys containsObject:@"icon"])) {} +} + diff --git a/test/Analysis/delegates.m b/test/Analysis/delegates.m new file mode 100644 index 000000000000..440f31113cff --- /dev/null +++ b/test/Analysis/delegates.m @@ -0,0 +1,114 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from +// Foundation.h (Mac OS X). +// +// It includes the basic definitions for the test cases below. +// Not directly including Foundation.h directly makes this test case +// both svelte and portable to non-Mac platforms. +//===----------------------------------------------------------------------===// + +typedef const void * CFTypeRef; +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +extern const CFAllocatorRef kCFAllocatorDefault; +extern CFTypeRef CFRetain(CFTypeRef cf); +void CFRelease(CFTypeRef cf); +typedef const struct __CFDictionary * CFDictionaryRef; +const void *CFDictionaryGetValue(CFDictionaryRef theDict, const void *key); +extern CFStringRef CFStringCreateWithFormat(CFAllocatorRef alloc, CFDictionaryRef formatOptions, CFStringRef format, ...); +typedef signed char BOOL; +typedef int NSInteger; +typedef unsigned int NSUInteger; +typedef struct objc_selector *SEL; +@class NSString, Protocol; +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); +typedef NSInteger NSComparisonResult; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject +- (BOOL)isEqual:(id)object; +- (oneway void)release; +- (Class)class; +- (id)retain; +@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> {} +- (id)init; ++ (id)alloc; ++ (Class)class; +- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait; +@end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +typedef struct {} NSFastEnumerationState; +@protocol NSFastEnumeration +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end +@class NSString; +typedef struct _NSRange {} NSRange; +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> +- (NSUInteger)count; +@end +@interface NSMutableArray : NSArray +- (void)addObject:(id)anObject; +- (id)initWithCapacity:(NSUInteger)numItems; +@end +typedef unsigned short unichar; +@class NSData, NSArray, NSDictionary, NSCharacterSet, NSData, NSURL, NSError, NSLocale; +typedef NSUInteger NSStringCompareOptions; +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; +- (NSComparisonResult)compare:(NSString *)string; +- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask; +- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange; +- (NSComparisonResult)compare:(NSString *)string options:(NSStringCompareOptions)mask range:(NSRange)compareRange locale:(id)locale; +- (NSComparisonResult)caseInsensitiveCompare:(NSString *)string; +- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator; +@end +@interface NSSimpleCString : NSString {} @end +@interface NSConstantString : NSSimpleCString @end +extern void *_NSConstantStringClassReference; + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +// <rdar://problem/6062730> +// The analyzer doesn't perform any inter-procedural analysis, so delegates +// involving [NSObject performSelector...] tend to lead to false positives. +// For now the analyzer just stops tracking the reference count of the +// receiver until we have better support for delegates. + +@interface test_6062730 : NSObject ++ (void)postNotification:(NSString *)str; +- (void)foo; +- (void)bar; +@end + +@implementation test_6062730 +- (void) foo { + NSString *str = [[NSString alloc] init]; + [test_6062730 performSelectorOnMainThread:@selector(postNotification:) withObject:str waitUntilDone:1]; +} + +- (void) bar { + NSString *str = [[NSString alloc] init]; // expected-warning{{leak}} + // FIXME: We need to resolve [self class] to 'test_6062730'. + [[self class] performSelectorOnMainThread:@selector(postNotification:) withObject:str waitUntilDone:1]; +} + ++ (void) postNotification:(NSString *)str { + [str release]; // no-warning +} +@end + diff --git a/test/Analysis/exercise-ps.c b/test/Analysis/exercise-ps.c new file mode 100644 index 000000000000..08842b1b8dbf --- /dev/null +++ b/test/Analysis/exercise-ps.c @@ -0,0 +1,25 @@ +// RUN: clang-cc -analyze -checker-simple -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s +// +// Just exercise the analyzer on code that has at one point caused issues +// (i.e., no assertions or crashes). + + +static const char * f1(const char *x, char *y) { + while (*x != 0) { + *y++ = *x++; + } +} + +// This following case checks that we properly handle typedefs when getting +// the RvalueType of an ElementRegion. +typedef struct F12_struct {} F12_typedef; +typedef void* void_typedef; +void_typedef f2_helper(); +static void f2(void *buf) { + F12_typedef* x; + x = f2_helper(); + memcpy((&x[1]), (buf), 1); // expected-warning{{implicitly declaring C library function 'memcpy' with type 'void *(void *, void const *}} \ + // expected-note{{please include the header <string.h> or explicitly provide a declaration for 'memcpy'}} +} diff --git a/test/Analysis/fields.c b/test/Analysis/fields.c new file mode 100644 index 000000000000..c012a9da7b81 --- /dev/null +++ b/test/Analysis/fields.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -analyze -checker-cfref %s --analyzer-store=basic -verify && +// RUN: clang-cc -analyze -checker-cfref %s --analyzer-store=region -verify + +unsigned foo(); +typedef struct bf { unsigned x:2; } bf; +void bar() { + bf y; + *(unsigned*)&y = foo(); + y.x = 1; +} diff --git a/test/Analysis/func.c b/test/Analysis/func.c new file mode 100644 index 000000000000..ac067a98103c --- /dev/null +++ b/test/Analysis/func.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -analyze -checker-simple -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +void f(void) { + void (*p)(void); + p = f; + p = &f; + p(); + (*p)(); +} + +void g(void (*fp)(void)); + +void f2() { + g(f); +} diff --git a/test/Analysis/misc-ps-64.m b/test/Analysis/misc-ps-64.m new file mode 100644 index 000000000000..163da4b4abeb --- /dev/null +++ b/test/Analysis/misc-ps-64.m @@ -0,0 +1,49 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=basic --verify -fblocks %s && +// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s && +// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s && +// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s + +// <rdar://problem/6440393> - A bunch of misc. failures involving evaluating +// these expressions and building CFGs. These tests are here to prevent +// regressions. +typedef long long int64_t; +@class NSString, NSDictionary; +typedef long NSInteger; +typedef unsigned long NSUInteger; +typedef unsigned char Boolean; +typedef const struct __CFDictionary * CFDictionaryRef; + +extern Boolean CFDictionaryGetValueIfPresent(CFDictionaryRef theDict, const void *key, const void **value); +static void shazam(NSUInteger i, unsigned char **out); + +void rdar_6440393_1(NSDictionary *dict) { + NSInteger x = 0; + unsigned char buf[10], *bufptr = buf; + if (!CFDictionaryGetValueIfPresent(0, dict, (void *)&x)) + return; + shazam(x, &bufptr); +} + +// <rdar://problem/6845148> - In this example we got a signedness +// mismatch between the literal '0' and the value of 'scrooge'. The +// trick is to have the evaluator convert the literal to an unsigned +// integer when doing a comparison with the pointer. This happens +// because of the transfer function logic of +// OSAtomicCompareAndSwap64Barrier, which doesn't have special casts +// in place to do this for us. +_Bool OSAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue ); +extern id objc_lookUpClass(const char *name); +void rdar_6845148(id debug_yourself) { + if (!debug_yourself) { + const char *wacky = ((void *)0); + Class scrooge = wacky ? (Class)objc_lookUpClass(wacky) : ((void *)0); + OSAtomicCompareAndSwap64Barrier(0, (int64_t)scrooge, (int64_t*)&debug_yourself); + } +} +void rdar_6845148_b(id debug_yourself) { + if (!debug_yourself) { + const char *wacky = ((void *)0); + Class scrooge = wacky ? (Class)objc_lookUpClass(wacky) : ((void *)0); + OSAtomicCompareAndSwap64Barrier((int64_t)scrooge, 0, (int64_t*)&debug_yourself); + } +} diff --git a/test/Analysis/misc-ps-basic-store.m b/test/Analysis/misc-ps-basic-store.m new file mode 100644 index 000000000000..1207f8663e90 --- /dev/null +++ b/test/Analysis/misc-ps-basic-store.m @@ -0,0 +1,21 @@ +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic --verify -fblocks %s + +//--------------------------------------------------------------------------- +// Test case 'checkaccess_union' differs for region store and basic store. +// The basic store doesn't reason about compound literals, so the code +// below won't fire an "uninitialized value" warning. +//--------------------------------------------------------------------------- + +// PR 2948 (testcase; crash on VisitLValue for union types) +// http://llvm.org/bugs/show_bug.cgi?id=2948 + +void checkaccess_union() { + int ret = 0, status; + if (((((__extension__ (((union { // no-warning + __typeof (status) __in; int __i;} + ) + { + .__in = (status)} + ).__i))) & 0xff00) >> 8) == 1) + ret = 1; +} diff --git a/test/Analysis/misc-ps-eager-assume.m b/test/Analysis/misc-ps-eager-assume.m new file mode 100644 index 000000000000..818922eba925 --- /dev/null +++ b/test/Analysis/misc-ps-eager-assume.m @@ -0,0 +1,79 @@ +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s -analyzer-eagerly-assume + +// Delta-reduced header stuff (needed for test cases). +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +- (oneway void)release; +@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> {} ++ (id)alloc; +@end typedef struct {} +NSFastEnumerationState; +@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; +@end @interface NSMutableArray : NSArray - (void)addObject:(id)anObject; +- (BOOL)isEqualToString:(NSString *)aString; +@end @interface NSAutoreleasePool : NSObject {} +- (void)drain; +- (id)init; +@end + +// This test case tests that (x != 0) is eagerly evaluated before stored to +// 'y'. This test case complements recoverCastedSymbol (see below) because +// the symbolic expression is stored to 'y' (which is a short instead of an +// int). recoverCastedSymbol() only recovers path-sensitivity when the +// symbolic expression is literally the branch condition. +// +void handle_assign_of_condition(int x) { + // The cast to 'short' causes us to lose symbolic constraint. + short y = (x != 0); + char *p = 0; + if (y) { + // This should be infeasible. + if (!(x != 0)) { + *p = 1; // no-warning + } + } +} + +// From <rdar://problem/6619921> +// +// In this test case, 'needsAnArray' is a signed char. The analyzer tracks +// a symbolic value for this variable, but in the branch condition it is +// promoted to 'int'. Currently the analyzer doesn't reason well about +// promotions of symbolic values, so this test case tests the logic in +// 'recoverCastedSymbol()' (GRExprEngine.cpp) to test that we recover +// path-sensitivity and use the symbol for 'needsAnArray' in the branch +// condition. +// +void handle_symbolic_cast_in_condition(void) { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"]; + NSMutableArray* array = needsAnArray ? [[NSMutableArray alloc] init] : 0; + if(needsAnArray) + [array release]; + + [pool drain]; +} + +// From PR 3836 (http://llvm.org/bugs/show_bug.cgi?id=3836) +// +// In this test case, the double '!' works fine with our symbolic constraints, +// but we don't support comparing SymConstraint != SymConstraint. By eagerly +// assuming the truth of !!a or !!b, we can compare these values directly. +// +void pr3836(int *a, int *b) { + if (!!a != !!b) /* one of them is NULL */ + return; + if (!a && !b) /* both are NULL */ + return; + + *a = 1; // no-warning + *b = 1; // no-warning +} diff --git a/test/Analysis/misc-ps-ranges.m b/test/Analysis/misc-ps-ranges.m new file mode 100644 index 000000000000..a191bec3cfb1 --- /dev/null +++ b/test/Analysis/misc-ps-ranges.m @@ -0,0 +1,23 @@ +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s && +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s + +// <rdar://problem/6776949> +// main's 'argc' argument is always > 0 +int main(int argc, char* argv[]) { + int *p = 0; + + if (argc == 0) + *p = 1; + + if (argc == 1) + return 1; + + int x = 1; + int i; + + for(i=1;i<argc;i++){ + p = &x; + } + + return *p; // no-warning +}
\ No newline at end of file diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m new file mode 100644 index 000000000000..8c8815ea63eb --- /dev/null +++ b/test/Analysis/misc-ps-region-store.m @@ -0,0 +1,70 @@ +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region --verify -fblocks %s + +typedef struct objc_selector *SEL; +typedef signed char BOOL; +typedef int NSInteger; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @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> {} - (id)init; @end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> +- (NSUInteger)length; ++ (id)stringWithUTF8String:(const char *)nullTerminatedCString; +@end extern NSString * const NSBundleDidLoadNotification; +@interface NSAssertionHandler : NSObject {} ++ (NSAssertionHandler *)currentHandler; +- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...; +@end +extern NSString * const NSConnectionReplyMode; + + +//--------------------------------------------------------------------------- +// Test case 'checkaccess_union' differs for region store and basic store. +// The basic store doesn't reason about compound literals, so the code +// below won't fire an "uninitialized value" warning. +//--------------------------------------------------------------------------- + +// PR 2948 (testcase; crash on VisitLValue for union types) +// http://llvm.org/bugs/show_bug.cgi?id=2948 + +void checkaccess_union() { + int ret = 0, status; + if (((((__extension__ (((union { // expected-warning {{ Branch condition evaluates to an uninitialized value.}} + __typeof (status) __in; int __i;} + ) + { + .__in = (status)} + ).__i))) & 0xff00) >> 8) == 1) + ret = 1; +} + + +// Check our handling of fields being invalidated by function calls. +struct test2_struct { int x; int y; char* s; }; +void test2_helper(struct test2_struct* p); + +char test2() { + struct test2_struct s; + test2_help(&s); + char *p = 0; + + if (s.x > 1) { + if (s.s != 0) { + p = "hello"; + } + } + + if (s.x > 1) { + if (s.s != 0) { + return *p; + } + } + + return 'a'; +} + diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m new file mode 100644 index 000000000000..205bac2c825f --- /dev/null +++ b/test/Analysis/misc-ps.m @@ -0,0 +1,287 @@ +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=basic --verify -fblocks %s && +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s + +// NOWORK: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s && +// NOWORK: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s + +typedef struct objc_selector *SEL; +typedef signed char BOOL; +typedef int NSInteger; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @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> {} - (id)init; @end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> +- (NSUInteger)length; ++ (id)stringWithUTF8String:(const char *)nullTerminatedCString; +@end extern NSString * const NSBundleDidLoadNotification; +@interface NSAssertionHandler : NSObject {} ++ (NSAssertionHandler *)currentHandler; +- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...; +@end +extern NSString * const NSConnectionReplyMode; +typedef float CGFloat; +typedef struct _NSPoint { + CGFloat x; + CGFloat y; +} NSPoint; +typedef struct _NSSize { + CGFloat width; + CGFloat height; +} NSSize; +typedef struct _NSRect { + NSPoint origin; + NSSize size; +} NSRect; + +// Reduced test case from crash in <rdar://problem/6253157> +@interface A @end +@implementation A +- (void)foo:(void (^)(NSObject *x))block { + if (!((block != ((void *)0)))) {} +} +@end + +// Reduced test case from crash in PR 2796; +// http://llvm.org/bugs/show_bug.cgi?id=2796 + +unsigned foo(unsigned x) { return __alignof__((x)) + sizeof(x); } + +// Improvement to path-sensitivity involving compound assignments. +// Addresses false positive in <rdar://problem/6268365> +// + +unsigned r6268365Aux(); + +void r6268365() { + unsigned x = 0; + x &= r6268365Aux(); + unsigned j = 0; + + if (x == 0) ++j; + if (x == 0) x = x / j; // no-warning +} + +void divzeroassume(unsigned x, unsigned j) { + x /= j; + if (j == 0) x /= 0; // no-warning + if (j == 0) x /= j; // no-warning + if (j == 0) x = x / 0; // no-warning +} + +void divzeroassumeB(unsigned x, unsigned j) { + x = x / j; + if (j == 0) x /= 0; // no-warning + if (j == 0) x /= j; // no-warning + if (j == 0) x = x / 0; // no-warning +} + +// InitListExpr processing + +typedef float __m128 __attribute__((__vector_size__(16), __may_alias__)); +__m128 return128() { + // This compound literal has a Vector type. We currently just + // return UnknownVal. + return __extension__(__m128) { 0.0f, 0.0f, 0.0f, 0.0f }; +} + +typedef long long __v2di __attribute__ ((__vector_size__ (16))); +typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__)); +__m128i vec128i(long long __q1, long long __q0) { + // This compound literal returns true for both isVectorType() and + // isIntegerType(). + return __extension__ (__m128i)(__v2di){ __q0, __q1 }; +} + +// Zero-sized VLAs. +void check_zero_sized_VLA(int x) { + if (x) + return; + + int vla[x]; // expected-warning{{Variable-length array 'vla' has zero elements (undefined behavior)}} +} + +void check_uninit_sized_VLA() { + int x; + int vla[x]; // expected-warning{{Variable-length array 'vla' garbage value for array size}} +} + +// sizeof(void) +// - Tests a regression reported in PR 3211: http://llvm.org/bugs/show_bug.cgi?id=3211 +void handle_sizeof_void(unsigned flag) { + int* p = 0; + + if (flag) { + if (sizeof(void) == 1) + return; + // Infeasible. + *p = 1; // no-warning + } + + void* q; + + if (!flag) { + if (sizeof(*q) == 1) + return; + // Infeasibe. + *p = 1; // no-warning + } + + // Infeasible. + *p = 1; // no-warning +} + +// PR 3422 +void pr3422_helper(char *p); +void pr3422() { + char buf[100]; + char *q = &buf[10]; + pr3422_helper(&q[1]); +} + +// PR 3543 (handle empty statement expressions) +int pr_3543(void) { + ({}); +} + +// <rdar://problem/6611677> +// This test case test the use of a vector type within an array subscript +// expression. +typedef long long __a64vector __attribute__((__vector_size__(8))); +typedef long long __a128vector __attribute__((__vector_size__(16))); +static inline __a64vector __attribute__((__always_inline__, __nodebug__)) +my_test_mm_movepi64_pi64(__a128vector a) { + return (__a64vector)a[0]; +} + +// Test basic tracking of ivars associated with 'self'. +@interface SelfIvarTest : NSObject { + int flag; +} +- (void)test_self_tracking; +@end + +@implementation SelfIvarTest +- (void)test_self_tracking { + char *p = 0; + char c; + + if (flag) + p = "hello"; + + if (flag) + c = *p; // no-warning +} +@end + +// PR 3770 +char pr3770(int x) { + int y = x & 0x2; + char *p = 0; + if (y == 1) + p = "hello"; + + if (y == 1) + return p[0]; // no-warning + + return 'a'; +} + +// PR 3772 +// - We just want to test that this doesn't crash the analyzer. +typedef struct st ST; +struct st { char *name; }; +extern ST *Cur_Pu; + +void pr3772(void) +{ + static ST *last_Cur_Pu; + if (last_Cur_Pu == Cur_Pu) { + return; + } +} + +// PR 3780 - This tests that StmtIterator isn't broken for VLAs in DeclGroups. +void pr3780(int sz) { typedef double MAT[sz][sz]; } + +// <rdar://problem/6695527> - Test that we don't symbolicate doubles before +// we are ready to do something with them. +int rdar6695527(double x) { + if (!x) { return 0; } + return 1; +} + +// <rdar://problem/6708148> - Test that we properly invalidate structs +// passed-by-reference to a function. +void pr6708148_invalidate(NSRect *x); +void pr6708148_use(NSRect x); +void pr6708148_test(void) { + NSRect x; + pr6708148_invalidate(&x); + pr6708148_use(x); // no-warning +} + +// Handle both kinds of noreturn attributes for pruning paths. +void rdar_6777003_noret() __attribute__((noreturn)); +void rdar_6777003_analyzer_noret() __attribute__((analyzer_noreturn)); + +void rdar_6777003(int x) { + int *p = 0; + + if (x == 1) { + rdar_6777003_noret(); + *p = 1; // no-warning; + } + + if (x == 2) { + rdar_6777003_analyzer_noret(); + *p = 1; // no-warning; + } + + *p = 1; // expected-warning{{Dereference of null pointer}} +} + +// For pointer arithmetic, --/++ should be treated as preserving non-nullness, +// regardless of how well the underlying StoreManager reasons about pointer +// arithmetic. +// <rdar://problem/6777209> +void rdar_6777209(char *p) { + if (p == 0) + return; + + ++p; + + // This branch should always be infeasible. + if (p == 0) + *p = 'c'; // no-warning +} + +// PR 4033. A symbolic 'void *' pointer can be used as the address for a +// computed goto. +typedef void *Opcode; +Opcode pr_4033_getOpcode(); +void pr_4033(void) { +next_opcode: + { + Opcode op = pr_4033_getOpcode(); + if (op) goto *op; + } +} + +// Test invalidating pointers-to-pointers with slightly different types. This +// example came from a recent false positive due to a regression where the +// branch condition was falsely reported as being uninitialized. +void invalidate_by_ref(char **x); +int test_invalidate_by_ref() { + unsigned short y; + invalidate_by_ref((char**) &y); + if (y) // no-warning + return 1; + return 0; +} + diff --git a/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m new file mode 100644 index 000000000000..9a64b3001e16 --- /dev/null +++ b/test/Analysis/nil-receiver-undefined-larger-than-voidptr-ret.m @@ -0,0 +1,67 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=basic %s -verify + +@interface MyClass {} +- (void *)voidPtrM; +- (int)intM; +- (long long)longlongM; +- (double)doubleM; +- (long double)longDoubleM; +- (void)voidM; +@end +@implementation MyClass +- (void *)voidPtrM { return (void *)0; } +- (int)intM { return 0; } +- (long long)longlongM { return 0; } +- (double)doubleM { return 0.0; } +- (long double)longDoubleM { return 0.0; } +- (void)voidM {} +@end + +void createFoo() { + MyClass *obj = 0; + + void *v = [obj voidPtrM]; // no-warning + int i = [obj intM]; // no-warning +} + +void createFoo2() { + MyClass *obj = 0; + + long double ld = [obj longDoubleM]; // expected-warning{{The receiver in the message expression is 'nil' and results in the returned value}} +} + +void createFoo3() { + MyClass *obj; + obj = 0; + + long long ll = [obj longlongM]; // expected-warning{{The receiver in the message expression is 'nil' and results in the returned value}} +} + +void createFoo4() { + MyClass *obj = 0; + + double d = [obj doubleM]; // expected-warning{{The receiver in the message expression is 'nil' and results in the returned value}} +} + +void createFoo5() { + MyClass *obj = @""; + + double d = [obj doubleM]; // no-warning +} + +void handleNilPruneLoop(MyClass *obj) { + if (!!obj) + return; + + // Test if [obj intM] evaluates to 0, thus pruning the entire loop. + for (int i = 0; i < [obj intM]; i++) { + long long j = [obj longlongM]; // no-warning + } + + long long j = [obj longlongM]; // expected-warning{{The receiver in the message expression is 'nil' and results in the returned value}} +} + +int handleVoidInComma() { + MyClass *obj = 0; + return [obj voidM], 0; +} diff --git a/test/Analysis/no-exit-cfg.c b/test/Analysis/no-exit-cfg.c new file mode 100644 index 000000000000..cad2127b2082 --- /dev/null +++ b/test/Analysis/no-exit-cfg.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +// This is a test case for the issue reported in PR 2819: +// http://llvm.org/bugs/show_bug.cgi?id=2819 +// The flow-sensitive dataflow solver should work even when no block in +// the CFG reaches the exit block. + +int g(int x); +void h(int x); + +int f(int x) +{ +out_err: + if (g(x)) { + h(x); + } + goto out_err; +} diff --git a/test/Analysis/no-outofbounds-basicstore.c b/test/Analysis/no-outofbounds-basicstore.c new file mode 100644 index 000000000000..9a0b35906d7c --- /dev/null +++ b/test/Analysis/no-outofbounds-basicstore.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -checker-cfref -analyze -analyzer-store=basic -verify %s + +void f() { + long x = 0; + char *y = (char*) &x; + char c = y[0] + y[1] + y[2]; // no-warning +} diff --git a/test/Analysis/null-deref-ps-region.c b/test/Analysis/null-deref-ps-region.c new file mode 100644 index 000000000000..80a5f9212fac --- /dev/null +++ b/test/Analysis/null-deref-ps-region.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -analyze -std=gnu99 -checker-cfref -analyzer-store=region -verify %s + + +// The store for 'a[1]' should not be removed mistakenly. SymbolicRegions may +// also be live roots. +void f14(int *a) { + int i; + a[1] = 1; + i = a[1]; + if (i != 1) { + int *p = 0; + i = *p; // no-warning + } +} diff --git a/test/Analysis/null-deref-ps.c b/test/Analysis/null-deref-ps.c new file mode 100644 index 000000000000..09b9c2ffa3b7 --- /dev/null +++ b/test/Analysis/null-deref-ps.c @@ -0,0 +1,265 @@ +// RUN: clang-cc -analyze -std=gnu99 -checker-simple -verify %s && +// RUN: clang-cc -analyze -std=gnu99 -checker-simple -verify %s -analyzer-constraints=range && +// RUN: clang-cc -analyze -std=gnu99 -checker-simple -analyzer-store=region -analyzer-purge-dead=false -verify %s && +// RUN: clang-cc -analyze -std=gnu99 -checker-cfref -analyzer-store=region -verify %s + +#include<stdint.h> +#include <assert.h> + +void f1(int *p) { + if (p) *p = 1; + else *p = 0; // expected-warning{{ereference}} +} + +struct foo_struct { + int x; +}; + +int f2(struct foo_struct* p) { + + if (p) + p->x = 1; + + return p->x++; // expected-warning{{Dereference of null pointer.}} +} + +int f3(char* x) { + + int i = 2; + + if (x) + return x[i - 1]; + + return x[i+1]; // expected-warning{{Dereference of null pointer.}} +} + +int f3_b(char* x) { + + int i = 2; + + if (x) + return x[i - 1]; + + return x[i+1]++; // expected-warning{{Dereference of null pointer.}} +} + +int f4(int *p) { + + uintptr_t x = (uintptr_t) p; + + if (x) + return 1; + + int *q = (int*) x; + return *q; // expected-warning{{Dereference of null pointer.}} +} + +int f4_b() { + short array[2]; + uintptr_t x = array; // expected-warning{{incompatible pointer to integer conversion initializing}} + short *p = x; // expected-warning{{incompatible integer to pointer conversion initializing}} + + // The following branch should be infeasible. + if (!(p = &array[0])) { + p = 0; + *p = 1; // no-warning + } + + if (p) { + *p = 5; // no-warning + p = 0; + } + else return; // expected-warning {{non-void function 'f4_b' should return a value}} + + *p += 10; // expected-warning{{Dereference of null pointer}} +} + + +int f5() { + + char *s = "hello world"; + return s[0]; // no-warning +} + +int bar(int* p, int q) __attribute__((nonnull)); + +int f6(int *p) { + return !p ? bar(p, 1) // expected-warning {{Null pointer passed as an argument to a 'nonnull' parameter}} + : bar(p, 0); // no-warning +} + +int bar2(int* p, int q) __attribute__((nonnull(1))); + +int f6b(int *p) { + return !p ? bar2(p, 1) // expected-warning {{Null pointer passed as an argument to a 'nonnull' parameter}} + : bar2(p, 0); // no-warning +} + +int bar3(int*p, int q, int *r) __attribute__((nonnull(1,3))); + +int f6c(int *p, int *q) { + return !p ? bar3(q, 2, p) // expected-warning {{Null pointer passed as an argument to a 'nonnull' parameter}} + : bar3(p, 2, q); // no-warning +} + +int* qux(); + +int f7(int x) { + + int* p = 0; + + if (0 == x) + p = qux(); + + if (0 == x) + *p = 1; // no-warning + + return x; +} + +int* f7b(int *x) { + + int* p = 0; + + if (((void*)0) == x) + p = qux(); + + if (((void*)0) == x) + *p = 1; // no-warning + + return x; +} + +int* f7c(int *x) { + + int* p = 0; + + if (((void*)0) == x) + p = qux(); + + if (((void*)0) != x) + return x; + + // If we reach here then 'p' is not null. + *p = 1; // no-warning + return x; +} + +int* f7c2(int *x) { + + int* p = 0; + + if (((void*)0) == x) + p = qux(); + + if (((void*)0) == x) + return x; + + *p = 1; // expected-warning{{null}} + return x; +} + + +int f8(int *p, int *q) { + if (!p) + if (p) + *p = 1; // no-warning + + if (q) + if (!q) + *q = 1; // no-warning +} + +int* qux(); + +int f9(unsigned len) { + assert (len != 0); + int *p = 0; + unsigned i; + + for (i = 0; i < len; ++i) + p = qux(i); + + return *p++; // no-warning +} + +int f9b(unsigned len) { + assert (len > 0); // note use of '>' + int *p = 0; + unsigned i; + + for (i = 0; i < len; ++i) + p = qux(i); + + return *p++; // no-warning +} + +int* f10(int* p, signed char x, int y) { + // This line tests symbolication with compound assignments where the + // LHS and RHS have different bitwidths. The new symbolic value + // for 'x' should have a bitwidth of 8. + x &= y; + + // This tests that our symbolication worked, and that we correctly test + // x against 0 (with the same bitwidth). + if (!x) { + if (!p) return; // expected-warning {{non-void function 'f10' should return a value}} + *p = 10; + } + else p = 0; + + if (!x) + *p = 5; // no-warning + + return p; +} + +// Test case from <rdar://problem/6407949> +void f11(unsigned i) { + int *x = 0; + if (i >= 0) { + // always true + } else { + *x = 42; // no-warning + } +} + +void f11b(unsigned i) { + int *x = 0; + if (i <= ~(unsigned)0) { + // always true + } else { + *x = 42; // no-warning + } +} + +// Test case for switch statements with weird case arms. +typedef int BOOL, *PBOOL, *LPBOOL; +typedef long LONG_PTR, *PLONG_PTR; +typedef unsigned long ULONG_PTR, *PULONG_PTR; +typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR; +typedef LONG_PTR LRESULT; +typedef struct _F12ITEM *HF12ITEM; + +void f12(HF12ITEM i, char *q) { + char *p = 0; + switch ((DWORD_PTR) i) { + case 0 ... 10: + p = q; + break; + case (DWORD_PTR) ((HF12ITEM) - 65535): + return; + default: + return; + } + + *p = 1; // no-warning +} + +// Test handling of translating between integer "pointers" and back. +void f13() { + int *x = 0; + if (((((int) x) << 2) + 1) >> 1) *x = 1; // no-warning +} + + diff --git a/test/Analysis/outofbound.c b/test/Analysis/outofbound.c new file mode 100644 index 000000000000..953075fe03d7 --- /dev/null +++ b/test/Analysis/outofbound.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -analyze -checker-simple -analyzer-store=region -verify %s + +char f1() { + char* s = "abcd"; + char c = s[4]; // no-warning + return s[5] + c; // expected-warning{{Load or store into an out-of-bound memory position.}} +} diff --git a/test/Analysis/override-werror.c b/test/Analysis/override-werror.c new file mode 100644 index 000000000000..f928ee031fe3 --- /dev/null +++ b/test/Analysis/override-werror.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -analyze -checker-cfref -Werror %s -analyzer-store=basic -verify && +// RUN: clang-cc -analyze -checker-cfref -Werror %s -analyzer-store=region -verify + +// This test case illustrates that using '-analyze' overrides the effect of +// -Werror. This allows basic warnings not to interfere with producing +// analyzer results. + +char* f(int *p) { + return p; // expected-warning{{incompatible pointer types returning 'int *', expected 'char *'}} +} + +void g(int *p) { + if (!p) *p = 0; // expected-warning{{null}} +} + diff --git a/test/Analysis/pr4209.m b/test/Analysis/pr4209.m new file mode 100644 index 000000000000..7d7d8fc5a157 --- /dev/null +++ b/test/Analysis/pr4209.m @@ -0,0 +1,70 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref -verify %s && +// RUN: clang-cc -triple i386-apple-darwin9 -analyze -checker-cfref -analyzer-store=region -verify %s + +// This test case was crashing due to how CFRefCount.cpp resolved the +// ObjCInterfaceDecl* and ClassName in EvalObjCMessageExpr. + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +@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 typedef float CGFloat; +typedef struct _NSPoint { +} +NSFastEnumerationState; +@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end @class NSString; +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; +@end @interface NSMutableArray : NSArray - (void)addObject:(id)anObject; +@end typedef unsigned short unichar; +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; +- (int)intValue; +@end @interface NSSimpleCString : NSString { +} +@end @interface NSConstantString : NSSimpleCString @end extern void *_NSConstantStringClassReference; +@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; +@end @interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey; +@end typedef struct { +} +CMProfileLocation; +@interface NSResponder : NSObject <NSCoding> { +} +@end @class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView; +@interface NSCell : NSObject <NSCopying, NSCoding> { +} +@end extern NSString *NSControlTintDidChangeNotification; +@interface NSActionCell : NSCell { +} +@end @class NSArray, NSDocument, NSWindow; +@interface NSWindowController : NSResponder <NSCoding> { +} +@end @class EBayCategoryType, GSEbayCategory, GBSearchRequest; +@interface GBCategoryChooserPanelController : NSWindowController { + GSEbayCategory *rootCategory; +} +- (NSMutableDictionary*)categoryDictionaryForCategoryID:(int)inID inRootTreeCategories:(NSMutableArray*)inRootTreeCategories; +-(NSString*) categoryID; +@end @interface GSEbayCategory : NSObject <NSCoding> { +} +- (int) categoryID; +- (GSEbayCategory *) parent; +- (GSEbayCategory*) subcategoryWithID:(int) inID; +@end @implementation GBCategoryChooserPanelController + (int) chooseCategoryIDFromCategories:(NSArray*) inCategories searchRequest:(GBSearchRequest*)inRequest parentWindow:(NSWindow*) inParent { +} +- (void) addCategory:(EBayCategoryType*)inCategory toRootTreeCategory:(NSMutableArray*)inRootTreeCategories { + GSEbayCategory *category = [rootCategory subcategoryWithID:[[inCategory categoryID] intValue]]; + if (rootCategory != category) { + GSEbayCategory *parent = category; + while ((((void*)0) != (parent = [parent parent])) && ([parent categoryID] != 0)) { + NSMutableDictionary *treeCategoryDict = [self categoryDictionaryForCategoryID:[parent categoryID] inRootTreeCategories:inRootTreeCategories]; + if (((void*)0) == treeCategoryDict) { + } + } + } +} diff --git a/test/Analysis/pr_2542_rdar_6793404.m b/test/Analysis/pr_2542_rdar_6793404.m new file mode 100644 index 000000000000..82a028d652d1 --- /dev/null +++ b/test/Analysis/pr_2542_rdar_6793404.m @@ -0,0 +1,68 @@ +// RUN: clang-cc -analyze -checker-cfref -pedantic -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -pedantic -analyzer-store=region -verify %s + +// BEGIN delta-debugging reduced header stuff + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSCoder; +@protocol NSObject +- (BOOL)isEqual:(id)object; +- (id)retain; +- (oneway void)release; +@end +@protocol NSCopying +- (id)copyWithZone:(NSZone *)zone; +@end +@protocol NSCoding +- (void)encodeWithCoder:(NSCoder *)aCoder; +@end +@interface NSObject <NSObject> {} +- (id)init; ++ (id)alloc; +@end +typedef double NSTimeInterval; +enum { NSAnimationEaseInOut, NSAnimationEaseIn, NSAnimationEaseOut, NSAnimationLinear }; +typedef NSUInteger NSAnimationCurve; +@interface NSAnimation : NSObject <NSCopying, NSCoding> {} +- (id)initWithDuration:(NSTimeInterval)duration animationCurve:(NSAnimationCurve)animationCurve; +- (void)startAnimation; +- (void)setDelegate:(id)delegate; +@end + +// END delta-debugging reduced header stuff + +// From NSAnimation Class Reference +// -(void)startAnimation +// The receiver retains itself and is then autoreleased at the end +// of the animation or when it receives stopAnimation. + +@interface MyClass { } +- (void)animationDidEnd:(NSAnimation *)animation; +@end + +@implementation MyClass +- (void)f1 { + // NOTE: The analyzer doesn't really handle this; it just stops tracking + // 'animation' when it is sent the message 'setDelegate:'. + NSAnimation *animation = [[NSAnimation alloc] // no-warning + initWithDuration:1.0 + animationCurve:NSAnimationEaseInOut]; + + [animation setDelegate:self]; + [animation startAnimation]; +} + +- (void)f2 { + NSAnimation *animation = [[NSAnimation alloc] // expected-warning{{leak}} + initWithDuration:1.0 + animationCurve:NSAnimationEaseInOut]; + + [animation startAnimation]; +} + +- (void)animationDidEnd:(NSAnimation *)animation { + [animation release]; +} +@end diff --git a/test/Analysis/pr_4164.c b/test/Analysis/pr_4164.c new file mode 100644 index 000000000000..cc2479c3e49c --- /dev/null +++ b/test/Analysis/pr_4164.c @@ -0,0 +1,41 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -triple x86_64-apple-darwin9 -analyze -checker-cfref -analyzer-store=region -verify %s + +// PR 4164: http://llvm.org/bugs/show_bug.cgi?id=4164 +// +// Eventually this should be pulled into misc-ps.m. This is in a separate test +// file for now to play around with the specific issues for BasicStoreManager +// and StoreManager (i.e., we can make a copy of this file for either +// StoreManager should one start to fail in the near future). +// +// The basic issue is that the VarRegion for 'size' is casted to (char*), +// resulting in an ElementRegion. 'getsockopt' is an unknown function that +// takes a void*, which means the ElementRegion should get stripped off. +typedef unsigned int __uint32_t; +typedef __uint32_t __darwin_socklen_t; +typedef __darwin_socklen_t socklen_t; +int getsockopt(int, int, int, void * restrict, socklen_t * restrict); + +int test1() { + int s = -1; + int size; + socklen_t size_len = sizeof(size); + if (getsockopt(s, 0xffff, 0x1001, (char *)&size, &size_len) < 0) + return -1; + + return size; // no-warning +} + +// Similar case: instead of passing a 'void*', we pass 'char*'. In this +// case we pass an ElementRegion to the invalidation logic. Since it is +// an ElementRegion that just layers on top of another typed region and the +// ElementRegion itself has elements whose type are integral (essentially raw +// data) we strip off the ElementRegion when doing the invalidation. +int takes_charptr(char* p); +int test2() { + int size; + if (takes_charptr((char*)&size)) + return -1; + return size; // no-warning +} + diff --git a/test/Analysis/ptr-arith.c b/test/Analysis/ptr-arith.c new file mode 100644 index 000000000000..ea8b7f566615 --- /dev/null +++ b/test/Analysis/ptr-arith.c @@ -0,0 +1,34 @@ +// RUN: clang-cc -analyze -checker-simple -analyzer-store=region -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify -triple x86_64-apple-darwin9 %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify -triple i686-apple-darwin9 %s + +void f1() { + int a[10]; + int *p = a; + ++p; +} + +char* foo(); + +void f2() { + char *p = foo(); + ++p; +} + +// This test case checks if we get the right rvalue type of a TypedViewRegion. +// The ElementRegion's type depends on the array region's rvalue type. If it was +// a pointer type, we would get a loc::SymbolVal for '*p'. +char* memchr(); +static int +domain_port (const char *domain_b, const char *domain_e, + const char **domain_e_ptr) +{ + int port = 0; + + const char *p; + const char *colon = memchr (domain_b, ':', domain_e - domain_b); + + for (p = colon + 1; p < domain_e ; p++) + port = 10 * port + (*p - '0'); + return port; +} diff --git a/test/Analysis/rdar-6442306-1.m b/test/Analysis/rdar-6442306-1.m new file mode 100644 index 000000000000..15d349884093 --- /dev/null +++ b/test/Analysis/rdar-6442306-1.m @@ -0,0 +1,31 @@ +// RUN: clang-cc -analyze -checker-cfref %s --analyzer-store=basic -verify && +// RUN: clang-cc -analyze -checker-cfref %s --analyzer-store=region -verify + +typedef int bar_return_t; +typedef struct { + unsigned char int_rep; +} Foo_record_t; +extern Foo_record_t Foo_record; +struct QuxSize {}; +typedef struct QuxSize QuxSize; +typedef struct { + Foo_record_t Foo; + QuxSize size; +} __Request__SetPortalSize_t; + +static __inline__ bar_return_t +__Beeble_check__Request__SetPortalSize_t(__attribute__((__unused__)) __Request__SetPortalSize_t *In0P) { + if (In0P->Foo.int_rep != Foo_record.int_rep) { + do { + int __i__, __C__ = (2); + for (__i__ = 0; + __i__ < __C__; + __i__++) do { + *(&((double *)(&In0P->size))[__i__]) = + __Foo_READSWAP__double(&((double *)(&In0P->size))[__i__]); + } + while (0); + } + while (0); + } +} diff --git a/test/Analysis/rdar-6539791.c b/test/Analysis/rdar-6539791.c new file mode 100644 index 000000000000..c1c989154337 --- /dev/null +++ b/test/Analysis/rdar-6539791.c @@ -0,0 +1,47 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +typedef const struct __CFAllocator * CFAllocatorRef; +typedef struct __CFDictionary * CFMutableDictionaryRef; +typedef signed long CFIndex; +typedef CFIndex CFNumberType; +typedef const void * CFTypeRef; +typedef struct {} CFDictionaryKeyCallBacks, CFDictionaryValueCallBacks; +typedef const struct __CFNumber * CFNumberRef; +extern const CFAllocatorRef kCFAllocatorDefault; +extern const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks; +extern const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks; +enum { kCFNumberSInt32Type = 3 }; +CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks); +void CFDictionaryAddValue(CFMutableDictionaryRef theDict, const void *key, const void *value); +void CFRelease(CFTypeRef cf); +CFTypeRef CFRetain(CFTypeRef cf); +extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr); +typedef const struct __CFArray * CFArrayRef; +typedef struct __CFArray * CFMutableArrayRef; +void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value); + +void f(CFMutableDictionaryRef y, void* key, void* val_key) { + CFMutableDictionaryRef x = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(y, key, x); + CFRelease(x); // the dictionary keeps a reference, so the object isn't deallocated yet + signed z = 1; + CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &z); + if (value) { + CFDictionaryAddValue(x, val_key, value); // no-warning + CFRelease(value); + CFDictionaryAddValue(y, val_key, value); // no-warning + } +} + +// <rdar://problem/6560661> +// Same issue, except with "AppendValue" functions. +void f2(CFMutableArrayRef x) { + signed z = 1; + CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &z); + // CFArrayAppendValue keeps a reference to value. + CFArrayAppendValue(x, value); + CFRelease(value); + CFRetain(value); + CFRelease(value); // no-warning +} diff --git a/test/Analysis/rdar-6540084.m b/test/Analysis/rdar-6540084.m new file mode 100644 index 000000000000..18ab038f6e2e --- /dev/null +++ b/test/Analysis/rdar-6540084.m @@ -0,0 +1,36 @@ +// RUN: clang-cc -analyze -warn-dead-stores -verify %s +// +// This test exercises the live variables analysis (LiveVariables.cpp). +// The case originally identified a non-termination bug. +// +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@interface NSObject <NSObject> {} @end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@class NSArray; +@class NSMutableArray, NSIndexSet, NSView, NSPredicate, NSString, NSViewAnimation, NSTimer; +@interface FooBazController : NSObject {} +@end +typedef struct {} TazVersion; +@class TazNode; +@interface TazGuttenberg : NSObject {} typedef NSUInteger BugsBunnyType; @end +@interface FooBaz : NSObject {} +@property (nonatomic) BugsBunnyType matchType; +@property (nonatomic, retain) NSArray *papyrus; @end +@implementation FooBazController +- (NSArray *)excitingStuff:(FooBaz *)options { + BugsBunnyType matchType = options.matchType; + NSPredicate *isSearchablePredicate = [NSPredicate predicateWithFormat:@"isSearchable == YES"]; // expected-warning{{receiver 'NSPredicate' is a forward class and corresponding}} // expected-warning{{return type defaults to 'id'}} + for (TazGuttenberg *Guttenberg in options.papyrus) { + NSArray *GuttenbergNodes = [Guttenberg nodes]; // expected-warning{{return type defaults to 'id'}} + NSArray *searchableNodes = [GuttenbergNodes filteredArrayUsingPredicate:isSearchablePredicate]; // expected-warning{{return type defaults to 'id'}} + for (TazNode *node in searchableNodes) { + switch (matchType) { + default: break; + } + } + } +} +@end diff --git a/test/Analysis/rdar-6541136-region.c b/test/Analysis/rdar-6541136-region.c new file mode 100644 index 000000000000..1e7a2d974bc4 --- /dev/null +++ b/test/Analysis/rdar-6541136-region.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -verify -analyze -checker-cfref -analyzer-store=region %s + +struct tea_cheese { unsigned magic; }; +typedef struct tea_cheese kernel_tea_cheese_t; +extern kernel_tea_cheese_t _wonky_gesticulate_cheese; + +// This test case exercises the ElementRegion::getRValueType() logic. + + +void foo( void ) +{ + kernel_tea_cheese_t *wonky = &_wonky_gesticulate_cheese; + struct load_wine *cmd = (void*) &wonky[1]; + cmd = cmd; + char *p = (void*) &wonky[1]; + *p = 1; + kernel_tea_cheese_t *q = &wonky[1]; + kernel_tea_cheese_t r = *q; // expected-warning{{out-of-bound memory position}} +} diff --git a/test/Analysis/rdar-6541136.c b/test/Analysis/rdar-6541136.c new file mode 100644 index 000000000000..6e6a479136b9 --- /dev/null +++ b/test/Analysis/rdar-6541136.c @@ -0,0 +1,20 @@ +// RUN: clang-cc -verify -analyze -checker-cfref -analyzer-store=basic %s + +struct tea_cheese { unsigned magic; }; +typedef struct tea_cheese kernel_tea_cheese_t; +extern kernel_tea_cheese_t _wonky_gesticulate_cheese; + +// This test case exercises the ElementRegion::getRValueType() logic. +// All it tests is that it does not crash or do anything weird. +// The out-of-bounds-access on line 19 is caught using the region store variant. + +void foo( void ) +{ + kernel_tea_cheese_t *wonky = &_wonky_gesticulate_cheese; + struct load_wine *cmd = (void*) &wonky[1]; + cmd = cmd; + char *p = (void*) &wonky[1]; + *p = 1; + kernel_tea_cheese_t *q = &wonky[1]; + kernel_tea_cheese_t r = *q; // no-warning +} diff --git a/test/Analysis/rdar-6562655.m b/test/Analysis/rdar-6562655.m new file mode 100644 index 000000000000..581d6eacf085 --- /dev/null +++ b/test/Analysis/rdar-6562655.m @@ -0,0 +1,63 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=basic -verify %s +// +// This test case mainly checks that the retain/release checker doesn't crash +// on this file. +// +typedef int int32_t; +typedef signed char BOOL; +typedef long NSInteger; +typedef unsigned long NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; +@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; +@end @interface NSObject <NSObject> {} +@end extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSResponder : NSObject <NSCoding> {} +@end @protocol NSAnimatablePropertyContainer - (id)animator; +@end extern NSString *NSAnimationTriggerOrderIn ; +@interface NSView : NSResponder <NSAnimatablePropertyContainer> { +} +@end enum { +NSNullCellType = 0, NSTextCellType = 1, NSImageCellType = 2 }; +typedef struct __CFlags { + unsigned int botnet:3; +} + _CFlags; +@interface Bar : NSObject <NSCopying, NSCoding> { + _CFlags _cFlags; +@private id _support; +} +@end extern NSString *NSControlTintDidChangeNotification; +typedef NSInteger NSBotnet; +@interface NSControl : NSView { +} +@end @class NSAttributedString, NSFont, NSImage, NSSound; +typedef int32_t Baz; +@interface Bar(BarInternal) - (void)_setIsWhite:(BOOL)isWhite; +@end +@interface Bar (BarBotnetCompatibility) +- (NSBotnet)_initialBotnetZorg; +@end +typedef struct _NSRunArrayItem { + unsigned int botnetIsSet:1; +} BarAuxFlags; +@interface BarAuxiliary : NSObject { +@public + NSControl *controlView; + BarAuxFlags auxCFlags; +} +@end +@implementation Bar +static Baz Qux = 0; +- (id)copyWithZone:(NSZone *)zone {} +- (void)encodeWithCoder:(NSCoder *)coder {} +@end +@implementation Bar (BarBotnet) +- (NSBotnet)botnet { + if (!(*(BarAuxiliary **)&self->_support)->auxCFlags.botnetIsSet) { + _cFlags.botnet = [self _initialBotnetZorg]; + } +} +@end diff --git a/test/Analysis/rdar-6582778-basic-store.c b/test/Analysis/rdar-6582778-basic-store.c new file mode 100644 index 000000000000..9ec38ef7a5f0 --- /dev/null +++ b/test/Analysis/rdar-6582778-basic-store.c @@ -0,0 +1,22 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s + +typedef const void * CFTypeRef; +typedef double CFTimeInterval; +typedef CFTimeInterval CFAbsoluteTime; +typedef const struct __CFAllocator * CFAllocatorRef; +typedef const struct __CFDate * CFDateRef; + +extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); +CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); + +void f(void) { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFTypeRef vals[] = { CFDateCreate(0, t) }; // no-warning +} + +CFTypeRef global; + +void g(void) { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + global = CFDateCreate(0, t); // no-warning +} diff --git a/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m b/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m new file mode 100644 index 000000000000..5d1fa37c46a8 --- /dev/null +++ b/test/Analysis/rdar-6600344-nil-receiver-undefined-struct-ret.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-constraints=basic -analyzer-store=basic %s -verify + +typedef struct Foo { int x; } Bar; + +@interface MyClass {} +- (Bar)foo; +@end +@implementation MyClass +- (Bar)foo { + struct Foo f = { 0 }; + return f; +} +@end + +void createFoo() { + MyClass *obj = 0; + Bar f = [obj foo]; // expected-warning{{The receiver in the message expression is 'nil' and results in the returned value (of type 'Bar') to be garbage or otherwise undefined.}} +} + +void createFoo2() { + MyClass *obj = 0; + [obj foo]; // no-warning + Bar f = [obj foo]; // expected-warning{{The receiver in the message expression is 'nil' and results in the returned value (of type 'Bar') to be garbage or otherwise undefined.}} +} + diff --git a/test/Analysis/refcnt_naming.m b/test/Analysis/refcnt_naming.m new file mode 100644 index 000000000000..bea404799ba3 --- /dev/null +++ b/test/Analysis/refcnt_naming.m @@ -0,0 +1,62 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +typedef const struct __CFURL * CFURLRef; +extern CFURLRef CFURLCreateWithString(CFAllocatorRef allocator, CFStringRef URLString, CFURLRef baseURL); +typedef signed char BOOL; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@interface NSObject <NSObject> {} @end +@class NSArray, NSString, NSURL; + +@interface NamingTest : NSObject {} +-(NSObject*)photocopy; // read as "photocopy" +-(NSObject*)photoCopy; // read as "photo Copy" +-(NSObject*)__blebPRCopy; // read as "bleb PRCopy" +-(NSObject*)__blebPRcopy; // read as "bleb P Rcopy" +-(NSObject*)new_theprefixdoesnotcount; // read as "theprefixdoesnotcount" +-(NSObject*)newestAwesomeStuff; // read as "newest awesome stuff" + +@end + +@interface MyClass : NSObject +{ + id myObject; +} +- (NSURL *)myMethod:(NSString *)inString; +- (NSURL *)getMethod:(NSString*)inString; +- (void)addObject:(id)X; +@end + +@implementation MyClass + +- (NSURL *)myMethod:(NSString *)inString +{ + NSURL *url = (NSURL *)CFURLCreateWithString(0, (CFStringRef)inString, 0); // expected-warning{{leak}} + return url; +} + +- (NSURL *)getMethod:(NSString *)inString +{ + NSURL *url = (NSURL *)CFURLCreateWithString(0, (CFStringRef)inString, 0); + [self addObject:url]; + return url; // no-warning +} + +void testNames(NamingTest* x) { + [x photocopy]; // no-warning + [x photoCopy]; // expected-warning{{leak}} + [x __blebPRCopy]; // expected-warning{{leak}} + [x __blebPRcopy]; // no-warning + [x new_theprefixdoesnotcount]; // no-warning + [x newestAwesomeStuff]; // no-warning +} + + +- (void)addObject:(id)X +{ + myObject = X; +} + +@end diff --git a/test/Analysis/region-1.m b/test/Analysis/region-1.m new file mode 100644 index 000000000000..ed172e431e99 --- /dev/null +++ b/test/Analysis/region-1.m @@ -0,0 +1,90 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s +// +// This test case simply should not crash. It evaluates the logic of not +// using MemRegion::getRValueType in incorrect places. + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +- (Class)class; +- (BOOL)isLegOfClass:(Class)aClass; +@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; +@end @interface NSObject <NSObject> { +} +@end @class NSArray; +@interface NSResponder : NSObject <NSCoding> { +} +@end @class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView; +@class JabasectItem; +@protocol EcoClassifier; +@protocol EcoClassInterfaceCommons <EcoClassifier> @end @protocol EcoImplementation; +@protocol EcoBehavioredClassifier <EcoClassInterfaceCommons> - (NSArray *) implementations; +@end enum { +CK_UNRESTRICTED= 0, CK_READ_ONLY, CK_ADD_ONLY, CK_REMOVE_ONLY }; +@protocol EcoClass <EcoBehavioredClassifier> - (NSArray *) ownedAttributes; +@end @protocol EcoNamespace; +@protocol EcoType; +@protocol EcoClassifier <EcoNamespace,EcoType> - (NSArray *) features; +@end @protocol EcoComment; +@protocol EcoElement <NSObject> - (NSArray *) ownedElements; +@end @protocol EcoDirectedRelationship; +@protocol EcoNamedElement <EcoElement> - (NSString *) name; +@end extern NSString *const JabaPathSeparator; +@protocol EcoNamespace <EcoNamedElement> - (NSArray *) Legs; +@end enum { +PDK_IN=0, PDK_INOUT, PDK_OUT, PDK_RETURN }; +@interface EcoElementImp : NSObject <EcoElement, NSCoding> { +} +@end @class EcoNamespace; +@interface EcoNamedElementImp : EcoElementImp <EcoNamedElement>{ +} +@end @interface EcoNamespaceImp : EcoNamedElementImp <EcoNamespace> { +} +@end @class JabaSCDocController, JabaSCDisplaySpecification; +@interface JabaSCSharedDiagramViewController : NSObject { +} +@end extern NSString *const JabaSCsectGraphicNamesectIdentifier; +@interface EcoClassifierImp : EcoNamespaceImp <EcoClassifier> { +} +@end @class EcoOperationImp; +@interface EcoClassImp : EcoClassifierImp <EcoClass> { +} +@end extern NSString *const JabaAddedUMLElements; +@class JabaSCClass, JabaSCInterface, JabaSCOperation; +@class DosLegVaseSymbol, DosProtocolSymbol, DosMethodSymbol, DosFileReference; +@interface HancodeFett : NSObject { +} ++ (DosLegVaseSymbol *) symbolFromClass: (JabaSCClass *) clz; +@end enum _JabaSourceLanguage { +JabaSourceUnknown=0, JabaSourcePrawn, JabaSourceC, JabaSourceCPP, JabaSourceObjectiveC }; +typedef NSUInteger JabaSourceLanguage; +@protocol JabaSCClassifier <EcoClassInterfaceCommons> - (JabaSourceLanguage)language; +@end @interface JabaSCClass : EcoClassImp <JabaSCClassifier> { +} +@end @class DosGlobalID, DosPQuLC, DosPQuUnLC; +@protocol XCProxyObjectProtocol - (id) representedObject; +@end typedef union _Dossymbollocation { +} + DosRecordArrPrl; +@interface DosIndexEntry : NSObject { +} +@end @class DosProjectIndex, DosTextPapyruswiggle, DosDocPapyruswiggle, DosLegVaseSymbol; +@interface DosSymbol : DosIndexEntry { +} +@end @interface DosLegVaseSymbol : DosSymbol { +} +@end typedef enum _DosTextRangeType { +Dos_CharacterRangeType = 0, Dos_LineRangeType = 1 } + DosTextRangeType; +@implementation JabaSCSharedDiagramViewController + (NSImage *)findImageNamed:(NSString *)name { +} +- (void)revealSourceInEditor:(JabasectItem *)sectItem duperGesture:(BOOL)duperGesture { + id <EcoNamedElement> selectedElement = [sectItem representedObject]; + id <EcoNamedElement> selectedClassifier = selectedElement; + DosSymbol *symbol=((void *)0); + if([selectedClassifier isLegOfClass:[JabaSCClass class]]) { + symbol = [HancodeFett symbolFromClass:(JabaSCClass *) selectedClassifier]; + } +} diff --git a/test/Analysis/region-only-test.c b/test/Analysis/region-only-test.c new file mode 100644 index 000000000000..fdc740488a2c --- /dev/null +++ b/test/Analysis/region-only-test.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -analyze -checker-simple -analyzer-store=region -verify %s + +// Region store must be enabled for tests in this file. + +// Exercise creating ElementRegion with symbolic super region. +void foo(int* p) { + int *x; + int a; + if (p[0] == 1) + x = &a; + if (p[0] == 1) + *x; // no-warning +} diff --git a/test/Analysis/retain-release-basic-store.m b/test/Analysis/retain-release-basic-store.m new file mode 100644 index 000000000000..b16c231ce23b --- /dev/null +++ b/test/Analysis/retain-release-basic-store.m @@ -0,0 +1,102 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from +// Foundation.h (Mac OS X). +// +// It includes the basic definitions for the test cases below. +// Not including Foundation.h directly makes this test case both svelte and +// portable to non-Mac platforms. +//===----------------------------------------------------------------------===// + +typedef unsigned int __darwin_natural_t; +typedef unsigned long UInt32; +typedef signed long CFIndex; +typedef const void * CFTypeRef; +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +extern const CFAllocatorRef kCFAllocatorDefault; +extern CFTypeRef CFRetain(CFTypeRef cf); +extern void CFRelease(CFTypeRef cf); +typedef struct { +} +CFArrayCallBacks; +extern const CFArrayCallBacks kCFTypeArrayCallBacks; +typedef const struct __CFArray * CFArrayRef; +typedef struct __CFArray * CFMutableArrayRef; +extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks); +extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); +typedef const struct __CFDictionary * CFDictionaryRef; +typedef UInt32 CFStringEncoding; +enum { +kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 }; +extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); +typedef double CFTimeInterval; +typedef CFTimeInterval CFAbsoluteTime; +typedef const struct __CFDate * CFDateRef; +extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); +extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); +typedef __darwin_natural_t natural_t; +typedef natural_t mach_port_name_t; +typedef mach_port_name_t mach_port_t; +typedef signed char BOOL; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +- (id)retain; +- (oneway void)release; +@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; +@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; +@end @interface NSObject <NSObject> { +} +@end typedef float CGFloat; +typedef double NSTimeInterval; +@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate; +@end enum { +NSObjCNoType = 0, NSObjCVoidType = 'v', NSObjCCharType = 'c', NSObjCShortType = 's', NSObjCLongType = 'l', NSObjCLonglongType = 'q', NSObjCFloatType = 'f', NSObjCDoubleType = 'd', NSObjCBoolType = 'B', NSObjCSelectorType = ':', NSObjCObjectType = '@', NSObjCStructType = '{', NSObjCPointerType = '^', NSObjCStringType = '*', NSObjCArrayType = '[', NSObjCUnionType = '(', NSObjCBitfield = 'b' } +__attribute__((deprecated)); +typedef int kern_return_t; +typedef kern_return_t mach_error_t; +typedef mach_port_t io_object_t; +typedef io_object_t io_service_t; +typedef struct __DASession * DASessionRef; +extern DASessionRef DASessionCreate( CFAllocatorRef allocator ); +typedef struct __DADisk * DADiskRef; +extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name ); +extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media ); +extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk ); +extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); +@interface NSAppleEventManager : NSObject { +} +@end enum { +kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; +typedef mach_error_t DAReturn; +typedef const struct __DADissenter * DADissenterRef; +extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +// Test to see if we supresss an error when we store the pointer +// to a struct. This is because the value "escapes" the basic reasoning +// of basic store. + +struct foo { + NSDate* f; +}; + +CFAbsoluteTime f4() { + struct foo x; + + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + [((NSDate*) date) retain]; + CFRelease(date); + CFDateGetAbsoluteTime(date); // no-warning + x.f = (NSDate*) date; + [((NSDate*) date) release]; + t = CFDateGetAbsoluteTime(date); // no-warning + return t; +} + diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m new file mode 100644 index 000000000000..70ad54f8aa4a --- /dev/null +++ b/test/Analysis/retain-release-gc-only.m @@ -0,0 +1,161 @@ +// RUN: clang-cc -analyze -checker-cfref -verify -fobjc-gc-only %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -fobjc-gc-only -verify %s + +//===----------------------------------------------------------------------===// +// Header stuff. +//===----------------------------------------------------------------------===// + +typedef unsigned int __darwin_natural_t; +typedef struct {} div_t; +typedef unsigned long UInt32; +typedef signed long CFIndex; +typedef const void * CFTypeRef; +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +extern const CFAllocatorRef kCFAllocatorDefault; +extern CFTypeRef CFRetain(CFTypeRef cf); +extern void CFRelease(CFTypeRef cf); +typedef struct { +} +CFArrayCallBacks; +extern const CFArrayCallBacks kCFTypeArrayCallBacks; +typedef const struct __CFArray * CFArrayRef; +typedef struct __CFArray * CFMutableArrayRef; +extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks); +extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); +extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value); +typedef const struct __CFDictionary * CFDictionaryRef; +typedef UInt32 CFStringEncoding; +enum { +kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 }; +extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); +typedef double CFTimeInterval; +typedef CFTimeInterval CFAbsoluteTime; +extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); +typedef const struct __CFDate * CFDateRef; +extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); +extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); +typedef __darwin_natural_t natural_t; +typedef natural_t mach_port_name_t; +typedef mach_port_name_t mach_port_t; +typedef struct { +} +CFRunLoopObserverContext; +typedef signed char BOOL; +typedef unsigned int NSUInteger; +@class NSString, Protocol; +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +- (id)retain; +- (oneway void)release; +- (id)autorelease; +@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> {} ++ (id)alloc; ++ (id)allocWithZone:(NSZone *)zone; +@end typedef float CGFloat; +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; +- (const char *)UTF8String; +- (id)initWithUTF8String:(const char *)nullTerminatedCString; ++ (id)stringWithUTF8String:(const char *)nullTerminatedCString; +- (id)init; +- (void)dealloc; +@end extern NSString * const NSCurrentLocaleDidChangeNotification ; +@protocol NSLocking - (void)lock; +@end extern NSString * const NSUndoManagerCheckpointNotification; +typedef enum { +ACL_READ_DATA = (1<<1), ACL_LIST_DIRECTORY = (1<<1), ACL_WRITE_DATA = (1<<2), ACL_ADD_FILE = (1<<2), ACL_EXECUTE = (1<<3), ACL_SEARCH = (1<<3), ACL_DELETE = (1<<4), ACL_APPEND_DATA = (1<<5), ACL_ADD_SUBDIRECTORY = (1<<5), ACL_DELETE_CHILD = (1<<6), ACL_READ_ATTRIBUTES = (1<<7), ACL_WRITE_ATTRIBUTES = (1<<8), ACL_READ_EXTATTRIBUTES = (1<<9), ACL_WRITE_EXTATTRIBUTES = (1<<10), ACL_READ_SECURITY = (1<<11), ACL_WRITE_SECURITY = (1<<12), ACL_CHANGE_OWNER = (1<<13) } +acl_entry_id_t; +typedef int kern_return_t; +typedef kern_return_t mach_error_t; +typedef mach_port_t io_object_t; +typedef io_object_t io_service_t; +typedef struct __DASession * DASessionRef; +extern DASessionRef DASessionCreate( CFAllocatorRef allocator ); +typedef struct __DADisk * DADiskRef; +extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name ); +extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media ); +extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk ); +extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); +@interface NSResponder : NSObject <NSCoding> { +} +@end @class NSColor, NSFont, NSNotification; +typedef struct __CFlags { +} +_CFlags; +@interface NSCell : NSObject <NSCopying, NSCoding> { +} +@end @class NSDate, NSDictionary, NSError, NSException, NSNotification; +@interface NSManagedObjectContext : NSObject <NSCoding, NSLocking> { +} +@end enum { +kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; +typedef mach_error_t DAReturn; +typedef const struct __DADissenter * DADissenterRef; +extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); + +CFTypeRef CFMakeCollectable(CFTypeRef cf) ; + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +void f1() { + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning + id x = [(id) A autorelease]; + CFRelease((CFMutableArrayRef) x); +} + +void f2() { + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}} + id x = [(id) A retain]; + [x release]; + [x release]; +} + +void f3() { + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}} + CFMakeCollectable(A); + CFRetain(A); +} + +// Test return of non-owned objects in contexts where an owned object +// is expected. +@interface TestReturnNotOwnedWhenExpectedOwned +- (NSString*)newString; +- (CFMutableArrayRef)newArray; +@end + +@implementation TestReturnNotOwnedWhenExpectedOwned +- (NSString*)newString { + NSString *s = [NSString stringWithUTF8String:"hello"]; // expected-warning{{Potential leak (when using garbage collection) of an object allocated on line 136 and stored into 's'}} + CFRetain(s); + return s; +} +- (CFMutableArrayRef)newArray{ + return CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} +@end + +//===----------------------------------------------------------------------===// +// Tests of ownership attributes. +//===----------------------------------------------------------------------===// + +@interface TestOwnershipAttr : NSObject +- (NSString*) returnsAnOwnedString __attribute__((ns_returns_retained)); +- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_retained)); +@end + +void test_attr_1(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedString]; // no-warning +} + +void test_attr_1b(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} +} + diff --git a/test/Analysis/retain-release-region-store.m b/test/Analysis/retain-release-region-store.m new file mode 100644 index 000000000000..66950e2190ed --- /dev/null +++ b/test/Analysis/retain-release-region-store.m @@ -0,0 +1,118 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from +// Foundation.h (Mac OS X). +// +// It includes the basic definitions for the test cases below. +// Not including Foundation.h directly makes this test case both svelte and +// portable to non-Mac platforms. +//===----------------------------------------------------------------------===// + +typedef unsigned int __darwin_natural_t; +typedef unsigned long UInt32; +typedef signed long CFIndex; +typedef const void * CFTypeRef; +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +extern const CFAllocatorRef kCFAllocatorDefault; +extern CFTypeRef CFRetain(CFTypeRef cf); +extern void CFRelease(CFTypeRef cf); +typedef struct { +} +CFArrayCallBacks; +extern const CFArrayCallBacks kCFTypeArrayCallBacks; +typedef const struct __CFArray * CFArrayRef; +typedef struct __CFArray * CFMutableArrayRef; +extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks); +extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); +typedef const struct __CFDictionary * CFDictionaryRef; +typedef UInt32 CFStringEncoding; +enum { +kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 }; +extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); +typedef double CFTimeInterval; +typedef CFTimeInterval CFAbsoluteTime; +typedef const struct __CFDate * CFDateRef; +extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); +extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); +typedef __darwin_natural_t natural_t; +typedef natural_t mach_port_name_t; +typedef mach_port_name_t mach_port_t; +typedef signed char BOOL; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +- (id)retain; +- (oneway void)release; +@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; +@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; +@end @interface NSObject <NSObject> { +} +@end typedef float CGFloat; +typedef double NSTimeInterval; +@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate; +@end enum { +NSObjCNoType = 0, NSObjCVoidType = 'v', NSObjCCharType = 'c', NSObjCShortType = 's', NSObjCLongType = 'l', NSObjCLonglongType = 'q', NSObjCFloatType = 'f', NSObjCDoubleType = 'd', NSObjCBoolType = 'B', NSObjCSelectorType = ':', NSObjCObjectType = '@', NSObjCStructType = '{', NSObjCPointerType = '^', NSObjCStringType = '*', NSObjCArrayType = '[', NSObjCUnionType = '(', NSObjCBitfield = 'b' } +__attribute__((deprecated)); +typedef int kern_return_t; +typedef kern_return_t mach_error_t; +typedef mach_port_t io_object_t; +typedef io_object_t io_service_t; +typedef struct __DASession * DASessionRef; +extern DASessionRef DASessionCreate( CFAllocatorRef allocator ); +typedef struct __DADisk * DADiskRef; +extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name ); +extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media ); +extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk ); +extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); +@interface NSAppleEventManager : NSObject { +} +@end enum { +kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; +typedef mach_error_t DAReturn; +typedef const struct __DADissenter * DADissenterRef; +extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +// Test to see if we *issue* an error when we store the pointer +// to a struct. This differs from basic store. + +struct foo { + NSDate* f; +}; + +CFAbsoluteTime f4() { + struct foo x; + + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + [((NSDate*) date) retain]; + CFRelease(date); + CFDateGetAbsoluteTime(date); // no-warning + x.f = (NSDate*) date; + [((NSDate*) date) release]; + t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} + return t; +} + +// Test that assigning to an self.ivar loses track of an object. +// This is a temporary hack to reduce false positives. +@interface Test3 : NSObject { + id myObj; +} +- (void)test_self_assign_ivar; +@end + +@implementation Test3 +- (void)test_self_assign_ivar { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); // no-warning + myObj = (id) date; +} +@end + + diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m new file mode 100644 index 000000000000..3ff007ed8b3a --- /dev/null +++ b/test/Analysis/retain-release.m @@ -0,0 +1,708 @@ +//>>SLICER +// RUN: clang-cc -analyze -checker-cfref -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from Mac OS X headers: +// +// #include <Cocoa/Cocoa.h> +// #include <CoreFoundation/CoreFoundation.h> +// #include <DiskArbitration/DiskArbitration.h> +// #include <QuartzCore/QuartzCore.h> +// #include <Quartz/Quartz.h> +// +// It includes the basic definitions for the test cases below. +//===----------------------------------------------------------------------===// + +typedef unsigned int __darwin_natural_t; +typedef unsigned int UInt32; +typedef signed long CFIndex; +typedef const void * CFTypeRef; +typedef const struct __CFString * CFStringRef; +typedef const struct __CFAllocator * CFAllocatorRef; +extern CFTypeRef CFRetain(CFTypeRef cf); +extern void CFRelease(CFTypeRef cf); +extern const CFAllocatorRef kCFAllocatorDefault; +typedef struct { +} +CFArrayCallBacks; +extern const CFArrayCallBacks kCFTypeArrayCallBacks; +typedef const struct __CFArray * CFArrayRef; +typedef struct __CFArray * CFMutableArrayRef; +extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks); +extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx); +extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value); +typedef const struct __CFDictionary * CFDictionaryRef; +typedef UInt32 CFStringEncoding; +enum { +kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 }; +extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); +typedef double CFTimeInterval; +typedef CFTimeInterval CFAbsoluteTime; +extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); +typedef const struct __CFDate * CFDateRef; +extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at); +CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate); +enum { +kCFCalendarComponentsWrap = (1UL << 0) }; +typedef __darwin_natural_t natural_t; +typedef natural_t mach_port_name_t; +typedef mach_port_name_t mach_port_t; +typedef int kern_return_t; +typedef kern_return_t mach_error_t; +typedef signed char BOOL; +typedef unsigned long NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +- (id)retain; +- (oneway void)release; +- (id)autorelease; +@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> { +} ++ (id)allocWithZone:(NSZone *)zone; ++ (id)alloc; +- (void)dealloc; +@end extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +typedef struct { +} +NSFastEnumerationState; +@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; +@end @interface NSArray (NSArrayCreation) + (id)array; +@end @interface NSAutoreleasePool : NSObject { +} +- (void)drain; +@end typedef double NSTimeInterval; +@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate; +@end enum { +NSWrapCalendarComponents = kCFCalendarComponentsWrap, }; +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; +- ( const char *)UTF8String; +- (id)initWithUTF8String:(const char *)nullTerminatedCString; ++ (id)stringWithUTF8String:(const char *)nullTerminatedCString; +@end @interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; ++ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length; ++ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b; +@end @interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; +@end @interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey; +- (void)setObject:(id)anObject forKey:(id)aKey; +@end @interface NSMutableDictionary (NSMutableDictionaryCreation) + (id)dictionaryWithCapacity:(NSUInteger)numItems; +struct CGRect { +}; +typedef struct CGRect CGRect; +- (id)init; +typedef mach_port_t io_object_t; +typedef io_object_t io_service_t; +typedef struct __DASession * DASessionRef; +extern DASessionRef DASessionCreate( CFAllocatorRef allocator ); +typedef struct __DADisk * DADiskRef; +extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name ); +extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media ); +extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk ); +extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk ); +typedef struct CGColorSpace *CGColorSpaceRef; +typedef struct CGImage *CGImageRef; +@end @class CIContext; +@class NSArray, NSError, NSEvent, NSMenu, NSUndoManager, NSWindow; +@interface NSResponder : NSObject <NSCoding> { +} +@end @protocol NSAnimatablePropertyContainer - (id)animator; +@end extern NSString *NSAnimationTriggerOrderIn ; +@interface NSView : NSResponder <NSAnimatablePropertyContainer> { +} +@end @class NSColor, NSFont, NSNotification; +@protocol NSValidatedUserInterfaceItem - (SEL)action; +@end @protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem; +@end typedef struct NSThreadPrivate _NSThreadPrivate; +@interface NSApplication : NSResponder <NSUserInterfaceValidations> { +} +@end enum { +NSTerminateCancel = 0, NSTerminateNow = 1, NSTerminateLater = 2 }; +typedef NSUInteger NSApplicationTerminateReply; +@protocol NSApplicationDelegate <NSObject> @optional - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; +@end enum { +NSUserInterfaceLayoutDirectionLeftToRight = 0, NSUserInterfaceLayoutDirectionRightToLeft = 1 }; +@interface CIImage : NSObject <NSCoding, NSCopying> { +} +typedef int CIFormat; +typedef struct __SFlags { +} +_SFlags; +@end extern NSString * const kCAGravityCenter __attribute__((visibility("default"))); +enum { +kDAReturnSuccess = 0, kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C }; +typedef mach_error_t DAReturn; +typedef const struct __DADissenter * DADissenterRef; +extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); +@interface CIContext: NSObject { +} +- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r; +- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r format:(CIFormat)f colorSpace:(CGColorSpaceRef)cs; +@end @protocol QCCompositionRenderer @end @interface QCRenderer : NSObject <QCCompositionRenderer> { +} +- (id) createSnapshotImageOfType:(NSString*)type; +@end @interface QCView : NSView <QCCompositionRenderer> { +} +- (id) createSnapshotImageOfType:(NSString*)type; +@end +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +CFAbsoluteTime f1() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + CFRetain(date); + CFRelease(date); + CFDateGetAbsoluteTime(date); // no-warning + CFRelease(date); + t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} + return t; +} + +CFAbsoluteTime f2() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + [((NSDate*) date) retain]; + CFRelease(date); + CFDateGetAbsoluteTime(date); // no-warning + [((NSDate*) date) release]; + t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}} + return t; +} + + +NSDate* global_x; + +// Test to see if we supresss an error when we store the pointer +// to a global. + +CFAbsoluteTime f3() { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); + [((NSDate*) date) retain]; + CFRelease(date); + CFDateGetAbsoluteTime(date); // no-warning + global_x = (NSDate*) date; + [((NSDate*) date) release]; + t = CFDateGetAbsoluteTime(date); // no-warning + return t; +} + +//--------------------------------------------------------------------------- +// Test case 'f4' differs for region store and basic store. See +// retain-release-region-store.m and retain-release-basic-store.m. +//--------------------------------------------------------------------------- + +// Test a leak. + +CFAbsoluteTime f5(int x) { + CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); + CFDateRef date = CFDateCreate(0, t); // expected-warning{{leak}} + + if (x) + CFRelease(date); + + return t; +} + +// Test a leak involving the return. + +CFDateRef f6(int x) { + CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); // expected-warning{{leak}} + CFRetain(date); + return date; +} + +// Test a leak involving an overwrite. + +CFDateRef f7() { + CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); //expected-warning{{leak}} + CFRetain(date); + date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); + return date; +} + +// Generalization of Create rule. MyDateCreate returns a CFXXXTypeRef, and +// has the word create. +CFDateRef MyDateCreate(); + +CFDateRef f8() { + CFDateRef date = MyDateCreate(); // expected-warning{{leak}} + CFRetain(date); + return date; +} + +CFDateRef f9() { + CFDateRef date = CFDateCreate(0, CFAbsoluteTimeGetCurrent()); + int *p = 0; + // When allocations fail, CFDateCreate can return null. + if (!date) *p = 1; // expected-warning{{null}} + return date; +} + +// Handle DiskArbitration API: +// +// http://developer.apple.com/DOCUMENTATION/DARWIN/Reference/DiscArbitrationFramework/ +// +void f10(io_service_t media, DADiskRef d, CFStringRef s) { + DADiskRef disk = DADiskCreateFromBSDName(kCFAllocatorDefault, 0, "hello"); // expected-warning{{leak}} + if (disk) NSLog(@"ok"); + + disk = DADiskCreateFromIOMedia(kCFAllocatorDefault, 0, media); // expected-warning{{leak}} + if (disk) NSLog(@"ok"); + + CFDictionaryRef dict = DADiskCopyDescription(d); // expected-warning{{leak}} + if (dict) NSLog(@"ok"); + + disk = DADiskCopyWholeDisk(d); // expected-warning{{leak}} + if (disk) NSLog(@"ok"); + + DADissenterRef dissenter = DADissenterCreate(kCFAllocatorDefault, // expected-warning{{leak}} + kDAReturnSuccess, s); + if (dissenter) NSLog(@"ok"); + + DASessionRef session = DASessionCreate(kCFAllocatorDefault); // expected-warning{{leak}} + if (session) NSLog(@"ok"); +} + +// Test retain/release checker with CFString and CFMutableArray. +void f11() { + // Create the array. + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); + + // Create a string. + CFStringRef s1 = CFStringCreateWithCString(0, "hello world", + kCFStringEncodingUTF8); + + // Add the string to the array. + CFArrayAppendValue(A, s1); + + // Decrement the reference count. + CFRelease(s1); // no-warning + + // Get the string. We don't own it. + s1 = (CFStringRef) CFArrayGetValueAtIndex(A, 0); + + // Release the array. + CFRelease(A); // no-warning + + // Release the string. This is a bug. + CFRelease(s1); // expected-warning{{Incorrect decrement of the reference count}} +} + +// PR 3337: Handle functions declared using typedefs. +typedef CFTypeRef CREATEFUN(); +CREATEFUN MyCreateFun; + +void f12() { + CFTypeRef o = MyCreateFun(); // expected-warning {{leak}} +} + +void f13_autorelease() { + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning + [(id) A autorelease]; // no-warning +} + +void f13_autorelease_b() { + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); + [(id) A autorelease]; + [(id) A autorelease]; // expected-warning{{Object sent -autorelease too many times}} +} + +CFMutableArrayRef f13_autorelease_c() { + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); + [(id) A autorelease]; + [(id) A autorelease]; + return A; // expected-warning{{Object sent -autorelease too many times}} +} + +CFMutableArrayRef f13_autorelease_d() { + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); + [(id) A autorelease]; + [(id) A autorelease]; + CFMutableArrayRef B = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{Object sent -autorelease too many times}} + CFRelease(B); // no-warning +} + + +// This case exercises the logic where the leak site is the same as the allocation site. +void f14_leakimmediately() { + CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // expected-warning{{leak}} +} + +// Test that we track an allocated object beyond the point where the *name* +// of the variable storing the reference is no longer live. +void f15() { + // Create the array. + CFMutableArrayRef A = CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); + CFMutableArrayRef *B = &A; + // At this point, the name 'A' is no longer live. + CFRelease(*B); // no-warning +} + + +// Test basic tracking of ivars associated with 'self'. For the retain/release +// checker we currently do not want to flag leaks associated with stores +// of tracked objects to ivars. +@interface SelfIvarTest : NSObject { + id myObj; +} +- (void)test_self_tracking; +@end + +@implementation SelfIvarTest +- (void)test_self_tracking { + myObj = (id) CFArrayCreateMutable(0, 10, &kCFTypeArrayCallBacks); // no-warning +} +@end + +// Test return of non-owned objects in contexts where an owned object +// is expected. +@interface TestReturnNotOwnedWhenExpectedOwned +- (NSString*)newString; +@end + +@implementation TestReturnNotOwnedWhenExpectedOwned +- (NSString*)newString { + NSString *s = [NSString stringWithUTF8String:"hello"]; + return s; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}} +} +@end + +// <rdar://problem/6659160> +int isFoo(char c); + +static void rdar_6659160(char *inkind, char *inname) +{ + // We currently expect that [NSObject alloc] cannot fail. This + // will be a toggled flag in the future. It can indeed return null, but + // Cocoa programmers generally aren't expected to reason about out-of-memory + // conditions. + NSString *kind = [[NSString alloc] initWithUTF8String:inkind]; // expected-warning{{leak}} + + // We do allow stringWithUTF8String to fail. This isn't really correct, as + // far as returning 0. In most error conditions it will throw an exception. + // If allocation fails it could return 0, but again this + // isn't expected. + NSString *name = [NSString stringWithUTF8String:inname]; + if(!name) + return; + + const char *kindC = 0; + const char *nameC = 0; + + // In both cases, we cannot reach a point down below where we + // dereference kindC or nameC with either being null. This is because + // we assume that [NSObject alloc] doesn't fail and that we have the guard + // up above. + + if(kind) + kindC = [kind UTF8String]; + if(name) + nameC = [name UTF8String]; + if(!isFoo(kindC[0])) // expected-warning{{null}} + return; + if(!isFoo(nameC[0])) // no-warning + return; + + [kind release]; + [name release]; // expected-warning{{Incorrect decrement of the reference count}} +} + +// PR 3677 - 'allocWithZone' should be treated as following the Cocoa naming +// conventions with respect to 'return'ing ownership. +@interface PR3677: NSObject @end +@implementation PR3677 ++ (id)allocWithZone:(NSZone *)inZone { + return [super allocWithZone:inZone]; // no-warning +} +@end + +// PR 3820 - Reason about calls to -dealloc +void pr3820_DeallocInsteadOfRelease(void) +{ + id foo = [[NSString alloc] init]; // no-warning + [foo dealloc]; + // foo is not leaked, since it has been deallocated. +} + +void pr3820_ReleaseAfterDealloc(void) +{ + id foo = [[NSString alloc] init]; + [foo dealloc]; + [foo release]; // expected-warning{{used after it is release}} + // NSInternalInconsistencyException: message sent to deallocated object +} + +void pr3820_DeallocAfterRelease(void) +{ + NSLog(@"\n\n[%s]", __FUNCTION__); + id foo = [[NSString alloc] init]; + [foo release]; + [foo dealloc]; // expected-warning{{used after it is released}} + // message sent to released object +} + +// From <rdar://problem/6704930>. The problem here is that 'length' binds to +// '($0 - 1)' after '--length', but SimpleConstraintManager doesn't know how to +// reason about '($0 - 1) > constant'. As a temporary hack, we drop the value +// of '($0 - 1)' and conjure a new symbol. +void rdar6704930(unsigned char *s, unsigned int length) { + NSString* name = 0; + if (s != 0) { + if (length > 0) { + while (length > 0) { + if (*s == ':') { + ++s; + --length; + name = [[NSString alloc] init]; // no-warning + break; + } + ++s; + --length; + } + if ((length == 0) && (name != 0)) { + [name release]; + name = 0; + } + if (length == 0) { // no ':' found -> use it all as name + name = [[NSString alloc] init]; // no-warning + } + } + } + + if (name != 0) { + [name release]; + } +} + +//===----------------------------------------------------------------------===// +// <rdar://problem/6833332> +// One build of the analyzer accidentally stopped tracking the allocated +// object after the 'retain'. +//===----------------------------------------------------------------------===// + +@interface rdar_6833332 : NSObject <NSApplicationDelegate> { + NSWindow *window; +} +@property (nonatomic, retain) NSWindow *window; +@end + +@implementation rdar_6833332 +@synthesize window; +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + NSMutableDictionary *dict = [[NSMutableDictionary dictionaryWithCapacity:4] retain]; // expected-warning{{leak}} + + [dict setObject:@"foo" forKey:@"bar"]; + + NSLog(@"%@", dict); +} +- (void)dealloc { + [window release]; + [super dealloc]; +} +@end + +//===----------------------------------------------------------------------===// +// <rdar://problem/6257780> clang checker fails to catch use-after-release +//===----------------------------------------------------------------------===// + +int rdar_6257780_Case1() { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + NSArray *array = [NSArray array]; + [array release]; // expected-warning{{Incorrect decrement of the reference count of an object is not owned at this point by the caller}} + [pool drain]; + return 0; +} + +//===----------------------------------------------------------------------===// +// <rdar://problem/6866843> Checker should understand new/setObject:/release constructs +//===----------------------------------------------------------------------===// + +void rdar_6866843() { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + NSMutableDictionary* dictionary = [[NSMutableDictionary alloc] init]; + NSArray* array = [[NSArray alloc] init]; + [dictionary setObject:array forKey:@"key"]; + [array release]; + // Using 'array' here should be fine + NSLog(@"array = %@\n", array); // no-warning + // Now the array is released + [dictionary release]; + [pool drain]; +} + + +//===----------------------------------------------------------------------===// +// <rdar://problem/6877235> Classes typedef-ed to CF objects should get the same treatment as CF objects +//===----------------------------------------------------------------------===// + +typedef CFTypeRef OtherRef; + +@interface RDar6877235 : NSObject {} +- (CFTypeRef)_copyCFTypeRef; +- (OtherRef)_copyOtherRef; +@end + +@implementation RDar6877235 +- (CFTypeRef)_copyCFTypeRef { + return [[NSString alloc] init]; // no-warning +} +- (OtherRef)_copyOtherRef { + return [[NSString alloc] init]; // no-warning +} +@end + +//===----------------------------------------------------------------------===// +//<rdar://problem/6320065> false positive - init method returns an object owned by caller +//===----------------------------------------------------------------------===// + +@interface RDar6320065 : NSObject { + NSString *_foo; +} +- (id)initReturningNewClass; +- (id)initReturningNewClassBad; +- (id)initReturningNewClassBad2; +@end + +@interface RDar6320065Subclass : RDar6320065 +@end + +@implementation RDar6320065 +- (id)initReturningNewClass { + [self release]; + self = [[RDar6320065Subclass alloc] init]; // no-warning + return self; +} +- (id)initReturningNewClassBad { + [self release]; + [[RDar6320065Subclass alloc] init]; // expected-warning {{leak}} + return self; +} +- (id)initReturningNewClassBad2 { + [self release]; + self = [[RDar6320065Subclass alloc] init]; + return [self autorelease]; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}} +} + +@end + +@implementation RDar6320065Subclass +@end + +int RDar6320065_test() { + RDar6320065 *test = [[RDar6320065 alloc] init]; // no-warning + [test release]; + return 0; +} + +//===----------------------------------------------------------------------===// +// <rdar://problem/6859457> [NSData dataWithBytesNoCopy] does not return a retained object +//===----------------------------------------------------------------------===// + +@interface RDar6859457 : NSObject {} +- (NSString*) NoCopyString; +- (NSString*) noCopyString; +@end + +@implementation RDar6859457 +- (NSString*) NoCopyString { return [[NSString alloc] init]; } // no-warning +- (NSString*) noCopyString { return [[NSString alloc] init]; } // no-warning +@end + +void test_RDar6859457(RDar6859457 *x, void *bytes, NSUInteger dataLength) { + [x NoCopyString]; // expected-warning{{leak}} + [x noCopyString]; // expected-warning{{leak}} + [NSData dataWithBytesNoCopy:bytes length:dataLength]; // no-warning + [NSData dataWithBytesNoCopy:bytes length:dataLength freeWhenDone:1]; // no-warning +} + +//===----------------------------------------------------------------------===// +// PR 4230 - an autorelease pool is not necessarily leaked during a premature +// return +//===----------------------------------------------------------------------===// + +static void PR4230(void) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // no-warning + NSString *object = [[[NSString alloc] init] autorelease]; // no-warning + return; +} + +//===----------------------------------------------------------------------===// +// Method name that has a null IdentifierInfo* for its first selector slot. +// This test just makes sure that we handle it. +//===----------------------------------------------------------------------===// + +@interface TestNullIdentifier +@end + +@implementation TestNullIdentifier ++ (id):(int)x, ... { + return [[NSString alloc] init]; // expected-warning{{leak}} +} +@end + +//===----------------------------------------------------------------------===// +// <rdar://problem/6893565> don't flag leaks for return types that cannot be +// determined to be CF types +//===----------------------------------------------------------------------===// + +// We don't know if 'struct s6893565' represents a Core Foundation type, so +// we shouldn't emit an error here. +typedef struct s6893565* TD6893565; + +@interface RDar6893565 {} +-(TD6893565)newThing; +@end + +@implementation RDar6893565 +-(TD6893565)newThing { + return (TD6893565) [[NSString alloc] init]; // no-warning +} +@end + +//===----------------------------------------------------------------------===// +// <rdar://problem/6902710> clang: false positives w/QC and CoreImage methods +//===----------------------------------------------------------------------===// + +void rdar6902710(QCView *view, QCRenderer *renderer, CIContext *context, + NSString *str, CIImage *img, CGRect rect, + CIFormat form, CGColorSpaceRef cs) { + [view createSnapshotImageOfType:str]; // expected-warning{{leak}} + [renderer createSnapshotImageOfType:str]; // expected-warning{{leak}} + [context createCGImage:img fromRect:rect]; // expected-warning{{leak}} + [context createCGImage:img fromRect:rect format:form colorSpace:cs]; // expected-warning{{leak}} +} + +//===----------------------------------------------------------------------===// +// Tests of ownership attributes. +//===----------------------------------------------------------------------===// + +typedef NSString* MyStringTy; + +@interface TestOwnershipAttr : NSObject +- (NSString*) returnsAnOwnedString __attribute__((ns_returns_retained)); // no-warning +- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_retained)); // no-warning +- (MyStringTy) returnsAnOwnedTypedString __attribute__((ns_returns_retained)); // no-warning +- (int) returnsAnOwnedInt __attribute__((ns_returns_retained)); // expected-warning{{'ns_returns_retained' attribute only applies to functions or methods that return a pointer or Objective-C object}} +@end + +static int ownership_attribute_doesnt_go_here __attribute__((ns_returns_retained)); // expected-warning{{'ns_returns_retained' attribute only applies to function or method types}} + +void test_attr_1(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} +} + +void test_attr_1b(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} +} +//<<SLICER + diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c new file mode 100644 index 000000000000..4bc9a7def2c8 --- /dev/null +++ b/test/Analysis/stack-addr-ps.c @@ -0,0 +1,44 @@ +// RUN: clang-cc -analyze -checker-simple -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +#include <stdlib.h> + +int* f1() { + int x = 0; + return &x; // expected-warning{{Address of stack memory associated with local variable 'x' returned.}} expected-warning{{address of stack memory associated with local variable 'x' returned}} +} + +int* f2(int y) { + return &y; // expected-warning{{Address of stack memory associated with local variable 'y' returned.}} expected-warning{{address of stack memory associated with local variable 'y' returned}} +} + +int* f3(int x, int *y) { + int w = 0; + + if (x) + y = &w; + + return y; // expected-warning{{Address of stack memory associated with local variable 'w' returned.}} +} + +void* compound_literal(int x, int y) { + if (x) + return &(unsigned short){((unsigned short)0x22EF)}; // expected-warning{{Address of stack memory}} + + int* array[] = {}; + struct s { int z; double y; int w; }; + + if (y) + return &((struct s){ 2, 0.4, 5 * 8 }); // expected-warning{{Address of stack memory}} + + + void* p = &((struct s){ 42, 0.4, x ? 42 : 0 }); + return p; // expected-warning{{Address of stack memory}} +} + +void* alloca_test() { + void* p = __builtin_alloca(10); + return p; // expected-warning{{Address of stack memory}} +} + diff --git a/test/Analysis/uninit-msg-expr.m b/test/Analysis/uninit-msg-expr.m new file mode 100644 index 000000000000..161ab8041de1 --- /dev/null +++ b/test/Analysis/uninit-msg-expr.m @@ -0,0 +1,58 @@ +// RUN: clang-cc -analyze -checker-simple -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from +// Foundation.h (Mac OS X). +// +// It includes the basic definitions for the test cases below. +// Not directly including Foundation.h directly makes this test case +// both svelte and portable to non-Mac platforms. +//===----------------------------------------------------------------------===// + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @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; +@class NSString, NSData, NSMutableData, NSMutableDictionary, NSMutableArray; +typedef struct {} NSFastEnumerationState; +@protocol NSFastEnumeration +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end +@class NSData, NSIndexSet, NSString, NSURL; +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> +- (NSUInteger)count; +@end +@interface NSArray (NSArrayCreation) ++ (id)array; +- (NSUInteger)length; +- (void)addObject:(id)object; +@end +extern NSString * const NSUndoManagerCheckpointNotification; + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +unsigned f1() { + NSString *aString; + return [aString length]; // expected-warning {{Receiver in message expression is an uninitialized value}} +} + +unsigned f2() { + NSString *aString = 0; + return [aString length]; // no-warning +} + +void f3() { + NSMutableArray *aArray = [NSArray array]; + NSString *aString; + [aArray addObject:aString]; // expected-warning {{Pass-by-value argument in message expression is undefined.}} +} diff --git a/test/Analysis/uninit-ps-rdar6145427.m b/test/Analysis/uninit-ps-rdar6145427.m new file mode 100644 index 000000000000..49eb26984a0b --- /dev/null +++ b/test/Analysis/uninit-ps-rdar6145427.m @@ -0,0 +1,37 @@ +// RUN: clang-cc -analyze -verify -analyzer-store=basic -checker-cfref %s && +// RUN: clang-cc -analyze -verify -analyzer-store=region -checker-cfref %s + +// Delta-Debugging reduced preamble. +typedef signed char BOOL; +typedef unsigned int NSUInteger; +@class NSString, Protocol; +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@protocol NSCopying - (id)copyWithZone:(NSZone *)zone; @end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end +@interface NSObject <NSObject> {} + (id)alloc; @end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSValue : NSObject <NSCopying, NSCoding> - (void)getValue:(void *)value; @end +@class NSString, NSData; +typedef struct _NSPoint {} NSRange; +@interface NSValue (NSValueRangeExtensions) ++ (NSValue *)valueWithRange:(NSRange)range; +- (id)objectAtIndex:(NSUInteger)index; +@end +@interface NSAutoreleasePool : NSObject {} - (void)drain; @end +extern NSString * const NSBundleDidLoadNotification; +typedef struct {} NSDecimal; +@interface NSNetService : NSObject {} - (id)init; @end +extern NSString * const NSUndoManagerCheckpointNotification; + +// Test case: <rdar://problem/6145427> + +int main (int argc, const char * argv[]) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + id someUnintializedPointer = [someUnintializedPointer objectAtIndex:0]; // expected-warning{{Receiver in message expression is an uninitialized value.}} + NSLog(@"%@", someUnintializedPointer); + [pool drain]; + return 0; +} diff --git a/test/Analysis/uninit-vals-ps-region.c b/test/Analysis/uninit-vals-ps-region.c new file mode 100644 index 000000000000..6f3762ee10bf --- /dev/null +++ b/test/Analysis/uninit-vals-ps-region.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -analyze -checker-simple -analyzer-store=region -verify %s + +struct s { + int data; +}; + +struct s global; + +void g(int); + +void f4() { + int a; + if (global.data == 0) + a = 3; + if (global.data == 0) // When the true branch is feasible 'a = 3'. + g(a); // no-warning +} diff --git a/test/Analysis/uninit-vals-ps.c b/test/Analysis/uninit-vals-ps.c new file mode 100644 index 000000000000..41771265367a --- /dev/null +++ b/test/Analysis/uninit-vals-ps.c @@ -0,0 +1,85 @@ +// RUN: clang-cc -analyze -checker-cfref -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +struct FPRec { + void (*my_func)(int * x); +}; + +int bar(int x); + +int f1_a(struct FPRec* foo) { + int x; + (*foo->my_func)(&x); + return bar(x)+1; // no-warning +} + +int f1_b() { + int x; + return bar(x)+1; // expected-warning{{Pass-by-value argument in function call is undefined.}} +} + +int f2() { + + int x; + + if (x+1) // expected-warning{{Branch}} + return 1; + + return 2; +} + +int f2_b() { + int x; + + return ((x+1)+2+((x))) + 1 ? 1 : 2; // expected-warning{{Branch}} +} + +int f3(void) { + int i; + int *p = &i; + if (*p > 0) // expected-warning{{Branch condition evaluates to an uninitialized value}} + return 0; + else + return 1; +} + +void f4_aux(float* x); +float f4(void) { + float x; + f4_aux(&x); + return x; // no-warning +} + +struct f5_struct { int x; }; +void f5_aux(struct f5_struct* s); +int f5(void) { + struct f5_struct s; + f5_aux(&s); + return s.x; // no-warning +} + +int ret_uninit() { + int i; + int *p = &i; + return *p; // expected-warning{{Uninitialized or undefined value returned to caller.}} +} + +// <rdar://problem/6451816> +typedef unsigned char Boolean; +typedef const struct __CFNumber * CFNumberRef; +typedef signed long CFIndex; +typedef CFIndex CFNumberType; +typedef unsigned long UInt32; +typedef UInt32 CFStringEncoding; +typedef const struct __CFString * CFStringRef; +extern Boolean CFNumberGetValue(CFNumberRef number, CFNumberType theType, void *valuePtr); +extern CFStringRef CFStringConvertEncodingToIANACharSetName(CFStringEncoding encoding); + +CFStringRef rdar_6451816(CFNumberRef nr) { + CFStringEncoding encoding; + // &encoding is casted to void*. This test case tests whether or not + // we properly invalidate the value of 'encoding'. + CFNumberGetValue(nr, 9, &encoding); + return CFStringConvertEncodingToIANACharSetName(encoding); // no-warning +} + diff --git a/test/Analysis/uninit-vals.c b/test/Analysis/uninit-vals.c new file mode 100644 index 000000000000..d69250b65c0b --- /dev/null +++ b/test/Analysis/uninit-vals.c @@ -0,0 +1,53 @@ +// RUN: clang-cc -analyze -warn-uninit-values -verify %s + +int f1() { + int x; + return x; // expected-warning {{use of uninitialized variable}} +} + +int f2(int x) { + int y; + int z = x + y; // expected-warning {{use of uninitialized variable}} + return z; +} + + +int f3(int x) { + int y; + return x ? 1 : y; // expected-warning {{use of uninitialized variable}} +} + +int f4(int x) { + int y; + if (x) y = 1; + return y; // expected-warning {{use of uninitialized variable}} +} + +int f5() { + int a; + a = 30; // no-warning +} + +void f6(int i) { + int x; + for (i = 0 ; i < 10; i++) + printf("%d",x++); // expected-warning {{use of uninitialized variable}} \ + // expected-warning{{implicitly declaring C library function 'printf' with type 'int (char const *, ...)'}} \ + // expected-note{{please include the header <stdio.h> or explicitly provide a declaration for 'printf'}} +} + +void f7(int i) { + int x = i; + int y; + for (i = 0; i < 10; i++ ) { + printf("%d",x++); // no-warning + x += y; // expected-warning {{use of uninitialized variable}} + } +} + +int f8(int j) { + int x = 1, y = x + 1; + if (y) // no-warning + return x; + return y; +} diff --git a/test/Analysis/uninit-vals.m b/test/Analysis/uninit-vals.m new file mode 100644 index 000000000000..7be247e7ca9e --- /dev/null +++ b/test/Analysis/uninit-vals.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s + +typedef unsigned int NSUInteger; + +@interface A +- (NSUInteger)foo; +@end + +NSUInteger f8(A* x){ + const NSUInteger n = [x foo]; + int* bogus; + + if (n > 0) { // tests const cast transfer function logic + NSUInteger i; + + for (i = 0; i < n; ++i) + bogus = 0; + + if (bogus) // no-warning + return n+1; + } + + return n; +} diff --git a/test/Analysis/unused-ivars.m b/test/Analysis/unused-ivars.m new file mode 100644 index 000000000000..632b395c3e08 --- /dev/null +++ b/test/Analysis/unused-ivars.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -analyze -warn-objc-unused-ivars %s -verify + +@interface A +{ + @private int x; // expected-warning {{Instance variable 'x' in class 'A' is never used}} +} +@end + +@implementation A @end + diff --git a/test/Analysis/xfail-no-outofbounds.c b/test/Analysis/xfail-no-outofbounds.c new file mode 100644 index 000000000000..f2ee732c2570 --- /dev/null +++ b/test/Analysis/xfail-no-outofbounds.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -checker-cfref -analyze -analyzer-store=region -verify %s + +void f() { + long x = 0; + char *y = (char*) &x; + char c = y[0] + y[1] + y[2]; // no-warning +} diff --git a/test/Analysis/xfail_regionstore_wine_crash.c b/test/Analysis/xfail_regionstore_wine_crash.c new file mode 100644 index 000000000000..2628d0dacf6a --- /dev/null +++ b/test/Analysis/xfail_regionstore_wine_crash.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -checker-cfref -analyze -analyzer-store=region -verify %s +// XFAIL + +// When this test passes we should put it in the misc-ps.m test file. +// This test fails now because RegionStoreManager::Retrieve() does correctly +// retrieve the first byte of 'x' when retrieving '*y'. +void foo() { + long x = 0; + char *y = (char *) &x; + if (!*y) + return; +} diff --git a/test/CodeGen/2007-11-29-ArraySizeFromInitializer.c b/test/CodeGen/2007-11-29-ArraySizeFromInitializer.c new file mode 100644 index 000000000000..3b158241c68e --- /dev/null +++ b/test/CodeGen/2007-11-29-ArraySizeFromInitializer.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +int array[] = {1, 2, 3, 4, 5}; + diff --git a/test/CodeGen/2008-02-07-bitfield-bug.c b/test/CodeGen/2008-02-07-bitfield-bug.c new file mode 100644 index 000000000000..dc2ebb75d598 --- /dev/null +++ b/test/CodeGen/2008-02-07-bitfield-bug.c @@ -0,0 +1,11 @@ +// RUN: clang-cc %s -emit-llvm -o %t +// PR1990 + +struct test { + char a[3]; + unsigned char b:1; +}; + +void f(struct test *t) { + t->b = 1; +} diff --git a/test/CodeGen/2008-02-08-bitfield-bug.c b/test/CodeGen/2008-02-08-bitfield-bug.c new file mode 100644 index 000000000000..fc69e58ed3cf --- /dev/null +++ b/test/CodeGen/2008-02-08-bitfield-bug.c @@ -0,0 +1,9 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +struct test { + unsigned a:1; + unsigned b:1; +}; + +struct test *t; + diff --git a/test/CodeGen/2008-02-26-inline-asm-bug.c b/test/CodeGen/2008-02-26-inline-asm-bug.c new file mode 100644 index 000000000000..a6816f5de8ff --- /dev/null +++ b/test/CodeGen/2008-02-26-inline-asm-bug.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -emit-llvm < %s | grep "\$0,\$1" + +void f() { + int d1, d2; + asm("%0,%1": "=r" (d1) : "r" (d2)); +} diff --git a/test/CodeGen/2008-07-17-no-emit-on-error.c b/test/CodeGen/2008-07-17-no-emit-on-error.c new file mode 100644 index 000000000000..89aeb18d9d13 --- /dev/null +++ b/test/CodeGen/2008-07-17-no-emit-on-error.c @@ -0,0 +1,10 @@ +// RUN: rm -f %t1.bc +// RUN: not clang-cc %s -emit-llvm-bc -o %t1.bc +// RUN: not test -f %t1.bc + +void f() { +} + +void g() { + *10; +} diff --git a/test/CodeGen/2008-07-21-mixed-var-fn-decl.c b/test/CodeGen/2008-07-21-mixed-var-fn-decl.c new file mode 100644 index 000000000000..c55c86b2fc6c --- /dev/null +++ b/test/CodeGen/2008-07-21-mixed-var-fn-decl.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -emit-llvm -o - %s | grep -e "@g[0-9] " | count 2 + +int g0, f0(); +int f1(), g1; + diff --git a/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c b/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c new file mode 100644 index 000000000000..19bf9a2b078e --- /dev/null +++ b/test/CodeGen/2008-07-22-bitfield-init-after-zero-len-array.c @@ -0,0 +1,11 @@ +// RUN: clang-cc --emit-llvm -o %t %s && +// RUN: grep "i8 52" %t | count 1 + +struct et7 { + float lv7[0]; + char mv7:6; +} yv7 = { + {}, + 52, +}; + diff --git a/test/CodeGen/2008-07-22-packed-bitfield-access.c b/test/CodeGen/2008-07-22-packed-bitfield-access.c new file mode 100644 index 000000000000..437a4be156b7 --- /dev/null +++ b/test/CodeGen/2008-07-22-packed-bitfield-access.c @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -emit-llvm -o - + +int main () { + struct foo { + unsigned a:16; + unsigned b:32 __attribute__ ((packed)); + } x; + x.b = 0x56789abcL; + return 0; +} diff --git a/test/CodeGen/2008-07-29-override-alias-decl.c b/test/CodeGen/2008-07-29-override-alias-decl.c new file mode 100644 index 000000000000..43f4e3ecedae --- /dev/null +++ b/test/CodeGen/2008-07-29-override-alias-decl.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -emit-llvm -o - %s | grep -e "^@f" | count 1 + +int x() {} + +int f() __attribute__((weak, alias("x"))); + +/* Test that we link to the alias correctly instead of making a new + forward definition. */ +int f(); +int h() { + return f(); +} diff --git a/test/CodeGen/2008-07-30-implicit-initialization.c b/test/CodeGen/2008-07-30-implicit-initialization.c new file mode 100644 index 000000000000..2f4c14eb728b --- /dev/null +++ b/test/CodeGen/2008-07-30-implicit-initialization.c @@ -0,0 +1,28 @@ +// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt --std-compile-opts | llvm-dis > %t && +// RUN: grep "ret i32" %t | count 2 && +// RUN: grep "ret i32 0" %t | count 2 +// <rdar://problem/6113085> + +struct s0 { + int x, y; +}; + +int f0() { + struct s0 x = {0}; + return x.y; +} + +#if 0 +/* Optimizer isn't smart enough to reduce this since we use + memset. Hrm. */ +int f1() { + struct s0 x[2] = { {0} }; + return x[1].x; +} +#endif + +int f2() { + int x[2] = { 0 }; + return x[1]; +} + diff --git a/test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c b/test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c new file mode 100644 index 000000000000..c374f8d00843 --- /dev/null +++ b/test/CodeGen/2008-07-30-redef-of-bitcasted-decl.c @@ -0,0 +1,28 @@ +// RUN: clang-cc --emit-llvm -o - %s +// <rdar://problem/6108358> + +/* For posterity, the issue here begins initial "char []" decl for + * s. This is a tentative definition and so a global was being + * emitted, however the mapping in GlobalDeclMap referred to a bitcast + * of this global. + * + * The problem was that later when the correct definition for s is + * emitted we were doing a RAUW on the old global which was destroying + * the bitcast in the GlobalDeclMap (since it cannot be replaced + * properly), leaving a dangling pointer. + * + * The purpose of bar is just to trigger a use of the old decl + * sometime after the dangling pointer has been introduced. + */ + +char s[]; + +static void bar(void *db) { + eek(s); +} + +char s[5] = "hi"; + +int foo() { + bar(0); +} diff --git a/test/CodeGen/2008-07-31-asm-labels.c b/test/CodeGen/2008-07-31-asm-labels.c new file mode 100644 index 000000000000..f114f65eded2 --- /dev/null +++ b/test/CodeGen/2008-07-31-asm-labels.c @@ -0,0 +1,33 @@ +// RUN: clang-cc -emit-llvm -o %t %s && +// RUN: grep "@pipe()" %t | count 0 && +// RUN: grep '_thisIsNotAPipe' %t | count 3 && +// RUN: grep 'g0' %t | count 0 && +// RUN: grep '_renamed' %t | count 2 && +// RUN: clang-cc -DUSE_DEF -emit-llvm -o %t %s && +// RUN: grep "@pipe()" %t | count 0 && +// RUN: grep '_thisIsNotAPipe' %t | count 3 +// <rdr://6116729> + +void pipe() asm("_thisIsNotAPipe"); + +void f0() { + pipe(); +} + +void pipe(int); + +void f1() { + pipe(1); +} + +#ifdef USE_DEF +void pipe(int arg) { + int x = 10; +} +#endif + +// PR3698 +extern int g0 asm("_renamed"); +int f2() { + return g0; +} diff --git a/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c b/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c new file mode 100644 index 000000000000..0ce4ba66ca12 --- /dev/null +++ b/test/CodeGen/2008-07-31-promotion-of-compound-pointer-arithmetic.c @@ -0,0 +1,25 @@ +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis | grep "ret i32 1" | count 3 +// <rdr://6115726> + +int f0() { + int x; + unsigned short n = 1; + int *a = &x; + int *b = &x; + a = a - n; + b -= n; + return a == b; +} + +int f1(int *a) { + long b = a - (int*) 1; + a -= (int*) 1; + return b == (long) a; +} + +int f2(long n) { + int *b = n + (int*) 1; + n += (int*) 1; + return b == (int*) n; +} + diff --git a/test/CodeGen/2008-08-04-void-pointer-arithmetic.c b/test/CodeGen/2008-08-04-void-pointer-arithmetic.c new file mode 100644 index 000000000000..22815f32ccc4 --- /dev/null +++ b/test/CodeGen/2008-08-04-void-pointer-arithmetic.c @@ -0,0 +1,6 @@ +// RUN: clang-cc --emit-llvm -o - %s +// <rdar://problem/6122967> + +int f0(void *a, void *b) { + return a - b; +} diff --git a/test/CodeGen/2008-08-19-cast-of-typedef.c b/test/CodeGen/2008-08-19-cast-of-typedef.c new file mode 100644 index 000000000000..3db5e903090a --- /dev/null +++ b/test/CodeGen/2008-08-19-cast-of-typedef.c @@ -0,0 +1,10 @@ +// RUN: clang-cc --emit-llvm -o %t %s + +typedef short T[4]; +struct s { + T f0; +}; + +void foo(struct s *x) { + bar((long) x->f0); +} diff --git a/test/CodeGen/2008-08-25-incompatible-cond-expr.m b/test/CodeGen/2008-08-25-incompatible-cond-expr.m new file mode 100644 index 000000000000..3cc42d89f6fa --- /dev/null +++ b/test/CodeGen/2008-08-25-incompatible-cond-expr.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm -o %t %s + +@protocol P0 +@end +@interface A <P0> +@end + +id f0(int a, id<P0> x, A* p) { + return a ? x : p; +} diff --git a/test/CodeGen/2008-09-22-bad-switch-type.c b/test/CodeGen/2008-09-22-bad-switch-type.c new file mode 100644 index 000000000000..2526dd9289c8 --- /dev/null +++ b/test/CodeGen/2008-09-22-bad-switch-type.c @@ -0,0 +1,34 @@ +// RUN: clang-cc -emit-llvm -o %t %s +// PR2817 + +void f0(void) { + switch (0) { + case (unsigned long long) 0 < 0: + break; + } + + switch (0) { + case (unsigned long long) 0 > 0: + break; + } + + switch (0) { + case (unsigned long long) 0 <= 0: + break; + } + + switch (0) { + case (unsigned long long) 0 >= 0: + break; + } + + switch (0) { + case (unsigned long long) 0 == 0: + break; + } + + switch (0) { + case (unsigned long long) 0 != 0: + break; + } +} diff --git a/test/CodeGen/2008-12-02-logical-or-fold.c b/test/CodeGen/2008-12-02-logical-or-fold.c new file mode 100644 index 000000000000..d54bf287d2e2 --- /dev/null +++ b/test/CodeGen/2008-12-02-logical-or-fold.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm -o - %s | grep "store i32 1" +// PR3150 + +int a() {return 1||1;} diff --git a/test/CodeGen/2009-01-21-invalid-debug-info.m b/test/CodeGen/2009-01-21-invalid-debug-info.m new file mode 100644 index 000000000000..9a955a1c0d95 --- /dev/null +++ b/test/CodeGen/2009-01-21-invalid-debug-info.m @@ -0,0 +1,16 @@ +// RUN: clang-cc -S -g -o %t.s %s + +// FIXME: This test case can be removed at some point (since it will +// no longer effectively test anything). The reason it was causing +// trouble was the synthesized self decl in im1 was causing the debug +// info for I1* to be generated, but referring to an invalid compile +// unit. This was later referred to by f1 and created ill formed debug +// information. + +@interface I1 @end + +@implementation I1 +-im0 {} +@end + +I1 *f1(void) { return 0; } diff --git a/test/CodeGen/2009-03-22-increment-bitfield.c b/test/CodeGen/2009-03-22-increment-bitfield.c new file mode 100644 index 000000000000..f0aaafda60ea --- /dev/null +++ b/test/CodeGen/2009-03-22-increment-bitfield.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -emit-llvm -O1 < %s | grep "ret i32 0" + +int a(void) { + return ++(struct x {unsigned x : 2;}){3}.x; +} + + diff --git a/test/CodeGen/2009-04-23-dbg.c b/test/CodeGen/2009-04-23-dbg.c new file mode 100644 index 000000000000..4be6dab7ea2b --- /dev/null +++ b/test/CodeGen/2009-04-23-dbg.c @@ -0,0 +1,20 @@ +// RUN: clang-cc -g -o %t %s -emit-llvm-bc && llc %t -f -o %t.s +# 1 "a.c" +# 1 "a.c" 1 +# 1 "<built-in>" 1 +# 103 "<built-in>" +# 103 "<command line>" 1 + +# 1 "/private/tmp/a.h" 1 +int bar; +# 105 "<command line>" 2 +# 105 "<built-in>" 2 +# 1 "a.c" 2 +# 1 "/private/tmp/a.h" 1 +int bar; +# 2 "a.c" 2 + +int main() { + bar = 0; + return 0; +} diff --git a/test/CodeGen/2009-05-22-callingconv.c b/test/CodeGen/2009-05-22-callingconv.c new file mode 100644 index 000000000000..2b70d840c061 --- /dev/null +++ b/test/CodeGen/2009-05-22-callingconv.c @@ -0,0 +1,25 @@ +// RUN: clang-cc %s -emit-llvm -o - | grep call | grep x86_stdcallcc +void abort(void) __attribute__((__noreturn__)); +typedef void re_string_t; +typedef void re_dfa_t; +typedef int reg_errcode_t; +static reg_errcode_t re_string_construct (re_string_t *pstr, const char *str, + int len, char * trans, + int icase, const re_dfa_t *dfa) + __attribute__ ((regparm (3), stdcall)); +static reg_errcode_t +re_string_construct (pstr, str, len, trans, icase, dfa) + re_string_t *pstr; + const char *str; + int len, icase; + char * trans; + const re_dfa_t *dfa; +{ + if (dfa != (void*)0x282020c0) + abort(); +return 0; +} +int main() +{ + return re_string_construct(0, 0, 0, 0, 0, (void*)0x282020c0); +} diff --git a/test/CodeGen/2009-05-28-const-typedef.c b/test/CodeGen/2009-05-28-const-typedef.c new file mode 100644 index 000000000000..e46e83b9478c --- /dev/null +++ b/test/CodeGen/2009-05-28-const-typedef.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -emit-llvm %s -o - +// PR4281 + +typedef struct { + int i; +} something; + +typedef const something const_something; + +something fail(void); + +int +main(int argc, char *argv[]) +{ + const_something R = fail(); +} + diff --git a/test/CodeGen/2009-06-01-addrofknr.c b/test/CodeGen/2009-06-01-addrofknr.c new file mode 100644 index 000000000000..16a5bbffc3af --- /dev/null +++ b/test/CodeGen/2009-06-01-addrofknr.c @@ -0,0 +1,21 @@ +// RUN: clang-cc %s -o %t -emit-llvm -verify +// PR4289 + +struct funcptr { + int (*func)(); +}; + +static int func(f) + void *f; +{ +} + +int +main(int argc, char *argv[]) +{ + struct funcptr fp; + + fp.func = &func; + fp.func = func; +} + diff --git a/test/CodeGen/OpaqueStruct.c b/test/CodeGen/OpaqueStruct.c new file mode 100644 index 000000000000..b994c3000246 --- /dev/null +++ b/test/CodeGen/OpaqueStruct.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -emit-llvm -o %t +typedef struct a b; + +b* x; + +struct a { + b* p; +}; + +void f() { + b* z = x->p; +} diff --git a/test/CodeGen/PR2001-bitfield-reload.c b/test/CodeGen/PR2001-bitfield-reload.c new file mode 100644 index 000000000000..797b494cf823 --- /dev/null +++ b/test/CodeGen/PR2001-bitfield-reload.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt --std-compile-opts | llvm-dis > %t && +// RUN: grep "ret i32" %t | count 1 && +// RUN: grep "ret i32 1" %t | count 1 +// PR2001 + +/* Test that the result of the assignment properly uses the value *in + the bitfield* as opposed to the RHS. */ +static int foo(int i) { + struct { + int f0 : 2; + } x; + return (x.f0 = i); +} + +int bar() { + return foo(-5) == -1; +} diff --git a/test/CodeGen/PR2413-void-address-cast-error.c b/test/CodeGen/PR2413-void-address-cast-error.c new file mode 100644 index 000000000000..95a4c6d80fc3 --- /dev/null +++ b/test/CodeGen/PR2413-void-address-cast-error.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -emit-llvm %s -o - +void f() +{ + void *addr; + addr = (void *)( ((long int)addr + 7L) ); +} diff --git a/test/CodeGen/PR2643-null-store-to-bitfield.c b/test/CodeGen/PR2643-null-store-to-bitfield.c new file mode 100644 index 000000000000..6a5b0e92f660 --- /dev/null +++ b/test/CodeGen/PR2643-null-store-to-bitfield.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm -o - %s +// PR2643 + +void foo() { + struct { + int a : 1; + int b : 1; + } entry = {0}; +} + diff --git a/test/CodeGen/PR2743-reference-missing-static.c b/test/CodeGen/PR2743-reference-missing-static.c new file mode 100644 index 000000000000..e152c5258527 --- /dev/null +++ b/test/CodeGen/PR2743-reference-missing-static.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -emit-llvm -o %t %s +// PR2743 +// <rdr://6094512> + +/* CodeGen should handle this even if it makes it past + sema. Unfortunately this test will become useless once sema starts + rejecting this. */ + +static void e0(); +void f0() { e0(); } + +inline void e1(); +void f1() { e1(); } + +void e2() __attribute__((weak)); +void f2() { e2(); } diff --git a/test/CodeGen/PR3130-cond-constant.c b/test/CodeGen/PR3130-cond-constant.c new file mode 100644 index 000000000000..e488eeb37f67 --- /dev/null +++ b/test/CodeGen/PR3130-cond-constant.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -emit-llvm %s -o - + +int a = 2.0 ? 1 : 2; diff --git a/test/CodeGen/PR3589-freestanding-libcalls.c b/test/CodeGen/PR3589-freestanding-libcalls.c new file mode 100644 index 000000000000..90b5fff1620f --- /dev/null +++ b/test/CodeGen/PR3589-freestanding-libcalls.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -emit-llvm %s -o - | grep 'declare i32 @printf' | count 1 && +// RUN: clang-cc -O2 -emit-llvm %s -o - | grep 'declare i32 @puts' | count 1 && +// RUN: clang-cc -ffreestanding -O2 -emit-llvm %s -o - | grep 'declare i32 @puts' | count 0 + +#include <stdio.h> + +void f0() { + printf("hello\n"); +} diff --git a/test/CodeGen/PR3613-static-decl.c b/test/CodeGen/PR3613-static-decl.c new file mode 100644 index 000000000000..365b9b2be05e --- /dev/null +++ b/test/CodeGen/PR3613-static-decl.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o %t %s && +// RUN: grep '@g0 = internal global .struct.s0 <{ i32 3 }>' %t | count 1 + +struct s0 { + int a; +}; + +static struct s0 g0; + +static int f0(void) { + return g0.a; +} + +static struct s0 g0 = {3}; + +void *g1 = f0; diff --git a/test/CodeGen/PR3709-int-to-pointer-sign.c b/test/CodeGen/PR3709-int-to-pointer-sign.c new file mode 100644 index 000000000000..24c42f649bbe --- /dev/null +++ b/test/CodeGen/PR3709-int-to-pointer-sign.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -emit-llvm %s -o - -O1 -triple=x86_64-gnu-linux | grep "i64 -1" + +// PR3709 +long long a() { return (long long)(int*)-1;} + diff --git a/test/CodeGen/PR3869-indirect-goto-long.c b/test/CodeGen/PR3869-indirect-goto-long.c new file mode 100644 index 000000000000..140e4ec14a86 --- /dev/null +++ b/test/CodeGen/PR3869-indirect-goto-long.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm-bc -o - %s +// PR3869 +int a(long long b) { goto *b; } + diff --git a/test/CodeGen/address-space-cast.c b/test/CodeGen/address-space-cast.c new file mode 100644 index 000000000000..2fba5ecd7dca --- /dev/null +++ b/test/CodeGen/address-space-cast.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm < %s + +volatile unsigned char* const __attribute__((address_space(1))) serial_ctrl = 0x02; + diff --git a/test/CodeGen/address-space.c b/test/CodeGen/address-space.c new file mode 100644 index 000000000000..3b6a8e654167 --- /dev/null +++ b/test/CodeGen/address-space.c @@ -0,0 +1,20 @@ +// RUN: clang-cc -emit-llvm < %s | grep '@foo.*global.*addrspace(1)' && +// RUN: clang-cc -emit-llvm < %s | grep '@ban.*global.*addrspace(1)' && +// RUN: clang-cc -emit-llvm < %s | grep 'load.*addrspace(1)' | count 2 && +// RUN: clang-cc -emit-llvm < %s | grep 'load.*addrspace(2).. @A' && +// RUN: clang-cc -emit-llvm < %s | grep 'load.*addrspace(2).. @B' + +int foo __attribute__((address_space(1))); +int ban[10] __attribute__((address_space(1))); + +int bar() { return foo; } + +int baz(int i) { return ban[i]; } + +// Both A and B point into addrspace(2). +__attribute__((address_space(2))) int *A, *B; + +void test3() { + *A = *B; +} + diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c new file mode 100644 index 000000000000..b0c71fbdfca4 --- /dev/null +++ b/test/CodeGen/alias.c @@ -0,0 +1,32 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s && +// RUN: grep '@g0 = common global i32 0' %t && +// RUN: grep '@f1 = alias void ()\* @f0' %t && +// RUN: grep '@g1 = alias i32\* @g0' %t && +// RUN: grep 'define void @f0() nounwind {' %t && + +void f0(void) { } +extern void f1(void); +extern void f1(void) __attribute((alias("f0"))); + +int g0; +extern int g1; +extern int g1 __attribute((alias("g0"))); + +// Make sure that aliases cause referenced values to be emitted. +// PR3200 +// RUN: grep 'define internal i32 @foo1()' %t && +static inline int foo1() { return 0; } +int foo() __attribute__((alias("foo1"))); + + +// RUN: grep '@bar1 = internal global i32 42' %t +static int bar1 = 42; +int bar() __attribute__((alias("bar1"))); + + +extern int test6(); +void test7() { test6(); } // test6 is emitted as extern. + +// test6 changes to alias. +int test6() __attribute__((alias("test7"))); + diff --git a/test/CodeGen/align-local.c b/test/CodeGen/align-local.c new file mode 100644 index 000000000000..afbe1d5dd0d0 --- /dev/null +++ b/test/CodeGen/align-local.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -emit-llvm < %s | grep "align 16" | count 2 + +typedef struct __attribute((aligned(16))) {int x[4];} ff; + +int a() { + ff a; + struct {int x[4];} b __attribute((aligned(16))); +} diff --git a/test/CodeGen/alignof.c b/test/CodeGen/alignof.c new file mode 100644 index 000000000000..d39f4e418eb1 --- /dev/null +++ b/test/CodeGen/alignof.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -triple i386-unknown-unknown -O1 -emit-llvm -o %t %s && +// RUN: grep 'ret i32 4' %t + +enum e0 { E0 }; +struct s0 { + enum e0 a:31; +}; + +struct s0 t1_tmp; +int f0() { + return __alignof__(t1_tmp); +} diff --git a/test/CodeGen/array.c b/test/CodeGen/array.c new file mode 100644 index 000000000000..5bcc26ecf38b --- /dev/null +++ b/test/CodeGen/array.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +int f() { + int a[2]; + a[0] = 0; +} + +int f2() { + int x = 0; + int y = 1; + int a[10] = { y, x, 2, 3}; + int b[10] = { 2,4,x,6,y,8}; + int c[5] = { 0,1,2,3}; +} diff --git a/test/CodeGen/asm-2.c b/test/CodeGen/asm-2.c new file mode 100644 index 000000000000..f5b378eb1017 --- /dev/null +++ b/test/CodeGen/asm-2.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm %s -o %t -triple i386-pc-linux-gnu -O2 && +// RUN: not grep "load" %t + +// <rdar://problem/6841383> +int cpuid(unsigned data) { + int a, b; + + asm("xyz" :"=a"(a), "=d"(b) : "a"(data)); + return a + b; +} diff --git a/test/CodeGen/asm.c b/test/CodeGen/asm.c new file mode 100644 index 000000000000..58373fc4c96e --- /dev/null +++ b/test/CodeGen/asm.c @@ -0,0 +1,103 @@ +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t && +void t1(int len) { + __asm__ volatile("" : "=&r"(len), "+&r"(len)); +} + +void t2(unsigned long long t) { + __asm__ volatile("" : "+m"(t)); +} + +void t3(unsigned char *src, unsigned long long temp) { + __asm__ volatile("" : "+m"(temp), "+r"(src)); +} + +void t4() { + unsigned long long a; + struct reg { unsigned long long a, b; } b; + + __asm__ volatile ("":: "m"(a), "m"(b)); +} + +// PR3417 +void t5(int i) { + asm("nop" : "=r"(i) : "0"(t5)); +} + +// PR3641 +void t6(void) { + __asm__ volatile("" : : "i" (t6)); +} + +// RUN: grep "T7 NAMED: \$1" %t && +void t7(int a) { + __asm__ volatile("T7 NAMED: %[input]" : "+r"(a): [input] "i" (4)); +} + +// RUN: grep "T8 NAMED MODIFIER: \${0:c}" %t +void t8() { + __asm__ volatile("T8 NAMED MODIFIER: %c[input]" :: [input] "i" (4)); +} + +// PR3682 +unsigned t9(unsigned int a) { + asm("bswap %0 %1" : "+r" (a)); + return a; +} + +// PR3908 +// RUN: grep "PR3908 \$1 \$3 \$2 \$0" %t +void t10(int r) { + __asm__("PR3908 %[lf] %[xx] %[li] %[r]" : [r] "+r" (r) : [lf] "mx" (0), [li] "mr" (0), [xx] "x" ((double)(0))); +} + + +// PR3373 +unsigned t11(signed char input) { + unsigned output; + __asm__("xyz" + : "=a" (output) + : "0" (input)); + return output; +} + +// PR3373 +unsigned char t12(unsigned input) { + unsigned char output; + __asm__("xyz" + : "=a" (output) + : "0" (input)); + return output; +} + +unsigned char t13(unsigned input) { + unsigned char output; + __asm__("xyz %1" + : "=a" (output) + : "0" (input)); + return output; +} + +struct large { + int x[1000]; +}; + +unsigned long t15(int x, struct large *P) { + __asm__("xyz " + : "=r" (x) + : "m" (*P), "0" (x)); + return x; +} + + + + +// bitfield destination of an asm. +struct S { + int a : 4; +}; + +void t14(struct S *P) { + __asm__("abc %0" : "=r"(P->a) ); +} + + diff --git a/test/CodeGen/atomic.c b/test/CodeGen/atomic.c new file mode 100644 index 000000000000..66dc702bfee9 --- /dev/null +++ b/test/CodeGen/atomic.c @@ -0,0 +1,53 @@ +// RUN: clang-cc %s -emit-llvm -o - -triple=i686-apple-darwin9 > %t1 && +// RUN: grep @llvm.atomic.load.add.i32 %t1 | count 3 && +// RUN: grep @llvm.atomic.load.sub.i8 %t1 | count 2 && +// RUN: grep @llvm.atomic.load.min.i32 %t1 && +// RUN: grep @llvm.atomic.load.max.i32 %t1 && +// RUN: grep @llvm.atomic.load.umin.i32 %t1 && +// RUN: grep @llvm.atomic.load.umax.i32 %t1 && +// RUN: grep @llvm.atomic.swap.i32 %t1 && +// RUN: grep @llvm.atomic.cmp.swap.i32 %t1 | count 4 && +// RUN: grep @llvm.atomic.load.and.i32 %t1 | count 2 && +// RUN: grep @llvm.atomic.load.or.i8 %t1 && +// RUN: grep @llvm.atomic.load.xor.i8 %t1 + + +int atomic(void) +{ + // non-sensical test for sync functions + int old; + int val = 1; + char valc = 1; + unsigned int uval = 1; + int cmp = 0; + + old = __sync_fetch_and_add(&val, 1); + old = __sync_fetch_and_sub(&valc, 2); + old = __sync_fetch_and_min(&val, 3); + old = __sync_fetch_and_max(&val, 4); + old = __sync_fetch_and_umin(&uval, 5u); + old = __sync_fetch_and_umax(&uval, 6u); + old = __sync_lock_test_and_set(&val, 7); + old = __sync_val_compare_and_swap(&val, 4, 1976); + old = __sync_bool_compare_and_swap(&val, 4, 1976); + old = __sync_fetch_and_and(&val, 0x9); + old = __sync_fetch_and_or(&val, 0xa); + old = __sync_fetch_and_xor(&val, 0xb); + old = __sync_fetch_and_nand(&val, 0xb); + + old = __sync_add_and_fetch(&val, 1); + old = __sync_sub_and_fetch(&val, 2); + old = __sync_and_and_fetch(&valc, 3); + old = __sync_or_and_fetch(&valc, 4); + old = __sync_xor_and_fetch(&valc, 5); + old = __sync_nand_and_fetch(&valc, 5); + + + __sync_val_compare_and_swap((void **)0, (void *)0, (void *)0); + + + __sync_lock_release(&val); + __sync_synchronize (); + + return old; +} diff --git a/test/CodeGen/attr-cleanup.c b/test/CodeGen/attr-cleanup.c new file mode 100644 index 000000000000..03dde3341e6c --- /dev/null +++ b/test/CodeGen/attr-cleanup.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +// <rdar://problem/6827047> +void f(void* arg); +void g() { + __attribute__((cleanup(f))) void *g; +} + diff --git a/test/CodeGen/attr-nodebug.c b/test/CodeGen/attr-nodebug.c new file mode 100644 index 000000000000..b96ad26d6d04 --- /dev/null +++ b/test/CodeGen/attr-nodebug.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -g -emit-llvm -o %t %s && +// RUN: not grep 'call void @llvm.dbg.func.start' %t + +void t1() __attribute__((nodebug)); + +void t1() +{ + int a = 10; + + a++; +} + diff --git a/test/CodeGen/attr-noinline.c b/test/CodeGen/attr-noinline.c new file mode 100644 index 000000000000..199c2918d425 --- /dev/null +++ b/test/CodeGen/attr-noinline.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -g -emit-llvm -o %t %s && +// RUN: grep 'noinline' %t + +void t1() __attribute__((noinline)); + +void t1() +{ +} + diff --git a/test/CodeGen/attr-used.c b/test/CodeGen/attr-used.c new file mode 100644 index 000000000000..8521ffd2e4bb --- /dev/null +++ b/test/CodeGen/attr-used.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -emit-llvm -o %t %s && +// RUN: grep '@llvm.used = .*@g0' %t && +// RUN: grep '@llvm.used = .*@f0' %t && +// RUN: grep '@llvm.used = .*@f1.l0' %t + + +int g0 __attribute__((used)); + +static void __attribute__((used)) f0(void) { +} + +void f1() { + static int l0 __attribute__((used)) = 5225; +} diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c new file mode 100644 index 000000000000..d45d5124b010 --- /dev/null +++ b/test/CodeGen/attributes.c @@ -0,0 +1,59 @@ +// RUN: clang-cc -emit-llvm -o %t %s && +// RUN: grep 't1.*noreturn' %t && +// RUN: grep 't2.*nounwind' %t && +// RUN: grep 'weak.*t3' %t && +// RUN: grep 'hidden.*t4' %t && +// RUN: grep 't5.*weak' %t && +// RUN: grep 't6.*protected' %t && +// RUN: grep 't7.*noreturn' %t && +// RUN: grep 't7.*nounwind' %t && +// RUN: grep 't9.*alias.*weak.*t8' %t && +// RUN: grep '@t10().*section "SECT"' %t && +// RUN: grep '@t11().*section "SECT"' %t && +// RUN: grep '@t12 =.*section "SECT"' %t && +// RUN: grep '@t13 =.*section "SECT"' %t && +// RUN: grep '@t14.x =.*section "SECT"' %t +// RUN: grep 'declare extern_weak i32 @t15()' %t && +// RUN: grep '@t16 = extern_weak global i32' %t + +void t1() __attribute__((noreturn)); +void t1() {} + +void t2() __attribute__((nothrow)); +void t2() {} + +void t3() __attribute__((weak)); +void t3() {} + +void t4() __attribute__((visibility("hidden"))); +void t4() {} + +int t5 __attribute__((weak)) = 2; + +int t6 __attribute__((visibility("protected"))); + +void t7() __attribute__((noreturn, nothrow)); +void t7() {} + +void __t8() {} +void t9() __attribute__((weak, alias("__t8"))); + +void t10(void) __attribute__((section("SECT"))); +void t10(void) {} +void __attribute__((section("SECT"))) t11(void) {} + +int t12 __attribute__((section("SECT"))); +struct s0 { int x; }; +struct s0 t13 __attribute__((section("SECT"))) = { 0 }; + +void t14(void) { + static int x __attribute__((section("SECT"))) = 0; +} + +int __attribute__((weak_import)) t15(void); +extern int t16 __attribute__((weak_import)); +int t17() { + return t15() + t16; +} + + diff --git a/test/CodeGen/bitfield-assign.c b/test/CodeGen/bitfield-assign.c new file mode 100644 index 000000000000..05d4dda353c7 --- /dev/null +++ b/test/CodeGen/bitfield-assign.c @@ -0,0 +1,44 @@ +/* Check that the result of a bitfield assignment is properly + truncated and does not generate a redundant load. */ + +/* Check that we get one load for each simple assign and two for the + compound assign (load the old value before the add then load again + to store back). Also check that our g0 pattern is good. */ +// RUN: clang-cc -triple i386-unknown-unknown -O0 -emit-llvm -o %t %s && +// RUN: grep 'load ' %t | count 5 && +// RUN: grep "@g0" %t | count 4 && + +// Check that we got the right value. +// RUN: clang-cc -triple i386-unknown-unknown -O3 -emit-llvm -o %t %s && +// RUN: grep 'load ' %t | count 0 && +// RUN: grep "@g0" %t | count 0 + +struct s0 { + int f0 : 2; + _Bool f1 : 1; + unsigned f2 : 2; +}; + +int g0(); + +void f0(void) { + struct s0 s; + if ((s.f0 = 3) != -1) g0(); +} + +void f1(void) { + struct s0 s; + if ((s.f1 = 3) != 1) g0(); +} + +void f2(void) { + struct s0 s; + if ((s.f2 = 3) != 3) g0(); +} + +void f3(void) { + struct s0 s; + // Just check this one for load counts. + s.f0 += 3; +} + diff --git a/test/CodeGen/bitfield-init.c b/test/CodeGen/bitfield-init.c new file mode 100644 index 000000000000..7459614a1254 --- /dev/null +++ b/test/CodeGen/bitfield-init.c @@ -0,0 +1,14 @@ +// RUN: clang-cc %s -emit-llvm -o %t +typedef struct { unsigned int i: 1; } c; +const c d = { 1 }; + +// PR2310 +struct Token { + unsigned n : 31; +}; +void sqlite3CodeSubselect(){ + struct Token one = { 1 }; +} + +typedef union T0 { char field0 : 2; } T0; +T0 T0_values = { 0 }; diff --git a/test/CodeGen/bitfield-promote.c b/test/CodeGen/bitfield-promote.c new file mode 100644 index 000000000000..5894e51626da --- /dev/null +++ b/test/CodeGen/bitfield-promote.c @@ -0,0 +1,19 @@ +// RUN: clang -O3 -emit-llvm -S -o %t %s && +// RUN: grep 'ret i64 4294967292' %t | count 2 && +// RUN: grep 'ret i64 -4' %t | count 1 && +// RUN: true + +long long f0(void) { + struct { unsigned f0 : 32; } x = { 18 }; + return (long long) (x.f0 - (int) 22); +} + +long long f1(void) { + struct { unsigned f0 : 31; } x = { 18 }; + return (long long) (x.f0 - (int) 22); +} + +long long f2(void) { + struct { unsigned f0 ; } x = { 18 }; + return (long long) (x.f0 - (int) 22); +} diff --git a/test/CodeGen/bitfield.c b/test/CodeGen/bitfield.c new file mode 100644 index 000000000000..02f2de79f6bc --- /dev/null +++ b/test/CodeGen/bitfield.c @@ -0,0 +1,74 @@ +// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t -O3 && +// RUN: grep "ret i32" %t | count 4 && +// RUN: grep "ret i32 1" %t | count 4 + +static int f0(int n) { + struct s0 { + int a : 30; + int b : 2; + long long c : 31; + } x = { 0xdeadbeef, 0xdeadbeef, 0xdeadbeef }; + + x.a += n; + x.b += n; + x.c += n; + + return x.a + x.b + x.c; +} + +int g0(void) { + return f0(-1) + 44335655; +} + +static int f1(void) { + struct s1 { + int a:13; + char b; + unsigned short c:7; + } x; + + x.a = -40; + x.b = 10; + x.c = 15; + + return x.a + x.b + x.c; +} + +int g1(void) { + return f1() + 16; +} + +static int f2(void) { + struct s2 { + short a[3]; + int b : 15; + } x; + + x.a[0] = x.a[1] = x.a[2] = -40; + x.b = 10; + + return x.b; +} + +int g2(void) { + return f2() - 9; +} + +static int f3(int n) { + struct s3 { + unsigned a:16; + unsigned b:28 __attribute__ ((packed)); + } x = { 0xdeadbeef, 0xdeadbeef }; + struct s4 { + signed a:16; + signed b:28 __attribute__ ((packed)); + } y; + y.a = -0x56789abcL; + y.b = -0x56789abcL; + return ((y.a += x.a += n) + + (y.b += x.b += n)); +} + +int g3(void) { + return f3(20) + 130725747; +} diff --git a/test/CodeGen/blocks-1.c b/test/CodeGen/blocks-1.c new file mode 100644 index 000000000000..10498cb00495 --- /dev/null +++ b/test/CodeGen/blocks-1.c @@ -0,0 +1,78 @@ +// RUN: clang-cc %s -emit-llvm -o %t -fblocks && +// RUN: grep "_Block_object_dispose" %t | count 17 && +// RUN: grep "__copy_helper_block_" %t | count 16 && +// RUN: grep "__destroy_helper_block_" %t | count 16 && +// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 && +// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 && +// RUN: grep "i32 135)" %t | count 2 && +// RUN: grep "_Block_object_assign" %t | count 10 + +#include <stdio.h> + +void test1() { + __block int a; + int b=2; + a=1; + printf("a is %d, b is %d\n", a, b); + ^{ a = 10; printf("a is %d, b is %d\n", a, b); }(); + printf("a is %d, b is %d\n", a, b); + a = 1; + printf("a is %d, b is %d\n", a, b); +} + +void test2() { + __block int a; + a=1; + printf("a is %d\n", a); + ^{ + ^{ + a = 10; + }(); + }(); + printf("a is %d\n", a); + a = 1; + printf("a is %d\n", a); +} + +void test3() { + __block int k; + __block int (^j)(int); + ^{j=0; k=0;}(); +} + +int test4() { + extern int g; + static int i = 1; + ^(int j){ i = j; g = 0; }(0); + return i + g; +} + +int g; + +void test5() { + __block struct { int i; } i; + ^{ (void)i; }(); +} + +void test6() { + __block int i; + ^{ i=1; }(); + ^{}(); +} + +void test7() { + ^{ + __block int i; + ^{ i = 1; }(); + }(); +} + +int main() { + int rv = 0; + test1(); + test2(); + test3(); + rv += test4(); + test5(); + return rv; +} diff --git a/test/CodeGen/blocks-2.c b/test/CodeGen/blocks-2.c new file mode 100644 index 000000000000..5ee2a73a82c9 --- /dev/null +++ b/test/CodeGen/blocks-2.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -g %s -emit-llvm -o %t -fblocks +// RUN: grep "func.start" %t | count 4 +// 1 declaration, 1 bar, 1 test_block_dbg and 1 for the block. + +static __inline__ __attribute__((always_inline)) int bar(int va, int vb) { return (va == vb); } + +int test_block_dbg() { + extern int g; + static int i = 1; + ^(int j){ i = bar(3,4); }(0); + return i + g; +} + diff --git a/test/CodeGen/blocks-seq.c b/test/CodeGen/blocks-seq.c new file mode 100644 index 000000000000..f637fbc0782e --- /dev/null +++ b/test/CodeGen/blocks-seq.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -fblocks -triple x86_64-apple-darwin10 -emit-llvm -o %t %s && +// RUN: grep '%call = call i32 (...)\* @rhs()' %t | count 1 && +// If this fails, see about sliding %4, %5, %6 and %7... +// RUN: grep '%forwarding1 = getelementptr %0\* %i, i32 0, i32 1' %t | count 1 && +// RUN: grep '%4 = bitcast i8\*\* %forwarding1 to %0\*\*' %t | count 1 && +// RUN: grep '%5 = load %0\*\* %4' %t | count 1 && +// RUN: grep '%call2 = call i32 (...)\* @rhs()' %t | count 1 && +// RUN: grep '%forwarding3 = getelementptr %0\* %i, i32 0, i32 1' %t | count 1 && +// RUN: grep '%6 = bitcast i8\*\* %forwarding3 to %0\*\*' %t | count 1 && +// RUN: grep '%7 = load %0\*\* %6' %t | count 1 + +int rhs(); + +void foo() { + __block int i; + i = rhs(); + i += rhs(); +} diff --git a/test/CodeGen/blocks.c b/test/CodeGen/blocks.c new file mode 100644 index 000000000000..39c5b06b1727 --- /dev/null +++ b/test/CodeGen/blocks.c @@ -0,0 +1,30 @@ +// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o %t -fblocks && +void (^f)(void) = ^{}; + +// rdar://6768379 +int f0(int (^a0)()) { + return a0(1, 2, 3); +} + +// Verify that attributes on blocks are set correctly. +typedef struct s0 T; +struct s0 { + int a[64]; +}; + +// RUN: grep 'internal void @__f2_block_invoke_(.struct.s0\* noalias sret .*, .*, .* byval .*)' %t && +struct s0 f2(struct s0 a0) { + return ^(struct s0 a1){ return a1; }(a0); +} + +// This should not crash: rdar://6808051 +void *P = ^{ + void *Q = __func__; +}; + +void (^test1)(void) = ^(void) { + __block int i; + ^ { i = 1; }(); +}; + +// RUN: true diff --git a/test/CodeGen/bool-bitfield.c b/test/CodeGen/bool-bitfield.c new file mode 100644 index 000000000000..50990a47c285 --- /dev/null +++ b/test/CodeGen/bool-bitfield.c @@ -0,0 +1,54 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +// From GCC PR19331 +struct SysParams +{ + unsigned short tag; + unsigned short version; + unsigned int seqnum; + int contrast; + int igain_1, igain_2; + int oattn_1, oattn_2; + int max_out_vltg_1, max_out_vltg_2; + int max_mains_current; + int meters_mode; + int input_select; + _Bool input_parallelch2:1; + _Bool cliplmt_ch1:1; + _Bool cliplmt_ch2:1; + _Bool gate_ch1:1; + _Bool gate_ch2:1; + _Bool mute_ch1:1; + _Bool mute_ch2:1; + _Bool brownout:1; + _Bool power_on:1; + _Bool pwrup_mute:1; + _Bool keylock:1; + _Bool dsp_ch1:1; + _Bool dsp_ch2:1; + int dsp_preset; + long unlock_code; +}; +extern struct SysParams params; + +void foo(void *); +void kcmd_setParams(void) +{ + struct { + unsigned char igain_1; + unsigned char igain_2; + unsigned char max_out_vltg_1; + unsigned char max_out_vltg_2; + unsigned char max_imains; + unsigned char cliplmt_ch1:1; + unsigned char cliplmt_ch2:1; + unsigned char gate_ch1:1; + unsigned char gate_ch2:1; + } msg; + foo(&msg); + params.cliplmt_ch1 = msg.cliplmt_ch1; + params.cliplmt_ch2 = msg.cliplmt_ch2; + params.gate_ch1 = msg.gate_ch1; + params.gate_ch2 = msg.gate_ch2; +} + diff --git a/test/CodeGen/bool-convert.c b/test/CodeGen/bool-convert.c new file mode 100644 index 000000000000..4df81bb82d7c --- /dev/null +++ b/test/CodeGen/bool-convert.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm < %s | grep i1 | count 1 +// All of these should uses the memory representation of _Bool +struct teststruct1 {_Bool a, b;} test1; +_Bool* test2; +_Bool test3[10]; +_Bool (*test4)[]; +void f(int x) { + _Bool test5; + _Bool test6[x]; +} diff --git a/test/CodeGen/bool-init.c b/test/CodeGen/bool-init.c new file mode 100644 index 000000000000..7d331ed07eb0 --- /dev/null +++ b/test/CodeGen/bool-init.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm < %s | grep i1 | count 1 + +// Check that the type of this global isn't i1 +_Bool test = &test; diff --git a/test/CodeGen/boolassign.c b/test/CodeGen/boolassign.c new file mode 100644 index 000000000000..2d14f8c1de19 --- /dev/null +++ b/test/CodeGen/boolassign.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +int testBoolAssign(void) { +int ss; +if ((ss = ss && ss)) {} +} diff --git a/test/CodeGen/builtin-count-zeros.c b/test/CodeGen/builtin-count-zeros.c new file mode 100644 index 000000000000..374acc43ae58 --- /dev/null +++ b/test/CodeGen/builtin-count-zeros.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm %s -o - | grep 'cttz' | count 2 && +// RUN: clang-cc -emit-llvm %s -o - | grep 'ctlz' | count 2 + +int a(int a) {return __builtin_ctz(a) + __builtin_clz(a);} diff --git a/test/CodeGen/builtin-memfns.c b/test/CodeGen/builtin-memfns.c new file mode 100644 index 000000000000..9ae380c5455b --- /dev/null +++ b/test/CodeGen/builtin-memfns.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s && +// RUN: grep '@llvm.memset.i32' %t && +// RUN: grep '@llvm.memcpy.i32' %t && +// RUN: grep '@llvm.memmove.i32' %t && +// RUN: grep __builtin %t | count 0 + +int main(int argc, char **argv) { + unsigned char a = 0x11223344; + unsigned char b = 0x11223344; + __builtin_bzero(&a, sizeof(a)); + __builtin_memset(&a, 0, sizeof(a)); + __builtin_memcpy(&a, &b, sizeof(a)); + __builtin_memmove(&a, &b, sizeof(a)); + return 0; +} diff --git a/test/CodeGen/builtin-nanf.c b/test/CodeGen/builtin-nanf.c new file mode 100644 index 000000000000..e048c7a1aa5a --- /dev/null +++ b/test/CodeGen/builtin-nanf.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s && +// RUN: grep 'float 0x7FF8000000000000, float 0x7FF8000000000000, float 0x7FF8000020000000, float 0x7FF8000000000000, float 0x7FF80001E0000000, float 0x7FF8001E00000000, float 0x7FF801E000000000, float 0x7FF81E0000000000, float 0x7FF9E00000000000, float 0x7FFFFFFFE0000000' %t + +float n[] = { + __builtin_nanf("0"), + __builtin_nanf(""), + __builtin_nanf("1"), + __builtin_nanf("0x7fc00000"), + __builtin_nanf("0x7fc0000f"), + __builtin_nanf("0x7fc000f0"), + __builtin_nanf("0x7fc00f00"), + __builtin_nanf("0x7fc0f000"), + __builtin_nanf("0x7fcf0000"), + __builtin_nanf("0xffffffff"), +}; diff --git a/test/CodeGen/builtin-rename.c b/test/CodeGen/builtin-rename.c new file mode 100644 index 000000000000..d0b5c2472de6 --- /dev/null +++ b/test/CodeGen/builtin-rename.c @@ -0,0 +1,8 @@ +// RUN: clang-cc %s -emit-llvm -o - | grep 'declare.*printf' | count 1 +// PR3612 + +int printf(const char *, ...); + +int foo(void) { + return printf(printf); +} diff --git a/test/CodeGen/builtin-stackaddress.c b/test/CodeGen/builtin-stackaddress.c new file mode 100644 index 000000000000..5c6d540172a0 --- /dev/null +++ b/test/CodeGen/builtin-stackaddress.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -emit-llvm < %s | grep "llvm.returnaddress" && +// RUN: clang-cc -emit-llvm < %s | grep "llvm.frameaddress" +void* a(unsigned x) { +return __builtin_return_address(0); +} + +void* c(unsigned x) { +return __builtin_frame_address(0); +} diff --git a/test/CodeGen/builtin-unwind-init.c b/test/CodeGen/builtin-unwind-init.c new file mode 100644 index 000000000000..49a016a304f0 --- /dev/null +++ b/test/CodeGen/builtin-unwind-init.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm < %s -o - | grep -F "llvm.eh.unwind.init" + +int a() { __builtin_unwind_init(); } + diff --git a/test/CodeGen/builtinmemcpy.c b/test/CodeGen/builtinmemcpy.c new file mode 100644 index 000000000000..d1fdebbe8287 --- /dev/null +++ b/test/CodeGen/builtinmemcpy.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -emit-llvm < %s -o - | grep "llvm.memcpy" + +char* x(char* a, char* b) {return __builtin_memcpy(a, b, 4);} diff --git a/test/CodeGen/builtins-ffs_parity_popcount.c b/test/CodeGen/builtins-ffs_parity_popcount.c new file mode 100644 index 000000000000..47469985eeda --- /dev/null +++ b/test/CodeGen/builtins-ffs_parity_popcount.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -emit-llvm -o - %s > %t +// RUN: ! grep "__builtin" %t + +#include <stdio.h> + +void test(int M, long long N) { + printf("%d %lld: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", + M, N, + __builtin_ffs(M), __builtin_ffsl(M), __builtin_ffsll(M), + __builtin_parity(M), __builtin_parityl(M), __builtin_parityll(M), + __builtin_popcount(M), __builtin_popcountl(M), __builtin_popcountll(M), + __builtin_ffs(N), __builtin_ffsl(N), __builtin_ffsll(N), + __builtin_parity(N), __builtin_parityl(N), __builtin_parityll(N), + __builtin_popcount(N), __builtin_popcountl(N), __builtin_popcountll(N)); +} diff --git a/test/CodeGen/builtins-powi.c b/test/CodeGen/builtins-powi.c new file mode 100644 index 000000000000..73f752f5e80e --- /dev/null +++ b/test/CodeGen/builtins-powi.c @@ -0,0 +1,29 @@ +// RUN: clang-cc -emit-llvm -o - %s > %t +// RUN: ! grep "__builtin" %t + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + +void test(long double a, int b) { + printf("%Lf**%d: %08x %08x %016Lx\n", + a, b, + __builtin_powi(a, b), + __builtin_powif(a, b), + __builtin_powil(a, b) + ); +} + +int main() { + int i; + + test(-1,-1LL); + test(0,0); + test(1,1); + + for (i=0; i<3; i++) { + test(random(), i); + } + + return 0; +} diff --git a/test/CodeGen/builtins-x86.c b/test/CodeGen/builtins-x86.c new file mode 100644 index 000000000000..33ab36074fe0 --- /dev/null +++ b/test/CodeGen/builtins-x86.c @@ -0,0 +1,522 @@ +// RUN: clang-cc -DUSE_64 -triple x86_64-unknown-unknown -emit-llvm -o %t %s && +// RUN: clang-cc -DUSE_ALL -triple x86_64-unknown-unknown -fsyntax-only -o %t %s + +#ifdef USE_ALL +#define USE_3DNOW +#define USE_64 +#define USE_SSE4 +#endif + +// 64-bit +typedef char V8c __attribute__((vector_size(8 * sizeof(char)))); +typedef signed short V4s __attribute__((vector_size(8))); +typedef signed int V2i __attribute__((vector_size(8))); +typedef signed long long V1LLi __attribute__((vector_size(8))); + +typedef float V2f __attribute__((vector_size(8))); + +// 128-bit +typedef char V16c __attribute__((vector_size(16))); +typedef signed short V8s __attribute__((vector_size(16))); +typedef signed int V4i __attribute__((vector_size(16))); +typedef signed long long V2LLi __attribute__((vector_size(16))); + +typedef float V4f __attribute__((vector_size(16))); +typedef double V2d __attribute__((vector_size(16))); + +void f0() { + signed char tmp_c; +// unsigned char tmp_Uc; + signed short tmp_s; +#ifdef USE_ALL + unsigned short tmp_Us; +#endif + signed int tmp_i; + unsigned int tmp_Ui; + signed long long tmp_LLi; +// unsigned long long tmp_ULLi; + float tmp_f; + double tmp_d; + + void* tmp_vp; + const void* tmp_vCp; + char* tmp_cp; + const char* tmp_cCp; + int* tmp_ip; + float* tmp_fp; + const float* tmp_fCp; + double* tmp_dp; + const double* tmp_dCp; + +#define imm_i 32 +#define imm_i_0_2 0 +#define imm_i_0_4 3 +#define imm_i_0_8 7 +#define imm_i_0_16 15 + // Check this. +#define imm_i_0_256 0 + + V2i* tmp_V2ip; + V1LLi* tmp_V1LLip; + V2LLi* tmp_V2LLip; + + // 64-bit + V8c tmp_V8c; + V4s tmp_V4s; + V2i tmp_V2i; + V1LLi tmp_V1LLi; +#ifdef USE_3DNOW + V2f tmp_V2f; +#endif + + // 128-bit + V16c tmp_V16c; + V8s tmp_V8s; + V4i tmp_V4i; + V2LLi tmp_V2LLi; + V4f tmp_V4f; + V2d tmp_V2d; + + tmp_i = __builtin_ia32_comieq(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_comilt(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_comile(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_comigt(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_comige(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_comineq(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_ucomieq(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_ucomilt(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_ucomile(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_ucomigt(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_ucomige(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_ucomineq(tmp_V4f, tmp_V4f); + tmp_i = __builtin_ia32_comisdeq(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_comisdlt(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_comisdle(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_comisdgt(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_comisdge(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_comisdneq(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_ucomisdeq(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_ucomisdlt(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_ucomisdle(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_ucomisdgt(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_ucomisdge(tmp_V2d, tmp_V2d); + tmp_i = __builtin_ia32_ucomisdneq(tmp_V2d, tmp_V2d); + tmp_V4f = __builtin_ia32_addps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_subps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_mulps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_divps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_addss(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_subss(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_mulss(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_divss(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_cmpps(tmp_V4f, tmp_V4f, 0); + tmp_V4f = __builtin_ia32_cmpps(tmp_V4f, tmp_V4f, 1); + tmp_V4f = __builtin_ia32_cmpps(tmp_V4f, tmp_V4f, 2); + tmp_V4f = __builtin_ia32_cmpps(tmp_V4f, tmp_V4f, 3); + tmp_V4f = __builtin_ia32_cmpps(tmp_V4f, tmp_V4f, 4); + tmp_V4f = __builtin_ia32_cmpps(tmp_V4f, tmp_V4f, 5); + tmp_V4f = __builtin_ia32_cmpps(tmp_V4f, tmp_V4f, 6); + tmp_V4f = __builtin_ia32_cmpps(tmp_V4f, tmp_V4f, 7); + tmp_V4f = __builtin_ia32_cmpss(tmp_V4f, tmp_V4f, 0); + tmp_V4f = __builtin_ia32_cmpss(tmp_V4f, tmp_V4f, 1); + tmp_V4f = __builtin_ia32_cmpss(tmp_V4f, tmp_V4f, 2); + tmp_V4f = __builtin_ia32_cmpss(tmp_V4f, tmp_V4f, 3); + tmp_V4f = __builtin_ia32_cmpss(tmp_V4f, tmp_V4f, 4); + tmp_V4f = __builtin_ia32_cmpss(tmp_V4f, tmp_V4f, 5); + tmp_V4f = __builtin_ia32_cmpss(tmp_V4f, tmp_V4f, 6); + tmp_V4f = __builtin_ia32_cmpss(tmp_V4f, tmp_V4f, 7); + tmp_V4f = __builtin_ia32_minps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_maxps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_minss(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_maxss(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_andps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_andnps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_orps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_xorps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_movss(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_movhlps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_movlhps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_unpckhps(tmp_V4f, tmp_V4f); + tmp_V4f = __builtin_ia32_unpcklps(tmp_V4f, tmp_V4f); + tmp_V8c = __builtin_ia32_paddb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_paddw(tmp_V4s, tmp_V4s); + tmp_V2i = __builtin_ia32_paddd(tmp_V2i, tmp_V2i); + + tmp_V1LLi = __builtin_ia32_paddq(tmp_V1LLi, tmp_V1LLi); + tmp_V8c = __builtin_ia32_psubb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_psubw(tmp_V4s, tmp_V4s); + tmp_V2i = __builtin_ia32_psubd(tmp_V2i, tmp_V2i); + tmp_V1LLi = __builtin_ia32_psubq(tmp_V1LLi, tmp_V1LLi); + tmp_V8c = __builtin_ia32_paddsb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_paddsw(tmp_V4s, tmp_V4s); + tmp_V8c = __builtin_ia32_psubsb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_psubsw(tmp_V4s, tmp_V4s); + tmp_V8c = __builtin_ia32_paddusb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_paddusw(tmp_V4s, tmp_V4s); + tmp_V8c = __builtin_ia32_psubusb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_psubusw(tmp_V4s, tmp_V4s); + tmp_V4s = __builtin_ia32_pmullw(tmp_V4s, tmp_V4s); + tmp_V4s = __builtin_ia32_pmulhw(tmp_V4s, tmp_V4s); + tmp_V4s = __builtin_ia32_pmulhuw(tmp_V4s, tmp_V4s); + tmp_V1LLi = __builtin_ia32_pand(tmp_V1LLi, tmp_V1LLi); + tmp_V1LLi = __builtin_ia32_pandn(tmp_V1LLi, tmp_V1LLi); + tmp_V1LLi = __builtin_ia32_por(tmp_V1LLi, tmp_V1LLi); + tmp_V1LLi = __builtin_ia32_pxor(tmp_V1LLi, tmp_V1LLi); + tmp_V8c = __builtin_ia32_pavgb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_pavgw(tmp_V4s, tmp_V4s); + tmp_V8c = __builtin_ia32_pcmpeqb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_pcmpeqw(tmp_V4s, tmp_V4s); + tmp_V2i = __builtin_ia32_pcmpeqd(tmp_V2i, tmp_V2i); + tmp_V8c = __builtin_ia32_pcmpgtb(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_pcmpgtw(tmp_V4s, tmp_V4s); + tmp_V2i = __builtin_ia32_pcmpgtd(tmp_V2i, tmp_V2i); + tmp_V8c = __builtin_ia32_pmaxub(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_pmaxsw(tmp_V4s, tmp_V4s); + tmp_V8c = __builtin_ia32_pminub(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_pminsw(tmp_V4s, tmp_V4s); + tmp_V8c = __builtin_ia32_punpckhbw(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_punpckhwd(tmp_V4s, tmp_V4s); + tmp_V2i = __builtin_ia32_punpckhdq(tmp_V2i, tmp_V2i); + tmp_V8c = __builtin_ia32_punpcklbw(tmp_V8c, tmp_V8c); + tmp_V4s = __builtin_ia32_punpcklwd(tmp_V4s, tmp_V4s); + tmp_V2i = __builtin_ia32_punpckldq(tmp_V2i, tmp_V2i); + tmp_V2d = __builtin_ia32_addpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_subpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_mulpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_divpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_addsd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_subsd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_mulsd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_divsd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_cmppd(tmp_V2d, tmp_V2d, 0); + tmp_V2d = __builtin_ia32_cmppd(tmp_V2d, tmp_V2d, 1); + tmp_V2d = __builtin_ia32_cmppd(tmp_V2d, tmp_V2d, 2); + tmp_V2d = __builtin_ia32_cmppd(tmp_V2d, tmp_V2d, 3); + tmp_V2d = __builtin_ia32_cmppd(tmp_V2d, tmp_V2d, 4); + tmp_V2d = __builtin_ia32_cmppd(tmp_V2d, tmp_V2d, 5); + tmp_V2d = __builtin_ia32_cmppd(tmp_V2d, tmp_V2d, 6); + tmp_V2d = __builtin_ia32_cmppd(tmp_V2d, tmp_V2d, 7); + tmp_V2d = __builtin_ia32_cmpsd(tmp_V2d, tmp_V2d, 0); + tmp_V2d = __builtin_ia32_cmpsd(tmp_V2d, tmp_V2d, 1); + tmp_V2d = __builtin_ia32_cmpsd(tmp_V2d, tmp_V2d, 2); + tmp_V2d = __builtin_ia32_cmpsd(tmp_V2d, tmp_V2d, 3); + tmp_V2d = __builtin_ia32_cmpsd(tmp_V2d, tmp_V2d, 4); + tmp_V2d = __builtin_ia32_cmpsd(tmp_V2d, tmp_V2d, 5); + tmp_V2d = __builtin_ia32_cmpsd(tmp_V2d, tmp_V2d, 6); + tmp_V2d = __builtin_ia32_cmpsd(tmp_V2d, tmp_V2d, 7); + tmp_V2d = __builtin_ia32_minpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_maxpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_minsd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_maxsd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_andpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_andnpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_orpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_xorpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_movsd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_unpckhpd(tmp_V2d, tmp_V2d); + tmp_V2d = __builtin_ia32_unpcklpd(tmp_V2d, tmp_V2d); + tmp_V16c = __builtin_ia32_paddb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_paddw128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_paddd128(tmp_V4i, tmp_V4i); + tmp_V2LLi = __builtin_ia32_paddq128(tmp_V2LLi, tmp_V2LLi); + tmp_V16c = __builtin_ia32_psubb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_psubw128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_psubd128(tmp_V4i, tmp_V4i); + tmp_V2LLi = __builtin_ia32_psubq128(tmp_V2LLi, tmp_V2LLi); + tmp_V16c = __builtin_ia32_paddsb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_paddsw128(tmp_V8s, tmp_V8s); + tmp_V16c = __builtin_ia32_psubsb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_psubsw128(tmp_V8s, tmp_V8s); + tmp_V16c = __builtin_ia32_paddusb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_paddusw128(tmp_V8s, tmp_V8s); + tmp_V16c = __builtin_ia32_psubusb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_psubusw128(tmp_V8s, tmp_V8s); + tmp_V8s = __builtin_ia32_pmullw128(tmp_V8s, tmp_V8s); + tmp_V8s = __builtin_ia32_pmulhw128(tmp_V8s, tmp_V8s); + tmp_V2LLi = __builtin_ia32_pand128(tmp_V2LLi, tmp_V2LLi); + tmp_V2LLi = __builtin_ia32_pandn128(tmp_V2LLi, tmp_V2LLi); + tmp_V2LLi = __builtin_ia32_por128(tmp_V2LLi, tmp_V2LLi); + tmp_V2LLi = __builtin_ia32_pxor128(tmp_V2LLi, tmp_V2LLi); + tmp_V16c = __builtin_ia32_pavgb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_pavgw128(tmp_V8s, tmp_V8s); + tmp_V16c = __builtin_ia32_pcmpeqb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_pcmpeqw128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_pcmpeqd128(tmp_V4i, tmp_V4i); + tmp_V16c = __builtin_ia32_pcmpgtb128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_pcmpgtw128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_pcmpgtd128(tmp_V4i, tmp_V4i); + tmp_V16c = __builtin_ia32_pmaxub128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_pmaxsw128(tmp_V8s, tmp_V8s); + tmp_V16c = __builtin_ia32_pminub128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_pminsw128(tmp_V8s, tmp_V8s); + tmp_V16c = __builtin_ia32_punpckhbw128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_punpckhwd128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_punpckhdq128(tmp_V4i, tmp_V4i); + tmp_V2LLi = __builtin_ia32_punpckhqdq128(tmp_V2LLi, tmp_V2LLi); + tmp_V16c = __builtin_ia32_punpcklbw128(tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_punpcklwd128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_punpckldq128(tmp_V4i, tmp_V4i); + tmp_V2LLi = __builtin_ia32_punpcklqdq128(tmp_V2LLi, tmp_V2LLi); + tmp_V8s = __builtin_ia32_packsswb128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_packssdw128(tmp_V4i, tmp_V4i); + tmp_V8s = __builtin_ia32_packuswb128(tmp_V8s, tmp_V8s); + tmp_V8s = __builtin_ia32_pmulhuw128(tmp_V8s, tmp_V8s); + tmp_V4f = __builtin_ia32_addsubps(tmp_V4f, tmp_V4f); + tmp_V2d = __builtin_ia32_addsubpd(tmp_V2d, tmp_V2d); + tmp_V4f = __builtin_ia32_haddps(tmp_V4f, tmp_V4f); + tmp_V2d = __builtin_ia32_haddpd(tmp_V2d, tmp_V2d); + tmp_V4f = __builtin_ia32_hsubps(tmp_V4f, tmp_V4f); + tmp_V2d = __builtin_ia32_hsubpd(tmp_V2d, tmp_V2d); + tmp_V8s = __builtin_ia32_phaddw128(tmp_V8s, tmp_V8s); + tmp_V4s = __builtin_ia32_phaddw(tmp_V4s, tmp_V4s); + tmp_V4i = __builtin_ia32_phaddd128(tmp_V4i, tmp_V4i); + tmp_V2i = __builtin_ia32_phaddd(tmp_V2i, tmp_V2i); + tmp_V8s = __builtin_ia32_phaddsw128(tmp_V8s, tmp_V8s); + tmp_V4s = __builtin_ia32_phaddsw(tmp_V4s, tmp_V4s); + tmp_V8s = __builtin_ia32_phsubw128(tmp_V8s, tmp_V8s); + tmp_V4s = __builtin_ia32_phsubw(tmp_V4s, tmp_V4s); + tmp_V4i = __builtin_ia32_phsubd128(tmp_V4i, tmp_V4i); + tmp_V2i = __builtin_ia32_phsubd(tmp_V2i, tmp_V2i); + tmp_V8s = __builtin_ia32_phsubsw128(tmp_V8s, tmp_V8s); + tmp_V4s = __builtin_ia32_phsubsw(tmp_V4s, tmp_V4s); + tmp_V16c = __builtin_ia32_pmaddubsw128(tmp_V16c, tmp_V16c); + tmp_V8c = __builtin_ia32_pmaddubsw(tmp_V8c, tmp_V8c); + tmp_V8s = __builtin_ia32_pmulhrsw128(tmp_V8s, tmp_V8s); + tmp_V4s = __builtin_ia32_pmulhrsw(tmp_V4s, tmp_V4s); + tmp_V16c = __builtin_ia32_pshufb128(tmp_V16c, tmp_V16c); + tmp_V8c = __builtin_ia32_pshufb(tmp_V8c, tmp_V8c); + tmp_V16c = __builtin_ia32_psignb128(tmp_V16c, tmp_V16c); + tmp_V8c = __builtin_ia32_psignb(tmp_V8c, tmp_V8c); + tmp_V8s = __builtin_ia32_psignw128(tmp_V8s, tmp_V8s); + tmp_V4s = __builtin_ia32_psignw(tmp_V4s, tmp_V4s); + tmp_V4i = __builtin_ia32_psignd128(tmp_V4i, tmp_V4i); + tmp_V2i = __builtin_ia32_psignd(tmp_V2i, tmp_V2i); + tmp_V16c = __builtin_ia32_pabsb128(tmp_V16c); + tmp_V8c = __builtin_ia32_pabsb(tmp_V8c); + tmp_V8s = __builtin_ia32_pabsw128(tmp_V8s); + tmp_V4s = __builtin_ia32_pabsw(tmp_V4s); + tmp_V4i = __builtin_ia32_pabsd128(tmp_V4i); + tmp_V2i = __builtin_ia32_pabsd(tmp_V2i); + tmp_V4s = __builtin_ia32_psllw(tmp_V4s, tmp_V1LLi); + tmp_V2i = __builtin_ia32_pslld(tmp_V2i, tmp_V1LLi); + tmp_V1LLi = __builtin_ia32_psllq(tmp_V1LLi, tmp_V1LLi); + tmp_V4s = __builtin_ia32_psrlw(tmp_V4s, tmp_V1LLi); + tmp_V2i = __builtin_ia32_psrld(tmp_V2i, tmp_V1LLi); + tmp_V1LLi = __builtin_ia32_psrlq(tmp_V1LLi, tmp_V1LLi); + tmp_V4s = __builtin_ia32_psraw(tmp_V4s, tmp_V1LLi); + tmp_V2i = __builtin_ia32_psrad(tmp_V2i, tmp_V1LLi); +#ifdef USE_ALL + tmp_V4s = __builtin_ia32_pshufw(tmp_V4s, imm_i); +#endif + tmp_V2i = __builtin_ia32_pmaddwd(tmp_V4s, tmp_V4s); + tmp_V8c = __builtin_ia32_packsswb(tmp_V4s, tmp_V4s); + tmp_V4s = __builtin_ia32_packssdw(tmp_V2i, tmp_V2i); + tmp_V8c = __builtin_ia32_packuswb(tmp_V4s, tmp_V4s); + + (void) __builtin_ia32_ldmxcsr(tmp_Ui); + tmp_Ui = __builtin_ia32_stmxcsr(); + tmp_V4f = __builtin_ia32_cvtpi2ps(tmp_V4f, tmp_V2i); + tmp_V2i = __builtin_ia32_cvtps2pi(tmp_V4f); + tmp_V4f = __builtin_ia32_cvtsi2ss(tmp_V4f, tmp_i); +#ifdef USE_64 + tmp_V4f = __builtin_ia32_cvtsi642ss(tmp_V4f, tmp_LLi); +#endif + tmp_i = __builtin_ia32_cvtss2si(tmp_V4f); +#ifdef USE_64 + tmp_LLi = __builtin_ia32_cvtss2si64(tmp_V4f); +#endif + tmp_V2i = __builtin_ia32_cvttps2pi(tmp_V4f); + tmp_i = __builtin_ia32_cvttss2si(tmp_V4f); +#ifdef USE_64 + tmp_LLi = __builtin_ia32_cvttss2si64(tmp_V4f); +#endif + (void) __builtin_ia32_maskmovq(tmp_V8c, tmp_V8c, tmp_cp); + tmp_V4f = __builtin_ia32_loadups(tmp_fCp); + (void) __builtin_ia32_storeups(tmp_fp, tmp_V4f); + tmp_V4f = __builtin_ia32_loadhps(tmp_V4f, tmp_V2ip); + tmp_V4f = __builtin_ia32_loadlps(tmp_V4f, tmp_V2ip); + (void) __builtin_ia32_storehps(tmp_V2ip, tmp_V4f); + (void) __builtin_ia32_storelps(tmp_V2ip, tmp_V4f); + tmp_i = __builtin_ia32_movmskps(tmp_V4f); + tmp_i = __builtin_ia32_pmovmskb(tmp_V8c); + (void) __builtin_ia32_movntps(tmp_fp, tmp_V4f); + (void) __builtin_ia32_movntq(tmp_V1LLip, tmp_V1LLi); + (void) __builtin_ia32_sfence(); + + tmp_V4s = __builtin_ia32_psadbw(tmp_V8c, tmp_V8c); + tmp_V4f = __builtin_ia32_rcpps(tmp_V4f); + tmp_V4f = __builtin_ia32_rcpss(tmp_V4f); + tmp_V4f = __builtin_ia32_rsqrtps(tmp_V4f); + tmp_V4f = __builtin_ia32_rsqrtss(tmp_V4f); + tmp_V4f = __builtin_ia32_sqrtps(tmp_V4f); + tmp_V4f = __builtin_ia32_sqrtss(tmp_V4f); + tmp_V4f = __builtin_ia32_shufps(tmp_V4f, tmp_V4f, imm_i); +#ifdef USE_3DNOW + (void) __builtin_ia32_femms(); + tmp_V8c = __builtin_ia32_pavgusb(tmp_V8c, tmp_V8c); + tmp_V2i = __builtin_ia32_pf2id(tmp_V2f); + tmp_V2f = __builtin_ia32_pfacc(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfadd(tmp_V2f, tmp_V2f); + tmp_V2i = __builtin_ia32_pfcmpeq(tmp_V2f, tmp_V2f); + tmp_V2i = __builtin_ia32_pfcmpge(tmp_V2f, tmp_V2f); + tmp_V2i = __builtin_ia32_pfcmpgt(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfmax(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfmin(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfmul(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfrcp(tmp_V2f); + tmp_V2f = __builtin_ia32_pfrcpit1(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfrcpit2(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfrsqrt(tmp_V2f); + tmp_V2f = __builtin_ia32_pfrsqit1(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfsub(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfsubr(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pi2fd(tmp_V2i); + tmp_V4s = __builtin_ia32_pmulhrw(tmp_V4s, tmp_V4s); +#endif +#ifdef USE_3DNOWA + tmp_V2i = __builtin_ia32_pf2iw(tmp_V2f); + tmp_V2f = __builtin_ia32_pfnacc(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pfpnacc(tmp_V2f, tmp_V2f); + tmp_V2f = __builtin_ia32_pi2fw(tmp_V2i); + tmp_V2f = __builtin_ia32_pswapdsf(tmp_V2f); + tmp_V2i = __builtin_ia32_pswapdsi(tmp_V2i); +#endif + (void) __builtin_ia32_maskmovdqu(tmp_V16c, tmp_V16c, tmp_cp); + tmp_V2d = __builtin_ia32_loadupd(tmp_dCp); + (void) __builtin_ia32_storeupd(tmp_dp, tmp_V2d); + tmp_V2d = __builtin_ia32_loadhpd(tmp_V2d, tmp_dCp); + tmp_V2d = __builtin_ia32_loadlpd(tmp_V2d, tmp_dCp); + tmp_i = __builtin_ia32_movmskpd(tmp_V2d); + tmp_i = __builtin_ia32_pmovmskb128(tmp_V16c); + (void) __builtin_ia32_movnti(tmp_ip, tmp_i); + (void) __builtin_ia32_movntpd(tmp_dp, tmp_V2d); + (void) __builtin_ia32_movntdq(tmp_V2LLip, tmp_V2LLi); + tmp_V4i = __builtin_ia32_pshufd(tmp_V4i, imm_i); + tmp_V8s = __builtin_ia32_pshuflw(tmp_V8s, imm_i); + tmp_V8s = __builtin_ia32_pshufhw(tmp_V8s, imm_i); + tmp_V2LLi = __builtin_ia32_psadbw128(tmp_V16c, tmp_V16c); + tmp_V2d = __builtin_ia32_sqrtpd(tmp_V2d); + tmp_V2d = __builtin_ia32_sqrtsd(tmp_V2d); + tmp_V2d = __builtin_ia32_shufpd(tmp_V2d, tmp_V2d, imm_i); + tmp_V2d = __builtin_ia32_cvtdq2pd(tmp_V4i); + tmp_V4f = __builtin_ia32_cvtdq2ps(tmp_V4i); + tmp_V2LLi = __builtin_ia32_cvtpd2dq(tmp_V2d); + tmp_V2i = __builtin_ia32_cvtpd2pi(tmp_V2d); + tmp_V4f = __builtin_ia32_cvtpd2ps(tmp_V2d); + tmp_V4i = __builtin_ia32_cvttpd2dq(tmp_V2d); + tmp_V2i = __builtin_ia32_cvttpd2pi(tmp_V2d); + tmp_V2d = __builtin_ia32_cvtpi2pd(tmp_V2i); + tmp_i = __builtin_ia32_cvtsd2si(tmp_V2d); + tmp_i = __builtin_ia32_cvttsd2si(tmp_V2d); +#ifdef USE_64 + tmp_LLi = __builtin_ia32_cvtsd2si64(tmp_V2d); + tmp_LLi = __builtin_ia32_cvttsd2si64(tmp_V2d); +#endif + tmp_V4i = __builtin_ia32_cvtps2dq(tmp_V4f); + tmp_V2d = __builtin_ia32_cvtps2pd(tmp_V4f); + tmp_V4i = __builtin_ia32_cvttps2dq(tmp_V4f); + tmp_V2d = __builtin_ia32_cvtsi2sd(tmp_V2d, tmp_i); +#ifdef USE_64 + tmp_V2d = __builtin_ia32_cvtsi642sd(tmp_V2d, tmp_LLi); +#endif + tmp_V4f = __builtin_ia32_cvtsd2ss(tmp_V4f, tmp_V2d); + tmp_V2d = __builtin_ia32_cvtss2sd(tmp_V2d, tmp_V4f); + (void) __builtin_ia32_clflush(tmp_vCp); + (void) __builtin_ia32_lfence(); + (void) __builtin_ia32_mfence(); + tmp_V16c = __builtin_ia32_loaddqu(tmp_cCp); + (void) __builtin_ia32_storedqu(tmp_cp, tmp_V16c); + tmp_V4s = __builtin_ia32_psllwi(tmp_V4s, tmp_i); + tmp_V2i = __builtin_ia32_pslldi(tmp_V2i, tmp_i); + tmp_V1LLi = __builtin_ia32_psllqi(tmp_V1LLi, tmp_i); + tmp_V4s = __builtin_ia32_psrawi(tmp_V4s, tmp_i); + tmp_V2i = __builtin_ia32_psradi(tmp_V2i, tmp_i); + tmp_V4s = __builtin_ia32_psrlwi(tmp_V4s, tmp_i); + tmp_V2i = __builtin_ia32_psrldi(tmp_V2i, tmp_i); + tmp_V1LLi = __builtin_ia32_psrlqi(tmp_V1LLi, tmp_i); + tmp_V1LLi = __builtin_ia32_pmuludq(tmp_V2i, tmp_V2i); + tmp_V2LLi = __builtin_ia32_pmuludq128(tmp_V4i, tmp_V4i); + tmp_V8s = __builtin_ia32_psraw128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_psrad128(tmp_V4i, tmp_V4i); + tmp_V8s = __builtin_ia32_psrlw128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_psrld128(tmp_V4i, tmp_V4i); + tmp_V2LLi = __builtin_ia32_psrlq128(tmp_V2LLi, tmp_V2LLi); + tmp_V8s = __builtin_ia32_psllw128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_pslld128(tmp_V4i, tmp_V4i); + tmp_V2LLi = __builtin_ia32_psllq128(tmp_V2LLi, tmp_V2LLi); + tmp_V8s = __builtin_ia32_psllwi128(tmp_V8s, tmp_i); + tmp_V4i = __builtin_ia32_pslldi128(tmp_V4i, tmp_i); + tmp_V2LLi = __builtin_ia32_psllqi128(tmp_V2LLi, tmp_i); + tmp_V8s = __builtin_ia32_psrlwi128(tmp_V8s, tmp_i); + tmp_V4i = __builtin_ia32_psrldi128(tmp_V4i, tmp_i); + tmp_V2LLi = __builtin_ia32_psrlqi128(tmp_V2LLi, tmp_i); + tmp_V8s = __builtin_ia32_psrawi128(tmp_V8s, tmp_i); + tmp_V4i = __builtin_ia32_psradi128(tmp_V4i, tmp_i); + tmp_V8s = __builtin_ia32_pmaddwd128(tmp_V8s, tmp_V8s); + (void) __builtin_ia32_monitor(tmp_vp, tmp_Ui, tmp_Ui); + (void) __builtin_ia32_mwait(tmp_Ui, tmp_Ui); +#ifdef USE_ALL + tmp_V4f = __builtin_ia32_movshdup(tmp_V4f); + tmp_V4f = __builtin_ia32_movsldup(tmp_V4f); +#endif + tmp_V16c = __builtin_ia32_lddqu(tmp_cCp); + tmp_V2LLi = __builtin_ia32_palignr128(tmp_V2LLi, tmp_V2LLi, imm_i); + tmp_V1LLi = __builtin_ia32_palignr(tmp_V1LLi, tmp_V1LLi, imm_i); + tmp_V2i = __builtin_ia32_vec_init_v2si(tmp_i, tmp_i); + tmp_V4s = __builtin_ia32_vec_init_v4hi(tmp_s, tmp_s, tmp_s, tmp_s); + tmp_V8c = __builtin_ia32_vec_init_v8qi(tmp_c, tmp_c, tmp_c, tmp_c, tmp_c, tmp_c, tmp_c, tmp_c); + tmp_d = __builtin_ia32_vec_ext_v2df(tmp_V2d, imm_i_0_2); + tmp_LLi = __builtin_ia32_vec_ext_v2di(tmp_V2LLi, imm_i_0_2); + tmp_f = __builtin_ia32_vec_ext_v4sf(tmp_V4f, imm_i_0_4); + tmp_i = __builtin_ia32_vec_ext_v4si(tmp_V4i, imm_i_0_4); +#ifdef USE_ALL + tmp_Us = __builtin_ia32_vec_ext_v8hi(tmp_V8s, imm_i_0_8); + tmp_s = __builtin_ia32_vec_ext_v4hi(tmp_V4s, imm_i_0_4); +#endif + tmp_i = __builtin_ia32_vec_ext_v2si(tmp_V2i, imm_i_0_2); + tmp_V8s = __builtin_ia32_vec_set_v8hi(tmp_V8s, tmp_s, imm_i_0_8); + tmp_V4s = __builtin_ia32_vec_set_v4hi(tmp_V4s, tmp_s, imm_i_0_4); + tmp_V4i = __builtin_ia32_loadlv4si(tmp_V2ip); + (void) __builtin_ia32_storelv4si(tmp_V2ip, tmp_V2LLi); +#ifdef USE_SSE4 + tmp_V16c = __builtin_ia32_pblendvb128(tmp_V16c, tmp_V16c, tmp_V16c); + tmp_V8s = __builtin_ia32_pblendw128(tmp_V8s, tmp_V8s, imm_i_0_256); + tmp_V2d = __builtin_ia32_blendpd(tmp_V2d, tmp_V2d, imm_i_0_256); + tmp_V4f = __builtin_ia32_blendps(tmp_V4f, tmp_V4f, imm_i_0_256); + tmp_V2d = __builtin_ia32_blendvpd(tmp_V2d, tmp_V2d, tmp_V2d); + tmp_V4f = __builtin_ia32_blendvps(tmp_V4f, tmp_V4f, tmp_V4f); + tmp_V8s = __builtin_ia32_packusdw128(tmp_V4i, tmp_V4i); + tmp_V16c = __builtin_ia32_pmaxsb128(tmp_V16c, tmp_V16c); + tmp_V4i = __builtin_ia32_pmaxsd128(tmp_V4i, tmp_V4i); + tmp_V4i = __builtin_ia32_pmaxud128(tmp_V4i, tmp_V4i); + tmp_V8s = __builtin_ia32_pmaxuw128(tmp_V8s, tmp_V8s); + tmp_V16c = __builtin_ia32_pminsb128(tmp_V16c, tmp_V16c); + tmp_V4i = __builtin_ia32_pminsd128(tmp_V4i, tmp_V4i); + tmp_V4i = __builtin_ia32_pminud128(tmp_V4i, tmp_V4i); + tmp_V8s = __builtin_ia32_pminuw128(tmp_V8s, tmp_V8s); + tmp_V4i = __builtin_ia32_pmovsxbd128(tmp_V16c); + tmp_V2LLi = __builtin_ia32_pmovsxbq128(tmp_V16c); + tmp_V8s = __builtin_ia32_pmovsxbw128(tmp_V16c); + tmp_V2LLi = __builtin_ia32_pmovsxdq128(tmp_V4i); + tmp_V4i = __builtin_ia32_pmovsxwd128(tmp_V8s); + tmp_V2LLi = __builtin_ia32_pmovsxwq128(tmp_V8s); + tmp_V4i = __builtin_ia32_pmovzxbd128(tmp_V16c); + tmp_V2LLi = __builtin_ia32_pmovzxbq128(tmp_V16c); + tmp_V8s = __builtin_ia32_pmovzxbw128(tmp_V16c); + tmp_V2LLi = __builtin_ia32_pmovzxdq128(tmp_V4i); + tmp_V4i = __builtin_ia32_pmovzxwd128(tmp_V8s); + tmp_V2LLi = __builtin_ia32_pmovzxwq128(tmp_V8s); + tmp_V2LLi = __builtin_ia32_pmuldq128(tmp_V4i, tmp_V4i); + tmp_V4i = __builtin_ia32_pmulld128(tmp_V4i, tmp_V4i); + tmp_V4f = __builtin_ia32_roundps(tmp_V4f, imm_i_0_16); + // tmp_V4f = __builtin_ia32_roundss(tmp_V4f, tmp_V4f, imm_i_0_16); + // tmp_V2d = __builtin_ia32_roundsd(tmp_V2d, tmp_V2d, imm_i_0_16); + tmp_V2d = __builtin_ia32_roundpd(tmp_V2d, imm_i_0_16); + tmp_V16c = __builtin_ia32_vec_set_v16qi(tmp_V16c, tmp_i, tmp_i); + tmp_V4i = __builtin_ia32_vec_set_v4si(tmp_V4i, tmp_i, tmp_i); + tmp_V4f = __builtin_ia32_insertps128(tmp_V4f, tmp_V4f, tmp_i); + tmp_V2LLi = __builtin_ia32_vec_set_v2di(tmp_V2LLi, tmp_LLi, tmp_i); +#endif +} + + diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c new file mode 100644 index 000000000000..ce5cd74bd4c4 --- /dev/null +++ b/test/CodeGen/builtins.c @@ -0,0 +1,124 @@ +// RUN: clang-cc -emit-llvm -o %t %s && +// RUN: not grep __builtin %t + +#include <stdio.h> +#include <math.h> + +void p(char *str, int x) { + printf("%s: %d\n", str, x); +} +void q(char *str, double x) { + printf("%s: %f\n", str, x); +} + +int main() { + int N = random(); +#define P(n,args) p(#n #args, __builtin_##n args) +#define Q(n,args) q(#n #args, __builtin_##n args) +#define V(n,args) p(#n #args, (__builtin_##n args, 0)) + P(types_compatible_p, (int, float)); + P(choose_expr, (0, 10, 20)); + P(constant_p, (sizeof(10))); + P(expect, (N == 12, 0)); + V(prefetch, (&N)); + V(prefetch, (&N, 1)); + V(prefetch, (&N, 1, 0)); + + // Numeric Constants + + Q(huge_val, ()); + Q(huge_valf, ()); + Q(huge_vall, ()); + Q(inf, ()); + Q(inff, ()); + Q(infl, ()); + + // FIXME: + // XXX note funny semantics for the (last) argument + // P(fpclassify, (FP_NAN, FP_INFINITE, FP_NORMAL, FP_SUBNORMAL, FP_ZERO, 1.0)); + // P(isinf_sign, (1.0)); + + Q(nan, ("")); + Q(nanf, ("")); + Q(nanl, ("")); + Q(nans, ("")); + Q(nan, ("10")); + Q(nanf, ("10")); + Q(nanl, ("10")); + Q(nans, ("10")); + + P(isgreater, (1., 2.)); + P(isgreaterequal, (1., 2.)); + P(isless, (1., 2.)); + P(islessequal, (1., 2.)); + P(islessgreater, (1., 2.)); + P(isunordered, (1., 2.)); + + // Bitwise & Numeric Functions + + P(abs, (N)); + + P(clz, (N)); + P(clzl, (N)); + P(clzll, (N)); + P(ctz, (N)); + P(ctzl, (N)); + P(ctzll, (N)); + P(ffs, (N)); + P(ffsl, (N)); + P(ffsll, (N)); + P(parity, (N)); + P(parityl, (N)); + P(parityll, (N)); + P(popcount, (N)); + P(popcountl, (N)); + P(popcountll, (N)); + Q(powi, (1.2f, N)); + Q(powif, (1.2f, N)); + Q(powil, (1.2f, N)); + + // Lib functions + int a, b, n = random(); // Avoid optimizing out. + char s0[10], s1[] = "Hello"; + V(strcat, (s0, s1)); + V(strcmp, (s0, s1)); + V(strncat, (s0, s1, n)); + V(strchr, (s0, s1[0])); + V(strrchr, (s0, s1[0])); + V(strcpy, (s0, s1)); + V(strncpy, (s0, s1, n)); + + // Object size checking + V(__memset_chk, (s0, 0, sizeof s0, n)); + V(__memcpy_chk, (s0, s1, sizeof s0, n)); + V(__memmove_chk, (s0, s1, sizeof s0, n)); + V(__mempcpy_chk, (s0, s1, sizeof s0, n)); + V(__strncpy_chk, (s0, s1, sizeof s0, n)); + V(__strcpy_chk, (s0, s1, n)); + s0[0] = 0; + V(__strcat_chk, (s0, s1, n)); + P(object_size, (s0, 0)); + P(object_size, (s0, 1)); + P(object_size, (s0, 2)); + P(object_size, (s0, 3)); + + // Whatever + + P(bswap32, (N)); + P(bswap64, (N)); + // FIXME + // V(clear_cache, (&N, &N+1)); + V(trap, ()); + P(extract_return_addr, (&N)); + + return 0; +} + + + +void strcat() {} + +void foo() { + __builtin_strcat(0, 0); +} + diff --git a/test/CodeGen/builtinshufflevector.c b/test/CodeGen/builtinshufflevector.c new file mode 100644 index 000000000000..9a3ae610282e --- /dev/null +++ b/test/CodeGen/builtinshufflevector.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -emit-llvm < %s | grep 'shufflevector' | count 1 +typedef int v4si __attribute__ ((vector_size (16))); + +v4si a(v4si x, v4si y) {return __builtin_shufflevector(x, y, 3, 2, 5, 7);} + diff --git a/test/CodeGen/c-strings.c b/test/CodeGen/c-strings.c new file mode 100644 index 000000000000..ee85f60ed15a --- /dev/null +++ b/test/CodeGen/c-strings.c @@ -0,0 +1,36 @@ +// RUN: clang-cc -emit-llvm -o %t %s && +// RUN: grep "hello" %t | count 3 && +// RUN: grep 'c"hello\\00"' %t | count 2 && +// RUN: grep 'c"hello\\00\\00\\00"' %t | count 1 && +// RUN: grep 'c"ola"' %t | count 1 + +/* Should be 3 hello string, two global (of different sizes), the rest + are shared. */ + +void f0() { + bar("hello"); +} + +void f1() { + static char *x = "hello"; + bar(x); +} + +void f2() { + static char x[] = "hello"; + bar(x); +} + +void f3() { + static char x[8] = "hello"; + bar(x); +} + +void f4() { + static struct s { + char *name; + } x = { "hello" }; + gaz(&x); +} + +char x[3] = "ola"; diff --git a/test/CodeGen/cast-to-union.c b/test/CodeGen/cast-to-union.c new file mode 100644 index 000000000000..03aee3e30c4f --- /dev/null +++ b/test/CodeGen/cast-to-union.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -emit-llvm < %s -o %t && +// RUN: grep "store i32 351, i32*" %t && +// RUN: grep "w = global %0 <{ i32 2, i8 0, i8 0, i8 0, i8 0 }>" %t && +// RUN: grep "y = global %1 <{ double 7.300000e+01 }>" %t + +union u { int i; double d; }; + +void foo() { + union u ola = (union u) 351; +} + +union u w = (union u)2; +union u y = (union u)73.0; diff --git a/test/CodeGen/cast.c b/test/CodeGen/cast.c new file mode 100644 index 000000000000..6fb2b116d47b --- /dev/null +++ b/test/CodeGen/cast.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +extern void go(const void *p); +float v[2] = { 0.0, 1.0 }; +void foo(void) { go(v); } + diff --git a/test/CodeGen/cfstring.c b/test/CodeGen/cfstring.c new file mode 100644 index 000000000000..a78dfdaf6502 --- /dev/null +++ b/test/CodeGen/cfstring.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -emit-llvm %s -o %t +#define CFSTR __builtin___CFStringMakeConstantString + +void f() { + CFSTR("Hello, World!"); +} + +// rdar://6248329 +void *G = CFSTR("yo joe"); + +void h() { + static void* h = CFSTR("Goodbye, World!"); +} diff --git a/test/CodeGen/cfstring2.c b/test/CodeGen/cfstring2.c new file mode 100644 index 000000000000..ceefeb9e832c --- /dev/null +++ b/test/CodeGen/cfstring2.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +typedef const struct __CFString * CFStringRef; + +#define CFSTR(x) (CFStringRef) __builtin___CFStringMakeConstantString (x) + +void f() { + CFSTR("Hello, World!"); +} + +// rdar://6151192 +void *G = CFSTR("yo joe"); + diff --git a/test/CodeGen/cleanup-stack.c b/test/CodeGen/cleanup-stack.c new file mode 100644 index 000000000000..b0c5e88d55ec --- /dev/null +++ b/test/CodeGen/cleanup-stack.c @@ -0,0 +1,25 @@ +// RUN: clang-cc -triple i386-unknown-unknown -O3 -emit-llvm %s -o %t && +// RUN: grep "ret i32 9" %t + +struct s0 { + int *var; + int addend; +}; + +static void f0(struct s0 *p) { + *p->var += p->addend; +} + +int f1(void) { + int var = 0; + + { + struct s0 x __attribute__((cleanup(f0))) = { &var, 2 }; + struct s0 y __attribute__((cleanup(f0))) = { &var, 3 }; + { + struct s0 y __attribute__((cleanup(f0))) = { &var, 4 }; + } + } + + return var; +} diff --git a/test/CodeGen/complex.c b/test/CodeGen/complex.c new file mode 100644 index 000000000000..6a0d3d628c54 --- /dev/null +++ b/test/CodeGen/complex.c @@ -0,0 +1,61 @@ +// RUN: clang-cc -emit-llvm < %s + +int main(void) +{ + double _Complex a = 5; + double _Complex b = 42; + + return a * b != b * a; +} + +_Complex double bar(int); +void test(_Complex double*); +void takecomplex(_Complex double); + +void test2(int c) { + _Complex double X; + X = bar(1); + test(&X); + takecomplex(X); +} + +_Complex double g1, g2; +_Complex float cf; +double D; + +void test3() { + g1 = g1 + g2; + g1 = g1 - g2; + g1 = g1 * g2; + g1 = +-~g1; + + double Gr = __real g1; + + cf += D; + // FIXME: Currently unsupported! + //D += cf; + cf /= g1; + g1 = g1 + D; + g1 = D + g1; +} + +void t1() { + (__real__ cf) = 4.0; +} + +void t2() { + (__imag__ cf) = 4.0; +} + +// PR1960 +void t3() { + __complex__ long long v = 2; +} + +// PR3131 +float _Complex t4(); + +void t5() { + float _Complex x = t4(); +} + diff --git a/test/CodeGen/compound-literal.c b/test/CodeGen/compound-literal.c new file mode 100644 index 000000000000..ef0436744dae --- /dev/null +++ b/test/CodeGen/compound-literal.c @@ -0,0 +1,12 @@ +// RUN: clang-cc < %s -emit-llvm + +int* a = &(int){1}; +struct s {int a, b, c;} * b = &(struct s) {1, 2, 3}; +// Not working; complex constants are broken +// _Complex double * x = &(_Complex double){1.0f}; + +int xxx() { +int* a = &(int){1}; +struct s {int a, b, c;} * b = &(struct s) {1, 2, 3}; +_Complex double * x = &(_Complex double){1.0f}; +} diff --git a/test/CodeGen/compound-type.c b/test/CodeGen/compound-type.c new file mode 100644 index 000000000000..352f6cc3ce65 --- /dev/null +++ b/test/CodeGen/compound-type.c @@ -0,0 +1,7 @@ +// RUN: clang-cc < %s -emit-llvm -triple i686-pc-linux-gnu > %t && +// RUN: grep "div i32" %t && +// RUN: grep "shl i32" %t + +unsigned char a,b; +void c(void) {a <<= b;} +void d(void) {a /= b;} diff --git a/test/CodeGen/compound.c b/test/CodeGen/compound.c new file mode 100644 index 000000000000..c54600705330 --- /dev/null +++ b/test/CodeGen/compound.c @@ -0,0 +1,25 @@ +// RUN: clang-cc < %s -emit-llvm +int A; +long long B; +int C; +int *P; +void test1() { + C = (A /= B); + + P -= 4; + + C = P - (P+10); +} + +short x; +void test2(char c) { x += c; } + +void foo(char *strbuf) { + int stufflen = 4; + strbuf += stufflen; +} + + +// Aggregate cast to void +union uu { int a;}; void f(union uu p) { (void) p;} + diff --git a/test/CodeGen/conditional-gnu-ext.c b/test/CodeGen/conditional-gnu-ext.c new file mode 100644 index 000000000000..1483d8af8592 --- /dev/null +++ b/test/CodeGen/conditional-gnu-ext.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -emit-llvm %s -o %t +// PR1824 + +int foo(int x, short y) { + return x ?: y; +} + +// rdar://6586493 +float test(float x, int Y) { + return Y != 0 ? : x; +} + diff --git a/test/CodeGen/conditional.c b/test/CodeGen/conditional.c new file mode 100644 index 000000000000..22286705c89c --- /dev/null +++ b/test/CodeGen/conditional.c @@ -0,0 +1,44 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +float test1(int cond, float a, float b) +{ + return cond ? a : b; +} +double test2(int cond, float a, double b) +{ + return cond ? a : b; +} + +void f(); + +void test3(){ + 1 ? f() : (void)0; +} + +void test4() { +int i; short j; +float* k = 1 ? &i : &j; +} + +void test5() { + const int* cip; + void* vp; + cip = 0 ? vp : cip; +} + +void test6(); +void test7(int); +void* test8() {return 1 ? test6 : test7;} + + +void _efree(void *ptr); + +void _php_stream_free3() +{ + (1 ? free(0) : _efree(0)); +} + +void _php_stream_free4() +{ + 1 ? _efree(0) : free(0); +} diff --git a/test/CodeGen/const-init.c b/test/CodeGen/const-init.c new file mode 100644 index 000000000000..0364cc153ff8 --- /dev/null +++ b/test/CodeGen/const-init.c @@ -0,0 +1,104 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -verify -emit-llvm -o %t %s && + +#include <stdint.h> + +// Brace-enclosed string array initializers +char a[] = { "asdf" }; + +// Double-implicit-conversions of array/functions (not legal C, but +// clang accepts it for gcc compat). +intptr_t b = a; // expected-warning {{incompatible pointer to integer conversion}} +int c(); +void *d = c; +intptr_t e = c; // expected-warning {{incompatible pointer to integer conversion}} + +int f, *g = __extension__ &f, *h = (1 != 1) ? &f : &f; + +union s2 { + struct { + struct { } *f0; + } f0; +}; + +int g0 = (int)(&(((union s2 *) 0)->f0.f0) - 0); + +// RUN: grep '@g1x = global %. { double 1.000000e+00, double 0.000000e+00 }' %t && +_Complex double g1x = 1.0f; +// RUN: grep '@g1y = global %. { double 0.000000e+00, double 1.000000e+00 }' %t && +_Complex double g1y = 1.0fi; +// RUN: grep '@g1 = global %. { i8 1, i8 10 }' %t && +_Complex char g1 = (char) 1 + (char) 10 * 1i; +// RUN: grep '@g2 = global %2 { i32 1, i32 10 }' %t && +_Complex int g2 = 1 + 10i; +// RUN: grep '@g3 = global %. { float 1.000000e+00, float 1.000000e+01 }' %t && +_Complex float g3 = 1.0 + 10.0i; +// RUN: grep '@g4 = global %. { double 1.000000e+00, double 1.000000e+01 }' %t && +_Complex double g4 = 1.0 + 10.0i; +// RUN: grep '@g5 = global %2 zeroinitializer' %t && +_Complex int g5 = (2 + 3i) == (5 + 7i); +// RUN: grep '@g6 = global %. { double -1.100000e+01, double 2.900000e+01 }' %t && +_Complex double g6 = (2.0 + 3.0i) * (5.0 + 7.0i); +// RUN: grep '@g7 = global i32 1' %t && +int g7 = (2 + 3i) * (5 + 7i) == (-11 + 29i); +// RUN: grep '@g8 = global i32 1' %t && +int g8 = (2.0 + 3.0i) * (5.0 + 7.0i) == (-11.0 + 29.0i); +// RUN: grep '@g9 = global i32 0' %t && +int g9 = (2 + 3i) * (5 + 7i) != (-11 + 29i); +// RUN: grep '@g10 = global i32 0' %t && +int g10 = (2.0 + 3.0i) * (5.0 + 7.0i) != (-11.0 + 29.0i); + + +// Global references +// RUN: grep '@g11.l0 = internal global i32 ptrtoint (i32 ()\* @g11 to i32)' %t && +long g11() { + static long l0 = (long) g11; + return l0; +} + +// RUN: grep '@g12 = global i32 ptrtoint (i8\* @g12_tmp to i32)' %t && +static char g12_tmp; +long g12 = (long) &g12_tmp; + +// RUN: grep '@g13 = global \[1 x .struct.g13_s0\] \[.struct.g13_s0 <{ i32 ptrtoint (i8\* @g12_tmp to i32) }>\]' %t && +struct g13_s0 { + long a; +}; +struct g13_s0 g13[] = { + { (long) &g12_tmp } +}; + +// RUN: grep '@g14 = global i8\* inttoptr (i64 100 to i8\*)' %t && +void *g14 = (void*) 100; + +// RUN: grep '@g15 = global i32 -1' %t && +int g15 = (int) (char) ((void*) 0 + 255); + +// RUN: grep '@g16 = global i64 4294967295' %t && +long long g16 = (long long) ((void*) 0xFFFFFFFF); + +// RUN: grep '@g17 = global i32\* @g15' %t && +int *g17 = (int *) ((long) &g15); + +// RUN: grep '@g18.p = internal global \[1 x i32\*\] \[i32\* @g19\]' %t && +void g18(void) { + extern int g19; + static int *p[] = { &g19 }; +} + +// RUN: grep '@g20.l0 = internal global .struct.g20_s1 <{ .struct.g20_s0\* null, .struct.g20_s0\*\* getelementptr (.struct.g20_s1\* @g20.l0, i32 0, i32 0) }>' %t && + +struct g20_s0; +struct g20_s1 { + struct g20_s0 *f0, **f1; +}; +void *g20(void) { + static struct g20_s1 l0 = { ((void*) 0), &l0.f0 }; + return l0.f1; +} + +// PR4108 +struct g21 {int g21;}; +const struct g21 g21 = (struct g21){1}; + +// RUN: true + diff --git a/test/CodeGen/const-label-addr.c b/test/CodeGen/const-label-addr.c new file mode 100644 index 000000000000..f8c35c676783 --- /dev/null +++ b/test/CodeGen/const-label-addr.c @@ -0,0 +1,4 @@ +// RUN: clang-cc %s -emit-llvm -o %t +int a() { +A:;static void* a = &&A; +} diff --git a/test/CodeGen/constant-comparison.c b/test/CodeGen/constant-comparison.c new file mode 100644 index 000000000000..ea3e8962b333 --- /dev/null +++ b/test/CodeGen/constant-comparison.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -emit-llvm %s -o - 2>&1 | not grep warning && +// RUN: clang-cc -emit-llvm %s -o - | grep @b | count 1 + +int a, b; +int *c1 = 1 < 2 ? &a : &b; +int *c2 = 3 != 3LL ? &b : &a; +int *c3 = !(3 <= 4.0) ? &b : &a; +int *c4 = &a - (6 * 5 > 30); +int *c5 = &a + (6 * 5 >= 30); +int c6 = 44 < 33; + + diff --git a/test/CodeGen/constructor-attribute.c b/test/CodeGen/constructor-attribute.c new file mode 100644 index 000000000000..9a1fa76c622a --- /dev/null +++ b/test/CodeGen/constructor-attribute.c @@ -0,0 +1,38 @@ +// RUN: clang-cc -emit-llvm -o %t %s && +// RUN: grep -e "global_ctors.*@A" %t && +// RUN: grep -e "global_dtors.*@B" %t && +// RUN: grep -e "global_ctors.*@C" %t && +// RUN: grep -e "global_dtors.*@D" %t + +#include <stdio.h> + +void A() __attribute__((constructor)); +void B() __attribute__((destructor)); + +void A() { + printf("A\n"); +} + +void B() { + printf("B\n"); +} + +static void C() __attribute__((constructor)); + +static void D() __attribute__((destructor)); + +static int foo() { + return 10; +} + +static void C() { + printf("A: %d\n", foo()); +} + +static void D() { + printf("B\n"); +} + +int main() { + return 0; +} diff --git a/test/CodeGen/cxx-condition.cpp b/test/CodeGen/cxx-condition.cpp new file mode 100644 index 000000000000..330a17a10a43 --- /dev/null +++ b/test/CodeGen/cxx-condition.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +void f() { + int a; + if (int x=a) ++a; else a=x; + while (int x=a) ++a; + for (; int x=a; --a) ; + switch (int x=0) { } +} diff --git a/test/CodeGen/cxx-default-arg.cpp b/test/CodeGen/cxx-default-arg.cpp new file mode 100644 index 000000000000..8391b9ccae19 --- /dev/null +++ b/test/CodeGen/cxx-default-arg.cpp @@ -0,0 +1,25 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +// Note: define CLANG_GENERATE_KNOWN_GOOD and compile to generate code +// that makes all of the defaulted arguments explicit. The resulting +// byte code should be identical to the compilation without +// CLANG_GENERATE_KNOWN_GOOD. +#ifdef CLANG_GENERATE_KNOWN_GOOD +# define DEFARG(...) __VA_ARGS__ +#else +# define DEFARG(...) +#endif + +extern int x; +struct S { float x; float y; } s; +double _Complex c; + +void f(int i = 0, int j = 1, int k = x, struct S t = s, double _Complex d = c); + +void g() { + f(0, 1, x, s DEFARG(, c)); + f(0, 1, x DEFARG(, s, c)); + f(0, 1 DEFARG(, x, s, c)); + f(0 DEFARG(, 1, x, s, c)); + f(DEFARG(0, 1, x, s, c)); +} diff --git a/test/CodeGen/cxx-value-init.cpp b/test/CodeGen/cxx-value-init.cpp new file mode 100644 index 000000000000..e23869879fbd --- /dev/null +++ b/test/CodeGen/cxx-value-init.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +enum E {}; +int v1 = E(); +float v2 = float(); + +void f() { + int v3 = int(); + _Complex int v4 = typeof(_Complex int)(); + _Complex float v5 = typeof(_Complex float)(); +} diff --git a/test/CodeGen/darwin-string-literals.c b/test/CodeGen/darwin-string-literals.c new file mode 100644 index 000000000000..ff245fcc7a5c --- /dev/null +++ b/test/CodeGen/darwin-string-literals.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm %s -o %t && + +// RUN: grep -F '@"\01LC" = internal constant [8 x i8] c"string0\00"' %t && +// RUN: grep -F '@"\01LC1" = internal constant [8 x i8] c"string1\00", section "__TEXT,__cstring,cstring_literals"' %t && +// RUN: grep -F '@__utf16_string_ = internal global [35 x i8] c"h\00e\00l\00l\00o\00 \00\92! \00\03& \00\90! \00w\00o\00r\00l\00d\00\00", section "__TEXT,__ustring", align 2' %t && +// RUN: true + +const char *g0 = "string0"; +const void *g1 = __builtin___CFStringMakeConstantString("string1"); +const void *g2 = __builtin___CFStringMakeConstantString("hello \u2192 \u2603 \u2190 world"); diff --git a/test/CodeGen/debug-info.c b/test/CodeGen/debug-info.c new file mode 100644 index 000000000000..e0ec2c9027cf --- /dev/null +++ b/test/CodeGen/debug-info.c @@ -0,0 +1,37 @@ +// RUN: clang-cc -o %t --emit-llvm -g %s + +// PR3023 +void convert(void) { + struct { typeof(0) f0; } v0; +} + +// PR2784 +struct OPAQUE; +typedef struct OPAQUE *PTR; +PTR p; + + +// PR2950 +struct s0; +struct s0 { struct s0 *p; } g0; + +struct s0 *f0(struct s0 *a0) { + return a0->p; +} + +// PR3134 +char xpto[]; + +// PR3427 +struct foo { + int a; + void *ptrs[]; +}; +struct foo bar; + +// PR4143 +struct foo2 { + enum bar *bar; +}; + +struct foo2 foo2; diff --git a/test/CodeGen/designated-initializers.c b/test/CodeGen/designated-initializers.c new file mode 100644 index 000000000000..466933928665 --- /dev/null +++ b/test/CodeGen/designated-initializers.c @@ -0,0 +1,21 @@ +// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o - | grep "<{ i8\* null, i32 1024 }>" && +// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o - | grep "i32 0, i32 22" + +struct foo { + void *a; + int b; +}; + +union { int i; float f; } u = { }; + +int main(int argc, char **argv) +{ + union { int i; float f; } u2 = { }; + static struct foo foo = { + .b = 1024, + }; +} + +int b[2] = { + [1] 22 +}; diff --git a/test/CodeGen/dllimport-dllexport.c b/test/CodeGen/dllimport-dllexport.c new file mode 100644 index 000000000000..fe49ae7a32af --- /dev/null +++ b/test/CodeGen/dllimport-dllexport.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -emit-llvm < %s -o %t && +// RUN: grep 'dllexport' %t | count 1 && +// RUN: not grep 'dllimport' %t + +void __attribute__((dllimport)) foo1(); +void __attribute__((dllexport)) foo1(){} +void __attribute__((dllexport)) foo2(); diff --git a/test/CodeGen/dostmt.c b/test/CodeGen/dostmt.c new file mode 100644 index 000000000000..4fb3dcdee9bc --- /dev/null +++ b/test/CodeGen/dostmt.c @@ -0,0 +1,70 @@ +// RUN: clang-cc %s -emit-llvm -o - + +int bar(); +int test0() { + int i; + i = 1 + 2; + do { + i = bar(); + i = bar(); + } while(0); + return i; +} + + +int test1() { + int i; + i = 1 + 2; + do { + i = bar(); + if (i == 42) + break; + i = bar(); + } while(1); + return i; +} + + +int test2() { + int i; + i = 1 + 2; + do { + i = bar(); + if (i == 42) + continue; + i = bar(); + } while(1); + return i; +} + + +int test3() { + int i; + i = 1 + 2; + do { + i = bar(); + if (i == 42) + break; + } while(0); + return i; +} + + +int test4() { + int i; + i = 1 + 2; + do { + i = bar(); + if (i == 42) + continue; + } while(0); + return i; +} + +// rdar://6103124 +void test5() { + do { break; } while(0); +} + + + diff --git a/test/CodeGen/emit-all-decls.c b/test/CodeGen/emit-all-decls.c new file mode 100644 index 000000000000..775cb6f118a8 --- /dev/null +++ b/test/CodeGen/emit-all-decls.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -emit-llvm -o %t %s && +// RUN: not grep "@foo" %t && +// RUN: clang-cc -femit-all-decls -emit-llvm -o %t %s && +// RUN: grep "@foo" %t + +static void foo() { + +} diff --git a/test/CodeGen/empty-union-init.c b/test/CodeGen/empty-union-init.c new file mode 100644 index 000000000000..8448b3ded798 --- /dev/null +++ b/test/CodeGen/empty-union-init.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -emit-llvm < %s -o - +// PR2419 + +struct Mem { + union { + } u; +}; + +struct Mem *columnMem(){ + static const struct Mem nullMem = { {} }; +} + + diff --git a/test/CodeGen/enum.c b/test/CodeGen/enum.c new file mode 100644 index 000000000000..172d308c2b0b --- /dev/null +++ b/test/CodeGen/enum.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm-bc -o - | opt -std-compile-opts | llvm-dis | grep 'ret i32 6' + +static enum { foo, bar = 1U } z; + +int main (void) +{ + int r = 0; + + if (bar - 2 < 0) + r += 4; + if (foo - 1 < 0) + r += 2; + if (z - 1 < 0) + r++; + + return r; +} + diff --git a/test/CodeGen/exprs.c b/test/CodeGen/exprs.c new file mode 100644 index 000000000000..36cfff9e8a69 --- /dev/null +++ b/test/CodeGen/exprs.c @@ -0,0 +1,118 @@ +// RUN: clang-cc %s -emit-llvm -o - + +// PR1895 +// sizeof function +int zxcv(void); +int x=sizeof(zxcv); +int y=__alignof__(zxcv); + + +void *test(int *i) { + short a = 1; + i += a; + i + a; + a + i; +} + +_Bool test2b; +int test2() {if (test2b);} + +// PR1921 +int test3() { + const unsigned char *bp; + bp -= (short)1; +} + +// PR2080 - sizeof void +int t1 = sizeof(void); +int t2 = __alignof__(void); +void test4() { + t1 = sizeof(void); + t2 = __alignof__(void); + + t1 = sizeof(test4()); + t2 = __alignof__(test4()); +} + +// 'const float' promotes to double in varargs. +int test5(const float x, float float_number) { + return __builtin_isless(x, float_number); +} + +// this one shouldn't fold +int ola() { + int a=2; + if ((0, (int)a) & 2) { return 1; } + return 2; +} + +// this one shouldn't fold as well +void eMaisUma() { + double t[1]; + if (*t) + return; +} + +// rdar://6520707 +void f0(void (*fp)(void), void (*fp2)(void)) { + int x = fp - fp2; +} + +// noop casts as lvalues. +struct X { + int Y; +}; +struct X foo(); +int bar() { + return ((struct X)foo()).Y + 1; +} + +// PR3809: INC/DEC of function pointers. +void f2(void); +unsigned f1(void) { + void (*fp)(void) = f2; + + ++fp; + fp++; + --fp; + fp--; + return (unsigned) fp; +} + +union f3_x {int x; float y;}; +int f3() {return ((union f3_x)2).x;} + +union f4_y {int x; _Complex float y;}; +_Complex float f4() {return ((union f4_y)(_Complex float)2.0).y;} + +struct f5_a { int a; } f5_a; +union f5_z {int x; struct f5_a y;}; +struct f5_a f5() {return ((union f5_z)f5_a).y;} + +// ?: in "lvalue" +struct s6 { int f0; }; +int f6(int a0, struct s6 a1, struct s6 a2) { + return (a0 ? a1 : a2).f0; +} + +// PR4026 +void f7() { + __func__; +} + +// PR4067 +int f8() { + return ({ foo(); }).Y; +} + +// rdar://6880558 +struct S; +struct C { + int i; + struct S *tab[]; +}; +struct S { struct C c; }; +void f9(struct S *x) { + foo(((void)1, x->c).tab[0]); +} + diff --git a/test/CodeGen/ext-vector-shuffle.c b/test/CodeGen/ext-vector-shuffle.c new file mode 100644 index 000000000000..37d3ed42d060 --- /dev/null +++ b/test/CodeGen/ext-vector-shuffle.c @@ -0,0 +1,15 @@ +// RUN: clang-cc %s -emit-llvm -o - | not grep 'extractelement' +// RUN: clang-cc %s -emit-llvm -o - | not grep 'insertelement' +// RUN: clang-cc %s -emit-llvm -o - | grep 'shufflevector' + +typedef __attribute__(( ext_vector_type(2) )) float float2; +typedef __attribute__(( ext_vector_type(4) )) float float4; + +float2 test1(float4 V) { + return V.xy + V.wz; +} + +float4 test2(float4 V) { + float2 W = V.ww; + return W.xyxy + W.yxyx; +} diff --git a/test/CodeGen/ext-vector.c b/test/CodeGen/ext-vector.c new file mode 100644 index 000000000000..e3b6211ee991 --- /dev/null +++ b/test/CodeGen/ext-vector.c @@ -0,0 +1,129 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +typedef __attribute__(( ext_vector_type(4) )) float float4; +typedef __attribute__(( ext_vector_type(2) )) float float2; +typedef __attribute__(( ext_vector_type(4) )) int int4; + +float4 foo = (float4){ 1.0, 2.0, 3.0, 4.0 }; + +const float4 bar = (float4){ 1.0, 2.0, 3.0, __builtin_inff() }; + +float4 test1(float4 V) { + return V.wzyx+V; +} + +float2 vec2, vec2_2; +float4 vec4, vec4_2; +float f; + +void test2() { + vec2 = vec4.xy; // shorten + f = vec2.x; // extract elt + vec4 = vec4.yyyy; // splat + + vec2.x = f; // insert one. + vec2.yx = vec2; // reverse +} + +void test3(float4 *out) { + *out = ((float4) {1.0f, 2.0f, 3.0f, 4.0f }); +} + +void test4(float4 *out) { + float a = 1.0f; + float b = 2.0f; + float c = 3.0f; + float d = 4.0f; + *out = ((float4) {a,b,c,d}); +} + +void test5(float4 *out) { + float a; + float4 b; + + a = 1.0f; + b = a; + b = b * 5.0f; + b = 5.0f * b; + b *= a; + + *out = b; +} + +void test6(float4 *ap, float4 *bp, float c) { + float4 a = *ap; + float4 b = *bp; + + a = a + b; + a = a - b; + a = a * b; + a = a / b; + + a = a + c; + a = a - c; + a = a * c; + a = a / c; + + a += b; + a -= b; + a *= b; + a /= b; + + a += c; + a -= c; + a *= c; + a /= c; + + // Vector comparisons can sometimes crash the x86 backend: rdar://6326239, + // reject them until the implementation is stable. +#if 0 + int4 cmp; + cmp = a < b; + cmp = a <= b; + cmp = a < b; + cmp = a >= b; + cmp = a == b; + cmp = a != b; +#endif +} + +void test7(int4 *ap, int4 *bp, int c) { + int4 a = *ap; + int4 b = *bp; + + a = a + b; + a = a - b; + a = a * b; + a = a / b; + a = a % b; + + a = a + c; + a = a - c; + a = a * c; + a = a / c; + a = a % c; + + a += b; + a -= b; + a *= b; + a /= b; + a %= b; + + a += c; + a -= c; + a *= c; + a /= c; + a %= c; + + // Vector comparisons can sometimes crash the x86 backend: rdar://6326239, + // reject them until the implementation is stable. +#if 0 + int4 cmp; + cmp = a < b; + cmp = a <= b; + cmp = a < b; + cmp = a >= b; + cmp = a == b; + cmp = a != b; +#endif +} diff --git a/test/CodeGen/extern-block-var.c b/test/CodeGen/extern-block-var.c new file mode 100644 index 000000000000..e8de3e7f11fe --- /dev/null +++ b/test/CodeGen/extern-block-var.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +int f() { + extern int a; + return a; +} diff --git a/test/CodeGen/flexible-array-init.c b/test/CodeGen/flexible-array-init.c new file mode 100644 index 000000000000..fb98a8ec07a6 --- /dev/null +++ b/test/CodeGen/flexible-array-init.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 7 | count 1 && +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 11 | count 1 && +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 13 | count 1 && +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o - %s | grep 15 | count 1 + +struct { int x; int y[]; } a = { 1, 7, 11 }; + +struct { int x; int y[]; } b = { 1, { 13, 15 } }; diff --git a/test/CodeGen/func-decl-cleanup.c b/test/CodeGen/func-decl-cleanup.c new file mode 100644 index 000000000000..4808e12fdfcc --- /dev/null +++ b/test/CodeGen/func-decl-cleanup.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -emit-llvm -o - + + +// PR2360 +typedef void fn_t(); + +fn_t a,b; + +void b() +{ +} + diff --git a/test/CodeGen/func-return-member.c b/test/CodeGen/func-return-member.c new file mode 100644 index 000000000000..e6fc5623904b --- /dev/null +++ b/test/CodeGen/func-return-member.c @@ -0,0 +1,23 @@ +// RUN: clang-cc -emit-llvm < %s 2>&1 | not grep 'cannot codegen this l-value expression yet' + +struct frk { float _Complex c; int x; }; +struct faz { struct frk f; }; +struct fuz { struct faz f; }; + +extern struct fuz foo(void); + +int X; +struct frk F; +float _Complex C; + +void bar(void) { + X = foo().f.f.x; +} + +void bun(void) { + F = foo().f.f; +} + +void ban(void) { + C = foo().f.f.c; +} diff --git a/test/CodeGen/function-attributes.c b/test/CodeGen/function-attributes.c new file mode 100644 index 000000000000..ba2e4e4d564d --- /dev/null +++ b/test/CodeGen/function-attributes.c @@ -0,0 +1,69 @@ +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o %t %s && +// RUN: grep 'define signext i8 @f0(i32 %x) nounwind' %t && +// RUN: grep 'define zeroext i8 @f1(i32 %x) nounwind' %t && +// RUN: grep 'define void @f2(i8 signext %x) nounwind' %t && +// RUN: grep 'define void @f3(i8 zeroext %x) nounwind' %t && +// RUN: grep 'define signext i16 @f4(i32 %x) nounwind' %t && +// RUN: grep 'define zeroext i16 @f5(i32 %x) nounwind' %t && +// RUN: grep 'define void @f6(i16 signext %x) nounwind' %t && +// RUN: grep 'define void @f7(i16 zeroext %x) nounwind' %t && + +signed char f0(int x) { return x; } + +unsigned char f1(int x) { return x; } + +void f2(signed char x) { } + +void f3(unsigned char x) { } + +signed short f4(int x) { return x; } + +unsigned short f5(int x) { return x; } + +void f6(signed short x) { } + +void f7(unsigned short x) { } + +// RUN: grep 'define void @f8() nounwind alwaysinline' %t && +void __attribute__((always_inline)) f8(void) { } + +// RUN: grep 'call void @f9_t() noreturn' %t && +void __attribute__((noreturn)) f9_t(void); +void f9(void) { f9_t(); } + +// FIXME: We should be setting nounwind on calls. +// RUN: grep 'call i32 @f10_t() readnone' %t && +int __attribute__((const)) f10_t(void); +int f10(void) { return f10_t(); } +int f11(void) { + exit: + return f10_t(); +} +int f12(int arg) { + return arg ? 0 : f10_t(); +} + +// RUN: grep 'define void @f13() nounwind readnone' %t && +void f13(void) __attribute__((pure)) __attribute__((const)); +void f13(void){} + + +// Ensure that these get inlined: rdar://6853279 +// RUN: not grep '@ai_' %t && +static __inline__ __attribute__((always_inline)) +int ai_1() { return 4; } + +static __inline__ __attribute__((always_inline)) +struct { + int a, b, c, d, e; +} ai_2() { } + + +int foo() { + ai_2(); + return ai_1(); +} + + + +// RUN: true diff --git a/test/CodeGen/function-decay.m b/test/CodeGen/function-decay.m new file mode 100644 index 000000000000..5652fdbb21ea --- /dev/null +++ b/test/CodeGen/function-decay.m @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -emit-llvm -o - + +@interface I0 @end +@implementation I0 +- (void) im0: (int (void)) a0 { +} +@end + +void func(int pf(void)) { +} diff --git a/test/CodeGen/functions.c b/test/CodeGen/functions.c new file mode 100644 index 000000000000..985599216e1c --- /dev/null +++ b/test/CodeGen/functions.c @@ -0,0 +1,35 @@ +// RUN: clang-cc %s -emit-llvm -o %t && + +int g(); + +int foo(int i) { + return g(i); +} + +int g(int i) { + return g(i); +} + +// rdar://6110827 +typedef void T(void); +void test3(T f) { + f(); +} + +int a(int); +int a() {return 1;} + +// RUN: grep 'define void @f0()' %t && +void f0() {} + +void f1(); +// RUN: grep 'call void @f1()' %t && +void f2(void) { + f1(1, 2, 3); +} +// RUN: grep 'define void @f1()' %t && +void f1() {} + +// RUN: grep 'define .* @f3' %t | not grep -F '...' +struct foo { int X, Y, Z; } f3() { +} diff --git a/test/CodeGen/global-decls.c b/test/CodeGen/global-decls.c new file mode 100644 index 000000000000..80222ea85ef1 --- /dev/null +++ b/test/CodeGen/global-decls.c @@ -0,0 +1,22 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s && + +// RUN: grep '@g0_ext = extern_weak global i32' %t && +extern int g0_ext __attribute__((weak)); +// RUN: grep 'declare extern_weak i32 @g1_ext()' %t && +extern int __attribute__((weak)) g1_ext (void); + +// RUN: grep '@g0_common = weak global i32' %t && +int g0_common __attribute__((weak)); + +// RUN: grep '@g0_def = weak global i32' %t && +int g0_def __attribute__((weak)) = 52; +// RUN: grep 'define weak i32 @g1_def()' %t && +int __attribute__((weak)) g1_def (void) {} + +// Force _ext references +void f0() { + int a = g0_ext; + int b = g1_ext(); +} + +// RUN: true diff --git a/test/CodeGen/global-init.c b/test/CodeGen/global-init.c new file mode 100644 index 000000000000..4b769f8ccbb0 --- /dev/null +++ b/test/CodeGen/global-init.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -emit-llvm -o - %s | not grep "common" + +// This checks that the global won't be marked as common. +// (It shouldn't because it's being initialized). + +int a; +int a = 242; diff --git a/test/CodeGen/global-with-initialiser.c b/test/CodeGen/global-with-initialiser.c new file mode 100644 index 000000000000..29b4e21b9129 --- /dev/null +++ b/test/CodeGen/global-with-initialiser.c @@ -0,0 +1,25 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +const int globalInt = 1; +int globalIntWithFloat = 1.5f; +int globalIntArray[5] = { 1, 2 }; +int globalIntFromSizeOf = sizeof(globalIntArray); +char globalChar = 'a'; +char globalCharArray[5] = { 'a', 'b' }; +float globalFloat = 1.0f; +float globalFloatWithInt = 1; +float globalFloatArray[5] = { 1.0f, 2.0f }; +double globalDouble = 1.0; +double globalDoubleArray[5] = { 1.0, 2.0 }; +char *globalString = "abc"; +char *globalStringArray[5] = { "123", "abc" }; +long double globalLongDouble = 1; +long double globalLongDoubleArray[5] = { 1.0, 2.0 }; + +struct Struct { + int member1; + float member2; + char *member3; +}; + +struct Struct globalStruct = { 1, 2.0f, "foobar"}; diff --git a/test/CodeGen/globalinit.c b/test/CodeGen/globalinit.c new file mode 100644 index 000000000000..2798cae712a2 --- /dev/null +++ b/test/CodeGen/globalinit.c @@ -0,0 +1,51 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +int A[10] = { 1,2,3,4,5 }; + + +extern int x[]; +void foo() { x[0] = 1; } +int x[10]; +void bar() { x[0] = 1; } + + +extern int y[]; +void *g = y; + +int latin_ptr2len (char *p); +int (*mb_ptr2len) (char *p) = latin_ptr2len; + + +char string[8] = "string"; // extend init +char string2[4] = "string"; // truncate init + +char *test(int c) { + static char buf[10]; + static char *bufptr = buf; + + return c ? buf : bufptr; +} + + +_Bool booltest = 0; +void booltest2() { + static _Bool booltest3 = 4; +} + +// Scalars in braces. +static int a = { 1 }; + +// References to enums. +enum { + EnumA, EnumB +}; + +int c[] = { EnumA, EnumB }; + +// Binary operators +int d[] = { EnumA | EnumB }; + +// PR1968 +static int array[]; +static int array[4]; + diff --git a/test/CodeGen/illegal-UTF8.m b/test/CodeGen/illegal-UTF8.m new file mode 100644 index 000000000000..a9d5a37ac757 --- /dev/null +++ b/test/CodeGen/illegal-UTF8.m @@ -0,0 +1,8 @@ +// RUN: clang %s -S -m64 -o - + +@class NSString; + +// FIXME: GCC emits the following warning: +// CodeGen/illegal-UTF8.m:4: warning: input conversion stopped due to an input byte that does not belong to the input codeset UTF-8 + +NSString *S = @"\xff\xff___WAIT___"; diff --git a/test/CodeGen/incomplete-function-type.c b/test/CodeGen/incomplete-function-type.c new file mode 100644 index 000000000000..a641268cf50f --- /dev/null +++ b/test/CodeGen/incomplete-function-type.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm %s -o - | not grep opaque + +enum teste1 test1f(void), (*test1)(void) = test1f; +struct tests2 test2f(), (*test2)() = test2f; +struct tests3; +void test3f(struct tests3), (*test3)(struct tests3) = test3f; +enum teste1 { TEST1 }; +struct tests2 { int x,y,z,a,b,c,d,e,f,g; }; +struct tests3 { float x; }; + diff --git a/test/CodeGen/indirect-goto.c b/test/CodeGen/indirect-goto.c new file mode 100644 index 000000000000..b9a601953877 --- /dev/null +++ b/test/CodeGen/indirect-goto.c @@ -0,0 +1,20 @@ +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t && +// RUN: grep "ret i32" %t | count 1 && +// RUN: grep "ret i32 210" %t | count 1 + +static int foo(unsigned i) { + const void *addrs[] = { &&L1, &&L2, &&L3, &&L4, &&L5 }; + int res = 1; + + goto *addrs[i]; + L5: res *= 11; + L4: res *= 7; + L3: res *= 5; + L2: res *= 3; + L1: res *= 2; + return res; +} + +int bar() { + return foo(3); +} diff --git a/test/CodeGen/init-with-member-expr.c b/test/CodeGen/init-with-member-expr.c new file mode 100644 index 000000000000..7750dbf9869d --- /dev/null +++ b/test/CodeGen/init-with-member-expr.c @@ -0,0 +1,21 @@ +// RUN: clang-cc < %s -emit-llvm +struct test { + int a; +}; + +extern struct test t; + +int *b=&t.a; + + +// PR2049 +typedef struct mark_header_tag { + unsigned char mark[7]; +} mark_header_t; +int is_rar_archive(int fd) { + const mark_header_t rar_hdr[2] = {{0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}, {'U', 'n', 'i', 'q', 'u', 'E', '!'}}; + foo(rar_hdr); + + return 0; +} + diff --git a/test/CodeGen/init.c b/test/CodeGen/init.c new file mode 100644 index 000000000000..2e239cf5438c --- /dev/null +++ b/test/CodeGen/init.c @@ -0,0 +1,31 @@ +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm %s -o %t && + +void f1() { + // Scalars in braces. + int a = { 1 }; +} + +void f2() { + int a[2][2] = { { 1, 2 }, { 3, 4 } }; + int b[3][3] = { { 1, 2 }, { 3, 4 } }; + int *c[2] = { &a[1][1], &b[2][2] }; + int *d[2][2] = { {&a[1][1], &b[2][2]}, {&a[0][0], &b[1][1]} }; + int *e[3][3] = { {&a[1][1], &b[2][2]}, {&a[0][0], &b[1][1]} }; + char ext[3][3] = {".Y",".U",".V"}; +} + +typedef void (* F)(void); +extern void foo(void); +struct S { F f; }; +void f3() { + struct S a[1] = { { foo } }; +} + +// Constants +// RUN: grep '@g3 = constant i32 10' %t && +// RUN: grep '@f4.g4 = internal constant i32 12' %t +const int g3 = 10; +int f4() { + static const int g4 = 12; + return g4; +} diff --git a/test/CodeGen/inline.c b/test/CodeGen/inline.c new file mode 100644 index 000000000000..234f1f8d93a8 --- /dev/null +++ b/test/CodeGen/inline.c @@ -0,0 +1,86 @@ +// RUN: echo "C89 tests:" && +// RUN: clang %s -emit-llvm -S -o %t -std=c89 && +// RUN: grep "define available_externally i32 @ei()" %t && +// RUN: grep "define i32 @foo()" %t && +// RUN: grep "define i32 @bar()" %t && +// RUN: grep "define void @unreferenced1()" %t && +// RUN: not grep unreferenced2 %t && +// RUN: grep "define void @gnu_inline()" %t && +// RUN: grep "define available_externally void @gnu_ei_inline()" %t && +// RUN: grep "define i32 @test1" %t && +// RUN: grep "define i32 @test2" %t && +// RUN: grep "define void @test3()" %t && +// RUN: grep "define available_externally i32 @test4" %t && +// RUN: grep "define available_externally i32 @test5" %t && + +// RUN: echo "\nC99 tests:" && +// RUN: clang %s -emit-llvm -S -o %t -std=c99 && +// RUN: grep "define i32 @ei()" %t && +// RUN: grep "define available_externally i32 @foo()" %t && +// RUN: grep "define i32 @bar()" %t && +// RUN: not grep unreferenced1 %t && +// RUN: grep "define void @unreferenced2()" %t && +// RUN: grep "define void @gnu_inline()" %t && +// RUN: grep "define available_externally void @gnu_ei_inline()" %t && +// RUN: grep "define i32 @test1" %t && +// RUN: grep "define i32 @test2" %t && +// RUN: grep "define available_externally void @test3" %t && +// RUN: grep "define available_externally i32 @test4" %t && +// RUN: grep "define i32 @test5" %t && + +// RUN: echo "\nC++ tests:" && +// RUN: clang %s -emit-llvm -S -o %t -std=c++98 && +// RUN: grep "define linkonce_odr i32 @_Z2eiv()" %t && +// RUN: grep "define linkonce_odr i32 @_Z3foov()" %t && +// RUN: grep "define i32 @_Z3barv()" %t && +// RUN: not grep unreferenced %t && +// RUN: grep "define void @_Z10gnu_inlinev()" %t && +// RUN: grep "define available_externally void @_Z13gnu_ei_inlinev()" %t + +extern __inline int ei() { return 123; } + +__inline int foo() { + return ei(); +} + +int bar() { return foo(); } + + +__inline void unreferenced1() {} +extern __inline void unreferenced2() {} + +__inline __attribute((__gnu_inline__)) void gnu_inline() {} + +// PR3988 +extern __inline __attribute__((gnu_inline)) void gnu_ei_inline() {} +void (*P)() = gnu_ei_inline; + +// <rdar://problem/6818429> +int test1(); +__inline int test1() { return 4; } +__inline int test2() { return 5; } +__inline int test2(); +int test2(); + +void test_test1() { test1(); } +void test_test2() { test2(); } + +// PR3989 +extern __inline void test3() __attribute__((gnu_inline)); +__inline void test3() {} + +void test_test3() { test3(); } + +extern int test4(void); +extern __inline __attribute__ ((__gnu_inline__)) int test4(void) +{ +} + +void test_test4() { test4(); } + +extern __inline int test5(void); +extern __inline int __attribute__ ((__gnu_inline__)) test5(void) +{ +} + +void test_test5() { test5(); } diff --git a/test/CodeGen/int-to-pointer.c b/test/CodeGen/int-to-pointer.c new file mode 100644 index 000000000000..7cefc3902ebc --- /dev/null +++ b/test/CodeGen/int-to-pointer.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +void *test(int i) +{ + return (void *)i; +} diff --git a/test/CodeGen/kr-func-promote.c b/test/CodeGen/kr-func-promote.c new file mode 100644 index 000000000000..d4c3851909ab --- /dev/null +++ b/test/CodeGen/kr-func-promote.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o - | grep "i32 @a(i32)" + +int a(); +int a(x) short x; {return x;} + diff --git a/test/CodeGen/kr-style-block.c b/test/CodeGen/kr-style-block.c new file mode 100644 index 000000000000..ac788dc9ab9f --- /dev/null +++ b/test/CodeGen/kr-style-block.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm %s -o %t -fblocks + +void foo (void(^)()); + +int main() +{ +foo( + ^() { } +); +} diff --git a/test/CodeGen/libcalls.c b/test/CodeGen/libcalls.c new file mode 100644 index 000000000000..695321622fed --- /dev/null +++ b/test/CodeGen/libcalls.c @@ -0,0 +1,22 @@ +// RUN: clang-cc -fmath-errno=1 -emit-llvm -o %t %s && +// RUN: grep "declare " %t | count 6 && +// RUN: grep "declare " %t | grep "@llvm." | count 1 && +// RUN: clang-cc -fmath-errno=0 -emit-llvm -o %t %s && +// RUN: grep "declare " %t | count 6 && +// RUN: grep "declare " %t | grep -v "@llvm." | count 0 + +// IRgen only pays attention to const; it should always call llvm for +// this. +float sqrtf(float) __attribute__((const)); + +void test_sqrt(float a0, double a1, long double a2) { + float l0 = sqrtf(a0); + double l1 = sqrt(a1); + long double l2 = sqrtl(a2); +} + +void test_pow(float a0, double a1, long double a2) { + float l0 = powf(a0, a0); + double l1 = pow(a1, a1); + long double l2 = powl(a2, a2); +} diff --git a/test/CodeGen/lineno-dbginfo.c b/test/CodeGen/lineno-dbginfo.c new file mode 100644 index 000000000000..fe9e59ac2d70 --- /dev/null +++ b/test/CodeGen/lineno-dbginfo.c @@ -0,0 +1,5 @@ +// RUN: echo "#include <stdio.h>" > %t.h +// RUN: clang -S -save-temps -g -include %t.h %s -emit-llvm -o %t.ll +// RUN: grep "i32 5" %t.ll +// outer is at line number 5. +int outer = 42; diff --git a/test/CodeGen/linkage-redecl.c b/test/CodeGen/linkage-redecl.c new file mode 100644 index 000000000000..b015ca854737 --- /dev/null +++ b/test/CodeGen/linkage-redecl.c @@ -0,0 +1,11 @@ +// RUN: clang-cc -emit-llvm %s -o - |grep internal + +// C99 6.2.2p3 +// PR3425 +static void f(int x); + +void g0() { + f(5); +} + +extern void f(int x) { } // still has internal linkage diff --git a/test/CodeGen/long-double-x86.c b/test/CodeGen/long-double-x86.c new file mode 100644 index 000000000000..b01ce0b93ec3 --- /dev/null +++ b/test/CodeGen/long-double-x86.c @@ -0,0 +1,4 @@ +// RUN: clang-cc %s -emit-llvm -o - -triple=i686-apple-darwin9 | grep x86_fp80 + +long double x = 0; +int checksize[sizeof(x) == 16 ? 1 : -1]; diff --git a/test/CodeGen/mandel.c b/test/CodeGen/mandel.c new file mode 100644 index 000000000000..6f46ee407f5c --- /dev/null +++ b/test/CodeGen/mandel.c @@ -0,0 +1,67 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +/* Sparc is not C99-compliant */ +#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) + +int main() { return 0; } + +#else /* sparc */ + +#define ESCAPE 2 +#define IMAGE_WIDTH 150 +#define IMAGE_HEIGHT 50 +#if 1 +#define IMAGE_SIZE 60 +#else +#define IMAGE_SIZE 5000 +#endif +#define START_X -2.1 +#define END_X 1.0 +#define START_Y -1.25 +#define MAX_ITER 100 + +#define step_X ((END_X - START_X)/IMAGE_WIDTH) +#define step_Y ((-START_Y - START_Y)/IMAGE_HEIGHT) + +#define I 1.0iF + +#include <math.h> + +#include <stdio.h> + +volatile double __complex__ accum; + +void mandel() { + int x, y, n; + for (y = 0; y < IMAGE_HEIGHT; ++y) { + for (x = 0; x < IMAGE_WIDTH; ++x) { + double __complex__ c = (START_X+x*step_X) + (START_Y+y*step_Y) * I; + double __complex__ z = 0.0; + + for (n = 0; n < MAX_ITER; ++n) { + z = z * z + c; + if (hypot(__real__ z, __imag__ z) >= ESCAPE) + break; + } + + if (n == MAX_ITER) + putchar(' '); + else if (n > 6) + putchar('.'); + else if (n > 3) + putchar('+'); + else if (n > 2) + putchar('x'); + else + putchar('*'); + } + putchar('\n'); + } +} + +int main() { + mandel(); + return 0; +} + +#endif /* sparc */ diff --git a/test/CodeGen/mangle.c b/test/CodeGen/mangle.c new file mode 100644 index 000000000000..17d74ba71f0c --- /dev/null +++ b/test/CodeGen/mangle.c @@ -0,0 +1,54 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s && +// RUN: grep '@_Z2f0i' %t && +// RUN: grep '@_Z2f0l' %t && + +// Make sure we mangle overloadable, even in C system headers. + +# 1 "somesystemheader.h" 1 3 4 +void __attribute__((__overloadable__)) f0(int a) {} +void __attribute__((__overloadable__)) f0(long b) {} + + + +// These should get merged. +void foo() __asm__("bar"); +void foo2() __asm__("bar"); + +// RUN: grep '@"\\01foo"' %t && +// RUN: grep '@"\\01bar"' %t + +int nux __asm__("foo"); +extern float nux2 __asm__("foo"); + +int test() { + foo(); + foo2(); + + return nux + nux2; +} + + +// Function becomes a variable. +void foo3() __asm__("var"); + +void test2() { + foo3(); +} +int foo4 __asm__("var") = 4; + + +// Variable becomes a function +extern int foo5 __asm__("var2"); + +void test3() { + foo5 = 1; +} + +void foo6() __asm__("var2"); +void foo6() { +} + + + +int foo7 __asm__("foo7") __attribute__((used)); +float foo8 __asm__("foo7") = 42; diff --git a/test/CodeGen/merge-attrs.c b/test/CodeGen/merge-attrs.c new file mode 100644 index 000000000000..1aab47a3a30c --- /dev/null +++ b/test/CodeGen/merge-attrs.c @@ -0,0 +1,13 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +void *malloc(__SIZE_TYPE__ size) __attribute__ ((__nothrow__)); + +inline static void __zend_malloc() { + malloc(1); +} + +void *malloc(__SIZE_TYPE__ size) __attribute__ ((__nothrow__)); + +void fontFetch() { + __zend_malloc(1); +} diff --git a/test/CodeGen/merge-statics.c b/test/CodeGen/merge-statics.c new file mode 100644 index 000000000000..c442669e6422 --- /dev/null +++ b/test/CodeGen/merge-statics.c @@ -0,0 +1,13 @@ +// RUN: clang-cc < %s -emit-llvm | grep internal | count 1 + +// The two decls for 'a' should merge into one llvm GlobalVariable. + +struct s { int x; }; +static struct s a; + +struct s *ap1 = &a; + +static struct s a = { + 10 +}; + diff --git a/test/CodeGen/mmintrin-test.c b/test/CodeGen/mmintrin-test.c new file mode 100644 index 000000000000..2a9ab5672330 --- /dev/null +++ b/test/CodeGen/mmintrin-test.c @@ -0,0 +1,26 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -mcpu=pentium4 -emit-llvm -o %t %s && +// RUN: grep define %t | count 1 && +// RUN: clang-cc -triple i386-apple-darwin9 -mcpu=pentium4 -g -emit-llvm -o %t %s && +// RUN: grep define %t | count 1 + +#include <mmintrin.h> +#include <stdio.h> + +int main(int argc, char *argv[]) { + int array[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; + __m64 *p = (__m64 *)array; + + __m64 accum = _mm_setzero_si64(); + + for (int i=0; i<8; ++i) + accum = _mm_add_pi32(p[i], accum); + + __m64 accum2 = _mm_unpackhi_pi32(accum, accum); + accum = _mm_add_pi32(accum, accum2); + + int result = _mm_cvtsi64_si32(accum); + _mm_empty(); + printf("%d\n", result ); + + return 0; +} diff --git a/test/CodeGen/no-common.c b/test/CodeGen/no-common.c new file mode 100644 index 000000000000..190873c745fe --- /dev/null +++ b/test/CodeGen/no-common.c @@ -0,0 +1,6 @@ +// RUN: clang -emit-llvm -S -o %t %s && +// RUN: grep '@x = common global' %t && +// RUN: clang -fno-common -emit-llvm -S -o %t %s && +// RUN: grep '@x = global' %t + +int x; diff --git a/test/CodeGen/offsetof.c b/test/CodeGen/offsetof.c new file mode 100644 index 000000000000..b0f5727a92dc --- /dev/null +++ b/test/CodeGen/offsetof.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +// PR2910 +struct sockaddr_un { + unsigned char sun_len; + char sun_path[104]; +}; + +int test(int len) { + return __builtin_offsetof(struct sockaddr_un, sun_path[len+1]); +} + diff --git a/test/CodeGen/opaque-pointer.c b/test/CodeGen/opaque-pointer.c new file mode 100644 index 000000000000..7f78b91fb17e --- /dev/null +++ b/test/CodeGen/opaque-pointer.c @@ -0,0 +1,13 @@ +// RUN: clang-cc %s -emit-llvm -o - +struct test; + +typedef void (*my_func) (struct test *); +my_func handler; + +struct test { + char a; +}; + +char f(struct test *t) { + return t->a; +} diff --git a/test/CodeGen/overloadable.c b/test/CodeGen/overloadable.c new file mode 100644 index 000000000000..4b58c8254624 --- /dev/null +++ b/test/CodeGen/overloadable.c @@ -0,0 +1,26 @@ +// RUN: clang-cc -emit-llvm %s -o - | grep _Z1fPA10_1X +int __attribute__((overloadable)) f(int x) { return x; } +float __attribute__((overloadable)) f(float x) { return x; } +double __attribute__((overloadable)) f(double x) { return x; } +double _Complex __attribute__((overloadable)) f(double _Complex x) { return x; } +typedef short v4hi __attribute__ ((__vector_size__ (8))); +v4hi __attribute__((overloadable)) f(v4hi x) { return x; } + +struct X { }; +void __attribute__((overloadable)) f(struct X (*ptr)[10]) { } + +void __attribute__((overloadable)) f(int x, int y, ...) { } + +int main() { + int iv = 17; + float fv = 3.0f; + double dv = 4.0; + double _Complex cdv; + v4hi vv; + + iv = f(iv); + fv = f(fv); + dv = f(dv); + cdv = f(cdv); + vv = f(vv); +} diff --git a/test/CodeGen/parameter-passing.c b/test/CodeGen/parameter-passing.c new file mode 100644 index 000000000000..2ace299ef770 --- /dev/null +++ b/test/CodeGen/parameter-passing.c @@ -0,0 +1,57 @@ +// Check the various ways in which the three classes of values +// (scalar, complex, aggregate) interact with parameter passing +// (function entry, function return, call argument, call result). +// +// We also check _Bool and empty structures, as these can have annoying +// corner cases. + +// RUN: clang-cc %s -triple i386-unknown-unknown -O3 -emit-llvm -o %t && +// RUN: not grep '@g0' %t && + +// RUN: clang-cc %s -triple x86_64-unknown-unknown -O3 -emit-llvm -o %t && +// RUN: not grep '@g0' %t && + +// RUN: clang-cc %s -triple ppc-unknown-unknown -O3 -emit-llvm -o %t && +// RUN: not grep '@g0' %t && +// RUN: true + +typedef _Bool BoolTy; +typedef int ScalarTy; +typedef _Complex int ComplexTy; +typedef struct { int a, b, c; } AggrTy; +typedef struct { int a[0]; } EmptyTy; + +static int result; + +static BoolTy bool_id(BoolTy a) { return a; } +static AggrTy aggr_id(AggrTy a) { return a; } +static EmptyTy empty_id(EmptyTy a) { return a; } +static ScalarTy scalar_id(ScalarTy a) { return a; } +static ComplexTy complex_id(ComplexTy a) { return a; } + +static void bool_mul(BoolTy a) { result *= a; } + +static void aggr_mul(AggrTy a) { result *= a.a * a.b * a.c; } + +static void empty_mul(EmptyTy a) { result *= 53; } + +static void scalar_mul(ScalarTy a) { result *= a; } + +static void complex_mul(ComplexTy a) { result *= __real a * __imag a; } + +extern void g0(void); + +void f0(void) { + result = 1; + + bool_mul(bool_id(1)); + aggr_mul(aggr_id((AggrTy) { 2, 3, 5})); + empty_mul(empty_id((EmptyTy) {})); + scalar_mul(scalar_id(7)); + complex_mul(complex_id(11 + 13i)); + + // This call should be eliminated. + if (result != 2 * 3 * 5 * 7 * 11 * 13 * 53) + g0(); +} + diff --git a/test/CodeGen/pascal-string.c b/test/CodeGen/pascal-string.c new file mode 100644 index 000000000000..fcd807cde7b1 --- /dev/null +++ b/test/CodeGen/pascal-string.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -emit-llvm -o - %s -fpascal-strings | grep "05Hello" + +unsigned char * Foo( void ) +{ + static unsigned char s[256] = "\pHello"; + return s; +} + diff --git a/test/CodeGen/pointer-arithmetic.c b/test/CodeGen/pointer-arithmetic.c new file mode 100644 index 000000000000..5049875dd3ed --- /dev/null +++ b/test/CodeGen/pointer-arithmetic.c @@ -0,0 +1,22 @@ +// RUN: clang-cc -S %s -o - + +typedef int Int; + +int f0(int *a, Int *b) { return a - b; } + +int f1(const char *a, char *b) { return b - a; } + +// GNU extensions +typedef void (*FP)(void); +void *f2(void *a, int b) { return a + b; } +void *f2_1(void *a, int b) { return (a += b); } +void *f3(int a, void *b) { return a + b; } +void *f3_1(int a, void *b) { return (a += b); } +void *f4(void *a, int b) { return a - b; } +void *f4_1(void *a, int b) { return (a -= b); } +FP f5(FP a, int b) { return a + b; } +FP f5_1(FP a, int b) { return (a += b); } +FP f6(int a, FP b) { return a + b; } +FP f6_1(int a, FP b) { return (a += b); } +FP f7(FP a, int b) { return a - b; } +FP f7_1(FP a, int b) { return (a -= b); } diff --git a/test/CodeGen/pointer-cmp-type.c b/test/CodeGen/pointer-cmp-type.c new file mode 100644 index 000000000000..d88c0911ba48 --- /dev/null +++ b/test/CodeGen/pointer-cmp-type.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -emit-llvm %s -o - | grep "icmp ult" + +int a(char* a, char* b) {return a<b;} diff --git a/test/CodeGen/pointer-to-int.c b/test/CodeGen/pointer-to-int.c new file mode 100644 index 000000000000..e40bd91d8f99 --- /dev/null +++ b/test/CodeGen/pointer-to-int.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -emit-llvm %s -o - + +int test(void* i) +{ + return (int)i; +} + +// rdar://6093986 +int test2(void) { + float x[2]; + return x; +} + diff --git a/test/CodeGen/private-extern.c b/test/CodeGen/private-extern.c new file mode 100644 index 000000000000..f3ffe5461d06 --- /dev/null +++ b/test/CodeGen/private-extern.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm -o %t %s && +// RUN: grep '@g0 = external hidden constant i32' %t && +// RUN: grep '@g1 = hidden constant i32 1' %t + +__private_extern__ const int g0; +__private_extern__ const int g1 = 1; + +int f0(void) { + return g0; +} diff --git a/test/CodeGen/rdr-6098585-default-after-caserange.c b/test/CodeGen/rdr-6098585-default-after-caserange.c new file mode 100644 index 000000000000..3a11ad64299c --- /dev/null +++ b/test/CodeGen/rdr-6098585-default-after-caserange.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t && +// RUN: grep "ret i32" %t | count 1 && +// RUN: grep "ret i32 10" %t | count 1 + +// Ensure that default after a case range is not ignored. + +static int f1(unsigned x) { + switch(x) { + case 10 ... 0xFFFFFFFF: + return 0; + default: + return 10; + } +} + +int g() { + return f1(2); +} diff --git a/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c b/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c new file mode 100644 index 000000000000..f1d15dcd4fd5 --- /dev/null +++ b/test/CodeGen/rdr-6098585-default-fallthrough-to-caserange.c @@ -0,0 +1,20 @@ +// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t && +// RUN: grep "ret i32 10" %t + +// Ensure that this doesn't compile to infinite loop in g() due to +// miscompilation of fallthrough from default to a (tested) case +// range. + +static int f0(unsigned x) { + switch(x) { + default: + x += 1; + case 10 ... 0xFFFFFFFF: + return 0; + } +} + +int g() { + f0(1); + return 10; +} diff --git a/test/CodeGen/rdr-6098585-empty-case-range.c b/test/CodeGen/rdr-6098585-empty-case-range.c new file mode 100644 index 000000000000..ca5ff1b71225 --- /dev/null +++ b/test/CodeGen/rdr-6098585-empty-case-range.c @@ -0,0 +1,23 @@ +// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t && +// RUN: grep "ret i32" %t | count 2 && +// RUN: grep "ret i32 3" %t | count 2 + +// This generated incorrect code because of poor switch chaining. +int f1(int x) { + switch(x) { + default: + return 3; + case 10 ... 0xFFFFFFFF: + return 0; + } +} + +// This just asserted because of the way case ranges were calculated. +int f2(int x) { + switch (x) { + default: + return 3; + case 10 ... -1: + return 0; + } +} diff --git a/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c b/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c new file mode 100644 index 000000000000..b34744970610 --- /dev/null +++ b/test/CodeGen/rdr-6098585-fallthrough-to-empty-range.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t && +// RUN: grep "ret i32 %" %t + +// Make sure return is not constant (if empty range is skipped or miscompiled) + +int f0(unsigned x) { + switch(x) { + case 2: + // fallthrough empty range + case 10 ... 9: + return 10; + default: + return 0; + } +} diff --git a/test/CodeGen/rdr-6098585-unsigned-caserange.c b/test/CodeGen/rdr-6098585-unsigned-caserange.c new file mode 100644 index 000000000000..80035982e1f4 --- /dev/null +++ b/test/CodeGen/rdr-6098585-unsigned-caserange.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -triple i386-unknown-unknown --emit-llvm-bc -o - %s | opt -std-compile-opts | llvm-dis > %t && +// RUN: grep "ret i32" %t | count 1 && +// RUN: grep "ret i32 3" %t | count 1 + +int f2(unsigned x) { + switch(x) { + default: + return 3; + case 0xFFFFFFFF ... 1: // This range should be empty because x is unsigned. + return 0; + } +} diff --git a/test/CodeGen/rdr-6732143-dangling-block-reference.m b/test/CodeGen/rdr-6732143-dangling-block-reference.m new file mode 100644 index 000000000000..2d1baa622009 --- /dev/null +++ b/test/CodeGen/rdr-6732143-dangling-block-reference.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm %s -o - + +void f0(id x) { + @synchronized (x) { + do { ; } while(0); + @try { + } @finally { + } + } +} diff --git a/test/CodeGen/regparm.c b/test/CodeGen/regparm.c new file mode 100644 index 000000000000..fdf07ead6de7 --- /dev/null +++ b/test/CodeGen/regparm.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o - | grep inreg | count 2 + +#define FASTCALL __attribute__((regparm(2))) + +typedef struct { + int aaa; + double bbbb; + int ccc[200]; +} foo; + +static void FASTCALL +reduced(char b, double c, foo* d, double e, int f) +{ +} + +int +main(void) { + reduced(0, 0.0, 0, 0.0, 0); +} diff --git a/test/CodeGen/shared-string-literals.c b/test/CodeGen/shared-string-literals.c new file mode 100644 index 000000000000..a05975b4aeb7 --- /dev/null +++ b/test/CodeGen/shared-string-literals.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -emit-llvm %s -o %t + +char *globalString = "abc"; +char *globalStringArray[5] = { "123", "abc" }; +char *anotherGlobalString = "123"; + +int main() { + printf("123"); +} diff --git a/test/CodeGen/sizeof-vla.c b/test/CodeGen/sizeof-vla.c new file mode 100644 index 000000000000..af5088553e48 --- /dev/null +++ b/test/CodeGen/sizeof-vla.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s + +// PR3442 + +static void *g(unsigned long len); + +void +f(int n) +{ + unsigned begin_set[n]; + + g(sizeof(begin_set)); +} diff --git a/test/CodeGen/statements.c b/test/CodeGen/statements.c new file mode 100644 index 000000000000..1ff7601adf68 --- /dev/null +++ b/test/CodeGen/statements.c @@ -0,0 +1,13 @@ +// RUN: clang-cc < %s -emit-llvm + +void test1(int x) { +switch (x) { +case 111111111111111111111111111111111111111: +bar(); +} +} + +// Mismatched type between return and function result. +int test2() { return; } +void test3() { return 4; } + diff --git a/test/CodeGen/static-forward-decl-fun.c b/test/CodeGen/static-forward-decl-fun.c new file mode 100644 index 000000000000..a945df3d3b38 --- /dev/null +++ b/test/CodeGen/static-forward-decl-fun.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +static int staticfun(void); +int (*staticuse1)(void) = staticfun; +static int staticfun() {return 1;} +int (*staticuse2)(void) = staticfun; diff --git a/test/CodeGen/static-forward-decl.c b/test/CodeGen/static-forward-decl.c new file mode 100644 index 000000000000..f12c22fb41af --- /dev/null +++ b/test/CodeGen/static-forward-decl.c @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -emit-llvm -o - -triple=i686-apple-darwin9 | grep "global i32 10" + +static int i; +int*j=&i; +static int i = 10; diff --git a/test/CodeGen/static-local-union.c b/test/CodeGen/static-local-union.c new file mode 100644 index 000000000000..f276b200eb10 --- /dev/null +++ b/test/CodeGen/static-local-union.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm < %s + +int a() {static union{int a;} r[2] = {1,2};return r[1].a;} + diff --git a/test/CodeGen/static-order.c b/test/CodeGen/static-order.c new file mode 100644 index 000000000000..243e96bf3e65 --- /dev/null +++ b/test/CodeGen/static-order.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -emit-llvm -o - %s | not grep "zeroinitializer" + +struct s { + int a; +}; + +static void *v; + +static struct s a; + +static struct s a = { + 10 +}; + +void *f() +{ + if (a.a) + return v; +} diff --git a/test/CodeGen/staticinit.c b/test/CodeGen/staticinit.c new file mode 100644 index 000000000000..91fcdcf69f00 --- /dev/null +++ b/test/CodeGen/staticinit.c @@ -0,0 +1,31 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s && +// RUN: grep "g.b = internal global i8. getelementptr" %t && + +struct AStruct { + int i; + char *s; + double d; +}; + +void f() { + static int i = 42; + static int is[] = { 1, 2, 3, 4 }; + static char* str = "forty-two"; + static char* strs[] = { "one", "two", "three", "four" }; + static struct AStruct myStruct = { 1, "two", 3.0 }; +} + +void g() { + static char a[10]; + static char *b = a; +} + +struct s { void *p; }; + +void foo(void) { + static struct s var = {((void*)&((char*)0)[0])}; +} + +// RUN: grep "f1.l0 = internal global i32 ptrtoint (i32 ()\* @f1 to i32)" %t +int f1(void) { static int l0 = (unsigned) f1; } + diff --git a/test/CodeGen/stdcall-fastcall.c b/test/CodeGen/stdcall-fastcall.c new file mode 100644 index 000000000000..11b652178ca8 --- /dev/null +++ b/test/CodeGen/stdcall-fastcall.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -emit-llvm < %s | grep 'fastcallcc' | count 4 +// RUN: clang-cc -emit-llvm < %s | grep 'stdcallcc' | count 4 + +void __attribute__((fastcall)) f1(void); +void __attribute__((stdcall)) f2(void); +void __attribute__((fastcall)) f3(void) { + f1(); +} +void __attribute__((stdcall)) f4(void) { + f2(); +} + +int main(void) { + f3(); f4(); + return 0; +} + diff --git a/test/CodeGen/string-init.c b/test/CodeGen/string-init.c new file mode 100644 index 000000000000..38c7ec057597 --- /dev/null +++ b/test/CodeGen/string-init.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm %s -o %t && +// RUN: grep 'internal constant \[10 x i8\]' %t && +// RUN: not grep -F "[5 x i8]" %t && +// RUN: not grep "store " %t + +void test(void) { + char a[10] = "asdf"; + char b[10] = { "asdf" }; +} + diff --git a/test/CodeGen/string-literal.c b/test/CodeGen/string-literal.c new file mode 100644 index 000000000000..a4011938c106 --- /dev/null +++ b/test/CodeGen/string-literal.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -emit-llvm %s -o - + +int main() { + char a[10] = "abc"; + + void *foo = L"AB"; +} diff --git a/test/CodeGen/struct-comma.c b/test/CodeGen/struct-comma.c new file mode 100644 index 000000000000..d7f50da13122 --- /dev/null +++ b/test/CodeGen/struct-comma.c @@ -0,0 +1,4 @@ +// RUN: clang-cc %s -emit-llvm -o - + +struct S {int a, b;} x; +void a(struct S* b) {*b = (r(), x);} diff --git a/test/CodeGen/struct-copy.c b/test/CodeGen/struct-copy.c new file mode 100644 index 000000000000..62c29aba6c9c --- /dev/null +++ b/test/CodeGen/struct-copy.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -emit-llvm %s -o - | grep 'call.*llvm.memcpy' +struct x { int a[100]; }; + + +void foo(struct x *P, struct x *Q) { + *P = *Q; +} diff --git a/test/CodeGen/struct-init.c b/test/CodeGen/struct-init.c new file mode 100644 index 000000000000..a38442b1a88f --- /dev/null +++ b/test/CodeGen/struct-init.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -emit-llvm -o - + +typedef struct _zend_ini_entry zend_ini_entry; +struct _zend_ini_entry { + void *mh_arg1; +}; + +char a; + +const zend_ini_entry ini_entries[] = { + { ((char*)&((zend_ini_entry*)0)->mh_arg1 - (char*)(void*)0)}, +}; diff --git a/test/CodeGen/struct-passing.c b/test/CodeGen/struct-passing.c new file mode 100644 index 000000000000..9a4f47651b74 --- /dev/null +++ b/test/CodeGen/struct-passing.c @@ -0,0 +1,21 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s && +// RUN: grep 'declare i32 @f0() readnone$' %t && +// RUN: grep 'declare i32 @f1() readonly$' %t && +// RUN: grep 'declare void @f2(.* noalias sret)$' %t && +// RUN: grep 'declare void @f3(.* noalias sret)$' %t && +// RUN: grep 'declare void @f4(.* byval)$' %t && +// RUN: grep 'declare void @f5(.* byval)$' %t && +// RUN: true +// PR3835 + +typedef int T0; +typedef struct { int a[16]; } T1; + +T0 __attribute__((const)) f0(void); +T0 __attribute__((pure)) f1(void); +T1 __attribute__((const)) f2(void); +T1 __attribute__((pure)) f3(void); +void __attribute__((const)) f4(T1 a); +void __attribute__((pure)) f5(T1 a); + +void *ps[] = { f0, f1, f2, f3, f4, f5 }; diff --git a/test/CodeGen/struct-x86-darwin.c b/test/CodeGen/struct-x86-darwin.c new file mode 100644 index 000000000000..050e26dcab9e --- /dev/null +++ b/test/CodeGen/struct-x86-darwin.c @@ -0,0 +1,25 @@ +// RUN: clang-cc < %s -emit-llvm > %t1 -triple=i686-apple-darwin9 +// Run grep "STest1 = type <{ i32, \[4 x i16\], double }>" %t1 && +// RUN: grep "STest2 = type <{ i16, i16, i32, i32 }>" %t1 && +// RUN: grep "STest3 = type <{ i8, i8, i16, i32 }>" %t1 && +// RUN: grep "STestB1 = type <{ i8, i8 }>" %t1 && +// RUN: grep "STestB2 = type <{ i8, i8, i8 }>" %t1 && +// RUN: grep "STestB3 = type <{ i8, i8 }>" %t1 && +// RUN: grep "STestB4 = type <{ i8, i8, i8, i8 }>" %t1 && +// RUN: grep "STestB5 = type <{ i8, i8, i8, i8, i8, i8 }>" %t1 && +// RUN: grep "STestB6 = type <{ i8, i8, i8, i8 }>" %t1 +// Test struct layout for x86-darwin target + +struct STest1 {int x; short y[4]; double z; } st1; +struct STest2 {short a,b; int c,d; } st2; +struct STest3 {char a; short b; int c; } st3; + +// Bitfields +struct STestB1 {char a; char b:2; } stb1; +struct STestB2 {char a; char b:5; char c:4; } stb2; +struct STestB3 {char a; char b:2; } stb3; +struct STestB4 {char a; short b:2; char c; } stb4; +struct STestB5 {char a; short b:10; char c; } stb5; +struct STestB6 {int a:1; char b; int c:13 } stb6; + +// Packed struct STestP1 {char a; short b; int c; } __attribute__((__packed__)) stp1; diff --git a/test/CodeGen/struct.c b/test/CodeGen/struct.c new file mode 100644 index 000000000000..ed3684280e88 --- /dev/null +++ b/test/CodeGen/struct.c @@ -0,0 +1,192 @@ +// RUN: clang-cc -triple i386-unknown-unknown %s -emit-llvm -o - + +struct { + int x; + int y; +} point; + +void fn1() { + point.x = 42; +} + +/* Nested member */ +struct { + struct { + int a; + int b; + } p1; +} point2; + +void fn2() { + point2.p1.a = 42; +} + +/* Indirect reference */ +typedef struct __sf { + unsigned char *c; + short flags; +} F; + +typedef struct __sf2 { + F *ff; +} F2; + +int fn3(F2 *c) { + if (c->ff->c >= 0) + return 1; + else + return 0; +} + +/* Nested structs */ +typedef struct NA { + int data; + struct NA *next; +} NA; +void f1() { NA a; } + +typedef struct NB { + int d1; + struct _B2 { + int d2; + struct NB *n2; + } B2; +} NB; + +void f2() { NB b; } + +extern NB *f3(); +void f4() { + f3()->d1 = 42; +} + +void f5() { + (f3())->d1 = 42; +} + +/* Function calls */ +typedef struct { + int location; + int length; +} range; +extern range f6(); +void f7() +{ + range r = f6(); +} + +/* Member expressions */ +typedef struct { + range range1; + range range2; +} rangepair; + +void f8() +{ + rangepair p; + + range r = p.range1; +} + +void f9(range *p) +{ + range r = *p; +} + +void f10(range *p) +{ + range r = p[0]; +} + +/* _Bool types */ + +struct _w +{ + short a,b; + short c,d; + short e,f; + short g; + + unsigned int h,i; + + _Bool j,k; +} ws; + +/* Implicit casts (due to typedefs) */ +typedef struct _a +{ + int a; +} a; + +void f11() +{ + struct _a a1; + a a2; + + a1 = a2; + a2 = a1; +} + +/* Implicit casts (due to const) */ +void f12() +{ + struct _a a1; + const struct _a a2; + + a1 = a2; +} + +/* struct initialization */ +struct a13 {int b; int c;}; +struct a13 c13 = {5}; +typedef struct a13 a13; +struct a14 { short a; int b; } x = {1, 1}; + +/* flexible array members */ +struct a15 {char a; int b[];} c15; +int a16(void) {c15.a = 1;} + +/* compound literals */ +void f13() +{ + a13 x; x = (a13){1,2}; +} + +/* va_arg */ +int f14(int i, ...) { + __builtin_va_list l; + __builtin_va_start(l,i); + a13 b = __builtin_va_arg(l, a13); + int c = __builtin_va_arg(l, a13).c; + return b.b; +} + +/* Attribute packed */ +struct __attribute__((packed)) S2839 { double a[19]; signed char b; } s2839[5]; + +struct __attribute__((packed)) SS { long double a; char b; } SS; + + +/* As lvalue */ + +int f15() { + extern range f15_ext(); + return f15_ext().location; +} + +range f16() { + extern rangepair f16_ext(); + return f16_ext().range1; +} + +int f17() { + extern range f17_ext(); + range r; + return (r = f17_ext()).location; +} + +range f18() { + extern rangepair f18_ext(); + rangepair rp; + return (rp = f18_ext()).range1; +} diff --git a/test/CodeGen/switch.c b/test/CodeGen/switch.c new file mode 100644 index 000000000000..3254fbf3c938 --- /dev/null +++ b/test/CodeGen/switch.c @@ -0,0 +1,87 @@ +// RUN: clang-cc %s -emit-llvm-bc -o - | opt -std-compile-opts -disable-output + +int foo(int i) { + int j = 0; + switch (i) { + case -1: + j = 1; break; + case 1 : + j = 2; break; + case 2: + j = 3; break; + default: + j = 42; break; + } + j = j + 1; + return j; +} + + +int foo2(int i) { + int j = 0; + switch (i) { + case 1 : + j = 2; break; + case 2 ... 10: + j = 3; break; + default: + j = 42; break; + } + j = j + 1; + return j; +} + + +int foo3(int i) { + int j = 0; + switch (i) { + default: + j = 42; break; + case 111: + j = 111; break; + case 0 ... 100: + j = 1; break; + case 222: + j = 222; break; + } + return j; +} + + +int foo4(int i) { + int j = 0; + switch (i) { + case 111: + j = 111; break; + case 0 ... 100: + j = 1; break; + case 222: + j = 222; break; + default: + j = 42; break; + case 501 ... 600: + j = 5; break; + } + return j; +} + +void foo5(){ + switch(0){ + default: + if (0) { + + } + } +} + +void foo6(){ + switch(0){ + } +} + +void foo7(){ + switch(0){ + foo7(); + } +} + diff --git a/test/CodeGen/tentative-decls.c b/test/CodeGen/tentative-decls.c new file mode 100644 index 000000000000..3301c234c55a --- /dev/null +++ b/test/CodeGen/tentative-decls.c @@ -0,0 +1,39 @@ +// RUN: clang-cc -emit-llvm -o %t %s && + +// RUN: grep '@r = common global \[1 x .*\] zeroinitializer' %t && + +int r[]; +int (*a)[] = &r; + +struct s0; +struct s0 x; +// RUN: grep '@x = common global .struct.s0 zeroinitializer' %t && + +struct s0 y; +// RUN: grep '@y = common global .struct.s0 zeroinitializer' %t && +struct s0 *f0() { + return &y; +} + +struct s0 { + int x; +}; + +// RUN: grep '@b = common global \[1 x .*\] zeroinitializer' %t && +int b[]; +int *f1() { + return b; +} + +// Check that the most recent tentative definition wins. +// RUN: grep '@c = common global \[4 x .*\] zeroinitializer' %t && +int c[]; +int c[4]; + +// Check that we emit static tentative definitions +// RUN: grep '@c5 = internal global \[1 x .*\] zeroinitializer' %t && +static int c5[]; +static int func() { return c5[0]; } +int callfunc() { return func(); } + +// RUN: true diff --git a/test/CodeGen/thread-specifier.c b/test/CodeGen/thread-specifier.c new file mode 100644 index 000000000000..456f7a6d9761 --- /dev/null +++ b/test/CodeGen/thread-specifier.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -triple i686-pc-linux-gnu -emit-llvm -o - %s | grep thread_local | count 4 + +__thread int a; +extern __thread int b; +int c() { return &b; } +int d() { + __thread static int e; + __thread static union {float a; int b;} f = {.b = 1}; +} + diff --git a/test/CodeGen/trapv.c b/test/CodeGen/trapv.c new file mode 100644 index 000000000000..c96488b8e99b --- /dev/null +++ b/test/CodeGen/trapv.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -ftrapv %s -emit-llvm -o %t && +// RUN: grep "__overflow_handler" %t | count 2 + +unsigned int ui, uj, uk; +int i, j, k; + +void foo() { + ui = uj + uk; + i = j + k; +} diff --git a/test/CodeGen/typedef-func.c b/test/CodeGen/typedef-func.c new file mode 100644 index 000000000000..a64426ddb274 --- /dev/null +++ b/test/CodeGen/typedef-func.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -emit-llvm < %s + +// PR2414 +struct mad_frame{}; +enum mad_flow {}; + +typedef enum mad_flow filter_func_t(void *, struct mad_frame *); + +filter_func_t mono_filter; + +void addfilter2(filter_func_t *func){} + +void setup_filters() +{ + addfilter2( mono_filter); +} diff --git a/test/CodeGen/typedef.c b/test/CodeGen/typedef.c new file mode 100644 index 000000000000..3bdd52f6c572 --- /dev/null +++ b/test/CodeGen/typedef.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -emit-llvm %s -o - + +typedef struct { int i; } Value; +typedef Value *PValue; + +int get_value(PValue v) { + return v->i; +} diff --git a/test/CodeGen/types.c b/test/CodeGen/types.c new file mode 100644 index 000000000000..75cb851c2599 --- /dev/null +++ b/test/CodeGen/types.c @@ -0,0 +1,34 @@ +// RUN: clang-cc -emit-llvm <%s + +struct FileName { + struct FileName *next; +} *fnhead; + + +struct ieeeExternal { + struct ieeeExternal *next; +} *exthead; + + +void test1() +{ + struct ieeeExternal *exttmp = exthead; +} + +struct MpegEncContext; +typedef struct MpegEncContext {int pb;} MpegEncContext; +static void test2(void) {MpegEncContext s; s.pb;} + + +struct Village; + +struct List { + struct Village *v; +}; + +struct Village { + struct List returned; +}; + +void test3(struct List a) { +} diff --git a/test/CodeGen/uint128_t.c b/test/CodeGen/uint128_t.c new file mode 100644 index 000000000000..b3bf7279623f --- /dev/null +++ b/test/CodeGen/uint128_t.c @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -emit-llvm -o - -triple=x86_64-apple-darwin9 + +typedef unsigned long long uint64_t; +extern uint64_t numer; +extern uint64_t denom; + +uint64_t +f(uint64_t val) +{ + __uint128_t tmp; + + tmp = val; + tmp *= numer; + tmp /= denom; + + return tmp; +} + diff --git a/test/CodeGen/union-init.c b/test/CodeGen/union-init.c new file mode 100644 index 000000000000..c882d3180c72 --- /dev/null +++ b/test/CodeGen/union-init.c @@ -0,0 +1,31 @@ +// RUN: clang-cc -emit-llvm < %s -o - + +// A nice and complicated initialization example with unions from Python +typedef int Py_ssize_t; + +typedef union _gc_head { + struct { + union _gc_head *gc_next; + union _gc_head *gc_prev; + Py_ssize_t gc_refs; + } gc; + long double dummy; /* force worst-case alignment */ +} PyGC_Head; + +struct gc_generation { + PyGC_Head head; + int threshold; /* collection threshold */ + int count; /* count of allocations or collections of younger + generations */ +}; + +#define NUM_GENERATIONS 3 +#define GEN_HEAD(n) (&generations[n].head) + +/* linked lists of container objects */ +struct gc_generation generations[NUM_GENERATIONS] = { + /* PyGC_Head, threshold, count */ + {{{GEN_HEAD(0), GEN_HEAD(0), 0}}, 700, 0}, + {{{GEN_HEAD(1), GEN_HEAD(1), 0}}, 10, 0}, + {{{GEN_HEAD(2), GEN_HEAD(2), 0}}, 10, 0}, +}; diff --git a/test/CodeGen/union.c b/test/CodeGen/union.c new file mode 100644 index 000000000000..4884690f3fdc --- /dev/null +++ b/test/CodeGen/union.c @@ -0,0 +1,41 @@ +// RUN: clang-cc %s -emit-llvm -o - + +union u_tag { + int a; + float b; +} u; + +void f() { + u.b = 11; +} + +float get_b(union u_tag *my_u) { + return my_u->b; +} + +int f2( float __x ) { + union{ + float __f; + unsigned int __u; + }__u; + return (int)(__u.__u >> 31); +} + +typedef union { int i; int *j; } value; + +int f3(value v) { + return *v.j; +} + +enum E9 { one, two }; +union S65 { enum E9 a; } ; union S65 s65; +void fS65() { enum E9 e = s65.a; } + +typedef union{ + unsigned char x[65536]; +} q; +int qfunc() {q buf; unsigned char* x = buf.x;} + +union RR {_Bool a : 1;} RRU; +int RRF(void) {return RRU.a;} + diff --git a/test/CodeGen/unwind-attr.c b/test/CodeGen/unwind-attr.c new file mode 100644 index 000000000000..b2890c4c10de --- /dev/null +++ b/test/CodeGen/unwind-attr.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -fexceptions -emit-llvm -o - %s | grep "@foo() {" | count 1 && +// RUN: clang-cc -emit-llvm -o - %s | grep "@foo() nounwind {" | count 1 + +int foo(void) { +} diff --git a/test/CodeGen/var-align.c b/test/CodeGen/var-align.c new file mode 100644 index 000000000000..b0b62ae26473 --- /dev/null +++ b/test/CodeGen/var-align.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -emit-llvm %s -o - | grep "align 16" | count 2 + +__attribute((aligned(16))) float a[128]; +union {int a[4]; __attribute((aligned(16))) float b[4];} u; diff --git a/test/CodeGen/variable-array.c b/test/CodeGen/variable-array.c new file mode 100644 index 000000000000..f5621c289d7a --- /dev/null +++ b/test/CodeGen/variable-array.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -emit-llvm < %s | grep puts | count 4 + +// PR3248 +int a(int x) +{ + int (*y)[x]; + return sizeof(*(puts("asdf"),y)); +} + +// PR3247 +int b() { + return sizeof(*(char(*)[puts("asdf")])0); +} + +// PR3247 +int c() { + static int (*y)[puts("asdf")]; + return sizeof(*y); +} diff --git a/test/CodeGen/vector.c b/test/CodeGen/vector.c new file mode 100644 index 000000000000..2e753b42c4d7 --- /dev/null +++ b/test/CodeGen/vector.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -emit-llvm %s -o - +typedef short __v4hi __attribute__ ((__vector_size__ (8))); + +void f() +{ + __v4hi A = (__v4hi)0LL; +} + +__v4hi x = {1,2,3}; +__v4hi y = {1,2,3,4}; + +typedef int vty __attribute((vector_size(16))); +int a() { vty b; return b[2LL]; } diff --git a/test/CodeGen/visibility.c b/test/CodeGen/visibility.c new file mode 100644 index 000000000000..bb9b6e0d50ce --- /dev/null +++ b/test/CodeGen/visibility.c @@ -0,0 +1,41 @@ +// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=default -emit-llvm -o %t %s && +// RUN: grep '@g_com = common global i32 0' %t && +// RUN: grep '@g_def = global i32 0' %t && +// RUN: grep '@g_ext = external global i32' %t && +// RUN: grep '@g_deferred = internal global' %t && +// RUN: grep 'declare void @f_ext()' %t && +// RUN: grep 'define internal void @f_deferred()' %t && +// RUN: grep 'define i32 @f_def()' %t && +// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=protected -emit-llvm -o %t %s && +// RUN: grep '@g_com = common protected global i32 0' %t && +// RUN: grep '@g_def = protected global i32 0' %t && +// RUN: grep '@g_ext = external global i32' %t && +// RUN: grep '@g_deferred = internal global' %t && +// RUN: grep 'declare void @f_ext()' %t && +// RUN: grep 'define internal void @f_deferred()' %t && +// RUN: grep 'define protected i32 @f_def()' %t && +// RUN: clang-cc -triple i386-unknown-unknown -fvisibility=hidden -emit-llvm -o %t %s && +// RUN: grep '@g_com = common hidden global i32 0' %t &&a +// RUN: grep '@g_def = hidden global i32 0' %t && +// RUN: grep '@g_ext = external global i32' %t && +// RUN: grep '@g_deferred = internal global' %t && +// RUN: grep 'declare void @f_ext()' %t && +// RUN: grep 'define internal void @f_deferred()' %t && +// RUN: grep 'define hidden i32 @f_def()' %t && +// RUN: true + +int g_com; +int g_def = 0; +extern int g_ext; +static char g_deferred[] = "hello"; + +extern void f_ext(void); + +static void f_deferred(void) { +} + +int f_def(void) { + f_ext(); + f_deferred(); + return g_com + g_def + g_ext + g_deferred[0]; +} diff --git a/test/CodeGen/vla.c b/test/CodeGen/vla.c new file mode 100644 index 000000000000..844e49e72c46 --- /dev/null +++ b/test/CodeGen/vla.c @@ -0,0 +1,37 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +int b(char* x); + +// Extremely basic VLA test +void a(int x) { + char arry[x]; + arry[0] = 10; + b(arry); +} + +int c(int n) +{ + return sizeof(int[n]); +} + +int f0(int x) { + int vla[x]; + return vla[x-1]; +} + +void +f(int count) +{ + int a[count]; + + do { } while (0); + + if (a[0] != 3) { + } +} + +void g(int count) { + // Make sure we emit sizes correctly in some obscure cases + int (*a[5])[count]; + int (*b)[][count]; +} diff --git a/test/CodeGen/volatile-1.c b/test/CodeGen/volatile-1.c new file mode 100644 index 000000000000..ac3b4c2e97b2 --- /dev/null +++ b/test/CodeGen/volatile-1.c @@ -0,0 +1,143 @@ +// RUN: clang-cc -Wno-unused-value -emit-llvm < %s -o %t && +// RUN: grep volatile %t | count 145 && +// RUN: grep memcpy %t | count 4 + +volatile int i, j, k; +volatile int ar[5]; +volatile char c; +volatile _Complex int ci; +volatile struct S { +#ifdef __cplusplus + void operator =(volatile struct S&o) volatile; +#endif + int i; +} a, b; + +//void operator =(volatile struct S&o1, volatile struct S&o2) volatile; +#include <stdio.h> + +int main() { + // A use. + i; + // A use of the real part + (float)(ci); + // A use. + (void)ci; + // A use. + (void)a; + // Not a use. + (void)(ci=ci); + // Not a use. + (void)(i=j); + ci+=ci; + (ci += ci) + ci; + asm("nop"); + (i += j) + k; + asm("nop"); + // A use + (i += j) + 1; + asm("nop"); + ci+ci; + // A use. + __real i; + // A use. + +ci; + asm("nop"); + // Not a use. + (void)(i=i); + (float)(i=i); + // A use. + (void)i; + i=i; + i=i=i; +#ifndef __cplusplus + // Not a use. + (void)__builtin_choose_expr(0, i=i, j=j); +#endif + // A use. + k ? (i=i) : (j=j); + (void)(i,(i=i)); + i=i,i; + (i=j,k=j); + (i=j,k); + (i,j); + i=c=k; + i+=k; + // A use of both. + ci; +#ifndef __cplusplus + // A use of _real. + (int)ci; + // A use of both. + (_Bool)ci; +#endif + ci=ci; + ci=ci=ci; + __imag ci = __imag ci = __imag ci; + // Not a use. + __real (i = j); + // Not a use. + __imag i; + + // ============================================================ + // FIXME: Test cases we get wrong. + + // A use. We load all of a into a copy of a, then load i. gcc forgets to do + // the assignment. + // (a = a).i; + + // ============================================================ + // Test cases where we intentionally differ from gcc, due to suspected bugs in + // gcc. + + // Not a use. gcc forgets to do the assignment. + ((a=a),a); + + // Not a use. gcc gets this wrong, it doesn't emit the copy! + // (void)(a=a); + + // Not a use. gcc got this wrong in 4.2 and omitted the side effects + // entirely, but it is fixed in 4.4.0. + __imag (i = j); + +#ifndef __cplusplus + // A use of the real part + (float)(ci=ci); + // Not a use, bug? gcc treats this as not a use, that's probably a bug due to + // tree folding ignoring volatile. + (int)(ci=ci); +#endif + + // A use. + (float)(i=i); + // A use. gcc treats this as not a use, that's probably a bug due to tree + // folding ignoring volatile. + (int)(i=i); + + // A use. + -(i=j); + // A use. gcc treats this a not a use, that's probably a bug due to tree + // folding ignoring volatile. + +(i=k); + + // A use. gcc treats this a not a use, that's probably a bug due to tree + // folding ignoring volatile. + __real (ci=ci); + + // A use. + i + 0; + // A use. + (i=j) + i; + // A use. gcc treats this as not a use, that's probably a bug due to tree + // folding ignoring volatile. + (i=j) + 0; + +#ifdef __cplusplus + (i,j)=k; + (j=k,i)=i; + struct { int x; } s, s1; + printf("s is at %p\n", &s); + printf("s is at %p\n", &(s = s1)); + printf("s.x is at %p\n", &((s = s1).x)); +#endif +} diff --git a/test/CodeGen/volatile.c b/test/CodeGen/volatile.c new file mode 100644 index 000000000000..212a0aeb1e35 --- /dev/null +++ b/test/CodeGen/volatile.c @@ -0,0 +1,94 @@ +// RUN: clang-cc -emit-llvm < %s -o %t && +// RUN: grep volatile %t | count 25 && +// RUN: grep memcpy %t | count 7 + +// The number 25 comes from the current codegen for volatile loads; +// if this number changes, it's not necessarily something wrong, but +// something has changed to affect volatile load/store codegen + +int S; +volatile int vS; + +int* pS; +volatile int* pvS; + +int A[10]; +volatile int vA[10]; + +struct { int x; } F; +struct { volatile int x; } vF; + +struct { int x; } F2; +volatile struct { int x; } vF2; +volatile struct { int x; } *vpF2; + +struct { struct { int y; } x; } F3; +volatile struct { struct { int y; } x; } vF3; + +struct { int x:3; } BF; +struct { volatile int x:3; } vBF; + +typedef int v4si __attribute__ ((vector_size (16))); +v4si V; +volatile v4si vV; + +typedef __attribute__(( ext_vector_type(4) )) int extv4; +extv4 VE; +volatile extv4 vVE; + +volatile struct {int x;} aggFct(void); + +void main() { + int i; + + // load + i=S; + i=vS; + i=*pS; + i=*pvS; + i=A[2]; + i=vA[2]; + i=F.x; + i=vF.x; + i=F2.x; + i=vF2.x; + i=vpF2->x; + i=F3.x.y; + i=vF3.x.y; + i=BF.x; + i=vBF.x; + i=V[3]; + i=vV[3]; + i=VE.yx[1]; + i=vVE.zy[1]; + i = aggFct().x; + + + // store + S=i; + vS=i; + *pS=i; + *pvS=i; + A[2]=i; + vA[2]=i; + F.x=i; + vF.x=i; + F2.x=i; + vF2.x=i; + vpF2->x=i; + vF3.x.y=i; + BF.x=i; + vBF.x=i; + V[3]=i; + vV[3]=i; + + // other ops: + ++S; + ++vS; + i+=S; + i+=vS; + (void)vF2; + vF2 = vF2; + vF2 = vF2 = vF2; + vF2 = (vF2, vF2); +} diff --git a/test/CodeGen/weak-global.c b/test/CodeGen/weak-global.c new file mode 100644 index 000000000000..d4ee52f48956 --- /dev/null +++ b/test/CodeGen/weak-global.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -emit-llvm < %s | grep common + +int i; diff --git a/test/CodeGen/weak-incomplete.c b/test/CodeGen/weak-incomplete.c new file mode 100644 index 000000000000..a15dbac03cb7 --- /dev/null +++ b/test/CodeGen/weak-incomplete.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -emit-llvm < %s | grep 'extern_weak' | count 1 + +struct S; +void __attribute__((weak)) foo1(struct S); +void (*foo2)(struct S) = foo1; diff --git a/test/CodeGen/whilestmt.c b/test/CodeGen/whilestmt.c new file mode 100644 index 000000000000..95e18f4d21ff --- /dev/null +++ b/test/CodeGen/whilestmt.c @@ -0,0 +1,62 @@ +// RUN: clang-cc %s -emit-llvm -o - + +int bar(); +int foo() { + int i; + i = 1 + 2; + while(1) { + i = bar(); + i = bar(); + }; + return i; +} + + +int foo1() { + int i; + i = 1 + 2; + while(1) { + i = bar(); + if (i == 42) + break; + i = bar(); + }; + return i; +} + + +int foo2() { + int i; + i = 1 + 2; + while(1) { + i = bar(); + if (i == 42) + continue; + i = bar(); + }; + return i; +} + + +int foo3() { + int i; + i = 1 + 2; + while(1) { + i = bar(); + if (i == 42) + break; + }; + return i; +} + + +int foo4() { + int i; + i = 1 + 2; + while(1) { + i = bar(); + if (i == 42) + continue; + }; + return i; +} diff --git a/test/CodeGen/writable-strings.c b/test/CodeGen/writable-strings.c new file mode 100644 index 000000000000..c8b70d5f0540 --- /dev/null +++ b/test/CodeGen/writable-strings.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -emit-llvm -o - -fwritable-strings %s + +int main() { + char *str = "abc"; + str[0] = '1'; + printf("%s", str); +} + diff --git a/test/CodeGen/x86.c b/test/CodeGen/x86.c new file mode 100644 index 000000000000..10808dca8782 --- /dev/null +++ b/test/CodeGen/x86.c @@ -0,0 +1,23 @@ +// RUN: clang-cc %s -triple=i686-pc-linux-gnu -emit-llvm -o - > %t1 +// RUN: grep "ax" %t1 && +// RUN: grep "bx" %t1 && +// RUN: grep "cx" %t1 && +// RUN: grep "dx" %t1 && +// RUN: grep "di" %t1 && +// RUN: grep "si" %t1 && +// RUN: grep "st" %t1 && +// RUN: grep "st(1)" %t1 + +void test1() { + int d1, d2; + asm ("" : "=a" (d1), "=b" (d2) : + "c" (0), "d" (0), "S" (0), "D" (0), "t" (0), "u" (0)); +} + + +// rdar://6803924 +typedef double T __attribute__ ((__vector_size__ (16))); +T test2(T va) { + return __builtin_ia32_shufpd(va, va, 3); +} + diff --git a/test/CodeGen/x86_32-arguments.c b/test/CodeGen/x86_32-arguments.c new file mode 100644 index 000000000000..8980c66b2072 --- /dev/null +++ b/test/CodeGen/x86_32-arguments.c @@ -0,0 +1,157 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s && +// RUN: grep 'define signext i8 @f0()' %t && +// RUN: grep 'define signext i16 @f1()' %t && +// RUN: grep 'define i32 @f2()' %t && +// RUN: grep 'define float @f3()' %t && +// RUN: grep 'define double @f4()' %t && +// RUN: grep 'define x86_fp80 @f5()' %t && +// RUN: grep 'define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8\* %a4)' %t && +// RUN: grep 'define void @f7(i32 %a0)' %t && +// RUN: grep 'define i64 @f8_1()' %t && +// RUN: grep 'define void @f8_2(i32 %a0.0, i32 %a0.1)' %t && + +char f0(void) { +} + +short f1(void) { +} + +int f2(void) { +} + +float f3(void) { +} + +double f4(void) { +} + +long double f5(void) { +} + +void f6(char a0, short a1, int a2, long long a3, void *a4) { +} + +typedef enum { A, B, C } E; + +void f7(E a0) { +} + +struct s8 { + int a; + int b; +}; +struct s8 f8_1(void) { +} +void f8_2(struct s8 a0) { +} + +// This should be passed just as s8. + +// RUN: grep 'define i64 @f9_1()' %t && + +// FIXME: llvm-gcc expands this, this may have some value for the +// backend in terms of optimization but doesn't change the ABI. +// RUN: grep 'define void @f9_2(%.truct.s9\* byval %a0)' %t && +struct s9 { + int a : 17; + int b; +}; +struct s9 f9_1(void) { +} +void f9_2(struct s9 a0) { +} + +// Return of small structures and unions + +// RUN: grep 'float @f10()' %t && +struct s10 { + union { }; + float f; +} f10(void) {} + +// Small vectors and 1 x {i64,double} are returned in registers + +// RUN: grep 'i32 @f11()' %t && +// RUN: grep -F 'void @f12(<2 x i32>* noalias sret %agg.result)' %t && +// RUN: grep 'i64 @f13()' %t && +// RUN: grep 'i64 @f14()' %t && +// RUN: grep '<2 x i64> @f15()' %t && +// RUN: grep '<2 x i64> @f16()' %t && +typedef short T11 __attribute__ ((vector_size (4))); +T11 f11(void) {} +typedef int T12 __attribute__ ((vector_size (8))); +T12 f12(void) {} +typedef long long T13 __attribute__ ((vector_size (8))); +T13 f13(void) {} +typedef double T14 __attribute__ ((vector_size (8))); +T14 f14(void) {} +typedef long long T15 __attribute__ ((vector_size (16))); +T15 f15(void) {} +typedef double T16 __attribute__ ((vector_size (16))); +T16 f16(void) {} + +// And when the single element in a struct (but not for 64 and +// 128-bits). + +// RUN: grep 'i32 @f17()' %t && +// RUN: grep -F 'void @f18(%2* noalias sret %agg.result)' %t && +// RUN: grep -F 'void @f19(%3* noalias sret %agg.result)' %t && +// RUN: grep -F 'void @f20(%4* noalias sret %agg.result)' %t && +// RUN: grep -F 'void @f21(%5* noalias sret %agg.result)' %t && +// RUN: grep -F 'void @f22(%6* noalias sret %agg.result)' %t && +struct { T11 a; } f17(void) {} +struct { T12 a; } f18(void) {} +struct { T13 a; } f19(void) {} +struct { T14 a; } f20(void) {} +struct { T15 a; } f21(void) {} +struct { T16 a; } f22(void) {} + +// Single element structures are handled specially + +// RUN: grep -F 'float @f23()' %t && +// RUN: grep -F 'float @f24()' %t && +// RUN: grep -F 'float @f25()' %t && +struct { float a; } f23(void) {} +struct { float a[1]; } f24(void) {} +struct { struct {} a; struct { float a[1]; } b; } f25(void) {} + +// Small structures are handled recursively +// RUN: grep -F 'i32 @f26()' %t && +// RUN: grep 'void @f27(%.truct.s27\* noalias sret %agg.result)' %t && +struct s26 { struct { char a, b; } a; struct { char a, b; } b; } f26(void) {} +struct s27 { struct { char a, b, c; } a; struct { char a; } b; } f27(void) {} + +// RUN: grep 'void @f28(%.truct.s28\* noalias sret %agg.result)' %t && +struct s28 { int a; int b[]; } f28(void) {} + +// RUN: grep 'define i16 @f29()' %t && +struct s29 { struct { } a[1]; char b; char c; } f29(void) {} + +// RUN: grep 'define i16 @f30()' %t && +struct s30 { char a; char b : 4; } f30(void) {} + +// RUN: grep 'define float @f31()' %t && +struct s31 { char : 0; float b; char : 0; } f31(void) {} + +// RUN: grep 'define i32 @f32()' %t && +struct s32 { char a; unsigned : 0; } f32(void) {} + +// RUN: grep 'define float @f33()' %t && +struct s33 { float a; long long : 0; } f33(void) {} + +// RUN: grep 'define float @f34()' %t && +struct s34 { struct { int : 0; } a; float b; } f34(void) {} + +// RUN: grep 'define i16 @f35()' %t && +struct s35 { struct { int : 0; } a; char b; char c; } f35(void) {} + +// RUN: grep 'define i16 @f36()' %t && +struct s36 { struct { int : 0; } a[2][10]; char b; char c; } f36(void) {} + +// RUN: grep 'define float @f37()' %t && +struct s37 { float c[1][1]; } f37(void) {} + +// RUN: grep 'define void @f38(.struct.s38. noalias sret .agg.result)' %t && +struct s38 { char a[3]; short b; } f38(void) {} + +// RUN: true diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c new file mode 100644 index 000000000000..6f7ec82872be --- /dev/null +++ b/test/CodeGen/x86_64-arguments.c @@ -0,0 +1,85 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s && +// RUN: grep 'define signext i8 @f0()' %t && +// RUN: grep 'define signext i16 @f1()' %t && +// RUN: grep 'define i32 @f2()' %t && +// RUN: grep 'define float @f3()' %t && +// RUN: grep 'define double @f4()' %t && +// RUN: grep 'define x86_fp80 @f5()' %t && +// RUN: grep 'define void @f6(i8 signext %a0, i16 signext %a1, i32 %a2, i64 %a3, i8\* %a4)' %t && +// RUN: grep 'define void @f7(i32 %a0)' %t && +// RUN: grep 'type { i64, double }.*type .0' %t && +// RUN: grep 'define .0 @f8_1()' %t && +// RUN: grep 'define void @f8_2(.0)' %t && + +char f0(void) { +} + +short f1(void) { +} + +int f2(void) { +} + +float f3(void) { +} + +double f4(void) { +} + +long double f5(void) { +} + +void f6(char a0, short a1, int a2, long long a3, void *a4) { +} + +typedef enum { A, B, C } E; + +void f7(E a0) { +} + +// Test merging/passing of upper eightbyte with X87 class. +union u8 { + long double a; + int b; +}; +union u8 f8_1() {} +void f8_2(union u8 a0) {} + +// RUN: grep 'define i64 @f9()' %t && +struct s9 { int a; int b; int : 0; } f9(void) {} + +// RUN: grep 'define void @f10(i64)' %t && +struct s10 { int a; int b; int : 0; }; +void f10(struct s10 a0) {} + +// RUN: grep 'define void @f11(.union.anon. noalias sret .agg.result)' %t && +union { long double a; float b; } f11() {} + +// RUN: grep 'define i64 @f12_0()' %t && +// RUN: grep 'define void @f12_1(i64)' %t && +struct s12 { int a __attribute__((aligned(16))); }; +struct s12 f12_0(void) {} +void f12_1(struct s12 a0) {} + +// Check that sret parameter is accounted for when checking available integer +// registers. +// RUN: grep 'define void @f13(.struct.s13_0. noalias sret .agg.result, i32 .a, i32 .b, i32 .c, i32 .d, .struct.s13_1. byval .e, i32 .f)' %t && + +struct s13_0 { long long f0[3]; }; +struct s13_0 f13(int a, int b, int c, int d, + struct s13_1 { long long f0[2]; } e, int f) {} + +// RUN: grep 'define void @f14(.*, i8 signext .X)' %t && +void f14(int a, int b, int c, int d, int e, int f, + char X) {} +// RUN: grep 'define void @f15(.*, i8\* .X)' %t && +void f15(int a, int b, int c, int d, int e, int f, + void *X) {} +// RUN: grep 'define void @f16(.*, float .X)' %t && +void f16(float a, float b, float c, float d, float e, float f, float g, float h, + float X) {} +// RUN: grep 'define void @f17(.*, x86_fp80 .X)' %t && +void f17(float a, float b, float c, float d, float e, float f, float g, float h, + long double X) {} + +// RUN: true diff --git a/test/CodeGenCXX/__null.cpp b/test/CodeGenCXX/__null.cpp new file mode 100644 index 000000000000..476b0ad083bc --- /dev/null +++ b/test/CodeGenCXX/__null.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +int* a = __null; +int b = __null; + +void f() { + int* c = __null; + int d = __null; +} diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp new file mode 100644 index 000000000000..427ba5372992 --- /dev/null +++ b/test/CodeGenCXX/const-init.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -verify -emit-llvm -o %t %s + +int a = 10; +int &ar = a; + +void f(); +void (&fr)() = f; + +struct S { int& a; }; +S s = { a }; + diff --git a/test/CodeGenCXX/explicit-instantiation.cpp b/test/CodeGenCXX/explicit-instantiation.cpp new file mode 100644 index 000000000000..38966aad2deb --- /dev/null +++ b/test/CodeGenCXX/explicit-instantiation.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -emit-llvm -femit-all-decls -o %t %s && +// RUN: grep "_ZNK4plusIillEclERKiRKl" %t | count 1 + +template<typename T, typename U, typename Result> +struct plus { + Result operator()(const T& t, const U& u) const { + return t + u; + } +}; + +template struct plus<int, long, long>; diff --git a/test/CodeGenCXX/expr.cpp b/test/CodeGenCXX/expr.cpp new file mode 100644 index 000000000000..ae5b0e644f27 --- /dev/null +++ b/test/CodeGenCXX/expr.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -emit-llvm -x c++ < %s + +void f(int x) { + if (x != 0) return; +} diff --git a/test/CodeGenCXX/extern-c.cpp b/test/CodeGenCXX/extern-c.cpp new file mode 100644 index 000000000000..635329323354 --- /dev/null +++ b/test/CodeGenCXX/extern-c.cpp @@ -0,0 +1,13 @@ +// RUN: clang-cc -emit-llvm %s -o %t && +namespace foo { + +// RUN: not grep "@a = global i32" %t && +extern "C" int a; + +// RUN: not grep "@_ZN3foo1bE = global i32" %t && +extern int b; + +// RUN: grep "@_ZN3foo1cE = global i32" %t | count 1 +int c = 5; + +} diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp new file mode 100644 index 000000000000..ef36a8b23cfc --- /dev/null +++ b/test/CodeGenCXX/mangle.cpp @@ -0,0 +1,87 @@ +// RUN: clang-cc -emit-llvm %s -o %t -triple=x86_64-apple-darwin9 && + +// FIXME: This test is intentionally trivial, because we can't yet +// CodeGen anything real in C++. +struct X { }; +struct Y { }; + +// RUN: grep _ZplRK1YRA100_P1X %t | count 1 && +bool operator+(const Y&, X* (&xs)[100]) { return false; } + +// RUN: grep _Z1f1s %t | count 1 && +typedef struct { int a; } s; +void f(s) { } + +// RUN: grep _Z1f1e %t| count 1 && +typedef enum { foo } e; +void f(e) { } + +// RUN: grep _Z1f1u %t | count 1 && +typedef union { int a; } u; +void f(u) { } + +// RUN: grep _Z1f1x %t | count 1 && +typedef struct { int a; } x,y; +void f(y) { } + +// RUN: grep _Z1fv %t | count 1 && +void f() { } + +// RUN: grep _ZN1N1fEv %t | count 1 && +namespace N { void f() { } } + +// RUN: grep _ZN1N1N1fEv %t | count 1 && +namespace N { namespace N { void f() { } } } + +// RUN: grep unmangled_function %t | count 1 && +extern "C" { namespace N { void unmangled_function() { } } } + +// RUN: grep unmangled_variable %t | count 1 && +extern "C" { namespace N { int unmangled_variable = 10; } } + +// RUN: grep _ZN1N1iE %t | count 1 && +namespace N { int i; } + +// RUN: grep _ZZN1N1fEiiE1b %t | count 2 && +namespace N { int f(int, int) { static int b; return b; } } + +// RUN: grep "_ZZN1N1gEvE1a =" %t | count 1 && +// RUN: grep "_ZGVZN1N1gEvE1a =" %t | count 1 && +namespace N { int h(); void g() { static int a = h(); } } + +// RUN: grep "_Z1fno" %t | count 1 && +void f(__int128_t, __uint128_t) { } + +template <typename T> struct S1 {}; + +// RUN: grep "_Z1f2S1IiE" %t | count 1 && +void f(S1<int>) {} + +// RUN: grep "_Z1f2S1IdE" %t | count 1 && +void f(S1<double>) {} + +template <int N> struct S2 {}; +// RUN: grep "_Z1f2S2ILi100EE" %t | count 1 && +void f(S2<100>) {} + +// RUN: grep "_Z1f2S2ILin100EE" %t | count 1 && +void f(S2<-100>) {} + +template <bool B> struct S3 {}; + +// RUN: grep "_Z1f2S3ILb1EE" %t | count 1 && +void f(S3<true>) {} + +// RUN: grep "_Z1f2S3ILb0EE" %t | count 1 && +void f(S3<false>) {} + +// RUN: grep "_Z2f22S3ILb1EE" %t | count 1 && +void f2(S3<100>) {} + +struct S; + +// RUN: grep "_Z1fM1SKFvvE" %t | count 1 && +void f(void (S::*)() const) {} + +// RUN: grep "_Z1fM1SFvvE" %t | count 1 +void f(void (S::*)()) {} diff --git a/test/CodeGenCXX/member-functions.cpp b/test/CodeGenCXX/member-functions.cpp new file mode 100644 index 000000000000..8ada907117be --- /dev/null +++ b/test/CodeGenCXX/member-functions.cpp @@ -0,0 +1,63 @@ +// RUN: clang-cc -emit-llvm %s -triple x86_64-apple-darwin9 -o %t && +struct C { + void f(); + void g(int, ...); +}; + +// RUN: grep "define void @_ZN1C1fEv" %t | count 1 && +void C::f() { +} + +void test1() { + C c; + +// RUN: grep "call void @_ZN1C1fEv" %t | count 1 && + c.f(); + +// RUN: grep "call void (.struct.C\*, i32, ...)\* @_ZN1C1gEiz" %t | count 1 && + c.g(1, 2, 3); +} + + +struct S { + // RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t && + inline S() { } + // RUN: grep "define linkonce_odr void @_ZN1SC1Ev" %t && + inline ~S() { } + + + // RUN: grep "define linkonce_odr void @_ZN1S9f_inline1Ev" %t && + void f_inline1() { } + // RUN: grep "define linkonce_odr void @_ZN1S9f_inline2Ev" %t && + inline void f_inline2() { } + + // RUN: grep "define linkonce_odr void @_ZN1S1gEv" %t && + static void g() { } + + static void f(); +}; + +// RUN: grep "define void @_ZN1S1fEv" %t && +void S::f() { +} + +void test2() { + S s; + + s.f_inline1(); + s.f_inline2(); + + S::g(); + +} + +struct T { + T operator+(const T&); +}; + +void test3() { + T t1, t2; + + // RUN: grep "call void @_ZN1TpsERK1T" %t + T result = t1 + t2; +} diff --git a/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp new file mode 100644 index 000000000000..480bbcefc08d --- /dev/null +++ b/test/CodeGenCXX/new.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc %s -emit-llvm -o %t && + +void t1() { + int* a = new int; +} + +// Placement. +void* operator new(unsigned long, void*) throw(); + +void t2(int* a) { + int* b = new (a) int; +} + +struct S { + int a; +}; + +// POD types. +void t3() { + int *a = new int(10); + _Complex int* b = new _Complex int(10i); + + S s; + s.a = 10; + S *sp = new S(s); +} + +// Non-POD +struct T { + T(); + int a; +}; + +void t4() { + // RUN: grep "call void @_ZN1TC1Ev" %t | count 1 && + T *t = new T; +} + +struct T2 { + int a; + T2(int, int); +}; + +void t5() { + // RUN: grep "call void @_ZN2T2C1Eii" %t | count 1 + T2 *t2 = new T2(10, 10); +} + +int *t6() { + // Null check. + return new (0) int(10); +} + +void t7() { + new int(); +} diff --git a/test/CodeGenCXX/reference-field.cpp b/test/CodeGenCXX/reference-field.cpp new file mode 100644 index 000000000000..88d4c1f37e6e --- /dev/null +++ b/test/CodeGenCXX/reference-field.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -emit-llvm -o - %s -O2 | grep "@_Z1bv" + +// Make sure the call to b() doesn't get optimized out. +extern struct x {char& x,y;}y; +int b(); +int a() { if (!&y.x) b(); } diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp new file mode 100644 index 000000000000..8e1935675766 --- /dev/null +++ b/test/CodeGenCXX/references.cpp @@ -0,0 +1,89 @@ +// RUN: clang-cc -verify -emit-llvm -o %t %s + +void t1() { + extern int& a; + int b = a; +} + +void t2(int& a) { + int b = a; +} + +int g; +int& gr = g; +int& grr = gr; +void t3() { + int b = gr; +} + +// Test reference binding. + +struct C { int a; }; + +void f(const bool&); +void f(const int&); +void f(const _Complex int&); +void f(const C&); + +C aggregate_return(); + +bool& bool_reference_return(); +int& int_reference_return(); +_Complex int& complex_int_reference_return(); +C& aggregate_reference_return(); + +void test_bool() { + bool a = true; + f(a); + + f(true); + + bool_reference_return() = true; + a = bool_reference_return(); +} + +void test_scalar() { + int a = 10; + f(a); + + struct { int bitfield : 3; } s = { 3 }; + f(s.bitfield); + + f(10); + + __attribute((vector_size(16))) typedef int vec4; + f((vec4){1,2,3,4}[0]); + + int_reference_return() = 10; + a = int_reference_return(); +} + +void test_complex() { + _Complex int a = 10i; + f(a); + + f(10i); + + complex_int_reference_return() = 10i; + a = complex_int_reference_return(); +} + +void test_aggregate() { + C c; + f(c); + + f(aggregate_return()); + aggregate_reference_return().a = 10; + + c = aggregate_reference_return(); +} + +int& reference_return() { + return g; +} + +int reference_decl() { + int& a = g; + const int& b = 1; + return a+b; +} diff --git a/test/CodeGenObjC/2008-10-23-invalid-icmp.m b/test/CodeGenObjC/2008-10-23-invalid-icmp.m new file mode 100644 index 000000000000..2c58b9217675 --- /dev/null +++ b/test/CodeGenObjC/2008-10-23-invalid-icmp.m @@ -0,0 +1,7 @@ +// RUN: clang-cc -emit-llvm -o %t %s + +@protocol P @end + +int f0(id<P> d) { + return (d != ((void*) 0)); +} diff --git a/test/CodeGenObjC/attr-strong.c b/test/CodeGenObjC/attr-strong.c new file mode 100644 index 000000000000..ca8333449435 --- /dev/null +++ b/test/CodeGenObjC/attr-strong.c @@ -0,0 +1,9 @@ +// RUN: clang -emit-llvm -S -o %t %s + +struct s0 { + void *a; +}; +struct s0 * __attribute__((objc_gc(strong))) g0; +void f0(void) { + g0->a = 0; +} diff --git a/test/CodeGenObjC/bitfield-1.m b/test/CodeGenObjC/bitfield-1.m new file mode 100644 index 000000000000..06ea91132ef3 --- /dev/null +++ b/test/CodeGenObjC/bitfield-1.m @@ -0,0 +1,81 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: clang-cc -triple i386-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: clang-cc -triple i386-pc-linux-gnu -emit-llvm -o %t %s + +@interface Object +- (id) alloc; +- (id) init; +@end + +extern void abort(void); + +#define CHECK_IF(expr) if(!(expr)) abort(); + +@interface Base: Object +{ + int full; + int full2: 32; + int _refs: 8; + int field2: 3; + unsigned f3: 8; + short cc; + unsigned g: 16; + int r2: 8; + int r3: 8; + int r4: 2; + int r5: 8; + char c; +} +- (void)setValues; +@end + +@interface Derived: Base +{ + char d; + int _field3: 6; +} +- (void)checkValues; +@end + +@implementation Base +-(void)setValues { + full = 1; + full2 = 2; + _refs = 3; + field2 = 1; + f3 = 6; + cc = 7; + g = 8; + r2 = 9; + r3 = 10; + r4 = 1; + r5 = 12; + c = 13; +} +@end + +@implementation Derived +-(void)checkValues { + CHECK_IF(full == 1); + CHECK_IF(full2 == 2); + CHECK_IF(_refs == 3); + CHECK_IF(field2 == 1); + CHECK_IF(f3 == 6); + CHECK_IF(cc == 7); + CHECK_IF(g == 8); + CHECK_IF(r2 == 9); + CHECK_IF(r3 == 10); + CHECK_IF(r4 == 1); + CHECK_IF(r5 == 12); + CHECK_IF(c == 13); +} +@end + +int main(void) { + Derived *obj = [[Derived alloc] init]; + + [obj setValues]; + [obj checkValues]; + + return 0; +} diff --git a/test/CodeGenObjC/bitfield-ivar-metadata.m b/test/CodeGenObjC/bitfield-ivar-metadata.m new file mode 100644 index 000000000000..542a2424caa1 --- /dev/null +++ b/test/CodeGenObjC/bitfield-ivar-metadata.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +@interface INTF +{ + unsigned ivar1; + unsigned ivar2; + unsigned char BDIVAR3:1; + unsigned char BDIVAR4:1; +} +@end + +@implementation INTF +@end + + diff --git a/test/CodeGenObjC/bitfield-ivar-offsets.m b/test/CodeGenObjC/bitfield-ivar-offsets.m new file mode 100644 index 000000000000..23a09a3a15b8 --- /dev/null +++ b/test/CodeGenObjC/bitfield-ivar-offsets.m @@ -0,0 +1,26 @@ +// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && +// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s && +// RUN: grep -F '@"OBJC_IVAR_$_I0._b0" = global i64 0, section "__DATA, __objc_const", align 8' %t && +// RUN: grep -F '@"OBJC_IVAR_$_I0._b1" = global i64 0, section "__DATA, __objc_const", align 8' %t && +// RUN: grep -F '@"OBJC_IVAR_$_I0._b2" = global i64 1, section "__DATA, __objc_const", align 8' %t && +// RUN: grep -F '@"OBJC_IVAR_$_I0._x" = global i64 2, section "__DATA, __objc_const", align 8' %t && +// RUN: grep -F '@"OBJC_IVAR_$_I0._b3" = global i64 4, section "__DATA, __objc_const", align 8' %t && +// RUN: grep -F '@"OBJC_IVAR_$_I0._y" = global i64 6, section "__DATA, __objc_const", align 8' %t && +// RUN: grep -F '@"OBJC_IVAR_$_I0._b4" = global i64 7, section "__DATA, __objc_const", align 8' %t && +// RUN: grep -F '@"OBJC_IVAR_$_I0." = global' %t | count 0 && +// RUN: true + +@interface I0 { + unsigned _b0:4; + unsigned _b1:5; + unsigned _b2:5; + char _x; + unsigned _b3:9; + char _y; + char _b4:3; + char : 0; +} +@end + +@implementation I0 +@end diff --git a/test/CodeGenObjC/blocks-1.m b/test/CodeGenObjC/blocks-1.m new file mode 100644 index 000000000000..2b4f8faeb82e --- /dev/null +++ b/test/CodeGenObjC/blocks-1.m @@ -0,0 +1,33 @@ +// RUN: clang-cc %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 && +// RUN: grep "_Block_object_dispose" %t | count 6 && +// RUN: grep "__copy_helper_block_" %t | count 4 && +// RUN: grep "__destroy_helper_block_" %t | count 4 && +// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 && +// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 && +// RUN: grep "i32 135)" %t | count 0 && +// RUN: grep "_Block_object_assign" %t | count 4 && +// RUN: grep "objc_read_weak" %t | count 2 && +// RUN: grep "objc_assign_weak" %t | count 3 + +@interface NSDictionary @end + +void test1(NSDictionary * dict) { + ^{ (void)dict; }(); +} + +@interface D +@end + +void foo() { + __block __weak D *weakSelf; + D *l; + l = weakSelf; + weakSelf = l; +} + +void (^__weak b)(void); + +void test2() { + __block int i = 0; + b = ^ { ++i; }; +} diff --git a/test/CodeGenObjC/blocks-2.m b/test/CodeGenObjC/blocks-2.m new file mode 100644 index 000000000000..a4d8bfa6b7fc --- /dev/null +++ b/test/CodeGenObjC/blocks-2.m @@ -0,0 +1,11 @@ +// RUN: clang-cc %s -emit-llvm -o %t -fobjc-gc -fblocks -triple i386-apple-darwin10 && +// RUN: grep "objc_assign_strongCast" %t | count 2 && +// RUN: true + +// This should generate a strong cast. + +id test3(id x) { + __block id result; + ^{ result = x; }(); + return result; +} diff --git a/test/CodeGenObjC/blocks.m b/test/CodeGenObjC/blocks.m new file mode 100644 index 000000000000..18c455ad9ebe --- /dev/null +++ b/test/CodeGenObjC/blocks.m @@ -0,0 +1,36 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -fblocks -o %t %s && +// rdar://6676764 + +struct S { + void (^F)(struct S*); +} P; + + +@interface T + + - (int)foo: (T (^)(T*)) x; +@end + +void foo(T *P) { + [P foo: 0]; +} + +@interface A +-(void) im0; +@end + +// RUN: grep 'define internal i32 @"__-\[A im0\]_block_invoke_"' %t && +@implementation A +-(void) im0 { + (void) ^{ return 1; }(); +} +@end + +@interface B : A @end +@implementation B +-(void) im1 { + ^(void) { [super im0]; }(); +} +@end + +// RUN: true diff --git a/test/CodeGenObjC/category-super-class-meth.m b/test/CodeGenObjC/category-super-class-meth.m new file mode 100644 index 000000000000..95d8b3103c9f --- /dev/null +++ b/test/CodeGenObjC/category-super-class-meth.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +@interface BASE ++ (int) BaseMeth; +@end + +@interface Child: BASE +@end + +@interface Child (Categ) ++ (int) flushCache2; +@end + +@implementation Child @end + +@implementation Child (Categ) ++ (int) flushCache2 { [super BaseMeth]; } +@end + diff --git a/test/CodeGenObjC/class-getter-dotsyntax.m b/test/CodeGenObjC/class-getter-dotsyntax.m new file mode 100644 index 000000000000..3c82f78d08b5 --- /dev/null +++ b/test/CodeGenObjC/class-getter-dotsyntax.m @@ -0,0 +1,21 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +@interface Test { } ++ (Test *)crash; ++ (void)setCrash: (int)value; +@end + +@implementation Test +static int _value; +- (void)cachesPath +{ + static Test *cachesPath; + + if (!cachesPath) { + Test *crash = Test.crash; + } +} ++ (Test *)crash{ return 0; } ++ (void)setCrash: (int)value{ _value = value; } +@end + diff --git a/test/CodeGenObjC/class-obj-hidden-visibility.m b/test/CodeGenObjC/class-obj-hidden-visibility.m new file mode 100644 index 000000000000..fc4ac12b1836 --- /dev/null +++ b/test/CodeGenObjC/class-obj-hidden-visibility.m @@ -0,0 +1,6 @@ +// RUN: clang-cc -fvisibility=hidden -triple x86_64-apple-darwin10 -S -o - %s | grep -e "private_extern _OBJC_" | count 2 + +@interface INTF @end + +@implementation INTF @end + diff --git a/test/CodeGenObjC/class-type.m b/test/CodeGenObjC/class-type.m new file mode 100644 index 000000000000..794d9a355794 --- /dev/null +++ b/test/CodeGenObjC/class-type.m @@ -0,0 +1,36 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o - %s && +// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o - %s && +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o - %s + + +@interface I0 { + struct { int a; } a; +} +@end + +@class I2; + +@interface I1 { + I2 *_imageBrowser; +} +@end + +@implementation I1 +@end + +@interface I2 : I0 +@end + +@implementation I2 +@end + + +// Implementations without interface declarations. +// rdar://6804402 +@class foo; +@implementation foo +@end + +@implementation bar +@end + diff --git a/test/CodeGenObjC/compatibility-alias.m b/test/CodeGenObjC/compatibility-alias.m new file mode 100644 index 000000000000..11e5a27ab713 --- /dev/null +++ b/test/CodeGenObjC/compatibility-alias.m @@ -0,0 +1,8 @@ +// RUN: clang-cc -emit-llvm -o %t %s + +@interface Int1 @end + +typedef Int1 Int1Typedef; +@compatibility_alias Int1Alias Int1Typedef; + +@implementation Int1Alias @end diff --git a/test/CodeGenObjC/constant-strings.m b/test/CodeGenObjC/constant-strings.m new file mode 100644 index 000000000000..d4fefd903653 --- /dev/null +++ b/test/CodeGenObjC/constant-strings.m @@ -0,0 +1,4 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +id a = @"Hello World!"; + diff --git a/test/CodeGenObjC/continuation-class.m b/test/CodeGenObjC/continuation-class.m new file mode 100644 index 000000000000..925f3cd0c50d --- /dev/null +++ b/test/CodeGenObjC/continuation-class.m @@ -0,0 +1,35 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +@interface Object +- (id)new; +@end + +@interface ReadOnly : Object +{ + int _object; + int _Anotherobject; +} +@property(readonly) int object; +@property(readonly) int Anotherobject; +@end + +@interface ReadOnly () +@property(readwrite) int object; +@property(readwrite, setter = myAnotherobjectSetter:) int Anotherobject; +@end + +@implementation ReadOnly +@synthesize object = _object; +@synthesize Anotherobject = _Anotherobject; +- (void) myAnotherobjectSetter : (int)val { + _Anotherobject = val; +} +@end + +int main(int argc, char **argv) { + ReadOnly *test = [ReadOnly new]; + test.object = 12345; + test.Anotherobject = 200; + return test.object - 12345 + test.Anotherobject - 200; +} + diff --git a/test/CodeGenObjC/debug-info.m b/test/CodeGenObjC/debug-info.m new file mode 100644 index 000000000000..9c461ba68fb4 --- /dev/null +++ b/test/CodeGenObjC/debug-info.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -g -emit-llvm -o %t %s && +// RUN: grep '@.str3 = internal constant \[8 x i8\] c"-\[A m0\]\\00"' %t && +// RUN: grep '@.str4 = internal constant \[9 x i8\] c"\\01-\[A m0\]\\00"' %t && +// RUN: grep '@llvm.dbg.subprogram = .* @.str3, .* @.str3, .* @.str4,' %t && +// RUN: grep '@llvm.dbg.composite.* = .* i32 15, i64 0, i64 8, .* i32 16' %t && +// RUN: true + + + + + + + + +@interface A @end +@implementation A // Line 15 +-(void) m0 {} +@end diff --git a/test/CodeGenObjC/dot-syntax-1.m b/test/CodeGenObjC/dot-syntax-1.m new file mode 100644 index 000000000000..6c4dcbbef0dc --- /dev/null +++ b/test/CodeGenObjC/dot-syntax-1.m @@ -0,0 +1,264 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +#include <stdio.h> + +@interface Root +-(id) alloc; +-(id) init; +@end + +// Property above methods... + +@interface Top0 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot0 : Top0 +-(int) x; +-(void) setX: (int) arg; +@end + +@implementation Top0 +-(int) _getX { + printf("-[ Top0 _getX ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top0 _setX: %d ]\n", arg); +} +@end + +@implementation Bot0 +-(int) x { + printf("-[ Bot0 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot0 _setX: %d ]\n", arg); +} +@end + +// Methods above property... + +@interface Top1 : Root +-(int) x; +-(void) setX: (int) arg; +@end + +@interface Bot1 : Top1 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top1 +-(int) x { + printf("-[ Top1 x ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top1 setX: %d ]\n", arg); +} +@end + +@implementation Bot1 +-(int) _getX { + printf("-[ Bot1 _getX ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot1 _setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 1) + +@interface Top2 : Root +-(int) x; +-(void) _setX: (int) arg; +@end + +@interface Bot2 : Top2 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top2 +-(int) x { + printf("-[ Top2 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top2 _setX: %d ]\n", arg); +} +@end + +@implementation Bot2 +-(int) _getX { + printf("-[ Bot2 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot2 setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 2) + +@interface Top3 : Root +-(int) _getX; +-(void) setX: (int) arg; +@end + +@interface Bot3 : Top3 +@property(getter=_getX,setter=_setX:) int x; +@end + +@implementation Top3 +-(int) _getX { + printf("-[ Top3 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top3 setX: %d ]\n", arg); +} +@end + +@implementation Bot3 +-(int) x { + printf("-[ Bot3 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot3 _setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 3) + +@interface Top4 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot4 : Top4 +-(int) _getX; +-(void) setX: (int) arg; +@end + +@implementation Top4 +-(int) x { + printf("-[ Top4 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Top4 _setX: %d ]\n", arg); +} +@end + +@implementation Bot4 +-(int) _getX { + printf("-[ Bot4 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Bot4 setX: %d ]\n", arg); +} +@end + +// Mixed setter & getter (variant 4) + +@interface Top5 : Root +@property(getter=_getX,setter=_setX:) int x; +@end + +@interface Bot5 : Top5 +-(int) x; +-(void) _setX: (int) arg; +@end + +@implementation Top5 +-(int) _getX { + printf("-[ Top5 _getX ]\n"); + return 0; +} +-(void) setX: (int) arg { + printf("-[ Top5 setX: %d ]\n", arg); +} +@end + +@implementation Bot5 +-(int) x { + printf("-[ Bot5 x ]\n"); + return 0; +} +-(void) _setX: (int) arg { + printf("-[ Bot5 _setX: %d ]\n", arg); +} +@end + +// Mixed level calls (variant 1) + +@interface Top6 : Root +-(int) x; +@end + +@interface Bot6 : Top6 +-(void) setX: (int) arg; +@end + +@implementation Top6 +-(int) x { + printf("-[ Top6 x ]\n"); + return 0; +} +@end + +@implementation Bot6 +-(void) setX: (int) arg { + printf("-[ Bot5 setX: %d ]\n", arg); +} +@end + +// Mixed level calls (variant 1) + +@interface Top7 : Root +-(void) setX: (int) arg; +@end + +@interface Bot7 : Top7 +-(int) x; +@end + +@implementation Top7 +-(void) setX: (int) arg { + printf("-[ Top7 setX: %d ]\n", arg); +} +@end + +@implementation Bot7 +-(int) x { + printf("-[ Bot7 x ]\n"); + return 0; +} +@end + +// + +// FIXME: Two more (thats it?) interesting cases. Method access on +// getter w/o setter and method access on setter w/o getter. + +int main() { +#define test(N) { \ + Bot##N *ob = [[Bot##N alloc] init]; \ + int x = ob.x; \ + ob.x = 10; } + + test(0); + test(1); + test(2); + test(3); + test(4); + test(5); + // test(6); + // test(7); + + return 0; +} + diff --git a/test/CodeGenObjC/dot-syntax.m b/test/CodeGenObjC/dot-syntax.m new file mode 100644 index 000000000000..68c8ad0b7580 --- /dev/null +++ b/test/CodeGenObjC/dot-syntax.m @@ -0,0 +1,98 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +#include <stdio.h> + +@interface Root +-(id) alloc; +-(id) init; +@end + +typedef struct { + float x, y, z[2]; +} S; + +@interface A : Root { + int myX; + // __complex myY; + S myZ; +} + +@property int x; +//@property __complex int y; +@property S z; +@end + +@implementation A +-(int) x { + printf("-[A x] = %d\n", myX); + return myX; +} +-(void) setX: (int) arg { + myX = arg; + printf("-[A setX: %d]\n", myX); +} + +// FIXME: Add back +#if 0 +-(__complex int) y { + printf("-[A y] = (%d, %d)\n", __real myY, __imag myY); + return myY; +} +-(void) setY: (__complex int) arg { + myY = arg; + printf("-[A setY: (%d, %d)]\n", __real myY, __imag myY); +} +#endif + +-(S) z { + printf("-[A z] = { %f, %f, { %f, %f } }\n", + myZ.x, myZ.y, myZ.z[0], myZ.z[1]); + return myZ; +} +-(void) setZ: (S) arg { + myZ = arg; + printf("-[A setZ: { %f, %f, { %f, %f } } ]\n", + myZ.x, myZ.y, myZ.z[0], myZ.z[1]); +} + +@end + +int main() { +#define SWAP(T,a,b) { T a_tmp = a; a = b; b = a_tmp; } + A *a = [[A alloc] init]; + A *b = [[A alloc] init]; + int a0 = 23; + // __complex a1 = 25 + 10i; + S a2 = { 246, 458, {275, 12} }; + int b0 = 42673; + // __complex b1 = 15 + 13i; + S b2 = { 26, 2, {367, 13} }; + + a.x = a0; + // a.y = a1; + a.z = a2; + + a.x += a0; + // a.y += a1; + // Yay, no compound assign of structures. A GCC extension in the + // works, perhaps? + + b.x = b0; + // b.y = b1; + b.z = b2; + + int x0 = (b.x = b0); + printf("(b.x = b0): %d\n", x0); + + // int x1 = __real (b.y = b1); + // printf("__real (b.y = b1) = %d\n", x1); + + float x2 = (b.z = b2).x; + printf("(b.z = b2).x: %f\n", x2); + + SWAP(int, a.x, b.x); + // SWAP(__complex int, a.y, b.y); + SWAP(S, a.z, b.z); + + return 0; +} diff --git a/test/CodeGenObjC/encode-test-1.m b/test/CodeGenObjC/encode-test-1.m new file mode 100644 index 000000000000..b4f3b0f9c33d --- /dev/null +++ b/test/CodeGenObjC/encode-test-1.m @@ -0,0 +1,36 @@ +// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep -e "{Base=b2b3b4b5}" %t | count 1 && +// RUN: grep -e "{Derived=b2b3b4b5b5b4b3}" %t | count 1 + +enum Enum { one, two, three, four }; + +@interface Base { + unsigned a: 2; + int b: 3; + enum Enum c: 4; + unsigned d: 5; +} +@end + +@interface Derived: Base { + signed e: 5; + int f: 4; + enum Enum g: 3; +} +@end + +@implementation Base @end + +@implementation Derived @end + +int main(void) +{ + + const char *en = @encode(Base); +// printf ("%s\n", en); + + const char *ed = @encode(Derived); + // printf ("%s\n", ed); + + return 0; +} diff --git a/test/CodeGenObjC/encode-test-2.m b/test/CodeGenObjC/encode-test-2.m new file mode 100644 index 000000000000..6901168b1d09 --- /dev/null +++ b/test/CodeGenObjC/encode-test-2.m @@ -0,0 +1,29 @@ +// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep -e "@\\\22<X>\\\22" %t && +// RUN: grep -e "@\\\22<X><Y>\\\22" %t && +// RUN: grep -e "@\\\22<X><Y><Z>\\\22" %t && +// RUN: grep -e "@\\\22Foo<X><Y><Z>\\\22" %t && +// RUN: grep -e "{Intf=@@@@}" %t + +@protocol X, Y, Z; +@class Foo; + +@protocol Proto +@end + +@interface Intf <Proto> +{ +id <X> IVAR_x; +id <X, Y> IVAR_xy; +id <X, Y, Z> IVAR_xyz; +Foo <X, Y, Z> *IVAR_Fooxyz; +} +@end + +@implementation Intf +@end + +int main() +{ + const char * en = @encode(Intf); +} diff --git a/test/CodeGenObjC/encode-test-3.m b/test/CodeGenObjC/encode-test-3.m new file mode 100644 index 000000000000..116e825e32a0 --- /dev/null +++ b/test/CodeGenObjC/encode-test-3.m @@ -0,0 +1,21 @@ +// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep -e "\^i" %t | count 1 && +// RUN: grep -e "\[0i\]" %t | count 1 + +int main() { + int n; + + const char * inc = @encode(int[]); + const char * vla = @encode(int[n]); +} + +// PR3648 +int a[sizeof(@encode(int)) == 2 ? 1 : -1]; // Type is char[2] +const char *B = @encode(int); +char (*c)[2] = &@encode(int); // @encode is an lvalue + +char d[] = @encode(int); // infer size. +char e[1] = @encode(int); // truncate +char f[2] = @encode(int); // fits +char g[3] = @encode(int); // zero fill + diff --git a/test/CodeGenObjC/encode-test-4.m b/test/CodeGenObjC/encode-test-4.m new file mode 100644 index 000000000000..90b300200a06 --- /dev/null +++ b/test/CodeGenObjC/encode-test-4.m @@ -0,0 +1,5 @@ +// RUN: clang-cc -emit-llvm -o - %s -O2 | grep "ret i32 1" + +int a() { + return @encode(int) == @encode(int); +} diff --git a/test/CodeGenObjC/encode-test-5.m b/test/CodeGenObjC/encode-test-5.m new file mode 100644 index 000000000000..a76b071e7fed --- /dev/null +++ b/test/CodeGenObjC/encode-test-5.m @@ -0,0 +1,16 @@ +// RUN: clang-cc -triple=x86_64-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && + +// RUN: grep ji %t | count 1 && +char *a = @encode(_Complex int); + +// RUN: grep jf %t | count 1 && +char *b = @encode(_Complex float); + +// RUN: grep jd %t | count 1 && +char *c = @encode(_Complex double); + +// RUN: grep "t.00" %t | count 1 && +char *e = @encode(__int128_t); + +// RUN: grep "T.00" %t | count 1 +char *f = @encode(__uint128_t); diff --git a/test/CodeGenObjC/encode-test.m b/test/CodeGenObjC/encode-test.m new file mode 100644 index 000000000000..ca54a51c3b1c --- /dev/null +++ b/test/CodeGenObjC/encode-test.m @@ -0,0 +1,94 @@ +// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep -e "\^{Innermost=CC}" %t | count 1 && +// RUN: grep -e "{Derived=#ib32b8b3b8sb16b8b8b2b8ccb6}" %t | count 1 && +// RUN: grep -e "{B1=#@c}" %t | count 1 && +// RUN: grep -e "v12@0:4\[3\[4@]]8" %t | count 1 && +// RUN: grep -e "r\^{S=i}" %t | count 1 && +// RUN: grep -e "\^{Object=#}" %t | count 1 + +@class Int1; + +struct Innermost { + unsigned char a, b; +}; + +@interface Int1 { + signed char a, b; + struct Innermost *innermost; +} +@end + +@implementation Int1 +@end + +@interface Base +{ + struct objc_class *isa; + int full; + int full2: 32; + int _refs: 8; + int field2: 3; + unsigned f3: 8; + short cc; + unsigned g: 16; + int r2: 8; + int r3: 8; + int r4: 2; + int r5: 8; + char c; +} +@end + +@interface Derived: Base +{ + char d; + int _field3: 6; +} +@end + +@implementation Base +@end + +@implementation Derived +@end + +@interface B1 +{ + struct objc_class *isa; + Int1 *sBase; + char c; +} +@end + +@implementation B1 +@end + +@interface Test +{ + int ivar; +} +-(void) test3: (Test* [3] [4])b ; +@end + +@implementation Test +-(void) test3: (Test* [3] [4])b {} +@end + +struct S { int iS; }; + +@interface Object +{ + Class isa; +} +@end +typedef Object MyObj; + +int main() +{ + const char *en = @encode(Derived); + const char *eb = @encode(B1); + const char *es = @encode(const struct S *); + const char *ec = @encode(const struct S); + const char *ee = @encode(MyObj *const); +} + diff --git a/test/CodeGenObjC/forward-class-impl-metadata.m b/test/CodeGenObjC/forward-class-impl-metadata.m new file mode 100644 index 000000000000..b8ce10aaa510 --- /dev/null +++ b/test/CodeGenObjC/forward-class-impl-metadata.m @@ -0,0 +1,41 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s + +@interface BASE { +@private + void* _reserved; +} +@end + +@class PVR; + +@interface PVRHandldler +{ + PVR *_imageBrowser; +} +@end + +@implementation PVRHandldler @end + + +@interface PVR : BASE +@end + +@implementation PVR +@end + +// Reopen of an interface after use. + +@interface A { +@public + int x; +} +@property int p0; +@end + +int f0(A *a) { + return a.p0; +} + +@implementation A +@synthesize p0 = _p0; +@end diff --git a/test/CodeGenObjC/hidden-synthesized-ivar.m b/test/CodeGenObjC/hidden-synthesized-ivar.m new file mode 100644 index 000000000000..50a87cb2f453 --- /dev/null +++ b/test/CodeGenObjC/hidden-synthesized-ivar.m @@ -0,0 +1,13 @@ +// RUN: clang-cc -fvisibility=hidden -triple x86_64-apple-darwin10 -S -o - %s | grep -e "private_extern _OBJC_IVAR_" +@interface I +{ + int P; +} + +@property int P; +@end + +@implementation I +@synthesize P; +@end + diff --git a/test/CodeGenObjC/hidden.m b/test/CodeGenObjC/hidden.m new file mode 100644 index 000000000000..6b86ca0581cc --- /dev/null +++ b/test/CodeGenObjC/hidden.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +__attribute__((visibility("hidden"))) +@interface Hidden ++(void) bar; +@end + +@implementation Hidden ++(void) bar {} +@end + +__attribute__((visibility("default"))) +@interface Default ++(void) bar; +@end + +@implementation Default ++(void) bar {} +@end diff --git a/test/CodeGenObjC/image-info.m b/test/CodeGenObjC/image-info.m new file mode 100644 index 000000000000..e8650129e3f7 --- /dev/null +++ b/test/CodeGenObjC/image-info.m @@ -0,0 +1,2 @@ +// RUN: clang-cc -triple x86_64-apple-darwin-10 -emit-llvm -o %t %s && +// RUN: grep -F '@"\01L_OBJC_IMAGE_INFO" = internal constant [2 x i32] [i32 0, i32 16], section "__OBJC, __image_info,regular"' %t diff --git a/test/CodeGenObjC/implicit-objc_msgSend.m b/test/CodeGenObjC/implicit-objc_msgSend.m new file mode 100644 index 000000000000..4511cca338b2 --- /dev/null +++ b/test/CodeGenObjC/implicit-objc_msgSend.m @@ -0,0 +1,7 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s && +// RUN: grep -F 'declare i8* @objc_msgSend(...)' %t + +typedef struct objc_selector *SEL; +id f0(id x, SEL s) { + return objc_msgSend(x, s); +} diff --git a/test/CodeGenObjC/implicit-property.m b/test/CodeGenObjC/implicit-property.m new file mode 100644 index 000000000000..206d496252d8 --- /dev/null +++ b/test/CodeGenObjC/implicit-property.m @@ -0,0 +1,16 @@ +// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin8 -o %t %s +// RUNX: clang-cc -emit-llvm -o %t %s + +@interface A + -(void) setOk:(int)arg; + -(int) ok; + + -(void) setX:(int)arg; + -(int) x; +@end + +void f0(A *a) { + a.x = 1; + a.ok = a.x; +} + diff --git a/test/CodeGenObjC/interface-layout-64.m b/test/CodeGenObjC/interface-layout-64.m new file mode 100644 index 000000000000..13d6a8770f65 --- /dev/null +++ b/test/CodeGenObjC/interface-layout-64.m @@ -0,0 +1,124 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s && +// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && + +// RUN: grep '@"OBJC_IVAR_$_I3._iv2" = global i64 8, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I3._iv3" = global i64 12, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I4._iv4" = global i64 13, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I5._iv5" = global i64 14, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I5._iv6_synth" = global i64 16, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I5._iv7_synth" = global i64 20, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I6.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I8.b" = global i64 8, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I9.iv0" = global i64 0, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I10.iv1" = global i64 4, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_IVAR_$_I12.iv2" = global i64 8, section "__DATA, __objc_const", align 8' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I3" = internal global .* { i32 0, i32 8, i32 13, .*' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I4" = internal global .* { i32 0, i32 13, i32 14, .*' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I5" = internal global .* { i32 0, i32 14, i32 24, .*' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I6" = internal global .* { i32 2, i32 0, i32 1, .*' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I8" = internal global .* { i32 0, i32 8, i32 16, .*' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I9" = internal global .* { i32 2, i32 0, i32 4, .*' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I10" = internal global .* { i32 0, i32 4, i32 5, .*' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I11" = internal global .* { i32 0, i32 5, i32 5, .*' %t && +// RUN: grep '_OBJC_CLASS_RO_$_I12" = internal global .* { i32 0, i32 8, i32 12, .*' %t && + +// RUN: true + +/* + Compare to: + gcc -m64 -S -o - interface-layout-64.m | grep '^_OBJC_IVAR_$_*.*' -A 1 + and + gcc -m64 -S -o - interface-layout-64.m | grep '^l.*_CLASS_RO_$_I[0-9]*' -A 3 + */ + +struct s0 { + double x; +}; + +@interface I2 { + struct s0 _iv1; +} +@end + +@interface I3 : I2 { + unsigned int _iv2 :1; + unsigned : 0; + unsigned int _iv3 : 3; +} +@end + +@interface I4 : I3 { + char _iv4; +} +@end + +@interface I5 : I4 { + char _iv5; +} + +@property int prop0; +@end + +@implementation I3 +@end + +@implementation I4 +@end + +@interface I5 () +@property int prop1; +@property char prop2; +@end + +@implementation I5 +@synthesize prop0 = _iv6_synth; +@synthesize prop1 = _iv7_synth; +@synthesize prop2 = _iv5; +@end + +// The size rounds up to the next available byte. +@interface I6 { + unsigned iv0 : 2; +} +@end +@implementation I6 +@end + +// The start of the subclass includes padding for its own alignment. +@interface I7 { + char a; +} +@end +@interface I8 : I7 { + double b; +} +@end +@implementation I8 +@end + +// Padding bit-fields +@interface I9 { + unsigned iv0 : 2; + unsigned : 0; +} +@end +@implementation I9 +@end +@interface I10 : I9 { + unsigned iv1 : 2; +} +@end +@implementation I10 +@end + +// Empty structures +@interface I11 : I10 +@end +@implementation I11 +@end +@interface I12 : I11 { + unsigned iv2; +} +@end +@implementation I12 +@end diff --git a/test/CodeGenObjC/interface.m b/test/CodeGenObjC/interface.m new file mode 100644 index 000000000000..d506e88ee7c9 --- /dev/null +++ b/test/CodeGenObjC/interface.m @@ -0,0 +1,34 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -O3 -emit-llvm -o %t %s && +// RUN: grep 'ret i32 385' %t + +void *alloca(); + +@interface I0 { +@public + int iv0; + int iv1; + int iv2; +} +@end + +static int f0(I0 *a0) { + return (*(a0 + 2)).iv0; +} + +static int f1(I0 *a0) { + return a0[2].iv1; +} + +static int f2(I0 *a0) { + return (*(a0 - 1)).iv2; +} + +int g0(void) { + I0 *a = alloca(sizeof(*a) * 4); + a[2].iv0 = 5; + a[2].iv1 = 7; + a[2].iv2 = 11; + return f0(a) * f1(a) * f2(&a[3]); +} + + diff --git a/test/CodeGenObjC/ivar-layout-64.m b/test/CodeGenObjC/ivar-layout-64.m new file mode 100644 index 000000000000..7301e168218e --- /dev/null +++ b/test/CodeGenObjC/ivar-layout-64.m @@ -0,0 +1,89 @@ +// RUNX: llvm-gcc -m64 -fobjc-gc -emit-llvm -S -o %t %s && +// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s && +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"A\\00"' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\11q\\10\\00"' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"!q\\00"' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_.*" = internal global .* c"\\01\\14\\00"' %t && +// RUN: true + +/* + +Here is a handy command for looking at llvm-gcc's output: +llvm-gcc -m64 -fobjc-gc -emit-llvm -S -o - ivar-layout-64.m | \ + grep 'OBJC_CLASS_NAME.* =.*global' | \ + sed -e 's#, section.*# ...#' | \ + sed -e 's#_[0-9]*"#_NNN#' | \ + sort + +*/ + +@interface B @end + +@interface A { + struct s0 { + int f0; + int f1; + } f0; + id f1; +__weak B *f2; + int f3 : 5; + struct s1 { + int *f0; + int *f1; + } f4[2][1]; +} +@end + +@interface C : A +@property int p3; +@end + +@implementation C +@synthesize p3 = _p3; +@end + +@interface A() +@property int p0; +@property (assign) __strong id p1; +@property (assign) __weak id p2; +@end + +// FIXME: Check layout for this class, once it is clear what the right +// answer is. +@implementation A +@synthesize p0 = _p0; +@synthesize p1 = _p1; +@synthesize p2 = _p2; +@end + +@interface D : A +@property int p3; +@end + +// FIXME: Check layout for this class, once it is clear what the right +// answer is. +@implementation D +@synthesize p3 = _p3; +@end + +typedef unsigned short UInt16; + + +typedef signed char BOOL; +typedef unsigned int FSCatalogInfoBitmap; + +@interface NSFileLocationComponent { + @private + + id _specifierOrStandardizedPath; + BOOL _carbonCatalogInfoAndNameAreValid; + FSCatalogInfoBitmap _carbonCatalogInfoMask; + id _name; + id _containerComponent; + id _presentableName; + id _iconAsAttributedString; +} +@end + +@implementation NSFileLocationComponent @end + diff --git a/test/CodeGenObjC/ivars.m b/test/CodeGenObjC/ivars.m new file mode 100644 index 000000000000..327b628532e1 --- /dev/null +++ b/test/CodeGenObjC/ivars.m @@ -0,0 +1,14 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o - %s && +// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o - %s + +// rdar://6800926 +@interface ITF { +@public + unsigned field :1 ; + _Bool boolfield :1 ; +} +@end + +void foo(ITF *P) { + P->boolfield = 1; +} diff --git a/test/CodeGenObjC/link-errors.m b/test/CodeGenObjC/link-errors.m new file mode 100644 index 000000000000..b50d93993fc8 --- /dev/null +++ b/test/CodeGenObjC/link-errors.m @@ -0,0 +1,39 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep '.lazy_reference .objc_class_name_A' %t | count 1 && +// RUN: grep '.lazy_reference .objc_class_name_Unknown' %t | count 1 && +// RUN: grep '.lazy_reference .objc_class_name_Protocol' %t | count 1 && +// RUN: clang-cc -triple i386-apple-darwin9 -DWITH_IMPL -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep '.lazy_reference .objc_class_name_Root' %t | count 1 + +@interface Root +-(id) alloc; +-(id) init; +@end + +@protocol P; + +@interface A : Root +@end + +@interface A (Category) ++(void) foo; +@end + +#ifdef WITH_IMPL +@implementation A +@end +#endif + +@interface Unknown ++test; +@end + + +int main() { + id x = @protocol(P); + [ A alloc ]; + [ A foo ]; + [ Unknown test ]; + return 0; +} + diff --git a/test/CodeGenObjC/message-arrays.m b/test/CodeGenObjC/message-arrays.m new file mode 100644 index 000000000000..c618672feab2 --- /dev/null +++ b/test/CodeGenObjC/message-arrays.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +void f0(id a) { + // This should have an implicit cast + [ a print: "hello" ]; +} + +@interface A +-(void) m: (int) arg0, ...; +@end + +int f1(A *a) { + // This should also get an implicit cast (for the vararg) + [a m: 1, "test"]; +} diff --git a/test/CodeGenObjC/messages-2.m b/test/CodeGenObjC/messages-2.m new file mode 100644 index 000000000000..ca0eb9493387 --- /dev/null +++ b/test/CodeGenObjC/messages-2.m @@ -0,0 +1,139 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +#include <stdio.h> + +@interface Root +@end + +typedef struct { + int x, y, z[10]; +} MyPoint; +typedef struct { + float width, height; +} MySize; + +@interface A : Root ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3; ++(float) returnAFloat; ++(double) returnADouble; ++(MyPoint) returnAPoint; ++(void) printThisSize: (MySize) arg0; ++(MySize) returnASize; + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3; +-(float) returnAFloat; +-(double) returnADouble; +-(MyPoint) returnAPoint; +-(void) printThisSize: (MySize) arg0; +-(MySize) returnASize; +@end +@interface B : A +@end + +@implementation A ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + printf("(CLASS) theInt: %d, theFloat: %f, theDouble: %f, thePoint: { %d, %d }\n", + arg0, arg1, arg2, arg3.x, arg3.y); +} ++(float) returnAFloat { + return 15.; +} ++(double) returnADouble { + return 25.; +} ++(MyPoint) returnAPoint { + MyPoint x = { 35, 45 }; + return x; +} ++(void) printThisSize: (MySize) arg0 { + printf("(CLASS) theSize: { %f, %f }\n", + arg0.width, arg0.height); +} ++(MySize) returnASize { + MySize x = { 32, 44 }; + return x; +} + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + printf("theInt: %d, theFloat: %f, theDouble: %f, thePoint: { %d, %d }\n", + arg0, arg1, arg2, arg3.x, arg3.y); +} +-(float) returnAFloat { + return 10.; +} +-(double) returnADouble { + return 20.; +} +-(MyPoint) returnAPoint { + MyPoint x = { 30, 40 }; + return x; +} +-(void) printThisSize: (MySize) arg0 { + printf("theSize: { %f, %f }\n", + arg0.width, arg0.height); +} +-(MySize) returnASize { + MySize x = { 22, 34 }; + return x; +} +@end + +@implementation B ++(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + arg3.x *= 2; + arg3.y *= 2; + [ super printThisInt: arg0*2 andThatFloat: arg1*2 andADouble: arg2*2 andAPoint: arg3 ]; +} ++(void) printThisSize: (MySize) arg0 { + arg0.width *= 2; + arg0.height *= 2; + [ super printThisSize: arg0 ]; +} ++(float) returnAFloat { + return [ super returnAFloat ]*2; +} ++(double) returnADouble { + return [ super returnADouble ]*2; +} ++(MyPoint) returnAPoint { + MyPoint x = [ super returnAPoint ]; + x.x *= 2; + x.y *= 2; + return x; +} ++(MySize) returnASize { + MySize x = [ super returnASize ]; + x.width *= 2; + x.height *= 2; + return x; +} + +-(void) printThisInt: (int) arg0 andThatFloat: (float) arg1 andADouble: (double) arg2 andAPoint: (MyPoint) arg3 { + arg3.x *= 2; + arg3.y *= 2; + [ super printThisInt: arg0*2 andThatFloat: arg1*2 andADouble: arg2*2 andAPoint: arg3 ]; +} +-(void) printThisSize: (MySize) arg0 { + arg0.width *= 2; + arg0.height *= 2; + [ super printThisSize: arg0 ]; +} +-(float) returnAFloat { + return [ super returnAFloat ]*2; +} +-(double) returnADouble { + return [ super returnADouble ]*2; +} +-(MyPoint) returnAPoint { + MyPoint x = [ super returnAPoint ]; + x.x *= 2; + x.y *= 2; + return x; +} +-(MySize) returnASize { + MySize x = [ super returnASize ]; + x.width *= 2; + x.height *= 2; + return x; +} +@end diff --git a/test/CodeGenObjC/messages.m b/test/CodeGenObjC/messages.m new file mode 100644 index 000000000000..f9b9be6e11a3 --- /dev/null +++ b/test/CodeGenObjC/messages.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s && +// RUN: grep "objc_msgSend" %t | count 6 && +// RUN: clang-cc -fgnu-runtime --emit-llvm -o %t %s && +// RUN: grep "objc_msg_lookup" %t | count 6 && +// RUN: clang-cc -fgnu-runtime -fobjc-sender-dependent-dispatch --emit-llvm -o %t %s && +// RUN: grep "objc_msg_lookup_sender" %t | count 6 +// RUN: true + +typedef struct { + int x; + int y; + int z[10]; +} MyPoint; + +void f0(id a) { + int i; + MyPoint pt = { 1, 2}; + + [a print0]; + [a print1: 10]; + [a print2: 10 and: "hello" and: 2.2]; + [a takeStruct: pt ]; + + void *s = @selector(print0); + for (i=0; i<2; ++i) + [a performSelector:s]; +} diff --git a/test/CodeGenObjC/metadata-symbols-32.m b/test/CodeGenObjC/metadata-symbols-32.m new file mode 100644 index 000000000000..8cebe4976e23 --- /dev/null +++ b/test/CodeGenObjC/metadata-symbols-32.m @@ -0,0 +1,88 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s && +// RUNX: llvm-gcc -m32 -emit-llvm -S -o %t %s && + +// RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*section "__OBJC,__category,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CATEGORY_CLASS_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CATEGORY_INSTANCE_METHODS_A_Cat" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CLASSEXT_A" = internal global .*section "__OBJC,__class_ext,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*section "__OBJC,__class,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_METHODS_A" = internal global .*section "__OBJC,__cls_meth,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_A" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__cls_refs,literal_pointers,no_dead_strip", align 4' %t && + +// Clang's Obj-C 32-bit doesn't emit ivars for the root class. +// RUNX: grep '@"\\01L_OBJC_CLASS_VARIABLES_A" = internal global .*section "__OBJC,__class_vars,regular,no_dead_strip", align 4' %t && + +// RUN: grep '@"\\01L_OBJC_INSTANCE_METHODS_A" = internal global .*section "__OBJC,__inst_meth,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_INSTANCE_VARIABLES_A" = internal global .*section "__OBJC,__instance_vars,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t && +// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t && +// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .*section "__TEXT,__cstring,cstring_literals", align 1' %t && +// RUN: grep '@"\\01L_OBJC_PROTOCOL_CLASS_METHODS_P" = internal global .*section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_PROTOCOL_INSTANCE_METHODS_P" = internal global .*section "__OBJC,__cat_inst_meth,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_[0-9]*" = internal global .*section "__OBJC,__message_refs,literal_pointers,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_SYMBOLS" = internal global .*section "__OBJC,__symbols,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .*section "__OBJC,__property,regular,no_dead_strip", align 4' %t && +// RUN: grep "\.lazy_reference \.objc_class_name_J0" %t && + +// RUN: true + +/* + +Here is a handy command for looking at llvm-gcc's output: +llvm-gcc -m32 -emit-llvm -S -o - metadata-symbols-32.m | \ + grep '=.*global' | \ + sed -e 's#global.*, section#global ... section#' | \ + sort + +*/ + +@interface B +@end +@interface C +@end + +@protocol P ++(void) fm0; +-(void) im0; +@end + +@interface A<P> { + int _ivar; +} + +@property (assign) int ivar; + ++(void) fm0; +-(void) im0; +@end + +@implementation A +@synthesize ivar = _ivar; ++(void) fm0 { +} +-(void) im0 { +} +@end + +@implementation A (Cat) ++(void) fm1 { +} +-(void) im1 { +} +@end + +@interface J0 +@end + +@implementation J0(Category) @end + +void *f0() { + [B im0]; + [C im1]; +} + diff --git a/test/CodeGenObjC/metadata-symbols-64.m b/test/CodeGenObjC/metadata-symbols-64.m new file mode 100644 index 000000000000..bfc4ae9e7546 --- /dev/null +++ b/test/CodeGenObjC/metadata-symbols-64.m @@ -0,0 +1,130 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s && +// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && + +// RUN: grep '@"OBJC_CLASS_$_A" = global' %t && +// RUN: grep '@"OBJC_CLASS_$_B" = external global' %t && +// RUN: grep '@"OBJC_IVAR_$_A._ivar" = global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"OBJC_METACLASS_$_A" = global .* section "__DATA, __objc_data", align 8' %t && +// RUN: grep '@"\\01L_OBJC_CLASSLIST_REFERENCES_$_[0-9]*" = internal global .* section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8' %t && +// RUN: grep '@"\\01L_OBJC_CLASSLIST_SUP_REFS_$_[0-9]*" = internal global .* section "__DATA, __objc_superrefs, regular, no_dead_strip", align 8' %t | count 2 && +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t && +// RUN: grep '@"\\01L_OBJC_LABEL_CATEGORY_$" = internal global .* section "__DATA, __objc_catlist, regular, no_dead_strip", align 8' %t && +// RUN: grep '@"\\01L_OBJC_LABEL_CLASS_$" = internal global .* section "__DATA, __objc_classlist, regular, no_dead_strip", align 8' %t && +// RUN: grep '@"\\01L_OBJC_METH_VAR_NAME_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t && +// RUN: grep '@"\\01L_OBJC_METH_VAR_TYPE_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t && +// RUN: grep '@"\\01L_OBJC_PROP_NAME_ATTR_[0-9]*" = internal global .* section "__TEXT,__cstring,cstring_literals", align 1' %t && +// RUN: grep '@"\\01L_OBJC_SELECTOR_REFERENCES_*" = internal global .* section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip"' %t && +// RUN: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_$_CATEGORY_CLASS_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_$_CATEGORY_INSTANCE_METHODS_A_$_Cat" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_$_CLASS_METHODS_A" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_$_INSTANCE_METHODS_A" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_$_INSTANCE_VARIABLES_A" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_$_PROP_LIST_A" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_$_PROTOCOL_CLASS_METHODS_P" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_P" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_CLASS_PROTOCOLS_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_CLASS_RO_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global .* section "__DATA, __objc_protolist, coalesced, no_dead_strip", align 8' %t && +// RUN: grep '@"\\01l_OBJC_METACLASS_RO_$_A" = internal global .* section "__DATA, __objc_const", align 8' %t && +// RUN: grep '@"\\01l_OBJC_PROTOCOL_$_P" = weak hidden global .* section "__DATA,__datacoal_nt,coalesced", align 8' %t && +// RUN: grep '@"\\01l_objc_msgSend_fixup_alloc" = weak hidden global .* section "__DATA, __objc_msgrefs, coalesced", align 16' %t && +// RUN: grep '@_objc_empty_cache = external global' %t && +// RUN: grep '@_objc_empty_vtable = external global' %t && +// RUN: grep '@objc_msgSend_fixup(' %t && +// RUN: grep '@objc_msgSend_fpret(' %t && + +// RUN: true + +/* + +Here is a handy command for looking at llvm-gcc's output: +llvm-gcc -m64 -emit-llvm -S -o - metadata-symbols-64.m | \ + grep '=.*global' | \ + sed -e 's#global.*, section#global ... section#' | \ + sort + +*/ + +@interface B +@end +@interface C +@end + +@protocol P ++(void) fm0; +-(void) im0; +@end + +@interface A<P> { + int _ivar; +} + +@property (assign) int ivar; + ++(void) fm0; +-(void) im0; +@end + +@implementation A +@synthesize ivar = _ivar; ++(void) fm0 { +} +-(void) im0 { +} +@end + +@implementation A (Cat) ++(void) fm1 { +} +-(void) im1 { +} +@end + +@interface D : A +@end + +@implementation D ++(void) fm2 { + [super fm1]; +} +-(void) im2 { + [super im1]; +} +@end + +// Test for FP dispatch method APIs +@interface Example +@end + +float FLOAT; +double DOUBLE; +long double LONGDOUBLE; +id ID; + +@implementation Example + - (double) RET_DOUBLE + { + return DOUBLE; + } + - (float) RET_FLOAT + { + return FLOAT; + } + - (long double) RET_LONGDOUBLE + { + return LONGDOUBLE; + } +@end + +void *f0(id x) { + Example* pe; + double dd = [pe RET_DOUBLE]; + dd = [pe RET_FLOAT]; + dd = [pe RET_LONGDOUBLE]; + + [B im0]; + [C im1]; + [D alloc]; +} + diff --git a/test/CodeGenObjC/metadata_symbols.m b/test/CodeGenObjC/metadata_symbols.m new file mode 100644 index 000000000000..1a1d1e1d9810 --- /dev/null +++ b/test/CodeGenObjC/metadata_symbols.m @@ -0,0 +1,61 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-llvm -o %t %s && + +// RUN: grep '@"OBJC_METACLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t && +// RUN: grep '@"OBJC_CLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak global .*section "__DATA,__datacoal_nt,coalesced", align 8' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH3" = global .*section "__DATA,__objc_const", align 8' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH3"' %t | count 3 && +// RUN: grep '@"\\01L_OBJC_CLASS_NAME_" =.*section "__TEXT,__cstring,cstring_literals", align 1' %t | count 1 && +// RUN: grep -F 'define internal void @"\01-[A im0]"' %t && +// RUN: grep -F 'define internal void @"\01-[A(Cat) im1]"' %t && + +// RUN: clang-cc -fvisibility=hidden -triple x86_64-apple-darwin9 -emit-llvm -o %t %s && + +// RUN: grep '@"OBJC_METACLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t && +// RUN: grep '@"OBJC_CLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak hidden global .*section "__DATA,__datacoal_nt,coalesced"' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH3" = hidden global .*section "__DATA,__objc_const", align 8' %t && +// RUN: grep -F 'define internal void @"\01-[A im0]"' %t && +// RUN: grep -F 'define internal void @"\01-[A(Cat) im1]"' %t && + +// RUN: true + +@interface A +@end + +@implementation A +-(void) im0 { +} +@end + +@implementation A (Cat) +-(void) im1 { +} +@end + +@interface EH1 +@end + +__attribute__((__objc_exception__)) +@interface EH2 +@end + +__attribute__((__objc_exception__)) +@interface EH3 +@end + +void f1(); + +void f0(id x) { + @try { + f1(); + } @catch (EH1 *x) { + } @catch (EH2 *x) { + } @catch (EH3 *x) { + } +} + +@implementation EH3 +@end diff --git a/test/CodeGenObjC/newproperty-nested-synthesis-1.m b/test/CodeGenObjC/newproperty-nested-synthesis-1.m new file mode 100644 index 000000000000..5196b8244dbb --- /dev/null +++ b/test/CodeGenObjC/newproperty-nested-synthesis-1.m @@ -0,0 +1,78 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +@interface Object +- (id) new; +@end + +@interface Tester : Object +@property char PropertyAtomic_char; +@property short PropertyAtomic_short; +@property int PropertyAtomic_int; +@property long PropertyAtomic_long; +@property long long PropertyAtomic_longlong; +@property float PropertyAtomic_float; +@property double PropertyAtomic_double; +@property(assign) id PropertyAtomic_id; +@property(retain) id PropertyAtomicRetained_id; +@property(copy) id PropertyAtomicRetainedCopied_id; +@property(retain) id PropertyAtomicRetainedGCOnly_id; +@property(copy) id PropertyAtomicRetainedCopiedGCOnly_id; +@end + +@implementation Tester +@dynamic PropertyAtomic_char; +@dynamic PropertyAtomic_short; +@dynamic PropertyAtomic_int; +@dynamic PropertyAtomic_long; +@dynamic PropertyAtomic_longlong; +@dynamic PropertyAtomic_float; +@dynamic PropertyAtomic_double; +@dynamic PropertyAtomic_id; +@dynamic PropertyAtomicRetained_id; +@dynamic PropertyAtomicRetainedCopied_id; +@dynamic PropertyAtomicRetainedGCOnly_id; +@dynamic PropertyAtomicRetainedCopiedGCOnly_id; +@end + +@interface SubClass : Tester +{ + char PropertyAtomic_char; + short PropertyAtomic_short; + int PropertyAtomic_int; + long PropertyAtomic_long; + long long PropertyAtomic_longlong; + float PropertyAtomic_float; + double PropertyAtomic_double; + id PropertyAtomic_id; + id PropertyAtomicRetained_id; + id PropertyAtomicRetainedCopied_id; + id PropertyAtomicRetainedGCOnly_id; + id PropertyAtomicRetainedCopiedGCOnly_id; +} +@end + +@implementation SubClass +@synthesize PropertyAtomic_char; +@synthesize PropertyAtomic_short; +@synthesize PropertyAtomic_int; +@synthesize PropertyAtomic_long; +@synthesize PropertyAtomic_longlong; +@synthesize PropertyAtomic_float; +@synthesize PropertyAtomic_double; +@synthesize PropertyAtomic_id; +@synthesize PropertyAtomicRetained_id; +@synthesize PropertyAtomicRetainedCopied_id; +@synthesize PropertyAtomicRetainedGCOnly_id; +@synthesize PropertyAtomicRetainedCopiedGCOnly_id; +@end + +int main() +{ + SubClass *f = [SubClass new]; + f.PropertyAtomic_int = 1; + + f.PropertyAtomic_int += 3; + + f.PropertyAtomic_int -= 4; + return f.PropertyAtomic_int; +} diff --git a/test/CodeGenObjC/no-category-class.m b/test/CodeGenObjC/no-category-class.m new file mode 100644 index 000000000000..34bf603da57d --- /dev/null +++ b/test/CodeGenObjC/no-category-class.m @@ -0,0 +1,8 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm -o %t %s + +@interface NSObject +@end + +@implementation NSObject(IBXLIFFIntegration) +@end + diff --git a/test/CodeGenObjC/non-lazy-classes.m b/test/CodeGenObjC/non-lazy-classes.m new file mode 100644 index 000000000000..079cc40886f9 --- /dev/null +++ b/test/CodeGenObjC/non-lazy-classes.m @@ -0,0 +1,33 @@ +// RUNX: llvm-gcc -m64 -emit-llvm -S -o %t %s && +// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s && +// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CLASS_$" = internal global \[1 x .*\] .*@"OBJC_CLASS_$_A".*, section "__DATA, __objc_nlclslist, regular, no_dead_strip", align 8' %t && +// RUN: grep '@".01L_OBJC_LABEL_NONLAZY_CATEGORY_$" = internal global \[1 x .*\] .*@".01l_OBJC_$_CATEGORY_A_$_Cat".*, section "__DATA, __objc_nlcatlist, regular, no_dead_strip", align 8' %t && +// RUN: true + +@interface A @end +@implementation A ++(void) load { +} +@end + +@interface A (Cat) @end +@implementation A (Cat) ++(void) load { +} +@end + +@interface B @end +@implementation B +-(void) load { +} +@end + +@interface B (Cat) @end +@implementation B (Cat) +-(void) load { +} +@end + +@interface C : A @end +@implementation C +@end diff --git a/test/CodeGenObjC/objc-align.m b/test/CodeGenObjC/objc-align.m new file mode 100644 index 000000000000..eca5959a392a --- /dev/null +++ b/test/CodeGenObjC/objc-align.m @@ -0,0 +1,47 @@ +// 32-bit + +// RUNX: llvm-gcc -m32 -emit-llvm -S -o %t %s && +// RUN: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s && +// RUN: grep '@"\\01L_OBJC_CATEGORY_A_Cat" = internal global .*, section "__OBJC,__category,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_A" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_C" = internal global .*, section "__OBJC,__class,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_CLASS_PROTOCOLS_C" = internal global .*, section "__OBJC,__cat_cls_meth,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_IMAGE_INFO" = internal constant .*, section "__OBJC, __image_info,regular"' %t && +// RUN: grep '@"\\01L_OBJC_METACLASS_A" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_METACLASS_C" = internal global .*, section "__OBJC,__meta_class,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_MODULES" = internal global .*, section "__OBJC,__module_info,regular,no_dead_strip", align 4' %t && +// RUN: grep '@"\\01L_OBJC_PROTOCOL_P" = internal global .*, section "__OBJC,__protocol,regular,no_dead_strip", align 4' %t && + +// 64-bit + +// RUNX: clang-cc -triple i386-apple-darwin9 -emit-llvm -o %t %s && +// RUNX: grep '@"OBJC_CLASS_$_A" = global' %t && +// RUNX: grep '@"OBJC_CLASS_$_C" = global' %t && +// RUNX: grep '@"OBJC_METACLASS_$_A" = global' %t && +// RUNX: grep '@"OBJC_METACLASS_$_C" = global' %t && +// RUNX: grep '@"\\01L_OBJC_CLASSLIST_REFERENCES_$_0" = internal global .*, section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8' %t && +// RUNX: grep '@"\\01L_OBJC_IMAGE_INFO" = internal constant .*, section "__DATA, __objc_imageinfo, regular, no_dead_strip"' %t && +// RUNX: grep '@"\\01L_OBJC_LABEL_CATEGORY_$" = internal global .*, section "__DATA, __objc_catlist, regular, no_dead_strip", align 8' %t && +// RUNX: grep '@"\\01L_OBJC_LABEL_CLASS_$" = internal global .*, section "__DATA, __objc_classlist, regular, no_dead_strip", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_$_CATEGORY_A_$_Cat" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_CLASS_PROTOCOLS_$_C" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_CLASS_RO_$_A" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_CLASS_RO_$_C" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_LABEL_PROTOCOL_$_P" = weak hidden global .*, section "__DATA, __objc_protolist, coalesced, no_dead_strip", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_METACLASS_RO_$_A" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_METACLASS_RO_$_C" = internal global .*, section "__DATA, __objc_const", align 8' %t && +// RUNX: grep '@"\\01l_OBJC_PROTOCOL_$_P" = weak hidden global .*, section "__DATA,__datacoal_nt,coalesced", align 8' %t && + +// RUN: true + +@interface A @end +@implementation A +@end +@implementation A (Cat) +@end +@protocol P +@end +@interface C <P> +@end +@implementation C +@end diff --git a/test/CodeGenObjC/objc2-assign-global.m b/test/CodeGenObjC/objc2-assign-global.m new file mode 100644 index 000000000000..ae407619093e --- /dev/null +++ b/test/CodeGenObjC/objc2-assign-global.m @@ -0,0 +1,8 @@ +// RUN: clang-cc -fnext-runtime -fobjc-gc -emit-llvm -o %t %s && +// RUN: grep -F '@objc_assign_global' %t | count 2 && +// RUN: true +id a; +int main() { + a = 0; +} + diff --git a/test/CodeGenObjC/objc2-no-strong-cast.m b/test/CodeGenObjC/objc2-no-strong-cast.m new file mode 100644 index 000000000000..bce50cd4544c --- /dev/null +++ b/test/CodeGenObjC/objc2-no-strong-cast.m @@ -0,0 +1,22 @@ +// RUN: clang-cc -emit-llvm -o %t %s + +@interface PDFViewPrivateVars +{ +@public + __attribute__((objc_gc(strong))) char *addedTooltips; +} +@end + +@interface PDFView +{ + PDFViewPrivateVars *_pdfPriv; +} +@end + +@implementation PDFView +- (void) addTooltipsForPage +{ + _pdfPriv->addedTooltips[4] = 1; +} +@end + diff --git a/test/CodeGenObjC/objc2-no-write-barrier.m b/test/CodeGenObjC/objc2-no-write-barrier.m new file mode 100644 index 000000000000..2c5350969416 --- /dev/null +++ b/test/CodeGenObjC/objc2-no-write-barrier.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s && +// RUN: grep 'objc_assign' %t | count 0 + +typedef struct { + int ival; + id submenu; +} XCBinderContextMenuItem; + +id actionMenuForDataNode(void) { + XCBinderContextMenuItem menusToCreate[] = { + {1, 0} + }; + return 0; +} + +XCBinderContextMenuItem GmenusToCreate[] = { + {1, 0} +}; diff --git a/test/CodeGenObjC/objc2-property-encode.m b/test/CodeGenObjC/objc2-property-encode.m new file mode 100644 index 000000000000..2bff2fc1a4ed --- /dev/null +++ b/test/CodeGenObjC/objc2-property-encode.m @@ -0,0 +1,13 @@ +// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep -e "T@\\\\22NSString\\\\22" %t +@interface NSString @end + +typedef NSString StoreVersionID ; + +@interface Parent + @property(retain) StoreVersionID* foo; +@end + +@implementation Parent +@dynamic foo; +@end diff --git a/test/CodeGenObjC/objc2-protocol-enc.m b/test/CodeGenObjC/objc2-protocol-enc.m new file mode 100644 index 000000000000..559b0b8c76a0 --- /dev/null +++ b/test/CodeGenObjC/objc2-protocol-enc.m @@ -0,0 +1,43 @@ +// RUN: clang-cc -triple=i686-apple-darwin9 -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep -e "T@\\\22<X>\\\22" %t && +// RUN: grep -e "T@\\\22<X><Y>\\\22" %t && +// RUN: grep -e "T@\\\22<X><Y><Z>\\\22" %t && +// RUN: grep -e "T@\\\22Foo<X><Y><Z>\\\22" %t + +@protocol X, Y, Z; +@class Foo; + +@protocol Proto +@property (copy) id <X> x; +@property (copy) id <X, Y> xy; +@property (copy) id <X, Y, Z> xyz; +@property(copy) Foo <X, Y, Z> *fooxyz; +@end + +@interface Intf <Proto> +{ +id <X> IVAR_x; +id <X, Y> IVAR_xy; +id <X, Y, Z> IVAR_xyz; +Foo <X, Y, Z> *IVAR_Fooxyz; +} +@end + +@implementation Intf +@dynamic x, xy, xyz, fooxyz; +@end + +/** +This protocol should generate the following metadata: +struct objc_property_list __Protocol_Test_metadata = { + sizeof(struct objc_property), 4, + { + { "x", "T@\"<X>\"" }, + { "xy", "T@\"<X><Y>\"" }, + { "xyz", "T@\"<X><Y><Z>\"" }, + { "fooxyz", "T@\"Foo<X><Y><Z>\"" } + } +}; + +"T@\"<X><Y><Z>\",D +*/ diff --git a/test/CodeGenObjC/objc2-retain-codegen.m b/test/CodeGenObjC/objc2-retain-codegen.m new file mode 100644 index 000000000000..d78bc366d398 --- /dev/null +++ b/test/CodeGenObjC/objc2-retain-codegen.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown -fobjc-gc-only -emit-llvm -o %t %s + +@interface I0 { + I0 *_f0; +} +@property (retain) id p0; +@end + +@implementation I0 + @synthesize p0 = _f0; +@end + diff --git a/test/CodeGenObjC/objc2-strong-cast-1.m b/test/CodeGenObjC/objc2-strong-cast-1.m new file mode 100644 index 000000000000..8cad08c88a60 --- /dev/null +++ b/test/CodeGenObjC/objc2-strong-cast-1.m @@ -0,0 +1,23 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown -fobjc-gc -emit-llvm -o %t %s + +@interface I { + __attribute__((objc_gc(strong))) int *i_IdocumentIDs; + __attribute__((objc_gc(strong))) long *l_IdocumentIDs; + __attribute__((objc_gc(strong))) long long *ll_IdocumentIDs; + __attribute__((objc_gc(strong))) float *IdocumentIDs; + __attribute__((objc_gc(strong))) double *d_IdocumentIDs; +} +- (void) _getResultsOfMatches; +@end + +@implementation I +-(void) _getResultsOfMatches { + IdocumentIDs[2] = IdocumentIDs[3]; + d_IdocumentIDs[2] = d_IdocumentIDs[3]; + l_IdocumentIDs[2] = l_IdocumentIDs[3]; + ll_IdocumentIDs[2] = ll_IdocumentIDs[3]; + i_IdocumentIDs[2] = i_IdocumentIDs[3]; +} + +@end + diff --git a/test/CodeGenObjC/objc2-strong-cast-2.m b/test/CodeGenObjC/objc2-strong-cast-2.m new file mode 100644 index 000000000000..b617c9fee4ea --- /dev/null +++ b/test/CodeGenObjC/objc2-strong-cast-2.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -triple x86_64-darwin-10 -fobjc-gc -emit-llvm -o %t %s && +// RUN: grep objc_assign_strongCast %t | count 4 && +// RUN: true + +@interface A +@end + +typedef struct s0 { + A *a[4]; +} T; + +T g0; + +void f0(id x) { + g0.a[0] = x; +} + +void f1(id x) { + ((T*) &g0)->a[0] = x; +} + +void f2(unsigned idx) +{ + id *keys; + keys[idx] = 0; +} + diff --git a/test/CodeGenObjC/objc2-strong-cast.m b/test/CodeGenObjC/objc2-strong-cast.m new file mode 100644 index 000000000000..d0fcb6ced928 --- /dev/null +++ b/test/CodeGenObjC/objc2-strong-cast.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fnext-runtime -fobjc-gc -emit-llvm -o %t %s + +@interface I { + __attribute__((objc_gc(strong))) signed long *_documentIDs; + __attribute__((objc_gc(strong))) id *IdocumentIDs; +} +- (void) _getResultsOfMatches; +@end + +@implementation I +-(void) _getResultsOfMatches { + _documentIDs[2] = _documentIDs[3]; + IdocumentIDs[2] = IdocumentIDs[3]; +} + +@end + diff --git a/test/CodeGenObjC/objc2-weak-compare.m b/test/CodeGenObjC/objc2-weak-compare.m new file mode 100644 index 000000000000..be769899a17d --- /dev/null +++ b/test/CodeGenObjC/objc2-weak-compare.m @@ -0,0 +1,24 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fnext-runtime -fobjc-gc -emit-llvm -o %t %s + +@interface PBXTarget +{ + +PBXTarget * __weak _lastKnownTarget; +PBXTarget * __weak _KnownTarget; +PBXTarget * result; +} +- Meth; +@end + +@implementation PBXTarget +- Meth { + if (_lastKnownTarget != result) + foo(); + if (result != _lastKnownTarget) + foo(); + + if (_lastKnownTarget != _KnownTarget) + foo(); +} + +@end diff --git a/test/CodeGenObjC/objc2-weak-ivar.m b/test/CodeGenObjC/objc2-weak-ivar.m new file mode 100644 index 000000000000..592c1f05474b --- /dev/null +++ b/test/CodeGenObjC/objc2-weak-ivar.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -fobjc-gc -emit-llvm -o %t %s +@class NSObject; + +@interface Foo { +@public + __weak NSObject *nsobject; +} +@end + +@implementation Foo @end diff --git a/test/CodeGenObjC/overloadable.m b/test/CodeGenObjC/overloadable.m new file mode 100644 index 000000000000..972dc4ed5895 --- /dev/null +++ b/test/CodeGenObjC/overloadable.m @@ -0,0 +1,10 @@ +// rdar://6657613 +// RUN: clang-cc -emit-llvm %s -o %t && + +@class C; + +// RUN: grep _Z1fP11objc_object %t | count 1 && +void __attribute__((overloadable)) f(C *c) { } + +// RUN: grep _Z1fP1C %t | count 1 +void __attribute__((overloadable)) f(id c) { } diff --git a/test/CodeGenObjC/predefined-expr-in-method.m b/test/CodeGenObjC/predefined-expr-in-method.m new file mode 100644 index 000000000000..812ef97252dc --- /dev/null +++ b/test/CodeGenObjC/predefined-expr-in-method.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +@interface A +@end +@implementation A ++(void) foo { + printf("__func__: %s\n", __func__); + printf("__FUNCTION__: %s\n", __FUNCTION__); + printf("__PRETTY_FUNCTION__: %s\n", __PRETTY_FUNCTION__); + return 0; +} +@end + +int main() { + [A foo]; + return 0; +} diff --git a/test/CodeGenObjC/property-aggr-type.m b/test/CodeGenObjC/property-aggr-type.m new file mode 100644 index 000000000000..0cb7a5e2f40a --- /dev/null +++ b/test/CodeGenObjC/property-aggr-type.m @@ -0,0 +1,50 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +@interface Object +- (id) new; +@end + +typedef struct {int x, y, w, h;} st1; +typedef struct {int x, y, w, h;} st2; + +@interface bar : Object +- (void)setFrame:(st1)frameRect; +@end + +@interface bar1 : Object +- (void)setFrame:(int)frameRect; +@end + +@interface foo : Object +{ + st2 ivar; +} +@property (assign) st2 frame; +@end + +@implementation foo +@synthesize frame = ivar; +@end + +extern void abort(); + +static st2 r = {1,2,3,4}; +st2 test (void) +{ + foo *obj = [foo new]; + id objid = [foo new];; + + obj.frame = r; + + ((foo*)objid).frame = obj.frame; + + return ((foo*)objid).frame; +} + +int main () +{ + st2 res = test (); + if (res.x != 1 || res.h != 4) + abort(); + return 0; +} diff --git a/test/CodeGenObjC/property-agrr-getter.m b/test/CodeGenObjC/property-agrr-getter.m new file mode 100644 index 000000000000..0a1df123bffe --- /dev/null +++ b/test/CodeGenObjC/property-agrr-getter.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +typedef struct { + unsigned f0; +} s0; + +@interface A +- (s0) f0; +@end + +@implementation A +-(s0) f0{} +- (unsigned) bar { + return self.f0.f0; +} +@end + diff --git a/test/CodeGenObjC/property-getter-dot-syntax.m b/test/CodeGenObjC/property-getter-dot-syntax.m new file mode 100644 index 000000000000..d98e9bab6da9 --- /dev/null +++ b/test/CodeGenObjC/property-getter-dot-syntax.m @@ -0,0 +1,11 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +@protocol NSObject +- (void *)description; +@end + +int main() +{ + id<NSObject> eggs; + void *eggsText= eggs.description; +} diff --git a/test/CodeGenObjC/property-incr-decr-1.m b/test/CodeGenObjC/property-incr-decr-1.m new file mode 100644 index 000000000000..772e872a214f --- /dev/null +++ b/test/CodeGenObjC/property-incr-decr-1.m @@ -0,0 +1,29 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +@interface Object +- (id) new; +@end + +@interface SomeClass : Object +{ + int _myValue; +} +@property int myValue; +@end + +@implementation SomeClass +@synthesize myValue=_myValue; +@end + +int main() +{ + int val; + SomeClass *o = [SomeClass new]; + o.myValue = -1; + val = o.myValue++; /* val -1, o.myValue 0 */ + val += o.myValue--; /* val -1. o.myValue -1 */ + val += ++o.myValue; /* val -1, o.myValue 0 */ + val += --o.myValue; /* val -2, o.myValue -1 */ + return ++o.myValue + (val+2); +} + diff --git a/test/CodeGenObjC/property-setter-attr.m b/test/CodeGenObjC/property-setter-attr.m new file mode 100644 index 000000000000..390392415d73 --- /dev/null +++ b/test/CodeGenObjC/property-setter-attr.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin8 -o %t %s +// RUN: grep -e "SiSetOtherThings:" %t + +@interface A +@property(setter=iSetOtherThings:) int otherThings; +@end + +@implementation A +@dynamic otherThings; +@end diff --git a/test/CodeGenObjC/property.m b/test/CodeGenObjC/property.m new file mode 100644 index 000000000000..264adf1106e2 --- /dev/null +++ b/test/CodeGenObjC/property.m @@ -0,0 +1,52 @@ +// RUN: clang-cc -fnext-runtime --emit-llvm -o %t %s + +#include <stdio.h> + +@interface Root +-(id) alloc; +-(id) init; +@end + +@interface A : Root { + int x; + int y, ro, z; + id ob0, ob1, ob2, ob3, ob4; +} +@property int x; +@property int y; +@property int z; +@property(readonly) int ro; +@property(assign) id ob0; +@property(retain) id ob1; +@property(copy) id ob2; +@property(retain, nonatomic) id ob3; +@property(copy, nonatomic) id ob4; +@end + +@implementation A +@dynamic x; +@synthesize y; +@synthesize z = z; +@synthesize ro; +@synthesize ob0; +@synthesize ob1; +@synthesize ob2; +@synthesize ob3; +@synthesize ob4; +-(int) y { + return x + 1; +} +-(void) setZ: (int) arg { + x = arg - 1; +} +@end + +@interface A (Cat) +@property int dyn; +@end + +@implementation A (Cat) +-(int) dyn { + return 10; +} +@end diff --git a/test/CodeGenObjC/protocol-definition-hidden-visibility.m b/test/CodeGenObjC/protocol-definition-hidden-visibility.m new file mode 100644 index 000000000000..31a864b22d55 --- /dev/null +++ b/test/CodeGenObjC/protocol-definition-hidden-visibility.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -S -o - %s | grep -e "private_extern l_OBJC_PROTOCOL_" | count 2 + +@interface FOO @end + +@interface NSObject @end + +@protocol SSHIPCProtocolHandler_BDC; + +typedef NSObject<SSHIPCProtocolHandler_BDC> _SSHIPCProtocolHandler_BDC; + +@interface SSHIPC_v2_RPFSProxy +@property(nonatomic,readonly,retain) _SSHIPCProtocolHandler_BDC* protocolHandler_BDC; +@end + +@implementation FOO +- (_SSHIPCProtocolHandler_BDC*) protocolHandler_BDC {@protocol(SSHIPCProtocolHandler_BDC); } +@end + + diff --git a/test/CodeGenObjC/protocol-property-synth.m b/test/CodeGenObjC/protocol-property-synth.m new file mode 100644 index 000000000000..e91f3552310d --- /dev/null +++ b/test/CodeGenObjC/protocol-property-synth.m @@ -0,0 +1,33 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s + +@interface BaseClass { + id _delegate; +} +@end + +@protocol MyProtocol +@optional +@property(assign) id delegate; +@end + +@protocol AnotherProtocol +@optional +@property(assign) id myanother; +@end + +@protocol SubProtocol <MyProtocol> +@property(assign) id another; +@end + +@interface SubClass : BaseClass <SubProtocol, AnotherProtocol> { +} + +@end + +@implementation BaseClass @end + +@implementation SubClass +@synthesize delegate = _Subdelegate; +@synthesize another; +@synthesize myanother; +@end diff --git a/test/CodeGenObjC/protocols-lazy.m b/test/CodeGenObjC/protocols-lazy.m new file mode 100644 index 000000000000..e91cc0aea836 --- /dev/null +++ b/test/CodeGenObjC/protocols-lazy.m @@ -0,0 +1,48 @@ +// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin8 -o %t %s && +// RUNX: llvm-gcc -S -emit-llvm -o %t %s && + +// No object generated +// RUN: grep OBJC_PROTOCOL_P0 %t | count 0 && +@protocol P0; + +// No object generated +// RUN: grep OBJC_PROTOCOL_P1 %t | count 0 && +@protocol P1 -im1; @end + +// Definition triggered by protocol reference. +// RUN: grep OBJC_PROTOCOL_P2 %t | count 3 && +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P2 %t | count 3 && +@protocol P2 -im1; @end +void f0() { id x = @protocol(P2); } + +// Forward definition triggered by protocol reference. +// RUN: grep OBJC_PROTOCOL_P3 %t | count 3 && +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P3 %t | count 0 && +@protocol P3; +void f1() { id x = @protocol(P3); } + +// Definition triggered by class reference. +// RUN: grep OBJC_PROTOCOL_P4 %t | count 3 && +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P4 %t | count 3 && +@protocol P4 -im1; @end +@interface I0<P4> @end +@implementation I0 -im1 {}; @end + +// Definition following forward reference. +// RUN: grep OBJC_PROTOCOL_P5 %t | count 3 && +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P5 %t | count 3 && +@protocol P5; +void f2() { id x = @protocol(P5); } // This generates a forward + // reference, which has to be + // updated on the next line. +@protocol P5 -im1; @end + +// Protocol reference following definition. +// RUN: grep OBJC_PROTOCOL_P6 %t | count 4 && +// RUN: grep OBJC_PROTOCOL_INSTANCE_METHODS_P6 %t | count 3 && +@protocol P6 -im1; @end +@interface I1<P6> @end +@implementation I1 -im1 {}; @end +void f3() { id x = @protocol(P6); } + +// RUN: true diff --git a/test/CodeGenObjC/runtime-fns.m b/test/CodeGenObjC/runtime-fns.m new file mode 100644 index 000000000000..0d8570799902 --- /dev/null +++ b/test/CodeGenObjC/runtime-fns.m @@ -0,0 +1,33 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep -e "^de.*objc_msgSend[0-9]*(" %t | count 1 && +// RUN: clang-cc -DWITHDEF -fnext-runtime -emit-llvm -o %t %s && +// RUN: grep -e "^de.*objc_msgSend[0-9]*(" %t | count 1 + +id objc_msgSend(int x); + +@interface A @end + +@implementation A +-(void) f0 { + objc_msgSend(12); +} + +-(void) hello { +} +@end + +void f0(id x) { + [x hello]; +} + +#ifdef WITHDEF +// This isn't a very good send function. +id objc_msgSend(int x) { + return 0; +} + +// rdar://6800430 +void objc_assign_weak(id value, id *location) { +} + +#endif diff --git a/test/CodeGenObjC/super-classmethod-category.m b/test/CodeGenObjC/super-classmethod-category.m new file mode 100644 index 000000000000..27cdbf6aed41 --- /dev/null +++ b/test/CodeGenObjC/super-classmethod-category.m @@ -0,0 +1,13 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s + +@interface SUPER ++ (void)Meth; +@end + +@interface CURRENT : SUPER ++ (void)Meth; +@end + +@implementation CURRENT(CAT) ++ (void)Meth { [super Meth]; } +@end diff --git a/test/CodeGenObjC/super-dotsyntax-property.m b/test/CodeGenObjC/super-dotsyntax-property.m new file mode 100644 index 000000000000..6e4f176724c8 --- /dev/null +++ b/test/CodeGenObjC/super-dotsyntax-property.m @@ -0,0 +1,41 @@ +// RUN: clang-cc -emit-llvm -o %t %s + +@interface B +{ + int _parent; +} +@property int parent; + +(int) classGetter; + +(void) setClassGetter:(int) arg; + + -(int) getter; + -(void) setGetter:(int)arg; +@end + +@interface A : B +@end + +@implementation A ++(int) classGetter { + return 0; +} + ++(int) classGetter2 { + super.classGetter = 100; + return super.classGetter; +} + +-(void) method { + super.getter = 200; + int x = super.getter; +} +-(void) setParent : (int) arg { + super.parent = arg + super.parent; + +} +@end + +void f0() { + int l1 = A.classGetter; + int l2 = [A classGetter2]; +} diff --git a/test/CodeGenObjC/synchronized.m b/test/CodeGenObjC/synchronized.m new file mode 100644 index 000000000000..b398ca6c0a59 --- /dev/null +++ b/test/CodeGenObjC/synchronized.m @@ -0,0 +1,41 @@ +// RUN: clang-cc -emit-llvm -triple=i686-apple-darwin9 -o %t %s -O2 && +// RUN: grep 'ret i32' %t | count 1 && +// RUN: grep 'ret i32 1' %t | count 1 + +@interface MyClass +{ +} +- (void)method; +@end + +@implementation MyClass + +- (void)method +{ + @synchronized(self) + { + } +} + +@end + +void foo(id a) { + @synchronized(a) { + return; + } +} + +int f0(id a) { + int x = 0; + @synchronized((x++, a)) { + } + return x; // ret i32 1 +} + +void f1(id a) { + // The trick here is that the return shouldn't go through clean up, + // but there isn't a simple way to check this property. + @synchronized(({ return; }), a) { + return; + } +} diff --git a/test/CodeGenObjC/synthesize_ivar-cont-class.m b/test/CodeGenObjC/synthesize_ivar-cont-class.m new file mode 100644 index 000000000000..b1a7d0e68030 --- /dev/null +++ b/test/CodeGenObjC/synthesize_ivar-cont-class.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s && +// RUN: grep '@"OBJC_IVAR_$_XCOrganizerDeviceNodeInfo.viewController"' %t + +@interface XCOrganizerNodeInfo +@property (readonly, retain) id viewController; +@end + +@interface XCOrganizerDeviceNodeInfo : XCOrganizerNodeInfo +@end + +@interface XCOrganizerDeviceNodeInfo() +@property (retain) id viewController; +@end + +@implementation XCOrganizerDeviceNodeInfo +@synthesize viewController; +@end + diff --git a/test/CodeGenObjC/synthesize_ivar.m b/test/CodeGenObjC/synthesize_ivar.m new file mode 100644 index 000000000000..7646f707bf76 --- /dev/null +++ b/test/CodeGenObjC/synthesize_ivar.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s + +@interface I +{ +} +@property int IP; +@end + +@implementation I +@synthesize IP; +- (int) Meth { + return IP; +} +@end + +// Test for synthesis of ivar for a property +// declared in continuation class. +@interface OrganizerViolatorView +@end + +@interface OrganizerViolatorView() +@property (retain) id bindingInfo; +@end + +@implementation OrganizerViolatorView +@synthesize bindingInfo; +@end diff --git a/test/CodeGenObjC/try.m b/test/CodeGenObjC/try.m new file mode 100644 index 000000000000..7701b23e0819 --- /dev/null +++ b/test/CodeGenObjC/try.m @@ -0,0 +1,9 @@ +// RUN: clang-cc %s -S -o - -triple=i686-apple-darwin9 && +// RUN: clang-cc %s -S -o - -triple=x86_64-apple-darwin9 + +// rdar://6757213 - Don't crash if the internal proto for +// __objc_personality_v0 mismatches with an actual one. +void __objc_personality_v0() { } +void test1(void) { + @try { } @catch (...) { } +} diff --git a/test/CodeGenObjC/unname-bf-metadata.m b/test/CodeGenObjC/unname-bf-metadata.m new file mode 100644 index 000000000000..a7636e4ebc8b --- /dev/null +++ b/test/CodeGenObjC/unname-bf-metadata.m @@ -0,0 +1,14 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s +// Test that meta-data for ivar lists with unnamed bitfield are generated. +// +@interface Foo { +@private + int first; + int :1; + int third :1; + int :1; + int fifth :1; +} +@end +@implementation Foo +@end diff --git a/test/Coverage/ast-printing.c b/test/Coverage/ast-printing.c new file mode 100644 index 000000000000..efa950934ba0 --- /dev/null +++ b/test/Coverage/ast-printing.c @@ -0,0 +1,6 @@ +// RUN: clang-cc --fsyntax-only %s && +// RUN: clang-cc --ast-print %s && +// RUN: clang-cc --ast-dump %s && +// RUN: clang-cc --ast-print-xml -o %t %s + +#include "c-language-features.inc" diff --git a/test/Coverage/ast-printing.cpp b/test/Coverage/ast-printing.cpp new file mode 100644 index 000000000000..10d01c743744 --- /dev/null +++ b/test/Coverage/ast-printing.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc --fsyntax-only %s && +// RUN: clang-cc --ast-print %s && +// RUN: clang-cc --ast-dump %s +// FIXME: clang-cc --ast-print-xml -o %t %s + +#include "cxx-language-features.inc" diff --git a/test/Coverage/ast-printing.m b/test/Coverage/ast-printing.m new file mode 100644 index 000000000000..85bbd4314a4d --- /dev/null +++ b/test/Coverage/ast-printing.m @@ -0,0 +1,5 @@ +// RUN: clang-cc --fsyntax-only %s && +// RUN: clang-cc --ast-print %s && +// RUN: clang-cc --ast-dump %s + +#include "objc-language-features.inc" diff --git a/test/Coverage/c-language-features.inc b/test/Coverage/c-language-features.inc new file mode 100644 index 000000000000..bcf4127299f0 --- /dev/null +++ b/test/Coverage/c-language-features.inc @@ -0,0 +1,181 @@ +//-*- C -*- + +/* This is a + multiline comment */ + +// Intended to exercise all syntactic parts of the C language. + +int g0; +int g1, g2; + +struct s0; + +struct s0 { + int x; +}; + +int g3 = 10; + +__asm(""); + +typedef int td0; + +td0 g4; + +enum e0 { + ec0 +}; + +static void f0(int x) { +} + +inline void f0_0(int x) { + ; +} + +extern void f0_1(int x) { +} + +void f1(int, ...); + +// Statements. +void f2() { + for (;;) { + break; + continue; + } + + while (0) { + } + + do { + } while (0); + + void *label = &&theif; + goto *label; + + goto theif; +theif: + if (0) { + ; + } else if (0) { + } else { + } + + switch(0) { + case 0: + case 1 ... 2: + break; + default: + break; + } + + asm ("nop"); + + return; +} + +// Expressions. + +#include <stdarg.h> + +typedef struct ipair { + int first, second; +} ipair; + +void f4(int a0, int a1, int a2, va_list ap) { + int t0 = a0 ? a1 : a2; + float t1 = (float) a0; + ipair t2 = {1, 2}; + ipair t2a = { .second = 2 }; + int t3 = sizeof(ipair); + ipair t4; + t4 = (ipair) {1, 2}; + extern int g(int); + int t5 = g(a0); + int t6 = t4.first; + int t7[10]; + int t8 = t7[a0]; + t8++; + const char *t9 = __FUNCTION__; + char t10 = 'x'; + int t11 = __builtin_offsetof(ipair, first); + int t12 = __builtin_types_compatible_p(ipair, int); + int t12_0 = __builtin_classify_type(t0); + int t12_1 = __builtin_classify_type(t1); + int t12_2 = __builtin_classify_type(t2); + // FIXME: Add _Complex and aggregate cases. + int t13 = va_arg(ap, int); + va_list t13_0; + va_copy(t13_0, ap); + int t14 = __extension__(t13); + int t15 = +t13; + unsigned t16 = t14 ^ t15; + int t17 = t14 % t15; + int t17_0 = t16 % t16; + float t18; + int t19 = t18 ? 0 : 1; + char *t20; ++t20; --t20; + float t21; ++t21; --t21; + double t22; ++t22; --t22; + long double t23; ++t23; --t23; + int t24 = !t19; + int t25 = __real t24; + int t26 = __imag t24; + const char *t27 = t9; + t27 += (unsigned char) 0xFF; + t27 += (signed char) 0xFF; + + struct { char f0[10]; } *t28; + int t29 = t28 - t28; + char *t30 = &t28->f0[1]; + + struct s1 { int f0; }; + struct s1 t31_a, t31_b; + int t31_cond; + int t31 = (t31_cond ? t31_a : t31_b).f0; + + _Complex float t32_a, t32_b; + int t32_cond; + int t32 = __real (t32_cond ? t32_a : t32_b); + + struct { int x, y; } t33, *t34, t35[12], t36(int, float); + float t37, *t38, t39[9], t40(double); +} + +// Extended vectors + +typedef __attribute__((ext_vector_type(2))) float float2; +typedef __attribute__((ext_vector_type(4))) float float4; + +void f5() { + float4 t0 = (float4) { 0, 1, 2, 3 }; + float4 t1 = t0; + t0.lo.even = t1.hi.x; + + // irgen doesn't support this yet. +#if 0 + int t2_cond; + float2 t2 = (t2_cond ? t0 : t1).lo; +#endif +} + +void f6() { + const char *s0 = __func__; + const char *s1 = __FUNCTION__; + const char *s2 = __PRETTY_FUNCTION__; +} + +// Arg mismatch with passed type. +void f7(x) + float x; +{ +} + +void f8(x) + short x; +{ +} + +// Function which inputs an array +void f9(int x[]) { } diff --git a/test/Coverage/codegen-gnu.m b/test/Coverage/codegen-gnu.m new file mode 100644 index 000000000000..bc8d6d642e41 --- /dev/null +++ b/test/Coverage/codegen-gnu.m @@ -0,0 +1,3 @@ +// RUN: clang-cc -triple i386-unknown-unknown -fgnu-runtime -emit-llvm -o %t %s + +#include "objc-language-features.inc" diff --git a/test/Coverage/codegen-next.m b/test/Coverage/codegen-next.m new file mode 100644 index 000000000000..bca83cba6931 --- /dev/null +++ b/test/Coverage/codegen-next.m @@ -0,0 +1,4 @@ +// RUN: clang-cc -fnext-runtime -emit-llvm -o %t %s && +// RUN: clang-cc -g -fnext-runtime -emit-llvm -o %t %s + +#include "objc-language-features.inc" diff --git a/test/Coverage/codegen.c b/test/Coverage/codegen.c new file mode 100644 index 000000000000..543c361e1bbd --- /dev/null +++ b/test/Coverage/codegen.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm -o %t %s && +// RUN: clang-cc -triple i386-unknown-unknown -emit-llvm-bc -o %t %s && +// RUN: clang-cc -triple i386-unknown-unknown -g -emit-llvm-bc -o %t %s && +// RUN: clang-cc -triple x86_64-unknown-unknown -emit-llvm-bc -o %t %s && +// RUN: clang-cc -triple x86_64-unknown-unknown -g -emit-llvm-bc -o %t %s + +#include "c-language-features.inc" diff --git a/test/Coverage/cxx-language-features.inc b/test/Coverage/cxx-language-features.inc new file mode 100644 index 000000000000..51c11046a84c --- /dev/null +++ b/test/Coverage/cxx-language-features.inc @@ -0,0 +1,21 @@ +//-*- C++ -*- + +// Intended to exercise all syntactic parts of the C++ language that +// aren't part of C. + +namespace std { + namespace debug { + } +} + +using namespace std::debug; +using namespace std; + +namespace safestl = ::std::debug; + +class Base1 { +}; + +class Base2 { }; + +class Derived1 : Base1, virtual public Base2 { }; diff --git a/test/Coverage/html-diagnostics.c b/test/Coverage/html-diagnostics.c new file mode 100644 index 000000000000..6144f2fb98a3 --- /dev/null +++ b/test/Coverage/html-diagnostics.c @@ -0,0 +1,15 @@ +// RUN: rm -rf %t && +// RUN: clang-cc --html-diags=%t -checker-simple %s + +void f0(int x) { + int *p = &x; + + if (x > 10) { + if (x == 22) + p = 0; + } + + *p = 10; +} + + diff --git a/test/Coverage/html-print.c b/test/Coverage/html-print.c new file mode 100644 index 000000000000..dab156b145a8 --- /dev/null +++ b/test/Coverage/html-print.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -emit-html -o %t %s + +#include "c-language-features.inc" diff --git a/test/Coverage/objc-language-features.inc b/test/Coverage/objc-language-features.inc new file mode 100644 index 000000000000..dd57dfbedd03 --- /dev/null +++ b/test/Coverage/objc-language-features.inc @@ -0,0 +1,81 @@ +//-*- ObjC -*- + +@protocol P0; + +@protocol P1 +-(void) fm0; +@end + +@class B; + +@interface Root +@end + +@interface A : Root <P1> { + int iv0; + B *iv1; +} + +@property(readonly) int p0; +@property(assign,nonatomic,readwrite) int p1; +@property(copy) id p2; +@property(retain) id p3; +@property(assign, getter=getme, setter=setme:) id p4; +@end + +@implementation A +@dynamic p0; +@synthesize p1 = iv0; ++(void) fm0 { + [super fm0]; +} +-(void) im0 { + const char *s0 = __func__; + const char *s1 = __FUNCTION__; + const char *s2 = __PRETTY_FUNCTION__; + [super im0]; + int x = super.p0; +} +-(void) im1: (int) x, ... { +} +@end + +@implementation C : A +@end + +@interface A (Cat) +@end + +@implementation A (Cat) +@end + +@interface B +@end + +int f0(id x) { + @synchronized(x) { + } + + @try { + @throw x; + + } @catch(A *e) { + @throw; + + // @catch param doesn't require name. + } @catch(B *) { + + } @finally { + ; + } + + for (id y in x) { + break; + } +} + +#ifndef __OBJC2__ +struct s0 { + @defs(A); +}; +#endif diff --git a/test/Coverage/parse-callbacks.c b/test/Coverage/parse-callbacks.c new file mode 100644 index 000000000000..309074de9e7d --- /dev/null +++ b/test/Coverage/parse-callbacks.c @@ -0,0 +1,4 @@ +// RUN: clang-cc --parse-noop %s && +// RUN: clang-cc --parse-print-callbacks %s + +#include "c-language-features.inc" diff --git a/test/Coverage/parse-callbacks.m b/test/Coverage/parse-callbacks.m new file mode 100644 index 000000000000..dc1dcfc66270 --- /dev/null +++ b/test/Coverage/parse-callbacks.m @@ -0,0 +1,4 @@ +// RUN: clang-cc --parse-noop %s && +// RUN: clang-cc --parse-print-callbacks %s + +#include "objc-language-features.inc" diff --git a/test/Coverage/targets.c b/test/Coverage/targets.c new file mode 100644 index 000000000000..5a547a53add9 --- /dev/null +++ b/test/Coverage/targets.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -g -triple i686-unknown-unknown -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple i686-pc-linux-gnu -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple i686-unknown-dragonfly -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple i686-unknown-win32 -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple i686-apple-darwin9 -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple x86_64-unknown-unknown -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple x86_64-pc-linux-gnu -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple x86_64-apple-darwin9 -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple ppc-unknown-unknown -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple ppc-apple-darwin9 -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple ppc64-unknown-unknown -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple ppc64-apple-darwin9 -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple armv6-unknown-unknown -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple armv6-apple-darwin9 -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple sparc-unknown-unknown -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple sparc-unknown-solaris -emit-llvm -o %t %s && +// RUN: clang-cc -g -triple pic16-unknown-unknown -emit-llvm -o %t %s && +// RUN: true diff --git a/test/Coverage/verbose.c b/test/Coverage/verbose.c new file mode 100644 index 000000000000..a75557b3fdee --- /dev/null +++ b/test/Coverage/verbose.c @@ -0,0 +1 @@ +// RUN: clang-cc -fsyntax-only -v %s diff --git a/test/Driver/Xarch.c b/test/Driver/Xarch.c new file mode 100644 index 000000000000..a2a3fdea309e --- /dev/null +++ b/test/Driver/Xarch.c @@ -0,0 +1,10 @@ +// RUN: clang -ccc-host-triple i386-apple-darwin9 -m32 -Xarch_i386 -O2 %s -S -### 2> %t.log && +// RUN: grep ' "-O2" ' %t.log | count 1 && +// RUN: clang -ccc-host-triple i386-apple-darwin9 -m64 -Xarch_i386 -O2 %s -S -### 2> %t.log && +// RUN: grep ' "-O2" ' %t.log | count 0 && +// RUN: grep "argument unused during compilation: '-Xarch_i386 -O2'" %t.log && +// RUN: not clang -ccc-host-triple i386-apple-darwin9 -m32 -Xarch_i386 -o -Xarch_i386 -S %s -S -Xarch_i386 -o 2> %t.log && +// RUN: grep "error: invalid Xarch argument: '-Xarch_i386 -o'" %t.log | count 2 && +// RUN: grep "error: invalid Xarch argument: '-Xarch_i386 -S'" %t.log && +// RUN: true + diff --git a/test/Driver/analyze.c b/test/Driver/analyze.c new file mode 100644 index 000000000000..338c6148c1c3 --- /dev/null +++ b/test/Driver/analyze.c @@ -0,0 +1,9 @@ +// Verify that the analyzer gets the same flags as normal compilation +// (at least for a few key ones). + +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### --analyze -o /dev/null %s -msse 2> %t.log && +// RUN: grep '"-analyze"' %t.log && +// RUN: grep '"--fmath-errno=0"' %t.log && +// RUN: grep '"-target-feature" "+sse"' %t.log && +// RUN: grep '"-mmacosx-version-min=10.5.0"' %t.log + diff --git a/test/Driver/bindings.c b/test/Driver/bindings.c new file mode 100644 index 000000000000..3cac22c94be3 --- /dev/null +++ b/test/Driver/bindings.c @@ -0,0 +1,56 @@ +// Basic binding. +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings %s 2> %t && +// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: ".*\.s"' %t && +// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t && +// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t && + +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang %s 2> %t && +// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: ".*\.s"' %t && +// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t && +// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t && + +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -no-integrated-cpp %s 2> %t && +// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: ".*\.i"' %t && +// RUN: grep '"gcc::Compile", inputs: \[".*\.i"\], output: ".*\.s"' %t && +// RUN: grep '"gcc::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t && +// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t && + +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -no-integrated-cpp -pipe %s 2> %t && +// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: (pipe)' %t && +// RUN: grep '"gcc::Compile", inputs: \[(pipe)\], output: (pipe)' %t && +// RUN: grep '"gcc::Assemble", inputs: \[(pipe)\], output: ".*\.o"' %t && +// RUN: grep '"gcc::Link", inputs: \[".*\.o"\], output: "a.out"' %t && + +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -x c-header %s 2> %t && +// RUN: grep '"gcc::Precompile", inputs: \[".*bindings.c"\], output: ".*bindings.c.gch' %t && + +// Clang control options + +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -fsyntax-only %s 2> %t && +// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: (nothing)' %t && +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang -fsyntax-only %s 2> %t && +// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: (nothing)' %t && +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -fsyntax-only -x c++ %s 2> %t && +// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: (nothing)' %t && +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-clang-cxx -fsyntax-only -x c++ %s 2> %t && +// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: (nothing)' %t && +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-bindings -ccc-no-clang-cpp -fsyntax-only -no-integrated-cpp %s 2> %t && +// RUN: grep '"gcc::Preprocess", inputs: \[".*bindings.c"\], output: ".*\.i"' %t && +// RUN: grep '"clang", inputs: \[".*\.i"\], output: (nothing)' %t && +// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings -ccc-clang-archs i386 %s -S -arch ppc 2> %t && +// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: "bindings.s"' %t && +// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings -ccc-clang-archs ppc %s -S -arch ppc 2> %t && +// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: "bindings.s"' %t && + +// RUN: clang -ccc-host-triple powerpc-unknown-unknown -ccc-print-bindings -ccc-clang-archs "" %s -S 2> %t && +// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: "bindings.s"' %t && +// RUN: clang -ccc-host-triple powerpc-unknown-unknown -ccc-print-bindings %s -S 2> %t && +// RUN: grep '"gcc::Compile", inputs: \[".*bindings.c"\], output: "bindings.s"' %t && + +// Darwin bindings +// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-bindings %s 2> %t && +// RUN: grep '"clang", inputs: \[".*bindings.c"\], output: ".*\.s"' %t && +// RUN: grep '"darwin::Assemble", inputs: \[".*\.s"\], output: ".*\.o"' %t && +// RUN: grep '"darwin::Link", inputs: \[".*\.o"\], output: "a.out"' %t && + +// RUN: true diff --git a/test/Driver/ccc-add-args.c b/test/Driver/ccc-add-args.c new file mode 100644 index 000000000000..b504b0b42933 --- /dev/null +++ b/test/Driver/ccc-add-args.c @@ -0,0 +1,3 @@ +// RUN: env CCC_ADD_ARGS="-ccc-echo,-ccc-print-options,,-v" clang -### 2> %t && +// RUN: grep -F 'Option 0 - Name: "-v", Values: {}' %t && +// RUN: grep -F 'Option 1 - Name: "-###", Values: {}' %t diff --git a/test/Driver/clang-translation.c b/test/Driver/clang-translation.c new file mode 100644 index 000000000000..ca60a8d8c6bc --- /dev/null +++ b/test/Driver/clang-translation.c @@ -0,0 +1,16 @@ +// RUN: clang -ccc-host-triple i386-unknown-unknown -### -S -O0 -Os %s -o %t.s -fverbose-asm 2> %t.log +// RUN: grep '"-triple" "i386-unknown-unknown"' %t.log && +// RUN: grep '"-S"' %t.log && +// RUN: grep '"-disable-free"' %t.log && +// RUN: grep '"--relocation-model" "static"' %t.log && +// RUN: grep '"--disable-fp-elim"' %t.log && +// RUN: grep '"--unwind-tables=0"' %t.log && +// RUN: grep '"--fmath-errno=1"' %t.log && +// RUN: grep '"-Os"' %t.log && +// RUN: grep '"-o" .*clang-translation\.c\.out\.tmp\.s' %t.log && +// RUN: grep '"--asm-verbose"' %t.log && +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S %s -o %t.s 2> %t.log +// RUN: grep '"--mcpu=yonah"' %t.log && +// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -### -S %s -o %t.s 2> %t.log +// RUN: grep '"--mcpu=core2"' %t.log && +// RUN: true diff --git a/test/Driver/clang_cpp.c b/test/Driver/clang_cpp.c new file mode 100644 index 000000000000..fdbb321e1e91 --- /dev/null +++ b/test/Driver/clang_cpp.c @@ -0,0 +1,4 @@ +// Verify that -include isn't included twice with -save-temps. +// RUN: clang -S -o - %s -include %t.h -save-temps -### 2> %t.log && +// RUN: grep '"-include' %t.log | count 1 + diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c new file mode 100644 index 000000000000..9dc8f63db8de --- /dev/null +++ b/test/Driver/clang_f_opts.c @@ -0,0 +1,10 @@ +// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings %s 2> %t && +// RUN: grep -F '"-fblocks"' %t && +// RUN: grep -F '"--fmath-errno=1"' %t && +// RUN: grep -F '"-fpascal-strings"' %t && +// RUN: clang -### -S -x c /dev/null -fblocks -fbuiltin -fmath-errno -fcommon -fpascal-strings -fno-blocks -fno-builtin -fno-math-errno -fno-common -fno-pascal-strings %s 2> %t && +// RUN: grep -F '"-fblocks=0"' %t && +// RUN: grep -F '"-fbuiltin=0"' %t && +// RUN: grep -F '"-fno-common"' %t && +// RUN: grep -F '"--fmath-errno=0"' %t && +// RUN: true diff --git a/test/Driver/darwin-cc.c b/test/Driver/darwin-cc.c new file mode 100644 index 000000000000..77193cda4441 --- /dev/null +++ b/test/Driver/darwin-cc.c @@ -0,0 +1,6 @@ +// RUN: clang -ccc-no-clang -ccc-host-triple i386-apple-darwin10 -m32 -### -MD -g -fast -Q -dA -mkernel -ansi -aFOO -S -o /tmp/OUTPUTNAME -g0 -gfull -O2 -Werror -pedantic -Wmost -w -std=c99 -trigraphs -v -pg -fFOO -undef -Qn --param a=b -fmudflap -coverage -save-temps -nostdinc -I ARG0 -F ARG1 -I ARG2 -P -MF ARG3 -MG -MP -remap -g3 -H -D ARG4 -U ARG5 -A ARG6 -D ARG7 -U ARG8 -A ARG9 -include ARG10 -pthread %s 2> %t.log && +// RUN: grep ' ".*cc1" "-E" "-nostdinc" "-v" "-I" "ARG0" "-F" "ARG1" "-I" "ARG2" "-P" "-MD" "/tmp/OUTPUTNAME.d" "-MF" "ARG3" "-MG" "-MP" "-MQ" "/tmp/OUTPUTNAME" "-remap" "-dD" "-H" "-D__STATIC__" "-D_REENTRANT" "-D" "ARG4" "-U" "ARG5" "-A" "ARG6" "-D" "ARG7" "-U" "ARG8" "-A" "ARG9" "-include" "ARG10" ".*darwin-cc.c" "-D_MUDFLAP" "-include" "mf-runtime.h" "-mmacosx-version-min=10.6.0" "-m32" "-mkernel" "-mtune=core2" "-ansi" "-std=c99" "-trigraphs" "-Werror" "-pedantic" "-Wmost" "-w" "-fast" "-fno-eliminate-unused-debug-symbols" "-fFOO" "-fmudflap" "-O2" "-undef" "-fpch-preprocess" "-o" ".*darwin-cc.i"' %t.log && +// RUN: grep ' ".*cc1" "-fpreprocessed" ".*darwin-cc.i" "-O3" "-dumpbase" ".*darwin-cc.c" "-dA" "-mmacosx-version-min=10.6.0" "-m32" "-mkernel" "-mtune=core2" "-ansi" "-aFOO" "-auxbase-strip" "/tmp/OUTPUTNAME" "-g" "-g0" "-g" "-g3" "-O2" "-Werror" "-pedantic" "-Wmost" "-w" "-ansi" "-std=c99" "-trigraphs" "-version" "-p" "-fast" "-fno-eliminate-unused-debug-symbols" "-fFOO" "-fmudflap" "-undef" "-fno-ident" "-o" "/tmp/OUTPUTNAME" "--param" "a=b" "-fno-builtin" "-fno-merge-constants" "-fprofile-arcs" "-ftest-coverage"' %t.log && + +// RUN: true + diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c new file mode 100644 index 000000000000..5ac5ae39172a --- /dev/null +++ b/test/Driver/darwin-ld.c @@ -0,0 +1,44 @@ +// Check that ld gets arch_multiple. + +// RUN: clang -ccc-host-triple i386-apple-darwin9 -arch i386 -arch x86_64 %s -### -o foo 2> %t.log && +// RUN: grep '".*ld" .*"-arch_multiple" "-final_output" "foo"' %t.log && + +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -filelist FOO -static 2> %t.log && +// RUN: grep '"-lcrt0.o" .*"-lgcc_static"' %t.log && +// RUN: grep '"-lgcc"' %t.log | count 0 && +// RUN: clang -ccc-host-triple i386-apple-darwin7 -### -filelist FOO 2> %t.log && +// RUN: grep '"-lcrt1.o" .*"-lgcc" "-lSystem"' %t.log && +// RUN: grep '"-lgcc_s"' %t.log | count 0 && +// RUN: clang -ccc-host-triple i386-apple-darwin8 -### -filelist FOO 2> %t.log && +// RUN: grep '"-lcrt1.o" .*"-lgcc_s.10.4" "-lgcc" "-lSystem"' %t.log && +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -filelist FOO 2> %t.log && +// RUN: grep '"-lcrt1.10.5.o" .*"-lgcc_s.10.5" "-lgcc" "-lSystem"' %t.log && +// RUN: clang -ccc-host-triple i386-apple-darwin10 -### -filelist FOO 2> %t.log && +// RUN: grep '"-lcrt1.10.6.o" .*"-lSystem" "-lgcc"' %t.log && +// RUN: grep '"-lgcc_s"' %t.log | count 0 && + +// Make sure we run dsymutil on source input files. +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -g %s -o BAR 2> %t.log && +// RUN: grep '".*dsymutil" "BAR"' %t.log && +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -g -filelist FOO %s -o BAR 2> %t.log && +// RUN: grep '".*dsymutil" "BAR"' %t.log && + +// Splatter test case. This is gross, but it works for now. For the +// driver, just getting coverage of the tool code and checking the +// output options is nearly good enough. The main thing we are +// protecting against here is unintended changes in the driver +// output. Intended changes should add more reasonable test cases, and +// just update this test to match the expected behavior. +// +// Note that at conception, this exactly matches gcc. + +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -A ARG0 -F ARG1 -L ARG2 -Mach -T ARG4 -X -Z -all_load -allowable_client ARG8 -bind_at_load -compatibility_version ARG11 -current_version ARG12 -d -dead_strip -dylib_file ARG14 -dylinker -dylinker_install_name ARG16 -dynamic -dynamiclib -e ARG19 -exported_symbols_list ARG20 -fexceptions -flat_namespace -fnested-functions -fopenmp -force_cpusubtype_ALL -fpie -fprofile-arcs -headerpad_max_install_names -image_base ARG29 -init ARG30 -install_name ARG31 -m ARG33 -miphoneos-version-min=2.0 -mmacosx-version-min=10.3.2 -multi_module -multiply_defined ARG37 -multiply_defined_unused ARG38 -no_dead_strip_inits_and_terms -nodefaultlibs -nofixprebinding -nomultidefs -noprebind -noseglinkedit -nostartfiles -nostdlib -object -pagezero_size ARG54 -pg -prebind -prebind_all_twolevel_modules -preload -r -read_only_relocs ARG55 -s -sectalign ARG57_0 ARG57_1 ARG57_2 -sectcreate ARG58_0 ARG58_1 ARG58_2 -sectobjectsymbols ARG59_0 ARG59_1 -sectorder ARG60_0 ARG60_1 ARG60_2 -seg1addr ARG61 -seg_addr_table ARG62 -seg_addr_table_filename ARG63 -segaddr ARG64_0 ARG64_1 -segcreate ARG65_0 ARG65_1 ARG65_2 -seglinkedit -segprot ARG67_0 ARG67_1 ARG67_2 -segs_read_FOO -segs_read_only_addr ARG69 -segs_read_write_addr ARG70 -shared-libgcc -single_module -static -static-libgcc -sub_library ARG77 -sub_umbrella ARG78 -t -twolevel_namespace -twolevel_namespace_hints -u ARG82 -umbrella ARG83 -undefined ARG84 -unexported_symbols_list ARG85 -w -weak_reference_mismatches ARG87 -whatsloaded -whyload -y -filelist FOO 2> %t.log && +// RUN: grep '".*ld" "-static" "-dylib" "-dylib_compatibility_version" "ARG11" "-dylib_current_version" "ARG12" "-arch" "i386" "-dylib_install_name" "ARG31" "-all_load" "-allowable_client" "ARG8" "-bind_at_load" "-dead_strip" "-no_dead_strip_inits_and_terms" "-dylib_file" "ARG14" "-dynamic" "-exported_symbols_list" "ARG20" "-flat_namespace" "-headerpad_max_install_names" "-image_base" "ARG29" "-init" "ARG30" "-macosx_version_min" "10.3.2" "-iphoneos_version_min" "2.0" "-nomultidefs" "-multi_module" "-single_module" "-multiply_defined" "ARG37" "-multiply_defined_unused" "ARG38" "-pie" "-prebind" "-noprebind" "-nofixprebinding" "-prebind_all_twolevel_modules" "-read_only_relocs" "ARG55" "-sectcreate" "ARG58_0" "ARG58_1" "ARG58_2" "-sectorder" "ARG60_0" "ARG60_1" "ARG60_2" "-seg1addr" "ARG61" "-segprot" "ARG67_0" "ARG67_1" "ARG67_2" "-segaddr" "ARG64_0" "ARG64_1" "-segs_read_only_addr" "ARG69" "-segs_read_write_addr" "ARG70" "-seg_addr_table" "ARG62" "-seg_addr_table_filename" "ARG63" "-sub_library" "ARG77" "-sub_umbrella" "ARG78" "-twolevel_namespace" "-twolevel_namespace_hints" "-umbrella" "ARG83" "-undefined" "ARG84" "-unexported_symbols_list" "ARG85" "-weak_reference_mismatches" "ARG87" "-X" "-y" "-w" "-pagezero_size" "ARG54" "-segs_read_FOO" "-seglinkedit" "-noseglinkedit" "-sectalign" "ARG57_0" "ARG57_1" "ARG57_2" "-sectobjectsymbols" "ARG59_0" "ARG59_1" "-segcreate" "ARG65_0" "ARG65_1" "ARG65_2" "-whyload" "-whatsloaded" "-dylinker_install_name" "ARG16" "-dylinker" "-Mach" "-d" "-s" "-t" "-Z" "-u" "ARG82" "-undefined" "ARG84" "-A" "ARG0" "-e" "ARG19" "-m" "ARG33" "-r" "-object" "-o" "a.out" "-L" "ARG2" "-lgomp" "-L/usr/lib/i686-apple-darwin9/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin9/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin9/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin9/4.2.1/../../../i686-apple-darwin9/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin9/4.2.1/../../.." "-filelist" "FOO" "-lgcov" "-allow_stack_execute" "-T" "ARG4" "-F" "ARG1"' %t.log && + +// Don't run dsymutil on a fat build of an executable. +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -arch i386 -arch x86_64 -g %s 2> %t.log && +// RUN: grep dsymutil %t.log | count 0 && + +// RUN: true + + diff --git a/test/Driver/darwin-version.c b/test/Driver/darwin-version.c new file mode 100644 index 000000000000..dd6905a58961 --- /dev/null +++ b/test/Driver/darwin-version.c @@ -0,0 +1,6 @@ +// RUN: env MACOSX_DEPLOYMENT_TARGET=10.1 clang -ccc-host-triple i386-apple-darwin9 -E %s + +#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ != 1010 +#error Invalid version +#endif + diff --git a/test/Driver/dragonfly.c b/test/Driver/dragonfly.c new file mode 100644 index 000000000000..5d7b0b0f0045 --- /dev/null +++ b/test/Driver/dragonfly.c @@ -0,0 +1,6 @@ +// RUN: clang -ccc-host-triple amd64-pc-dragonfly %s -### 2> %t.log && +// RUN: grep 'clang-cc" "-triple" "x86_64-pc-dragonfly"' %t.log && +// RUN: grep 'as" "-o" ".*\.o" ".*\.s' %t.log && +// RUN: grep 'ld" "-dynamic-linker" ".*ld-elf.*" "-o" "a\.out" ".*crt1.o" ".*crti.o" "crtbegin.o" ".*\.o" "-L.*/gcc.*" .* "-lc" "-lgcc" ".*crtend.o" ".*crtn.o"' %t.log && +// RUN: true + diff --git a/test/Driver/emit-llvm.c b/test/Driver/emit-llvm.c new file mode 100644 index 000000000000..a4aabe7256dc --- /dev/null +++ b/test/Driver/emit-llvm.c @@ -0,0 +1,3 @@ +// RUN: not clang -ccc-host-triple i386-pc-linux-gnu -emit-llvm -o %t %s 2> %t.log && +// RUN: grep 'unable to pass LLVM bit-code files to linker' %t.log + diff --git a/test/Driver/flags.c b/test/Driver/flags.c new file mode 100644 index 000000000000..53f3995f394d --- /dev/null +++ b/test/Driver/flags.c @@ -0,0 +1,9 @@ +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -msoft-float %s 2> %t.log && +// RUN: grep '"--soft-float"' %t.log && + +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -msoft-float -mno-soft-float %s 2> %t.log && +// RUN: grep '"--soft-float"' %t.log | count 0 && + +// RUN: clang -ccc-host-triple i386-apple-darwin9 -### -S -mno-soft-float %s -msoft-float 2> %t.log && +// RUN: grep '"--soft-float"' %t.log + diff --git a/test/Driver/freebsd.c b/test/Driver/freebsd.c new file mode 100644 index 000000000000..91258d9e5728 --- /dev/null +++ b/test/Driver/freebsd.c @@ -0,0 +1,7 @@ +// RUN: clang -ccc-clang-archs "" -ccc-host-triple ppc64-pc-freebsd8 %s -### 2> %t.log && +// RUN: cat %t.log && +// RUN: grep 'clang-cc" "-triple" "powerpc64-pc-freebsd8"' %t.log && +// RUN: grep 'as" "-o" ".*\.o" ".*\.s' %t.log && +// RUN: grep 'ld" "--eh-frame-hdr" "-dynamic-linker" ".*ld-elf.*" "-o" "a\.out" ".*crt1.o" ".*crti.o" "crtbegin.o" ".*\.o" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" "-lc" "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" ".*crtend.o" ".*crtn.o"' %t.log && +// RUN: true + diff --git a/test/Driver/hello.c b/test/Driver/hello.c new file mode 100644 index 000000000000..7dbe9c74f9c5 --- /dev/null +++ b/test/Driver/hello.c @@ -0,0 +1,14 @@ +// RUN: clang -ccc-echo -o %t %s 2> %t.log && + +// Make sure we used clang. +// RUN: grep 'clang-cc" .*hello.c' %t.log && + +// RUN: %t > %t.out && +// RUN: grep "I'm a little driver, short and stout." %t.out + +#include <stdio.h> + +int main() { + printf("I'm a little driver, short and stout."); + return 0; +} diff --git a/test/Driver/immediate-options.c b/test/Driver/immediate-options.c new file mode 100644 index 000000000000..34af89f44d0e --- /dev/null +++ b/test/Driver/immediate-options.c @@ -0,0 +1,5 @@ +// RUN: clang --help && +// RUN: clang --help-hidden && +// RUN: clang -dumpversion && +// RUN: clang -print-search-dirs && +// RUN: true diff --git a/test/Driver/lto.c b/test/Driver/lto.c new file mode 100644 index 000000000000..01ef2ebc2e03 --- /dev/null +++ b/test/Driver/lto.c @@ -0,0 +1,25 @@ +// -emit-llvm, -flto, and -O4 all cause a switch to llvm-bc object +// files. +// RUN: clang -ccc-print-phases -c %s -flto 2> %t.log && +// RUN: grep '2: compiler, {1}, llvm-bc' %t.log && +// RUN: clang -ccc-print-phases -c %s -O4 2> %t.log && +// RUN: grep '2: compiler, {1}, llvm-bc' %t.log && + +// and -emit-llvm doesn't alter pipeline (unfortunately?). +// RUN: clang -ccc-print-phases %s -emit-llvm 2> %t.log && +// RUN: grep '0: input, ".*lto.c", c' %t.log && +// RUN: grep '1: preprocessor, {0}, cpp-output' %t.log && +// RUN: grep '2: compiler, {1}, llvm-bc' %t.log && +// RUN: grep '3: linker, {2}, image' %t.log && + +// llvm-bc and llvm-ll outputs need to match regular suffixes +// (unfortunately). +// RUN: clang %s -emit-llvm -save-temps -### 2> %t.log && +// RUN: grep '"-o" ".*lto\.i" "-x" "c" ".*lto\.c"' %t.log && +// RUN: grep '"-o" ".*lto\.o" .*".*lto\.i"' %t.log && +// RUN: grep '".*a.out" .*".*lto\.o"' %t.log && + +// RUN: clang %s -emit-llvm -S -### 2> %t.log && +// RUN: grep '"-o" ".*lto\.s" "-x" "c" ".*lto\.c"' %t.log && + +// RUN: true diff --git a/test/Driver/parsing.c b/test/Driver/parsing.c new file mode 100644 index 000000000000..7b6444050d7d --- /dev/null +++ b/test/Driver/parsing.c @@ -0,0 +1,24 @@ +// RUN: clang -ccc-print-options input -Yunknown -m32 -arch ppc -djoined -A separate -Ajoined -Wp,one,two -Xarch_joined AndSeparate -sectalign 1 2 3 2> %t && +// RUN: grep 'Option 0 - Name: "<input>", Values: {"input"}' %t && +// RUN: grep 'Option 1 - Name: "<unknown>", Values: {"-Yunknown"}' %t && +// RUN: grep 'Option 2 - Name: "-m32", Values: {}' %t && +// RUN: grep 'Option 3 - Name: "-arch", Values: {"ppc"}' %t && +// RUN: grep 'Option 4 - Name: "-d", Values: {"joined"}' %t && +// RUN: grep 'Option 5 - Name: "-A", Values: {"separate"}' %t && +// RUN: grep 'Option 6 - Name: "-A", Values: {"joined"}' %t && +// RUN: grep 'Option 7 - Name: "-Wp,", Values: {"one", "two"}' %t && +// RUN: grep 'Option 8 - Name: "-Xarch_", Values: {"joined", "AndSeparate"}' %t && +// RUN: grep 'Option 9 - Name: "-sectalign", Values: {"1", "2", "3"}' %t && + +// RUN: not clang -V 2> %t && +// RUN: grep "error: argument to '-V' is missing (expected 1 value)" %t && +// RUN: not clang -sectalign 1 2 2> %t && +// RUN: grep "error: argument to '-sectalign' is missing (expected 3 values)" %t && + +// Verify that search continues after find the first option. +// RUN: clang -ccc-print-options -Wally 2> %t && +// RUN: grep 'Option 0 - Name: "-W", Values: {"ally"}' %t && + +// RUN: true + + diff --git a/test/Driver/phases.c b/test/Driver/phases.c new file mode 100644 index 000000000000..0967d33816fe --- /dev/null +++ b/test/Driver/phases.c @@ -0,0 +1,79 @@ +// Basic compilation for various types of files. +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c %s -x objective-c %s -x c++ %s -x objective-c++ -x assembler %s -x assembler-with-cpp %s -x none %s 2> %t && +// RUN: grep '0: input, ".*phases.c", c' %t && +// RUN: grep -F '1: preprocessor, {0}, cpp-output' %t && +// RUN: grep -F '2: compiler, {1}, assembler' %t && +// RUN: grep -F '3: assembler, {2}, object' %t && +// RUN: grep '4: input, ".*phases.c", objective-c' %t && +// RUN: grep -F '5: preprocessor, {4}, objective-c-cpp-output' %t && +// RUN: grep -F '6: compiler, {5}, assembler' %t && +// RUN: grep -F '7: assembler, {6}, object' %t && +// RUN: grep '8: input, ".*phases.c", c++' %t && +// RUN: grep -F '9: preprocessor, {8}, c++-cpp-output' %t && +// RUN: grep -F '10: compiler, {9}, assembler' %t && +// RUN: grep -F '11: assembler, {10}, object' %t && +// RUN: grep '12: input, ".*phases.c", assembler' %t && +// RUN: grep -F '13: assembler, {12}, object' %t && +// RUN: grep '14: input, ".*phases.c", assembler-with-cpp' %t && +// RUN: grep -F '15: preprocessor, {14}, assembler' %t && +// RUN: grep -F '16: assembler, {15}, object' %t && +// RUN: grep '17: input, ".*phases.c", c' %t && +// RUN: grep -F '18: preprocessor, {17}, cpp-output' %t && +// RUN: grep -F '19: compiler, {18}, assembler' %t && +// RUN: grep -F '20: assembler, {19}, object' %t && +// RUN: grep -F '21: linker, {3, 7, 11, 13, 16, 20}, image' %t && + +// Universal linked image. +// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -x c %s -arch ppc -arch i386 2> %t && +// RUN: grep '0: input, ".*phases.c", c' %t && +// RUN: grep -F '1: preprocessor, {0}, cpp-output' %t && +// RUN: grep -F '2: compiler, {1}, assembler' %t && +// RUN: grep -F '3: assembler, {2}, object' %t && +// RUN: grep -F '4: linker, {3}, image' %t && +// RUN: grep -F '5: bind-arch, "ppc", {4}, image' %t && +// RUN: grep -F '6: bind-arch, "i386", {4}, image' %t && +// RUN: grep -F '7: lipo, {5, 6}, image' %t && + +// Universal object file. +// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x c %s -arch ppc -arch i386 2> %t && +// RUN: grep '0: input, ".*phases.c", c' %t && +// RUN: grep -F '1: preprocessor, {0}, cpp-output' %t && +// RUN: grep -F '2: compiler, {1}, assembler' %t && +// RUN: grep -F '3: assembler, {2}, object' %t && +// RUN: grep -F '4: bind-arch, "ppc", {3}, object' %t && +// RUN: grep -F '5: bind-arch, "i386", {3}, object' %t && +// RUN: grep -F '6: lipo, {4, 5}, object' %t && + +// Arch defaulting +// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s 2> %t && +// RUN: grep -F '2: bind-arch, "i386", {1}, object' %t && +// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c -x assembler %s -m32 -m64 2> %t && +// RUN: grep -F '2: bind-arch, "x86_64", {1}, object' %t && +// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s 2> %t && +// RUN: grep -F '2: bind-arch, "x86_64", {1}, object' %t && +// RUN: clang -ccc-host-triple x86_64-apple-darwin9 -ccc-print-phases -c -x assembler %s -m64 -m32 2> %t && +// RUN: grep -F '2: bind-arch, "i386", {1}, object' %t && + +// Analyzer +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases --analyze %s 2> %t && +// RUN: grep '0: input, ".*phases.c", c' %t && +// RUN: grep -F '1: preprocessor, {0}, cpp-output' %t && +// RUN: grep -F '2: analyzer, {1}, plist' %t && + +// Precompiler +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -x c-header %s 2> %t && +// RUN: grep '0: input, ".*phases.c", c-header' %t && +// RUN: grep -F '1: preprocessor, {0}, c-header-cpp-output' %t && +// RUN: grep -F '2: precompiler, {1}, precompiled-header' %t && + +// Darwin overrides the handling for .s +// RUN: touch %t.s && +// RUN: clang -ccc-host-triple i386-unknown-unknown -ccc-print-phases -c %t.s 2> %t && +// RUN: grep '0: input, ".*\.s", assembler' %t && +// RUN: grep -F '1: assembler, {0}, object' %t && +// RUN: clang -ccc-host-triple i386-apple-darwin9 -ccc-print-phases -c %t.s 2> %t && +// RUN: grep '0: input, ".*\.s", assembler-with-cpp' %t && +// RUN: grep -F '1: preprocessor, {0}, assembler' %t && +// RUN: grep -F '2: assembler, {1}, object' %t && + +// RUN: true diff --git a/test/Driver/preprocessor.c b/test/Driver/preprocessor.c new file mode 100644 index 000000000000..ec1f42f5bafd --- /dev/null +++ b/test/Driver/preprocessor.c @@ -0,0 +1,6 @@ +// RUN: clang -E -x c-header %s > %t && +// RUN: grep 'B B' %t + +#define A B +A A + diff --git a/test/Driver/pth.c b/test/Driver/pth.c new file mode 100644 index 000000000000..748053809a7c --- /dev/null +++ b/test/Driver/pth.c @@ -0,0 +1,8 @@ +// Test transparent PTH support. + +// RUN: clang -ccc-pch-is-pth -x c-header %s -o %t.h.pth -### 2> %t.log && +// RUN: grep '".*/clang-cc" .* "-o" ".*\.h\.pth" "-x" "c-header" ".*pth\.c"' %t.log && + +// RUN: touch %t.h.pth && +// RUN: clang -ccc-pch-is-pth -E -include %t.h %s -### 2> %t.log && +// RUN: grep '".*/clang-cc" .*"-include-pth" ".*\.h\.pth" .*"-x" "c" ".*pth\.c"' %t.log diff --git a/test/Driver/qa_override.c b/test/Driver/qa_override.c new file mode 100644 index 000000000000..0ff578c2a814 --- /dev/null +++ b/test/Driver/qa_override.c @@ -0,0 +1,6 @@ +// RUN: env QA_OVERRIDE_GCC3_OPTIONS="+-Os +-Oz +-O +-O3 +-Oignore +a +b +c xb Xa Omagic ^-ccc-print-options " clang x -O2 b -O3 2> %t && +// RUN: grep -F 'Option 0 - Name: "<input>", Values: {"x"}' %t && +// RUN: grep -F 'Option 1 - Name: "-O", Values: {"ignore"}' %t && +// RUN: grep -F 'Option 2 - Name: "-O", Values: {"magic"}' %t && +// RUN: true + diff --git a/test/Driver/std.c b/test/Driver/std.c new file mode 100644 index 000000000000..ef6d8f197754 --- /dev/null +++ b/test/Driver/std.c @@ -0,0 +1,8 @@ +// RUN: clang -std=c99 -trigraphs -std=gnu99 %s -E -o %t && +// RUN: grep '??(??)' %t && +// RUN: clang -ansi %s -E -o %t && +// RUN: grep -F '[]' %t && +// RUN: clang -std=gnu99 -trigraphs %s -E -o %t && +// RUN: grep -F '[]' %t + +??(??) diff --git a/test/Driver/unknown-gcc-arch.c b/test/Driver/unknown-gcc-arch.c new file mode 100644 index 000000000000..de9e8e84c4ae --- /dev/null +++ b/test/Driver/unknown-gcc-arch.c @@ -0,0 +1,8 @@ +// RUN: clang -ccc-host-triple x86_64-unknown-unknown -c -x assembler %s -### 2> %t.log && +// RUN: grep '.*gcc.*"-m64"' %t.log && +// RUN: clang -ccc-host-triple x86_64-unknown-unknown -c -x assembler %s -### -m32 2> %t.log && +// RUN: grep '.*gcc.*"-m32"' %t.log && +// RUN: clang -ccc-host-triple i386-unknown-unknown -c -x assembler %s -### 2> %t.log && +// RUN: grep '.*gcc.*"-m32"' %t.log && +// RUN: clang -ccc-host-triple i386-unknown-unknown -c -x assembler %s -### -m64 2> %t.log && +// RUN: grep '.*gcc.*"-m64"' %t.log diff --git a/test/Driver/x86_features.c b/test/Driver/x86_features.c new file mode 100644 index 000000000000..efb3681f9de0 --- /dev/null +++ b/test/Driver/x86_features.c @@ -0,0 +1,3 @@ +// RUN: clang -ccc-host-triple i386-unknown-unknown -### -S %s -msse -msse4 -mno-sse -mno-mmx -msse 2> %t && +// RUN: grep '"-target-feature" "+sse" "-target-feature" "+sse4" "-target-feature" "-sse" "-target-feature" "-mmx" "-target-feature" "+sse"' %t + diff --git a/test/FixIt/fixit-at.c b/test/FixIt/fixit-at.c new file mode 100644 index 000000000000..42488f56bc7b --- /dev/null +++ b/test/FixIt/fixit-at.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -fixit-at=fixit-at.c:3:1 %s -o - | clang-cc -verify -x c - + +_Complex cd; + +int i0[1] = { { 17 } }; // expected-warning{{braces}} diff --git a/test/FixIt/fixit-c90.c b/test/FixIt/fixit-c90.c new file mode 100644 index 000000000000..03c94953db4e --- /dev/null +++ b/test/FixIt/fixit-c90.c @@ -0,0 +1,11 @@ +/* RUN: clang-cc -fsyntax-only -std=c90 -pedantic -fixit %s -o - | clang-cc -pedantic -x c -std=c90 -Werror - + */ + +/* This is a test of the various code modification hints that are + provided as part of warning or extension diagnostics. All of the + warnings will be fixed by -fixit, and the resulting file should + compile cleanly with -Werror -pedantic. */ + +enum e0 { + e1, +}; diff --git a/test/FixIt/fixit-errors-1.c b/test/FixIt/fixit-errors-1.c new file mode 100644 index 000000000000..14329ead8599 --- /dev/null +++ b/test/FixIt/fixit-errors-1.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -pedantic -Werror -x c - + +/* This is a test of the various code modification hints that are + provided as part of warning or extension diagnostics. All of the + warnings will be fixed by -fixit, and the resulting file should + compile cleanly with -Werror -pedantic. */ + +// FIXME: If you put a space at the end of the line, it doesn't work yet! +char *s = "hi\ +there"; + +// The following line isn't terminated, don't fix it. +int i; // expected-error{{no newline at end of file}} diff --git a/test/FixIt/fixit-errors.c b/test/FixIt/fixit-errors.c new file mode 100644 index 000000000000..9c5258dbcb74 --- /dev/null +++ b/test/FixIt/fixit-errors.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -pedantic -Werror -x c - + +/* This is a test of the various code modification hints that are + provided as part of warning or extension diagnostics. All of the + warnings will be fixed by -fixit, and the resulting file should + compile cleanly with -Werror -pedantic. */ + +struct s; // expected-note{{previous use is here}} + +union s *s1; // expected-error{{use of 's' with tag type that does not match previous declaration}} diff --git a/test/FixIt/fixit-objc.m b/test/FixIt/fixit-objc.m new file mode 100644 index 000000000000..baef2337c10c --- /dev/null +++ b/test/FixIt/fixit-objc.m @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -fixit-at=fixit-at.c:3:1 %s -o %t.m && +// RUN: clang-cc -verify %t.m + +@protocol X; + +void foo() { + <X> *P; // should be fixed to 'id<X>'. +} diff --git a/test/FixIt/fixit.c b/test/FixIt/fixit.c new file mode 100644 index 000000000000..1378df4de152 --- /dev/null +++ b/test/FixIt/fixit.c @@ -0,0 +1,29 @@ +// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -pedantic -Werror -x c - + +/* This is a test of the various code modification hints that are + provided as part of warning or extension diagnostics. All of the + warnings will be fixed by -fixit, and the resulting file should + compile cleanly with -Werror -pedantic. */ +#include <string.h> // FIXME: FIX-IT hint should add this for us! + +void f0(void) { }; + +struct s { + int x, y;; +}; + +_Complex cd; + +struct s s0 = { y: 5 }; +int array0[5] = { [3] 3 }; + +void f1(x, y) +{ +} + +int i0 = { 17 }; + +int f2(const char *my_string) { + // FIXME: terminal output isn't so good when "my_string" is shorter + return my_string == "foo"; +} diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp new file mode 100644 index 000000000000..ccddd959452b --- /dev/null +++ b/test/FixIt/fixit.cpp @@ -0,0 +1,29 @@ +// RUN: clang-cc -fsyntax-only -pedantic -fixit %s -o - | clang-cc -fsyntax-only -pedantic -Werror -x c++ - + +/* This is a test of the various code modification hints that are + provided as part of warning or extension diagnostics. All of the + warnings will be fixed by -fixit, and the resulting file should + compile cleanly with -Werror -pedantic. */ + +struct C1 { + virtual void f(); + static void g(); +}; +struct C2 : virtual public virtual C1 { }; // expected-error{{duplicate}} + +virtual void C1::f() { } // expected-error{{'virtual' can only be specified inside the class definition}} + +static void C1::g() { } // expected-error{{'static' can only be specified inside the class definition}} + +template<int Value> struct CT { }; // expected-note{{previous use is here}} + +CT<10 >> 2> ct; // expected-warning{{require parentheses}} + +class C3 { +public: + C3(C3, int i = 0); // expected-error{{copy constructor must pass its first argument by reference}} +}; + +struct CT<0> { }; // expected-error{{'template<>'}} + +template<> class CT<1> { }; // expected-error{{tag type}} diff --git a/test/Frontend/darwin-version.c b/test/Frontend/darwin-version.c new file mode 100644 index 000000000000..513ea197e847 --- /dev/null +++ b/test/Frontend/darwin-version.c @@ -0,0 +1,23 @@ +// RUN: clang-cc -triple armv6-apple-darwin9 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '10000' | count 1 && +// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | count 0 && +// RUN: clang-cc -triple armv6-apple-darwin9 -miphoneos-version-min=2.0 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '20000' | count 1 && +// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | count 0 && +// RUN: clang-cc -triple armv6-apple-darwin9 -miphoneos-version-min=2.2 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | grep '20200' | count 1 && +// RUN: clang-cc -triple i686-apple-darwin8 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | count 0 && +// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1040' | count 1 && +// RUN: clang-cc -triple i686-apple-darwin9 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1050' | count 1 && +// RUN: clang-cc -triple i686-apple-darwin10 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1060' | count 1 && +// RUN: clang-cc -triple i686-apple-darwin9 -mmacosx-version-min=10.4 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__' %t | count 0 && +// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1040' | count 1 && +// RUN: clang-cc -triple i686-apple-darwin9 -mmacosx-version-min=10.5 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1050' | count 1 && +// RUN: clang-cc -triple i686-apple-darwin9 -mmacosx-version-min=10.6 -dM -E -o %t - < /dev/null && +// RUN: grep '__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__' %t | grep '1060' | count 1 && +// RUN: true diff --git a/test/Frontend/dependency-gen.c b/test/Frontend/dependency-gen.c new file mode 100644 index 000000000000..456ce947f091 --- /dev/null +++ b/test/Frontend/dependency-gen.c @@ -0,0 +1,7 @@ +// rdar://6533411 +// RUN: clang -MD -MF %t.d -c -x c -o %t.o /dev/null && +// RUN: grep '.*dependency-gen.c.out.tmp.o:' %t.d && +// RUN: grep '/dev/null' %t.d && + +// RUN: clang -M -x c /dev/null -o %t.deps && +// RUN: grep 'null.o: /dev/null' %t.deps diff --git a/test/Frontend/mmacosx-version-min-test.c b/test/Frontend/mmacosx-version-min-test.c new file mode 100644 index 000000000000..d117d1c776a8 --- /dev/null +++ b/test/Frontend/mmacosx-version-min-test.c @@ -0,0 +1 @@ +// RUN: not clang-cc -fsyntax-only -mmacosx-version-min=10.4 -triple=x86_64-apple-darwin %s diff --git a/test/Frontend/rewrite-macros.c b/test/Frontend/rewrite-macros.c new file mode 100644 index 000000000000..32e02ecb266f --- /dev/null +++ b/test/Frontend/rewrite-macros.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -verify --rewrite-macros -o %t %s && + +#define A(a,b) a ## b + +// RUN: grep '12 */\*A\*/ /\*(1,2)\*/' %t && +A(1,2) + +// RUN: grep '/\*_Pragma("mark")\*/' %t && +_Pragma("mark") + +// RUN: grep "//#warning eek" %t && +/* expected-warning {{#warning eek}} */ #warning eek + +// RUN: grep "//#pragma mark mark" %t && +#pragma mark mark + +// RUN: true + diff --git a/test/Frontend/stdin.c b/test/Frontend/stdin.c new file mode 100644 index 000000000000..35fe45d35b40 --- /dev/null +++ b/test/Frontend/stdin.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -E - < /dev/null > %t +// RUN: grep '<built-in>' %t + diff --git a/test/Lexer/11-27-2007-FloatLiterals.c b/test/Lexer/11-27-2007-FloatLiterals.c new file mode 100644 index 000000000000..f3ea7cbaf9f4 --- /dev/null +++ b/test/Lexer/11-27-2007-FloatLiterals.c @@ -0,0 +1,7 @@ +// RUN: clang-cc %s -emit-llvm -o - | grep 0x3BFD83C940000000 | count 2 && +// RUN: clang-cc %s -emit-llvm -o - | grep 2.000000e+32 | count 2 + +float F = 1e-19f; +double D = 2e32; +float F2 = 01e-19f; +double D2 = 02e32; diff --git a/test/Lexer/badstring_in_if0.c b/test/Lexer/badstring_in_if0.c new file mode 100644 index 000000000000..5fa5a2bb2403 --- /dev/null +++ b/test/Lexer/badstring_in_if0.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -E %s 2>&1 | not grep error +#if 0 + + " + + ' + +#endif diff --git a/test/Lexer/block_cmt_end.c b/test/Lexer/block_cmt_end.c new file mode 100644 index 000000000000..d85cf81f214a --- /dev/null +++ b/test/Lexer/block_cmt_end.c @@ -0,0 +1,38 @@ +/* + RUN: clang-cc -E -trigraphs %s | grep bar && + RUN: clang-cc -E -trigraphs %s | grep foo && + RUN: clang-cc -E -trigraphs %s | not grep abc && + RUN: clang-cc -E -trigraphs %s | not grep xyz && + RUN: clang-cc -fsyntax-only -trigraphs -verify %s +*/ + +// This is a simple comment, /*/ does not end a comment, the trailing */ does. +int i = /*/ */ 1; + +/* abc + +next comment ends with normal escaped newline: +*/ + +/* expected-warning {{escaped newline}} expected-warning {{backslash and newline}} *\ +/ + +int bar + +/* xyz + +next comment ends with a trigraph escaped newline: */ + +/* expected-warning {{escaped newline between}} expected-warning {{backslash and newline separated by space}} expected-warning {{trigraph ends block comment}} *??/ +/ + +foo /* expected-error {{invalid token after top level declarator}} */ + + +// rdar://6060752 - We should not get warnings about trigraphs in comments: +// '????' +/* ???? */ + + + + diff --git a/test/Lexer/c90.c b/test/Lexer/c90.c new file mode 100644 index 000000000000..d743d68cd501 --- /dev/null +++ b/test/Lexer/c90.c @@ -0,0 +1,13 @@ +/* RUN: clang-cc -std=c90 -fsyntax-only %s -verify -pedantic-errors + */ + +enum { cast_hex = (long) ( + 0x0p-1 /* expected-error {{hexadecimal floating constants are a C99 feature}} */ + ) }; + +/* PR2477 */ +int test1(int a,int b) {return a//* This is a divide followed by block comment in c89 mode */ +b;} + +// comment accepted as extension /* expected-error {{// comments are not allowed in this language}} + diff --git a/test/Lexer/comment-escape.c b/test/Lexer/comment-escape.c new file mode 100644 index 000000000000..c568cd611f1b --- /dev/null +++ b/test/Lexer/comment-escape.c @@ -0,0 +1,6 @@ +// RUN: clang -fsyntax-only %s +// rdar://6757323 +// foo \ + +#define blork 32 + diff --git a/test/Lexer/constants.c b/test/Lexer/constants.c new file mode 100644 index 000000000000..fcb6de954516 --- /dev/null +++ b/test/Lexer/constants.c @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic -trigraphs %s + +int x = 000000080; // expected-error {{invalid digit}} + +int y = 0000\ +00080; // expected-error {{invalid digit}} + + + +float X = 1.17549435e-38F; +float Y = 08.123456; + +// PR2252 +#if -0x8000000000000000 // should not warn. +#endif + + +char c[] = { + 'df', // expected-warning {{multi-character character constant}} + '\t', + '\\ +t', + '??!', // expected-warning {{trigraph converted to '|' character}} + 'abcd' // expected-warning {{multi-character character constant}} +}; + + +#pragma clang diagnostic ignored "-Wmultichar" + +char d = 'df'; // no warning. +char e = 'abcd'; // still warn: expected-warning {{multi-character character constant}} + +#pragma clang diagnostic ignored "-Wfour-char-constants" + +char f = 'abcd'; // ignored. diff --git a/test/Lexer/counter.c b/test/Lexer/counter.c new file mode 100644 index 000000000000..9b2c2c7434f4 --- /dev/null +++ b/test/Lexer/counter.c @@ -0,0 +1,16 @@ +// __COUNTER__ support: rdar://4329310 +// RUN: clang -E %s > %t && + +#define PASTE2(x,y) x##y +#define PASTE1(x,y) PASTE2(x,y) +#define UNIQUE(x) PASTE1(x,__COUNTER__) + +// RUN: grep "A: 0" %t && +A: __COUNTER__ + +// RUN: grep "B: foo1" %t && +B: UNIQUE(foo); +// RUN: grep "C: foo2" %t && +C: UNIQUE(foo); +// RUN: grep "D: 3" %t +D: __COUNTER__ diff --git a/test/Lexer/cxx0x_keyword.cpp b/test/Lexer/cxx0x_keyword.cpp new file mode 100644 index 000000000000..412c25e83c48 --- /dev/null +++ b/test/Lexer/cxx0x_keyword.cpp @@ -0,0 +1,2 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s 2>&1 +int static_assert; /* expected-error {{expected unqualified-id}} */ diff --git a/test/Lexer/cxx0x_keyword_as_cxx98.cpp b/test/Lexer/cxx0x_keyword_as_cxx98.cpp new file mode 100644 index 000000000000..9f8aea127cb9 --- /dev/null +++ b/test/Lexer/cxx0x_keyword_as_cxx98.cpp @@ -0,0 +1,2 @@ +// RUN: clang-cc %s -fsyntax-only +int static_assert; diff --git a/test/Lexer/digraph.c b/test/Lexer/digraph.c new file mode 100644 index 000000000000..4d494ca1dd94 --- /dev/null +++ b/test/Lexer/digraph.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify < %s + +%:include <stdio.h> + + %:ifndef BUFSIZE + %:define BUFSIZE 512 + %:endif + + void copy(char d<::>, const char s<::>, int len) + <% + while (len-- >= 0) + <% + d<:len:> = s<:len:>; + %> + %> diff --git a/test/Lexer/dollar-idents.c b/test/Lexer/dollar-idents.c new file mode 100644 index 000000000000..7635ea112eb7 --- /dev/null +++ b/test/Lexer/dollar-idents.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -dump-tokens %s 2> %t && +// RUN: grep "identifier '\$A'" %t +// RUN: clang-cc -dump-tokens -x assembler-with-cpp %s 2> %t && +// RUN: grep "identifier 'A'" %t +// PR3808 + +$A diff --git a/test/Lexer/escape_newline.c b/test/Lexer/escape_newline.c new file mode 100644 index 000000000000..ce120ed7c828 --- /dev/null +++ b/test/Lexer/escape_newline.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -E -trigraphs %s | grep -- ' ->' && +// RUN: clang-cc -E -trigraphs %s 2>&1 | grep 'backslash and newline separated by space' && +// RUN: clang-cc -E -trigraphs %s 2>&1 | grep 'trigraph converted' + +// This is an ugly way to spell a -> token. + -??/ +> diff --git a/test/Lexer/multiple-include.c b/test/Lexer/multiple-include.c new file mode 100644 index 000000000000..e5fd52926eee --- /dev/null +++ b/test/Lexer/multiple-include.c @@ -0,0 +1,27 @@ +// RUN: clang-cc %s -fsyntax-only + +#ifndef XVID_AUTO_INCLUDE + +#define XVID_AUTO_INCLUDE +#define FUNC_H H_Pass_16_C +#include "multiple-include.c" + +#define FUNC_H H_Pass_8_C + +#include "multiple-include.c" +#undef XVID_AUTO_INCLUDE + +typedef void ff(); +typedef struct { ff *a;} S; + +S s = { H_Pass_8_C }; + +#endif + +#if defined(XVID_AUTO_INCLUDE) && defined(REFERENCE_CODE) +#elif defined(XVID_AUTO_INCLUDE) && !defined(REFERENCE_CODE) + +static void FUNC_H(){}; +#undef FUNC_H + +#endif diff --git a/test/Lexer/numeric-literal-trash.c b/test/Lexer/numeric-literal-trash.c new file mode 100644 index 000000000000..047e0b8e95f9 --- /dev/null +++ b/test/Lexer/numeric-literal-trash.c @@ -0,0 +1,13 @@ +/* RUN: clang-cc -fsyntax-only -verify %s + */ +# define XRECORD(x, c_name) e##c (x, __LINE__) + + + + + + + void x() { + +XRECORD (XRECORD (1, 1), 1); + } diff --git a/test/Lexer/pragma-mark.c b/test/Lexer/pragma-mark.c new file mode 100644 index 000000000000..f4204aa9d807 --- /dev/null +++ b/test/Lexer/pragma-mark.c @@ -0,0 +1,11 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// Lexer diagnostics shouldn't be included in #pragma mark. +#pragma mark Mike's world +_Pragma("mark foo ' bar") + +#define X(S) _Pragma(S) +X("mark foo ' bar") + +int i; + diff --git a/test/Lexer/rdr-6096838-2.c b/test/Lexer/rdr-6096838-2.c new file mode 100644 index 000000000000..b135dc1409cb --- /dev/null +++ b/test/Lexer/rdr-6096838-2.c @@ -0,0 +1,5 @@ +/* RUN: clang-cc -pedantic -std=gnu89 -fsyntax-only -verify %s + rdar://6096838 + */ + +long double d = 0x0.0000003ffffffff00000p-16357L; /* expected-warning {{ hexadecimal floating constants are a C99 feature }} */ diff --git a/test/Lexer/rdr-6096838.c b/test/Lexer/rdr-6096838.c new file mode 100644 index 000000000000..60e5244646ad --- /dev/null +++ b/test/Lexer/rdr-6096838.c @@ -0,0 +1,6 @@ +/* RUN: clang-cc -fsyntax-only -verify %s && + * RUN: clang-cc -std=gnu89 -fsyntax-only -verify %s + rdar://6096838 + */ + +long double d = 0x0.0000003ffffffff00000p-16357L; diff --git a/test/Lexer/token-concat.c b/test/Lexer/token-concat.c new file mode 100644 index 000000000000..4e27d5d723e2 --- /dev/null +++ b/test/Lexer/token-concat.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -E -x c -o %t %s && +// RUN: grep 'IDENT.2' %t + +IDENT.2 diff --git a/test/Lexer/unknown-char.c b/test/Lexer/unknown-char.c new file mode 100644 index 000000000000..acbf4f039a71 --- /dev/null +++ b/test/Lexer/unknown-char.c @@ -0,0 +1,2 @@ +// RUN: clang-cc -E %s 2>&1 | not grep error + ` ` ` ` diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 000000000000..1ebaedd6b7da --- /dev/null +++ b/test/Makefile @@ -0,0 +1,47 @@ +LEVEL = ../../.. +include $(LEVEL)/Makefile.common + +# Test in all immediate subdirectories if unset. +TESTDIRS ?= $(shell echo $(PROJ_SRC_DIR)/*/) + +# Only run rewriter tests on darwin. +ifeq ($(OS),Darwin) +TESTDIRS += +endif + +ifdef VERBOSE +ifeq ($(VERBOSE),0) +PROGRESS = : +REPORTFAIL = echo 'FAIL: clang' $(TARGET_TRIPLE) $(subst $(LLVM_SRC_ROOT)/tools/clang/,,$<) +DONE = $(LLVMToolDir)/clang -v +else +PROGRESS = echo $< +REPORTFAIL = cat $@ +DONE = true +endif +else +PROGRESS = printf '.' +REPORTFAIL = (echo; echo '----' $< 'failed ----') +DONE = echo +endif + +TESTS := $(addprefix Output/, $(addsuffix .testresults, $(shell find $(TESTDIRS) \( -name '*.c' -or -name '*.cpp' -or -name '*.m' -or -name '*.mm' -or -name '*.S' \) | grep -v "Output/"))) +Output/%.testresults: % + @ $(PROGRESS) + @ PATH=$(ToolDir):$(LLVM_SRC_ROOT)/test/Scripts:$$PATH VG=$(VG) $(PROJ_SRC_DIR)/TestRunner.sh $< > $@ || $(REPORTFAIL) + +all:: + @ mkdir -p $(addprefix Output/, $(TESTDIRS)) + @ rm -f $(TESTS) + @ echo '--- Running clang tests for $(TARGET_TRIPLE) ---' + @ $(MAKE) $(TESTS) + @ $(DONE) + @ !(cat $(TESTS) | grep -q " FAILED! ") + +report: $(TESTS) + @ cat $^ + +clean:: + @ rm -rf Output/ + +.PHONY: all report clean diff --git a/test/Misc/caret-diags-macros.c b/test/Misc/caret-diags-macros.c new file mode 100644 index 000000000000..58d293fb043e --- /dev/null +++ b/test/Misc/caret-diags-macros.c @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only %s > %t 2>&1 && + +#define M1(x) x + +// RUN: grep ":6:12: note: instantiated from:" %t && +#define M2 1; + +void foo() { + // RUN: grep ":10:2: warning: expression result unused" %t && + M1( + // RUN: grep ":12:5: note: instantiated from:" %t && + M2) +} + +// RUN: grep ":16:11: note: instantiated from:" %t && +#define A 1 +// RUN: grep ":18:11: note: instantiated from:" %t && +#define B A +// RUN: grep ":20:11: note: instantiated from:" %t && +#define C B + +void bar() { + // RUN: grep ":24:3: warning: expression result unused" %t + C; +} + diff --git a/test/Misc/caret-diags-scratch-buffer.c b/test/Misc/caret-diags-scratch-buffer.c new file mode 100644 index 000000000000..e339d5635754 --- /dev/null +++ b/test/Misc/caret-diags-scratch-buffer.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only %s 2>&1 | not grep keyXXXX +// This should not show keyXXXX in the caret diag output. This once +// happened because the two tokens ended up in the scratch buffer and +// the caret diag from the scratch buffer included the previous token. +#define M(name) \ + if (name ## XXXX != name ## _sb); + +void foo() { + int keyXXXX; + M(key); +} + diff --git a/test/Misc/diag-checker.c b/test/Misc/diag-checker.c new file mode 100644 index 000000000000..4733ee1e03d7 --- /dev/null +++ b/test/Misc/diag-checker.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stdio.h> + +void foo(FILE *FP) {} diff --git a/test/Misc/diag-mapping.c b/test/Misc/diag-mapping.c new file mode 100644 index 000000000000..dc07e0d092b5 --- /dev/null +++ b/test/Misc/diag-mapping.c @@ -0,0 +1,30 @@ +// This should warn by default. +// RUN: clang-cc %s 2>&1 | grep "warning:" && +// This should not emit anything. +// RUN: clang-cc %s -Wno-extra-tokens 2>&1 | not grep diagnostic && + +// -Werror can map all warnings to error. +// RUN: clang-cc %s -Werror 2>&1 | grep "error:" && + +// -Werror can map this one warning to error. +// RUN: clang-cc %s -Werror=extra-tokens 2>&1 | grep "error:" && + +// Mapping unrelated diags to errors doesn't affect this one. +// RUN: clang-cc %s -Werror=trigraphs 2>&1 | grep "warning:" && + +// This should stay a warning with -pedantic. +// RUN: clang-cc %s -pedantic 2>&1 | grep "warning:" && + +// This should emit an error with -pedantic-errors. +// RUN: clang-cc %s -pedantic-errors 2>&1 | grep "error:" && + +// This should emit a warning, because -Wfoo overrides -pedantic*. +// RUN: clang-cc %s -pedantic-errors -Wextra-tokens 2>&1 | grep "warning:" && + +// This should emit nothing, because -Wno-extra-tokens overrides -pedantic* +// RUN: clang-cc %s -pedantic-errors -Wno-extra-tokens 2>&1 | not grep diagnostic + +#ifdef foo +#endif bad // extension! + +int x; diff --git a/test/Misc/diag-mapping2.c b/test/Misc/diag-mapping2.c new file mode 100644 index 000000000000..7e0d7742a9fe --- /dev/null +++ b/test/Misc/diag-mapping2.c @@ -0,0 +1,19 @@ +// This should warn by default. +// RUN: clang-cc %s 2>&1 | grep "warning:" && + +// This should not emit anything. +// RUN: clang-cc %s -w 2>&1 | not grep diagnostic && +// RUN: clang-cc %s -Wno-#warnings 2>&1 | not grep diagnostic && + +// -Werror can map all warnings to error. +// RUN: clang-cc %s -Werror 2>&1 | grep "error:" && + +// -Werror can map this one warning to error. +// RUN: clang-cc %s -Werror=#warnings 2>&1 | grep "error:" && + +// -Wno-error= overrides -Werror. rdar://3158301 +// RUN: clang-cc %s -Werror -Wno-error=#warnings 2>&1 | grep "warning:" + +#warning foo + + diff --git a/test/Misc/emit-html-insert.c b/test/Misc/emit-html-insert.c new file mode 100644 index 000000000000..ac6b519a3a0d --- /dev/null +++ b/test/Misc/emit-html-insert.c @@ -0,0 +1,4 @@ +// RUN: clang-cc %s -emit-html -o - | grep ">< 10; }" + +int a(int x) { return x +< 10; } diff --git a/test/Misc/emit-html.c b/test/Misc/emit-html.c new file mode 100644 index 000000000000..22d0d28dd65d --- /dev/null +++ b/test/Misc/emit-html.c @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -emit-html -o - + +// rdar://6562329 +#line 42 "foo.c" + +// PR3635 +#define F(fmt, ...) fmt, ## __VA_ARGS__ +int main(int argc, char **argv) { + return F(argc, 1); +} + +// PR3798 +#define FOR_ALL_FILES(f,i) i + +#if 0 + FOR_ALL_FILES(f) { } +#endif + diff --git a/test/Misc/message-length.c b/test/Misc/message-length.c new file mode 100644 index 000000000000..ac5dab99ca52 --- /dev/null +++ b/test/Misc/message-length.c @@ -0,0 +1,35 @@ +// RUN: clang -fsyntax-only -fmessage-length=72 %s 2> %t && + +// RUN: grep -A4 "FILE:23" %t > %t.msg && +// FIXME: This diagnostic is getting truncated very poorly. +// RUN: grep -e '^ ...// some long comment text and a brace, eh {} ' %t.msg && +// RUN: grep -e '^ \^' %t.msg && +// RUN: clang -fsyntax-only -fmessage-length=1 %s && +// RUN: true + +// Hack so we can check things better, force the file name and line. + +# 1 "FILE" 1 + +/* It's tough to verify the results of this test mechanically, since + the length of the filename (and, therefore, how the word-wrapping + behaves) changes depending on where the test-suite resides in the + file system. */ +void f(int, float, char, float); + +void g() { + int (*fp1)(int, float, short, float) = f; + + int (*fp2)(int, float, short, float) = f; +} + +void a_func_to_call(int, int, int); + +void a_very_long_line(int *ip, float *FloatPointer) { + for (int ALongIndexName = 0; ALongIndexName < 100; ALongIndexName++) if (ip[ALongIndexName] == 17) a_func_to_call(ip == FloatPointer, ip[ALongIndexName], FloatPointer[ALongIndexName]); + + + int array0[] = { [3] 3, 5, 7, 4, 2, 7, 6, 3, 4, 5, 6, 7, 8, 9, 12, 345, 14, 345, 789, 234, 678, 345, 123, 765, 234 }; +} + +#pragma STDC CX_LIMITED_RANGE // some long comment text and a brace, eh {} diff --git a/test/Misc/predefines.c b/test/Misc/predefines.c new file mode 100644 index 000000000000..c7fac86331a5 --- /dev/null +++ b/test/Misc/predefines.c @@ -0,0 +1,5 @@ +/* RUN: clang-cc -fsyntax-only -verify -std=c89 -pedantic-errors %s + * rdar://6814950 + */ +#include <stdint.h> + diff --git a/test/PCH/asm.c b/test/PCH/asm.c new file mode 100644 index 000000000000..bff271de0390 --- /dev/null +++ b/test/PCH/asm.c @@ -0,0 +1,11 @@ +// Test this without pch. +// RUN: clang-cc -triple i386-unknown-unknown -include %S/asm.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -triple i386-unknown-unknown -emit-pch -o %t %S/asm.h && +// RUN: clang-cc -triple i386-unknown-unknown -include-pch %t -fsyntax-only -verify %s + + +void call_f(void) { f(); } + +void call_clobbers(void) { clobbers(); } diff --git a/test/PCH/asm.h b/test/PCH/asm.h new file mode 100644 index 000000000000..a568058d58f6 --- /dev/null +++ b/test/PCH/asm.h @@ -0,0 +1,14 @@ +// Header for the PCH test asm.c + +void f() { + int i; + + asm ("foo\n" : : "a" (i + 2)); + asm ("foo\n" : [symbolic_name] "=a" (i) : "[symbolic_name]" (i)); +} + +void clobbers() { + asm ("nop" : : : "ax", "#ax", "%ax"); + asm ("nop" : : : "eax", "rax", "ah", "al"); + asm ("nop" : : : "0", "%0", "#0"); +} diff --git a/test/PCH/attrs.c b/test/PCH/attrs.c new file mode 100644 index 000000000000..1ffb467f63db --- /dev/null +++ b/test/PCH/attrs.c @@ -0,0 +1,8 @@ +// Test this without pch. +// RUN: clang-cc -include %S/attrs.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/attrs.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s +// expected-note{{previous overload}} +double f(double); // expected-error{{overloadable}} diff --git a/test/PCH/attrs.h b/test/PCH/attrs.h new file mode 100644 index 000000000000..0d0156515c88 --- /dev/null +++ b/test/PCH/attrs.h @@ -0,0 +1,7 @@ +// Header for PCH test exprs.c + + + + + +int f(int) __attribute__((overloadable)); diff --git a/test/PCH/blocks.c b/test/PCH/blocks.c new file mode 100644 index 000000000000..f3efc8ac4bcc --- /dev/null +++ b/test/PCH/blocks.c @@ -0,0 +1,12 @@ +// Test this without pch. +// RUN: clang-cc -fblocks -include %S/blocks.h -fsyntax-only -emit-llvm -o - %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -fblocks -o %t %S/blocks.h && +// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -emit-llvm -o - %s + +int do_add(int x, int y) { return add(x, y); } + +int do_scaled_add(int a, int b, int s) { + return scaled_add(a, b, s); +} diff --git a/test/PCH/blocks.h b/test/PCH/blocks.h new file mode 100644 index 000000000000..af7bb6fc657f --- /dev/null +++ b/test/PCH/blocks.h @@ -0,0 +1,14 @@ +// Header for PCH test blocks.c + +int call_block(int (^bl)(int x, int y), int a, int b) { + return bl(a, b); +} + +int add(int a, int b) { + return call_block(^(int x, int y) { return x + y; }, a, b); +} + +int scaled_add(int a, int b, int s) { + __block int scale = s; + return call_block(^(int x, int y) { return x*scale + y; }, a, b); +} diff --git a/test/PCH/builtins.c b/test/PCH/builtins.c new file mode 100644 index 000000000000..3d1786ba7713 --- /dev/null +++ b/test/PCH/builtins.c @@ -0,0 +1,10 @@ +// Test this without pch. +// RUN: clang-cc -include %S/builtins.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/builtins.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +void hello() { + printf("Hello, World!"); +} diff --git a/test/PCH/builtins.h b/test/PCH/builtins.h new file mode 100644 index 000000000000..56e4a53814de --- /dev/null +++ b/test/PCH/builtins.h @@ -0,0 +1,2 @@ +// Header for PCH test builtins.c +int printf(char const *, ...); diff --git a/test/PCH/enum.c b/test/PCH/enum.c new file mode 100644 index 000000000000..45b0491c6f53 --- /dev/null +++ b/test/PCH/enum.c @@ -0,0 +1,15 @@ +// Test this without pch. +// RUN: clang-cc -include %S/enum.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/enum.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +int i = Red; + +int return_enum_constant() { + int result = aRoundShape; + return result; +} + +enum Shape s = Triangle; diff --git a/test/PCH/enum.h b/test/PCH/enum.h new file mode 100644 index 000000000000..7dc4e631d6cb --- /dev/null +++ b/test/PCH/enum.h @@ -0,0 +1,16 @@ +/* Used in enum.c test */ + +enum Color { + Red, + Green, + Blue +}; + +enum Shape { + Square, + Triangle = 17, + Rhombus, + Circle +}; + +enum Shape aRoundShape = Circle; diff --git a/test/PCH/exprs.c b/test/PCH/exprs.c new file mode 100644 index 000000000000..c8e6d1dc3030 --- /dev/null +++ b/test/PCH/exprs.c @@ -0,0 +1,89 @@ +// Test this without pch. +// RUN: clang-cc -fblocks -include %S/exprs.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -fblocks -o %t %S/exprs.h && +// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s + +int integer; +long long_integer; +double floating; +_Complex double floating_complex; + +// DeclRefExpr +int_decl_ref *int_ptr1 = &integer; +enum_decl_ref *enum_ptr1 = &integer; + +// IntegerLiteral +integer_literal *int_ptr2 = &integer; +long_literal *long_ptr1 = &long_integer; + +// FloatingLiteral + ParenExpr +floating_literal *double_ptr = &floating; + +// ImaginaryLiteral +imaginary_literal *cdouble_ptr = &floating_complex; + +// StringLiteral +const char* printHello() { + return hello; +} + +// CharacterLiteral +char_literal *int_ptr3 = &integer; + +// UnaryOperator +negate_enum *int_ptr4 = &integer; + +// SizeOfAlignOfExpr +typeof(sizeof(float)) size_t_value; +typeof_sizeof *size_t_ptr = &size_t_value; +typeof_sizeof2 *size_t_ptr2 = &size_t_value; + +// ArraySubscriptExpr +array_subscript *double_ptr1_5 = &floating; + +// CallExpr +call_returning_double *double_ptr2 = &floating; + +// MemberExpr +member_ref_double *double_ptr3 = &floating; + +// BinaryOperator +add_result *int_ptr5 = &integer; + +// CompoundAssignOperator +addeq_result *int_ptr6 = &integer; + +// ConditionalOperator +conditional_operator *double_ptr4 = &floating; + +// CStyleCastExpr +void_ptr vp1 = &integer; + +// CompoundLiteral +struct S s; +compound_literal *sptr = &s; + +// ExtVectorElementExpr +ext_vector_element *double_ptr5 = &floating; + +// InitListExpr +double get_from_double_array(unsigned Idx) { return double_array[Idx]; } + +/// DesignatedInitExpr +float get_from_designated(unsigned Idx) { + return designated_inits[2].y; +} + +// TypesCompatibleExpr +types_compatible *int_ptr7 = &integer; + +// ChooseExpr +choose_expr *int_ptr8 = &integer; + +// GNUNullExpr FIXME: needs C++ +//null_type null = __null; + +// ShuffleVectorExpr +shuffle_expr *vec_ptr = &vec2; diff --git a/test/PCH/exprs.h b/test/PCH/exprs.h new file mode 100644 index 000000000000..7012422aad33 --- /dev/null +++ b/test/PCH/exprs.h @@ -0,0 +1,86 @@ +// Header for PCH test exprs.c + +// DeclRefExpr +int i = 17; +enum Enum { Enumerator = 18 }; +typedef typeof(i) int_decl_ref; +typedef typeof(Enumerator) enum_decl_ref; + +// IntegerLiteral +typedef typeof(17) integer_literal; +typedef typeof(17l) long_literal; + +// FloatingLiteral and ParenExpr +typedef typeof((42.5)) floating_literal; + +// ImaginaryLiteral +typedef typeof(17.0i) imaginary_literal; + +// StringLiteral +const char *hello = "Hello" "PCH" "World"; + +// CharacterLiteral +typedef typeof('a') char_literal; + +// UnaryOperator +typedef typeof(-Enumerator) negate_enum; + +// SizeOfAlignOfExpr +typedef typeof(sizeof(int)) typeof_sizeof; +typedef typeof(sizeof(Enumerator)) typeof_sizeof2; + +// ArraySubscriptExpr +extern double values[]; +typedef typeof(values[2]) array_subscript; + +// CallExpr +double dplus(double x, double y); +double d0, d1; +typedef typeof((&dplus)(d0, d1)) call_returning_double; + +// MemberExpr +struct S { + double x; +}; +typedef typeof(((struct S*)0)->x) member_ref_double; + +// BinaryOperator +typedef typeof(i + Enumerator) add_result; + +// CompoundAssignOperator +typedef typeof(i += Enumerator) addeq_result; + +// ConditionalOperator +typedef typeof(i? : d0) conditional_operator; + +// CStyleCastExpr +typedef typeof((void *)0) void_ptr; + +// CompoundLiteral +typedef typeof((struct S){.x = 3.5}) compound_literal; + +// ExtVectorElementExpr +typedef __attribute__(( ext_vector_type(2) )) double double2; +extern double2 vec2, vec2b; +typedef typeof(vec2.x) ext_vector_element; + +// InitListExpr +double double_array[3] = { 1.0, 2.0 }; + +// DesignatedInitExpr +struct { + int x; + float y; +} designated_inits[3] = { [0].y = 17, [2].x = 12.3, 3.5 }; + +// TypesCompatibleExpr +typedef typeof(__builtin_types_compatible_p(float, double)) types_compatible; + +// ChooseExpr +typedef typeof(__builtin_choose_expr(17 > 19, d0, 1)) choose_expr; + +// GNUNullExpr FIXME: needs C++ +// typedef typeof(__null) null_type; + +// ShuffleVectorExpr +typedef typeof(__builtin_shufflevector(vec2, vec2b, 2, 1)) shuffle_expr; diff --git a/test/PCH/ext_vector.c b/test/PCH/ext_vector.c new file mode 100644 index 000000000000..4b5c25980e56 --- /dev/null +++ b/test/PCH/ext_vector.c @@ -0,0 +1,10 @@ +// Test this without pch. +// RUN: clang-cc -include %S/ext_vector.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/ext_vector.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +int test(float4 f4) { + return f4.xy; // expected-error{{float2}} +} diff --git a/test/PCH/ext_vector.h b/test/PCH/ext_vector.h new file mode 100644 index 000000000000..39ab9233584d --- /dev/null +++ b/test/PCH/ext_vector.h @@ -0,0 +1,4 @@ +// Header file for ext_vector.c PCH test + +typedef __attribute__((ext_vector_type(2))) float float2; +typedef __attribute__((ext_vector_type(4))) float float4; diff --git a/test/PCH/external-defs.c b/test/PCH/external-defs.c new file mode 100644 index 000000000000..b7eb700e6b3e --- /dev/null +++ b/test/PCH/external-defs.c @@ -0,0 +1,19 @@ +// Test with pch. +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-pch -o %t.pch %S/external-defs.h && +// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -emit-llvm -o %t %s && + +// RUN: grep "@x = common global i32 0" %t | count 1 && +// RUN: grep "@z" %t | count 0 && + +// RUN: grep "@x2 = global i32 19" %t | count 1 && +int x2 = 19; + +// RUN: grep "@incomplete_array = common global .*1 x i32" %t | count 1 && +// RUN: grep "@incomplete_array2 = common global .*17 x i32" %t | count 1 && +int incomplete_array2[17]; +// RUN: grep "@incomplete_array3 = common global .*1 x i32" %t | count 1 +int incomplete_array3[]; + +struct S { + int x, y; +}; diff --git a/test/PCH/external-defs.h b/test/PCH/external-defs.h new file mode 100644 index 000000000000..657b47bcc141 --- /dev/null +++ b/test/PCH/external-defs.h @@ -0,0 +1,13 @@ +// Helper for external-defs.c test + +// Tentative definitions +int x; +int x2; + +// Should not show up +static int z; + +int incomplete_array[]; +int incomplete_array2[]; + +struct S s; diff --git a/test/PCH/functions.c b/test/PCH/functions.c new file mode 100644 index 000000000000..6d3c5a0f7b81 --- /dev/null +++ b/test/PCH/functions.c @@ -0,0 +1,20 @@ +// Test this without pch. +// RUN: clang-cc -include %S/functions.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/functions.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +int f0(int x0, int y0, ...) { return x0 + y0; } + +float *test_f1(int val, double x, double y) { + if (val > 5) + return f1(x, y); + else + return f1(x); // expected-error{{too few arguments to function call}} +} + +void test_g0(int *x, float * y) { + g0(y); // expected-warning{{incompatible pointer types passing 'float *', expected 'int *'}} + g0(x); +} diff --git a/test/PCH/functions.h b/test/PCH/functions.h new file mode 100644 index 000000000000..bc28ad7321c7 --- /dev/null +++ b/test/PCH/functions.h @@ -0,0 +1,6 @@ +/* For use with the functions.c test */ + +int f0(int x, int y, ...); +float *f1(float x, float y); + +void g0(int *); diff --git a/test/PCH/fuzzy-pch.c b/test/PCH/fuzzy-pch.c new file mode 100644 index 000000000000..2ddcb8bb089b --- /dev/null +++ b/test/PCH/fuzzy-pch.c @@ -0,0 +1,19 @@ +// Test with pch. +// RUN: clang-cc -emit-pch -DFOO -o %t %S/variables.h && +// RUN: clang-cc -DBAR=int -include-pch %t -fsyntax-only -pedantic %s && +// RUN: clang-cc -DFOO -DBAR=int -include-pch %t -Werror %s && +// RUN: not clang-cc -DFOO -DBAR=int -DX=5 -include-pch %t -Werror %s + +BAR bar = 17; + +#ifndef FOO +# error FOO was not defined +#endif + +#if FOO != 1 +# error FOO has the wrong definition +#endif + +#ifndef BAR +# error BAR was not defined +#endif diff --git a/test/PCH/fuzzy-pch.h b/test/PCH/fuzzy-pch.h new file mode 100644 index 000000000000..9eb1005ce447 --- /dev/null +++ b/test/PCH/fuzzy-pch.h @@ -0,0 +1,2 @@ +// Header for PCH test fuzzy-pch.c +void f(int X); diff --git a/test/PCH/line-directive.c b/test/PCH/line-directive.c new file mode 100644 index 000000000000..53edb3c06b8c --- /dev/null +++ b/test/PCH/line-directive.c @@ -0,0 +1,25 @@ +// Test this without pch. +// RUN: clang-cc -include %S/line-directive.h -fsyntax-only %s 2>&1|grep "25:5" && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/line-directive.h && +// RUN: clang-cc -include-pch %t -fsyntax-only %s 2>&1|grep "25:5" + +double x; // expected-error{{redefinition of 'x' with a different type}} + + + + + + + + + + + + + + + + +// expected-note{{previous definition is here}} diff --git a/test/PCH/line-directive.h b/test/PCH/line-directive.h new file mode 100644 index 000000000000..c5594b420e65 --- /dev/null +++ b/test/PCH/line-directive.h @@ -0,0 +1,2 @@ +#line 25 "line-directive.c" +int x; diff --git a/test/PCH/method_pool.h b/test/PCH/method_pool.h new file mode 100644 index 000000000000..f7af9044d92d --- /dev/null +++ b/test/PCH/method_pool.h @@ -0,0 +1,37 @@ +/* For use with the method_pool.m test */ + +/* Whitespace below is significant */ + + + + + + + + + + + +@interface TestMethodPool1 ++ alloc; +- (double)instMethod:(int)foo; +@end + +@interface TestMethodPool2 +- (char)instMethod:(int)foo; +@end + +@implementation TestMethodPool1 ++ alloc { +} + +- (double)instMethod:(int)foo { + return foo; +} +@end + +@implementation TestMethodPool2 +- (char)instMethod:(int)foo { + return foo; +} +@end diff --git a/test/PCH/method_pool.m b/test/PCH/method_pool.m new file mode 100644 index 000000000000..8dd7834f1dab --- /dev/null +++ b/test/PCH/method_pool.m @@ -0,0 +1,21 @@ +// Test this without pch. +// RUN: clang-cc -include %S/method_pool.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/method_pool.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +int message_id(id x) { + return [x instMethod:17]; // expected-warning{{multiple methods}} +} + + + + + +/* Whitespace below is significant */ +/* expected-note{{using}} */ + + + +/* expected-note{{also}} */ diff --git a/test/PCH/multiple_decls.c b/test/PCH/multiple_decls.c new file mode 100644 index 000000000000..4b2fc6247ce7 --- /dev/null +++ b/test/PCH/multiple_decls.c @@ -0,0 +1,17 @@ +// Test this without pch. +// RUN: clang-cc -include %S/multiple_decls.h -fsyntax-only -ast-print -o - %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/multiple_decls.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -ast-print -o - %s + +void f0(char c) { + wide(c); +} + +struct wide w; +struct narrow n; + +void f1(int i) { + narrow(i); +} diff --git a/test/PCH/multiple_decls.h b/test/PCH/multiple_decls.h new file mode 100644 index 000000000000..23696b0470dc --- /dev/null +++ b/test/PCH/multiple_decls.h @@ -0,0 +1,7 @@ +// Header for PCH test multiple_decls.c + +struct wide { int value; }; +int wide(char); + +struct narrow { char narrow; }; +char narrow(int); diff --git a/test/PCH/nonvisible-external-defs.c b/test/PCH/nonvisible-external-defs.c new file mode 100644 index 000000000000..bfe5ccab20a3 --- /dev/null +++ b/test/PCH/nonvisible-external-defs.c @@ -0,0 +1,10 @@ +// Test this without pch. +// RUN: clang-cc -include %S/nonvisible-external-defs.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/nonvisible-external-defs.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +int g(int, float); // expected-error{{conflicting types}} + +// expected-note{{previous declaration}} diff --git a/test/PCH/nonvisible-external-defs.h b/test/PCH/nonvisible-external-defs.h new file mode 100644 index 000000000000..a36fc2ea468c --- /dev/null +++ b/test/PCH/nonvisible-external-defs.h @@ -0,0 +1,11 @@ +// Helper for PCH test nonvisible-external-defs.h + + + + + + + +void f() { + extern int g(int, int); +} diff --git a/test/PCH/objc_exprs.h b/test/PCH/objc_exprs.h new file mode 100644 index 000000000000..b811430c2e89 --- /dev/null +++ b/test/PCH/objc_exprs.h @@ -0,0 +1,18 @@ + +@protocol foo; +@class itf; + +// Expressions +typedef typeof(@"foo" "bar") objc_string; +typedef typeof(@encode(int)) objc_encode; +typedef typeof(@protocol(foo)) objc_protocol; +typedef typeof(@selector(noArgs)) objc_selector_noArgs; +typedef typeof(@selector(oneArg:)) objc_selector_oneArg; +typedef typeof(@selector(foo:bar:)) objc_selector_twoArg; + + +// Types. +typedef typeof(id<foo>) objc_id_protocol_ty; + +typedef typeof(itf*) objc_interface_ty; +typedef typeof(itf<foo>*) objc_qual_interface_ty; diff --git a/test/PCH/objc_exprs.m b/test/PCH/objc_exprs.m new file mode 100644 index 000000000000..eb1ae434a7e0 --- /dev/null +++ b/test/PCH/objc_exprs.m @@ -0,0 +1,28 @@ +// Test this without pch. +// RUN: clang-cc -fblocks -include %S/objc_exprs.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -x objective-c-header -emit-pch -fblocks -o %t %S/objc_exprs.h && +// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s + +// Expressions +int *A1 = (objc_string)0; // expected-warning {{'struct objc_object *'}} + +char A2 = (objc_encode){}; // expected-error {{not a compile-time constant}} \ + expected-warning {{char [2]}} + +int *A3 = (objc_protocol)0; // expected-warning {{aka 'Protocol *'}} + + +// Types. +int *T0 = (objc_id_protocol_ty)0; // expected-error {{not a compile-time constant}} \ + expected-warning {{aka 'id<foo>'}} + +int *T1 = (objc_interface_ty)0; // expected-warning {{aka 'itf *'}} +int *T2 = (objc_qual_interface_ty)0; // expected-warning {{aka 'itf<foo> *'}} + +objc_selector_noArgs s1; +objc_selector_oneArg s2; +objc_selector_twoArg s3; + + diff --git a/test/PCH/objc_import.h b/test/PCH/objc_import.h new file mode 100644 index 000000000000..8af87ab25c7d --- /dev/null +++ b/test/PCH/objc_import.h @@ -0,0 +1,7 @@ +/* For use with the objc_import.m test */ + +@interface TestPCH ++ alloc; +- (void)instMethod; +@end + diff --git a/test/PCH/objc_import.m b/test/PCH/objc_import.m new file mode 100644 index 000000000000..86c1c25ae5c9 --- /dev/null +++ b/test/PCH/objc_import.m @@ -0,0 +1,15 @@ +// Test this without pch. +// RUN: clang-cc -include %S/objc_import.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_import.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +#import "objc_import.h" + +void func() { + TestPCH *xx; + + xx = [TestPCH alloc]; + [xx instMethod]; +} diff --git a/test/PCH/objc_methods.h b/test/PCH/objc_methods.h new file mode 100644 index 000000000000..4c6b1e1ccec0 --- /dev/null +++ b/test/PCH/objc_methods.h @@ -0,0 +1,11 @@ +/* For use with the methods.m test */ + +@interface TestPCH ++ alloc; +- (void)instMethod; +@end + +@class TestForwardClassDecl; + +// FIXME: @compatibility_alias AliasForTestPCH TestPCH; + diff --git a/test/PCH/objc_methods.m b/test/PCH/objc_methods.m new file mode 100644 index 000000000000..1a198b18d380 --- /dev/null +++ b/test/PCH/objc_methods.m @@ -0,0 +1,16 @@ +// Test this without pch. +// RUN: clang-cc -include %S/objc_methods.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_methods.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +void func() { + TestPCH *xx; + TestForwardClassDecl *yy; +// FIXME: +// AliasForTestPCH *zz; + + xx = [TestPCH alloc]; + [xx instMethod]; +} diff --git a/test/PCH/objc_property.h b/test/PCH/objc_property.h new file mode 100644 index 000000000000..2432370be4e8 --- /dev/null +++ b/test/PCH/objc_property.h @@ -0,0 +1,12 @@ +/* For use with the objc_property.m PCH test */ +@interface TestProperties +{ + int value; + float percentage; +} + ++ alloc; + +@property int value; +@property float percentage; +@end diff --git a/test/PCH/objc_property.m b/test/PCH/objc_property.m new file mode 100644 index 000000000000..5cf6de759375 --- /dev/null +++ b/test/PCH/objc_property.m @@ -0,0 +1,11 @@ +// Test this without pch. +// RUN: clang-cc -include %S/objc_property.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -x=objective-c -emit-pch -o %t %S/objc_property.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +void func() { + TestProperties *xx = [TestProperties alloc]; + xx.value = 5; +} diff --git a/test/PCH/preprocess.c b/test/PCH/preprocess.c new file mode 100644 index 000000000000..128cc0acb973 --- /dev/null +++ b/test/PCH/preprocess.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -emit-pch -o %t %S/preprocess.h && +// RUN: clang-cc -include-pch %t -E -o - %s | grep -c "a_typedef" | count 1 +#include "preprocess.h" + +int a_value; diff --git a/test/PCH/preprocess.h b/test/PCH/preprocess.h new file mode 100644 index 000000000000..39fa006181f2 --- /dev/null +++ b/test/PCH/preprocess.h @@ -0,0 +1,7 @@ +// Helper header for preprocess.c PCH test +#ifndef PREPROCESS_H +#define PREPROCESS_H + +typedef int a_typedef; + +#endif // PREPROCESS_H diff --git a/test/PCH/stmts.c b/test/PCH/stmts.c new file mode 100644 index 000000000000..0d906f291f2c --- /dev/null +++ b/test/PCH/stmts.c @@ -0,0 +1,14 @@ +// Test this without pch. +// RUN: clang-cc -include %S/stmts.h -fsyntax-only -emit-llvm -o - %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/stmts.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -emit-llvm -o - %s + +void g0(void) { f0(5); } +int g1(int x) { return f1(x); } +const char* query_name(void) { return what_is_my_name(); } + +int use_computed_goto(int x) { return computed_goto(x); } + +int get_weird_max(int x, int y) { return weird_max(x, y); } diff --git a/test/PCH/stmts.h b/test/PCH/stmts.h new file mode 100644 index 000000000000..4267e2c2b352 --- /dev/null +++ b/test/PCH/stmts.h @@ -0,0 +1,96 @@ +// Header for PCH test stmts.c + +void f0(int x) { + // NullStmt + ; + // IfStmt + if (x) { + } else if (x + 1) { + } + + switch (x) { + case 0: + x = 17; + break; + + case 1: + break; + + default: + switch (x >> 1) { + case 7: + // fall through + case 9: + break; + } + x += 2; + break; + } + + while (x > 20) { + if (x > 30) { + --x; + continue; + } else if (x < 5) + break; + else + goto done; + } + + do { + x++; + } while (x < 10); + + almost_done: + for (int y = x; y < 20; ++y) { + if (x + y == 12) + return; + else if (x - y == 7) + goto almost_done; + } + + done: + x = x + 2; + + int z = x, *y, j = 5; +} + +int f1(int x) { + switch (x) { + case 17: + return 12; + + default: + break; + } + + // variable-length array + int array[x * 17 + 3]; + + return x*2; +} + +const char* what_is_my_name(void) { return __func__; } + +int computed_goto(int x) { + start: + x = x << 1; + void *location = &&start; + + if (x > 17) + location = &&done; + + while (x > 12) { + --x; + if (x == 15) + goto *location; + } + + done: + return 5; +} + +#define maxint(a,b) ({int _a = (a), _b = (b); _a > _b ? _a : _b; }) +int weird_max(int x, int y) { + return maxint(++x, --y); +} diff --git a/test/PCH/struct.c b/test/PCH/struct.c new file mode 100644 index 000000000000..f1e28115d0d7 --- /dev/null +++ b/test/PCH/struct.c @@ -0,0 +1,28 @@ +// Test this without pch. +// RUN: clang-cc -include %S/struct.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/struct.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +struct Point *p1; + +float getX(struct Point *p1) { + return p1->x; +} + +void *get_fun_ptr() { + return fun->is_ptr? fun->ptr : 0; +} + +struct Fun2 { + int very_fun; +}; + +int get_very_fun() { + return fun2->very_fun; +} + +int *int_ptr_fail = &fun->is_ptr; // expected-error{{address of bit-field requested}} + +struct Nested nested = { 1, 2 }; diff --git a/test/PCH/struct.h b/test/PCH/struct.h new file mode 100644 index 000000000000..2ffdd4aea586 --- /dev/null +++ b/test/PCH/struct.h @@ -0,0 +1,29 @@ +// Used with the struct.c test + +struct Point { + float x, y, z; +}; + +struct Point2 { + float xValue, yValue, zValue; +}; + +struct Fun; + +struct Fun *fun; + +struct Fun { + int is_ptr : 1; + + union { + void *ptr; + int *integer; + }; +}; + +struct Fun2; +struct Fun2 *fun2; + +struct S { + struct Nested { int x, y; } nest; +}; diff --git a/test/PCH/tentative-defs.c b/test/PCH/tentative-defs.c new file mode 100644 index 000000000000..980cfab0834b --- /dev/null +++ b/test/PCH/tentative-defs.c @@ -0,0 +1,9 @@ +// Test with pch. +// RUN: clang-cc -triple x86_64-apple-darwin9 -emit-pch -o %t.pch %S/tentative-defs.h && +// RUN: clang-cc -triple x86_64-apple-darwin9 -include-pch %t.pch -verify -emit-llvm -o %t %s && + +// RUN: grep "@variable = common global i32 0" %t | count 1 && +// RUN: grep "@incomplete_array = common global .*1 x i32" %t | count 1 + + +// FIXME: tentative-defs.h expected-warning{{tentative}} diff --git a/test/PCH/tentative-defs.h b/test/PCH/tentative-defs.h new file mode 100644 index 000000000000..4675d9a62eac --- /dev/null +++ b/test/PCH/tentative-defs.h @@ -0,0 +1,9 @@ +// Header for PCH test tentative-defs.c +int variable; + + + + + + +int incomplete_array[]; diff --git a/test/PCH/types.c b/test/PCH/types.c new file mode 100644 index 000000000000..c111c9ea7459 --- /dev/null +++ b/test/PCH/types.c @@ -0,0 +1,72 @@ +// Test this without pch. +// RUN: clang-cc -fblocks -include %S/types.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -fblocks -o %t %S/types.h && +// RUN: clang-cc -fblocks -include-pch %t -fsyntax-only -verify %s + +typedef int INT; +INT int_value; + +__attribute__((address_space(1))) int int_as_one; + +// TYPE_EXT_QUAL +ASInt *as_int_ptr1 = &int_value; // expected-error{{different address spaces}} \ + // FIXME: expected-warning{{discards qualifiers}} +ASInt *as_int_ptr2 = &int_as_one; + +// FIXME: TYPE_FIXED_WIDTH_INT + +// TYPE_COMPLEX +_Complex float Cfloat_val; +Cfloat *Cfloat_ptr = &Cfloat_val; + +// TYPE_POINTER +int_ptr int_value_ptr = &int_value; + +// TYPE_BLOCK_POINTER +void test_block_ptr(Block *bl) { + *bl = ^(int x, float f) { return x; }; +} + +// TYPE_CONSTANT_ARRAY +five_ints fvi = { 1, 2, 3, 4, 5 }; + +// TYPE_INCOMPLETE_ARRAY +float_array fa1 = { 1, 2, 3 }; +float_array fa2 = { 1, 2, 3, 4, 5, 6, 7, 8 }; + +// TYPE_VARIABLE_ARRAY in stmts.[ch] + +// TYPE_VECTOR +float4 f4 = { 1.0, 2.0, 3.0, 4.0 }; + +// TYPE_EXT_VECTOR +ext_float4 ef4 = { 1.0, 2.0, 3.0, 4.0 }; + +// TYPE_FUNCTION_NO_PROTO +noproto np1; +int np1(x, y) + int x; + float y; +{ + return x; +} + +// TYPE_FUNCTION_PROTO +proto p1; +float p1(float x, float y, ...) { + return x + y; +} +proto *p2 = p1; + +// TYPE_TYPEDEF +int_ptr_ptr ipp = &int_value_ptr; + +// TYPE_TYPEOF_EXPR +typeof_17 *t17 = &int_value; +struct S { int x, y; }; +typeof_17 t17_2 = (struct S){1, 2}; // expected-error{{incompatible type initializing}} + +// TYPE_TYPEOF +int_ptr_ptr2 ipp2 = &int_value_ptr; diff --git a/test/PCH/types.h b/test/PCH/types.h new file mode 100644 index 000000000000..df9f5c8607f7 --- /dev/null +++ b/test/PCH/types.h @@ -0,0 +1,44 @@ +/* Used with the types.c test */ + +// TYPE_EXT_QUAL +typedef __attribute__((address_space(1))) int ASInt; + +// FIXME: TYPE_FIXED_WIDTH_INT + +// TYPE_COMPLEX +typedef _Complex float Cfloat; + +// TYPE_POINTER +typedef int * int_ptr; + +// TYPE_BLOCK_POINTER +typedef int (^Block)(int, float); + +// TYPE_CONSTANT_ARRAY +typedef int five_ints[5]; + +// TYPE_INCOMPLETE_ARRAY +typedef float float_array[]; + +// TYPE_VARIABLE_ARRAY in stmts.[ch] + +// TYPE_VECTOR +typedef float float4 __attribute__((vector_size(16))); + +// TYPE_EXT_VECTOR +typedef float ext_float4 __attribute__((ext_vector_type(4))); + +// TYPE_FUNCTION_NO_PROTO +typedef int noproto(); + +// TYPE_FUNCTION_PROTO +typedef float proto(float, float, ...); + +// TYPE_TYPEDEF +typedef int_ptr * int_ptr_ptr; + +// TYPE_TYPEOF_EXPR +typedef typeof(17) typeof_17; + +// TYPE_TYPEOF +typedef typeof(int_ptr *) int_ptr_ptr2; diff --git a/test/PCH/va_arg.c b/test/PCH/va_arg.c new file mode 100644 index 000000000000..75cee06d656f --- /dev/null +++ b/test/PCH/va_arg.c @@ -0,0 +1,12 @@ +// Test this without pch. +// RUN: clang-cc -triple=x86_64-unknown-freebsd7.0 -include %S/va_arg.h %s -emit-llvm -o - && + +// Test with pch. +// RUN: clang-cc -triple=x86_64-unknown-freebsd7.0 -emit-pch -o %t %S/va_arg.h && +// RUN: clang-cc -triple=x86_64-unknown-freebsd7.0 -include-pch %t %s -emit-llvm -o - + +char *g0(char** argv, int argc) { return argv[argc]; } + +char *g(char **argv) { + f(g0, argv, 1, 2, 3); +} diff --git a/test/PCH/va_arg.h b/test/PCH/va_arg.h new file mode 100644 index 000000000000..4a8e5102bc6d --- /dev/null +++ b/test/PCH/va_arg.h @@ -0,0 +1,8 @@ +// Header for PCH test va_arg.c + +typedef __builtin_va_list va_list; +char *f (char * (*g) (char **, int), char **p, ...) { + char *s; + va_list v; + s = g (p, __builtin_va_arg(v, int)); +} diff --git a/test/PCH/variables.c b/test/PCH/variables.c new file mode 100644 index 000000000000..c988a59ce605 --- /dev/null +++ b/test/PCH/variables.c @@ -0,0 +1,23 @@ +// Test this without pch. +// RUN: clang-cc -include %S/variables.h -fsyntax-only -verify %s && + +// Test with pch. +// RUN: clang-cc -emit-pch -o %t %S/variables.h && +// RUN: clang-cc -include-pch %t -fsyntax-only -verify %s + +int *ip2 = &x; +float *fp = &ip; // expected-warning{{incompatible pointer types}} +// FIXME:variables.h expected-note{{previous}} +double z; // expected-error{{redefinition}} +// FIXME:variables.h expected-note{{previous}} +int z2 = 18; // expected-error{{redefinition}} +double VeryHappy; // expected-error{{redefinition}} +// FIXME:variables.h expected-note{{previous definition is here}} + +int Q = A_MACRO_IN_THE_PCH; + +int R = FUNCLIKE_MACRO(A_MACRO_, IN_THE_PCH); + + +int UNIQUE(a); // a2 +int *Arr[] = { &a0, &a1, &a2 }; diff --git a/test/PCH/variables.h b/test/PCH/variables.h new file mode 100644 index 000000000000..70aec6518091 --- /dev/null +++ b/test/PCH/variables.h @@ -0,0 +1,26 @@ +// RUN: clang-cc -emit-pch -o variables.h.pch variables.h +// Do not mess with the whitespace in this file. It's important. + + + + +extern float y; +extern int *ip, x; + +float z; + +int z2 = 17; + +#define MAKE_HAPPY(X) X##Happy +int MAKE_HAPPY(Very); + +#define A_MACRO_IN_THE_PCH 492 +#define FUNCLIKE_MACRO(X, Y) X ## Y + +#define PASTE2(x,y) x##y +#define PASTE1(x,y) PASTE2(x,y) +#define UNIQUE(x) PASTE1(x,__COUNTER__) + +int UNIQUE(a); // a0 +int UNIQUE(a); // a1 + diff --git a/test/Parser/2008-10-31-parse-noop-failure.c b/test/Parser/2008-10-31-parse-noop-failure.c new file mode 100755 index 000000000000..0598ea7dc9e7 --- /dev/null +++ b/test/Parser/2008-10-31-parse-noop-failure.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -verify -parse-noop %t + +void add_attribute(id) int id; {} + diff --git a/test/Parser/CompoundStmtScope.c b/test/Parser/CompoundStmtScope.c new file mode 100644 index 000000000000..6a404aa3a2c6 --- /dev/null +++ b/test/Parser/CompoundStmtScope.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int foo() { + { + typedef float X; + } + X Y; // expected-error {{use of undeclared identifier}} +} diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c new file mode 100644 index 000000000000..6f5622e93932 --- /dev/null +++ b/test/Parser/MicrosoftExtensions.c @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify -fms-extensions -x=objective-c++ %s +__stdcall int func0(); +int __stdcall func(); +typedef int (__cdecl *tptr)(); +void (*__fastcall fastpfunc)(); +extern __declspec(dllimport) void __stdcall VarR4FromDec(); +__declspec(deprecated) __declspec(deprecated) char * __cdecl ltoa( long _Val, char * _DstBuf, int _Radix); +__declspec(noalias) __declspec(restrict) void * __cdecl xxx( void * _Memory ); +typedef __w64 unsigned long ULONG_PTR, *PULONG_PTR; +void * __ptr64 PtrToPtr64(const void *p) +{ + return((void * __ptr64) (unsigned __int64) (ULONG_PTR)p ); +} +__forceinline InterlockedBitTestAndSet (long *Base, long Bit) // expected-warning {{type specifier missing, defaults to 'int'}} +{ + __asm { + mov eax, Bit + mov ecx, Base + lock bts [ecx], eax + setc al + }; +} + +void *_alloca(int); + +void foo() { + __declspec(align(16)) int *buffer = (int *)_alloca(9); +} + +typedef bool (__stdcall __stdcall *blarg)(int); diff --git a/test/Parser/argument_qualified.c b/test/Parser/argument_qualified.c new file mode 100644 index 000000000000..c9494e7373a0 --- /dev/null +++ b/test/Parser/argument_qualified.c @@ -0,0 +1,5 @@ +// RUN: clang-cc %s +int abc (const float x) { + return 1; +} + diff --git a/test/Parser/argument_redef.c b/test/Parser/argument_redef.c new file mode 100644 index 000000000000..1a43178a40cd --- /dev/null +++ b/test/Parser/argument_redef.c @@ -0,0 +1,6 @@ +/* RUN: clang-cc -fsyntax-only -verify %s +*/ + +int foo(int A) { /* expected-note {{previous definition is here}} */ + int A; /* expected-error {{redefinition of 'A'}} */ +} diff --git a/test/Parser/argument_scope.c b/test/Parser/argument_scope.c new file mode 100644 index 000000000000..5e6f439cfdf8 --- /dev/null +++ b/test/Parser/argument_scope.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only %s +typedef struct foo foo; + +void blah(int foo) { + foo = 1; +} diff --git a/test/Parser/asm.c b/test/Parser/asm.c new file mode 100644 index 000000000000..9cf9046aab6a --- /dev/null +++ b/test/Parser/asm.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f1() { + asm ("ret" : : :); // expected-error {{expected string literal}} +} + +void f2() { + asm("foo" : "=r" (a)); // expected-error {{use of undeclared identifier 'a'}} + asm("foo" : : "r" (b)); // expected-error {{use of undeclared identifier 'b'}} +} + + +// rdar://5952468 +__asm ; // expected-error {{expected '(' after 'asm'}} + diff --git a/test/Parser/attributes.c b/test/Parser/attributes.c new file mode 100644 index 000000000000..dc2bb02670c6 --- /dev/null +++ b/test/Parser/attributes.c @@ -0,0 +1,53 @@ +// RUN: clang-cc -fsyntax-only -verify %s -pedantic -std=c99 + +int __attribute__(()) x; + +__inline void __attribute__((__always_inline__, __nodebug__)) +foo(void) { +} + + +__attribute__(()) y; // expected-warning {{defaults to 'int'}} + +// PR2796 +int (__attribute__(()) *z)(long y); + + +void f1(__attribute__(()) int x); + +int f2(y, __attribute__(()) x); // expected-error {{expected identifier}} + +// This is parsed as a normal argument list (with two args that are implicit +// int) because the __attribute__ is a declspec. +void f3(__attribute__(()) x, // expected-warning {{defaults to 'int'}} + y); // expected-warning {{defaults to 'int'}} + +void f4(__attribute__(())); // expected-error {{expected parameter declarator}} + + +// This is ok, the __attribute__ applies to the pointer. +int baz(int (__attribute__(()) *x)(long y)); + +void g1(void (*f1)(__attribute__(()) int x)); +void g2(int (*f2)(y, __attribute__(()) x)); // expected-error {{expected identifier}} +void g3(void (*f3)(__attribute__(()) x, int y)); // expected-warning {{defaults to 'int'}} +void g4(void (*f4)(__attribute__(()))); // expected-error {{expected parameter declarator}} + + +void (*h1)(void (*f1)(__attribute__(()) int x)); +void (*h2)(int (*f2)(y, __attribute__(()) x)); // expected-error {{expected identifier}} + +void (*h3)(void (*f3)(__attribute__(()) x)); // expected-warning {{defaults to 'int'}} +void (*h4)(void (*f4)(__attribute__(()))); // expected-error {{expected parameter declarator}} + + + +// rdar://6131260 +int foo42(void) { + int x, __attribute__((unused)) y, z; + return 0; +} + +// rdar://6096491 +void __attribute__((noreturn)) d0(void), __attribute__((noreturn)) d1(void); + diff --git a/test/Parser/bad-control.c b/test/Parser/bad-control.c new file mode 100644 index 000000000000..6e59667c3549 --- /dev/null +++ b/test/Parser/bad-control.c @@ -0,0 +1,9 @@ +/* RUN: clang-cc -fsyntax-only -verify %s +*/ +int foo() { + break; /* expected-error {{'break' statement not in loop or switch statement}} */ +} + +int foo2() { + continue; /* expected-error {{'continue' statement not in loop statement}} */ +} diff --git a/test/Parser/block-block-storageclass.c b/test/Parser/block-block-storageclass.c new file mode 100644 index 000000000000..d24ec5f1c698 --- /dev/null +++ b/test/Parser/block-block-storageclass.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify -parse-noop %s +#if 0 +#include <stdio.h> +void _Block_byref_release(void*src){} + +int main() { + __block int X = 1234; + __block const char * message = "HELLO"; + + X = X - 1234; + + X += 1; + + printf ("%s(%d)\n", message, X); + X -= 1; + + return X; +} +#endif diff --git a/test/Parser/block-pointer-decl.c b/test/Parser/block-pointer-decl.c new file mode 100644 index 000000000000..7a21651bad32 --- /dev/null +++ b/test/Parser/block-pointer-decl.c @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -verify -parse-noop -fblocks %s + +struct blockStruct { + int (^a)(float, int); + int b; +}; + +int blockTaker (int (^myBlock)(int), int other_input) +{ + return 5 * myBlock (other_input); +} + +int main (int argc, char **argv) +{ + int (^blockptr) (int) = ^(int inval) { + printf ("Inputs: %d, %d.\n", argc, inval); + return argc * inval; + }; + + + argc = 10; + printf ("I got: %d.\n", + blockTaker (blockptr, 6)); + return 0; +} + diff --git a/test/Parser/builtin_classify_type.c b/test/Parser/builtin_classify_type.c new file mode 100644 index 000000000000..7046310eb4a8 --- /dev/null +++ b/test/Parser/builtin_classify_type.c @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct foo { int a; }; + +int main() { + int a; + float b; + double d; + struct foo s; + + static int ary[__builtin_classify_type(a)]; + static int ary2[(__builtin_classify_type)(a)]; // expected-error{{variable length array declaration can not have 'static' storage duration}} + static int ary3[(*__builtin_classify_type)(a)]; // expected-error{{variable length array declaration can not have 'static' storage duration}} + + int result; + + result = __builtin_classify_type(a); + result = __builtin_classify_type(b); + result = __builtin_classify_type(d); + result = __builtin_classify_type(s); +} diff --git a/test/Parser/builtin_types_compatible.c b/test/Parser/builtin_types_compatible.c new file mode 100644 index 000000000000..0664a9f55641 --- /dev/null +++ b/test/Parser/builtin_types_compatible.c @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +extern int funcInt(int); +extern float funcFloat(float); +extern double funcDouble(double); +// figure out why "char *" doesn't work (with gcc, nothing to do with clang) +//extern void funcCharPtr(char *); + +#define func(expr) \ + do { \ + typeof(expr) tmp; \ + if (__builtin_types_compatible_p(typeof(expr), int)) funcInt(tmp); \ + else if (__builtin_types_compatible_p(typeof(expr), float)) funcFloat(tmp); \ + else if (__builtin_types_compatible_p(typeof(expr), double)) funcDouble(tmp); \ + } while (0) +#define func_choose(expr) \ + __builtin_choose_expr(__builtin_types_compatible_p(typeof(expr), int), funcInt(expr), \ + __builtin_choose_expr(__builtin_types_compatible_p(typeof(expr), float), funcFloat(expr), \ + __builtin_choose_expr(__builtin_types_compatible_p(typeof(expr), double), funcDouble(expr), (void)0))) + +static void test() +{ + int a; + float b; + double d; + + func(a); + func(b); + func(d); + a = func_choose(a); + b = func_choose(b); + d = func_choose(d); + + int c; + struct xx { int a; } x, y; + + c = __builtin_choose_expr(a+3-7, b, x); // expected-error{{'__builtin_choose_expr' requires a constant expression}} + c = __builtin_choose_expr(0, b, x); // expected-error{{incompatible type assigning 'struct xx', expected 'int'}} + c = __builtin_choose_expr(5+3-7, b, x); + y = __builtin_choose_expr(4+3-7, b, x); + +} + diff --git a/test/Parser/c-namespace.c b/test/Parser/c-namespace.c new file mode 100644 index 000000000000..ffca15e6a2eb --- /dev/null +++ b/test/Parser/c-namespace.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only %s +void bla1() { + struct XXX; + int XXX; +} + diff --git a/test/Parser/char-literal-printing.c b/test/Parser/char-literal-printing.c new file mode 100644 index 000000000000..f6ad0ff511be --- /dev/null +++ b/test/Parser/char-literal-printing.c @@ -0,0 +1,31 @@ +// RUN: clang-cc -ast-print %s + +#include <stddef.h> + +char test1(void) { return '\\'; } +wchar_t test2(void) { return L'\\'; } +char test3(void) { return '\''; } +wchar_t test4(void) { return L'\''; } +char test5(void) { return '\a'; } +wchar_t test6(void) { return L'\a'; } +char test7(void) { return '\b'; } +wchar_t test8(void) { return L'\b'; } +char test9(void) { return '\e'; } +wchar_t test10(void) { return L'\e'; } +char test11(void) { return '\f'; } +wchar_t test12(void) { return L'\f'; } +char test13(void) { return '\n'; } +wchar_t test14(void) { return L'\n'; } +char test15(void) { return '\r'; } +wchar_t test16(void) { return L'\r'; } +char test17(void) { return '\t'; } +wchar_t test18(void) { return L'\t'; } +char test19(void) { return '\v'; } +wchar_t test20(void) { return L'\v'; } + +char test21(void) { return 'c'; } +wchar_t test22(void) { return L'c'; } +char test23(void) { return '\x3'; } +wchar_t test24(void) { return L'\x3'; } + +wchar_t test25(void) { return L'\x333'; } diff --git a/test/Parser/check-objc2-syntax-1.m b/test/Parser/check-objc2-syntax-1.m new file mode 100644 index 000000000000..f596e9ba0f37 --- /dev/null +++ b/test/Parser/check-objc2-syntax-1.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Subclass ++ (int)magicNumber; +@end + +int main (void) { + return Subclass.magicNumber; +} + diff --git a/test/Parser/check-syntax-1.m b/test/Parser/check-syntax-1.m new file mode 100644 index 000000000000..f4aa430cde18 --- /dev/null +++ b/test/Parser/check-syntax-1.m @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int @interface bla ; // expected-error {{cannot combine with previous 'int' declaration specifier}} +@end diff --git a/test/Parser/check_cast.c b/test/Parser/check_cast.c new file mode 100644 index 000000000000..4df851c7bf9f --- /dev/null +++ b/test/Parser/check_cast.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct foo { + int a; +}; + +int main() { + struct foo xxx; + int i; + + xxx = (struct foo)1; // expected-error {{used type 'struct foo' where arithmetic or pointer type is required}} + i = (int)xxx; // expected-error {{operand of type 'struct foo' where arithmetic or pointer type is required}} +} diff --git a/test/Parser/compound_literal.c b/test/Parser/compound_literal.c new file mode 100644 index 000000000000..c263763b2e2a --- /dev/null +++ b/test/Parser/compound_literal.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int main() { + char *s; + s = (char []){"whatever"}; +} diff --git a/test/Parser/control-scope.c b/test/Parser/control-scope.c new file mode 100644 index 000000000000..7ffc6ac46c0f --- /dev/null +++ b/test/Parser/control-scope.c @@ -0,0 +1,8 @@ +// RUN: clang-cc %s -std=c90 -verify && +// RUN: clang-cc %s -std=c99 + +int f (int z) { + if (z + sizeof (enum {a})) // expected-note {{previous definition is here}} + return 1 + sizeof (enum {a}); // expected-error {{redefinition of enumerator 'a'}} + return 0; +} diff --git a/test/Parser/cxx-ambig-paren-expr.cpp b/test/Parser/cxx-ambig-paren-expr.cpp new file mode 100644 index 000000000000..6f23b35d3e6b --- /dev/null +++ b/test/Parser/cxx-ambig-paren-expr.cpp @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +void f() { + typedef int T; + int x, *px; + + // Type id. + (T())x; // expected-error {{used type 'T (void)'}} + (T())+x; // expected-error {{used type 'T (void)'}} + (T())*px; // expected-error {{used type 'T (void)'}} + + // Expression. + x = (T()); + x = (T())/x; + + typedef int *PT; + // Make sure stuff inside the parens are parsed only once (only one warning). + x = (PT()[(int){1}]); // expected-warning {{compound literals}} + + // Special case: empty parens is a call, not an expression + struct S{int operator()();}; + (S())(); + + // FIXME: Special case: "++" is postfix here, not prefix + // (S())++; +} diff --git a/test/Parser/cxx-bool.cpp b/test/Parser/cxx-bool.cpp new file mode 100644 index 000000000000..f0b3a9f9f038 --- /dev/null +++ b/test/Parser/cxx-bool.cpp @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only %s + +bool a = true; +bool b = false; diff --git a/test/Parser/cxx-casting.cpp b/test/Parser/cxx-casting.cpp new file mode 100644 index 000000000000..1fdc28d2c880 --- /dev/null +++ b/test/Parser/cxx-casting.cpp @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only %s + +char *const_cast_test(const char *var) +{ + return const_cast<char*>(var); +} + +#if 0 +// FIXME: Uncomment when C++ is supported more. +struct A { + virtual ~A() {} +}; + +struct B : public A { +}; + +struct B *dynamic_cast_test(struct A *a) +{ + return dynamic_cast<struct B*>(a); +} +#endif + +char *reinterpret_cast_test() +{ + return reinterpret_cast<char*>(0xdeadbeef); +} + +double static_cast_test(int i) +{ + return static_cast<double>(i); +} + +char postfix_expr_test() +{ + return reinterpret_cast<char*>(0xdeadbeef)[0]; +} diff --git a/test/Parser/cxx-class.cpp b/test/Parser/cxx-class.cpp new file mode 100644 index 000000000000..ff452b919114 --- /dev/null +++ b/test/Parser/cxx-class.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class C; +class C { +public: +protected: + typedef int A,B; + static int sf(), u; + + struct S {}; + enum {}; + int; // expected-error {{declaration does not declare anything}} + int : 1, : 2; + +public: + void m() { + int l = 2; + } + virtual int vf() const volatile = 0; + +private: + int x,f(),y,g(); + inline int h(); + static const int sci = 10; + mutable int mi; +}; +void glo() +{ + struct local {}; +} + +// PR3177 +typedef union { + __extension__ union { + int a; + float b; + } y; +} bug3177; + diff --git a/test/Parser/cxx-condition.cpp b/test/Parser/cxx-condition.cpp new file mode 100644 index 000000000000..8fbca2a90f78 --- /dev/null +++ b/test/Parser/cxx-condition.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -parse-noop -verify %s + +void f() { + int a; + while (a) ; + while (int x) ; // expected-error {{expected '=' after declarator}} + while (float x = 0) ; + if (const int x = a) ; + switch (int x = a+10) {} + for (; int x = ++a; ) ; +} diff --git a/test/Parser/cxx-decl.cpp b/test/Parser/cxx-decl.cpp new file mode 100644 index 000000000000..3fa284282ad6 --- /dev/null +++ b/test/Parser/cxx-decl.cpp @@ -0,0 +1,3 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +int x(*g); // expected-error {{use of undeclared identifier 'g'}} diff --git a/test/Parser/cxx-exception-spec.cpp b/test/Parser/cxx-exception-spec.cpp new file mode 100644 index 000000000000..0a87ab702302 --- /dev/null +++ b/test/Parser/cxx-exception-spec.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only %s + +struct X { }; + +struct Y { }; + +void f() throw() { } + +void g(int) throw(X) { } + +void h() throw(X, Y) { } + +class Class { + void foo() throw (X, Y) { } +}; + +void (*fptr)() throw(); diff --git a/test/Parser/cxx-friend.cpp b/test/Parser/cxx-friend.cpp new file mode 100644 index 000000000000..ea30ddcbd0a8 --- /dev/null +++ b/test/Parser/cxx-friend.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only %s + +class C { + friend class D; +}; + +class A { +public: + void f(); +}; + +class B { + // 'A' here should refer to the declaration above. + friend class A; + + void f(A *a) { a->f(); } +}; diff --git a/test/Parser/cxx-namespace-alias.cpp b/test/Parser/cxx-namespace-alias.cpp new file mode 100644 index 000000000000..65e1459d379b --- /dev/null +++ b/test/Parser/cxx-namespace-alias.cpp @@ -0,0 +1,8 @@ +// RUN: clang-cc -parse-noop -verify %s + +namespace A = B; + +namespace A = !; // expected-error {{expected namespace name}} +namespace A = A::!; // expected-error {{expected namespace name}} + + diff --git a/test/Parser/cxx-reference.cpp b/test/Parser/cxx-reference.cpp new file mode 100644 index 000000000000..0d2b9d29c369 --- /dev/null +++ b/test/Parser/cxx-reference.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +extern char *bork; +char *& bar = bork; + +int val; + +void foo(int &a) { +} + +typedef int & A; + +void g(const A aref) { +} + +int & const X = val; // expected-error {{'const' qualifier may not be applied to a reference}} +int & volatile Y = val; // expected-error {{'volatile' qualifier may not be applied to a reference}} +int & const volatile Z = val; /* expected-error {{'const' qualifier may not be applied}} \ + expected-error {{'volatile' qualifier may not be applied}} */ + +typedef int && RV; // expected-error {{rvalue references are only allowed in C++0x}} diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp new file mode 100644 index 000000000000..ae5d8f9e0cce --- /dev/null +++ b/test/Parser/cxx-template-decl.cpp @@ -0,0 +1,82 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Errors +export class foo { }; // expected-error {{expected template}} +template x; // expected-error {{C++ requires a type specifier for all declarations}} +export template x; // expected-error {{expected '<' after 'template'}} \ + // expected-note {{exported templates are unsupported}} \ +// expected-error {{C++ requires a type specifier for all declarations}} +// See Sema::ParsedFreeStandingDeclSpec about the double diagnostic. This is +// because ParseNonTypeTemplateParameter starts parsing a DeclSpec. +template < ; // expected-error {{parse error}} expected-error {{declaration does not declare anything}} +template <template X> struct Err1; // expected-error {{expected '<' after 'template'}} +template <template <typename> > struct Err2; // expected-error {{expected 'class' before '>'}} +template <template <typename> Foo> struct Err3; // expected-error {{expected 'class' before 'Foo'}} + +// Template function declarations +template <typename T> void foo(); +template <typename T, typename U> void foo(); + +// Template function definitions. +template <typename T> void foo() { } + +// Template class (forward) declarations +template <typename T> struct A; +template <typename T, typename U> struct b; +template <typename> struct C; +template <typename, typename> struct D; + +// Forward declarations with default parameters? +template <typename T = int> class X1; +template <typename = int> class X2; + +// Forward declarations w/template template parameters +template <template <typename> class T> class TTP1; +template <template <typename> class> class TTP2; +template <template <typename> class T = foo> class TTP3; // FIXME:expected-error{{template argument for template template parameter must be a template}} +template <template <typename> class = foo> class TTP3; // FIXME:expected-error{{template argument for template template parameter must be a template}} +template <template <typename X, typename Y> class T> class TTP5; + +// Forward declararations with non-type params +template <int> class NTP0; +template <int N> class NTP1; +template <int N = 5> class NTP2; +template <int = 10> class NTP3; +template <unsigned int N = 12u> class NTP4; +template <unsigned int = 12u> class NTP5; +template <unsigned = 15u> class NTP6; +template <typename T, T Obj> class NTP7; + +// Template class declarations +template <typename T> struct A { }; +template <typename T, typename U> struct B { }; + +// Template parameter shadowing +template<typename T, // expected-note{{template parameter is declared here}} + typename T> // expected-error{{declaration of 'T' shadows template parameter}} + void shadow1(); + +template<typename T> // expected-note{{template parameter is declared here}} +void shadow2(int T); // expected-error{{declaration of 'T' shadows template parameter}} + +template<typename T> // expected-note{{template parameter is declared here}} +class T { // expected-error{{declaration of 'T' shadows template parameter}} +}; + +template<int Size> // expected-note{{template parameter is declared here}} +void shadow3(int Size); // expected-error{{declaration of 'Size' shadows template parameter}} + +// Non-type template parameters in scope +template<int Size> +void f(int& i) { + i = Size; + Size = i; // expected-error{{expression is not assignable}} +} + +template<typename T> +const T& min(const T&, const T&); + +void f2() { + int x; + A< typeof(x>1) > a; +} diff --git a/test/Parser/cxx-throw.cpp b/test/Parser/cxx-throw.cpp new file mode 100644 index 000000000000..bcc49ec1b4fb --- /dev/null +++ b/test/Parser/cxx-throw.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int i; + +void foo() { + (throw,throw); + (1 ? throw 1 : throw 2); + throw int(1); + throw; + throw 1; + throw; + 1 ? throw : (void)42; + __extension__ throw 1; // expected-error {{expected expression}} + (void)throw; // expected-error {{expected expression}} +} diff --git a/test/Parser/cxx-try.cpp b/test/Parser/cxx-try.cpp new file mode 100644 index 000000000000..535f40d78057 --- /dev/null +++ b/test/Parser/cxx-try.cpp @@ -0,0 +1,41 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() +{ + try { + ; + } catch(int i) { + ; + } catch(...) { + } +} + +void g() +{ + try; // expected-error {{expected '{'}} + + try {} + catch; // expected-error {{expected '('}} + + try {} + catch (...); // expected-error {{expected '{'}} + + try {} + catch {} // expected-error {{expected '('}} +} + +void h() try { +} catch(...) { +} + +struct A { + int i; + A(int); + A(char); + A() try : i(0) {} catch(...) {} + void f() try {} catch(...) {} + A(float) : i(0) try {} // expected-error {{expected '{' or ','}} +}; + +A::A(char) : i(0) try {} // expected-error {{expected '{' or ','}} +A::A(int j) try : i(j) {} catch(...) {} diff --git a/test/Parser/cxx-typeid.cpp b/test/Parser/cxx-typeid.cpp new file mode 100644 index 000000000000..5a92e7322f1f --- /dev/null +++ b/test/Parser/cxx-typeid.cpp @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// FIXME: This should really include <typeinfo>, but we don't have that yet. +namespace std { + class type_info; +} + +void f() +{ + (void)typeid(int); + (void)typeid(0); + (void)typeid 1; // expected-error {{error: expected '(' after 'typeid'}} +} diff --git a/test/Parser/cxx-typeof.cpp b/test/Parser/cxx-typeof.cpp new file mode 100644 index 000000000000..0bf446316cfc --- /dev/null +++ b/test/Parser/cxx-typeof.cpp @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +static void test() { + int *pi; + int x; + typeof pi[x] y; +} diff --git a/test/Parser/cxx-using-directive.cpp b/test/Parser/cxx-using-directive.cpp new file mode 100644 index 000000000000..676f4e6c5a5e --- /dev/null +++ b/test/Parser/cxx-using-directive.cpp @@ -0,0 +1,41 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class A {}; + +namespace B { + namespace A {} + using namespace A ; +} + +namespace C {} + +namespace D { + + class C { + + using namespace B ; // expected-error{{expected member name or ';' after declaration specifiers}} + //FIXME: this needs better error message + }; + + namespace B {} + + using namespace C ; + using namespace B::A ; // expected-error{{expected namespace name}} + //FIXME: would be nice to note, that A is not member of D::B + using namespace ::B::A ; + using namespace ::D::C ; // expected-error{{expected namespace name}} +} + +using namespace ! ; // expected-error{{expected namespace name}} +using namespace A ; // expected-error{{expected namespace name}} +using namespace ::A // expected-error{{expected namespace name}} \ + // expected-error{{expected ';' after namespace name}} + B ; + +void test_nslookup() { + int B; + class C; + using namespace B; + using namespace C; +} + diff --git a/test/Parser/cxx-variadic-func.cpp b/test/Parser/cxx-variadic-func.cpp new file mode 100644 index 000000000000..86d6b6bf2c5d --- /dev/null +++ b/test/Parser/cxx-variadic-func.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only %s + +void f(...) { + int g(int(...)); +} diff --git a/test/Parser/cxx0x-rvalue-reference.cpp b/test/Parser/cxx0x-rvalue-reference.cpp new file mode 100644 index 000000000000..389f2b947003 --- /dev/null +++ b/test/Parser/cxx0x-rvalue-reference.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s + +int && r1(int &&a); + +typedef int && R; +void r2(const R a) { + int & &&ar = a; // expected-error{{'ar' declared as a reference to a reference}} +} + diff --git a/test/Parser/declarators.c b/test/Parser/declarators.c new file mode 100644 index 000000000000..26e8027d1078 --- /dev/null +++ b/test/Parser/declarators.c @@ -0,0 +1,66 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic + +extern int a1[]; + +void f0(); +void f1(int [*]); +void f2(int [const *]); +void f3(int [volatile const*]); +int f4(*XX)(void); /* expected-error {{cannot return}} expected-warning {{type specifier missing, defaults to 'int'}} */ + +char ((((*X)))); + +void (*signal(int, void (*)(int)))(int); + +int aaaa, ***C, * const D, B(int); + +int *A; + +struct str; + +int test2(int *P, int A) { + struct str; + + // Hard case for array decl, not Array[*]. + int Array[*(int*)P+A]; +} + +typedef int atype; +int test3(x, + atype /* expected-error {{unexpected type name 'atype': expected identifier}} */ + ) int x, atype; {} + +int test4(x, x) int x; {} /* expected-error {{redefinition of parameter 'x'}} */ + + +// PR3031 +int (test5), ; // expected-error {{expected identifier or '('}} + + + +// PR3963 & rdar://6759604 - test error recovery for mistyped "typenames". + +foo_t *d; // expected-error {{unknown type name 'foo_t'}} +foo_t a; // expected-error {{unknown type name 'foo_t'}} +int test6() { return a; } // a should be declared. + +// Use of tagged type without tag. rdar://6783347 +struct xyz { int y; }; +enum myenum { ASDFAS }; +xyz b; // expected-error {{use of tagged type 'xyz' without 'struct' tag}} +myenum c; // expected-error {{use of tagged type 'myenum' without 'enum' tag}} + +float *test7() { + // We should recover 'b' by parsing it with a valid type of "struct xyz", which + // allows us to diagnose other bad things done with y, such as this. + return &b.y; // expected-warning {{incompatible pointer types returning 'int *', expected 'float *'}} +} + +struct xyz test8() { return a; } // a should be be marked invalid, no diag. + + +// Verify that implicit int still works. +static f; // expected-warning {{type specifier missing, defaults to 'int'}} +static g = 4; // expected-warning {{type specifier missing, defaults to 'int'}} +static h // expected-warning {{type specifier missing, defaults to 'int'}} + __asm__("foo"); diff --git a/test/Parser/designator.c b/test/Parser/designator.c new file mode 100644 index 000000000000..76c2d435227f --- /dev/null +++ b/test/Parser/designator.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only %s -verify -pedantic + +int X[] = { + [4]4, // expected-warning {{use of GNU 'missing =' extension in designator}} + [5] = 7 +}; + +struct foo { + int arr[10]; +}; + +struct foo Y[10] = { + [4] .arr [2] = 4, + + // This is not the GNU array init designator extension. + [4] .arr [2] 4 // expected-error {{expected '=' or another designator}} +}; diff --git a/test/Parser/encode.m b/test/Parser/encode.m new file mode 100644 index 000000000000..1e088a011511 --- /dev/null +++ b/test/Parser/encode.m @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int main(void) { + const char ch = @encode(char *)[2]; + char c = @encode(char *)[2] + 4; + return c; +} + diff --git a/test/Parser/enhanced-proto-1.m b/test/Parser/enhanced-proto-1.m new file mode 100644 index 000000000000..1f42ec2efbb4 --- /dev/null +++ b/test/Parser/enhanced-proto-1.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol MyProto1 +@optional +- (void) FOO; +@optional +- (void) FOO; +@required +- (void) REQ; +@optional +@end + +@protocol MyProto2 <MyProto1> +- (void) FOO2; +@optional +- (void) FOO3; +@end diff --git a/test/Parser/expressions.c b/test/Parser/expressions.c new file mode 100644 index 000000000000..2b4d4636ebb1 --- /dev/null +++ b/test/Parser/expressions.c @@ -0,0 +1,50 @@ +// RUN: clang-cc -parse-noop -verify %s + +void test1() { + if (sizeof (int){ 1}); // sizeof compound literal + if (sizeof (int)); // sizeof type + + (int)4; // cast. + (int){4}; // compound literal. + + // FIXME: change this to the struct version when we can. + //int A = (struct{ int a;}){ 1}.a; + int A = (int){ 1}.a; +} + +int test2(int a, int b) { + return a ? a,b : a; +} + +int test3(int a, int b, int c) { + return a = b = c; +} + +int test4() { + test4(); +} + +int test_offsetof() { + // FIXME: change into something that is semantically correct. + __builtin_offsetof(int, a.b.c[4][5]); +} + +void test_sizeof(){ + int arr[10]; + sizeof arr[0]; + sizeof(arr[0]); + sizeof(arr)[0]; +} + +// PR3418 +int test_leading_extension() { + __extension__ (*(char*)0) = 1; +} + +// PR3972 +int test5(int); +int test6(void) { + return test5( // expected-note {{to match}} + test5(1) + ; // expected-error {{expected ')'}} +} diff --git a/test/Parser/expressions.m b/test/Parser/expressions.m new file mode 100644 index 000000000000..e9e41216f986 --- /dev/null +++ b/test/Parser/expressions.m @@ -0,0 +1,6 @@ +// RUN: clang-cc -parse-noop %s + +void test1() { + @"s"; // expected-warning {{expression result unused}} +} + diff --git a/test/Parser/extension.c b/test/Parser/extension.c new file mode 100644 index 000000000000..519dc053c82f --- /dev/null +++ b/test/Parser/extension.c @@ -0,0 +1,20 @@ +/* RUN: clang-cc %s -fsyntax-only -pedantic -verify -std=c89 + */ + +/* Top level extension marker. */ + +__extension__ typedef struct +{ + long long int quot; + long long int rem; +} lldiv_t; + + +/* Decl/expr __extension__ marker. */ +void bar() { + __extension__ int i; + int j; + __extension__ (j = 10LL); + __extension__ j = 10LL; /* expected-warning {{'long long' is an extension}} */ +} + diff --git a/test/Parser/function-decls.c b/test/Parser/function-decls.c new file mode 100644 index 000000000000..28bb5c2e18da --- /dev/null +++ b/test/Parser/function-decls.c @@ -0,0 +1,10 @@ +/* RUN: clang-cc %s -ast-print + */ + +void foo() { + int X; + X = sizeof(void (*(*)())()); + X = sizeof(int(*)(int, float, ...)); + X = sizeof(void (*(int arga, void (*argb)(double Y)))(void* Z)); +} + diff --git a/test/Parser/goto-ident.c b/test/Parser/goto-ident.c new file mode 100644 index 000000000000..e8d1963e38c2 --- /dev/null +++ b/test/Parser/goto-ident.c @@ -0,0 +1,6 @@ +/* RUN: clang-cc -fsyntax-only -verify %s +*/ + +void foo() { + goto ; /* expected-error {{expected identifier}} */ +} diff --git a/test/Parser/if-scope-c90.c b/test/Parser/if-scope-c90.c new file mode 100644 index 000000000000..fdc75e9f10b0 --- /dev/null +++ b/test/Parser/if-scope-c90.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify --std=c90 %s + +int f (int z) +{ + if (z > sizeof (enum {a, b})) + return a; + return b; +} diff --git a/test/Parser/if-scope-c99.c b/test/Parser/if-scope-c99.c new file mode 100644 index 000000000000..37cd0e15ab8e --- /dev/null +++ b/test/Parser/if-scope-c99.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify --std=c99 %s + +int f (int z) +{ + if (z > sizeof (enum {a, b})) + return a; + return b; // expected-error{{use of undeclared identifier}} +} diff --git a/test/Parser/implicit-casts.c b/test/Parser/implicit-casts.c new file mode 100644 index 000000000000..e7d20980da47 --- /dev/null +++ b/test/Parser/implicit-casts.c @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s +_Complex double X; +void test1(int c) { + X = 5; +} +void test2() { + int i; + double d = i; + double _Complex a = 5; + + test1(a); + a = 5; + d = i; +} +int test3() { + int a[2]; + a[0] = test3; // expected-warning{{incompatible pointer to integer conversion assigning 'int ()', expected 'int'}} +} +short x; void test4(char c) { x += c; } +int y; void test5(char c) { y += c; } diff --git a/test/Parser/method-prototype-1.m b/test/Parser/method-prototype-1.m new file mode 100644 index 000000000000..1d535de8c140 --- /dev/null +++ b/test/Parser/method-prototype-1.m @@ -0,0 +1,43 @@ +// RUN: clang-cc %s -parse-noop +@interface MyObject +- (void) bycopy : (int) woodo, ... ; +- (void) break : (int) woodo, ... ; +- (void) enum : (int) woodo, ... ; +- (void) struct : (int) woodo, ... ; +- (void) union : (int) woodo, ... ; +- (void) if : (int) woodo, int i, char chh, ... ; +- (void) else : (int) woodo, ... ; +- (void) while : (int) woodo, ... ; +- (void) do : (int) woodo, ... ; +- (void) for : (int) woodo, ... ; +- (void) switch : (int) woodo, ... ; +- (void) case : (int) woodo, ... ; +- (void) default : (int) woodo, ... ; +- (void) break : (int) woodo, ... ; +- (void) continue : (int) woodo, ... ; +- (void) return : (int) woodo, ... ; +- (void) goto : (int) woodo, ... ; +- (void) sizeof : (int) woodo, ... ; +- (void) typeof : (int) woodo, ... ; +- (void) __alignof : (int) woodo, ... ; +- (void) unsigned : (int) woodo, ... ; +- (void) long : (int) woodo, ... ; +- (void) const : (int) woodo, ... ; +- (void) short : (int) woodo, ... ; +- (void) volatile : (int) woodo, ... ; +- (void) signed : (int) woodo, ... ; +- (void) restrict : (int) woodo, ... ; +- (void) _Complex : (int) woodo, ... ; +- (void) in : (int) woodo, ... ; +- (void) out : (int) woodo, ... ; +- (void) inout : (int) woodo, ... ; +- (void) bycopy : (int) woodo, ... ; +- (void) byref : (int) woodo, ... ; +- (void) oneway : (int) woodo, ... ; +- (void) int : (int) woodo, ... ; +- (void) char : (int) woodo, ... ; +- (void) float : (int) woodo, ... ; +- (void) double : (int) woodo, ... ; +- (void) void : (int) woodo, ... ; +- (void) _Bool : (int) woodo, ... ; +@end diff --git a/test/Parser/namelookup-bug-1.c b/test/Parser/namelookup-bug-1.c new file mode 100644 index 000000000000..3c8b85a2d61a --- /dev/null +++ b/test/Parser/namelookup-bug-1.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -verify %s + +typedef int Object; + +struct Object *pp; + +Object staticObject1; diff --git a/test/Parser/namelookup-bug-2.c b/test/Parser/namelookup-bug-2.c new file mode 100644 index 000000000000..42298c39c46f --- /dev/null +++ b/test/Parser/namelookup-bug-2.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -verify %s + +typedef int Object; + +struct Object {int i1; } *P; + +void foo() { + struct Object { int i2; } *X; + Object: + { + Object a; + } +} + diff --git a/test/Parser/objc-alias-printing.m b/test/Parser/objc-alias-printing.m new file mode 100644 index 000000000000..e121bed0aea8 --- /dev/null +++ b/test/Parser/objc-alias-printing.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -ast-print %s + +@protocol P1 @end +@protocol P2 @end + +@interface INTF @end + +@compatibility_alias alias INTF; + + +int foo () +{ + INTF *pi; + INTF<P2,P1> *pi2; + alias *p; + alias<P1,P2> *p2; + return pi2 == p2; +} diff --git a/test/Parser/objc-category-neg-1.m b/test/Parser/objc-category-neg-1.m new file mode 100644 index 000000000000..6c1bd2951736 --- /dev/null +++ b/test/Parser/objc-category-neg-1.m @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void __assert_rtn(const char *, const char *, int, const char *) __attribute__((__noreturn__)); +static __inline__ int __inline_isfinitef (float ) __attribute__ ((always_inline)); + +@interface NSATSTypesetter (NSPantherCompatibility) // expected-error {{ "cannot find interface declaration for 'NSATSTypesetter'" }} +- (id)lineFragmentRectForProposedRect:(id)proposedRect remainingRect:(id)remainingRect __attribute__((deprecated)); +@end diff --git a/test/Parser/objc-forcollection-1.m b/test/Parser/objc-forcollection-1.m new file mode 100644 index 000000000000..21ec308a28a1 --- /dev/null +++ b/test/Parser/objc-forcollection-1.m @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only %s + +typedef struct objc_class *Class; +typedef struct objc_object { + Class isa; +} *id; + + +@protocol P @end + +@interface MyList +@end + +@implementation MyList +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +@end + +@interface MyList (BasicTest) +- (void)compilerTestAgainst; +@end + +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { + int i; + for (id elem in self) + ++i; + for (MyList *elem in self) + ++i; + for (id<P> se in self) + ++i; + + MyList<P> *p; + for (p in self) + ++i; + + for (p in p) + ++i; +} +@end + diff --git a/test/Parser/objc-forcollection-neg-2.m b/test/Parser/objc-forcollection-neg-2.m new file mode 100644 index 000000000000..ddb279b6f7c1 --- /dev/null +++ b/test/Parser/objc-forcollection-neg-2.m @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef struct objc_class *Class; +typedef struct objc_object { + Class isa; +} *id; + + +@protocol P @end + +@interface MyList +@end + +@implementation MyList +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +@end + +@interface MyList (BasicTest) +- (void)compilerTestAgainst; +@end + +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { + static i;// expected-warning {{type specifier missing, defaults to 'int'}} + for (id el, elem in self) // expected-error {{only one element declaration is allowed}} + ++i; + for (id el in self) + ++i; + MyList<P> ***p; + for (p in self) // expected-error {{selector element type 'MyList<P> ***' is not a valid object type}} + ++i; + +} +@end + diff --git a/test/Parser/objc-forcollection-neg.m b/test/Parser/objc-forcollection-neg.m new file mode 100644 index 000000000000..0f2bb90df85f --- /dev/null +++ b/test/Parser/objc-forcollection-neg.m @@ -0,0 +1,37 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef struct objc_class *Class; +typedef struct objc_object { + Class isa; +} *id; + + +@interface MyList +@end + +@implementation MyList +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +@end + +@interface MyList (BasicTest) +- (void)compilerTestAgainst; +@end + +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { + + int i=0; + for (int * elem in elem) // expected-error {{selector element type 'int *' is not a valid object}} \ + expected-error {{collection expression type 'int *' is not a valid object}} + ++i; + for (i in elem) // expected-error {{use of undeclared identifier 'elem'}} \ + expected-error {{selector element type 'int' is not a valid object}} + ++i; + for (id se in i) // expected-error {{collection expression type 'int' is not a valid object}} + ++i; +} +@end + diff --git a/test/Parser/objc-foreach-syntax.m b/test/Parser/objc-foreach-syntax.m new file mode 100644 index 000000000000..977dccc88b1d --- /dev/null +++ b/test/Parser/objc-foreach-syntax.m @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -verify %s + + + +@implementation MyList // expected-warning {{cannot find interface declaration for 'MyList'}} +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +@end + + +int LOOP(); + +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { +MyList * el; + for (el in @"foo") + { LOOP(); } +} +@end + + +static int test7(id keys) { + for (id key; in keys) ; // expected-error {{use of undeclared identifier 'in'}} +} diff --git a/test/Parser/objc-init.m b/test/Parser/objc-init.m new file mode 100644 index 000000000000..a91ac9cf285b --- /dev/null +++ b/test/Parser/objc-init.m @@ -0,0 +1,41 @@ +// RUN: clang-cc -fsyntax-only -verify %s -pedantic +// rdar://5707001 + +@interface NSNumber; +- () METH; +- (unsigned) METH2; +@end + +struct SomeStruct { + int x, y, z, q; +}; + +void test1() { + id objects[] = {[NSNumber METH]}; +} + +void test2(NSNumber x) { // expected-error {{Objective-C interface type 'NSNumber' cannot be passed by value}} + id objects[] = {[x METH]}; +} + +void test3(NSNumber *x) { + id objects[] = {[x METH]}; +} + + +// rdar://5977581 +void test4() { + unsigned x[] = {[NSNumber METH2]+2}; +} + +void test5(NSNumber *x) { + unsigned y[] = { + [4][NSNumber METH2]+2, // expected-warning {{use of GNU 'missing =' extension in designator}} + [4][x METH2]+2 // expected-warning {{use of GNU 'missing =' extension in designator}} + }; + + struct SomeStruct z = { + .x = [x METH2], // ok. + .x [x METH2] // expected-error {{expected '=' or another designator}} + }; +} diff --git a/test/Parser/objc-interfaces.m b/test/Parser/objc-interfaces.m new file mode 100644 index 000000000000..7aa672901fff --- /dev/null +++ b/test/Parser/objc-interfaces.m @@ -0,0 +1,8 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// Test features and error recovery for objc interfaces. + +@interface INTF +- (int*) foo2 __attribute__((deprecated)) : (int) x1 __attribute__((deprecated)); // expected-error {{expected ';' after method prototype}} +@end + diff --git a/test/Parser/objc-messaging-1.m b/test/Parser/objc-messaging-1.m new file mode 100644 index 000000000000..4a36fc950fa8 --- /dev/null +++ b/test/Parser/objc-messaging-1.m @@ -0,0 +1,19 @@ +// RUN: clang-cc %s -parse-noop +int main () +{ + int i,j; + struct S *p; + id a, b, c; + [p ii]; + [p if: 1 :2]; + [p inout: 1 :2 another:(2,3,4)]; + [p inout: 1 :2 another:(2,3,4), 6,6,8]; + [p inout: 1 :2 another:(2,3,4), (6,4,5),6,8]; + [p inout: 1 :2 another:(i+10), (i,j-1,5),6,8]; + [p long: 1 :2 another:(i+10), (i,j-1,5),6,8]; + [p : "Hello\n" :2 another:(i+10), (i,j-1,5),6,8]; + + // Comma expression as receiver (rdar://6222856) + [a, b, c foo]; + +} diff --git a/test/Parser/objc-messaging-neg-1.m b/test/Parser/objc-messaging-neg-1.m new file mode 100644 index 000000000000..a1ec116fb7b4 --- /dev/null +++ b/test/Parser/objc-messaging-neg-1.m @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int main() + { + id a; + [a bla:0 6:7]; // expected-error {{expected ']'}} + } diff --git a/test/Parser/objc-missing-impl.m b/test/Parser/objc-missing-impl.m new file mode 100644 index 000000000000..9108451f1bff --- /dev/null +++ b/test/Parser/objc-missing-impl.m @@ -0,0 +1,2 @@ +// RUN: clang-cc -fsyntax-only -verify %s +@end // expected-warning {{@end must appear in an @implementation context}} diff --git a/test/Parser/objc-property-syntax.m b/test/Parser/objc-property-syntax.m new file mode 100644 index 000000000000..cf75aaa2d5a2 --- /dev/null +++ b/test/Parser/objc-property-syntax.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface MyClass { + +}; +@property unsigned char bufferedUTF8Bytes[4]; // expected-error {{property cannot have array or function type}} +@property unsigned char bufferedUTFBytes:1; // expected-error {{property name cannot be a bitfield}} +@end + +@implementation MyClass +@end + diff --git a/test/Parser/objc-quirks.m b/test/Parser/objc-quirks.m new file mode 100644 index 000000000000..2913b580c5fc --- /dev/null +++ b/test/Parser/objc-quirks.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// FIXME: This is a horrible error message here. Fix. +int @"s" = 5; // expected-error {{prefix attribute must be}} + + +// rdar://6480479 +@interface A +}; // expected-error {{missing @end}} expected-error {{expected external declaration}} + diff --git a/test/Parser/objc-try-catch-1.m b/test/Parser/objc-try-catch-1.m new file mode 100644 index 000000000000..a8d37f0ab959 --- /dev/null +++ b/test/Parser/objc-try-catch-1.m @@ -0,0 +1,68 @@ +// RUN: clang-cc -fsyntax-only -verify %s && +// RUN: clang-cc -fsyntax-only -verify -x objective-c++ %s +void * proc(); + +@interface NSConstantString +@end + +@interface Frob +@end + +@interface Frob1 +@end + +void * foo() +{ + @try { + return proc(); + } + @catch (Frob* ex) { + @throw; + } + @catch (Frob1* ex) { + @throw proc(); + } + @finally { + @try { + return proc(); + } + @catch (Frob* ex) { + @throw 1,2; // expected-error {{@throw requires an Objective-C object type ('int' invalid)}} + } + @catch (float x) { // expected-error {{@catch parameter is not a pointer to an interface type}} + + } + @catch(...) { + @throw (4,3,proc()); + } + } + + @try { // expected-error {{@try statement without a @catch and @finally clause}} + return proc(); + } +} + + +void bar() +{ + @try {}// expected-error {{@try statement without a @catch and @finally clause}} + @"s"; // expected-warning {{result unused}} +} + +void baz() +{ + @try {}// expected-error {{@try statement without a @catch and @finally clause}} + @try {} + @finally {} +} + +void noTwoTokenLookAheadRequiresABitOfFancyFootworkInTheParser() { + @try { + // Do something + } @catch (...) {} + @try { + // Do something + } @catch (...) {} + return; +} + diff --git a/test/Parser/objc-type-printing.m b/test/Parser/objc-type-printing.m new file mode 100644 index 000000000000..d9ad70474f2b --- /dev/null +++ b/test/Parser/objc-type-printing.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -ast-print %s + +@protocol P1 @end +@protocol P2 @end +@protocol P3 @end + +@interface INTF +- (INTF<P1>*) METH; +@end + +void foo() +{ + INTF *pintf; + INTF<P1>* p1; + INTF<P1, P1>* p2; + INTF<P1, P3>* p3; + INTF<P1, P3, P2>* p4; + INTF<P2,P2, P3, P1>* p5; +} diff --git a/test/Parser/parmvardecl_conversion.c b/test/Parser/parmvardecl_conversion.c new file mode 100644 index 000000000000..f35487ee95c6 --- /dev/null +++ b/test/Parser/parmvardecl_conversion.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f (int p[]) { p++; } + diff --git a/test/Parser/pointer-arithmetic.c b/test/Parser/pointer-arithmetic.c new file mode 100644 index 000000000000..d252b42c9b15 --- /dev/null +++ b/test/Parser/pointer-arithmetic.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int *test1(int *a) { return a + 1; } +int *test2(int *a) { return 1 + a; } +int *test3(int *a) { return a - 1; } +int test4(int *a, int *b) { return a - b; } + +int test5(int *a, int *b) { return a + b; } /* expected-error {{invalid operands}} */ +int *test6(int *a) { return 1 - a; } /* expected-error {{invalid operands}} */ diff --git a/test/Parser/pointer_promotion.c b/test/Parser/pointer_promotion.c new file mode 100644 index 000000000000..0254828e0f02 --- /dev/null +++ b/test/Parser/pointer_promotion.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int test() { + void *vp; + int *ip; + char *cp; + struct foo *fp; + struct bar *bp; + short sint = 7; + + if (ip < cp) {} // expected-warning {{comparison of distinct pointer types ('int *' and 'char *')}} + if (cp < fp) {} // expected-warning {{comparison of distinct pointer types ('char *' and 'struct foo *')}} + if (fp < bp) {} // expected-warning {{comparison of distinct pointer types ('struct foo *' and 'struct bar *')}} + if (ip < 7) {} // expected-warning {{comparison between pointer and integer ('int *' and 'int')}} + if (sint < ip) {} // expected-warning {{comparison between pointer and integer ('int' and 'int *')}} + if (ip == cp) {} // expected-warning {{comparison of distinct pointer types ('int *' and 'char *')}} +} + diff --git a/test/Parser/pragma-pack.c b/test/Parser/pragma-pack.c new file mode 100644 index 000000000000..d42bbe5c40d2 --- /dev/null +++ b/test/Parser/pragma-pack.c @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Note that this puts the expected lines before the directives to work around +// limitations in the -verify mode. + +/* expected-warning {{missing '(' after '#pragma pack'}}*/ #pragma pack 10 +#pragma pack() +#pragma pack(8) + +/*expected-warning {{unknown action for '#pragma pack'}}*/ #pragma pack(hello) +#pragma pack(push) +#pragma pack(pop) + +/* expected-warning {{expected integer or identifier in '#pragma pack'}}*/ #pragma pack(push,) +/* expected-warning {{expected integer or identifier in '#pragma pack'}}*/ #pragma pack(push,) +/* expected-warning {{expected integer or identifier in '#pragma pack'}}*/ #pragma pack(pop,) + +#pragma pack(push,i) +/* expected-warning {{expected integer or identifier in '#pragma pack'}}*/ #pragma pack(push,i, +/* expected-warning {{expected integer or identifier in '#pragma pack'}}*/ #pragma pack(push,i,) +/* expected-warning {{expected integer or identifier in '#pragma pack'}}*/ #pragma pack(push,i,help) + +#pragma pack(push,8) +/* expected-warning {{missing ')' after '#pragma pack'}}*/ #pragma pack(push,8, +/* expected-warning {{missing ')' after '#pragma pack'}}*/ #pragma pack(push,8,) +/* expected-warning {{missing ')' after '#pragma pack'}}*/ #pragma pack(push,i,8 +#pragma pack(push,i,8) + +/* expected-warning {{missing ')' after '#pragma pack'}}*/ #pragma pack(push + +_Pragma("pack(push)") +/* expected-warning {{expected integer or identifier in '#pragma pack'}}*/ _Pragma("pack(push,)") diff --git a/test/Parser/prefix-attributes.m b/test/Parser/prefix-attributes.m new file mode 100644 index 000000000000..bb6d04da2a08 --- /dev/null +++ b/test/Parser/prefix-attributes.m @@ -0,0 +1,8 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +__attribute__((deprecated)) @class B; // expected-error {{prefix attribute must be followed by an interface or protocol}} + +__attribute__((deprecated)) @interface A @end +__attribute__((deprecated)) @protocol P0; +__attribute__((deprecated)) @protocol P1 +@end diff --git a/test/Parser/promote_types_in_proto.c b/test/Parser/promote_types_in_proto.c new file mode 100644 index 000000000000..faff3e35d5a3 --- /dev/null +++ b/test/Parser/promote_types_in_proto.c @@ -0,0 +1,9 @@ +// RUN: clang-cc %s +void functionPromotion(void f(char *const [])); +void arrayPromotion(char * const argv[]); + +int whatever(int argc, char *argv[]) +{ + arrayPromotion(argv); + functionPromotion(arrayPromotion); +} diff --git a/test/Parser/recovery.c b/test/Parser/recovery.c new file mode 100644 index 000000000000..89eac564a329 --- /dev/null +++ b/test/Parser/recovery.c @@ -0,0 +1,75 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic -fblocks %s + +// PR2241 +float test2241[2] = { + 1e, // expected-error {{exponent}} + 1ee0 // expected-error {{exponent}} +}; + + +// Testcase derived from PR2692 +static char *f (char * (*g) (char **, int), char **p, ...) { + char *s; + va_list v; // expected-error {{identifier}} + s = g (p, __builtin_va_arg(v, int)); // expected-error {{identifier}} +} + + +// PR3172 +} // expected-error {{expected external declaration}} + + +// rdar://6094870 +int test(int a) { + struct { int i; } x; + + if (x.hello) // expected-error {{no member named 'hello'}} + test(0); + else + ; + + if (x.hello == 0) // expected-error {{no member named 'hello'}} + test(0); + else + ; + + if ((x.hello == 0)) // expected-error {{no member named 'hello'}} + test(0); + else + ; + + if (x.i == 0)) // expected-error {{expected expression}} + test(0); + else + ; +} + + + +char (((( /* expected-note {{to match this '('}} */ + *X x ] )))); /* expected-error {{expected ')'}} */ + +; // expected-warning {{ISO C does not allow an extra ';' outside of a function}} + + + + +struct S { void *X, *Y; }; + +struct S A = { +&BADIDENT, 0 /* expected-error {{use of undeclared identifier}} */ +}; + +// rdar://6248081 +int test6248081() { + [10] // expected-error {{expected expression}} +} + +struct forward; // expected-note{{forward declaration of 'struct forward'}} +void x(struct forward* x) {switch(x->a) {}} // expected-error {{incomplete definition of type}} + +// PR3410 +void foo() { + int X; + X = 4 // expected-error{{expected ';' after expression}} +} diff --git a/test/Parser/selector-1.m b/test/Parser/selector-1.m new file mode 100644 index 000000000000..85ef919689df --- /dev/null +++ b/test/Parser/selector-1.m @@ -0,0 +1,14 @@ +// RUN: clang-cc -parse-noop %s + +int main() { + SEL s = @selector(retain); + SEL s1 = @selector(meth1:); + SEL s2 = @selector(retainArgument::); + SEL s3 = @selector(retainArgument:::::); + SEL s4 = @selector(retainArgument:with:); + SEL s5 = @selector(meth1:with:with:); + SEL s6 = @selector(getEnum:enum:bool:); + SEL s7 = @selector(char:float:double:unsigned:short:long:); + + SEL s9 = @selector(:enum:bool:); +} diff --git a/test/Parser/statements.c b/test/Parser/statements.c new file mode 100644 index 000000000000..c5923bc0641b --- /dev/null +++ b/test/Parser/statements.c @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int test1() { + { ; { ;;}} ;; +} + +int test2() { + if (0) { if (1) {} } else { } + + do { } while (0); + + while (0) while(0) do ; while(0); + + for (0;0;0) + for (;;) + for (9;0;2) + ; + for (int X = 0; 0; 0); +} + +int test3() { + switch (0) { + + case 4: + if (0) { + case 6: ; + } + default: + ; + } +} + +int test4() { + if (0); // expected-warning {{if statement has empty body}} + + int X; // declaration in a block. + +foo: if (0); // expected-warning {{if statement has empty body}} +} + +typedef int t; +void test5() { + if (0); // expected-warning {{if statement has empty body}} + + t x = 0; + + if (0); // expected-warning {{if statement has empty body}} +} + + +void test6(void) { + do + . // expected-error {{expected expression}} + while (0); +} + diff --git a/test/Parser/struct-recursion.c b/test/Parser/struct-recursion.c new file mode 100644 index 000000000000..11e5f7e97ab1 --- /dev/null +++ b/test/Parser/struct-recursion.c @@ -0,0 +1,11 @@ +// RUN: clang-cc %s -fsyntax-only + +// C99 6.7.2.3p11 + +// mutually recursive structs +struct s1 { struct s2 *A; }; +struct s2 { struct s1 *B; }; + +// both types are complete now. +struct s1 a; +struct s2 b; diff --git a/test/Parser/traditional_arg_scope.c b/test/Parser/traditional_arg_scope.c new file mode 100644 index 000000000000..2a21ec3708d4 --- /dev/null +++ b/test/Parser/traditional_arg_scope.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only %s -verify + +int x(a) int a; {return a;} +int y(b) int b; {return a;} // expected-error {{use of undeclared identifier}} + +// PR2332 +int a(a)int a;{a=10;return a;} diff --git a/test/Parser/typeof.c b/test/Parser/typeof.c new file mode 100644 index 000000000000..a7c488023ae2 --- /dev/null +++ b/test/Parser/typeof.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef int TInt; + +static void test() { + int *pi; + + int typeof (int) aIntInt; // expected-error{{cannot combine with previous 'int' declaration specifier}} + short typeof (int) aShortInt; // expected-error{{'short typeof' is invalid}} + int int ttt; // expected-error{{cannot combine with previous 'int' declaration specifier}} + typeof(TInt) anInt; + short TInt eee; // expected-error{{expected ';' at end of declaration}} + void ary[7] fff; // expected-error{{array has incomplete element type 'void'}} expected-error{{expected ';' at end of declaration}} + typeof(void ary[7]) anIntError; // expected-error{{expected ')'}} expected-note {{to match this '('}} expected-error {{variable has incomplete type 'typeof(void)' (aka 'void')}} + typeof(const int) aci; + const typeof (*pi) aConstInt; + int xx; + int *i; +} diff --git a/test/Parser/types.c b/test/Parser/types.c new file mode 100644 index 000000000000..2131ab0346f4 --- /dev/null +++ b/test/Parser/types.c @@ -0,0 +1,14 @@ +// RUN: clang-cc %s -parse-noop + +// Test the X can be overloaded inside the struct. +typedef int X; +struct Y { short X; }; + +// Variable shadows type, PR3872 + +typedef struct foo { int x; } foo; +void test() { + foo *foo; + foo->x = 0; +} + diff --git a/test/Preprocessor/_Pragma-dependency.c b/test/Preprocessor/_Pragma-dependency.c new file mode 100644 index 000000000000..da1d87f741e6 --- /dev/null +++ b/test/Preprocessor/_Pragma-dependency.c @@ -0,0 +1,7 @@ +// RUN: clang-cc %s -E 2>&1 | grep 'DO_PRAGMA (STR' && +// RUN: clang-cc %s -E 2>&1 | grep '7:3' + +#define DO_PRAGMA _Pragma +#define STR "GCC dependency \"parse.y\"") + // Test that this line is printed by caret diagnostics. + DO_PRAGMA (STR diff --git a/test/Preprocessor/_Pragma-location.c b/test/Preprocessor/_Pragma-location.c new file mode 100644 index 000000000000..61cadfbb8a18 --- /dev/null +++ b/test/Preprocessor/_Pragma-location.c @@ -0,0 +1,4 @@ +// RUN: clang-cc %s -E | not grep 'scratch space' + +#define push _Pragma ("pack(push)") +push diff --git a/test/Preprocessor/_Pragma-physloc.c b/test/Preprocessor/_Pragma-physloc.c new file mode 100644 index 000000000000..87379491676d --- /dev/null +++ b/test/Preprocessor/_Pragma-physloc.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -E | grep '#pragma x y z' && +// RUN: clang-cc %s -E | grep '#pragma a b c' + +_Pragma("x y z") +_Pragma("a b c") + diff --git a/test/Preprocessor/_Pragma-syshdr2.c b/test/Preprocessor/_Pragma-syshdr2.c new file mode 100644 index 000000000000..de7f2d3dc3b1 --- /dev/null +++ b/test/Preprocessor/_Pragma-syshdr2.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -E %s 2>&1 | grep 'file not found' + +#define DO_PRAGMA _Pragma +DO_PRAGMA ("GCC dependency \"blahblabh\"") + diff --git a/test/Preprocessor/_Pragma.c b/test/Preprocessor/_Pragma.c new file mode 100644 index 000000000000..9c0c97d1f011 --- /dev/null +++ b/test/Preprocessor/_Pragma.c @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -verify -Wall + +_Pragma ("GCC system_header") // expected-warning {{system_header ignored in main file}} + +// rdar://6880630 +_Pragma("#define macro") // expected-warning {{unknown pragma ignored}} + +#ifdef macro +#error #define invalid +#endif diff --git a/test/Preprocessor/assembler-with-cpp.c b/test/Preprocessor/assembler-with-cpp.c new file mode 100644 index 000000000000..2e84ed1a6b07 --- /dev/null +++ b/test/Preprocessor/assembler-with-cpp.c @@ -0,0 +1,77 @@ +// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=0 -E %s > %t && + +#ifndef __ASSEMBLER__ +#error "__ASSEMBLER__ not defined" +#endif + + +// Invalid token pasting is ok. +// RUN: grep '1: X .' %t && +#define A X ## . +1: A + +// Line markers are not linemarkers in .S files, they are passed through. +// RUN: grep '# 321' %t && +# 321 + +// Unknown directives are passed through. +// RUN: grep '# B C' %t && +# B C + +// Unknown directives are expanded. +// RUN: grep '# BAR42' %t && +#define D(x) BAR ## x +# D(42) + +// Unmatched quotes are permitted. +// RUN: grep "2: '" %t && +// RUN: grep '3: "' %t && +2: ' +3: " + +// (balance quotes to keep editors happy): "' + +// Empty char literals are ok. +// RUN: grep "4: ''" %t && +4: '' + + +// Portions of invalid pasting should still expand as macros. +// rdar://6709206 +// RUN: grep "5: expanded (" %t && +#define M4 expanded +#define M5() M4 ## ( + +5: M5() + +// rdar://6804322 +// RUN: grep -F "6: blarg $foo" %t && +#define FOO(name) name ## $foo +6: FOO(blarg) + +// RUN: clang-cc -x assembler-with-cpp -fdollars-in-identifiers=1 -E %s > %t && +// RUN: grep -F "7: blarg$foo" %t && +#define FOO(name) name ## $foo +7: FOO(blarg) + + +// +#define T6() T6 #nostring +#define T7(x) T7 #x +8: T6() +9: T7(foo) +// RUN: grep '8: T6 #nostring' %t && +// RUN: grep '9: T7 "foo"' %t && + +// Concatenation with period doesn't leave a space +// RUN: grep -F '10: .T8' %t && +#define T8(A,B) A ## B +10: T8(.,T8) + + +// This should not crash. +// RUN: grep '11: #0' %t && +#define T11(a) #0 +11: T11(b) + +// RUN: true diff --git a/test/Preprocessor/builtin_line.c b/test/Preprocessor/builtin_line.c new file mode 100644 index 000000000000..db01e47995a8 --- /dev/null +++ b/test/Preprocessor/builtin_line.c @@ -0,0 +1,13 @@ +// RUN: clang-cc %s -E | grep "^ 4" && +#define FOO __LINE__ + + FOO + +// PR3579 - This should expand to the __LINE__ of the ')' not of the X. +// RUN: clang-cc %s -E | grep "^A 13" + +#define X() __LINE__ + +A X( + +) diff --git a/test/Preprocessor/c90.c b/test/Preprocessor/c90.c new file mode 100644 index 000000000000..ed63d1b3d7cc --- /dev/null +++ b/test/Preprocessor/c90.c @@ -0,0 +1,10 @@ +/* RUN: clang-cc %s -std=c89 -Eonly -verify -pedantic-errors + */ + +/* PR3919 */ + +#define foo`bar /* expected-error {{whitespace required after macro name}} */ +#define foo2!bar /* expected-warning {{whitespace recommended after macro name}} */ + +#define foo3$bar /* expected-error {{'$' in identifier}} */ + diff --git a/test/Preprocessor/c99-6_10_3_3_p4.c b/test/Preprocessor/c99-6_10_3_3_p4.c new file mode 100644 index 000000000000..89660549b9a1 --- /dev/null +++ b/test/Preprocessor/c99-6_10_3_3_p4.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -E %s | grep -F 'char p[] = "x ## y";' +#define hash_hash # ## # +#define mkstr(a) # a +#define in_between(a) mkstr(a) +#define join(c, d) in_between(c hash_hash d) +char p[] = join(x, y); diff --git a/test/Preprocessor/c99-6_10_3_4_p5.c b/test/Preprocessor/c99-6_10_3_4_p5.c new file mode 100644 index 000000000000..22bdf8258cbe --- /dev/null +++ b/test/Preprocessor/c99-6_10_3_4_p5.c @@ -0,0 +1,29 @@ +// Example from C99 6.10.3.4p5 + +// RUN: clang-cc -E %s | grep -F 'f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);' && +// RUN: clang-cc -E %s | grep -F 'f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);' && +// RUN: clang-cc -E %s | grep -F 'int i[] = { 1, 23, 4, 5, };' && +// RUN: clang-cc -E %s | grep -F 'char c[2][6] = { "hello", "" };' + + +#define x 3 +#define f(a) f(x * (a)) +#undef x +#define x 2 +#define g f +#define z z[0] +#define h g(~ +#define m(a) a(w) +#define w 0,1 +#define t(a) a +#define p() int +#define q(x) x +#define r(x,y) x ## y +#define str(x) # x + f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); + g(x+(3,4)-w) | h 5) & m +(f)^m(m); +p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) }; +char c[2][6] = { str(hello), str() }; + + diff --git a/test/Preprocessor/c99-6_10_3_4_p6.c b/test/Preprocessor/c99-6_10_3_4_p6.c new file mode 100644 index 000000000000..c48d2efd2eff --- /dev/null +++ b/test/Preprocessor/c99-6_10_3_4_p6.c @@ -0,0 +1,24 @@ +// Example from C99 6.10.3.4p6 + +// RUN: clang-cc -E %s | grep -F 'printf("x" "1" "= %d, x" "2" "= s" x1, x2);' && +// RUN: clang-cc -E %s | grep 'fputs("strncmp(\\"abc\\\\0d\\" \\"abc\\", .\\\\4.) == 0" ": @\\n", s);' && +// RUN: clang-cc -E %s | grep -F 'include "vers2.h"' && +// RUN: clang-cc -E %s | grep -F '"hello";' && +// RUN: clang-cc -E %s | grep -F '"hello" ", world"' + +#define str(s) # s +#define xstr(s) str(s) +#define debug(s, t) printf("x" # s "= %d, x" # t "= s" \ + x ## s, x ## t) +#define INCFILE(n) vers ## n +#define glue(a, b) a ## b +#define xglue(a, b) glue(a, b) +#define HIGHLOW "hello" +#define LOW LOW ", world" +debug(1, 2); +fputs(str(strncmp("abc\0d" "abc", '\4') // this goes away + == 0) str(: @\n), s); +include xstr(INCFILE(2).h) +glue(HIGH, LOW); +xglue(HIGH, LOW) + diff --git a/test/Preprocessor/c99-6_10_3_4_p7.c b/test/Preprocessor/c99-6_10_3_4_p7.c new file mode 100644 index 000000000000..a53df8263f19 --- /dev/null +++ b/test/Preprocessor/c99-6_10_3_4_p7.c @@ -0,0 +1,9 @@ +// Example from C99 6.10.3.4p7 + +// RUN: clang-cc -E %s | grep -F 'int j[] = { 123, 45, 67, 89,' && +// RUN: clang-cc -E %s | grep -F '10, 11, 12, };' + +#define t(x,y,z) x ## y ## z +int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), +t(10,,), t(,11,), t(,,12), t(,,) }; + diff --git a/test/Preprocessor/c99-6_10_3_4_p9.c b/test/Preprocessor/c99-6_10_3_4_p9.c new file mode 100644 index 000000000000..39c34546ad4d --- /dev/null +++ b/test/Preprocessor/c99-6_10_3_4_p9.c @@ -0,0 +1,16 @@ +// Example from C99 6.10.3.4p9 + +// RUN: clang-cc -E %s | grep -F 'fprintf(stderr, "Flag");' && +// RUN: clang-cc -E %s | grep -F 'fprintf(stderr, "X = %d\n", x);' && +// RUN: clang-cc -E %s | grep -F 'puts("The first, second, and third items.");' && +// RUN: clang-cc -E %s | grep -F '((x>y)?puts("x>y"): printf("x is %d but y is %d", x, y));' + +#define debug(...) fprintf(stderr, __VA_ARGS__) +#define showlist(...) puts(#__VA_ARGS__) +#define report(test, ...) ((test)?puts(#test):\ + printf(__VA_ARGS__)) +debug("Flag"); +debug("X = %d\n", x); +showlist(The first, second, and third items.); +report(x>y, "x is %d but y is %d", x, y); + diff --git a/test/Preprocessor/clang_headers.c b/test/Preprocessor/clang_headers.c new file mode 100644 index 000000000000..1cb331998f43 --- /dev/null +++ b/test/Preprocessor/clang_headers.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -E %s + +#include <limits.h> diff --git a/test/Preprocessor/comment_save.c b/test/Preprocessor/comment_save.c new file mode 100644 index 000000000000..30b043433c97 --- /dev/null +++ b/test/Preprocessor/comment_save.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -E -C %s | grep '^// foo$' && +// RUN: clang-cc -E -C %s | grep -F '^/* bar */$' + +// foo +/* bar */ + + diff --git a/test/Preprocessor/comment_save_if.c b/test/Preprocessor/comment_save_if.c new file mode 100644 index 000000000000..c08b2d7c78b7 --- /dev/null +++ b/test/Preprocessor/comment_save_if.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -E -CC -pedantic 2>&1 | grep -v '^/' | not grep warning + +#if 1 /*bar */ + +#endif /*foo*/ + diff --git a/test/Preprocessor/comment_save_macro.c b/test/Preprocessor/comment_save_macro.c new file mode 100644 index 000000000000..66b59d136d73 --- /dev/null +++ b/test/Preprocessor/comment_save_macro.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -E -C %s | grep '^boo bork bar // zot$' && +// RUN: clang-cc -E -CC %s | grep -F '^boo bork /* blah*/ bar // zot$' && +// RUN: clang-cc -E %s | grep '^boo bork bar$' + + +#define FOO bork // blah +boo FOO bar // zot + diff --git a/test/Preprocessor/cxx_and.cpp b/test/Preprocessor/cxx_and.cpp new file mode 100644 index 000000000000..971b7bc991dc --- /dev/null +++ b/test/Preprocessor/cxx_and.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -DA -DB -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DA -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -DB -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -E %s | grep 'int a = 927 == 927' +#if defined(A) and defined(B) +#define X 37 +#else +#define X 927 +#endif + +#if defined(A) && defined(B) +#define Y 37 +#else +#define Y 927 +#endif + +int a = X == Y; diff --git a/test/Preprocessor/cxx_bitand.cpp b/test/Preprocessor/cxx_bitand.cpp new file mode 100644 index 000000000000..8d7fe678e3e0 --- /dev/null +++ b/test/Preprocessor/cxx_bitand.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -DA=1 -DB=2 -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -E %s | grep 'int a = 927 == 927' +#if A bitand B +#define X 37 +#else +#define X 927 +#endif + +#if A & B +#define Y 37 +#else +#define Y 927 +#endif + +int a = X == Y; diff --git a/test/Preprocessor/cxx_bitor.cpp b/test/Preprocessor/cxx_bitor.cpp new file mode 100644 index 000000000000..7645c7ee5133 --- /dev/null +++ b/test/Preprocessor/cxx_bitor.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DA=0 -DB=1 -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DA=1 -DB=0 -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DA=0 -DB=0 -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -E %s | grep 'int a = 927 == 927' +#if A bitor B +#define X 37 +#else +#define X 927 +#endif + +#if A | B +#define Y 37 +#else +#define Y 927 +#endif + +int a = X == Y; diff --git a/test/Preprocessor/cxx_compl.cpp b/test/Preprocessor/cxx_compl.cpp new file mode 100644 index 000000000000..f1cc6d2800d5 --- /dev/null +++ b/test/Preprocessor/cxx_compl.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -DA=1 -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DA=0 -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -E %s | grep 'int a = 927 == 927' +#if compl 0 bitand A +#define X 37 +#else +#define X 927 +#endif + +#if ~0 & A +#define Y 37 +#else +#define Y 927 +#endif + +int a = X == Y; diff --git a/test/Preprocessor/cxx_not.cpp b/test/Preprocessor/cxx_not.cpp new file mode 100644 index 000000000000..dd3190117d92 --- /dev/null +++ b/test/Preprocessor/cxx_not.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -DA=1 -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -E %s | grep 'int a = 37 == 37' +#if not defined(A) +#define X 37 +#else +#define X 927 +#endif + +#if ! defined(A) +#define Y 37 +#else +#define Y 927 +#endif + +int a = X == Y; diff --git a/test/Preprocessor/cxx_not_eq.cpp b/test/Preprocessor/cxx_not_eq.cpp new file mode 100644 index 000000000000..4940f3b0a7bf --- /dev/null +++ b/test/Preprocessor/cxx_not_eq.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -DA=1 -DB=2 -E %s | grep 'int a = 37 == 37' +#if A not_eq B +#define X 37 +#else +#define X 927 +#endif + +#if A != B +#define Y 37 +#else +#define Y 927 +#endif + +int a = X == Y; diff --git a/test/Preprocessor/cxx_oper_keyword.cpp b/test/Preprocessor/cxx_oper_keyword.cpp new file mode 100644 index 000000000000..faae68741eed --- /dev/null +++ b/test/Preprocessor/cxx_oper_keyword.cpp @@ -0,0 +1,7 @@ +// RUN: not clang-cc %s -E && +// RUN: clang-cc %s -E -fno-operator-names + +// Not valid in C++ unless -fno-operator-names is passed. +#define and foo + + diff --git a/test/Preprocessor/cxx_oper_spelling.cpp b/test/Preprocessor/cxx_oper_spelling.cpp new file mode 100644 index 000000000000..85f0426ca3a9 --- /dev/null +++ b/test/Preprocessor/cxx_oper_spelling.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -E %s | grep 'a: "and"' + +#define X(A) #A + +// C++'03 2.5p2: "In all respects of the language, each alternative +// token behaves the same, respectively, as its primary token, +// except for its spelling" +// +// This should be spelled as 'and', not '&&' +a: X(and) + diff --git a/test/Preprocessor/cxx_or.cpp b/test/Preprocessor/cxx_or.cpp new file mode 100644 index 000000000000..133f28516b42 --- /dev/null +++ b/test/Preprocessor/cxx_or.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -DA -DB -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DA -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DB -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -E %s | grep 'int a = 927 == 927' +#if defined(A) or defined(B) +#define X 37 +#else +#define X 927 +#endif + +#if defined(A) || defined(B) +#define Y 37 +#else +#define Y 927 +#endif + +int a = X == Y; diff --git a/test/Preprocessor/cxx_true.cpp b/test/Preprocessor/cxx_true.cpp new file mode 100644 index 000000000000..e35c54d7b3fc --- /dev/null +++ b/test/Preprocessor/cxx_true.cpp @@ -0,0 +1,13 @@ +/* RUN: clang-cc -E %s -x=c++ | grep block_1 && + RUN: clang-cc -E %s -x=c++ | not grep block_2 && + RUN: clang-cc -E %s -x=c | not grep block +*/ + +#if true +block_1 +#endif + +#if false +block_2 +#endif + diff --git a/test/Preprocessor/cxx_xor.cpp b/test/Preprocessor/cxx_xor.cpp new file mode 100644 index 000000000000..a38c3c5454b9 --- /dev/null +++ b/test/Preprocessor/cxx_xor.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -DA=1 -DB=1 -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -DA=0 -DB=1 -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DA=1 -DB=0 -E %s | grep 'int a = 37 == 37' && +// RUN: clang-cc -DA=0 -DB=0 -E %s | grep 'int a = 927 == 927' && +// RUN: clang-cc -E %s | grep 'int a = 927 == 927' +#if A xor B +#define X 37 +#else +#define X 927 +#endif + +#if A ^ B +#define Y 37 +#else +#define Y 927 +#endif + +int a = X == Y; diff --git a/test/Preprocessor/dependencies-and-pp.c b/test/Preprocessor/dependencies-and-pp.c new file mode 100644 index 000000000000..1dc4d026b18d --- /dev/null +++ b/test/Preprocessor/dependencies-and-pp.c @@ -0,0 +1,5 @@ +// RUN: clang -E -o %t.1 %s && +// RUN: clang -E -MD -MF %t.d -MT foo -o %t.2 %s && +// RUN: diff %t.1 %t.2 && +// RUN: grep "foo:" %t.d && +// RUN: grep "dependencies-and-pp.c" %t.d diff --git a/test/Preprocessor/disabled-cond-diags.c b/test/Preprocessor/disabled-cond-diags.c new file mode 100644 index 000000000000..eb7632f29b3f --- /dev/null +++ b/test/Preprocessor/disabled-cond-diags.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -E %s 2>&1 | not grep "warning\|error" + +#if 0 + +// Shouldn't get warnings here. +??( ??) + +// Should not get an error here. +` ` ` ` +#endif diff --git a/test/Preprocessor/dump-macros-spacing.c b/test/Preprocessor/dump-macros-spacing.c new file mode 100644 index 000000000000..335e37c97e0e --- /dev/null +++ b/test/Preprocessor/dump-macros-spacing.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -E -dD < %s | grep stdin | grep -v define +#define A A +/* 1 + * 2 + * 3 + * 4 + * 5 + * 6 + * 7 + * 8 + */ +#define B B + diff --git a/test/Preprocessor/dump-options.c b/test/Preprocessor/dump-options.c new file mode 100644 index 000000000000..6910e1a314e4 --- /dev/null +++ b/test/Preprocessor/dump-options.c @@ -0,0 +1,3 @@ +// RUN: clang %s -E -dD | grep __INTMAX_MAX__ && +// RUN: clang %s -E -dM | grep __INTMAX_MAX__ + diff --git a/test/Preprocessor/dump_macros.c b/test/Preprocessor/dump_macros.c new file mode 100644 index 000000000000..d3e06b2bfac7 --- /dev/null +++ b/test/Preprocessor/dump_macros.c @@ -0,0 +1,31 @@ +// RUN: clang-cc -E -dM %s -o %t && + +// Space even without expansion tokens +// RUN: grep "#define A(x) " %t && +#define A(x) + +// Space before expansion list. +// RUN: grep "#define B(x,y) x y" %t && +#define B(x,y)x y + +// No space in expansion list. +// RUN: grep "#define C(x,y) x y" %t && +#define C(x, y) x y + +// No paste avoidance. +// RUN: grep "#define X() .." %t && +#define X() .. + +// Simple test. +// RUN: grep "#define Y ." %t && +// RUN: grep "#define Z X()Y" %t && +#define Y . +#define Z X()Y + +// gcc prints macros at end of translation unit, so last one wins. +// RUN: grep "#define foo 2" %t && +// RUN: not grep "#define foo 1" %t +#define foo 1 +#undef foo +#define foo 2 + diff --git a/test/Preprocessor/dumptokens_phyloc.c b/test/Preprocessor/dumptokens_phyloc.c new file mode 100644 index 000000000000..c0e78c9b155d --- /dev/null +++ b/test/Preprocessor/dumptokens_phyloc.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -dump-tokens %s 2>&1 | grep "Spelling=.*dumptokens_phyloc.c:3:20" + +#define TESTPHYLOC 10 + +TESTPHYLOC diff --git a/test/Preprocessor/expr_comma.c b/test/Preprocessor/expr_comma.c new file mode 100644 index 000000000000..0a24baca46c9 --- /dev/null +++ b/test/Preprocessor/expr_comma.c @@ -0,0 +1,10 @@ +// Comma is not allowed in C89 +// RUN: not clang-cc -E %s -std=c89 -pedantic-errors && + +// Comma is allowed if unevaluated in C99 +// RUN: clang-cc -E %s -std=c99 -pedantic-errors + +// PR2279 + +#if 0? 1,2:3 +#endif diff --git a/test/Preprocessor/expr_invalid_tok.c b/test/Preprocessor/expr_invalid_tok.c new file mode 100644 index 000000000000..5e750a462be0 --- /dev/null +++ b/test/Preprocessor/expr_invalid_tok.c @@ -0,0 +1,15 @@ +// RUN: not clang-cc -E %s 2>&1 | grep 'invalid token at start of a preprocessor expression' && +// RUN: not clang-cc -E %s 2>&1 | grep 'token is not a valid binary operator in a preprocessor subexpression' && +// RUN: not clang-cc -E %s 2>&1 | grep ':14: error: expected end of line in preprocessor expression' +// PR2220 + +#if 1 * * 2 +#endif + +#if 4 [ 2 +#endif + + +// PR2284 - The constant-expr production does not including comma. +#if 1 ? 2 : 0, 1 +#endif diff --git a/test/Preprocessor/expr_liveness.c b/test/Preprocessor/expr_liveness.c new file mode 100644 index 000000000000..3d1e25edd4e6 --- /dev/null +++ b/test/Preprocessor/expr_liveness.c @@ -0,0 +1,52 @@ +/* RUN: clang-cc -E %s -DNO_ERRORS -Werror -Wundef && + RUN: not clang-cc -E %s + */ + +#ifdef NO_ERRORS +/* None of these divisions by zero are in live parts of the expression, do not + emit any diagnostics. */ + +#define MACRO_0 0 +#define MACRO_1 1 + +#if MACRO_0 && 10 / MACRO_0 +foo +#endif + +#if MACRO_1 || 10 / MACRO_0 +bar +#endif + +#if 0 ? 124/0 : 42 +#endif + +// PR2279 +#if 0 ? 1/0: 2 +#else +#error +#endif + +// PR2279 +#if 1 ? 2 ? 3 : 4 : 5 +#endif + +// PR2284 +#if 1 ? 0: 1 ? 1/0: 1/0 +#endif + +#else + + +/* The 1/0 is live, it should error out. */ +#if 0 && 1 ? 4 : 1 / 0 +baz +#endif + + +#endif + +// rdar://6505352 +// -Wundef should not warn about use of undefined identifier if not live. +#if (!defined(XXX) || XXX > 42) +#endif + diff --git a/test/Preprocessor/expr_multichar.c b/test/Preprocessor/expr_multichar.c new file mode 100644 index 000000000000..4df8f3d4f9ea --- /dev/null +++ b/test/Preprocessor/expr_multichar.c @@ -0,0 +1,5 @@ +// RUN: clang-cc < %s -E -verify -triple i686-pc-linux-gnu + +#if (('1234' >> 24) != '1') +#error Bad multichar constant calculation! +#endif diff --git a/test/Preprocessor/expr_usual_conversions.c b/test/Preprocessor/expr_usual_conversions.c new file mode 100644 index 000000000000..47aca7beca6f --- /dev/null +++ b/test/Preprocessor/expr_usual_conversions.c @@ -0,0 +1,13 @@ +// RUN: clang-cc %s -E 2>&1 | grep warning | wc -l | grep 2 + +#define INTMAX_MIN (-9223372036854775807LL -1) + +#if (-42 + 0U) / -2 +foo +#endif + +// Shifts don't want the usual conversions: PR2279 +#if (2 << 1U) - 30 >= 0 +#error +#endif + diff --git a/test/Preprocessor/extension-warning.c b/test/Preprocessor/extension-warning.c new file mode 100644 index 000000000000..7b5095f6e923 --- /dev/null +++ b/test/Preprocessor/extension-warning.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +// The preprocessor shouldn't warn about extensions within macro bodies that +// aren't expanded. +#define TY typeof +#define TY1 typeof(1) + +// But we should warn here +TY1 x; // expected-warning {{extension}} +TY(1) x; // FIXME: And we should warn here + +// Note: this warning intentionally doesn't trigger on keywords like +// __attribute; the standard allows implementation-defined extensions +// prefixed with "__". +// Current list of keywords this can trigger on: +// inline, restrict, asm, typeof, _asm + +void whatever() {} diff --git a/test/Preprocessor/file_to_include.h b/test/Preprocessor/file_to_include.h new file mode 100644 index 000000000000..97728ab0830b --- /dev/null +++ b/test/Preprocessor/file_to_include.h @@ -0,0 +1,3 @@ + +#warning file successfully included + diff --git a/test/Preprocessor/function_macro_file.c b/test/Preprocessor/function_macro_file.c new file mode 100644 index 000000000000..6a266dd0790a --- /dev/null +++ b/test/Preprocessor/function_macro_file.c @@ -0,0 +1,5 @@ +/* RUN: clang-cc -E -P %s | grep f + */ + +#include "function_macro_file.h" +() diff --git a/test/Preprocessor/function_macro_file.h b/test/Preprocessor/function_macro_file.h new file mode 100644 index 000000000000..43d1199bfebb --- /dev/null +++ b/test/Preprocessor/function_macro_file.h @@ -0,0 +1,3 @@ + +#define f() x +f diff --git a/test/Preprocessor/hash_line.c b/test/Preprocessor/hash_line.c new file mode 100644 index 000000000000..7ed65d1b424d --- /dev/null +++ b/test/Preprocessor/hash_line.c @@ -0,0 +1,8 @@ +// The 1 and # should not go on the same line. +// RUN: clang-cc %s -E | not grep "1 #" && +// RUN: clang-cc %s -E | grep '^1$' && +// RUN: clang-cc %s -E | grep '^ #$' +1 +#define EMPTY +EMPTY # + diff --git a/test/Preprocessor/hash_space.c b/test/Preprocessor/hash_space.c new file mode 100644 index 000000000000..e7dbd3bc617b --- /dev/null +++ b/test/Preprocessor/hash_space.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -E | grep " #" + +// Should put a space before the # so that -fpreprocessed mode doesn't +// macro expand this again. +#define HASH # +HASH define foo bar diff --git a/test/Preprocessor/header_lookup1.c b/test/Preprocessor/header_lookup1.c new file mode 100644 index 000000000000..df58a6ea9c54 --- /dev/null +++ b/test/Preprocessor/header_lookup1.c @@ -0,0 +1,2 @@ +// RUN: clang-cc -I /usr/include %s -E | grep 'stdio.h.*3.*4' +#include <stdio.h> diff --git a/test/Preprocessor/if_warning.c b/test/Preprocessor/if_warning.c new file mode 100644 index 000000000000..5567513c3630 --- /dev/null +++ b/test/Preprocessor/if_warning.c @@ -0,0 +1,21 @@ +// RUN: clang-cc %s -Eonly -Werror=undef -verify && +// RUN: clang-cc %s -Eonly -Werror-undef -verify + +extern int x; + +#if foo // expected-error {{'foo' is not defined, evaluates to 0}} +#endif + +#ifdef foo +#endif + +#if defined(foo) +#endif + + +// PR3938 +#if 0 +#ifdef D +#else 1 // Should not warn due to C99 6.10p4 +#endif +#endif diff --git a/test/Preprocessor/ifdef-recover.c b/test/Preprocessor/ifdef-recover.c new file mode 100644 index 000000000000..3fffcc0290de --- /dev/null +++ b/test/Preprocessor/ifdef-recover.c @@ -0,0 +1,15 @@ +/* RUN: clang-cc -E %s 2>&1 >/dev/null | grep error: | count 3 + */ + +#ifdef + +#endif + +/* End of function-like macro invocation in #ifdef */ +/* PR1936 */ +#define f(x) x +#if f(2 +#endif + +int x; + diff --git a/test/Preprocessor/import_self.c b/test/Preprocessor/import_self.c new file mode 100644 index 000000000000..2cabe3d71ca6 --- /dev/null +++ b/test/Preprocessor/import_self.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -E -I. %s | grep BODY_OF_FILE | wc -l | grep 1 + +// This #import should have no effect, as we're importing the current file. +#import <import_self.c> + +BODY_OF_FILE + diff --git a/test/Preprocessor/include-directive1.c b/test/Preprocessor/include-directive1.c new file mode 100644 index 000000000000..66f70fb3a9e5 --- /dev/null +++ b/test/Preprocessor/include-directive1.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -E %s -fno-caret-diagnostics 2>&1 >/dev/null | grep 'file successfully included' | count 3 + +// XX expands to nothing. +#define XX + +// expand macros to get to file to include +#define FILE "file_to_include.h" +#include XX FILE + +#include FILE + +// normal include +#include "file_to_include.h" + diff --git a/test/Preprocessor/include-directive2.c b/test/Preprocessor/include-directive2.c new file mode 100644 index 000000000000..123998246bff --- /dev/null +++ b/test/Preprocessor/include-directive2.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -Eonly -verify %s +# define HEADER <float.h> + +# include HEADER + +#include <limits.h> NON_EMPTY // expected-warning {{extra tokens at end of #include directive}} + +// PR3916: these are ok. +#define EMPTY +#include <limits.h> EMPTY +#include HEADER EMPTY + +// PR3916 +#define FN limits.h> +#include <FN + +#include <> // expected-error {{empty filename}} diff --git a/test/Preprocessor/include-directive3.c b/test/Preprocessor/include-directive3.c new file mode 100644 index 000000000000..e5b7a940c6cb --- /dev/null +++ b/test/Preprocessor/include-directive3.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -include %S/file_to_include.h -E %s -fno-caret-diagnostics 2>&1 >/dev/null | grep 'file successfully included' | count 1 +// PR3464 + diff --git a/test/Preprocessor/include-macros.c b/test/Preprocessor/include-macros.c new file mode 100644 index 000000000000..d64ee5e3e6d9 --- /dev/null +++ b/test/Preprocessor/include-macros.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -E -Dtest=FOO -imacros %S/pr2086.h %s | grep 'HERE: test' + +// This should not be expanded into FOO because pr2086.h undefs 'test'. +HERE: test diff --git a/test/Preprocessor/include-pth.c b/test/Preprocessor/include-pth.c new file mode 100644 index 000000000000..2afc66a55b0b --- /dev/null +++ b/test/Preprocessor/include-pth.c @@ -0,0 +1,3 @@ +// RUN: clang-cc -emit-pth %s -o %t && +// RUN: clang-cc -include-pth %t %s -E | grep 'file_to_include' | count 2 +#include "file_to_include.h" diff --git a/test/Preprocessor/indent_macro.c b/test/Preprocessor/indent_macro.c new file mode 100644 index 000000000000..f6b411e93ff0 --- /dev/null +++ b/test/Preprocessor/indent_macro.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -E %s | grep '^ zzap$' + +// zzap is on a new line, should be indented. +#define BLAH zzap + BLAH + diff --git a/test/Preprocessor/line-directive.c b/test/Preprocessor/line-directive.c new file mode 100644 index 000000000000..ed9a6c40e5d7 --- /dev/null +++ b/test/Preprocessor/line-directive.c @@ -0,0 +1,92 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s && +// RUN: clang-cc -E %s 2>&1 | grep 'blonk.c:92:2: error: #error ABC' && +// RUN: clang-cc -E %s 2>&1 | grep 'blonk.c:93:2: error: #error DEF' + +#line 'a' // expected-error {{#line directive requires a positive integer argument}} +#line 0 // expected-error {{#line directive requires a positive integer argument}} +#line 00 // expected-error {{#line directive requires a positive integer argument}} +#line 2147483648 // expected-warning {{C requires #line number to be less than 2147483648, allowed as extension}} +#line 42 // ok +#line 42 'a' // expected-error {{invalid filename for #line directive}} +#line 42 "foo/bar/baz.h" // ok + + +// #line directives expand macros. +#define A 42 "foo" +#line A + +# 42 +# 42 "foo" +# 42 "foo" 2 // expected-error {{invalid line marker flag '2': cannot pop empty include stack}} +# 42 "foo" 1 3 // enter +# 42 "foo" 2 3 // exit +# 42 "foo" 2 3 4 // expected-error {{invalid line marker flag '2': cannot pop empty include stack}} +# 42 "foo" 3 4 + +# 'a' // expected-error {{invalid preprocessing directive}} +# 42 'f' // expected-error {{invalid filename for line marker directive}} +# 42 1 3 // expected-error {{invalid filename for line marker directive}} +# 42 "foo" 3 1 // expected-error {{invalid flag line marker directive}} +# 42 "foo" 42 // expected-error {{invalid flag line marker directive}} +# 42 "foo" 1 2 // expected-error {{invalid flag line marker directive}} + + +// These are checked by the RUN line. +#line 92 "blonk.c" +#error ABC // expected-error {{#error ABC}} +#error DEF // expected-error {{#error DEF}} + + +// Verify that linemarker diddling of the system header flag works. + +# 192 "glomp.h" // not a system header. +typedef int x; // expected-note {{previous definition is here}} +typedef int x; // expected-error {{redefinition of typedef 'x' is invalid in C}} + +# 192 "glomp.h" 3 // System header. +typedef int y; // ok +typedef int y; // ok + +typedef int q; // q is in system header. + +#line 42 "blonk.h" // doesn't change system headerness. + +typedef int z; // ok +typedef int z; // ok + +# 97 // doesn't change system headerness. + +typedef int z1; // ok +typedef int z1; // ok + +# 42 "blonk.h" // DOES change system headerness. + +typedef int w; // expected-note {{previous definition is here}} +typedef int w; // expected-error {{redefinition of typedef 'w' is invalid in C}} + +typedef int q; // original definition in system header, should not diagnose. + +// This should not produce an "extra tokens at end of #line directive" warning, +// because #line is allowed to contain expanded tokens. +#define EMPTY() +#line 2 "foo.c" EMPTY( ) +#line 2 "foo.c" NONEMPTY( ) // expected-warning{{extra tokens at end of #line directive}} + +// PR3940 +#line 0xf // expected-error {{#line directive requires a simple digit sequence}} +#line 42U // expected-error {{#line directive requires a simple digit sequence}} + + +// Line markers are digit strings interpreted as decimal numbers, this is +// 10, not 8. +#line 010 // expected-warning {{#line directive interprets number as decimal, not octal}} +extern int array[__LINE__ == 10 ? 1:-1]; + +/* PR3917 */ +#line 41 +extern char array2[\ +_\ +_LINE__ == 42 ? 1: -1]; /* line marker is location of first _ */ + + + diff --git a/test/Preprocessor/macro-multiline.c b/test/Preprocessor/macro-multiline.c new file mode 100644 index 000000000000..eb15668ce31f --- /dev/null +++ b/test/Preprocessor/macro-multiline.c @@ -0,0 +1,8 @@ +// RUN: clang -E %s "-DX=A +// RUN: THIS_SHOULD_NOT_EXIST_IN_THE_OUTPUT" > %t && +// RUN: grep "GOOD: A" %t && +// RUN: not grep THIS_SHOULD_NOT_EXIST_IN_THE_OUTPUT %t +// rdar://6762183 + +GOOD: X + diff --git a/test/Preprocessor/macro_arg_keyword.c b/test/Preprocessor/macro_arg_keyword.c new file mode 100644 index 000000000000..92b1ae535713 --- /dev/null +++ b/test/Preprocessor/macro_arg_keyword.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -E %s | grep xxx-xxx + +#define foo(return) return-return + +foo(xxx) + diff --git a/test/Preprocessor/macro_disable.c b/test/Preprocessor/macro_disable.c new file mode 100644 index 000000000000..ff861d262197 --- /dev/null +++ b/test/Preprocessor/macro_disable.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -E %s | grep 'a: 2 + M_0(3)(4)(5);' && +// RUN: clang-cc -E %s | grep 'b: 4 + 4 + 3 + 2 + 1 + M_0(3)(2)(1);' + +#define M_0(x) M_ ## x +#define M_1(x) x + M_0(0) +#define M_2(x) x + M_1(1) +#define M_3(x) x + M_2(2) +#define M_4(x) x + M_3(3) +#define M_5(x) x + M_4(4) + +a: M_0(1)(2)(3)(4)(5); +b: M_0(5)(4)(3)(2)(1); + diff --git a/test/Preprocessor/macro_disable2.c b/test/Preprocessor/macro_disable2.c new file mode 100644 index 000000000000..286539e96f43 --- /dev/null +++ b/test/Preprocessor/macro_disable2.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -E %s | grep 'A B C A B A C A B C A' + +#define A A B C +#define B B C A +#define C C A B + +A + diff --git a/test/Preprocessor/macro_disable3.c b/test/Preprocessor/macro_disable3.c new file mode 100644 index 000000000000..011de3beed3d --- /dev/null +++ b/test/Preprocessor/macro_disable3.c @@ -0,0 +1,8 @@ +// RUN: clang-cc %s -E | grep -F 'f(2 * (f(2 * (z[0]))));' +// Check for C99 6.10.3.4p2. + +#define f(a) f(x * (a)) +#define x 2 +#define z z[0] +f(f(z)); + diff --git a/test/Preprocessor/macro_disable4.c b/test/Preprocessor/macro_disable4.c new file mode 100644 index 000000000000..b652b988d020 --- /dev/null +++ b/test/Preprocessor/macro_disable4.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -P -E %s | grep 'int f(void)' +// PR1820 + +#define f(x) h(x +#define h(x) x(void) +extern int f(f)); diff --git a/test/Preprocessor/macro_expand.c b/test/Preprocessor/macro_expand.c new file mode 100644 index 000000000000..74b3922d1e13 --- /dev/null +++ b/test/Preprocessor/macro_expand.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -E %s | grep '^A: Y$' && +// RUN: clang-cc -E %s | grep '^B: f()$' && +// RUN: clang-cc -E %s | grep '^C: for()$' + +#define X() Y +#define Y() X + +A: X()()() + +// PR3927 +#define f(x) h(x +#define for(x) h(x +#define h(x) x() +B: f(f)) +C: for(for)) + +// rdar://6880648 +#define f(x,y...) y +f() diff --git a/test/Preprocessor/macro_expandloc.c b/test/Preprocessor/macro_expandloc.c new file mode 100644 index 000000000000..ce1efd20a277 --- /dev/null +++ b/test/Preprocessor/macro_expandloc.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -E 2>&1 | grep '#include' +#define FOO 1 + +// The error message should be on the #include line, not the 1. +#include FOO + diff --git a/test/Preprocessor/macro_expandloc2.c b/test/Preprocessor/macro_expandloc2.c new file mode 100644 index 000000000000..9adf3fd911f9 --- /dev/null +++ b/test/Preprocessor/macro_expandloc2.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -E 2>&1 | grep '#include' +#define FOO BAR + +// The error message should be on the #include line, not the 1. +#include FOO + diff --git a/test/Preprocessor/macro_fn.c b/test/Preprocessor/macro_fn.c new file mode 100644 index 000000000000..5c55c0ceed5f --- /dev/null +++ b/test/Preprocessor/macro_fn.c @@ -0,0 +1,46 @@ +/* RUN: clang-cc %s -Eonly -std=c89 -pedantic -verify +*/ +/* PR3937 */ +#define zero() 0 +#define one(x) 0 +#define two(x, y) 0 +#define zero_dot(...) 0 /* expected-warning {{variadic macros were introduced in C99}} */ +#define one_dot(x, ...) 0 /* expected-warning {{variadic macros were introduced in C99}} */ + +zero() +zero(1); /* expected-error {{too many arguments provided to function-like macro invocation}} */ +zero(1, 2, 3); /* expected-error {{too many arguments provided to function-like macro invocation}} */ + +one() /* ok */ +one(a) +one(a,) /* expected-error {{too many arguments provided to function-like macro invocation}} */ +one(a, b) /* expected-error {{too many arguments provided to function-like macro invocation}} */ + +two() /* expected-error {{too few arguments provided to function-like macro invocation}} */ +two(a) /* expected-error {{too few arguments provided to function-like macro invocation}} */ +two(a,b) +two(a, ) /* expected-warning {{empty macro arguments were standardized in C99}} */ +two(a,b,c) /* expected-error {{too many arguments provided to function-like macro invocation}} */ +two( + , /* expected-warning {{empty macro arguments were standardized in C99}} */ + , /* expected-warning {{empty macro arguments were standardized in C99}} \ + expected-error {{too many arguments provided to function-like macro invocation}} */ + ) +two(,) /* expected-warning 2 {{empty macro arguments were standardized in C99}} */ + + + +/* PR4006 & rdar://6807000 */ +#define e(...) __VA_ARGS__ /* expected-warning {{variadic macros were introduced in C99}} */ +e(x) +e() + +zero_dot() +one_dot(x) /* empty ... argument: expected-warning {{varargs argument missing, but tolerated as an extension}} */ +one_dot() /* empty first argument, elided ...: expected-warning {{varargs argument missing, but tolerated as an extension}} */ + + +/* rdar://6816766 - Crash with function-like macro test at end of directive. */ +#define E() (i == 0) +#if E +#endif diff --git a/test/Preprocessor/macro_fn_comma_swallow.c b/test/Preprocessor/macro_fn_comma_swallow.c new file mode 100644 index 000000000000..e985138a5c44 --- /dev/null +++ b/test/Preprocessor/macro_fn_comma_swallow.c @@ -0,0 +1,21 @@ +// Test the GNU comma swallowing extension. +// RUN: clang-cc %s -E | grep 'foo{A, }' && +// RUN: clang-cc %s -E | grep 'fo2{A,}' && +// RUN: clang-cc %s -E | grep '{foo}' + +#define X(Y) foo{A, Y} +X() + +#define X2(Y) fo2{A,##Y} +X2() + +// should eat the comma. +#define X3(b, ...) {b, ## __VA_ARGS__} +X3(foo) + + + +// RUN: clang-cc %s -E | grep 'AA BB' +// PR3880 +#define X4(...) AA , ## __VA_ARGS__ BB +X4() diff --git a/test/Preprocessor/macro_fn_disable_expand.c b/test/Preprocessor/macro_fn_disable_expand.c new file mode 100644 index 000000000000..d99c01832eac --- /dev/null +++ b/test/Preprocessor/macro_fn_disable_expand.c @@ -0,0 +1,11 @@ +// RUN: clang-cc %s -E | grep 'bar foo (2)' && +// RUN: clang-cc %s -E | grep 'm(ABCD)' + +#define foo(x) bar x +foo(foo) (2) + + +#define m(a) a(w) +#define w ABCD +m(m) // m(ABCD) + diff --git a/test/Preprocessor/macro_fn_lparen_scan.c b/test/Preprocessor/macro_fn_lparen_scan.c new file mode 100644 index 000000000000..1056fd82341a --- /dev/null +++ b/test/Preprocessor/macro_fn_lparen_scan.c @@ -0,0 +1,27 @@ +// RUN: clang-cc -E %s | grep 'noexp: foo y' && +// RUN: clang-cc -E %s | grep 'expand: abc' && +// RUN: clang-cc -E %s | grep 'noexp2: foo nonexp' && +// RUN: clang-cc -E %s | grep 'expand2: abc' + +#define A foo +#define foo() abc +#define X A y + +// This should not expand to abc, because the foo macro isn't followed by (. +noexp: X + + +// This should expand to abc. +#undef X +#define X A () +expand: X + + +// This should be 'foo nonexp' +noexp2: A nonexp + +// This should expand +expand2: A ( +) + + diff --git a/test/Preprocessor/macro_fn_lparen_scan2.c b/test/Preprocessor/macro_fn_lparen_scan2.c new file mode 100644 index 000000000000..fb64befaf1e9 --- /dev/null +++ b/test/Preprocessor/macro_fn_lparen_scan2.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -E %s | grep 'FUNC (3 +1);' + +#define F(a) a +#define FUNC(a) (a+1) + +F(FUNC) FUNC (3); /* final token sequence is FUNC(3+1) */ + diff --git a/test/Preprocessor/macro_fn_placemarker.c b/test/Preprocessor/macro_fn_placemarker.c new file mode 100644 index 000000000000..ff688ce2d7ae --- /dev/null +++ b/test/Preprocessor/macro_fn_placemarker.c @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -E | grep 'foo(A, )' + +#define X(Y) foo(A, Y) +X() + diff --git a/test/Preprocessor/macro_fn_preexpand.c b/test/Preprocessor/macro_fn_preexpand.c new file mode 100644 index 000000000000..a392263aef43 --- /dev/null +++ b/test/Preprocessor/macro_fn_preexpand.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -E | grep 'pre: 1 1 X' && +// RUN: clang-cc %s -E | grep 'nopre: 1A(X)' + +/* Preexpansion of argument. */ +#define A(X) 1 X +pre: A(A(X)) + +/* The ## operator disables preexpansion. */ +#undef A +#define A(X) 1 ## X +nopre: A(A(X)) + diff --git a/test/Preprocessor/macro_fn_varargs_iso.c b/test/Preprocessor/macro_fn_varargs_iso.c new file mode 100644 index 000000000000..78ad212405cf --- /dev/null +++ b/test/Preprocessor/macro_fn_varargs_iso.c @@ -0,0 +1,11 @@ + +// RUN: clang-cc -E %s | grep 'foo{a, b, c, d, e}' && +// RUN: clang-cc -E %s | grep 'foo2{d, C, B}' && +// RUN: clang-cc -E %s | grep 'foo2{d,e, C, B}' + +#define va1(...) foo{a, __VA_ARGS__, e} +va1(b, c, d) +#define va2(a, b, ...) foo2{__VA_ARGS__, b, a} +va2(B, C, d) +va2(B, C, d,e) + diff --git a/test/Preprocessor/macro_fn_varargs_named.c b/test/Preprocessor/macro_fn_varargs_named.c new file mode 100644 index 000000000000..c2841b1574b1 --- /dev/null +++ b/test/Preprocessor/macro_fn_varargs_named.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -E %s | grep '^a: x$' && +// RUN: clang-cc -E %s | grep '^b: x y, z,h$' && +// RUN: clang-cc -E %s | grep '^c: foo(x)$' + +#define A(b, c...) b c +a: A(x) +b: A(x, y, z,h) + +#define B(b, c...) foo(b, ## c) +c: B(x) diff --git a/test/Preprocessor/macro_misc.c b/test/Preprocessor/macro_misc.c new file mode 100644 index 000000000000..169c5ec772a2 --- /dev/null +++ b/test/Preprocessor/macro_misc.c @@ -0,0 +1,23 @@ +// RUN: clang-cc %s -Eonly -verify + +// This should not be rejected. +#ifdef defined +#endif + + + +// PR3764 + +// This should not produce a redefinition warning. +#define FUNC_LIKE(a) (a) +#define FUNC_LIKE(a)(a) + +// This either. +#define FUNC_LIKE2(a)\ +(a) +#define FUNC_LIKE2(a) (a) + +// This should. +#define FUNC_LIKE3(a) ( a) // expected-note {{previous definition is here}} +#define FUNC_LIKE3(a) (a) // expected-warning {{'FUNC_LIKE3' macro redefined}} + diff --git a/test/Preprocessor/macro_not_define.c b/test/Preprocessor/macro_not_define.c new file mode 100644 index 000000000000..a42240bab607 --- /dev/null +++ b/test/Preprocessor/macro_not_define.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -E %s | grep '^ # define X 3$' + +#define H # + #define D define + + #define DEFINE(a, b) H D a b + + DEFINE(X, 3) + diff --git a/test/Preprocessor/macro_paste_bad.c b/test/Preprocessor/macro_paste_bad.c new file mode 100644 index 000000000000..1212c44c1aa7 --- /dev/null +++ b/test/Preprocessor/macro_paste_bad.c @@ -0,0 +1,35 @@ +// RUN: clang-cc -Eonly -verify -pedantic %s +// pasting ""x"" and ""+"" does not give a valid preprocessing token +#define XYZ x ## + +XYZ // expected-error {{pasting formed 'x+', an invalid preprocessing token}} +#define XXYZ . ## test +XXYZ // expected-error {{pasting formed '.test', an invalid preprocessing token}} + +// GCC PR 20077 + +#define a a ## ## // expected-error {{'##' cannot appear at end of macro expansion}} +#define b() b ## ## // expected-error {{'##' cannot appear at end of macro expansion}} +#define c c ## // expected-error {{'##' cannot appear at end of macro expansion}} +#define d() d ## // expected-error {{'##' cannot appear at end of macro expansion}} + + +#define e ## ## e // expected-error {{'##' cannot appear at start of macro expansion}} +#define f() ## ## f // expected-error {{'##' cannot appear at start of macro expansion}} +#define g ## g // expected-error {{'##' cannot appear at start of macro expansion}} +#define h() ## h // expected-error {{'##' cannot appear at start of macro expansion}} +#define i ## // expected-error {{'##' cannot appear at start of macro expansion}} +#define j() ## // expected-error {{'##' cannot appear at start of macro expansion}} + +// Invalid token pasting. +// PR3918 + +// When pasting creates poisoned identifiers, we error. +#pragma GCC poison BLARG +BLARG // expected-error {{attempt to use a poisoned identifier}} +#define XX BL ## ARG +XX // expected-error {{attempt to use a poisoned identifier}} + +#define VA __VA_ ## ARGS__ +int VA; // expected-warning {{__VA_ARGS__ can only appear in the expansion of a C99 variadic macro}} + + diff --git a/test/Preprocessor/macro_paste_bcpl_comment.c b/test/Preprocessor/macro_paste_bcpl_comment.c new file mode 100644 index 000000000000..8bbee5dc2dd9 --- /dev/null +++ b/test/Preprocessor/macro_paste_bcpl_comment.c @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -Eonly 2>&1 | grep error + +#define COMM1 / ## / +COMM1 + diff --git a/test/Preprocessor/macro_paste_c_block_comment.c b/test/Preprocessor/macro_paste_c_block_comment.c new file mode 100644 index 000000000000..86f812421d8c --- /dev/null +++ b/test/Preprocessor/macro_paste_c_block_comment.c @@ -0,0 +1,7 @@ +// RUN: clang-cc %s -Eonly 2>&1 | grep error && +// RUN: clang-cc %s -Eonly 2>&1 | not grep unterminated && +// RUN: clang-cc %s -Eonly 2>&1 | not grep scratch + +#define COMM / ## * +COMM + diff --git a/test/Preprocessor/macro_paste_commaext.c b/test/Preprocessor/macro_paste_commaext.c new file mode 100644 index 000000000000..e98849b15afc --- /dev/null +++ b/test/Preprocessor/macro_paste_commaext.c @@ -0,0 +1,13 @@ +// RUN: clang-cc %s -E | grep 'V);' && +// RUN: clang-cc %s -E | grep 'W, 1, 2);' && +// RUN: clang-cc %s -E | grep 'X, 1, 2);' && +// RUN: clang-cc %s -E | grep 'Y, );' && +// RUN: clang-cc %s -E | grep 'Z, );' + +#define debug(format, ...) format, ## __VA_ARGS__) +debug(V); +debug(W, 1, 2); +debug(X, 1, 2 ); +debug(Y, ); +debug(Z,); + diff --git a/test/Preprocessor/macro_paste_empty.c b/test/Preprocessor/macro_paste_empty.c new file mode 100644 index 000000000000..75504bc22a78 --- /dev/null +++ b/test/Preprocessor/macro_paste_empty.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -E %s | grep 'a:Y' && +// RUN: clang-cc -E %s | grep 'b:Y' && +// RUN: clang-cc -E %s | grep 'c:YY' + +#define FOO(X) X ## Y +a:FOO() + +#define FOO2(X) Y ## X +b:FOO2() + +#define FOO3(X) X ## Y ## X ## Y ## X ## X +c:FOO3() + diff --git a/test/Preprocessor/macro_paste_hard.c b/test/Preprocessor/macro_paste_hard.c new file mode 100644 index 000000000000..25b6c1994b5c --- /dev/null +++ b/test/Preprocessor/macro_paste_hard.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -E %s | grep '1: aaab 2' && +// RUN: clang-cc -E %s | grep '2: 2 baaa' && +// RUN: clang-cc -E %s | grep '3: 2 xx' + +#define a(n) aaa ## n +#define b 2 +1: a(b b) // aaab 2 2 gets expanded, not b. + +#undef a +#undef b +#define a(n) n ## aaa +#define b 2 +2: a(b b) // 2 baaa 2 gets expanded, not b. + +#define baaa xx +3: a(b b) // 2 xx + diff --git a/test/Preprocessor/macro_paste_hashhash.c b/test/Preprocessor/macro_paste_hashhash.c new file mode 100644 index 000000000000..42654fd1b18b --- /dev/null +++ b/test/Preprocessor/macro_paste_hashhash.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -E %s | grep '^"x ## y";$' +#define hash_hash # ## # +#define mkstr(a) # a +#define in_between(a) mkstr(a) +#define join(c, d) in_between(c hash_hash d) +join(x, y); + diff --git a/test/Preprocessor/macro_paste_mscomment.c b/test/Preprocessor/macro_paste_mscomment.c new file mode 100644 index 000000000000..b0fc57101c64 --- /dev/null +++ b/test/Preprocessor/macro_paste_mscomment.c @@ -0,0 +1,20 @@ +// RUN: clang-cc -P -E -fms-extensions %s | sed '/^#.\+/d' | tr -d '\n' | +// RUN: grep '^int foo;int bar;int baz;$' | count 1 +// This horrible stuff should preprocess into (other than whitespace): +// int foo; +// int bar; +// int baz; + +int foo; + +#define comment /##/ dead tokens live here +comment This is stupidity + +int bar; + +#define nested(x) int x comment cute little dead tokens... + +nested(baz) rise of the dead tokens + +; + diff --git a/test/Preprocessor/macro_paste_none.c b/test/Preprocessor/macro_paste_none.c new file mode 100644 index 000000000000..e978fca22508 --- /dev/null +++ b/test/Preprocessor/macro_paste_none.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -E %s | grep '!!' + +#define A(B,C) B ## C + +!A(,)! + diff --git a/test/Preprocessor/macro_paste_simple.c b/test/Preprocessor/macro_paste_simple.c new file mode 100644 index 000000000000..2affbac0dec3 --- /dev/null +++ b/test/Preprocessor/macro_paste_simple.c @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -E | grep "barbaz123" + +#define FOO bar ## baz ## 123 + +FOO diff --git a/test/Preprocessor/macro_paste_spacing.c b/test/Preprocessor/macro_paste_spacing.c new file mode 100644 index 000000000000..130548dbf99e --- /dev/null +++ b/test/Preprocessor/macro_paste_spacing.c @@ -0,0 +1,7 @@ +// RUN: clang-cc %s -E | grep "^xy$" + +#define A x ## y +blah + +A + diff --git a/test/Preprocessor/macro_paste_spacing2.c b/test/Preprocessor/macro_paste_spacing2.c new file mode 100644 index 000000000000..0db721aa7b41 --- /dev/null +++ b/test/Preprocessor/macro_paste_spacing2.c @@ -0,0 +1,6 @@ +// RUN: clang-cc %s -E | grep "movl %eax" +// PR4132 +#define R1E %eax +#define epilogue(r1) movl r1 ## E; +epilogue(R1) + diff --git a/test/Preprocessor/macro_rescan.c b/test/Preprocessor/macro_rescan.c new file mode 100644 index 000000000000..17b4dc2756fd --- /dev/null +++ b/test/Preprocessor/macro_rescan.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -E %s | grep 'ei_1 = (17 +1);' && +// RUN: clang-cc -E %s | grep 'ei_2 = (M1)(17);' + +#define M1(a) (a+1) +#define M2(b) b + +int ei_1 = M2(M1)(17); /* becomes int ei_1 = (17+1); */ +int ei_2 = (M2(M1))(17); /* becomes int ei_2 = (M1)(17); */ + diff --git a/test/Preprocessor/macro_rescan2.c b/test/Preprocessor/macro_rescan2.c new file mode 100644 index 000000000000..6914ae0ac5f3 --- /dev/null +++ b/test/Preprocessor/macro_rescan2.c @@ -0,0 +1,15 @@ +// RUN: clang-cc %s -E | grep 'a: 2\*f(9)' && +// RUN: clang-cc %s -E | grep 'b: 2\*9\*g' + +#define f(a) a*g +#define g f +a: f(2)(9) + +#undef f +#undef g + +#define f(a) a*g +#define g(a) f(a) + +b: f(2)(9) + diff --git a/test/Preprocessor/macro_rescan_varargs.c b/test/Preprocessor/macro_rescan_varargs.c new file mode 100644 index 000000000000..ed1056ab1b3f --- /dev/null +++ b/test/Preprocessor/macro_rescan_varargs.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -E %s | grep -F "1: F, (, 'a', 'b', );" && +// RUN: clang-cc -E %s | grep -F "2: 'a' + 'b';" +#define LPAREN ( +#define RPAREN ) +#define F(x, y) x + y +#define ELLIP_FUNC(...) __VA_ARGS__ + +1: ELLIP_FUNC(F, LPAREN, 'a', 'b', RPAREN); /* 1st invocation */ +2: ELLIP_FUNC(F LPAREN 'a', 'b' RPAREN); /* 2nd invocation */ + diff --git a/test/Preprocessor/macro_rparen_scan.c b/test/Preprocessor/macro_rparen_scan.c new file mode 100644 index 000000000000..927509883845 --- /dev/null +++ b/test/Preprocessor/macro_rparen_scan.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -E %s | grep '^3 ;$' + +/* Right paren scanning, hard case. Should expand to 3. */ +#define i(x) 3 +#define a i(yz +#define b ) +a b ) ; + diff --git a/test/Preprocessor/macro_rparen_scan2.c b/test/Preprocessor/macro_rparen_scan2.c new file mode 100644 index 000000000000..41748ac459b9 --- /dev/null +++ b/test/Preprocessor/macro_rparen_scan2.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -E %s | grep -F 'static int glob = (1 + 1 );' + +#define R_PAREN ) + +#define FUNC(a) a + +static int glob = (1 + FUNC(1 R_PAREN ); + diff --git a/test/Preprocessor/macro_space.c b/test/Preprocessor/macro_space.c new file mode 100644 index 000000000000..4fdbb0a0ceef --- /dev/null +++ b/test/Preprocessor/macro_space.c @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -E | grep '! ,' + +#define XX +! XX, + diff --git a/test/Preprocessor/mi_opt.c b/test/Preprocessor/mi_opt.c new file mode 100644 index 000000000000..aa69e2b4aeac --- /dev/null +++ b/test/Preprocessor/mi_opt.c @@ -0,0 +1,11 @@ +// RUN: not clang-cc -fsyntax-only %s +// PR1900 +// This test should get a redefinition error from m_iopt.h: the MI opt +// shouldn't apply. + +#define MACRO +#include "mi_opt.h" +#undef MACRO +#define MACRO || 1 +#include "mi_opt.h" + diff --git a/test/Preprocessor/mi_opt.h b/test/Preprocessor/mi_opt.h new file mode 100644 index 000000000000..a82aa6af0f9c --- /dev/null +++ b/test/Preprocessor/mi_opt.h @@ -0,0 +1,4 @@ +#if !defined foo MACRO +#define foo +int x = 2; +#endif diff --git a/test/Preprocessor/objc-pp.m b/test/Preprocessor/objc-pp.m new file mode 100644 index 000000000000..4ab2f07cef26 --- /dev/null +++ b/test/Preprocessor/objc-pp.m @@ -0,0 +1,4 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic + +#import <limits.h> // no warning on #import in objc mode. + diff --git a/test/Preprocessor/optimize.c b/test/Preprocessor/optimize.c new file mode 100644 index 000000000000..46df2a66b920 --- /dev/null +++ b/test/Preprocessor/optimize.c @@ -0,0 +1,29 @@ +// RUN: clang-cc -Eonly %s -DOPT_O2 -O2 -verify && +#ifdef OPT_O2 + #ifndef __OPTIMIZE__ + #error "__OPTIMIZE__ not defined" + #endif + #ifdef __OPTIMIZE_SIZE__ + #error "__OPTIMIZE_SIZE__ defined" + #endif +#endif + +// RUN: clang-cc -Eonly %s -DOPT_O0 -O0 -verify && +#ifdef OPT_O0 + #ifdef __OPTIMIZE__ + #error "__OPTIMIZE__ defined" + #endif + #ifdef __OPTIMIZE_SIZE__ + #error "__OPTIMIZE_SIZE__ defined" + #endif +#endif + +// RUN: clang-cc -Eonly %s -DOPT_OS -Os -verify +#ifdef OPT_OS + #ifndef __OPTIMIZE__ + #error "__OPTIMIZE__ not defined" + #endif + #ifdef __OPTIMIZE_SIZE__ + #error "__OPTIMIZE_SIZE__ not defined" + #endif +#endif diff --git a/test/Preprocessor/output_paste_avoid.c b/test/Preprocessor/output_paste_avoid.c new file mode 100644 index 000000000000..ff8afc3e47ac --- /dev/null +++ b/test/Preprocessor/output_paste_avoid.c @@ -0,0 +1,23 @@ +// RUN: clang-cc -E %s -o %t && +// This should print as ".. ." to avoid turning into ... +// RUN: grep -F 'A: . . .' %t && +#define y(a) ..a +A: y(.) + +// RUN: grep -F 'C: .. .' %t && +#define DOT . +C: ..DOT + + +// RUN: grep -F 'D: + + - - + + = = =' %t && +#define PLUS + +#define EMPTY +#define f(x) =x= +D: +PLUS -EMPTY- PLUS+ f(=) + +// RUN: grep -F 'E: L "str"' %t + +// Should expand to L "str" not L"str" +#define test(x) L#x +E: test(str) + diff --git a/test/Preprocessor/overflow.c b/test/Preprocessor/overflow.c new file mode 100644 index 000000000000..297a35e658fd --- /dev/null +++ b/test/Preprocessor/overflow.c @@ -0,0 +1,25 @@ +// RUN: clang-cc -Eonly %s -verify -triple i686-pc-linux-gnu + +// Multiply signed overflow +#if 0x7FFFFFFFFFFFFFFF*2 // expected-warning {{overflow}} +#endif + +// Multiply unsigned overflow +#if 0xFFFFFFFFFFFFFFFF*2 +#endif + +// Add signed overflow +#if 0x7FFFFFFFFFFFFFFF+1 // expected-warning {{overflow}} +#endif + +// Add unsigned overflow +#if 0xFFFFFFFFFFFFFFFF+1 +#endif + +// Subtract signed overflow +#if 0x7FFFFFFFFFFFFFFF- -1 // expected-warning {{overflow}} +#endif + +// Subtract unsigned overflow +#if 0xFFFFFFFFFFFFFFFF- -1 // expected-warning {{converted from negative value}} +#endif diff --git a/test/Preprocessor/pic.c b/test/Preprocessor/pic.c new file mode 100644 index 000000000000..1cddaa1a91e6 --- /dev/null +++ b/test/Preprocessor/pic.c @@ -0,0 +1,10 @@ +// RUN: clang -ccc-host-triple i386-unknown-unknown -static -dM -E -o %t %s && +// RUN: grep '#define __PIC__' %t | count 0 && +// RUN: grep '#define __pic__' %t | count 0 && +// RUN: clang -ccc-host-triple i386-unknown-unknown -fpic -dM -E -o %t %s && +// RUN: grep '#define __PIC__ 1' %t | count 1 && +// RUN: grep '#define __pic__ 1' %t | count 1 && +// RUN: clang -ccc-host-triple i386-unknown-unknown -fPIC -dM -E -o %t %s && +// RUN: grep '#define __PIC__ 2' %t | count 1 && +// RUN: grep '#define __pic__ 2' %t | count 1 && +// RUN: true diff --git a/test/Preprocessor/pr2086.c b/test/Preprocessor/pr2086.c new file mode 100644 index 000000000000..4df65a4f7c67 --- /dev/null +++ b/test/Preprocessor/pr2086.c @@ -0,0 +1,11 @@ +// RUN: clang-cc -E %s + +#define test +#include "pr2086.h" +#define test +#include "pr2086.h" + +#ifdef test +#error +#endif + diff --git a/test/Preprocessor/pr2086.h b/test/Preprocessor/pr2086.h new file mode 100644 index 000000000000..b98b996d6cca --- /dev/null +++ b/test/Preprocessor/pr2086.h @@ -0,0 +1,6 @@ +#ifndef test +#endif + +#ifdef test +#undef test +#endif diff --git a/test/Preprocessor/pragma_microsoft.c b/test/Preprocessor/pragma_microsoft.c new file mode 100644 index 000000000000..81e90e3de69f --- /dev/null +++ b/test/Preprocessor/pragma_microsoft.c @@ -0,0 +1,20 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fms-extensions + +// rdar://6495941 + +#define FOO 1 +#define BAR "2" + +#pragma comment(linker,"foo=" FOO) // expected-error {{pragma comment requires parenthesized identifier and optional string}} +#pragma comment(linker," bar=" BAR) + +#pragma comment( user, "Compiled on " __DATE__ " at " __TIME__ ) + +#pragma comment(foo) // expected-error {{unknown kind of pragma comment}} +#pragma comment(compiler,) // expected-error {{pragma comment requires}} +#define foo compiler +#pragma comment(foo) // macro expand kind. +#pragma comment(foo) x // expected-error {{pragma comment requires}} + +#pragma comment(user, "foo\abar\nbaz\tsome thing") + diff --git a/test/Preprocessor/pragma_poison.c b/test/Preprocessor/pragma_poison.c new file mode 100644 index 000000000000..d91feb7ff2de --- /dev/null +++ b/test/Preprocessor/pragma_poison.c @@ -0,0 +1,20 @@ +// RUN: clang-cc %s -Eonly -verify + +#pragma GCC poison rindex +rindex(some_string, 'h'); // expected-error {{attempt to use a poisoned identifier}} + +#define BAR _Pragma ("GCC poison XYZW") XYZW /*NO ERROR*/ + XYZW // ok +BAR + XYZW // expected-error {{attempt to use a poisoned identifier}} + +// Pragma poison shouldn't warn from macro expansions defined before the token +// is poisoned. + +#define strrchr rindex2 +#pragma GCC poison rindex2 + +// Can poison multiple times. +#pragma GCC poison rindex2 + +strrchr(some_string, 'h'); // ok. diff --git a/test/Preprocessor/pragma_unknown.c b/test/Preprocessor/pragma_unknown.c new file mode 100644 index 000000000000..16bf43b3f42e --- /dev/null +++ b/test/Preprocessor/pragma_unknown.c @@ -0,0 +1,28 @@ +// RUN: clang-cc -E %s | grep '#pragma foo bar' && +// RUN: clang-cc -fsyntax-only -Wunknown-pragmas -verify %s + +// GCC doesn't expand macro args for unrecognized pragmas. +#define bar xX +#pragma foo bar // expected-warning {{unknown pragma ignored}} + +#pragma STDC FP_CONTRACT ON +#pragma STDC FP_CONTRACT OFF +#pragma STDC FP_CONTRACT DEFAULT +#pragma STDC FP_CONTRACT IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} + +#pragma STDC FENV_ACCESS ON // expected-warning {{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}} +#pragma STDC FENV_ACCESS OFF +#pragma STDC FENV_ACCESS DEFAULT +#pragma STDC FENV_ACCESS IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} + +#pragma STDC CX_LIMITED_RANGE ON +#pragma STDC CX_LIMITED_RANGE OFF +#pragma STDC CX_LIMITED_RANGE DEFAULT +#pragma STDC CX_LIMITED_RANGE IN_BETWEEN // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} + +#pragma STDC CX_LIMITED_RANGE // expected-warning {{expected 'ON' or 'OFF' or 'DEFAULT' in pragma}} +#pragma STDC CX_LIMITED_RANGE ON FULL POWER // expected-warning {{expected end of macro in STDC pragma}} + +#pragma STDC SO_GREAT // expected-warning {{unknown pragma in STDC namespace}} +#pragma STDC // expected-warning {{unknown pragma in STDC namespace}} + diff --git a/test/Preprocessor/print_line_track.c b/test/Preprocessor/print_line_track.c new file mode 100644 index 000000000000..539433d1af04 --- /dev/null +++ b/test/Preprocessor/print_line_track.c @@ -0,0 +1,17 @@ +/* RUN: clang-cc -E %s | grep 'a 3' && + * RUN: clang-cc -E %s | grep 'b 16' && + * RUN: clang-cc -E -P %s | grep 'a 3' && + * RUN: clang-cc -E -P %s | grep 'b 16' && + * RUN: clang-cc -E %s | not grep '# 0 ' + * PR1848 + * PR3437 +*/ + +#define t(x) x + +t(a +3) + +t(b +__LINE__) + diff --git a/test/Preprocessor/skipping_unclean.c b/test/Preprocessor/skipping_unclean.c new file mode 100644 index 000000000000..31ce9b460def --- /dev/null +++ b/test/Preprocessor/skipping_unclean.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -E %s | grep bark + +#if 0 +blah +#\ +else +bark +#endif + diff --git a/test/Preprocessor/stringize_misc.c b/test/Preprocessor/stringize_misc.c new file mode 100644 index 000000000000..251116acad66 --- /dev/null +++ b/test/Preprocessor/stringize_misc.c @@ -0,0 +1,26 @@ +// RUN: clang-cc -E %s | grep -F '"f(1, 2)" "g((x=y++, y))"' && +// RUN: clang-cc -E %s | grep -F '"{a=1" "b=2;}"' && +// RUN: clang-cc -E %s | grep -F '"<" "["' && +// RUN: clang-cc -E %s | grep -F '"(,)" "(...)"' && +// RUN: clang-cc -E %s | grep -F '{a=1 c=3; b=2;}' && +// RUN: clang-cc -E %s | grep -F '"a COMMA b" "(a, b)"' + +#define M(x, y) #x #y + +M( f(1, 2), g((x=y++, y))) +M( {a=1 , b=2;} ) /* A semicolon is not a comma */ +M( <, [ ) /* Passes the arguments < and [ */ +M( (,), (...) ) /* Passes the arguments (,) and (...) */ + +#define START_END(start, end) start c=3; end + +START_END( {a=1 , b=2;} ) /* braces are not parentheses */ + +/* + * To pass a comma token as an argument it is + * necessary to write: + */ +#define COMMA , + +M(a COMMA b, (a, b)) + diff --git a/test/Preprocessor/stringize_space.c b/test/Preprocessor/stringize_space.c new file mode 100644 index 000000000000..e41736c81683 --- /dev/null +++ b/test/Preprocessor/stringize_space.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -E %s | grep -- '-"" , - "" , -"" , - ""' + +#define A(b) -#b , - #b , -# b , - # b +A() diff --git a/test/Preprocessor/stringize_space2.c b/test/Preprocessor/stringize_space2.c new file mode 100644 index 000000000000..6a96894de6ee --- /dev/null +++ b/test/Preprocessor/stringize_space2.c @@ -0,0 +1,6 @@ +/* RUN: clang-cc -E %s | grep 'a c' + */ +#define t(x) #x +t(a +c) + diff --git a/test/Preprocessor/undef-error.c b/test/Preprocessor/undef-error.c new file mode 100644 index 000000000000..f818e59a6d1f --- /dev/null +++ b/test/Preprocessor/undef-error.c @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -pedantic-errors -verify +// PR2045 + +#define b +/* expected-error {{extra tokens at end of #undef directive}} */ #undef a b diff --git a/test/Preprocessor/unterminated.c b/test/Preprocessor/unterminated.c new file mode 100644 index 000000000000..2040aac17de2 --- /dev/null +++ b/test/Preprocessor/unterminated.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -E -verify %s +// PR3096 +#ifdef FOO // expected-error {{unterminated conditional directive}} +/* /* */ + diff --git a/test/Preprocessor/x86_target_features.c b/test/Preprocessor/x86_target_features.c new file mode 100644 index 000000000000..90a717b81e8a --- /dev/null +++ b/test/Preprocessor/x86_target_features.c @@ -0,0 +1,35 @@ +// FIXME: Use -triple, not -ccc-host-triple. + +// RUN: clang -ccc-host-triple i386-unknown-unknown -march=core2 -msse4 -x c -E -dM -o %t %s && +// RUN: grep '#define __SSE2_MATH__ 1' %t && +// RUN: grep '#define __SSE2__ 1' %t && +// RUN: grep '#define __SSE3__ 1' %t && +// RUN: grep '#define __SSE4_1__ 1' %t && +// RUN: grep '#define __SSE4_2__ 1' %t && +// RUN: grep '#define __SSE_MATH__ 1' %t && +// RUN: grep '#define __SSE__ 1' %t && +// RUN: grep '#define __SSSE3__ 1' %t && + +// RUN: clang -ccc-host-triple i386-unknown-unknown -march=core2 -msse4 -mno-sse2 -x c -E -dM -o %t %s && +// RUN: grep '#define __SSE2_MATH__ 1' %t | count 0 && +// RUN: grep '#define __SSE2__ 1' %t | count 0 && +// RUN: grep '#define __SSE3__ 1' %t | count 0 && +// RUN: grep '#define __SSE4_1__ 1' %t | count 0 && +// RUN: grep '#define __SSE4_2__ 1' %t | count 0 && +// RUN: grep '#define __SSE_MATH__ 1' %t && +// RUN: grep '#define __SSE__ 1' %t && +// RUN: grep '#define __SSSE3__ 1' %t | count 0 && + +// RUN: clang -ccc-host-triple i386-unknown-unknown -march=pentium-m -x c -E -dM -o %t %s && +// RUN: grep '#define __SSE2_MATH__ 1' %t && +// RUN: grep '#define __SSE2__ 1' %t && +// RUN: grep '#define __SSE3__ 1' %t | count 0 && +// RUN: grep '#define __SSE4_1__ 1' %t | count 0 && +// RUN: grep '#define __SSE4_2__ 1' %t | count 0 && +// RUN: grep '#define __SSE_MATH__ 1' %t && +// RUN: grep '#define __SSE__ 1' %t && +// RUN: grep '#define __SSSE3__ 1' %t | count 0 && + +// RUN: true + + diff --git a/test/Rewriter/block-test.c b/test/Rewriter/block-test.c new file mode 100644 index 000000000000..9b24e6323d45 --- /dev/null +++ b/test/Rewriter/block-test.c @@ -0,0 +1,38 @@ +// RUN: clang-cc -rewrite-blocks %s -fblocks -o - + +static int (^block)(const void *, const void *) = (int (^)(const void *, const void *))0; +static int (*func)(int (^block)(void *, void *)) = (int (*)(int (^block)(void *, void *)))0; + +typedef int (^block_T)(const void *, const void *); +typedef int (*func_T)(int (^block)(void *, void *)); + +void foo(const void *a, const void *b, void *c) { + int (^block)(const void *, const void *) = (int (^)(const void *, const void *))c; + int (*func)(int (^block)(void *, void *)) = (int (*)(int (^block)(void *, void *)))c; +} + +typedef void (^test_block_t)(); + +int main(int argc, char **argv) { + int a; + + void (^test_block_v)(); + void (^test_block_v2)(int, float); + + void (^test_block_v3)(void (^barg)(int)); + + a = 77; + test_block_v = ^(){ int local=1; printf("a=%d\n",a+local); }; + test_block_v(); + a++; + test_block_v(); + + __block int b; + + b = 88; + test_block_v2 = ^(int x, float f){ printf("b=%d\n",b); }; + test_block_v2(1,2.0); + b++; + test_block_v2(3,4.0); + return 7; +} diff --git a/test/Rewriter/crash.m b/test/Rewriter/crash.m new file mode 100644 index 000000000000..d4aba58c7b60 --- /dev/null +++ b/test/Rewriter/crash.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -rewrite-objc -o - %s +// rdar://5950938 +@interface NSArray {} ++ (id)arrayWithObjects:(id)firstObj, ...; +@end + +@interface NSConstantString {} +@end + +int main() { + id foo = [NSArray arrayWithObjects:@"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9", @"10", @"11", @"12", 0]; + return 0; +} + +// rdar://6291588 +@protocol A +@end + +@interface Foo +@end + +void func() { + id <A> obj = (id <A>)[Foo bar]; +} + diff --git a/test/Rewriter/finally.m b/test/Rewriter/finally.m new file mode 100644 index 000000000000..bdc5a34fdf2d --- /dev/null +++ b/test/Rewriter/finally.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -rewrite-objc -verify %s -o - + +int main() { + @try { + printf("executing try"); // expected-warning{{implicitly declaring C library function 'printf' with type 'int (char const *, ...)'}} \ + // expected-note{{please include the header <stdio.h> or explicitly provide a declaration for 'printf'}} + return(0); // expected-warning{{rewriter doesn't support user-specified control flow semantics for @try/@finally (code may not execute properly)}} + } @finally { + printf("executing finally"); + } + while (1) { + @try { + printf("executing try"); + break; // expected-warning{{rewriter doesn't support user-specified control flow semantics for @try/@finally (code may not execute properly)}} + } @finally { + printf("executing finally"); + } + printf("executing after finally block"); + } + @try { + printf("executing try"); + } @finally { + printf("executing finally"); + } + return 0; +} + diff --git a/test/Rewriter/id-test-3.m b/test/Rewriter/id-test-3.m new file mode 100644 index 000000000000..ad1e76decf80 --- /dev/null +++ b/test/Rewriter/id-test-3.m @@ -0,0 +1,14 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@protocol P +- (id<P>) Meth: (id<P>) Arg; +@end + +@interface INTF<P> +- (id<P>)IMeth; +@end + +@implementation INTF +- (id<P>)IMeth { return [(id<P>)self Meth: (id<P>)0]; } +- (id<P>) Meth : (id<P>) Arg {} +@end diff --git a/test/Rewriter/ivar-encoding-1.m b/test/Rewriter/ivar-encoding-1.m new file mode 100644 index 000000000000..759146175d44 --- /dev/null +++ b/test/Rewriter/ivar-encoding-1.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface Intf +{ + id ivar; + id ivar1[12]; + + id **ivar3; + + id (*ivar4) (id, id); +} +@end + +@implementation Intf +@end diff --git a/test/Rewriter/ivar-encoding-2.m b/test/Rewriter/ivar-encoding-2.m new file mode 100644 index 000000000000..86cc9b6a88f3 --- /dev/null +++ b/test/Rewriter/ivar-encoding-2.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@implementation Intf +{ + id ivar; + id ivar1[12]; + + id **ivar3; + + id (*ivar4) (id, id); +} +@end diff --git a/test/Rewriter/metadata-test-1.m b/test/Rewriter/metadata-test-1.m new file mode 100644 index 000000000000..40eded121ece --- /dev/null +++ b/test/Rewriter/metadata-test-1.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface Intf +@end + +@implementation Intf(Category) +- (void) CatMeth {} +@end + +@implementation Another +- (void) CatMeth {} +@end diff --git a/test/Rewriter/metadata-test-2.m b/test/Rewriter/metadata-test-2.m new file mode 100644 index 000000000000..ab838f18bb93 --- /dev/null +++ b/test/Rewriter/metadata-test-2.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +typedef struct _NSPoint { + float x; + float y; +} NSPoint; + +@interface Intf +- (void) MyMeth : (NSPoint) Arg1; +@end + +@implementation Intf +- (void) MyMeth : (NSPoint) Arg1{} +@end + diff --git a/test/Rewriter/method-encoding-1.m b/test/Rewriter/method-encoding-1.m new file mode 100644 index 000000000000..25dccbf75084 --- /dev/null +++ b/test/Rewriter/method-encoding-1.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@protocol P1 +- (void) MyProtoMeth : (int **) arg1 : (void*) arg2; ++ (void) MyProtoMeth : (int **) arg1 : (void*) arg2; +@end + +@interface Intf <P1> +- (char *) MyMeth : (double) arg1 : (char *[12]) arg2; +- (id) address:(void *)location with:(unsigned **)arg2; +@end + +@implementation Intf +- (char *) MyMeth : (double) arg1 : (char *[12]) arg2{} +- (void) MyProtoMeth : (int **) arg1 : (void*) arg2 {} ++ (void) MyProtoMeth : (int **) arg1 : (void*) arg2 {} +- (id) address:(void *)location with:(unsigned **)arg2{} +@end diff --git a/test/Rewriter/objc-encoding-bug-1.m b/test/Rewriter/objc-encoding-bug-1.m new file mode 100644 index 000000000000..684a0d2ded09 --- /dev/null +++ b/test/Rewriter/objc-encoding-bug-1.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +typedef struct NSMethodFrameArgInfo { + struct NSMethodFrameArgInfo *subInfo; + struct NSMethodFrameArgInfo *an; +} NSMethodFrameArgInfo; + +@interface NSMethodSignature +- (NSMethodFrameArgInfo *)_argInfo; +@end + +@implementation NSMethodSignature + +- (NSMethodFrameArgInfo *)_argInfo{ + return 0; +} + +@end + diff --git a/test/Rewriter/objc-ivar-receiver-1.m b/test/Rewriter/objc-ivar-receiver-1.m new file mode 100644 index 000000000000..c7ad05a1884d --- /dev/null +++ b/test/Rewriter/objc-ivar-receiver-1.m @@ -0,0 +1,24 @@ +// RUN: clang-cc -rewrite-objc %s -o - && +// RUN: clang-cc -rewrite-objc %s -o - | grep 'newInv->_container' + +@interface NSMutableArray +- (void)addObject:(id)addObject; +@end + +@interface NSInvocation { +@private + id _container; +} ++ (NSInvocation *)invocationWithMethodSignature; + +@end + +@implementation NSInvocation + ++ (NSInvocation *)invocationWithMethodSignature { + NSInvocation *newInv; + id obj = newInv->_container; + [newInv->_container addObject:0]; + return 0; +} +@end diff --git a/test/Rewriter/objc-string-concat-1.m b/test/Rewriter/objc-string-concat-1.m new file mode 100644 index 000000000000..e8f8a88f2056 --- /dev/null +++ b/test/Rewriter/objc-string-concat-1.m @@ -0,0 +1,14 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@class NSString; + +@interface NSConstantString; +@end + + + +NSConstantString *t0 = @"123"; +NSConstantString *t = @"123" @"4567"; // concat +NSConstantString *t1 = @"123" @"4567" /* COMMENT */ @"89"; // concat +NSConstantString *t2 = @"123" @/* COMMENT */ "4567"; // concat + diff --git a/test/Rewriter/objc-super-test.m b/test/Rewriter/objc-super-test.m new file mode 100644 index 000000000000..500933d835da --- /dev/null +++ b/test/Rewriter/objc-super-test.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -rewrite-objc %s -o - | grep objc_msgSendSuper | grep MainMethod + +typedef struct objc_selector *SEL; +typedef struct objc_object *id; + +@interface SUPER +- (int) MainMethod; +@end + +@interface MyDerived : SUPER +- (int) instanceMethod; +@end + +@implementation MyDerived +- (int) instanceMethod { + return [super MainMethod]; +} +@end diff --git a/test/Rewriter/objc-synchronized-1.m b/test/Rewriter/objc-synchronized-1.m new file mode 100644 index 000000000000..e3c41165db22 --- /dev/null +++ b/test/Rewriter/objc-synchronized-1.m @@ -0,0 +1,20 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +id SYNCH_EXPR(); +void SYNCH_BODY(); +void SYNCH_BEFORE(); +void SYNC_AFTER(); + +void foo(id sem) +{ + SYNCH_BEFORE(); + @synchronized (SYNCH_EXPR()) { + SYNCH_BODY(); + return; + } + SYNC_AFTER(); + @synchronized ([sem self]) { + SYNCH_BODY(); + return; + } +} diff --git a/test/Rewriter/properties.m b/test/Rewriter/properties.m new file mode 100644 index 000000000000..ac8ee9ff8c97 --- /dev/null +++ b/test/Rewriter/properties.m @@ -0,0 +1,54 @@ +// RUN: clang-cc -rewrite-objc %s -o - + +@interface Foo { + int i; + int rrrr; + Foo *o; +} +@property int i; +@property(readonly) int rrrr; +@property int d; +@property(retain) Foo *o; + +- (void)foo; +@end + +@implementation Foo +@synthesize i; +@synthesize rrrr; +@synthesize o; + +@dynamic d; + +- (void)foo { + i = 99; +} + +- (int)bar { + return i; +} +@end + +@interface Bar { +} +@end + +@implementation Bar + +static int func(int i); + +- (void)baz { + Foo *obj1, *obj2; + int i; + if (obj1.i == obj2.rrrr) + obj1.i = 33; + obj1.i = func(obj2.rrrr); + obj1.i = obj2.rrrr; + obj1.i = (obj2.rrrr); + [obj1 setI:[obj2 rrrr]]; + obj1.i = [obj2 rrrr]; + obj1.i = 3 + [obj2 rrrr]; + i = obj1.o.i; + obj1.o.i = 77; +} +@end diff --git a/test/Rewriter/protocol-rewrite-1.m b/test/Rewriter/protocol-rewrite-1.m new file mode 100644 index 000000000000..263a97d85d28 --- /dev/null +++ b/test/Rewriter/protocol-rewrite-1.m @@ -0,0 +1,48 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +typedef struct MyWidget { + int a; +} MyWidget; + +MyWidget gWidget = { 17 }; + +@protocol MyProto +- (MyWidget *)widget; +@end + +@interface Foo +@end + +@interface Bar: Foo <MyProto> +@end + +@interface Container ++ (MyWidget *)elementForView:(Foo *)view; +@end + +@implementation Foo +@end + +@implementation Bar +- (MyWidget *)widget { + return &gWidget; +} +@end + +@implementation Container ++ (MyWidget *)elementForView:(Foo *)view +{ + MyWidget *widget = (void*)0; + if (@protocol(MyProto)) { + widget = [(id <MyProto>)view widget]; + } + return widget; +} +@end + +int main(void) { + id view; + MyWidget *w = [Container elementForView: view]; + + return 0; +} diff --git a/test/Rewriter/rewrite-api-bug.m b/test/Rewriter/rewrite-api-bug.m new file mode 100644 index 000000000000..ba0511b64650 --- /dev/null +++ b/test/Rewriter/rewrite-api-bug.m @@ -0,0 +1,11 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface MyDerived +- (void) instanceMethod; +@end + +@implementation MyDerived +- (void) instanceMethod { +} +@end + diff --git a/test/Rewriter/rewrite-foreach-1.m b/test/Rewriter/rewrite-foreach-1.m new file mode 100644 index 000000000000..eef33f88c9ca --- /dev/null +++ b/test/Rewriter/rewrite-foreach-1.m @@ -0,0 +1,37 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@protocol P @end + +@interface MyList +@end + +@implementation MyList +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +@end + +@interface MyList (BasicTest) +- (void)compilerTestAgainst; +@end + +int LOOP(); +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { + id el; + for (el in self) + { LOOP(); } + for (id el1 in self) + LOOP(); + + for (el in (self)) + if (el) + LOOP(); + + for (el in ((self))) + if (el) + LOOP(); +} +@end + diff --git a/test/Rewriter/rewrite-foreach-2.m b/test/Rewriter/rewrite-foreach-2.m new file mode 100644 index 000000000000..12f0e834df42 --- /dev/null +++ b/test/Rewriter/rewrite-foreach-2.m @@ -0,0 +1,34 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@protocol P @end + +@interface MyList +@end + +@implementation MyList +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +@end + +@interface MyList (BasicTest) +- (void)compilerTestAgainst; +@end + +int LOOP(); +int INNERLOOP(); +void END_LOOP(); +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { + id el; + for (el in self) + { LOOP(); + for (id el1 in self) + INNER_LOOP(); + + END_LOOP(); + } +} +@end + diff --git a/test/Rewriter/rewrite-foreach-3.m b/test/Rewriter/rewrite-foreach-3.m new file mode 100644 index 000000000000..3aa0d95b44bb --- /dev/null +++ b/test/Rewriter/rewrite-foreach-3.m @@ -0,0 +1,29 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@protocol P @end + +@interface MyList +@end + +@implementation MyList +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +@end + +@interface MyList (BasicTest) +- (void)compilerTestAgainst; +@end + +int LOOP(); +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { + MyList * el; + for (el in self) + { LOOP(); } + for (MyList * el1 in self) + LOOP(); +} +@end + diff --git a/test/Rewriter/rewrite-foreach-4.m b/test/Rewriter/rewrite-foreach-4.m new file mode 100644 index 000000000000..774f9a0b75c8 --- /dev/null +++ b/test/Rewriter/rewrite-foreach-4.m @@ -0,0 +1,32 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface MyList +- (id) allKeys; +@end + +@implementation MyList +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +- (id) allKeys {} +@end + +@interface MyList (BasicTest) +- (void)compilerTestAgainst; +@end + +int LOOP(); +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { + MyList * el; + for (el in [el allKeys]) { LOOP(); + } + + for (id el1 in[el allKeys]) { LOOP(); + } + for (el in([el allKeys])) { LOOP(); + } +} +@end + diff --git a/test/Rewriter/rewrite-foreach-5.m b/test/Rewriter/rewrite-foreach-5.m new file mode 100644 index 000000000000..d0d12444a3e7 --- /dev/null +++ b/test/Rewriter/rewrite-foreach-5.m @@ -0,0 +1,47 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface MyList +- (id) allKeys; +@end + +@implementation MyList +- (unsigned int)countByEnumeratingWithState: (struct __objcFastEnumerationState *)state objects: (id *)items count:(unsigned int)stackcount +{ + return 0; +} +- (id) allKeys {} +@end + +@interface MyList (BasicTest) +- (void)compilerTestAgainst; +@end + +int LOOP(); +@implementation MyList (BasicTest) +- (void)compilerTestAgainst { + MyList * el; + int i; + for (el in [el allKeys]) { + for (i = 0; i < 10; i++) + if (i == 5) + break; + + if (el == 0) + break; + if (el != self) + continue; + LOOP(); + } + + for (id el1 in[el allKeys]) { + LOOP(); + for (el in self) { + if (el) + continue; + } + if (el1) + break; + } +} +@end + diff --git a/test/Rewriter/rewrite-foreach-6.m b/test/Rewriter/rewrite-foreach-6.m new file mode 100644 index 000000000000..c6043bb98eb4 --- /dev/null +++ b/test/Rewriter/rewrite-foreach-6.m @@ -0,0 +1,13 @@ +// RUN: clang-cc %s -rewrite-objc -o=- +// rdar://5716356 +// FIXME: Should be able to pipe into clang, but code is not +// yet correct for other reasons: rdar://5716940 + +@class NSNotification; +@class NSMutableArray; + +void foo(NSMutableArray *notificationArray, id X) { + for (NSNotification *notification in notificationArray) + [X postNotification:notification]; +} + diff --git a/test/Rewriter/rewrite-nest.m b/test/Rewriter/rewrite-nest.m new file mode 100644 index 000000000000..7a1690a3630b --- /dev/null +++ b/test/Rewriter/rewrite-nest.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface NSMapTable @end +@interface NSEnumerator @end + +typedef unsigned int NSUInteger; + +@interface NSConcreteMapTable : NSMapTable { +@public + NSUInteger capacity; +} +@end + +@interface NSConcreteMapTableValueEnumerator : NSEnumerator { + NSConcreteMapTable *mapTable; +} +@end + +@implementation NSConcreteMapTableValueEnumerator + +- nextObject { + while (mapTable->capacity) { + } + return 0; +} +@end + diff --git a/test/Rewriter/rewrite-protocol-type-1.m b/test/Rewriter/rewrite-protocol-type-1.m new file mode 100644 index 000000000000..48dc02971ca9 --- /dev/null +++ b/test/Rewriter/rewrite-protocol-type-1.m @@ -0,0 +1,24 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@protocol MyProto1 +@end + +@protocol MyProto2 +@end + +@interface INTF @end + +INTF <MyProto1> *g1; + +INTF <MyProto1, MyProto2> *g2, *g3; + +INTF <MyProto1> * Func(INTF <MyProto1> *p2, INTF<MyProto1> *p3, INTF *p4, INTF<MyProto1> *p5) +{ + return p2; +} + +INTF <MyProto1, MyProto2> * Func1(INTF *p2, INTF<MyProto1, MyProto2> *p3, INTF *p4, INTF<MyProto1> *p5) +{ + return p3; +} + diff --git a/test/Rewriter/rewrite-try-catch.m b/test/Rewriter/rewrite-try-catch.m new file mode 100644 index 000000000000..8c6d08f2e01d --- /dev/null +++ b/test/Rewriter/rewrite-try-catch.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface Foo @end +@interface GARF @end + +void foo() { + @try { TRY(); } + @catch (...) { SPLATCH(); @throw; } +} + +int main() +{ + + @try { + MYTRY(); + } + + @catch (Foo* localException) { + MYCATCH(); + @throw; + } + + // no catch clause + @try { } + @finally { } +} + diff --git a/test/Rewriter/static-type-protocol-1.m b/test/Rewriter/static-type-protocol-1.m new file mode 100644 index 000000000000..0985a9d77554 --- /dev/null +++ b/test/Rewriter/static-type-protocol-1.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@protocol Proto +- (void) ProtoDidget; +@end + +@protocol MyProto <Proto> +- (void) widget; +@end + +@interface Foo +- (void)StillMode; +@end + +@interface Container ++ (void)MyMeth; +@end + +@implementation Container ++ (void)MyMeth +{ + Foo *view; + [(Foo <MyProto> *)view StillMode]; + [(Foo <MyProto> *)view widget]; + [(Foo <MyProto> *)view ProtoDidget]; +} +@end diff --git a/test/Rewriter/undecl-objc-h.m b/test/Rewriter/undecl-objc-h.m new file mode 100644 index 000000000000..b09765163ec0 --- /dev/null +++ b/test/Rewriter/undecl-objc-h.m @@ -0,0 +1,29 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +typedef struct S { + int * pint; + int size; +}NSRec; + +@interface SUPER +- (NSRec) MainMethod : (NSRec) Arg1 : (NSRec) Arg2; +@end + +@interface MyDerived : SUPER +{ + NSRec d; +} +- (int) instanceMethod; +- (int) another : (int) arg; +- (NSRec) MainMethod : (NSRec) Arg1 : (NSRec) Arg2; +@end + +@implementation MyDerived +- (int) instanceMethod { + return [self another : [self MainMethod : d : d].size]; +} + +- (int) another : (int) arg { return arg; } +- (NSRec) MainMethod : (NSRec) Arg1 : (NSRec) Arg2 { return Arg2; } +@end + diff --git a/test/Rewriter/undeclared-method-1.m b/test/Rewriter/undeclared-method-1.m new file mode 100644 index 000000000000..795fd61b4afa --- /dev/null +++ b/test/Rewriter/undeclared-method-1.m @@ -0,0 +1,9 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface Derived @end + +int main(void) { + Derived *v ; + [v free]; + return 0; +} diff --git a/test/Rewriter/undef-field-reference-1.m b/test/Rewriter/undef-field-reference-1.m new file mode 100644 index 000000000000..43bc2ad8bfa5 --- /dev/null +++ b/test/Rewriter/undef-field-reference-1.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +@interface MyDerived +{ +@public + int IVAR; +} +@end + +MyDerived *pd; +int main() { + return pd->IVAR; +} + + diff --git a/test/Rewriter/va-method.m b/test/Rewriter/va-method.m new file mode 100644 index 000000000000..3bee599435e7 --- /dev/null +++ b/test/Rewriter/va-method.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -rewrite-objc %s -o=- + +#include <stdarg.h> + +@interface NSObject @end +@interface XX : NSObject @end + +@implementation XX +- (void)encodeValuesOfObjCTypes:(const char *)types, ... { + va_list ap; + va_start(ap, types); + while (*types) ; + va_end(ap); +} + +@end + diff --git a/test/Sema/128bitint.c b/test/Sema/128bitint.c new file mode 100644 index 000000000000..2a18d904f8f2 --- /dev/null +++ b/test/Sema/128bitint.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef int i128 __attribute__((__mode__(TI))); +typedef unsigned u128 __attribute__((__mode__(TI))); + +int a[((i128)-1 ^ (i128)-2) == 1 ? 1 : -1]; +int a[(u128)-1 > 1LL ? 1 : -1]; diff --git a/test/Sema/PR2727.c b/test/Sema/PR2727.c new file mode 100644 index 000000000000..52d8392ee9e5 --- /dev/null +++ b/test/Sema/PR2727.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -verify -fsyntax-only -std=c90 %s && +// RUN: clang-cc -verify -fsyntax-only -std=c99 %s + +int f (int x) +{ + // sizeof applied to a type should not delete the type. + return sizeof (int[x]); +} diff --git a/test/Sema/PR2728.c b/test/Sema/PR2728.c new file mode 100644 index 000000000000..26c96fe625be --- /dev/null +++ b/test/Sema/PR2728.c @@ -0,0 +1,9 @@ +// RUN: clang-cc -verify -fsyntax-only -std=c90 %s && +// RUN: clang-cc -verify -fsyntax-only -std=c99 %s + +struct s +{ + int a; +}; + +int a[__builtin_offsetof(struct s, a) == 0]; diff --git a/test/Sema/PR2919-builtin-types-compat-strips-crv.c b/test/Sema/PR2919-builtin-types-compat-strips-crv.c new file mode 100644 index 000000000000..160ec4a38058 --- /dev/null +++ b/test/Sema/PR2919-builtin-types-compat-strips-crv.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only %s + +typedef struct foo T0; +typedef const struct foo T1; + +int a0[__builtin_types_compatible_p(T0, + const T1) ? 1 : -1]; diff --git a/test/Sema/PR2923.c b/test/Sema/PR2923.c new file mode 100644 index 000000000000..c75e7baed1a1 --- /dev/null +++ b/test/Sema/PR2923.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Test for absence of crash reported in PR 2923: +// +// http://llvm.org/bugs/show_bug.cgi?id=2923 +// +// Previously we had a crash when deallocating the FunctionDecl for 'bar' +// because FunctionDecl::getNumParams() just used the type of foo to determine +// the number of parameters it has. In the case of 'bar' there are no +// ParmVarDecls. +int foo(int x, int y) { return x + y; } +extern typeof(foo) bar; diff --git a/test/Sema/PR2963-enum-constant.c b/test/Sema/PR2963-enum-constant.c new file mode 100644 index 000000000000..78f2326dae1b --- /dev/null +++ b/test/Sema/PR2963-enum-constant.c @@ -0,0 +1,17 @@ +// RUN: clang-cc %s -verify -pedantic -fsyntax-only + +typedef short short_fixed; + +enum +{ + // 8.8 short_fixed + SHORT_FIXED_FRACTIONAL_BITS= 8, + SHORT_FIXED_ONE= 1<<SHORT_FIXED_FRACTIONAL_BITS +}; + +#define FLOAT_TO_SHORT_FIXED(f) ((short_fixed)((f)*SHORT_FIXED_ONE)) + +enum +{ + SOME_VALUE= FLOAT_TO_SHORT_FIXED(0.1) // expected-warning{{expression is not integer constant expression}} +}; diff --git a/test/Sema/address-constant.c b/test/Sema/address-constant.c new file mode 100644 index 000000000000..69f2f79f6857 --- /dev/null +++ b/test/Sema/address-constant.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int i; +int a[] = {0}; +struct { int i; } s; + +int *array[] = {&i, a, &s.i}; + +extern void f(void); +void (*f_addr)(void) = &f; diff --git a/test/Sema/address_spaces.c b/test/Sema/address_spaces.c new file mode 100644 index 000000000000..b79799f0230c --- /dev/null +++ b/test/Sema/address_spaces.c @@ -0,0 +1,32 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +#define _AS1 __attribute__((address_space(1))) +#define _AS2 __attribute__((address_space(2))) +#define _AS3 __attribute__((address_space(3))) + +void foo(_AS3 float *a) { + _AS2 *x;// expected-warning {{type specifier missing, defaults to 'int'}} + _AS1 float * _AS2 *B; + + int _AS1 _AS2 *Y; // expected-error {{multiple address spaces specified for type}} + int *_AS1 _AS2 *Z; // expected-error {{multiple address spaces specified for type}} + + _AS1 int local; // expected-error {{automatic variable qualified with an address space}} + _AS1 int array[5]; // expected-error {{automatic variable qualified with an address space}} + _AS1 int arrarr[5][5]; // expected-error {{automatic variable qualified with an address space}} + + *a = 5.0f; +} + +struct _st { + int x, y; +} s __attribute ((address_space(1))) = {1, 1}; + + +// rdar://6774906 +__attribute__((address_space(256))) void * * const base = 0; +void * get_0(void) { + return base[0]; // expected-error {{illegal implicit cast between two pointers with different address spaces}} \ + expected-warning {{returning 'void __attribute__((address_space(256)))*' discards qualifiers, expected 'void *'}} +} + diff --git a/test/Sema/align-x86.c b/test/Sema/align-x86.c new file mode 100644 index 000000000000..2bc1cc848554 --- /dev/null +++ b/test/Sema/align-x86.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -verify %s + +// PR3433 +double g1; +short chk1[__alignof__(g1) == 8 ? 1 : -1]; +short chk2[__alignof__(double) == 8 ? 1 : -1]; + +long long g2; +short chk1[__alignof__(g2) == 8 ? 1 : -1]; +short chk2[__alignof__(long long) == 8 ? 1 : -1]; + +_Complex double g3; +short chk1[__alignof__(g3) == 8 ? 1 : -1]; +short chk2[__alignof__(_Complex double) == 8 ? 1 : -1]; diff --git a/test/Sema/annotate.c b/test/Sema/annotate.c new file mode 100644 index 000000000000..aec2af8b022f --- /dev/null +++ b/test/Sema/annotate.c @@ -0,0 +1,7 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +void __attribute__((annotate("foo"))) foo(float *a) { + __attribute__((annotate("bar"))) int x; + __attribute__((annotate(1))) int y; // expected-error {{argument to annotate attribute was not a string literal}} + __attribute__((annotate("bar", 1))) int z; // expected-error {{attribute requires 1 argument(s)}} +} diff --git a/test/Sema/anonymous-struct-union.c b/test/Sema/anonymous-struct-union.c new file mode 100644 index 000000000000..ca1133bd8ace --- /dev/null +++ b/test/Sema/anonymous-struct-union.c @@ -0,0 +1,98 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct X { + union { + float f3; + double d2; + } named; + + union { + int i; + float f; + + union { + float f2; + double d; + }; + }; + + struct { + int a; + float b; + }; +}; + +void test_unqual_references(struct X x, const struct X xc) { + x.i = 0; + x.f = 0.0; + x.f2 = x.f; + x.d = x.f; + x.f3 = 0; // expected-error{{no member named 'f3'}} + x.a = 0; + + xc.d = 0.0; // expected-error{{read-only variable is not assignable}} + xc.f = 0; // expected-error{{read-only variable is not assignable}} + xc.a = 0; // expected-error{{read-only variable is not assignable}} +} + + +struct Redecl { + int x; // expected-note{{previous declaration is here}} + struct y { }; + + union { + int x; // expected-error{{member of anonymous union redeclares 'x'}} + float y; + double z; // expected-note{{previous declaration is here}} + double zz; // expected-note{{previous declaration is here}} + }; + + int z; // expected-error{{duplicate member 'z'}} + void zz(); // expected-error{{duplicate member 'zz'}} +}; + +union { // expected-error{{declaration does not declare anything}} + int int_val; + float float_val; +}; + +static union { // expected-error{{declaration does not declare anything}} + int int_val2; + float float_val2; +}; + +void f() { + int_val2 = 0; // expected-error{{use of undeclared identifier}} + float_val2 = 0.0; // expected-error{{use of undeclared identifier}} +} + +void g() { + union { // expected-error{{declaration does not declare anything}} + int i; + float f2; + }; + i = 0; // expected-error{{use of undeclared identifier}} + f2 = 0.0; // expected-error{{use of undeclared identifier}} +} + +// <rdar://problem/6483159> +struct s0 { union { int f0; }; }; + +// <rdar://problem/6481130> +typedef struct { }; // expected-error{{declaration does not declare anything}} + +// PR3675 +struct s1 { + int f0; // expected-note{{previous declaration is here}} + union { + int f0; // expected-error{{member of anonymous union redeclares 'f0'}} + }; +}; + +// PR3680 +struct {}; // expected-error{{declaration does not declare anything}} + +struct s2 { + union { + int a; + } +}; // expected-error{{expected member name or ';' after declaration specifiers}} diff --git a/test/Sema/arg-duplicate.c b/test/Sema/arg-duplicate.c new file mode 100644 index 000000000000..e40a964234d9 --- /dev/null +++ b/test/Sema/arg-duplicate.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int f3(y, x, + x) // expected-error {{redefinition of parameter}} + int y, x, + x; // expected-error {{redefinition of parameter}} +{ + return x + y; +} + +void f4(void) { + f3 (1, 1, 2, 3, 4); // expected-warning{{too many arguments}} +} + diff --git a/test/Sema/arg-scope-c99.c b/test/Sema/arg-scope-c99.c new file mode 100644 index 000000000000..b5b1c8a812c1 --- /dev/null +++ b/test/Sema/arg-scope-c99.c @@ -0,0 +1,2 @@ +// RUN: clang-cc -fsyntax-only -std=c99 -verify %s +int bb(int sz, int ar[sz][sz]) { } diff --git a/test/Sema/arg-scope.c b/test/Sema/arg-scope.c new file mode 100644 index 000000000000..c1cc7e112f88 --- /dev/null +++ b/test/Sema/arg-scope.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int aa(int b, int x[sizeof b]) {} + +void foo(int i, int A[i]) {} + diff --git a/test/Sema/array-constraint.c b/test/Sema/array-constraint.c new file mode 100644 index 000000000000..5a09e20ecbff --- /dev/null +++ b/test/Sema/array-constraint.c @@ -0,0 +1,52 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +struct s; // expected-note 2 {{forward declaration of 'struct s'}} +struct s* t (struct s z[]) { // expected-error {{array has incomplete element type}} + return z; +} + +void ff() { + struct s v, *p; // expected-error {{variable has incomplete type 'struct s'}} + + p = &v; +} + +void *k (void l[2]) { // expected-error {{array has incomplete element type}} + return l; +} + +struct vari { + int a; + int b[]; +}; + +struct vari *func(struct vari a[]) { // expected-warning {{'struct vari' may not be used as an array element due to flexible array member}} + return a; +} + +int foo[](void); // expected-error {{'foo' declared as array of functions}} +int foo2[1](void); // expected-error {{'foo2' declared as array of functions}} + +typedef int (*pfunc)(void); + +pfunc xx(int f[](void)) { // expected-error {{'f' declared as array of functions}} + return f; +} + +void check_size() { + float f; + int size_not_int[f]; // expected-error {{size of array has non-integer type 'float'}} + int negative_size[1-2]; // expected-error{{array size is negative}} + int zero_size[0]; // expected-warning{{zero size arrays are an extension}} +} + +static int I; +typedef int TA[I]; // expected-error {{variable length array declaration not allowed at file scope}} + +void strFunc(char *); +const char staticAry[] = "test"; +int checkStaticAry() { + strFunc(staticAry); // expected-warning{{passing 'char const [5]' discards qualifiers, expected 'char *'}} +} + + diff --git a/test/Sema/array-declared-as-incorrect-type.c b/test/Sema/array-declared-as-incorrect-type.c new file mode 100644 index 000000000000..3f6fa33a3bd2 --- /dev/null +++ b/test/Sema/array-declared-as-incorrect-type.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +extern int a1[]; +int a1[1]; + +extern int a2[]; // expected-note {{previous definition is here}} +float a2[1]; // expected-error {{redefinition of 'a2'}} + +extern int a3[][2]; +int a3[1][2]; + +extern int a4[][2]; // expected-note {{previous definition is here}} +int a4[2]; // expected-error {{redefinition of 'a4'}} + +extern int a5[1][2][3]; // expected-note {{previous definition is here}} +int a5[3][2][1]; // expected-error {{redefinition of 'a5'}} diff --git a/test/Sema/array-init.c b/test/Sema/array-init.c new file mode 100644 index 000000000000..50148a83ae13 --- /dev/null +++ b/test/Sema/array-init.c @@ -0,0 +1,265 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +extern int foof() = 1; // expected-error{{illegal initializer (only variables can be initialized)}} + +static int x, y, z; + +static int ary[] = { x, y, z }; // expected-error{{initializer element is not a compile-time constant}} +int ary2[] = { x, y, z }; // expected-error{{initializer element is not a compile-time constant}} + +extern int fileScopeExtern[3] = { 1, 3, 5 }; // expected-warning{{'extern' variable has an initializer}} + +static long ary3[] = { 1, "abc", 3, 4 }; // expected-warning{{incompatible pointer to integer conversion initializing 'char [4]', expected 'long'}} + +void func() { + int x = 1; + + typedef int TInt = 1; // expected-error{{illegal initializer (only variables can be initialized)}} + + int xComputeSize[] = { 1, 3, 5 }; + + int x3[x] = { 1, 2 }; // expected-error{{variable-sized object may not be initialized}} + + int x4 = { 1, 2 }; // expected-warning{{excess elements in scalar initializer}} + + int y[4][3] = { + { 1, 3, 5 }, + { 2, 4, 6 }, + { 3, 5, 7 }, + }; + + int y2[4][3] = { + 1, 3, 5, 2, 4, 6, 3, 5, 7 + }; + + int y3[4][3] = { + { 1, 3, 5 }, + { 2, 4, 6 }, + { 3, 5, 7 }, + { 4, 6, 8 }, + { 5 }, // expected-warning{{excess elements in array initializer}} + }; + + struct threeElements { + int a,b,c; + } z = { 1 }; + + struct threeElements *p = 7; // expected-warning{{incompatible integer to pointer conversion initializing 'int', expected 'struct threeElements *'}} + + extern int blockScopeExtern[3] = { 1, 3, 5 }; // expected-error{{'extern' variable cannot have an initializer}} + + static long x2[3] = { 1.0, "abc" , 5.8 }; // expected-warning{{incompatible pointer to integer conversion initializing 'char [4]', expected 'long'}} +} + +void test() { + int y1[3] = { + { 1, 2, 3 } // expected-warning{{braces around scalar initializer}} expected-warning{{excess elements in scalar initializer}} + }; + int y3[4][3] = { + { 1, 3, 5 }, + { 2, 4, 6 }, + { 3, 5, 7 }, + { 4, 6, 8 }, + { }, // expected-warning{{use of GNU empty initializer extension}} expected-warning{{excess elements in array initializer}} + }; + int y4[4][3] = { + { 1, 3, 5, 2 }, // expected-warning{{excess elements in array initializer}} + { 4, 6 }, + { 3, 5, 7 }, + { 4, 6, 8 }, + }; +} + +void allLegalAndSynonymous() { + short q[4][3][2] = { + { 1 }, + { 2, 3 }, + { 4, 5, 6 } + }; + short q2[4][3][2] = { + { 1, 0, 0, 0, 0, 0 }, + { 2, 3, 0, 0, 0, 0 }, + { 4, 5, 6 } + }; + short q3[4][3][2] = { + { + { 1 }, + }, + { + { 2, 3 }, + }, + { + { 4, 5 }, + { 6 }, + }, + }; +} + +void legal() { + short q[][3][2] = { + { 1 }, + { 2, 3 }, + { 4, 5, 6 } + }; + int q_sizecheck[(sizeof(q) / sizeof(short [3][2])) == 3? 1 : -1]; +} + +unsigned char asso_values[] = { 34 }; +int legal2() { + return asso_values[0]; +} + +void illegal() { + short q2[4][][2] = { // expected-error{{array has incomplete element type 'short [][2]'}} + { 1, 0, 0, 0, 0, 0 }, + { 2, 3, 0, 0, 0, 0 }, + { 4, 5, 6 } + }; + short q3[4][3][] = { // expected-error{{array has incomplete element type 'short []'}} + { + { 1 }, + }, + { + { 2, 3 }, + }, + { + { 4, 5 }, + { 6 }, + }, + }; + int a[][] = { 1, 2 }; // expected-error{{array has incomplete element type 'int []'}} +} + +typedef int AryT[]; + +void testTypedef() +{ + AryT a = { 1, 2 }, b = { 3, 4, 5 }; + int a_sizecheck[(sizeof(a) / sizeof(int)) == 2? 1 : -1]; + int b_sizecheck[(sizeof(b) / sizeof(int)) == 3? 1 : -1]; +} + +static char const xx[] = "test"; +int xx_sizecheck[(sizeof(xx) / sizeof(char)) == 5? 1 : -1]; +static char const yy[5] = "test"; +static char const zz[3] = "test"; // expected-warning{{initializer-string for char array is too long}} + +void charArrays() +{ + static char const test[] = "test"; + int test_sizecheck[(sizeof(test) / sizeof(char)) == 5? 1 : -1]; + static char const test2[] = { "weird stuff" }; + static char const test3[] = { "test", "excess stuff" }; // expected-warning{{excess elements in char array initializer}} + + char* cp[] = { "Hello" }; + + char c[] = { "Hello" }; + int l[sizeof(c) == 6 ? 1 : -1]; + + int i[] = { "Hello "}; // expected-warning{{incompatible pointer to integer conversion initializing 'char [7]', expected 'int'}} + char c2[] = { "Hello", "Good bye" }; //expected-warning{{excess elements in char array initializer}} + + int i2[1] = { "Hello" }; //expected-warning{{incompatible pointer to integer conversion initializing 'char [6]', expected 'int'}} + char c3[5] = { "Hello" }; + char c4[4] = { "Hello" }; //expected-warning{{initializer-string for char array is too long}} + + int i3[] = {}; //expected-warning{{zero size arrays are an extension}} expected-warning{{use of GNU empty initializer extension}} +} + +void variableArrayInit() { + int a = 4; + char strlit[a] = "foo"; //expected-error{{variable-sized object may not be initialized}} + int b[a] = { 1, 2, 4 }; //expected-error{{variable-sized object may not be initialized}} +} + +// Pure array tests +float r1[10] = {{7}}; //expected-warning{{braces around scalar initializer}} +float r2[] = {{8}}; //expected-warning{{braces around scalar initializer}} +char r3[][5] = {1,2,3,4,5,6}; +int r3_sizecheck[(sizeof(r3) / sizeof(char[5])) == 2? 1 : -1]; +char r3_2[sizeof r3 == 10 ? 1 : -1]; +float r4[1][2] = {1,{2},3,4}; //expected-warning{{braces around scalar initializer}} expected-warning{{excess elements in array initializer}} +char r5[][5] = {"aa", "bbb", "ccccc"}; +char r6[sizeof r5 == 15 ? 1 : -1]; +const char r7[] = "zxcv"; +char r8[5] = "5char"; +char r9[5] = "6chars"; //expected-warning{{initializer-string for char array is too long}} + +int r11[0] = {}; //expected-warning{{zero size arrays are an extension}} expected-warning{{use of GNU empty initializer extension}} + +// Some struct tests +void autoStructTest() { +struct s1 {char a; char b;} t1; +struct s2 {struct s1 c;} t2 = { t1 }; +// The following is a less than great diagnostic (though it's on par with EDG). +struct s1 t3[] = {t1, t1, "abc", 0}; //expected-warning{{incompatible pointer to integer conversion initializing 'char [4]', expected 'char'}} +int t4[sizeof t3 == 6 ? 1 : -1]; +} +struct foo { int z; } w; +int bar (void) { + struct foo z = { w }; //expected-error{{incompatible type initializing 'struct foo', expected 'int'}} + return z.z; +} +struct s3 {void (*a)(void);} t5 = {autoStructTest}; +struct {int a; int b[];} t6 = {1, {1, 2, 3}}; // expected-warning{{flexible array initialization is a GNU extension}} \ +// expected-note{{initialized flexible array member 'b' is here}} +union {char a; int b;} t7[] = {1, 2, 3}; +int t8[sizeof t7 == (3*sizeof(int)) ? 1 : -1]; + +struct bittest{int : 31, a, :21, :12, b;}; +struct bittest bittestvar = {1, 2, 3, 4}; //expected-warning{{excess elements in struct initializer}} + +// Not completely sure what should happen here... +int u1 = {}; //expected-warning{{use of GNU empty initializer extension}} expected-error{{scalar initializer cannot be empty}} +int u2 = {{3}}; //expected-error{{too many braces around scalar initializer}} + +// PR2362 +void varArray() { + int c[][x] = { 0 }; //expected-error{{variable-sized object may not be initialized}} +} + +// PR2151 +int emptyInit() {struct {} x[] = {6};} //expected-warning{{empty struct extension}} expected-error{{initializer for aggregate with no elements}} + +int noNamedInit() { +struct {int:5;} x[] = {6}; //expected-error{{initializer for aggregate with no elements}} +} +struct {int a; int:5;} noNamedImplicit[] = {1,2,3}; +int noNamedImplicitCheck[sizeof(noNamedImplicit) == 3 * sizeof(*noNamedImplicit) ? 1 : -1]; + + +// ptrs are constant +struct soft_segment_descriptor { + long ssd_base; +}; +static int dblfault_tss; + +union uniao { int ola; } xpto[1]; + +struct soft_segment_descriptor gdt_segs[] = { + {(long) &dblfault_tss}, + { (long)xpto}, +}; + +static void sppp_ipv6cp_up(); +const struct {} ipcp = { sppp_ipv6cp_up }; //expected-warning{{empty struct extension}} expected-warning{{excess elements in struct initializer}} + +struct _Matrix { union { float m[4][4]; }; }; //expected-warning{{anonymous unions are a GNU extension in C}} +typedef struct _Matrix Matrix; +void test_matrix() { + const Matrix mat1 = { + { { 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f } } + }; + + const Matrix mat2 = { + 1.0f, 2.0f, 3.0f, 4.0f, + 5.0f, 6.0f, 7.0f, 8.0f, + 9.0f, 10.0f, 11.0f, 12.0f, + 13.0f, 14.0f, 15.0f, 16.0f + }; +} + +char badchararray[1] = { badchararray[0], "asdf" }; // expected-warning {{excess elements in array initializer}} expected-error {{initializer element is not a compile-time constant}} diff --git a/test/Sema/asm.c b/test/Sema/asm.c new file mode 100644 index 000000000000..0a62545a1e08 --- /dev/null +++ b/test/Sema/asm.c @@ -0,0 +1,78 @@ +// RUN: clang-cc %s -triple i386-pc-linux-gnu -verify -fsyntax-only + +void f() { + int i; + + asm ("foo\n" : : "a" (i + 2)); + asm ("foo\n" : : "a" (f())); // expected-error {{invalid type 'void' in asm input}} + + asm ("foo\n" : "=a" (f())); // expected-error {{invalid lvalue in asm output}} + asm ("foo\n" : "=a" (i + 2)); // expected-error {{invalid lvalue in asm output}} + + asm ("foo\n" : [symbolic_name] "=a" (i) : "[symbolic_name]" (i)); + asm ("foo\n" : "=a" (i) : "[" (i)); // expected-error {{invalid input constraint '[' in asm}} + asm ("foo\n" : "=a" (i) : "[foo" (i)); // expected-error {{invalid input constraint '[foo' in asm}} + asm ("foo\n" : "=a" (i) : "[symbolic_name]" (i)); // expected-error {{invalid input constraint '[symbolic_name]' in asm}} +} + +void clobbers() { + asm ("nop" : : : "ax", "#ax", "%ax"); + asm ("nop" : : : "eax", "rax", "ah", "al"); + asm ("nop" : : : "0", "%0", "#0"); + asm ("nop" : : : "foo"); // expected-error {{unknown register name 'foo' in asm}} + asm ("nop" : : : "52"); + asm ("nop" : : : "53"); // expected-error {{unknown register name '53' in asm}} + asm ("nop" : : : "-1"); // expected-error {{unknown register name '-1' in asm}} + asm ("nop" : : : "+1"); // expected-error {{unknown register name '+1' in asm}} +} + +// rdar://6094010 +void test3() { + int x; + asm(L"foo" : "=r"(x)); // expected-error {{wide string}} + asm("foo" : L"=r"(x)); // expected-error {{wide string}} +} + +// <rdar://problem/6156893> +void test4(const volatile void *addr) +{ + asm ("nop" : : "r"(*addr)); // expected-error {{invalid type 'void const volatile' in asm input for constraint 'r'}} + asm ("nop" : : "m"(*addr)); + + asm ("nop" : : "r"(test4(addr))); // expected-error {{invalid type 'void' in asm input for constraint 'r'}} + asm ("nop" : : "m"(test4(addr))); // expected-error {{invalid lvalue in asm input for constraint 'm'}} + + asm ("nop" : : "m"(f())); // expected-error {{invalid lvalue in asm input for constraint 'm'}} +} + +// <rdar://problem/6512595> +void test5() { + asm("nop" : : "X" (8)); +} + +// PR3385 +void test6(long i) { + asm("nop" : : "er"(i)); +} + +void asm_string_tests(int i) { + asm("%!"); // simple asm string, %! is not an error. + asm("%!" : ); // expected-error {{invalid % escape in inline assembly string}} + asm("xyz %" : ); // expected-error {{invalid % escape in inline assembly string}} + + asm ("%[somename]" :: [somename] "i"(4)); // ok + asm ("%[somename]" :: "i"(4)); // expected-error {{unknown symbolic operand name in inline assembly string}} + asm ("%[somename" :: "i"(4)); // expected-error {{unterminated symbolic operand name in inline assembly string}} + asm ("%[]" :: "i"(4)); // expected-error {{empty symbolic operand name in inline assembly string}} + + // PR3258 + asm("%9" :: "i"(4)); // expected-error {{invalid operand number in inline asm string}} + asm("%1" : "+r"(i)); // ok, referring to input. +} + +// PR4077 +int test7(unsigned long long b) { + int a; + asm volatile("foo %0 %1" : "=a" (a) :"0" (b)); // expected-error {{input with type 'unsigned long long' matching output with type 'int'}} + return a; +} diff --git a/test/Sema/assign-null.c b/test/Sema/assign-null.c new file mode 100644 index 000000000000..a343c8069fdc --- /dev/null +++ b/test/Sema/assign-null.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stddef.h> + +typedef void (*hookfunc)(void *arg); +hookfunc hook; + +void clear_hook() { + hook = NULL; +} diff --git a/test/Sema/assign.c b/test/Sema/assign.c new file mode 100644 index 000000000000..b25262c62438 --- /dev/null +++ b/test/Sema/assign.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void *test1(void) { return 0; } + +void test2 (const struct {int a;} *x) { + x->a = 10; // expected-error {{read-only variable is not assignable}} +} + +typedef int arr[10]; +void test3() { + const arr b; + const int b2[10]; + b[4] = 1; // expected-error {{read-only variable is not assignable}} + b2[4] = 1; // expected-error {{read-only variable is not assignable}} +} diff --git a/test/Sema/ast-print.c b/test/Sema/ast-print.c new file mode 100644 index 000000000000..a8988b029f49 --- /dev/null +++ b/test/Sema/ast-print.c @@ -0,0 +1,8 @@ +// RUN: clang-cc %s -ast-print + +typedef void func_typedef(); +func_typedef xxx; + +typedef void func_t(int x); +func_t a; + diff --git a/test/Sema/attr-aligned.c b/test/Sema/attr-aligned.c new file mode 100644 index 000000000000..6e641cb371f9 --- /dev/null +++ b/test/Sema/attr-aligned.c @@ -0,0 +1,21 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -verify %s + +int x __attribute__((aligned(3))); // expected-error {{requested alignment is not a power of 2}} + +// PR3254 +short g0[3] __attribute__((aligned)); +short g0_chk[__alignof__(g0) == 16 ? 1 : -1]; + +// <rdar://problem/6840045> +typedef char ueber_aligned_char __attribute__((aligned(8))); + +struct struct_with_ueber_char { + ueber_aligned_char c; +}; + +char c = 0; + +char a0[__alignof__(ueber_aligned_char) == 8? 1 : -1] = { 0 }; +char a1[__alignof__(struct struct_with_ueber_char) == 8? 1 : -1] = { 0 }; +char a2[__alignof__(c) == 1? : -1] = { 0 }; +char a3[sizeof(c) == 1? : -1] = { 0 }; diff --git a/test/Sema/attr-cleanup.c b/test/Sema/attr-cleanup.c new file mode 100644 index 000000000000..0434981c6c4a --- /dev/null +++ b/test/Sema/attr-cleanup.c @@ -0,0 +1,40 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +void c1(int *a); + +extern int g1 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}} +int g2 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}} +static int g3 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}} + +void t1() +{ + int v1 __attribute((cleanup)); // expected-error {{attribute requires 1 argument(s)}} + int v2 __attribute((cleanup(1, 2))); // expected-error {{attribute requires 1 argument(s)}} + + static int v3 __attribute((cleanup(c1))); // expected-warning {{cleanup attribute ignored}} + + int v4 __attribute((cleanup(h))); // expected-error {{'cleanup' argument 'h' not found}} + + int v5 __attribute((cleanup(c1))); + int v6 __attribute((cleanup(v3))); // expected-error {{'cleanup' argument 'v3' is not a function}} +} + +struct s { + int a, b; +}; + +void c2(); +void c3(struct s a); + +void t2() +{ + int v1 __attribute__((cleanup(c2))); // expected-error {{'cleanup' function 'c2' must take 1 parameter}} + int v2 __attribute__((cleanup(c3))); // expected-error {{'cleanup' function 'c3' parameter has type 'struct s' which is incompatible with type 'int *'}} +} + +// This is a manufactured testcase, but gcc accepts it... +void c4(_Bool a); +void t4() { + __attribute((cleanup(c4))) void* g; +} + diff --git a/test/Sema/attr-deprecated.c b/test/Sema/attr-deprecated.c new file mode 100644 index 000000000000..6597bad4b572 --- /dev/null +++ b/test/Sema/attr-deprecated.c @@ -0,0 +1,45 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +int f() __attribute__((deprecated)); +void g() __attribute__((deprecated)); +void g(); + +void z() __attribute__((bogusattr)); // expected-warning {{'bogusattr' attribute ignored}} + +extern int var __attribute__((deprecated)); + +int a() { + int (*ptr)() = f; // expected-warning {{'f' is deprecated}} + f(); // expected-warning {{'f' is deprecated}} + + // test if attributes propagate to functions + g(); // expected-warning {{'g' is deprecated}} + + return var; // expected-warning {{'var' is deprecated}} +} + +// test if attributes propagate to variables +extern int var; +int w() { + return var; // expected-warning {{'var' is deprecated}} +} + +int old_fn() __attribute__ ((deprecated)); +int old_fn(); +int (*fn_ptr)() = old_fn; // expected-warning {{'old_fn' is deprecated}} + +int old_fn() { + return old_fn()+1; // no warning, deprecated functions can use deprecated symbols. +} + + +struct foo { + int x __attribute__((deprecated)); +}; + +void test1(struct foo *F) { + ++F->x; // expected-warning {{'x' is deprecated}} +} + +typedef struct foo foo_dep __attribute__((deprecated)); +foo_dep *test2; // expected-warning {{'foo_dep' is deprecated}} diff --git a/test/Sema/attr-mode.c b/test/Sema/attr-mode.c new file mode 100644 index 000000000000..ac411d7c42dd --- /dev/null +++ b/test/Sema/attr-mode.c @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef int i16_1 __attribute((mode(HI))); +int i16_1_test[sizeof(i16_1) == 2 ? 1 : -1]; +typedef int i16_2 __attribute((__mode__(__HI__))); +int i16_2_test[sizeof(i16_1) == 2 ? 1 : -1]; + +typedef float f64 __attribute((mode(DF))); +int f64_test[sizeof(f64) == 8 ? 1 : -1]; + +typedef int invalid_1 __attribute((mode)); // expected-error{{attribute requires unquoted parameter}} +typedef int invalid_2 __attribute((mode())); // expected-error{{attribute requires unquoted parameter}} +typedef int invalid_3 __attribute((mode(II))); // expected-error{{unknown machine mode}} +typedef struct {int i,j,k;} invalid_4 __attribute((mode(SI))); // expected-error{{mode attribute only supported for integer and floating-point types}} +typedef float invalid_5 __attribute((mode(SI))); // expected-error{{type of machine mode does not match type of base type}} + +int **__attribute((mode(QI)))* i32; // expected-error{{mode attribute}} + +typedef _Complex double c32 __attribute((mode(SC))); +int c32_test[sizeof(c32) == 8 ? 1 : -1]; +typedef _Complex float c64 __attribute((mode(DC))); +typedef _Complex float c80 __attribute((mode(XC))); diff --git a/test/Sema/attr-nodebug.c b/test/Sema/attr-nodebug.c new file mode 100644 index 000000000000..512ecfdcafc6 --- /dev/null +++ b/test/Sema/attr-nodebug.c @@ -0,0 +1,8 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +int a __attribute__((nodebug)); // expected-warning {{'nodebug' attribute only applies to function types}} + +void t1() __attribute__((nodebug)); + +void t2() __attribute__((nodebug(2))); // expected-error {{attribute requires 0 argument(s)}} + diff --git a/test/Sema/attr-noinline.c b/test/Sema/attr-noinline.c new file mode 100644 index 000000000000..cf695f0d21f5 --- /dev/null +++ b/test/Sema/attr-noinline.c @@ -0,0 +1,8 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +int a __attribute__((noinline)); // expected-warning {{'noinline' attribute only applies to function types}} + +void t1() __attribute__((noinline)); + +void t2() __attribute__((noinline(2))); // expected-error {{attribute requires 0 argument(s)}} + diff --git a/test/Sema/attr-noreturn.c b/test/Sema/attr-noreturn.c new file mode 100644 index 000000000000..d1417f093ffb --- /dev/null +++ b/test/Sema/attr-noreturn.c @@ -0,0 +1,27 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +static void (*fp0)(void) __attribute__((noreturn)); + +static void __attribute__((noreturn)) f0(void) { + fatal(); +} + +// On K&R +int f1() __attribute__((noreturn)); + +int g0 __attribute__((noreturn)); // expected-warning {{'noreturn' attribute only applies to function types}} + +int f2() __attribute__((noreturn(1, 2))); // expected-error {{attribute requires 0 argument(s)}} + +void f3() __attribute__((noreturn)); +void f3() { + return; // expected-error {{function 'f3' declared 'noreturn' should not return}} +} + +#pragma clang diagnostic warning "-Winvalid-noreturn" + +void f4() __attribute__((noreturn)); +void f4() { + return; // expected-warning {{function 'f4' declared 'noreturn' should not return}} +} + diff --git a/test/Sema/attr-regparm.c b/test/Sema/attr-regparm.c new file mode 100644 index 000000000000..944f01489c8b --- /dev/null +++ b/test/Sema/attr-regparm.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -verify %s + +__attribute((regparm(2))) int x(void); +__attribute((regparm(1.0))) int x(void); // expected-error{{'regparm' attribute requires integer constant}} +__attribute((regparm(-1))) int x(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}} +__attribute((regparm(5))) int x(void); // expected-error{{'regparm' parameter must be between 0 and 3 inclusive}} +__attribute((regparm(5,3))) int x(void); // expected-error{{attribute requires 1 argument(s)}} diff --git a/test/Sema/attr-unused.c b/test/Sema/attr-unused.c new file mode 100644 index 000000000000..dbb5e630d7a1 --- /dev/null +++ b/test/Sema/attr-unused.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +static void (*fp0)(void) __attribute__((unused)); + +static void __attribute__((unused)) f0(void); + +// On K&R +int f1() __attribute__((unused)); + +int g0 __attribute__((unused)); + +int f2() __attribute__((unused(1, 2))); // expected-error {{attribute requires 0 argument(s)}} diff --git a/test/Sema/attr-used.c b/test/Sema/attr-used.c new file mode 100644 index 000000000000..fdabf7ff2ad5 --- /dev/null +++ b/test/Sema/attr-used.c @@ -0,0 +1,20 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +extern int l0 __attribute__((used)); // expected-warning {{used attribute ignored}} +__private_extern__ int l1 __attribute__((used)); // expected-warning {{used attribute ignored}} + +struct __attribute__((used)) s { // expected-warning {{'used' attribute only applies to variable and function types}} + int x; +}; + +int a __attribute__((used)); + +static void __attribute__((used)) f0(void) { +} + +void f1() { + static int a __attribute__((used)); + int b __attribute__((used)); // expected-warning {{used attribute ignored}} +} + + diff --git a/test/Sema/attr-warn_unused_result.c b/test/Sema/attr-warn_unused_result.c new file mode 100644 index 000000000000..b4ef1bbeaf0e --- /dev/null +++ b/test/Sema/attr-warn_unused_result.c @@ -0,0 +1,19 @@ +// RUN: clang-cc %s -fsyntax-only -verify +// rdar://6587766 + +int fn1() __attribute__ ((warn_unused_result)); +int fn2() __attribute__ ((pure)); +int fn3() __attribute__ ((const)); + +int foo() { + if (fn1() < 0 || fn2(2,1) < 0 || fn3(2) < 0) // no warnings + return -1; + + fn1(); // expected-warning {{expression result unused}} + fn2(92, 21); // expected-warning {{expression result unused}} + fn3(42); // expected-warning {{expression result unused}} + return 0; +} + +int bar __attribute__ ((warn_unused_result)); // expected-warning {{warning: 'warn_unused_result' attribute only applies to function types}} + diff --git a/test/Sema/attr-weak.c b/test/Sema/attr-weak.c new file mode 100644 index 000000000000..b79e1e7dfca7 --- /dev/null +++ b/test/Sema/attr-weak.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +extern int g0 __attribute__((weak)); +extern int g1 __attribute__((weak_import)); +int g2 __attribute__((weak)); +int g3 __attribute__((weak_import)); // expected-warning {{'weak_import' attribute cannot be specified on a definition}} +int __attribute__((weak_import)) g4(void); +int __attribute__((weak_import)) g5(void) { +} + +struct __attribute__((weak)) s0 {}; // expected-warning {{'weak' attribute only applies to variable and function types}} +struct __attribute__((weak_import)) s1 {}; // expected-warning {{'weak_import' attribute only applies to variable and function types}} + diff --git a/test/Sema/bitfield-layout.c b/test/Sema/bitfield-layout.c new file mode 100644 index 000000000000..4405c80fee6b --- /dev/null +++ b/test/Sema/bitfield-layout.c @@ -0,0 +1,32 @@ +// RUN: clang-cc %s -fsyntax-only -verify -triple=i686-apple-darwin9 + +#define CHECK_SIZE(kind, name, size) extern int name##1[sizeof(kind name) == size ? 1 : -1]; +#define CHECK_ALIGN(kind, name, size) extern int name##2[__alignof(kind name) == size ? 1 : -1]; + +// Zero-width bit-fields +struct a {char x; int : 0; char y;}; +CHECK_SIZE(struct, a, 5) +CHECK_ALIGN(struct, a, 1) + +union b {char x; int : 0; char y;}; +CHECK_SIZE(union, b, 1) +CHECK_ALIGN(union, b, 1) + +// Unnamed bit-field align +struct c {char x; int : 20;}; +CHECK_SIZE(struct, c, 4) +CHECK_ALIGN(struct, c, 1) + +union d {char x; int : 20;}; +CHECK_SIZE(union, d, 3) +CHECK_ALIGN(union, d, 1) + +// Bit-field packing +struct __attribute__((packed)) e {int x : 4, y : 30, z : 30;}; +CHECK_SIZE(struct, e, 8) +CHECK_ALIGN(struct, e, 1) + +// Alignment on bit-fields +struct f {__attribute((aligned(8))) int x : 30, y : 30, z : 30;}; +CHECK_SIZE(struct, f, 24) +CHECK_ALIGN(struct, f, 8) diff --git a/test/Sema/bitfield.c b/test/Sema/bitfield.c new file mode 100644 index 000000000000..655f74121a32 --- /dev/null +++ b/test/Sema/bitfield.c @@ -0,0 +1,36 @@ +// RUN: clang-cc %s -fsyntax-only -verify +enum e0; // expected-note{{forward declaration of 'enum e0'}} + +struct a { + int a : -1; // expected-error{{bit-field 'a' has negative width}} + + // rdar://6081627 + int b : 33; // expected-error{{size of bit-field 'b' exceeds size of its type (32 bits)}} + + int c : (1 + 0.25); // expected-error{{expression is not an integer constant expression}} + int d : (int)(1 + 0.25); + + // rdar://6138816 + int e : 0; // expected-error {{bit-field 'e' has zero width}} + + float xx : 4; // expected-error {{bit-field 'xx' has non-integral type}} + + // PR3607 + enum e0 f : 1; // expected-error {{field has incomplete type 'enum e0'}} + + int g : (_Bool)1; + + // PR4017 + char : 10; // expected-error {{size of anonymous bitfield exceeds size of its type (8 bits)}} + unsigned : -2; // expected-error {{anonymous bit-field has negative width (-2)}} + float : 12; // expected-error {{anonymous bit-field has non-integral type 'float'}} +}; + +struct b {unsigned x : 2;} x; +__typeof__(x.x+1) y; +int y; + +struct {unsigned x : 2;} x2; +__typeof__((x.x+=1)+1) y; +__typeof__(x.x<<1) y; +int y; diff --git a/test/Sema/block-args.c b/test/Sema/block-args.c new file mode 100644 index 000000000000..a2d8e5a86731 --- /dev/null +++ b/test/Sema/block-args.c @@ -0,0 +1,29 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fblocks + +void take(void*); + +void test() { + take(^(int x){}); + take(^(int x, int y){}); + take(^(int x, int y){}); + take(^(int x, int x){}); // expected-error {{redefinition of parameter 'x'}} + + + take(^(int x) { return x+1; }); + + int (^CP)(int) = ^(int x) { return x*x; }; + take(CP); + + int arg; + ^{return 1;}(); + ^{return 2;}(arg); // expected-error {{too many arguments to block call}} + ^(void){return 3;}(1); // expected-error {{too many arguments to block call}} + ^(){return 4;}(arg); // C style (...), ok. + ^(int x, ...){return 5;}(arg, arg); // Explicit varargs, ok. +} + +int main(int argc) { + ^(int argCount) { + argCount = 3; + }(argc); +} diff --git a/test/Sema/block-as-object.m b/test/Sema/block-as-object.m new file mode 100644 index 000000000000..219b1a065325 --- /dev/null +++ b/test/Sema/block-as-object.m @@ -0,0 +1,20 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fblocks + +@interface Whatever +- copy; +@end + +typedef long (^MyBlock)(id obj1, id obj2); + +void foo(MyBlock b) { + id bar = [b copy]; +} + +void foo2(id b) { +} + +void foo3(void (^block)(void)) { + foo2(block); + id x; + foo(x); +} diff --git a/test/Sema/block-byref-args.c b/test/Sema/block-byref-args.c new file mode 100644 index 000000000000..39745d54efa4 --- /dev/null +++ b/test/Sema/block-byref-args.c @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fblocks + +#include <stdio.h> + +int main(int argc, char **argv) { + __block void(*bobTheFunction)(void); + __block void(^bobTheBlock)(void); + + bobTheBlock = ^{;}; + + __block int JJJJ; + __attribute__((__blocks__(byref))) int III; + + int (^XXX)(void) = ^{ return III+JJJJ; }; + + return 0; +} + diff --git a/test/Sema/block-call.c b/test/Sema/block-call.c new file mode 100644 index 000000000000..9d3ff71e2195 --- /dev/null +++ b/test/Sema/block-call.c @@ -0,0 +1,55 @@ +// RUN: clang-cc -fsyntax-only -verify %s -fblocks + +int (*FP)(); +int (^IFP) (); +int (^II) (int); +int main() { + int (*FPL) (int) = FP; // C doesn't consider this an error. + + // For Blocks, the ASTContext::typesAreBlockCompatible() makes sure this is an error. + int (^PFR) (int) = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int (^)(int)'}} + PFR = II; // OK + + int (^IFP) () = PFR; + + + const int (^CIC) () = IFP; // expected-error {{incompatible block pointer types initializing 'int (^)()', expected 'int const (^)()'}} + + + const int (^CICC) () = CIC; + + int * const (^IPCC) () = 0; + + int * const (^IPCC1) () = IPCC; + + int * (^IPCC2) () = IPCC; // expected-error {{incompatible block pointer types initializing 'int *const (^)()', expected 'int *(^)()'}} + + int (^IPCC3) (const int) = PFR; + + + int (^IPCC4) (int, char (^CArg) (double)); + + + int (^IPCC5) (int, char (^CArg) (double)) = IPCC4; + + int (^IPCC6) (int, char (^CArg) (float)) = IPCC4; // expected-error {{incompatible block pointer types initializing 'int (^)(int, char (^)(double))', expected 'int (^)(int, char (^)(float))'}} + + IPCC2 = 0; + IPCC2 = 1; // expected-error {{invalid conversion assigning integer 'int', expected block pointer 'int *(^)()'}} + int (^x)() = 0; + int (^y)() = 3; // expected-error {{invalid conversion initializing integer 'int', expected block pointer 'int (^)()'}} + int a = 1; + int (^z)() = a+4; // expected-error {{invalid conversion initializing integer 'int', expected block pointer 'int (^)()'}} +} + +int blah() { + int (^IFP) (float); + char (^PCP)(double, double, char); + + IFP(1.0); + IFP (1.0, 2.0); // expected-error {{too many arguments to block call}} + + char ch = PCP(1.0, 2.0, 'a'); + return PCP(1.0, 2.0); // expected-error {{too few arguments to block}} +} + diff --git a/test/Sema/block-explicit-return-type.c b/test/Sema/block-explicit-return-type.c new file mode 100644 index 000000000000..c7b26b3d6bf6 --- /dev/null +++ b/test/Sema/block-explicit-return-type.c @@ -0,0 +1,81 @@ +// RUN: clang-cc -ObjC -fsyntax-only %s -verify -fblocks +// FIXME: should compile +// Test for blocks with explicit return type specified. + +typedef float * PF; +float gf; + +@interface NSView + - (id) some_method_that_returns_id; +@end + +NSView *some_object; + +void some_func (NSView * (^) (id)); + +typedef struct dispatch_item_s *dispatch_item_t; +typedef void (^completion_block_t)(void); + +typedef double (^myblock)(int); +double test(myblock I); + +int main() +{ + __block int x = 1; + __block int y = 2; + + (void)^void *{ return 0; }; + + (void)^float(float y){ return y; }; + + (void)^double (float y, double d) + { + if (y) + return d; + else + return y; + }; + + const char * (^chb) (int flag, const char *arg, char *arg1) = ^ const char * (int flag, const char *arg, char *arg1) { + if (flag) + return 0; + if (flag == 1) + return arg; + else if (flag == 2) + return ""; + return arg1; + }; + + (void)^PF { return &gf; }; + + some_func(^ NSView * (id whatever) { return [some_object some_method_that_returns_id]; }); + + double res = test(^(int z){x = y+z; return (double)z; }); +} + +void func() +{ + completion_block_t X; + + completion_block_t (^blockx)(dispatch_item_t) = ^completion_block_t (dispatch_item_t item) { + return X; + }; + + completion_block_t (^blocky)(dispatch_item_t) = ^(dispatch_item_t item) { + return X; + }; + + blockx = blocky; + +} + + +// intent: block taking int returning block that takes char,int and returns int +int (^(^block)(double x))(char, short); + +void foo() { + int one = 1; + block = ^(double x){ return ^(char c, short y) { return one + c + y; };}; // expected-error {{returning block that lives on the local stack}} + // or: + block = ^(double x){ return ^(char c, short y) { return one + (int)c + y; };}; // expected-error {{returning block that lives on the local stack}} +} diff --git a/test/Sema/block-labels.c b/test/Sema/block-labels.c new file mode 100644 index 000000000000..f0f8c4856d81 --- /dev/null +++ b/test/Sema/block-labels.c @@ -0,0 +1,17 @@ +// RUN: clang-cc %s -verify -fblocks -fsyntax-only + +int a() { + A:if (1) xx(); + return ^{A:return 1;}(); +} +int b() { + A: return ^{int a; A:return 1;}(); +} + +int d() { + A: return ^{int a; A: a = ^{int a; A:return 1;}() + ^{int b; A:return 2;}(); return a; }(); +} + +int c() { + goto A; return ^{ A:return 1;}(); // expected-error {{use of undeclared label 'A'}} +} diff --git a/test/Sema/block-literal.c b/test/Sema/block-literal.c new file mode 100644 index 000000000000..19d476fc294f --- /dev/null +++ b/test/Sema/block-literal.c @@ -0,0 +1,124 @@ +// RUN: clang-cc -fsyntax-only %s -verify -fblocks + +void I( void (^)(void)); +void (^noop)(void); + +void nothing(); +int printf(const char*, ...); + +typedef void (^T) (void); + +void takeclosure(T); +int takeintint(int (^C)(int)) { return C(4); } + +T somefunction() { + if (^{ }) + nothing(); + + noop = ^{}; + + noop = ^{printf("\nClosure\n"); }; + + I(^{ }); + + return ^{printf("\nClosure\n"); }; +} +void test2() { + int x = 4; + + takeclosure(^{ printf("%d\n", x); }); + + while (1) { + takeclosure(^{ + break; // expected-error {{'break' statement not in loop or switch statement}} + continue; // expected-error {{'continue' statement not in loop statement}} + while(1) break; // ok + goto foo; // expected-error {{goto not allowed}} + }); + break; + } + +foo: + takeclosure(^{ x = 4; }); // expected-error {{variable is not assignable (missing __block type specifier)}} + __block y = 7; // expected-warning {{type specifier missing, defaults to 'int'}} + takeclosure(^{ y = 8; }); +} + + +void (^test3())(void) { + return ^{}; +} + +void test4() { + void (^noop)(void) = ^{}; + void (*noop2)() = 0; +} + +void myfunc(int (^block)(int)) {} + +void myfunc3(const int *x); + +void test5() { + int a; + + myfunc(^(int abcd) { + myfunc3(&a); + return 1; + }); +} + +void *X; + +void test_arguments() { + int y; + int (^c)(char); + (1 ? c : 0)('x'); + (1 ? 0 : c)('x'); + + (1 ? c : c)('x'); +} + +static int global_x = 10; +void (^global_block)(void) = ^{ printf("global x is %d\n", global_x); }; + +typedef void (^void_block_t)(void); + +static const void_block_t myBlock = ^{ }; + +static const void_block_t myBlock2 = ^ void(void) { }; + +#if 0 +// Old syntax. FIXME: convert/test. +void test_byref() { + int i; + + X = ^{| g |}; // error {{use of undeclared identifier 'g'}} + + X = ^{| i,i,i | }; + + X = ^{|i| i = 0; }; + +} + +// TODO: global closures someday. +void *A = ^{}; +void *B = ^(int){ A = 0; }; + + +// Closures can not take return types at this point. +void test_retvals() { + // Explicit return value. + ^int{}; // error {{closure with explicit return type requires argument list}} + X = ^void(){}; + + // Optional specification of return type. + X = ^char{ return 'x'; }; // error {{closure with explicit return type requires argument list}} + + X = ^/*missing declspec*/ *() { return (void*)0; }; + X = ^void*() { return (void*)0; }; + + //X = ^char(short c){ if (c) return c; else return (int)4; }; + +} + +#endif diff --git a/test/Sema/block-misc.c b/test/Sema/block-misc.c new file mode 100644 index 000000000000..93ca3c49d425 --- /dev/null +++ b/test/Sema/block-misc.c @@ -0,0 +1,187 @@ +// RUN: clang-cc -fsyntax-only -verify %s -fblocks +void donotwarn(); + +int (^IFP) (); +int (^II) (int); +int test1() { + int (^PFR) (int) = 0; // OK + PFR = II; // OK + + if (PFR == II) // OK + donotwarn(); + + if (PFR == IFP) // expected-error {{comparison of distinct block types}} + donotwarn(); + + if (PFR == (int (^) (int))IFP) // OK + donotwarn(); + + if (PFR == 0) // OK + donotwarn(); + + if (PFR) // OK + donotwarn(); + + if (!PFR) // OK + donotwarn(); + + return PFR != IFP; // expected-error {{comparison of distinct block types}} +} + +int test2(double (^S)()) { + double (^I)(int) = (void*) S; + (void*)I = (void *)S; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} + + void *pv = I; + + pv = S; + + I(1); + + return (void*)I == (void *)S; +} + +int^ x; // expected-error {{block pointer to non-function type is invalid}} +int^^ x1; // expected-error {{block pointer to non-function type is invalid}} expected-error {{block pointer to non-function type is invalid}} + +int test3() { + char *^ y; // expected-error {{block pointer to non-function type is invalid}} +} + + + +enum {NSBIRLazilyAllocated = 0}; + +int test4(int argc) { // rdar://6251437 + ^{ + switch (argc) { + case NSBIRLazilyAllocated: // is an integer constant expression. + default: + break; + } + }(); + return 0; +} + + +// rdar://6257721 - reference to static/global is byref by default. +static int test5g; +void test5() { + bar(^{ test5g = 1; }); +} + +// rdar://6405429 - __func__ in a block refers to the containing function name. +const char*test6() { + return ^{ + return __func__; + } (); +} + +// radr://6732116 - block comparisons +void (^test7a)(); +int test7(void (^p)()) { + return test7a == p; +} + + +void test8() { +somelabel: + // FIXME: This should say "jump out of block not legal" when gotos are allowed. + ^{ goto somelabel; }(); // expected-error {{goto not allowed in block literal}} +} + +void test9() { + goto somelabel; // expected-error {{use of undeclared label 'somelabel'}} + ^{ somelabel: ; }(); +} + +void test10(int i) { + switch (i) { + case 41: ; + ^{ case 42: ; }(); // expected-error {{'case' statement not in switch statement}} + } +} + +void test11(int i) { + switch (i) { + case 41: ; + ^{ break; }(); // expected-error {{'break' statement not in loop or switch statement}} + } + + for (; i < 100; ++i) + ^{ break; }(); // expected-error {{'break' statement not in loop or switch statement}} +} + +void (^test12f)(void); +void test12() { + test12f = ^test12f; // expected-error {{type name requires a specifier or qualifier}} expected-error {{expected expression}} +} + +// rdar://6808730 +void *test13 = ^{ + int X = 32; + + void *P = ^{ + return X+4; // References outer block's "X", so outer block is constant. + }; +}; + +void test14() { + int X = 32; + static void *P = ^{ // expected-error {{initializer element is not a compile-time constant}} + + void *Q = ^{ + // References test14's "X": outer block is non constant. + return X+4; + }; + }; +} + +enum { LESS }; + +void foo(long (^comp)()) { +} + +void (^test15f)(void); +void test15() { + foo(^{ return LESS; }); // expected-error {{incompatible block pointer types passing 'int (^)(void)', expected 'long (^)()'}} +} + +__block int test16i; // expected-error {{__block attribute not allowed, only allowed on local variables}} + +void test16(__block int i) { // expected-error {{__block attribute not allowed, only allowed on local variables}} + int size = 5; + extern __block double extern_var; // expected-error {{__block attribute not allowed, only allowed on local variables}} + static __block char * pch; // expected-error {{__block attribute not allowed, only allowed on local variables}} + __block int a[size]; // expected-error {{__block attribute not allowed on declaration with a variably modified type}} + __block int (*ap)[size]; // expected-error {{__block attribute not allowed on declaration with a variably modified type}} +} + +void test17() { + void (^bp)(int); + void (*rp)(int); + void (^bp1)(); + void *vp = bp; + + f(1 ? bp : vp); + f(1 ? vp : bp); + f(1 ? bp : bp1); // expected-error {{incompatible operand types ('void (^)(int)' and 'void (^)()')}} + (void)(bp > rp); // expected-error {{invalid operands}} + (void)(bp > 0); // expected-error {{invalid operands}} + (void)(bp > bp); // expected-error {{invalid operands}} + (void)(bp > vp); // expected-error {{invalid operands}} + f(1 ? bp : rp); // expected-error {{incompatible operand types ('void (^)(int)' and 'void (*)(int)')}} + (void)(bp == 1); // expected-error {{invalid operands to binary expression}} + (void)(bp == 0); + (void)(1 == bp); // expected-error {{invalid operands to binary expression}} + (void)(0 == bp); + (void)(bp < 1); // expected-error {{invalid operands to binary expression}} + (void)(bp < 0); // expected-error {{invalid operands to binary expression}} + (void)(1 < bp); // expected-error {{invalid operands to binary expression}} + (void)(0 < bp); // expected-error {{invalid operands to binary expression}} +} + +void test18() { + void (^const blockA)(void) = ^{ }; + blockA = ^{ }; // expected-error {{read-only variable is not assignable}} +} diff --git a/test/Sema/block-printf-attribute-1.c b/test/Sema/block-printf-attribute-1.c new file mode 100644 index 000000000000..ce30b8e855b7 --- /dev/null +++ b/test/Sema/block-printf-attribute-1.c @@ -0,0 +1,15 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fblocks + +int main() +{ + void (^b) (int arg, const char * format, ...) __attribute__ ((__format__ (__printf__, 1, 3))) = // expected-error {{format argument not a string type}} + ^ __attribute__ ((__format__ (__printf__, 1, 3))) (int arg, const char * format, ...) {}; // expected-error {{format argument not a string type}} + + void (^z) (int arg, const char * format, ...) __attribute__ ((__format__ (__printf__, 2, 3))) = ^ __attribute__ ((__format__ (__printf__, 2, 3))) (int arg, const char * format, ...) {}; + + // FIXME: argument type poking not yet supportted. + z(1, "%s", 1); /* { dg-warning "format \\'\%s\\' expects type \\'char \\*\\'\, but argument 3 has type \\'int\\'" } */ + z(1, "%s", "HELLO"); // OK + +} + diff --git a/test/Sema/block-return.c b/test/Sema/block-return.c new file mode 100644 index 000000000000..e1a3cfd8123d --- /dev/null +++ b/test/Sema/block-return.c @@ -0,0 +1,104 @@ +// RUN: clang-cc -fsyntax-only %s -verify -fblocks + +typedef void (^CL)(void); + +CL foo() { + short y; + short (^add1)(void) = ^{ return y+1; }; // expected-error {{incompatible block pointer types initializing 'int (^)(void)', expected 'short (^)(void)'}} + + CL X = ^{ + if (2) + return; + return 1; // expected-error {{void block should not return a value}} + }; + + int (^Y) (void) = ^{ + if (3) + return 1; + else + return; // expected-error {{non-void block should return a value}} + }; + + char *(^Z)(void) = ^{ + if (3) + return ""; + else + return (char*)0; + }; + + double (^A)(void) = ^ { // expected-error {{incompatible block pointer types initializing 'float (^)(void)', expected 'double (^)(void)'}} + if (1) + return (float)1.0; + else + if (2) + return (double)2.0; + return 1; + }; + char *(^B)(void) = ^{ + if (3) + return ""; + else + return 2; // expected-warning {{incompatible integer to pointer conversion returning 'int', expected 'char *'}} + }; + + return ^{ return 1; }; // expected-error {{incompatible block pointer types returning 'int (^)(void)', expected 'CL'}} +} + +typedef int (^CL2)(void); + +CL2 foo2() { + return ^{ return 1; }; +} + +typedef unsigned int * uintptr_t; +typedef char Boolean; +typedef int CFBasicHash; + +#define INVOKE_CALLBACK2(P, A, B) (P)(A, B) + +typedef struct { + Boolean (^isEqual)(const CFBasicHash *, uintptr_t stack_value_or_key1, uintptr_t stack_value_or_key2, Boolean is_key); +} CFBasicHashCallbacks; + +int foo3() { + CFBasicHashCallbacks cb; + + Boolean (*value_equal)(uintptr_t, uintptr_t) = 0; + + cb.isEqual = ^(const CFBasicHash *table, uintptr_t stack_value_or_key1, uintptr_t stack_value_or_key2, Boolean is_key) { + return (Boolean)(uintptr_t)INVOKE_CALLBACK2(value_equal, (uintptr_t)stack_value_or_key1, (uintptr_t)stack_value_or_key2); + }; +} + +static int funk(char *s) { + if (^{} == ((void*)0)) + return 1; + else + return 0; +} +void foo4() { + int (^xx)(const char *s) = ^(char *s) { return 1; }; // expected-error {{incompatible block pointer types initializing 'int (^)(char *)', expected 'int (^)(char const *)'}} + int (*yy)(const char *s) = funk; // expected-warning {{incompatible pointer types initializing 'int (char *)', expected 'int (*)(char const *)'}} + + int (^nested)(char *s) = ^(char *str) { void (^nest)(void) = ^(void) { printf("%s\n", str); }; next(); return 1; }; // expected-warning{{implicitly declaring C library function 'printf' with type 'int (char const *, ...)'}} \ + // expected-note{{please include the header <stdio.h> or explicitly provide a declaration for 'printf'}} +} + +typedef void (^bptr)(void); + +bptr foo5(int j) { + __block int i; + if (j) + return ^{ ^{ i=0; }(); }; // expected-error {{returning block that lives on the local stack}} + return ^{ i=0; }; // expected-error {{returning block that lives on the local stack}} +} + +int (*funcptr3[5])(long); +int sz8 = sizeof(^int (*[5])(long) {return funcptr3;}); // expected-error {{block declared as returning an array}} + +void foo6() { + int (^b)(int) __attribute__((noreturn)); + b = ^ (int i) __attribute__((noreturn)) { return 1; }; // expected-error {{block declared 'noreturn' should not return}} + b(1); + int (^c)(void) __attribute__((noreturn)) = ^ __attribute__((noreturn)) { return 100; }; // expected-error {{block declared 'noreturn' should not return}} +} diff --git a/test/Sema/block-sentinel-attribute.c b/test/Sema/block-sentinel-attribute.c new file mode 100644 index 000000000000..a7d4df108ea7 --- /dev/null +++ b/test/Sema/block-sentinel-attribute.c @@ -0,0 +1,25 @@ +// RUN: clang-cc -fblocks -fsyntax-only -verify %s + +void (^e) (int arg, const char * format, ...) __attribute__ ((__sentinel__ (1,1))); + +int main() +{ + void (^bbad) (int arg, const char * format) __attribute__ ((__sentinel__)) ; // expected-warning {{sentinel' attribute only supported for variadic blocks}} + void (^b) (int arg, const char * format, ...) __attribute__ ((__sentinel__)) = // expected-note {{block has been explicitly marked sentinel here}} + ^ __attribute__ ((__sentinel__)) (int arg, const char * format, ...) {}; + void (^z) (int arg, const char * format, ...) __attribute__ ((__sentinel__ (2))) = ^ __attribute__ ((__sentinel__ (2))) (int arg, const char * format, ...) {}; // expected-note {{block has been explicitly marked sentinel here}} + + + void (^y) (int arg, const char * format, ...) __attribute__ ((__sentinel__ (5))) = ^ __attribute__ ((__sentinel__ (5))) (int arg, const char * format, ...) {}; // expected-note {{block has been explicitly marked sentinel here}} + + b(1, "%s", (void*)0); // OK + b(1, "%s", 0); // expected-warning {{missing sentinel in block call}} + z(1, "%s",4 ,1,0); // expected-warning {{missing sentinel in block call}} + z(1, "%s", (void*)0, 1, 0); // OK + + y(1, "%s", 1,2,3,4,5,6,7); // expected-warning {{missing sentinel in block call}} + + y(1, "%s", (void*)0,3,4,5,6,7); // OK + +} + diff --git a/test/Sema/block-storageclass.c b/test/Sema/block-storageclass.c new file mode 100644 index 000000000000..3d2527b3f4e8 --- /dev/null +++ b/test/Sema/block-storageclass.c @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fblocks + +#include <stdio.h> +void _Block_byref_release(void*src){} + +int main() { + __block int X = 1234; + __block const char * message = "HELLO"; + + X = X - 1234; + + X += 1; + + printf ("%s(%d)\n", message, X); + X -= 1; + + return X; +} diff --git a/test/Sema/builtin-object-size.c b/test/Sema/builtin-object-size.c new file mode 100644 index 000000000000..4b15cb1f0e23 --- /dev/null +++ b/test/Sema/builtin-object-size.c @@ -0,0 +1,28 @@ +// RUN: clang-cc -fsyntax-only -verify %s && +// RUN: clang-cc -fsyntax-only -triple x86_64-apple-darwin9 -verify %s + +int a[10]; + +int f0() { + return __builtin_object_size(&a); // expected-error {{too few arguments to function}} +} +int f1() { + return (__builtin_object_size(&a, 0) + + __builtin_object_size(&a, 1) + + __builtin_object_size(&a, 2) + + __builtin_object_size(&a, 3)); +} +int f2() { + return __builtin_object_size(&a, -1); // expected-error {{argument should be a value from 0 to 3}} +} +int f3() { + return __builtin_object_size(&a, 4); // expected-error {{argument should be a value from 0 to 3}} +} + + +// rdar://6252231 - cannot call vsnprintf with va_list on x86_64 +void f4(const char *fmt, ...) { + __builtin_va_list args; + __builtin___vsnprintf_chk (0, 42, 0, 11, fmt, args); +} + diff --git a/test/Sema/builtin-prefetch.c b/test/Sema/builtin-prefetch.c new file mode 100644 index 000000000000..6b39e75d5257 --- /dev/null +++ b/test/Sema/builtin-prefetch.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int foo() { + int a; + __builtin_prefetch(&a); + __builtin_prefetch(&a, 1); + __builtin_prefetch(&a, 1, 2); + __builtin_prefetch(&a, 1, 9, 3); // expected-error{{too many arguments to function}} + __builtin_prefetch(&a, "hello", 2); // expected-error{{argument to __builtin_prefetch must be a constant integer}} + __builtin_prefetch(&a, 2); // expected-error{{argument should be a value from 0 to 1}} + __builtin_prefetch(&a, 0, 4); // expected-error{{argument should be a value from 0 to 3}} + __builtin_prefetch(&a, -1, 4); // expected-error{{argument should be a value from 0 to 1}} +} diff --git a/test/Sema/builtin-stackaddress.c b/test/Sema/builtin-stackaddress.c new file mode 100644 index 000000000000..67582a549f5f --- /dev/null +++ b/test/Sema/builtin-stackaddress.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s +void* a(unsigned x) { +return __builtin_return_address(0); +} + +void b(unsigned x) { +return __builtin_return_address(x); // expected-error{{the level argument for a stack address builtin must be constant}} +} + +void* c(unsigned x) { +return __builtin_frame_address(0); +} + +void d(unsigned x) { +return __builtin_frame_address(x); // expected-error{{the level argument for a stack address builtin must be constant}} +} diff --git a/test/Sema/builtins.c b/test/Sema/builtins.c new file mode 100644 index 000000000000..e57aec51bc55 --- /dev/null +++ b/test/Sema/builtins.c @@ -0,0 +1,52 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic -triple=i686-apple-darwin9 +// This test needs to set the target because it uses __builtin_ia32_vec_ext_v4si + +int test1(float a, int b) { + return __builtin_isless(a, b); +} +int test2(int a, int b) { + return __builtin_islessequal(a, b); // expected-error {{floating point type}} +} + +int test3(double a, float b) { + return __builtin_isless(a, b); +} +int test4(int* a, double b) { + return __builtin_islessequal(a, b); // expected-error {{floating point type}} +} + +int test5(float a, long double b) { + return __builtin_isless(a, b, b); // expected-error {{too many arguments}} +} +int test6(float a, long double b) { + return __builtin_islessequal(a); // expected-error {{too few arguments}} +} + + +#define CFSTR __builtin___CFStringMakeConstantString +void test7() { + CFSTR("\242"); + CFSTR("\0"); // expected-warning {{ CFString literal contains NUL character }} + CFSTR(242); // expected-error {{ CFString literal is not a string constant }} expected-warning {{incompatible integer to pointer conversion}} + CFSTR("foo", "bar"); // expected-error {{too many arguments to function call}} +} + + +typedef __attribute__(( ext_vector_type(16) )) unsigned char uchar16; + +// rdar://5905347 +unsigned char test8( short v ) { + uchar16 c; + return __builtin_ia32_vec_ext_v4si( c ); // expected-error {{too few arguments to function}} +} + + +// atomics. + +unsigned char test9(short v) { + unsigned i, old; + + old = __sync_fetch_and_add(); // expected-error {{too few arguments to function call}} + old = __sync_fetch_and_add(&old); // expected-error {{too few arguments to function call}} + old = __sync_fetch_and_add((int**)0, 42i); // expected-warning {{imaginary constants are an extension}} +} diff --git a/test/Sema/c89-2.c b/test/Sema/c89-2.c new file mode 100644 index 000000000000..723bd7c18d88 --- /dev/null +++ b/test/Sema/c89-2.c @@ -0,0 +1,7 @@ +/* RUN: not clang-cc %s -std=c89 -pedantic-errors + */ + +/* We can't put expected-warning lines on #if lines. */ + +#if 1LL /* expected-warning {{long long}} */ +#endif diff --git a/test/Sema/c89.c b/test/Sema/c89.c new file mode 100644 index 000000000000..e7585c31926c --- /dev/null +++ b/test/Sema/c89.c @@ -0,0 +1,82 @@ +/* RUN: clang-cc %s -std=c89 -pedantic -fsyntax-only -verify + */ +void test1() { + { + int i; + i = i + 1; + int j; /* expected-warning {{mixing declarations and code}} */ + } + { + __extension__ int i; + i = i + 1; + int j; /* expected-warning {{mixing declarations and code}} */ + } + { + int i; + i = i + 1; + __extension__ int j; /* expected-warning {{mixing declarations and code}} */ + } +} + +long long test2; /* expected-warning {{extension}} */ + + +void test3(int i) { + int A[i]; /* expected-warning {{variable length array}} */ +} + +int test4 = 0LL; /* expected-warning {{long long}} */ + +/* PR1999 */ +void test5(register); + +/* PR2041 */ +int *restrict; +int *__restrict; /* expected-error {{expected identifier}} */ + + +/* Implicit int, always ok */ +test6() {} + +/* PR2012 */ +test7; /* expected-warning {{declaration specifier missing, defaulting to 'int'}} */ + +void test8(int, x); /* expected-warning {{declaration specifier missing, defaulting to 'int'}} */ + +typedef int sometype; +int a(sometype, y) {return 0;} /* expected-warning {{declaration specifier missing, defaulting to 'int'}} \ + expected-error {{parameter name omitted}}*/ + + + + +void bar (void *); +void f11 (z) /* expected-error {{may not have 'void' type}} */ +void z; +{ bar (&z); } + +typedef void T; +void foo(T); /* typedef for void is allowed */ + +void foo(void) {} + +/* PR2759 */ +void test10 (int x[*]); /* expected-warning {{use of C99-specific array features}} */ +void test11 (int x[static 4]); /* expected-warning {{use of C99-specific array features}} */ + +void test12 (int x[const 4]) { /* expected-warning {{use of C99-specific array features}} */ + int Y[x[1]]; /* expected-warning {{variable length arrays are a C99 feature, accepted as an extension}} */ +} + +/* PR4074 */ +struct test13 { + int X[23]; +} test13a(); + +void test13b() { + int a = test13a().X[1]; /* expected-warning {{ISO C90 does not allow subscripting non-lvalue array}} */ + int b = 1[test13a().X]; /* expected-warning {{ISO C90 does not allow subscripting non-lvalue array}} */ +} + +/* Make sure we allow *test14 as a "function designator" */ +int test14() { return (&*test14)(); } diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c new file mode 100644 index 000000000000..cb69c59c403a --- /dev/null +++ b/test/Sema/callingconv.c @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +void __attribute__((fastcall)) foo(float *a) { +} + +void __attribute__((stdcall)) bar(float *a) { +} + +void __attribute__((fastcall(1))) baz(float *a) { // expected-error {{attribute requires 0 argument(s)}} +} diff --git a/test/Sema/carbon-pth.c b/test/Sema/carbon-pth.c new file mode 100644 index 000000000000..c956d2a7a1c8 --- /dev/null +++ b/test/Sema/carbon-pth.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -mcpu=pentium4 -emit-pth -o %t %s && +// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s && +// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s -E %s -o /dev/null +#ifdef __APPLE__ +#include <Carbon/Carbon.h> +#endif + diff --git a/test/Sema/carbon.c b/test/Sema/carbon.c new file mode 100644 index 000000000000..5eda4385ac49 --- /dev/null +++ b/test/Sema/carbon.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -mcpu=pentium4 %s -print-stats +#ifdef __APPLE__ +#include <Carbon/Carbon.h> +#endif + diff --git a/test/Sema/cast-to-union.c b/test/Sema/cast-to-union.c new file mode 100644 index 000000000000..24f913b9ea33 --- /dev/null +++ b/test/Sema/cast-to-union.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +union u { int i; }; +void f(union u); + +void test(int x) { + f((union u)x); // expected-warning {{C99 forbids casts to union type}} + f((union u)&x); // expected-error {{cast to union type from type 'int *' not present in union}} +} + +union u w = (union u)2; // expected-warning {{C99 forbids casts to union type}} +union u ww = (union u)1.0; // expected-error{{cast to union type from type 'double' not present in union}} +union u x = 7; // expected-error{{incompatible type initializing 'int', expected 'union u'}} +int i; +union u zz = (union u)i; // expected-error{{initializer element is not a compile-time constant}} expected-warning {{C99 forbids casts to union type}} + +struct s {int a, b;}; +struct s y = { 1, 5 }; +struct s z = (struct s){ 1, 5 }; diff --git a/test/Sema/cast.c b/test/Sema/cast.c new file mode 100644 index 000000000000..ec19626d28e0 --- /dev/null +++ b/test/Sema/cast.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only %s -verify + +typedef struct { unsigned long bits[(((1) + (64) - 1) / (64))]; } cpumask_t; +cpumask_t x; +void foo() { + (void)x; +} +void bar() { + char* a; + double b; + b = (double)a; // expected-error {{pointer cannot be cast to type}} + a = (char*)b; // expected-error {{cannot be cast to a pointer type}} +} + diff --git a/test/Sema/check-increment.c b/test/Sema/check-increment.c new file mode 100644 index 000000000000..9809544854d8 --- /dev/null +++ b/test/Sema/check-increment.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stdio.h> +typedef int *pint; +int main() { + int a[5] = {0}; + pint p = a; + p++; + printf("%d\n", *p); +} diff --git a/test/Sema/compare.c b/test/Sema/compare.c new file mode 100644 index 000000000000..4b44bf5b96a0 --- /dev/null +++ b/test/Sema/compare.c @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +int test(char *C) { // nothing here should warn. + return C != ((void*)0); + return C != (void*)0; + return C != 0; +} + +int equal(char *a, const char *b) +{ + return a == b; +} + +int arrays(char (*a)[5], char(*b)[10], char(*c)[5]) { + int d = (a == c); + return a == b; // expected-warning {{comparison of distinct pointer types}} +} diff --git a/test/Sema/complex-int.c b/test/Sema/complex-int.c new file mode 100644 index 000000000000..5977b4d1e0cb --- /dev/null +++ b/test/Sema/complex-int.c @@ -0,0 +1,52 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +void a() { +__complex__ int arr; +__complex__ short brr; +__complex__ unsigned xx; +__complex__ signed yy; +__complex__ int result; +int ii; +int aa = 1 + 1.0iF; + +result = arr*ii; +result = ii*brr; + +result = arr*brr; +result = xx*yy; + +switch (arr) { // expected-error{{statement requires expression of integer type ('_Complex int' invalid)}} + case brr: ; // expected-error{{expression is not an integer constant expression}} + case xx: ; // expected-error{{expression is not an integer constant expression}} +} +} + +void Tester() { +__complex short a1; +__complex int a2; +__complex float a3; +__complex double a4; +short a5; +int a6; +float a7; +double a8; +#define TestPair(m,n) int x##m##n = a##m+a##n; +#define TestPairs(m) TestPair(m,1) TestPair(m,2) \ + TestPair(m,3) TestPair(m,4) \ + TestPair(m,5) TestPair(m,6) \ + TestPair(m,7) TestPair(m,8) +TestPairs(1); TestPairs(2); +TestPairs(3); TestPairs(4); +TestPairs(5); TestPairs(6); +TestPairs(7); TestPairs(8); +} + +// rdar://6097730 +void test3(_Complex int *x) { + *x = ~*x; +} + +void test4(_Complex float *x) { + *x = ~*x; +} + diff --git a/test/Sema/complex-promotion.c b/test/Sema/complex-promotion.c new file mode 100644 index 000000000000..3d86c20eb248 --- /dev/null +++ b/test/Sema/complex-promotion.c @@ -0,0 +1,15 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +float a; + +int b[__builtin_classify_type(a + 1i) == 9 ? 1 : -1]; +int c[__builtin_classify_type(1i + a) == 9 ? 1 : -1]; + +double d; +__typeof__ (d + 1i) e; + +int f[sizeof(e) == 2 * sizeof(double) ? 1 : -1]; + +int g; +int h[__builtin_classify_type(g + 1.0i) == 9 ? 1 : -1]; +int i[__builtin_classify_type(1.0i + a) == 9 ? 1 : -1]; diff --git a/test/Sema/compound-literal.c b/test/Sema/compound-literal.c new file mode 100644 index 000000000000..b51bcfe2a233 --- /dev/null +++ b/test/Sema/compound-literal.c @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +struct foo { int a, b; }; + +static struct foo t = (struct foo){0,0}; +static struct foo t2 = {0,0}; +static struct foo t3 = t2; // -expected-error {{initializer element is not a compile-time constant}} +static int *p = (int []){2,4}; +static int x = (int){1}; + +static int *p2 = (int []){2,x}; // -expected-error {{initializer element is not a compile-time constant}} +static long *p3 = (long []){2,"x"}; // -expected-warning {{incompatible pointer to integer conversion initializing 'char [2]', expected 'long'}} + +typedef struct { } cache_t; // -expected-warning{{use of empty struct extension}} +static cache_t clo_I1_cache = ((cache_t) { } ); // -expected-warning{{use of GNU empty initializer extension}} + +typedef struct Test {int a;int b;} Test; +static Test* ll = &(Test) {0,0}; + +extern void fooFunc(struct foo *pfoo); + +int main(int argc, char **argv) { + int *l = (int []){x, *p, *p2}; + fooFunc(&(struct foo){ 1, 2 }); +} + +struct Incomplete; // expected-note{{forward declaration of 'struct Incomplete'}} +struct Incomplete* I1 = &(struct Incomplete){1, 2, 3}; // -expected-error {{variable has incomplete type}} +void IncompleteFunc(unsigned x) { + struct Incomplete* I2 = (struct foo[x]){1, 2, 3}; // -expected-error {{variable-sized object may not be initialized}} + (void){1,2,3}; // -expected-error {{variable has incomplete type}} + (void(void)) { 0 }; // -expected-error{{illegal initializer type 'void (void)'}} +} diff --git a/test/Sema/conditional-expr.c b/test/Sema/conditional-expr.c new file mode 100644 index 000000000000..1f0a9deb5e47 --- /dev/null +++ b/test/Sema/conditional-expr.c @@ -0,0 +1,51 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s +void foo() { + *(0 ? (double *)0 : (void *)0) = 0; + // FIXME: GCC doesn't consider the the following two statements to be errors. + *(0 ? (double *)0 : (void *)(int *)0) = 0; // expected-error {{incomplete type 'void' is not assignable}} + *(0 ? (double *)0 : (void *)(double *)0) = 0; // expected-error {{incomplete type 'void' is not assignable}} + *(0 ? (double *)0 : (int *)(void *)0) = 0; // expected-error {{incomplete type 'void' is not assignable}} expected-warning {{pointer type mismatch ('double *' and 'int *')}} + *(0 ? (double *)0 : (double *)(void *)0) = 0; + *((void *) 0) = 0; // expected-error {{incomplete type 'void' is not assignable}} + double *dp; + int *ip; + void *vp; + + dp = vp; + vp = dp; + ip = dp; // expected-warning {{incompatible pointer types assigning 'double *', expected 'int *'}} + dp = ip; // expected-warning {{incompatible pointer types assigning 'int *', expected 'double *'}} + dp = 0 ? (double *)0 : (void *)0; + vp = 0 ? (double *)0 : (void *)0; + ip = 0 ? (double *)0 : (void *)0; // expected-warning {{incompatible pointer types assigning 'double *', expected 'int *'}} + + const int *cip; + vp = (0 ? vp : cip); // expected-warning {{discards qualifiers}} + vp = (0 ? cip : vp); // expected-warning {{discards qualifiers}} + + int i = 2; + int (*pf)[2]; + int (*pv)[i]; + pf = (i ? pf : pv); + + enum {xxx,yyy,zzz} e, *ee; + short x; + ee = ee ? &x : ee ? &i : &e; // expected-warning {{pointer type mismatch}} + + typedef void *asdf; + *(0 ? (asdf) 0 : &x) = 10; +} + +int Postgresql() { + char x; + return ((((&x) != ((void *) 0)) ? (*(&x) = ((char) 1)) : (void) ((void *) 0)), (unsigned long) ((void *) 0)); // expected-warning {{C99 forbids conditional expressions with only one void side}} +} + +#define nil ((void*) 0) + +extern int f1(void); + +int f0(int a) { + // GCC considers this a warning. + return a ? f1() : nil; // expected-warning {{pointer/integer type mismatch in conditional expression ('int' and 'void *')}} expected-warning {{incompatible pointer to integer conversion returning 'void *', expected 'int'}} +} diff --git a/test/Sema/conditional.c b/test/Sema/conditional.c new file mode 100644 index 000000000000..1c7486a6133e --- /dev/null +++ b/test/Sema/conditional.c @@ -0,0 +1,15 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +const char* test1 = 1 ? "i" : 1 == 1 ? "v" : "r"; + +void _efree(void *ptr); + +int _php_stream_free1() +{ + return (1 ? free(0) : _efree(0)); // expected-error {{incompatible type returning 'void', expected 'int'}} +} + +int _php_stream_free2() +{ + return (1 ? _efree(0) : free(0)); // expected-error {{incompatible type returning 'void', expected 'int'}} +} diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c new file mode 100644 index 000000000000..79f96b9c39bf --- /dev/null +++ b/test/Sema/const-eval.c @@ -0,0 +1,67 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#define EVAL_EXPR(testno, expr) int test##testno = sizeof(struct{char qq[expr];}); +int x; +EVAL_EXPR(1, (_Bool)&x) +EVAL_EXPR(2, (int)(1.0+(double)4)) +EVAL_EXPR(3, (int)(1.0+(float)4.0)) +EVAL_EXPR(4, (_Bool)(1 ? (void*)&x : 0)) +EVAL_EXPR(5, (_Bool)(int[]){0}) +struct y {int x,y;}; +EVAL_EXPR(6, (int)(1+(struct y*)0)) +EVAL_EXPR(7, (int)&((struct y*)0)->y) +EVAL_EXPR(8, (_Bool)"asdf") +EVAL_EXPR(9, !!&x) +EVAL_EXPR(10, ((void)1, 12)) +void g0(void); +EVAL_EXPR(11, (g0(), 12)) // FIXME: This should give an error +EVAL_EXPR(12, 1.0&&2.0) +EVAL_EXPR(13, x || 3.0) + +unsigned int l_19 = 1; +EVAL_EXPR(14, (1 ^ l_19) && 1); // expected-error {{fields must have a constant size}} + +void f() +{ + int a; + EVAL_EXPR(15, (_Bool)&a); // expected-error {{fields must have a constant size}} +} + +// FIXME: Turn into EVAL_EXPR test once we have more folding. +_Complex float g16 = (1.0f + 1.0fi); + +// ?: in constant expressions. +int g17[(3?:1) - 2]; + +EVAL_EXPR(18, ((int)((void*)10 + 10)) == 20 ? 1 : -1); + +struct s { + int a[(int)-1.0f]; // expected-error {{array size is negative}} +}; + +EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1)); + +EVAL_EXPR(20, __builtin_constant_p(*((int*) 10), -1, 1)); + +EVAL_EXPR(21, (__imag__ 2i) == 2 ? 1 : -1); + +EVAL_EXPR(22, (__real__ (2i+3)) == 3 ? 1 : -1); + +int g23[(int)(1.0 / 1.0)] = { 1 }; +int g24[(int)(1.0 / 1.0)] = { 1 , 2 }; // expected-warning {{excess elements in array initializer}} +int g25[(int)(1.0 + 1.0)], g26 = sizeof(g25); + +EVAL_EXPR(26, (_Complex double)0 ? -1 : 1) +EVAL_EXPR(27, (_Complex int)0 ? -1 : 1) +EVAL_EXPR(28, (_Complex double)1 ? 1 : -1) +EVAL_EXPR(29, (_Complex int)1 ? 1 : -1) + + +// PR4027 + rdar://6808859 +struct a { int x, y }; +static struct a V2 = (struct a)(struct a){ 1, 2}; +static const struct a V1 = (struct a){ 1, 2}; + +EVAL_EXPR(30, (int)(_Complex float)((1<<30)-1) == (1<<30) ? 1 : -1) +EVAL_EXPR(31, (int*)0 == (int*)0 ? 1 : -1) +EVAL_EXPR(32, (int*)0 != (int*)0 ? -1 : 1) diff --git a/test/Sema/const-ptr-int-ptr-cast.c b/test/Sema/const-ptr-int-ptr-cast.c new file mode 100644 index 000000000000..4e08bfff2cbb --- /dev/null +++ b/test/Sema/const-ptr-int-ptr-cast.c @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stdint.h> + +char *a = (void*)(uintptr_t)(void*)&a; diff --git a/test/Sema/constant-builtins-2.c b/test/Sema/constant-builtins-2.c new file mode 100644 index 000000000000..146d9e9bb92b --- /dev/null +++ b/test/Sema/constant-builtins-2.c @@ -0,0 +1,50 @@ +// RUN: clang-cc -fsyntax-only %s + +// Math stuff + +double g0 = __builtin_huge_val(); +float g1 = __builtin_huge_valf(); +long double g2 = __builtin_huge_vall(); + +double g3 = __builtin_inf(); +float g4 = __builtin_inff(); +long double g5 = __builtin_infl(); + +double g6 = __builtin_nan(""); +float g7 = __builtin_nanf(""); +long double g8 = __builtin_nanl(""); + +// GCC constant folds these too (via native strtol): +//double g6_1 = __builtin_nan("1"); +//float g7_1 = __builtin_nanf("1"); +//long double g8_1 = __builtin_nanl("1"); + +// APFloat doesn't have signalling NaN functions. +//double g9 = __builtin_nans(""); +//float g10 = __builtin_nansf(""); +//long double g11 = __builtin_nansl(""); + +//int g12 = __builtin_abs(-12); + +double g13 = __builtin_fabs(-12.); +double g13_0 = __builtin_fabs(-0.); +double g13_1 = __builtin_fabs(-__builtin_inf()); +float g14 = __builtin_fabsf(-12.f); +// GCC doesn't eat this one. +//long double g15 = __builtin_fabsfl(-12.0L); + +float g16 = __builtin_copysign(1.0, -1.0); +double g17 = __builtin_copysignf(1.0f, -1.0f); +long double g18 = __builtin_copysignl(1.0L, -1.0L); + +//double g19 = __builtin_powi(2.0, 4); +//float g20 = __builtin_powif(2.0f, 4); +//long double g21 = __builtin_powil(2.0L, 4); + +// GCC misc stuff + +extern int f(); + +int h0 = __builtin_types_compatible_p(int, float); +//int h1 = __builtin_choose_expr(1, 10, f()); +//int h2 = __builtin_expect(0, 0); diff --git a/test/Sema/constant-builtins.c b/test/Sema/constant-builtins.c new file mode 100644 index 000000000000..f8cea33d6762 --- /dev/null +++ b/test/Sema/constant-builtins.c @@ -0,0 +1,24 @@ +// RUN: clang-cc -fsyntax-only %s -verify -pedantic + +// Math stuff + +float g0 = __builtin_huge_val(); +double g1 = __builtin_huge_valf(); +long double g2 = __builtin_huge_vall(); +float g3 = __builtin_inf(); +double g4 = __builtin_inff(); +long double g5 = __builtin_infl(); + +// GCC misc stuff + +extern int f(); + +int h0 = __builtin_types_compatible_p(int,float); +//int h1 = __builtin_choose_expr(1, 10, f()); +//int h2 = __builtin_expect(0, 0); + +short somefunc(); + +short t = __builtin_constant_p(5353) ? 42 : somefunc(); + + diff --git a/test/Sema/constructor-attribute.c b/test/Sema/constructor-attribute.c new file mode 100644 index 000000000000..bf876f344a8f --- /dev/null +++ b/test/Sema/constructor-attribute.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int x __attribute__((constructor)); // expected-warning {{'constructor' attribute only applies to function types}} +int f() __attribute__((constructor)); +int f() __attribute__((constructor(1))); +int f() __attribute__((constructor(1,2))); // expected-error {{attribute requires 0 or 1 argument(s)}} +int f() __attribute__((constructor(1.0))); // expected-error {{'constructor' attribute requires parameter 1 to be an integer constant}} + +int x __attribute__((destructor)); // expected-warning {{'destructor' attribute only applies to function types}} +int f() __attribute__((destructor)); +int f() __attribute__((destructor(1))); +int f() __attribute__((destructor(1,2))); // expected-error {{attribute requires 0 or 1 argument(s)}} +int f() __attribute__((destructor(1.0))); // expected-error {{'destructor' attribute requires parameter 1 to be an integer constant}} + + diff --git a/test/Sema/darwin-align-cast.c b/test/Sema/darwin-align-cast.c new file mode 100644 index 000000000000..09808b5af2e8 --- /dev/null +++ b/test/Sema/darwin-align-cast.c @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef long unsigned int __darwin_size_t; +typedef long __darwin_ssize_t; +typedef __darwin_size_t size_t; +typedef __darwin_ssize_t ssize_t; + +struct cmsghdr {}; + +#if 0 +This code below comes from the following system headers: +sys/socket.h:#define CMSG_SPACE(l) (__DARWIN_ALIGN(sizeof(struct +cmsghdr)) + __DARWIN_ALIGN(l)) + +i386/_param.h:#define __DARWIN_ALIGN(p) ((__darwin_size_t)((char *)(p) ++ __DARWIN_ALIGNBYTES) &~ __DARWIN_ALIGNBYTES) +#endif + +ssize_t sendFileDescriptor(int fd, void *data, size_t nbytes, int sendfd) { + union { + char control[(((__darwin_size_t)((char *)(sizeof(struct cmsghdr)) + (sizeof(__darwin_size_t) - 1)) &~ (sizeof(__darwin_size_t) - 1)) + ((__darwin_size_t)((char *)(sizeof(int)) + (sizeof(__darwin_size_t) - 1)) &~ (sizeof(__darwin_size_t) - 1)))]; + } control_un; +} + diff --git a/test/Sema/decl-invalid.c b/test/Sema/decl-invalid.c new file mode 100644 index 000000000000..051f0f7ffbcc --- /dev/null +++ b/test/Sema/decl-invalid.c @@ -0,0 +1,29 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// See Sema::ParsedFreeStandingDeclSpec about the double diagnostic +typedef union <anonymous> __mbstate_t; // expected-error {{declaration of anonymous union must be a definition}} expected-error {{declaration does not declare anything}} + + +// PR2017 +void x(); +int a() { + int r[x()]; // expected-error {{size of array has non-integer type 'void'}} + + static y ?; // expected-error{{unknown type name 'y'}} \ + expected-error{{expected identifier or '('}} \ + expected-error{{expected ';' at end of declaration}} +} + +int; // expected-error {{declaration does not declare anything}} +typedef int; // expected-error {{declaration does not declare anything}} +const int; // expected-error {{declaration does not declare anything}} +struct; // expected-error {{declaration of anonymous struct must be a definition}} // expected-error {{declaration does not declare anything}} +typedef int I; +I; // expected-error {{declaration does not declare anything}} + + + +// rdar://6880449 +register int test1; // expected-error {{illegal storage class on file-scoped variable}} +register int test2 __asm__("edi"); // expected-error {{global register variables are not supported}} + diff --git a/test/Sema/decl-type-merging.c b/test/Sema/decl-type-merging.c new file mode 100644 index 000000000000..1b789a142ade --- /dev/null +++ b/test/Sema/decl-type-merging.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -std=c99 -verify -pedantic %s + +int x[10]; +int x[] = {1,2,3}; +int testx[(sizeof(x) == sizeof(int) * 10) ? 1 : -1]; + +int (*a)(int (*x)[10], int (*y)[]); +int (*a)(int (*x)[], int (*y)[5]); +int b() { +int x[10], y[5]; +a(&x, &y); +a(&y, &y); // expected-warning {{incompatible pointer}} +a(&x, &x); // expected-warning {{incompatible pointer}} +} + + diff --git a/test/Sema/declspec.c b/test/Sema/declspec.c new file mode 100644 index 000000000000..e325cc83521a --- /dev/null +++ b/test/Sema/declspec.c @@ -0,0 +1,23 @@ +// RUN: clang-cc %s -verify -fsyntax-only +typedef char T[4]; + +T foo(int n, int m) { } // expected-error {{cannot return array or function}} + +void foof(const char *, ...) __attribute__((__format__(__printf__, 1, 2))), barf (void); + +int typedef validTypeDecl() { } // expected-error {{function definition declared 'typedef'}} + +struct _zend_module_entry { } +typedef struct _zend_function_entry { } // expected-error {{cannot combine with previous 'struct' declaration specifier}} +static void buggy(int *x) { } // expected-error {{function definition declared 'typedef'}} \ + // expected-error {{cannot combine with previous 'typedef' declaration specifier}} \ + // expected-error {{cannot combine with previous 'struct' declaration specifier}} + +// Type qualifiers. +typedef int f(void); +typedef f* fptr; +const f* v1; // expected-warning {{qualifier on function type 'f' (aka 'int (void)') has unspecified behavior}} +__restrict__ f* v2; // expected-error {{restrict requires a pointer or reference ('f' (aka 'int (void)') is invalid)}} +__restrict__ fptr v3; // expected-error {{pointer to function type 'f' (aka 'int (void)') may not be 'restrict' qualified}} +f *__restrict__ v4; // expected-error {{pointer to function type 'f' (aka 'int (void)') may not be 'restrict' qualified}} + diff --git a/test/Sema/default.c b/test/Sema/default.c new file mode 100644 index 000000000000..5dac99131b6b --- /dev/null +++ b/test/Sema/default.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f5 (int z) { + if (z) + default: // expected-error {{not in switch statement}} + ; // expected-warning {{if statement has empty body}} +} + diff --git a/test/Sema/default1.c b/test/Sema/default1.c new file mode 100644 index 000000000000..6e8a27bf5733 --- /dev/null +++ b/test/Sema/default1.c @@ -0,0 +1,2 @@ +// RUN: clang-cc -fsyntax-only -verify %s +void f(int i = 0); // expected-error {{C does not support default arguments}} diff --git a/test/Sema/deref.c b/test/Sema/deref.c new file mode 100644 index 000000000000..965940e26d5e --- /dev/null +++ b/test/Sema/deref.c @@ -0,0 +1,44 @@ +/* RUN: clang-cc -fsyntax-only -verify -std=c90 -pedantic %s + */ +void +foo (void) +{ + struct b; + struct b* x = 0; + struct b* y = &*x; +} + +void foo2 (void) +{ + typedef int (*arrayptr)[]; + arrayptr x = 0; + arrayptr y = &*x; +} + +void foo3 (void) +{ + void* x = 0; + void* y = &*x; /* expected-warning{{address of an expression of type 'void'}} */ +} + +extern const void cv1; + +const void *foo4 (void) +{ + return &cv1; +} + +extern void cv2; +void *foo5 (void) +{ + return &cv2; /* expected-warning{{address of an expression of type 'void'}} */ +} + +typedef const void CVT; +extern CVT cv3; + +const void *foo6 (void) +{ + return &cv3; +} + diff --git a/test/Sema/designated-initializers.c b/test/Sema/designated-initializers.c new file mode 100644 index 000000000000..ae951d42a1a6 --- /dev/null +++ b/test/Sema/designated-initializers.c @@ -0,0 +1,234 @@ +// RUN: clang-cc -fsyntax-only -verify -triple x86_64-unknown-unknown %s + +int complete_array_from_init[] = { 1, 2, [10] = 5, 1, 2, [5] = 2, 6 }; + +int complete_array_from_init_check[((sizeof(complete_array_from_init) / sizeof(int)) == 13)? 1 : -1]; + +int iarray[10] = { + [0] = 1, + [1 ... 5] = 2, + [ 6 ... 6 ] = 3, + [ 8 ... 7 ] = 4, // expected-error{{array designator range [8, 7] is empty}} + [10] = 5, + [-1] = 6 // expected-error{{array designator value '-1' is negative}} +}; + +int iarray2[10] = { + [10] = 1, // expected-error{{array designator index (10) exceeds array bounds (10)}} +}; + +int iarray3[10] = { + [3] 2, // expected-warning{{use of GNU 'missing =' extension in designator}} + [5 ... 12] = 2 // expected-error{{array designator index (12) exceeds array bounds (10)}} +}; + +struct point { + double x; + double y; +}; + +struct point p1 = { + .y = 1.0, + x: 2.0, // expected-warning{{}} + .a = 4.0, // expected-error{{field designator 'a' does not refer to any field in type 'struct point'}} +}; + +struct point p2 = { + [1] = 1.0 // expected-error{{array designator cannot initialize non-array type}} +}; + +struct point array[10] = { + [0].x = 1.0, + [1].y = 2.0, + [2].z = 3.0, // expected-error{{field designator 'z' does not refer to any field in type 'struct point'}} +}; + +struct point array2[10] = { + [10].x = 2.0, // expected-error{{array designator index (10) exceeds array bounds (10)}} + [4 ... 5].y = 2.0, + [4 ... 6] = { .x = 3, .y = 4.0 } +}; + +struct point array3[10] = { + .x = 5 // expected-error{{field designator cannot initialize a non-struct, non-union type}} +}; + +struct rect { + struct point top_left; + struct point bottom_right; +}; + +struct rect window = { .top_left.x = 1.0 }; + +struct rect windows[] = { + [2].top_left = { 1.0, 2.0 }, + [4].bottom_right = { .y = 1.0 }, + { { .y = 7.0, .x = 8.0 }, { .x = 5.0 } }, + [3] = { .top_left = { 1.1, 2.2 }, .bottom_right = { .y = 1.1 } } +}; + +int windows_size[((sizeof(windows) / sizeof(struct rect)) == 6)? 1 : -1]; + +struct rect windows_bad[3] = { + [2].top_left = { { .x = 1.1 } }, // expected-error{{designator in initializer for scalar type}} + [1].top_left = { .x = 1.1 } +}; + +struct gui { + struct rect windows[10]; +}; + +struct gui gui[] = { + [5].windows[3].top_left.x = { 7.0 } // expected-warning{{braces around scalar initializer}} +}; + +struct translator { + struct wonky { int * ptr; } wonky ; + struct rect window; + struct point offset; +} tran = { + .window = { .top_left = { 1.0, 2.0 } }, + { .x = 5.0, .y = 6.0 }, + .wonky = { 0 } +}; + +int anint; +struct {int x,*y;} z[] = {[0].x = 2, &z[0].x}; + +struct outer { struct inner { int x, *y; } in, *inp; } zz[] = { + [0].in.x = 2, &zz[0].in.x, &zz[0].in, + 0, &anint, &zz[1].in, + [3].in = { .y = &anint, .x = 17 }, + [7].in.y = &anint, &zz[0].in, + [4].in.y = &anint, [5].in.x = 12 +}; + +int zz_sizecheck[sizeof(zz) / sizeof(struct outer) == 8? 1 : -1 ]; + +struct disklabel_ops { + struct {} type; + int labelsize; +}; + +struct disklabel_ops disklabel64_ops = { + .labelsize = sizeof(struct disklabel_ops) +}; + +// PR clang/3378 +int bitwidth[] = { [(long long int)1] = 5, [(short int)2] = 2 }; +int a[]= { [sizeof(int)] = 0 }; +int a2[]= { [0 ... sizeof(int)] = 0 }; + +// Test warnings about initializers overriding previous initializers +struct X { + int a, b, c; +}; + +int counter = 0; +int get8() { ++counter; return 8; } + +void test() { + struct X xs[] = { + [0] = (struct X){1, 2}, // expected-note{{previous initialization is here}} + [0].c = 3, // expected-warning{{subobject initialization overrides initialization of other fields within its enclosing subobject}} + (struct X) {4, 5, 6}, // expected-note{{previous initialization is here}} + [1].b = get8(), // expected-warning{{subobject initialization overrides initialization of other fields within its enclosing subobject}} + [0].b = 8 + }; +} + +// FIXME: How do we test that this initializes the long properly? +union { char c; long l; } u1 = { .l = 0xFFFF }; + +extern float global_float; + +struct XX { int a, *b; }; +struct XY { int before; struct XX xx, *xp; float* after; } xy[] = { + 0, 0, &xy[0].xx.a, &xy[0].xx, &global_float, + [1].xx = 0, &xy[1].xx.a, &xy[1].xx, &global_float, + 0, // expected-note{{previous initialization is here}} + 0, // expected-note{{previous initialization is here}} + [2].before = 0, // expected-warning{{initializer overrides prior initialization of this subobject}} + 0, // expected-warning{{initializer overrides prior initialization of this subobject}} + &xy[2].xx.a, &xy[2].xx, &global_float +}; + +// PR3519 +struct foo { + int arr[10]; +}; + +struct foo Y[10] = { + [1] .arr [1] = 2, + [4] .arr [2] = 4 +}; + +struct bar { + struct foo f; + float *arr[10]; +}; + +extern float f; +struct bar saloon = { + .f.arr[3] = 1, + .arr = { &f } +}; + +typedef unsigned char u_char; +typedef unsigned short u_short; + +union wibble { + u_char arr1[6]; + u_short arr2[3]; +}; + +const union wibble wobble = { .arr2[0] = 0xffff, + .arr2[1] = 0xffff, + .arr2[2] = 0xffff }; + +const union wibble wobble2 = { .arr2 = {4, 5, 6}, 7 }; // expected-warning{{excess elements in union initializer}} + +// PR3778 +struct s { + union { int i; }; +}; +struct s si = { + { .i = 1 } +}; + +double d0; +char c0; +float f0; +int i0; + +struct Enigma { + union { + struct { + struct { + double *double_ptr; + char *string; + }; + float *float_ptr; + }; + int *int_ptr; + }; + char *string2; +}; + +struct Enigma enigma = { + .double_ptr = &d0, &c0, + &f0, // expected-note{{previous}} + &c0, + .float_ptr = &f0 // expected-warning{{overrides}} +}; + + +/// PR4073 +/// Should use evaluate to fold aggressively and emit a warning if not an ice. +extern int crazy_x; + +int crazy_Y[] = { + [ 0 ? crazy_x : 4] = 1 +}; + + diff --git a/test/Sema/dllimport-dllexport.c b/test/Sema/dllimport-dllexport.c new file mode 100644 index 000000000000..90ed1456d24d --- /dev/null +++ b/test/Sema/dllimport-dllexport.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +inline void __attribute__((dllexport)) foo1(){} // expected-warning{{dllexport attribute ignored}} +inline void __attribute__((dllimport)) foo2(){} // expected-warning{{dllimport attribute ignored}} + +void __attribute__((dllimport)) foo3(){} // expected-error{{dllimport attribute can be applied only to symbol declaration}} + +void __attribute__((dllimport, dllexport)) foo4(); // expected-warning{{dllimport attribute ignored}} + +void __attribute__((dllexport)) foo5(); +void __attribute__((dllimport)) foo5(); // expected-warning{{dllimport attribute ignored}} + +typedef int __attribute__((dllexport)) type6; // expected-warning{{'dllexport' attribute only applies to variable and function types}} + +typedef int __attribute__((dllimport)) type7; // expected-warning{{'dllimport' attribute only applies to variable and function}} + +void __attribute__((dllimport)) foo6(); +void foo6(){} // expected-warning {{'foo6' redeclared without dllimport attribute: previous dllimport ignored}} diff --git a/test/Sema/enum.c b/test/Sema/enum.c new file mode 100644 index 000000000000..adb937551237 --- /dev/null +++ b/test/Sema/enum.c @@ -0,0 +1,86 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic +enum e {A, + B = 42LL << 32, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} + C = -4, D = 12456 }; + +enum f { a = -2147483648, b = 2147483647 }; // ok. + +enum g { // too negative + c = -2147483649, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} + d = 2147483647 }; +enum h { e = -2147483648, // too pos + f = 2147483648 // expected-warning {{ISO C restricts enumerator values to range of 'int'}} +}; + +// minll maxull +enum x // expected-warning {{enumeration values exceed range of largest integer}} +{ y = -9223372036854775807LL-1, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} +z = 9223372036854775808ULL }; // expected-warning {{ISO C restricts enumerator values to range of 'int'}} + +int test() { + return sizeof(enum e) ; +} + +enum gccForwardEnumExtension ve; // expected-warning{{ISO C forbids forward references to 'enum' types}} \ +// expected-error{{tentative definition has type 'enum gccForwardEnumExtension' that is never completed}} \ +// expected-note{{forward declaration of 'enum gccForwardEnumExtension'}} + +int test2(int i) +{ + ve + i; // expected-error{{invalid operands to binary expression}} +} + +// PR2020 +union u0; // expected-note {{previous use is here}} +enum u0 { U0A }; // expected-error {{use of 'u0' with tag type that does not match previous declaration}} + + +// rdar://6095136 +extern enum some_undefined_enum ve2; // expected-warning {{ISO C forbids forward references to 'enum' types}} + +void test4() { + for (; ve2;) // expected-error {{statement requires expression of scalar type}} + ; + (_Bool)ve2; // expected-error {{arithmetic or pointer type is required}} + + for (; ;ve2) + ; + (void)ve2; + ve2; // expected-warning {{expression result unused}} +} + +// PR2416 +enum someenum {}; // expected-warning {{use of empty enum extension}} + +// <rdar://problem/6093889> +enum e0 { // expected-note {{previous definition is here}} + E0 = sizeof(enum e0 { E1 }), // expected-error {{nested redefinition}} +}; + +// PR3173 +enum { PR3173A, PR3173B = PR3173A+50 }; + +// PR2753 +void foo() { + enum xpto; // expected-warning{{ISO C forbids forward references to 'enum' types}} + enum xpto; // expected-warning{{ISO C forbids forward references to 'enum' types}} +} + +// <rdar://problem/6503878> +typedef enum { X = 0 }; // expected-warning{{typedef requires a name}} + + +enum NotYetComplete { // expected-note{{definition of 'enum NotYetComplete' is not complete until the closing '}'}} + NYC1 = sizeof(enum NotYetComplete) // expected-error{{invalid application of 'sizeof' to an incomplete type 'enum NotYetComplete'}} +}; + +/// PR3688 +struct s1 { + enum e1 (*bar)(void); // expected-warning{{ISO C forbids forward references to 'enum' types}} +}; + +enum e1 { YES, NO }; + +static enum e1 badfunc(struct s1 *q) { + return q->bar(); +} diff --git a/test/Sema/expr-address-of.c b/test/Sema/expr-address-of.c new file mode 100644 index 000000000000..909acfb26662 --- /dev/null +++ b/test/Sema/expr-address-of.c @@ -0,0 +1,109 @@ +// RUN: clang-cc %s -verify -fsyntax-only +struct xx { int bitf:1; }; + +struct entry { struct xx *whatever; + int value; + int bitf:1; }; +void add_one(int *p) { (*p)++; } + +void test() { + register struct entry *p; + add_one(&p->value); + struct entry pvalue; + add_one(&p->bitf); // expected-error {{address of bit-field requested}} + add_one(&pvalue.bitf); // expected-error {{address of bit-field requested}} + add_one(&p->whatever->bitf); // expected-error {{address of bit-field requested}} +} + +void foo() { + register int x[10]; + &x[10]; // expected-error {{address of register variable requested}} + + register int *y; + + int *x2 = &y; // expected-error {{address of register variable requested}} + int *x3 = &y[10]; +} + +void testVectorComponentAccess() { + typedef float v4sf __attribute__ ((vector_size (16))); + static v4sf q; + float* r = &q[0]; // expected-error {{address of vector element requested}} +} + +typedef __attribute__(( ext_vector_type(4) )) float float4; + +float *testExtVectorComponentAccess(float4 x) { + return &x.w; // expected-error {{address of vector element requested}} +} + +void f0() { + register int *x0; + int *_dummy0 = &(*x0); + + register int *x1; + int *_dummy1 = &(*(x1 + 1)); +} + +// FIXME: The checks for this function are broken; we should error +// on promoting a register array to a pointer! (C99 6.3.2.1p3) +void f1() { + register int x0[10]; + int *_dummy00 = x0; // fixme-error {{address of register variable requested}} + int *_dummy01 = &(*x0); // fixme-error {{address of register variable requested}} + + register int x1[10]; + int *_dummy1 = &(*(x1 + 1)); // fixme-error {{address of register variable requested}} + + register int *x2; + int *_dummy2 = &(*(x2 + 1)); + + register int x3[10][10][10]; + int (*_dummy3)[10] = &x3[0][0]; // expected-error {{address of register variable requested}} + + register struct { int f0[10]; } x4; + int *_dummy4 = &x4.f0[2]; // expected-error {{address of register variable requested}} +} + +void f2() { + register int *y; + + int *_dummy0 = &y; // expected-error {{address of register variable requested}} + int *_dummy1 = &y[10]; +} + +void f3() { + extern void f4(); + void (*_dummy0)() = &****f4; +} + +void f4() { + register _Complex int x; + + int *_dummy0 = &__real__ x; // expected-error {{address of register variable requested}} +} + +void f5() { + register int arr[2]; + + /* This is just here because if we happened to support this as an + lvalue we would need to give a warning. Note that gcc warns about + this as a register before it warns about it as an invalid + lvalue. */ + int *_dummy0 = &(int*) arr; // expected-error {{address expression must be an lvalue or a function designator}} + int *_dummy1 = &(arr + 1); // expected-error {{address expression must be an lvalue or a function designator}} +} + +void f6(register int x) { + int * dummy0 = &x; // expected-error {{address of register variable requested}} +} + +char* f7() { + register struct {char* x;} t1 = {"Hello"}; + char* dummy1 = &(t1.x[0]); + + struct {int a : 10;} t2; + int* dummy2 = &(t2.a); // expected-error {{address of bit-field requested}} + + void* t3 = &(*(void*)0); +} diff --git a/test/Sema/expr-comma-c89.c b/test/Sema/expr-comma-c89.c new file mode 100644 index 000000000000..b2b17dc33591 --- /dev/null +++ b/test/Sema/expr-comma-c89.c @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -fsyntax-only -verify -std=c99 +// rdar://6095180 + +#include <assert.h> +struct s { char c[17]; }; +extern struct s foo(void); + +struct s a, b, c; + +int A[sizeof((foo().c)) == 17 ? 1 : -1]; +int B[sizeof((a.c)) == 17 ? 1 : -1]; + + +// comma does array/function promotion in c99. +int X[sizeof(0, (foo().c)) == sizeof(char*) ? 1 : -1]; +int Y[sizeof(0, (a,b).c) == sizeof(char*) ? 1 : -1]; +int Z[sizeof(0, (a=b).c) == sizeof(char*) ? 1 : -1]; + diff --git a/test/Sema/expr-comma.c b/test/Sema/expr-comma.c new file mode 100644 index 000000000000..64079866ca99 --- /dev/null +++ b/test/Sema/expr-comma.c @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -fsyntax-only -verify -std=c89 +// rdar://6095180 + +#include <assert.h> +struct s { char c[17]; }; +extern struct s foo(void); + +struct s a, b, c; + +int A[sizeof((foo().c)) == 17 ? 1 : -1]; +int B[sizeof((a.c)) == 17 ? 1 : -1]; + + +// comma does not promote array/function in c90 unless they are lvalues. +int W[sizeof(0, a.c) == sizeof(char*) ? 1 : -1]; +int X[sizeof(0, (foo().c)) == 17 ? 1 : -1]; +int Y[sizeof(0, (a,b).c) == 17 ? 1 : -1]; +int Z[sizeof(0, (a=b).c) == 17 ? 1 : -1]; diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c new file mode 100644 index 000000000000..3fd1437da880 --- /dev/null +++ b/test/Sema/exprs.c @@ -0,0 +1,108 @@ +// RUN: clang-cc %s -verify -pedantic -fsyntax-only -fblocks=0 + +// PR1966 +_Complex double test1() { + return __extension__ 1.0if; +} + +_Complex double test2() { + return 1.0if; // expected-warning {{imaginary constants are an extension}} +} + +// rdar://6097308 +void test3() { + int x; + (__extension__ x) = 10; +} + +// rdar://6162726 +void test4() { + static int var; + var =+ 5; // expected-warning {{use of unary operator that may be intended as compound assignment (+=)}} + var =- 5; // expected-warning {{use of unary operator that may be intended as compound assignment (-=)}} + var = +5; // no warning when space between the = and +. + var = -5; + + var =+5; // no warning when the subexpr of the unary op has no space before it. + var =-5; + +#define FIVE 5 + var=-FIVE; // no warning with macros. + var=-FIVE; +} + +// rdar://6319320 +void test5(int *X, float *P) { + (float*)X = P; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} +#define FOO ((float*) X) + FOO = P; // expected-error {{assignment to cast is illegal, lvalue casts are not supported}} +} + +void test6() { + int X; + X(); // expected-error {{called object type 'int' is not a function or function pointer}} +} + +void test7(int *P, _Complex float Gamma) { + P = (P-42) + Gamma*4; // expected-error {{invalid operands to binary expression ('int *' and '_Complex float')}} +} + + +// rdar://6095061 +int test8(void) { + int i; + __builtin_choose_expr (0, 42, i) = 10; + return i; +} + + +// PR3386 +struct f { int x : 4; float y[]; }; +int test9(struct f *P) { + int R; + R = __alignof(P->x); // expected-error {{invalid application of '__alignof' to bitfield}} + R = __alignof(P->y); // ok. + R = sizeof(P->x); // expected-error {{invalid application of 'sizeof' to bitfield}} + return R; +} + +// PR3562 +void test10(int n,...) { + struct S { + double a[n]; // expected-error {{fields must have a constant size}} + } s; + double x = s.a[0]; // should not get another error here. +} + + +#define MYMAX(A,B) __extension__ ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; }) + +struct mystruct {int A; }; +void test11(struct mystruct P, float F) { + MYMAX(P, F); // expected-error {{invalid operands to binary expression ('typeof (P)' (aka 'struct mystruct') and 'typeof (F)' (aka 'float'))}} +} + +// PR3753 +int test12(const char *X) { + return X == "foo"; // expected-warning {{comparison against a string literal is unspecified}} +} + +// rdar://6719156 +void test13( + void (^P)()) { // expected-error {{blocks support disabled - compile with -fblocks}} + P(); + P = ^(){}; // expected-error {{blocks support disabled - compile with -fblocks}} +} + + +// rdar://6326239 - Vector comparisons are not fully trusted yet, until the +// backend is known to work, just unconditionally reject them. +void test14() { + typedef long long __m64 __attribute__((__vector_size__(8))); + typedef short __v4hi __attribute__((__vector_size__(8))); + + __v4hi a; + __m64 mask = (__m64)((__v4hi)a > // expected-error {{comparison of vector types ('__v4hi' and '__v4hi') not supported yet}} + (__v4hi)a); +} + diff --git a/test/Sema/ext_vector_components.c b/test/Sema/ext_vector_components.c new file mode 100644 index 000000000000..422a9e6f2287 --- /dev/null +++ b/test/Sema/ext_vector_components.c @@ -0,0 +1,37 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef __attribute__(( ext_vector_type(2) )) float float2; +typedef __attribute__(( ext_vector_type(3) )) float float3; +typedef __attribute__(( ext_vector_type(4) )) float float4; + +static void test() { + float2 vec2, vec2_2; + float3 vec3; + float4 vec4, vec4_2, *vec4p; + float f; + + vec2.z; // expected-error {{vector component access exceeds type 'float2'}} + vec2.xyzw; // expected-error {{vector component access exceeds type 'float2'}} + vec4.xyzw; // expected-warning {{expression result unused}} + vec4.xyzc; // expected-error {{illegal vector component name 'c'}} + vec4.s01z; // expected-error {{illegal vector component name 'z'}} + vec2 = vec4.s01; // legal, shorten + + vec3 = vec4.xyz; // legal, shorten + f = vec2.x; // legal, shorten + f = vec4.xy.x; // legal, shorten + + vec2 = vec3.hi; // expected-error {{vector component access invalid for odd-sized type 'float3'}} + + vec4_2.xyzx = vec4.xyzw; // expected-error {{vector is not assignable (contains duplicate components)}} + vec4_2.xyzz = vec4.xyzw; // expected-error {{vector is not assignable (contains duplicate components)}} + vec4_2.xyyw = vec4.xyzw; // expected-error {{vector is not assignable (contains duplicate components)}} + vec2.x = f; + vec2.xx = vec2_2.xy; // expected-error {{vector is not assignable (contains duplicate components)}} + vec2.yx = vec2_2.xy; + vec4 = (float4){ 1,2,3,4 }; + vec4.xy.w; // expected-error {{vector component access exceeds type 'float2'}} + vec4.s06; // expected-error {{vector component access exceeds type 'float4'}} + + vec4p->yz = vec4p->xy; +} diff --git a/test/Sema/flexible-array-init.c b/test/Sema/flexible-array-init.c new file mode 100644 index 000000000000..afe31fb8294f --- /dev/null +++ b/test/Sema/flexible-array-init.c @@ -0,0 +1,58 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +struct one { + int a; + int values[]; // expected-note 3{{initialized flexible array member 'values' is here}} +} x = {5, {1, 2, 3}}; // expected-warning{{flexible array initialization is a GNU extension}} + +struct one x2 = { 5, 1, 2, 3 }; // expected-warning{{flexible array initialization is a GNU extension}} + +void test() { + struct one x3 = {5, {1, 2, 3}}; // expected-warning{{flexible array initialization is a GNU extension}} +} + +struct foo { + int x; + int y[]; // expected-note 6 {{initialized flexible array member 'y' is here}} +}; +struct bar { struct foo z; }; // expected-warning {{'z' may not be nested in a struct due to flexible array member}} + +struct foo a = { 1, { 2, 3, 4 } }; // expected-warning{{flexible array initialization is a GNU extension}} +struct bar b = { { 1, { 2, 3, 4 } } }; // expected-error{{non-empty initialization of flexible array member inside subobject}} +struct bar c = { { 1, { } } }; // // expected-warning{{flexible array initialization is a GNU extension}} \ + // expected-warning{{use of GNU empty initializer extension}} \ + // expected-warning{{zero size arrays are an extension}} +struct foo d[1] = { { 1, { 2, 3, 4 } } }; // expected-warning{{'struct foo' may not be used as an array element due to flexible array member}} \ + // expected-error{{non-empty initialization of flexible array member inside subobject}} + +struct foo desig_foo = { .y = {2, 3, 4} }; +struct bar desig_bar = { .z.y = { } }; // expected-warning{{use of GNU empty initializer extension}} \ + // expected-warning{{zero size arrays are an extension}} +struct bar desig_bar2 = { .z.y = { 2, 3, 4} }; // expected-error{{non-empty initialization of flexible array member inside subobject}} +struct foo design_foo2 = { .y = 2 }; // expected-error{{flexible array requires brace-enclosed initializer}} + +struct point { + int x, y; +}; + +struct polygon { + int numpoints; + struct point points[]; // expected-note{{initialized flexible array member 'points' is here}} +}; +struct polygon poly = { + .points[2] = { 1, 2} }; // expected-error{{designator into flexible array member subobject}} + +// PR3540 +struct X { + int a; + int b; + char data[]; +}; + +struct Y { + int a:4; + int b:4; + int c; + int d; + int e; + struct X xs[]; // expected-warning{{'struct X' may not be used as an array element due to flexible array member}} +}; diff --git a/test/Sema/floating-point-compare.c b/test/Sema/floating-point-compare.c new file mode 100644 index 000000000000..763a8f4b86b4 --- /dev/null +++ b/test/Sema/floating-point-compare.c @@ -0,0 +1,25 @@ +// RUN: clang-cc -fsyntax-only -Wfloat-equal -verify %s + +int f1(float x, float y) { + return x == y; // expected-warning {{comparing floating point with ==}} +} + +int f2(float x, float y) { + return x != y; // expected-warning {{comparing floating point with ==}} +} + +int f3(float x) { + return x == x; // no-warning +} + +int f4(float x) { + return x == 0.0; // no-warning {{comparing}} +} + +int f5(float x) { + return x == __builtin_inf(); // no-warning +} + +int f7(float x) { + return x == 3.14159; // expected-warning {{comparing}} +} diff --git a/test/Sema/for.c b/test/Sema/for.c new file mode 100644 index 000000000000..183a95d0ab44 --- /dev/null +++ b/test/Sema/for.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Check C99 6.8.5p3 +void b1 (void) { for (void (*f) (void);;); } +void b2 (void) { for (void f (void);;); } // expected-error {{declaration of non-local variable}} +void b3 (void) { for (static int f;;); } // expected-error {{declaration of non-local variable}} +void b4 (void) { for (typedef int f;;); } // expected-error {{declaration of non-local variable}} diff --git a/test/Sema/format-attribute.c b/test/Sema/format-attribute.c new file mode 100644 index 000000000000..cb823318592e --- /dev/null +++ b/test/Sema/format-attribute.c @@ -0,0 +1,34 @@ +//RUN: clang-cc -fsyntax-only -verify %s + +#include <stdarg.h> + +void a(const char *a, ...) __attribute__((format(printf, 1,2))); // no-error +void b(const char *a, ...) __attribute__((format(printf, 1,1))); // expected-error {{'format' attribute parameter 3 is out of bounds}} +void c(const char *a, ...) __attribute__((format(printf, 0,2))); // expected-error {{'format' attribute parameter 2 is out of bounds}} +void d(const char *a, int c) __attribute__((format(printf, 1,2))); // expected-error {{format attribute requires variadic function}} +void e(char *str, int c, ...) __attribute__((format(printf, 2,3))); // expected-error {{format argument not a string type}} + +typedef const char* xpto; +void f(xpto c, va_list list) __attribute__((format(printf, 1, 0))); // no-error +void g(xpto c) __attribute__((format(printf, 1, 0))); // no-error + +void y(char *str) __attribute__((format(strftime, 1,0))); // no-error +void z(char *str, int c, ...) __attribute__((format(strftime, 1,2))); // expected-error {{strftime format attribute requires 3rd parameter to be 0}} + +int (*f_ptr)(char*,...) __attribute__((format(printf, 1,2))); // no-error +int (*f2_ptr)(double,...) __attribute__((format(printf, 1, 2))); // expected-error {{format argument not a string type}} + +struct _mystruct { + int (*printf)(const char *format, ...) __attribute__((__format__(printf, 1, 2))); // no-error + int (*printf2)(double format, ...) __attribute__((__format__(printf, 1, 2))); // expected-error {{format argument not a string type}} +}; + +typedef int (*f3_ptr)(char*,...) __attribute__((format(printf,1,0))); // no-error + +// <rdar://problem/6623513> +int rdar6623513(void *, const char*, const char*, ...) + __attribute__ ((format (printf, 3, 0))); + +int rdar6623513_aux(int len, const char* s) { + rdar6623513(0, "hello", "%.*s", len, s); +} diff --git a/test/Sema/format-string-percentm.c b/test/Sema/format-string-percentm.c new file mode 100644 index 000000000000..f531372fd451 --- /dev/null +++ b/test/Sema/format-string-percentm.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s -triple i686-pc-linux-gnu + +int printf(char const*,...); +void percentm(void) { + printf("%m"); +} diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c new file mode 100644 index 000000000000..1826c7457e30 --- /dev/null +++ b/test/Sema/format-strings.c @@ -0,0 +1,132 @@ +// RUN: clang-cc -fsyntax-only -verify -Wformat-nonliteral %s + +// Define this to get vasprintf on Linux +#define _GNU_SOURCE + +#include <stdio.h> +#include <stdarg.h> + +char * global_fmt; + +void check_string_literal( FILE* fp, const char* s, char *buf, ... ) { + + char * b; + va_list ap; + va_start(ap,buf); + + printf(s); // expected-warning {{format string is not a string literal}} + vprintf(s,ap); // // no-warning + fprintf(fp,s); // expected-warning {{format string is not a string literal}} + vfprintf(fp,s,ap); // no-warning + asprintf(&b,s); // expected-warning {{format string is not a string lit}} + vasprintf(&b,s,ap); // no-warning + sprintf(buf,s); // expected-warning {{format string is not a string literal}} + snprintf(buf,2,s); // expected-warning {{format string is not a string lit}} + __builtin___sprintf_chk(buf,0,-1,s); // expected-warning {{format string is not a string literal}} + __builtin___snprintf_chk(buf,2,0,-1,s); // expected-warning {{format string is not a string lit}} + vsprintf(buf,s,ap); // no-warning + vsnprintf(buf,2,s,ap); // no-warning + vsnprintf(buf,2,global_fmt,ap); // expected-warning {{format string is not a string literal}} + __builtin___vsnprintf_chk(buf,2,0,-1,s,ap); // no-warning + __builtin___vsnprintf_chk(buf,2,0,-1,global_fmt,ap); // expected-warning {{format string is not a string literal}} + + // rdar://6079877 + printf("abc" + "%*d", (unsigned) 1, 1); // expected-warning {{field width should have type 'int'}} + printf("abc\ +def" + "%*d", (unsigned) 1, 1); // expected-warning {{field width should have type 'int'}} + +} + +void check_conditional_literal(const char* s, int i) { + printf(i == 1 ? "yes" : "no"); // no-warning + printf(i == 0 ? (i == 1 ? "yes" : "no") : "dont know"); // no-warning + printf(i == 0 ? (i == 1 ? s : "no") : "dont know"); // expected-warning{{format string is not a string literal}} +} + +void check_writeback_specifier() +{ + int x; + char *b; + + printf("%n",&x); // expected-warning {{'%n' in format string discouraged}} + sprintf(b,"%d%%%n",1, &x); // expected-warning {{'%n' in format string dis}} +} + +void check_invalid_specifier(FILE* fp, char *buf) +{ + printf("%s%lb%d","unix",10,20); // expected-warning {{lid conversion '%lb'}} + fprintf(fp,"%%%l"); // expected-warning {{lid conversion '%l'}} + sprintf(buf,"%%%%%ld%d%d", 1, 2, 3); // no-warning + snprintf(buf, 2, "%%%%%ld%;%d", 1, 2, 3); // expected-warning {{sion '%;'}} +} + +void check_null_char_string(char* b) +{ + printf("\0this is bogus%d",1); // expected-warning {{string contains '\0'}} + snprintf(b,10,"%%%%%d\0%d",1,2); // expected-warning {{string contains '\0'}} + printf("%\0d",1); // expected-warning {{string contains '\0'}} +} + +void check_empty_format_string(char* buf, ...) +{ + va_list ap; + va_start(ap,buf); + vprintf("",ap); // expected-warning {{format string is empty}} + sprintf(buf,""); // expected-warning {{format string is empty}} +} + +void check_wide_string(char* b, ...) +{ + va_list ap; + va_start(ap,b); + + printf(L"foo %d",2); // expected-warning {{incompatible pointer types}}, expected-warning {{should not be a wide string}} + vasprintf(&b,L"bar %d",ap); // expected-warning {{incompatible pointer types}}, expected-warning {{should not be a wide string}} +} + +void check_asterisk_precision_width(int x) { + printf("%*d"); // expected-warning {{'*' specified field width is missing a matching 'int' argument}} + printf("%.*d"); // expected-warning {{'.*' specified field precision is missing a matching 'int' argument}} + printf("%*d",12,x); // no-warning + printf("%*d","foo",x); // expected-warning {{field width should have type 'int', but argument has type 'char *'}} + printf("%.*d","foo",x); // expected-warning {{field precision should have type 'int', but argument has type 'char *'}} +} + +void __attribute__((format(printf,1,3))) myprintf(const char*, int blah, ...); + +void test_myprintf() { + myprintf("%d", 17, 18); // okay +} + +void test_constant_bindings(void) { + const char * const s1 = "hello"; + const char s2[] = "hello"; + const char *s3 = "hello"; + char * const s4 = "hello"; + extern const char s5[]; + + printf(s1); // no-warning + printf(s2); // no-warning + printf(s3); // expected-warning{{not a string literal}} + printf(s4); // expected-warning{{not a string literal}} + printf(s5); // expected-warning{{not a string literal}} +} + + +// Test what happens when -Wformat-security only. +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#pragma GCC diagnostic warning "-Wformat-security" + +void test9(char *P) { + int x; + printf(P); // expected-warning {{format string is not a string literal (potentially insecure)}} + printf(P, 42); + printf("%n", &x); // expected-warning {{use of '%n' in format string discouraged }} +} + +void torture(va_list v8) { + vprintf ("%*.*d", v8); // no-warning +} + diff --git a/test/Sema/function-pointer-sentinel-attribute.c b/test/Sema/function-pointer-sentinel-attribute.c new file mode 100644 index 000000000000..0de02fa5363c --- /dev/null +++ b/test/Sema/function-pointer-sentinel-attribute.c @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void (*e) (int arg, const char * format, ...) __attribute__ ((__sentinel__ (1,1))); + +int main() +{ + void (*b) (int arg, const char * format, ...) __attribute__ ((__sentinel__)); // expected-note {{function has been explicitly marked sentinel here}} + void (*z) (int arg, const char * format, ...) __attribute__ ((__sentinel__ (2))); // expected-note {{function has been explicitly marked sentinel here}} + + + void (*y) (int arg, const char * format, ...) __attribute__ ((__sentinel__ (5))); // expected-note {{function has been explicitly marked sentinel here}} + + b(1, "%s", (void*)0); // OK + b(1, "%s", 0); // expected-warning {{missing sentinel in function call}} + z(1, "%s",4 ,1,0); // expected-warning {{missing sentinel in function call}} + z(1, "%s", (void*)0, 1, 0); // OK + + y(1, "%s", 1,2,3,4,5,6,7); // expected-warning {{missing sentinel in function call}} + + y(1, "%s", (void*)0,3,4,5,6,7); // OK + +} + diff --git a/test/Sema/function-ptr.c b/test/Sema/function-ptr.c new file mode 100644 index 000000000000..6b410018f4b7 --- /dev/null +++ b/test/Sema/function-ptr.c @@ -0,0 +1,11 @@ +// RUN: clang-cc %s -verify -pedantic +typedef int unary_int_func(int arg); +unary_int_func *func; + +unary_int_func *set_func(void *p) { + func = p; // expected-warning {{converts between void* and function pointer}} + p = func; // expected-warning {{converts between void* and function pointer}} + + return p; // expected-warning {{converts between void* and function pointer}} +} + diff --git a/test/Sema/function-redecl.c b/test/Sema/function-redecl.c new file mode 100644 index 000000000000..28593b0678d1 --- /dev/null +++ b/test/Sema/function-redecl.c @@ -0,0 +1,127 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR3588 +void g0(int, int); +void g0(); // expected-note{{previous declaration is here}} + +void f0() { + g0(1, 2, 3); // expected-error{{too many arguments to function call}} +} + +void g0(int); // expected-error{{conflicting types for 'g0'}} + +int g1(int, int); + +typedef int INT; + +INT g1(x, y) + int x; + int y; +{ + return x + y; +} + +int g2(int, int); // expected-note{{previous declaration is here}} + +INT g2(x) // expected-error{{conflicting types for 'g2'}} + int x; +{ + return x; +} + +void test() { + int f1; + { + void f1(double); + { + void f1(double); // expected-note{{previous declaration is here}} + { + int f1(int); // expected-error{{conflicting types for 'f1'}} + } + } + } +} + +extern void g3(int); // expected-note{{previous declaration is here}} +static void g3(int x) { } // expected-error{{static declaration of 'g3' follows non-static declaration}} + +void test2() { + extern int f2; // expected-note 2 {{previous definition is here}} + { + void f2(int); // expected-error{{redefinition of 'f2' as different kind of symbol}} + } + + { + int f2; + { + void f2(int); // expected-error{{redefinition of 'f2' as different kind of symbol}} + } + } +} + +// <rdar://problem/6127293> +int outer1(int); // expected-note{{previous declaration is here}} +struct outer3 { }; +int outer4(int); +int outer5; // expected-note{{previous definition is here}} +int *outer7(int); + +void outer_test() { + int outer1(float); // expected-error{{conflicting types for 'outer1'}} + int outer2(int); // expected-note{{previous declaration is here}} + int outer3(int); // expected-note{{previous declaration is here}} + int outer4(int); // expected-note{{previous declaration is here}} + int outer5(int); // expected-error{{redefinition of 'outer5' as different kind of symbol}} + int* outer6(int); // expected-note{{previous declaration is here}} + int *outer7(int); + int outer8(int); + + int *ip7 = outer7(6); +} + +int outer2(float); // expected-error{{conflicting types for 'outer2'}} +int outer3(float); // expected-error{{conflicting types for 'outer3'}} +int outer4(float); // expected-error{{conflicting types for 'outer4'}} + +void outer_test2(int x) { + int* ip = outer6(x); // expected-warning{{use of out-of-scope declaration of 'outer6'}} + int *ip2 = outer7(x); +} + +void outer_test3() { + int *(*fp)(int) = outer8; // expected-error{{use of undeclared identifier 'outer8'}} +} + +static float outer8(float); // okay + +enum e { e1, e2 }; + +// GNU extension: prototypes and K&R function definitions +int isroot(short x, // expected-note{{previous declaration is here}} + enum e); + +int isroot(x, y) + short x; // expected-warning{{promoted type 'int' of K&R function parameter is not compatible with the parameter type 'short' declared in a previous prototype}} + unsigned int y; +{ + return x == 1; +} + +// PR3817 +void *h0(unsigned a0, ...); +extern __typeof (h0) h1 __attribute__((__sentinel__)); +extern __typeof (h1) h1 __attribute__((__sentinel__)); + +// PR3840 +void i0 (unsigned short a0); +extern __typeof (i0) i1; +extern __typeof (i1) i1; + +typedef int a(); +typedef int a2(int*); +a x; +a2 x2; +void test_x() { + x(5); + x2(5); // expected-warning{{incompatible integer to pointer conversion passing 'int', expected 'int *'}} +} diff --git a/test/Sema/function-sentinel-attr.c b/test/Sema/function-sentinel-attr.c new file mode 100644 index 000000000000..66304796127f --- /dev/null +++ b/test/Sema/function-sentinel-attr.c @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#define NULL (void*)0 + +#define ATTR __attribute__ ((__sentinel__)) + +void foo1 (int x, ...) ATTR; // expected-note {{function has been explicitly marked sentinel here}} +void foo5 (int x, ...) __attribute__ ((__sentinel__(1))); // expected-note {{function has been explicitly marked sentinel here}} +void foo6 (int x, ...) __attribute__ ((__sentinel__(5))); // expected-note {{function has been explicitly marked sentinel here}} +void foo7 (int x, ...) __attribute__ ((__sentinel__(0))); // expected-note {{function has been explicitly marked sentinel here}} +void foo10 (int x, ...) __attribute__ ((__sentinel__(1,1))); +void foo12 (int x, ... ) ATTR; // expected-note {{function has been explicitly marked sentinel here}} + +int main () +{ + + foo1(1, NULL); // OK + foo1(1, 0) ; // expected-warning {{missing sentinel in function call}} + foo5(1, NULL, 2); // OK + foo5(1,2,NULL, 1); // OK + foo5(1, NULL, 2, 1); // expected-warning {{missing sentinel in function call}} + + foo6(1,2,3,4,5,6,7); // expected-warning {{missing sentinel in function call}} + foo6(1,NULL,3,4,5,6,7); // OK + foo7(1); // expected-warning {{not enough variable arguments in 'foo7' declaration to fit a sentinel}} + foo7(1, NULL); // OK + + foo12(1); // expected-warning {{not enough variable arguments in 'foo12' declaration to fit a sentinel}} +} + diff --git a/test/Sema/function.c b/test/Sema/function.c new file mode 100644 index 000000000000..c9d8630c47f6 --- /dev/null +++ b/test/Sema/function.c @@ -0,0 +1,89 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic +// PR1892 +void f(double a[restrict][5]); // should promote to restrict ptr. +void f(double (* restrict a)[5]); + +int foo (__const char *__path); +int foo(__const char *__restrict __file); + +void func(const char*); // expected-note {{previous declaration is here}} +void func(char*); // expected-error{{conflicting types for 'func'}} + +void g(int (*)(const void **, const void **)); +void g(int (*compar)()) { +} + +void h(); // expected-note {{previous declaration is here}} +void h (const char *fmt, ...) {} // expected-error{{conflicting types for 'h'}} + +// PR1965 +int t5(b); // expected-error {{parameter list without types}} +int t6(int x, g); // expected-warning {{type specifier missing, defaults to 'int'}} + +int t7(, ); // expected-error {{expected parameter declarator}} expected-error {{expected parameter declarator}} +int t8(, int a); // expected-error {{expected parameter declarator}} +int t9(int a, ); // expected-error {{expected parameter declarator}} + + +// PR2042 +void t10(){} +void t11(){t10(1);} // expected-warning{{too many arguments}} + +// PR3208 +void t12(int) {} // expected-error{{parameter name omitted}} + +// PR2790 +void t13() { + return 0; // expected-warning {{void function 't13' should not return a value}} +} +int t14() { + return; // expected-warning {{non-void function 't14' should return a value}} +} + +// <rdar://problem/6097326> +y(y) { return y; } // expected-warning{{parameter 'y' was not declared, defaulting to type 'int'}} \ + // expected-warning{{type specifier missing, defaults to 'int'}} + + +// PR3137, <rdar://problem/6127293> +extern int g0_3137(void); +void f0_3137() { + int g0_3137(void); +} +void f1_3137() { + int (*fp)(void) = g0_3137; +} + +void f1static() { + static void f2static(int); // expected-error{{function declared in block scope cannot have 'static' storage class}} + register void f2register(int); // expected-error{{illegal storage class on function}} +} + +struct incomplete_test a(void) {} // expected-error{{incomplete result type 'struct incomplete_test' in function definition}} \ + // expected-note{{forward declaration of 'struct incomplete_test'}} + + +extern __inline +__attribute__((__gnu_inline__)) +void gnu_inline1() {} + +void +__attribute__((__gnu_inline__)) // expected-warning {{'gnu_inline' attribute requires function to be marked 'inline', attribute ignored}} +gnu_inline2() {} + + +// rdar://6802350 +inline foo_t invalid_type() { // expected-error {{unknown type name 'foo_t'}} +} + +typedef void fn_t(void); +fn_t t17; + +// PR4049 +unknown_type t18(void*) { // expected-error {{unknown type name 'unknown_type'}} expected-error{{parameter name omitted}} +} + +unknown_type t19(int* P) { // expected-error {{unknown type name 'unknown_type'}} + P = P+1; // no warning. +} + diff --git a/test/Sema/gnu89.c b/test/Sema/gnu89.c new file mode 100644 index 000000000000..4601cbe93f6e --- /dev/null +++ b/test/Sema/gnu89.c @@ -0,0 +1,3 @@ +// RUN: clang-cc %s -std=gnu89 -pedantic -fsyntax-only -verify + +int f(int restrict); diff --git a/test/Sema/heinous-extensions-off.c b/test/Sema/heinous-extensions-off.c new file mode 100644 index 000000000000..3a9880ce7f75 --- /dev/null +++ b/test/Sema/heinous-extensions-off.c @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -verify + +int foo() { + int a; + // PR3788 + asm("nop" : : "m"((int)(a))); // expected-error {{cast in a inline asm context requiring an l-value}} + // PR3794 + asm("nop" : "=r"((unsigned)a)); // expected-error {{cast in a inline asm context requiring an l-value}} +} + diff --git a/test/Sema/heinous-extensions-on.c b/test/Sema/heinous-extensions-on.c new file mode 100644 index 000000000000..480b1b41e906 --- /dev/null +++ b/test/Sema/heinous-extensions-on.c @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -verify -fheinous-gnu-extensions + +int foo() { + int a; + // PR3788 + asm("nop" : : "m"((int)(a))); // expected-warning {{cast in a inline asm context requiring an l-value}} + // PR3794 + asm("nop" : "=r"((unsigned)a)); // expected-warning {{cast in a inline asm context requiring an l-value}} +} + diff --git a/test/Sema/i-c-e.c b/test/Sema/i-c-e.c new file mode 100644 index 000000000000..de279669922b --- /dev/null +++ b/test/Sema/i-c-e.c @@ -0,0 +1,66 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic -fpascal-strings + +#include <stdint.h> +#include <limits.h> + +int a() {int p; *(1 ? &p : (void*)(0 && (a(),1))) = 10;} // expected-error {{incomplete type 'void' is not assignable}} + +// rdar://6091492 - ?: with __builtin_constant_p as the operand is an i-c-e. +int expr; +char w[__builtin_constant_p(expr) ? expr : 1]; + + +// __builtin_constant_p as the condition of ?: allows arbitrary foldable +// constants to be transmogrified into i-c-e's. +char b[__builtin_constant_p((int)(1.0+2.0)) ? (int)(1.0+2.0) : -1]; + +struct c { + int a : ( // expected-error {{expression is not an integer constant expression}} + __builtin_constant_p((int)(1.0+2.0)) ? (int)(1.0+ + expr // expected-note {{subexpression not valid in an integer constant expression}} + ) : -1); +}; + + + + +void test1(int n, int* p) { *(n ? p : (void *)(7-7)) = 1; } +void test2(int n, int* p) { *(n ? p : (void *)0) = 1; } + + + +char array[1024/(sizeof (long))]; + +int x['\xBb' == (char) 187 ? 1: -1]; + +// PR1992 +void func(int x) +{ + switch (x) { + case sizeof("abc"): break; + case sizeof("loooong"): func(4); + case sizeof("\ploooong"): func(4); + } +} + + +// rdar://4213768 +int expr; +char y[__builtin_constant_p(expr) ? -1 : 1]; +char z[__builtin_constant_p(4) ? 1 : -1]; + +// Comma tests +int comma1[0?1,2:3]; +int comma2[1||(1,2)]; +int comma3[(1,2)]; // expected-warning {{size of static array must be an integer constant expression}} + +// Pointer + __builtin_constant_p +char pbcp[__builtin_constant_p(4) ? (intptr_t)&expr : 0]; // expected-error {{variable length array declaration not allowed at file scope}} + +int illegaldiv1[1 || 1/0]; +int illegaldiv2[1/0]; // expected-error {{variable length array declaration not allowed at file scope}} +int illegaldiv3[INT_MIN / -1]; // expected-error {{variable length array declaration not allowed at file scope}} + +int chooseexpr[__builtin_choose_expr(1, 1, expr)]; +int realop[(__real__ 4) == 4 ? 1 : -1]; +int imagop[(__imag__ 4) == 0 ? 1 : -1]; diff --git a/test/Sema/if-empty-body.c b/test/Sema/if-empty-body.c new file mode 100644 index 000000000000..1d1df40bd6a3 --- /dev/null +++ b/test/Sema/if-empty-body.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f1(int a) { + if (a); // expected-warning {{if statement has empty body}} +} + +void f2(int a) { + if (a) {} +} + +void f3() { + if (1) + xx; // expected-error {{use of undeclared identifier}} + return; // no empty body warning. +} + diff --git a/test/Sema/illegal-types.c b/test/Sema/illegal-types.c new file mode 100644 index 000000000000..c932bb28dcca --- /dev/null +++ b/test/Sema/illegal-types.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 %s + +void a (void []()); // expected-error{{'type name' declared as array of functions}} +void b (void p[]()); // expected-error{{'p' declared as array of functions}} +void c (int &[]); // expected-error{{'type name' declared as array of references}} +void d (int &p[]); // expected-error{{'p' declared as array of references}} + diff --git a/test/Sema/implicit-builtin-decl.c b/test/Sema/implicit-builtin-decl.c new file mode 100644 index 000000000000..696a2b926c9b --- /dev/null +++ b/test/Sema/implicit-builtin-decl.c @@ -0,0 +1,53 @@ +// RUN: clang-cc -fsyntax-only -verify %s +void f() { + int *ptr = malloc(sizeof(int) * 10); // expected-warning{{implicitly declaring C library function 'malloc' with type}} \ + // expected-note{{please include the header <stdlib.h> or explicitly provide a declaration for 'malloc'}} \ + // expected-note{{'malloc' is a builtin with type 'void *}} +} + +void *alloca(__SIZE_TYPE__); // redeclaration okay + +int *calloc(__SIZE_TYPE__, __SIZE_TYPE__); // expected-warning{{incompatible redeclaration of library function 'calloc'}} \ + // expected-note{{'calloc' is a builtin with type 'void *}} + + +void g(int malloc) { // okay: these aren't functions + int calloc = 1; +} + +void h() { + int malloc(int); // expected-warning{{incompatible redeclaration of library function 'malloc'}} + int strcpy(int); // expected-warning{{incompatible redeclaration of library function 'strcpy'}} \ + // expected-note{{'strcpy' is a builtin with type 'char *(char *, char const *)'}} +} + +void f2() { + fprintf(0, "foo"); // expected-error{{implicit declaration of 'fprintf' requires inclusion of the header <stdio.h>}} +} + +// PR2892 +void __builtin_object_size(); // expected-error{{conflicting types}} \ +// expected-note{{'__builtin_object_size' is a builtin with type}} + +int a[10]; + +int f0() { + return __builtin_object_size(&a); // expected-error {{too few arguments to function}} +} + +void * realloc(void *p, int size) { // expected-warning{{incompatible redeclaration of library function 'realloc'}} \ +// expected-note{{'realloc' is a builtin with type 'void *(void *,}} + return p; +} + +// PR3855 +void snprintf(); // expected-warning{{incompatible redeclaration of library function 'snprintf'}} \ + // expected-note{{'snprintf' is a builtin}} + +int +main(int argc, char *argv[]) +{ + snprintf(); +} + +void snprintf() { } diff --git a/test/Sema/implicit-builtin-freestanding.c b/test/Sema/implicit-builtin-freestanding.c new file mode 100644 index 000000000000..9bd5c05892ec --- /dev/null +++ b/test/Sema/implicit-builtin-freestanding.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -verify -ffreestanding %s + +int malloc(int a) { return a; } + diff --git a/test/Sema/implicit-builtin-redecl.c b/test/Sema/implicit-builtin-redecl.c new file mode 100644 index 000000000000..cd99b5455318 --- /dev/null +++ b/test/Sema/implicit-builtin-redecl.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR3592 +static void* malloc(int); +static void* malloc(int size) { + return ((void*)0); /*do not use heap in this file*/ +} + +void *calloc(int, int, int); // expected-warning{{incompatible redeclaration of library function 'calloc' will be ignored}} \ +// expected-note{{'calloc' is a builtin with type 'void *}} + +void f1(void) { + calloc(0, 0, 0); +} diff --git a/test/Sema/implicit-cast.c b/test/Sema/implicit-cast.c new file mode 100644 index 000000000000..ce34ad6d1c65 --- /dev/null +++ b/test/Sema/implicit-cast.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only %s + +static char *test1(int cf) { + return cf ? "abc" : 0; +} +static char *test2(int cf) { + return cf ? 0 : "abc"; +} diff --git a/test/Sema/implicit-decl.c b/test/Sema/implicit-decl.c new file mode 100644 index 000000000000..8873e76098ca --- /dev/null +++ b/test/Sema/implicit-decl.c @@ -0,0 +1,17 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +typedef int int32_t; +typedef unsigned char Boolean; + +void func() { + int32_t *vector[16]; + const char compDesc[16 + 1]; + int32_t compCount = 0; + if (_CFCalendarDecomposeAbsoluteTimeV(compDesc, vector, compCount)) { // expected-note {{previous implicit declaration is here}} + } + return ((void *)0); // expected-warning {{void function 'func' should not return a value}} +} +Boolean _CFCalendarDecomposeAbsoluteTimeV(const char *componentDesc, int32_t **vector, int32_t count) { // expected-error{{conflicting types for '_CFCalendarDecomposeAbsoluteTimeV'}} + return 0; +} + diff --git a/test/Sema/implicit-def.c b/test/Sema/implicit-def.c new file mode 100644 index 000000000000..2c2594680a11 --- /dev/null +++ b/test/Sema/implicit-def.c @@ -0,0 +1,8 @@ +/* RUN: clang-cc -fsyntax-only %s -std=c89 && + * RUN: not clang-cc -fsyntax-only %s -std=c99 -pedantic-errors + */ + +int A() { + return X(); +} + diff --git a/test/Sema/implicit-int.c b/test/Sema/implicit-int.c new file mode 100644 index 000000000000..04b27a8f0ea9 --- /dev/null +++ b/test/Sema/implicit-int.c @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only %s -verify -pedantic + +foo() { // expected-warning {{type specifier missing, defaults to 'int'}} +} + +y; // expected-warning {{type specifier missing, defaults to 'int'}} + +// rdar://6131634 +void f((x)); // expected-warning {{type specifier missing, defaults to 'int'}} + + +// PR3702 +#define PAD(ms10) { \ + register i; \ +} + +#define ILPAD() PAD((NROW - tt.tt_row) * 10) /* 1 ms per char */ + +void +h19_insline(n) // expected-warning {{parameter 'n' was not declared, defaulting to type 'int'}} +{ + ILPAD(); // expected-warning {{type specifier missing, defaults to 'int'}} +} + +struct foo { + __extension__ __attribute__((packed)) x : 4; // expected-warning {{type specifier missing, defaults to 'int'}} +}; + + + + diff --git a/test/Sema/incompatible-sign.c b/test/Sema/incompatible-sign.c new file mode 100644 index 000000000000..a62f9a8ba709 --- /dev/null +++ b/test/Sema/incompatible-sign.c @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +int a(int* x); +int b(unsigned* y) { return a(y); } // expected-warning {{pointer types point to integer types with different sign}} + diff --git a/test/Sema/incomplete-call.c b/test/Sema/incomplete-call.c new file mode 100644 index 000000000000..aedfe50bbfdd --- /dev/null +++ b/test/Sema/incomplete-call.c @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct foo; // expected-note 3 {{forward declaration of 'struct foo'}} + +struct foo a(); +void b(struct foo); +void c(); + +void func() { + a(); // expected-error{{return type of called function ('struct foo') is incomplete}} + b(*(struct foo*)0); // expected-error{{argument type 'struct foo' is incomplete}} + c(*(struct foo*)0); // expected-error{{argument type 'struct foo' is incomplete}} +} diff --git a/test/Sema/incomplete-decl.c b/test/Sema/incomplete-decl.c new file mode 100644 index 000000000000..eb93e8e38031 --- /dev/null +++ b/test/Sema/incomplete-decl.c @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct foo; // expected-note 4 {{forward declaration of 'struct foo'}} + +void b; // expected-error {{variable has incomplete type 'void'}} +struct foo f; // expected-error{{tentative definition has type 'struct foo' that is never completed}} + +static void c; // expected-error {{variable has incomplete type 'void'}} +static struct foo g; // expected-error {{variable has incomplete type 'struct foo'}} + +extern void d; +extern struct foo e; + +int ary[]; // expected-warning {{tentative array definition assumed to have one element}} +struct foo bary[]; // expected-error {{array has incomplete element type 'struct foo'}} + +void func() { + int ary[]; // expected-error{{variable has incomplete type 'int []'}} + void b; // expected-error {{variable has incomplete type 'void'}} + struct foo f; // expected-error {{variable has incomplete type 'struct foo'}} +} + +int h[]; // expected-warning {{tentative array definition assumed to have one element}} +int (*i)[] = &h+1; // expected-error {{arithmetic on pointer to incomplete type 'int (*)[]'}} + +struct bar j = {1}; // expected-error {{variable has incomplete type 'struct bar'}} \ + expected-note {{forward declaration of 'struct bar'}} +struct bar k; +struct bar { int a; }; + diff --git a/test/Sema/indirect-goto.c b/test/Sema/indirect-goto.c new file mode 100644 index 000000000000..35fb5e6315e2 --- /dev/null +++ b/test/Sema/indirect-goto.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct c {int x;}; +int a(struct c x, long long y) { + goto *x; // expected-error{{incompatible type}} + goto *y; // expected-warning{{incompatible integer to pointer conversion}} +} + diff --git a/test/Sema/init-struct-qualified.c b/test/Sema/init-struct-qualified.c new file mode 100644 index 000000000000..539820ae418c --- /dev/null +++ b/test/Sema/init-struct-qualified.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify < %s +typedef float CGFloat; +typedef struct _NSPoint { CGFloat x; CGFloat y; } NSPoint; +typedef struct _NSSize { CGFloat width; CGFloat height; } NSSize; +typedef struct _NSRect { NSPoint origin; NSSize size; } NSRect; + +extern const NSPoint NSZeroPoint; + +extern NSSize canvasSize(); +void func() { + const NSRect canvasRect = { NSZeroPoint, canvasSize() }; +} diff --git a/test/Sema/init.c b/test/Sema/init.c new file mode 100644 index 000000000000..1cbcbb7e36f8 --- /dev/null +++ b/test/Sema/init.c @@ -0,0 +1,128 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +#include <stddef.h> +#include <stdint.h> + +typedef void (* fp)(void); +void foo(void); + +// PR clang/3377 +fp a[(short int)1] = { foo }; + +int myArray[5] = {1, 2, 3, 4, 5}; +int *myPointer2 = myArray; +int *myPointer = &(myArray[2]); + + +extern int x; +void *g = &x; +int *h = &x; + +int test() { +int a[10]; +int b[10] = a; // expected-error {{initialization with '{...}' expected}} +int +; // expected-error {{expected identifier or '('}} expected-error {{expected ';' at end of declaration}} +} + + +// PR2050 +struct cdiff_cmd { + const char *name; + unsigned short argc; + int (*handler)(); +}; +int cdiff_cmd_open(); +struct cdiff_cmd commands[] = { + {"OPEN", 1, &cdiff_cmd_open } +}; + +// PR2348 +static struct { int z; } s[2]; +int *t = &(*s).z; + +// PR2349 +short *a2(void) +{ + short int b; + static short *bp = &b; // expected-error {{initializer element is not a compile-time constant}} + + return bp; +} + +int pbool(void) { + typedef const _Bool cbool; + _Bool pbool1 = (void *) 0; + cbool pbool2 = &pbool; + return pbool2; +} + + +// rdar://5870981 +union { float f; unsigned u; } u = { 1.0f }; + +// rdar://6156694 +int f3(int x) { return x; } +typedef void (*vfunc)(void); +void *bar = (vfunc) f3; + +// PR2747 +struct sym_reg { + char nc_gpreg; +}; +int sym_fw1a_scr[] = { + ((int)(&((struct sym_reg *)0)->nc_gpreg)) & 0, + 8 * ((int)(&((struct sym_reg *)0)->nc_gpreg)) +}; + +// PR3001 +struct s1 s2 = { + .a = sizeof(struct s3), // expected-error {{invalid application of 'sizeof'}} \ + // expected-note{{forward declaration of 'struct s3'}} + .b = bogus // expected-error {{use of undeclared identifier 'bogus'}} +} + +// PR3382 +char t[] = ("Hello"); + +// <rdar://problem/6094855> +typedef struct { } empty; + +typedef struct { + empty e; + int i2; +} st; + +st st1 = { .i2 = 1 }; + +// <rdar://problem/6096826> +struct { + int a; + int z[2]; +} y = { .z = {} }; + +int bbb[10]; + +struct foo2 { + uintptr_t a; +}; + +struct foo2 bar2[] = { + { (intptr_t)bbb } +}; + +struct foo2 bar3 = { 1, 2 }; // expected-warning{{excess elements in struct initializer}} + +int* ptest1 = __builtin_choose_expr(1, (int*)0, (int*)0); + +typedef int32_t ivector4 __attribute((vector_size(16))); +ivector4 vtest1 = 1 ? (ivector4){1} : (ivector4){1}; +ivector4 vtest2 = __builtin_choose_expr(1, (ivector4){1}, (ivector4){1}); +ivector4 vtest3 = __real__ (ivector4){1}; +ivector4 vtest4 = __imag__ (ivector4){1}; + +uintptr_t ptrasintadd1 = (uintptr_t)&a - 4; +uintptr_t ptrasintadd2 = (uintptr_t)&a + 4; +uintptr_t ptrasintadd3 = 4 + (uintptr_t)&a; + +// PR4285 +const wchar_t widestr[] = L"asdf"; diff --git a/test/Sema/inline.c b/test/Sema/inline.c new file mode 100644 index 000000000000..adcde51363eb --- /dev/null +++ b/test/Sema/inline.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Check that we don't allow illegal uses of inline +inline int a; // expected-error{{'inline' can only appear on functions}} +typedef inline int b; // expected-error{{'inline' can only appear on functions}} +int d(inline int a); // expected-error{{'inline' can only appear on functions}} diff --git a/test/Sema/int-arith-convert.c b/test/Sema/int-arith-convert.c new file mode 100644 index 000000000000..5bbab7d9af96 --- /dev/null +++ b/test/Sema/int-arith-convert.c @@ -0,0 +1,12 @@ +// RUN: clang-cc -triple=i686-linux-gnu -fsyntax-only -verify %s + +// Check types are the same through redeclaration +unsigned long x; +__typeof(1u+1l) x; + +unsigned y; +__typeof(1+1u) y; +__typeof(1u+1) y; + +long long z; +__typeof(1ll+1u) z; diff --git a/test/Sema/invalid-decl.c b/test/Sema/invalid-decl.c new file mode 100644 index 000000000000..8c458008cb5c --- /dev/null +++ b/test/Sema/invalid-decl.c @@ -0,0 +1,22 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +void test() { + char = 4; // expected-error {{expected identifier}} +} + + +// PR2400 +typedef xtype (*x)(void* handle); // expected-error {{function cannot return array or function type}} expected-warning {{type specifier missing, defaults to 'int'}} expected-warning {{type specifier missing, defaults to 'int'}} + +typedef void ytype(); + + +typedef struct _zend_module_entry zend_module_entry; +struct _zend_module_entry { + ytype globals_size; // expected-error {{field 'globals_size' declared as a function}} +}; + +zend_module_entry openssl_module_entry = { + sizeof(zend_module_entry) +}; + diff --git a/test/Sema/invalid-init-diag.c b/test/Sema/invalid-init-diag.c new file mode 100644 index 000000000000..724d0ea368ba --- /dev/null +++ b/test/Sema/invalid-init-diag.c @@ -0,0 +1,4 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +int a; +struct {int x;} x = a; // expected-error {{incompatible type initializing 'int', expected 'struct <anonymous>'}} diff --git a/test/Sema/invalid-struct-init.c b/test/Sema/invalid-struct-init.c new file mode 100644 index 000000000000..73e2e446f131 --- /dev/null +++ b/test/Sema/invalid-struct-init.c @@ -0,0 +1,29 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +typedef struct _zend_module_entry zend_module_entry; +struct _zend_module_entry { + _efree((p)); // expected-error{{type name requires a specifier or qualifier}} \ + expected-error{{field '_efree' declared as a function}} \ + expected-warning {{type specifier missing, defaults to 'int'}} \ + expected-warning {{type specifier missing, defaults to 'int'}} + +}; +typedef struct _zend_function_entry { } zend_function_entry; +typedef struct _zend_pcre_globals { } zend_pcre_globals; +zend_pcre_globals pcre_globals; + +static void zm_globals_ctor_pcre(zend_pcre_globals *pcre_globals ) { } +static void zm_globals_dtor_pcre(zend_pcre_globals *pcre_globals ) { } +static void zm_info_pcre(zend_module_entry *zend_module ) { } +static int zm_startup_pcre(int type, int module_number ) { } + +static int zm_shutdown_pcre(int type, int module_number ) { + zend_function_entry pcre_functions[] = {{ }; // expected-error{{expected '}'}} expected-note {{to match this '{'}} + zend_module_entry pcre_module_entry = { + sizeof(zend_module_entry), 20071006, 0, 0, ((void *)0), ((void *)0), + "pcre", pcre_functions, zm_startup_pcre, zm_shutdown_pcre, ((void *)0), + ((void *)0), zm_info_pcre, ((void *)0), sizeof(zend_pcre_globals), &pcre_globals, + ((void (*)(void* ))(zm_globals_ctor_pcre)), ((void (*)(void* ))(zm_globals_dtor_pcre)), + ((void *)0), 0, 0, ((void *)0), 0 + }; +} diff --git a/test/Sema/knr-def-call.c b/test/Sema/knr-def-call.c new file mode 100644 index 000000000000..6b033fc3a21f --- /dev/null +++ b/test/Sema/knr-def-call.c @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// C DR #316, PR 3626. +void f0(a, b, c, d) int a,b,c,d; {} +void t0(void) { + f0(1); // expected-warning{{too few arguments}} +} + +void f1(a, b) int a, b; {} +void t1(void) { + f1(1, 2, 3); // expected-warning{{too many arguments}} +} + +void f2(float); // expected-note{{previous declaration is here}} +void f2(x) float x; { } // expected-warning{{promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype}} + +typedef void (*f3)(void); +f3 t3(int b) { return b? f0 : f1; } // okay diff --git a/test/Sema/knr-variadic-def.c b/test/Sema/knr-variadic-def.c new file mode 100644 index 000000000000..070ba071ca67 --- /dev/null +++ b/test/Sema/knr-variadic-def.c @@ -0,0 +1,29 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s +// PR4287 + +#include <stdarg.h> +char *foo = "test"; +int test(char*,...); + +int test(fmt) + char*fmt; +{ + va_list ap; + char*a; + int x; + + va_start(ap,fmt); + a=va_arg(ap,char*); + x=(a!=foo); + va_end(ap); + return x; +} + +void exit(); + +int main(argc,argv) + int argc;char**argv; +{ + exit(test("",foo)); +} + diff --git a/test/Sema/member-reference.c b/test/Sema/member-reference.c new file mode 100644 index 000000000000..b810ccf15b72 --- /dev/null +++ b/test/Sema/member-reference.c @@ -0,0 +1,20 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +struct simple { int i; }; + +void f(void) { + struct simple s[1]; + s->i = 1; +} + +typedef int x; +struct S { + int x; + x z; +}; + +void g(void) { + struct S s[1]; + s->x = 1; + s->z = 2; +} diff --git a/test/Sema/merge-decls.c b/test/Sema/merge-decls.c new file mode 100644 index 000000000000..f4c25f511429 --- /dev/null +++ b/test/Sema/merge-decls.c @@ -0,0 +1,39 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +void foo(void); +void foo(void) {} +void foo(void); +void foo(void); // expected-note {{previous declaration is here}} + +void foo(int); // expected-error {{conflicting types for 'foo'}} + +int funcdef() +{ + return 0; +} + +int funcdef(); + +int funcdef2() { return 0; } // expected-note {{previous definition is here}} +int funcdef2() { return 0; } // expected-error {{redefinition of 'funcdef2'}} + +// PR2502 +void (*f)(void); +void (*f)() = 0; + +typedef __attribute__(( ext_vector_type(2) )) int Vi2; +typedef __attribute__(( ext_vector_type(2) )) float Vf2; + +Vf2 g0; // expected-note {{previous definition is here}} +Vi2 g0; // expected-error {{redefinition of 'g0'}} + +_Complex int g1; // expected-note {{previous definition is here}} +_Complex float g1; // expected-error {{redefinition of 'g1'}} + +// rdar://6096412 +extern char i6096412[10]; +extern char i6096412[]; +void foo6096412(void) { + int x = sizeof(i6096412); +} + diff --git a/test/Sema/ms-fuzzy-asm.c b/test/Sema/ms-fuzzy-asm.c new file mode 100644 index 000000000000..58dcbcfc5232 --- /dev/null +++ b/test/Sema/ms-fuzzy-asm.c @@ -0,0 +1,9 @@ +// RUN: clang-cc %s -verify -fms-extensions + +#define M __asm int 0x2c +#define M2 int + +void t1(void) { M } +void t2(void) { __asm int 0x2c } +void t3(void) { __asm M2 0x2c } + diff --git a/test/Sema/nested-redef.c b/test/Sema/nested-redef.c new file mode 100644 index 000000000000..ea180910128b --- /dev/null +++ b/test/Sema/nested-redef.c @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct X { // expected-note{{previous definition is here}} + struct X { } x; // expected-error{{nested redefinition of 'X'}} +}; + +struct Y { }; +void f(void) { + struct Y { }; // okay: this is a different Y +} + +struct T; +struct Z { + struct T { int x; } t; + struct U { int x; } u; +}; + +void f2(void) { + struct T t; + struct U u; +} + + diff --git a/test/Sema/nonnull.c b/test/Sema/nonnull.c new file mode 100644 index 000000000000..3bed2feb5012 --- /dev/null +++ b/test/Sema/nonnull.c @@ -0,0 +1,32 @@ +// RUN: clang-cc -fblocks -fsyntax-only -verify %s + +int f1(int x) __attribute__((nonnull)); // expected-warning{{'nonnull' attribute applied to function with no pointer arguments}} +int f2(int *x) __attribute__ ((nonnull (1))); +int f3(int *x) __attribute__ ((nonnull (0))); // expected-error {{'nonnull' attribute parameter 1 is out of bounds}} +int f4(int *x, int *y) __attribute__ ((nonnull (1,2))); +int f5(int *x, int *y) __attribute__ ((nonnull (2,1))); + +extern void func1 (void (^block1)(), void (^block2)(), int) __attribute__((nonnull)); + +extern void func3 (void (^block1)(), int, void (^block2)(), int) +__attribute__((nonnull(1,3))); + +extern void func4 (void (^block1)(), void (^block2)()) __attribute__((nonnull(1))) +__attribute__((nonnull(2))); + +void +foo (int i1, int i2, int i3, void (^cp1)(), void (^cp2)(), void (^cp3)()) +{ + func1(cp1, cp2, i1); + + func1(0, cp2, i1); // expected-warning {{null passed to a callee which requires a non-null argument}} + func1(cp1, 0, i1); // expected-warning {{null passed to a callee which requires a non-null argument}} + func1(cp1, cp2, 0); + + + func3(0, i2, cp3, i3); // expected-warning {{null passed to a callee which requires a non-null argument}} + func3(cp3, i2, 0, i3); // expected-warning {{null passed to a callee which requires a non-null argument}} + + func4(0, cp1); // expected-warning {{null passed to a callee which requires a non-null argument}} + func4(cp1, 0); // expected-warning {{null passed to a callee which requires a non-null argument}} +} diff --git a/test/Sema/offsetof.c b/test/Sema/offsetof.c new file mode 100644 index 000000000000..f8b9fed03c3c --- /dev/null +++ b/test/Sema/offsetof.c @@ -0,0 +1,50 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER) + +typedef struct P { int i; float f; } PT; +struct external_sun3_core +{ + unsigned c_regs; + + PT X[100]; + +}; + +void swap() +{ + int x; + x = offsetof(struct external_sun3_core, c_regs); + x = __builtin_offsetof(struct external_sun3_core, X[42].f); + + x = __builtin_offsetof(struct external_sun3_core, X[42].f2); // expected-error {{no member named 'f2'}} + x = __builtin_offsetof(int, X[42].f2); // expected-error {{offsetof requires struct}} + + int a[__builtin_offsetof(struct external_sun3_core, X) == 4 ? 1 : -1]; + int b[__builtin_offsetof(struct external_sun3_core, X[42]) == 340 ? 1 : -1]; + int c[__builtin_offsetof(struct external_sun3_core, X[42].f2) == 344 ? 1 : -1]; // expected-error {{no member named 'f2'}} +} + +extern int f(); + +struct s1 { int a; }; +int v1 = offsetof (struct s1, a) == 0 ? 0 : f(); + +struct s2 { int a; }; +int v2 = (int)(&((struct s2 *) 0)->a) == 0 ? 0 : f(); + +struct s3 { int a; }; +int v3 = __builtin_offsetof(struct s3, a) == 0 ? 0 : f(); + +// PR3396 +struct sockaddr_un { + unsigned char sun_len; + char sun_path[104]; +}; +int a(int len) { +int a[__builtin_offsetof(struct sockaddr_un, sun_path[len+1])]; +} + +// PR4079 +union x {struct {int x;};}; +int x[__builtin_offsetof(union x, x)]; diff --git a/test/Sema/overloadable-complex.c b/test/Sema/overloadable-complex.c new file mode 100644 index 000000000000..62b388213347 --- /dev/null +++ b/test/Sema/overloadable-complex.c @@ -0,0 +1,50 @@ +// RUN: clang-cc -fsyntax-only -verify %s +char *foo(float) __attribute__((__overloadable__)); // expected-note 3 {{candidate function}} + +void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); + // Note: GCC and EDG reject these two, but they are valid C99 conversions + char *cp3 = foo(fc); + char *cp4 = foo(dc); +} + +int *foo(float _Complex) __attribute__((__overloadable__)); // expected-note 3 {{candidate function}} + +void test_foo_2(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}} + int *ip = foo(fc); + int *lp = foo(dc); // expected-error{{call to 'foo' is ambiguous; candidates are:}} +} + +long *foo(double _Complex) __attribute__((__overloadable__)); // expected-note {{candidate function}} + +void test_foo_3(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}} + int *ip = foo(fc); + long *lp = foo(dc); +} + +char *promote_or_convert(double _Complex) __attribute__((__overloadable__)); // expected-note 2 {{candidate function}} +int *promote_or_convert(long double _Complex) __attribute__((__overloadable__)); // expected-note 2 {{candidate function}} + +void test_promote_or_convert(float f, float _Complex fc) { + char *cp = promote_or_convert(fc); // expected-error{{call to 'promote_or_convert' is ambiguous; candidates are:}} + int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous; candidates are:}} +} + +char *promote_or_convert2(float) __attribute__((__overloadable__)); +int *promote_or_convert2(double _Complex) __attribute__((__overloadable__)); + +void test_promote_or_convert2(float _Complex fc) { + int *cp = promote_or_convert2(fc); +} + +char *promote_or_convert3(int _Complex) __attribute__((__overloadable__)); +int *promote_or_convert3(long _Complex) __attribute__((__overloadable__)); + +void test_promote_or_convert3(short _Complex sc) { + char *cp = promote_or_convert3(sc); +} diff --git a/test/Sema/overloadable.c b/test/Sema/overloadable.c new file mode 100644 index 000000000000..0d5db3a98454 --- /dev/null +++ b/test/Sema/overloadable.c @@ -0,0 +1,53 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int var __attribute__((overloadable)); // expected-error{{'overloadable' attribute can only be applied to a function}} + +int *f(int) __attribute__((overloadable)); // expected-note 2{{previous overload of function is here}} +float *f(float); // expected-error{{overloaded function 'f' must have the 'overloadable' attribute}} +int *f(int); // expected-error{{redeclaration of 'f' must have the 'overloadable' attribute}} \ + // expected-note{{previous declaration is here}} +double *f(double) __attribute__((overloadable)); // okay, new + +void test_f(int iv, float fv, double dv) { + int *ip = f(iv); + float *fp = f(fv); + double *dp = f(dv); +} + +int *accept_funcptr(int (*)()) __attribute__((overloadable)); // \ + // expected-note{{candidate function}} +float *accept_funcptr(int (*)(int, double)) __attribute__((overloadable)); // \ + // expected-note{{candidate function}} + +void test_funcptr(int (*f1)(int, double), + int (*f2)(int, float)) { + float *fp = accept_funcptr(f1); + accept_funcptr(f2); // expected-error{{no matching function for call to 'accept_funcptr'; candidates are:}} +} + +struct X { int x; float y; }; +struct Y { int x; float y; }; +int* accept_struct(struct X x) __attribute__((__overloadable__)); +float* accept_struct(struct Y y) __attribute__((overloadable)); + +void test_struct(struct X x, struct Y y) { + int *ip = accept_struct(x); + float *fp = accept_struct(y); +} + +double *f(int) __attribute__((overloadable)); // expected-error{{conflicting types for 'f'}} + +double promote(float) __attribute__((__overloadable__)); +double promote(double) __attribute__((__overloadable__)); +long double promote(long double) __attribute__((__overloadable__)); + +void promote() __attribute__((__overloadable__)); // expected-error{{'overloadable' function 'promote' must have a prototype}} +void promote(...) __attribute__((__overloadable__, __unavailable__)); // \ + // expected-note{{candidate function}} + +void test_promote(short* sp) { + promote(1.0); + promote(sp); // expected-error{{call to unavailable function 'promote'}} +} + + diff --git a/test/Sema/pointer-addition.c b/test/Sema/pointer-addition.c new file mode 100644 index 000000000000..87d5eaf39c99 --- /dev/null +++ b/test/Sema/pointer-addition.c @@ -0,0 +1,19 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic + +typedef struct S S; // expected-note 3 {{forward declaration of 'struct S'}} +void a(S* b, void* c) { + void (*fp)(int) = 0; + b++; // expected-error {{arithmetic on pointer to incomplete type}} + b += 1; // expected-error {{arithmetic on pointer to incomplete type}} + c++; // expected-warning {{use of GNU void* extension}} + c += 1; // expected-warning {{use of GNU void* extension}} + c--; // expected-warning {{use of GNU void* extension}} + c -= 1; // expected-warning {{use of GNU void* extension}} + b = 1+b; // expected-error {{arithmetic on pointer to incomplete type}} + /* The next couple tests are only pedantic warnings in gcc */ + void (*d)(S*,void*) = a; + d += 1; // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}} + d++; // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}}} + d--; // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}} + d -= 1; // expected-warning {{arithmetic on pointer to function type 'void (*)(S *, void *)' is a GNU extension}} +} diff --git a/test/Sema/pointer-subtract-compat.c b/test/Sema/pointer-subtract-compat.c new file mode 100644 index 000000000000..b3be37e7f185 --- /dev/null +++ b/test/Sema/pointer-subtract-compat.c @@ -0,0 +1,11 @@ +// RUN: clang-cc %s -fsyntax-only -verify -pedantic + +typedef const char rchar; +int a(char* a, rchar* b) { + return a-b; +} + +// <rdar://problem/6520707> +void f0(void (*fp)(void)) { + int x = fp - fp; // expected-warning{{arithmetic on pointer to function type 'void (*)(void)' is a GNU extension}} +} diff --git a/test/Sema/pragma-pack-2.c b/test/Sema/pragma-pack-2.c new file mode 100644 index 000000000000..25be5539783e --- /dev/null +++ b/test/Sema/pragma-pack-2.c @@ -0,0 +1,93 @@ +// RUN: clang-cc -triple i686-apple-darwin9 %s -fsyntax-only -verify + +#include <stddef.h> + +#pragma pack(4) + +// Baseline +struct s0 { + char f0; + int f1; +}; +extern int a0[offsetof(struct s0, f1) == 4 ? 1 : -1]; + +#pragma pack(push, 2) +struct s1 { + char f0; + int f1; +}; +extern int a1[offsetof(struct s1, f1) == 2 ? 1 : -1]; +#pragma pack(pop) + +// Test scope of definition + +#pragma pack(push, 2) +struct s2_0 { +#pragma pack(pop) + char f0; + int f1; +}; +extern int a2_0[offsetof(struct s2_0, f1) == 2 ? 1 : -1]; + +struct s2_1 { + char f0; +#pragma pack(push, 2) + int f1; +#pragma pack(pop) +}; +extern int a2_1[offsetof(struct s2_1, f1) == 4 ? 1 : -1]; + +struct s2_2 { + char f0; + int f1; +#pragma pack(push, 2) +}; +#pragma pack(pop) +extern int a2_2[offsetof(struct s2_2, f1) == 4 ? 1 : -1]; + +struct s2_3 { + char f0; +#pragma pack(push, 2) + struct s2_3_0 { +#pragma pack(pop) + int f0; + } f1; +}; +extern int a2_3[offsetof(struct s2_3, f1) == 2 ? 1 : -1]; + +struct s2_4 { + char f0; + struct s2_4_0 { + int f0; +#pragma pack(push, 2) + } f1; +#pragma pack(pop) +}; +extern int a2_4[offsetof(struct s2_4, f1) == 4 ? 1 : -1]; + +#pragma pack(1) +struct s3_0 { + char f0; + int f1; +}; +#pragma pack() +struct s3_1 { + char f0; + int f1; +}; +extern int a3_0[offsetof(struct s3_0, f1) == 1 ? 1 : -1]; +extern int a3_1[offsetof(struct s3_1, f1) == 4 ? 1 : -1]; + +// pack(0) is like pack() +#pragma pack(1) +struct s4_0 { + char f0; + int f1; +}; +#pragma pack(0) +struct s4_1 { + char f0; + int f1; +}; +extern int a4_0[offsetof(struct s4_0, f1) == 1 ? 1 : -1]; +extern int a4_1[offsetof(struct s4_1, f1) == 4 ? 1 : -1]; diff --git a/test/Sema/pragma-pack-3.c b/test/Sema/pragma-pack-3.c new file mode 100644 index 000000000000..a2d665ea7417 --- /dev/null +++ b/test/Sema/pragma-pack-3.c @@ -0,0 +1,34 @@ +// RUN: clang-cc -triple i686-apple-darwin9 %s -fsyntax-only -verify + +// Stack: [], Alignment: 8 + +#pragma pack(push, 1) +// Stack: [8], Alignment: 1 + +#pragma pack(push, 4) +// Stack: [8, 1], Alignment: 4 + +// Note that this differs from gcc; pack() in gcc appears to pop the +// top stack entry and resets the current alignment. This is both +// inconsistent with MSVC, and the gcc documentation. In other cases, +// for example changing this to pack(8), I don't even understand what gcc +// is doing. + +#pragma pack() +// Stack: [8, 1], Alignment: 8 + +#pragma pack(pop) +// Stack: [8], Alignment: 1 +struct s0 { + char f0; + short f1; +}; +int a[sizeof(struct s0) == 3 ? 1 : -1]; + +#pragma pack(pop) +// Stack: [], Alignment: 8 +struct s1 { + char f0; + short f1; +}; +int b[sizeof(struct s1) == 4 ? 1 : -1]; diff --git a/test/Sema/pragma-pack.c b/test/Sema/pragma-pack.c new file mode 100644 index 000000000000..51398fa0a554 --- /dev/null +++ b/test/Sema/pragma-pack.c @@ -0,0 +1,27 @@ +// RUN: clang-cc -triple i686-apple-darwin9 -fsyntax-only -verify %s + +/* expected-warning {{value of #pragma pack(show) == 8}} */ #pragma pack(show) +/* expected-warning {{expected #pragma pack parameter to be}} */ #pragma pack(3) +/* expected-warning {{value of #pragma pack(show) == 8}} */ #pragma pack(show) +#pragma pack(4) +/* expected-warning {{value of #pragma pack(show) == 4}} */ #pragma pack(show) +#pragma pack() // resets to default +/* expected-warning {{value of #pragma pack(show) == 8}} */ #pragma pack(show) +#pragma pack(2) +#pragma pack(push, eek, 16) // -> (eek, 2), 16 +/* expected-warning {{value of #pragma pack(show) == 16}} */ #pragma pack(show) +#pragma pack(push) // -> (eek, 2), (, 2), 16 +/* expected-warning {{value of #pragma pack(show) == 16}} */ #pragma pack(show) +#pragma pack(1) +#pragma pack(push, 8) // -> (eek, 2), (, 2), (, 1), 8 +/* expected-warning {{value of #pragma pack(show) == 8}} */ #pragma pack(show) +#pragma pack(pop) // -> (eek, 2), (,2), 1 +/* expected-warning {{value of #pragma pack(show) == 1}} */ #pragma pack(show) +#pragma pack(pop, eek) +/* expected-warning {{value of #pragma pack(show) == 2}} */ #pragma pack(show) +/* expected-warning {{pack(pop, ...) failed: stack empty}} */ #pragma pack(pop) + +#pragma pack(push) +#pragma pack(pop, 16) +/* expected-warning {{value of #pragma pack(show) == 16}} */ #pragma pack(show) + diff --git a/test/Sema/pragma-unused.c b/test/Sema/pragma-unused.c new file mode 100644 index 000000000000..fe8bf8608bc3 --- /dev/null +++ b/test/Sema/pragma-unused.c @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f1(void) { + int x, y, z; + #pragma unused(x) + #pragma unused(y, z) + + int w; // FIXME: We should emit a warning that 'w' is unused. + #pragma unused w // expected-warning{{missing '(' after '#pragma unused' - ignoring}} +} + +void f2(void) { + int x, y; + #pragma unused(x,) // expected-warning{{expected '#pragma unused' argument to be a variable name}} + #pragma unused() // expected-warning{{expected '#pragma unused' argument to be a variable name}} +} + +void f3(void) { + #pragma unused(x) // expected-error{{use of undeclared identifier 'x'}} +} + +void f4(void) { + int w; // FIXME: We should emit a warning that 'w' is unused. + #pragma unused((w)) // expected-warning{{expected '#pragma unused' argument to be a variable name}} +} + +int k; +void f5(void) { + #pragma unused(k) // expected-warning{{only local variables can be arguments to '#pragma unused' - ignored}} +} + +void f6(void) { + int z; // no-warning + { + #pragma unused(z) // no-warning + } +} + diff --git a/test/Sema/predef.c b/test/Sema/predef.c new file mode 100644 index 000000000000..7b3fe5038f96 --- /dev/null +++ b/test/Sema/predef.c @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void abcdefghi12(void) { + const char (*ss)[12] = &__func__; + static int arr[sizeof(__func__)==12 ? 1 : -1]; +} + +char *X = __func__; // expected-warning {{predefined identifier is only valid}} \ + expected-warning {{initializing 'char const [1]' discards qualifiers, expected 'char *'}} + +void a() { + __func__[0] = 'a'; // expected-error {{variable is not assignable}} +} + +// rdar://6097892 - GCC permits this insanity. +const char *b = __func__; // expected-warning {{predefined identifier is only valid}} +const char *c = __FUNCTION__; // expected-warning {{predefined identifier is only valid}} +const char *d = __PRETTY_FUNCTION__; // expected-warning {{predefined identifier is only valid}} + diff --git a/test/Sema/predefined-function.c b/test/Sema/predefined-function.c new file mode 100644 index 000000000000..e8ccb3636b8e --- /dev/null +++ b/test/Sema/predefined-function.c @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +char *funk(int format); +enum Test {A=-1}; +char *funk(enum Test x); + +int eli(float b); // expected-note {{previous declaration is here}} +int b(int c) {return 1;} + +int foo(); +int foo() +{ + int eli(int (int)); // expected-error {{conflicting types for 'eli'}} + eli(b); // expected-error{{incompatible type passing}} + return 0; +} + +int bar(); +int bar(int i) // expected-note {{previous definition is here}} +{ + return 0; +} +int bar() // expected-error {{redefinition of 'bar'}} +{ + return 0; +} + +int foobar(int); // note {{previous declaration is here}} +int foobar() // error {{conflicting types for 'foobar'}} +{ + return 0; +} + +int wibble(); // expected-note {{previous declaration is here}} +float wibble() // expected-error {{conflicting types for 'wibble'}} +{ + return 0.0f; +} diff --git a/test/Sema/private-extern.c b/test/Sema/private-extern.c new file mode 100644 index 000000000000..5dd37f430efa --- /dev/null +++ b/test/Sema/private-extern.c @@ -0,0 +1,88 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +static int g0; // expected-note{{previous definition}} +int g0; // expected-error{{non-static declaration of 'g0' follows static declaration}} + +static int g1; +extern int g1; + +static int g2; +__private_extern__ int g2; + +int g3; // expected-note{{previous definition}} +static int g3; // expected-error{{static declaration of 'g3' follows non-static declaration}} + +extern int g4; // expected-note{{previous definition}} +static int g4; // expected-error{{static declaration of 'g4' follows non-static declaration}} + +__private_extern__ int g5; // expected-note{{previous definition}} +static int g5; // expected-error{{static declaration of 'g5' follows non-static declaration}} + +void f0() { + // FIXME: Diagnose this? + int g6; + extern int g6; +} + +void f1() { + // FIXME: Diagnose this? + int g7; + __private_extern__ int g7; +} + +void f2() { + extern int g8; // expected-note{{previous definition}} + // FIXME: Improve this diagnostic. + int g8; // expected-error{{redefinition of 'g8'}} +} + +void f3() { + __private_extern__ int g9; // expected-note{{previous definition}} + // FIXME: Improve this diagnostic. + int g9; // expected-error{{redefinition of 'g9'}} +} + +void f4() { + extern int g10; + extern int g10; +} + +void f5() { + __private_extern__ int g11; + __private_extern__ int g11; +} + +void f6() { + // FIXME: Diagnose + extern int g12; + __private_extern__ int g12; +} + +void f7() { + // FIXME: Diagnose + __private_extern__ int g13; + extern int g13; +} + +struct s0; +void f8() { + extern struct s0 g14; + __private_extern__ struct s0 g14; +} +struct s0 { int x; }; + +void f9() { + extern int g15 = 0; // expected-error{{'extern' variable cannot have an initializer}} + // FIXME: linkage specifier in warning. + __private_extern__ int g16 = 0; // expected-error{{'extern' variable cannot have an initializer}} +} + +extern int g17; +int g17 = 0; + +extern int g18 = 0; // expected-warning{{'extern' variable has an initializer}} + +__private_extern__ int g19; +int g19 = 0; + +__private_extern__ int g20 = 0; diff --git a/test/Sema/rdar6248119.m b/test/Sema/rdar6248119.m new file mode 100644 index 000000000000..631c7b35a992 --- /dev/null +++ b/test/Sema/rdar6248119.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only %s -verify +// Test case for: +// <rdar://problem/6248119> @finally doesn't introduce a new scope + +void f0() { + int i; + @try { + } @finally { + int i = 0; + } +} + +void f1() { + int i; + @try { + int i =0; + } @finally { + } +} + +void f2() { + int i; + @try { + } @catch(id e) { + int i = 0; + } +} diff --git a/test/Sema/rdr6094103-unordered-compare-promote.c b/test/Sema/rdr6094103-unordered-compare-promote.c new file mode 100644 index 000000000000..636f770e3ee0 --- /dev/null +++ b/test/Sema/rdr6094103-unordered-compare-promote.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -ast-dump %s 2>&1 | grep ImplicitCastExpr | count 2 + +int foo (double x, long double y) { + // There needs to be an implicit cast on x here. + return __builtin_isgreater(x, y); +} diff --git a/test/Sema/recover-goto.c b/test/Sema/recover-goto.c new file mode 100644 index 000000000000..e7b9f3c8eafc --- /dev/null +++ b/test/Sema/recover-goto.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only %s -verify + +void a() {goto A; // expected-error {{use of undeclared label}} +// expected-error {{expected '}'}} diff --git a/test/Sema/redefinition.c b/test/Sema/redefinition.c new file mode 100644 index 000000000000..26c90c8e6d4f --- /dev/null +++ b/test/Sema/redefinition.c @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -fsyntax-only -verify +int f(int a) { } // expected-note {{previous definition is here}} +int f(int); +int f(int a) { } // expected-error {{redefinition of 'f'}} + +// <rdar://problem/6097326> +int foo(x) { + return 0; +} +int x = 1; diff --git a/test/Sema/return-silent.c b/test/Sema/return-silent.c new file mode 100644 index 000000000000..b3b2a5621819 --- /dev/null +++ b/test/Sema/return-silent.c @@ -0,0 +1,9 @@ +// RUN: clang-cc %s -Wno-return-type -fsyntax-only -verify + +int t14() { + return; +} + +void t15() { + return 1; +} diff --git a/test/Sema/return.c b/test/Sema/return.c new file mode 100644 index 000000000000..d96cede68a61 --- /dev/null +++ b/test/Sema/return.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// clang emits the following warning by default. +// With GCC, -pedantic, -Wreturn-type or -Wall are required to produce the +// following warning. +int t14() { + return; // expected-warning {{non-void function 't14' should return a value}} +} + +void t15() { + return 1; // expected-warning {{void function 't15' should not return a value}} +} diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c new file mode 100644 index 000000000000..76041c491653 --- /dev/null +++ b/test/Sema/scope-check.c @@ -0,0 +1,196 @@ +// RUN: clang-cc -fsyntax-only -verify -fblocks -std=gnu99 %s + +int test1(int x) { + goto L; // expected-error{{illegal goto into protected scope}} + int a[x]; // expected-note {{jump bypasses initialization of variable length array}} + int b[x]; // expected-note {{jump bypasses initialization of variable length array}} + L: + return sizeof a; +} + +int test2(int x) { + goto L; // expected-error{{illegal goto into protected scope}} + typedef int a[x]; // expected-note {{jump bypasses initialization of VLA typedef}} + L: + return sizeof(a); +} + +void test3clean(int*); + +int test3() { + goto L; // expected-error{{illegal goto into protected scope}} +int a __attribute((cleanup(test3clean))); // expected-note {{jump bypasses initialization of declaration with __attribute__((cleanup))}} +L: + return a; +} + +int test4(int x) { + goto L; // expected-error{{illegal goto into protected scope}} +int a[x]; // expected-note {{jump bypasses initialization of variable length array}} + test4(x); +L: + return sizeof a; +} + +int test5(int x) { + int a[x]; + test5(x); + goto L; // Ok. +L: + goto L; // Ok. + return sizeof a; +} + +int test6() { + // just plain invalid. + goto x; // expected-error {{use of undeclared label 'x'}} +} + +void test7(int x) { + switch (x) { + case 1: ; + int a[x]; // expected-note {{jump bypasses initialization of variable length array}} + case 2: // expected-error {{illegal switch case into protected scope}} + a[1] = 2; + break; + } +} + +int test8(int x) { + // For statement. + goto L2; // expected-error {{illegal goto into protected scope}} + for (int arr[x]; // expected-note {{jump bypasses initialization of variable length array}} + ; ++x) + L2:; + + // Statement expressions. + goto L3; // expected-error {{illegal goto into protected scope}} + int Y = ({ int a[x]; // expected-note {{jump bypasses initialization of variable length array}} + L3: 4; }); + + goto L4; // expected-error {{illegal goto into protected scope}} + { + int A[x], // expected-note {{jump bypasses initialization of variable length array}} + B[x]; // expected-note {{jump bypasses initialization of variable length array}} + L4: ; + } + + { + L5: ;// ok + int A[x], B = ({ if (x) + goto L5; + else + goto L6; + 4; }); + L6:; // ok. + if (x) goto L6; // ok + } + + { + L7: ;// ok + int A[x], B = ({ if (x) + goto L7; + else + goto L8; // expected-error {{illegal goto into protected scope}} + 4; }), + C[x]; // expected-note {{jump bypasses initialization of variable length array}} + L8:; // bad + } + + { + L9: ;// ok + int A[({ if (x) + goto L9; + else + // FIXME: + goto L10; // fixme-error {{illegal goto into protected scope}} + 4; })]; + L10:; // bad + } + + { + // FIXME: Crashes goto checker. + //goto L11;// ok + //int A[({ L11: 4; })]; + } + + { + goto L12; + + int y = 4; // fixme-warn: skips initializer. + L12: + ; + } + + // Statement expressions 2. + goto L1; // expected-error {{illegal goto into protected scope}} + return x == ({ + int a[x]; // expected-note {{jump bypasses initialization of variable length array}} + L1: + 42; }); +} + +void test9(int n, void *P) { + int Y; + int Z = 4; + goto *P; // ok. + +L2: ; + int a[n]; // expected-note 2 {{jump bypasses initialization of variable length array}} + +L3: +L4: + goto *P; // expected-error {{illegal indirect goto in protected scope, unknown effect on scopes}} + goto L3; // ok + goto L4; // ok + + void *Ptrs[] = { + &&L2, // Ok. + &&L3 // expected-error {{address taken of label in protected scope, jump to it would have unknown effect on scope}} + }; +} + +void test10(int n, void *P) { + goto L0; // expected-error {{illegal goto into protected scope}} + typedef int A[n]; // expected-note {{jump bypasses initialization of VLA typedef}} +L0: + + goto L1; // expected-error {{illegal goto into protected scope}} + A b, c[10]; // expected-note 2 {{jump bypasses initialization of variable length array}} +L1: + goto L2; // expected-error {{illegal goto into protected scope}} + A d[n]; // expected-note {{jump bypasses initialization of variable length array}} +L2: + return; +} + +void test11(int n) { + void *P = ^{ + switch (n) { + case 1:; + case 2: + case 3:; + int Arr[n]; // expected-note {{jump bypasses initialization of variable length array}} + case 4: // expected-error {{illegal switch case into protected scope}} + return; + } + }; +} + + +// TODO: When and if gotos are allowed in blocks, this should work. +void test12(int n) { + void *P = ^{ + goto L1; // expected-error {{goto not allowed in block literal}} + L1: + goto L2; // expected-error {{goto not allowed in block literal}} + L2: + goto L3; // expected-error {{goto not allowed in block literal}} + // todo-error {{illegal goto into protected scope}} + int Arr[n]; // todo-note {{jump bypasses initialization of variable length array}} + L3: + goto L4; // expected-error {{goto not allowed in block literal}} + L4: return; + }; +} + diff --git a/test/Sema/self-comparison.c b/test/Sema/self-comparison.c new file mode 100644 index 000000000000..db56e8bf17d8 --- /dev/null +++ b/test/Sema/self-comparison.c @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int foo(int x) { + return x == x; // expected-warning {{self-comparison always results}} +} + +int foo2(int x) { + return (x) != (((x))); // expected-warning {{self-comparison always results}} +} + +int qux(int x) { + return x < x; // expected-warning {{self-comparison}} +} + +int qux2(int x) { + return x > x; // expected-warning {{self-comparison}} +} + +int bar(float x) { + return x == x; // no-warning +} + +int bar2(float x) { + return x != x; // no-warning +} + +// Motivated by <rdar://problem/6703892>, self-comparisons of enum constants +// should not be warned about. These can be expanded from macros, and thus +// are usually deliberate. +int compare_enum() { + enum { A }; + return A == A; // no-warning +} diff --git a/test/Sema/sentinel-attribute.c b/test/Sema/sentinel-attribute.c new file mode 100644 index 000000000000..c40f8df29c33 --- /dev/null +++ b/test/Sema/sentinel-attribute.c @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int x __attribute__((sentinel)); //expected-warning{{'sentinel' attribute only applies to function, method or block types}} + +void f1(int a, ...) __attribute__ ((sentinel)); +void f2(int a, ...) __attribute__ ((sentinel(1))); + +void f3(int a, ...) __attribute__ ((sentinel("hello"))); //expected-error{{'sentinel' attribute requires parameter 1 to be an integer constant}} +void f4(int a, ...) __attribute__ ((sentinel(1, 2, 3))); //expected-error{{attribute requires 0, 1 or 2 argument(s)}} +void f4(int a, ...) __attribute__ ((sentinel(-1))); //expected-error{{parameter 1 less than zero}} +void f4(int a, ...) __attribute__ ((sentinel(0, 2))); // expected-error{{parameter 2 not 0 or 1}} + +void f5(int a) __attribute__ ((sentinel)); //expected-warning{{'sentinel' attribute only supported for variadic functions}} + + +void f6() __attribute__((__sentinel__)); // expected-warning {{'sentinel' attribute requires named arguments}} diff --git a/test/Sema/shift.c b/test/Sema/shift.c new file mode 100644 index 000000000000..5acbe12ac33e --- /dev/null +++ b/test/Sema/shift.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only %s + +void test() { + char c; + c <<= 14; +} diff --git a/test/Sema/statements.c b/test/Sema/statements.c new file mode 100644 index 000000000000..9a71a403700d --- /dev/null +++ b/test/Sema/statements.c @@ -0,0 +1,29 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +typedef unsigned __uint32_t; + +#define __byte_swap_int_var(x) \ +__extension__ ({ register __uint32_t __X = (x); \ + __asm ("bswap %0" : "+r" (__X)); \ + __X; }) + +int test(int _x) { + return (__byte_swap_int_var(_x)); +} + +// PR2374 +int test2() { return ({L:5;}); } +int test3() { return ({ {5;} }); } // expected-error {{incompatible type returning 'void', expected 'int'}}\ + // expected-warning {{expression result unused}} +int test4() { return ({ ({5;}); }); } +int test5() { return ({L1: L2: L3: 5;}); } +int test6() { return ({5;}); } +void test7() { ({5;}); } // expected-warning {{expression result unused}} + +// PR3062 +int test8[({10;})]; // expected-error {{statement expression not allowed at file scope}} + +// PR3912 +void test9(const void *P) { + __builtin_prefetch(P); +} diff --git a/test/Sema/static-init.c b/test/Sema/static-init.c new file mode 100644 index 000000000000..cd495568ca3f --- /dev/null +++ b/test/Sema/static-init.c @@ -0,0 +1,23 @@ +// RUN: clang-cc -triple i386-pc-linux-gnu -fsyntax-only -verify %s + +#include <stdint.h> + +static int f = 10; +static int b = f; // expected-error {{initializer element is not a compile-time constant}} + +float r = (float) (intptr_t) &r; // expected-error {{initializer element is not a compile-time constant}} +intptr_t s = (intptr_t) &s; +_Bool t = &t; + + +union bar { + int i; +}; + +struct foo { + unsigned ptr; +}; + +union bar u[1]; +struct foo x = {(intptr_t) u}; // no-error +struct foo y = {(char) u}; // expected-error {{initializer element is not a compile-time constant}} diff --git a/test/Sema/stdcall-fastcall.c b/test/Sema/stdcall-fastcall.c new file mode 100644 index 000000000000..353bbfc25297 --- /dev/null +++ b/test/Sema/stdcall-fastcall.c @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// CC qualifier can be applied only to functions +int __attribute__((stdcall)) var1; // expected-warning{{'stdcall' attribute only applies to function types}} +int __attribute__((fastcall)) var2; // expected-warning{{'fastcall' attribute only applies to function types}} + +// Different CC qualifiers are not compatible +void __attribute__((stdcall, fastcall)) foo3(); // expected-error{{stdcall and fastcall attributes are not compatible}} +void __attribute__((stdcall)) foo4(); +void __attribute__((fastcall)) foo4(); // expected-error{{fastcall and stdcall attributes are not compatible}} diff --git a/test/Sema/struct-cast.c b/test/Sema/struct-cast.c new file mode 100644 index 000000000000..063e8e32c02d --- /dev/null +++ b/test/Sema/struct-cast.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only %s -verify + +struct S { + int one; + int two; +}; + +struct S const foo(void); + +struct S tmp; + +void priv_sock_init() { + tmp = (struct S)foo(); +} diff --git a/test/Sema/struct-compat.c b/test/Sema/struct-compat.c new file mode 100644 index 000000000000..35d8fb1aa0c2 --- /dev/null +++ b/test/Sema/struct-compat.c @@ -0,0 +1,17 @@ +/* RUN: clang-cc %s -fsyntax-only -pedantic -verify + */ + +extern struct {int a;} x; // expected-note {{previous definition is here}} +extern struct {int a;} x; // expected-error {{redefinition of 'x'}} + +struct x; +int a(struct x* b) { +// Per C99 6.7.2.3, since the outer and inner "struct x"es have different +// scopes, they don't refer to the same type, and are therefore incompatible +struct x {int a;} *c = b; // expected-warning {{incompatible pointer types}} +} + +struct x {int a;} r; +int b() { +struct x {char x;} s = r; // expected-error {{incompatible type initializing}} +} diff --git a/test/Sema/struct-decl.c b/test/Sema/struct-decl.c new file mode 100644 index 000000000000..2c0945f9f86b --- /dev/null +++ b/test/Sema/struct-decl.c @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR3459 +struct bar { + char n[1]; +}; + +struct foo { + char name[(int)&((struct bar *)0)->n]; + char name2[(int)&((struct bar *)0)->n - 1]; //expected-error{{array size is negative}} +}; + +// PR3430 +struct s { + struct st { + int v; + } *ts; +}; + +struct st; + +int foo() { + struct st *f; + return f->v + f[0].v; +} + +// PR3642, PR3671 +struct pppoe_tag { + short tag_type; + char tag_data[]; +}; +struct datatag { + struct pppoe_tag hdr; //expected-warning{{field 'hdr' with variable sized type 'struct pppoe_tag' not at the end of a struct or class is a GNU extension}} + char data; +}; + + +// PR4092 +struct s0 { + char a; // expected-note {{previous declaration is here}} + char a; // expected-error {{duplicate member 'a'}} +}; + +struct s0 f0(void) {} diff --git a/test/Sema/struct-packed-align.c b/test/Sema/struct-packed-align.c new file mode 100644 index 000000000000..8250c14d4420 --- /dev/null +++ b/test/Sema/struct-packed-align.c @@ -0,0 +1,111 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// Packed structs. +struct s { + char a; + int b __attribute__((packed)); + char c; + int d; +}; + +extern int a1[sizeof(struct s) == 12 ? 1 : -1]; +extern int a2[__alignof(struct s) == 4 ? 1 : -1]; + +struct __attribute__((packed)) packed_s { + char a; + int b __attribute__((packed)); + char c; + int d; +}; + +extern int b1[sizeof(struct packed_s) == 10 ? 1 : -1]; +extern int b2[__alignof(struct packed_s) == 1 ? 1 : -1]; + +struct fas { + char a; + int b[]; +}; + +extern int c1[sizeof(struct fas) == 4 ? 1 : -1]; +extern int c2[__alignof(struct fas) == 4 ? 1 : -1]; + +struct __attribute__((packed)) packed_fas { + char a; + int b[]; +}; + +extern int d1[sizeof(struct packed_fas) == 1 ? 1 : -1]; +extern int d2[__alignof(struct packed_fas) == 1 ? 1 : -1]; + +// Alignment + +struct __attribute__((aligned(8))) as1 { + char c; +}; + +extern int e1[sizeof(struct as1) == 8 ? 1 : -1]; +extern int e2[__alignof(struct as1) == 8 ? 1 : -1]; + +// FIXME: Will need to force arch once max usable alignment isn't hard +// coded. +struct __attribute__((aligned)) as1_2 { + char c; +}; +extern int e1_2[sizeof(struct as1_2) == 16 ? 1 : -1]; +extern int e2_2[__alignof(struct as1_2) == 16 ? 1 : -1]; + +struct as2 { + char c; + int __attribute__((aligned(8))) a; +}; + +extern int f1[sizeof(struct as2) == 16 ? 1 : -1]; +extern int f2[__alignof(struct as2) == 8 ? 1 : -1]; + +struct __attribute__((packed)) as3 { + char c; + int a; + int __attribute__((aligned(8))) b; +}; + +extern int g1[sizeof(struct as3) == 16 ? 1 : -1]; +extern int g2[__alignof(struct as3) == 8 ? 1 : -1]; + + +// rdar://5921025 +struct packedtest { + int ted_likes_cheese; + void *args[] __attribute__((packed)); +}; + +// Packed union +union __attribute__((packed)) au4 {char c; int x;}; +extern int h1[sizeof(union au4) == 4 ? 1 : -1]; +extern int h2[__alignof(union au4) == 1 ? 1 : -1]; + +// Aligned union +union au5 {__attribute__((aligned(4))) char c;}; +extern int h1[sizeof(union au5) == 4 ? 1 : -1]; +extern int h2[__alignof(union au5) == 4 ? 1 : -1]; + +// Alignment+packed +struct as6 {char c; __attribute__((packed, aligned(2))) int x;}; +extern int i1[sizeof(struct as6) == 6 ? 1 : -1]; +extern int i2[__alignof(struct as6) == 2 ? 1 : -1]; + +union au6 {char c; __attribute__((packed, aligned(2))) int x;}; +extern int k1[sizeof(union au6) == 4 ? 1 : -1]; +extern int k2[__alignof(union au6) == 2 ? 1 : -1]; + +// Check postfix attributes +union au7 {char c; int x;} __attribute__((packed)); +extern int l1[sizeof(union au7) == 4 ? 1 : -1]; +extern int l2[__alignof(union au7) == 1 ? 1 : -1]; + +struct packed_fas2 { + char a; + int b[]; +} __attribute__((packed)); + +extern int m1[sizeof(struct packed_fas2) == 1 ? 1 : -1]; +extern int m2[__alignof(struct packed_fas2) == 1 ? 1 : -1]; diff --git a/test/Sema/surpress-deprecated.c b/test/Sema/surpress-deprecated.c new file mode 100644 index 000000000000..8dbe9dd36581 --- /dev/null +++ b/test/Sema/surpress-deprecated.c @@ -0,0 +1,7 @@ +// RUN: clang -fsyntax-only -Wno-deprecated-declarations -verify %s +extern void OldFunction() __attribute__((deprecated)); + +int main (int argc, const char * argv[]) { + OldFunction(); +} + diff --git a/test/Sema/switch.c b/test/Sema/switch.c new file mode 100644 index 000000000000..5999f342aefa --- /dev/null +++ b/test/Sema/switch.c @@ -0,0 +1,70 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f (int z) { + while (z) { + default: z--; // expected-error {{statement not in switch}} + } +} + +void foo(int X) { + switch (X) { + case 42: ; // expected-note {{previous case}} + case 5000000000LL: // expected-warning {{overflow}} + case 42: // expected-error {{duplicate case value}} + ; + + case 100 ... 99: ; // expected-warning {{empty case range}} + + case 43: ; // expected-note {{previous case}} + case 43 ... 45: ; // expected-error {{duplicate case value}} + + case 100 ... 20000:; // expected-note {{previous case}} + case 15000 ... 40000000:; // expected-error {{duplicate case value}} + } +} + +void test3(void) { + // empty switch; + switch (0); +} + +extern int g(); + +void test4() +{ + switch (1) { + case 0 && g(): + case 1 || g(): + break; + } + + switch(1) { + case g(): // expected-error {{expression is not an integer constant expression}} + case 0 ... g(): // expected-error {{expression is not an integer constant expression}} + break; + } + + switch (1) { + case 0 && g() ... 1 || g(): + break; + } + + switch (1) { + case g() && 0: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}} + break; + } + + switch (1) { + case 0 ... g() || 1: // expected-error {{expression is not an integer constant expression}} // expected-note {{subexpression not valid in an integer constant expression}} + break; + } +} + +void test5(int z) { + switch(z) { + default: // expected-note {{previous case defined here}} + default: // expected-error {{multiple default labels in one switch}} + break; + } +} + diff --git a/test/Sema/tentative-decls.c b/test/Sema/tentative-decls.c new file mode 100644 index 000000000000..e3c893c77718 --- /dev/null +++ b/test/Sema/tentative-decls.c @@ -0,0 +1,65 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// PR3310 +struct a x1; // expected-note 2{{forward declaration of 'struct a'}} +static struct a x2; // expected-error{{variable has incomplete type 'struct a'}} +struct a x3[10]; // expected-error{{array has incomplete element type 'struct a'}} +struct a {int x;}; +static struct a x2_okay; +struct a x3_okay[10]; +struct b x4; // expected-error{{tentative definition has type 'struct b' that is never completed}} \ + // expected-note{{forward declaration of 'struct b'}} + +const int a [1] = {1}; +extern const int a[]; + +extern const int b[]; +const int b [1] = {1}; + +extern const int c[] = {1}; // expected-warning{{'extern' variable has an initializer}} +const int c[]; + +int i1 = 1; // expected-note {{previous definition is here}} +int i1 = 2; // expected-error {{redefinition of 'i1'}} +int i1; +int i1; +extern int i5; // expected-note {{previous definition is here}} +static int i5; // expected-error{{static declaration of 'i5' follows non-static declaration}} + +static int i2 = 5; // expected-note 1 {{previous definition is here}} +int i2 = 3; // expected-error{{non-static declaration of 'i2' follows static declaration}} + +static int i3 = 5; +extern int i3; + +__private_extern__ int pExtern; +int pExtern = 0; + +int i4; +int i4; +extern int i4; + +int (*pToArray)[]; +int (*pToArray)[8]; + +int redef[10]; +int redef[]; // expected-note {{previous definition is here}} +int redef[11]; // expected-error{{redefinition of 'redef'}} + +void func() { + extern int i6; // expected-note {{previous definition is here}} + static int i6; // expected-error{{static declaration of 'i6' follows non-static declaration}} +} + +void func2(void) +{ + extern double *p; + extern double *p; +} + +// <rdar://problem/6808352> +static int a0[]; +static int b0; + +static int a0[] = { 4 }; +static int b0 = 5; diff --git a/test/Sema/text-diag.c b/test/Sema/text-diag.c new file mode 100644 index 000000000000..19847c6d1e91 --- /dev/null +++ b/test/Sema/text-diag.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only %s +unsigned char *foo = "texto\ +que continua\ +e continua"; diff --git a/test/Sema/thread-specifier.c b/test/Sema/thread-specifier.c new file mode 100644 index 000000000000..8d66e539c875 --- /dev/null +++ b/test/Sema/thread-specifier.c @@ -0,0 +1,21 @@ +// RUN: clang-cc -triple i686-pc-linux-gnu -fsyntax-only -verify %s + +__thread int t1; +__thread extern int t2; +__thread static int t3; +__thread __private_extern__ int t4; +struct t5 { __thread int x; }; // expected-error {{type name does not allow storage class to be specified}} +__thread int t6(); // expected-error {{'__thread' is only allowed on variable declarations}} +int f(__thread int t7) { // expected-error {{'__thread' is only allowed on variable declarations}} + __thread int t8; // expected-error {{'__thread' variables must have global storage}} + __thread extern int t9; + __thread static int t10; + __thread __private_extern__ int t11; + __thread auto int t12; // expected-error {{'__thread' variables must have global storage}} + __thread register int t13; // expected-error {{'__thread' variables must have global storage}} +} +__thread typedef int t14; // expected-error {{'__thread' is only allowed on variable declarations}} +__thread int t15; // expected-note {{[previous definition is here}} +int t15; // expected-error {{non-thread-local declaration of 't15' follows thread-local declaration}} +int t16; // expected-note {{[previous definition is here}} +__thread int t16; // expected-error {{thread-local declaration of 't16' follows non-thread-local declaration}} diff --git a/test/Sema/transparent-union-pointer.c b/test/Sema/transparent-union-pointer.c new file mode 100644 index 000000000000..ea761f17e7d6 --- /dev/null +++ b/test/Sema/transparent-union-pointer.c @@ -0,0 +1,14 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +typedef union { + union wait *__uptr; + int *__iptr; +} __WAIT_STATUS __attribute__ ((__transparent_union__)); + +extern int wait (__WAIT_STATUS __stat_loc); + +void fastcgi_cleanup() { + int status = 0; + wait(&status); +} + diff --git a/test/Sema/transparent-union.c b/test/Sema/transparent-union.c new file mode 100644 index 000000000000..90ecaadea6e7 --- /dev/null +++ b/test/Sema/transparent-union.c @@ -0,0 +1,40 @@ +// RUN: clang -fsyntax-only -Xclang -verify %s +typedef union { + int *ip; + float *fp; +} TU __attribute__((transparent_union)); + +void f(TU); + +void g(int *ip, float *fp, char *cp) { + f(ip); + f(fp); + f(cp); // expected-error{{incompatible type}} + f(0); + + TU tu_ip = ip; // expected-error{{incompatible type}} + TU tu; + tu.ip = ip; +} + +/* FIXME: we'd like to just use an "int" here and align it differently + from the normal "int", but if we do so we lose the alignment + information from the typedef within the compiler. */ +typedef struct { int x, y; } __attribute__((aligned(8))) aligned_struct8; + +typedef struct { int x, y; } __attribute__((aligned(4))) aligned_struct4; +typedef union { + aligned_struct4 s4; // expected-note{{alignment of first field}} + aligned_struct8 s8; // expected-warning{{alignment of field}} +} TU1 __attribute__((transparent_union)); + +typedef union { + char c; // expected-note{{size of first field is 8 bits}} + int i; // expected-warning{{size of field}} +} TU2 __attribute__((transparent_union)); + +typedef union { + float f; // expected-warning{{floating}} +} TU3 __attribute__((transparent_union)); + +typedef union { } TU4 __attribute__((transparent_union)); // expected-warning{{field}} diff --git a/test/Sema/type-spec-struct-union.c b/test/Sema/type-spec-struct-union.c new file mode 100644 index 000000000000..2b68b7877318 --- /dev/null +++ b/test/Sema/type-spec-struct-union.c @@ -0,0 +1,65 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +/* This test checks the introduction of struct and union types based + on a type specifier of the form "struct-or-union identifier" when they + type has not yet been declared. See C99 6.7.2.3p8. */ + +typedef struct S1 { + union { + struct S2 *x; + struct S3 *y; + } u1; +} S1; + +int test_struct_scope(S1 *s1, struct S2 *s2, struct S3 *s3) { + if (s1->u1.x == s2) return 1; + if (s1->u1.y == s3) return 1; + return 0; +} + +int test_struct_scope_2(S1 *s1) { + struct S2 { int x; } *s2 = 0; + if (s1->u1.x == s2) return 1; /* expected-warning {{comparison of distinct pointer types ('struct S2 *' and 'struct S2 *')}} */ + return 0; +} + +// FIXME: We do not properly implement C99 6.2.1p4, which says that +// the type "struct S4" declared in the function parameter list has +// block scope within the function definition. The problem, in this +// case, is that the code is ill-formed but we warn about the two S4's +// being incompatible (we think they are two different types). +int test_struct_scope_3(struct S4 * s4) { // expected-warning{{declaration of 'struct S4' will not be visible outside of this function}} + struct S4 { int y; } *s4_2 = 0; + /* if (s4 == s4_2) return 1; */ + return 0; +} + +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; +} diff --git a/test/Sema/typecheck-binop.c b/test/Sema/typecheck-binop.c new file mode 100644 index 000000000000..f5bdcbb70e83 --- /dev/null +++ b/test/Sema/typecheck-binop.c @@ -0,0 +1,27 @@ +/* RUN: clang-cc %s -fsyntax-only -pedantic -verify + */ +struct incomplete; // expected-note{{forward declaration of 'struct incomplete'}} + +int sub1(int *a, double *b) { + return a - b; /* expected-error{{not pointers to compatible types}} */ +} + +void *sub2(struct incomplete *P) { + return P-4; /* expected-error{{subtraction of pointer 'struct incomplete *' requires pointee to be a complete object type}} */ +} + +void *sub3(void *P) { + return P-4; /* expected-warning{{GNU void* extension}} */ +} + +int sub4(void *P, void *Q) { + return P-Q; /* expected-warning{{GNU void* extension}} */ +} + +int sub5(void *P, int *Q) { + return P-Q; /* expected-error{{not pointers to compatible types}} */ +} + +int logicaland1(int a) { + return a && (void)a; /* expected-error{{invalid operands}} */ +} diff --git a/test/Sema/typedef-prototype.c b/test/Sema/typedef-prototype.c new file mode 100644 index 000000000000..fc0e05ead292 --- /dev/null +++ b/test/Sema/typedef-prototype.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef int unary_int_func(int arg); +unary_int_func add_one; + +int add_one(int arg) { + return arg + 1; +} diff --git a/test/Sema/typedef-redef.c b/test/Sema/typedef-redef.c new file mode 100644 index 000000000000..9a1c48873242 --- /dev/null +++ b/test/Sema/typedef-redef.c @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef const int x; // expected-note {{previous definition is here}} +extern x a; +typedef int x; // expected-error {{typedef redefinition with different types}} +extern x a; + +// <rdar://problem/6097585> +int y; // expected-note 2 {{previous definition is here}} +float y; // expected-error{{redefinition of 'y' with a different type}} +double y; // expected-error{{redefinition of 'y' with a different type}} diff --git a/test/Sema/typedef-retain.c b/test/Sema/typedef-retain.c new file mode 100644 index 000000000000..ef9ec76f467b --- /dev/null +++ b/test/Sema/typedef-retain.c @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s -fno-lax-vector-conversions + +typedef float float4 __attribute__((vector_size(16))); +typedef int int4 __attribute__((vector_size(16))); +typedef int4* int4p; + +void test1(float4 a, int4 *result, int i) { + result[i] = a; // expected-error {{assigning 'float4', expected 'int4'}} +} + +void test2(float4 a, int4p result, int i) { + result[i] = a; // expected-error {{assigning 'float4', expected 'int4'}} +} + +// PR2039 +typedef int a[5]; +void test3() { + typedef const a b; + b r; + r[0]=10; // expected-error {{read-only variable is not assignable}} +} + +int test4(const a y) { + y[0] = 10; // expected-error {{read-only variable is not assignable}} +} + +// PR2189 +int test5() { + const int s[5]; int t[5]; + return &s == &t; // expected-warning {{comparison of distinct pointer types}} +} + +int test6() { + const a s; + a t; + return &s == &t; // expected-warning {{comparison of distinct pointer types}} +} + diff --git a/test/Sema/typedef-variable-type.c b/test/Sema/typedef-variable-type.c new file mode 100644 index 000000000000..7a9bb4879bc2 --- /dev/null +++ b/test/Sema/typedef-variable-type.c @@ -0,0 +1,3 @@ +// RUN: clang-cc %s -verify -fsyntax-only -pedantic + +typedef int (*a)[!.0]; // expected-warning{{size of static array must be an integer constant expression}} diff --git a/test/Sema/types.c b/test/Sema/types.c new file mode 100644 index 000000000000..e7d4b00a4d2a --- /dev/null +++ b/test/Sema/types.c @@ -0,0 +1,39 @@ +// RUN: clang-cc %s -pedantic -verify -triple=x86_64-apple-darwin9 + +// rdar://6097662 +typedef int (*T)[2]; +restrict T x; + +typedef int *S[2]; +restrict S y; // expected-error {{restrict requires a pointer or reference ('S' (aka 'int *[2]') is invalid)}} + + + +// int128_t is available. +int a() { + __int128_t s; + __uint128_t t; +} +// but not a keyword +int b() { + int __int128_t; + int __uint128_t; +} + + +// Array type merging should convert array size to whatever matches the target +// pointer size. +// rdar://6880874 +extern int i[1LL]; +int i[(short)1]; + +enum e { e_1 }; +extern int j[sizeof(enum e)]; // expected-note {{previous definition}} +int j[42]; // expected-error {{redefinition of 'j' with a different type}} + +// rdar://6880104 +_Decimal32 x; // expected-error {{GNU decimal type extension not supported}} + + +// rdar://6880951 +int __attribute__ ((vector_size (8), vector_size (8))) v; // expected-error {{invalid vector type}} diff --git a/test/Sema/ucn-cstring.c b/test/Sema/ucn-cstring.c new file mode 100644 index 000000000000..6d021fd82d16 --- /dev/null +++ b/test/Sema/ucn-cstring.c @@ -0,0 +1,17 @@ +// RUN: clang-cc %s -verify -fsyntax-only -pedantic + +#include <stdio.h> + +int main(void) { + int a[sizeof("hello \u2192 \u2603 \u2190 world") == 24 ? 1 : -1]; + + printf("%s (%d)\n", "hello \u2192 \u2603 \u2190 world", sizeof("hello \u2192 \u2603 \u2190 world")); + printf("%s (%d)\n", "\U00010400\U0001D12B", sizeof("\U00010400\U0001D12B")); + // Some error conditions... + printf("%s\n", "\U"); // expected-error{{\u used with no following hex digits}} + printf("%s\n", "\U00"); // expected-error{{incomplete universal character name}} + printf("%s\n", "\U0001"); // expected-error{{incomplete universal character name}} + printf("%s\n", "\u0001"); // expected-error{{invalid universal character}} + return 0; +} + diff --git a/test/Sema/unnamed-bitfield-init.c b/test/Sema/unnamed-bitfield-init.c new file mode 100644 index 000000000000..249f06e07d94 --- /dev/null +++ b/test/Sema/unnamed-bitfield-init.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef struct { + int a; int : 24; char b; +} S; + +S a = { 1, 2 }; diff --git a/test/Sema/unused-expr.c b/test/Sema/unused-expr.c new file mode 100644 index 000000000000..9c231e960a2a --- /dev/null +++ b/test/Sema/unused-expr.c @@ -0,0 +1,46 @@ +// RUN: clang-cc -fsyntax-only -verify -fmath-errno=0 %s + +int foo(int X, int Y); + +double sqrt(double X); // implicitly const because of -fno-math-errno! + +void bar(volatile int *VP, int *P, int A, + _Complex double C, volatile _Complex double VC) { + + VP == P; // expected-warning {{expression result unused}} + (void)A; + (void)foo(1,2); // no warning. + + A == foo(1, 2); // expected-warning {{expression result unused}} + + foo(1,2)+foo(4,3); // expected-warning {{expression result unused}} + + + *P; // expected-warning {{expression result unused}} + *VP; // no warning. + P[4]; // expected-warning {{expression result unused}} + VP[4]; // no warning. + + __real__ C; // expected-warning {{expression result unused}} + __real__ VC; + + // We know this can't change errno because of -fno-math-errno. + sqrt(A); // expected-warning {{expression result unused}} +} + +extern void t1(); +extern void t2(); +void t3(int c) { + c ? t1() : t2(); +} + +// This shouldn't warn: the expr at the end of the stmtexpr really is used. +int stmt_expr(int x, int y) { + return ({int _a = x, _b = y; _a > _b ? _a : _b; }); +} + +void nowarn(unsigned char* a, unsigned char* b) +{ + unsigned char c = 1; + *a |= c, *b += c; +} diff --git a/test/Sema/usual-float.c b/test/Sema/usual-float.c new file mode 100644 index 000000000000..40c0bde4e0cf --- /dev/null +++ b/test/Sema/usual-float.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -fsyntax-only + +typedef float CGFloat; + +extern void func(CGFloat); +void foo(int dir, int n, int tindex) { + const float PI = 3.142; + CGFloat cgf = 3.4; + + float ang = (float) tindex * (-dir*2.0f*PI/n); + func((CGFloat)cgf/65535.0f); +} diff --git a/test/Sema/va_arg_x86_32.c b/test/Sema/va_arg_x86_32.c new file mode 100644 index 000000000000..850d324dbfc9 --- /dev/null +++ b/test/Sema/va_arg_x86_32.c @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify -triple=i686-pc-linux-gnu %s + +int a() { + __builtin_va_arg((char*)0, int); // expected-error {{expression is not assignable}} + __builtin_va_arg((void*){0}, int); // expected-error {{first argument to 'va_arg' is of type 'void *'}} +} diff --git a/test/Sema/va_arg_x86_64.c b/test/Sema/va_arg_x86_64.c new file mode 100644 index 000000000000..680abb714b91 --- /dev/null +++ b/test/Sema/va_arg_x86_64.c @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify -triple=x86_64-unknown-freebsd7.0 %s + +// PR2631 +char* foo(char *fmt, __builtin_va_list ap) +{ + return __builtin_va_arg((ap), char *); +} + +// PR2692 +typedef __builtin_va_list va_list; +static char *f (char * (*g) (char **, int), char **p, ...) { + char *s; + va_list v; + s = g (p, __builtin_va_arg(v, int)); +} + diff --git a/test/Sema/var-redecl.c b/test/Sema/var-redecl.c new file mode 100644 index 000000000000..129fd17cd533 --- /dev/null +++ b/test/Sema/var-redecl.c @@ -0,0 +1,61 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int outer1; // expected-note{{previous definition is here}} +extern int outer2; // expected-note{{previous definition is here}} +int outer4; +int outer4; // expected-note{{previous definition is here}} +int outer5; +int outer6(float); // expected-note{{previous definition is here}} +int outer7(float); + +void outer_test() { + extern float outer1; // expected-error{{redefinition of 'outer1' with a different type}} + extern float outer2; // expected-error{{redefinition of 'outer2' with a different type}} + extern float outer3; // expected-note{{previous definition is here}} + double outer4; + extern int outer5; // expected-note{{previous definition is here}} + extern int outer6; // expected-error{{redefinition of 'outer6' as different kind of symbol}} + int outer7; + extern int outer8; // expected-note{{previous definition is here}} + extern int outer9; + { + extern int outer9; // expected-note{{previous definition is here}} + } +} + +int outer3; // expected-error{{redefinition of 'outer3' with a different type}} +float outer4; // expected-error{{redefinition of 'outer4' with a different type}} +float outer5; // expected-error{{redefinition of 'outer5' with a different type}} +int outer8(int); // expected-error{{redefinition of 'outer8' as different kind of symbol}} +float outer9; // expected-error{{redefinition of 'outer9' with a different type}} + +extern int outer13; // expected-note{{previous definition is here}} +void outer_shadowing_test() { + extern int outer10; + extern int outer11; // expected-note{{previous definition is here}} + extern int outer12; // expected-note{{previous definition is here}} + { + float outer10; + float outer11; + float outer12; + { + extern int outer10; // okay + extern float outer11; // expected-error{{redefinition of 'outer11' with a different type}} + static double outer12; + { + extern float outer12; // expected-error{{redefinition of 'outer12' with a different type}} + extern float outer13; // expected-error{{redefinition of 'outer13' with a different type}} + } + } + } +} + +void g18(void) { + extern int g19; +} +int *p=&g19; // expected-error{{use of undeclared identifier 'g19'}} + +// PR3645 +static int a; +extern int a; +int a; diff --git a/test/Sema/varargs-x86-64.c b/test/Sema/varargs-x86-64.c new file mode 100644 index 000000000000..7c71c9673891 --- /dev/null +++ b/test/Sema/varargs-x86-64.c @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s -triple x86_64-apple-darwin9 + +// rdar://6726818 +void f1() { + const __builtin_va_list args2; + (void)__builtin_va_arg(args2, int); // expected-error {{first argument to 'va_arg' is of type '__builtin_va_list const' and not 'va_list'}} +} + diff --git a/test/Sema/varargs.c b/test/Sema/varargs.c new file mode 100644 index 000000000000..8d2f0b1fa83e --- /dev/null +++ b/test/Sema/varargs.c @@ -0,0 +1,63 @@ +// RUN: clang-cc -fsyntax-only -verify %s && +// RUN: clang-cc -fsyntax-only -verify %s -triple x86_64-apple-darwin9 + +void f1(int a) +{ + __builtin_va_list ap; + + __builtin_va_start(ap, a, a); // expected-error {{too many arguments to function}} + __builtin_va_start(ap, a); // expected-error {{'va_start' used in function with fixed args}} +} + +void f2(int a, int b, ...) +{ + __builtin_va_list ap; + + __builtin_va_start(ap, 10); // expected-warning {{second parameter of 'va_start' not last named argument}} + __builtin_va_start(ap, a); // expected-warning {{second parameter of 'va_start' not last named argument}} + __builtin_va_start(ap, b); +} + +void f3(float a, ...) +{ + __builtin_va_list ap; + + __builtin_va_start(ap, a); + __builtin_va_start(ap, (a)); +} + + +// stdarg: PR3075 +void f4(const char *msg, ...) { + __builtin_va_list ap; + __builtin_stdarg_start((ap), (msg)); + __builtin_va_end (ap); +} + +void f5() { + __builtin_va_list ap; + __builtin_va_start(ap,ap); // expected-error {{'va_start' used in function with fixed args}} +} + +void f6(int a, ...) { + __builtin_va_list ap; + __builtin_va_start(ap); // expected-error {{too few arguments to function}} +} + +// PR3350 +void +foo(__builtin_va_list authors, ...) { + __builtin_va_start (authors, authors); + (void)__builtin_va_arg(authors, int); + __builtin_va_end (authors); +} + +void f7(int a, ...) { + __builtin_va_list ap; + __builtin_va_start(ap, a); + // FIXME: This error message is sub-par. + __builtin_va_arg(ap, int) = 1; // expected-error {{expression is not assignable}} + int *x = &__builtin_va_arg(ap, int); // expected-error {{address expression must be an lvalue or a function designator}} + __builtin_va_end(ap); +} + diff --git a/test/Sema/variadic-block.c b/test/Sema/variadic-block.c new file mode 100644 index 000000000000..29f597b00672 --- /dev/null +++ b/test/Sema/variadic-block.c @@ -0,0 +1,41 @@ +// RUN: clang-cc %s -verify -fsyntax-only -fblocks + +#include <stdarg.h> + +int main(int argc, char *argv[]) { + + long (^addthem)(const char *, ...) = ^long (const char *format, ...){ + va_list argp; + const char *p; + int i; + char c; + double d; + long result = 0; + va_start(argp, format); + for (p = format; *p; p++) switch (*p) { + case 'i': + i = va_arg(argp, int); + result += i; + break; + case 'd': + d = va_arg(argp, double); + result += (int)d; + break; + case 'c': + c = va_arg(argp, int); + result += c; + break; + } + return result; + }; + long testresult = addthem("ii", 10, 20); + if (testresult != 30) { + return 1; + } + testresult = addthem("idc", 30, 40.0, 'a'); + if (testresult != (70+'a')) { + return 1; + } + return 0; +} + diff --git a/test/Sema/vector-assign.c b/test/Sema/vector-assign.c new file mode 100644 index 000000000000..5162e1a41c21 --- /dev/null +++ b/test/Sema/vector-assign.c @@ -0,0 +1,45 @@ +// RUN: clang-cc %s -verify -fsyntax-only -Wvector-conversions +typedef unsigned int v2u __attribute__ ((vector_size (8))); +typedef signed int v2s __attribute__ ((vector_size (8))); +typedef signed int v1s __attribute__ ((vector_size (4))); +typedef float v2f __attribute__ ((vector_size(8))); +typedef signed short v4ss __attribute__ ((vector_size (8))); + +void f() { + v2s v1; + v2u v2; + v1s v3; + v2f v4; + v4ss v5; + + v1 = v2; // expected-warning {{incompatible vector types assigning 'v2u', expected 'v2s'}} + v1 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2s'}} + v1 = v4; // expected-warning {{incompatible vector types assigning 'v2f', expected 'v2s'}} + v1 = v5; // expected-warning {{incompatible vector types assigning 'v4ss', expected 'v2s'}} + + v2 = v1; // expected-warning {{incompatible vector types assigning 'v2s', expected 'v2u'}} + v2 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2u'}} + v2 = v4; // expected-warning {{incompatible vector types assigning 'v2f', expected 'v2u'}} + v2 = v5; // expected-warning {{incompatible vector types assigning 'v4ss', expected 'v2u'}} + + v3 = v1; // expected-error {{incompatible type assigning 'v2s', expected 'v1s'}} + v3 = v2; // expected-error {{incompatible type assigning 'v2u', expected 'v1s'}} + v3 = v4; // expected-error {{incompatible type assigning 'v2f', expected 'v1s'}} + v3 = v5; // expected-error {{incompatible type assigning 'v4ss', expected 'v1s'}} + + v4 = v1; // expected-warning {{incompatible vector types assigning 'v2s', expected 'v2f'}} + v4 = v2; // expected-warning {{incompatible vector types assigning 'v2u', expected 'v2f'}} + v4 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v2f'}} + v4 = v5; // expected-warning {{incompatible vector types assigning 'v4ss', expected 'v2f'}} + + v5 = v1; // expected-warning {{incompatible vector types assigning 'v2s', expected 'v4ss'}} + v5 = v2; // expected-warning {{incompatible vector types assigning 'v2u', expected 'v4ss'}} + v5 = v3; // expected-error {{incompatible type assigning 'v1s', expected 'v4ss'}} + v5 = v4; // expected-warning {{incompatible vector types assigning 'v2f', expected 'v4ss'}} +} + +// PR2263 +float f2(__attribute__((vector_size(16))) float a, int b) { + return a[b]; +} + diff --git a/test/Sema/vector-cast.c b/test/Sema/vector-cast.c new file mode 100644 index 000000000000..bd09e69800cc --- /dev/null +++ b/test/Sema/vector-cast.c @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only %s -verify -Wvector-conversions + +typedef long long t1 __attribute__ ((vector_size (8))); +typedef char t2 __attribute__ ((vector_size (16))); +typedef float t3 __attribute__ ((vector_size (16))); + +void f() +{ + t1 v1; + t2 v2; + t3 v3; + + v2 = (t2)v1; // -expected-error {{invalid conversion between vector type \ +'t1' and 't2' of different size}} + v1 = (t1)v2; // -expected-error {{invalid conversion between vector type \ +'t2' and 't1' of different size}} + v3 = (t3)v2; + + v1 = (t1)(char *)10; // -expected-error {{invalid conversion between vector \ +type 't1' and scalar type 'char *'}} + v1 = (t1)(long long)10; + v1 = (t1)(short)10; // -expected-error {{invalid conversion between vector \ +type 't1' and integer type 'int' of different size}} + + long long r1 = (long long)v1; + short r2 = (short)v1; // -expected-error {{invalid conversion between vector \ +type 't1' and integer type 'short' of different size}} + char *r3 = (char *)v1; // -expected-error {{invalid conversion between vector\ + type 't1' and scalar type 'char *'}} +} + + +void f2(t2 X); + +void f3(t3 Y) { + f2(Y); // expected-warning {{incompatible vector types passing 't3', expected 't2'}} +} + diff --git a/test/Sema/vector-init.c b/test/Sema/vector-init.c new file mode 100644 index 000000000000..6eab32425adf --- /dev/null +++ b/test/Sema/vector-init.c @@ -0,0 +1,23 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +//typedef __attribute__(( ext_vector_type(4) )) float float4; +typedef float float4 __attribute__((vector_size(16))); + +float4 foo = (float4){ 1.0, 2.0, 3.0, 4.0 }; + +float4 foo2 = (float4){ 1.0, 2.0, 3.0, 4.0 , 5.0 }; // expected-warning{{excess elements in vector initializer}} + +float4 array[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0}; +int array_sizecheck[(sizeof(array) / sizeof(float4)) == 3? 1 : -1]; + +float4 array2[2] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, + 9.0 }; // expected-warning {{excess elements in array initializer}} + +float4 array3[2] = { {1.0, 2.0, 3.0}, 5.0, 6.0, 7.0, 8.0, + 9.0 }; // expected-warning {{excess elements in array initializer}} + + +// rdar://6881069 +__attribute__((vector_size(16))) // expected-error {{unsupported type 'float (void)' for vector_size attribute, please use on typedef}} +float f1(void) { +} diff --git a/test/Sema/vla.c b/test/Sema/vla.c new file mode 100644 index 000000000000..70ba08b7eb0a --- /dev/null +++ b/test/Sema/vla.c @@ -0,0 +1,56 @@ +// RUN: clang-cc %s -verify -fsyntax-only -pedantic + +int test1() { + typedef int x[test1()]; // vla + static int y = sizeof(x); // expected-error {{not a compile-time constant}} +} + +// PR2347 +void f (unsigned int m) +{ + int e[2][m]; + + e[0][0] = 0; +} + +// PR3048 +int x = sizeof(struct{char qq[x];}); // expected-error {{fields must have a constant size}} + +// PR2352 +void f2(unsigned int m) +{ + extern int e1[2][m]; // expected-error {{variable length array declaration can not have 'extern' linkage}} + + e1[0][0] = 0; + +} + +// PR2361 +int i; +int c[][i]; // expected-error {{variably modified type declaration not allowed at file scope}} +int d[i]; // expected-error {{variable length array declaration not allowed at file scope}} + +int (*e)[i]; // expected-error {{variably modified type declaration not allowed at file scope}} + +void f3() +{ + static int a[i]; // expected-error {{variable length array declaration can not have 'static' storage duration}} + extern int b[i]; // expected-error {{variable length array declaration can not have 'extern' linkage}} + + extern int (*c1)[i]; // expected-error {{variably modified type declaration can not have 'extern' linkage}} + static int (*d)[i]; +} + +// PR3663 +static const unsigned array[((2 * (int)((((4) / 2) + 1.0/3.0) * (4) - 1e-8)) + 1)]; // expected-warning {{size of static array must be an integer constant expression}} + +int a[*]; // expected-error {{star modifier used outside of function prototype}} +int f4(int a[*][*]); + +// PR2044 +int pr2044(int b) {int (*c(void))[b];**c() = 2;} // expected-error {{variably modified type}} +int pr2044b; +int (*pr2044c(void))[pr2044b]; // expected-error {{variably modified type}} + +const int f5_ci = 1; +void f5() { char a[][f5_ci] = {""}; } // expected-error {{variable-sized object may not be initialized}} diff --git a/test/Sema/void_arg.c b/test/Sema/void_arg.c new file mode 100644 index 000000000000..6799146a5ff9 --- /dev/null +++ b/test/Sema/void_arg.c @@ -0,0 +1,26 @@ +/* RUN: clang-cc -fsyntax-only %s -verify + */ + +typedef void Void; + +void foo() { + int X; + + X = sizeof(int (void a)); // expected-error {{argument may not have 'void' type}} + X = sizeof(int (int, void)); // expected-error {{must be the first and only parameter}} + X = sizeof(int (void, ...)); // expected-error {{must be the first and only parameter}} + + X = sizeof(int (Void a)); // expected-error {{argument may not have 'void' type}} + X = sizeof(int (int, Void)); // expected-error {{must be the first and only parameter}} + X = sizeof(int (Void, ...)); // expected-error {{must be the first and only parameter}} + + // Accept these. + X = sizeof(int (void)); + X = sizeof(int (Void)); +} + +// this is ok. +void bar(Void) { +} + +void f(const void); // expected-error {{parameter must not have type qualifiers}} diff --git a/test/Sema/warn-freestanding-complex.c b/test/Sema/warn-freestanding-complex.c new file mode 100644 index 000000000000..a4d3f5be3189 --- /dev/null +++ b/test/Sema/warn-freestanding-complex.c @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -ffreestanding -pedantic -verify %s + +void foo(float _Complex c) { // expected-warning{{complex numbers are an extension in a freestanding C99 implementation}} +} diff --git a/test/Sema/warn-missing-prototypes.c b/test/Sema/warn-missing-prototypes.c new file mode 100644 index 000000000000..299d8a726585 --- /dev/null +++ b/test/Sema/warn-missing-prototypes.c @@ -0,0 +1,37 @@ +// RUN: clang -Wmissing-prototypes -fsyntax-only -Xclang -verify %s + +int f(); + +int f(int x) { return x; } // expected-warning{{no previous prototype for function 'f'}} + +static int g(int x) { return x; } + +int h(int x) { return x; } // expected-warning{{no previous prototype for function 'h'}} + +static int g2(); + +int g2(int x) { return x; } + +void test(void); + +int h3(); +int h4(int); +int h4(); + +void test(void) { + int h2(int x); + int h3(int x); + int h4(); +} + +int h2(int x) { return x; } // expected-warning{{no previous prototype for function 'h2'}} +int h3(int x) { return x; } // expected-warning{{no previous prototype for function 'h3'}} +int h4(int x) { return x; } + +int f2(int); +int f2(); + +int f2(int x) { return x; } + +// rdar://6759522 +int main(void) { return 0; } diff --git a/test/Sema/wchar.c b/test/Sema/wchar.c new file mode 100644 index 000000000000..16376009ab13 --- /dev/null +++ b/test/Sema/wchar.c @@ -0,0 +1,12 @@ +// RUN: clang-cc %s -fsyntax-only -verify +#include <wchar.h> + +int check_wchar_size[sizeof(*L"") == sizeof(wchar_t) ? 1 : -1]; + +void foo() { + int t1[] = L"x"; + wchar_t tab[] = L"x"; + + int t2[] = "x"; // expected-error {{initialization}} + char t3[] = L"x"; // expected-error {{initialization}} +} diff --git a/test/SemaCXX/__null.cpp b/test/SemaCXX/__null.cpp new file mode 100644 index 000000000000..4672801fd7bb --- /dev/null +++ b/test/SemaCXX/__null.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify && +// RUN: clang-cc -triple i686-unknown-unknown %s -fsyntax-only -verify + +void f() { + int* i = __null; + i = __null; + int i2 = __null; + + // Verify statically that __null is the right size + int a[sizeof(typeof(__null)) == sizeof(void*)? 1 : -1]; + + // Verify that null is evaluated as 0. + int b[__null ? -1 : 1]; +} diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp new file mode 100644 index 000000000000..dc764da5322b --- /dev/null +++ b/test/SemaCXX/abstract.cpp @@ -0,0 +1,128 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#define __CONCAT(__X, __Y) __CONCAT1(__X, __Y) +#define __CONCAT1(__X, __Y) __X ## __Y + +#define static_assert(__b, __m) \ + typedef int __CONCAT(__sa, __LINE__)[__b ? 1 : -1] +#endif + +class C { + virtual void f() = 0; // expected-note {{pure virtual function 'f'}} +}; + +static_assert(__is_abstract(C), "C has a pure virtual function"); + +class D : C { +}; + +static_assert(__is_abstract(D), "D inherits from an abstract class"); + +class E : D { + virtual void f(); +}; + +static_assert(!__is_abstract(E), "E inherits from an abstract class but implements f"); + +C *d = new C; // expected-error {{allocation of an object of abstract type 'C'}} + +C c; // expected-error {{variable type 'C' is an abstract class}} +void t1(C c); // expected-error {{parameter type 'C' is an abstract class}} +void t2(C); // expected-error {{parameter type 'C' is an abstract class}} + +struct S { + C c; // expected-error {{field type 'C' is an abstract class}} +}; + +void t3(const C&); + +void f() { + C(); // expected-error {{allocation of an object of abstract type 'C'}} + t3(C()); // expected-error {{allocation of an object of abstract type 'C'}} +} + +C e1[2]; // expected-error {{variable type 'C' is an abstract class}} +C (*e2)[2]; // expected-error {{variable type 'C' is an abstract class}} +C (**e3)[2]; // expected-error {{variable type 'C' is an abstract class}} + +void t4(C c[2]); // expected-error {{parameter type 'C' is an abstract class}} + +void t5(void (*)(C)); // expected-error {{parameter type 'C' is an abstract class}} + +typedef void (*Func)(C); // expected-error {{parameter type 'C' is an abstract class}} +void t6(Func); + +class F { + F a() { } // expected-error {{return type 'F' is an abstract class}} + + class D { + void f(F c); // expected-error {{parameter type 'F' is an abstract class}} + }; + + union U { + void u(F c); // expected-error {{parameter type 'F' is an abstract class}} + }; + + virtual void f() = 0; // expected-note {{pure virtual function 'f'}} +}; + +class Abstract; + +void t7(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}} + +void t8() { + void h(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}} +} + +namespace N { + void h(Abstract a); // expected-error {{parameter type 'Abstract' is an abstract class}} +} + +class Abstract { + virtual void f() = 0; // expected-note {{pure virtual function 'f'}} +}; + +// <rdar://problem/6854087> +class foo { +public: + virtual foo *getFoo() = 0; +}; + +class bar : public foo { +public: + virtual bar *getFoo(); +}; + +bar x; + +// <rdar://problem/6902298> +class A +{ +public: + virtual void release() = 0; + virtual void release(int count) = 0; + virtual void retain() = 0; +}; + +class B : public A +{ +public: + virtual void release(); + virtual void release(int count); + virtual void retain(); +}; + +void foo(void) +{ + B b; +} + +struct K { + int f; + virtual ~K(); +}; + +struct L : public K { + void f(); +}; diff --git a/test/SemaCXX/access-base-class.cpp b/test/SemaCXX/access-base-class.cpp new file mode 100644 index 000000000000..4a9ee51dbfb5 --- /dev/null +++ b/test/SemaCXX/access-base-class.cpp @@ -0,0 +1,82 @@ +// RUN: clang-cc -fsyntax-only -faccess-control -verify %s +namespace T1 { + +class A { }; +class B : private A { }; // expected-note {{'private' inheritance specifier here}} + +void f(B* b) { + A *a = b; // expected-error{{conversion from 'class T1::B' to inaccessible base class 'class T1::A'}} \ + expected-error{{incompatible type initializing 'class T1::B *', expected 'class T1::A *'}} +} + +} + +namespace T2 { + +class A { }; +class B : A { }; // expected-note {{inheritance is implicitly 'private'}} + +void f(B* b) { + A *a = b; // expected-error {{conversion from 'class T2::B' to inaccessible base class 'class T2::A'}} \ + expected-error {{incompatible type initializing 'class T2::B *', expected 'class T2::A *'}} +} + +} + +namespace T3 { + +class A { }; +class B : public A { }; + +void f(B* b) { + A *a = b; +} + +} + +namespace T4 { + +class A {}; + +class B : private virtual A {}; +class C : public virtual A {}; + +class D : public B, public C {}; + +void f(D *d) { + // This takes the D->C->B->A path. + A *a = d; +} + +} + +namespace T5 { + class A {}; + + class B : private A { + void f(B *b) { + A *a = b; + } + }; +} + +namespace T6 { + class C; + + class A {}; + + class B : private A { // expected-note {{'private' inheritance specifier here}} + void f(C* c); + }; + + class C : public B { + void f(C *c) { + A* a = c; // expected-error {{conversion from 'class T6::C' to inaccessible base class 'class T6::A'}} \ + expected-error {{incompatible type initializing 'class T6::C *', expected 'class T6::A *'}} + } + }; + + void B::f(C *c) { + A *a = c; + } +} diff --git a/test/SemaCXX/access.cpp b/test/SemaCXX/access.cpp new file mode 100644 index 000000000000..cfbc9c80692b --- /dev/null +++ b/test/SemaCXX/access.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class C { + struct S; // expected-note {{previously declared 'private' here}} +public: + + struct S {}; // expected-error {{'S' redeclared with 'public' access}} +}; + +struct S { + class C; // expected-note {{previously declared 'public' here}} + +private: + class C { }; // expected-error {{'C' redeclared with 'private' access}} +}; + +class T { +protected: + template<typename T> struct A; // expected-note {{previously declared 'protected' here}} + +private: + template<typename T> struct A {}; // expected-error {{'A' redeclared with 'private' access}} +}; diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp new file mode 100644 index 000000000000..9c9f0e19ef3c --- /dev/null +++ b/test/SemaCXX/addr-of-overloaded-function.cpp @@ -0,0 +1,29 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int f(double); +int f(int); + +int (*pfd)(double) = f; // selects f(double) +int (*pfd2)(double) = &f; // selects f(double) +int (*pfd3)(double) = ((&((f)))); // selects f(double) +int (*pfi)(int) = &f; // selects f(int) +// FIXME: This error message is not very good. We need to keep better +// track of what went wrong when the implicit conversion failed to +// give a better error message here. +int (*pfe)(...) = &f; // expected-error{{incompatible type initializing '<overloaded function type>', expected 'int (*)(...)'}} +int (&rfi)(int) = f; // selects f(int) +int (&rfd)(double) = f; // selects f(double) + +void g(int (*fp)(int)); // expected-note{{note: candidate function}} +void g(int (*fp)(float)); +void g(int (*fp)(double)); // expected-note{{note: candidate function}} + +int g1(int); +int g1(char); + +int g2(int); +int g2(double); + +void g_test() { + g(g1); + g(g2); // expected-error{{call to 'g' is ambiguous; candidates are:}} +} diff --git a/test/SemaCXX/address-of.cpp b/test/SemaCXX/address-of.cpp new file mode 100644 index 000000000000..4e436d6e98b2 --- /dev/null +++ b/test/SemaCXX/address-of.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR clang/3175 + +void bar(int*); + +class c { + int var; + static int svar; + void foo() { + bar(&var); + bar(&svar); + } + + static void wibble() { + bar(&var); // expected-error{{invalid use of member 'var' in static member function}} + bar(&svar); + } +}; + +enum E { + Enumerator +}; + +void test() { + (void)&Enumerator; // expected-error{{address expression must be an lvalue or a function designator}} +} + +template<int N> +void test2() { + (void)&N; // expected-error{{address expression must be an lvalue or a function designator}} +} + +// PR clang/3222 +void xpto(); +void (*xyz)(void) = &xpto; diff --git a/test/SemaCXX/aggregate-initialization.cpp b/test/SemaCXX/aggregate-initialization.cpp new file mode 100644 index 000000000000..c96eda448032 --- /dev/null +++ b/test/SemaCXX/aggregate-initialization.cpp @@ -0,0 +1,28 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 %s + +// Verify that we can't initialize non-aggregates with an initializer +// list. +struct NonAggr1 { + NonAggr1(int) { } + + int m; +}; + +struct Base { }; +struct NonAggr2 : public Base { + int m; +}; + +class NonAggr3 { + int m; +}; + +struct NonAggr4 { + int m; + virtual void f(); +}; + +NonAggr1 na1 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr1' with an initializer list}} +NonAggr2 na2 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr2' with an initializer list}} +NonAggr3 na3 = { 17 }; // expected-error{{initialization of non-aggregate type 'class NonAggr3' with an initializer list}} +NonAggr4 na4 = { 17 }; // expected-error{{initialization of non-aggregate type 'struct NonAggr4' with an initializer list}} diff --git a/test/SemaCXX/anonymous-union.cpp b/test/SemaCXX/anonymous-union.cpp new file mode 100644 index 000000000000..f77fa03328f6 --- /dev/null +++ b/test/SemaCXX/anonymous-union.cpp @@ -0,0 +1,113 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct X { + union { + float f3; + double d2; + } named; + + union { + int i; + float f; + + union { + float f2; + mutable double d; + }; + }; + + void test_unqual_references(); + + struct { + int a; + float b; + }; + + void test_unqual_references_const() const; + + mutable union { // expected-error{{anonymous union at class scope must not have a storage specifier}} + float c1; + double c2; + }; +}; + +void X::test_unqual_references() { + i = 0; + f = 0.0; + f2 = f; + d = f; + f3 = 0; // expected-error{{use of undeclared identifier 'f3'}} + a = 0; +} + +void X::test_unqual_references_const() const { + d = 0.0; + f2 = 0; // expected-error{{read-only variable is not assignable}} + a = 0; // expected-error{{read-only variable is not assignable}} +} + +void test_unqual_references(X x, const X xc) { + x.i = 0; + x.f = 0.0; + x.f2 = x.f; + x.d = x.f; + x.f3 = 0; // expected-error{{no member named 'f3'}} + x.a = 0; + + xc.d = 0.0; + xc.f = 0; // expected-error{{read-only variable is not assignable}} + xc.a = 0; // expected-error{{read-only variable is not assignable}} +} + + +struct Redecl { + int x; // expected-note{{previous declaration is here}} + class y { }; + + union { + int x; // expected-error{{member of anonymous union redeclares 'x'}} + float y; + double z; // expected-note{{previous declaration is here}} + double zz; // expected-note{{previous definition is here}} + }; + + int z; // expected-error{{duplicate member 'z'}} + void zz(); // expected-error{{redefinition of 'zz' as different kind of symbol}} +}; + +union { // expected-error{{anonymous unions at namespace or global scope must be declared 'static'}} + int int_val; + float float_val; +}; + +static union { + int int_val2; + float float_val2; +}; + +void f() { + int_val2 = 0; + float_val2 = 0.0; +} + +void g() { + union { + int i; + float f2; + }; + i = 0; + f2 = 0.0; +} + +struct BadMembers { + union { + struct X { }; // expected-error {{types cannot be declared in an anonymous union}} + struct { int x; int y; } y; + + void f(); // expected-error{{functions cannot be declared in an anonymous union}} + private: int x1; // expected-error{{anonymous union cannot contain a private data member}} + protected: float x2; // expected-error{{anonymous union cannot contain a protected data member}} + }; +}; + +// <rdar://problem/6481130> +typedef union { }; // expected-error{{declaration does not declare anything}} diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp new file mode 100644 index 000000000000..8e5f76bcacfa --- /dev/null +++ b/test/SemaCXX/attr-unavailable.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int &foo(int); +double &foo(double); +void foo(...) __attribute__((__unavailable__)); // expected-note {{candidate function}} \ +// expected-note{{function has been explicitly marked unavailable here}} + +void bar(...) __attribute__((__unavailable__)); // expected-note 2{{explicitly marked unavailable}} + +void test_foo(short* sp) { + int &ir = foo(1); + double &dr = foo(1.0); + foo(sp); // expected-error{{call to unavailable function 'foo'}} + + void (*fp)(...) = &bar; // expected-warning{{'bar' is unavailable}} + void (*fp2)(...) = bar; // expected-warning{{'bar' is unavailable}} + + int &(*fp3)(int) = foo; + void (*fp4)(...) = foo; // expected-warning{{'foo' is unavailable}} +} diff --git a/test/SemaCXX/basic_lookup_argdep.cpp b/test/SemaCXX/basic_lookup_argdep.cpp new file mode 100644 index 000000000000..486a688d9437 --- /dev/null +++ b/test/SemaCXX/basic_lookup_argdep.cpp @@ -0,0 +1,60 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N { + struct X { }; + + X operator+(X, X); + + void f(X); + void g(X); // expected-note{{candidate function}} + + void test_multiadd(X x) { + (void)(x + x); + } +} + +namespace M { + struct Y : N::X { }; +} + +void f(); + +void test_operator_adl(N::X x, M::Y y) { + (void)(x + x); + (void)(y + y); +} + +void test_func_adl(N::X x, M::Y y) { + f(x); + f(y); + (f)(x); // expected-error{{too many arguments to function call}} + ::f(x); // expected-error{{too many arguments to function call}} +} + +namespace N { + void test_multiadd2(X x) { + (void)(x + x); + } +} + + +void test_func_adl_only(N::X x) { + g(x); +} + +namespace M { + int g(N::X); // expected-note{{candidate function}} + + void test(N::X x) { + g(x); // expected-error{{call to 'g' is ambiguous; candidates are:}} + int i = (g)(x); + + int g(N::X); + g(x); // okay; calls locally-declared function, no ADL + } +} + + +void test_operator_name_adl(N::X x) { + (void)operator+(x, x); +} diff --git a/test/SemaCXX/blocks.cpp b/test/SemaCXX/blocks.cpp new file mode 100644 index 000000000000..9d789bb3252a --- /dev/null +++ b/test/SemaCXX/blocks.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s -fblocks + +void tovoid(void*); + +void tovoid_test(int (^f)(int, int)) { + tovoid(f); +} + +void reference_lvalue_test(int& (^f)()) { + f() = 10; +} diff --git a/test/SemaCXX/bool.cpp b/test/SemaCXX/bool.cpp new file mode 100644 index 000000000000..bc44c73d8cac --- /dev/null +++ b/test/SemaCXX/bool.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Bool literals can be enum values. +enum { + ReadWrite = false, + ReadOnly = true +}; + +// bool cannot be decremented, and gives a warning on increment +void test(bool b) +{ + ++b; // expected-warning {{incrementing expression of type bool is deprecated}} + b++; // expected-warning {{incrementing expression of type bool is deprecated}} + --b; // expected-error {{cannot decrement expression of type bool}} + b--; // expected-error {{cannot decrement expression of type bool}} + + bool *b1 = (int *)0; // expected-error{{expected 'bool *'}} +} diff --git a/test/SemaCXX/carbon.cpp b/test/SemaCXX/carbon.cpp new file mode 100644 index 000000000000..0e7570f33529 --- /dev/null +++ b/test/SemaCXX/carbon.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -mcpu=pentium4 %s -fsyntax-only -print-stats +#ifdef __APPLE__ +#include <Carbon/Carbon.h> +#endif + diff --git a/test/SemaCXX/class-names.cpp b/test/SemaCXX/class-names.cpp new file mode 100644 index 000000000000..a5569c0c767b --- /dev/null +++ b/test/SemaCXX/class-names.cpp @@ -0,0 +1,52 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class C { }; + +C c; + +void D(int); + +class D {}; // expected-note {{previous use is here}} + +void foo() +{ + D(5); + class D d; +} + +class D; + +enum D; // expected-error {{use of 'D' with tag type that does not match previous declaration}} + +class A * A; + +class A * a2; + +void bar() +{ + A = 0; +} + +void C(int); + +void bar2() +{ + C(17); +} + +extern int B; +class B; +class B {}; +int B; + +enum E { e1_val }; +E e1; + +void E(int); + +void bar3() { + E(17); +} + +enum E e2; + +enum E2 { E2 }; diff --git a/test/SemaCXX/class.cpp b/test/SemaCXX/class.cpp new file mode 100644 index 000000000000..d2a8114f7b06 --- /dev/null +++ b/test/SemaCXX/class.cpp @@ -0,0 +1,112 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class C { +public: + auto int errx; // expected-error {{error: storage class specified for a member declaration}} + register int erry; // expected-error {{error: storage class specified for a member declaration}} + extern int errz; // expected-error {{error: storage class specified for a member declaration}} + + static void sm() { + sx = 0; + this->x = 0; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}} + x = 0; // expected-error {{error: invalid use of member 'x' in static member function}} + } + + class NestedC { + void m() { + sx = 0; + x = 0; // expected-error {{error: invalid use of nonstatic data member 'x'}} + } + }; + + int b : 1, w : 2; + int : 1, : 2; + typedef int E : 1; // expected-error {{typedef member 'E' cannot be a bit-field}} + static int sb : 1; // expected-error {{error: static member 'sb' cannot be a bit-field}} + static int vs; + + typedef int func(); + func tm; + func *ptm; + func btm : 1; // expected-error {{bit-field 'btm' has non-integral type}} + NestedC bc : 1; // expected-error {{bit-field 'bc' has non-integral type}} + + enum E1 { en1, en2 }; + + int i = 0; // expected-error {{error: 'i' can only be initialized if it is a static const integral data member}} + static int si = 0; // expected-error {{error: 'si' can only be initialized if it is a static const integral data member}} + static const NestedC ci = 0; // expected-error {{error: 'ci' can only be initialized if it is a static const integral data member}} + static const int nci = vs; // expected-error {{in-class initializer is not an integral constant expression}} + static const int vi = 0; + static const E evi = 0; + + void m() { + sx = 0; + this->x = 0; + y = 0; + this = 0; // expected-error {{error: expression is not assignable}} + } + + int f1(int p) { + A z = 6; + return p + x + this->y + z; + } + + typedef int A; + + virtual int viv; // expected-error {{'virtual' can only appear on non-static member functions}} + virtual static int vsif(); // expected-error {{error: 'virtual' can only appear on non-static member functions}} + virtual int vif(); + +private: + int x,y; + static int sx; + + mutable int mi; + mutable int &mir; // expected-error {{error: 'mutable' cannot be applied to references}} + mutable void mfn(); // expected-error {{error: 'mutable' cannot be applied to functions}} + mutable const int mci; // expected-error {{error: 'mutable' and 'const' cannot be mixed}} + + static const int number = 50; + static int arr[number]; +}; + +class C2 { + void f() { + static int lx; + class LC1 { + int m() { return lx; } + }; + class LC2 { + int m() { return lx; } + }; + } +}; + +struct C3 { + int i; + mutable int j; +}; +void f() +{ + const C3 c3 = { 1, 2 }; + (void)static_cast<int*>(&c3.i); // expected-error {{static_cast from 'int const *' to 'int *' is not allowed}} + // but no error here + (void)static_cast<int*>(&c3.j); +} + +// Play with mutable a bit more, to make sure it doesn't crash anything. +mutable int gi; // expected-error {{error: 'mutable' can only be applied to member variables}} +mutable void gfn(); // expected-error {{illegal storage class on function}} +void ogfn() +{ + mutable int ml; // expected-error {{error: 'mutable' can only be applied to member variables}} + + // PR3020: This used to crash due to double ownership of C4. + struct C4; + C4; // expected-error {{declaration does not declare anything}} +} + +struct C4 { + void f(); // expected-note{{previous declaration is here}} + int f; // expected-error{{duplicate member 'f'}} +}; diff --git a/test/SemaCXX/complex-overload.cpp b/test/SemaCXX/complex-overload.cpp new file mode 100644 index 000000000000..55d3c76d0638 --- /dev/null +++ b/test/SemaCXX/complex-overload.cpp @@ -0,0 +1,50 @@ +// RUN: clang-cc -fsyntax-only -verify %s +char *foo(float); // expected-note 3 {{candidate function}} + +void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); + // Note: GCC and EDG reject these two, but they are valid C99 conversions + char *cp3 = foo(fc); + char *cp4 = foo(dc); +} + +int *foo(float _Complex); // expected-note 3 {{candidate function}} + +void test_foo_2(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}} + int *ip = foo(fc); + int *lp = foo(dc); // expected-error{{call to 'foo' is ambiguous; candidates are:}} +} + +long *foo(double _Complex); // expected-note {{candidate function}} + +void test_foo_3(float fv, double dv, float _Complex fc, double _Complex dc) { + char *cp1 = foo(fv); + char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}} + int *ip = foo(fc); + long *lp = foo(dc); +} + +char *promote_or_convert(double _Complex); // expected-note{{candidate function}} +int *promote_or_convert(long double _Complex); // expected-note{{candidate function}} + +void test_promote_or_convert(float f, float _Complex fc) { + char *cp = promote_or_convert(fc); + int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous; candidates are:}} +} + +char *promote_or_convert2(float); +int *promote_or_convert2(double _Complex); + +void test_promote_or_convert2(float _Complex fc) { + int *cp = promote_or_convert2(fc); +} + +char *promote_or_convert3(int _Complex); +int *promote_or_convert3(long _Complex); + +void test_promote_or_convert3(short _Complex sc) { + char *cp = promote_or_convert3(sc); +} diff --git a/test/SemaCXX/composite-pointer-type.cpp b/test/SemaCXX/composite-pointer-type.cpp new file mode 100644 index 000000000000..b4a5c884f755 --- /dev/null +++ b/test/SemaCXX/composite-pointer-type.cpp @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class Base { }; +class Derived1 : public Base { }; +class Derived2 : public Base { }; + +void f0(volatile Base *b, Derived1 *d1, const Derived2 *d2) { + if (b > d1) + return; + if (d1 <= b) + return; + if (b > d2) + return; + if (d1 >= d2) // expected-error{{comparison of distinct}} + return; +} + +void f1(volatile Base *b, Derived1 *d1, const Derived2 *d2) { + if (b == d1) + return; + if (d1 == b) + return; + if (b != d2) + return; + if (d1 == d2) // expected-error{{comparison of distinct}} + return; +} diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp new file mode 100644 index 000000000000..7c9cee59da6f --- /dev/null +++ b/test/SemaCXX/condition.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void test() { + int x; + if (x) ++x; + if (int x=0) ++x; + + typedef int arr[10]; + while (arr x=0) ; // expected-error {{an array type is not allowed here}} expected-error {{initialization with '{...}' expected for array}} + while (int f()=0) ; // expected-error {{a function type is not allowed here}} + + struct S {} s; + if (s) ++x; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + while (struct S x=s) ; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + do ; while (s); // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + for (;s;) ; // expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + switch (s) {} // expected-error {{statement requires expression of integer type ('struct S' invalid)}} + + while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize 'x' with an rvalue of type 'int'}} expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} + while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize 'x' with an rvalue of type 'int'}} expected-error {{value of type 'struct <anonymous>' is not contextually convertible to 'bool'}} + switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{incompatible type}} + + if (int x=0) { // expected-note 2 {{previous definition is here}} + int x; // expected-error {{redefinition of 'x'}} + } + else + int x; // expected-error {{redefinition of 'x'}} + while (int x=0) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + while (int x=0) { int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + for (int x; int x=0; ) ; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + for (int x; ; ) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + for (; int x=0; ) int x; // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + for (; int x=0; ) { int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} + switch (int x=0) { default: int x; } // expected-error {{redefinition of 'x'}} expected-note {{previous definition is here}} +} diff --git a/test/SemaCXX/conditional-expr.cpp b/test/SemaCXX/conditional-expr.cpp new file mode 100644 index 000000000000..3f4d7159a0f8 --- /dev/null +++ b/test/SemaCXX/conditional-expr.cpp @@ -0,0 +1,181 @@ +// RUN: clang-cc -fsyntax-only -verify -faccess-control -std=c++0x %s + +// C++ rules for ?: are a lot stricter than C rules, and have to take into +// account more conversion options. +// This test runs in C++0x mode for the contextual conversion of the condition. + +struct ToBool { explicit operator bool(); }; + +struct B; +struct A { A(); A(const B&); }; +struct B { operator A() const; }; +struct I { operator int(); }; +struct J { operator I(); }; +struct K { operator double(); }; +typedef void (*vfn)(); +struct F { operator vfn(); }; +struct G { operator vfn(); }; + +struct Base { + int trick(); + A trick() const; + void fn1(); +}; +struct Derived : Base { + void fn2(); +}; +struct Convertible { operator Base&(); }; +struct Priv : private Base {}; // expected-note 2 {{'private' inheritance specifier here}} +struct Mid : Base {}; +struct Fin : Mid, Derived {}; +typedef void (Derived::*DFnPtr)(); +struct ToMemPtr { operator DFnPtr(); }; + +struct BadDerived; +struct BadBase { operator BadDerived&(); }; +struct BadDerived : BadBase {}; + +struct Fields { + int i1, i2, b1 : 3, b2 : 3; +}; +struct MixedFields { + int i; + volatile int vi; + const int ci; + const volatile int cvi; +}; +struct MixedFieldsDerived : MixedFields { +}; + +enum Enum { EVal }; + +struct Ambig { + operator short(); + operator signed char(); +}; + +void test() +{ + // This function tests C++0x 5.16 + + // p1 (contextually convert to bool) + int i1 = ToBool() ? 0 : 1; + + // p2 (one or both void, and throwing) + i1 ? throw 0 : throw 1; + i1 ? test() : throw 1; + i1 ? throw 0 : test(); + i1 ? test() : test(); + i1 = i1 ? throw 0 : 0; + i1 = i1 ? 0 : throw 0; + i1 ? 0 : test(); // expected-error {{right operand to ? is void, but left operand is of type 'int'}} + i1 ? test() : 0; // expected-error {{left operand to ? is void, but right operand is of type 'int'}} + (i1 ? throw 0 : i1) = 0; // expected-error {{expression is not assignable}} + (i1 ? i1 : throw 0) = 0; // expected-error {{expression is not assignable}} + + // p3 (one or both class type, convert to each other) + // b1 (lvalues) + Base base; + Derived derived; + Convertible conv; + Base &bar1 = i1 ? base : derived; + Base &bar2 = i1 ? derived : base; + Base &bar3 = i1 ? base : conv; + Base &bar4 = i1 ? conv : base; + // these are ambiguous + BadBase bb; + BadDerived bd; + (void)(i1 ? bb : bd); // expected-error {{conditional expression is ambiguous; 'struct BadBase' can be converted to 'struct BadDerived' and vice versa}} + (void)(i1 ? bd : bb); // expected-error {{conditional expression is ambiguous}} + // curiously enough (and a defect?), these are not + // for rvalues, hierarchy takes precedence over other conversions + (void)(i1 ? BadBase() : BadDerived()); + (void)(i1 ? BadDerived() : BadBase()); + + // b2.1 (hierarchy stuff) + const Base constret(); + const Derived constder(); + // should use const overload + A a1((i1 ? constret() : Base()).trick()); + A a2((i1 ? Base() : constret()).trick()); + A a3((i1 ? constret() : Derived()).trick()); + A a4((i1 ? Derived() : constret()).trick()); + // should use non-const overload + i1 = (i1 ? Base() : Base()).trick(); + i1 = (i1 ? Base() : Base()).trick(); + i1 = (i1 ? Base() : Derived()).trick(); + i1 = (i1 ? Derived() : Base()).trick(); + // should fail: const lost + (void)(i1 ? Base() : constder()); // expected-error {{incompatible operand types ('struct Base' and 'struct Derived const')}} + (void)(i1 ? constder() : Base()); // expected-error {{incompatible operand types ('struct Derived const' and 'struct Base')}} + + // FIXME: these are invalid hierarchy conversions + Priv priv; + Fin fin; + (void)(i1 ? Base() : Priv()); // xpected-error private base + (void)(i1 ? Priv() : Base()); // xpected-error private base + (void)(i1 ? Base() : Fin()); // xpected-error ambiguous base + (void)(i1 ? Fin() : Base()); // xpected-error ambiguous base + (void)(i1 ? base : priv); // expected-error {{conversion from 'struct Priv' to inaccessible base class 'struct Base'}} + (void)(i1 ? priv : base); // expected-error {{conversion from 'struct Priv' to inaccessible base class 'struct Base'}} + (void)(i1 ? base : fin); // expected-error {{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} + (void)(i1 ? fin : base); // expected-error {{ambiguous conversion from derived class 'struct Fin' to base class 'struct Base'}} + + // b2.2 (non-hierarchy) + i1 = i1 ? I() : i1; + i1 = i1 ? i1 : I(); + I i2(i1 ? I() : J()); + I i3(i1 ? J() : I()); + // "the type [it] woud have if E2 were converted to an rvalue" + vfn pfn = i1 ? F() : test; + pfn = i1 ? test : F(); + // these are ambiguous - better messages would be nice + (void)(i1 ? A() : B()); // expected-error {{incompatible operand types}} + (void)(i1 ? B() : A()); // expected-error {{incompatible operand types}} + (void)(i1 ? 1 : Ambig()); // expected-error {{incompatible operand types}} + (void)(i1 ? Ambig() : 1); // expected-error {{incompatible operand types}} + // By the way, this isn't an lvalue: + &(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}} + + // p4 (lvalue, same type) + Fields flds; + int &ir1 = i1 ? flds.i1 : flds.i2; + (i1 ? flds.b1 : flds.i2) = 0; + (i1 ? flds.i1 : flds.b2) = 0; + (i1 ? flds.b1 : flds.b2) = 0; + + // p5 (conversion to built-in types) + // GCC 4.3 fails these + double d1 = i1 ? I() : K(); + pfn = i1 ? F() : G(); + DFnPtr pfm; + pfm = i1 ? DFnPtr() : &Base::fn1; + pfm = i1 ? &Base::fn1 : DFnPtr(); + + // p6 (final conversions) + i1 = i1 ? i1 : ir1; + int *pi1 = i1 ? &i1 : 0; + pi1 = i1 ? 0 : &i1; + i1 = i1 ? i1 : EVal; + i1 = i1 ? EVal : i1; + d1 = i1 ? 'c' : 4.0; + d1 = i1 ? 4.0 : 'c'; + Base *pb = i1 ? (Base*)0 : (Derived*)0; + pb = i1 ? (Derived*)0 : (Base*)0; + pfm = i1 ? &Base::fn1 : &Derived::fn2; + pfm = i1 ? &Derived::fn2 : &Base::fn1; + pfm = i1 ? &Derived::fn2 : 0; + pfm = i1 ? 0 : &Derived::fn2; + const int (MixedFieldsDerived::*mp1) = + i1 ? &MixedFields::ci : &MixedFieldsDerived::i; + const volatile int (MixedFields::*mp2) = + i1 ? &MixedFields::ci : &MixedFields::cvi; + i1 ? &MixedFields::ci : &MixedFields::vi; // expected-error {{incompatible operand types}} + // Conversion of primitives does not result in an lvalue. + &(i1 ? i1 : d1); // expected-error {{address expression must be an lvalue or a function designator}} + + + // Note the thing that this does not test: since DR446, various situations + // *must* create a separate temporary copy of class objects. This can only + // be properly tested at runtime, though. +} diff --git a/test/SemaCXX/const-cast.cpp b/test/SemaCXX/const-cast.cpp new file mode 100644 index 000000000000..39d61db0dc94 --- /dev/null +++ b/test/SemaCXX/const-cast.cpp @@ -0,0 +1,63 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A {}; + +// See if aliasing can confuse this baby. +typedef char c; +typedef c *cp; +typedef cp *cpp; +typedef cpp *cppp; +typedef cppp &cpppr; +typedef const cppp &cpppcr; +typedef const char cc; +typedef cc *ccp; +typedef volatile ccp ccvp; +typedef ccvp *ccvpp; +typedef const volatile ccvpp ccvpcvp; +typedef ccvpcvp *ccvpcvpp; +typedef int iar[100]; +typedef iar &iarr; +typedef int (*f)(int); + +char ***good_const_cast_test(ccvpcvpp var) +{ + // Cast away deep consts and volatiles. + char ***var2 = const_cast<cppp>(var); + char ***const &var3 = var2; + // Const reference to reference. + char ***&var4 = const_cast<cpppr>(var3); + // Drop reference. Intentionally without qualifier change. + char *** var5 = const_cast<cppp>(var4); + const int ar[100] = {0}; + int (&rar)[100] = const_cast<iarr>(ar); // expected-error {{const_cast from 'int const [100]' to 'iarr' (aka 'iar &') is not allowed}} + // Array decay. Intentionally without qualifier change. + int *pi = const_cast<int*>(ar); + f fp = 0; + // Don't misidentify fn** as a function pointer. + f *fpp = const_cast<f*>(&fp); + int const A::* const A::*icapcap = 0; + int A::* A::* iapap = const_cast<int A::* A::*>(icapcap); + + return var4; +} + +short *bad_const_cast_test(char const *volatile *const volatile *var) +{ + // Different pointer levels. + char **var2 = const_cast<char**>(var); // expected-error {{const_cast from 'char const *volatile *const volatile *' to 'char **' is not allowed}} + // Different final type. + short ***var3 = const_cast<short***>(var); // expected-error {{const_cast from 'char const *volatile *const volatile *' to 'short ***' is not allowed}} + // Rvalue to reference. + char ***&var4 = const_cast<cpppr>(&var2); // expected-error {{const_cast from rvalue to reference type 'cpppr'}} + // Non-pointer. + char v = const_cast<char>(**var2); // expected-error {{const_cast to 'char', which is not a reference, pointer-to-object, or pointer-to-data-member}} + const int *ar[100] = {0}; + // Not even lenient g++ accepts this. + int *(*rar)[100] = const_cast<int *(*)[100]>(&ar); // expected-error {{const_cast from 'int const *(*)[100]' to 'int *(*)[100]' is not allowed}} + f fp1 = 0; + // Function pointers. + f fp2 = const_cast<f>(fp1); // expected-error {{const_cast to 'f' (aka 'int (*)(int)'), which is not a reference, pointer-to-object, or pointer-to-data-member}} + void (A::*mfn)() = 0; + (void)const_cast<void (A::*)()>(mfn); // expected-error {{const_cast to 'void (struct A::*)(void)', which is not a reference, pointer-to-object, or pointer-to-data-member}} + return **var3; +} diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp new file mode 100644 index 000000000000..02ea802c7265 --- /dev/null +++ b/test/SemaCXX/constant-expression.cpp @@ -0,0 +1,83 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 %s + +// C++ [expr.const]p1: +// In several places, C++ requires expressions that evaluate to an integral +// or enumeration constant: as array bounds, as case expressions, as +// bit-field lengths, as enumerator initializers, as static member +// initializers, and as integral or enumeration non-type template arguments. +// An integral constant-expression can involve only literals, enumerators, +// const variables or static data members of integral or enumeration types +// initialized with constant expressions, and sizeof expressions. Floating +// literals can appear only if they are cast to integral or enumeration types. + +enum Enum { eval = 1 }; +const int cval = 2; +const Enum ceval = eval; +struct Struct { + static const int sval = 3; + static const Enum seval = eval; +}; + +template <int itval, Enum etval> struct C { + enum E { + v1 = 1, + v2 = eval, + v3 = cval, + v4 = ceval, + v5 = Struct::sval, + v6 = Struct::seval, + v7 = itval, + v8 = etval, + v9 = (int)1.5, + v10 = sizeof(Struct), + v11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + }; + unsigned + b1 : 1, + b2 : eval, + b3 : cval, + b4 : ceval, + b5 : Struct::sval, + b6 : Struct::seval, + b7 : itval, + b8 : etval, + b9 : (int)1.5, + b10 : sizeof(Struct), + b11 : true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + ; + static const int + i1 = 1, + i2 = eval, + i3 = cval, + i4 = ceval, + i5 = Struct::sval, + i6 = Struct::seval, + i7 = itval, + i8 = etval, + i9 = (int)1.5, + i10 = sizeof(Struct), + i11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + ; + void f() { + switch(0) { + case 0 + 1: + case 100 + eval: + case 200 + cval: + case 300 + ceval: + case 400 + Struct::sval: + case 500 + Struct::seval: + case 600 + itval: + case 700 + etval: + case 800 + (int)1.5: + case 900 + sizeof(Struct): + case 1000 + (true? 1 + cval * Struct::sval ^ + itval / (int)1.5 - sizeof(Struct) : 0): + ; + } + } + typedef C<itval, etval> T0; +}; + +template struct C<1, eval>; +//template struct C<cval, ceval>; +//template struct C<Struct::sval, Struct::seval>; diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp new file mode 100644 index 000000000000..d0c978a80d15 --- /dev/null +++ b/test/SemaCXX/constructor-initializer.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class A { + int m; +}; + +class B : public A { +public: + B() : A(), m(1), n(3.14) { } + +private: + int m; + float n; +}; + + +class C : public virtual B { +public: + C() : B() { } +}; + +class D : public C { +public: + D() : B(), C() { } +}; + +class E : public D, public B { +public: + E() : B(), D() { } // expected-error{{base class initializer 'B' names both a direct base class and an inherited virtual base class}} +}; + + +typedef int INT; + +class F : public B { +public: + int B; + + F() : B(17), + m(17), // expected-error{{member initializer 'm' does not name a non-static data member or base class}} + INT(17) // expected-error{{constructor initializer 'INT' (aka 'int') does not name a class}} + { + } +}; + +class G : A { + G() : A(10); // expected-error{{expected '{'}} +}; + +void f() : a(242) { } // expected-error{{only constructors take base initializers}} + +class H : A { + H(); +}; + +H::H() : A(10) { } + diff --git a/test/SemaCXX/constructor-recovery.cpp b/test/SemaCXX/constructor-recovery.cpp new file mode 100644 index 000000000000..50fdc9622e4c --- /dev/null +++ b/test/SemaCXX/constructor-recovery.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct C { // expected-note {{candidate function}} + virtual C() = 0; // expected-error{{constructor cannot be declared 'virtual'}} \ + expected-note {{candidate function}} +}; + +void f() { + C c; // expected-error {{call to constructor of 'c' is ambiguous}} +} diff --git a/test/SemaCXX/constructor.cpp b/test/SemaCXX/constructor.cpp new file mode 100644 index 000000000000..8f289a2b1e96 --- /dev/null +++ b/test/SemaCXX/constructor.cpp @@ -0,0 +1,60 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef int INT; + +class Foo { + Foo(); + (Foo)(float) { } + explicit Foo(int); // expected-note {{previous declaration is here}} + Foo(const Foo&); + + ((Foo))(INT); // expected-error{{cannot be redeclared}} + + Foo(Foo foo, int i = 17, int j = 42); // expected-error{{copy constructor must pass its first argument by reference}} + + static Foo(short, short); // expected-error{{constructor cannot be declared 'static'}} + virtual Foo(double); // expected-error{{constructor cannot be declared 'virtual'}} + Foo(long) const; // expected-error{{'const' qualifier is not allowed on a constructor}} + + int Foo(int, int); // expected-error{{constructor cannot have a return type}} +}; + +Foo::Foo(const Foo&) { } + +typedef struct { + int version; +} Anon; +extern const Anon anon; +extern "C" const Anon anon2; + +// PR3188: The extern declaration complained about not having an appropriate +// constructor. +struct x; +extern x a; + +// A similar case. +struct y { + y(int); +}; +extern y b; + +struct Length { + Length l() const { return *this; } +}; + +// <rdar://problem/6815988> +struct mmst_reg{ + char mmst_reg[10]; +}; + +// PR3948 +namespace PR3948 { +// PR3948 +class a { + public: + int b(int a()); +}; +int x(); +void y() { + a z; z.b(x); +} +} diff --git a/test/SemaCXX/conversion-function.cpp b/test/SemaCXX/conversion-function.cpp new file mode 100644 index 000000000000..1ca1e689eab0 --- /dev/null +++ b/test/SemaCXX/conversion-function.cpp @@ -0,0 +1,66 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class X { +public: + operator bool(); + operator int() const; + + bool f() { + return operator bool(); + } + + float g() { + return operator float(); // expected-error{{no matching function for call to 'operator float'}} + } +}; + +operator int(); // expected-error{{conversion function must be a non-static member function}} + +operator int; // expected-error{{'operator int' cannot be the name of a variable or data member}} + +typedef int func_type(int); +typedef int array_type[10]; + +class Y { +public: + void operator bool(int, ...) const; // expected-error{{conversion function cannot have a return type}} \ + // expected-error{{conversion function cannot have any parameters}} + + operator float(...) const; // expected-error{{conversion function cannot be variadic}} + + + operator func_type(); // expected-error{{conversion function cannot convert to a function type}} + operator array_type(); // expected-error{{conversion function cannot convert to an array type}} +}; + + +typedef int INT; +typedef INT* INT_PTR; + +class Z { + operator int(); // expected-note {{previous declaration is here}} + operator int**(); // expected-note {{previous declaration is here}} + + operator INT(); // expected-error{{conversion function cannot be redeclared}} + operator INT_PTR*(); // expected-error{{conversion function cannot be redeclared}} +}; + + +class A { }; + +class B : public A { +public: + operator A&() const; // expected-warning{{conversion function converting 'class B' to its base class 'class A' will never be used}} + operator const void() const; // expected-warning{{conversion function converting 'class B' to 'void const' will never be used}} + operator const B(); // expected-warning{{conversion function converting 'class B' to itself will never be used}} +}; + +// This used to crash Clang. +struct Flip; +struct Flop { + Flop(); + Flop(const Flip&); +}; +struct Flip { + operator Flop() const; +}; +Flop flop = Flip(); // expected-error {{cannot initialize 'flop' with an rvalue of type 'struct Flip'}} diff --git a/test/SemaCXX/convert-to-bool.cpp b/test/SemaCXX/convert-to-bool.cpp new file mode 100644 index 000000000000..937b2729d1c3 --- /dev/null +++ b/test/SemaCXX/convert-to-bool.cpp @@ -0,0 +1,67 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct ConvToBool { + operator bool() const; +}; + +struct ConvToInt { + operator int(); +}; + +struct ExplicitConvToBool { + explicit operator bool(); // expected-warning{{explicit conversion functions are a C++0x extension}} +}; + +void test_conv_to_bool(ConvToBool ctb, ConvToInt cti, ExplicitConvToBool ecb) { + if (ctb) { } + if (cti) { } + if (ecb) { } + for (; ctb; ) { } + for (; cti; ) { } + for (; ecb; ) { } + while (ctb) { }; + while (cti) { } + while (ecb) { } + do { } while (ctb); + do { } while (cti); + do { } while (ecb); + + if (!ctb) { } + if (!cti) { } + if (!ecb) { } + + bool b1 = !ecb; + if (ctb && ecb) { } + bool b2 = ctb && ecb; + if (ctb || ecb) { } + bool b3 = ctb || ecb; +} + +void accepts_bool(bool) { } // expected-note{{candidate function}} + +struct ExplicitConvToRef { + explicit operator int&(); // expected-warning{{explicit conversion functions are a C++0x extension}} +}; + +void test_explicit_bool(ExplicitConvToBool ecb) { + bool b1(ecb); // okay + bool b2 = ecb; // expected-error{{incompatible type initializing 'struct ExplicitConvToBool', expected 'bool'}} + accepts_bool(ecb); // expected-error{{no matching function for call to}} +} + +void test_explicit_conv_to_ref(ExplicitConvToRef ecr) { + int& i1 = ecr; // expected-error{{non-const lvalue reference to type 'int' cannot be initialized with a value of type 'struct ExplicitConvToRef'}} + int& i2(ecr); // okay +} + +struct A { }; +struct B { }; +struct C { + explicit operator A&(); // expected-warning{{explicit conversion functions are a C++0x extension}} + operator B&(); +}; + +void test_copy_init_conversions(C c) { + A &a = c; // expected-error{{non-const lvalue reference to type 'struct A' cannot be initialized with a value of type 'struct C'}} + B &b = b; // okay +} + diff --git a/test/SemaCXX/converting-constructor.cpp b/test/SemaCXX/converting-constructor.cpp new file mode 100644 index 000000000000..59b793e3f28c --- /dev/null +++ b/test/SemaCXX/converting-constructor.cpp @@ -0,0 +1,40 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class Z { }; + +class Y { +public: + Y(const Z&); +}; + +class X { +public: + X(int); + X(const Y&); +}; + +void f(X); // expected-note{{candidate function}} + +void g(short s, Y y, Z z) { + f(s); + f(1.0f); + f(y); + f(z); // expected-error{{no matching function}} +} + + +class FromShort { +public: + FromShort(short s); +}; + +class FromShortExplicitly { +public: + explicit FromShortExplicitly(short s); +}; + +void explicit_constructor(short s) { + FromShort fs1(s); + FromShort fs2 = s; + FromShortExplicitly fse1(s); + FromShortExplicitly fse2 = s; // expected-error{{error: cannot initialize 'fse2' with an lvalue of type 'short'}} +} diff --git a/test/SemaCXX/copy-assignment.cpp b/test/SemaCXX/copy-assignment.cpp new file mode 100644 index 000000000000..6e5012f5a7a1 --- /dev/null +++ b/test/SemaCXX/copy-assignment.cpp @@ -0,0 +1,99 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct A { +}; + +struct ConvertibleToA { + operator A(); +}; + +struct ConvertibleToConstA { + operator const A(); +}; + +struct B { + B& operator=(B&); +}; + +struct ConvertibleToB { + operator B(); +}; + +struct ConvertibleToBref { + operator B&(); +}; + +struct ConvertibleToConstB { + operator const B(); +}; + +struct ConvertibleToConstBref { + operator const B&(); +}; + +struct C { + int operator=(int); // expected-note{{candidate function}} + long operator=(long); // expected-note{{candidate function}} + int operator+=(int); // expected-note{{candidate function}} + int operator+=(long); // expected-note{{candidate function}} +}; + +struct D { + D& operator+=(const D &); +}; + +struct ConvertibleToInt { + operator int(); +}; + +void test() { + A a, na; + const A constA; + ConvertibleToA convertibleToA; + ConvertibleToConstA convertibleToConstA; + + B b, nb; + const B constB; + ConvertibleToB convertibleToB; + ConvertibleToBref convertibleToBref; + ConvertibleToConstB convertibleToConstB; + ConvertibleToConstBref convertibleToConstBref; + + C c, nc; + const C constC; + + D d, nd; + const D constD; + + ConvertibleToInt convertibleToInt; + + na = a; + na = constA; + na = convertibleToA; + na = convertibleToConstA; + na += a; // expected-error{{no viable overloaded '+='}} + + nb = b; + nb = constB; // expected-error{{no viable overloaded '='}} + nb = convertibleToB; // expected-error{{no viable overloaded '='}} + nb = convertibleToBref; + nb = convertibleToConstB; // expected-error{{no viable overloaded '='}} + nb = convertibleToConstBref; // expected-error{{no viable overloaded '='}} + + nc = c; + nc = constC; + nc = 1; + nc = 1L; + nc = 1.0; // expected-error{{use of overloaded operator '=' is ambiguous}} + nc += 1; + nc += 1L; + nc += 1.0; // expected-error{{use of overloaded operator '+=' is ambiguous}} + + nd = d; + nd += d; + nd += constD; + + int i; + i = convertibleToInt; + i = a; // expected-error{{incompatible type assigning 'struct A', expected 'int'}} +} + diff --git a/test/SemaCXX/copy-initialization.cpp b/test/SemaCXX/copy-initialization.cpp new file mode 100644 index 000000000000..5b1fbaa46052 --- /dev/null +++ b/test/SemaCXX/copy-initialization.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class X { +public: + explicit X(const X&); + X(int*); // expected-note{{candidate function}} + explicit X(float*); +}; + +class Y : public X { }; + +void f(Y y, int *ip, float *fp) { + X x1 = y; // expected-error{{no matching constructor for initialization of 'x1'; candidate is:}} + X x2 = 0; + X x3 = ip; + X x4 = fp; // expected-error{{cannot initialize 'x4' with an lvalue of type 'float *'}} +} + +struct foo { + void bar(); +}; + +// PR3600 +void test(const foo *P) { P->bar(); } // expected-error{{cannot initialize object parameter of type 'struct foo' with an expression of type 'struct foo const'}} diff --git a/test/SemaCXX/dcl_ambig_res.cpp b/test/SemaCXX/dcl_ambig_res.cpp new file mode 100644 index 000000000000..57bf4095afd0 --- /dev/null +++ b/test/SemaCXX/dcl_ambig_res.cpp @@ -0,0 +1,66 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +// [dcl.ambig.res]p1: +struct S { + S(int); + void bar(); +}; + +int returns_an_int(); + +void foo(double a) +{ + S w(int(a)); // expected-warning{{disambiguated}} + w(17); + S x(int()); // expected-warning{{disambiguated}} + x(&returns_an_int); + S y((int)a); + y.bar(); + S z = int(a); + z.bar(); +} + +// [dcl.ambig.res]p3: +char *p; +void *operator new(__SIZE_TYPE__, int); +void foo3() { + const int x = 63; + new (int(*p)) int; //new-placement expression + new (int(*[x])); //new type-id +} + +// [dcl.ambig.res]p4: +template <class T> // expected-note{{here}} +struct S4 { + T *p; +}; +S4<int()> x; //type-id +S4<int(1)> y; // expected-error{{must be a type}} + +// [dcl.ambig.res]p5: +void foo5() +{ + (void)sizeof(int(1)); //expression + // FIXME: should we make this an error rather than a warning? + // (It affects SFINAE) + (void)sizeof(int()); // expected-warning{{function type}} +} + +// [dcl.ambig.res]p6: +void foo6() +{ + (void)(int(1)); //expression + (void)(int())1; // expected-error{{used type}} +} + +// [dcl.ambig.res]p7: +class C7 { }; +void f7(int(C7)) { } // expected-note{{candidate}} +int g7(C7); +void foo7() { + f7(1); // expected-error{{no matching function}} + f7(g7); //OK +} + +void h7(int *(C7[10])) { } // expected-note{{previous}} +void h7(int *(*_fp)(C7 _parm[10])) { } // expected-error{{redefinition}} diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp new file mode 100644 index 000000000000..10c15ccc9061 --- /dev/null +++ b/test/SemaCXX/dcl_init_aggr.cpp @@ -0,0 +1,122 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +// C++ [dcl.init.aggr]p2 +struct A { + int x; + struct B { + int i; + int j; + } b; +} a1 = { 1, { 2, 3 } }; + +struct NonAggregate { + NonAggregate(); + + int a, b; +}; +NonAggregate non_aggregate_test = { 1, 2 }; // expected-error{{initialization of non-aggregate type 'struct NonAggregate' with an initializer list}} + +NonAggregate non_aggregate_test2[2] = { { 1, 2 }, { 3, 4 } }; // expected-error 2 {{initialization of non-aggregate type 'struct NonAggregate' with an initializer list}} + + +// C++ [dcl.init.aggr]p3 +A a_init = A(); + +// C++ [dcl.init.aggr]p4 +int x[] = { 1, 3, 5 }; +int x_sizecheck[(sizeof(x) / sizeof(int)) == 3? 1 : -1]; +int x2[] = { }; // expected-warning{{zero size arrays are an extension}} + +// C++ [dcl.init.aggr]p5 +struct StaticMemberTest { + int i; + static int s; + int *j; +} smt = { 1, &smt.i }; + +// C++ [dcl.init.aggr]p6 +char cv[4] = { 'a', 's', 'd', 'f', 0 }; // expected-error{{excess elements in array initializer}} + +// C++ [dcl.init.aggr]p7 +struct TooFew { int a; char* b; int c; }; +TooFew too_few = { 1, "asdf" }; // okay + +struct NoDefaultConstructor { // expected-note 5 {{candidate function}} + NoDefaultConstructor(int); // expected-note 5 {{candidate function}} +}; +struct TooFewError { + int a; + NoDefaultConstructor nodef; +}; +TooFewError too_few_okay = { 1, 1 }; +TooFewError too_few_error = { 1 }; // expected-error{{no matching constructor}} + +TooFewError too_few_okay2[2] = { 1, 1 }; +TooFewError too_few_error2[2] = { 1 }; // expected-error{{no matching constructor}} + +NoDefaultConstructor too_few_error3[3] = { }; // expected-error 3 {{no matching constructor}} + +// C++ [dcl.init.aggr]p8 +struct Empty { }; +struct EmptyTest { + Empty s; + int i; +} empty_test = { { }, 3 }; + +EmptyTest empty_test2 = { 3 }; // expected-error{{initializer for aggregate with no elements requires explicit braces}} + +struct NonEmpty { + int a; + Empty empty; +}; +struct NonEmptyTest { + NonEmpty a, b; +} non_empty_test = { { }, { } }; + +// C++ [dcl.init.aggr]p9 +struct HasReference { + int i; + int &j; // expected-note{{uninitialized reference member is here}} +}; +int global_int; +HasReference r1 = { 1, global_int }; +HasReference r2 = { 1 } ; // expected-error{{initialization leaves reference member of type 'int &' uninitialized}} + +// C++ [dcl.init.aggr]p10 +// Note: the behavior here is identical to C +int xs[2][2] = { 3, 1, 4, 2 }; +float y[4][3] = { { 1 }, { 2 }, { 3 }, { 4 } }; + +// C++ [dcl.init.aggr]p11 +// Note: the behavior here is identical to C +float y2[4][3] = { { 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 } }; +float same_as_y2[4][3] = { 1, 3, 5, 2, 4, 6, 3, 5, 7 }; + +// C++ [dcl.init.aggr]p12 +struct A2 { + int i; + operator int *(); +}; +struct B2 { + A2 a1, a2; + int *z; +}; +struct C2 { + operator A2(); +}; +struct D2 { + operator int(); +}; +A2 a2; +C2 c2; +D2 d2; +B2 b2 = { 4, a2, a2 }; +B2 b2_2 = { 4, d2, 0 }; +B2 b2_3 = { c2, a2, a2 }; + +// C++ [dcl.init.aggr]p15: +union u { int a; char* b; }; +u u1 = { 1 }; +u u2 = u1; +u u3 = 1; // expected-error{{cannot initialize 'u3' with an rvalue of type 'int'}} +u u4 = { 0, "asdf" }; // expected-error{{excess elements in union initializer}} +u u5 = { "asdf" }; // expected-error{{incompatible type initializing 'char const [5]', expected 'int'}} diff --git a/test/SemaCXX/decl-expr-ambiguity.cpp b/test/SemaCXX/decl-expr-ambiguity.cpp new file mode 100644 index 000000000000..bff333464b91 --- /dev/null +++ b/test/SemaCXX/decl-expr-ambiguity.cpp @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic-errors %s + +void f() { + int a; + struct S { int m; }; + typedef S *T; + + // Expressions. + T(a)->m = 7; + int(a)++; // expected-error {{expression is not assignable}} + __extension__ int(a)++; // expected-error {{expression is not assignable}} + __typeof(int)(a,5)<<a; // expected-error {{function-style cast to a builtin type can only take one argument}} + void(a), ++a; // expected-warning {{expression result unused}} + if (int(a)+1) {} + for (int(a)+1;;) {} + a = sizeof(int()+1); + a = sizeof(int(1)); + typeof(int()+1) a2; // expected-error {{extension used}} + (int(1)); // expected-warning {{expression result unused}} + + // type-id + (int())1; // expected-error {{used type 'int (void)' where arithmetic or pointer type is required}} + + // Declarations. + int fd(T(a)); // expected-warning {{parentheses were disambiguated as a function declarator}} + T(*d)(int(p)); // expected-warning {{parentheses were disambiguated as a function declarator}} expected-note {{previous definition is here}} + T(d)[5]; // expected-error {{redefinition of 'd'}} + typeof(int[])(f) = { 1, 2 }; // expected-error {{extension used}} + void(b)(int); + int(d2) __attribute__(()); + if (int(a)=1) {} + int(d3(int())); +} + +class C { }; +void fn(int(C)) { } // void fn(int(*fp)(C c)) { } expected-note{{candidate function}} + // not: void fn(int C); +int g(C); + +void foo() { + fn(1); // expected-error {{no matching function}} + fn(g); // OK +} diff --git a/test/SemaCXX/default1.cpp b/test/SemaCXX/default1.cpp new file mode 100644 index 000000000000..be264ad62b13 --- /dev/null +++ b/test/SemaCXX/default1.cpp @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s +void f(int i); +void f(int i = 0); // expected-note {{previous definition is here}} +void f(int i = 17); // expected-error {{redefinition of default argument}} + + +void g(int i, int j, int k = 3); +void g(int i, int j = 2, int k); +void g(int i = 1, int j, int k); + +void h(int i, int j = 2, int k = 3, + int l, // expected-error {{missing default argument on parameter 'l'}} + int, // expected-error {{missing default argument on parameter}} + int n);// expected-error {{missing default argument on parameter 'n'}} + +struct S { } s; +void i(int = s) { } // expected-error {{incompatible type}} + +struct X { + X(int); +}; + +void j(X x = 17); + +struct Y { + explicit Y(int); +}; + +void k(Y y = 17); // expected-error{{cannot initialize 'y' with an rvalue of type 'int'}} + +void kk(Y = 17); // expected-error{{cannot initialize a value of type 'struct Y' with an rvalue of type 'int'}} diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp new file mode 100644 index 000000000000..f99e45415dc4 --- /dev/null +++ b/test/SemaCXX/default2.cpp @@ -0,0 +1,123 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f(int i, int j, int k = 3); +void f(int i, int j, int k); +void f(int i, int j = 2, int k); +void f(int i, int j, int k); +void f(int i = 1, int j, int k); +void f(int i, int j, int k); + +void i() +{ + f(); + f(0); + f(0, 1); + f(0, 1, 2); +} + + +int f1(int i, int i, int j) { // expected-error {{redefinition of parameter 'i'}} + i = 17; + return j; +} + +int x; +void g(int x, int y = x); // expected-error {{default argument references parameter 'x'}} + +void h() +{ + int i; + extern void h2(int x = sizeof(i)); // expected-error {{default argument references local variable 'i' of enclosing function}} +} + +void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}} + +void nondecl(int (*f)(int x = 5)) // {expected-error {{default arguments can only be specified}}} +{ + void (*f2)(int = 17) // {expected-error {{default arguments can only be specified}}} + = (void (*)(int = 42))f; // {expected-error {{default arguments can only be specified}}} +} + +class X { + void f(X* x = this); // expected-error{{invalid use of 'this' outside of a nonstatic member function}} + + void g() { + int f(X* x = this); // expected-error{{default argument references 'this'}} + } +}; + +// C++ [dcl.fct.default]p6 +class C { + static int x; + void f(int i = 3); // expected-note{{previous definition is here}} + void g(int i, int j = x); + + void h(); +}; +void C::f(int i = 3) // expected-error{{redefinition of default argument}} +{ } + +void C::g(int i = 88, int j) {} + +void C::h() { + g(); // okay +} + +// C++ [dcl.fct.default]p9 +struct Y { + int a; + int mem1(int i = a); // expected-error{{invalid use of nonstatic data member 'a'}} + int mem2(int i = b); // OK; use Y::b + int mem3(int i); + int mem4(int i); + + struct Nested { + int mem5(int i = b, // OK; use Y::b + int j = c, // OK; use Y::Nested::c + int k = j, // expected-error{{default argument references parameter 'j'}} + int l = a, // expected-error{{invalid use of nonstatic data member 'a'}} + Nested* self = this, // expected-error{{invalid use of 'this' outside of a nonstatic member function}} + int m); // expected-error{{missing default argument on parameter 'm'}} + static int c; + }; + + static int b; + + int (*f)(int = 17); // expected-error{{default arguments can only be specified for parameters in a function declaration}} + + void mem8(int (*fp)(int) = (int (*)(int = 17))0); // expected-error{{default arguments can only be specified for parameters in a function declaration}} +}; + +int Y::mem3(int i = b) { return i; } // OK; use X::b + +int Y::mem4(int i = a) // expected-error{{invalid use of nonstatic data member 'a'}} +{ return i; } + + +// Try to verify that default arguments interact properly with copy +// constructors. +class Z { +public: + Z(Z&, int i = 17); // expected-note 2 {{candidate function}} + + void f(Z& z) { + Z z2; // expected-error{{no matching constructor for initialization}} + Z z3(z); + } + + void test_Z(const Z& z) { + Z z2(z); // expected-error{{no matching constructor for initialization of 'z2'}} + } +}; + +void test_Z(const Z& z) { + Z z2(z); // expected-error{{no matching constructor for initialization of 'z2'}} +} + +struct ZZ { + void f(ZZ z = g()); // expected-error{{no matching constructor for initialization}} + + static ZZ g(int = 17); + + ZZ(ZZ&, int = 17); // expected-note{{candidate function}} +}; diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp new file mode 100644 index 000000000000..8064ed349b08 --- /dev/null +++ b/test/SemaCXX/deleted-function.cpp @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s + +int i = delete; // expected-error {{only functions can have deleted definitions}} + +void fn() = delete; // expected-note {{candidate function has been explicitly deleted}} + +void fn2(); // expected-note {{previous declaration is here}} +void fn2() = delete; // expected-error {{deleted definition must be first declaration}} + +void fn3() = delete; +void fn3() { + // FIXME: This definition should be invalid. +} + +void ov(int) {} // expected-note {{candidate function}} +void ov(double) = delete; // expected-note {{candidate function has been explicitly deleted}} + +struct WithDel { + WithDel() = delete; // expected-note {{candidate function has been explicitly deleted}} + void fn() = delete; // expected-note {{function has been explicitly marked deleted here}} + operator int() = delete; + void operator +(int) = delete; + + int i = delete; // expected-error {{only functions can have deleted definitions}} +}; + +void test() { + fn(); // expected-error {{call to deleted function 'fn'}} + ov(1); + ov(1.0); // expected-error {{call to deleted function 'ov'}} + + WithDel dd; // expected-error {{call to deleted constructor of 'dd'}} + WithDel *d = 0; + d->fn(); // expected-error {{attempt to use a deleted function}} + int i = *d; // expected-error {{incompatible type initializing}} +} diff --git a/test/SemaCXX/dependent-types.cpp b/test/SemaCXX/dependent-types.cpp new file mode 100644 index 000000000000..b2a5c45787c9 --- /dev/null +++ b/test/SemaCXX/dependent-types.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +template<typename T, int Size> void f() { + T x1; + T* x2; + T& x3; // expected-error{{declaration of reference variable 'x3' requires an initializer}} + T x4[]; // expected-error{{variable has incomplete type 'T []'}} + T x5[Size]; + int x6[Size]; +} diff --git a/test/SemaCXX/derived-to-base-ambig.cpp b/test/SemaCXX/derived-to-base-ambig.cpp new file mode 100644 index 000000000000..e15ddde9d91f --- /dev/null +++ b/test/SemaCXX/derived-to-base-ambig.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class A { }; +class B : public A { }; +class C : public A { }; +class D : public B, public C { }; + +void f(D* d) { + A* a; + a = d; // expected-error{{ambiguous conversion from derived class 'class D' to base class 'class A'}} expected-error{{incompatible type assigning 'class D *', expected 'class A *'}} +} + +class Object2 { }; +class A2 : public Object2 { }; +class B2 : public virtual A2 { }; +class C2 : virtual public A2 { }; +class D2 : public B2, public C2 { }; +class E2 : public D2, public C2, public virtual A2 { }; +class F2 : public E2, public A2 { }; + +void g(E2* e2, F2* f2) { + Object2* o2; + o2 = e2; + o2 = f2; // expected-error{{ambiguous conversion from derived class 'class F2' to base class 'class Object2'}} expected-error{{incompatible type assigning 'class F2 *', expected 'class Object2 *'}} +} + +// Test that ambiguous/inaccessibility checking does not trigger too +// early, because it should not apply during overload resolution. +void overload_okay(Object2*); +void overload_okay(E2*); + +void overload_call(F2* f2) { + overload_okay(f2); +} diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp new file mode 100644 index 000000000000..f544db0b1b6e --- /dev/null +++ b/test/SemaCXX/destructor.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class A { +public: + ~A(); +}; + +class B { +public: + ~B() { } +}; + +class C { +public: + (~C)() { } +}; + +struct D { + static void ~D(int, ...) const { } // \ + // expected-error{{type qualifier is not allowed on this function}} \ + // expected-error{{destructor cannot be declared 'static'}} \ + // expected-error{{destructor cannot have any parameters}} \ + // expected-error{{destructor cannot be variadic}} +}; + +struct D2 { + void ~D2() { } // \ + // expected-error{{destructor cannot have a return type}} +}; + + +struct E; + +typedef E E_typedef; +struct E { + ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'struct E') of the class name}} +}; + +struct F { + (~F)(); // expected-note {{previous declaration is here}} + ~F(); // expected-error {{destructor cannot be redeclared}} +}; + +~; // expected-error {{expected class name}} +~undef(); // expected-error {{expected class name}} +~F(){} // expected-error {{destructor must be a non-static member function}} + +struct G { + ~G(); +}; + +G::~G() { } + +// <rdar://problem/6841210> +struct H { + ~H(void) { } +}; diff --git a/test/SemaCXX/direct-initializer.cpp b/test/SemaCXX/direct-initializer.cpp new file mode 100644 index 000000000000..149b65c8d71d --- /dev/null +++ b/test/SemaCXX/direct-initializer.cpp @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int x(1); +int (x2)(1); + +void f() { + int x(1); + int (x2)(1); + for (int x(1);;) {} +} + +class Y { + explicit Y(float); +}; + +class X { // expected-note{{candidate function}} +public: + explicit X(int); // expected-note{{candidate function}} + X(float, float, float); // expected-note{{candidate function}} + X(float, Y); // expected-note{{candidate function}} +}; + +class Z { +public: + Z(int); +}; + +void g() { + X x1(5); + X x2(1.0, 3, 4.2); + X x3(1.0, 1.0); // expected-error{{no matching constructor for initialization of 'x3'; candidates are:}} + Y y(1.0); + X x4(3.14, y); + + Z z; // expected-error{{no matching constructor for initialization of 'z'}} +} diff --git a/test/SemaCXX/do-while-scope.cpp b/test/SemaCXX/do-while-scope.cpp new file mode 100644 index 000000000000..4e4a48325c1c --- /dev/null +++ b/test/SemaCXX/do-while-scope.cpp @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void test() { + int x; + do + int x; + while (1); +} diff --git a/test/SemaCXX/dynamic-cast.cpp b/test/SemaCXX/dynamic-cast.cpp new file mode 100644 index 000000000000..42c5e0132a82 --- /dev/null +++ b/test/SemaCXX/dynamic-cast.cpp @@ -0,0 +1,74 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A {}; +struct B : A {}; +struct C : B {}; + +struct D : private A {}; +struct E : A {}; +struct F : B, E {}; + +struct Incomplete; // expected-note 2 {{forward declaration of 'struct Incomplete'}} + +struct Poly +{ + virtual void f(); +}; + +struct PolyDerived : Poly +{ +}; + +void basic_bad() +{ + // ptr -> nonptr + (void)dynamic_cast<A>((A*)0); // expected-error {{'struct A' is not a reference or pointer}} + // nonptr -> ptr + (void)dynamic_cast<A*>(0); // expected-error {{'int' is not a pointer}} + // ptr -> noncls + (void)dynamic_cast<int*>((A*)0); // expected-error {{'int' is not a class}} + // noncls -> ptr + (void)dynamic_cast<A*>((int*)0); // expected-error {{'int' is not a class}} + // ref -> noncls + (void)dynamic_cast<int&>(*((A*)0)); // expected-error {{'int' is not a class}} + // noncls -> ref + (void)dynamic_cast<A&>(*((int*)0)); // expected-error {{'int' is not a class}} + // ptr -> incomplete + (void)dynamic_cast<Incomplete*>((A*)0); // expected-error {{'struct Incomplete' is an incomplete type}} + // incomplete -> ptr + (void)dynamic_cast<A*>((Incomplete*)0); // expected-error {{'struct Incomplete' is an incomplete type}} +} + +void same() +{ + (void)dynamic_cast<A*>((A*)0); + (void)dynamic_cast<A&>(*((A*)0)); +} + +void up() +{ + (void)dynamic_cast<A*>((B*)0); + (void)dynamic_cast<A&>(*((B*)0)); + (void)dynamic_cast<A*>((C*)0); + (void)dynamic_cast<A&>(*((C*)0)); + + // Inaccessible + //(void)dynamic_cast<A*>((D*)0); + //(void)dynamic_cast<A&>(*((D*)0)); + + // Ambiguous + (void)dynamic_cast<A*>((F*)0); // expected-error {{ambiguous conversion from derived class 'struct F' to base class 'struct A':\n struct F -> struct B -> struct A\n struct F -> struct E -> struct A}} + (void)dynamic_cast<A&>(*((F*)0)); // expected-error {{ambiguous conversion from derived class 'struct F' to base class 'struct A':\n struct F -> struct B -> struct A\n struct F -> struct E -> struct A}} +} + +void poly() +{ + (void)dynamic_cast<A*>((Poly*)0); + (void)dynamic_cast<A&>(*((Poly*)0)); + (void)dynamic_cast<A*>((PolyDerived*)0); + (void)dynamic_cast<A&>(*((PolyDerived*)0)); + + // Not polymorphic source + (void)dynamic_cast<Poly*>((A*)0); // expected-error {{'struct A' is not polymorphic}} + (void)dynamic_cast<PolyDerived&>(*((A*)0)); // expected-error {{'struct A' is not polymorphic}} +} diff --git a/test/SemaCXX/elaborated-type-specifier.cpp b/test/SemaCXX/elaborated-type-specifier.cpp new file mode 100644 index 000000000000..70478e0f32c4 --- /dev/null +++ b/test/SemaCXX/elaborated-type-specifier.cpp @@ -0,0 +1,47 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Test the use of elaborated-type-specifiers to inject the names of +// structs (or classes or unions) into an outer scope as described in +// C++ [basic.scope.pdecl]p5. +typedef struct S1 { + union { + struct S2 *x; + struct S3 *y; + }; +} S1; + +bool test_elab(S1 *s1, struct S2 *s2, struct S3 *s3) { + if (s1->x == s2) return true; + if (s1->y == s3) return true; + return false; +} + +namespace NS { + class X { + public: + void test_elab2(struct S4 *s4); + }; + + void X::test_elab2(S4 *s4) { } +} + +void test_X_elab(NS::X x) { + struct S4 *s4 = 0; + x.test_elab2(s4); // expected-error{{incompatible type passing 'struct S4 *', expected 'struct NS::S4 *'}} +} + +namespace NS { + S4 *get_S4(); +} + +void test_S5_scope() { + S4 *s4; // expected-error{{use of undeclared identifier 'S4'}} +} + +int test_funcparam_scope(struct S5 * s5) { + struct S5 { int y; } *s5_2 = 0; + if (s5 == s5_2) return 1; // expected-error {{comparison of distinct pointer types ('struct S5 *' and 'struct S5 *')}} + return 0; +} + + diff --git a/test/SemaCXX/enum.cpp b/test/SemaCXX/enum.cpp new file mode 100644 index 000000000000..9668c84693d3 --- /dev/null +++ b/test/SemaCXX/enum.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s +enum E { + Val1, + Val2 +}; + +int& enumerator_type(int); +float& enumerator_type(E); + +void f() { + E e = Val1; + float& fr = enumerator_type(Val2); +} + +// <rdar://problem/6502934> +typedef enum Foo { + A = 0, + B = 1 +} Foo; + + +void bar() { + Foo myvar = A; + myvar = B; +} + +/// PR3688 +struct s1 { + enum e1 (*bar)(void); // expected-error{{ISO C++ forbids forward references to 'enum' types}} expected-note{{forward declaration of 'enum s1::e1'}} +}; + +enum e1 { YES, NO }; + +static enum e1 badfunc(struct s1 *q) { + return q->bar(); // expected-error{{return type of called function ('enum s1::e1') is incomplete}} +} + +enum e2; // expected-error{{ISO C++ forbids forward references to 'enum' types}} diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp new file mode 100644 index 000000000000..ea02aac4915f --- /dev/null +++ b/test/SemaCXX/exception-spec.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Straight from the standard: +// Plain function with spec +void f() throw(int); +// Pointer to function with spec +void (*fp)() throw (int); +// Function taking reference to function with spec +void g(void pfa() throw(int)); +// Typedef for pointer to function with spec +typedef int (*pf)() throw(int); // expected-error {{specifications are not allowed in typedefs}} + +// Some more: +// Function returning function with spec +void (*h())() throw(int); +// Ultimate parser thrill: function with spec returning function with spec and +// taking pointer to function with spec. +// The actual function throws int, the return type double, the argument float. +void (*i() throw(int))(void (*)() throw(float)) throw(double); +// Pointer to pointer to function taking function with spec +void (**k)(void pfa() throw(int)); // no-error +// Pointer to pointer to function with spec +void (**j)() throw(int); // expected-error {{not allowed beyond a single}} +// Pointer to function returning pointer to pointer to function with spec +void (**(*h())())() throw(int); // expected-error {{not allowed beyond a single}} + +struct Incomplete; + +// Exception spec must not have incomplete types, or pointers to them, except +// void. +void ic1() throw(void); // expected-error {{incomplete type 'void' is not allowed in exception specification}} +void ic2() throw(Incomplete); // expected-error {{incomplete type 'struct Incomplete' is not allowed in exception specification}} +void ic3() throw(void*); +void ic4() throw(Incomplete*); // expected-error {{pointer to incomplete type 'struct Incomplete' is not allowed in exception specification}} +void ic5() throw(Incomplete&); // expected-error {{reference to incomplete type 'struct Incomplete' is not allowed in exception specification}} diff --git a/test/SemaCXX/exceptions.cpp b/test/SemaCXX/exceptions.cpp new file mode 100644 index 000000000000..5882b9cb7083 --- /dev/null +++ b/test/SemaCXX/exceptions.cpp @@ -0,0 +1,99 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A; // expected-note 4 {{forward declaration of 'struct A'}} + +struct Abstract { virtual void f() = 0; }; // expected-note {{pure virtual function 'f'}} + +void trys() { + try { + } catch(int i) { // expected-note {{previous definition}} + int j = i; + int i; // expected-error {{redefinition of 'i'}} + } catch(float i) { + } catch(void v) { // expected-error {{cannot catch incomplete type 'void'}} + } catch(A a) { // expected-error {{cannot catch incomplete type 'struct A'}} + } catch(A *a) { // expected-error {{cannot catch pointer to incomplete type 'struct A'}} + } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'struct A'}} + } catch(Abstract) { // expected-error {{variable type 'Abstract' is an abstract class}} + } catch(...) { + int j = i; // expected-error {{use of undeclared identifier 'i'}} + } + + try { + } catch(...) { // expected-error {{catch-all handler must come last}} + } catch(int) { + } +} + +void throws() { + throw; + throw 0; + throw throw; // expected-error {{cannot throw object of incomplete type 'void'}} + throw (A*)0; // expected-error {{cannot throw pointer to object of incomplete type 'struct A'}} +} + +void jumps() { +l1: + goto l5; + goto l4; // expected-error {{illegal goto into protected scope}} + goto l3; // expected-error {{illegal goto into protected scope}} + goto l2; // expected-error {{illegal goto into protected scope}} + goto l1; + try { // expected-note 4 {{jump bypasses initialization of try block}} + l2: + goto l5; + goto l4; // expected-error {{illegal goto into protected scope}} + goto l3; // expected-error {{illegal goto into protected scope}} + goto l2; + goto l1; + } catch(int) { // expected-note 4 {{jump bypasses initialization of catch block}} + l3: + goto l5; + goto l4; // expected-error {{illegal goto into protected scope}} + goto l3; + goto l2; // expected-error {{illegal goto into protected scope}} + goto l1; + } catch(...) { // expected-note 4 {{jump bypasses initialization of catch block}} + l4: + goto l5; + goto l4; + goto l3; // expected-error {{illegal goto into protected scope}} + goto l2; // expected-error {{illegal goto into protected scope}} + goto l1; + } +l5: + goto l5; + goto l4; // expected-error {{illegal goto into protected scope}} + goto l3; // expected-error {{illegal goto into protected scope}} + goto l2; // expected-error {{illegal goto into protected scope}} + goto l1; +} + +struct BadReturn { + BadReturn() try { + } catch(...) { + // Try to hide + try { + } catch(...) { + { + if (0) + return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} + } + } + } + BadReturn(int); +}; + +BadReturn::BadReturn(int) try { +} catch(...) { + // Try to hide + try { + } catch(int) { + return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} + } catch(...) { + { + if (0) + return; // expected-error {{return in the catch of a function try block of a constructor is illegal}} + } + } +} diff --git a/test/SemaCXX/expressions.cpp b/test/SemaCXX/expressions.cpp new file mode 100644 index 000000000000..6a2f30d33e5e --- /dev/null +++ b/test/SemaCXX/expressions.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void choice(int); +int choice(bool); + +void test() { + // Result of ! must be type bool. + int i = choice(!1); +} diff --git a/test/SemaCXX/fntype-decl.cpp b/test/SemaCXX/fntype-decl.cpp new file mode 100644 index 000000000000..ae85ff45353d --- /dev/null +++ b/test/SemaCXX/fntype-decl.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR2942 +typedef void fn(int); +fn f; // expected-note {{previous declaration is here}} + +int g(int x, int y); +int g(int x, int y = 2); + +typedef int g_type(int, int); +g_type g; + +int h(int x) { // expected-note {{previous definition is here}} + return g(x); +} + +float f(int) { } // expected-error{{functions that differ only in their return type cannot be overloaded}} + +int h(int) { } // expected-error{{redefinition of 'h'}} + diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp new file mode 100644 index 000000000000..76e84e5fbe84 --- /dev/null +++ b/test/SemaCXX/friend.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +friend class A; // expected-error {{'friend' used outside of class}} +void f() { friend class A; } // expected-error {{'friend' used outside of class}} +class C { friend class A; }; +class D { void f() { friend class A; } }; // expected-error {{'friend' used outside of class}} diff --git a/test/SemaCXX/function-redecl.cpp b/test/SemaCXX/function-redecl.cpp new file mode 100644 index 000000000000..9f6783731d33 --- /dev/null +++ b/test/SemaCXX/function-redecl.cpp @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int foo(int); + +namespace N { + void f1() { + void foo(int); // okay + } + + // FIXME: we shouldn't even need this declaration to detect errors + // below. + void foo(int); // expected-note{{previous declaration is here}} + + void f2() { + int foo(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} + + { + int foo; + { + // FIXME: should diagnose this because it's incompatible with + // N::foo. However, name lookup isn't properly "skipping" the + // "int foo" above. + float foo(int); + } + } + } +} diff --git a/test/SemaCXX/function-type-qual.cpp b/test/SemaCXX/function-type-qual.cpp new file mode 100644 index 000000000000..f1d5aac7fc99 --- /dev/null +++ b/test/SemaCXX/function-type-qual.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() const; // expected-error {{type qualifier is not allowed on this function}} + +typedef void cfn() const; +cfn f2; // expected-error {{a qualified function type cannot be used to declare a nonmember function or a static member function}} + +class C { + void f() const; + cfn f2; + static void f3() const; // expected-error {{type qualifier is not allowed on this function}} + static cfn f4; // expected-error {{a qualified function type cannot be used to declare a nonmember function or a static member function}} + + void m1() { + x = 0; + } + + void m2() const { + x = 0; // expected-error {{read-only variable is not assignable}} + } + + int x; +}; diff --git a/test/SemaCXX/functional-cast.cpp b/test/SemaCXX/functional-cast.cpp new file mode 100644 index 000000000000..0be7ddb53ae8 --- /dev/null +++ b/test/SemaCXX/functional-cast.cpp @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct SimpleValueInit { + int i; +}; + +struct InitViaConstructor { + InitViaConstructor(int i = 7); +}; + +// FIXME: error messages for implicitly-declared special member +// function candidates are very poor +struct NoValueInit { // expected-note 2 {{candidate function}} + NoValueInit(int i, int j); // expected-note 2 {{candidate function}} +}; + +void test_cxx_functional_value_init() { + (void)SimpleValueInit(); + (void)InitViaConstructor(); + (void)NoValueInit(); // expected-error{{no matching constructor for initialization}} +} + +void test_cxx_function_cast_multi() { + (void)NoValueInit(0, 0); + (void)NoValueInit(0, 0, 0); // expected-error{{no matching constructor for initialization}} + (void)int(1, 2); // expected-error{{function-style cast to a builtin type can only take one argument}} +} diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp new file mode 100644 index 000000000000..32d04e2da40b --- /dev/null +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// C++-specific tests for integral constant expressions. + +const int c = 10; +int ar[c]; diff --git a/test/SemaCXX/implicit-int.cpp b/test/SemaCXX/implicit-int.cpp new file mode 100644 index 000000000000..6fa8dd3463d3 --- /dev/null +++ b/test/SemaCXX/implicit-int.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +x; // expected-error{{C++ requires a type specifier for all declarations}} + +f(int y) { return y; } // expected-error{{C++ requires a type specifier for all declarations}} diff --git a/test/SemaCXX/inherit.cpp b/test/SemaCXX/inherit.cpp new file mode 100644 index 000000000000..eaad97cc82a0 --- /dev/null +++ b/test/SemaCXX/inherit.cpp @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class A { }; + +class B1 : A { }; + +class B2 : virtual A { }; + +class B3 : virtual virtual A { }; // expected-error{{duplicate 'virtual' in base specifier}} + +class C : public B1, private B2 { }; + + +class D; // expected-note {{forward declaration of 'class D'}} + +class E : public D { }; // expected-error{{base class has incomplete type}} + +typedef int I; + +class F : public I { }; // expected-error{{base specifier must name a class}} + +union U1 : public A { }; // expected-error{{unions cannot have base classes}} + +union U2 {}; + +class G : public U2 { }; // expected-error{{unions cannot be base classes}} + +typedef G G_copy; +typedef G G_copy_2; +typedef G_copy G_copy_3; + +class H : G_copy, A, G_copy_2, // expected-error{{base class 'G_copy' (aka 'class G') specified more than once as a direct base class}} + public G_copy_3 { }; // expected-error{{base class 'G_copy' (aka 'class G') specified more than once as a direct base class}} diff --git a/test/SemaCXX/inline.cpp b/test/SemaCXX/inline.cpp new file mode 100644 index 000000000000..7d0505a435ee --- /dev/null +++ b/test/SemaCXX/inline.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Check that we don't allow illegal uses of inline +// (checking C++-only constructs here) +struct c {inline int a;}; // expected-error{{'inline' can only appear on functions}} diff --git a/test/SemaCXX/linkage-spec.cpp b/test/SemaCXX/linkage-spec.cpp new file mode 100644 index 000000000000..864953e9f9c2 --- /dev/null +++ b/test/SemaCXX/linkage-spec.cpp @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s +extern "C" { + extern "C" void f(int); +} + +extern "C++" { + extern "C++" int& g(int); + float& g(); +} +double& g(double); + +void test(int x, double d) { + f(x); + float &f1 = g(); + int& i1 = g(x); + double& d1 = g(d); +} + +extern "C" int foo; +extern "C" int foo; + +extern "C" const int bar; +extern "C" int const bar; + +// <rdar://problem/6895431> +extern "C" struct bar d; +extern struct bar e; diff --git a/test/SemaCXX/member-expr-static.cpp b/test/SemaCXX/member-expr-static.cpp new file mode 100644 index 000000000000..b6495a852041 --- /dev/null +++ b/test/SemaCXX/member-expr-static.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef void (*thread_continue_t)(); + +extern "C" { +extern void kernel_thread_start(thread_continue_t continuation); +extern void pure_c(void); +} + +class _IOConfigThread +{ +public: + static void main( void ); +}; + + +void foo( void ) +{ + kernel_thread_start(&_IOConfigThread::main); + kernel_thread_start((thread_continue_t)&_IOConfigThread::main); + kernel_thread_start(&pure_c); +} diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp new file mode 100644 index 000000000000..60ee10df7f6a --- /dev/null +++ b/test/SemaCXX/member-expr.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class X{ +public: + enum E {Enumerator}; + int f(); + static int mem; + static float g(); +}; + +void test(X* xp, X x) { + int i1 = x.f(); + int i2 = xp->f(); + x.E; // expected-error{{cannot refer to type member 'E' with '.'}} + xp->E; // expected-error{{cannot refer to type member 'E' with '->'}} + int i3 = x.Enumerator; + int i4 = xp->Enumerator; + x.mem = 1; + xp->mem = 2; + float f1 = x.g(); + float f2 = xp->g(); +} + +struct A { + int f0; +}; +struct B { + A *f0(); +}; +int f0(B *b) { + return b->f0->f0; // expected-error{{member reference base type 'struct A *(void)' is not a structure or union}} \ + // expected-note{{perhaps you meant to call this function}} +} diff --git a/test/SemaCXX/member-location.cpp b/test/SemaCXX/member-location.cpp new file mode 100644 index 000000000000..cb53ae15123d --- /dev/null +++ b/test/SemaCXX/member-location.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR4103: Make sure we have a location for the error +class A { float a(int *); int b(); }; +int A::b() { return a(a((int*)0)); } // expected-error {{incompatible type}} + diff --git a/test/SemaCXX/member-name-lookup.cpp b/test/SemaCXX/member-name-lookup.cpp new file mode 100644 index 000000000000..9fcd922ddf7d --- /dev/null +++ b/test/SemaCXX/member-name-lookup.cpp @@ -0,0 +1,148 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct A { + int a; // expected-note 4{{member found by ambiguous name lookup}} + static int b; + static int c; // expected-note 4{{member found by ambiguous name lookup}} + + enum E { enumerator }; + + typedef int type; + + static void f(int); + void f(float); // expected-note 2{{member found by ambiguous name lookup}} + + static void static_f(int); + static void static_f(double); +}; + +struct B : A { + int d; // expected-note 2{{member found by ambiguous name lookup}} + + enum E2 { enumerator2 }; + + enum E3 { enumerator3 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct C : A { + int c; // expected-note 2{{member found by ambiguous name lookup}} + int d; // expected-note 2{{member found by ambiguous name lookup}} + + enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct D : B, C { + void test_lookup(); +}; + +void test_lookup(D d) { + d.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + (void)d.b; // okay + d.c; // expected-error{{member 'c' found in multiple base classes of different types}} + d.d; // expected-error{{member 'd' found in multiple base classes of different types}} + d.f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'struct A'}} + d.static_f(0); // okay + + D::E e = D::enumerator; // okay + D::type t = 0; // okay + + D::E2 e2 = D::enumerator2; // okay + + D::E3 e3; // expected-error{{multiple base classes}} +} + +void D::test_lookup() { + a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + (void)b; // okay + c; // expected-error{{member 'c' found in multiple base classes of different types}} + d; // expected-error{{member 'd' found in multiple base classes of different types}} + f(0); // expected-error{{non-static member 'f' found in multiple base-class subobjects of type 'struct A'}} + static_f(0); // okay + + E e = enumerator; // okay + type t = 0; // okay + + E2 e2 = enumerator2; // okay + + E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} +} + +struct B2 : virtual A { + int d; // expected-note 2{{member found by ambiguous name lookup}} + + enum E2 { enumerator2 }; + + enum E3 { enumerator3 }; // expected-note 2 {{member found by ambiguous name lookup}} +}; + +struct C2 : virtual A { + int c; // expected-note 2{{member found by ambiguous name lookup}} + int d; // expected-note 2{{member found by ambiguous name lookup}} + + enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} +}; + +struct D2 : B2, C2 { + void test_virtual_lookup(); +}; + +struct F : A { }; +struct G : F, D2 { + void test_virtual_lookup(); +}; + +void test_virtual_lookup(D2 d2, G g) { + (void)d2.a; + (void)d2.b; + d2.c; // expected-error{{member 'c' found in multiple base classes of different types}} + d2.d; // expected-error{{member 'd' found in multiple base classes of different types}} + d2.f(0); // okay + d2.static_f(0); // okay + + D2::E e = D2::enumerator; // okay + D2::type t = 0; // okay + + D2::E2 e2 = D2::enumerator2; // okay + + D2::E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} + + g.a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + g.static_f(0); // okay +} + +void D2::test_virtual_lookup() { + (void)a; + (void)b; + c; // expected-error{{member 'c' found in multiple base classes of different types}} + d; // expected-error{{member 'd' found in multiple base classes of different types}} + f(0); // okay + static_f(0); // okay + + E e = enumerator; // okay + type t = 0; // okay + + E2 e2 = enumerator2; // okay + + E3 e3; // expected-error{{member 'E3' found in multiple base classes of different types}} +} + +void G::test_virtual_lookup() { + a; // expected-error{{non-static member 'a' found in multiple base-class subobjects of type 'struct A'}} + static_f(0); // okay +} + + +struct HasMemberType1 { + struct type { }; // expected-note{{member found by ambiguous name lookup}} +}; + +struct HasMemberType2 { + struct type { }; // expected-note{{member found by ambiguous name lookup}} +}; + +struct HasAnotherMemberType : HasMemberType1, HasMemberType2 { + struct type { }; +}; + +struct UsesAmbigMemberType : HasMemberType1, HasMemberType2 { + type t; // expected-error{{member 'type' found in multiple base classes of different types}} +}; diff --git a/test/SemaCXX/member-pointer-size.cpp b/test/SemaCXX/member-pointer-size.cpp new file mode 100644 index 000000000000..f86e72b288cd --- /dev/null +++ b/test/SemaCXX/member-pointer-size.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -triple x86_64-unknown-unknown %s -fsyntax-only -verify && +// RUN: clang-cc -triple i686-unknown-unknown %s -fsyntax-only -verify +#include <stddef.h> + +struct A; + +void f() { + int A::*dataMember; + + int (A::*memberFunction)(); + + typedef int assert1[sizeof(dataMember) == sizeof(ptrdiff_t) ? 1 : -1]; + typedef int assert2[sizeof(memberFunction) == sizeof(ptrdiff_t) * 2 ? 1 : -1]; +} + diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp new file mode 100644 index 000000000000..cfe4f75dd17d --- /dev/null +++ b/test/SemaCXX/member-pointer.cpp @@ -0,0 +1,129 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A {}; +enum B { Dummy }; +namespace C {} +struct D : A {}; +struct E : A {}; +struct F : D, E {}; +struct G : virtual D {}; + +int A::*pdi1; +int (::A::*pdi2); +int (A::*pfi)(int); + +int B::*pbi; // expected-error {{expected a class or namespace}} +int C::*pci; // expected-error {{'pci' does not point into a class}} +void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}} +int& A::*pdr; // expected-error {{'pdr' declared as a pointer to a reference}} + +void f() { + // This requires tentative parsing. + int (A::*pf)(int, int); + + // Implicit conversion to bool. + bool b = pdi1; + b = pfi; + + // Conversion from null pointer constant. + pf = 0; + pf = __null; + + // Conversion to member of derived. + int D::*pdid = pdi1; + pdid = pdi2; + + // Fail conversion due to ambiguity and virtuality. + int F::*pdif = pdi1; // expected-error {{ambiguous conversion from pointer to member of base class 'struct A' to pointer to member of derived class 'struct F'}} expected-error {{incompatible type}} + int G::*pdig = pdi1; // expected-error {{conversion from pointer to member of class 'struct A' to pointer to member of class 'struct G' via virtual base 'struct D' is not allowed}} expected-error {{incompatible type}} + + // Conversion to member of base. + pdi1 = pdid; // expected-error {{incompatible type assigning 'int struct D::*', expected 'int struct A::*'}} +} + +struct TheBase +{ + void d(); +}; + +struct HasMembers : TheBase +{ + int i; + void f(); + + void g(); + void g(int); + static void g(double); +}; + +namespace Fake +{ + int i; + void f(); +} + +void g() { + HasMembers hm; + + int HasMembers::*pmi = &HasMembers::i; + int *pni = &Fake::i; + int *pmii = &hm.i; + + void (HasMembers::*pmf)() = &HasMembers::f; + void (*pnf)() = &Fake::f; + &hm.f; // FIXME: needs diagnostic expected-warning{{result unused}} + + void (HasMembers::*pmgv)() = &HasMembers::g; + void (HasMembers::*pmgi)(int) = &HasMembers::g; + void (*pmgd)(double) = &HasMembers::g; + + void (HasMembers::*pmd)() = &HasMembers::d; +} + +struct Incomplete; + +void h() { + HasMembers hm, *phm = &hm; + + int HasMembers::*pi = &HasMembers::i; + hm.*pi = 0; + int i = phm->*pi; + (void)&(hm.*pi); + (void)&(phm->*pi); + (void)&((&hm)->*pi); // expected-error {{address expression must be an lvalue or a function designator}} + + void (HasMembers::*pf)() = &HasMembers::f; + (hm.*pf)(); + (phm->*pf)(); + + (void)(hm->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct HasMembers'}} + (void)(phm.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct HasMembers *'}} + (void)(i.*pi); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'int'}} + int *ptr; + (void)(ptr->*pi); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'int *'}} + + int A::*pai = 0; + D d, *pd = &d; + (void)(d.*pai); + (void)(pd->*pai); + F f, *ptrf = &f; + (void)(f.*pai); // expected-error {{left hand operand to .* must be a class compatible with the right hand operand, but is 'struct F'}} + (void)(ptrf->*pai); // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct F *'}} + + (void)(hm.*i); // expected-error {{pointer-to-member}} + (void)(phm->*i); // expected-error {{pointer-to-member}} + + Incomplete *inc; + int Incomplete::*pii = 0; + (void)(inc->*pii); // okay +} + +struct OverloadsPtrMem +{ + int operator ->*(const char *); +}; + +void i() { + OverloadsPtrMem m; + int foo = m->*"Awesome!"; +} diff --git a/test/SemaCXX/ms-exception-spec.cpp b/test/SemaCXX/ms-exception-spec.cpp new file mode 100644 index 000000000000..b84ea178e1e2 --- /dev/null +++ b/test/SemaCXX/ms-exception-spec.cpp @@ -0,0 +1,3 @@ +// RUN: clang-cc %s -fsyntax-only -verify -fms-extensions + +void f() throw(...) { } diff --git a/test/SemaCXX/namespace-alias.cpp b/test/SemaCXX/namespace-alias.cpp new file mode 100644 index 000000000000..d5e423848cb5 --- /dev/null +++ b/test/SemaCXX/namespace-alias.cpp @@ -0,0 +1,64 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N { }; + +namespace A = N; + +int B; // expected-note {{previous definition is here}} +namespace B = N; // expected-error {{redefinition of 'B' as different kind of symbol}} + +namespace C { } // expected-note {{previous definition is here}} +namespace C = N; // expected-error {{redefinition of 'C'}} + +int i; +namespace D = i; // expected-error {{expected namespace name}} + +namespace E = N::Foo; // expected-error {{expected namespace name}} + +namespace F { + namespace A { namespace B { } } // expected-note {{candidate found by name lookup is 'F::A::B'}} + namespace B { } // expected-note {{candidate found by name lookup is 'F::B'}} + using namespace A; + namespace D = B; // expected-error {{reference to 'B' is ambiguous}} +} + +namespace G { + namespace B = N; +} + +namespace H { + namespace A1 { } + namespace A2 { } + + // These all point to A1. + namespace B = A1; // expected-note {{previous definition is here}} + namespace B = A1; + namespace C = B; + namespace B = C; + + namespace B = A2; // expected-error {{redefinition of 'B' as different kind of symbol}} +} + +namespace I { + namespace A1 { int i; } + + namespace A2 = A1; +} + +int f() { + return I::A2::i; +} + +namespace J { + namespace A { + namespace B { void func (); } + } + + namespace C = A; + + using namespace C::B; + + void g() { + func(); + } +} diff --git a/test/SemaCXX/namespace.cpp b/test/SemaCXX/namespace.cpp new file mode 100644 index 000000000000..696ea818f657 --- /dev/null +++ b/test/SemaCXX/namespace.cpp @@ -0,0 +1,69 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace A { // expected-note 2 {{previous definition is here}} + int A; + void f() { A = 0; } +} + +void f() { A = 0; } // expected-error {{unexpected namespace name 'A': expected expression}} +int A; // expected-error {{redefinition of 'A' as different kind of symbol}} +class A; // expected-error {{redefinition of 'A' as different kind of symbol}} + +class B {}; // expected-note {{previous definition is here}} + +void C(); // expected-note {{previous definition is here}} +namespace C {} // expected-error {{redefinition of 'C' as different kind of symbol}} + +namespace D { + class D {}; +} + +namespace S1 { + int x; + + namespace S2 { + + namespace S3 { + B x; + } + } +} + +namespace S1 { + void f() { + x = 0; + } + + namespace S2 { + + namespace S3 { + void f() { + x = 0; // expected-error {{no viable overloaded '='}} + } + } + + int y; + } +} + +namespace S1 { + namespace S2 { + namespace S3 { + void f3() { + y = 0; + } + } + } +} + +namespace B {} // expected-error {{redefinition of 'B' as different kind of symbol}} + + +namespace foo { + enum x { + Y + }; +} + +static foo::x test1; // ok + +static foo::X test2; // typo: expected-error {{unknown type name 'X'}} diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp new file mode 100644 index 000000000000..4c3ecee09051 --- /dev/null +++ b/test/SemaCXX/nested-name-spec.cpp @@ -0,0 +1,173 @@ +// RUN: clang-cc -fsyntax-only -std=c++98 -verify %s +namespace A { + struct C { + static int cx; + + static int cx2; + + static int Ag1(); + static int Ag2(); + }; + int ax; + void Af(); +} + +A:: ; // expected-error {{expected unqualified-id}} +::A::ax::undef ex3; // expected-error {{expected a class or namespace}} expected-error {{unknown type name 'undef'}} +A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} expected-error {{unknown type name 'undef2'}} + +int A::C::Ag1() { return 0; } + +static int A::C::Ag2() { return 0; } // expected-error{{'static' can}} + +int A::C::cx = 17; + + +static int A::C::cx2 = 17; // expected-error{{'static' can}} + +class C2 { + void m(); // expected-note{{member declaration nearly matches}} + + void f(const int& parm); // expected-note{{member declaration nearly matches}} + void f(int) const; // expected-note{{member declaration nearly matches}} + void f(float); + + int x; +}; + +void C2::m() const { } // expected-error{{out-of-line definition does not match any declaration in 'C2'}} + +void C2::f(int) { } // expected-error{{out-of-line definition does not match any declaration in 'C2'}} + +void C2::m() { + x = 0; +} + +namespace B { + void ::A::Af() {} // expected-error {{definition or redeclaration of 'Af' not in a namespace enclosing 'A'}} +} + +void f1() { + void A::Af(); // expected-error {{definition or redeclaration of 'Af' not allowed inside a function}} +} + +void f2() { + A:: ; // expected-error {{expected unqualified-id}} + A::C::undef = 0; // expected-error {{no member named 'undef'}} + ::A::C::cx = 0; + int x = ::A::ax = A::C::cx; + x = sizeof(A::C); + x = sizeof(::A::C::cx); +} + +A::C c1; +struct A::C c2; +struct S : public A::C {}; +struct A::undef; // expected-error {{'undef' does not name a tag member in the specified scope}} + +namespace A2 { + typedef int INT; + struct RC; + struct CC { + struct NC; + }; +} + +struct A2::RC { + INT x; +}; + +struct A2::CC::NC { + void m() {} +}; + +void f3() { + N::x = 0; // expected-error {{use of undeclared identifier 'N'}} + int N; + N::x = 0; // expected-error {{expected a class or namespace}} + { int A; A::ax = 0; } + { typedef int A; A::ax = 0; } // expected-error{{expected a class or namespace}} + { int A(); A::ax = 0; } + { typedef A::C A; A::ax = 0; } // expected-error {{no member named 'ax'}} + { typedef A::C A; A::cx = 0; } +} + +// make sure the following doesn't hit any asserts +void f4(undef::C); // expected-error {{use of undeclared identifier 'undef'}} \ + expected-error {{variable has incomplete type 'void'}} + +typedef void C2::f5(int); // expected-error{{typedef declarator cannot be qualified}} + +void f6(int A2::RC::x); // expected-error{{parameter declarator cannot be qualified}} + +int A2::RC::x; // expected-error{{non-static data member defined out-of-line}} + +void A2::CC::NC::m(); // expected-error{{out-of-line declaration of a member must be a definition}} + + +namespace E { + int X = 5; + + namespace Nested { + enum E { + X = 0 + }; + + void f() { + return E::X; // expected-error{{expected a class or namespace}} + } + } +} + + +class Operators { + Operators operator+(const Operators&) const; // expected-note{{member declaration nearly matches}} + operator bool(); +}; + +Operators Operators::operator+(const Operators&) { // expected-error{{out-of-line definition does not match any declaration in 'Operators'}} + Operators ops; + return ops; +} + +Operators Operators::operator+(const Operators&) const { + Operators ops; + return ops; +} + +Operators::operator bool() { + return true; +} + +namespace A { + void g(int&); // expected-note{{member declaration nearly matches}} +} + +void A::f() {} // expected-error{{out-of-line definition does not match any declaration in 'A'}} + +void A::g(const int&) { } // expected-error{{out-of-line definition does not match any declaration in 'A'}} + +struct Struct { }; + +void Struct::f() { } // expected-error{{out-of-line definition does not match any declaration in 'Struct'}} + +void global_func(int); +void global_func2(int); + +namespace N { + void ::global_func(int) { } // expected-error{{definition or redeclaration of 'global_func' cannot name the global scope}} + + void f(); + // FIXME: if we move this to a separate definition of N, things break! +} +void ::global_func2(int) { } // expected-error{{definition or redeclaration of 'global_func2' cannot name the global scope}} + +void N::f() { } // okay + +struct Y; // expected-note{{forward declaration of 'struct Y'}} +Y::foo y; // expected-error{{incomplete type 'struct Y' named in nested name specifier}} \ + // expected-error{{unknown type name 'foo'}} + +X::X() : a(5) { } // expected-error{{use of undeclared identifier 'X'}} \ + // expected-error{{C++ requires a type specifier for all declarations}} \ + // expected-error{{only constructors take base initializers}} diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp new file mode 100644 index 000000000000..f890bf56e36b --- /dev/null +++ b/test/SemaCXX/new-delete.cpp @@ -0,0 +1,97 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stddef.h> + +struct S // expected-note {{candidate}} +{ + S(int, int, double); // expected-note {{candidate}} + S(double, int); // expected-note 2 {{candidate}} + S(float, int); // expected-note 2 {{candidate}} +}; +struct T; // expected-note{{forward declaration of 'struct T'}} +struct U +{ + // A special new, to verify that the global version isn't used. + void* operator new(size_t, S*); // expected-note {{candidate}} +}; +struct V : U +{ +}; + +void* operator new(size_t); // expected-note 2 {{candidate}} +void* operator new(size_t, int*); // expected-note 3 {{candidate}} +void* operator new(size_t, float*); // expected-note 3 {{candidate}} +void* operator new(size_t, S); // expected-note 2 {{candidate}} + +void good_news() +{ + int *pi = new int; + float *pf = new (pi) float(); + pi = new int(1); + pi = new int('c'); + const int *pci = new const int(); + S *ps = new S(1, 2, 3.4); + ps = new (pf) (S)(1, 2, 3.4); + S *(*paps)[2] = new S*[*pi][2]; + ps = new (S[3])(1, 2, 3.4); + typedef int ia4[4]; + ia4 *pai = new (int[3][4]); + pi = ::new int; + U *pu = new (ps) U; + // FIXME: Inherited functions are not looked up currently. + //V *pv = new (ps) V; + + pi = new (S(1.0f, 2)) int; +} + +struct abstract { + virtual ~abstract() = 0; +}; + +void bad_news(int *ip) +{ + int i = 1; + (void)new; // expected-error {{missing type specifier}} + (void)new 4; // expected-error {{missing type specifier}} + (void)new () int; // expected-error {{expected expression}} + (void)new int[1.1]; // expected-error {{array size expression must have integral or enumerated type, not 'double'}} + (void)new int[1][i]; // expected-error {{only the first dimension}} + (void)new (int[1][i]); // expected-error {{only the first dimension}} + (void)new int(*(S*)0); // expected-error {{incompatible type initializing}} + (void)new int(1, 2); // expected-error {{initializer of a builtin type can only take one argument}} + (void)new S(1); // expected-error {{no matching constructor}} + (void)new S(1, 1); // expected-error {{call to constructor of 'S' is ambiguous}} + (void)new const int; // expected-error {{must provide an initializer}} + (void)new float*(ip); // expected-error {{incompatible type initializing 'int *', expected 'float *'}} + // Undefined, but clang should reject it directly. + (void)new int[-1]; // expected-error {{array size is negative}} + (void)new int[*(S*)0]; // expected-error {{array size expression must have integral or enumerated type, not 'struct S'}} + (void)::S::new int; // expected-error {{expected unqualified-id}} + (void)new (0, 0) int; // expected-error {{no matching function for call to 'operator new'}} + (void)new (0L) int; // expected-error {{call to 'operator new' is ambiguous}} + // This must fail, because the member version shouldn't be found. + (void)::new ((S*)0) U; // expected-error {{no matching function for call to 'operator new'}} + // This must fail, because any member version hides all global versions. + (void)new U; // expected-error {{no matching function for call to 'operator new'}} + (void)new (int[]); // expected-error {{array size must be specified in new expressions}} + (void)new int&; // expected-error {{cannot allocate reference type 'int &' with new}} + // Some lacking cases due to lack of sema support. +} + +void good_deletes() +{ + delete (int*)0; + delete [](int*)0; + delete (S*)0; + ::delete (int*)0; +} + +void bad_deletes() +{ + delete 0; // expected-error {{cannot delete expression of type 'int'}} + delete [0] (int*)0; // expected-error {{expected ']'}} \ + // expected-note {{to match this '['}} + delete (void*)0; // expected-error {{cannot delete expression}} + delete (T*)0; // expected-warning {{deleting pointer to incomplete type}} + ::S::delete (int*)0; // expected-error {{expected unqualified-id}} +} diff --git a/test/SemaCXX/no-implicit-builtin-decls.cpp b/test/SemaCXX/no-implicit-builtin-decls.cpp new file mode 100644 index 000000000000..bd11f92f7e62 --- /dev/null +++ b/test/SemaCXX/no-implicit-builtin-decls.cpp @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() { + void *p = malloc(sizeof(int) * 10); // expected-error{{no matching function for call to 'malloc'}} +} + +int malloc(double); diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp new file mode 100644 index 000000000000..6cc5a8168313 --- /dev/null +++ b/test/SemaCXX/nullptr.cpp @@ -0,0 +1,67 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s +#include <stdint.h> + +// Don't have decltype yet. +typedef __typeof__(nullptr) nullptr_t; + +struct A {}; + +int o1(char*); +void o1(uintptr_t); +void o2(char*); // expected-note {{candidate}} +void o2(int A::*); // expected-note {{candidate}} + +nullptr_t f(nullptr_t null) +{ + // Implicit conversions. + null = nullptr; + void *p = nullptr; + p = null; + int *pi = nullptr; + pi = null; + null = 0; + int A::*pm = nullptr; + pm = null; + void (*pf)() = nullptr; + pf = null; + void (A::*pmf)() = nullptr; + pmf = null; + bool b = nullptr; + + // Can't convert nullptr to integral implicitly. + uintptr_t i = nullptr; // expected-error {{incompatible type initializing}} + + // Operators + (void)(null == nullptr); + (void)(null <= nullptr); + (void)(null == (void*)0); + (void)((void*)0 == nullptr); + (void)(null <= (void*)0); + (void)((void*)0 <= nullptr); + (void)(1 > nullptr); // expected-error {{invalid operands to binary expression}} + (void)(1 != nullptr); // expected-error {{invalid operands to binary expression}} + (void)(1 + nullptr); // expected-error {{invalid operands to binary expression}} + (void)(0 ? nullptr : 0); // expected-error {{incompatible operand types}} + (void)(0 ? nullptr : (void*)0); + + // Overloading + int t = o1(nullptr); + t = o1(null); + o2(nullptr); // expected-error {{ambiguous}} + + // nullptr is an rvalue, null is an lvalue + (void)&nullptr; // expected-error {{address expression must be an lvalue}} + nullptr_t *pn = &null; + + // You can reinterpret_cast nullptr to an integer. + (void)reinterpret_cast<uintptr_t>(nullptr); + + // You can throw nullptr. + throw nullptr; +} + +// Template arguments can be nullptr. +template <int *PI, void (*PF)(), int A::*PM, void (A::*PMF)()> +struct T {}; + +typedef T<nullptr, nullptr, nullptr, nullptr> NT; diff --git a/test/SemaCXX/offsetof.cpp b/test/SemaCXX/offsetof.cpp new file mode 100644 index 000000000000..f0290e889a29 --- /dev/null +++ b/test/SemaCXX/offsetof.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s -Winvalid-offsetof + +struct NonPOD { + virtual void f(); + int m; +}; + +struct P { + NonPOD fieldThatPointsToANonPODType; +}; + +void f() { + int i = __builtin_offsetof(P, fieldThatPointsToANonPODType.m); // expected-warning{{offset of on non-POD type 'struct P'}} +} + diff --git a/test/SemaCXX/overload-call-copycon.cpp b/test/SemaCXX/overload-call-copycon.cpp new file mode 100644 index 000000000000..755e27adbac8 --- /dev/null +++ b/test/SemaCXX/overload-call-copycon.cpp @@ -0,0 +1,48 @@ +// RUN: clang-cc -fsyntax-only %s +class X { }; + +int& copycon(X x); +float& copycon(...); + +void test_copycon(X x, X const xc, X volatile xv) { + int& i1 = copycon(x); + int& i2 = copycon(xc); + float& f1 = copycon(xv); +} + +class A { +public: + A(A&); +}; + +class B : public A { }; + +short& copycon2(A a); +int& copycon2(B b); +float& copycon2(...); + +void test_copycon2(A a, const A ac, B b, B const bc, B volatile bv) { + int& i1 = copycon2(b); + float& f1 = copycon2(bc); + float& f2 = copycon2(bv); + short& s1 = copycon2(a); + float& f3 = copycon2(ac); +} + +int& copycon3(A a); +float& copycon3(...); + +void test_copycon3(B b, const B bc) { + int& i1 = copycon3(b); + float& f1 = copycon3(bc); +} + + +class C : public B { }; + +float& copycon4(A a); +int& copycon4(B b); + +void test_copycon4(C c) { + int& i = copycon4(c); +}; diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp new file mode 100644 index 000000000000..94f352efc76c --- /dev/null +++ b/test/SemaCXX/overload-call.cpp @@ -0,0 +1,280 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +int* f(int) { return 0; } +float* f(float) { return 0; } +void f(); + +void test_f(int iv, float fv) { + float* fp = f(fv); + int* ip = f(iv); +} + +int* g(int, float, int); // expected-note {{ candidate function }} +float* g(int, int, int); // expected-note {{ candidate function }} +double* g(int, float, float); // expected-note {{ candidate function }} +char* g(int, float, ...); // expected-note {{ candidate function }} +void g(); + +void test_g(int iv, float fv) { + int* ip1 = g(iv, fv, 0); + float* fp1 = g(iv, iv, 0); + double* dp1 = g(iv, fv, fv); + char* cp1 = g(0, 0); + char* cp2 = g(0, 0, 0, iv, fv); + + double* dp2 = g(0, fv, 1.5); // expected-error {{ call to 'g' is ambiguous; candidates are: }} +} + +double* h(double f); +int* h(int); + +void test_h(float fv, unsigned char cv) { + double* dp = h(fv); + int* ip = h(cv); +} + +int* i(int); +double* i(long); + +void test_i(short sv, int iv, long lv, unsigned char ucv) { + int* ip1 = i(sv); + int* ip2 = i(iv); + int* ip3 = i(ucv); + double* dp1 = i(lv); +} + +int* j(void*); +double* j(bool); + +void test_j(int* ip) { + int* ip1 = j(ip); +} + +int* k(char*); +double* k(bool); + +void test_k() { + int* ip1 = k("foo"); + double* dp1 = k(L"foo"); +} + +int* l(wchar_t*); +double* l(bool); + +void test_l() { + int* ip1 = l(L"foo"); + double* dp1 = l("foo"); +} + +int* m(const char*); +double* m(char*); + +void test_m() { + int* ip = m("foo"); +} + +int* n(char*); +double* n(void*); +class E; + +void test_n(E* e) { + char ca[7]; + int* ip1 = n(ca); + int* ip2 = n("foo"); + + float fa[7]; + double* dp1 = n(fa); + + double* dp2 = n(e); +} + +enum PromotesToInt { + PromotesToIntValue = -1 +}; + +enum PromotesToUnsignedInt { + PromotesToUnsignedIntValue = 1u +}; + +int* o(int); +double* o(unsigned int); +float* o(long); + +void test_o() { + int* ip1 = o(PromotesToIntValue); + double* dp1 = o(PromotesToUnsignedIntValue); +} + +int* p(int); +double* p(double); + +void test_p() { + int* ip = p((short)1); + double* dp = p(1.0f); +} + +struct Bits { + signed short int_bitfield : 5; + unsigned int uint_bitfield : 8; +}; + +int* bitfields(int, int); +float* bitfields(unsigned int, int); + +void test_bitfield(Bits bits, int x) { + int* ip = bitfields(bits.int_bitfield, 0); + float* fp = bitfields(bits.uint_bitfield, 0u); +} + +int* multiparm(long, int, long); // expected-note {{ candidate function }} +float* multiparm(int, int, int); // expected-note {{ candidate function }} +double* multiparm(int, int, short); // expected-note {{ candidate function }} + +void test_multiparm(long lv, short sv, int iv) { + int* ip1 = multiparm(lv, iv, lv); + int* ip2 = multiparm(lv, sv, lv); + float* fp1 = multiparm(iv, iv, iv); + float* fp2 = multiparm(sv, iv, iv); + double* dp1 = multiparm(sv, sv, sv); + double* dp2 = multiparm(iv, sv, sv); + multiparm(sv, sv, lv); // expected-error {{ call to 'multiparm' is ambiguous; candidates are: }} +} + +// Test overloading based on qualification vs. no qualification +// conversion. +int* quals1(int const * p); +char* quals1(int * p); + +int* quals2(int const * const * pp); +char* quals2(int * * pp); + +int* quals3(int const * * const * ppp); +char* quals3(int *** ppp); + +void test_quals(int * p, int * * pp, int * * * ppp) { + char* q1 = quals1(p); + char* q2 = quals2(pp); + char* q3 = quals3(ppp); +} + +// Test overloading based on qualification ranking (C++ 13.3.2)p3. +int* quals_rank1(int const * p); +float* quals_rank1(int const volatile *p); +char* quals_rank1(char*); +double* quals_rank1(const char*); + +int* quals_rank2(int const * const * pp); +float* quals_rank2(int * const * pp); + +void quals_rank3(int const * const * const volatile * p); // expected-note{{candidate function}} +void quals_rank3(int const * const volatile * const * p); // expected-note{{candidate function}} + +void quals_rank3(int const *); // expected-note{{candidate function}} +void quals_rank3(int volatile *); // expected-note{{candidate function}} + +void test_quals_ranking(int * p, int volatile *pq, int * * pp, int * * * ppp) { + int* q1 = quals_rank1(p); + float* q2 = quals_rank1(pq); + double* q3 = quals_rank1("string literal"); + char a[17]; + const char* ap = a; + char* q4 = quals_rank1(a); + double* q5 = quals_rank1(ap); + + float* q6 = quals_rank2(pp); + + quals_rank3(ppp); // expected-error {{call to 'quals_rank3' is ambiguous; candidates are:}} + + quals_rank3(p); // expected-error {{call to 'quals_rank3' is ambiguous; candidates are:}} + quals_rank3(pq); +} + +// Test overloading based on derived-to-base conversions +class A { }; +class B : public A { }; +class C : public B { }; +class D : public C { }; + +int* derived1(A*); +char* derived1(const A*); +float* derived1(void*); + +int* derived2(A*); +float* derived2(B*); + +int* derived3(A*); +float* derived3(const B*); +char* derived3(C*); + +void test_derived(B* b, B const* bc, C* c, const C* cc, void* v, D* d) { + int* d1 = derived1(b); + char* d2 = derived1(bc); + int* d3 = derived1(c); + char* d4 = derived1(cc); + float* d5 = derived1(v); + + float* d6 = derived2(b); + float* d7 = derived2(c); + + char* d8 = derived3(d); +} + +// Test overloading of references. +// (FIXME: tests binding to determine candidate sets, not overload +// resolution per se). +int* intref(int&); +float* intref(const int&); + +void intref_test() { + float* ir1 = intref(5); + float* ir2 = intref(5.5); +} + +// Test reference binding vs. standard conversions. +int& bind_vs_conv(const double&); +float& bind_vs_conv(int); + +void bind_vs_conv_test() +{ + int& i1 = bind_vs_conv(1.0f); + float& f1 = bind_vs_conv((short)1); +} + +// Test that cv-qualifiers get subsumed in the reference binding. +struct X { }; +struct Y { }; +struct Z : X, Y { }; + +int& cvqual_subsume(X&); // expected-note{{candidate function}} +float& cvqual_subsume(const Y&); // expected-note{{candidate function}} + +int& cvqual_subsume2(const X&); +float& cvqual_subsume2(const volatile Y&); + +Z get_Z(); + +void cvqual_subsume_test(Z z) { + cvqual_subsume(z); // expected-error{{call to 'cvqual_subsume' is ambiguous; candidates are:}} + int& x = cvqual_subsume2(get_Z()); // okay: only binds to the first one +} + +// Test overloading with cv-qualification differences in reference +// binding. +int& cvqual_diff(X&); +float& cvqual_diff(const X&); + +void cvqual_diff_test(X x, Z z) { + int& i1 = cvqual_diff(x); + int& i2 = cvqual_diff(z); +} + +// Test overloading with derived-to-base differences in reference +// binding. +struct Z2 : Z { }; + +int& db_rebind(X&); +long& db_rebind(Y&); +float& db_rebind(Z&); + +void db_rebind_test(Z2 z2) { + float& f1 = db_rebind(z2); +} diff --git a/test/SemaCXX/overload-decl.cpp b/test/SemaCXX/overload-decl.cpp new file mode 100644 index 000000000000..2bc832f558f7 --- /dev/null +++ b/test/SemaCXX/overload-decl.cpp @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s +void f(); +void f(int); +void f(int, float); +void f(int, int); +void f(int, ...); + +typedef float Float; +void f(int, Float); // expected-note {{previous declaration is here}} + +int f(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}} + +void g(void); // expected-note {{previous declaration is here}} +int g(); // expected-error {{functions that differ only in their return type cannot be overloaded}} + +typedef int INT; + +class X { + void f(); + void f(int); // expected-note {{previous declaration is here}} + void f() const; + + void f(INT); // expected-error{{cannot be redeclared}} + + void g(int); // expected-note {{previous declaration is here}} + void g(int, float); // expected-note {{previous declaration is here}} + int g(int, Float); // expected-error {{functions that differ only in their return type cannot be overloaded}} + + static void g(float); + static void g(int); // expected-error {{static and non-static member functions with the same parameter types cannot be overloaded}} +}; diff --git a/test/SemaCXX/overload-member-call.cpp b/test/SemaCXX/overload-member-call.cpp new file mode 100644 index 000000000000..96e570da654b --- /dev/null +++ b/test/SemaCXX/overload-member-call.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct X { + int& f(int) const; // expected-note 2 {{candidate function}} + float& f(int); // expected-note 2 {{candidate function}} + + void test_f(int x) const { + int& i = f(x); + } + + void test_f2(int x) { + float& f2 = f(x); + } + + int& g(int) const; // expected-note 2 {{candidate function}} + float& g(int); // expected-note 2 {{candidate function}} + static double& g(double); // expected-note 2 {{candidate function}} + + void h(int); + + void test_member() { + float& f1 = f(0); + float& f2 = g(0); + double& d1 = g(0.0); + } + + void test_member_const() const { + int &i1 = f(0); + int &i2 = g(0); + double& d1 = g(0.0); + } + + static void test_member_static() { + double& d1 = g(0.0); + g(0); // expected-error{{call to 'g' is ambiguous; candidates are:}} + } +}; + +void test(X x, const X xc, X* xp, const X* xcp, volatile X xv, volatile X* xvp) { + int& i1 = xc.f(0); + int& i2 = xcp->f(0); + float& f1 = x.f(0); + float& f2 = xp->f(0); + xv.f(0); // expected-error{{no matching member function for call to 'f'; candidates are:}} + xvp->f(0); // expected-error{{no matching member function for call to 'f'; candidates are:}} + + int& i3 = xc.g(0); + int& i4 = xcp->g(0); + float& f3 = x.g(0); + float& f4 = xp->g(0); + double& d1 = xp->g(0.0); + double& d2 = X::g(0.0); + X::g(0); // expected-error{{call to 'g' is ambiguous; candidates are:}} + + X::h(0); // expected-error{{call to non-static member function without an object argument}} +} diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp new file mode 100644 index 000000000000..2a6c24a6778a --- /dev/null +++ b/test/SemaCXX/overloaded-builtin-operators.cpp @@ -0,0 +1,122 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct yes; +struct no; + +struct Short { + operator short(); +}; + +struct Long { + operator long(); +}; + +enum E1 { }; +struct Enum1 { + operator E1(); +}; + +enum E2 { }; +struct Enum2 { + operator E2(); +}; + +yes& islong(long); +yes& islong(unsigned long); // FIXME: shouldn't be needed +no& islong(int); + +void f(Short s, Long l, Enum1 e1, Enum2 e2) { + // C++ [over.built]p8 + int i1 = +e1; + int i2 = -e2; + + // C++ [over.built]p10: + int i3 = ~s; + bool b1 = !s; + + // C++ [over.built]p12 + (void)static_cast<yes&>(islong(s + l)); + (void)static_cast<no&>(islong(s + s)); + + // C++ [over.built]p17 + (void)static_cast<yes&>(islong(s % l)); + (void)static_cast<yes&>(islong(l << s)); + (void)static_cast<no&>(islong(s << l)); + (void)static_cast<yes&>(islong(e1 % l)); + // FIXME: should pass (void)static_cast<no&>(islong(e1 % e2)); +} + +struct ShortRef { + operator short&(); +}; + +struct LongRef { + operator volatile long&(); +}; + +void g(ShortRef sr, LongRef lr) { + // C++ [over.built]p3 + short s1 = sr++; + + // C++ [over.built]p3 + long l1 = lr--; + + // C++ [over.built]p18 + short& sr1 = (sr *= lr); + volatile long& lr1 = (lr *= sr); + + // C++ [over.built]p22 + short& sr2 = (sr %= lr); + volatile long& lr2 = (lr <<= sr); + + bool b1 = (sr && lr) || (sr || lr); +} + +struct VolatileIntPtr { + operator int volatile *(); +}; + +struct ConstIntPtr { + operator int const *(); +}; + +struct VolatileIntPtrRef { + operator int volatile *&(); +}; + +struct ConstIntPtrRef { + operator int const *&(); +}; + +void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr, + VolatileIntPtrRef vipr, ConstIntPtrRef cipr) { + const int& cir1 = cip[sr]; + const int& cir2 = sr[cip]; + volatile int& vir1 = vip[sr]; + volatile int& vir2 = sr[vip]; + bool b1 = (vip == cip); + long p1 = vip - cip; + + // C++ [over.built]p5: + int volatile *vip1 = vipr++; + int const *cip1 = cipr++; + int volatile *&vipr1 = ++vipr; + int const *&cipr1 = --cipr; + + // C++ [over.built]p6: + int volatile &ivr = *vip; + + // C++ [over.built]p8: + int volatile *vip2 = +vip; + int i1 = +sr; + int i2 = -sr; + + // C++ [over.built]p13: + int volatile &ivr2 = vip[17]; + int const &icr2 = 17[cip]; +} + +// C++ [over.match.open]p4 + +void test_assign_restrictions(ShortRef& sr) { + sr = (short)0; // expected-error{{no viable overloaded '='}} +} diff --git a/test/SemaCXX/overloaded-operator-decl.cpp b/test/SemaCXX/overloaded-operator-decl.cpp new file mode 100644 index 000000000000..fc17faf6634f --- /dev/null +++ b/test/SemaCXX/overloaded-operator-decl.cpp @@ -0,0 +1,39 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct X { + X(); + X(int); +}; + +X operator+(X, X); +X operator-(X, X) { X x; return x; } + +struct Y { + Y operator-() const; + void operator()(int x = 17) const; + int operator[](int); + + static int operator+(Y, Y); // expected-error{{overloaded 'operator+' cannot be a static member function}} +}; + + +void f(X x) { + x = operator+(x, x); +} + +X operator+(int, float); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}} + +X operator*(X, X = 5); // expected-error{{parameter of overloaded 'operator*' cannot have a default argument}} + +X operator/(X, X, ...); // expected-error{{overloaded 'operator/' cannot be variadic}} + +X operator%(Y); // expected-error{{overloaded 'operator%' must be a binary operator (has 1 parameter)}} + +void operator()(Y&, int, int); // expected-error{{overloaded 'operator()' must be a non-static member function}} + +typedef int INT; +typedef float FLOAT; +Y& operator++(Y&); +Y operator++(Y&, INT); +X operator++(X&, FLOAT); // expected-error{{parameter of overloaded post-increment operator must have type 'int' (not 'FLOAT' (aka 'float'))}} + +int operator+; // expected-error{{'operator+' cannot be the name of a variable or data member}} diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp new file mode 100644 index 000000000000..916d753a3ff5 --- /dev/null +++ b/test/SemaCXX/overloaded-operator.cpp @@ -0,0 +1,211 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class X { }; + +X operator+(X, X); + +void f(X x) { + x = x + x; +} + +struct Y; +struct Z; + +struct Y { + Y(const Z&); +}; + +struct Z { + Z(const Y&); +}; + +Y operator+(Y, Y); +bool operator-(Y, Y); // expected-note{{candidate function}} +bool operator-(Z, Z); // expected-note{{candidate function}} + +void g(Y y, Z z) { + y = y + z; + bool b = y - z; // expected-error{{use of overloaded operator '-' is ambiguous; candidates are:}} +} + +struct A { + bool operator==(Z&); // expected-note{{candidate function}} +}; + +A make_A(); + +bool operator==(A&, Z&); // expected-note{{candidate function}} + +void h(A a, const A ac, Z z) { + make_A() == z; + a == z; // expected-error{{use of overloaded operator '==' is ambiguous; candidates are:}} + ac == z; // expected-error{{invalid operands to binary expression ('struct A const' and 'struct Z')}} +} + +struct B { + bool operator==(const B&) const; + + void test(Z z) { + make_A() == z; + } +}; + +enum Enum1 { }; +enum Enum2 { }; + +struct E1 { + E1(Enum1) { } +}; + +struct E2 { + E2(Enum2); +}; + +// C++ [over.match.oper]p3 - enum restriction. +float& operator==(E1, E2); + +void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2) { + float &f1 = (e1 == e2); + float &f2 = (enum1 == e2); + float &f3 = (e1 == enum2); + float &f4 = (enum1 == enum2); // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a temporary of type 'bool'}} +} + + +struct PostInc { + PostInc operator++(int); + PostInc& operator++(); +}; + +struct PostDec { + PostDec operator--(int); + PostDec& operator--(); +}; + +void incdec_test(PostInc pi, PostDec pd) { + const PostInc& pi1 = pi++; + const PostDec& pd1 = pd--; + PostInc &pi2 = ++pi; + PostDec &pd2 = --pd; +} + +struct SmartPtr { + int& operator*(); + long& operator*() const volatile; +}; + +void test_smartptr(SmartPtr ptr, const SmartPtr cptr, + const volatile SmartPtr cvptr) { + int &ir = *ptr; + long &lr = *cptr; + long &lr2 = *cvptr; +} + + +struct ArrayLike { + int& operator[](int); +}; + +void test_arraylike(ArrayLike a) { + int& ir = a[17]; +} + +struct SmartRef { + int* operator&(); +}; + +void test_smartref(SmartRef r) { + int* ip = &r; +} + +bool& operator,(X, Y); + +void test_comma(X x, Y y) { + bool& b1 = (x, y); + X& xr = (x, x); +} + +struct Callable { + int& operator()(int, double = 2.71828); // expected-note{{candidate function}} + float& operator()(int, double, long, ...); // expected-note{{candidate function}} + + double& operator()(float); // expected-note{{candidate function}} +}; + +struct Callable2 { + int& operator()(int i = 0); + double& operator()(...) const; +}; + +void test_callable(Callable c, Callable2 c2, const Callable2& c2c) { + int &ir = c(1); + float &fr = c(1, 3.14159, 17, 42); + + c(); // expected-error{{no matching function for call to object of type 'struct Callable'; candidates are:}} + + double &dr = c(1.0f); + + int &ir2 = c2(); + int &ir3 = c2(1); + double &fr2 = c2c(); +} + +typedef float FLOAT; +typedef int& INTREF; +typedef INTREF Func1(FLOAT, double); +typedef float& Func2(int, double); + +struct ConvertToFunc { + operator Func1*(); // expected-note{{conversion candidate of type 'INTREF (*)(FLOAT, double)'}} + operator Func2&(); // expected-note{{conversion candidate of type 'float &(&)(int, double)'}} + void operator()(); +}; + +void test_funcptr_call(ConvertToFunc ctf) { + int &i1 = ctf(1.0f, 2.0); + float &f2 = ctf((short int)1, 1.0f); + ctf((long int)17, 2.0); // expected-error{{error: call to object of type 'struct ConvertToFunc' is ambiguous; candidates are:}} + ctf(); +} + +struct HasMember { + int m; +}; + +struct Arrow1 { + HasMember* operator->(); +}; + +struct Arrow2 { + Arrow1 operator->(); // expected-note{{candidate function}} +}; + +void test_arrow(Arrow1 a1, Arrow2 a2, const Arrow2 a3) { + int &i1 = a1->m; + int &i2 = a2->m; + a3->m; // expected-error{{no viable overloaded 'operator->'; candidate is}} +} + +struct CopyConBase { +}; + +struct CopyCon : public CopyConBase { + CopyCon(const CopyConBase &Base); + + CopyCon(const CopyConBase *Base) { + *this = *Base; + } +}; + +namespace N { + struct X { }; +} + +namespace M { + N::X operator+(N::X, N::X); +} + +namespace M { + void test_X(N::X x) { + (void)(x + x); + } +} diff --git a/test/SemaCXX/qualification-conversion.cpp b/test/SemaCXX/qualification-conversion.cpp new file mode 100644 index 000000000000..01e503ddac6c --- /dev/null +++ b/test/SemaCXX/qualification-conversion.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +int* quals1(int const * p); +int* quals2(int const * const * pp); +int* quals3(int const * * const * ppp); // expected-note{{candidate function}} + +void test_quals(int * p, int * * pp, int * * * ppp) { + int const * const * pp2 = pp; + quals1(p); + quals2(pp); + quals3(ppp); // expected-error {{no matching}} +} + +struct A {}; +void mquals1(int const A::*p); +void mquals2(int const A::* const A::*pp); +void mquals3(int const A::* A::* const A::*ppp); // expected-note{{candidate function}} + +void test_mquals(int A::*p, int A::* A::*pp, int A::* A::* A::*ppp) { + int const A::* const A::* pp2 = pp; + mquals1(p); + mquals2(pp); + mquals3(ppp); // expected-error {{no matching}} +} diff --git a/test/SemaCXX/qualified-id-lookup.cpp b/test/SemaCXX/qualified-id-lookup.cpp new file mode 100644 index 000000000000..254a18de1f32 --- /dev/null +++ b/test/SemaCXX/qualified-id-lookup.cpp @@ -0,0 +1,111 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace Ns { + int f(); // expected-note{{previous declaration is here}} + + enum E { + Enumerator + }; +} +namespace Ns { + double f(); // expected-error{{functions that differ only in their return type cannot be overloaded}} + + int x = Enumerator; +} + +namespace Ns2 { + float f(); +} + +int y = Ns::Enumerator; + +namespace Ns2 { + float f(int); // expected-note{{previous declaration is here}} +} + +namespace Ns2 { + double f(int); // expected-error{{functions that differ only in their return type cannot be overloaded}} +} + +namespace N { + int& f1(); +} + +namespace N { + struct f1 { + static int member; + + typedef int type; + + void foo(type); + }; + + void test_f1() { + int &i1 = f1(); + } +} + +void N::f1::foo(int i) { + f1::member = i; + f1::type &ir = i; +} + +namespace N { + float& f1(int x) { + N::f1::type& i1 = x; + f1::type& i2 = x; + } + + struct f2 { + static int member; + }; + void f2(); +} + +int i1 = N::f1::member; +typedef struct N::f1 type1; +int i2 = N::f2::member; +typedef struct N::f2 type2; + +void test_f1(int i) { + int &v1 = N::f1(); + float &v2 = N::f1(i); + int v3 = ::i1; + int v4 = N::f1::member; +} + +typedef int f2_type; +namespace a { + typedef int f2_type(int, int); + + void test_f2() { + ::f2_type(1, 2); // expected-error {{function-style cast to a builtin type can only take one argument}} + } +} + +// PR clang/3291 +namespace a { + namespace a { // A1 + namespace a { // A2 + int i; + } + } +} + +void test_a() { + a::a::i = 3; // expected-error{{no member named 'i'}} + a::a::a::i = 4; +} + +struct Undef { // expected-note{{definition of 'struct Undef' is not complete until the closing '}'}} + typedef int type; + + Undef::type member; + + static int size = sizeof(Undef); // expected-error{{invalid application of 'sizeof' to an incomplete type 'struct Undef'}} + + int f(); +}; + +int Undef::f() { + return sizeof(Undef); +} diff --git a/test/SemaCXX/qualified-names-diag.cpp b/test/SemaCXX/qualified-names-diag.cpp new file mode 100644 index 000000000000..3bffd7c05d3b --- /dev/null +++ b/test/SemaCXX/qualified-names-diag.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace foo { + namespace wibble { + struct x { int y; }; + + namespace bar { + namespace wonka { + struct x { + struct y { }; + }; + } + } + } +} + +namespace bar { + typedef int y; + + struct incomplete; // expected-note{{forward declaration of 'struct bar::incomplete'}} +} +void test() { + foo::wibble::x a; + ::bar::y b; + a + b; // expected-error{{invalid operands to binary expression ('foo::wibble::x' and '::bar::y' (aka 'int'))}} + + ::foo::wibble::bar::wonka::x::y c; + c + b; // expected-error{{invalid operands to binary expression ('::foo::wibble::bar::wonka::x::y' and '::bar::y' (aka 'int'))}} + + (void)sizeof(bar::incomplete); // expected-error{{invalid application of 'sizeof' to an incomplete type 'bar::incomplete'}} +} + +int ::foo::wibble::bar::wonka::x::y::* ptrmem; + diff --git a/test/SemaCXX/qualified-names-print.cpp b/test/SemaCXX/qualified-names-print.cpp new file mode 100644 index 000000000000..1cb19f0312e4 --- /dev/null +++ b/test/SemaCXX/qualified-names-print.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -ast-print %s 2>&1 | grep "N::M::X<INT>::value" +namespace N { + namespace M { + template<typename T> + struct X { + enum { value }; + }; + } +} + +typedef int INT; + +int test() { + return N::M::X<INT>::value; +} diff --git a/test/SemaCXX/references.cpp b/test/SemaCXX/references.cpp new file mode 100644 index 000000000000..9067a8661d7c --- /dev/null +++ b/test/SemaCXX/references.cpp @@ -0,0 +1,89 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int g(int); + +void f() { + int i; + int &r = i; + r = 1; + int *p = &r; + int &rr = r; + int (&rg)(int) = g; + rg(i); + int a[3]; + int (&ra)[3] = a; + ra[1] = i; + int *Q; + int *& P = Q; + P[1] = 1; +} + +typedef int t[1]; +void test2() { + t a; + t& b = a; + + + int c[3]; + int (&rc)[3] = c; +} + +// C++ [dcl.init.ref]p5b1 +struct A { }; +struct B : A { } b; + +void test3() { + double d = 2.0; + double& rd = d; // rd refers to d + const double& rcd = d; // rcd refers to d + + A& ra = b; // ra refers to A subobject in b + const A& rca = b; // rca refers to A subobject in b +} + +B fB(); + +// C++ [dcl.init.ref]p5b2 +void test4() { + double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot be initialized with a temporary of type 'double'}} + int i = 2; + double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot be initialized with a value of type 'int'}} + + const A& rca = fB(); +} + +void test5() { + const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0 + const volatile int cvi = 1; + const int& r = cvi; // expected-error{{initialization of reference to type 'int const' with a value of type 'int const volatile' drops qualifiers}} +} + +// C++ [dcl.init.ref]p3 +int& test6(int& x) { + int& yo; // expected-error{{declaration of reference variable 'yo' requires an initializer}} + + return x; +} +int& not_initialized_error; // expected-error{{declaration of reference variable 'not_initialized_error' requires an initializer}} +extern int& not_initialized_okay; + +class Test6 { + int& okay; +}; + +struct C : B, A { }; + +void test7(C& c) { + A& a1 = c; // expected-error {{ambiguous conversion from derived class 'struct C' to base class 'struct A':}} +} + +// C++ [dcl.ref]p1, C++ [dcl.ref]p4 +void test8(int& const,// expected-error{{'const' qualifier may not be applied to a reference}} + + void&, // expected-error{{cannot form a reference to 'void'}} + int& &) // expected-error{{type name declared as a reference to a reference}} +{ + typedef int& intref; + typedef intref& intrefref; // C++ DR 106: reference collapsing + + typedef intref const intref_c; // okay. FIXME: how do we verify that this is the same type as intref? +} diff --git a/test/SemaCXX/reinterpret-cast.cpp b/test/SemaCXX/reinterpret-cast.cpp new file mode 100644 index 000000000000..fd5ca8cf39d4 --- /dev/null +++ b/test/SemaCXX/reinterpret-cast.cpp @@ -0,0 +1,90 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +enum test { testval = 1 }; +struct structure { int m; }; +typedef void (*fnptr)(); + +// Test the conversion to self. +void self_conversion() +{ + // T*->T* is allowed, T->T in general not. + int i = 0; + (void)reinterpret_cast<int>(i); // expected-error {{reinterpret_cast from 'int' to 'int' is not allowed}} + structure s; + (void)reinterpret_cast<structure>(s); // expected-error {{reinterpret_cast from 'struct structure' to 'struct structure' is not allowed}} + int *pi = 0; + (void)reinterpret_cast<int*>(pi); +} + +// Test conversion between pointer and integral types, as in /3 and /4. +void integral_conversion() +{ + void *vp = reinterpret_cast<void*>(testval); + long l = reinterpret_cast<long>(vp); + (void)reinterpret_cast<float*>(l); + fnptr fnp = reinterpret_cast<fnptr>(l); + (void)reinterpret_cast<char>(fnp); // expected-error {{cast from pointer to smaller type 'char' loses information}} + (void)reinterpret_cast<long>(fnp); +} + +void pointer_conversion() +{ + int *p1 = 0; + float *p2 = reinterpret_cast<float*>(p1); + structure *p3 = reinterpret_cast<structure*>(p2); + typedef int **ppint; + ppint *deep = reinterpret_cast<ppint*>(p3); + (void)reinterpret_cast<fnptr*>(deep); +} + +void constness() +{ + int ***const ipppc = 0; + // Valid: T1* -> T2 const* + int const *icp = reinterpret_cast<int const*>(ipppc); + // Invalid: T1 const* -> T2* + (void)reinterpret_cast<int*>(icp); // expected-error {{reinterpret_cast from 'int const *' to 'int *' casts away constness}} + // Invalid: T1*** -> T2 const* const** + int const *const **icpcpp = reinterpret_cast<int const* const**>(ipppc); // expected-error {{reinterpret_cast from 'int ***const' to 'int const *const **' casts away constness}} + // Valid: T1* -> T2* + int *ip = reinterpret_cast<int*>(icpcpp); + // Valid: T* -> T const* + (void)reinterpret_cast<int const*>(ip); + // Valid: T*** -> T2 const* const* const* + (void)reinterpret_cast<int const* const* const*>(ipppc); +} + +void fnptrs() +{ + typedef int (*fnptr2)(int); + fnptr fp = 0; + (void)reinterpret_cast<fnptr2>(fp); + void *vp = reinterpret_cast<void*>(fp); + (void)reinterpret_cast<fnptr>(vp); +} + +void refs() +{ + long l = 0; + char &c = reinterpret_cast<char&>(l); + // Bad: from rvalue + (void)reinterpret_cast<int&>(&c); // expected-error {{reinterpret_cast from rvalue to reference type 'int &'}} +} + +void memptrs() +{ + const int structure::*psi = 0; + (void)reinterpret_cast<const float structure::*>(psi); + (void)reinterpret_cast<int structure::*>(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'int struct structure::*' casts away constness}} + + void (structure::*psf)() = 0; + (void)reinterpret_cast<int (structure::*)()>(psf); + + (void)reinterpret_cast<void (structure::*)()>(psi); // expected-error {{reinterpret_cast from 'int const struct structure::*' to 'void (struct structure::*)(void)' is not allowed}} + (void)reinterpret_cast<int structure::*>(psf); // expected-error {{reinterpret_cast from 'void (struct structure::*)(void)' to 'int struct structure::*' is not allowed}} + + // Cannot cast from integers to member pointers, not even the null pointer + // literal. + (void)reinterpret_cast<void (structure::*)()>(0); // expected-error {{reinterpret_cast from 'int' to 'void (struct structure::*)(void)' is not allowed}} + (void)reinterpret_cast<int structure::*>(0); // expected-error {{reinterpret_cast from 'int' to 'int struct structure::*' is not allowed}} +} diff --git a/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp b/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp new file mode 100644 index 000000000000..16b8659711e2 --- /dev/null +++ b/test/SemaCXX/reinterpret-fn-obj-pedantic.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 -pedantic %s + +void fnptrs() +{ + typedef void (*fnptr)(); + fnptr fp = 0; + void *vp = reinterpret_cast<void*>(fp); // expected-warning {{reinterpret_cast between pointer-to-function and pointer-to-object is an extension}} + (void)reinterpret_cast<fnptr>(vp); // expected-warning {{reinterpret_cast between pointer-to-function and pointer-to-object is an extension}} +} diff --git a/test/SemaCXX/return-stack-addr.cpp b/test/SemaCXX/return-stack-addr.cpp new file mode 100644 index 000000000000..457de297b008 --- /dev/null +++ b/test/SemaCXX/return-stack-addr.cpp @@ -0,0 +1,112 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +int* ret_local() { + int x = 1; + return &x; // expected-warning {{address of stack memory}} +} + +int* ret_local_array() { + int x[10]; + return x; // expected-warning {{address of stack memory}} +} + +int* ret_local_array_element(int i) { + int x[10]; + return &x[i]; // expected-warning {{address of stack memory}} +} + +int *ret_local_array_element_reversed(int i) { + int x[10]; + return &i[x]; // expected-warning {{address of stack memory}} +} + +int* ret_local_array_element_const_index() { + int x[10]; + return &x[2]; // expected-warning {{address of stack memory}} +} + +int& ret_local_ref() { + int x = 1; + return x; // expected-warning {{reference to stack memory}} +} + +int* ret_local_addrOf() { + int x = 1; + return &*&x; // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_paren() { + int x = 1; + return (&(*(&x))); // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_ptr_arith() { + int x = 1; + return &*(&x+1); // expected-warning {{address of stack memory}} +} + +int* ret_local_addrOf_ptr_arith2() { + int x = 1; + return &*(&x+1); // expected-warning {{address of stack memory}} +} + +int* ret_local_field() { + struct { int x; } a; + return &a.x; // expected-warning {{address of stack memory}} +} + +int& ret_local_field_ref() { + struct { int x; } a; + return a.x; // expected-warning {{reference to stack memory}} +} + +int* ret_conditional(bool cond) { + int x = 1; + int y = 2; + return cond ? &x : &y; // expected-warning {{address of stack memory}} +} + +int* ret_conditional_rhs(int *x, bool cond) { + int y = 1; + return cond ? x : &y; // expected-warning {{address of stack memory}} +} + +void* ret_c_cast() { + int x = 1; + return (void*) &x; // expected-warning {{address of stack memory}} +} + +int* ret_static_var() { + static int x = 1; + return &x; // no warning. +} + +int z = 1; + +int* ret_global() { + return &z; // no warning. +} + +int* ret_parameter(int x) { + return &x; // expected-warning {{address of stack memory}} +} + + +void* ret_cpp_static_cast(short x) { + return static_cast<void*>(&x); // expected-warning {{address of stack memory}} +} + +int* ret_cpp_reinterpret_cast(double x) { + return reinterpret_cast<int*>(&x); // expected-warning {{address of stack me}} +} + +int* ret_cpp_reinterpret_cast_no_warning(long x) { + return reinterpret_cast<int*>(x); // no-warning +} + +int* ret_cpp_const_cast(const int x) { + return const_cast<int*>(&x); // expected-warning {{address of stack memory}} +} + +// TODO: test case for dynamic_cast. clang does not yet have +// support for C++ classes to write such a test case. diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp new file mode 100644 index 000000000000..a7d26bb4b0e1 --- /dev/null +++ b/test/SemaCXX/rval-references.cpp @@ -0,0 +1,91 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++0x %s + +typedef int&& irr; +typedef irr& ilr_c1; // Collapses to int& +typedef int& ilr; +typedef ilr&& ilr_c2; // Collapses to int& + +irr ret_irr() { + return 0; +} + +struct not_int {}; + +int over(int&); +not_int over(int&&); + +int over2(const int&); +not_int over2(int&&); + +struct conv_to_not_int_rvalue { + operator not_int &&(); +}; + +void f() { + int &&virr1; // expected-error {{declaration of reference variable 'virr1' requires an initializer}} + int &&virr2 = 0; + int &&virr3 = virr2; // expected-error {{rvalue reference cannot bind to lvalue}} + int i1 = 0; + int &&virr4 = i1; // expected-error {{rvalue reference cannot bind to lvalue}} + int &&virr5 = ret_irr(); + int &&virr6 = static_cast<int&&>(i1); + (void)static_cast<not_int&&>(i1); // expected-error {{types are not compatible}} + + int i2 = over(i1); + not_int ni1 = over(0); + int i3 = over(virr2); + not_int ni2 = over(ret_irr()); + + int i4 = over2(i1); + not_int ni3 = over2(0); + + ilr_c1 vilr1 = i1; + ilr_c2 vilr2 = i1; + + conv_to_not_int_rvalue cnir; + not_int &&ni4 = cnir; // expected-error {{rvalue reference cannot bind to lvalue}} + not_int &ni5 = cnir; // expected-error{{non-const lvalue reference to type 'struct not_int' cannot be initialized with a value of type 'struct conv_to_not_int_rvalue'}} + not_int &&ni6 = conv_to_not_int_rvalue(); + + + try { + } catch(int&&) { // expected-error {{cannot catch exceptions by rvalue reference}} + } +} + +int&& should_warn(int i) { + // FIXME: The stack address return test doesn't reason about casts. + return static_cast<int&&>(i); // xpected-warning {{returning reference to temporary}} +} +int&& should_not_warn(int&& i) { // But GCC 4.4 does + return static_cast<int&&>(i); +} + + +// Test the return dance. This also tests IsReturnCopyElidable. +struct MoveOnly { + MoveOnly(); + MoveOnly(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&); + MoveOnly(int&&); +}; + +MoveOnly returning() { + MoveOnly mo; + return mo; +} + +MoveOnly gmo; +MoveOnly returningNonEligible() { + int i; + static MoveOnly mo; + MoveOnly &r = mo; + if (0) // Copy from global can't be elided + return gmo; // expected-error {{incompatible type returning}} + else if (0) // Copy from local static can't be elided + return mo; // expected-error {{incompatible type returning}} + else if (0) // Copy from reference can't be elided + return r; // expected-error {{incompatible type returning}} + else // Construction from different type can't be elided + return i; // expected-error {{incompatible type returning}} +} diff --git a/test/SemaCXX/statements.cpp b/test/SemaCXX/statements.cpp new file mode 100644 index 000000000000..d6925fe032e9 --- /dev/null +++ b/test/SemaCXX/statements.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc %s -fsyntax-only -pedantic + +void foo() { + return foo(); +} diff --git a/test/SemaCXX/static-assert.cpp b/test/SemaCXX/static-assert.cpp new file mode 100644 index 000000000000..caf76033af70 --- /dev/null +++ b/test/SemaCXX/static-assert.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +int f(); + +static_assert(f(), "f"); // expected-error {{static_assert expression is not an integral constant expression}} +static_assert(true, "true is not false"); +static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} + +void g() { + static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} +} + +class C { + static_assert(false, "false is false"); // expected-error {{static_assert failed "false is false"}} +}; + +template<int N> struct T { + static_assert(N == 2, "N is not 2!"); // expected-error {{static_assert failed "N is not 2!"}} +}; + +T<1> t1; // expected-note {{in instantiation of template class 'struct T<1>' requested here}} +T<2> t2; + +template<typename T> struct S { + static_assert(sizeof(T) > sizeof(char), "Type not big enough!"); // expected-error {{static_assert failed "Type not big enough!"}} +}; + +S<char> s1; // expected-note {{in instantiation of template class 'struct S<char>' requested here}} +S<int> s2; + diff --git a/test/SemaCXX/static-cast.cpp b/test/SemaCXX/static-cast.cpp new file mode 100644 index 000000000000..8399e77085b3 --- /dev/null +++ b/test/SemaCXX/static-cast.cpp @@ -0,0 +1,129 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A {}; +struct B : public A {}; // Single public base. +struct C1 : public virtual B {}; // Single virtual base. +struct C2 : public virtual B {}; +struct D : public C1, public C2 {}; // Diamond +struct E : private A {}; // Single private base. +struct F : public C1 {}; // Single path to B with virtual. +struct G1 : public B {}; +struct G2 : public B {}; +struct H : public G1, public G2 {}; // Ambiguous path to B. + +enum Enum { En1, En2 }; +enum Onom { On1, On2 }; + +// Explicit implicits +void t_529_2() +{ + int i = 1; + (void)static_cast<float>(i); + double d = 1.0; + (void)static_cast<float>(d); + (void)static_cast<int>(d); + (void)static_cast<char>(i); + (void)static_cast<unsigned long>(i); + (void)static_cast<int>(En1); + (void)static_cast<double>(En1); + (void)static_cast<int&>(i); + (void)static_cast<const int&>(i); + + int ar[1]; + (void)static_cast<const int*>(ar); + (void)static_cast<void (*)()>(t_529_2); + + (void)static_cast<void*>(0); + (void)static_cast<void*>((int*)0); + (void)static_cast<volatile const void*>((const int*)0); + (void)static_cast<A*>((B*)0); + (void)static_cast<A&>(*((B*)0)); + (void)static_cast<const B*>((C1*)0); + (void)static_cast<B&>(*((C1*)0)); + (void)static_cast<A*>((D*)0); + (void)static_cast<const A&>(*((D*)0)); + (void)static_cast<int B::*>((int A::*)0); + (void)static_cast<void (B::*)()>((void (A::*)())0); + + // TODO: User-defined conversions + + // Bad code below + + (void)static_cast<void*>((const int*)0); // expected-error {{static_cast from 'int const *' to 'void *' is not allowed}} + //(void)static_cast<A*>((E*)0); // {{static_cast from 'struct E *' to 'struct A *' is not allowed}} + //(void)static_cast<A*>((H*)0); // {{static_cast from 'struct H *' to 'struct A *' is not allowed}} + (void)static_cast<int>((int*)0); // expected-error {{static_cast from 'int *' to 'int' is not allowed}} + (void)static_cast<A**>((B**)0); // expected-error {{static_cast from 'struct B **' to 'struct A **' is not allowed}} + (void)static_cast<char&>(i); // expected-error {{non-const lvalue reference to type 'char' cannot be initialized with a value of type 'int'}} +} + +// Anything to void +void t_529_4() +{ + static_cast<void>(1); + static_cast<void>(t_529_4); +} + +// Static downcasts +void t_529_5_8() +{ + (void)static_cast<B*>((A*)0); + (void)static_cast<B&>(*((A*)0)); + (void)static_cast<const G1*>((A*)0); + (void)static_cast<const G1&>(*((A*)0)); + + // Bad code below + + (void)static_cast<C1*>((A*)0); // expected-error {{cannot cast 'struct A *' to 'struct C1 *' via virtual base 'struct B'}} + (void)static_cast<C1&>(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'struct C1 &' via virtual base 'struct B'}} + (void)static_cast<D*>((A*)0); // expected-error {{cannot cast 'struct A *' to 'struct D *' via virtual base 'struct B'}} + (void)static_cast<D&>(*((A*)0)); // expected-error {{cannot cast 'struct A' to 'struct D &' via virtual base 'struct B'}} + (void)static_cast<B*>((const A*)0); // expected-error {{static_cast from 'struct A const *' to 'struct B *' casts away constness}} + (void)static_cast<B&>(*((const A*)0)); // expected-error {{static_cast from 'struct A const' to 'struct B &' casts away constness}} + // Accessibility is not yet tested + //(void)static_cast<E*>((A*)0); // {{static_cast from 'struct A *' to 'struct E *' is not allowed}} + //(void)static_cast<E&>(*((A*)0)); // {{static_cast from 'struct A' to 'struct E &' is not allowed}} + (void)static_cast<H*>((A*)0); // expected-error {{ambiguous static_cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)static_cast<H&>(*((A*)0)); // expected-error {{ambiguous static_cast from base 'struct A' to derived 'struct H':\n struct A -> struct B -> struct G1 -> struct H\n struct A -> struct B -> struct G2 -> struct H}} + (void)static_cast<E*>((B*)0); // expected-error {{static_cast from 'struct B *' to 'struct E *' is not allowed}} + (void)static_cast<E&>(*((B*)0)); // expected-error {{non-const lvalue reference to type 'struct E' cannot be initialized with a value of type 'struct B'}} + + // TODO: Test inaccessible base in context where it's accessible, i.e. + // member function and friend. + + // TODO: Test DR427. This requires user-defined conversions, though. +} + +// Enum conversions +void t_529_7() +{ + (void)static_cast<Enum>(1); + (void)static_cast<Enum>(1.0); + (void)static_cast<Onom>(En1); + + // Bad code below + + (void)static_cast<Enum>((int*)0); // expected-error {{static_cast from 'int *' to 'enum Enum' is not allowed}} +} + +// Void pointer to object pointer +void t_529_10() +{ + (void)static_cast<int*>((void*)0); + (void)static_cast<const A*>((void*)0); + + // Bad code below + + (void)static_cast<int*>((const void*)0); // expected-error {{static_cast from 'void const *' to 'int *' casts away constness}} + (void)static_cast<void (*)()>((void*)0); // expected-error {{static_cast from 'void *' to 'void (*)(void)' is not allowed}} +} + +// Member pointer upcast. +void t_529_9() +{ + (void)static_cast<int A::*>((int B::*)0); + + // Bad code below + (void)static_cast<int A::*>((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'struct H'}} + (void)static_cast<int A::*>((int F::*)0); // expected-error {{conversion from pointer to member of class 'struct F'}} +} diff --git a/test/SemaCXX/static-initializers.cpp b/test/SemaCXX/static-initializers.cpp new file mode 100644 index 000000000000..3d92a532ae1a --- /dev/null +++ b/test/SemaCXX/static-initializers.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int f() +{ + return 10; +} + +void g() +{ + static int a = f(); +} + +static int b = f(); diff --git a/test/SemaCXX/struct-class-redecl.cpp b/test/SemaCXX/struct-class-redecl.cpp new file mode 100644 index 000000000000..4b6cef6dd2bf --- /dev/null +++ b/test/SemaCXX/struct-class-redecl.cpp @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -Wmismatched-tags -verify %s +class X; // expected-note 2{{here}} +typedef struct X * X_t; // expected-warning{{previously declared}} + +template<typename T> struct Y; // expected-note{{previous}} +template<class U> class Y { }; // expected-warning{{previously declared}} + +union X { int x; float y; }; // expected-error{{use of 'X' with tag type that does not match previous declaration}} diff --git a/test/SemaCXX/template-specialization.cpp b/test/SemaCXX/template-specialization.cpp new file mode 100644 index 000000000000..b3bb08d7e6a2 --- /dev/null +++ b/test/SemaCXX/template-specialization.cpp @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<int N> void f(int (&array)[N]); + +template<> void f<1>(int (&array)[1]) { } diff --git a/test/SemaCXX/this.cpp b/test/SemaCXX/this.cpp new file mode 100644 index 000000000000..0577d3c2b9bf --- /dev/null +++ b/test/SemaCXX/this.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s +int x = this; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}} + +void f() { + int x = this; // expected-error {{error: invalid use of 'this' outside of a nonstatic member function}} +} diff --git a/test/SemaCXX/trivial-constructor.cpp b/test/SemaCXX/trivial-constructor.cpp new file mode 100644 index 000000000000..8fc14d9c82cb --- /dev/null +++ b/test/SemaCXX/trivial-constructor.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x +struct T1 { +}; +static_assert(__has_trivial_constructor(T1), "T1 has trivial constructor!"); + +struct T2 { + T2(); +}; +static_assert(!__has_trivial_constructor(T2), "T2 has a user-declared constructor!"); + +struct T3 { + virtual void f(); +}; +static_assert(!__has_trivial_constructor(T3), "T3 has a virtual function!"); + +struct T4 : virtual T3 { +}; +static_assert(!__has_trivial_constructor(T4), "T4 has a virtual base class!"); + +struct T5 : T1 { +}; +static_assert(__has_trivial_constructor(T5), "All the direct base classes of T5 have trivial constructors!"); + +struct T6 { + T5 t5; + T1 t1[2][2]; + static T2 t2; +}; +static_assert(__has_trivial_constructor(T6), "All nonstatic data members of T6 have trivial constructors!"); + +struct T7 { + T4 t4; +}; +static_assert(!__has_trivial_constructor(T7), "t4 does not have a trivial constructor!"); + +struct T8 : T2 { +}; +static_assert(!__has_trivial_constructor(T8), "The base class T2 does not have a trivial constructor!"); diff --git a/test/SemaCXX/trivial-destructor.cpp b/test/SemaCXX/trivial-destructor.cpp new file mode 100644 index 000000000000..9e7f3a16dd66 --- /dev/null +++ b/test/SemaCXX/trivial-destructor.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x +struct T1 { +}; +static_assert(__has_trivial_destructor(T1), "T1 has trivial destructor!"); + +struct T2 { + ~T2(); +}; +static_assert(!__has_trivial_destructor(T2), "T2 has a user-declared destructor!"); + +struct T3 { + virtual void f(); +}; +static_assert(__has_trivial_destructor(T3), "T3 has a virtual function (but still a trivial destructor)!"); + +struct T4 : virtual T3 { +}; +static_assert(__has_trivial_destructor(T4), "T4 has a virtual base class! (but still a trivial destructor)!"); + +struct T5 : T1 { +}; +static_assert(__has_trivial_destructor(T5), "All the direct base classes of T5 have trivial destructors!"); + +struct T6 { + T5 t5; + T1 t1[2][2]; + static T2 t2; +}; +static_assert(__has_trivial_destructor(T6), "All nonstatic data members of T6 have trivial destructors!"); + +struct T7 { + T2 t2; +}; +static_assert(!__has_trivial_destructor(T7), "t2 does not have a trivial destructor!"); + +struct T8 : T2 { +}; +static_assert(!__has_trivial_destructor(T8), "The base class T2 does not have a trivial destructor!"); diff --git a/test/SemaCXX/type-convert-construct.cpp b/test/SemaCXX/type-convert-construct.cpp new file mode 100644 index 000000000000..1840456bde8e --- /dev/null +++ b/test/SemaCXX/type-convert-construct.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() { + float v1 = float(1); + int v2 = typeof(int)(1,2); // expected-error {{function-style cast to a builtin type can only take one argument}} + typedef int arr[]; + int v3 = arr(); // expected-error {{array types cannot be value-initialized}} + int v4 = int(); + int v5 = int; // expected-error {{expected '(' for function-style cast or type construction}} + typedef int T; + int *p; + bool v6 = T(0) == p; + char *str; + str = "a string"; + wchar_t *wstr; + wstr = L"a wide string"; +} diff --git a/test/SemaCXX/type-definition-in-specifier.cpp b/test/SemaCXX/type-definition-in-specifier.cpp new file mode 100644 index 000000000000..60c28b0f5e43 --- /dev/null +++ b/test/SemaCXX/type-definition-in-specifier.cpp @@ -0,0 +1,25 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct S0; +struct S1; +struct S2; +struct S3; +struct S4; +struct S5; +struct S6; + +struct S0 { int x; }; + +void f0() { + typedef struct S1 { int x; } S1_typedef; + + (void)((struct S2 { int x; }*)0); // expected-error{{can not be defined}} + + struct S3 { int x; } s3; + + (void)static_cast<struct S4 { int x; } *>(0); // expected-error{{can not be defined}} +} + +struct S5 { int x; } f1() { return S5(); } // expected-error{{result type}} + +void f2(struct S6 { int x; } p); // expected-error{{parameter type}} diff --git a/test/SemaCXX/type-dependent-exprs.cpp b/test/SemaCXX/type-dependent-exprs.cpp new file mode 100644 index 000000000000..dd31ef020c6a --- /dev/null +++ b/test/SemaCXX/type-dependent-exprs.cpp @@ -0,0 +1,24 @@ +// RUN: clang-cc -fsyntax-only -verify %s +class X { +public: + virtual int f(); +}; + +void g(int); // expected-note{{candidate function}} + +template<typename T> +T f(T x) { + (void)(x + 0); + (void)T(0); + (void)(x += 0); + (void)(x? x : x); + (void)static_cast<int>(x); + (void)reinterpret_cast<int>(x); + (void)dynamic_cast<X*>(&x); + (void)const_cast<int>(x); + return g(x); + h(x); // h is a dependent name + g(1, 1); // expected-error{{no matching function for call}} + h(1); // expected-error{{no matching function for call to 'h'}} + return 0; +} diff --git a/test/SemaCXX/type-traits.cpp b/test/SemaCXX/type-traits.cpp new file mode 100644 index 000000000000..1a2e329b2a44 --- /dev/null +++ b/test/SemaCXX/type-traits.cpp @@ -0,0 +1,111 @@ +// RUN: clang-cc -fsyntax-only -verify %s +#define T(b) (b) ? 1 : -1 +#define F(b) (b) ? -1 : 1 + +struct NonPOD { NonPOD(int); }; + +// PODs +enum Enum { EV }; +struct POD { Enum e; int i; float f; NonPOD* p; }; +typedef int Int; +typedef Int IntAr[10]; +class Statics { static int priv; static NonPOD np; }; + +// Not PODs +struct Derives : POD {}; +struct HasCons { HasCons(int); }; +struct HasAssign { HasAssign operator =(const HasAssign&); }; +struct HasDest { ~HasDest(); }; +class HasPriv { int priv; }; +class HasProt { protected: int prot; }; +struct HasRef { int i; int& ref; HasRef() : i(0), ref(i) {} }; +struct HasNonPOD { NonPOD np; }; +struct HasVirt { virtual void Virt() {}; }; +typedef Derives NonPODAr[10]; + +void is_pod() +{ + int t01[T(__is_pod(int))]; + int t02[T(__is_pod(Enum))]; + int t03[T(__is_pod(POD))]; + int t04[T(__is_pod(Int))]; + int t05[T(__is_pod(IntAr))]; + int t06[T(__is_pod(Statics))]; + + int t21[F(__is_pod(Derives))]; + int t22[F(__is_pod(HasCons))]; + int t23[F(__is_pod(HasAssign))]; + int t24[F(__is_pod(HasDest))]; + int t25[F(__is_pod(HasPriv))]; + int t26[F(__is_pod(HasProt))]; + int t27[F(__is_pod(HasRef))]; + int t28[F(__is_pod(HasNonPOD))]; + int t29[F(__is_pod(HasVirt))]; + int t30[F(__is_pod(NonPODAr))]; +} + +union Union { int i; float f; }; +typedef Derives ClassType; + +void is_class() +{ + int t01[T(__is_class(Derives))]; + int t02[T(__is_class(HasPriv))]; + int t03[T(__is_class(ClassType))]; + + int t11[F(__is_class(int))]; + int t12[F(__is_class(Enum))]; + int t13[F(__is_class(Int))]; + int t14[F(__is_class(IntAr))]; + int t15[F(__is_class(NonPODAr))]; + int t16[F(__is_class(Union))]; +} + +typedef Union UnionAr[10]; +typedef Union UnionType; + +void is_union() +{ + int t01[T(__is_union(Union))]; + int t02[T(__is_union(UnionType))]; + + int t11[F(__is_union(int))]; + int t12[F(__is_union(Enum))]; + int t13[F(__is_union(Int))]; + int t14[F(__is_union(IntAr))]; + int t15[F(__is_union(UnionAr))]; +} + +typedef Enum EnumType; + +void is_enum() +{ + int t01[T(__is_enum(Enum))]; + int t02[T(__is_enum(EnumType))]; + + int t11[F(__is_enum(int))]; + int t12[F(__is_enum(Union))]; + int t13[F(__is_enum(Int))]; + int t14[F(__is_enum(IntAr))]; + int t15[F(__is_enum(UnionAr))]; + int t16[F(__is_enum(Derives))]; + int t17[F(__is_enum(ClassType))]; +} + +struct Polymorph { virtual void f(); }; +struct InheritPolymorph : Polymorph {}; + +void is_polymorphic() +{ + int t01[T(__is_polymorphic(Polymorph))]; + int t02[T(__is_polymorphic(InheritPolymorph))]; + + int t11[F(__is_polymorphic(int))]; + int t12[F(__is_polymorphic(Union))]; + int t13[F(__is_polymorphic(Int))]; + int t14[F(__is_polymorphic(IntAr))]; + int t15[F(__is_polymorphic(UnionAr))]; + int t16[F(__is_polymorphic(Derives))]; + int t17[F(__is_polymorphic(ClassType))]; + int t18[F(__is_polymorphic(Enum))]; +} diff --git a/test/SemaCXX/typedef-redecl.cpp b/test/SemaCXX/typedef-redecl.cpp new file mode 100644 index 000000000000..e38f47436d1c --- /dev/null +++ b/test/SemaCXX/typedef-redecl.cpp @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef int INT; +typedef INT REALLY_INT; // expected-note {{previous definition is here}} +typedef REALLY_INT REALLY_REALLY_INT; +typedef REALLY_INT BOB; +typedef float REALLY_INT; // expected-error{{typedef redefinition with different types ('float' vs 'INT' (aka 'int'))}} + +struct X { + typedef int result_type; // expected-note {{previous definition is here}} + typedef INT result_type; // expected-error {{redefinition of 'result_type'}} +}; + +struct Y; // expected-note{{previous definition is here}} +typedef int Y; // expected-error{{typedef redefinition with different types ('int' vs 'struct Y')}} + +typedef int Y2; // expected-note{{previous definition is here}} +struct Y2; // expected-error{{definition of type 'struct Y2' conflicts with typedef of the same name}} + +void f(); // expected-note{{previous definition is here}} +typedef int f; // expected-error{{redefinition of 'f' as different kind of symbol}} + +typedef int f2; // expected-note{{previous definition is here}} +void f2(); // expected-error{{redefinition of 'f2' as different kind of symbol}} + +typedef struct s s; +typedef int I; +typedef int I; +typedef I I; + +struct s { }; + diff --git a/test/SemaCXX/typeid.cpp b/test/SemaCXX/typeid.cpp new file mode 100644 index 000000000000..f9ad7592187c --- /dev/null +++ b/test/SemaCXX/typeid.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void f() +{ + (void)typeid(int); // expected-error {{error: you need to include <typeinfo> before using the 'typeid' operator}} +} + +// FIXME: This should really include <typeinfo>, but we don't have that yet. +namespace std { + class type_info; +} + +void g() +{ + (void)typeid(int); +} diff --git a/test/SemaCXX/types_compatible_p.cpp b/test/SemaCXX/types_compatible_p.cpp new file mode 100644 index 000000000000..30b16006c685 --- /dev/null +++ b/test/SemaCXX/types_compatible_p.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +bool f() { + return __builtin_types_compatible_p(int, const int); // expected-error{{C++}} +} diff --git a/test/SemaCXX/unused.cpp b/test/SemaCXX/unused.cpp new file mode 100644 index 000000000000..55f959de0f02 --- /dev/null +++ b/test/SemaCXX/unused.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR4103 : Make sure we don't get a bogus unused expression warning +class APInt { + char foo; +}; +class APSInt : public APInt { + char bar; +public: + APSInt &operator=(const APSInt &RHS); +}; + +APSInt& APSInt::operator=(const APSInt &RHS) { + APInt::operator=(RHS); + return *this; +} diff --git a/test/SemaCXX/user-defined-conversions.cpp b/test/SemaCXX/user-defined-conversions.cpp new file mode 100644 index 000000000000..0a4bb773d396 --- /dev/null +++ b/test/SemaCXX/user-defined-conversions.cpp @@ -0,0 +1,69 @@ +// RUN: clang-cc -fsyntax-only -verify %s +struct X { + operator bool(); +}; + +int& f(bool); +float& f(int); + +void f_test(X x) { + int& i1 = f(x); +} + +struct Y { + operator short(); + operator float(); +}; + +void g(int); + +void g_test(Y y) { + g(y); + short s; + s = y; +} + +struct A { }; +struct B : A { }; + +struct C { + operator B&(); +}; + +// Test reference binding via an lvalue conversion function. +void h(volatile A&); +void h_test(C c) { + h(c); +} + +// Test conversion followed by copy-construction +struct FunkyDerived; + +struct Base { + Base(const FunkyDerived&); +}; + +struct Derived : Base { }; + +struct FunkyDerived : Base { }; + +struct ConvertibleToBase { + operator Base(); +}; + +struct ConvertibleToDerived { + operator Derived(); +}; + +struct ConvertibleToFunkyDerived { + operator FunkyDerived(); +}; + +void test_conversion(ConvertibleToBase ctb, ConvertibleToDerived ctd, + ConvertibleToFunkyDerived ctfd) { + Base b1 = ctb; + Base b2(ctb); + Base b3 = ctd; + Base b4(ctd); + Base b5 = ctfd; +} diff --git a/test/SemaCXX/using-directive.cpp b/test/SemaCXX/using-directive.cpp new file mode 100644 index 000000000000..924cf077b63f --- /dev/null +++ b/test/SemaCXX/using-directive.cpp @@ -0,0 +1,108 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace A { + short i; // expected-note 2{{candidate found by name lookup is 'A::i'}} + namespace B { + long i; // expected-note{{candidate found by name lookup is 'A::B::i'}} + void f() {} // expected-note{{candidate function}} + int k; + namespace E {} // \ + expected-note{{candidate found by name lookup is 'A::B::E'}} + } + + namespace E {} // expected-note{{candidate found by name lookup is 'A::E'}} + + namespace C { + using namespace B; + namespace E {} // \ + expected-note{{candidate found by name lookup is 'A::C::E'}} + } + + void f() {} // expected-note{{candidate function}} + + class K1 { + void foo(); + }; + + void local_i() { + char i; + using namespace A; + using namespace B; + int a[sizeof(i) == sizeof(char)? 1 : -1]; // okay + } + namespace B { + int j; + } + + void ambig_i() { + using namespace A; + using namespace A::B; + (void) i; // expected-error{{reference to 'i' is ambiguous}} + f(); // expected-error{{call to 'f' is ambiguous}} + (void) j; // okay + using namespace C; + (void) k; // okay + using namespace E; // expected-error{{reference to 'E' is ambiguous}} + } + + struct K2 {}; // expected-note{{candidate found by name lookup is 'A::K2'}} +} + +struct K2 {}; // expected-note{{candidate found by name lookup is 'K2'}} + +using namespace A; + +void K1::foo() {} // okay + +// FIXME: Do we want err_ovl_no_viable_function_in_init here? +struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \ + expected-error{{incomplete type}} + +// FIXME: This case is incorrectly diagnosed! +//K2 k3; + + +class X { // expected-note{{candidate found by name lookup is 'X'}} + // FIXME: produce a suitable error message for this + using namespace A; // expected-error{{expected member name or}} +}; + +namespace N { + struct K2; + struct K2 { }; +} + +namespace Ni { + int i(); // expected-note{{candidate found by name lookup is 'Ni::i'}} +} + +namespace NiTest { + using namespace A; + using namespace Ni; + + int test() { + return i; // expected-error{{reference to 'i' is ambiguous}} + } +} + +namespace OneTag { + struct X; // expected-note{{candidate found by name lookup is 'OneTag::X'}} +} + +namespace OneFunction { + void X(); // expected-note{{candidate found by name lookup is 'OneFunction::X'}} +} + +namespace TwoTag { + struct X; // expected-note{{candidate found by name lookup is 'TwoTag::X'}} +} + +namespace FuncHidesTagAmbiguity { + using namespace OneTag; + using namespace OneFunction; + using namespace TwoTag; + + void test() { + (void)X(); // expected-error{{reference to 'X' is ambiguous}} + } +} diff --git a/test/SemaCXX/vararg-non-pod.cpp b/test/SemaCXX/vararg-non-pod.cpp new file mode 100644 index 000000000000..1c5fe74a154d --- /dev/null +++ b/test/SemaCXX/vararg-non-pod.cpp @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify -fblocks %s + +extern char version[]; + +class C { +public: + C(int); + void g(int a, ...); + static void h(int a, ...); +}; + +void g(int a, ...); + +void t1() +{ + C c(10); + + g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}} + g(10, version); +} + +void t2() +{ + C c(10); + + c.g(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + c.g(10, version); + + C::h(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic function; call will abort at runtime}} + C::h(10, version); +} + +int (^block)(int, ...); + +void t3() +{ + C c(10); + + block(10, c); // expected-warning{{cannot pass object of non-POD type 'class C' through variadic block; call will abort at runtime}} + block(10, version); +} + +class D { +public: + void operator() (int a, ...); +}; + +void t4() +{ + C c(10); + + D d; + + d(10, c); // expected-warning{{Line 48: cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + d(10, version); +} diff --git a/test/SemaCXX/virtual-override.cpp b/test/SemaCXX/virtual-override.cpp new file mode 100644 index 000000000000..4a3b10fa9764 --- /dev/null +++ b/test/SemaCXX/virtual-override.cpp @@ -0,0 +1,106 @@ +// RUN: clang-cc -fsyntax-only -faccess-control -verify %s + +namespace T1 { + +class A { + virtual int f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual void f(); // expected-error{{virtual function 'f' has a different return type ('void') than the function it overrides (which has return type 'int')}} +}; + +} + +namespace T2 { + +struct a { }; +struct b { }; + +class A { + virtual a* f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides ('struct T2::b *' is not derived from 'struct T2::a *')}} +}; + +} + +namespace T3 { + +struct a { }; +struct b : private a { }; // expected-note{{'private' inheritance specifier here}} + +class A { + virtual a* f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides (conversion from 'struct T3::b' to inaccessible base class 'struct T3::a')}} +}; + +} + +namespace T4 { + +struct a { }; +struct a1 : a { }; +struct b : a, a1 { }; + +class A { + virtual a* f(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual b* f(); // expected-error{{return type of virtual function 'f' is not covariant with the return type of the function it overrides (ambiguous conversion from derived class 'struct T4::b' to base class 'struct T4::a':\n\ + struct T4::b -> struct T4::a\n\ + struct T4::b -> struct T4::a1 -> struct T4::a)}} +}; + +} + +namespace T5 { + +struct a { }; + +class A { + virtual a* const f(); + virtual a* const g(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual a* const f(); + virtual a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides ('struct T5::a *' has different qualifiers than 'struct T5::a *const')}} +}; + +} + +namespace T6 { + +struct a { }; + +class A { + virtual const a* f(); + virtual a* g(); // expected-note{{overridden virtual function is here}} +}; + +class B : A { + virtual a* f(); + virtual const a* g(); // expected-error{{return type of virtual function 'g' is not covariant with the return type of the function it overrides (class type 'struct T6::a const *' is more qualified than class type 'struct T6::a *'}} +}; + +} + +namespace T7 { + struct a { }; + struct b { }; + + class A { + a* f(); + }; + + class B : A { + virtual b* f(); + }; +} diff --git a/test/SemaCXX/virtuals.cpp b/test/SemaCXX/virtuals.cpp new file mode 100644 index 000000000000..c2ac77b30479 --- /dev/null +++ b/test/SemaCXX/virtuals.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class A { + virtual void f(); + virtual void g() = 0; + + void h() = 0; // expected-error {{'h' is not virtual and cannot be declared pure}} + void i() = 1; // expected-error {{initializer on function does not look like a pure-specifier}} + void j() = 0u; // expected-error {{initializer on function does not look like a pure-specifier}} + + + void k(); + +public: + A(int); +}; + +virtual void A::k() { } // expected-error{{'virtual' can only be specified inside the class definition}} + +class B : public A { + // Needs to recognize that overridden function is virtual. + //void g() = 0; + + // Needs to recognize that function does not override. + //void g(int) = 0; +}; + +// Needs to recognize invalid uses of abstract classes. +/* +A fn(A) +{ + A a; + static_cast<A>(0); + try { + } catch(A) { + } +} +*/ diff --git a/test/SemaCXX/warn-for-var-in-else.cpp b/test/SemaCXX/warn-for-var-in-else.cpp new file mode 100644 index 000000000000..3368da223a48 --- /dev/null +++ b/test/SemaCXX/warn-for-var-in-else.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// rdar://6425550 +int bar(); +void do_something(int); + +int foo() { + if (int X = bar()) { + return X; + } else { + do_something(X); // expected-warning{{'X' is always zero in this context}} + } +} + +bool foo2() { + if (bool B = bar()) { + if (int Y = bar()) { + return B; + } else { + do_something(Y); // expected-warning{{'Y' is always zero in this context}} + return B; + } + } else { + if (bool B2 = B) { // expected-warning{{'B' is always false in this context}} + do_something(B); // expected-warning{{'B' is always false in this context}} + } else if (B2) { // expected-warning{{'B2' is always false in this context}} + do_something(B); // expected-warning{{'B' is always false in this context}} + } + return B; // expected-warning{{'B' is always false in this context}} + } +} diff --git a/test/SemaCXX/wchar_t.cpp b/test/SemaCXX/wchar_t.cpp new file mode 100644 index 000000000000..fc258da7d1a6 --- /dev/null +++ b/test/SemaCXX/wchar_t.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +wchar_t x; + +void f(wchar_t p) { + wchar_t x; + unsigned wchar_t y; // expected-warning {{'wchar_t' cannot be signed or unsigned}} + signed wchar_t z; // expected-warning {{'wchar_t' cannot be signed or unsigned}} + ++x; +} diff --git a/test/SemaObjC/ContClassPropertyLookup.m b/test/SemaObjC/ContClassPropertyLookup.m new file mode 100644 index 000000000000..aa5afa7854f0 --- /dev/null +++ b/test/SemaObjC/ContClassPropertyLookup.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface MyObject { + int _foo; +} +@end + +@interface MyObject(whatever) +@property (assign) int foo; +@end + +@interface MyObject() +@property (assign) int foo; +@end + +@implementation MyObject +@synthesize foo = _foo; +@end diff --git a/test/SemaObjC/DoubleMethod.m b/test/SemaObjC/DoubleMethod.m new file mode 100644 index 000000000000..e43c1a0ab032 --- /dev/null +++ b/test/SemaObjC/DoubleMethod.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Subclass +{ + int ivar; +} + +- (void) method; +- (void) method; +@end + +@implementation Subclass +- (void) method {;} // expected-note {{previous declaration is here}} +- (void) method {;} // expected-error {{duplicate declaration of method 'method'}} +@end + +int main (void) { + return 0; +} diff --git a/test/SemaObjC/access-property-getter.m b/test/SemaObjC/access-property-getter.m new file mode 100644 index 000000000000..50a301688905 --- /dev/null +++ b/test/SemaObjC/access-property-getter.m @@ -0,0 +1,35 @@ +// RUN: clang-cc -verify %s + +@protocol NSObject +- (oneway void)release; +@end + +@protocol XCOutputStreams <NSObject> +@end + + +@interface XCWorkQueueCommandInvocation +{ + id <XCOutputStreams> _outputStream; +} +@end + +@interface XCWorkQueueCommandSubprocessInvocation : XCWorkQueueCommandInvocation +@end + +@interface XCWorkQueueCommandLocalSubprocessInvocation : XCWorkQueueCommandSubprocessInvocation +@end + +@interface XCWorkQueueCommandDistributedSubprocessInvocation : XCWorkQueueCommandSubprocessInvocation +@end + +@interface XCWorkQueueCommandCacheFetchInvocation : XCWorkQueueCommandSubprocessInvocation + +@end + +@implementation XCWorkQueueCommandCacheFetchInvocation +- (id)harvestPredictivelyProcessedOutputFiles +{ + _outputStream.release; +} +@end diff --git a/test/SemaObjC/alias-test-1.m b/test/SemaObjC/alias-test-1.m new file mode 100644 index 000000000000..39358cd62a6c --- /dev/null +++ b/test/SemaObjC/alias-test-1.m @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@compatibility_alias alias4 foo; // expected-warning {{cannot find interface declaration for 'foo'}} + +@class class2; // expected-note {{previous declaration is here}} +@class class3; + +typedef int I; // expected-note {{previous declaration is here}} + +@compatibility_alias alias1 I; // expected-warning {{cannot find interface declaration for 'I'}} + +@compatibility_alias alias class2; +@compatibility_alias alias class3; // expected-error {{conflicting types for alias 'alias'}} + + +typedef int alias2; // expected-note {{previous declaration is here}} +@compatibility_alias alias2 class3; // expected-error {{conflicting types for alias 'alias2'}} + +alias *p; +class2 *p2; + +int foo () +{ + + if (p == p2) { + int alias = 1; + } + + alias *p3; + return p3 == p2; +} diff --git a/test/SemaObjC/alias-test-2.m b/test/SemaObjC/alias-test-2.m new file mode 100644 index 000000000000..e0baf4e4d374 --- /dev/null +++ b/test/SemaObjC/alias-test-2.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Note: GCC doesn't produce any of the following errors. +@interface Super @end // expected-note {{previous definition is here}} + +@interface MyWpModule @end // expected-note {{previous definition is here}} + +@compatibility_alias MyAlias MyWpModule; + +@compatibility_alias AliasForSuper Super; + +@interface MyAlias : AliasForSuper // expected-error {{duplicate interface definition for class 'MyWpModule'}} +@end + +@implementation MyAlias : AliasForSuper // expected-error {{conflicting super class name 'Super'}} +@end + diff --git a/test/SemaObjC/argument-checking.m b/test/SemaObjC/argument-checking.m new file mode 100644 index 000000000000..1b6c10d29c6b --- /dev/null +++ b/test/SemaObjC/argument-checking.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +struct S { int a; }; + +extern int charStarFunc(char *); +extern int charFunc(char); + +@interface Test ++alloc; +-(int)charStarMeth:(char *)s; +-structMeth:(struct S)s; +-structMeth:(struct S)s :(struct S)s2; +@end + +void test() { + id obj = [Test alloc]; + struct S sInst; + + charStarFunc(1); // expected-warning {{incompatible integer to pointer conversion passing 'int', expected 'char *'}} + charFunc("abc"); // expected-warning {{incompatible pointer to integer conversion passing 'char [4]', expected 'char'}} + + [obj charStarMeth:1]; // expected-warning {{incompatible integer to pointer conversion sending 'int'}} + [obj structMeth:1]; // expected-error {{incompatible type sending 'int'}} + [obj structMeth:sInst :1]; // expected-error {{incompatible type sending 'int'}} +} diff --git a/test/SemaObjC/at-defs.m b/test/SemaObjC/at-defs.m new file mode 100644 index 000000000000..78ce63cd5299 --- /dev/null +++ b/test/SemaObjC/at-defs.m @@ -0,0 +1,29 @@ +// RUN: clang-cc -triple i386-unknown-unknown %s -fsyntax-only + +@interface Test { + double a; +} +@end +@implementation Test +@end +@interface TestObject : Test { +@public + float bar; + int foo; +} +@end +@implementation TestObject +@end +struct wibble { + @defs(TestObject) +}; + + +int main(void) +{ + TestObject * a = (id)malloc(100); + a->foo = 12; + printf("12: %d\n", ((struct wibble*)a)->foo); + printf("%d: %d\n", ((char*)&(((struct wibble*)a)->foo)) - (char*)a, ((char*)&(a->foo)) - (char*)a); + return 0; +} diff --git a/test/SemaObjC/attr-cleanup.m b/test/SemaObjC/attr-cleanup.m new file mode 100644 index 000000000000..f4d057b2b830 --- /dev/null +++ b/test/SemaObjC/attr-cleanup.m @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +@class NSString; + +void c1(id *a); + +void t1() +{ + NSString *s __attribute((cleanup(c1))); +} diff --git a/test/SemaObjC/attr-deprecated.m b/test/SemaObjC/attr-deprecated.m new file mode 100644 index 000000000000..e385a977f55b --- /dev/null +++ b/test/SemaObjC/attr-deprecated.m @@ -0,0 +1,99 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +@interface A { + int X __attribute__((deprecated)); +} ++ (void)F __attribute__((deprecated)); +- (void)f __attribute__((deprecated)); +@end + +@implementation A ++ (void)F __attribute__((deprecated)) +{ // expected-warning {{method attribute can only be specified on method declarations}} + [self F]; // no warning, since the caller is also deprecated. +} + +- (void)g +{ + X++; // expected-warning{{'X' is deprecated}} + self->X++; // expected-warning{{'X' is deprecated}} + [self f]; // expected-warning{{'f' is deprecated}} +} + +- (void)f +{ + [self f]; // no warning, the caller is deprecated in its interface. +} +@end + +@interface B: A +@end + +@implementation B ++ (void)G +{ + [super F]; // expected-warning{{'F' is deprecated}} +} + +- (void)g +{ + [super f]; // // expected-warning{{'f' is deprecated}} +} +@end + +@protocol P +- (void)p __attribute__((deprecated)); +@end + +void t1(A *a) +{ + [A F]; // expected-warning{{'F' is deprecated}} + [a f]; // expected-warning{{'f' is deprecated}} +} + +void t2(id a) +{ + [a f]; +} + +void t3(A<P>* a) +{ + [a f]; // expected-warning{{'f' is deprecated}} + [a p]; // expected-warning{{'p' is deprecated}} +} + +void t4(Class c) +{ + [c F]; +} + + + +@interface Bar + +@property (assign, setter = MySetter:) int FooBar __attribute__ ((deprecated)); +- (void) MySetter : (int) value; +@end + +int t5() { + Bar *f; + f.FooBar = 1; // expected-warning {{warning: 'FooBar' is deprecated}} + return f.FooBar; // expected-warning {{warning: 'FooBar' is deprecated}} +} + + +__attribute ((deprecated)) +@interface DEPRECATED { + @public int ivar; +} +- (int) instancemethod; +@property int prop; +@end + +@interface DEPRECATED (Category) // expected-warning {{warning: 'DEPRECATED' is deprecated}} +@end + +@interface NS : DEPRECATED // expected-warning {{warning: 'DEPRECATED' is deprecated}} +@end + + diff --git a/test/SemaObjC/attr-objc-exception.m b/test/SemaObjC/attr-objc-exception.m new file mode 100644 index 000000000000..3efb8cfa40ce --- /dev/null +++ b/test/SemaObjC/attr-objc-exception.m @@ -0,0 +1,16 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +__attribute__((__objc_exception__)) +@interface NSException { + int x; +} + +@end + + +__attribute__((__objc_exception__)) // expected-error {{attribute may only be applied to an Objective-C interface}} +int X; + +__attribute__((__objc_exception__)) // expected-error {{attribute may only be applied to an Objective-C interface}} +void foo(); + diff --git a/test/SemaObjC/attr-objc-gc.m b/test/SemaObjC/attr-objc-gc.m new file mode 100644 index 000000000000..20da639c3cb9 --- /dev/null +++ b/test/SemaObjC/attr-objc-gc.m @@ -0,0 +1,8 @@ +// RUN: clang-cc -fsyntax-only -verify %s +static id __attribute((objc_gc(weak))) a; +static id __attribute((objc_gc(strong))) b; + +static id __attribute((objc_gc())) c; // expected-error{{'objc_gc' attribute requires parameter 1 to be a string}} +static id __attribute((objc_gc(123))) d; // expected-error{{'objc_gc' attribute requires parameter 1 to be a string}} +static id __attribute((objc_gc(foo, 456))) e; // expected-error{{attribute requires 1 argument(s)}} +static id __attribute((objc_gc(hello))) f; // expected-warning{{'objc_gc' attribute argument not supported: 'hello'}} diff --git a/test/SemaObjC/bad-receiver-1.m b/test/SemaObjC/bad-receiver-1.m new file mode 100644 index 000000000000..64ff3d199314 --- /dev/null +++ b/test/SemaObjC/bad-receiver-1.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface I +- (id) retain; +@end + +void __raiseExc1() { + [objc_lookUpClass("NSString") retain]; // expected-warning {{receiver type 'int' is not 'id'}} \ + expected-warning {{method '-retain' not found}} +} + +typedef const struct __CFString * CFStringRef; + +void func() { + CFStringRef obj; + + [obj self]; // expected-warning {{receiver type 'CFStringRef' (aka 'struct __CFString const *') is not 'id'}} \\ + expected-warning {{method '-self' not found}} +} diff --git a/test/SemaObjC/block-attr.m b/test/SemaObjC/block-attr.m new file mode 100644 index 000000000000..d67fd3543548 --- /dev/null +++ b/test/SemaObjC/block-attr.m @@ -0,0 +1,9 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -fsyntax-only -verify -fblocks -fobjc-gc-only %s + +@interface Thing {} + +@property void(^someBlock)(void); // expected-warning {{'copy' attribute must be specified for the block property}} +@property(copy) void(^OK)(void); + + +@end diff --git a/test/SemaObjC/block-ivar.m b/test/SemaObjC/block-ivar.m new file mode 100644 index 000000000000..231c9a23f8ad --- /dev/null +++ b/test/SemaObjC/block-ivar.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s -fblocks + +@interface NSObject { + struct objc_object *isa; +} +@end +@interface Foo : NSObject { + int _prop; +} +@end + +@implementation Foo +- (int)doSomething { + int (^blk)(void) = ^{ return _prop; }; + return blk(); +} + +@end + diff --git a/test/SemaObjC/blocks.m b/test/SemaObjC/blocks.m new file mode 100644 index 000000000000..baadbde3e040 --- /dev/null +++ b/test/SemaObjC/blocks.m @@ -0,0 +1,46 @@ +// RUN: clang-cc -fsyntax-only -verify -fblocks %s +@protocol NSObject; + +void bar(id(^)(void)); +void foo(id <NSObject>(^objectCreationBlock)(void)) { + return bar(objectCreationBlock); +} + +void bar2(id(*)(void)); +void foo2(id <NSObject>(*objectCreationBlock)(void)) { + return bar2(objectCreationBlock); +} + +void bar3(id(*)()); +void foo3(id (*objectCreationBlock)(int)) { + return bar3(objectCreationBlock); +} + +void bar4(id(^)()); +void foo4(id (^objectCreationBlock)(int)) { + return bar4(objectCreationBlock); +} + +void bar5(id(^)(void)); +void foo5(id (^objectCreationBlock)(int)) { + return bar5(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)(int)', expected 'id (^)(void)'}} +} + +void bar6(id(^)(int)); +void foo6(id (^objectCreationBlock)()) { + return bar6(objectCreationBlock); // expected-error {{incompatible block pointer types passing 'id (^)()', expected 'id (^)(int)'}} +} + +void foo7(id (^x)(int)) { + if (x) { } +} + +@interface itf +@end + +void foo8() { + void *P = ^(itf x) {}; // expected-error {{Objective-C interface type 'itf' cannot be passed by value}} + P = ^itf(int x) {}; // expected-error {{Objective-C interface type 'itf' cannot be returned by value}} + P = ^itf() {}; // expected-error {{Objective-C interface type 'itf' cannot be returned by value}} + P = ^itf{}; // expected-error {{Objective-C interface type 'itf' cannot be returned by value}} +} diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m new file mode 100644 index 000000000000..92bec27c6783 --- /dev/null +++ b/test/SemaObjC/call-super-2.m @@ -0,0 +1,98 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stddef.h> + +typedef struct objc_object *id; +id objc_getClass(const char *s); + +@interface Object +@end + +@protocol Func ++ (int) class_func0; +- (int) instance_func0; +@end + +@interface Derived: Object ++ (int) class_func1; ++ (int) class_func2; ++ (int) class_func3; ++ (int) class_func4; ++ (int) class_func5; ++ (int) class_func6; ++ (int) class_func7; +- (int) instance_func1; +- (int) instance_func2; +- (int) instance_func3; +- (int) instance_func4; +- (int) instance_func5; +- (int) instance_func6; +- (int) instance_func7; +@end + +@implementation Derived ++ (int) class_func1 +{ + int i = (size_t)[self class_func0]; // expected-warning {{method '-class_func0' not found (return type defaults to 'id')}} + return i + (size_t)[super class_func0]; // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}} +} ++ (int) class_func2 +{ + int i = [(id <Func>)self class_func0]; + i += [(id <Func>)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} + i += [(Class <Func>)self class_func0]; // expected-error {{protocol qualified 'Class' is unsupported}} + return i + [(Class <Func>)super class_func0]; // expected-error {{protocol qualified 'Class' is unsupported}} // expected-error {{cannot cast 'super' (it isn't an expression)}} +} ++ (int) class_func3 +{ + return [(Object <Func> *)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} ++ (int) class_func4 +{ + return [(Derived <Func> *)super class_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} ++ (int) class_func5 +{ + int i = (size_t)[Derived class_func0]; // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}} + return i + (size_t)[Object class_func0]; // expected-warning {{method '+class_func0' not found (return type defaults to 'id')}} +} ++ (int) class_func6 +{ + return (size_t)[objc_getClass("Object") class_func1]; // GCC warns about this +} ++ (int) class_func7 +{ + return [objc_getClass("Derived") class_func1]; +} +- (int) instance_func1 +{ + int i = (size_t)[self instance_func0]; // expected-warning {{method '-instance_func0' not found (return type defaults to 'id'))}} + return i + (size_t)[super instance_func0]; // expected-warning {{method '-instance_func0' not found (return type defaults to 'id')}} +} +- (int) instance_func2 +{ + return [(id <Func>)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} +- (int) instance_func3 +{ + return [(Object <Func> *)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} +- (int) instance_func4 +{ + return [(Derived <Func> *)super instance_func0]; // expected-error {{cannot cast 'super' (it isn't an expression)}} +} +- (int) instance_func5 +{ + int i = (size_t)[Derived instance_func1]; // expected-warning {{method '+instance_func1' not found (return type defaults to 'id')}} + return i + (size_t)[Object instance_func1]; // expected-warning {{method '+instance_func1' not found (return type defaults to 'id')}} +} +- (int) instance_func6 +{ + return (size_t)[objc_getClass("Object") class_func1]; +} +- (int) instance_func7 +{ + return [objc_getClass("Derived") class_func1]; +} +@end + diff --git a/test/SemaObjC/catch-stmt.m b/test/SemaObjC/catch-stmt.m new file mode 100644 index 000000000000..6dcbcdebfba4 --- /dev/null +++ b/test/SemaObjC/catch-stmt.m @@ -0,0 +1,13 @@ +// RUN: clang-cc -verify %s + +@protocol P; + +void f() { + @try { + } @catch (void a) { // expected-error{{@catch parameter is not a pointer to an interface type}} + } @catch (int) { // expected-error{{@catch parameter is not a pointer to an interface type}} + } @catch (int *b) { // expected-error{{@catch parameter is not a pointer to an interface type}} + } @catch (id <P> c) { // expected-error{{illegal qualifiers on @catch parameter}} + } +} + diff --git a/test/SemaObjC/category-1.m b/test/SemaObjC/category-1.m new file mode 100644 index 000000000000..6ae775848e78 --- /dev/null +++ b/test/SemaObjC/category-1.m @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface MyClass1 @end + +@protocol p1,p2,p3; + +@interface MyClass1 (Category1) <p1> // expected-warning {{cannot find protocol definition for 'p1'}} expected-note {{previous definition is here}} +@end + +@interface MyClass1 (Category1) // expected-warning {{duplicate definition of category 'Category1' on interface 'MyClass1'}} +@end + +@interface MyClass1 (Category3) +@end + +@interface MyClass1 (Category4) @end // expected-note {{previous definition is here}} +@interface MyClass1 (Category5) @end +@interface MyClass1 (Category6) @end +@interface MyClass1 (Category7) @end // expected-note {{previous definition is here}} +@interface MyClass1 (Category8) @end // expected-note {{previous definition is here}} + + +@interface MyClass1 (Category4) @end // expected-warning {{duplicate definition of category 'Category4' on interface 'MyClass1'}} +@interface MyClass1 (Category7) @end // expected-warning {{duplicate definition of category 'Category7' on interface 'MyClass1'}} +@interface MyClass1 (Category8) @end // expected-warning {{duplicate definition of category 'Category8' on interface 'MyClass1'}} + + +@protocol p3 @end + +@interface MyClass1 (Category) <p2, p3> @end // expected-warning {{cannot find protocol definition for 'p2'}} + +@interface MyClass (Category) @end // expected-error {{cannot find interface declaration for 'MyClass'}} + +@class MyClass2; + +@interface MyClass2 (Category) @end // expected-error {{cannot find interface declaration for 'MyClass2'}} + +@interface XCRemoteComputerManager +@end + +@interface XCRemoteComputerManager() +@end + +@interface XCRemoteComputerManager() +@end + +@interface XCRemoteComputerManager(x) // expected-note {{previous definition is here}} +@end + +@interface XCRemoteComputerManager(x) // expected-warning {{duplicate definition of category 'x' on interface 'XCRemoteComputerManager'}} +@end + +@implementation XCRemoteComputerManager +@end + + diff --git a/test/SemaObjC/category-method-lookup-2.m b/test/SemaObjC/category-method-lookup-2.m new file mode 100644 index 000000000000..76048cc2f74c --- /dev/null +++ b/test/SemaObjC/category-method-lookup-2.m @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef struct objc_class *Class; +@interface NSObject +- (Class)class; +@end +@interface Bar : NSObject +@end +@interface Bar (Cat) +@end + +// NOTE: No class implementation for Bar precedes this category definition. +@implementation Bar (Cat) + +// private method. ++ classMethod { return self; } + +- instanceMethod { + [[self class] classMethod]; +} + +@end diff --git a/test/SemaObjC/category-method-lookup.m b/test/SemaObjC/category-method-lookup.m new file mode 100644 index 000000000000..bda465783b5d --- /dev/null +++ b/test/SemaObjC/category-method-lookup.m @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Foo +@end +@implementation Foo +@end + +@implementation Foo(Whatever) ++(float)returnsFloat { return 7.0; } +@end + +@interface Foo (MoreStuff) ++(int)returnsInt; +@end + +@implementation Foo (MoreStuff) ++(int)returnsInt { + return 0; +} + ++(void)returnsNothing { +} +-(int)callsReturnsInt { + float f = [Foo returnsFloat]; // GCC doesn't find this method (which is a bug IMHO). + [Foo returnsNothing]; + return [Foo returnsInt]; +} +@end + +int main() {return 0;} + diff --git a/test/SemaObjC/check-dup-decl-methods-1.m b/test/SemaObjC/check-dup-decl-methods-1.m new file mode 100644 index 000000000000..ae0cab0b5d41 --- /dev/null +++ b/test/SemaObjC/check-dup-decl-methods-1.m @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface SUPER +- (int) meth; ++ (int) foobar; +@end + +@interface T @end + +@interface class1 : SUPER +- (int) meth; // expected-note {{previous declaration is here}} +- (int*) meth; // expected-error {{duplicate declaration of method 'meth'}} +- (T*) meth1; +- (T*) meth1; ++ (T*) meth1; +@end + +@interface class1(cat) +- (int) catm : (char)ch1; // expected-note {{previous declaration is here}} +- (int) catm1 : (char)ch : (int)i; +- (int) catm : (char*)ch1; // expected-error {{duplicate declaration of method 'catm:'}} ++ (int) catm1 : (char)ch : (int)i; ++ (T*) meth1; +@end + +@interface class1(cat1) ++ (int) catm1 : (char)ch : (int)i; // expected-note {{previous declaration is here}} ++ (T*) meth1; // expected-note {{previous declaration is here}} ++ (int) catm1 : (char)ch : (int*)i; // expected-error {{duplicate declaration of method 'catm1::'}} ++ (T**) meth1; // expected-error {{duplicate declaration of method 'meth1'}} ++ (int) foobar; +@end + +@protocol P +- (int) meth; // expected-note {{previous declaration is here}} +- (int*) meth; // expected-error {{duplicate declaration of method 'meth'}} +@end + diff --git a/test/SemaObjC/check-dup-objc-decls-1.m b/test/SemaObjC/check-dup-objc-decls-1.m new file mode 100644 index 000000000000..1dfaf0905083 --- /dev/null +++ b/test/SemaObjC/check-dup-objc-decls-1.m @@ -0,0 +1,39 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Foo // expected-note {{previous definition is here}} +@end + +float Foo; // expected-error {{redefinition of 'Foo' as different kind of symbol}} + +@class Bar; // expected-note {{previous definition is here}} + +typedef int Bar; // expected-error {{redefinition of 'Bar' as different kind of symbol}} + +@implementation FooBar // expected-warning {{cannot find interface declaration for 'FooBar'}} +@end + + +typedef int OBJECT; // expected-note {{previous definition is here}} + +@class OBJECT ; // expected-error {{redefinition of 'OBJECT' as different kind of symbol}} + + +typedef int Gorf; // expected-note {{previous definition is here}} + +@interface Gorf @end // expected-error {{redefinition of 'Gorf' as different kind of symbol}} expected-note {{previous definition is here}} + +void Gorf() // expected-error {{redefinition of 'Gorf' as different kind of symbol}} +{ + int Bar, Foo, FooBar; +} + +@protocol P -im1; @end +@protocol Q -im2; @end +@interface A<P> @end // expected-note {{previous definition is here}} +@interface A<Q> @end // expected-error {{duplicate interface definition for class 'A'}} + +@protocol PP<P> @end // expected-note {{previous definition is here}} +@protocol PP<Q> @end // expected-warning {{duplicate protocol definition of 'PP'}} + +@interface A(Cat)<P> @end // expected-note {{previous definition is here}} +@interface A(Cat)<Q> @end // expected-warning {{duplicate definition of category 'Cat' on interface 'A'}} diff --git a/test/SemaObjC/class-bitfield.m b/test/SemaObjC/class-bitfield.m new file mode 100644 index 000000000000..01b532464c28 --- /dev/null +++ b/test/SemaObjC/class-bitfield.m @@ -0,0 +1,37 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +@interface X +{ + int a : -1; // expected-error{{bit-field 'a' has negative width}} + + // rdar://6081627 + int b : 33; // expected-error{{size of bit-field 'b' exceeds size of its type (32 bits)}} + + int c : (1 + 0.25); // expected-error{{expression is not an integer constant expression}} + int d : (int)(1 + 0.25); + + // rdar://6138816 + int e : 0; // expected-error {{bit-field 'e' has zero width}} +} +@end + +@interface Base { + int i; +} +@end + +@interface WithBitfields: Base { + void *isa; // expected-note {{previous definition is here}} + unsigned a: 5; + signed b: 4; + int c: 5; // expected-note {{previous definition is here}} +} +@end + +@implementation WithBitfields { + char *isa; // expected-error {{instance variable 'isa' has conflicting type: 'char *' vs 'void *'}} + unsigned a: 5; + signed b: 4; + int c: 3; // expected-error {{instance variable 'c' has conflicting bitfield width}} +} +@end diff --git a/test/SemaObjC/class-conforming-protocol-1.m b/test/SemaObjC/class-conforming-protocol-1.m new file mode 100644 index 000000000000..a9712b23a6a8 --- /dev/null +++ b/test/SemaObjC/class-conforming-protocol-1.m @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol P1 @end +@protocol P2 @end +@protocol P3 @end + +@interface INTF +- (INTF*) METH1; // expected-note {{previous declaration is here}} +- (INTF<P1>*) METH1; // expected-error {{duplicate declaration of method 'METH1'}} + +- (INTF<P1,P2>*) METH2; +- (INTF<P2,P1>*) METH2; // expected-note {{previous declaration is here}} +- (INTF<P2,P1,P3>*) METH2; // expected-error {{duplicate declaration of method 'METH2'}} + +- (INTF<P2,P1,P3>*) METH3; +- (INTF<P3,P1,P2, P3>*) METH3; + +@end + +INTF<P2,P1,P3>* p1; + diff --git a/test/SemaObjC/class-conforming-protocol-2.m b/test/SemaObjC/class-conforming-protocol-2.m new file mode 100644 index 000000000000..7b218bdbd803 --- /dev/null +++ b/test/SemaObjC/class-conforming-protocol-2.m @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol NSWindowDelegate @end + +@interface NSWindow +- (void)setDelegate:(id <NSWindowDelegate>)anObject; +- (id <NSWindowDelegate>) delegate; +@end + +@protocol IBStringsTableWindowDelegate <NSWindowDelegate> +@end + +@interface IBStringsTableWindow : NSWindow {} +@end + +@implementation IBStringsTableWindow +- (void)setDelegate:(id <IBStringsTableWindowDelegate>)delegate { +} +- (id <IBStringsTableWindowDelegate>)delegate { + return 0; +} +@end diff --git a/test/SemaObjC/class-def-test-1.m b/test/SemaObjC/class-def-test-1.m new file mode 100644 index 000000000000..da8a3267662f --- /dev/null +++ b/test/SemaObjC/class-def-test-1.m @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol SUPER; + +@interface SUPER <SUPER> @end // expected-warning {{cannot find protocol definition for 'SUPER'}} + +typedef int INTF; // expected-note {{previous definition is here}} + +@interface INTF @end // expected-error {{redefinition of 'INTF' as different kind of symbol}} + +@interface OBJECT @end // expected-note {{previous definition is here}} + +@interface INTF1 : OBJECT @end // expected-note {{previous definition is here}} + +@interface INTF1 : OBJECT @end // expected-error {{duplicate interface definition for class 'INTF1'}} + +typedef int OBJECT; // expected-error {{redefinition of 'OBJECT' as different kind of symbol}} + +typedef int OBJECT2; // expected-note {{previous definition is here}} +@interface INTF2 : OBJECT2 @end // expected-error {{redefinition of 'OBJECT2' as different kind of symbol}} + + +@protocol PROTO; + +@interface INTF3 : PROTO @end // expected-error {{cannot find interface declaration for 'PROTO', superclass of 'INTF3'}} + +// Make sure we allow the following (for GCC compatibility). +@interface NSObject @end +typedef NSObject TD_NSObject; +@interface XCElementUnit : TD_NSObject {} +@end + + diff --git a/test/SemaObjC/class-extension-dup-methods.m b/test/SemaObjC/class-extension-dup-methods.m new file mode 100644 index 000000000000..f50b293ade36 --- /dev/null +++ b/test/SemaObjC/class-extension-dup-methods.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Foo +- (int) garf; // expected-note {{ previous declaration is here}} +- (int) OK; ++ (int) cgarf; // expected-note {{ previous declaration is here}} +- (int) InstMeth; +@end + +@interface Foo() +- (void) garf; // expected-error {{duplicate declaration of method 'garf'}} ++ (void) cgarf; // expected-error {{duplicate declaration of method 'cgarf'}} ++ (int) InstMeth; +- (int) OK; +@end diff --git a/test/SemaObjC/class-impl-1.m b/test/SemaObjC/class-impl-1.m new file mode 100644 index 000000000000..5a67bef3d605 --- /dev/null +++ b/test/SemaObjC/class-impl-1.m @@ -0,0 +1,40 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef int INTF3; // expected-note {{previous definition is here}} + +@interface SUPER @end // expected-note {{previous definition is here}} + +@interface OBJECT @end + +@interface INTF : OBJECT +@end + +@implementation INTF @end + +@implementation INTF // expected-error {{reimplementation of class 'INTF'}} +@end + + +@interface INTF1 : OBJECT +@end + +@implementation INTF1 : SUPER // expected-error {{conflicting super class name 'SUPER'}} +@end + +@interface INTF2 +@end + +@implementation INTF2 : SUPR // expected-error {{cannot find interface declaration for 'SUPR', superclass of 'INTF2'}} +@end + +@implementation INTF3 @end // expected-error {{redefinition of 'INTF3' as different kind of symbol}} + +@implementation INTF4 @end // expected-warning {{cannot find interface declaration for 'INTF4'}} + +@class INTF5; + +@implementation INTF5 { // expected-warning {{cannot find interface declaration for 'INTF5'}} + int x; +} +@end + diff --git a/test/SemaObjC/class-method-lookup.m b/test/SemaObjC/class-method-lookup.m new file mode 100644 index 000000000000..cba93825a4e0 --- /dev/null +++ b/test/SemaObjC/class-method-lookup.m @@ -0,0 +1,46 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface MyBase +- (void) rootInstanceMethod; +@end + +@interface MyIntermediate: MyBase +@end + +@interface MyDerived: MyIntermediate +- (void) instanceMethod; ++ (void) classMethod; +@end + +@implementation MyDerived +- (void) instanceMethod { +} + ++ (void) classMethod { /* If a class method is not found, the root */ + [self rootInstanceMethod]; /* class is searched for an instance method */ + [MyIntermediate rootInstanceMethod]; /* with the same name. */ + + [self instanceMethod];// expected-warning {{'-instanceMethod' not found (return type defaults to 'id')}} + [MyDerived instanceMethod];// expected-warning {{'+instanceMethod' not found (return type defaults to 'id')}} +} +@end + +@interface Object @end + +@interface Class1 +- (void)setWindow:(Object *)wdw; +@end + +@interface Class2 +- (void)setWindow:(Class1 *)window; +@end + +#define nil (void*)0 + +id foo(void) { + Object *obj; + id obj2 = obj; + [obj setWindow:nil]; // expected-warning {{Object may not respond to 'setWindow:'}} + + return obj; +} diff --git a/test/SemaObjC/class-method-self.m b/test/SemaObjC/class-method-self.m new file mode 100644 index 000000000000..d36bc8cbc91b --- /dev/null +++ b/test/SemaObjC/class-method-self.m @@ -0,0 +1,26 @@ +// RUN: clang-cc -verify %s + +typedef struct objc_class *Class; +@interface XX + +- (void)addObserver:(XX*)o; + +@end + +@interface YY + ++ (void)classMethod; + +@end + +@implementation YY + +static XX *obj; + ++ (void)classMethod { + [obj addObserver:self]; + Class whatever; + [obj addObserver:whatever]; // GCC warns about this. +} +@end + diff --git a/test/SemaObjC/class-property-access.m b/test/SemaObjC/class-property-access.m new file mode 100644 index 000000000000..663b87d2ff18 --- /dev/null +++ b/test/SemaObjC/class-property-access.m @@ -0,0 +1,12 @@ +// RUN: clang -fsyntax-only -verify %s + +@interface Test {} ++ (Test*)one; +- (int)two; +@end + +int main () +{ + return Test.one.two; +} + diff --git a/test/SemaObjC/class-proto-1.m b/test/SemaObjC/class-proto-1.m new file mode 100644 index 000000000000..8f0f3d8826c2 --- /dev/null +++ b/test/SemaObjC/class-proto-1.m @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface INTF1 @end + +@protocol p1,p2,p3; + +@protocol p1; + +@protocol PROTO1 +- (INTF1<p1>*) meth; +@end + +@protocol p1 @end + +@interface I1 <p1> @end + +@interface E1 <p2> @end // expected-warning {{cannot find protocol definition for 'p2'}} + +@protocol p2 @end + + +@interface I2 <p1,p2> @end + +@interface E2 <p1,p2,p3> @end // expected-warning {{cannot find protocol definition for 'p3'}} + +@class U1, U2; + +@interface E3 : U1 @end // expected-error {{cannot find interface declaration for 'U1', superclass of 'E3'}} + + +@interface I3 : E3 @end + +@interface U2 @end + +@interface I4 : U2 <p1,p2> +@end diff --git a/test/SemaObjC/cocoa-pth.m b/test/SemaObjC/cocoa-pth.m new file mode 100644 index 000000000000..dc806dfb7c09 --- /dev/null +++ b/test/SemaObjC/cocoa-pth.m @@ -0,0 +1,7 @@ +// RUN: clang-cc -mcpu=pentium4 -emit-pth -o %t %s && +// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s && +// RUN: clang-cc -mcpu=pentium4 -token-cache %t %s -E %s -o /dev/null +#ifdef __APPLE__ +#include <Cocoa/Cocoa.h> +#endif + diff --git a/test/SemaObjC/cocoa.m b/test/SemaObjC/cocoa.m new file mode 100644 index 000000000000..b73b3c4ccd33 --- /dev/null +++ b/test/SemaObjC/cocoa.m @@ -0,0 +1,5 @@ +// RUN: clang-cc -mcpu=pentium4 %s -print-stats +#ifdef __APPLE__ +#include <Cocoa/Cocoa.h> +#endif + diff --git a/test/SemaObjC/compare-qualified-id.m b/test/SemaObjC/compare-qualified-id.m new file mode 100644 index 000000000000..86845c0358d2 --- /dev/null +++ b/test/SemaObjC/compare-qualified-id.m @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @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 +typedef struct {} NSFastEnumerationState; +@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; @end +@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; @end +@interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey; @end +extern NSString * const NSTaskDidTerminateNotification; + +@interface XCPropertyExpansionContext : NSObject <NSCopying> { + NSMutableDictionary * _propNamesToPropValuesCache; +} @end + +@protocol XCPropertyValues <NSObject, NSCopying> +- (NSString *)evaluateAsStringInContext:(XCPropertyExpansionContext *)context withNestingState:(const void *)state; +@end + +@implementation XCPropertyExpansionContext +- (NSString *)expandedValueForProperty:(NSString *)property { + id <XCPropertyValues> cachedValueNode = [_propNamesToPropValuesCache objectForKey:property]; // expected-warning {{method '-objectForKey:' not found (return type defaults to 'id')}} + if (cachedValueNode == ((void *)0)) { } + NSString * expandedValue = [cachedValueNode evaluateAsStringInContext:self withNestingState:((void *)0)]; + return expandedValue; +} + diff --git a/test/SemaObjC/compatible-protocol-qualified-types.m b/test/SemaObjC/compatible-protocol-qualified-types.m new file mode 100644 index 000000000000..3c27b5f0d3cd --- /dev/null +++ b/test/SemaObjC/compatible-protocol-qualified-types.m @@ -0,0 +1,75 @@ +// RUN: clang-cc -pedantic -fsyntax-only -verify %s +typedef signed char BOOL; + +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject +- (BOOL)isEqual:(id)object; +@end + +@protocol NSCoding +- (void)encodeWithCoder:(NSCoder *)aCoder; +@end + +@interface NSObject <NSObject> {} +@end + +typedef float CGFloat; + +@interface NSResponder : NSObject <NSCoding> {} +@end + +@protocol XCSelectionSource; + +@interface XCSelection : NSResponder {} +- (NSObject <XCSelectionSource> *) source; +@end + +extern NSString * const XCActiveSelectionLevel; + +@interface XCActionManager : NSResponder {} ++defaultActionManager; +-selectionAtLevel:(NSString *const)s; +@end + +@implementation XDMenuItemsManager // expected-warning {{cannot find interface declaration for 'XDMenuItemsManager'}} ++ (void)initialize { + id<XCSelectionSource, NSObject> source = + [[[XCActionManager defaultActionManager] selectionAtLevel:XCActiveSelectionLevel] source]; +} +@end + +@protocol NSTextStorageDelegate; +@class NSNotification; + +@interface NSTextStorage : NSObject + +- (void)setDelegate:(id <NSTextStorageDelegate>)delegate; +- (id <NSTextStorageDelegate>)delegate; + +@end + +@protocol NSTextStorageDelegate <NSObject> +@optional + +- (void)textStorageWillProcessEditing:(NSNotification *)notification; +- (void)textStorageDidProcessEditing:(NSNotification *)notification; + +@end + +@interface SKTText : NSObject { + @private + + + NSTextStorage *_contents; +} +@end + +@implementation SKTText + + +- (NSTextStorage *)contents { + [_contents setDelegate:self]; // expected-warning {{incompatible type sending 'SKTText *', expected 'id<NSTextStorageDelegate>'}} +} + +@end diff --git a/test/SemaObjC/comptypes-1.m b/test/SemaObjC/comptypes-1.m new file mode 100644 index 000000000000..8717bd09eb84 --- /dev/null +++ b/test/SemaObjC/comptypes-1.m @@ -0,0 +1,91 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +#define nil (void *)0; +#define Nil (void *)0; + +extern void foo(); + +@protocol MyProtocol +- (void) foo; +@end + +@interface MyClass +@end + +@interface MyOtherClass <MyProtocol> +- (void) foo; +@end + +int main() +{ + id obj = nil; + id<MyProtocol> obj_p = nil; + MyClass *obj_c = nil; + MyOtherClass *obj_cp = nil; + Class obj_C = Nil; + + /* Assigning to an 'id' variable should never + generate a warning. */ + obj = obj_p; /* Ok */ + obj = obj_c; /* Ok */ + obj = obj_cp; /* Ok */ + obj = obj_C; /* Ok */ + + /* Assigning to a 'MyClass *' variable should always generate a + warning, unless done from an 'id'. */ + obj_c = obj; /* Ok */ + obj_c = obj_cp; // // expected-warning {{incompatible pointer types assigning 'MyOtherClass *', expected 'MyClass *'}} + obj_c = obj_C; + + /* Assigning to an 'id<MyProtocol>' variable should generate a + warning if done from a 'MyClass *' (which doesn't implement + MyProtocol), but not from an 'id' or from a 'MyOtherClass *' + (which implements MyProtocol). */ + obj_p = obj; /* Ok */ + obj_p = obj_c; // expected-warning {{incompatible type assigning 'MyClass *', expected 'id<MyProtocol>'}} + obj_p = obj_cp; /* Ok */ + obj_p = obj_C; // Ok + + /* Assigning to a 'MyOtherClass *' variable should always generate + a warning, unless done from an 'id' or an 'id<MyProtocol>' (since + MyOtherClass implements MyProtocol). */ + obj_cp = obj; /* Ok */ + obj_cp = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected 'MyOtherClass *'}} + obj_cp = obj_p; /* Ok */ + obj_cp = obj_C; + + /* Any comparison involving an 'id' must be without warnings. */ + if (obj == obj_p) foo() ; /* Ok */ /*Bogus warning here in 2.95.4*/ + if (obj_p == obj) foo() ; /* Ok */ + if (obj == obj_c) foo() ; /* Ok */ + if (obj_c == obj) foo() ; /* Ok */ + if (obj == obj_cp) foo() ; /* Ok */ + if (obj_cp == obj) foo() ; /* Ok */ + if (obj == obj_C) foo() ; /* Ok */ + if (obj_C == obj) foo() ; /* Ok */ + + /* Any comparison between 'MyClass *' and anything which is not an 'id' + must generate a warning. */ + /* FIXME: GCC considers this a warning ("comparison of distinct pointer types"). */ + /* There is a corresponding FIXME in ASTContext::mergeTypes() */ + if (obj_p == obj_c) foo() ; + + if (obj_c == obj_cp) foo() ; // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'MyOtherClass *')}} + if (obj_cp == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('MyOtherClass *' and 'MyClass *')}} + + if (obj_c == obj_C) foo() ; + if (obj_C == obj_c) foo() ; + + /* Any comparison between 'MyOtherClass *' (which implements + MyProtocol) and an 'id' implementing MyProtocol are Ok. */ + if (obj_cp == obj_p) foo() ; /* Ok */ + if (obj_p == obj_cp) foo() ; /* Ok */ + + + if (obj_p == obj_C) foo() ; + if (obj_C == obj_p) foo() ; + if (obj_cp == obj_C) foo() ; + if (obj_C == obj_cp) foo() ; + + return 0; +} diff --git a/test/SemaObjC/comptypes-2.m b/test/SemaObjC/comptypes-2.m new file mode 100644 index 000000000000..c24b67b15ed1 --- /dev/null +++ b/test/SemaObjC/comptypes-2.m @@ -0,0 +1,37 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#define nil (void *)0; +#define Nil (void *)0; + +@protocol MyProtocol +- (void) foo; +@end + +@interface MyClass +@end + +int main() +{ + id obj = nil; + id<MyProtocol> obj_p = nil; + MyClass *obj_c = nil; + Class obj_C = Nil; + + /* All these casts should generate no warnings. */ + + obj = (id)obj_p; + obj = (id)obj_c; + obj = (id)obj_C; + obj_c = (MyClass *)obj; + obj_c = (MyClass *)obj_p; + obj_c = (MyClass *)obj_C; + obj_p = (id<MyProtocol>)obj; + obj_p = (id<MyProtocol>)obj_c; + obj_p = (id<MyProtocol>)obj_C; + obj_C = (Class)obj; + obj_C = (Class)obj_p; + obj_C = (Class)obj_c; + + + return 0; +} diff --git a/test/SemaObjC/comptypes-3.m b/test/SemaObjC/comptypes-3.m new file mode 100644 index 000000000000..2d8f19d806a7 --- /dev/null +++ b/test/SemaObjC/comptypes-3.m @@ -0,0 +1,64 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#define nil (void *)0; + +extern void foo(); + +@protocol MyProtocolA +- (void) methodA; +@end + +@protocol MyProtocolB +- (void) methodB; +@end + +@protocol MyProtocolAB <MyProtocolA, MyProtocolB> +@end + +@protocol MyProtocolAC <MyProtocolA> +- (void) methodC; +@end + +int main() +{ + id<MyProtocolA> obj_a = nil; + id<MyProtocolB> obj_b = nil; + id<MyProtocolAB> obj_ab = nil; + id<MyProtocolAC> obj_ac = nil; + + obj_a = obj_b; // expected-warning {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolA>'}} + obj_a = obj_ab; /* Ok */ + obj_a = obj_ac; /* Ok */ + + obj_b = obj_a; // expected-warning {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolB>'}} + obj_b = obj_ab; /* Ok */ + obj_b = obj_ac; // expected-warning {{incompatible type assigning 'id<MyProtocolAC>', expected 'id<MyProtocolB>'}} + + obj_ab = obj_a; // expected-warning {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAB>'}} + obj_ab = obj_b; // expected-warning {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAB>'}} + obj_ab = obj_ac; // expected-warning {{incompatible type assigning 'id<MyProtocolAC>', expected 'id<MyProtocolAB>'}} + + obj_ac = obj_a; // expected-warning {{incompatible type assigning 'id<MyProtocolA>', expected 'id<MyProtocolAC>'}} + obj_ac = obj_b; // expected-warning {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAC>'}} + obj_ac = obj_ab; // expected-warning {{incompatible type assigning 'id<MyProtocolAB>', expected 'id<MyProtocolAC>'}} + + if (obj_a == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolA>' and 'id<MyProtocolB>')}} + if (obj_b == obj_a) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolA>')}} + + if (obj_a == obj_ab) foo (); /* Ok */ + if (obj_ab == obj_a) foo (); /* Ok */ + + if (obj_a == obj_ac) foo (); /* Ok */ + if (obj_ac == obj_a) foo (); /* Ok */ + + if (obj_b == obj_ab) foo (); /* Ok */ + if (obj_ab == obj_b) foo (); /* Ok */ + + if (obj_b == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolAC>')}} + if (obj_ac == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolB>')}} + + if (obj_ab == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAB>' and 'id<MyProtocolAC>')}} + if (obj_ac == obj_ab) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolAB>')}} + + return 0; +} diff --git a/test/SemaObjC/comptypes-4.m b/test/SemaObjC/comptypes-4.m new file mode 100644 index 000000000000..598901148a8a --- /dev/null +++ b/test/SemaObjC/comptypes-4.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +extern void foo(); + +@protocol MyProtocol @end + +@interface MyClass @end + +int main() +{ + MyClass <MyProtocol> *obj_p; + MyClass *obj_cp; + + obj_cp = obj_p; + obj_p = obj_cp; + + if (obj_cp == obj_p) + foo(); + + if (obj_p == obj_cp) + foo(); + +} + + diff --git a/test/SemaObjC/comptypes-5.m b/test/SemaObjC/comptypes-5.m new file mode 100644 index 000000000000..afd8a4949ed6 --- /dev/null +++ b/test/SemaObjC/comptypes-5.m @@ -0,0 +1,44 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s + +#define nil (void *)0; + +extern void foo(); + +@protocol MyProtocol +- (void) method; +@end + +@interface MyClass +@end + +@interface MyClass (Addition) <MyProtocol> +- (void) method; +@end + +@interface MyOtherClass : MyClass +@end + +int main() +{ + id <MyProtocol> obj_id_p = nil; + MyClass *obj_c_cat_p = nil; + MyOtherClass *obj_c_super_p = nil; + MyOtherClass<MyProtocol> *obj_c_super_p_q = nil; + MyClass<MyProtocol> *obj_c_cat_p_q = nil; + + obj_c_cat_p = obj_id_p; // expected-warning {{incompatible type assigning 'id<MyProtocol>', expected 'MyClass *'}} + obj_c_super_p = obj_id_p; // expected-warning {{incompatible type assigning 'id<MyProtocol>', expected 'MyOtherClass *'}} + obj_id_p = obj_c_cat_p; /* Ok */ + obj_id_p = obj_c_super_p; /* Ok */ + + if (obj_c_cat_p == obj_id_p) foo(); /* Ok */ + if (obj_c_super_p == obj_id_p) foo() ; /* Ok */ + if (obj_id_p == obj_c_cat_p) foo(); /* Ok */ + if (obj_id_p == obj_c_super_p) foo(); /* Ok */ + + obj_c_cat_p = obj_c_super_p; // ok. + obj_c_cat_p = obj_c_super_p_q; // ok. + obj_c_super_p = obj_c_cat_p_q; // expected-warning {{incompatible pointer types}} + obj_c_cat_p_q = obj_c_super_p; + return 0; +} diff --git a/test/SemaObjC/comptypes-6.m b/test/SemaObjC/comptypes-6.m new file mode 100644 index 000000000000..32176755ef76 --- /dev/null +++ b/test/SemaObjC/comptypes-6.m @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +@interface Derived +@end + +@interface Object @end + +extern Object* foo(void); + +static Derived *test(void) +{ + Derived *m = foo(); // expected-warning {{incompatible pointer types initializing 'Object *', expected 'Derived *'}} + + return m; +} + diff --git a/test/SemaObjC/comptypes-7.m b/test/SemaObjC/comptypes-7.m new file mode 100644 index 000000000000..faca6937cb74 --- /dev/null +++ b/test/SemaObjC/comptypes-7.m @@ -0,0 +1,70 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +#define nil (void *)0; +#define Nil (void *)0; + +extern void foo(); + +@protocol MyProtocol +- (void) method; +@end + +@interface MyClass +@end + +int main() +{ + id obj = nil; + id <MyProtocol> obj_p = nil; + MyClass *obj_c = nil; + Class obj_C = Nil; + + int i = 0; + int *j = nil; + + /* These should all generate warnings. */ + + obj = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'id'}} + obj = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'id'}} + + obj_p = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'id<MyProtocol>'}} + obj_p = j; // expected-warning {{incompatible type assigning 'int *', expected 'id<MyProtocol>'}} + + obj_c = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'MyClass *'}} + obj_c = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'MyClass *'}} + + obj_C = i; // expected-warning {{incompatible integer to pointer conversion assigning 'int', expected 'Class'}} + obj_C = j; // expected-warning {{incompatible pointer types assigning 'int *', expected 'Class'}} + + i = obj; // expected-warning {{incompatible pointer to integer conversion assigning 'id', expected 'int'}} + i = obj_p; // expected-warning {{incompatible pointer to integer conversion assigning 'id<MyProtocol>', expected 'int'}} + i = obj_c; // expected-warning {{incompatible pointer to integer conversion assigning 'MyClass *', expected 'int'}} + i = obj_C; // expected-warning {{incompatible pointer to integer conversion assigning 'Class', expected 'int'}} + + j = obj; // expected-warning {{incompatible pointer types assigning 'id', expected 'int *'}} + j = obj_p; // expected-warning {{incompatible type assigning 'id<MyProtocol>', expected 'int *'}} + j = obj_c; // expected-warning {{incompatible pointer types assigning 'MyClass *', expected 'int *'}} + j = obj_C; // expected-warning {{incompatible pointer types assigning 'Class', expected 'int *'}} + + if (obj == i) foo() ; // expected-warning {{comparison between pointer and integer ('id' and 'int')}} + if (i == obj) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'id')}} + if (obj == j) foo() ; // expected-warning {{comparison of distinct pointer types ('id' and 'int *')}} + if (j == obj) foo() ; // expected-warning {{comparison of distinct pointer types ('int *' and 'id')}} + + if (obj_c == i) foo() ; // expected-warning {{comparison between pointer and integer ('MyClass *' and 'int')}} + if (i == obj_c) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'MyClass *')}} + if (obj_c == j) foo() ; // expected-warning {{comparison of distinct pointer types ('MyClass *' and 'int *')}} + if (j == obj_c) foo() ; // expected-warning {{comparison of distinct pointer types ('int *' and 'MyClass *')}} + + if (obj_p == i) foo() ; // expected-warning {{comparison between pointer and integer ('id<MyProtocol>' and 'int')}} + if (i == obj_p) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'id<MyProtocol>')}} + if (obj_p == j) foo() ; // expected-warning {{comparison of distinct pointer types ('id<MyProtocol>' and 'int *')}} + if (j == obj_p) foo() ; // expected-warning {{comparison of distinct pointer types ('int *' and 'id<MyProtocol>')}} + + if (obj_C == i) foo() ; // expected-warning {{comparison between pointer and integer ('Class' and 'int')}} + if (i == obj_C) foo() ; // expected-warning {{comparison between pointer and integer ('int' and 'Class')}} + if (obj_C == j) foo() ; // expected-warning {{comparison of distinct pointer types ('Class' and 'int *')}} + if (j == obj_C) foo() ; // expected-warning {{comparison of distinct pointer types ('int *' and 'Class')}} + + return 0; +} diff --git a/test/SemaObjC/comptypes-8.m b/test/SemaObjC/comptypes-8.m new file mode 100644 index 000000000000..af9267e499f6 --- /dev/null +++ b/test/SemaObjC/comptypes-8.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol MyProtocol +@end + +id<MyProtocol> obj_p = 0; + +int main() +{ + obj_p = 0; +} + diff --git a/test/SemaObjC/comptypes-9.m b/test/SemaObjC/comptypes-9.m new file mode 100644 index 000000000000..caa93b49e6f3 --- /dev/null +++ b/test/SemaObjC/comptypes-9.m @@ -0,0 +1,86 @@ +// RUN: clang-cc -fsyntax-only %s +// FIXME: This test case tests the patch applied in: http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20080602/006017.html +// Eventually that logic should be treated as an extension. + +typedef signed char BOOL; +typedef int NSInteger; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject +- (BOOL)isEqual:(id)object; +@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 NSArray; + +typedef struct {} NSFastEnumerationState; + +@protocol NSFastEnumeration +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end + +@class NSString; + +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> +- (NSUInteger)count; +- (id)objectAtIndex:(NSUInteger)index; +@end + +typedef unsigned short unichar; + +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> +- (NSUInteger)length; +@end + +@interface NSSimpleCString : NSString +{} + +@end + +@interface NSConstantString : NSSimpleCString @end + +extern void *_NSConstantStringClassReference; + +@interface NSResponder : NSObject <NSCoding> {} +@end + +@class NSDate, NSDictionary, NSError, NSException, NSNotification; + +@interface NSWindowController : NSResponder <NSCoding> {} +@end + +@class PBXBuildLog, PBXBuildLogItem, PBXBuildLogContainerItem, XCWorkQueueCommand, XCBuildLogContainerItemMutationState; + +@protocol PBXBuildLogContainerItems <NSObject> +- (PBXBuildLog *)buildLog; +@end + +@interface PBXBuildLogItem : NSObject {} +- (id <PBXBuildLogContainerItems>)superitem; +@end +@interface PBXBuildResultsModule +@end + +@implementation PBXBuildResultsModule +- (void) revealItems +{ + PBXBuildLogItem *objItem; + PBXBuildLogItem *superitem = [objItem superitem]; +} +@end diff --git a/test/SemaObjC/comptypes-a.m b/test/SemaObjC/comptypes-a.m new file mode 100644 index 000000000000..936c6dfc5de9 --- /dev/null +++ b/test/SemaObjC/comptypes-a.m @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s +typedef signed char BOOL; +typedef int NSInteger; + +@class NSString; + +@protocol PBXCompletionItem +- (NSString *) name; +- (NSInteger)priority; +@end + +extern NSInteger codeAssistantCaseCompareItems(id a, id b, void *context); + +NSInteger codeAssistantCaseCompareItems(id<PBXCompletionItem> a, id<PBXCompletionItem> b, void *context) +{ +} + +@interface TedWantsToVerifyObjCDoesTheRightThing + +- compareThis:(int)a withThat:(id)b; // expected-note {{previous definition is here}} + +@end + +@implementation TedWantsToVerifyObjCDoesTheRightThing + +- compareThis:(id<PBXCompletionItem>) + a // expected-warning {{conflicting parameter types in implementation of 'compareThis:withThat:': 'int' vs 'id<PBXCompletionItem>'}} + withThat:(id<PBXCompletionItem>)b { + return self; +} + +@end diff --git a/test/SemaObjC/comptypes-legal.m b/test/SemaObjC/comptypes-legal.m new file mode 100644 index 000000000000..cd7f89b61d0d --- /dev/null +++ b/test/SemaObjC/comptypes-legal.m @@ -0,0 +1,37 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s + +@protocol NSObject +@end +@interface NSObject <NSObject> { +} +@end +@interface NSString : NSObject +@end +void __setRetained(id *ivar, id value, NSObject **o) { + *ivar = value; +} +static NSString *_logProcessPrefix = 0; +void func() { + __setRetained(&_logProcessPrefix, _logProcessPrefix, &_logProcessPrefix); +} +@implementation NSObject (ScopeAdditions) ++ (void)setObjectLogProcessPrefix:(NSString *)processPrefix { + __setRetained(&_logProcessPrefix, processPrefix, &_logProcessPrefix); +} +@end + +@class Derived; + +NSObject *ExternFunc (NSObject *filePath, NSObject *key); +typedef id FuncSignature (NSObject *arg1, Derived *arg2); + +@interface Derived: NSObject ++ (void)registerFunc:(FuncSignature *)function; +@end + +void foo(void) +{ + // GCC currently allows this (it has some fiarly new support for covariant return types and contravariant argument types). + // Since registerFunc: expects a Derived object as it's second argument, I don't know why this would be legal. + [Derived registerFunc: ExternFunc]; // expected-warning{{incompatible pointer types sending 'NSObject *(NSObject *, NSObject *)', expected 'FuncSignature *'}} +} diff --git a/test/SemaObjC/conditional-expr-2.m b/test/SemaObjC/conditional-expr-2.m new file mode 100644 index 000000000000..08758488c540 --- /dev/null +++ b/test/SemaObjC/conditional-expr-2.m @@ -0,0 +1,29 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface A +@end +@interface B +@end + +void f0(int cond, A *a, B *b) { + // Ensure that we can still send a message to result of incompatible + // conditional expression. + [ (cond ? a : b) test ]; // expected-warning{{incompatible operand types ('A *' and 'B *')}} expected-warning {{method '-test' not found}} +} + +@interface NSKey @end +@interface KeySub : NSKey @end + +@interface UpdatesList @end + +void foo (int i, NSKey *NSKeyValueCoding_NullValue, UpdatesList *nukedUpdatesList) +{ + id obj; + NSKey *key; + KeySub *keysub; + + obj = i ? NSKeyValueCoding_NullValue : nukedUpdatesList; // expected-warning{{incompatible operand types ('NSKey *' and 'UpdatesList *')}} + key = i ? NSKeyValueCoding_NullValue : nukedUpdatesList; // expected-warning{{incompatible operand types ('NSKey *' and 'UpdatesList *')}} + key = i ? NSKeyValueCoding_NullValue : keysub; + keysub = i ? NSKeyValueCoding_NullValue : keysub; // expected-warning{{incompatible pointer types assigning 'NSKey *', expected 'KeySub *'}} +} diff --git a/test/SemaObjC/conditional-expr-3.m b/test/SemaObjC/conditional-expr-3.m new file mode 100644 index 000000000000..31d4834ff0af --- /dev/null +++ b/test/SemaObjC/conditional-expr-3.m @@ -0,0 +1,67 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol P0 +@end +@protocol P1 +@end +@protocol P2 +@end + +@interface A <P0> +@end + +@interface B : A +@end + +void bar(id x); +void barP0(id<P0> x); +void barP1(id<P1> x); +void barP2(id<P2> x); + +void f0(A *a) { + id l = a; +} + +void f1(id x, A *a) { + id<P0> l = a; +} + +void f2(id<P1> x) { + id<P0> l = x; // expected-warning {{incompatible type initializing 'id<P1>', expected 'id<P0>'}} +} + +void f3(A *a) { + id<P1> l = a; // expected-warning {{incompatible type initializing 'A *', expected 'id<P1>'}} +} + +void f4(int cond, id x, A *a) { + bar(cond ? x : a); +} + +void f5(int cond, A *a, B *b) { + bar(cond ? a : b); +} + +void f6(int cond, id x, A *a) { + bar(cond ? (id<P0, P1>) x : a); +} + +void f7(int cond, id x, A *a) { + bar(cond ? a : (id<P0, P1>) x); +} + +void f8(int cond, id<P0,P1> x0, id<P0,P2> x1) { + barP0(cond ? x0 : x1); +} + +void f9(int cond, id<P0,P1> x0, id<P0,P2> x1) { + barP1(cond ? x0 : x1); +} + +void f10(int cond, id<P0,P1> x0, id<P0,P2> x1) { + barP2(cond ? x0 : x1); +} + +int f11(int cond, A* a, B* b) { + return (cond? b : a)->x; // expected-error{{'A' does not have a member named 'x'}} +} diff --git a/test/SemaObjC/conditional-expr-4.m b/test/SemaObjC/conditional-expr-4.m new file mode 100644 index 000000000000..7d50ba60750c --- /dev/null +++ b/test/SemaObjC/conditional-expr-4.m @@ -0,0 +1,78 @@ +// RUN: clang-cc -fsyntax-only %s +// XFAIL +// <rdar://problem/6212771> + +#define nil ((void*) 0) + +@interface A +@property int x; +@end + +@interface B : A +@end + +// Basic checks... +id f0(int cond, id a, void *b) { + return cond ? a : b; +} +A *f0_a(int cond, A *a, void *b) { + return cond ? a : b; +} + +id f1(int cond, id a) { + return cond ? a : nil; +} +A *f1_a(int cond, A *a) { + return cond ? a : nil; +} + +// Check interaction with qualified id + +@protocol P0 @end + +id f2(int cond, id<P0> a, void *b) { + return cond ? a : b; +} + +id f3(int cond, id<P0> a) { + return cond ? a : nil; +} + +// Check that result actually has correct type. + +// Using properties is one way to find the compiler internal type of a +// conditional expression. Simple assignment doesn't work because if +// the type is id then it can be implicitly promoted. +@protocol P1 +@property int x; +@end + +int f5(int cond, id<P1> a, id<P1> b) { + // This should result in something with id type, currently. This is + // almost certainly wrong and should be fixed. + return (cond ? a : b).x; // expected-error {{member reference base type ('id') is not a structure or union}} +} +int f5_a(int cond, A *a, A *b) { + return (cond ? a : b).x; +} +int f5_b(int cond, A *a, B *b) { + return (cond ? a : b).x; +} + +int f6(int cond, id<P1> a, void *b) { + // This should result in something with id type, currently. + return (cond ? a : b).x; // expected-error {{member reference base type ('id') is not a structure or union}} +} + +int f7(int cond, id<P1> a) { + return (cond ? a : nil).x; +} + +int f8(int cond, id<P1> a, A *b) { + // GCC regards this as a warning (comparison of distinct Objective-C types lacks a cast) + return a == b; // expected-error {{invalid operands to binary expression}} +} + +int f9(int cond, id<P1> a, A *b) { + return (cond ? a : b).x; // expected-error {{incompatible operand types}} +} diff --git a/test/SemaObjC/conditional-expr.m b/test/SemaObjC/conditional-expr.m new file mode 100644 index 000000000000..ec3613b2aa9b --- /dev/null +++ b/test/SemaObjC/conditional-expr.m @@ -0,0 +1,44 @@ +// RUN: clang-cc -fsyntax-only -verify -pedantic %s +@protocol NSObject +@end + +@protocol DTOutputStreams <NSObject> +@end + +@interface DTFilterOutputStream <DTOutputStreams> +- nextOutputStream; +@end + +@implementation DTFilterOutputStream +- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream { + id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; + self = nextOutputStream; + return nextOutputStream ? nextOutputStream : self; +} +- nextOutputStream { + return self; +} +@end + +@interface DTFilterOutputStream2 +- nextOutputStream; +@end + +@implementation DTFilterOutputStream2 // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'nextOutputStream' not found}} +- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream { + id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; + // GCC warns about both of these. + self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream2 *'}} + return nextOutputStream ? nextOutputStream : self; +} +@end + +// No @interface declaration for DTFilterOutputStream3 +@implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}} +- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream { + id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // expected-warning {{method '-nextOutputStream' not found (return type defaults to 'id')}} + // GCC warns about both of these as well (no errors). + self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream3 *'}} + return nextOutputStream ? nextOutputStream : self; +} +@end diff --git a/test/SemaObjC/conflicting-ivar-test-1.m b/test/SemaObjC/conflicting-ivar-test-1.m new file mode 100644 index 000000000000..20ed15722477 --- /dev/null +++ b/test/SemaObjC/conflicting-ivar-test-1.m @@ -0,0 +1,86 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface INTF +{ +@public + int IVAR; // expected-note {{previous definition is here}} +} +@end + +@implementation INTF +{ +@private + + int XIVAR; // expected-error {{conflicting instance variable names: 'XIVAR' vs 'IVAR'}} +} +@end + + + +@interface INTF1 +{ +@public + int IVAR; + int IVAR1; // expected-error {{inconsistent number of instance variables specified}} +} +@end + +@implementation INTF1 +{ +@private + + int IVAR; +} +@end + + +@interface INTF2 +{ +@public + int IVAR; +} +@end + +@implementation INTF2 +{ +@private + + int IVAR; + int IVAR1; // expected-error {{inconsistent number of instance variables specified}} +} +@end + + +@interface INTF3 +{ +@public + int IVAR; // expected-note {{previous definition is here}} +} +@end + +@implementation INTF3 +{ +@private + + short IVAR; // expected-error {{instance variable 'IVAR' has conflicting type: 'short' vs 'int'}} +} +@end + +@implementation INTF4 // expected-warning {{cannot find interface declaration for 'INTF4'}} +{ +@private + + short IVAR; +} +@end + +@interface INTF5 +{ + char * ch; +} +@end + +@implementation INTF5 +{ +} +@end diff --git a/test/SemaObjC/continuation-class-err.m b/test/SemaObjC/continuation-class-err.m new file mode 100644 index 000000000000..f516a9326a95 --- /dev/null +++ b/test/SemaObjC/continuation-class-err.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface ReadOnly +{ + id _object; + id _object1; +} +@property(readonly) id object; +@property(readwrite, assign) id object1; +@end + +@interface ReadOnly () +@property(readwrite, copy) id object; +@property(readonly) id object1; // expected-error {{attribute of property in continuation class of 'ReadOnly' can only be 'readwrite'}} +@end diff --git a/test/SemaObjC/duplicate-ivar-check.m b/test/SemaObjC/duplicate-ivar-check.m new file mode 100644 index 000000000000..7cab982e6e21 --- /dev/null +++ b/test/SemaObjC/duplicate-ivar-check.m @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface B1 { +@public + double fill_B; // expected-note {{previous declaration is here}} + unsigned : 0; +} +@end + +@interface B : B1 { +@public + int one; // expected-note {{previous declaration is here}} + int one; // expected-error {{duplicate member 'one'}} + unsigned : 0; +} +@end + +@interface A : B { +@public + int fill_B; // expected-error {{duplicate member 'fill_B'}} +} +@end diff --git a/test/SemaObjC/enhanced-proto-2.m b/test/SemaObjC/enhanced-proto-2.m new file mode 100644 index 000000000000..0450d7ba9deb --- /dev/null +++ b/test/SemaObjC/enhanced-proto-2.m @@ -0,0 +1,21 @@ +// RUN: clang-cc -verify %s + +@protocol MyProto1 +@optional +- (void) FOO; +@optional +- (void) FOO; +@optional +- (void) REQ; +@optional +@end + +@interface MyProto2 <MyProto1> +- (void) FOO2; +- (void) FOO3; +@end + +@implementation MyProto2 +- (void) FOO2{} +- (void) FOO3{} +@end diff --git a/test/SemaObjC/error-property-gc-attr.m b/test/SemaObjC/error-property-gc-attr.m new file mode 100644 index 000000000000..a44ba4f3768d --- /dev/null +++ b/test/SemaObjC/error-property-gc-attr.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fobjc-gc -fsyntax-only -verify %s + +@interface INTF +{ + id IVAR; + __weak id II; + __weak id WID; + id ID; + __weak INTF* AWEAK; + __weak INTF* WI; +} +@property (assign) __weak id pweak; +@property (assign) __weak id WID; +@property (assign) __strong id not; +@property (assign) id ID; +@property (assign) INTF* AWEAK; +@property (assign) __weak INTF* WI; +@end + +@implementation INTF +@synthesize pweak=IVAR; // expected-error {{existing ivar 'IVAR' for __weak property 'pweak' must be __weak}} +@synthesize not=II; // expected-error {{existing ivar 'II' for a __strong property 'not' must be garbage collectable}} +@synthesize WID; +@synthesize ID; +@synthesize AWEAK; // expected-error {{existing ivar 'AWEAK' for a __strong property 'AWEAK' must be garbage collectable}} +@synthesize WI; +@end diff --git a/test/SemaObjC/exprs.m b/test/SemaObjC/exprs.m new file mode 100644 index 000000000000..d51d135fa27a --- /dev/null +++ b/test/SemaObjC/exprs.m @@ -0,0 +1,21 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// rdar://6597252 +Class test1(Class X) { + return 1 ? X : X; +} + + +// rdar://6079877 +void test2() { + id str = @"foo" + "bar\0" // expected-warning {{literal contains NUL character}} + @"baz" " blarg"; + id str2 = @"foo" + "bar" + @"baz" + " b\0larg"; // expected-warning {{literal contains NUL character}} + + + if (@encode(int) == "foo") { } // expected-warning {{result of comparison against @encode is unspecified}} +} diff --git a/test/SemaObjC/foreach.m b/test/SemaObjC/foreach.m new file mode 100644 index 000000000000..f136adfa363b --- /dev/null +++ b/test/SemaObjC/foreach.m @@ -0,0 +1,18 @@ +/* RUN: clang-cc -fsyntax-only -verify -std=c89 -pedantic %s + */ + +@class NSArray; + +void f(NSArray *a) { + id keys; + for (int i in a); /* expected-error{{selector element type 'int' is not a valid object}} */ + for ((id)2 in a); /* expected-error{{selector element is not a valid lvalue}} */ + for (2 in a); /* expected-error{{selector element is not a valid lvalue}} */ + + /* This should be ok, 'thisKey' should be scoped to the loop in question, + * and no diagnostics even in pedantic mode should happen. + * rdar://6814674 + */ + for (id thisKey in keys); + for (id thisKey in keys); +} diff --git a/test/SemaObjC/format-arg-attribute.m b/test/SemaObjC/format-arg-attribute.m new file mode 100644 index 000000000000..60cc7cb44f25 --- /dev/null +++ b/test/SemaObjC/format-arg-attribute.m @@ -0,0 +1,28 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +@class NSString; + +extern NSString *fa2 (const NSString *) __attribute__((format_arg(1))); +extern NSString *fa3 (NSString *) __attribute__((format_arg(1))); + +extern void fc1 (const NSString *) __attribute__((format_arg)); // expected-error {{attribute requires 1 argument(s)}} +extern void fc2 (const NSString *) __attribute__((format_arg())); // expected-error {{attribute requires 1 argument(s)}} +extern void fc3 (const NSString *) __attribute__((format_arg(1, 2))); // expected-error {{attribute requires 1 argument(s)}} + +struct s1 { int i; } __attribute__((format_arg(1))); // expected-warning {{'format_arg' attribute only applies to function types}} +union u1 { int i; } __attribute__((format_arg(1))); // expected-warning {{'format_arg' attribute only applies to function types}} +// FIXME: We don't flag this yet. +enum e1 { E1V0 } __attribute__((format_arg(1))); /* { dg-error "does not apply|only applies" "format_arg on enum" } */ + +extern NSString *ff3 (const NSString *) __attribute__((format_arg(3-2))); +extern NSString *ff4 (const NSString *) __attribute__((format_arg(foo))); // expected-error {{attribute requires 1 argument(s)}} + +/* format_arg formats must take and return a string. */ +extern NSString *fi0 (int) __attribute__((format_arg(1))); // expected-error {{format argument not a string type}} +extern NSString *fi1 (NSString *) __attribute__((format_arg(1))); + +extern NSString *fi2 (NSString *) __attribute__((format_arg(1))); + +extern int fi3 (const NSString *) __attribute__((format_arg(1))); // expected-error {{function does not return NSString}} +extern NSString *fi4 (const NSString *) __attribute__((format_arg(1))); +extern NSString *fi5 (const NSString *) __attribute__((format_arg(1))); diff --git a/test/SemaObjC/format-strings-objc.m b/test/SemaObjC/format-strings-objc.m new file mode 100644 index 000000000000..4b8490291ad0 --- /dev/null +++ b/test/SemaObjC/format-strings-objc.m @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +//===----------------------------------------------------------------------===// +// The following code is reduced using delta-debugging from +// Foundation.h (Mac OS X). +// +// It includes the basic definitions for the test cases below. +// Not including Foundation.h directly makes this test case both svelt and +// portable to non-Mac platforms. +//===----------------------------------------------------------------------===// + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +@class NSString, Protocol; +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @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 +typedef float CGFloat; +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; @end +@interface NSSimpleCString : NSString {} @end +@interface NSConstantString : NSSimpleCString @end +extern void *_NSConstantStringClassReference; + +typedef const struct __CFString * CFStringRef; +extern void CFStringCreateWithFormat(CFStringRef format, ...) __attribute__((format(CFString, 1, 2))); + +//===----------------------------------------------------------------------===// +// Test cases. +//===----------------------------------------------------------------------===// + +void check_nslog(unsigned k) { + NSLog(@"%d%%", k); // no-warning + NSLog(@"%s%lb%d", "unix", 10,20); // expected-warning {{lid conversion '%lb'}} +} + +// Check type validation +extern void NSLog2(int format, ...) __attribute__((format(__NSString__, 1, 2))); // expected-error {{format argument not an NSString}} +extern void CFStringCreateWithFormat2(int *format, ...) __attribute__((format(CFString, 1, 2))); // expected-error {{format argument not a CFString}} diff --git a/test/SemaObjC/forward-class-1.m b/test/SemaObjC/forward-class-1.m new file mode 100644 index 000000000000..f5f950566672 --- /dev/null +++ b/test/SemaObjC/forward-class-1.m @@ -0,0 +1,47 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@class FOO, BAR; +@class FOO, BAR; + +@interface INTF : FOO // expected-error {{cannot find interface declaration for 'FOO', superclass of 'INTF'}} +@end + +@interface FOO +- (BAR*) Meth1; +- (FOO*) Meth2; +@end + +@interface INTF1 : FOO +@end + +@interface INTF2 : INTF1 // expected-note {{previous definition is here}} +@end + + +@class INTF1, INTF2; + +@interface INTF2 : INTF1 // expected-error {{duplicate interface definition for class 'INTF2'}} +@end + +// 2nd test of a forward class declaration matching a typedef name +// referring to class object. +// FIXME. This may become a negative test should we decide to make this an error. +// +@interface NSObject @end + +@protocol XCElementP @end + +typedef NSObject <XCElementP> XCElement; + +@interface XCElementMainImp { + XCElement * _editingElement; +} +@end + +@class XCElement; + +@implementation XCElementMainImp +- (XCElement *)editingElement { return _editingElement; } +@end + + diff --git a/test/SemaObjC/forward-class-receiver.m b/test/SemaObjC/forward-class-receiver.m new file mode 100644 index 000000000000..ebba0fd896dc --- /dev/null +++ b/test/SemaObjC/forward-class-receiver.m @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface I ++ new; // expected-note {{method 'new' is used for the forward class}} +@end +Class isa; + +@class NotKnown; + +void foo(NotKnown *n) { + [isa new]; + [NotKnown new]; /* expected-warning {{receiver 'NotKnown' is a forward class and corresponding}} */ +} diff --git a/test/SemaObjC/gcc-cast-ext.m b/test/SemaObjC/gcc-cast-ext.m new file mode 100644 index 000000000000..5d6670e0f67c --- /dev/null +++ b/test/SemaObjC/gcc-cast-ext.m @@ -0,0 +1,24 @@ +// RUN: clang-cc %s -verify -fms-extensions +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +typedef struct _NSRange { } NSRange; + +@class PBXFileReference; + +@interface PBXDocBookmark ++ alloc; +- autorelease; +@end + +// GCC allows pointer expressions in integer constant expressions. +struct { + char control[((int)(char *)2)]; +} xx; + +@implementation PBXDocBookmark // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'autorelease' not found}} expected-warning {{method definition for 'alloc' not found}} + ++ (id)bookmarkWithFileReference:(PBXFileReference *)fileRef gylphRange:(NSRange)range anchor:(NSString *)htmlAnchor +{ + NSRange r = (NSRange)range; + return [[[self alloc] initWithFileReference:fileRef gylphRange:(NSRange)range anchor:(NSString *)htmlAnchor] autorelease]; // expected-warning {{method '-initWithFileReference:gylphRange:anchor:' not found (return type defaults to 'id')}} +} +@end diff --git a/test/SemaObjC/id.m b/test/SemaObjC/id.m new file mode 100644 index 000000000000..1781ce71d9c3 --- /dev/null +++ b/test/SemaObjC/id.m @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol Foo; + +Class T; +id<Foo> S; +id R; +void foo() { + // Test assignment compatibility of Class and id. No warning should be + // produced. + // rdar://6770142 - Class and id<foo> are compatible. + S = T; T = S; + R = T; T = R; + R = S; S = R; +} + +// Test attempt to redefine 'id' in an incompatible fashion. +typedef int id; // expected-error {{typedef redefinition with different types}} +id b; + diff --git a/test/SemaObjC/id_builtin.m b/test/SemaObjC/id_builtin.m new file mode 100644 index 000000000000..134753726cbb --- /dev/null +++ b/test/SemaObjC/id_builtin.m @@ -0,0 +1,10 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// id is now builtin. There should be no errors. +id obj; + +@interface Foo + +- defaultToId; + +@end diff --git a/test/SemaObjC/ignore-weakimport-method.m b/test/SemaObjC/ignore-weakimport-method.m new file mode 100644 index 000000000000..369d9023acfb --- /dev/null +++ b/test/SemaObjC/ignore-weakimport-method.m @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface foo ++ (void) cx __attribute__((weak_import)); +- (void) x __attribute__((weak_import)); +@end + diff --git a/test/SemaObjC/incompatible-protocol-qualified-types.m b/test/SemaObjC/incompatible-protocol-qualified-types.m new file mode 100644 index 000000000000..862265ca6476 --- /dev/null +++ b/test/SemaObjC/incompatible-protocol-qualified-types.m @@ -0,0 +1,40 @@ +// RUN: clang-cc -pedantic -fsyntax-only -verify %s + +@protocol MyProto1 +@end + +@protocol MyProto2 +@end + +@interface INTF @end + +INTF <MyProto1> * Func(INTF <MyProto1, MyProto2> *p2) +{ + return p2; +} + + +INTF <MyProto1> * Func1(INTF <MyProto1, MyProto2> *p2) +{ + return p2; +} + +INTF <MyProto1, MyProto2> * Func2(INTF <MyProto1> *p2) +{ + Func(p2); // expected-warning {{incompatible pointer types passing 'INTF<MyProto1> *', expected 'INTF<MyProto1,MyProto2> *}} + return p2; // expected-warning {{incompatible pointer types returning 'INTF<MyProto1> *', expected 'INTF<MyProto1,MyProto2> *}} +} + + + +INTF <MyProto1> * Func3(INTF <MyProto2> *p2) +{ + return p2; // expected-warning {{incompatible pointer types returning 'INTF<MyProto2> *', expected 'INTF<MyProto1> *}} +} + + +INTF <MyProto1, MyProto2> * Func4(INTF <MyProto2, MyProto1> *p2) +{ + return p2; +} + diff --git a/test/SemaObjC/inst-method-lookup-in-root.m b/test/SemaObjC/inst-method-lookup-in-root.m new file mode 100644 index 000000000000..93f28e69f945 --- /dev/null +++ b/test/SemaObjC/inst-method-lookup-in-root.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol P +- (id) inst_in_proto; +@end + +@interface Object <P> +- (id) inst_in_root; +@end + +@interface Base +@end + +@interface Derived: Base +- (id)starboard; +@end + +void foo(void) { + Class receiver; + + [Derived starboard]; // expected-warning {{method '+starboard' not found}} + + [receiver starboard]; // expected-warning {{instance method 'starboard' is being used on 'Class'}} + [receiver inst_in_root]; // Ok! + [receiver inst_in_proto]; // Ok! +} + diff --git a/test/SemaObjC/interface-1.m b/test/SemaObjC/interface-1.m new file mode 100644 index 000000000000..85a2a91a8c13 --- /dev/null +++ b/test/SemaObjC/interface-1.m @@ -0,0 +1,38 @@ +// RUN: clang-cc -triple i386-apple-darwin9 %s -fsyntax-only -verify +// rdar://5957506 + +@interface NSWhatever : +NSObject // expected-error {{cannot find interface declaration for 'NSObject'}} +<NSCopying> // expected-error {{cannot find protocol declaration for 'NSCopying'}} +@end + + +// rdar://6095245 +@interface A +{ + int x +} // expected-error {{expected ';' at end of declaration list}} +@end + + +// rdar://4304469 +@interface INT1 +@end + +void test2() { + // rdar://6827200 + INT1 b[3]; // expected-error {{array of interface 'INT1' is invalid (probably should be an array of pointers)}} + INT1 *c = &b[0]; + ++c; +} + + +// rdar://6611778 +@interface FOO // expected-note {{previous definition is here}} +- (void)method; +@end + +@interface FOO // expected-error {{duplicate interface definition for class 'FOO'}} +- (void)method2; +@end + diff --git a/test/SemaObjC/interface-layout-2.m b/test/SemaObjC/interface-layout-2.m new file mode 100644 index 000000000000..ec03a00ca75e --- /dev/null +++ b/test/SemaObjC/interface-layout-2.m @@ -0,0 +1,16 @@ +// RUN: clang-cc %s -fsyntax-only -verify +@interface A +{ + int ivar; +} +@end + +@interface B : A +- (int)ivar; +@end + +@implementation B +- (int)ivar { + return ivar; +} +@end diff --git a/test/SemaObjC/interface-layout.m b/test/SemaObjC/interface-layout.m new file mode 100644 index 000000000000..6ad891554844 --- /dev/null +++ b/test/SemaObjC/interface-layout.m @@ -0,0 +1,27 @@ +// RUN: clang-cc %s -fsyntax-only -verify -triple i386-apple-darwin9 +typedef struct objc_object {} *id; +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; + +@protocol NSObject +- (BOOL) isEqual:(id) object; +@end + +@protocol NSCopying +- (id) copyWithZone:(NSZone *) zone; +@end + +@interface NSObject < NSObject > {} +@end + +extern id NSAllocateObject (Class aClass, NSUInteger extraBytes, NSZone * zone); + +@interface MyClassBase : NSObject < NSCopying > {} +@end + +@interface MyClassDirectNode : MyClassBase < NSCopying > +{ + @public NSUInteger attributeRuns[((1024 - 16 - sizeof (MyClassBase)) / (sizeof (NSUInteger) + sizeof (void *)))]; +} +@end diff --git a/test/SemaObjC/interface-scope-2.m b/test/SemaObjC/interface-scope-2.m new file mode 100644 index 000000000000..d054e714f3b2 --- /dev/null +++ b/test/SemaObjC/interface-scope-2.m @@ -0,0 +1,126 @@ +// RUN: clang-cc -fsyntax-only -verify -triple i686-apple-darwin9 %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 diff --git a/test/SemaObjC/interface-scope.m b/test/SemaObjC/interface-scope.m new file mode 100644 index 000000000000..b4dfff683bb1 --- /dev/null +++ b/test/SemaObjC/interface-scope.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface I1 { +@private + int x; + struct { + unsigned int x : 3; + unsigned int y : 3; + } flags; + int y; +} +@end diff --git a/test/SemaObjC/interface-tu-variable.m b/test/SemaObjC/interface-tu-variable.m new file mode 100644 index 000000000000..9bf816ab69fb --- /dev/null +++ b/test/SemaObjC/interface-tu-variable.m @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface XX +int x; // expected-error {{cannot declare variable inside @interface or @protocol}} +int one=1; // expected-error {{cannot declare variable inside @interface or @protocol}} +@end + +@protocol PPP +int ddd; // expected-error {{cannot declare variable inside @interface or @protocol}} +@end + +@interface XX(CAT) + char * III; // expected-error {{cannot declare variable inside @interface or @protocol}} + extern int OK; +@end + +@interface XX() + char * III2; // expected-error {{cannot declare variable inside @interface or @protocol}} + extern int OK2; +@end + + +int main( int argc, const char *argv[] ) { + return x+one; +} + diff --git a/test/SemaObjC/invalid-code.m b/test/SemaObjC/invalid-code.m new file mode 100644 index 000000000000..6eacba05f4ae --- /dev/null +++ b/test/SemaObjC/invalid-code.m @@ -0,0 +1,7 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// rdar://6124613 +void test1() { + void *p = @1; // expected-error {{unexpected '@' in program}} +} + diff --git a/test/SemaObjC/invalid-objc-decls-1.m b/test/SemaObjC/invalid-objc-decls-1.m new file mode 100644 index 000000000000..e3a94f62d5a6 --- /dev/null +++ b/test/SemaObjC/invalid-objc-decls-1.m @@ -0,0 +1,34 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Super @end +Super s1; // expected-error{{interface type cannot be statically allocated}} + +extern Super e1; // expected-error{{interface type cannot be statically allocated}} + +struct S { + Super s1; // expected-error{{interface type cannot be statically allocated}} +}; + +@protocol P1 @end + +@interface INTF +{ + Super ivar1; // expected-error{{interface type cannot be statically allocated}} +} +@end + +struct whatever { + Super objField; // expected-error{{interface type cannot be statically allocated}} +}; + +@interface MyIntf +{ + Super<P1> ivar1; // expected-error{{interface type cannot be statically allocated}} +} +@end + +Super foo( // expected-error{{interface interface type 'Super' cannot be returned by value}} + Super parm1) { // expected-error{{interface interface type 'Super' cannot be passed by value}} + Super p1; // expected-error{{interface type cannot be statically allocated}} + return p1; +} diff --git a/test/SemaObjC/invalid-receiver.m b/test/SemaObjC/invalid-receiver.m new file mode 100644 index 000000000000..e79df96942cc --- /dev/null +++ b/test/SemaObjC/invalid-receiver.m @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef struct NotAClass { + int a, b; +} NotAClass; + +void foo() { + [NotAClass nonexistent_method]; // expected-error {{invalid receiver to message expression}} +} diff --git a/test/SemaObjC/invalid-typename.m b/test/SemaObjC/invalid-typename.m new file mode 100644 index 000000000000..4077f91a9a66 --- /dev/null +++ b/test/SemaObjC/invalid-typename.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@class NSString, NSArray; + +@protocol ISyncSessionCallback +- (oneway void)clientWithId:(bycopy NSString *)clientId + canBeginSyncingPlanWithId:(bycopy NSString *)planId + syncModes:(bycopy NSArray /* ISDSyncState */ *)syncModes + entities:(bycopy NSArray /* ISDEntity */ *)entities + truthPullers:(bycopy NSDictionary /* NSString -> [NSString] */ *)truthPullers; // expected-error{{expected ')'}} expected-note {{to match this '('}} +@end + diff --git a/test/SemaObjC/ivar-access-package.m b/test/SemaObjC/ivar-access-package.m new file mode 100644 index 000000000000..77a15cca5142 --- /dev/null +++ b/test/SemaObjC/ivar-access-package.m @@ -0,0 +1,45 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef unsigned char BOOL; + +@interface NSObject { + id isa; +} ++new; ++alloc; +-init; +-autorelease; +@end + +@interface NSAutoreleasePool : NSObject +- drain; +@end + +@interface A : NSObject { +@package + id object; +} +@end + +@interface B : NSObject +- (BOOL)containsSelf:(A*)a; +@end + +@implementation A +@end + +@implementation B +- (BOOL)containsSelf:(A*)a { + return a->object == self; +} +@end + +int main (int argc, const char * argv[]) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + A *a = [[A new] autorelease]; + B *b = [[B new] autorelease]; + NSLog(@"%s", [b containsSelf:a] ? "YES" : "NO"); + [pool drain]; + return 0; +} + diff --git a/test/SemaObjC/ivar-access-tests.m b/test/SemaObjC/ivar-access-tests.m new file mode 100644 index 000000000000..ca3cc4cf1d46 --- /dev/null +++ b/test/SemaObjC/ivar-access-tests.m @@ -0,0 +1,122 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface MySuperClass +{ +@private + int private; + +@protected + int protected; + +@public + int public; +} +@end + +@implementation MySuperClass +- (void) test { + int access; + MySuperClass *s = 0; + access = s->private; + access = s->protected; +} +@end + + +@interface MyClass : MySuperClass +@end + +@implementation MyClass +- (void) test { + int access; + MySuperClass *s = 0; + access = s->private; // expected-error {{instance variable 'private' is private}} + access = s->protected; + MyClass *m=0; + access = m->private; // expected-error {{instance variable 'private' is private}} + access = m->protected; +} +@end + + +@interface Deeper : MyClass +@end + +@implementation Deeper +- (void) test { + int access; + MySuperClass *s = 0; + access = s->private; // expected-error {{instance variable 'private' is private}} + access = s->protected; + MyClass *m=0; + access = m->private; // expected-error {{instance variable 'private' is private}} + access = m->protected; +} +@end + +@interface Unrelated +@end + +@implementation Unrelated +- (void) test { + int access; + MySuperClass *s = 0; + access = s->private; // expected-error {{instance variable 'private' is private}} + access = s->protected; // expected-error {{instance variable 'protected' is protected}} + MyClass *m=0; + access = m->private; // expected-error {{instance variable 'private' is private}} + access = m->protected; // expected-error {{instance variable 'protected' is protected}} +} +@end + +int main (void) +{ + MySuperClass *s = 0; + int access; + access = s->private; // expected-error {{instance variable 'private' is private}} + access = s->protected; // expected-error {{instance variable 'protected' is protected}} + return 0; +} + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +@end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; +@end +@interface NSObject <NSObject> {} +@end +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSResponder : NSObject <NSCoding> {} +@end +@protocol NSAnimatablePropertyContainer +- (id)animator; +@end +extern NSString *NSAnimationTriggerOrderIn ; +@interface NSView : NSResponder <NSAnimatablePropertyContainer> { + struct __VFlags2 { + } + _vFlags2; +} +@end +@class NSFontDescriptor, NSAffineTransform, NSGraphicsContext; +@interface NSScrollView : NSView {} +@end + +@class CasperMixerView; +@interface CasperDiffScrollView : NSScrollView { +@private + CasperMixerView *_comparatorView; + NSView *someField; +} +@end + +@implementation CasperDiffScrollView ++ (void)initialize {} +static void _CasperDiffScrollViewInstallMixerView(CasperDiffScrollView *scrollView) { + if (scrollView->someField != ((void *)0)) { + } +} +@end diff --git a/test/SemaObjC/ivar-lookup.m b/test/SemaObjC/ivar-lookup.m new file mode 100644 index 000000000000..b168976da136 --- /dev/null +++ b/test/SemaObjC/ivar-lookup.m @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +@interface Test { + int x; +} + +-(void) setX: (int) d; +@end + +extern struct foo x; + +@implementation Test + +-(void) setX: (int) n { + x = n; +} + +@end diff --git a/test/SemaObjC/ivar-ref-misuse.m b/test/SemaObjC/ivar-ref-misuse.m new file mode 100644 index 000000000000..85ede5786d5b --- /dev/null +++ b/test/SemaObjC/ivar-ref-misuse.m @@ -0,0 +1,41 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Sprite { + int sprite, spree; + int UseGlobalBar; +} ++ (void)setFoo:(int)foo; ++ (void)setSprite:(int)sprite; +- (void)setFoo:(int)foo; +- (void)setSprite:(int)sprite; +@end + +int spree = 23; +int UseGlobalBar; + +@implementation Sprite ++ (void)setFoo:(int)foo { + sprite = foo; // expected-error {{use of undeclared identifier 'sprite'}} + spree = foo; + Xsprite = foo; // expected-error {{use of undeclared identifier 'Xsprite'}} + UseGlobalBar = 10; +} ++ (void)setSprite:(int)sprite { + int spree; + sprite = 15; + spree = 17; + ((Sprite *)self)->sprite = 16; /* NB: This is how one _should_ access */ + ((Sprite *)self)->spree = 18; /* ivars from within class methods! */ +} +- (void)setFoo:(int)foo { + sprite = foo; + spree = foo; +} +- (void)setSprite:(int)sprite { + int spree; + sprite = 15; // expected-warning {{local declaration of 'sprite' hides instance variable}} + self->sprite = 16; + spree = 17; // expected-warning {{local declaration of 'spree' hides instance variable}} + self->spree = 18; +} +@end diff --git a/test/SemaObjC/ivar-sem-check-1.m b/test/SemaObjC/ivar-sem-check-1.m new file mode 100644 index 000000000000..957abc397e89 --- /dev/null +++ b/test/SemaObjC/ivar-sem-check-1.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct S; // expected-note{{forward declaration of 'struct S'}} +typedef int FOO(); + +@interface INTF +{ + struct F {} JJ; + int arr[]; // expected-error {{field has incomplete type}} + struct S IC; // expected-error {{field has incomplete type}} + struct T { // expected-note {{previous definition is here}} + struct T {} X; // expected-error {{nested redefinition of 'T'}} + }YYY; + FOO BADFUNC; // expected-error {{field 'BADFUNC' declared as a function}} + int kaka; // expected-note {{previous declaration is here}} + int kaka; // expected-error {{duplicate member 'kaka'}} + char ch[]; // expected-error {{field has incomplete type}} +} +@end diff --git a/test/SemaObjC/ivar-sem-check-2.m b/test/SemaObjC/ivar-sem-check-2.m new file mode 100644 index 000000000000..ba6b38934bd1 --- /dev/null +++ b/test/SemaObjC/ivar-sem-check-2.m @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -triple x86_64-apple-darwin10 -verify %s + +@interface Super { + id value2; // expected-note {{previously declared 'value2' here}} +} +@property(retain) id value; +@property(retain) id value1; +@property(retain) id prop; +@end + +@interface Sub : Super +{ + id value; +} +@end + +@implementation Sub +@synthesize value; // expected-note {{previous use is here}} +@synthesize value1=value; // expected-error {{synthesized properties 'value1' and 'value' both claim ivar 'value'}} +@synthesize prop=value2; // expected-error {{property 'prop' attempting to use ivar 'value2' declared in super class 'Super'}} +@end + + diff --git a/test/SemaObjC/legacy-implementation-1.m b/test/SemaObjC/legacy-implementation-1.m new file mode 100644 index 000000000000..63768ffb50ea --- /dev/null +++ b/test/SemaObjC/legacy-implementation-1.m @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@implementation INTF // expected-warning {{cannot find interface declaration for 'INTF'}} +@end + +INTF* pi; + +INTF* FUNC() +{ + return pi; +} diff --git a/test/SemaObjC/message.m b/test/SemaObjC/message.m new file mode 100644 index 000000000000..7b6a4ee3f796 --- /dev/null +++ b/test/SemaObjC/message.m @@ -0,0 +1,100 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef struct objc_object { + Class isa; +} *id; + + +@interface foo +- (void)meth; +@end + +@implementation foo +- (void) contents {} // No declaration in @interface! +- (void) meth { [self contents]; } +@end + +typedef struct _NSPoint { + float x; + float y; +} NSPoint; + +typedef struct _NSSize { + float width; + float height; +} NSSize; + +typedef struct _NSRect { + NSPoint origin; + NSSize size; +} NSRect; + +@interface AnyClass +- (NSRect)rect; +@end + +@class Helicopter; + +static void func(Helicopter *obj) { + // Note that the proto for "rect" is found in the global pool even when + // a statically typed object's class interface isn't in scope! This + // behavior isn't very desirable, however wee need it for GCC compatibility. + NSRect r = [obj rect]; +} + +@interface NSObject @end + +extern Class NSClassFromObject(id object); + +@interface XX : NSObject +@end + +@implementation XX + ++ _privateMethod { + return self; +} + +- (void) xx { + [NSClassFromObject(self) _privateMethod]; +} +@end + +@implementation XX (Private) +- (void) yy { + [NSClassFromObject(self) _privateMethod]; +} +@end + +@interface I0 +-(void) nonVararg: (int) x; +@end + +int f0(I0 *ob) { + [ ob nonVararg: 0, 1, 2]; // expected-error {{too many arguments to method call}} +} + +int f2() { + const id foo; + [foo bar]; // expected-warning {{method '-bar' not found (return type defaults to 'id')}} + return 0; +} + + +// PR3766 +struct S { int X; } S; + +int test5(int X) { + int a = [X somemsg]; // expected-warning {{receiver type 'int' is not 'id'}} \ + expected-warning {{method '-somemsg' not found}} \ + expected-warning {{incompatible pointer to integer conversion initializing 'id', expected 'int'}} + int b = [S somemsg]; // expected-error {{bad receiver type 'struct S'}} +} + +// PR4021 +void foo4() { + struct objc_object X[10]; + + [X rect]; +} + diff --git a/test/SemaObjC/method-arg-decay.m b/test/SemaObjC/method-arg-decay.m new file mode 100644 index 000000000000..4b045914c095 --- /dev/null +++ b/test/SemaObjC/method-arg-decay.m @@ -0,0 +1,95 @@ +// RUN: clang-cc -checker-cfref -verify %s +typedef signed char BOOL; +typedef int NSInteger; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +@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 extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSValue : NSObject <NSCopying, NSCoding> - (void)getValue:(void *)value; +@end @class NSString, NSData, NSMutableData, NSMutableDictionary, NSMutableArray; +typedef struct { +} + NSFastEnumerationState; +@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end @class NSString; +typedef struct _NSRange { +} + NSRange; +@interface NSValue (NSValueRangeExtensions) + (NSValue *)valueWithRange:(NSRange)range; +- (id)objectAtIndex:(NSUInteger)index; +@end typedef unsigned short unichar; +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length; +@end @class NSArray, NSDictionary, NSString, NSError; +@interface NSSet : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; +@end extern NSString *NSAccessibilityRoleDescription(NSString *role, NSString *subrole) ; +@interface NSResponder : NSObject <NSCoding> { +} +@end @protocol NSAnimatablePropertyContainer - (id)animator; +@end extern NSString *NSAnimationTriggerOrderIn ; +@interface NSView : NSResponder <NSAnimatablePropertyContainer> { +} +@end @class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView; +@interface NSWindowController : NSResponder <NSCoding> { +} +@end @class NSArray, NSFont, NSTabViewItem; +@interface NSTabView : NSView { +} +- (NSArray *)tabViewItems; +- (NSString *)label; +@end typedef enum { +PBXNoItemChanged = 0x00, PBXProjectItemChanged = 0x01, PBXReferenceChanged = 0x02, PBXGroupChanged = 0x04, PBXTargetChanged = 0x08, PBXBuildPhaseChanged = 0x10, PBXBuildFileChanged = 0x20, PBXBreakpointChanged = 0x40, } + PBXArchiveMask; +@interface PBXModule : NSWindowController { +} +@end typedef enum { +PBXFindMatchContains, PBXFindMatchStartsWith, PBXFindMatchWholeWords, PBXFindMatchEndsWith } + PBXFindMatchStyle; +@protocol PBXSelectableText - (NSString *)selectedString; +@end @protocol PBXFindableText <PBXSelectableText> - (BOOL)findText:(NSString *)string ignoreCase:(BOOL)ignoreCase matchStyle:(PBXFindMatchStyle)matchStyle backwards:(BOOL)backwards wrap:(BOOL)wrap; +@end @class PBXProjectDocument, PBXProject, PBXAttributedStatusView; +@interface PBXProjectModule : PBXModule <PBXFindableText> { +} +@end @class PBXBookmark; +@protocol PBXSelectionTarget - (NSObject <PBXSelectionTarget> *) performAction:(id)action withSelection:(NSArray *)selection; +@end @class XCPropertyDictionary, XCPropertyCondition, XCPropertyConditionSet, XCMutablePropertyConditionSet; +extern NSMutableArray *XCFindPossibleKeyModules(PBXModule *module, BOOL useExposedModulesOnly); +@interface NSString (StringUtilities) - (NSString *) trimToLength:(NSInteger)length preserveRange:(NSRange)range; +- (id) objectOfType:(Class)type matchingFunction:(BOOL (void *, void *))comparator usingData:(void *)data; +@end @class XCControlView; +@protocol XCDockViewHeader - (NSImage *) headerImage; +@end @class XCDockableTabModule; +@interface XCExtendedTabView : NSTabView <XCDockViewHeader> { +} +@end @class PBXProjectDocument, PBXFileReference, PBXModule, XCWindowTool; +@interface XCPerspectiveModule : PBXProjectModule <PBXSelectionTarget> { + XCExtendedTabView *_perspectivesTabView; +} +- (PBXModule *) moduleForTab:(NSTabViewItem *)item; +@end +@implementation XCPerspectiveModule ++ (void) openForProjectDocument:(PBXProjectDocument *)projectDocument { +} +- (PBXModule *) type:(Class)type inPerspective:(id)perspectiveIdentifer matchingFunction:(BOOL (void *, void *))comparator usingData:(void *)data { + NSArray *allItems = [_perspectivesTabView tabViewItems]; + NSInteger i, c = [allItems count]; + for (i = 0; + i < c; + i++) { + NSTabViewItem *item = [allItems objectAtIndex:i]; + if ([[item label] isEqual:perspectiveIdentifer]) { + PBXProjectModule *pModule = (PBXProjectModule *)[self moduleForTab:item]; + PBXModule *obj = [XCFindPossibleKeyModules(pModule, (BOOL)0) objectOfType:type matchingFunction:comparator usingData:data]; + } + } +} +- (BOOL)buffer:(char *)buf containsAnyPrompts:(char *[])prompts +{ + prompts++; + return (BOOL)0; +} diff --git a/test/SemaObjC/method-attributes.m b/test/SemaObjC/method-attributes.m new file mode 100644 index 000000000000..c4d4fba25d6e --- /dev/null +++ b/test/SemaObjC/method-attributes.m @@ -0,0 +1,32 @@ +// RUN: clang-cc -verify -fsyntax-only %s + +@class NSString; + +@interface A +-t1 __attribute__((noreturn)); +- (NSString *)stringByAppendingFormat:(NSString *)format, ... __attribute__((format(__NSString__, 1, 2))); +-(void) m0 __attribute__((noreturn)); +-(void) m1 __attribute__((unused)); +@end + + +@interface INTF +- (int) foo1: (int)arg1 __attribute__((deprecated)); + +- (int) foo: (int)arg1; + +- (int) foo2: (int)arg1 __attribute__((deprecated)) __attribute__((unavailable)); +@end + +@implementation INTF +- (int) foo: (int)arg1 __attribute__((deprecated)){ // expected-warning {{method attribute can only be specified}} + return 10; +} +- (int) foo1: (int)arg1 { + return 10; +} +- (int) foo2: (int)arg1 __attribute__((deprecated)) { // expected-warning {{method attribute can only be specified}} + return 10; +} +@end + diff --git a/test/SemaObjC/method-bad-param.m b/test/SemaObjC/method-bad-param.m new file mode 100644 index 000000000000..f797188669ad --- /dev/null +++ b/test/SemaObjC/method-bad-param.m @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface foo +@end + +@implementation foo +@end + +@interface bar +-(void) my_method:(foo) my_param; // expected-error {{Objective-C interface type 'foo' cannot be passed by value}} +- (foo)cccccc:(long)ddddd; // expected-error {{Objective-C interface type 'foo' cannot be returned by value}} +@end + +@implementation bar +-(void) my_method:(foo) my_param // expected-error {{Objective-C interface type 'foo' cannot be passed by value}} +{ +} +- (foo)cccccc:(long)ddddd // expected-error {{Objective-C interface type 'foo' cannot be returned by value}} +{ +} +@end + +void somefunc(foo x) {} // expected-error {{Objective-C interface type 'foo' cannot be passed by value}} +foo somefunc2() {} // expected-error {{Objective-C interface type 'foo' cannot be returned by value}} + +// rdar://6780761 +void f0(foo *a0) { + extern void g0(int x, ...); + g0(1, *(foo*)0); // expected-error {{cannot pass object with interface type 'foo' by-value through variadic function}} +} diff --git a/test/SemaObjC/method-conflict.m b/test/SemaObjC/method-conflict.m new file mode 100644 index 000000000000..7a9b9f0beee8 --- /dev/null +++ b/test/SemaObjC/method-conflict.m @@ -0,0 +1,53 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; +@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 extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +@interface NSValue : NSObject <NSCopying, NSCoding> - (void)getValue:(void *)value; +@end @class NSString; +typedef struct _NSRange { +} + NSRange; +@interface NSValue (NSValueRangeExtensions) + (NSValue *)valueWithRange:(NSRange)range; +@end @interface NSAttributedString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSString *)string; +@end @interface NSMutableAttributedString : NSAttributedString - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str; +@end @class NSArray, NSDictionary, NSString, NSError; +@interface NSScanner : NSObject <NSCopying> - (NSString *)string; +@end typedef struct { +} + CSSM_FIELDGROUP, *CSSM_FIELDGROUP_PTR; +@protocol XDUMLClassifier; +@protocol XDUMLClassInterfaceCommons <XDUMLClassifier> +@end @protocol XDUMLImplementation; +@protocol XDUMLElement <NSObject> - (NSArray *) ownedElements; +@end @protocol XDUMLDataType; +@protocol XDUMLNamedElement <XDUMLElement> - (NSString *) name; +@end enum _XDSourceLanguage { +XDSourceUnknown=0, XDSourceJava, XDSourceC, XDSourceCPP, XDSourceObjectiveC }; +typedef NSUInteger XDSourceLanguage; +@protocol XDSCClassifier <XDUMLClassInterfaceCommons> - (XDSourceLanguage)language; +@end @class XDSCDocController; +@interface XDSCDisplaySpecification : NSObject <NSCoding>{ +} +@end @class XDSCOperation; +@interface XDSCClassFormatter : NSObject { +} ++ (NSUInteger) compartmentsForClassifier: (id <XDUMLClassifier>) classifier withSpecification: (XDSCDisplaySpecification *) displaySpec; +@end +@class NSString; +@implementation XDSCClassFormatter + ++ appendVisibility: (id <XDUMLNamedElement>) element withSpecification: (XDSCDisplaySpecification *) displaySpec to: (NSMutableAttributedString *) attributedString +{ +} ++ (NSUInteger) compartmentsForClassifier: (id <XDSCClassifier>) classifier withSpecification: (XDSCDisplaySpecification *) displaySpec { +} +@end diff --git a/test/SemaObjC/method-def-1.m b/test/SemaObjC/method-def-1.m new file mode 100644 index 000000000000..3eb94b9153d9 --- /dev/null +++ b/test/SemaObjC/method-def-1.m @@ -0,0 +1,40 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface foo +- (int)meth; +@end + +@implementation foo +- (int) meth { return [self meth]; } +@end + +// PR2708 +@interface MyClass ++- (void)myMethod; // expected-error {{expected selector for Objective-C method}} +- (vid)myMethod2; // expected-error {{expected a type}} +@end + +@implementation MyClass +- (void)myMethod { } +- (vid)myMethod2 { } // expected-error {{expected a type}} + +@end + + +@protocol proto; +@protocol NSObject; + +//@protocol GrowlPluginHandler <NSObject> @end + + +@interface SomeClass2 +- (int)myMethod1: (id<proto>) +arg; // expected-note {{previous definition is here}} +@end + +@implementation SomeClass2 +- (int)myMethod1: (id<NSObject>) + arg { // expected-warning {{conflicting parameter types in implementation of 'myMethod1:': 'id<proto>' vs 'id<NSObject>'}} + +} +@end diff --git a/test/SemaObjC/method-def-2.m b/test/SemaObjC/method-def-2.m new file mode 100644 index 000000000000..84cdd70259fa --- /dev/null +++ b/test/SemaObjC/method-def-2.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -ast-print %s +extern void abort(void); +#define CHECK_IF(expr) if(!(expr)) abort() + +static double d = 4.5920234e2; + +@interface Foo +-(void) brokenType: (int)x floatingPoint: (double)y; +@end + + +@implementation Foo +-(void) brokenType: (int)x floatingPoint: (double)y +{ + CHECK_IF(x == 459); + CHECK_IF(y == d); +} +@end + diff --git a/test/SemaObjC/method-encoding-2.m b/test/SemaObjC/method-encoding-2.m new file mode 100644 index 000000000000..64a0bc4c323d --- /dev/null +++ b/test/SemaObjC/method-encoding-2.m @@ -0,0 +1,12 @@ +// RUN: clang-cc %s +// TODO: We don't support rewrite of method definitions + +@interface Intf +- (in out bycopy id) address:(byref inout void *)location with:(out oneway unsigned **)arg2; +- (id) another:(void *)location with:(unsigned **)arg2; +@end + +@implementation Intf +- (in out bycopy id) address:(byref inout void *)location with:(out oneway unsigned **)arg2{} +- (id) another:(void *)location with:(unsigned **)arg2 {} +@end diff --git a/test/SemaObjC/method-lookup-2.m b/test/SemaObjC/method-lookup-2.m new file mode 100644 index 000000000000..dd0bca93644e --- /dev/null +++ b/test/SemaObjC/method-lookup-2.m @@ -0,0 +1,62 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef signed char BOOL; + +@protocol NSObject ++ alloc; +- init; +- (BOOL) isEqual:(id) object; +- (Class)class; +@end + +@interface NSObject < NSObject > {} @end + +@class NSString, NSPort; + +@interface NSPortNameServer:NSObject ++ (NSPortNameServer *) systemDefaultPortNameServer; +@end + +@interface NSMachBootstrapServer:NSPortNameServer + (id) sharedInstance; @end + +enum { + NSWindowsNTOperatingSystem = 1, NSWindows95OperatingSystem, NSSolarisOperatingSystem, NSHPUXOperatingSystem, NSMACHOperatingSystem, NSSunOSOperatingSystem, NSOSF1OperatingSystem +}; + +@interface NSRunLoop:NSObject {} @end + +@interface NSRunLoop(NSRunLoopConveniences) +- (void) run; +@end + +extern NSString *const NSWillBecomeMultiThreadedNotification; + +@interface SenTestTool:NSObject {} +@end + +@implementation SenTestTool ++ (void) initialize {} ++(SenTestTool *) sharedInstance {} +-(int) run {} ++(int) run { + return[[self sharedInstance] run]; +} +@end + +@interface XX : NSObject + ++ classMethod; + +@end + +@interface YY : NSObject +- whatever; +@end + +@implementation YY + +- whatever { + id obj = [[XX alloc] init]; + [[obj class] classMethod]; +} + +@end diff --git a/test/SemaObjC/method-lookup-3.m b/test/SemaObjC/method-lookup-3.m new file mode 100644 index 000000000000..8ed583faebc7 --- /dev/null +++ b/test/SemaObjC/method-lookup-3.m @@ -0,0 +1,52 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef struct { int y; } Abstract; + +typedef struct { int x; } Alternate; + +#define INTERFERE_TYPE Alternate* + +@protocol A +@property Abstract *x; // expected-note {{using}} +@end + +@interface B +@property Abstract *y; // expected-note {{using}} +@end + +@interface B (Category) +@property Abstract *z; // expected-note {{using}} +@end + +@interface InterferencePre +-(void) x; // expected-note {{also found}} +-(void) y; // expected-note {{also found}} +-(void) z; // expected-note {{also found}} +-(void) setX: (INTERFERE_TYPE) arg; +-(void) setY: (INTERFERE_TYPE) arg; +-(void) setZ: (INTERFERE_TYPE) arg; +@end + +void f0(id a0) { + Abstract *l = [a0 x]; // expected-warning {{multiple methods named 'x' found}} +} + +void f1(id a0) { + Abstract *l = [a0 y]; // expected-warning {{multiple methods named 'y' found}} +} + +void f2(id a0) { + Abstract *l = [a0 z]; // expected-warning {{multiple methods named 'z' found}} +} + +void f3(id a0, Abstract *a1) { + [ a0 setX: a1]; +} + +void f4(id a0, Abstract *a1) { + [ a0 setY: a1]; +} + +void f5(id a0, Abstract *a1) { + [ a0 setZ: a1]; +} diff --git a/test/SemaObjC/method-lookup-4.m b/test/SemaObjC/method-lookup-4.m new file mode 100644 index 000000000000..3b2548b92c11 --- /dev/null +++ b/test/SemaObjC/method-lookup-4.m @@ -0,0 +1,62 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface NSObject {} + +@end + +@interface MyClass : NSObject {} + +@end + +@interface MyClass (MyCategorie) + +@end + +@interface MySubClass : MyClass {} + +@end + +@interface MySubSubClass : MySubClass {} + +@end + +@implementation NSObject (NSObjectCategory) +- (void)rootMethod {} +@end + +@implementation MyClass + ++ (void)myClassMethod { } +- (void)myMethod { } + +@end + +@implementation MyClass (MyCategorie) ++ (void)myClassCategoryMethod { } +- (void)categoryMethod {} +@end + +@implementation MySubClass + +- (void)mySubMethod {} + +- (void)myTest { + [self mySubMethod]; + // should lookup method in superclass implementation if available + [self myMethod]; + [super myMethod]; + + [self categoryMethod]; + [super categoryMethod]; + + // instance method of root class + [MyClass rootMethod]; + + [MyClass myClassMethod]; + [MySubClass myClassMethod]; + + [MyClass myClassCategoryMethod]; + [MySubClass myClassCategoryMethod]; +} + +@end diff --git a/test/SemaObjC/method-lookup.m b/test/SemaObjC/method-lookup.m new file mode 100644 index 000000000000..917ad6b3ee92 --- /dev/null +++ b/test/SemaObjC/method-lookup.m @@ -0,0 +1,34 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef signed char BOOL; +typedef int NSInteger; + +@protocol NSObject +- (BOOL)isEqual:(id)object; +- (BOOL)respondsToSelector:(SEL)s; +@end + +@interface NSObject <NSObject> {} +@end + +@class NSString, NSData, NSMutableData, NSMutableDictionary, NSMutableArray; + +@protocol PBXCompletionItem +- (NSString *) name; +- (NSInteger)priority; +- setPriority:(NSInteger)p; +@end + +@implementation PBXCodeAssistant // expected-warning{{cannot find interface declaration for 'PBXCodeAssistant'}} +static NSMutableArray * recentCompletions = ((void *)0); ++ (float) factorForRecentCompletion:(NSString *) completion +{ + for (NSObject<PBXCompletionItem> * item in [self completionItems]) // expected-warning{{method '-completionItems' not found (return type defaults to 'id')}} + { + if ([item respondsToSelector:@selector(setPriority:)]) + { + [(id)item setPriority:[item priority] / [PBXCodeAssistant factorForRecentCompletion:[item name]]]; + } + } +} +@end + diff --git a/test/SemaObjC/method-no-context.m b/test/SemaObjC/method-no-context.m new file mode 100644 index 000000000000..9351cb91579a --- /dev/null +++ b/test/SemaObjC/method-no-context.m @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +- im0 { int a; return 0; // expected-error{{missing context for method declaration}} +// expected-error{{expected '}'}} diff --git a/test/SemaObjC/method-not-defined.m b/test/SemaObjC/method-not-defined.m new file mode 100644 index 000000000000..3848fa28c927 --- /dev/null +++ b/test/SemaObjC/method-not-defined.m @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Foo +@end + +void test() { + Foo *fooObj; + id obj; + + [[Foo alloc] init]; // expected-warning {{method '+alloc' not found (return type defaults to 'id')}} expected-warning {{method '-init' not found (return type defaults to 'id')}} + [fooObj notdefined]; // expected-warning {{method '-notdefined' not found (return type defaults to 'id')}} + [obj whatever:1 :2 :3]; // expected-warning {{method '-whatever:::' not found (return type defaults to 'id'))}} +} diff --git a/test/SemaObjC/method-sentinel-attr.m b/test/SemaObjC/method-sentinel-attr.m new file mode 100644 index 000000000000..8f31e9ab5e41 --- /dev/null +++ b/test/SemaObjC/method-sentinel-attr.m @@ -0,0 +1,37 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#define NULL (void*)0 + +#define ATTR __attribute__ ((__sentinel__)) + +@interface INTF +- (void) foo1 : (int)x, ... ATTR; // expected-note {{method has been explicitly marked sentinel here}} +- (void) foo3 : (int)x __attribute__ ((__sentinel__)) ; // expected-warning {{'sentinel' attribute only supported for variadic functions}} +- (void) foo5 : (int)x, ... __attribute__ ((__sentinel__(1))); // expected-note {{method has been explicitly marked sentinel here}} +- (void) foo6 : (int)x, ... __attribute__ ((__sentinel__(5))); // expected-note {{method has been explicitly marked sentinel here}} +- (void) foo7 : (int)x, ... __attribute__ ((__sentinel__(0))); // expected-note {{method has been explicitly marked sentinel here}} +- (void) foo8 : (int)x, ... __attribute__ ((__sentinel__("a"))); // expected-error {{'sentinel' attribute requires parameter 1 to be an integer constant}} +- (void) foo9 : (int)x, ... __attribute__ ((__sentinel__(-1))); // expected-error {{'sentinel' parameter 1 less than zero}} +- (void) foo10 : (int)x, ... __attribute__ ((__sentinel__(1,1))); +- (void) foo11 : (int)x, ... __attribute__ ((__sentinel__(1,1,3))); // expected-error {{attribute requires 0, 1 or 2 argument(s)}} +- (void) foo12 : (int)x, ... ATTR; // expected-note {{method has been explicitly marked sentinel here}} +@end + +int main () +{ + INTF *p; + + [p foo1:1, NULL]; // OK + [p foo1:1, 0]; // expected-warning {{missing sentinel in method dispatch}} + [p foo5:1, NULL, 2]; // OK + [p foo5:1, 2, NULL, 1]; // OK + [p foo5:1, NULL, 2, 1]; // expected-warning {{missing sentinel in method dispatch}} + + [p foo6:1,2,3,4,5,6,7]; // expected-warning {{missing sentinel in method dispatch}} + [p foo6:1,NULL,3,4,5,6,7]; // OK + [p foo7:1]; // expected-warning {{not enough variable arguments in 'foo7:' declaration to fit a sentinel}} + [p foo7:1, NULL]; // ok + + [p foo12:1]; // expected-warning {{not enough variable arguments in 'foo12:' declaration to fit a sentinel}} +} + diff --git a/test/SemaObjC/method-typecheck-1.m b/test/SemaObjC/method-typecheck-1.m new file mode 100644 index 000000000000..d110c858a41a --- /dev/null +++ b/test/SemaObjC/method-typecheck-1.m @@ -0,0 +1,37 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface A +- (void) setMoo: (int) x; // expected-note {{previous definition is here}} +- (int) setMoo1: (int) x; // expected-note {{previous definition is here}} +- (int) setOk : (int) x : (double) d; +@end + +@implementation A +-(void) setMoo: (float) x {} // expected-warning {{conflicting parameter types in implementation of 'setMoo:': 'int' vs 'float'}} +- (char) setMoo1: (int) x {} // expected-warning {{conflicting return type in implementation of 'setMoo1:': 'int' vs 'char'}} +- (int) setOk : (int) x : (double) d {} +@end + + + +@interface C ++ (void) cMoo: (int) x; // expected-note 2 {{previous definition is here}} +@end + +@implementation C ++(float) cMoo: // expected-warning {{conflicting return type in implementation of 'cMoo:': 'void' vs 'float'}} + (float) x {} // expected-warning {{conflicting parameter types in implementation of 'cMoo:': 'int' vs 'float'}} +@end + + +@interface A(CAT) +- (void) setCat: (int) x; // expected-note 2 {{previous definition is here}} ++ (void) cCat: (int) x; // expected-note {{previous definition is here}} +@end + +@implementation A(CAT) +-(float) setCat: // expected-warning {{conflicting return type in implementation of 'setCat:': 'void' vs 'float'}} +(float) x {} // expected-warning {{conflicting parameter types in implementation of 'setCat:': 'int' vs 'float'}} ++ (int) cCat: (int) x {} // expected-warning {{conflicting return type in implementation of 'cCat:': 'void' vs 'int'}} +@end + diff --git a/test/SemaObjC/method-typecheck-2.m b/test/SemaObjC/method-typecheck-2.m new file mode 100644 index 000000000000..d0a091d85615 --- /dev/null +++ b/test/SemaObjC/method-typecheck-2.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol P +- (void) doSomethingInProtocol: (float) x; // expected-note {{previous definition is here}} ++ (void) doSomethingClassyInProtocol: (float) x; // expected-note {{previous definition is here}} +- (void) doNothingInProtocol : (float) x; ++ (void) doNothingClassyInProtocol : (float) x; +@end + +@interface I <P> +- (void) doSomething: (float) x; // expected-note {{previous definition is here}} ++ (void) doSomethingClassy: (int) x; // expected-note {{previous definition is here}} +@end + +@interface Bar : I +@end + +@implementation Bar +- (void) doSomething: (int) x {} // expected-warning {{conflicting parameter types}} ++ (void) doSomethingClassy: (float) x{} // expected-warning {{conflicting parameter types}} +- (void) doSomethingInProtocol: (id) x {} // expected-warning {{conflicting parameter types}} ++ (void) doSomethingClassyInProtocol: (id) x {} // expected-warning {{conflicting parameter types}} +@end + + diff --git a/test/SemaObjC/method-undef-category-warn-1.m b/test/SemaObjC/method-undef-category-warn-1.m new file mode 100644 index 000000000000..82fd3c8ba6ff --- /dev/null +++ b/test/SemaObjC/method-undef-category-warn-1.m @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface MyClass1 +@end + +@protocol P +- (void) Pmeth; +- (void) Pmeth1; +@end + +@interface MyClass1(CAT) <P> +- (void) meth2; +@end + +@implementation MyClass1(CAT) // expected-warning {{incomplete implementation}} \ + expected-warning {{method definition for 'meth2' not found}} \ + expected-warning {{method definition for 'Pmeth' not found}} +- (void) Pmeth1{} +@end + +@interface MyClass1(DOG) <P> +- (void)ppp; +@end + +@implementation MyClass1(DOG) // expected-warning {{incomplete implementation}} \ + expected-warning {{method definition for 'ppp' not found}} \ + expected-warning {{method definition for 'Pmeth1' not found}} +- (void) Pmeth {} +@end + +@implementation MyClass1(CAT1) +@end diff --git a/test/SemaObjC/method-undef-extension-warn-1.m b/test/SemaObjC/method-undef-extension-warn-1.m new file mode 100644 index 000000000000..7ce015f886ec --- /dev/null +++ b/test/SemaObjC/method-undef-extension-warn-1.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface MyClass +@end + +@protocol P +- (void)Pmeth; +- (void)Pmeth1; +@end + +// Class extension +@interface MyClass () <P> +- (void)meth2; +@end + +// Add a category to test that clang does not emit warning for this method. +@interface MyClass (Category) +- (void)categoryMethod; +@end + +@implementation MyClass // expected-warning {{incomplete implementation}} \ + expected-warning {{method definition for 'meth2' not found}} \ + expected-warning {{method definition for 'Pmeth1' not found}} +- (void)Pmeth {} +@end diff --git a/test/SemaObjC/method-undefined-warn-1.m b/test/SemaObjC/method-undefined-warn-1.m new file mode 100644 index 000000000000..fbb01dfb1f79 --- /dev/null +++ b/test/SemaObjC/method-undefined-warn-1.m @@ -0,0 +1,42 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface INTF +- (void) meth; +- (void) meth : (int) arg1; +- (int) int_meth; ++ (int) cls_meth; ++ (void) cls_meth1 : (int) arg1; +@end + +@implementation INTF // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'int_meth' not found}} expected-warning {{method definition for 'cls_meth' not found}} expected-warning {{method definition for 'cls_meth1:' not found}} +- (void) meth {} +- (void) meth : (int) arg2{} +- (void) cls_meth1 : (int) arg2{} +@end + +@interface INTF1 +- (void) meth; +- (void) meth : (int) arg1; +- (int) int_meth; ++ (int) cls_meth; ++ (void) cls_meth1 : (int) arg1; +@end + +@implementation INTF1 // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'int_meth' not found}} expected-warning {{method definition for 'cls_meth' not found}} expected-warning {{method definition for 'cls_meth1:' not found}} +- (void) meth {} +- (void) meth : (int) arg2{} +- (void) cls_meth1 : (int) arg2{} +@end + +@interface INTF2 +- (void) meth; +- (void) meth : (int) arg1; +- (void) cls_meth1 : (int) arg1; +@end + +@implementation INTF2 +- (void) meth {} +- (void) meth : (int) arg2{} +- (void) cls_meth1 : (int) arg2{} +@end + diff --git a/test/SemaObjC/missing-method-context.m b/test/SemaObjC/missing-method-context.m new file mode 100644 index 000000000000..2d0758b1fa8d --- /dev/null +++ b/test/SemaObjC/missing-method-context.m @@ -0,0 +1,4 @@ +// RUN: clang-cc %s -verify -fsyntax-only +- (void)compilerTestAgainst; // expected-error {{missing context for method declaration}} + +void xx(); // expected-error {{expected method body}} diff --git a/test/SemaObjC/newproperty-class-method-1.m b/test/SemaObjC/newproperty-class-method-1.m new file mode 100644 index 000000000000..4946210c8dcc --- /dev/null +++ b/test/SemaObjC/newproperty-class-method-1.m @@ -0,0 +1,60 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +@interface Subclass ++ (int)magicNumber; ++ (void)setMagicNumber:(int)value; ++ (void)setFakeSetterNumber:(int)value; +@end + +@implementation Subclass +int _magicNumber = 0; ++ (int)magicNumber { + return _magicNumber; +} + ++ (void)setMagicNumber:(int)value { + _magicNumber = value; +} + ++ (void)setFakeSetterNumber:(int)value { + _magicNumber = value; +} + ++ (void) classMeth +{ + self.magicNumber = 10; + if (self.magicNumber != 10) + abort (); +} +@end + +int main (void) { + + int a; + Subclass.magicNumber = 2 /*[Subclass setMagicNumber:2]*/; + if (Subclass.magicNumber != 0) + abort (); + if (Subclass.magicNumber != 2) + abort (); + Subclass.magicNumber += 3; + if (Subclass.magicNumber != 5) + abort (); + Subclass.magicNumber -= 5; + if (Subclass.magicNumber != 0) + abort (); + /* We only have a setter in the following case. */ + Subclass.fakeSetterNumber = 123; + + /* We read it using the other getter. */ + if (Subclass.magicNumber != 123) + abort (); + Subclass.fakeSetterNumber = Subclass.magicNumber; + if (Subclass.magicNumber != 123) + abort (); + + Subclass.fakeSetterNumberX = 123; // expected-error{{property 'fakeSetterNumberX' not found on object of type 'Subclass'}} + + /* Test class methods using the new syntax. */ + [Subclass classMeth]; + return 0; +} diff --git a/test/SemaObjC/no-gc-weak-test.m b/test/SemaObjC/no-gc-weak-test.m new file mode 100644 index 000000000000..f494929ce02d --- /dev/null +++ b/test/SemaObjC/no-gc-weak-test.m @@ -0,0 +1,28 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -verify %s + +@interface Subtask +{ + id _delegate; +} +@property(nonatomic,readwrite,assign) id __weak delegate; +@end + +@implementation Subtask +@synthesize delegate = _delegate; +@end + + +@interface PVSelectionOverlayView2 +{ + id __weak _selectionRect; +} + +@property(assign) id selectionRect; + +@end + +@implementation PVSelectionOverlayView2 + +@synthesize selectionRect = _selectionRect; +@end + diff --git a/test/SemaObjC/no-warn-synth-protocol-meth.m b/test/SemaObjC/no-warn-synth-protocol-meth.m new file mode 100644 index 000000000000..860a0ca2befe --- /dev/null +++ b/test/SemaObjC/no-warn-synth-protocol-meth.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol CYCdef +- (int)name; +@end + +@interface JSCdef <CYCdef> { + int name; +} + +@property (assign) int name; +@end + +@implementation JSCdef +@synthesize name; +@end + diff --git a/test/SemaObjC/no-warn-unimpl-method.m b/test/SemaObjC/no-warn-unimpl-method.m new file mode 100644 index 000000000000..756c47b2fe80 --- /dev/null +++ b/test/SemaObjC/no-warn-unimpl-method.m @@ -0,0 +1,42 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -fsyntax-only -verify %s +// This program tests that if class implements the forwardInvocation method, then +// every method possible is implemented in the class and should not issue +// warning of the "Method definition not found" kind. */ + +@interface NSObject +@end + +@interface NSInvocation +@end + +@interface NSProxy +@end + +@protocol MyProtocol + -(void) doSomething; +@end + +@interface DestinationClass : NSObject<MyProtocol> + -(void) doSomething; +@end + +@implementation DestinationClass + -(void) doSomething + { + } +@end + +@interface MyProxy : NSProxy<MyProtocol> +{ + DestinationClass *mTarget; +} + - (id) init; + - (void)forwardInvocation:(NSInvocation *)anInvocation; +@end + +@implementation MyProxy + - (void)forwardInvocation:(NSInvocation *)anInvocation + { + } + - (id) init {} +@end diff --git a/test/SemaObjC/nsobject-attribute-1.m b/test/SemaObjC/nsobject-attribute-1.m new file mode 100644 index 000000000000..d1f673a9fba9 --- /dev/null +++ b/test/SemaObjC/nsobject-attribute-1.m @@ -0,0 +1,48 @@ +// RUN: clang-cc -fblocks -fsyntax-only -verify %s + +@interface NSObject +- (id)self; +- (id)copy; +@end + +typedef struct _foo *__attribute__((NSObject)) Foo_ref; + +@interface TestObject { + Foo_ref dict; +} +@property(retain) Foo_ref dict; +@end + +@implementation TestObject +@synthesize dict; +@end + +@interface NSDictionary +- (int)retainCount; +@end + +int main(int argc, char *argv[]) { + NSDictionary *dictRef; + Foo_ref foo = (Foo_ref)dictRef; + + // do Properties retain? + int before = [dictRef retainCount]; + int after = [dictRef retainCount]; + + if ([foo retainCount] != [dictRef retainCount]) { + } + + // do Blocks retain? + { + void (^block)(void) = ^{ + [foo self]; + }; + before = [foo retainCount]; + id save = [block copy]; + after = [foo retainCount]; + if (after <= before) { + ; + } + } + return 0; +} diff --git a/test/SemaObjC/nsobject-attribute.m b/test/SemaObjC/nsobject-attribute.m new file mode 100644 index 000000000000..3544cb139aab --- /dev/null +++ b/test/SemaObjC/nsobject-attribute.m @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef struct CGColor * __attribute__ ((NSObject)) CGColorRef; +static int count; +static CGColorRef tmp = 0; + +typedef struct S1 __attribute__ ((NSObject)) CGColorRef1; // expected-error {{__attribute ((NSObject)) is for pointer types only}} +typedef void * __attribute__ ((NSObject)) CGColorRef2; // expected-error {{__attribute ((NSObject)) is for pointer types only}} + +@interface HandTested { +@public + CGColorRef x; +} +@property(copy) CGColorRef x; +@end + +void setProperty(id self, id value) { + ((HandTested *)self)->x = value; +} + +id getProperty(id self) { + return (id)((HandTested *)self)->x; +} + +@implementation HandTested +@synthesize x=x; +@end + +int main(char *argc, char *argv[]) { + HandTested *to; + to.x = tmp; // setter + if (tmp != to.x) + to.x = tmp; + return 0; +} + diff --git a/test/SemaObjC/objc-string-constant.m b/test/SemaObjC/objc-string-constant.m new file mode 100644 index 000000000000..98239229a2c7 --- /dev/null +++ b/test/SemaObjC/objc-string-constant.m @@ -0,0 +1,39 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +#define nil 0 /* id of Nil instance */ + +@interface NSObject +@end + +@interface NSString : NSObject + +@end + +@interface NSMutableString : NSString + +@end + +@interface NSSimpleCString : NSString { +@protected + char *bytes; + int numBytes; +} +@end + +@interface NSConstantString : NSSimpleCString +@end + + +@interface Subclass : NSObject +- (NSString *)token; +@end + +@implementation Subclass +- (NSString *)token; +{ + NSMutableString *result = nil; + + return (result != nil) ? result : @""; +} +@end + diff --git a/test/SemaObjC/objc2-merge-gc-attribue-decl.m b/test/SemaObjC/objc2-merge-gc-attribue-decl.m new file mode 100644 index 000000000000..4e3b3ec7a4dd --- /dev/null +++ b/test/SemaObjC/objc2-merge-gc-attribue-decl.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fobjc-gc -fsyntax-only -verify %s +@interface INTF @end + +extern INTF* p2; +extern __strong INTF* p2; + +extern __strong id p1; +extern id p1; + +extern id CFRunLoopGetMain(); +extern __strong id CFRunLoopGetMain(); + diff --git a/test/SemaObjC/objc2-warn-weak-decl.m b/test/SemaObjC/objc2-warn-weak-decl.m new file mode 100644 index 000000000000..5de52ba2203c --- /dev/null +++ b/test/SemaObjC/objc2-warn-weak-decl.m @@ -0,0 +1,10 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -fobjc-gc -verify %s +struct S { + __weak id p; // expected-warning {{__weak attribute cannot be specified on a field declaration}} +}; + +int main () +{ + __weak id local; // expected-warning {{__weak attribute cannot be specified on an automatic variable}} +} + diff --git a/test/SemaObjC/property-10.m b/test/SemaObjC/property-10.m new file mode 100644 index 000000000000..81b8ee199cb2 --- /dev/null +++ b/test/SemaObjC/property-10.m @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -Wreadonly-setter-attrs -verify %s -fblocks + +// Check property attribute consistency. + +@interface I0 +@property(readonly, readwrite) int p0; // expected-error {{property attributes 'readonly' and 'readwrite' are mutually exclusive}} + +@property(retain) int p1; // expected-error {{property with 'retain' attribute must be of object type}} + +@property(copy) int p2; // expected-error {{property with 'copy' attribute must be of object type}} + +@property(assign, copy) id p3_0; // expected-error {{property attributes 'assign' and 'copy' are mutually exclusive}} +@property(assign, retain) id p3_1; // expected-error {{property attributes 'assign' and 'retain' are mutually exclusive}} +@property(copy, retain) id p3_2; // expected-error {{property attributes 'copy' and 'retain' are mutually exclusive}} +@property(assign, copy, retain) id p3_3; // expected-error {{property attributes 'assign' and 'copy' are mutually exclusive}}, expected-error {{property attributes 'assign' and 'retain' are mutually exclusive}} + +@property id p4; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}}, expected-warning {{default property attribute 'assign' not appropriate for non-gc object}} + +@property(nonatomic,copy) int (^includeMailboxCondition)(); +@property(nonatomic,copy) int (*includeMailboxCondition2)(); // expected-error {{property with 'copy' attribute must be of object type}} + +@end diff --git a/test/SemaObjC/property-11.m b/test/SemaObjC/property-11.m new file mode 100644 index 000000000000..e8e60914716d --- /dev/null +++ b/test/SemaObjC/property-11.m @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface NSSound +@end +@interface NSFont +@end + +@interface NSSound (Adds) +@end + +@implementation NSSound (Adds) +- foo { + return self; +} +- (void)setFoo:obj { +} +@end + +@implementation NSFont (Adds) + +- xx { + NSSound *x; + id o; + + // GCC does *not* warn about the following. Since foo/setFoo: are not in the + // class or category interface for NSSound, the compiler shouldn't find them. + // For now, we will support GCC's behavior (sigh). + o = [x foo]; + o = x.foo; + [x setFoo:o]; + x.foo = o; +} + +@end + diff --git a/test/SemaObjC/property-12.m b/test/SemaObjC/property-12.m new file mode 100644 index 000000000000..50fb63bc006b --- /dev/null +++ b/test/SemaObjC/property-12.m @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -Wreadonly-setter-attrs -verify %s + +@protocol P0 +@property(readonly,assign) id X; // expected-warning {{property attributes 'readonly' and 'assign' are mutually exclusive}} +@end + +@protocol P1 +@property(readonly,retain) id X; // expected-warning {{property attributes 'readonly' and 'retain' are mutually exclusive}} +@end + +@protocol P2 +@property(readonly,copy) id X; // expected-warning {{property attributes 'readonly' and 'copy' are mutually exclusive}} +@end + +@protocol P3 +@property(readonly,readwrite) id X; // expected-error {{property attributes 'readonly' and 'readwrite' are mutually exclusive}} +@end + +@protocol P4 +@property(assign,copy) id X; // expected-error {{property attributes 'assign' and 'copy' are mutually exclusive}} +@end + +@protocol P5 +@property(assign,retain) id X; // expected-error {{property attributes 'assign' and 'retain' are mutually exclusive}} +@end + +@protocol P6 +@property(copy,retain) id X; // expected-error {{property attributes 'copy' and 'retain' are mutually exclusive}} +@end + + + diff --git a/test/SemaObjC/property-13.m b/test/SemaObjC/property-13.m new file mode 100644 index 000000000000..d0e40dcf86ed --- /dev/null +++ b/test/SemaObjC/property-13.m @@ -0,0 +1,77 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface NSObject ++ alloc; +- init; +@end + +@protocol Test + @property int required; + +@optional + @property int optional; + @property int optional1; + @property int optional_preexisting_setter_getter; + @property (setter = setOptional_preexisting_setter_getter: , + getter = optional_preexisting_setter_getter) int optional_with_setter_getter_attr; +@required + @property int required1; +@optional + @property int optional_to_be_defined; + @property (readonly, getter = optional_preexisting_setter_getter) int optional_getter_attr; +@end + +@interface Test : NSObject <Test> { + int ivar; + int ivar1; + int ivar2; +} +@property int required; +@property int optional_to_be_defined; +- (int) optional_preexisting_setter_getter; +- (void) setOptional_preexisting_setter_getter:(int)value; +@end + +@implementation Test +@synthesize required = ivar; +@synthesize required1 = ivar1; +@synthesize optional_to_be_defined = ivar2; +- (int) optional_preexisting_setter_getter { return ivar; } +- (void) setOptional_preexisting_setter_getter:(int)value + { + ivar = value; + } +- (void) setOptional_getter_attr:(int)value { ivar = value; } +@end + +int main () +{ + Test *x = [[Test alloc] init]; + /* 1. Test of a requred property */ + x.required1 = 100; + if (x.required1 != 100) + abort (); + + /* 2. Test of a synthesize optional property */ + x.optional_to_be_defined = 123; + if (x.optional_to_be_defined != 123) + abort (); + + /* 3. Test of optional property with pre-sxisting defined setter/getter */ + x.optional_preexisting_setter_getter = 200; + if (x.optional_preexisting_setter_getter != 200) + abort (); + + /* 4. Test of optional property with setter/getter attribute */ + if (x.optional_with_setter_getter_attr != 200) + abort (); + return 0; + + /* 5. Test of optional property with getter attribute and default setter method. */ + x.optional_getter_attr = 1000; + if (x.optional_getter_attr != 1000) + abort (); + + return 0; +} + diff --git a/test/SemaObjC/property-2.m b/test/SemaObjC/property-2.m new file mode 100644 index 000000000000..159e06b07afa --- /dev/null +++ b/test/SemaObjC/property-2.m @@ -0,0 +1,63 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Tester +@property char PropertyAtomic_char; +@property short PropertyAtomic_short; +@property int PropertyAtomic_int; +@property long PropertyAtomic_long; +@property long long PropertyAtomic_longlong; +@property float PropertyAtomic_float; +@property double PropertyAtomic_double; +@property(assign) id PropertyAtomic_id; +@property(retain) id PropertyAtomicRetained_id; +@property(copy) id PropertyAtomicRetainedCopied_id; +@property(retain) id PropertyAtomicRetainedGCOnly_id; +@property(copy) id PropertyAtomicRetainedCopiedGCOnly_id; +@end + +@implementation Tester +@dynamic PropertyAtomic_char; +@dynamic PropertyAtomic_short; +@dynamic PropertyAtomic_int; +@dynamic PropertyAtomic_long; +@dynamic PropertyAtomic_longlong; +@dynamic PropertyAtomic_float; +@dynamic PropertyAtomic_double; +@dynamic PropertyAtomic_id; +@dynamic PropertyAtomicRetained_id; +@dynamic PropertyAtomicRetainedCopied_id; +@dynamic PropertyAtomicRetainedGCOnly_id; +@dynamic PropertyAtomicRetainedCopiedGCOnly_id; +@end + +@interface SubClass : Tester +{ + char PropertyAtomic_char; + short PropertyAtomic_short; + int PropertyAtomic_int; + long PropertyAtomic_long; + long long PropertyAtomic_longlong; + float PropertyAtomic_float; + double PropertyAtomic_double; + id PropertyAtomic_id; + id PropertyAtomicRetained_id; + id PropertyAtomicRetainedCopied_id; + id PropertyAtomicRetainedGCOnly_id; + id PropertyAtomicRetainedCopiedGCOnly_id; +} +@end + +@implementation SubClass +@synthesize PropertyAtomic_char; +@synthesize PropertyAtomic_short; +@synthesize PropertyAtomic_int; +@synthesize PropertyAtomic_long; +@synthesize PropertyAtomic_longlong; +@synthesize PropertyAtomic_float; +@synthesize PropertyAtomic_double; +@synthesize PropertyAtomic_id; +@synthesize PropertyAtomicRetained_id; +@synthesize PropertyAtomicRetainedCopied_id; +@synthesize PropertyAtomicRetainedGCOnly_id; +@synthesize PropertyAtomicRetainedCopiedGCOnly_id; +@end diff --git a/test/SemaObjC/property-3.m b/test/SemaObjC/property-3.m new file mode 100644 index 000000000000..a66b3d5e1e16 --- /dev/null +++ b/test/SemaObjC/property-3.m @@ -0,0 +1,14 @@ +// RUN: clang-cc -verify %s + +@interface I +{ + id d1; +} +@property (readwrite, copy) id d1; +@property (readwrite, copy) id d2; +@end + +@interface NOW : I +@property (readonly) id d1; // expected-warning {{attribute 'readonly' of property 'd1' restricts attribute 'readwrite' of property inherited from 'I'}} expected-warning {{property 'd1' 'copy' attribute does not match the property inherited from 'I'}} +@property (readwrite, copy) I* d2; +@end diff --git a/test/SemaObjC/property-4.m b/test/SemaObjC/property-4.m new file mode 100644 index 000000000000..56db28274c1a --- /dev/null +++ b/test/SemaObjC/property-4.m @@ -0,0 +1,29 @@ +// RUN: clang-cc -verify %s + +@interface Object +@end + +@protocol ProtocolObject +@property int class; +@property (copy) id MayCauseError; +@end + +@protocol ProtocolDerivedGCObject <ProtocolObject> +@property int Dclass; +@end + +@interface GCObject : Object <ProtocolDerivedGCObject> { + int ifield; + int iOwnClass; + int iDclass; +} +@property int OwnClass; +@end + +@interface ReleaseObject : GCObject <ProtocolObject> { + int newO; + int oldO; +} +@property (retain) id MayCauseError; // expected-warning {{property 'MayCauseError' 'copy' attribute does not match the property inherited from 'ProtocolObject'}} +@end + diff --git a/test/SemaObjC/property-5.m b/test/SemaObjC/property-5.m new file mode 100644 index 000000000000..f463aae62910 --- /dev/null +++ b/test/SemaObjC/property-5.m @@ -0,0 +1,34 @@ +// RUN: clang-cc -verify %s + +@protocol P1 @end +@protocol P2 @end +@protocol P3 @end + +@interface NSData @end + +@interface MutableNSData : NSData @end + +@interface Base : NSData <P1> +@property(readonly) id ref; +@property(readonly) Base *p_base; +@property(readonly) NSData *nsdata; +@property(readonly) NSData * m_nsdata; +@end + +@interface Data : Base <P1, P2> +@property(readonly) NSData *ref; +@property(readonly) Data *p_base; +@property(readonly) MutableNSData * m_nsdata; +@end + +@interface MutedData: Data +@property(readonly) id p_base; +@end + +@interface ConstData : Data <P1, P2, P3> +@property(readonly) ConstData *p_base; +@end + +void foo(Base *b, id x) { + [ b setRef: x ]; // expected-warning {{method '-setRef:' not found}} +} diff --git a/test/SemaObjC/property-6.m b/test/SemaObjC/property-6.m new file mode 100644 index 000000000000..8f77cf1ad212 --- /dev/null +++ b/test/SemaObjC/property-6.m @@ -0,0 +1,69 @@ +// RUN: clang-cc -fsyntax-only -verify %s +# 1 "<command line>" +# 1 "/System/Library/Frameworks/Foundation.framework/Headers/Foundation.h" 1 3 +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; + +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject +- (BOOL)isEqual:(id)object; ++ class; +@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 + +typedef struct {} NSFastEnumerationState; + +@protocol NSFastEnumeration +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end + +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> +- (NSUInteger)count; +@end + +@interface NSMutableArray : NSArray +- (void)addObject:(id)anObject; ++ (id)arrayWithCapacity:(int)numItems; +@end + +@interface NSBundle : NSObject {} ++ (NSBundle *)bundleForClass:(Class)aClass; +- (NSString *)bundlePath; +- (void)setBundlePath:(NSString *)x; +@end + +@interface NSException : NSObject <NSCopying, NSCoding> {} +@end + +@class NSArray, NSDictionary, NSError, NSString, NSURL; + +@interface DTPlugInManager : NSObject +@end + +@implementation DTPlugInManager ++ (DTPlugInManager *)defaultPlugInManager { + @try { + NSMutableArray *plugInPaths = [NSMutableArray arrayWithCapacity:100]; + NSBundle *frameworkBundle = [NSBundle bundleForClass:[DTPlugInManager class]]; + frameworkBundle.bundlePath = 0; + [plugInPaths addObject:frameworkBundle.bundlePath]; + } + @catch (NSException *exception) {} +} +@end diff --git a/test/SemaObjC/property-7.m b/test/SemaObjC/property-7.m new file mode 100644 index 000000000000..99c16cef73d8 --- /dev/null +++ b/test/SemaObjC/property-7.m @@ -0,0 +1,34 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef signed char BOOL; +typedef struct _NSZone NSZone; + +@protocol NSObject +- (BOOL)isEqual:(id)object; +@end + +@protocol NSCopying +- (id)copyWithZone:(NSZone *)zone; +@end + +@interface NSObject <NSObject> {} +@end + +@class NSString, NSData, NSMutableData, NSMutableDictionary, NSMutableArray; + +@interface SCMObject : NSObject <NSCopying> {} + @property(assign) SCMObject *__attribute__((objc_gc(weak))) parent; +@end + +@interface SCMNode : SCMObject +{ + NSString *_name; +} +@property(copy) NSString *name; +@end + +@implementation SCMNode + @synthesize name = _name; + - (void) setParent:(SCMObject *__attribute__((objc_gc(weak)))) inParent { + super.parent = inParent; + } +@end diff --git a/test/SemaObjC/property-8.m b/test/SemaObjC/property-8.m new file mode 100644 index 000000000000..49bd409f27c5 --- /dev/null +++ b/test/SemaObjC/property-8.m @@ -0,0 +1,74 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; + +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject - (BOOL)isEqual:(id)object; @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 + +typedef float CGFloat; + +typedef enum { NSMinXEdge = 0, NSMinYEdge = 1, NSMaxXEdge = 2, NSMaxYEdge = 3 } NSFastEnumerationState; + +@protocol NSFastEnumeration +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end + +@class NSString; + +@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> +- (NSUInteger)count; +@end + +extern NSString * const NSBundleDidLoadNotification; + +@interface NSObject(NSKeyValueObserving) +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context; +- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath; +@end + +enum { NSCaseInsensitivePredicateOption = 0x01, NSDiacriticInsensitivePredicateOption = 0x02 }; + +@interface NSResponder : NSObject <NSCoding> {} +@end + +extern NSString * const NSFullScreenModeAllScreens; +@interface NSWindowController : NSResponder <NSCoding> {} +@end + +extern NSString *NSAlignmentBinding ; + +@interface _XCOQQuery : NSObject {} +@end + +extern NSString *PBXWindowDidChangeFirstResponderNotification; + +@interface PBXModule : NSWindowController {} +@end + +@class _XCOQHelpTextBackgroundView; +@interface PBXOpenQuicklyModule : PBXModule +{ +@private + _XCOQQuery *_query; +} +@end + +@interface PBXOpenQuicklyModule () +@property(readwrite, retain) _XCOQQuery *query; +@end + +@implementation PBXOpenQuicklyModule +@synthesize query = _query; +- (void) _clearQuery +{ + [self.query removeObserver: self forKeyPath: @"matches"]; +} +@end + diff --git a/test/SemaObjC/property-9-impl-method.m b/test/SemaObjC/property-9-impl-method.m new file mode 100644 index 000000000000..c97f38891190 --- /dev/null +++ b/test/SemaObjC/property-9-impl-method.m @@ -0,0 +1,94 @@ +// RUN: clang-cc %s -fsyntax-only -verify +// rdar://5967199 + +typedef signed char BOOL; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject +- (BOOL) isEqual:(id) object; +@end + +@protocol NSCoding +- (void) encodeWithCoder:(NSCoder *) aCoder; +@end + +@interface NSObject < NSObject > {} +@end + +typedef float CGFloat; +typedef struct _NSPoint {} NSSize; +typedef struct _NSRect {} NSRect; +typedef enum { NSMinXEdge = 0, NSMinYEdge = 1, NSMaxXEdge = 2, NSMaxYEdge = 3} NSRectEdge; +extern void NSDivideRect(NSRect inRect, NSRect * slice, NSRect * rem, CGFloat amount, NSRectEdge edge); + +@interface NSResponder:NSObject < NSCoding > {} +@end + +@protocol NSAnimatablePropertyContainer +- (id) animator; +@end + +extern NSString *NSAnimationTriggerOrderIn; + +@interface NSView:NSResponder < NSAnimatablePropertyContainer > {} +-(NSRect) bounds; +@end + +enum { + NSBackgroundStyleLight = 0, NSBackgroundStyleDark, NSBackgroundStyleRaised, NSBackgroundStyleLowered +}; + +@interface NSTabView:NSView {} +@end + +@ class OrganizerTabHeader; + +@interface OrganizerTabView:NSTabView {} +@property(assign) +NSSize minimumSize; +@end + +@interface OrganizerTabView() +@property(readonly) OrganizerTabHeader *tabHeaderView; +@property(readonly) NSRect headerRect; +@end + +@implementation OrganizerTabView +@dynamic tabHeaderView, headerRect, minimumSize; +-(CGFloat) tabAreaThickness {} +-(NSRectEdge) rectEdgeForTabs { + NSRect dummy, result = {}; + NSDivideRect(self.bounds, &result, &dummy, self.tabAreaThickness, self.rectEdgeForTabs); +} +@end + +@class NSImage; + +@interface XCImageArchiveEntry : NSObject +{ + NSImage *_cachedImage; +} + +@end + +@implementation XCImageArchiveEntry + +- (NSImage *)image +{ + return _cachedImage; +} + +@end + +@interface XCImageArchive : NSObject +@end + +@implementation XCImageArchive + +- (NSImage *)imageNamed:(NSString *)name +{ + XCImageArchiveEntry * entry; + return entry ? entry.image : ((void *)0); +} + +@end diff --git a/test/SemaObjC/property-9.m b/test/SemaObjC/property-9.m new file mode 100644 index 000000000000..752f9c09ebf6 --- /dev/null +++ b/test/SemaObjC/property-9.m @@ -0,0 +1,86 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef signed char BOOL; +@protocol NSObject - (BOOL)isEqual:(id)object; @end + +@interface NSObject <NSObject> {} @end + +@interface _NSServicesInContextMenu : NSObject { + id _requestor; + NSObject *_appleEventDescriptor; +} + +@property (retain, nonatomic) id requestor; +@property (retain, nonatomic) id appleEventDescriptor; + +@end + +@implementation _NSServicesInContextMenu + +@synthesize requestor = _requestor, appleEventDescriptor = _appleEventDescriptor; + +@end + +@class NSString; + +@protocol MyProtocol +- (NSString *)stringValue; +@end + +@interface MyClass : NSObject { + id _myIvar; +} +@property (readwrite, retain) id<MyProtocol> myIvar; +@end + +@implementation MyClass +@synthesize myIvar = _myIvar; +@end + + +@interface BadPropClass +{ + int _awesome; +} + +@property (readonly) int; // expected-error {{declaration does not declare anything}} +@property (readonly) ; // expected-error {{type name requires a specifier or qualifier}} \ + expected-error {{declaration does not declare anything}} +@property (readonly) int : 4; // expected-error {{property requires fields to be named}} + + +// test parser recovery: rdar://6254579 +@property ( // expected-note {{to match this '('}} + readonly getter=isAwesome) // expected-error {{error: expected ')'}} + + int _awesome; +@property (readonlyx) // expected-error {{unknown property attribute 'readonlyx'}} + int _awesome2; + +@property ( // expected-note {{to match this '('}} + +) // expected-error {{error: expected ')'}} + + int _awesome3; + +@end + +@protocol PVImageViewProtocol +@property int inEyeDropperMode; +@end + +@interface Cls +@property int inEyeDropperMode; +@end + +@interface PVAdjustColor @end + +@implementation PVAdjustColor + +- xx { + id <PVImageViewProtocol> view; + Cls *c; + + c.inEyeDropperMode = 1; + view.inEyeDropperMode = 1; +} +@end diff --git a/test/SemaObjC/property-category-1.m b/test/SemaObjC/property-category-1.m new file mode 100644 index 000000000000..6695239fd352 --- /dev/null +++ b/test/SemaObjC/property-category-1.m @@ -0,0 +1,52 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Object ++ (id)new; +@end + +@interface ReadOnly : Object +{ + int _object; + int _Anotherobject; +} +@property(readonly) int object; +@property(readonly) int Anotherobject; +@end + +@interface ReadOnly () +@property(readwrite) int object; +@property(readwrite, setter = myAnotherobjectSetter:) int Anotherobject; +@end + +@implementation ReadOnly +@synthesize object = _object; +@synthesize Anotherobject = _Anotherobject; +- (void) myAnotherobjectSetter : (int)val { + _Anotherobject = val; +} +@end + +int main(int argc, char **argv) { + ReadOnly *test = [ReadOnly new]; + test.object = 12345; + test.Anotherobject = 200; + return test.object - 12345 + test.Anotherobject - 200; +} + +/// + +@interface I0 +@property(readonly) int p0; // expected-warning {{property 'p0' requires method 'p0' to be defined}} +@end + +@interface I0 (Cat0) +@end + +@interface I0 (Cat1) +@end + +@implementation I0 // expected-note {{implementation is here}} +- (void) foo { + self.p0 = 0; // expected-error {{assigning to property with 'readonly' attribute not allowed}} +} +@end diff --git a/test/SemaObjC/property-category-2.m b/test/SemaObjC/property-category-2.m new file mode 100644 index 000000000000..c245e36819cc --- /dev/null +++ b/test/SemaObjC/property-category-2.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// Test that a property can be synthesize in a category +// implementation with no error. + +@protocol MyProtocol +@property float myFloat; +@property float anotherFloat; +@end + +@interface MyObject { float anotherFloat; } +@end + +@interface MyObject (CAT) <MyProtocol> +@end + +@implementation MyObject (CAT) +@dynamic myFloat; // OK +@synthesize anotherFloat; // expected-error {{@synthesize not allowed in a category's implementation}} +@end diff --git a/test/SemaObjC/property-category-3.m b/test/SemaObjC/property-category-3.m new file mode 100644 index 000000000000..bf9e8cbd9d9f --- /dev/null +++ b/test/SemaObjC/property-category-3.m @@ -0,0 +1,31 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol P + @property(readonly) int X; +@end + +@protocol P1<P> + @property (copy) id ID; +@end + +@interface I +@end + +@interface I (Cat) <P> +@property float X; // expected-warning {{property type 'float' is incompatible with type 'int' inherited from 'P'}} +@end + +@interface I (Cat2) <P1> +@property (retain) id ID; // expected-warning {{property 'ID' 'copy' attribute does not match the property inherited from 'P1'}} +@end + + +@interface A +@property(assign) int categoryProperty; +@end + +// Don't issue warning on unimplemented setter/getter +// because property is @dynamic. +@implementation A +@dynamic categoryProperty; +@end diff --git a/test/SemaObjC/property-error-readonly-assign.m b/test/SemaObjC/property-error-readonly-assign.m new file mode 100644 index 000000000000..edeff09dfadd --- /dev/null +++ b/test/SemaObjC/property-error-readonly-assign.m @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface A + -(int) x; +@property (readonly) int x; +@property int ok; +@end + +@interface B + -(void) setOk:(int)arg; + -(int) x; + -(int) ok; +@end + +void f0(A *a, B* b) { + a.x = 10; // expected-error {{assigning to property with 'readonly' attribute not allowed}} + a.ok = 20; + b.x = 10; // expected-error {{setter method is needed to assign to object using property assignment syntax}} + b.ok = 20; +} + diff --git a/test/SemaObjC/property-impl-misuse.m b/test/SemaObjC/property-impl-misuse.m new file mode 100644 index 000000000000..7b956b5f7b4d --- /dev/null +++ b/test/SemaObjC/property-impl-misuse.m @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface I { + int Y; +} +@property int X; +@property int Y; +@property int Z; +@end + +@implementation I +@dynamic X; // expected-note {{previous declaration is here}} +@dynamic X; // expected-error {{property 'X' is already implemented}} +@synthesize Y; // expected-note {{previous use is here}} +@synthesize Z=Y; // expected-error {{synthesized properties 'Z' and 'Y' both claim ivar 'Y'}} +@end diff --git a/test/SemaObjC/property-inherited.m b/test/SemaObjC/property-inherited.m new file mode 100644 index 000000000000..6c06b90a9f0a --- /dev/null +++ b/test/SemaObjC/property-inherited.m @@ -0,0 +1,44 @@ +// RUN: clang-cc %s -fsyntax-only -verify + +// <rdar://problem/6497242> Inherited overridden protocol declared objects don't work + +@protocol NSObject @end +@interface NSObject @end + +@protocol FooDelegate<NSObject> +@optional +- (void)fooTask; +@end + +@protocol BarDelegate<NSObject, FooDelegate> +@optional +- (void)barTask; +@end + +@interface Foo : NSObject { + id _delegate; +} +@property(nonatomic, assign) id<FooDelegate> delegate; +@property(nonatomic, assign) id<BarDelegate> delegate2; +@end +@interface Bar : Foo { +} +@property(nonatomic, assign) id<BarDelegate> delegate; +@property(nonatomic, assign) id<FooDelegate> delegate2; // expected-warning{{property type 'id<FooDelegate>' is incompatible with type 'id<BarDelegate>' inherited from 'Foo'}} +@end + +@interface NSData @end + +@interface NSMutableData : NSData @end + +@interface Base : NSData +@property(assign) id ref; +@property(assign) Base *p_base; +@property(assign) NSMutableData *p_data; +@end + +@interface Data : Base +@property(assign) NSData *ref; +@property(assign) Data *p_base; +@property(assign) NSData *p_data; // expected-warning{{property type 'NSData *' is incompatible with type 'NSMutableData *' inherited from 'Base'}} +@end diff --git a/test/SemaObjC/property-ivar-mismatch.m b/test/SemaObjC/property-ivar-mismatch.m new file mode 100644 index 000000000000..75c1e97c4ee9 --- /dev/null +++ b/test/SemaObjC/property-ivar-mismatch.m @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// Test that arithmatic types on property and its ivar have exact match. + +@interface Test4 +{ + char ivar; +} +@property int prop; +@end + +@implementation Test4 +@synthesize prop = ivar; // expected-error {{type of property 'prop' does not match type of ivar 'ivar'}} +@end + diff --git a/test/SemaObjC/property-method-lookup-impl.m b/test/SemaObjC/property-method-lookup-impl.m new file mode 100644 index 000000000000..ed7e9bcd4315 --- /dev/null +++ b/test/SemaObjC/property-method-lookup-impl.m @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface SSyncCEList +{ + id _list; +} +@end + +@implementation SSyncCEList + +- (id) list +{ +} +@end + +@interface SSyncConflictList : SSyncCEList +@end + +@implementation SSyncConflictList + +- (id)Meth : (SSyncConflictList*)other + { + return other.list; + } +@end + diff --git a/test/SemaObjC/property-missing.m b/test/SemaObjC/property-missing.m new file mode 100644 index 000000000000..1aa94ce71b25 --- /dev/null +++ b/test/SemaObjC/property-missing.m @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR3234 + +@protocol NSCopying @end +@interface NSObject @end + +void f1(NSObject *o) +{ + o.foo; // expected-error{{property 'foo' not found on object of type 'NSObject *'}} +} + +void f2(id<NSCopying> o) +{ + o.foo; // expected-error{{property 'foo' not found on object of type 'id<NSCopying>'}} +} + +void f3(id o) +{ + o.foo; // expected-error{{member reference base type 'id' is not a structure or union}} +} + diff --git a/test/SemaObjC/property-nonfragile-abi.m b/test/SemaObjC/property-nonfragile-abi.m new file mode 100644 index 000000000000..e2de77d3a28c --- /dev/null +++ b/test/SemaObjC/property-nonfragile-abi.m @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -triple x86_64-apple-darwin9 -verify %s + +typedef signed char BOOL; + +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject +- (BOOL)isEqual:(id)object; +@end + +@interface NSObject <NSObject> {} +@end + +@interface XCDeviceWillExecuteInfoBaton : NSObject {} + @property (retain) __attribute__((objc_gc(strong))) NSString *sdkPath; +@end + +@implementation XCDeviceWillExecuteInfoBaton + @synthesize sdkPath; +@end + diff --git a/test/SemaObjC/property-noprotocol-warning.m b/test/SemaObjC/property-noprotocol-warning.m new file mode 100644 index 000000000000..95ec15aa1e0c --- /dev/null +++ b/test/SemaObjC/property-noprotocol-warning.m @@ -0,0 +1,36 @@ +// RUN: clang-cc -fsyntax-only -verify %s + + +@interface Object ++ (id) new; +@end + +@protocol GCObject +@property int class; +@end + +@protocol DerivedGCObject <GCObject> +@property int Dclass; +@end + +@interface GCObject : Object <DerivedGCObject> { + int ifield; + int iOwnClass; + int iDclass; +} +@property int OwnClass; +@end + +@implementation GCObject : Object +@synthesize class=ifield; +@synthesize Dclass=iDclass; +@synthesize OwnClass=iOwnClass; +@end + +int main(int argc, char **argv) { + GCObject *f = [GCObject new]; + f.class = 5; + f.Dclass = 1; + f.OwnClass = 3; + return f.class + f.Dclass + f.OwnClass - 9; +} diff --git a/test/SemaObjC/property-redundant-decl-accessor.m b/test/SemaObjC/property-redundant-decl-accessor.m new file mode 100644 index 000000000000..ffd5129c8e5a --- /dev/null +++ b/test/SemaObjC/property-redundant-decl-accessor.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -Werror -verify %s + +@interface MyClass { + const char *_myName; +} + +@property const char *myName; + +- (const char *)myName; +- (void)setMyName:(const char *)name; + +@end + +@implementation MyClass + +@synthesize myName = _myName; + +@end diff --git a/test/SemaObjC/property-typecheck-1.m b/test/SemaObjC/property-typecheck-1.m new file mode 100644 index 000000000000..ca8a1393b01b --- /dev/null +++ b/test/SemaObjC/property-typecheck-1.m @@ -0,0 +1,101 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface A +-(float) x; // expected-note {{declared at}} +@property int x; // expected-warning {{type of property 'x' does not match type of accessor 'x'}} +@end + +@interface A (Cat) +@property int moo; // expected-note {{previous definition is here}} +@end + +@implementation A (Cat) +-(int) moo { + return 0; +} +-(void) setMoo: (float) x { // expected-warning {{conflicting parameter types in implementation of 'setMoo:': 'int' vs 'float'}} +} +@end + + +typedef int T[2]; +typedef void (F)(void); + +@interface C +@property(assign) T p2; // expected-error {{property cannot have array or function type 'T'}} + +@property(assign) F f2; // expected-error {{property cannot have array or function type 'F'}} + +@end + + +@class SSyncSet; + +@interface SPeer + @property(nonatomic,readonly,retain) SSyncSet* syncSet; +@end + +@class SSyncSet_iDisk; + +@interface SPeer_iDisk_remote1 : SPeer +- (SSyncSet_iDisk*) syncSet; // expected-note {{declared at}} +@end + +@interface SPeer_iDisk_local +- (SSyncSet_iDisk*) syncSet; +@end + +@interface SSyncSet +@end + +@interface SSyncSet_iDisk +@property(nonatomic,readonly,retain) SPeer_iDisk_local* localPeer; +@end + +@interface SPeer_iDisk_remote1 (protected) +@end + +@implementation SPeer_iDisk_remote1 (protected) +- (id) preferredSource1 +{ + return self.syncSet.localPeer; // expected-warning {{type of property 'syncSet' does not match type of accessor 'syncSet'}} +} +@end + +@interface NSArray @end + +@interface NSMutableArray : NSArray +@end + +@interface Class1 +{ + NSMutableArray* pieces; + NSArray* first; +} + +@property (readonly) NSArray* pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}} +@property (readonly) NSMutableArray* first; + +- (NSMutableArray*) pieces; // expected-note {{declared at}} // expected-note {{declared at}} +- (NSArray*) first; +@end + +@interface Class2 { + Class1* container; +} + +@end + +@implementation Class2 + +- (id) lastPiece +{ + return container.pieces; // expected-warning {{type of property 'pieces' does not match type of accessor 'pieces'}} +} + +- (id)firstPeice +{ + return container.first; +} +@end + diff --git a/test/SemaObjC/property-user-setter.m b/test/SemaObjC/property-user-setter.m new file mode 100644 index 000000000000..9b0380ede88e --- /dev/null +++ b/test/SemaObjC/property-user-setter.m @@ -0,0 +1,90 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface I0 +@property(readonly) int x; +@property(readonly) int y; +@property(readonly) int z; +-(void) setY: (int) y0; +@end + +@interface I0 (Cat0) +-(void) setX: (int) a0; +@end + +@implementation I0 +@dynamic x; +@dynamic y; +@dynamic z; +-(void) setY: (int) y0{} + +-(void) im0 { + self.x = 0; + self.y = 2; + self.z = 2; // expected-error {{assigning to property with 'readonly' attribute not allowed}} +} +@end + +// Test when property is 'readonly' but it has a setter in +// its implementation only. +@interface I1 { +} +@property(readonly) int identifier; +@end + + +@implementation I1 +@dynamic identifier; +- (void)setIdentifier:(int)ident {} + +- (id)initWithIdentifier:(int)Arg { + self.identifier = 0; +} + +@end + + +// Also in a category implementation +@interface I1(CAT) +@property(readonly) int rprop; +@end + + +@implementation I1(CAT) +@dynamic rprop; +- (void)setRprop:(int)ident {} + +- (id)initWithIdentifier:(int)Arg { + self.rprop = 0; +} + +@end + +static int g_val; + +@interface Root ++ alloc; +- init; +@end + +@interface Subclass : Root +{ + int setterOnly; +} +- (void) setSetterOnly:(int)value; +@end + +@implementation Subclass +- (void) setSetterOnly:(int)value { + setterOnly = value; + g_val = setterOnly; +} +@end + +int main (void) { + Subclass *x = [[Subclass alloc] init]; + + x.setterOnly = 4; + if (g_val != 4) + abort (); + return 0; +} diff --git a/test/SemaObjC/property-weak.m b/test/SemaObjC/property-weak.m new file mode 100644 index 000000000000..293432fc828f --- /dev/null +++ b/test/SemaObjC/property-weak.m @@ -0,0 +1,5 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -verify %s + +@interface foo +@property(nonatomic) int foo __attribute__((weak_import)); +@end diff --git a/test/SemaObjC/property.m b/test/SemaObjC/property.m new file mode 100644 index 000000000000..cf2624f8204d --- /dev/null +++ b/test/SemaObjC/property.m @@ -0,0 +1,55 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -verify %s + +@interface I +{ + int IVAR; + int name; +} +@property int d1; +@property id prop_id; // expected-warning {{no 'assign', 'retain', or 'copy' attribute is specified - 'assign' is assumed}}, expected-warning {{default property attribute 'assign' not appropriate for non-gc object}} +@property int name; +@end + +@interface I(CAT) +@property int d1; +@end + +@implementation I +@synthesize d1; // expected-error {{synthesized property 'd1' must either be named the same as}} +@dynamic bad; // expected-error {{property implementation must have its declaration in interface 'I'}} +@synthesize prop_id; // expected-error {{synthesized property 'prop_id' must either be named the same}} // expected-note {{previous declaration is here}} +@synthesize prop_id = IVAR; // expected-error {{type of property 'prop_id' does not match type of ivar 'IVAR'}} // expected-error {{property 'prop_id' is already implemented}} +@synthesize name; // OK! property with same name as an accessible ivar of same name +@end + +@implementation I(CAT) +@synthesize d1; // expected-error {{@synthesize not allowed in a category's implementation}} +@dynamic bad; // expected-error {{property implementation must have its declaration in the category 'CAT'}} +@end + +@implementation E // expected-warning {{cannot find interface declaration for 'E'}} +@dynamic d; // expected-error {{property implementation must have its declaration in interface 'E'}} +@end + +@implementation Q(MYCAT) // expected-error {{cannot find interface declaration for 'Q'}} +@dynamic d; // expected-error {{property implementation in a category with no category declaration}} +@end + +@interface Foo +@property double bar; +@end + +int func1() { + id foo; + double bar = [foo bar]; + return 0; +} + +// PR3932 +typedef id BYObjectIdentifier; +@interface Foo1 { + void *isa; +} +@property(copy) BYObjectIdentifier identifier; +@end + diff --git a/test/SemaObjC/props-on-prots.m b/test/SemaObjC/props-on-prots.m new file mode 100644 index 000000000000..7bee8a0bc319 --- /dev/null +++ b/test/SemaObjC/props-on-prots.m @@ -0,0 +1,65 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef signed char BOOL; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject +- (BOOL) isEqual:(id) object; +@end + +@protocol NSCoding +- (void) encodeWithCoder:(NSCoder *) aCoder; +@end + +@interface NSObject < NSObject > {} @end + +typedef float CGFloat; + +@interface NSResponder:NSObject < NSCoding > {} @end + +@class XCElementView; + +typedef struct _XCElementInset {} XCElementInset; + +@protocol XCElementP < NSObject > +-(id) vertical; +@end + +@protocol XCElementDisplayDelegateP; +@protocol XCElementTabMarkerP; + +typedef NSObject < XCElementTabMarkerP > XCElementTabMarker; + +@protocol XCElementTabberP < XCElementP > +-(void) setMarker:(XCElementTabMarker *) marker; +@end + +typedef NSObject < XCElementTabberP > XCElementTabber; + +@protocol XCElementTabMarkerP < NSObject > +@property(nonatomic) +BOOL variableSized; +@end + +@protocol XCElementJustifierP < XCElementP > +-(void) setHJustification:(CGFloat) hJust; +@end + +typedef NSObject < XCElementJustifierP > XCElementJustifier; +@interface XCElementImp:NSObject < XCElementP > {} +@end + +@class XCElementImp; + +@interface XCElementTabberImp:XCElementImp < XCElementTabberP > { + XCElementTabMarker *_marker; +} +@end + +@implementation XCElementTabberImp +- (void) setMarker:(XCElementTabMarker *) marker { + if (_marker && _marker.variableSized) { + } +} +- (id)vertical { return self; } +- (BOOL)isEqual:x { return 1; } +@end diff --git a/test/SemaObjC/protocol-archane.m b/test/SemaObjC/protocol-archane.m new file mode 100644 index 000000000000..3e70c0509652 --- /dev/null +++ b/test/SemaObjC/protocol-archane.m @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// rdar://5986251 + +@protocol SomeProtocol +- (void) bar; +@end + +void foo(id x) { + bar((short<SomeProtocol>)x); // expected-error {{expected ')'}} expected-note {{to match this '('}} + bar((<SomeProtocol>)x); // expected-warning {{protocol qualifiers without 'id' is archaic}} + + [(<SomeProtocol>)x bar]; // expected-warning {{protocol qualifiers without 'id' is archaic}} +} + +@protocol MyProtocol +- (void)doSomething; +@end + +@interface MyClass +- (void)m1:(id <MyProtocol> const)arg1; + +// FIXME: provide a better diagnostic (no typedef). +- (void)m2:(id <MyProtocol> short)arg1; // expected-error {{'short type-name' is invalid}} +@end + +typedef int NotAnObjCObjectType; + +// GCC doesn't diagnose this. +NotAnObjCObjectType <SomeProtocol> *obj; // expected-error {{invalid protocol qualifiers on non-ObjC type}} + +// Decided not to support the following GCC extension. Found while researching rdar://6497631 +typedef struct objc_class *Class; + +Class <SomeProtocol> UnfortunateGCCExtension; // expected-error {{protocol qualified 'Class' is unsupported}} + diff --git a/test/SemaObjC/protocol-attribute.m b/test/SemaObjC/protocol-attribute.m new file mode 100644 index 000000000000..ae8441132c77 --- /dev/null +++ b/test/SemaObjC/protocol-attribute.m @@ -0,0 +1,49 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +__attribute ((unavailable)) +@protocol FwProto; // expected-note{{marked unavailable}} + +Class <FwProto> cFw = 0; // expected-warning {{'FwProto' is unavailable}} expected-error{{protocol qualified 'Class' is unsupported}} + + +__attribute ((deprecated)) @protocol MyProto1 +@end + +@protocol Proto2 <MyProto1> // expected-warning {{'MyProto1' is deprecated}} ++method2; +@end + + +@interface MyClass1 <MyProto1> // expected-warning {{'MyProto1' is deprecated}} +{ + Class isa; +} +@end + +@interface Derived : MyClass1 <MyProto1> // expected-warning {{'MyProto1' is deprecated}} +{ + id <MyProto1> ivar; // expected-warning {{'MyProto1' is deprecated}} +} +@end + +@interface MyClass1 (Category) <MyProto1, Proto2> // expected-warning {{'MyProto1' is deprecated}} +@end + + + +Class <MyProto1> clsP1 = 0; // expected-warning {{'MyProto1' is deprecated}} expected-error{{protocol qualified 'Class' is unsupported}} + +@protocol FwProto @end // expected-note{{marked unavailable}} + +@interface MyClass2 <FwProto> // expected-warning {{'FwProto' is unavailable}} +@end + +__attribute ((unavailable)) __attribute ((deprecated)) @protocol XProto; // expected-note{{marked unavailable}} + +id <XProto> idX = 0; // expected-warning {{'XProto' is unavailable}} expected-warning {{'XProto' is deprecated}} + +int main () +{ + MyClass1 <MyProto1> *p1; // expected-warning {{'MyProto1' is deprecated}} +} + diff --git a/test/SemaObjC/protocol-expr-1.m b/test/SemaObjC/protocol-expr-1.m new file mode 100644 index 000000000000..cc1c3231d5e5 --- /dev/null +++ b/test/SemaObjC/protocol-expr-1.m @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol fproto; + +@protocol p1 +@end + +@class cl; + +int main() +{ + Protocol *proto = @protocol(p1); + Protocol *fproto = @protocol(fproto); +} + diff --git a/test/SemaObjC/protocol-expr-neg-1.m b/test/SemaObjC/protocol-expr-neg-1.m new file mode 100644 index 000000000000..9393fde3c3c7 --- /dev/null +++ b/test/SemaObjC/protocol-expr-neg-1.m @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@class Protocol; + +@protocol fproto; + +@protocol p1 +@end + +@class cl; + +int main() +{ + Protocol *proto = @protocol(p1); + Protocol *fproto = @protocol(fproto); + Protocol *pp = @protocol(i); // expected-error {{cannot find protocol declaration for 'i'}} + Protocol *p1p = @protocol(cl); // expected-error {{cannot find protocol declaration for 'cl'}} +} + diff --git a/test/SemaObjC/protocol-id-test-1.m b/test/SemaObjC/protocol-id-test-1.m new file mode 100644 index 000000000000..5e737a8fae07 --- /dev/null +++ b/test/SemaObjC/protocol-id-test-1.m @@ -0,0 +1,16 @@ +// RUN: clang-cc -verify %s + +@interface FF +- (void) Meth; +@end + +@protocol P +@end + +@interface INTF<P> +- (void)IMeth; +@end + +@implementation INTF +- (void)IMeth {INTF<P> *pi; [pi Meth]; } // expected-warning {{method '-Meth' not found (return type defaults to 'id')}} +@end diff --git a/test/SemaObjC/protocol-id-test-2.m b/test/SemaObjC/protocol-id-test-2.m new file mode 100644 index 000000000000..a55923c21058 --- /dev/null +++ b/test/SemaObjC/protocol-id-test-2.m @@ -0,0 +1,12 @@ +// RUN: clang-cc -verify %s + +@protocol P +@end + +@interface INTF<P> +- (void)IMeth; +@end + +@implementation INTF +- (void)IMeth { [(id<P>)self Meth]; } // expected-warning {{method '-Meth' not found (return type defaults to 'id')}} +@end diff --git a/test/SemaObjC/protocol-id-test-3.m b/test/SemaObjC/protocol-id-test-3.m new file mode 100644 index 000000000000..3c7f84a181f1 --- /dev/null +++ b/test/SemaObjC/protocol-id-test-3.m @@ -0,0 +1,94 @@ +// RUN: clang-cc -pedantic -fsyntax-only -verify %s + +@protocol MyProto1 +@end + +@protocol MyProto2 +@end + +@interface INTF @end + +id<MyProto1> Func(INTF <MyProto1, MyProto2> *p2) +{ + return p2; +} + + + + + id<MyProto1> Gunc(id <MyProto1, MyProto2>p2) +{ + return p2; +} + + + id<MyProto1> Gunc1(id <MyProto1, MyProto2>p2) +{ + return p2; +} + +id<MyProto1, MyProto2> Gunc2(id <MyProto1>p2) +{ + Func(p2); // expected-warning {{incompatible type passing 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}} + return p2; // expected-warning {{incompatible type returning 'id<MyProto1>', expected 'id<MyProto1,MyProto2>'}} +} + + + +id<MyProto1> Gunc3(id <MyProto2>p2) +{ + return p2; // expected-warning {{incompatible type returning 'id<MyProto2>', expected 'id<MyProto1>'}} +} + + +id<MyProto1, MyProto2> Gunc4(id <MyProto2, MyProto1>p2) +{ + return p2; +} + + + +INTF<MyProto1> * Hunc(id <MyProto1, MyProto2>p2) +{ + return p2; +} + + +INTF<MyProto1> * Hunc1(id <MyProto1, MyProto2>p2) +{ + return p2; +} + +INTF<MyProto1, MyProto2> * Hunc2(id <MyProto1>p2) +{ + Func(p2); // expected-warning {{incompatible type passing 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}} + return p2; // expected-warning {{incompatible type returning 'id<MyProto1>', expected 'INTF<MyProto1,MyProto2> *'}} +} + +INTF<MyProto1> * Hunc3(id <MyProto2>p2) +{ + return p2; // expected-warning {{incompatible type returning 'id<MyProto2>', expected 'INTF<MyProto1> *'}} +} + + +INTF<MyProto1, MyProto2> * Hunc4(id <MyProto2, MyProto1>p2) +{ + return p2; +} + +id Iunc(id <MyProto1, MyProto2>p2) +{ + return p2; +} + + +id<MyProto1> Iunc1(id p2) +{ + return p2; +} + +id<MyProto1, MyProto2> Iunc2(id p2) +{ + Iunc(p2); + return p2; +} diff --git a/test/SemaObjC/protocol-implementation-inherited.m b/test/SemaObjC/protocol-implementation-inherited.m new file mode 100644 index 000000000000..1aace211c844 --- /dev/null +++ b/test/SemaObjC/protocol-implementation-inherited.m @@ -0,0 +1,56 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol P0 +-bar; +@end + +@interface A <P0> +@end + +// Interface conforms to inherited protocol + +@interface B0 : A <P0> +@end + +@implementation B0 +@end + +// Interface conforms to a protocol which extends another. The other +// protocol is inherited, and extended methods are implemented. + +@protocol P1 <P0> +-foo; +@end + +@interface B1 : A <P1> +@end + +@implementation B1 +-foo {}; +@end + +// Interface conforms to a protocol whose methods are provided by an +// alternate inherited protocol. + +@protocol P2 +-bar; +@end + +@interface B2 : A <P2> +@end + +@implementation B2 +@end + +// Interface conforms to a protocol whose methods are provided by a base class. + +@interface A1 +-bar; +@end + +@interface B3 : A1 <P2> +@end + +@implementation B3 +@end + diff --git a/test/SemaObjC/protocol-lookup-2.m b/test/SemaObjC/protocol-lookup-2.m new file mode 100644 index 000000000000..64d0c3acf036 --- /dev/null +++ b/test/SemaObjC/protocol-lookup-2.m @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s +@interface NSObject @end + +@protocol ProtocolA + ++ (id)classMethod; +- (id)instanceMethod; + +@end + +@protocol ProtocolB <ProtocolA> + +@end + +@interface Foo : NSObject <ProtocolB> + +@end + +@interface SubFoo : Foo + +@end + +@implementation SubFoo + ++ (id)method { + return [super classMethod]; +} + +- (id)method { + return [super instanceMethod]; +} + +@end diff --git a/test/SemaObjC/protocol-lookup.m b/test/SemaObjC/protocol-lookup.m new file mode 100644 index 000000000000..0f1860d2c88e --- /dev/null +++ b/test/SemaObjC/protocol-lookup.m @@ -0,0 +1,50 @@ +// RUN: clang-cc -fsyntax-only -verify %s +@protocol NSObject +- retain; +- release; +@end + +@interface NSObject +- init; +- dealloc; +@end + +@protocol Foo <NSObject> +@end + +@protocol Bar <Foo> +@end + +@interface Baz : NSObject { + id <Foo> _foo; + id <Bar> _bar; +} +- (id)initWithFoo:(id <Foo>)foo bar:(id <Bar>)bar; +@end + +@implementation Baz + +- (id)init +{ + return [self initWithFoo:0 bar:0]; +} + +- (id)initWithFoo:(id <Foo>)foo bar:(id <Bar>)bar +{ + self = [super init]; + if (self != 0) { + _foo = [foo retain]; + _bar = [bar retain]; + } + return self; +} + +- dealloc +{ + [_foo release]; + [_bar release]; + [super dealloc]; +} + +@end + diff --git a/test/SemaObjC/protocol-qualified-class-unsupported.m b/test/SemaObjC/protocol-qualified-class-unsupported.m new file mode 100644 index 000000000000..ad1ed5dc9411 --- /dev/null +++ b/test/SemaObjC/protocol-qualified-class-unsupported.m @@ -0,0 +1,40 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stddef.h> + +typedef struct objc_class *Class; +typedef struct objc_object { + Class isa; +} *id; +id objc_getClass(const char *s); + +@interface Object ++ self; +@end + +@protocol Func ++ (void) class_func0; +- (void) instance_func0; +@end + +@interface Derived: Object <Func> +@end + +@interface Derived2: Object <Func> +@end + +static void doSomething(Class <Func> unsupportedObjectType) { // expected-error {{protocol qualified 'Class' is unsupported}} + [unsupportedObjectType class_func0]; +} + +static void doSomethingElse(id <Func> pleaseConvertToThisType) { + [pleaseConvertToThisType class_func0]; +} + +int main(int argv, char *argc[]) { + doSomething([Derived self]); + doSomething([Derived2 self]); + doSomethingElse([Derived self]); + doSomethingElse([Derived2 self]); +} + diff --git a/test/SemaObjC/protocol-typecheck.m b/test/SemaObjC/protocol-typecheck.m new file mode 100644 index 000000000000..de66dedda70a --- /dev/null +++ b/test/SemaObjC/protocol-typecheck.m @@ -0,0 +1,25 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface NSObject @end +@protocol XCElementP @end +@protocol XCElementSpacerP <XCElementP> @end + +@protocol PWhatever @end + +@interface XX + +- (void)setFlexElement:(NSObject <PWhatever, XCElementP> *)flexer; +- (void)setFlexElement2:(NSObject <PWhatever, XCElementSpacerP> *)flexer; + +@end + +void func() { + NSObject <PWhatever, XCElementSpacerP> * flexer; + NSObject <PWhatever, XCElementP> * flexer2; + XX *obj; + [obj setFlexElement:flexer]; + // FIXME: GCC provides the following diagnostic (which is much better): + // protocol-typecheck.m:21: warning: class 'NSObject <PWhatever, XCElementP>' does not implement the 'XCElementSpacerP' protocol + [obj setFlexElement2:flexer2]; // expected-warning{{incompatible pointer types sending 'NSObject<PWhatever,XCElementP> *', expected 'NSObject<PWhatever,XCElementSpacerP> *'}} +} + diff --git a/test/SemaObjC/protocols.m b/test/SemaObjC/protocols.m new file mode 100644 index 000000000000..9fbdc16759dd --- /dev/null +++ b/test/SemaObjC/protocols.m @@ -0,0 +1,63 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface INTF1 +@required // expected-error {{directive may only be specified in protocols only}} +- (int) FooBar; +- (int) FooBar1; +- (int) FooBar2; +@optional // expected-error {{directive may only be specified in protocols only}} ++ (int) C; + +- (int)I; +@end + +@protocol p1,p2,p3; + +@protocol p1; + +@protocol PROTO1 +@required +- (int) FooBar; +@optional +- (void) MyMethod1; ++ (int) S; +@end + + +@protocol PROTO2<p1> +@end + +@protocol p1 @end + +@protocol PROTO<p1> // expected-note {{previous definition is here}} +@end + +@protocol PROTO<p1> // expected-warning {{duplicate protocol definition of 'PROTO'}} +@end + +@protocol PROTO3<p1, p1> +@end + +@protocol p2 <p1> +@end + +@protocol PROTO4 <p1, p2, PROTO, PROTO3, p3> +@end + + +// rdar://6771034 +@protocol XX; +@protocol YY <XX> // Use of declaration of XX here should not cause a warning. +- zz; +@end + + +// Detect circular dependencies. +@protocol B; +@protocol C < B > // expected-note{{previous definition is here}} +@end +@protocol A < C > +@end +@protocol B < A > // expected-error{{protocol has circular dependency}} +@end + diff --git a/test/SemaObjC/rdr-6211479-array-property.m b/test/SemaObjC/rdr-6211479-array-property.m new file mode 100644 index 000000000000..f8e4a07cba58 --- /dev/null +++ b/test/SemaObjC/rdr-6211479-array-property.m @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// XFAIL +// <rdar://problem/6211479> + +typedef int T[2]; + +@interface A +@property(assign) T p2; // expected-error {{FIXME: property has invalid type}} +@end diff --git a/test/SemaObjC/scope-check.m b/test/SemaObjC/scope-check.m new file mode 100644 index 000000000000..0835373ba748 --- /dev/null +++ b/test/SemaObjC/scope-check.m @@ -0,0 +1,103 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@class A, B, C; + +void test1() { + goto L; // expected-error{{illegal goto into protected scope}} + goto L2; // expected-error{{illegal goto into protected scope}} + goto L3; // expected-error{{illegal goto into protected scope}} + @try { // expected-note {{jump bypasses initialization of @try block}} +L: ; + } @catch (A *x) { // expected-note {{jump bypasses initialization of @catch block}} +L2: ; + } @catch (B *x) { + } @catch (C *c) { + } @finally {// expected-note {{jump bypasses initialization of @finally block}} +L3: ; + } + + @try { + goto L4; // expected-error{{illegal goto into protected scope}} + goto L5; // expected-error{{illegal goto into protected scope}} + } @catch (C *c) { // expected-note {{jump bypasses initialization of @catch block}} + L5: ; + goto L6; // expected-error{{illegal goto into protected scope}} + } @catch (B *c) { // expected-note {{jump bypasses initialization of @catch block}} + L6: ; + } @finally { // expected-note {{jump bypasses initialization of @finally block}} + L4: ; + } + + + @try { // expected-note 2 {{jump bypasses initialization of @try block}} + L7: ; + } @catch (C *c) { + goto L7; // expected-error{{illegal goto into protected scope}} + } @finally { + goto L7; // expected-error{{illegal goto into protected scope}} + } + + goto L8; // expected-error{{illegal goto into protected scope}} + @try { + } @catch (A *c) { + } @catch (B *c) { + } @catch (C *c) { // expected-note {{jump bypasses initialization of @catch block}} + L8: ; + } + + // rdar://6810106 + id X; + goto L9; // expected-error{{illegal goto into protected scope}} + goto L10; // ok + @synchronized // expected-note {{jump bypasses initialization of @synchronized block}} + ( ({ L10: ; X; })) { + L9: + ; + } +} + +void test2(int a) { + if (a) goto L0; + @try {} @finally {} + L0: + return; +} + +// rdar://6803963 +void test3() { + @try { + goto blargh; + blargh: ; + } @catch (...) {} +} + +@interface Greeter ++ (void) hello; +@end + +@implementation Greeter ++ (void) hello { + + @try { + goto blargh; // expected-error {{illegal goto into protected scope}} + } @catch (...) { // expected-note {{jump bypasses initialization of @catch block}} + blargh: ; + } +} + ++ (void)meth2 { + int n; void *P; + goto L0; // expected-error {{illegal goto into protected scope}} + typedef int A[n]; // expected-note {{jump bypasses initialization of VLA typedef}} + L0: + + goto L1; // expected-error {{illegal goto into protected scope}} + A b, c[10]; // expected-note 2 {{jump bypasses initialization of variable length array}} + L1: + goto L2; // expected-error {{illegal goto into protected scope}} + A d[n]; // expected-note {{jump bypasses initialization of variable length array}} + L2: + return; +} + +@end diff --git a/test/SemaObjC/selector-1.m b/test/SemaObjC/selector-1.m new file mode 100644 index 000000000000..ee77015041db --- /dev/null +++ b/test/SemaObjC/selector-1.m @@ -0,0 +1,22 @@ +// RUN: clang-cc -verify %s + +@interface Lancelot @end +@implementation Lancelot + +- (void):(int)x {} +- (void)xx:(int)x :(int)y { } + +@end + +int main() { + SEL s = @selector(retain); + SEL s1 = @selector(meth1:); + SEL s2 = @selector(retainArgument::); + SEL s3 = @selector(retainArgument:::::); + SEL s4 = @selector(retainArgument:with:); + SEL s5 = @selector(meth1:with:with:); + SEL s6 = @selector(getEnum:enum:bool:); + SEL s7 = @selector(char:float:double:unsigned:short:long:); + + SEL s9 = @selector(:enum:bool:); +} diff --git a/test/SemaObjC/selector-error.m b/test/SemaObjC/selector-error.m new file mode 100644 index 000000000000..cc2a40472640 --- /dev/null +++ b/test/SemaObjC/selector-error.m @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Foo +- (char*) foo; +- (void) bar; +@end + +@implementation Foo +- (void) bar +{ +} + +- (char*) foo +{ + char* a,b,c; + a = (char*)@selector(bar); // expected-error {{cannot type cast @selector expression}} + return (char*)@selector(bar); // expected-error {{cannot type cast @selector expression}} +} +@end + diff --git a/test/SemaObjC/selector-overload.m b/test/SemaObjC/selector-overload.m new file mode 100644 index 000000000000..7c30f79ceaec --- /dev/null +++ b/test/SemaObjC/selector-overload.m @@ -0,0 +1,47 @@ +// RUN: clang-cc %s -fsyntax-only + +@interface NSObject ++ alloc; +- init; +@end + +struct D { + double d; +}; + +@interface Foo : NSObject + +- method:(int)a; +- method:(int)a; + +@end + +@interface Bar : NSObject + +- method:(void *)a; + +@end + +@interface Car : NSObject + +- method:(struct D)a; + +@end + +@interface Zar : NSObject + +- method:(float)a; + +@end + +@interface Rar : NSObject + +- method:(float)a; + +@end + +int main() { + id xx = [[Car alloc] init]; // expected-warning {{incompatible types assigning 'int' to 'id'}} + + [xx method:4]; +} diff --git a/test/SemaObjC/sizeof-interface.m b/test/SemaObjC/sizeof-interface.m new file mode 100644 index 000000000000..75d7daafbbcc --- /dev/null +++ b/test/SemaObjC/sizeof-interface.m @@ -0,0 +1,79 @@ +// RUN: clang-cc -triple x86_64-apple-darwin9 -verify -fsyntax-only %s + +@class I0; + +// rdar://6811884 +int g0 = sizeof(I0); // expected-error{{invalid application of 'sizeof' to an incomplete type 'I0'}} + +// rdar://6821047 +void *g3(I0 *P) { + P = P+5; // expected-error {{arithmetic on pointer to incomplete type 'I0 *'}} + + return &P[4]; // expected-error{{subscript of pointer to incomplete type 'I0'}} +} + + + +@interface I0 { +@public + char x[4]; +} + +@property int p0; +@end + +// size == 4 +int g1[ sizeof(I0) // expected-error {{invalid application of 'sizeof' to interface 'I0' in non-fragile ABI}} + == 4 ? 1 : -1]; + +@implementation I0 +@synthesize p0 = _p0; +@end + +// size == 4 (we do not include extended properties in the +// sizeof). +int g2[ sizeof(I0) // expected-error {{invalid application of 'sizeof' to interface 'I0' in non-fragile ABI}} + == 4 ? 1 : -1]; + +@interface I1 +@property int p0; +@end + +@implementation I1 +@synthesize p0 = _p0; +@end + +typedef struct { @defs(I1) } I1_defs; // expected-error {{invalid application of @defs in non-fragile ABI}} + +// FIXME: This is currently broken due to the way the record layout we +// create is tied to whether we have seen synthesized properties. Ugh. +// int g3[ sizeof(I1) == 0 ? 1 : -1]; + +// rdar://6821047 +int bar(I0 *P) { + P = P+5; // expected-error {{arithmetic on pointer to interface 'I0', which is not a constant size in non-fragile ABI}} + P = 5+P; // expected-error {{arithmetic on pointer to interface 'I0', which is not a constant size in non-fragile ABI}} + P = P-5; // expected-error {{arithmetic on pointer to interface 'I0', which is not a constant size in non-fragile ABI}} + + return P[4].x[2]; // expected-error {{subscript requires size of interface 'I0', which is not constant in non-fragile ABI}} +} + + +@interface I @end + +@interface XCAttributeRunDirectNode +{ + @public + unsigned long attributeRuns[1024 + sizeof(I)]; // expected-error {{invalid application of 'sizeof' to interface 'I' in non-fragile ABI}} + int i; +} +@end + +@implementation XCAttributeRunDirectNode + +- (unsigned long)gatherStats:(id )stats +{ + return attributeRuns[i]; +} +@end + diff --git a/test/SemaObjC/static-ivar-ref-1.m b/test/SemaObjC/static-ivar-ref-1.m new file mode 100644 index 000000000000..3c37e9e83026 --- /dev/null +++ b/test/SemaObjC/static-ivar-ref-1.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -ast-print %s + +@interface current +{ +@public + int ivar; + int ivar1; + int ivar2; +} +@end + +current *pc; + +int foo() +{ + return pc->ivar2 + (*pc).ivar + pc->ivar1; +} diff --git a/test/SemaObjC/stmts.m b/test/SemaObjC/stmts.m new file mode 100644 index 000000000000..1d4ea0a77189 --- /dev/null +++ b/test/SemaObjC/stmts.m @@ -0,0 +1,14 @@ +// RUN: clang-cc %s -verify -fsyntax-only + +struct some_struct; + +// Note: NSException is not declared. +void f0(id x) { + @try { + } @catch (NSException *x) { // expected-error {{unknown type name 'NSException'}} + } @catch (struct some_struct x) { // expected-error {{@catch parameter is not a pointer to an interface type}} + } @catch (int x) { // expected-error {{@catch parameter is not a pointer to an interface type}} + } @catch (...) { + } +} + diff --git a/test/SemaObjC/string.m b/test/SemaObjC/string.m new file mode 100644 index 000000000000..3f078f6543ee --- /dev/null +++ b/test/SemaObjC/string.m @@ -0,0 +1,15 @@ +// RUN: clang-cc %s -verify -fsyntax-only && +// RUN: clang-cc %s -verify -fsyntax-only -DDECLAREIT + +// a declaration of NSConstantString is not required. +#ifdef DECLAREIT +@interface NSConstantString; +@end +#endif + + + +id s = @"123"; // simple +id t = @"123" @"456"; // concat +id u = @"123" @ blah; // expected-error {{unexpected token}} + diff --git a/test/SemaObjC/super-cat-prot.m b/test/SemaObjC/super-cat-prot.m new file mode 100644 index 000000000000..1ab0752faa38 --- /dev/null +++ b/test/SemaObjC/super-cat-prot.m @@ -0,0 +1,48 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef signed char BOOL; +typedef unsigned int NSUInteger; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; @end +@interface NSObject <NSObject> {} @end +typedef float CGFloat; +typedef struct _NSSize {} NSSize; +typedef struct _NSRect {} NSRect; +@interface NSResponder : NSObject <NSCoding> {} @end +@protocol NSAnimatablePropertyContainer - (id)animator; @end +extern NSString *NSAnimationTriggerOrderIn ; +@interface NSView : NSResponder <NSAnimatablePropertyContainer> {} @end +@class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView; +enum { NSBoxPrimary = 0, NSBoxSecondary = 1, NSBoxSeparator = 2, NSBoxOldStyle = 3, NSBoxCustom = 4}; +typedef NSUInteger NSBoxType; +@interface NSBox : NSView {} - (NSBoxType)boxType; @end +@class NSArray, NSError, NSImage, NSView, NSNotificationCenter, NSURL; +@interface NSProBox:NSBox {} @end +enum IBKnobPosition { IBNoKnobPosition = -1, IBBottomLeftKnobPosition = 0, + IBMiddleLeftKnobPosition, IBTopLeftKnobPosition, + IBTopMiddleKnobPosition, IBTopRightKnobPosition, + IBMiddleRightKnobPosition, IBBottomRightKnobPosition, + IBBottomMiddleKnobPosition }; +typedef enum IBKnobPosition IBKnobPosition; +typedef struct _IBInset {} IBInset; +@protocol IBObjectProtocol -(NSString *)inspectorClassName; @end +@protocol IBViewProtocol + -(NSSize)minimumFrameSizeFromKnobPosition:(IBKnobPosition)position; + -(IBInset)ibShadowInset; +@end +@class NSPasteboard; +@interface NSObject (NSObject_IBObjectProtocol) <IBObjectProtocol> @end +@interface NSView (NSView_IBViewProtocol) <IBViewProtocol> - (NSRect)layoutRect; @end +typedef enum { NSProTextFieldSquareBezel = 0, NSProTextFieldRoundedBezel = 1, NSProTextFieldDisplayBezel = 2 } MKModuleReusePolicy; +@implementation NSProBox(IBAdditions) +-(NSString *)inspectorClassName {} +-(IBInset)ibShadowInset { + if ([self boxType] == NSBoxSeparator) { + return [super ibShadowInset]; + } +} +-(NSSize)minimumFrameSizeFromKnobPosition:(IBKnobPosition)knobPosition { + if ([self boxType] != NSBoxSeparator) + return [super minimumFrameSizeFromKnobPosition:knobPosition]; +} +@end diff --git a/test/SemaObjC/super-property-message-expr.m b/test/SemaObjC/super-property-message-expr.m new file mode 100644 index 000000000000..082d8bd5b48a --- /dev/null +++ b/test/SemaObjC/super-property-message-expr.m @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface SStoreNodeInfo + +@property(nonatomic,readonly,retain) id descriptionShort; + +- (id)stringByAppendingFormat:(int)format, ... ; + +@end + +@interface SStoreNodeInfo_iDisk : SStoreNodeInfo +{ +@private + id _etag; +} +@end + +@implementation SStoreNodeInfo_iDisk +- (id) X { return [super.descriptionShort stringByAppendingFormat:1, _etag]; } + +@end diff --git a/test/SemaObjC/super-property-notation.m b/test/SemaObjC/super-property-notation.m new file mode 100644 index 000000000000..3b0887f26eff --- /dev/null +++ b/test/SemaObjC/super-property-notation.m @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface B ++(int) classGetter; +-(int) getter; +@end + +@interface A : B +@end + +@implementation A ++(int) classGetter { + return 0; +} + ++(int) classGetter2 { + return super.classGetter; +} + +-(void) method { + int x = super.getter; +} +@end + +void f0() { + // FIXME: not implemented yet. + //int l1 = A.classGetter; + int l2 = [A classGetter2]; +} + diff --git a/test/SemaObjC/super.m b/test/SemaObjC/super.m new file mode 100644 index 000000000000..9afd4eb983c5 --- /dev/null +++ b/test/SemaObjC/super.m @@ -0,0 +1,40 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Foo +- iMethod; ++ cMethod; +@end + +@interface A +@end + +@interface B : A +- (void)instanceMethod; ++ classMethod; +@end + +@implementation B + +- (void)instanceMethod { + [super iMethod]; // expected-warning{{method '-iMethod' not found (return type defaults to 'id')}} +} + ++ classMethod { + [super cMethod]; // expected-warning{{method '+cMethod' not found (return type defaults to 'id')}} +} +@end + +@interface XX +- m; +@end + +void f(id super) { + [super m]; +} +void f0(int super) { + [super m]; // expected-warning{{receiver type 'int' is not 'id'}} \ + expected-warning {{method '-m' not found (return type defaults to 'id')}} +} +void f1(int puper) { + [super m]; // expected-error{{use of undeclared identifier 'super'}} +} diff --git a/test/SemaObjC/synchronized.m b/test/SemaObjC/synchronized.m new file mode 100644 index 000000000000..7131265b5bb7 --- /dev/null +++ b/test/SemaObjC/synchronized.m @@ -0,0 +1,23 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface PBXTrackableTaskManager @end + +@implementation PBXTrackableTaskManager +- (id) init {} +- (void) unregisterTask:(id) task { + @synchronized (self) { + id taskID = [task taskIdentifier]; // expected-warning {{method '-taskIdentifier' not found (return type defaults to 'id')}} + } +} +@end + + +struct x { int a; } b; + +void test1() { + @synchronized (b) { // expected-error {{@synchronized requires an Objective-C object type ('struct x' invalid)}} + } + + @synchronized (42) { // expected-error {{@synchronized requires an Objective-C object type ('int' invalid)}} + } +} diff --git a/test/SemaObjC/synthesize-setter-contclass.m b/test/SemaObjC/synthesize-setter-contclass.m new file mode 100644 index 000000000000..78490c8db0d3 --- /dev/null +++ b/test/SemaObjC/synthesize-setter-contclass.m @@ -0,0 +1,24 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface TestClass +{ + int _isItIsOrIsItAint; +} +@property (readonly) int itIsOrItAint; +-(void) doSomething; +@end + +@interface TestClass() +@property (readwrite) int itIsOrItAint; +@end + +@implementation TestClass +@synthesize itIsOrItAint = _isItIsOrIsItAint; + +-(void) doSomething +{ + int i = [self itIsOrItAint]; + + [self setItIsOrItAint:(int)1]; +} +@end diff --git a/test/SemaObjC/synthesized-ivar.m b/test/SemaObjC/synthesized-ivar.m new file mode 100644 index 000000000000..de44857934fc --- /dev/null +++ b/test/SemaObjC/synthesized-ivar.m @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -triple x86_64-apple-darwin9 -verify %s +@interface I +{ +} +@property int IP; +@end + +@implementation I +@synthesize IP; +- (int) Meth { + return IP; +} +@end diff --git a/test/SemaObjC/try-catch.m b/test/SemaObjC/try-catch.m new file mode 100644 index 000000000000..076eff542968 --- /dev/null +++ b/test/SemaObjC/try-catch.m @@ -0,0 +1,47 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef signed char BOOL; +typedef struct _NSZone NSZone; + +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject +- (BOOL)isEqual:(id)object; +@end + +@protocol NSCopying +- (id)copyWithZone:(NSZone *)zone; +@end + +@protocol NSCoding +- (void)encodeWithCoder:(NSCoder *)aCoder; +@end + +@interface NSObject <NSObject> {} +@end + +@class NSData, NSArray, NSDictionary, NSCharacterSet, NSData, NSURL, NSError, NSLocale; + +@interface NSException : NSObject <NSCopying, NSCoding> {} +@end + +@class ASTNode, XCRefactoringParser, Transform, TransformInstance, XCRefactoringSelectionInfo; + +@interface XCRefactoringTransformation : NSObject {} +@end + +@implementation XCRefactoringTransformation +- (NSDictionary *)setUpInfoForTransformKey:(NSString *)transformKey outError:(NSError **)outError; { + @try {} + // the exception name is optional (weird) + @catch (NSException *) {} +} +@end + +int foo() { + struct s { int a, b; } agg, *pagg; + + @throw 42; // expected-error {{@throw requires an Objective-C object type ('int' invalid))}} + @throw agg; // expected-error {{@throw requires an Objective-C object type ('struct s' invalid)}} + @throw pagg; // expected-error {{@throw requires an Objective-C object type ('struct s *' invalid)}} + @throw; // expected-error {{@throw (rethrow) used outside of a @catch block}} +} diff --git a/test/SemaObjC/typedef-class.m b/test/SemaObjC/typedef-class.m new file mode 100644 index 000000000000..128815602d4d --- /dev/null +++ b/test/SemaObjC/typedef-class.m @@ -0,0 +1,78 @@ +// RUN: clang-cc -fsyntax-only -verify %s +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; + +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; + +@protocol NSObject - (BOOL) isEqual:(id) object; @end +@protocol NSCopying - (id) copyWithZone:(NSZone *) zone; @end +@protocol NSCoding - (void) encodeWithCoder:(NSCoder *) aCoder; @end + +@interface NSObject < NSObject > {} ++(id) alloc; +@end + +typedef float CGFloat; + +@interface NSTask:NSObject +- (id) init; +@end + +typedef NSUInteger NSControlSize; +typedef struct __CFlags {} _CFlags; + +@interface NSCell:NSObject < NSCopying, NSCoding > {} +@end + +@interface NSActionCell:NSCell {} @end + +@class NSAttributedString, NSFont, NSImage, NSSound; + +typedef struct _XCElementInset {} XCElementInset; + +@protocol XCElementP < NSObject > +-(BOOL) vertical; +@end + +@protocol XCElementDisplayDelegateP; +@protocol XCElementDisplayDelegateP < NSObject > +-(void) configureForControlSize:(NSControlSize)size font:(NSFont *)font addDefaultSpace:(XCElementInset) additionalSpace; +@end + +@protocol XCElementSpacerP < XCElementP > +@end + +typedef NSObject < XCElementSpacerP > XCElementSpacer; + +@protocol XCElementTogglerP < XCElementP > -(void) setDisplayed:(BOOL) displayed; +@end + +typedef NSObject < XCElementTogglerP > XCElementToggler; + +@interface XCElementRootFace:NSObject {} @end + +@interface XCElementFace:XCElementRootFace {} @end + +@class XCElementToggler; + +@interface XCRASlice:XCElementFace {} @end + +@class XCElementSpacings; + +@interface XCElementDisplay:NSObject < XCElementDisplayDelegateP > {} @end +@interface XCElementDisplayRect:XCElementDisplay {} @end + +typedef XCElementDisplayRect XCElementGraphicsRect; + +@interface XCElementDisplayFillerImage:XCElementDisplay {} @end + +@implementation XCRASlice +- (void) addSliceWithLabel:(NSString *)label statusKey:(NSString *)statusKey disclosed:(BOOL)disclosed +{ + static XCElementGraphicsRect *_sGraphicsDelegate = ((void *) 0); + if (!_sGraphicsDelegate) { + _sGraphicsDelegate =[[XCElementGraphicsRect alloc] init]; + } +} +@end diff --git a/test/SemaObjC/ucn-objc-string.m b/test/SemaObjC/ucn-objc-string.m new file mode 100644 index 000000000000..1d94ea2363a1 --- /dev/null +++ b/test/SemaObjC/ucn-objc-string.m @@ -0,0 +1,13 @@ +// RUN: clang %s -verify -fsyntax-only +@class NSString; +extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); + +int main() { + NSLog(@"Hi…"); + NSLog(@"Exposé"); + NSLog(@"\U00010400\U0001D12B"); + NSLog(@"hello \u2192 \u2603 \u2190 world"); + NSLog(@"hello → ☃ ← world"); + return 0; +} + diff --git a/test/SemaObjC/undef-class-messagin-error.m b/test/SemaObjC/undef-class-messagin-error.m new file mode 100644 index 000000000000..114b6ca5f6f4 --- /dev/null +++ b/test/SemaObjC/undef-class-messagin-error.m @@ -0,0 +1,13 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface _Child ++ (int) flashCache; +@end + +@interface Child (Categ) // expected-error {{cannot find interface declaration for 'Child'}} ++ (int) flushCache2; +@end + +@implementation Child (Categ) // expected-error {{cannot find interface declaration for 'Child'}} ++ (int) flushCache2 { [super flashCache]; } // expected-error {{no @interface declaration found in class messaging of 'flushCache2'}} +@end diff --git a/test/SemaObjC/undef-protocol-methods-1.m b/test/SemaObjC/undef-protocol-methods-1.m new file mode 100644 index 000000000000..05245523fb6a --- /dev/null +++ b/test/SemaObjC/undef-protocol-methods-1.m @@ -0,0 +1,42 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol P1 +- (void) P1proto; ++ (void) ClsP1Proto; +- (void) DefP1proto; +@end +@protocol P2 +- (void) P2proto; ++ (void) ClsP2Proto; +@end + +@protocol P3<P2> +- (void) P3proto; ++ (void) ClsP3Proto; ++ (void) DefClsP3Proto; +@end + +@protocol PROTO<P1, P3> +- (void) meth; +- (void) meth : (int) arg1; ++ (void) cls_meth : (int) arg1; +@end + +@interface INTF <PROTO> +@end + +@implementation INTF // expected-warning {{incomplete implementation}} \ + expected-warning {{method definition for 'meth' not found}} \ + expected-warning {{method definition for 'meth:' not found}} \ + expected-warning {{method definition for 'cls_meth:' not found}} \ + expected-warning {{method definition for 'P3proto' not found}} \ + expected-warning {{method definition for 'ClsP3Proto' not found}} \ + expected-warning {{method definition for 'P2proto' not found}} \ + expected-warning {{method definition for 'ClsP2Proto' not found}} \ + expected-warning {{method definition for 'ClsP1Proto' not found}} \ + expected-warning {{method definition for 'P1proto' not found}} +- (void) DefP1proto{} + ++ (void) DefClsP3Proto{} + +@end diff --git a/test/SemaObjC/undef-superclass-1.m b/test/SemaObjC/undef-superclass-1.m new file mode 100644 index 000000000000..0d670f8c0809 --- /dev/null +++ b/test/SemaObjC/undef-superclass-1.m @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@class SUPER, Y; + +@interface INTF :SUPER // expected-error {{cannot find interface declaration for 'SUPER', superclass of 'INTF'}} +@end + +@interface SUPER @end + +@interface INTF1 : SUPER // expected-note {{previous definition is here}} +@end + +@interface INTF2 : INTF1 +@end + +@interface INTF3 : Y // expected-error {{cannot find interface declaration for 'Y', superclass of 'INTF3'}} +@end + +@interface INTF1 // expected-error {{duplicate interface definition for class 'INTF1'}} +@end + +@implementation SUPER +- (void)dealloc { + [super dealloc]; // expected-error {{no super class declared in @interface for 'SUPER'}} +} +@end diff --git a/test/SemaObjC/undefined-protocol-type-1.m b/test/SemaObjC/undefined-protocol-type-1.m new file mode 100644 index 000000000000..572d55f26854 --- /dev/null +++ b/test/SemaObjC/undefined-protocol-type-1.m @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@protocol p1, p4; +@protocol p2 @end + +@interface T +- (T<p2, p3, p1, p4>*) meth; // expected-error {{cannot find protocol declaration for 'p3'}} +- (T<p2, p3, p1, p4>*) meth; // expected-error {{cannot find protocol declaration for 'p3'}} +@end diff --git a/test/SemaObjC/unused.m b/test/SemaObjC/unused.m new file mode 100644 index 000000000000..88c6f1054c8d --- /dev/null +++ b/test/SemaObjC/unused.m @@ -0,0 +1,18 @@ +// RUN: clang-cc %s -verify -fsyntax-only +#include <stdio.h> + +@interface Greeter ++ (void) hello; +@end + +@implementation Greeter ++ (void) hello { + fprintf(stdout, "Hello, World!\n"); +} +@end + +int main (void) { + [Greeter hello]; + return 0; +} + diff --git a/test/SemaObjC/va-method-1.m b/test/SemaObjC/va-method-1.m new file mode 100644 index 000000000000..3c8998f983ce --- /dev/null +++ b/test/SemaObjC/va-method-1.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +#include <stdarg.h> + +@interface NSObject @end +@interface XX : NSObject @end + +@implementation XX +- (void)encodeValuesOfObjCTypes:(const char *)types, ... { + va_list ap; + va_start(ap, types); + while (*types) ; + va_end(ap); +} + +@end + diff --git a/test/SemaObjC/warn-selector-selection.m b/test/SemaObjC/warn-selector-selection.m new file mode 100644 index 000000000000..4ab89b7e1e2c --- /dev/null +++ b/test/SemaObjC/warn-selector-selection.m @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface Object +- (void)foo; +@end + +@interface Class1 +- (void)setWindow:(Object *)wdw; +@end + +void foo(void) { + Object *obj; + [obj setWindow:0]; // expected-warning{{Object may not respond to 'setWindow:'}} +} diff --git a/test/SemaObjC/warn-weak-field.m b/test/SemaObjC/warn-weak-field.m new file mode 100644 index 000000000000..3850f217beea --- /dev/null +++ b/test/SemaObjC/warn-weak-field.m @@ -0,0 +1,24 @@ +// RUN: clang-cc -triple i386-apple-darwin9 -fsyntax-only -fobjc-gc -verify %s + +struct S { + __weak id w; // expected-warning {{__weak attribute cannot be specified on a field declaration}} + __strong id p1; +}; + +@interface I +{ + __weak id w; // OK + __strong id LHS; +} +- (void) foo; +@end +@implementation I +- (void) foo { w = 0; LHS = w; } +@end + +int main () +{ + struct I { + __weak id w1; // expected-warning {{__weak attribute cannot be specified on a field declaration}} + }; +} diff --git a/test/SemaObjC/weak-attr-ivar.m b/test/SemaObjC/weak-attr-ivar.m new file mode 100644 index 000000000000..9e0e8cb4b3af --- /dev/null +++ b/test/SemaObjC/weak-attr-ivar.m @@ -0,0 +1,73 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef signed char BOOL; +typedef unsigned int NSUInteger; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject +- (BOOL)isEqual:(id)object; +@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 +extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone); +typedef struct { + id *itemsPtr; + unsigned long *mutationsPtr; +} NSFastEnumerationState; +@protocol NSFastEnumeration +- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; +@end +@class NSString; +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; +@end +@interface NSMutableArray : NSArray - (void)addObject:(id)anObject; +@end +extern NSString * const NSUndoManagerCheckpointNotification; +@interface NSValueTransformer : NSObject {} @end +@class FooModel; +@interface FooObject : NSObject <NSCopying> {} +@end +@interface FooNode : FooObject {} +- (NSArray *) children; +@end +typedef enum { Foo_HUH_NONE } FooHUHCode; +@interface FooPlaypenEntry : FooNode { + NSMutableArray *_interestingChildren; + FooHUHCode _HUH; + __attribute__((objc_gc(weak))) FooPlaypenEntry *_mostInterestingChild; + id _author; +} +@property(copy) NSString *author; +- (BOOL) isInteresting; +@end NSString *FooHUHCodeToString(FooHUHCode HUH) { +} +@interface FooHUHCodeToStringTransformer: NSValueTransformer { +} +@end @implementation FooPlaypenEntry @synthesize author = _author; +- (BOOL) isInteresting { return 1; } +- (NSArray *) interestingChildren { + if (!_interestingChildren) { + for (FooPlaypenEntry *child in [self children]) { + if ([child isInteresting]) { + if (!_mostInterestingChild) + _mostInterestingChild = child; + else if (child->_HUH > _mostInterestingChild->_HUH) + _mostInterestingChild = child; + } + } + } +} +- (FooHUHCode) HUH { + if (_HUH == Foo_HUH_NONE) { + if (_mostInterestingChild) + return [_mostInterestingChild HUH]; + } +} +@end + diff --git a/test/SemaObjC/writable-property-in-superclass.m b/test/SemaObjC/writable-property-in-superclass.m new file mode 100644 index 000000000000..182b1c47bb39 --- /dev/null +++ b/test/SemaObjC/writable-property-in-superclass.m @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface MessageStore +@property (assign, readonly) int P; +@end + +@interface MessageStore (CAT) +@property (assign) int P; +@end + +@interface NeXTMbox : MessageStore +@end + +@implementation NeXTMbox +- (void) Meth { self.P = 1; } +@end + diff --git a/test/SemaObjCXX/blocks.mm b/test/SemaObjCXX/blocks.mm new file mode 100644 index 000000000000..3d421a878e59 --- /dev/null +++ b/test/SemaObjCXX/blocks.mm @@ -0,0 +1,46 @@ +// RUN: clang-cc -fsyntax-only -verify -fblocks %s +@protocol NSObject; + +void bar(id(^)(void)); +void foo(id <NSObject>(^objectCreationBlock)(void)) { + return bar(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (^)(void)', expected 'id<NSObject> (^)(void)'}} +} + +void bar2(id(*)(void)); +void foo2(id <NSObject>(*objectCreationBlock)(void)) { + return bar2(objectCreationBlock); // expected-warning{{incompatible pointer types passing 'id (*)(void)', expected 'id<NSObject> (*)(void)'}} +} + +void bar3(id(*)()); // expected-note{{candidate function}} +void foo3(id (*objectCreationBlock)(int)) { + return bar3(objectCreationBlock); // expected-error{{no matching}} +} + +void bar4(id(^)()); // expected-note{{candidate function}} +void foo4(id (^objectCreationBlock)(int)) { + return bar4(objectCreationBlock); // expected-error{{no matching}} +} + +void foo5(id (^x)(int)) { + if (x) { } +} + +// <rdar://problem/6590445> +@interface Foo { + @private + void (^_block)(void); +} +- (void)bar; +@end + +namespace N { + class X { }; + void foo(X); +} + +@implementation Foo +- (void)bar { + _block(); + foo(N::X()); // okay +} +@end diff --git a/test/SemaObjCXX/cocoa.mm b/test/SemaObjCXX/cocoa.mm new file mode 100644 index 000000000000..c061d4e09684 --- /dev/null +++ b/test/SemaObjCXX/cocoa.mm @@ -0,0 +1,4 @@ +// RUN: clang-cc -mcpu=pentium4 %s -print-stats +#ifdef __APPLE__ +#include <Cocoa/Cocoa.h> +#endif diff --git a/test/SemaObjCXX/linkage-spec.mm b/test/SemaObjCXX/linkage-spec.mm new file mode 100644 index 000000000000..2cc0936b2ed2 --- /dev/null +++ b/test/SemaObjCXX/linkage-spec.mm @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -verify %s +extern "C" { +@class Protocol; +} diff --git a/test/SemaObjCXX/objc-decls-inside-namespace.mm b/test/SemaObjCXX/objc-decls-inside-namespace.mm new file mode 100644 index 000000000000..cedfcfdb9e4b --- /dev/null +++ b/test/SemaObjCXX/objc-decls-inside-namespace.mm @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace C { + +@protocol P; //expected-error{{Objective-C declarations may only appear in global scope}} + +@class Bar; //expected-error{{Objective-C declarations may only appear in global scope}} + +@compatibility_alias Foo Bar; //expected-error{{Objective-C declarations may only appear in global scope}} + +@interface A //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +@implementation A //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +@protocol P //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +@interface A(C) //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +@implementation A(C) //expected-error{{Objective-C declarations may only appear in global scope}} +@end + +} + diff --git a/test/SemaObjCXX/overload.mm b/test/SemaObjCXX/overload.mm new file mode 100644 index 000000000000..8ab22e1ca73e --- /dev/null +++ b/test/SemaObjCXX/overload.mm @@ -0,0 +1,94 @@ +// RUN: clang-cc -fsyntax-only -verify %s +@interface Foo +@end + +@implementation Foo + +void func(id); + ++ zone { + func(self); + return self; +} +@end + +@protocol P0 +@end + +@protocol P1 +@end + +@interface A <P0> +@end + +@interface B : A +@end + +@interface C <P1> +@end + +int& f(A*); +float& f(B*); +void g(A*); + +int& h(A*); +float& h(id); + +void test(A* a, B* b, id val) { + int& i1 = f(a); + float& f1 = f(b); + float& f2 = f(val); + g(a); + g(b); + g(val); + int& i2 = h(a); + float& f3 = h(val); + // int& i3 = h(b); FIXME: we match GCC here, but shouldn't this work? +} + +void downcast_test(A* a, A** ap) { + B* b = a; // expected-warning{{incompatible pointer types initializing 'B *', expected 'A *'}} + b = a; // expected-warning{{incompatible pointer types assigning 'B *', expected 'A *'}} + + B** bp = ap; // expected-warning{{incompatible pointer types initializing 'B **', expected 'A **'}} + bp = ap; // expected-warning{{incompatible pointer types assigning 'B **', expected 'A **'}} +} + +int& cv(A*); +float& cv(const A*); +int& cv2(void*); +float& cv2(const void*); + +void cv_test(A* a, B* b, const A* ac, const B* bc) { + int &i1 = cv(a); + int &i2 = cv(b); + float &f1 = cv(ac); + float &f2 = cv(bc); + int& i3 = cv2(a); + float& f3 = cv2(ac); +} + + +int& qualid(id<P0>); +float& qualid(id<P1>); // FIXME: GCC complains that this isn't an overload. Is it? + +void qualid_test(A *a, B *b, C *c) { + int& i1 = qualid(a); + int& i2 = qualid(b); + float& f1 = qualid(c); + + id<P0> p1 = 0; + p1 = 0; +} + + +@class NSException; +typedef struct { + void (*throw_exc)(id); +} +objc_exception_functions_t; + +void (*_NSExceptionRaiser(void))(NSException *) { + objc_exception_functions_t exc_funcs; + return exc_funcs.throw_exc; // expected-warning{{incompatible pointer types returning 'void (*)(NSException *)', expected 'void (*)(id)'}} +} diff --git a/test/SemaObjCXX/protocol-lookup.mm b/test/SemaObjCXX/protocol-lookup.mm new file mode 100644 index 000000000000..0f1860d2c88e --- /dev/null +++ b/test/SemaObjCXX/protocol-lookup.mm @@ -0,0 +1,50 @@ +// RUN: clang-cc -fsyntax-only -verify %s +@protocol NSObject +- retain; +- release; +@end + +@interface NSObject +- init; +- dealloc; +@end + +@protocol Foo <NSObject> +@end + +@protocol Bar <Foo> +@end + +@interface Baz : NSObject { + id <Foo> _foo; + id <Bar> _bar; +} +- (id)initWithFoo:(id <Foo>)foo bar:(id <Bar>)bar; +@end + +@implementation Baz + +- (id)init +{ + return [self initWithFoo:0 bar:0]; +} + +- (id)initWithFoo:(id <Foo>)foo bar:(id <Bar>)bar +{ + self = [super init]; + if (self != 0) { + _foo = [foo retain]; + _bar = [bar retain]; + } + return self; +} + +- dealloc +{ + [_foo release]; + [_bar release]; + [super dealloc]; +} + +@end + diff --git a/test/SemaObjCXX/reserved-keyword-selectors.mm b/test/SemaObjCXX/reserved-keyword-selectors.mm new file mode 100644 index 000000000000..2875f9352737 --- /dev/null +++ b/test/SemaObjCXX/reserved-keyword-selectors.mm @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +@interface A +- (void)asm; +- (void)bool; +- (void)catch; +- (void)class; +- (void)const_cast; +- (void)delete; +- (void)dynamic_cast; +- (void)explicit; +- (void)export; +- (void)false; +- (void)friend; +- (void)mutable; +- (void)namespace; +- (void)new; +- (void)operator; +- (void)private; +- (void)protected; +- (void)public; +- (void)reinterpret_cast; +- (void)static_cast; +- (void)template; +- (void)this; +- (void)throw; +- (void)true; +- (void)try; +- (void)typename; +- (void)typeid; +- (void)using; +- (void)virtual; +- (void)wchar_t; +@end + diff --git a/test/SemaObjCXX/vararg-non-pod.mm b/test/SemaObjCXX/vararg-non-pod.mm new file mode 100644 index 000000000000..eeed09e61637 --- /dev/null +++ b/test/SemaObjCXX/vararg-non-pod.mm @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +extern char version[]; + +@protocol P; + +class C { +public: + C(int); +}; + +@interface D +- (void)g:(int)a, ...; +@end + +void t1(D *d) +{ + C c(10); + + [d g:10, c]; // expected-warning{{cannot pass object of non-POD type 'class C' through variadic method; call will abort at runtime}} + [d g:10, version]; +} + +void t2(D *d, id p) +{ + [d g:10, p]; +} + +void t3(D *d, id<P> p) +{ + [d g:10, p]; +} diff --git a/test/SemaObjCXX/void_to_obj.mm b/test/SemaObjCXX/void_to_obj.mm new file mode 100644 index 000000000000..d1fbf6b69079 --- /dev/null +++ b/test/SemaObjCXX/void_to_obj.mm @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// <rdar://problem/6463729> +@class XX; + +void func() { + XX *obj; + void *vv; + + obj = vv; // expected-error{{incompatible type assigning 'void *', expected 'XX *'}} +} diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp new file mode 100644 index 000000000000..c81267771297 --- /dev/null +++ b/test/SemaTemplate/class-template-decl.cpp @@ -0,0 +1,49 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> class A; + +extern "C++" { + template<typename T> class B; +} + +namespace N { + template<typename T> class C; +} + +extern "C" { + template<typename T> class D; // expected-error{{templates must have C++ linkage}} +} + +template<class U> class A; // expected-note{{previous template declaration is here}} + +template<int N> class A; // expected-error{{template parameter has a different kind in template redeclaration}} + +template<int N> class NonTypeTemplateParm; + +typedef int INT; + +template<INT M> class NonTypeTemplateParm; // expected-note{{previous non-type template parameter with type 'INT' (aka 'int') is here}} + +template<long> class NonTypeTemplateParm; // expected-error{{template non-type parameter has a different type 'long' in template redeclaration}} + +template<template<typename T> class X> class TemplateTemplateParm; + +template<template<class> class Y> class TemplateTemplateParm; // expected-note{{previous template declaration is here}} \ + // expected-note{{previous template template parameter is here}} + +template<typename> class TemplateTemplateParm; // expected-error{{template parameter has a different kind in template redeclaration}} + +template<template<typename T, int> class X> class TemplateTemplateParm; // expected-error{{too many template parameters in template template parameter redeclaration}} + +#if 0 +// FIXME: parse template declarations in these scopes, so that we can +// complain about the one at function scope. +class X { +public: + template<typename T> class C; +}; + +void f() { + template<typename T> class X; +} +#endif diff --git a/test/SemaTemplate/class-template-id-2.cpp b/test/SemaTemplate/class-template-id-2.cpp new file mode 100644 index 000000000000..c4388a7c1556 --- /dev/null +++ b/test/SemaTemplate/class-template-id-2.cpp @@ -0,0 +1,24 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace N { + template<typename T> class A { }; + + template<> class A<int> { }; + + template<> class A<float>; // expected-note{{forward declaration of 'class N::A<float>'}} + + class B : public A<int> { }; +} + +class C1 : public N::A<int> { }; + +class C2 : public N::A<float> { }; // expected-error{{base class has incomplete type}} + +struct D1 { + operator N::A<int>(); +}; + +namespace N { + struct D2 { + operator A<int>(); + }; +} diff --git a/test/SemaTemplate/class-template-id.cpp b/test/SemaTemplate/class-template-id.cpp new file mode 100644 index 000000000000..e74a6f8dcca9 --- /dev/null +++ b/test/SemaTemplate/class-template-id.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T, typename U = float> struct A { }; + +typedef A<int> A_int; + +typedef float FLOAT; + +A<int, FLOAT> *foo(A<int> *ptr, A<int> const *ptr2, A<int, double> *ptr3) { + if (ptr) + return ptr; // okay + else if (ptr2) + return ptr2; // expected-error{{incompatible type returning 'A<int> const *', expected 'A<int, FLOAT> *'}} + else { + return ptr3; // expected-error{{incompatible type returning 'A<int, double> *', expected 'A<int, FLOAT> *'}} + } +} + +template<int I> struct B; + +const int value = 12; +B<17 + 2> *bar(B<(19)> *ptr1, B< (::value + 7) > *ptr2, B<19 - 3> *ptr3) { + if (ptr1) + return ptr1; + else if (ptr2) + return ptr2; + else + return ptr3; // expected-error{{incompatible type returning 'B<19 - 3> *', expected 'B<17 + 2> *'}} +} + +typedef B<5> B5; + + +namespace N { + template<typename T> struct C {}; +} + +N::C<int> c1; +typedef N::C<float> c2; diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp new file mode 100644 index 000000000000..71d8ea14be6b --- /dev/null +++ b/test/SemaTemplate/class-template-spec.cpp @@ -0,0 +1,80 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T, typename U = int> struct A; // expected-note 2{{template is declared here}} + +template<> struct A<double, double>; // expected-note{{forward declaration}} + +template<> struct A<float, float> { // expected-note{{previous definition}} + int x; +}; + +template<> struct A<float> { // expected-note{{previous definition}} + int y; +}; + +int test_specs(A<float, float> *a1, A<float, int> *a2) { + return a1->x + a2->y; +} + +int test_incomplete_specs(A<double, double> *a1, + A<double> *a2) +{ + (void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}} + (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}} +} + +typedef float FLOAT; + +template<> struct A<float, FLOAT>; + +template<> struct A<FLOAT, float> { }; // expected-error{{redefinition}} + +template<> struct A<float, int> { }; // expected-error{{redefinition}} + +template<typename T, typename U = int> struct X; + +template <> struct X<int, int> { int foo(); }; // #1 +template <> struct X<float> { int bar(); }; // #2 + +typedef int int_type; +void testme(X<int_type> *x1, X<float, int> *x2) { + (void)x1->foo(); // okay: refers to #1 + (void)x2->bar(); // okay: refers to #2 +} + +// Make sure specializations are proper classes. +template<> +struct A<char> { + A(); +}; + +A<char>::A() { } + +// Diagnose specialization errors +struct A<double> { }; // expected-error{{template specialization requires 'template<>'}} + +template<> struct ::A<double>; + +namespace N { + template<typename T> struct B; // expected-note 2{{template is declared here}} + + template<> struct ::N::B<char>; // okay + template<> struct ::N::B<short>; // okay + template<> struct ::N::B<int>; // okay + + int f(int); +} + +template<> struct N::B<int> { }; // okay + +template<> struct N::B<float> { }; // expected-error{{class template specialization of 'B' not in namespace 'N'}} + +namespace M { + template<> struct ::N::B<short> { }; // expected-error{{class template specialization of 'B' not in a namespace enclosing 'N'}} + + template<> struct ::A<long double>; // expected-error{{class template specialization of 'A' must occur in the global scope}} +} + +template<> struct N::B<char> { + int testf(int x) { return f(x); } +}; + diff --git a/test/SemaTemplate/current-instantiation.cpp b/test/SemaTemplate/current-instantiation.cpp new file mode 100644 index 000000000000..603c14016fbc --- /dev/null +++ b/test/SemaTemplate/current-instantiation.cpp @@ -0,0 +1,71 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// This test concerns the identity of dependent types within the +// canonical type system, specifically focusing on the difference +// between members of the current instantiation and membmers of an +// unknown specialization. This considers C++ [temp.type], which +// specifies type equivalence within a template, and C++0x +// [temp.dep.type], which defines what it means to be a member of the +// current instantiation. + +template<typename T, typename U> +struct X0 { + typedef T T_type; + typedef U U_type; + + void f0(T&); // expected-note{{previous}} + void f0(typename X0::U_type&); + void f0(typename X0::T_type&); // expected-error{{redecl}} + + void f1(T&); // expected-note{{previous}} + void f1(typename X0::U_type&); + void f1(typename X0<T, U>::T_type&); // expected-error{{redecl}} + + void f2(T&); // expected-note{{previous}} + void f2(typename X0::U_type&); + void f2(typename X0<T_type, U_type>::T_type&); // expected-error{{redecl}} + + void f3(T&); // expected-note{{previous}} + void f3(typename X0::U_type&); + void f3(typename ::X0<T_type, U_type>::T_type&); // expected-error{{redecl}} + + struct X1 { + typedef T my_T_type; + + void g0(T&); // expected-note{{previous}} + void g0(typename X0::U_type&); + void g0(typename X0::T_type&); // expected-error{{redecl}} + + void g1(T&); // expected-note{{previous}} + void g1(typename X0::U_type&); + void g1(typename X0<T, U>::T_type&); // expected-error{{redecl}} + + void g2(T&); // expected-note{{previous}} + void g2(typename X0::U_type&); + void g2(typename X0<T_type, U_type>::T_type&); // expected-error{{redecl}} + + void g3(T&); // expected-note{{previous}} + void g3(typename X0::U_type&); + void g3(typename ::X0<T_type, U_type>::T_type&); // expected-error{{redecl}} + + void g4(T&); // expected-note{{previous}} + void g4(typename X0::U_type&); + void g4(typename X1::my_T_type&); // expected-error{{redecl}} + + void g5(T&); // expected-note{{previous}} + void g5(typename X0::U_type&); + void g5(typename X0::X1::my_T_type&); // expected-error{{redecl}} + + void g6(T&); // expected-note{{previous}} + void g6(typename X0::U_type&); + void g6(typename X0<T, U>::X1::my_T_type&); // expected-error{{redecl}} + + void g7(T&); // expected-note{{previous}} + void g7(typename X0::U_type&); + void g7(typename ::X0<typename X1::my_T_type, U_type>::X1::my_T_type&); // expected-error{{redecl}} + + void g8(T&); // expected-note{{previous}} + void g8(typename X0<U, T_type>::T_type&); + void g8(typename ::X0<typename X0<T_type, U>::X1::my_T_type, U_type>::X1::my_T_type&); // expected-error{{redecl}} + }; +}; diff --git a/test/SemaTemplate/default-arguments.cpp b/test/SemaTemplate/default-arguments.cpp new file mode 100644 index 000000000000..572227cb61de --- /dev/null +++ b/test/SemaTemplate/default-arguments.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T, int N = 2> struct X; // expected-note{{template is declared here}} + +X<int, 1> *x1; +X<int> *x2; + +X<> *x3; // expected-error{{too few template arguments for class template 'X'}} + +template<typename U = float, int M> struct X; + +X<> *x4; diff --git a/test/SemaTemplate/dependent-type-identity.cpp b/test/SemaTemplate/dependent-type-identity.cpp new file mode 100644 index 000000000000..739cb7f39fa3 --- /dev/null +++ b/test/SemaTemplate/dependent-type-identity.cpp @@ -0,0 +1,72 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// This test concerns the identity of dependent types within the +// canonical type system. This corresponds to C++ [temp.type], which +// specifies type equivalence within a template. +// +// FIXME: template template parameters + +namespace N { + template<typename T> + struct X2 { + template<typename U> + struct apply { + typedef U* type; + }; + }; +} + +namespace Nalias = N; + +template<typename T> +struct X0 { }; + +using namespace N; + +template<typename T, typename U> +struct X1 { + typedef T type; + typedef U U_type; + + void f0(T); // expected-note{{previous}} + void f0(U); + void f0(type); // expected-error{{redeclar}} + + void f1(T*); // expected-note{{previous}} + void f1(U*); + void f1(type*); // expected-error{{redeclar}} + + void f2(X0<T>*); // expected-note{{previous}} + void f2(X0<U>*); + void f2(X0<type>*); // expected-error{{redeclar}} + + void f3(X0<T>*); // expected-note{{previous}} + void f3(X0<U>*); + void f3(::X0<type>*); // expected-error{{redeclar}} + + void f4(typename T::template apply<U>*); // expected-note{{previous}} + void f4(typename U::template apply<U>*); + void f4(typename type::template apply<T>*); + void f4(typename type::template apply<U_type>*); // expected-error{{redeclar}} + + void f5(typename T::template apply<U>::type*); // expected-note{{previous}} + void f5(typename U::template apply<U>::type*); + void f5(typename U::template apply<T>::type*); + void f5(typename type::template apply<T>::type*); + void f5(typename type::template apply<U_type>::type*); // expected-error{{redeclar}} + + void f6(typename N::X2<T>::template apply<U> *); // expected-note{{previous}} + void f6(typename N::X2<U>::template apply<U> *); + void f6(typename N::X2<U>::template apply<T> *); + void f6(typename ::N::X2<type>::template apply<U_type> *); // expected-error{{redeclar}} + + void f7(typename N::X2<T>::template apply<U> *); // expected-note{{previous}} + void f7(typename N::X2<U>::template apply<U> *); + void f7(typename N::X2<U>::template apply<T> *); + void f7(typename X2<type>::template apply<U_type> *); // expected-error{{redeclar}} + + void f8(typename N::X2<T>::template apply<U> *); // expected-note{{previous}} + void f8(typename N::X2<U>::template apply<U> *); + void f8(typename N::X2<U>::template apply<T> *); + void f8(typename ::Nalias::X2<type>::template apply<U_type> *); // expected-error{{redeclar}} +}; diff --git a/test/SemaTemplate/enum-argument.cpp b/test/SemaTemplate/enum-argument.cpp new file mode 100644 index 000000000000..101a1d0cd9da --- /dev/null +++ b/test/SemaTemplate/enum-argument.cpp @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +enum Enum { val = 1 }; +template <Enum v> struct C { + typedef C<v> Self; +}; +template struct C<val>; diff --git a/test/SemaTemplate/example-dynarray.cpp b/test/SemaTemplate/example-dynarray.cpp new file mode 100644 index 000000000000..cca3709bebbf --- /dev/null +++ b/test/SemaTemplate/example-dynarray.cpp @@ -0,0 +1,150 @@ +// RUN: clang-cc -fsyntax-only -verify %s +#include <stddef.h> +#include <stdlib.h> +#include <assert.h> + +// Placement new requires <new> to be included, but we don't support that yet. +void* operator new(size_t, void* ptr) throw() { + return ptr; +} +void operator delete(void*, void*) throw() { +} + +template<typename T> +class dynarray { +public: + dynarray() { Start = Last = End = 0; } + + dynarray(const dynarray &other) { + Start = (T*)malloc(sizeof(T) * other.size()); + Last = End = Start + other.size(); + + for (unsigned I = 0, N = other.size(); I != N; ++I) + new (Start + I) T(other[I]); + } + + ~dynarray() { + free(Start); + } + + dynarray &operator=(const dynarray &other) { + T* NewStart = (T*)malloc(sizeof(T) * other.size()); + + for (unsigned I = 0, N = other.size(); I != N; ++I) + new (NewStart + I) T(other[I]); + + // FIXME: destroy everything in Start + free(Start); + Start = NewStart; + Last = End = NewStart + other.size(); + return *this; + } + + unsigned size() const { return Last - Start; } + unsigned capacity() const { return End - Start; } + + void push_back(const T& value) { + if (Last == End) { + unsigned NewCapacity = capacity() * 2; + if (NewCapacity == 0) + NewCapacity = 4; + + T* NewStart = (T*)malloc(sizeof(T) * NewCapacity); + + unsigned Size = size(); + for (unsigned I = 0; I != Size; ++I) + new (NewStart + I) T(Start[I]); + + // FIXME: destruct old values + free(Start); + + Start = NewStart; + Last = Start + Size; + End = Start + NewCapacity; + } + + new (Last) T(value); + ++Last; + } + + void pop_back() { + // FIXME: destruct old value + --Last; + } + + T& operator[](unsigned Idx) { + return Start[Idx]; + } + + const T& operator[](unsigned Idx) const { + return Start[Idx]; + } + + typedef T* iterator; + typedef const T* const_iterator; + + iterator begin() { return Start; } + const_iterator begin() const { return Start; } + + iterator end() { return Last; } + const_iterator end() const { return Last; } + +public: + T* Start, *Last, *End; +}; + +struct Point { + Point() { x = y = z = 0.0; } + Point(const Point& other) : x(other.x), y(other.y), z(other.z) { } + + float x, y, z; +}; + +// FIXME: remove these when we have implicit instantiation for member +// functions of class templates. +template class dynarray<int>; +template class dynarray<Point>; + +int main() { + dynarray<int> di; + di.push_back(0); + di.push_back(1); + di.push_back(2); + di.push_back(3); + di.push_back(4); + assert(di.size() == 5); + for (dynarray<int>::iterator I = di.begin(), IEnd = di.end(); I != IEnd; ++I) + assert(*I == I - di.begin()); + + for (int I = 0, N = di.size(); I != N; ++I) + assert(di[I] == I); + + di.pop_back(); + assert(di.size() == 4); + di.push_back(4); + + dynarray<int> di2 = di; + assert(di2.size() == 5); + assert(di.begin() != di2.begin()); + for (dynarray<int>::iterator I = di2.begin(), IEnd = di2.end(); + I != IEnd; ++I) + assert(*I == I - di2.begin()); + + dynarray<int> di3(di); + assert(di3.size() == 5); + assert(di.begin() != di3.begin()); + for (dynarray<int>::iterator I = di3.begin(), IEnd = di3.end(); + I != IEnd; ++I) + assert(*I == I - di3.begin()); + + dynarray<int> di4; + assert(di4.size() == 0); + di4 = di; + assert(di4.size() == 5); + assert(di.begin() != di4.begin()); + for (dynarray<int>::iterator I = di4.begin(), IEnd = di4.end(); + I != IEnd; ++I) + assert(*I == I - di4.begin()); + + return 0; +} diff --git a/test/SemaTemplate/fibonacci.cpp b/test/SemaTemplate/fibonacci.cpp new file mode 100644 index 000000000000..6cd50157e2bd --- /dev/null +++ b/test/SemaTemplate/fibonacci.cpp @@ -0,0 +1,66 @@ +// RUN: clang-cc -fsyntax-only %s + +template<unsigned I> +struct FibonacciEval; + +template<unsigned I> +struct Fibonacci { + enum { value = FibonacciEval<I-1>::value + FibonacciEval<I-2>::value }; +}; + +template<unsigned I> +struct FibonacciEval { + enum { value = Fibonacci<I>::value }; +}; + +template<> struct Fibonacci<0> { + enum { value = 0 }; +}; + +template<> struct Fibonacci<1> { + enum { value = 1 }; +}; + +int array5[Fibonacci<5>::value == 5? 1 : -1]; +int array10[Fibonacci<10>::value == 55? 1 : -1]; + +template<unsigned I> +struct FibonacciEval2; + +template<unsigned I> +struct Fibonacci2 { + static const unsigned value + = FibonacciEval2<I-1>::value + FibonacciEval2<I-2>::value; +}; + +template<unsigned I> +struct FibonacciEval2 { + static const unsigned value = Fibonacci2<I>::value; +}; + +template<> struct Fibonacci2<0> { + static const unsigned value = 0; +}; + +template<> struct Fibonacci2<1> { + static const unsigned value = 1; +}; + +int array5_2[Fibonacci2<5>::value == 5? 1 : -1]; +int array10_2[Fibonacci2<10>::value == 55? 1 : -1]; + +template<unsigned I> +struct Fibonacci3 { + static const unsigned value = Fibonacci3<I-1>::value + Fibonacci3<I-2>::value; +}; + +template<> struct Fibonacci3<0> { + static const unsigned value = 0; +}; + +template<> struct Fibonacci3<1> { + static const unsigned value = 1; +}; + +int array5_3[Fibonacci3<5>::value == 5? 1 : -1]; +int array10_3[Fibonacci3<10>::value == 55? 1 : -1]; diff --git a/test/SemaTemplate/fun-template-def.cpp b/test/SemaTemplate/fun-template-def.cpp new file mode 100644 index 000000000000..8833ef4ddc1d --- /dev/null +++ b/test/SemaTemplate/fun-template-def.cpp @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Tests that dependent expressions are always allowed, whereas non-dependent +// are checked as usual. + +#include <stddef.h> + +// Fake typeid, lacking a typeinfo header. +namespace std { class type_info {}; } + +struct dummy {}; + +template <typename T, typename U> +T f(T t1, U u1, int i1) +{ + T t2 = i1; + t2 = i1 + u1; + ++u1; + u1++; + int i2 = u1; + + i1 = t1[u1]; + i1 *= t1; + + i1(u1, t1); // error + u1(i1, t1); + + U u2 = (T)i1; + static_cast<void>(static_cast<U>(reinterpret_cast<T>( + dynamic_cast<U>(const_cast<T>(i1))))); + + new U(i1, t1); + new int(t1, u1); // expected-error {{initializer of a builtin type can only take one argument}} + new (t1, u1) int; + delete t1; + + dummy d1 = sizeof(t1); // FIXME: delayed checking okay? + dummy d2 = offsetof(T, foo); // expected-error {{cannot initialize 'd2'}} + dummy d3 = __alignof(u1); // FIXME: delayed checking okay? + i1 = typeid(t1); // expected-error {{incompatible type assigning}} + + return u1; +} diff --git a/test/SemaTemplate/injected-class-name.cpp b/test/SemaTemplate/injected-class-name.cpp new file mode 100644 index 000000000000..c5f826d849ca --- /dev/null +++ b/test/SemaTemplate/injected-class-name.cpp @@ -0,0 +1,40 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> +struct X { + X<T*> *ptr; +}; + +X<int> x; + +template<> +struct X<int***> { + typedef X<int***> *ptr; +}; + +// FIXME: EDG rejects this in their strict-conformance mode, but I +// don't see any wording making this ill-formed. Actually, +// [temp.local]p2 might make it ill-formed. Are we "in the scope of +// the class template specialization?" +X<float>::X<int> xi = x; + +// [temp.local]p1: + +// FIXME: test non-type and template template parameters +template<typename T, typename U> +struct X0 { + typedef T type; + typedef U U_type; + typedef U_type U_type2; + + void f0(const X0&); // expected-note{{here}} + void f0(X0&); + void f0(const X0<T, U>&); // expected-error{{redecl}} + + void f1(const X0&); // expected-note{{here}} + void f1(X0&); + void f1(const X0<type, U_type2>&); // expected-error{{redecl}} + + void f2(const X0&); // expected-note{{here}} + void f2(X0&); + void f2(const ::X0<type, U_type2>&); // expected-error{{redecl}} +}; diff --git a/test/SemaTemplate/instantiate-array.cpp b/test/SemaTemplate/instantiate-array.cpp new file mode 100644 index 000000000000..29279b436899 --- /dev/null +++ b/test/SemaTemplate/instantiate-array.cpp @@ -0,0 +1,28 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#define __CONCAT(__X, __Y) __CONCAT1(__X, __Y) +#define __CONCAT1(__X, __Y) __X ## __Y + +#define static_assert(__b, __m) \ + typedef int __CONCAT(__sa, __LINE__)[__b ? 1 : -1] +#endif + +template <int N> class IntArray { + int elems[N]; +}; + +static_assert(sizeof(IntArray<10>) == sizeof(int) * 10, "Array size mismatch"); +static_assert(sizeof(IntArray<1>) == sizeof(int) * 1, "Array size mismatch"); + +template <typename T> class TenElementArray { + int elems[10]; +}; + +static_assert(sizeof(TenElementArray<int>) == sizeof(int) * 10, "Array size mismatch"); + +template<typename T, int N> class Array { + T elems[N]; +}; + +static_assert(sizeof(Array<int, 10>) == sizeof(int) * 10, "Array size mismatch"); diff --git a/test/SemaTemplate/instantiate-c99.cpp b/test/SemaTemplate/instantiate-c99.cpp new file mode 100644 index 000000000000..cf691cffad36 --- /dev/null +++ b/test/SemaTemplate/instantiate-c99.cpp @@ -0,0 +1,81 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Test template instantiation for C99-specific features. + +// --------------------------------------------------------------------- +// Designated initializers +// --------------------------------------------------------------------- +template<typename T, typename XType, typename YType> +struct DesigInit0 { + void f(XType x, YType y) { + T agg = { + .y = y, // expected-error{{does not refer}} + .x = x // expected-error{{does not refer}} + }; + } +}; + +struct Point2D { + float x, y; +}; + +template struct DesigInit0<Point2D, int, double>; + +struct Point3D { + float x, y, z; +}; + +template struct DesigInit0<Point3D, int, double>; + +struct Color { + unsigned char red, green, blue; +}; + +struct ColorPoint3D { + Color color; + float x, y, z; +}; + +template struct DesigInit0<ColorPoint3D, int, double>; +template struct DesigInit0<Color, int, double>; // expected-note{{instantiation}} + +template<typename T, int Subscript1, int Subscript2, + typename Val1, typename Val2> +struct DesigArrayInit0 { + void f(Val1 val1, Val2 val2) { + T array = { + [Subscript1] = val1, + [Subscript2] = val2 // expected-error{{exceeds array bounds}} + }; + + int array2[10] = { [5] = 3 }; + } +}; + +template struct DesigArrayInit0<int[8], 5, 3, float, int>; +template struct DesigArrayInit0<int[8], 5, 13, float, int>; // expected-note{{instantiation}} + +template<typename T, int Subscript1, int Subscript2, + typename Val1> +struct DesigArrayRangeInit0 { + void f(Val1 val1) { + T array = { + [Subscript1...Subscript2] = val1 // expected-error{{exceeds}} + }; + } +}; + +template struct DesigArrayRangeInit0<int[8], 3, 5, float>; +template struct DesigArrayRangeInit0<int[8], 5, 13, float>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// Compound literals +// --------------------------------------------------------------------- +template<typename T, typename Arg1, typename Arg2> +struct CompoundLiteral0 { + T f(Arg1 a1, Arg2 a2) { + return (T){a1, a2}; + } +}; + +template struct CompoundLiteral0<Point2D, int, float>; diff --git a/test/SemaTemplate/instantiate-call.cpp b/test/SemaTemplate/instantiate-call.cpp new file mode 100644 index 000000000000..a9c4bf481ded --- /dev/null +++ b/test/SemaTemplate/instantiate-call.cpp @@ -0,0 +1,50 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N1 { + struct X0 { }; + + int& f0(X0); +} + +namespace N2 { + char& f0(char); + + template<typename T, typename Result> + struct call_f0 { + void test_f0(T t) { + Result result = f0(t); + } + }; +} + +template struct N2::call_f0<int, char&>; +template struct N2::call_f0<N1::X0, int&>; + +namespace N3 { + template<typename T, typename Result> + struct call_f0 { + void test_f0(T t) { + Result &result = f0(t); // expected-error 2{{no matching}} + } + }; +} + +template struct N3::call_f0<int, char&>; // expected-note{{instantiation}} +template struct N3::call_f0<N1::X0, int&>; + +short& f0(char); +namespace N4 { + template<typename T, typename Result> + struct call_f0 { + void test_f0(T t) { + Result &result = f0(t); + } + }; +} + +template struct N4::call_f0<int, short&>; +template struct N4::call_f0<N1::X0, int&>; +template struct N3::call_f0<int, short&>; // expected-note{{instantiation}} + +// FIXME: test overloaded function call operators, calls to member +// functions, etc. diff --git a/test/SemaTemplate/instantiate-cast.cpp b/test/SemaTemplate/instantiate-cast.cpp new file mode 100644 index 000000000000..d99f3e556602 --- /dev/null +++ b/test/SemaTemplate/instantiate-cast.cpp @@ -0,0 +1,109 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct A { int x; }; + +class Base { +public: + virtual void f(); +}; + +class Derived : public Base { }; + +struct ConvertibleToInt { + operator int() const; +}; + +struct Constructible { + Constructible(int, float); +}; + +// --------------------------------------------------------------------- +// C-style casts +// --------------------------------------------------------------------- +template<typename T, typename U> +struct CStyleCast0 { + void f(T t) { + (void)((U)t); // FIXME:ugly expected-error{{operand}} + } +}; + +template struct CStyleCast0<int, float>; +template struct CStyleCast0<A, int>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// static_cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct StaticCast0 { + void f(T t) { + (void)static_cast<U>(t); // expected-error{{static_cast}} + } +}; + +template struct StaticCast0<ConvertibleToInt, bool>; +template struct StaticCast0<int, float>; +template struct StaticCast0<int, A>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// dynamic_cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct DynamicCast0 { + void f(T t) { + (void)dynamic_cast<U>(t); // expected-error{{not a reference or pointer}} + } +}; + +template struct DynamicCast0<Base*, Derived*>; +template struct DynamicCast0<Base*, A>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// reinterpret_cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct ReinterpretCast0 { + void f(T t) { + (void)reinterpret_cast<U>(t); // expected-error{{constness}} + } +}; + +template struct ReinterpretCast0<void (*)(int), void (*)(float)>; +template struct ReinterpretCast0<int const *, float *>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// const_cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct ConstCast0 { + void f(T t) { + (void)const_cast<U>(t); // expected-error{{not allowed}} + } +}; + +template struct ConstCast0<int const * *, int * *>; +template struct ConstCast0<int const *, float *>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// C++ functional cast +// --------------------------------------------------------------------- +template<typename T, typename U> +struct FunctionalCast1 { + void f(T t) { + (void)U(t); // FIXME:ugly expected-error{{operand}} + } +}; + +template struct FunctionalCast1<int, float>; +template struct FunctionalCast1<A, int>; // expected-note{{instantiation}} + +#if 0 +// Generates temporaries, which we cannot handle yet. +template<int N, long M> +struct FunctionalCast2 { + void f() { + (void)Constructible(N, M); + } +}; + +template struct FunctionalCast2<1, 3>; +#endif diff --git a/test/SemaTemplate/instantiate-clang.cpp b/test/SemaTemplate/instantiate-clang.cpp new file mode 100644 index 000000000000..a6c28d9e19db --- /dev/null +++ b/test/SemaTemplate/instantiate-clang.cpp @@ -0,0 +1,35 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Test template instantiation for Clang-specific features. + +// --------------------------------------------------------------------- +// Vector types +// --------------------------------------------------------------------- +typedef __attribute__(( ext_vector_type(2) )) double double2; +typedef __attribute__(( ext_vector_type(4) )) double double4; + +template<typename T> +struct ExtVectorAccess0 { + void f(T v1, double4 v2) { + v1.xy = v2.yx; + } +}; + +template struct ExtVectorAccess0<double2>; +template struct ExtVectorAccess0<double4>; + +typedef __attribute__(( ext_vector_type(2) )) double double2; + +template<typename T, typename U, int N, int M> +struct ShuffleVector0 { + void f(T t, U u, double2 a, double2 b) { + (void)__builtin_shufflevector(t, u, N, M); // expected-error{{index}} + (void)__builtin_shufflevector(a, b, N, M); + (void)__builtin_shufflevector(a, b, 2, 1); + } +}; + +template struct ShuffleVector0<double2, double2, 2, 1>; +template struct ShuffleVector0<double2, double2, 4, 3>; // expected-note{{instantiation}} + + diff --git a/test/SemaTemplate/instantiate-complete.cpp b/test/SemaTemplate/instantiate-complete.cpp new file mode 100644 index 000000000000..babc55217a95 --- /dev/null +++ b/test/SemaTemplate/instantiate-complete.cpp @@ -0,0 +1,47 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Tests various places where requiring a complete type involves +// instantiation of that type. + +template<typename T> +struct X { + X(T); + + T f; // expected-error{{data member instantiated with function type 'float (int)'}} \ + // expected-error{{data member instantiated with function type 'int (int)'}} \ + // expected-error{{data member instantiated with function type 'char (char)'}} \ + // expected-error{{data member instantiated with function type 'short (short)'}} \ + // expected-error{{data member instantiated with function type 'float (float)'}} +}; + +X<int> f() { return 0; } + +struct XField { + X<float(int)> xf; // expected-note{{in instantiation of template class 'struct X<float (int)>' requested here}} +}; + +void test_subscript(X<double> *ptr1, X<int(int)> *ptr2, int i) { + (void)ptr1[i]; + (void)ptr2[i]; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}} +} + +void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2, + X<char(char)> *ptr3, X<short(short)> *ptr4) { + (void)(ptr1 + 5); + // FIXME: if I drop the ')' after void, below, it still parses (!) + (void)(5 + ptr2); + (void)(ptr3 + 5); // expected-note{{in instantiation of template class 'struct X<char (char)>' requested here}} + (void)(5 + ptr4); // expected-note{{in instantiation of template class 'struct X<short (short)>' requested here}} +} + +void test_new() { + (void)new X<float>(0); + (void)new X<float(float)>; // expected-note{{in instantiation of template class 'struct X<float (float)>' requested here}} +} + +void test_memptr(X<long> *p1, long X<long>::*pm1, + X<long(long)> *p2, + long (X<long(long)>::*pm2)(long)) { + (void)(p1->*pm1); + (void)((p2->*pm2)(0)); +} diff --git a/test/SemaTemplate/instantiate-declref.cpp b/test/SemaTemplate/instantiate-declref.cpp new file mode 100644 index 000000000000..051c6050abea --- /dev/null +++ b/test/SemaTemplate/instantiate-declref.cpp @@ -0,0 +1,71 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace N { + struct Outer { + struct Inner { + template<typename T> + struct InnerTemplate { + struct VeryInner { + typedef T type; + + static enum K1 { K1Val = sizeof(T) } Kind1; + static enum { K2Val = sizeof(T)*2 } Kind2; + enum { K3Val = sizeof(T)*2 } Kind3; + + void foo() { + K1 k1 = K1Val; + Kind1 = K1Val; + Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val; + Kind3 = K3Val; + } + + struct UeberInner { + void bar() { + K1 k1 = K1Val; + Kind1 = K1Val; + Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val; + + InnerTemplate t; + InnerTemplate<type> t2; + } + }; + }; + }; + }; + }; +} + +typedef int INT; +template struct N::Outer::Inner::InnerTemplate<INT>::VeryInner; +template struct N::Outer::Inner::InnerTemplate<INT>::UeberInner; // expected-error{{'UeberInner' does not name a tag member}} + +namespace N2 { + struct Outer2 { + template<typename T, typename U = T> + struct Inner { + void foo() { + enum { K1Val = sizeof(T) } k1; + enum K2 { K2Val = sizeof(T)*2 } k2a; + + K2 k2b = K2Val; + + struct S { T x, y; } s1; + struct { U x, y; } s2; + s1.x = s2.x; // expected-error{{incompatible}} + + typedef T type; + type t2 = s1.x; + + typedef struct { T z; } type2; + type2 t3 = { s1.x }; + + Inner i1; + i1.foo(); + Inner<T> i2; + i2.foo(); + } + }; + }; +} + +template struct N2::Outer2::Inner<float>; +template struct N2::Outer2::Inner<int*, float*>; // expected-note{{instantiation}} diff --git a/test/SemaTemplate/instantiate-enum.cpp b/test/SemaTemplate/instantiate-enum.cpp new file mode 100644 index 000000000000..a7acf22a45a1 --- /dev/null +++ b/test/SemaTemplate/instantiate-enum.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only %s + +template<typename T, T I, int J> +struct adder { + enum { + value = I + J, + value2 + }; +}; + +int array1[adder<long, 3, 4>::value == 7? 1 : -1]; diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp new file mode 100644 index 000000000000..13ee3ab525ba --- /dev/null +++ b/test/SemaTemplate/instantiate-expr-1.cpp @@ -0,0 +1,71 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<int I, int J> +struct Bitfields { + int simple : I; // expected-error{{bit-field 'simple' has zero width}} + int parens : (J); +}; + +void test_Bitfields(Bitfields<0, 5> *b) { + (void)sizeof(Bitfields<10, 5>); + (void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'struct Bitfields<0, 1>' requested here}} +} + +template<int I, int J> +struct BitfieldPlus { + int bitfield : I + J; // expected-error{{bit-field 'bitfield' has zero width}} +}; + +void test_BitfieldPlus() { + (void)sizeof(BitfieldPlus<0, 1>); + (void)sizeof(BitfieldPlus<-5, 5>); // expected-note{{in instantiation of template class 'struct BitfieldPlus<-5, 5>' requested here}} +} + +template<int I, int J> +struct BitfieldMinus { + int bitfield : I - J; // expected-error{{bit-field 'bitfield' has negative width (-1)}} \ + // expected-error{{bit-field 'bitfield' has zero width}} +}; + +void test_BitfieldMinus() { + (void)sizeof(BitfieldMinus<5, 1>); + (void)sizeof(BitfieldMinus<0, 1>); // expected-note{{in instantiation of template class 'struct BitfieldMinus<0, 1>' requested here}} + (void)sizeof(BitfieldMinus<5, 5>); // expected-note{{in instantiation of template class 'struct BitfieldMinus<5, 5>' requested here}} +} + +template<int I, int J> +struct BitfieldDivide { + int bitfield : I / J; // expected-error{{expression is not an integer constant expression}} \ + // expected-note{{division by zero}} +}; + +void test_BitfieldDivide() { + (void)sizeof(BitfieldDivide<5, 1>); + (void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'struct BitfieldDivide<5, 0>' requested here}} +} + +template<typename T, T I, int J> +struct BitfieldDep { + int bitfield : I + J; +}; + +void test_BitfieldDep() { + (void)sizeof(BitfieldDep<int, 1, 5>); +} + +template<int I> +struct BitfieldNeg { + int bitfield : (-I); // expected-error{{bit-field 'bitfield' has negative width (-5)}} +}; + +template<typename T, T I> +struct BitfieldNeg2 { + int bitfield : (-I); // expected-error{{bit-field 'bitfield' has negative width (-5)}} +}; + +void test_BitfieldNeg() { + (void)sizeof(BitfieldNeg<-5>); // okay + (void)sizeof(BitfieldNeg<5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg<5>' requested here}} + (void)sizeof(BitfieldNeg2<int, -5>); // okay + (void)sizeof(BitfieldNeg2<int, 5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg2<int, 5>' requested here}} +} diff --git a/test/SemaTemplate/instantiate-expr-2.cpp b/test/SemaTemplate/instantiate-expr-2.cpp new file mode 100644 index 000000000000..80f403ed56fe --- /dev/null +++ b/test/SemaTemplate/instantiate-expr-2.cpp @@ -0,0 +1,132 @@ +// RUN: clang-cc -fsyntax-only %s +typedef char one_byte; +typedef char (&two_bytes)[2]; +typedef char (&four_bytes)[4]; +typedef char (&eight_bytes)[8]; + +template<int N> struct A { }; + +namespace N1 { + struct X { }; +} + +namespace N2 { + struct Y { }; + + two_bytes operator+(Y, Y); +} + +namespace N3 { + struct Z { }; + + eight_bytes operator+(Z, Z); +} + +namespace N4 { + one_byte operator+(N1::X, N2::Y); + + template<typename T, typename U> + struct BinOpOverload { + typedef A<sizeof(T() + U())> type; + }; +} + +namespace N1 { + four_bytes operator+(X, X); +} + +namespace N3 { + eight_bytes operator+(Z, Z); // redeclaration +} + +void test_bin_op_overload(A<1> *a1, A<2> *a2, A<4> *a4, A<8> *a8) { + typedef N4::BinOpOverload<N1::X, N2::Y>::type XY; + XY *xy = a1; + typedef N4::BinOpOverload<N1::X, N1::X>::type XX; + XX *xx = a4; + typedef N4::BinOpOverload<N2::Y, N2::Y>::type YY; + YY *yy = a2; + typedef N4::BinOpOverload<N3::Z, N3::Z>::type ZZ; + ZZ *zz = a8; +} + +namespace N3 { + eight_bytes operator-(::N3::Z); +} + +namespace N4 { + template<typename T> + struct UnaryOpOverload { + typedef A<sizeof(-T())> type; + }; +} + +void test_unary_op_overload(A<8> *a8) { + typedef N4::UnaryOpOverload<N3::Z>::type UZ; + UZ *uz = a8; +} + +/* +namespace N5 { + template<int I> + struct Lookup { + enum { val = I, more = val + 1 }; + }; + + template<bool B> + struct Cond { + enum Junk { is = B ? Lookup<B>::more : Lookup<Lookup<B+1>::more>::val }; + }; + + enum { resultT = Cond<true>::is, + resultF = Cond<false>::is }; +} +*/ + +namespace N6 { + // non-typedependent + template<int I> + struct Lookup {}; + + template<bool B, typename T, typename E> + struct Cond { + typedef Lookup<B ? sizeof(T) : sizeof(E)> True; + typedef Lookup<!B ? sizeof(T) : sizeof(E)> False; + }; + + typedef Cond<true, int, char>::True True; + typedef Cond<true, int, char>::False False; + + // check that we have the right types + Lookup<1> const &L1(False()); + Lookup<sizeof(int)> const &L2(True()); +} + + +namespace N7 { + // type dependent + template<int I> + struct Lookup {}; + + template<bool B, typename T, typename E> + struct Cond { + T foo() { return B ? T() : E(); } + typedef Lookup<sizeof(B ? T() : E())> Type; + }; + + //Cond<true, int*, double> C; // Errors + //int V(C.foo()); // Errors + //typedef Cond<true, int*, double>::Type Type; // Errors + typedef Cond<true, int, double>::Type Type; +} + +template<typename T, unsigned long N> struct IntegralConstant { }; + +template<typename T> +struct X0 { + void f(T x, IntegralConstant<T, sizeof(x)>); +}; + +void test_X0(X0<int> x, IntegralConstant<int, sizeof(int)> ic) { + x.f(5,ic); +} diff --git a/test/SemaTemplate/instantiate-expr-3.cpp b/test/SemaTemplate/instantiate-expr-3.cpp new file mode 100644 index 000000000000..696b58325cd7 --- /dev/null +++ b/test/SemaTemplate/instantiate-expr-3.cpp @@ -0,0 +1,115 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// --------------------------------------------------------------------- +// Imaginary literals +// --------------------------------------------------------------------- +template<typename T> +struct ImaginaryLiteral0 { + void f(T &x) { + x = 3.0I; // expected-error{{incompatible type}} + } +}; + +template struct ImaginaryLiteral0<_Complex float>; +template struct ImaginaryLiteral0<int*>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// Compound assignment operator +// --------------------------------------------------------------------- +namespace N1 { + struct X { }; + + int& operator+=(X&, int); // expected-note{{candidate}} +} + +namespace N2 { + long& operator+=(N1::X&, long); // expected-note{{candidate}} + + template<typename T, typename U, typename Result> + struct PlusEquals0 { + void f(T t, U u) { + Result r = t += u; // expected-error{{ambiguous}} + } + }; +} + +namespace N3 { + struct Y : public N1::X { + short& operator+=(long); // expected-note{{candidate}} + }; +} + +template struct N2::PlusEquals0<N1::X, int, int&>; +template struct N2::PlusEquals0<N1::X, long, long&>; +template struct N2::PlusEquals0<N3::Y, long, short&>; +template struct N2::PlusEquals0<int, int, int&>; +template struct N2::PlusEquals0<N3::Y, int, short&>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// Conditional operator +// --------------------------------------------------------------------- +template<typename T, typename U, typename Result> +struct Conditional0 { + void f(T t, U u) { + Result result = t? : u; + } +}; + +template struct Conditional0<int, int, int>; + +// --------------------------------------------------------------------- +// Statement expressions +// --------------------------------------------------------------------- +template<typename T> +struct StatementExpr0 { + void f(T t) { + (void)({ if (t) t = t + 17; t + 12;}); // expected-error{{invalid}} + } +}; + +template struct StatementExpr0<int>; +template struct StatementExpr0<N1::X>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// __builtin_choose_expr +// --------------------------------------------------------------------- +template<bool Cond, typename T, typename U, typename Result> +struct Choose0 { + void f(T t, U u) { + Result r = __builtin_choose_expr(Cond, t, u); // expected-error{{lvalue}} + } +}; + +template struct Choose0<true, int, float, int&>; +template struct Choose0<false, int, float, float&>; +template struct Choose0<true, int, float, float&>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// __builtin_va_arg +// --------------------------------------------------------------------- +template<typename ArgType> +struct VaArg0 { + void f(int n, ...) { + __builtin_va_list va; + __builtin_va_start(va, n); + for (int i = 0; i != n; ++i) + (void)__builtin_va_arg(va, ArgType); + __builtin_va_end(va); + } +}; + +template struct VaArg0<int>; + +template<typename VaList, typename ArgType> +struct VaArg1 { + void f(int n, ...) { + VaList va; + __builtin_va_start(va, n); // expected-error{{int}} + for (int i = 0; i != n; ++i) + (void)__builtin_va_arg(va, ArgType); + __builtin_va_end(va); + } +}; + +template struct VaArg1<__builtin_va_list, int>; +template struct VaArg1<int, int>; // expected-note{{instantiation}} diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp new file mode 100644 index 000000000000..cd74a21d6dbc --- /dev/null +++ b/test/SemaTemplate/instantiate-expr-4.cpp @@ -0,0 +1,289 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// --------------------------------------------------------------------- +// C++ Functional Casts +// --------------------------------------------------------------------- +template<int N> +struct ValueInit0 { + int f() { + return int(); + } +}; + +template struct ValueInit0<5>; + +template<int N> +struct FunctionalCast0 { + int f() { + return int(N); + } +}; + +template struct FunctionalCast0<5>; + +struct X { // expected-note 2 {{candidate function}} + X(int, int); // expected-note 2 {{candidate function}} +}; + +template<int N, int M> +struct BuildTemporary0 { + X f() { + return X(N, M); + } +}; + +template struct BuildTemporary0<5, 7>; + +template<int N, int M> +struct Temporaries0 { + void f() { + (void)X(N, M); + } +}; + +template struct Temporaries0<5, 7>; + +// --------------------------------------------------------------------- +// new/delete expressions +// --------------------------------------------------------------------- +struct Y { }; + +template<typename T> +struct New0 { + T* f(bool x) { + if (x) + return new T; // expected-error{{no matching}} + else + return new T(); + } +}; + +template struct New0<int>; +template struct New0<Y>; +template struct New0<X>; // expected-note{{instantiation}} + +template<typename T, typename Arg1> +struct New1 { + T* f(bool x, Arg1 a1) { + return new T(a1); // expected-error{{no matching}} + } +}; + +template struct New1<int, float>; +template struct New1<Y, Y>; +template struct New1<X, Y>; // expected-note{{instantiation}} + +template<typename T, typename Arg1, typename Arg2> +struct New2 { + T* f(bool x, Arg1 a1, Arg2 a2) { + return new T(a1, a2); // expected-error{{no matching}} + } +}; + +template struct New2<X, int, float>; +template struct New2<X, int, int*>; // expected-note{{instantiation}} +// FIXME: template struct New2<int, int, float>; + +template<typename T> +struct Delete0 { + void f(T t) { + delete t; // expected-error{{cannot delete}} + ::delete [] t; + } +}; + +template struct Delete0<int*>; +template struct Delete0<X*>; +template struct Delete0<int>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// throw expressions +// --------------------------------------------------------------------- +template<typename T> +struct Throw1 { + void f(T t) { + throw; + throw t; // expected-error{{incomplete type}} + } +}; + +struct Incomplete; // expected-note{{forward}} + +template struct Throw1<int>; +template struct Throw1<int*>; +template struct Throw1<Incomplete*>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// typeid expressions +// --------------------------------------------------------------------- + +// FIXME: This should really include <typeinfo>, but we don't have that yet. +namespace std { + class type_info; +} + +template<typename T> +struct TypeId0 { + const std::type_info &f(T* ptr) { + if (ptr) + return typeid(ptr); + else + return typeid(T); + } +}; + +struct Abstract { + virtual void f() = 0; +}; + +template struct TypeId0<int>; +template struct TypeId0<Incomplete>; +template struct TypeId0<Abstract>; + +// --------------------------------------------------------------------- +// type traits +// --------------------------------------------------------------------- +template<typename T> +struct is_pod { + static const bool value = __is_pod(T); +}; + +static const int is_pod0[is_pod<X>::value? -1 : 1]; +static const int is_pod1[is_pod<Y>::value? 1 : -1]; + +// --------------------------------------------------------------------- +// initializer lists +// --------------------------------------------------------------------- +template<typename T, typename Val1> +struct InitList1 { + void f(Val1 val1) { + T x = { val1 }; + } +}; + +struct APair { + int *x; + const float *y; +}; + +template struct InitList1<int[1], float>; +template struct InitList1<APair, int*>; + +template<typename T, typename Val1, typename Val2> +struct InitList2 { + void f(Val1 val1, Val2 val2) { + T x = { val1, val2 }; // expected-error{{incompatible}} + } +}; + +template struct InitList2<APair, int*, float*>; +template struct InitList2<APair, int*, double*>; // expected-note{{instantiation}} + +// --------------------------------------------------------------------- +// member references +// --------------------------------------------------------------------- +template<typename T, typename Result> +struct DotMemRef0 { + void f(T t) { + Result result = t.m; // expected-error{{cannot be initialized}} + } +}; + +struct MemInt { + int m; +}; + +struct InheritsMemInt : MemInt { }; + +struct MemIntFunc { + static int m(int); +}; + +template struct DotMemRef0<MemInt, int&>; +template struct DotMemRef0<InheritsMemInt, int&>; +template struct DotMemRef0<MemIntFunc, int (*)(int)>; +template struct DotMemRef0<MemInt, float&>; // expected-note{{instantiation}} + +template<typename T, typename Result> +struct ArrowMemRef0 { + void f(T t) { + Result result = t->m; // expected-error 2{{cannot be initialized}} + } +}; + +template<typename T> +struct ArrowWrapper { + T operator->(); +}; + +template struct ArrowMemRef0<MemInt*, int&>; +template struct ArrowMemRef0<InheritsMemInt*, int&>; +template struct ArrowMemRef0<MemIntFunc*, int (*)(int)>; +template struct ArrowMemRef0<MemInt*, float&>; // expected-note{{instantiation}} + +template struct ArrowMemRef0<ArrowWrapper<MemInt*>, int&>; +template struct ArrowMemRef0<ArrowWrapper<InheritsMemInt*>, int&>; +template struct ArrowMemRef0<ArrowWrapper<MemIntFunc*>, int (*)(int)>; +template struct ArrowMemRef0<ArrowWrapper<MemInt*>, float&>; // expected-note{{instantiation}} +template struct ArrowMemRef0<ArrowWrapper<ArrowWrapper<MemInt*> >, int&>; + +// FIXME: we should be able to return a MemInt without the reference! +MemInt &createMemInt(int); + +template<int N> +struct NonDepMemberExpr0 { + void f() { + createMemInt(N).m = N; + } +}; + +template struct NonDepMemberExpr0<0>; + +template<typename T, typename Result> +struct MemberFuncCall0 { + void f(T t) { + Result result = t.f(); + } +}; + +template<typename T> +struct HasMemFunc0 { + T f(); +}; + + +template struct MemberFuncCall0<HasMemFunc0<int&>, const int&>; + +template<typename Result> +struct ThisMemberFuncCall0 { + Result g(); + + void f() { + Result r1 = g(); + Result r2 = this->g(); + } +}; + +template struct ThisMemberFuncCall0<int&>; + +template<typename T> +struct NonDepMemberCall0 { + void foo(HasMemFunc0<int&> x) { + T result = x.f(); // expected-error{{initialized}} + } +}; + +template struct NonDepMemberCall0<int&>; +template struct NonDepMemberCall0<const int&>; +template struct NonDepMemberCall0<float&>; // expected-note{{instantiation}} + + +template<typename T> +struct QualifiedDeclRef0 { + T f() { + return is_pod<X>::value; // expected-error{{initialized}} + } +}; + +template struct QualifiedDeclRef0<bool>; +template struct QualifiedDeclRef0<int&>; // expected-note{{instantiation}} diff --git a/test/SemaTemplate/instantiate-expr-basic.cpp b/test/SemaTemplate/instantiate-expr-basic.cpp new file mode 100644 index 000000000000..2b5fcaeb0454 --- /dev/null +++ b/test/SemaTemplate/instantiate-expr-basic.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only -Wno-unused-value -std=c++0x %s + +template <typename T> +struct S { + void f() { + __func__; // PredefinedExpr + 10; // IntegerLiteral + 10.5; // FloatingLiteral + 'c'; // CharacterLiteral + "hello"; // StringLiteral + true; // CXXBooleanLiteralExpr + nullptr; // CXXNullPtrLiteralExpr + __null; // GNUNullExpr + } +}; + +template struct S<int>; diff --git a/test/SemaTemplate/instantiate-field.cpp b/test/SemaTemplate/instantiate-field.cpp new file mode 100644 index 000000000000..8e2a3758b0d7 --- /dev/null +++ b/test/SemaTemplate/instantiate-field.cpp @@ -0,0 +1,28 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> +struct X { + int x; + T y; // expected-error{{data member instantiated with function type}} + T* z; + T bitfield : 12; // expected-error{{bit-field 'bitfield' has non-integral type 'float'}} \ + // expected-error{{data member instantiated with function type}} + + mutable T x2; // expected-error{{data member instantiated with function type}} +}; + +void test1(const X<int> *xi) { + int i1 = xi->x; + const int &i2 = xi->y; + int* ip1 = xi->z; + int i3 = xi->bitfield; + xi->x2 = 17; +} + +void test2(const X<float> *xf) { + (void)xf->x; // expected-note{{in instantiation of template class 'struct X<float>' requested here}} +} + +void test3(const X<int(int)> *xf) { + (void)xf->x; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}} +} diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp new file mode 100644 index 000000000000..5b3a6d998404 --- /dev/null +++ b/test/SemaTemplate/instantiate-function-1.cpp @@ -0,0 +1,211 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T, typename U> +struct X0 { + void f(T x, U y) { + (void)(x + y); // expected-error{{invalid operands}} + } +}; + +struct X1 { }; + +template struct X0<int, float>; +template struct X0<int*, int>; +template struct X0<int X1::*, int>; // expected-note{{instantiation of}} + +template<typename T> +struct X2 { + void f(T); + + T g(T x, T y) { + /* DeclStmt */; + T *xp = &x, &yr = y; // expected-error{{pointer to a reference}} + /* NullStmt */; + } +}; + +template struct X2<int>; +template struct X2<int&>; // expected-note{{instantiation of}} + +template<typename T> +struct X3 { + void f(T) { + Label: + T x; + goto Label; + } +}; + +template struct X3<int>; + +template <typename T> struct X4 { + T f() const { + return; // expected-warning{{non-void function 'f' should return a value}} + } + + T g() const { + return 1; // expected-warning{{void function 'g' should not return a value}} + } +}; + +template struct X4<void>; // expected-note{{in instantiation of}} +template struct X4<int>; // expected-note{{in instantiation of}} + +struct Incomplete; // expected-note 2{{forward declaration}} + +template<typename T> struct X5 { + T f() { } // expected-error{{incomplete result type}} +}; +void test_X5(X5<Incomplete> x5); // okay! + +template struct X5<Incomplete>; // expected-note{{instantiation}} + +template<typename T, typename U, typename V> struct X6 { + U f(T t, U u, V v) { + // IfStmt + if (t > 0) + return u; + else { + if (t < 0) + return v; // expected-error{{incompatible type}} + } + + if (T x = t) { + t = x; + } + return v; + } +}; + +struct ConvertibleToInt { + operator int() const; +}; + +template struct X6<ConvertibleToInt, float, char>; +template struct X6<bool, int, int*>; // expected-note{{instantiation}} + +template <typename T> struct X7 { + void f() { + void *v = this; + } +}; + +template struct X7<int>; + +template<typename T> struct While0 { + void f(T t) { + while (t) { + } + + while (T t2 = T()) ; + } +}; + +template struct While0<float>; + +template<typename T> struct Do0 { + void f(T t) { + do { + } while (t); // expected-error{{not contextually}} + + do { + } while (T t2 = T()); + } +}; + +struct NotConvertibleToBool { }; +template struct Do0<ConvertibleToInt>; +template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}} + +template<typename T> struct For0 { + void f(T f, T l) { + for (; f != l; ++f) { + if (*f) + continue; + else if (*f == 17) + break; + } + } +}; + +template struct For0<int*>; + +template<typename T> struct Member0 { + void f(T t) { + t; + t.f; + t->f; + + T* tp; + tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}} + tp->f; + + this->f; + this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}} + } +}; + +template<typename T, typename U> struct Switch0 { + U f(T value, U v0, U v1, U v2) { + switch (value) { + case 0: return v0; + + case 1: return v1; + + case 2: // fall through + + default: + return v2; + } + } +}; + +template struct Switch0<int, float>; + +template<typename T, int I1, int I2> struct Switch1 { + T f(T x, T y, T z) { + switch (x) { + case I1: return y; // expected-note{{previous}} + case I2: return z; // expected-error{{duplicate}} + default: return x; + } + } +}; + +template struct Switch1<int, 1, 2>; +template struct Switch1<int, 2, 2>; // expected-note{{instantiation}} + +template<typename T> struct IndirectGoto0 { + void f(T x) { + // FIXME: crummy error message below + goto *x; // expected-error{{incompatible}} + + prior: + T prior_label = &&prior; + + T later_label = &&later; + + later: + (void)(1+1); + } +}; + +template struct IndirectGoto0<void*>; +template struct IndirectGoto0<int>; // expected-note{{instantiation}} + +template<typename T> struct TryCatch0 { + void f() { + try { + } catch (T t) { // expected-error{{incomplete type}} \ + // expected-error{{abstract class}} + } catch (...) { + } + } +}; + +struct Abstract { + virtual void foo() = 0; // expected-note{{pure virtual}} +}; + +template struct TryCatch0<int>; // okay +template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}} +template struct TryCatch0<Abstract>; // expected-note{{instantiation}} diff --git a/test/SemaTemplate/instantiate-function-1.mm b/test/SemaTemplate/instantiate-function-1.mm new file mode 100644 index 000000000000..aef2d9dbb7eb --- /dev/null +++ b/test/SemaTemplate/instantiate-function-1.mm @@ -0,0 +1,14 @@ +template<typename T> struct Member0 { + void f(T t) { + t; + t.f; + t->f; + + T* tp; + tp.f; + tp->f; + + this->f; + this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}} + } +}; diff --git a/test/SemaTemplate/instantiate-function-2.cpp b/test/SemaTemplate/instantiate-function-2.cpp new file mode 100644 index 000000000000..51a60146d46a --- /dev/null +++ b/test/SemaTemplate/instantiate-function-2.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template <typename T> struct S { + S() { } + S(T t); +}; + +template struct S<int>; + +void f() { + S<int> s1; + S<int> s2(10); +} diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp new file mode 100644 index 000000000000..fab65cef2e45 --- /dev/null +++ b/test/SemaTemplate/instantiate-member-class.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> +class X { +public: + struct C { T &foo(); }; + + struct D { + struct E { T &bar(); }; // expected-error{{cannot form a reference to 'void'}} + struct F; // expected-note{{member is declared here}} + }; +}; + +X<int>::C *c1; +X<float>::C *c2; + +X<int>::X *xi; +X<float>::X *xf; + +void test_naming() { + c1 = c2; // expected-error{{incompatible type assigning 'X<float>::C *', expected 'X<int>::C *'}} + xi = xf; // expected-error{{incompatible type assigning}} + // FIXME: error above doesn't print the type X<int>::X cleanly! +} + +void test_instantiation(X<double>::C *x, + X<float>::D::E *e, + X<float>::D::F *f) { + double &dr = x->foo(); + float &fr = e->bar(); + f->foo(); // expected-error{{implicit instantiation of undefined member 'struct X<float>::D::F'}} + +} + + +X<void>::C *c3; // okay +X<void>::D::E *e1; // okay +X<void>::D::E e2; // expected-note{{in instantiation of member class 'struct X<void>::D::E' requested here}} diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp new file mode 100644 index 000000000000..daea7465dc12 --- /dev/null +++ b/test/SemaTemplate/instantiate-method.cpp @@ -0,0 +1,74 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> +class X { +public: + void f(T x); // expected-error{{argument may not have 'void' type}} + void g(T*); + + static int h(T, T); // expected-error 2{{argument may not have 'void' type}} +}; + +int identity(int x) { return x; } + +void test(X<int> *xi, int *ip, X<int(int)> *xf) { + xi->f(17); + xi->g(ip); + xf->f(&identity); + xf->g(identity); + X<int>::h(17, 25); + X<int(int)>::h(identity, &identity); +} + +void test_bad() { + X<void> xv; // expected-note{{in instantiation of template class 'class X<void>' requested here}} +} + +template<typename T, typename U> +class Overloading { +public: + int& f(T, T); // expected-note{{previous declaration is here}} + float& f(T, U); // expected-error{{functions that differ only in their return type cannot be overloaded}} +}; + +void test_ovl(Overloading<int, long> *oil, int i, long l) { + int &ir = oil->f(i, i); + float &fr = oil->f(i, l); +} + +void test_ovl_bad() { + Overloading<float, float> off; // expected-note{{in instantiation of template class 'class Overloading<float, float>' requested here}} +} + +template<typename T> +class HasDestructor { +public: + virtual ~HasDestructor() = 0; +}; + +int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but + // the code below should probably instantiate by itself. +int abstract_destructor[__is_abstract(HasDestructor<int>)? 1 : -1]; + + +template<typename T> +class Constructors { +public: + Constructors(const T&); + Constructors(const Constructors &other); +}; + +void test_constructors() { + Constructors<int> ci1(17); + Constructors<int> ci2 = ci1; +} + + +template<typename T> +struct ConvertsTo { + operator T(); +}; + +void test_converts_to(ConvertsTo<int> ci, ConvertsTo<int *> cip) { + int i = ci; + int *ip = cip; +} diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp new file mode 100644 index 000000000000..99e6b9cc06c3 --- /dev/null +++ b/test/SemaTemplate/instantiate-static-var.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T, T Divisor> +class X { +public: + static const T value = 10 / Divisor; // expected-error{{in-class initializer is not an integral constant expression}} +}; + +int array1[X<int, 2>::value == 5? 1 : -1]; +X<int, 0> xi0; // expected-note{{in instantiation of template class 'class X<int, 0>' requested here}} + + +template<typename T> +class Y { + static const T value = 0; // expected-error{{'value' can only be initialized if it is a static const integral data member}} +}; + +Y<float> fy; // expected-note{{in instantiation of template class 'class Y<float>' requested here}} diff --git a/test/SemaTemplate/instantiate-subscript.cpp b/test/SemaTemplate/instantiate-subscript.cpp new file mode 100644 index 000000000000..434d84e2b893 --- /dev/null +++ b/test/SemaTemplate/instantiate-subscript.cpp @@ -0,0 +1,26 @@ +// RUN: clang-cc -fsyntax-only -verify %s + + +struct Sub0 { + int &operator[](int); +}; + +struct Sub1 { + long &operator[](long); +}; + +struct ConvertibleToInt { + operator int(); +}; + +template<typename T, typename U, typename Result> +struct Subscript0 { + void test(T t, U u) { + Result &result = t[u]; // expected-error{{subscripted value is not}} + } +}; + +template struct Subscript0<int*, int, int&>; +template struct Subscript0<Sub0, int, int&>; +template struct Subscript0<Sub1, ConvertibleToInt, long&>; +template struct Subscript0<Sub1, Sub0, long&>; // expected-note{{instantiation}} diff --git a/test/SemaTemplate/instantiate-template-template-parm.cpp b/test/SemaTemplate/instantiate-template-template-parm.cpp new file mode 100644 index 000000000000..b158251915a0 --- /dev/null +++ b/test/SemaTemplate/instantiate-template-template-parm.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<template<typename T> class MetaFun, typename Value> +struct apply { + typedef typename MetaFun<Value>::type type; +}; + +template<class T> +struct add_pointer { + typedef T* type; +}; + +template<class T> +struct add_reference { + typedef T& type; +}; + +int i; +apply<add_pointer, int>::type ip = &i; +apply<add_reference, int>::type ir = i; +apply<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a value of type 'int'}} diff --git a/test/SemaTemplate/instantiate-try-catch.cpp b/test/SemaTemplate/instantiate-try-catch.cpp new file mode 100644 index 000000000000..074afa9d173d --- /dev/null +++ b/test/SemaTemplate/instantiate-try-catch.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s + +template<typename T> struct TryCatch0 { + void f() { + try { + } catch (T&&) { // expected-error 2{{cannot catch exceptions by rvalue reference}} + } + } +}; + +template struct TryCatch0<int&>; // okay +template struct TryCatch0<int&&>; // expected-note{{instantiation}} +template struct TryCatch0<int>; // expected-note{{instantiation}} + diff --git a/test/SemaTemplate/instantiate-type.cpp b/test/SemaTemplate/instantiate-type.cpp new file mode 100644 index 000000000000..48060c4e384e --- /dev/null +++ b/test/SemaTemplate/instantiate-type.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc -fsyntax-only %s + +int* f(int); +float *f(...); + +template<typename T> +struct X { + typedef typeof(T*) typeof_type; + typedef typeof(f(T())) typeof_expr; +}; + +int *iptr0; +float *fptr0; +X<int>::typeof_type &iptr1 = iptr0; + +X<int>::typeof_expr &iptr2 = iptr0; +X<float*>::typeof_expr &fptr1 = fptr0; diff --git a/test/SemaTemplate/instantiate-typedef.cpp b/test/SemaTemplate/instantiate-typedef.cpp new file mode 100644 index 000000000000..d30309cc86ca --- /dev/null +++ b/test/SemaTemplate/instantiate-typedef.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> +struct add_pointer { + typedef T* type; // expected-error{{'type' declared as a pointer to a reference}} +}; + +add_pointer<int>::type test1(int * ptr) { return ptr; } + +add_pointer<float>::type test2(int * ptr) { + return ptr; // expected-error{{incompatible type returning 'int *', expected 'add_pointer<float>::type' (aka 'float *')}} +} + +add_pointer<int&>::type // expected-note{{in instantiation of template class 'struct add_pointer<int &>' requested here}} \ +// expected-error {{unknown type name 'type'}} +test3(); diff --git a/test/SemaTemplate/instantiation-backtrace.cpp b/test/SemaTemplate/instantiation-backtrace.cpp new file mode 100644 index 000000000000..869662268dd2 --- /dev/null +++ b/test/SemaTemplate/instantiation-backtrace.cpp @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> struct A; // expected-note 4{{template is declared here}} + +template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}} \ +// expected-error{{implicit instantiation of undefined template 'struct A<X *>'}} + +template<typename T> struct C : B<T> { } ; // expected-note{{instantiation of template class}} + +template<typename T> struct D : C<T> { }; // expected-note{{instantiation of template class}} + +template<typename T> struct E : D<T> { }; // expected-note{{instantiation of template class}} + +template<typename T> struct F : E<T(T)> { }; // expected-note{{instantiation of template class}} + +void f() { + (void)sizeof(F<int>); // expected-note{{instantiation of template class}} +} + +typedef struct { } X; + +void g() { + (void)sizeof(B<X>); // expected-note{{in instantiation of template class 'struct B<X>' requested here}} +} + +template<typename T> +struct G : A<T>, // expected-error{{implicit instantiation of undefined template 'struct A<int>'}} + A<T*> // expected-error{{implicit instantiation of undefined template 'struct A<int *>'}} + { }; + +void h() { + (void)sizeof(G<int>); // expected-note{{in instantiation of template class 'struct G<int>' requested here}} +} diff --git a/test/SemaTemplate/instantiation-default-1.cpp b/test/SemaTemplate/instantiation-default-1.cpp new file mode 100644 index 000000000000..f0ce0d3cc669 --- /dev/null +++ b/test/SemaTemplate/instantiation-default-1.cpp @@ -0,0 +1,102 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T, typename U = const T> struct Def1; + +template<> struct Def1<int> { + void foo(); +}; + +template<> struct Def1<const int> { // expected-note{{previous definition is here}} + void bar(); +}; + +template<> struct Def1<int&> { + void wibble(); +}; + +void test_Def1(Def1<int, const int> *d1, Def1<const int, const int> *d2, + Def1<int&, int&> *d3) { + d1->foo(); + d2->bar(); + d3->wibble(); +} + +template<typename T, // FIXME: bad error message below, needs better location info + typename T2 = const T*> // expected-error{{'T2' declared as a pointer to a reference}} + struct Def2; + +template<> struct Def2<int> { + void foo(); +}; + +void test_Def2(Def2<int, int const*> *d2) { + d2->foo(); +} + +typedef int& int_ref_t; +Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}} + + +template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1<int const>'}} + +template<typename T, typename T2 = T&> struct Def3; + +template<> struct Def3<int> { + void foo(); +}; + +template<> struct Def3<int&> { + void bar(); +}; + +void test_Def3(Def3<int, int&> *d3a, Def3<int&, int&> *d3b) { + d3a->foo(); + d3b->bar(); +} + + +template<typename T, typename T2 = T[]> struct Def4; + +template<> struct Def4<int> { + void foo(); +}; + +void test_Def4(Def4<int, int[]> *d4a) { + d4a->foo(); +} + +template<typename T, typename T2 = T const[12]> struct Def5; + +template<> struct Def5<int> { + void foo(); +}; + +template<> struct Def5<int, int const[13]> { + void bar(); +}; + +void test_Def5(Def5<int, const int[12]> *d5a, Def5<int, const int[13]> *d5b) { + d5a->foo(); + d5b->bar(); +} + +template<typename R, typename Arg1, typename Arg2 = Arg1, + typename FuncType = R (*)(Arg1, Arg2)> + struct Def6; + +template<> struct Def6<int, float> { + void foo(); +}; + +template<> struct Def6<bool, int[5], float(double, double)> { + void bar(); +}; + +bool test_Def6(Def6<int, float, float> *d6a, + Def6<int, float, float, int (*)(float, float)> *d6b, + Def6<bool, int[5], float(double, double), + bool(*)(int*, float(*)(double, double))> *d6c) { + d6a->foo(); + d6b->foo(); + d6c->bar(); + return d6a == d6b; +} diff --git a/test/SemaTemplate/instantiation-default-2.cpp b/test/SemaTemplate/instantiation-default-2.cpp new file mode 100644 index 000000000000..740832c5ba39 --- /dev/null +++ b/test/SemaTemplate/instantiation-default-2.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T, T Value> struct Constant; // expected-note{{template parameter is declared here}} \ +// FIXME: bad location expected-error{{a non-type template parameter cannot have type 'float'}} + +Constant<int, 5> *c1; + +int x; +float f(int, double); + +Constant<int&, x> *c2; +Constant<int*, &x> *c3; +Constant<float (*)(int, double), f> *c4; +Constant<float (*)(int, double), &f> *c5; + +Constant<float (*)(int, int), f> *c6; // expected-error{{non-type template argument of type 'float (*)(int, double)' cannot be converted to a value of type 'float (*)(int, int)'}} + +Constant<float, 0> *c7; // expected-note{{in instantiation of default argument for 'Constant<float>' required here}} diff --git a/test/SemaTemplate/instantiation-default-3.cpp b/test/SemaTemplate/instantiation-default-3.cpp new file mode 100644 index 000000000000..521edf66f24c --- /dev/null +++ b/test/SemaTemplate/instantiation-default-3.cpp @@ -0,0 +1,21 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> struct A { }; + +template<typename T, typename U = A<T*> > + struct B : U { }; + +template<> +struct A<int*> { + void foo(); +}; + +template<> +struct A<float*> { + void bar(); +}; + +void test(B<int> *b1, B<float> *b2) { + b1->foo(); + b2->bar(); +} diff --git a/test/SemaTemplate/instantiation-depth.cpp b/test/SemaTemplate/instantiation-depth.cpp new file mode 100644 index 000000000000..522c4e1cbb5c --- /dev/null +++ b/test/SemaTemplate/instantiation-depth.cpp @@ -0,0 +1,9 @@ +// RUN: clang-cc -fsyntax-only -ftemplate-depth=5 -verify %s + +template<typename T> struct X : X<T*> { }; // expected-error{{recursive template instantiation exceeded maximum depth of 5}} \ +// expected-note{{use -ftemplate-depth-N to increase recursive template instantiation depth}} \ +// expected-note 5 {{instantiation of template class}} + +void test() { + (void)sizeof(X<int>); // expected-note {{instantiation of template class}} +} diff --git a/test/SemaTemplate/metafun-apply.cpp b/test/SemaTemplate/metafun-apply.cpp new file mode 100644 index 000000000000..7bc971f24b59 --- /dev/null +++ b/test/SemaTemplate/metafun-apply.cpp @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct add_pointer { + template<typename T> + struct apply { + typedef T* type; + }; +}; + +struct add_reference { + template<typename T> + struct apply { + typedef T& type; // expected-error{{cannot form a reference to 'void'}} + }; +}; + +struct bogus { + struct apply { + typedef int type; + }; +}; + +template<typename MetaFun, typename T> +struct apply1 { + typedef typename MetaFun::template apply<T>::type type; // expected-note{{in instantiation of template class 'struct add_reference::apply<void>' requested here}} \ + // expected-error{{'apply' following the 'template' keyword does not refer to a template}} \ + // FIXME: expected-error{{type 'MetaFun::template apply<int>' cannot be used prior to '::' because it has no members}} +}; + +int i; +apply1<add_pointer, int>::type ip = &i; +apply1<add_reference, int>::type ir = i; +apply1<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a value of type 'int'}} + +void test() { + apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} \ + // FIXME: expected-error{{unexpected type name 'type': expected expression}} + + apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} \ + // FIXME: expected-error{{unexpected type name 'type': expected expression}} +} + + diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp new file mode 100644 index 000000000000..a5aa2dcb527a --- /dev/null +++ b/test/SemaTemplate/nested-name-spec-template.cpp @@ -0,0 +1,61 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace N { + namespace M { + template<typename T> struct Promote; + + template<> struct Promote<short> { + typedef int type; + }; + + template<> struct Promote<int> { + typedef int type; + }; + + template<> struct Promote<float> { + typedef double type; + }; + + Promote<short>::type *ret_intptr(int* ip) { return ip; } + Promote<int>::type *ret_intptr2(int* ip) { return ip; } + } + + M::Promote<int>::type *ret_intptr3(int* ip) { return ip; } + M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; } +} + +N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; } +::N::M::Promote<int>::type *ret_intptr6(int* ip) { return ip; } + + +N::M::template; // expected-error{{expected template name after 'template' keyword in nested name specifier}} \ + // expected-error{{expected unqualified-id}} + +N::M::template Promote; // expected-error{{expected '<' after 'template Promote' in nested name specifier}} \ +// expected-error{{C++ requires a type specifier for all declarations}} + +namespace N { + template<typename T> struct A; + + template<> + struct A<int> { + struct X; + }; + + struct B; +} + +struct ::N::A<int>::X { + int foo; +}; + +#if 0 +// FIXME: the following crashes the parser, because Sema has no way to +// communicate that the "dependent" template-name N::template B doesn't +// actually refer to a template. +template<typename T> +struct TestA { + typedef typename N::template B<T>::type type; // xpected-error{{'B' following the 'template' keyword does not refer to a template}} + // FIXME: should show what B *does* refer to. +}; +#endif diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp new file mode 100644 index 000000000000..bd9e89f76a0a --- /dev/null +++ b/test/SemaTemplate/nested-template.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only %s + +class A; + +class S { +public: + template<typename T> struct A { + struct Nested { + typedef T type; + }; + }; +}; + +int i; +S::A<int>::Nested::type *ip = &i; + diff --git a/test/SemaTemplate/qualified-names-diag.cpp b/test/SemaTemplate/qualified-names-diag.cpp new file mode 100644 index 000000000000..c875332905fb --- /dev/null +++ b/test/SemaTemplate/qualified-names-diag.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +namespace std { + template<typename T> class vector { }; +} + +typedef int INT; +typedef float Real; + +void test() { + using namespace std; + + std::vector<INT> v1; + vector<Real> v2; + v1 = v2; // expected-error{{no viable overloaded '='}} +} diff --git a/test/SemaTemplate/right-angle-brackets-0x.cpp b/test/SemaTemplate/right-angle-brackets-0x.cpp new file mode 100644 index 000000000000..57b6ee22410c --- /dev/null +++ b/test/SemaTemplate/right-angle-brackets-0x.cpp @@ -0,0 +1,22 @@ +// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s +template<typename T> struct X; +template<int I> struct Y; + +X<X<int>> *x1; + +Y<(1 >> 2)> *y1; +Y<1 >> 2> *y2; // FIXME: expected-error{{expected unqualified-id}} + +X<X<X<X<X<int>>>>> *x2; + +template<> struct X<int> { }; +typedef X<int> X_int; +struct Z : X_int { }; + +void f(const X<int> x) { + (void)reinterpret_cast<X<int>>(x); // expected-error{{reinterpret_cast from}} + (void)reinterpret_cast<X<X<X<int>>>>(x); // expected-error{{reinterpret_cast from}} + + X<X<int>> *x1; +} + diff --git a/test/SemaTemplate/right-angle-brackets-98.cpp b/test/SemaTemplate/right-angle-brackets-98.cpp new file mode 100644 index 000000000000..764bb7bae073 --- /dev/null +++ b/test/SemaTemplate/right-angle-brackets-98.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -std=c++98 -verify %s +template<typename T> struct X; +template<int I> struct Y; + +X<X<int> > *x1; +X<X<int>> *x2; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + +X<X<X<X<int>> // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + >> *x3; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} + +Y<(1 >> 2)> *y1; +Y<1 >> 2> *y2; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++0x}} diff --git a/test/SemaTemplate/temp.cpp b/test/SemaTemplate/temp.cpp new file mode 100644 index 000000000000..8be4739a741b --- /dev/null +++ b/test/SemaTemplate/temp.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + + +// p3 +template<typename T> int foo(T), bar(T, T); // expected-error{{single entity}} diff --git a/test/SemaTemplate/temp_arg.cpp b/test/SemaTemplate/temp_arg.cpp new file mode 100644 index 000000000000..e873b8e2a61d --- /dev/null +++ b/test/SemaTemplate/temp_arg.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T, + int I, + template<typename> class TT> + class A; // expected-note 2 {{template is declared here}} + +template<typename> class X; + +A<int, 0, X> * a1; + +A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}} +A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}} diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp new file mode 100644 index 000000000000..fe18fe657c16 --- /dev/null +++ b/test/SemaTemplate/temp_arg_nontype.cpp @@ -0,0 +1,124 @@ +// RUN: clang-cc -fsyntax-only -std=c++98 -verify %s +template<int N> struct A; // expected-note 5{{template parameter is declared here}} + +A<0> *a0; + +A<int()> *a1; // expected-error{{template argument for non-type template parameter is treated as type 'int (void)'}} + +A<int> *a2; // expected-error{{template argument for non-type template parameter must be an expression}} + +A<1 >> 2> *a3; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++0x}} + +// C++ [temp.arg.nontype]p5: +A<A> *a4; // expected-error{{must have an integral or enumeration type}} \ + // FIXME: the error message above is a bit lame + +enum E { Enumerator = 17 }; +A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}} +template<E Value> struct A1; // expected-note{{template parameter is declared here}} +A1<Enumerator> *a6; // okay +A1<17> *a7; // expected-error{{non-type template argument of type 'int' cannot be converted to a value of type 'enum E'}} + +const long LongValue = 12345678; +A<LongValue> *a8; +const short ShortValue = 17; +A<ShortValue> *a9; + +int f(int); +A<f(17)> *a10; // expected-error{{non-type template argument of type 'int' is not an integral constant expression}} + +class X { +public: + X(); + X(int, int); + operator int() const; +}; +A<X(17, 42)> *a11; // expected-error{{non-type template argument of type 'class X' must have an integral or enumeration type}} + +template<X const *Ptr> struct A2; + +X *X_ptr; +X an_X; +X array_of_Xs[10]; +A2<X_ptr> *a12; +A2<array_of_Xs> *a13; +A2<&an_X> *a13_2; +A2<(&an_X)> *a13_3; // expected-error{{non-type template argument cannot be surrounded by parentheses}} + +float f(float); + +float g(float); +double g(double); + +int h(int); +float h2(float); + +template<int fp(int)> struct A3; // expected-note 2{{template parameter is declared here}} +A3<h> *a14_1; +A3<&h> *a14_2; +A3<f> *a14_3; +A3<&f> *a14_4; +A3<h2> *a14_6; // expected-error{{non-type template argument of type 'float (*)(float)' cannot be converted to a value of type 'int (*)(int)'}} +A3<g> *a14_7; // expected-error{{non-type template argument of type '<overloaded function type>' cannot be converted to a value of type 'int (*)(int)'}} +// FIXME: the first error includes the string <overloaded function +// type>, which makes Doug slightly unhappy. + + +struct Y { } y; + +volatile X * X_volatile_ptr; +template<X const &AnX> struct A4; // expected-note 2{{template parameter is declared here}} +A4<an_X> *a15_1; // okay +A4<*X_volatile_ptr> *a15_2; // expected-error{{reference binding of non-type template parameter of type 'class X const &' to template argument of type 'class X volatile' ignores qualifiers}} +A4<y> *15_3; // expected-error{{non-type template parameter of reference type 'class X const &' cannot bind to template argument of type 'struct Y'}} \ + // FIXME: expected-error{{expected unqualified-id}} + +template<int (&fr)(int)> struct A5; // expected-note 2{{template parameter is declared here}} +A5<h> *a16_1; +A5<f> *a16_3; +A5<h2> *a16_6; // expected-error{{non-type template argument of type 'float (float)' cannot be converted to a value of type 'int (&)(int)'}} +A5<g> *a14_7; // expected-error{{non-type template argument of type '<overloaded function type>' cannot be converted to a value of type 'int (&)(int)'}} +// FIXME: the first error includes the string <overloaded function +// type>, which makes Doug slightly unhappy. + +struct Z { + int foo(int); + float bar(float); + int bar(int); + double baz(double); + + int int_member; + float float_member; +}; +template<int (Z::*pmf)(int)> struct A6; // expected-note{{template parameter is declared here}} +A6<&Z::foo> *a17_1; +A6<&Z::bar> *a17_2; +A6<&Z::baz> *a17_3; // expected-error{{non-type template argument of type 'double (struct Z::*)(double)' cannot be converted to a value of type 'int (struct Z::*)(int)'}} + + +template<int Z::*pm> struct A7; // expected-note{{template parameter is declared here}} +template<int Z::*pm> struct A7c; +A7<&Z::int_member> *a18_1; +A7c<&Z::int_member> *a18_2; +A7<&Z::float_member> *a18_3; // expected-error{{non-type template argument of type 'float struct Z::*' cannot be converted to a value of type 'int struct Z::*'}} +A7c<(&Z::int_member)> *a18_3; // expected-error{{non-type template argument cannot be surrounded by parentheses}} + +template<unsigned char C> struct Overflow; // expected-note{{template parameter is declared here}} + +Overflow<5> *overflow1; // okay +Overflow<256> *overflow2; // expected-error{{non-type template argument value '256' is too large for template parameter of type 'unsigned char'}} + + +template<unsigned> struct Signedness; // expected-note{{template parameter is declared here}} +Signedness<10> *signedness1; // okay +Signedness<-10> *signedness2; // expected-error{{non-type template argument provides negative value '-10' for unsigned template parameter of type 'unsigned int'}} + +// Check canonicalization of template arguments. +template<int (*)(int, int)> struct FuncPtr0; +int func0(int, int); +extern FuncPtr0<&func0> *fp0; +template<int (*)(int, int)> struct FuncPtr0; +extern FuncPtr0<&func0> *fp0; +int func0(int, int); +extern FuncPtr0<&func0> *fp0; + diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp new file mode 100644 index 000000000000..a5e9f75fa77a --- /dev/null +++ b/test/SemaTemplate/temp_arg_template.cpp @@ -0,0 +1,38 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<template<typename T> class X> struct A; // expected-note 2{{previous template template parameter is here}} + +template<template<typename T, int I> class X> struct B; // expected-note{{previous template template parameter is here}} + +template<template<int I> class X> struct C; // expected-note{{previous non-type template parameter with type 'int' is here}} + +template<class> struct X; // expected-note{{too few template parameters in template template argument}} +template<int N> struct Y; // expected-note{{template parameter has a different kind in template argument}} +template<long N> struct Ylong; // expected-note{{template non-type parameter has a different type 'long' in template argument}} + +namespace N { + template<class> struct Z; +} +template<class, class> struct TooMany; // expected-note{{too many template parameters in template template argument}} + + +A<X> *a1; +A<N::Z> *a2; +A< ::N::Z> *a3; + +A<Y> *a4; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} +A<TooMany> *a5; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} +B<X> *a6; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} +C<Y> *a7; +C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} + +template<typename T> void f(int); + +// FIXME: we're right to provide an error message, but it should say +// that we need a class template. We won't get this right until name +// lookup of 'f' returns a TemplateDecl. +A<f> *a9; // expected-error{{template argument for template template parameter must be a template}} + +// FIXME: The code below is ill-formed, because of the evil digraph '<:'. +// We should provide a much better error message than we currently do. +// A<::N::Z> *a10; diff --git a/test/SemaTemplate/temp_arg_type.cpp b/test/SemaTemplate/temp_arg_type.cpp new file mode 100644 index 000000000000..b322dae98b90 --- /dev/null +++ b/test/SemaTemplate/temp_arg_type.cpp @@ -0,0 +1,24 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> class A; // expected-note 2 {{template parameter is declared here}} + +// [temp.arg.type]p1 +A<0> *a1; // expected-error{{template argument for template type parameter must be a type}} + +A<A> *a2; // expected-error{{template argument for template type parameter must be a type}} + +A<int> *a3; +A<int()> *a4; +A<int(float)> *a5; +A<A<int> > *a6; + +// [temp.arg.type]p2 +void f() { + class X { }; + A<X> * a = 0; // expected-error{{template argument uses local type 'class X'}} +} + +struct { int x; } Unnamed; // expected-note{{unnamed type used in template argument was declared here}} +A<__typeof__(Unnamed)> *a7; // expected-error{{template argument uses unnamed type}} + +// FIXME: [temp.arg.type]p3. The check doesn't really belong here (it +// belongs somewhere in the template instantiation section). diff --git a/test/SemaTemplate/temp_class_spec.cpp b/test/SemaTemplate/temp_class_spec.cpp new file mode 100644 index 000000000000..df652b5ba38d --- /dev/null +++ b/test/SemaTemplate/temp_class_spec.cpp @@ -0,0 +1,20 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> +struct is_pointer { + static const bool value = false; +}; + +template<typename T> +struct is_pointer<T*> { + static const bool value = true; +}; + +template<typename T> +struct is_pointer<const T*> { + static const bool value = true; +}; + +int array0[is_pointer<int>::value? -1 : 1]; +int array1[is_pointer<int*>::value? 1 : -1]; +int array2[is_pointer<const int*>::value? 1 : -1]; // expected-error{{partial ordering}} \ +// expected-error{{negative}} diff --git a/test/SemaTemplate/temp_explicit.cpp b/test/SemaTemplate/temp_explicit.cpp new file mode 100644 index 000000000000..0292964a1a76 --- /dev/null +++ b/test/SemaTemplate/temp_explicit.cpp @@ -0,0 +1,111 @@ +// RUN: clang-cc -fsyntax-only -pedantic -verify %s +// +// Tests explicit instantiation of templates. +template<typename T, typename U = T> class X0 { }; + +namespace N { + template<typename T, typename U = T> class X1 { }; +} + +// Check the syntax of explicit instantiations. +template class X0<int, float>; +template class X0<int>; // expected-note{{previous}} + +template class N::X1<int>; +template class ::N::X1<int, float>; + +using namespace N; +template class X1<float>; + +// Check for some bogus syntax that probably means that the user +// wanted to write an explicit specialization, but forgot the '<>' +// after 'template'. +template class X0<double> { }; // expected-error{{explicit specialization}} + +// Check for explicit instantiations that come after other kinds of +// instantiations or declarations. +template class X0<int, int>; // expected-error{{duplicate}} + +template<> class X0<char> { }; // expected-note{{previous}} +template class X0<char>; // expected-warning{{ignored}} + +void foo(X0<short>) { } +template class X0<short>; + +// Check that explicit instantiations actually produce definitions. We +// determine whether this happens by placing semantic errors in the +// definition of the template we're instantiating. +template<typename T> struct X2; // expected-note{{declared here}} + +template struct X2<float>; // expected-error{{undefined template}} + +template<typename T> +struct X2 { + void f0(T*); // expected-error{{pointer to a reference}} +}; + +template struct X2<int>; // okay +template struct X2<int&>; // expected-note{{in instantiation of}} + +// Check that explicit instantiations instantiate member classes. +template<typename T> struct X3 { + struct Inner { + void f(T*); // expected-error{{pointer to a reference}} + }; +}; + +void f1(X3<int&>); // okay, Inner, not instantiated + +template struct X3<int&>; // expected-note{{instantiation}} + +template<typename T> struct X4 { + struct Inner { + struct VeryInner { + void f(T*); // expected-error 2{{pointer to a reference}} + }; + }; +}; + +void f2(X4<int&>); // okay, Inner, not instantiated +void f3(X4<int&>::Inner); // okay, Inner::VeryInner, not instantiated + +template struct X4<int&>; // expected-note{{instantiation}} +template struct X4<float&>; // expected-note{{instantiation}} + +// Check explicit instantiation of member classes +namespace N2 { + +template<typename T> +struct X5 { + struct Inner1 { + void f(T&); + }; + + struct Inner2 { + struct VeryInner { + void g(T*); // expected-error 2{{pointer to a reference}} + }; + }; +}; + +} + +template struct N2::X5<void>::Inner2; + +using namespace N2; +template struct X5<int&>::Inner2; // expected-note{{instantiation}} + +void f4(X5<float&>::Inner2); +template struct X5<float&>::Inner2; // expected-note{{instantiation}} + +namespace N3 { + template struct N2::X5<int>::Inner2; +} + +struct X6 { + struct Inner { // expected-note{{here}} + void f(); + }; +}; + +template struct X6::Inner; // expected-error{{non-templated}} diff --git a/test/SemaTemplate/temp_explicit_cxx0x.cpp b/test/SemaTemplate/temp_explicit_cxx0x.cpp new file mode 100644 index 000000000000..7045afc3032f --- /dev/null +++ b/test/SemaTemplate/temp_explicit_cxx0x.cpp @@ -0,0 +1,24 @@ +// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s +namespace N1 { + + template<typename T> struct X0 { }; // expected-note{{here}} + + namespace Inner { + template<typename T> struct X1 { }; + } + + template struct X0<int>; + template struct Inner::X1<int>; +} + +template<typename T> struct X2 { }; // expected-note{{here}} + +template struct ::N1::Inner::X1<float>; + +namespace N2 { + using namespace N1; + + template struct X0<double>; // expected-error{{not in a namespace enclosing}} + + template struct X2<float>; // expected-error{{at global scope}} +} diff --git a/test/SemaTemplate/temp_param.cpp b/test/SemaTemplate/temp_param.cpp new file mode 100644 index 000000000000..c042f0849a04 --- /dev/null +++ b/test/SemaTemplate/temp_param.cpp @@ -0,0 +1,90 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class X; + +// C++ [temp.param]p4 +typedef int INT; +enum E { enum1, enum2 }; +template<int N> struct A1; +template<INT N, INT M> struct A2; +template<enum E x, E y> struct A3; +template<int &X> struct A4; +template<int *Ptr> struct A5; +template<int (&f)(int, int)> struct A6; +template<int (*fp)(float, double)> struct A7; +template<int X::*pm> struct A8; +template<float (X::*pmf)(float, int)> struct A9; +template<typename T, T x> struct A10; + +template<float f> struct A11; // expected-error{{a non-type template parameter cannot have type 'float'}} + +template<void *Ptr> struct A12; // expected-error{{a non-type template parameter cannot have type 'void *'}} + +// C++ [temp.param]p8 +template<int X[10]> struct A5; +template<int f(float, double)> struct A7; + +// C++ [temp.param]p11: +template<typename> struct Y1; // expected-note{{too few template parameters in template template argument}} +template<typename, int> struct Y2; + +template<class T1 = int, // expected-note{{previous default template argument defined here}} + class T2> // expected-error{{template parameter missing a default argument}} + class B1; + +template<template<class> class = Y1, // expected-note{{previous default template argument defined here}} + template<class> class> // expected-error{{template parameter missing a default argument}} + class B1t; + +template<int N = 5, // expected-note{{previous default template argument defined here}} + int M> // expected-error{{template parameter missing a default argument}} + class B1n; + +// Check for bogus template parameter shadow warning. +template<template<class T> class, + template<class T> class> + class B1noshadow; + +// C++ [temp.param]p10: +template<class T1, class T2 = int> class B2; +template<class T1 = int, class T2> class B2; + +template<template<class, int> class, template<class> class = Y1> class B2t; +template<template<class, int> class = Y2, template<class> class> class B2t; + +template<int N, int M = 5> class B2n; +template<int N = 5, int M> class B2n; + +// C++ [temp.param]p12: +template<class T1, + class T2 = int> // expected-note{{previous default template argument defined here}} + class B3; +template<class T1, typename T2> class B3; +template<class T1, + typename T2 = float> // expected-error{{template parameter redefines default argument}} + class B3; + +template<template<class, int> class, + template<class> class = Y1> // expected-note{{previous default template argument defined here}} + class B3t; + +template<template<class, int> class, template<class> class> class B3t; + +template<template<class, int> class, + template<class> class = Y1> // expected-error{{template parameter redefines default argument}} + class B3t; + +template<int N, + int M = 5> // expected-note{{previous default template argument defined here}} + class B3n; + +template<int N, int M> class B3n; + +template<int N, + int M = 7> // expected-error{{template parameter redefines default argument}} + class B3n; + +// Check validity of default arguments +template<template<class, int> class // expected-note{{previous template template parameter is here}} + = Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} + class C1; diff --git a/test/SemaTemplate/typename-specifier-2.cpp b/test/SemaTemplate/typename-specifier-2.cpp new file mode 100644 index 000000000000..99e628523158 --- /dev/null +++ b/test/SemaTemplate/typename-specifier-2.cpp @@ -0,0 +1,30 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename MetaFun, typename T> +struct bind_metafun { + typedef typename MetaFun::template apply<T> type; +}; + +struct add_pointer { + template<typename T> + struct apply { + typedef T* type; + }; +}; + +int i; +// FIXME: if we make the declarator below a pointer (e.g., with *ip), +// the error message isn't so good because we don't get the handy +// 'aka' telling us that we're dealing with an int**. Should we fix +// getDesugaredType to dig through pointers and such? +bind_metafun<add_pointer, int>::type::type ip = &i; +bind_metafun<add_pointer, float>::type::type fp = &i; // expected-error{{incompatible type initializing 'int *', expected 'bind_metafun<add_pointer, float>::type::type' (aka 'float *')}} + + +template<typename T> +struct extract_type_type { + typedef typename T::type::type t; +}; + +double d; +extract_type_type<bind_metafun<add_pointer, double> >::t dp = &d; diff --git a/test/SemaTemplate/typename-specifier.cpp b/test/SemaTemplate/typename-specifier.cpp new file mode 100644 index 000000000000..d3fca3eacad5 --- /dev/null +++ b/test/SemaTemplate/typename-specifier.cpp @@ -0,0 +1,74 @@ +// RUN: clang-cc -fsyntax-only -verify %s +namespace N { + struct A { + typedef int type; + }; + + struct B { + }; + + struct C { + struct type { }; + int type; // expected-note 2{{referenced member 'type' is declared here}} + }; +} + +int i; + +typename N::A::type *ip1 = &i; +typename N::B::type *ip2 = &i; // expected-error{{ no type named 'type' in 'B'}} +typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}} + +void test(double d) { + typename N::A::type f(typename N::A::type(a)); // expected-warning{{parentheses were disambiguated as a function declarator}} + int five = f(5); + + using namespace N; + for (typename A::type i = 0; i < 10; ++i) + five += 1; + + const typename N::A::type f2(d); +} + +namespace N { + template<typename T> + struct X { + typedef typename T::type type; // expected-error 2{{no type named 'type' in 'B'}} \ + // FIXME: location info for error above isn't very good \ + // expected-error 2{{typename specifier refers to non-type member 'type'}} \ + // expected-error{{type 'int' cannot be used prior to '::' because it has no members}} + }; +} + +N::X<N::A>::type *ip4 = &i; +N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::B>' requested here}} \ +// expected-error{{unknown type name 'type'}} +N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::C>' requested here}} \ +// expected-error{{unknown type name 'type'}} + +N::X<int>::type fail1; // expected-note{{in instantiation of template class 'struct N::X<int>' requested here}} \ +// expected-error{{unknown type name 'type'}} + +template<typename T> +struct Y { + typedef typename N::X<T>::type *type; // expected-note{{in instantiation of template class 'struct N::X<struct B>' requested here}} \ + // expected-note{{in instantiation of template class 'struct N::X<struct C>' requested here}} +}; + +struct A { + typedef int type; +}; + +struct B { +}; + +struct C { + struct type { }; + int type; // expected-note{{referenced member 'type' is declared here}} +}; + +::Y<A>::type ip7 = &i; +::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'struct Y<struct B>' requested here}} \ +// expected-error{{unknown type name 'type'}} +::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'struct Y<struct C>' requested here}} \ +// expected-error{{unknown type name 'type'}} diff --git a/test/TestRunner.sh b/test/TestRunner.sh new file mode 100755 index 000000000000..bb20728578c1 --- /dev/null +++ b/test/TestRunner.sh @@ -0,0 +1,134 @@ +#!/bin/sh +# +# TestRunner.sh - This script is used to run arbitrary unit tests. Unit +# tests must contain the command used to run them in the input file, starting +# immediately after a "RUN:" string. +# +# This runner recognizes and replaces the following strings in the command: +# +# %s - Replaced with the input name of the program, or the program to +# execute, as appropriate. +# %S - Replaced with the directory where the input file resides +# %prcontext - prcontext.tcl script +# %t - temporary file name (derived from testcase name) +# + +FILENAME=$1 +TESTNAME=$1 +SUBST=$1 +FILEDIR=`dirname $TESTNAME` + +OUTPUT=Output/$1.out + +# create the output directory if it does not already exist +mkdir -p `dirname $OUTPUT` > /dev/null 2>&1 + +if test $# != 1; then + # If more than one parameter is passed in, there must be three parameters: + # The filename to read from (already processed), the command used to execute, + # and the file to output to. + SUBST=$2 + OUTPUT=$3 + TESTNAME=$3 +fi + +ulimit -t 40 + +# Verify the script contains a run line. +grep -q 'RUN:' $FILENAME || ( + echo "******************** TEST '$TESTNAME' HAS NO RUN LINE! ********************" + exit 1 +) + +# Run under valgrind if the VG environment variable has been set. +CLANG=$CLANG +if [ ! -n "$CLANG" ]; then + CLANG="clang" +fi + +# Resolve the path, and Make sure $CLANG actually exists; otherwise +# ensuing failures are non-obvious. +CLANG=$(which "$CLANG") +if [ -z $CLANG ]; then + echo "Couldn't find 'clang' program, try setting CLANG in your environment" + exit 1 +fi + +if [ -n "$VG" ]; then + rm -f $OUTPUT.vg + CLANG="valgrind --leak-check=full --quiet --log-file=$OUTPUT.vg $CLANG" +fi + +# Assuming $CLANG is correct, use it to derive clang-cc. We expect to +# be looking in a build directory, so just add '-cc'. +CLANGCC=$CLANGCC +if [ ! -n "$CLANGCC" ]; then + CLANGCC="$CLANG-cc" +fi + +# Try to sanity check $CLANGCC too +CLANGCC=$(which "$CLANGCC") +# If that failed, ask clang. +if [ -z "$CLANGCC" ]; then + CLANGCC=$($CLANG -print-prog-name=clang-cc) +fi +if [ -z "$CLANGCC" ]; then + echo "Couldn't find 'clang-cc' program, make sure clang is found in your build directory" + exit 1 +fi + +SCRIPT=$OUTPUT.script +TEMPOUTPUT=$OUTPUT.tmp +grep 'RUN:' $FILENAME | \ + sed -e "s|^.*RUN:\(.*\)$|\1|g" \ + -e "s| clang | $CLANG |g" \ + -e "s| clang-cc | $CLANGCC |g" \ + -e "s|%s|$SUBST|g" \ + -e "s|%S|$FILEDIR|g" \ + -e "s|%prcontext|prcontext.tcl|g" \ + -e "s|%t|$TEMPOUTPUT|g" > $SCRIPT + +IS_XFAIL=0 +if (grep -q XFAIL $FILENAME); then + IS_XFAIL=1 + printf "XFAILED '$TESTNAME': " + grep XFAIL $FILENAME +fi + +/bin/sh $SCRIPT > $OUTPUT 2>&1 +SCRIPT_STATUS=$? + +if [ -n "$VG" ]; then + [ ! -s $OUTPUT.vg ] + VG_STATUS=$? +else + VG_STATUS=0 +fi + +if [ $IS_XFAIL -ne 0 ]; then + if [ $SCRIPT_STATUS -ne 0 ]; then + SCRIPT_STATUS=0 + else + SCRIPT_STATUS=1 + fi +fi + +if [ $SCRIPT_STATUS -ne 0 -o $VG_STATUS -ne 0 ]; then + echo "******************** TEST '$TESTNAME' FAILED! ********************" + echo "Command: " + cat $SCRIPT + if [ $SCRIPT_STATUS -eq 0 ]; then + echo "Output:" + elif [ $IS_XFAIL -ne 0 ]; then + echo "Incorrect Output (Expected Failure):" + else + echo "Incorrect Output:" + fi + cat $OUTPUT + if [ $VG_STATUS -ne 0 ]; then + echo "Valgrind Output:" + cat $OUTPUT.vg + fi + echo "******************** TEST '$TESTNAME' FAILED! ********************" + exit 1 +fi |