diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-03-03 17:28:16 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-03-03 17:28:16 +0000 |
commit | df90325d4c0a65ee64d2dae3ed9b5b34f7418533 (patch) | |
tree | e1a885aadfd80632f5bd70d4bd2d37e715e35a79 /test | |
parent | fd035e6496665b1f1197868e21cb0a4594e8db6e (diff) | |
download | FreeBSD-src-df90325d4c0a65ee64d2dae3ed9b5b34f7418533.zip FreeBSD-src-df90325d4c0a65ee64d2dae3ed9b5b34f7418533.tar.gz |
Update clang to 97654.
Diffstat (limited to 'test')
162 files changed, 4047 insertions, 233 deletions
diff --git a/test/ASTMerge/Inputs/category1.m b/test/ASTMerge/Inputs/category1.m new file mode 100644 index 0000000..ade1c6c --- /dev/null +++ b/test/ASTMerge/Inputs/category1.m @@ -0,0 +1,25 @@ +@interface I1 +@end + +// Matching category +@interface I1 (Cat1) +- (int)method0; +@end + +// Matching class extension +@interface I1 () +- (int)method1; +@end + +// Mismatched category +@interface I1 (Cat2) +- (int)method2; +@end + +@interface I2 +@end + +// Mismatched class extension +@interface I2 () +- (int)method3; +@end diff --git a/test/ASTMerge/Inputs/category2.m b/test/ASTMerge/Inputs/category2.m new file mode 100644 index 0000000..f66c208 --- /dev/null +++ b/test/ASTMerge/Inputs/category2.m @@ -0,0 +1,27 @@ +typedef int Int; + +@interface I1 +@end + +// Matching category +@interface I1 (Cat1) +- (Int)method0; +@end + +// Matching class extension +@interface I1 () +- (Int)method1; +@end + +// Mismatched category +@interface I1 (Cat2) +- (float)method2; +@end + +@interface I2 +@end + +// Mismatched class extension +@interface I2 () +- (float)method3; +@end diff --git a/test/ASTMerge/Inputs/exprs1.c b/test/ASTMerge/Inputs/exprs1.c new file mode 100644 index 0000000..1c268da --- /dev/null +++ b/test/ASTMerge/Inputs/exprs1.c @@ -0,0 +1,10 @@ +// Matching +enum E0 { + E0_Val0 = 'a', + E0_Val1 = (17), + E0_Val2 = (1 << 2), + E0_Val3 = E0_Val2, + E0_Val4 = sizeof(int*), + E0_Val5 = (unsigned int)-1 +}; + diff --git a/test/ASTMerge/Inputs/exprs2.c b/test/ASTMerge/Inputs/exprs2.c new file mode 100644 index 0000000..1c268da --- /dev/null +++ b/test/ASTMerge/Inputs/exprs2.c @@ -0,0 +1,10 @@ +// Matching +enum E0 { + E0_Val0 = 'a', + E0_Val1 = (17), + E0_Val2 = (1 << 2), + E0_Val3 = E0_Val2, + E0_Val4 = sizeof(int*), + E0_Val5 = (unsigned int)-1 +}; + diff --git a/test/ASTMerge/Inputs/interface1.m b/test/ASTMerge/Inputs/interface1.m index 1aa1c3b..7e9935d 100644 --- a/test/ASTMerge/Inputs/interface1.m +++ b/test/ASTMerge/Inputs/interface1.m @@ -1,7 +1,81 @@ // Matches -@interface I1 +@interface I1 { + int ivar1; +} @end // Matches -@interface I2 : I1 +@interface I2 : I1 { + float ivar2; +} +@end + +// Ivar mismatch +@interface I3 { + int ivar1; + int ivar2; +} +@end + +// Superclass mismatch +@interface I4 : I2 { +} +@end + +// Methods match +@interface I5 +- (int)foo; ++ (float)bar; +@end + +// Method mismatch +@interface I6 +- (int)foo; ++ (int)foo; +@end + +// Method mismatch +@interface I7 +- (int)foo; ++ (int)bar:(int)x; +@end + +// Method mismatch +@interface I8 +- (int)foo; ++ (int)bar:(float)x; +@end + +// Matching protocol +@protocol P0 ++ (int)foo; +- (int)bar:(float)x; +@end + +// Protocol with mismatching method +@protocol P1 ++ (int)foo; +- (int)bar:(float)x; +@end + +// Interface with protocol +@interface I9 <P0> ++ (int)foo; +- (int)bar:(float)x; +@end + +// Protocol with protocol +@protocol P2 <P0> +- (float)wibble:(int)a1 second:(int)a2; +@end + +// Forward-declared interfaces +@class I10, I11; +@interface I12 +@end + +// Forward-declared protocols +@protocol P3, P5; +@protocol P4 +- (double)honk:(int)a; @end diff --git a/test/ASTMerge/Inputs/interface2.m b/test/ASTMerge/Inputs/interface2.m index 1aa1c3b..bef7fb8 100644 --- a/test/ASTMerge/Inputs/interface2.m +++ b/test/ASTMerge/Inputs/interface2.m @@ -1,7 +1,80 @@ // Matches -@interface I1 +@interface I1 { + int ivar1; +} @end // Matches -@interface I2 : I1 +@interface I2 : I1 { + float ivar2; +} +@end + +// Ivar mismatch +@interface I3 { + int ivar1; + float ivar2; +} +@end + +// Superclass mismatch +@interface I4 : I1 { +} +@end + +// Methods match +@interface I5 ++ (float)bar; +- (int)foo; +@end + +// Method mismatch +@interface I6 ++ (float)foo; +@end + +// Method mismatch +@interface I7 +- (int)foo; ++ (int)bar:(float)x; +@end + +// Method mismatch +@interface I8 +- (int)foo; ++ (int)bar:(float)x, ...; +@end + +// Matching protocol +@protocol P0 ++ (int)foo; +- (int)bar:(float)x; +@end + +// Protocol with mismatching method +@protocol P1 ++ (int)foo; +- (int)bar:(double)x; +@end + +// Interface with protocol +@interface I9 <P0> ++ (int)foo; +- (int)bar:(float)x; +@end + +// Protocol with protocol +@protocol P2 <P0> +- (float)wibble:(int)a1 second:(int)a2; +@end + +// Forward-declared interface +@class I12, I10; +@interface I11 +@end + +// Forward-declared protocols +@protocol P3, P4; +@protocol P5 +- (double)honk:(int)a; @end diff --git a/test/ASTMerge/Inputs/namespace1.cpp b/test/ASTMerge/Inputs/namespace1.cpp new file mode 100644 index 0000000..1ff84f31 --- /dev/null +++ b/test/ASTMerge/Inputs/namespace1.cpp @@ -0,0 +1,17 @@ +// Merge success +namespace N1 { + int x; +} + +// Merge multiple namespaces +namespace N2 { + extern int x; +} +namespace N2 { + extern float y; +} + +// Merge namespace with conflict +namespace N3 { + extern float z; +} diff --git a/test/ASTMerge/Inputs/namespace2.cpp b/test/ASTMerge/Inputs/namespace2.cpp new file mode 100644 index 0000000..80429f7 --- /dev/null +++ b/test/ASTMerge/Inputs/namespace2.cpp @@ -0,0 +1,17 @@ +// Merge success +namespace N1 { + extern int x0; +} + +// Merge multiple namespaces +namespace N2 { + extern int x; +} +namespace N2 { + extern float y; +} + +// Merge namespace with conflict +namespace N3 { + extern double z; +} diff --git a/test/ASTMerge/Inputs/property1.m b/test/ASTMerge/Inputs/property1.m new file mode 100644 index 0000000..37887a3 --- /dev/null +++ b/test/ASTMerge/Inputs/property1.m @@ -0,0 +1,12 @@ +// Matching properties +@interface I1 { +} +- (int)getProp2; +- (void)setProp2:(int)value; +@end + +// Mismatched property +@interface I2 +@property (readonly) float Prop1; +@end + diff --git a/test/ASTMerge/Inputs/property2.m b/test/ASTMerge/Inputs/property2.m new file mode 100644 index 0000000..6039f10 --- /dev/null +++ b/test/ASTMerge/Inputs/property2.m @@ -0,0 +1,13 @@ +// Matching properties +@interface I1 { +} +- (int)getProp2; +- (void)setProp2:(int)value; +@property (readonly) int Prop1; +@property (getter = getProp2, setter = setProp2:) int Prop2; +@end + +// Mismatched property +@interface I2 +@property (readonly) int Prop1; +@end diff --git a/test/ASTMerge/category.m b/test/ASTMerge/category.m new file mode 100644 index 0000000..bf0d11b --- /dev/null +++ b/test/ASTMerge/category.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/category1.m +// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/category2.m +// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: category2.m:18:1: error: instance method 'method2' has incompatible result types in different translation units ('float' vs. 'int') +// CHECK: category1.m:16:1: note: instance method 'method2' also declared here +// CHECK: category2.m:26:1: error: instance method 'method3' has incompatible result types in different translation units ('float' vs. 'int') +// CHECK: category1.m:24:1: note: instance method 'method3' also declared here +// CHECK: 4 diagnostics generated. diff --git a/test/ASTMerge/exprs.c b/test/ASTMerge/exprs.c new file mode 100644 index 0000000..0a4e1e5 --- /dev/null +++ b/test/ASTMerge/exprs.c @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/exprs1.c +// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/exprs2.c +// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only -verify %s + diff --git a/test/ASTMerge/interface.m b/test/ASTMerge/interface.m index d6af2f4..47e4e05 100644 --- a/test/ASTMerge/interface.m +++ b/test/ASTMerge/interface.m @@ -1,6 +1,19 @@ // RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/interface1.m // RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/interface2.m -// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 +// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s -// FIXME: FileCheck! +// CHECK: interface2.m:16:9: error: instance variable 'ivar2' declared with incompatible types in different translation units ('float' vs. 'int') +// CHECK: interface1.m:16:7: note: declared here with type 'int' +// CHECK: interface1.m:21:1: error: class 'I4' has incompatible superclasses +// CHECK: interface1.m:21:17: note: inherits from superclass 'I2' here +// CHECK: interface2.m:21:17: note: inherits from superclass 'I1' here +// CHECK: interface2.m:33:1: error: class method 'foo' has incompatible result types in different translation units ('float' vs. 'int') +// CHECK: interface1.m:34:1: note: class method 'foo' also declared here +// CHECK: interface2.m:39:19: error: class method 'bar:' has a parameter with a different types in different translation units ('float' vs. 'int') +// CHECK: interface1.m:40:17: note: declared here with type 'int' +// CHECK: interface2.m:45:1: error: class method 'bar:' is variadic in one translation unit and not variadic in another +// CHECK: interface1.m:46:1: note: class method 'bar:' also declared here +// CHECK: interface2.m:57:20: error: instance method 'bar:' has a parameter with a different types in different translation units ('double' vs. 'float') +// CHECK: interface1.m:58:19: note: declared here with type 'float' +// CHECK: 13 diagnostics generated diff --git a/test/ASTMerge/namespace.cpp b/test/ASTMerge/namespace.cpp new file mode 100644 index 0000000..6c46f0a --- /dev/null +++ b/test/ASTMerge/namespace.cpp @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/namespace1.cpp +// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/namespace2.cpp +// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: namespace2.cpp:16:17: error: external variable 'z' declared with incompatible types in different translation units ('double' vs. 'float') +// CHECK: namespace1.cpp:16:16: note: declared here with type 'float' diff --git a/test/ASTMerge/property.m b/test/ASTMerge/property.m new file mode 100644 index 0000000..0fd7e48 --- /dev/null +++ b/test/ASTMerge/property.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/property1.m +// RUN: %clang_cc1 -emit-pch -o %t.2.ast %S/Inputs/property2.m +// RUN: %clang_cc1 -ast-merge %t.1.ast -ast-merge %t.2.ast -fsyntax-only %s 2>&1 | FileCheck %s + +// CHECK: property2.m:12:26: error: property 'Prop1' declared with incompatible types in different translation units ('int' vs. 'float') +// CHECK: property1.m:10:28: note: declared here with type 'float' +// CHECK: property2.m:12:26: error: instance method 'Prop1' has incompatible result types in different translation units ('int' vs. 'float') +// CHECK: property1.m:10:28: note: instance method 'Prop1' also declared here +// CHECK: 4 diagnostics generated. diff --git a/test/Analysis/blocks.m b/test/Analysis/blocks.m index e8e96a2..b05b198 100644 --- a/test/Analysis/blocks.m +++ b/test/Analysis/blocks.m @@ -83,3 +83,8 @@ void test2_b() { // 'x' is bound at block creation. ^{ y = x + 1; }(); // no-warning } + +void test2_c() { + typedef void (^myblock)(void); + myblock f = ^() { f(); }; // expected-warning{{Variable 'f' is captured by block with a garbage value}} +}
\ No newline at end of file diff --git a/test/Analysis/dead-stores.m b/test/Analysis/dead-stores.m index 765a24a..701e580 100644 --- a/test/Analysis/dead-stores.m +++ b/test/Analysis/dead-stores.m @@ -34,3 +34,10 @@ void DeadStoreTest(NSObject *anObject) { ([keys containsObject:@"name"] && [keys containsObject:@"icon"])) {} } +// This test case was a false positive due to how clang models +// pointer types and ObjC object pointer types differently. Here +// we don't warn about a dead store because 'nil' is assigned to +// an object pointer for the sake of defensive programming. +void rdar_7631278(NSObject *x) { + x = ((void*)0); +} diff --git a/test/Analysis/inline.c b/test/Analysis/inline.c new file mode 100644 index 0000000..13d4f7f --- /dev/null +++ b/test/Analysis/inline.c @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f2 -verify %s + +int f1() { + int y = 1; + y++; + return y; +} + +void f2() { + int x = 1; + x = f1(); + if (x == 1) { + int *p = 0; + *p = 3; // no-warning + } + if (x == 2) { + int *p = 0; + *p = 3; // expected-warning{{Dereference of null pointer loaded from variable}} + } +} diff --git a/test/Analysis/inline2.c b/test/Analysis/inline2.c new file mode 100644 index 0000000..e2758c1 --- /dev/null +++ b/test/Analysis/inline2.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -analyze -inline-call -analyzer-store region -analyze-function f2 -verify %s + +// Test parameter 'a' is registered to LiveVariables analysis data although it +// is not referenced in the function body. +// Before processing 'return 1;', in RemoveDeadBindings(), we query the liveness +// of 'a', because we have a binding for it due to parameter passing. +int f1(int a) { + return 1; +} + +void f2() { + int x; + x = f1(1); +} diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index 201cbc9..21a54c3 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -1,6 +1,10 @@ // RUN: %clang_cc1 -triple i386-apple-darwin9 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -DTEST_64 -analyze -analyzer-experimental-internal-checks -analyzer-check-objc-mem -analyzer-store=region -verify -fblocks -analyzer-opt-analyze-nested-blocks %s +typedef long unsigned int size_t; +void *memcpy(void *, const void *, size_t); +void *alloca(size_t); + typedef struct objc_selector *SEL; typedef signed char BOOL; typedef int NSInteger; @@ -867,3 +871,20 @@ int test_c_rev96062() { test_a_rev96062_aux2(&z); return a + b; // no-warning } + +//===----------------------------------------------------------------------===// +// <rdar://problem/7242010> - The access to y[0] at the bottom previously +// was reported as an uninitialized value. +//===----------------------------------------------------------------------===// + +char *rdar_7242010(int count, char **y) { + char **x = alloca((count + 4) * sizeof(*x)); + x[0] = "hi"; + x[1] = "there"; + x[2] = "every"; + x[3] = "body"; + memcpy(x + 4, y, count * sizeof(*x)); + y = x; + return y[0]; // no-warning +} + diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 1c41d85..675e9a6 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -7,6 +7,12 @@ #if __has_feature(attribute_cf_returns_retained) #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) #endif +#if __has_feature(attribute_ns_returns_not_retained) +#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) +#endif +#if __has_feature(attribute_cf_returns_not_retained) +#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) +#endif //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from Mac OS X headers: @@ -1188,6 +1194,8 @@ typedef NSString* MyStringTy; - (NSString*) returnsAnOwnedString NS_RETURNS_RETAINED; // no-warning - (NSString*) returnsAnOwnedCFString CF_RETURNS_RETAINED; // no-warning - (MyStringTy) returnsAnOwnedTypedString NS_RETURNS_RETAINED; // no-warning +- (NSString*) newString NS_RETURNS_NOT_RETAINED; // no-warning +- (NSString*) newStringNoAttr; - (int) returnsAnOwnedInt NS_RETURNS_RETAINED; // expected-warning{{'ns_returns_retained' attribute only applies to functions or methods that return a pointer or Objective-C object}} @end @@ -1201,9 +1209,16 @@ void test_attr_1b(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} } +void test_attr1c(TestOwnershipAttr *X) { + NSString *str = [X newString]; // no-warning + NSString *str2 = [X newStringNoAttr]; // expected-warning{{leak}} +} + @interface MyClassTestCFAttr : NSObject {} - (NSDate*) returnsCFRetained CF_RETURNS_RETAINED; - (CFDateRef) returnsCFRetainedAsCF CF_RETURNS_RETAINED; +- (CFDateRef) newCFRetainedAsCF CF_RETURNS_NOT_RETAINED; +- (CFDateRef) newCFRetainedAsCFNoAttr; - (NSDate*) alsoReturnsRetained; - (CFDateRef) alsoReturnsRetainedAsCF; - (NSDate*) returnsNSRetained NS_RETURNS_RETAINED; @@ -1223,6 +1238,13 @@ CFDateRef returnsRetainedCFDate() { return returnsRetainedCFDate(); // No leak. } +- (CFDateRef) newCFRetainedAsCF { + return (CFDateRef)[(id)[self returnsCFRetainedAsCF] autorelease]; +} + +- (CFDateRef) newCFRetainedAsCFNoAttr { + return (CFDateRef)[(id)[self returnsCFRetainedAsCF] autorelease]; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}} +} - (NSDate*) alsoReturnsRetained { return (NSDate*) returnsRetainedCFDate(); // expected-warning{{leak}} diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c new file mode 100644 index 0000000..777ad19 --- /dev/null +++ b/test/Analysis/unix-fns.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem %s -analyzer-store=region +// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem %s -analyzer-store=basic + +#ifndef O_CREAT +#define O_CREAT 0x0200 +#define O_RDONLY 0x0000 +#endif +int open(const char *, int, ...); + +void test_open(const char *path) { + int fd; + fd = open(path, O_RDONLY); // no-warning + if (!fd) + close(fd); + + fd = open(path, O_CREAT); // expected-warning{{Call to 'open' requires a third argument when the 'O_CREAT' flag is set}} + if (!fd) + close(fd); +} diff --git a/test/Analysis/unused-ivars.m b/test/Analysis/unused-ivars.m index 600f0e2..14c43a8 100644 --- a/test/Analysis/unused-ivars.m +++ b/test/Analysis/unused-ivars.m @@ -81,3 +81,18 @@ int radar_7254495(RDar7254495 *a) { return a->x; } @end + +//===----------------------------------------------------------------------===// +// <rdar://problem/7353683> - consult attribute((unused)) to silence warnings +// about unused instance variables +//===----------------------------------------------------------------------===// + +@interface RDar7353683 { +@private + id x __attribute__((unused)); +} +@end + +@implementation RDar7353683 +@end + diff --git a/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp b/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp new file mode 100644 index 0000000..4a0b387 --- /dev/null +++ b/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [basic.lookup.classref]p3: +// If the unqualified-id is ∼type-name, the type-name is looked up in the +// context of the entire postfix-expression. If the type T of the object +// expression is of a class type C, the type-name is also looked up in the +// scope of class C. At least one of the lookups shall find a name that +// refers to (possibly cv-qualified) T. + +// From core issue 305 +struct A { +}; + +struct C { + struct A {}; + void f (); +}; + +void C::f () { + ::A *a; + a->~A (); +} + +// From core issue 414 +struct X {}; +void f() { + X x; + struct X {}; + x.~X(); +} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp new file mode 100644 index 0000000..35efba5 --- /dev/null +++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s +struct C { + typedef int I; +}; + +typedef int I1, I2; +extern int* p; +extern int* q; + +void f() { + p->C::I::~I(); + q->I1::~I2(); +} + +struct A { + ~A(); +}; + +typedef A AB; +int main() { + AB *p; + p->AB::~AB(); +} diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp new file mode 100644 index 0000000..633d5cd --- /dev/null +++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct C { + typedef int I; +}; + +typedef int I1, I2; +extern int* p; +extern int* q; + +void f() { + p->C::I::~I(); + q->I1::~I2(); +} + +struct A { + ~A(); +}; + +typedef A AB; +int main() { + AB *p; + p->AB::~AB(); // expected-error{{identifier 'AB' in pseudo-destructor expression does not name a type}} +} diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp new file mode 100644 index 0000000..22f77b0 --- /dev/null +++ b/test/CXX/class.access/class.friend/p1.cpp @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++'0x [class.friend] p1: +// A friend of a class is a function or class that is given permission to use +// the private and protected member names from the class. A class specifies +// its friends, if any, by way of friend declarations. Such declarations give +// special access rights to the friends, but they do not make the nominated +// friends members of the befriending class. +// +// FIXME: Add tests for access control when implemented. Currently we only test +// for parsing. + +struct S { static void f(); }; +S* g() { return 0; } + +struct X { + friend struct S; + friend S* g(); +}; + +void test1() { + S s; + g()->f(); + S::f(); + X::g(); // expected-error{{no member named 'g' in 'struct X'}} + X::S x_s; // expected-error{{no member named 'S' in 'struct X'}} + X x; + x.g(); // expected-error{{no member named 'g' in 'struct X'}} +} + +// Test that we recurse through namespaces to find already declared names, but +// new names are declared within the enclosing namespace. +namespace N { + struct X { + friend struct S; + friend S* g(); + + friend struct S2; + friend struct S2* g2(); + }; + + struct S2 { static void f2(); }; + S2* g2() { return 0; } + + void test() { + g()->f(); + S s; + S::f(); + X::g(); // expected-error{{no member named 'g' in 'struct N::X'}} + X::S x_s; // expected-error{{no member named 'S' in 'struct N::X'}} + X x; + x.g(); // expected-error{{no member named 'g' in 'struct N::X'}} + + g2(); + S2 s2; + ::g2(); // expected-error{{no member named 'g2' in the global namespace}} + ::S2 g_s2; // expected-error{{no member named 'S2' in the global namespace}} + X::g2(); // expected-error{{no member named 'g2' in 'struct N::X'}} + X::S2 x_s2; // expected-error{{no member named 'S2' in 'struct N::X'}} + x.g2(); // expected-error{{no member named 'g2' in 'struct N::X'}} + } +} diff --git a/test/CXX/class.derived/class.member.lookup/p6.cpp b/test/CXX/class.derived/class.member.lookup/p6.cpp new file mode 100644 index 0000000..5f4b2a7 --- /dev/null +++ b/test/CXX/class.derived/class.member.lookup/p6.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +class V { +public: + int f(); + int x; +}; + +class W { +public: + int g(); // expected-note{{member found by ambiguous name lookup}} + int y; // expected-note{{member found by ambiguous name lookup}} +}; + +class B : public virtual V, public W +{ +public: + int f(); + int x; + int g(); // expected-note{{member found by ambiguous name lookup}} + int y; // expected-note{{member found by ambiguous name lookup}} +}; + +class C : public virtual V, public W { }; + +class D : public B, public C { void glorp(); }; + +void D::glorp() { + x++; + f(); + y++; // expected-error{{member 'y' found in multiple base classes of different types}} + g(); // expected-error{{error: member 'g' found in multiple base classes of different types}} +} + +// PR6462 +struct BaseIO { BaseIO* rdbuf() { return 0; } }; +struct Pcommon : virtual BaseIO { int rdbuf() { return 0; } }; +struct P : virtual BaseIO, Pcommon {}; + +void f() { P p; p.rdbuf(); } diff --git a/test/CXX/class/class.nest/p3.cpp b/test/CXX/class/class.nest/p3.cpp new file mode 100644 index 0000000..c4c4ca7 --- /dev/null +++ b/test/CXX/class/class.nest/p3.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// C++0x [class.nest] p3: +// If class X is defined in a namespace scope, a nested class Y may be +// declared in class X and later defined in the definition of class X or be +// later defined in a namespace scope enclosing the definition of class X. + +namespace example { + class E { + class I1; + class I2; + class I1 { }; + }; + class E::I2 { }; +} + +// Don't insert out-of-line inner class definitions into the namespace scope. +namespace PR6107 { + struct S1 { }; + struct S2 { + struct S1; + }; + struct S2::S1 { }; + S1 s1; +} diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp index 1f962a9..a5f314d 100644 --- a/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp +++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp @@ -1,5 +1,47 @@ // RUN: %clang_cc1 -fsyntax-only %s +// C++'0x [namespace.memdef] p3: +// Every name first declared in a namespace is a member of that namespace. If +// a friend declaration in a non-local class first declares a class or +// function the friend class or function is a member of the innermost +// enclosing namespace. + +namespace N { + struct S0 { + friend struct F0; + friend void f0(int); + struct F0 member_func(); + }; + struct F0 { }; + F0 f0() { return S0().member_func(); } +} +N::F0 f0_var = N::f0(); + +// Ensure we can handle attaching friend declarations to an enclosing namespace +// with multiple contexts. +namespace N { struct S1 { struct IS1; }; } +namespace N { + struct S1::IS1 { + friend struct F1; + friend void f1(int); + struct F1 member_func(); + }; + struct F1 { }; + F1 f1() { return S1::IS1().member_func(); } +} +N::F1 f1_var = N::f1(); + +// The name of the friend is not found by unqualified lookup (3.4.1) or by +// qualified lookup (3.4.3) until a matching declaration is provided in that +// namespace scope (either before or after the class definition granting +// friendship). If a friend function is called, its name may be found by the +// name lookup that considers functions from namespaces and classes +// associated with the types of the function arguments (3.4.2). If the name +// in a friend declaration is neither qualified nor a template-id and the +// declaration is a function or an elaborated-type-specifier, the lookup to +// determine whether the entity has been previously declared shall not +// consider any scopes outside the innermost enclosing namespace. + template<typename T> struct X0 { }; struct X1 { }; @@ -11,5 +53,4 @@ struct Y { friend union X1; }; - // FIXME: Woefully inadequate for testing diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp index cf52909..4c7ee94 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp @@ -10,3 +10,15 @@ namespace PR5909 { const Foo f = { 0 }; // It compiles without the 'const'. bool z = Test(f.x); } + +namespace PR6264 { + typedef int (&T)[3]; + struct S + { + operator T (); + }; + void f() + { + T bar = S(); + } +} diff --git a/test/CXX/expr/expr.unary/expr.new/p19.cpp b/test/CXX/expr/expr.unary/expr.new/p19.cpp new file mode 100644 index 0000000..6134779 --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p19.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +typedef __SIZE_TYPE__ size_t; + +// Operator delete template for placement new with global lookup +template<int I> +struct X0 { + X0(); + + static void* operator new(size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X0() { + // Using the global operator new suppresses the search for a + // operator delete in the class. + ::new X0<2>; + + new X0<3>; // expected-note 2{{instantiation}} +} + +// Operator delete template for placement new[] with global lookup +template<int I> +struct X1 { + X1(); + + static void* operator new[](size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete[](void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X1() { + // Using the global operator new suppresses the search for a + // operator delete in the class. + ::new X1<2> [17]; + + new X1<3> [17]; // expected-note 2{{instantiation}} +} diff --git a/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp b/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp new file mode 100644 index 0000000..c188e1e --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p20-0x.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s +typedef __SIZE_TYPE__ size_t; + +struct S { + // Placement allocation function: + static void* operator new(size_t, size_t); + // Usual (non-placement) deallocation function: + static void operator delete(void*, size_t); // expected-note{{declared here}} +}; + +void testS() { + S* p = new (0) S; // expected-error{{'new' expression with placement arguments refers to non-placement 'operator delete'}} +} diff --git a/test/CXX/expr/expr.unary/expr.new/p20.cpp b/test/CXX/expr/expr.unary/expr.new/p20.cpp new file mode 100644 index 0000000..71e584e --- /dev/null +++ b/test/CXX/expr/expr.unary/expr.new/p20.cpp @@ -0,0 +1,141 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +typedef __SIZE_TYPE__ size_t; + +// Overloaded operator delete with two arguments +template<int I> +struct X0 { + X0(); + static void* operator new(size_t); + static void operator delete(void*, size_t) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X0() { + new X0<1>; // expected-note{{instantiation}} +} + +// Overloaded operator delete with one argument +template<int I> +struct X1 { + X1(); + + static void* operator new(size_t); + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X1() { + new X1<1>; // expected-note{{instantiation}} +} + +// Overloaded operator delete for placement new +template<int I> +struct X2 { + X2(); + + static void* operator new(size_t, double, double); + static void* operator new(size_t, int, int); + + static void operator delete(void*, const int, int) { + int *ip = I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*, double, double); +}; + +void test_X2() { + new (0, 0) X2<1>; // expected-note{{instantiation}} +} + +// Operator delete template for placement new +struct X3 { + X3(); + + static void* operator new(size_t, double, double); + + template<typename T> + static void operator delete(void*, T x, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} + } +}; + +void test_X3() { + new (0, 0) X3; // expected-note{{instantiation}} +} + +// Operator delete template for placement new in global scope. +struct X4 { + X4(); + static void* operator new(size_t, double, double); +}; + +template<typename T> +void operator delete(void*, T x, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} +} + +void test_X4() { + new (0, 0) X4; // expected-note{{instantiation}} +} + +// Useless operator delete hides global operator delete template. +struct X5 { + X5(); + static void* operator new(size_t, double, double); + void operator delete(void*, double*, double*); +}; + +void test_X5() { + new (0, 0) X5; // okay, we found X5::operator delete but didn't pick it +} + +// Operator delete template for placement new +template<int I> +struct X6 { + X6(); + + static void* operator new(size_t) { + return I; // expected-error{{cannot initialize}} + } + + static void operator delete(void*) { + int *ip = I; // expected-error{{cannot initialize}} + } +}; + +void test_X6() { + new X6<3>; // expected-note 2{{instantiation}} +} + +void *operator new(size_t, double, double, double); + +template<typename T> +void operator delete(void*, T x, T, T) { + double *dp = &x; + int *ip = &x; // expected-error{{cannot initialize}} +} +void test_int_new() { + new (1.0, 1.0, 1.0) int; // expected-note{{instantiation}} +} + +// We don't need an operator delete if the type has a trivial +// constructor, since we know that constructor cannot throw. +// FIXME: Is this within the standard? Seems fishy, but both EDG+GCC do it. +#if 0 +template<int I> +struct X7 { + static void* operator new(size_t); + static void operator delete(void*, size_t) { + int *ip = I; // okay, since it isn't instantiated. + } +}; + +void test_X7() { + new X7<1>; +} +#endif + diff --git a/test/CXX/special/class.copy/p3.cpp b/test/CXX/special/class.copy/p3.cpp new file mode 100644 index 0000000..3d87266 --- /dev/null +++ b/test/CXX/special/class.copy/p3.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +// PR6141 +template<typename T> +struct X { + X(); + template<typename U> X(X<U>); + X(const X<T>&); +}; + +void f(X<int>) { } + +struct Y : X<int> { }; +struct Z : X<float> { }; + +// CHECK: define i32 @main() +int main() { + // CHECK: call void @_ZN1YC1Ev + // CHECK: call void @_ZN1XIiEC1ERKS0_ + // CHECK: call void @_Z1f1XIiE + f(Y()); + // CHECK: call void @_ZN1ZC1Ev + // CHECK: call void @_ZN1XIfEC1ERKS0_ + // CHECK: call void @_ZN1XIiEC1IfEES_IT_E + // CHECK: call void @_Z1f1XIiE + f(Z()); +} diff --git a/test/CXX/temp/temp.decls/temp.mem/p1.cpp b/test/CXX/temp/temp.decls/temp.mem/p1.cpp index 1b9da84..b057eed 100644 --- a/test/CXX/temp/temp.decls/temp.mem/p1.cpp +++ b/test/CXX/temp/temp.decls/temp.mem/p1.cpp @@ -14,3 +14,22 @@ int foo() { A<bool>::cond = true; return A<bool>::B<int>::twice(4); } + +namespace PR6376 { + template<typename T> + struct X { + template<typename Y> + struct Y { }; + }; + + template<> + struct X<float> { + template<typename Y> + struct Y { }; + }; + + template<typename T, typename U> + struct Z : public X<T>::template Y<U> { }; + + Z<float, int> z0; +} diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp index a8b83d4..eb5465c 100644 --- a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp @@ -33,5 +33,4 @@ template <typename T> void g(T); template <typename T> void g(T, T); int typeof2[is_same<__typeof__(g<float>), void (int)>::value? 1 : -1]; // \ - // expected-error{{cannot determine the type of an overloaded function}} \ - // FIXME: expected-error{{use of undeclared identifier}} + // expected-error{{cannot determine the type of an overloaded function}} diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp index 95f9640..dc79300 100644 --- a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp @@ -3,8 +3,9 @@ template<class X, class Y, class Z> X f(Y,Z); // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} void g() { - f<int,char*,double>("aa",3.0); - f<int,char*>("aa",3.0); // Z is deduced to be double + f<int,char*,double>("aa",3.0); // expected-warning{{conversion from string literal to 'char *' is deprecated}} + f<int,char*>("aa",3.0); // Z is deduced to be double \ + // expected-warning{{conversion from string literal to 'char *' is deprecated}} f<int>("aa",3.0); // Y is deduced to be char*, and // Z is deduced to be double f("aa",3.0); // expected-error{{no matching}} diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp index 34c3710..f539471 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp @@ -54,3 +54,10 @@ void f(Array<String>& v) { template<> void sort<String>(Array<String>& v); // // expected-error{{after instantiation}} template<> void sort<>(Array<char*>& v); // OK: sort<char*> not yet used + +namespace PR6160 { + template<typename T> void f(T); + template<> void f(int); + extern template void f(int); + template<> void f(int) { } +} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp index f292b5a..2b85213 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp @@ -30,3 +30,19 @@ template long X0<long>::value; template<> struct X0<double>; template struct X0<double>; + +// PR 6458 +namespace test0 { + template <class T> class foo { + int compare(T x, T y); + }; + + template <> int foo<char>::compare(char x, char y); + template <class T> int foo<T>::compare(T x, T y) { + // invalid at T=char; if we get a diagnostic here, we're + // inappropriately instantiating this template. + void *ptr = x; + } + extern template class foo<char>; + template class foo<char>; +} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p6.cpp b/test/CXX/temp/temp.spec/temp.explicit/p6.cpp index 44ce41b..1382272 100644 --- a/test/CXX/temp/temp.spec/temp.explicit/p6.cpp +++ b/test/CXX/temp/temp.spec/temp.explicit/p6.cpp @@ -12,3 +12,24 @@ template<typename T, typename U> void f0(T, U*) { } template void f0<int>(int, float*); template void f0<>(double, float*); + +template<typename T> struct hash { }; +struct S { + bool operator==(const S&) const { return false; } +}; + +template<typename T> struct Hash_map { + void Method(const T& x) { h(x); } + hash<T> h; +}; + +Hash_map<S> *x; +const Hash_map<S> *foo() { + return x; +} + +template<> struct hash<S> { + int operator()(const S& k) const { + return 0; + } +}; diff --git a/test/CodeGen/2010-02-16-DbgScopes.c b/test/CodeGen/2010-02-16-DbgScopes.c new file mode 100644 index 0000000..b11f920 --- /dev/null +++ b/test/CodeGen/2010-02-16-DbgScopes.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -emit-llvm -g < %s | grep lexical | count 5 +// Test to check number of lexical scope identified in debug info. + +extern int bar(); +extern void foobar(); +void foo(int s) { + unsigned loc = 0; + if (s) { + if (bar()) { + foobar(); + } + } else { + loc = 1; + if (bar()) { + loc = 2; + } + } +} diff --git a/test/CodeGen/2010-02-18-Dbg-VectorType.c b/test/CodeGen/2010-02-18-Dbg-VectorType.c new file mode 100644 index 0000000..eb17d11 --- /dev/null +++ b/test/CodeGen/2010-02-18-Dbg-VectorType.c @@ -0,0 +1,9 @@ +// RUN: %clang -emit-llvm -S -O0 -g %s -o - | grep DW_TAG_typedef | grep float4 +typedef float float4 __attribute__((vector_size(16))); + +int main(){ + volatile float4 x = (float4) { 0.0f, 1.0f, 2.0f, 3.0f }; + x += x; + return 0; +} + diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c index 770ce76..4fdf1a5 100644 --- a/test/CodeGen/attributes.c +++ b/test/CodeGen/attributes.c @@ -30,6 +30,12 @@ int t12 __attribute__((section("SECT"))); void __t8() {} void t9() __attribute__((weak, alias("__t8"))); +static void t22(void) __attribute__((weakref("t8"))); +// CHECK: @t22 = alias weak void ()* @t8 + +static void t23(void) __attribute__((weakref, alias("t8"))); +// CHECK: @t23 = alias weak void ()* @t8 + // CHECK: declare extern_weak i32 @t15() int __attribute__((weak_import)) t15(void); int t17() { diff --git a/test/CodeGen/blocksignature.c b/test/CodeGen/blocksignature.c new file mode 100644 index 0000000..6ed8750 --- /dev/null +++ b/test/CodeGen/blocksignature.c @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -check-prefix=X64 +// RUN: %clang_cc1 -fblocks -triple i686-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -check-prefix=X32 + +// X64: @.str = private constant [6 x i8] c"v8@?0\00" +// X64: @__block_literal_global = internal constant %1 { i8** @_NSConcreteGlobalBlock, i32 1342177280, +// X64: @.str1 = private constant [12 x i8] c"i16@?0c8f12\00" +// X64: store i32 1073741824, i32* + +// X32: @.str = private constant [6 x i8] c"v4@?0\00" +// X32: @__block_literal_global = internal constant %1 { i8** @_NSConcreteGlobalBlock, i32 1342177280, +// X32: @.str1 = private constant [11 x i8] c"i12@?0c4f8\00" +// X32: store i32 1073741824, i32* + +// rdar://7635294 + + +int globalInt; +void (^global)(void) = ^{ ++globalInt; }; + + +void foo(int param) { + extern int rand(void); + extern void rand_r(int (^b)(char x, float y)); // name a function present at runtime + while (param--) + rand_r(^(char x, float y){ return x + (int)y + param + rand(); }); // generate a local block binding param +} + +#if 0 +#include <stdio.h> +enum { + BLOCK_HAS_COPY_DISPOSE = (1 << 25), + BLOCK_HAS_CXX_OBJ = (1 << 26), + BLOCK_IS_GLOBAL = (1 << 28), + BLOCK_HAS_DESCRIPTOR = (1 << 29), + BLOCK_HAS_OBJC_TYPE = (1 << 30) +}; + +struct block_descriptor_big { + unsigned long int reserved; + unsigned long int size; + void (*copy)(void *dst, void *src); // conditional on BLOCK_HAS_COPY_DISPOSE + void (*dispose)(void *); // conditional on BLOCK_HAS_COPY_DISPOSE + const char *signature; // conditional on BLOCK_HAS_OBJC + const char *layout; // conditional on BLOCK_HAS_OBJC +}; +struct block_descriptor_small { + unsigned long int reserved; + unsigned long int size; + const char *signature; // conditional on BLOCK_HAS_OBJC + const char *layout; // conditional on BLOCK_HAS_OBJC +}; + +struct block_layout_abi { // can't change + void *isa; + int flags; + int reserved; + void (*invoke)(void *, ...); + struct block_descriptor_big *descriptor; +}; + +const char *getBlockSignature(void *block) { + struct block_layout_abi *layout = (struct block_layout_abi *)block; + if ((layout->flags & BLOCK_HAS_OBJC_TYPE) != BLOCK_HAS_OBJC_TYPE) return NULL; + if (layout->flags & BLOCK_HAS_COPY_DISPOSE) + return layout->descriptor->signature; + else + return ((struct block_descriptor_small *)layout->descriptor)->signature; +} + + + +int main(int argc, char *argv[]) { + printf("desired global flags: %d\n", BLOCK_IS_GLOBAL | BLOCK_HAS_OBJC_TYPE); + printf("desired stack flags: %d\n", BLOCK_HAS_OBJC_TYPE); + + printf("types for global: %s\n", getBlockSignature(global)); + printf("types for local: %s\n", getBlockSignature(^int(char x, float y) { return (int)(y + x); })); + return 0; +} + +/* +x86_64 +desired global flags: 1342177280 +desired stack flags: 1073741824 +types for global: v8@?0 +types for local: i16@?0c8f12 + +i386 +desired global flags: 1342177280 +desired stack flags: 1073741824 +types for global: v4@?0 +types for local: i12@?0c4f8 +*/ +#endif diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c index 4fa4785..417ca7d 100644 --- a/test/CodeGen/builtins.c +++ b/test/CodeGen/builtins.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -emit-llvm -o %t %s // RUN: not grep __builtin %t +// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-darwin-apple | FileCheck %s int printf(const char *, ...); @@ -9,11 +10,17 @@ void p(char *str, int x) { void q(char *str, double x) { printf("%s: %f\n", str, x); } +void r(char *str, void *ptr) { + printf("%s: %p\n", str, ptr); +} + +int random(void); 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 R(n,args) r(#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)); @@ -110,16 +117,48 @@ int main() { // FIXME // V(clear_cache, (&N, &N+1)); V(trap, ()); - P(extract_return_addr, (&N)); + R(extract_return_addr, (&N)); return 0; } -void strcat() {} - void foo() { __builtin_strcat(0, 0); } +// CHECK: define void @bar( +void bar() { + float f; + double d; + long double ld; + + // LLVM's hex representation of float constants is really unfortunate; + // basically it does a float-to-double "conversion" and then prints the + // hex form of that. That gives us wierd artifacts like exponents + // that aren't numerically similar to the original exponent and + // significand bit-patterns that are offset by three bits (because + // the exponent was expanded from 8 bits to 11). + // + // 0xAE98 == 1010111010011000 + // 0x15D3 == 1010111010011 + + f = __builtin_huge_valf(); // CHECK: float 0x7FF0000000000000 + d = __builtin_huge_val(); // CHECK: double 0x7FF0000000000000 + ld = __builtin_huge_vall(); // CHECK: x86_fp80 0xK7FFF8000000000000000 + f = __builtin_nanf(""); // CHECK: float 0x7FF8000000000000 + d = __builtin_nan(""); // CHECK: double 0x7FF8000000000000 + ld = __builtin_nanl(""); // CHECK: x86_fp80 0xK7FFFC000000000000000 + f = __builtin_nanf("0xAE98"); // CHECK: float 0x7FF815D300000000 + d = __builtin_nan("0xAE98"); // CHECK: double 0x7FF800000000AE98 + ld = __builtin_nanl("0xAE98"); // CHECK: x86_fp80 0xK7FFFC00000000000AE98 + f = __builtin_nansf(""); // CHECK: float 0x7FF4000000000000 + d = __builtin_nans(""); // CHECK: double 0x7FF4000000000000 + ld = __builtin_nansl(""); // CHECK: x86_fp80 0xK7FFFA000000000000000 + f = __builtin_nansf("0xAE98"); // CHECK: float 0x7FF015D300000000 + d = __builtin_nans("0xAE98"); // CHECK: double 0x7FF000000000AE98 + ld = __builtin_nansl("0xAE98");// CHECK: x86_fp80 0xK7FFF800000000000AE98 + +} +// CHECK: } diff --git a/test/CodeGen/cast-emit.c b/test/CodeGen/cast-emit.c new file mode 100644 index 0000000..4e33fa3 --- /dev/null +++ b/test/CodeGen/cast-emit.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s + +typedef union { + int i; + float f; +} MyUnion; +void unionf(MyUnion a); +void uniontest(float a) { + f((MyUnion)1.0f); +// CHECK: store float 1.000000e+00 +} + diff --git a/test/CodeGen/dllimport-dllexport.c b/test/CodeGen/dllimport-dllexport.c index c7c2420..c187503 100644 --- a/test/CodeGen/dllimport-dllexport.c +++ b/test/CodeGen/dllimport-dllexport.c @@ -1,7 +1,12 @@ -// RUN: %clang_cc1 -emit-llvm < %s -o %t -// RUN: grep 'dllexport' %t | count 1 -// RUN: not grep 'dllimport' %t +// RUN: %clang_cc1 -triple i386-mingw32 -emit-llvm < %s | FileCheck %s void __attribute__((dllimport)) foo1(); void __attribute__((dllexport)) foo1(){} +// CHECK: define dllexport void @foo1 void __attribute__((dllexport)) foo2(); + +// PR6269 +__declspec(dllimport) void foo3(); +__declspec(dllexport) void foo3(){} +// CHECK: define dllexport void @foo3 +__declspec(dllexport) void foo4(); diff --git a/test/CodeGen/extern-inline.c b/test/CodeGen/extern-inline.c new file mode 100644 index 0000000..5dd9bfd --- /dev/null +++ b/test/CodeGen/extern-inline.c @@ -0,0 +1,25 @@ +// RUN: %clang -S -emit-llvm -std=gnu89 -o - %s | FileCheck %s +// PR5253 + +// If an extern inline function is redefined, functions should call the +// redefinition. +extern inline int f(int a) {return a;} +int g(void) {return f(0);} +// CHECK: call i32 @f +int f(int b) {return 1+b;} +// CHECK: load i32* %{{.*}} +// CHECK: add nsw i32 1, %{{.*}} +int h(void) {return f(1);} +// CHECK: call i32 @f + +// It shouldn't matter if the function was redefined static. +extern inline int f2(int a, int b) {return a+b;} +int g2(void) {return f2(0,1);} +// CHECK: call i32 @f2 +static int f2(int a, int b) {return a*b;} +// CHECK: load i32* %{{.*}} +// CHECK: load i32* %{{.*}} +// CHECK: mul i32 %{{.*}}, %{{.*}} +int h2(void) {return f2(1,2);} +// CHECK: call i32 @f2 + diff --git a/test/CodeGen/functions.c b/test/CodeGen/functions.c index cb9a4ef..5629ef5 100644 --- a/test/CodeGen/functions.c +++ b/test/CodeGen/functions.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -o %t +// RUN: %clang_cc1 %s -emit-llvm -o - -verify | FileCheck %s int g(); @@ -19,22 +19,31 @@ void test3(T f) { int a(int); int a() {return 1;} -// RUN: grep 'define void @f0()' %t void f0() {} +// CHECK: define void @f0() void f1(); -// RUN: grep 'call void @f1()' %t void f2(void) { +// CHECK: call void @f1() f1(1, 2, 3); } -// RUN: grep 'define void @f1()' %t +// CHECK: define void @f1() void f1() {} -// RUN: grep 'define .* @f3' %t | not grep -F '...' +// CHECK: define {{.*}} @f3{{\(\)|\(.*sret.*\)}} struct foo { int X, Y, Z; } f3() { while (1) {} } // PR4423 - This shouldn't crash in codegen void f4() {} -void f5() { f4(42); } +void f5() { f4(42); } //expected-warning {{too many arguments}} + +// Qualifiers on parameter types shouldn't make a difference. +static void f6(const float f, const float g) { +} +void f7(float f, float g) { + f6(f, g); +// CHECK: define void @f7(float{{.*}}, float{{.*}}) +// CHECK: call void @f6(float{{.*}}, float{{.*}}) +} diff --git a/test/CodeGenCXX/alloca-align.cpp b/test/CodeGenCXX/alloca-align.cpp index de6b34d..b70e366 100644 --- a/test/CodeGenCXX/alloca-align.cpp +++ b/test/CodeGenCXX/alloca-align.cpp @@ -1,12 +1,28 @@ // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s -// -// CHECK: alloca %struct.MemsetRange, align 16 -struct MemsetRange { +struct s0 { int Start, End; unsigned Alignment; int TheStores __attribute__((aligned(16))); }; -void foobar() { - (void) MemsetRange(); + +// CHECK: define void @f0 +// CHECK: alloca %struct.s0, align 16 +extern "C" void f0() { + (void) s0(); +} + +// CHECK: define void @f1 +// CHECK: alloca %struct.s0, align 16 +extern "C" void f1() { + (void) (struct s0) { 0, 0, 0, 0 }; +} + +// CHECK: define i64 @f2 +// CHECK: alloca %struct.s1, align 2 +struct s1 { short x; short y; }; +extern "C" struct s1 f2(int a, struct s1 *x, struct s1 *y) { + if (a) + return *x; + return *y; } diff --git a/test/CodeGenCXX/constructors.cpp b/test/CodeGenCXX/constructors.cpp new file mode 100644 index 0000000..2c95c91 --- /dev/null +++ b/test/CodeGenCXX/constructors.cpp @@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 %s -emit-llvm -o - | FileCheck %s + +struct Member { int x; Member(); Member(int); Member(const Member &); }; +struct VBase { int x; VBase(); VBase(int); VBase(const VBase &); }; + +struct ValueClass { + ValueClass(int x, int y) : x(x), y(y) {} + int x; + int y; +}; // subject to ABI trickery + + + +/* Test basic functionality. */ +class A { + A(struct Undeclared &); + A(ValueClass); + Member mem; +}; + +A::A(struct Undeclared &ref) : mem(0) {} + +// Check that delegation works. +// CHECK: define void @_ZN1AC1ER10Undeclared( +// CHECK: call void @_ZN1AC2ER10Undeclared( + +// CHECK: define void @_ZN1AC2ER10Undeclared( +// CHECK: call void @_ZN6MemberC1Ei( + +A::A(ValueClass v) : mem(v.y - v.x) {} + +// CHECK: define void @_ZN1AC1E10ValueClass( +// CHECK: call void @_ZN1AC2E10ValueClass( + +// CHECK: define void @_ZN1AC2E10ValueClass( +// CHECK: call void @_ZN6MemberC1Ei( + + +/* Test that things work for inheritance. */ +struct B : A { + B(struct Undeclared &); + Member mem; +}; + +B::B(struct Undeclared &ref) : A(ref), mem(1) {} + +// CHECK: define void @_ZN1BC1ER10Undeclared( +// CHECK: call void @_ZN1BC2ER10Undeclared( + +// CHECK: define void @_ZN1BC2ER10Undeclared( +// CHECK: call void @_ZN1AC2ER10Undeclared( +// CHECK: call void @_ZN6MemberC1Ei( + + + +/* Test that the delegation optimization is disabled for classes with + virtual bases (for now). This is necessary because a vbase + initializer could access one of the parameter variables by + reference. That's a solvable problem, but let's not solve it right + now. */ +struct C : virtual A { + C(int); + Member mem; +}; +C::C(int x) : A(ValueClass(x, x+1)), mem(x * x) {} + +// CHECK: define void @_ZN1CC1Ei( +// CHECK: call void @_ZN10ValueClassC1Eii( +// CHECK: call void @_ZN1AC2E10ValueClass( +// CHECK: call void @_ZN6MemberC1Ei( + +// CHECK: define void @_ZN1CC2Ei( +// CHECK: call void @_ZN6MemberC1Ei( + + + +/* Test that the delegation optimization is disabled for varargs + constructors. */ +struct D : A { + D(int, ...); + Member mem; +}; + +D::D(int x, ...) : A(ValueClass(x, x+1)), mem(x*x) {} + +// CHECK: define void @_ZN1DC1Eiz( +// CHECK: call void @_ZN10ValueClassC1Eii( +// CHECK: call void @_ZN1AC2E10ValueClass( +// CHECK: call void @_ZN6MemberC1Ei( + +// CHECK: define void @_ZN1DC2Eiz( +// CHECK: call void @_ZN10ValueClassC1Eii( +// CHECK: call void @_ZN1AC2E10ValueClass( +// CHECK: call void @_ZN6MemberC1Ei( diff --git a/test/CodeGenCXX/default-arguments.cpp b/test/CodeGenCXX/default-arguments.cpp index 282e5d0..2ed1567 100644 --- a/test/CodeGenCXX/default-arguments.cpp +++ b/test/CodeGenCXX/default-arguments.cpp @@ -43,11 +43,7 @@ struct C { }; // CHECK: define void @_ZN1CC1Ev( -// CHECK: call void @_ZN2A1C1Ev( -// CHECK: call void @_ZN2A2C1Ev( -// CHECK: call void @_ZN1BC1ERK2A1RK2A2( -// CHECK: call void @_ZN2A2D1Ev -// CHECK: call void @_ZN2A1D1Ev +// CHECK: call void @_ZN1CC2Ev( // CHECK: define void @_ZN1CC2Ev( // CHECK: call void @_ZN2A1C1Ev( diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 0a7e1e5..d40b174 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -1,4 +1,11 @@ -// RUN: %clang_cc1 %s -emit-llvm -o - +// RUN: %clang_cc1 %s -emit-llvm -o - -mconstructor-aliases | FileCheck %s + +// CHECK: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev +// CHECK: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev +// CHECK: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev +// CHECK: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev +// CHECK: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev + struct A { int a; @@ -42,3 +49,101 @@ namespace PR5529 { B::~B() {} } + +// FIXME: there's a known problem in the codegen here where, if one +// destructor throws, the remaining destructors aren't run. Fix it, +// then make this code check for it. +namespace test0 { + void foo(); + struct VBase { ~VBase(); }; + struct Base { ~Base(); }; + struct Member { ~Member(); }; + + struct A : Base { + Member M; + ~A(); + }; + + // The function-try-block won't suppress -mconstructor-aliases here. + A::~A() try { } catch (int i) {} + +// complete destructor alias tested above + +// CHECK: define void @_ZN5test01AD2Ev +// CHECK: invoke void @_ZN5test06MemberD1Ev +// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK: invoke void @_ZN5test04BaseD2Ev +// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] + + struct B : Base, virtual VBase { + Member M; + ~B(); + }; + B::~B() try { } catch (int i) {} + // It will suppress the delegation optimization here, though. + +// CHECK: define void @_ZN5test01BD1Ev +// CHECK: invoke void @_ZN5test06MemberD1Ev +// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK: invoke void @_ZN5test04BaseD2Ev +// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK: invoke void @_ZN5test05VBaseD2Ev +// CHECK: unwind label [[VBASE_UNWIND:%[a-zA-Z0-9.]+]] + +// CHECK: define void @_ZN5test01BD2Ev +// CHECK: invoke void @_ZN5test06MemberD1Ev +// CHECK: unwind label [[MEM_UNWIND:%[a-zA-Z0-9.]+]] +// CHECK: invoke void @_ZN5test04BaseD2Ev +// CHECK: unwind label [[BASE_UNWIND:%[a-zA-Z0-9.]+]] +} + +// Test base-class aliasing. +namespace test1 { + struct A { ~A(); char ***m; }; // non-trivial destructor + struct B { ~B(); }; // non-trivial destructor + struct Empty { }; // trivial destructor, empty + struct NonEmpty { int x; }; // trivial destructor, non-empty + + // There must be a definition in this translation unit for the alias + // optimization to apply. + A::~A() { delete m; } + + struct M : A { ~M(); }; + M::~M() {} // alias tested above + + struct N : A, Empty { ~N(); }; + N::~N() {} // alias tested above + + struct O : Empty, A { ~O(); }; + O::~O() {} // alias tested above + + struct P : NonEmpty, A { ~P(); }; + P::~P() {} // CHECK: define void @_ZN5test11PD2Ev + + struct Q : A, B { ~Q(); }; + Q::~Q() {} // CHECK: define void @_ZN5test11QD2Ev + + struct R : A { ~R(); }; + R::~R() { A a; } // CHECK: define void @_ZN5test11RD2Ev + + struct S : A { ~S(); int x; }; + S::~S() {} // alias tested above + + struct T : A { ~T(); B x; }; + T::~T() {} // CHECK: define void @_ZN5test11TD2Ev + + // The VTT parameter prevents this. We could still make this work + // for calling conventions that are safe against extra parameters. + struct U : A, virtual B { ~U(); }; + U::~U() {} // CHECK: define void @_ZN5test11UD2Ev +} + +// PR6471 +namespace test2 { + struct A { ~A(); char ***m; }; + struct B : A { ~B(); }; + + B::~B() {} + // CHECK: define void @_ZN5test21BD2Ev + // CHECK: call void @_ZN5test21AD2Ev +} diff --git a/test/CodeGenCXX/mangle-subst-std.cpp b/test/CodeGenCXX/mangle-subst-std.cpp index 913c8f1..062610b 100644 --- a/test/CodeGenCXX/mangle-subst-std.cpp +++ b/test/CodeGenCXX/mangle-subst-std.cpp @@ -55,3 +55,9 @@ namespace std terminate_handler set_terminate(terminate_handler) { return 0; } } } + +// Make sure we don't treat the following like std::string +// CHECK: define void @_Z1f12basic_stringIcSt11char_traitsIcESaIcEE +template<typename, typename, typename> struct basic_string { }; +typedef basic_string<char, std::char_traits<char>, std::allocator<char> > not_string; +void f(not_string) { } diff --git a/test/CodeGenCXX/mangle-template.cpp b/test/CodeGenCXX/mangle-template.cpp index c8296f3..57f30a7 100644 --- a/test/CodeGenCXX/mangle-template.cpp +++ b/test/CodeGenCXX/mangle-template.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s - namespace test1 { int x; template <int& D> class T { }; @@ -66,3 +65,42 @@ template <void(A::*)(float)> class T { }; // CHECK-FAIL: void @_ZN5test62f0ENS_1TIXadL_ZNS_1A3im0EfEEEE( void f0(T<&A::im0> a0) {} } + +namespace test7 { + template<typename T> + struct meta { + static const unsigned value = sizeof(T); + }; + + template<unsigned> struct int_c { + typedef float type; + }; + + template<typename T> + struct X { + template<typename U> + X(U*, typename int_c<(meta<T>::value + meta<U>::value)>::type *) { } + }; + + // CHECK: define void @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsrNS6_IS3_EE5valueEE4typeE + template X<int>::X(double*, float*); +} + +namespace test8 { + template<typename T> + struct meta { + struct type { + static const unsigned value = sizeof(T); + }; + }; + + template<unsigned> struct int_c { + typedef float type; + }; + + template<typename T> + void f(int_c<meta<T>::type::value>) { } + + // CHECK: define void @_ZN5test81fIiEEvNS_5int_cIXsrNS_4metaIT_E4typeE5valueEEE + template void f<int>(int_c<sizeof(int)>); +} diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 0718378..e18ca03 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++0x | FileCheck %s struct X { }; struct Y { }; @@ -363,7 +363,7 @@ namespace test0 { char buffer[1024]; j<A>(buffer); } - // CHECK: define linkonce_odr void @_ZN5test01jINS_1AEEEvRAszmecvT__E6buffer_c( + // CHECK: define linkonce_odr void @_ZN5test01jINS_1AEEEvRAszdtcvT__E6buffer_c( } namespace test1 { @@ -376,3 +376,41 @@ namespace test1 { // CHECK: define internal void @_Z27functionWithInternalLinkagev() static void functionWithInternalLinkage() { } void g() { functionWithInternalLinkage(); } + +namespace test2 { + template <class T> decltype(((T*) 0)->member) read_member(T& obj) { + return obj.member; + } + + struct A { int member; } obj; + int test() { + return read_member(obj); + } + + // CHECK: define linkonce_odr i32 @_ZN5test211read_memberINS_1AEEEDtptcvPT_Li0E6memberERS2_( +} + +namespace test3 { + struct AmbiguousBase { int ab; }; + struct Path1 : AmbiguousBase { float p; }; + struct Path2 : AmbiguousBase { double p; }; + struct Derived : Path1, Path2 { }; + + //template <class T> decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; } + //template <class T> decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; } + + // define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path11pERS2_( + template <class T> decltype(((T*) 0)->Path1::p) get_p_1(T &ref) { return ref.Path1::p; } + + // define linkonce_odr double @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path21pERS2_( + template <class T> decltype(((T*) 0)->Path2::p) get_p_2(T &ref) { return ref.Path2::p; } + + Derived obj; + void test() { + // FIXME: uncomment these when we support diamonds competently + //get_ab_1(obj); + //get_ab_2(obj); + get_p_1(obj); + get_p_2(obj); + } +} diff --git a/test/CodeGenCXX/virtual-base-destructor-call.cpp b/test/CodeGenCXX/virtual-base-destructor-call.cpp index 1ee598a..b6e85e2 100644 --- a/test/CodeGenCXX/virtual-base-destructor-call.cpp +++ b/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -16,4 +16,36 @@ basic_iostream<char> res; int main() { } -// CHECK: call void @_ZN9basic_iosD2Ev +// basic_iostream's complete dtor calls its base dtor, then its +// virtual base's dtor. +// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED1Ev +// CHECK: call void @_ZN14basic_iostreamIcED2Ev +// CHECK: call void @_ZN9basic_iosD2Ev + +// basic_iostream's deleting dtor calls its complete dtor, then +// operator delete(). +// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED0Ev +// CHECK: call void @_ZN14basic_iostreamIcED1Ev +// CHECK: call void @_ZdlPv + +// basic_istream's complete dtor calls the base dtor, +// then its virtual base's base dtor. +// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED1Ev +// CHECK: call void @_ZN13basic_istreamIcED2Ev +// CHECK: call void @_ZN9basic_iosD2Ev + +// basic_istream's deleting dtor calls the complete dtor, then +// operator delete(). +// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED0Ev +// CHECK: call void @_ZN13basic_istreamIcED1Ev +// CHECK: call void @_ZdlPv + +// basic_iostream's base dtor calls its non-virtual base dtor. +// CHECK: define linkonce_odr void @_ZN14basic_iostreamIcED2Ev +// CHECK: call void @_ZN13basic_istreamIcED2Ev +// CHECK: } + +// basic_istream's base dtor is a no-op. +// CHECK: define linkonce_odr void @_ZN13basic_istreamIcED2Ev +// CHECK-NOT: call +// CHECK: } diff --git a/test/CodeGenCXX/virtual-bases.cpp b/test/CodeGenCXX/virtual-bases.cpp index 200f21a..6277175 100644 --- a/test/CodeGenCXX/virtual-bases.cpp +++ b/test/CodeGenCXX/virtual-bases.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases | FileCheck %s struct A { A(); }; -// CHECK: define void @_ZN1AC1Ev(%struct.A* %this) +// CHECK: @_ZN1AC1Ev = alias {{.*}} @_ZN1AC2Ev // CHECK: define void @_ZN1AC2Ev(%struct.A* %this) A::A() { } diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index 01ca144..c5b9262 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -1,24 +1,48 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 -mconstructor-aliases | FileCheck %s + +struct Member { + ~Member(); +}; struct A { virtual ~A(); }; struct B : A { + Member m; virtual ~B(); }; -// Complete dtor. -// CHECK: define void @_ZN1BD1Ev -// CHECK: call void @_ZN1AD2Ev +// Complete dtor: just an alias because there are no virtual bases. +// CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev -// Deleting dtor. +// (aliases from C) +// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev +// CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev + +// Deleting dtor: defers to the complete dtor. // CHECK: define void @_ZN1BD0Ev -// CHECK: call void @_ZN1AD2Ev -// check: call void @_ZdlPv +// CHECK: call void @_ZN1BD1Ev +// CHECK: call void @_ZdlPv -// Base dtor. +// Base dtor: actually calls A's base dtor. // CHECK: define void @_ZN1BD2Ev +// CHECK: call void @_ZN6MemberD1Ev // CHECK: call void @_ZN1AD2Ev B::~B() { } + +struct C : B { + ~C(); +}; + +C::~C() { } + +// Complete dtor: just an alias (checked above). + +// Deleting dtor: defers to the complete dtor. +// CHECK: define void @_ZN1CD0Ev +// CHECK: call void @_ZN1CD1Ev +// CHECK: call void @_ZdlPv + +// Base dtor: just an alias to B's base dtor. diff --git a/test/CodeGenCXX/vtable-layout-abi-examples.cpp b/test/CodeGenCXX/vtable-layout-abi-examples.cpp new file mode 100644 index 0000000..2c6b7a4 --- /dev/null +++ b/test/CodeGenCXX/vtable-layout-abi-examples.cpp @@ -0,0 +1,189 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s + +/// Examples from the Itanium C++ ABI specification. +/// http://www.codesourcery.com/public/cxx-abi/ + +namespace Test1 { + +// This is from http://www.codesourcery.com/public/cxx-abi/cxx-vtable-ex.html + +// CHECK: Vtable for 'Test1::A' (5 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test1::A RTTI +// CHECK-NEXT: -- (Test1::A, 0) vtable address -- +// CHECK-NEXT: 2 | void Test1::A::f() +// CHECK-NEXT: 3 | void Test1::A::g() +// CHECK-NEXT: 4 | void Test1::A::h() +struct A { + virtual void f (); + virtual void g (); + virtual void h (); + int ia; +}; +void A::f() {} + +// CHECK: Vtable for 'Test1::B' (13 entries). +// CHECK-NEXT: 0 | vbase_offset (16) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test1::B RTTI +// CHECK-NEXT: -- (Test1::B, 0) vtable address -- +// CHECK-NEXT: 3 | void Test1::B::f() +// CHECK-NEXT: 4 | void Test1::B::h() +// CHECK-NEXT: 5 | vcall_offset (-16) +// CHECK-NEXT: 6 | vcall_offset (0) +// CHECK-NEXT: 7 | vcall_offset (-16) +// CHECK-NEXT: 8 | offset_to_top (-16) +// CHECK-NEXT: 9 | Test1::B RTTI +// CHECK-NEXT: -- (Test1::A, 16) vtable address -- +// CHECK-NEXT: 10 | void Test1::B::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 11 | void Test1::A::g() +// CHECK-NEXT: 12 | void Test1::B::h() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -40 vcall offset offset] +struct B: public virtual A { + void f (); + void h (); + int ib; +}; +void B::f() {} + +// CHECK: Vtable for 'Test1::C' (13 entries). +// CHECK-NEXT: 0 | vbase_offset (16) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test1::C RTTI +// CHECK-NEXT: -- (Test1::C, 0) vtable address -- +// CHECK-NEXT: 3 | void Test1::C::g() +// CHECK-NEXT: 4 | void Test1::C::h() +// CHECK-NEXT: 5 | vcall_offset (-16) +// CHECK-NEXT: 6 | vcall_offset (-16) +// CHECK-NEXT: 7 | vcall_offset (0) +// CHECK-NEXT: 8 | offset_to_top (-16) +// CHECK-NEXT: 9 | Test1::C RTTI +// CHECK-NEXT: -- (Test1::A, 16) vtable address -- +// CHECK-NEXT: 10 | void Test1::A::f() +// CHECK-NEXT: 11 | void Test1::C::g() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-NEXT: 12 | void Test1::C::h() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -40 vcall offset offset] +struct C: public virtual A { + void g (); + void h (); + int ic; +}; +void C::g() {} + +// CHECK: Vtable for 'Test1::D' (18 entries). +// CHECK-NEXT: 0 | vbase_offset (32) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test1::D RTTI +// CHECK-NEXT: -- (Test1::B, 0) vtable address -- +// CHECK-NEXT: -- (Test1::D, 0) vtable address -- +// CHECK-NEXT: 3 | void Test1::B::f() +// CHECK-NEXT: 4 | void Test1::D::h() +// CHECK-NEXT: 5 | vbase_offset (16) +// CHECK-NEXT: 6 | offset_to_top (-16) +// CHECK-NEXT: 7 | Test1::D RTTI +// CHECK-NEXT: -- (Test1::C, 16) vtable address -- +// CHECK-NEXT: 8 | void Test1::C::g() +// CHECK-NEXT: 9 | void Test1::D::h() +// CHECK-NEXT: [this adjustment: -16 non-virtual] +// CHECK-NEXT: 10 | vcall_offset (-32) +// CHECK-NEXT: 11 | vcall_offset (-16) +// CHECK-NEXT: 12 | vcall_offset (-32) +// CHECK-NEXT: 13 | offset_to_top (-32) +// CHECK-NEXT: 14 | Test1::D RTTI +// CHECK-NEXT: -- (Test1::A, 32) vtable address -- +// CHECK-NEXT: 15 | void Test1::B::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 16 | void Test1::C::g() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-NEXT: 17 | void Test1::D::h() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -40 vcall offset offset] +struct D: public B, public C { + void h (); + int id; +}; +void D::h() { } + +struct X { + int ix; + virtual void x(); +}; + +// CHECK: Vtable for 'Test1::E' (24 entries). +// CHECK-NEXT: 0 | vbase_offset (56) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test1::E RTTI +// CHECK-NEXT: -- (Test1::E, 0) vtable address -- +// CHECK-NEXT: -- (Test1::X, 0) vtable address -- +// CHECK-NEXT: 3 | void Test1::X::x() +// CHECK-NEXT: 4 | void Test1::E::f() +// CHECK-NEXT: 5 | void Test1::E::h() +// CHECK-NEXT: 6 | vbase_offset (40) +// CHECK-NEXT: 7 | offset_to_top (-16) +// CHECK-NEXT: 8 | Test1::E RTTI +// CHECK-NEXT: -- (Test1::B, 16) vtable address -- +// CHECK-NEXT: -- (Test1::D, 16) vtable address -- +// CHECK-NEXT: 9 | void Test1::E::f() +// CHECK-NEXT: [this adjustment: -16 non-virtual] +// CHECK-NEXT: 10 | void Test1::E::h() +// CHECK-NEXT: [this adjustment: -16 non-virtual] +// CHECK-NEXT: 11 | vbase_offset (24) +// CHECK-NEXT: 12 | offset_to_top (-32) +// CHECK-NEXT: 13 | Test1::E RTTI +// CHECK-NEXT: -- (Test1::C, 32) vtable address -- +// CHECK-NEXT: 14 | void Test1::C::g() +// CHECK-NEXT: 15 | void Test1::E::h() +// CHECK-NEXT: [this adjustment: -32 non-virtual] +// CHECK-NEXT: 16 | vcall_offset (-56) +// CHECK-NEXT: 17 | vcall_offset (-24) +// CHECK-NEXT: 18 | vcall_offset (-56) +// CHECK-NEXT: 19 | offset_to_top (-56) +// CHECK-NEXT: 20 | Test1::E RTTI +// CHECK-NEXT: -- (Test1::A, 56) vtable address -- +// CHECK-NEXT: 21 | void Test1::E::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 22 | void Test1::C::g() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-NEXT: 23 | void Test1::E::h() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -40 vcall offset offset] +struct E : X, D { + int ie; + void f(); + void h (); +}; +void E::f() { } + +} + +namespace Test2 { + +// From http://www.codesourcery.com/public/cxx-abi/abi.html#class-types. + +struct A { virtual void f(); }; +struct B : virtual public A { int i; }; +struct C : virtual public A { int j; }; + +// CHECK: Vtable for 'Test2::D' (11 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test2::D RTTI +// CHECK-NEXT: -- (Test2::A, 0) vtable address -- +// CHECK-NEXT: -- (Test2::B, 0) vtable address -- +// CHECK-NEXT: -- (Test2::D, 0) vtable address -- +// CHECK-NEXT: 4 | void Test2::A::f() +// CHECK-NEXT: 5 | void Test2::D::d() +// CHECK-NEXT: 6 | vbase_offset (-16) +// CHECK-NEXT: 7 | vcall_offset (-16) +// CHECK-NEXT: 8 | offset_to_top (-16) +// CHECK-NEXT: 9 | Test2::D RTTI +// CHECK-NEXT: -- (Test2::A, 16) vtable address -- +// CHECK-NEXT: -- (Test2::C, 16) vtable address -- +// CHECK-NEXT: 10 | [unused] void Test2::A::f() +struct D : public B, public C { + virtual void d(); +}; +void D::d() { } + +} diff --git a/test/CodeGenCXX/vtable-layout-extreme.cpp b/test/CodeGenCXX/vtable-layout-extreme.cpp new file mode 100644 index 0000000..14e7879 --- /dev/null +++ b/test/CodeGenCXX/vtable-layout-extreme.cpp @@ -0,0 +1,210 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm-only -fdump-vtable-layouts 2>&1 | FileCheck %s + +// A collection of big class hierarchies and their vtables. + +namespace Test1 { + +class C0 +{ +}; +class C1 + : virtual public C0 +{ + int k0; +}; +class C2 + : public C0 + , virtual public C1 +{ + int k0; +}; +class C3 + : virtual public C0 + , virtual public C1 + , public C2 +{ + int k0; + int k1; + int k2; + int k3; +}; +class C4 + : public C2 + , virtual public C3 + , public C0 +{ + int k0; +}; +class C5 + : public C0 + , virtual public C4 + , public C2 + , public C1 + , virtual public C3 +{ + int k0; +}; +class C6 + : virtual public C3 + , public C0 + , public C5 + , public C4 + , public C1 +{ + int k0; +}; +class C7 + : virtual public C5 + , virtual public C6 + , virtual public C3 + , public C4 + , virtual public C2 +{ + int k0; + int k1; +}; +class C8 + : public C7 + , public C5 + , public C3 + , virtual public C4 + , public C1 + , public C2 +{ + int k0; + int k1; +}; + +// CHECK: Vtable for 'Test1::C9' (87 entries). +// CHECK-NEXT: 0 | vbase_offset (344) +// CHECK-NEXT: 1 | vbase_offset (312) +// CHECK-NEXT: 2 | vbase_offset (184) +// CHECK-NEXT: 3 | vbase_offset (168) +// CHECK-NEXT: 4 | vbase_offset (120) +// CHECK-NEXT: 5 | vbase_offset (48) +// CHECK-NEXT: 6 | vbase_offset (148) +// CHECK-NEXT: 7 | vbase_offset (152) +// CHECK-NEXT: 8 | offset_to_top (0) +// CHECK-NEXT: 9 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 0) vtable address -- +// CHECK-NEXT: -- (Test1::C9, 0) vtable address -- +// CHECK-NEXT: 10 | void Test1::C9::f() +// CHECK-NEXT: 11 | vbase_offset (104) +// CHECK-NEXT: 12 | vbase_offset (132) +// CHECK-NEXT: 13 | vbase_offset (136) +// CHECK-NEXT: 14 | offset_to_top (-16) +// CHECK-NEXT: 15 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 16) vtable address -- +// CHECK-NEXT: -- (Test1::C4, 16) vtable address -- +// CHECK-NEXT: 16 | vbase_offset (72) +// CHECK-NEXT: 17 | vbase_offset (120) +// CHECK-NEXT: 18 | vbase_offset (100) +// CHECK-NEXT: 19 | vbase_offset (104) +// CHECK-NEXT: 20 | offset_to_top (-48) +// CHECK-NEXT: 21 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 48) vtable address -- +// CHECK-NEXT: -- (Test1::C5, 48) vtable address -- +// CHECK-NEXT: -- (Test1::C6, 48) vtable address -- +// CHECK-NEXT: 22 | vbase_offset (84) +// CHECK-NEXT: 23 | offset_to_top (-64) +// CHECK-NEXT: 24 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C1, 64) vtable address -- +// CHECK-NEXT: 25 | vbase_offset (32) +// CHECK-NEXT: 26 | vbase_offset (60) +// CHECK-NEXT: 27 | vbase_offset (64) +// CHECK-NEXT: 28 | offset_to_top (-88) +// CHECK-NEXT: 29 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 88) vtable address -- +// CHECK-NEXT: -- (Test1::C4, 88) vtable address -- +// CHECK-NEXT: 30 | vbase_offset (44) +// CHECK-NEXT: 31 | offset_to_top (-104) +// CHECK-NEXT: 32 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C1, 104) vtable address -- +// CHECK-NEXT: 33 | vbase_offset (28) +// CHECK-NEXT: 34 | vbase_offset (32) +// CHECK-NEXT: 35 | offset_to_top (-120) +// CHECK-NEXT: 36 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 120) vtable address -- +// CHECK-NEXT: -- (Test1::C3, 120) vtable address -- +// CHECK-NEXT: 37 | vbase_offset (-4) +// CHECK-NEXT: 38 | offset_to_top (-152) +// CHECK-NEXT: 39 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C1, 152) vtable address -- +// CHECK-NEXT: 40 | vbase_offset (-48) +// CHECK-NEXT: 41 | vbase_offset (-20) +// CHECK-NEXT: 42 | vbase_offset (-16) +// CHECK-NEXT: 43 | offset_to_top (-168) +// CHECK-NEXT: 44 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 168) vtable address -- +// CHECK-NEXT: -- (Test1::C4, 168) vtable address -- +// CHECK-NEXT: 45 | vbase_offset (160) +// CHECK-NEXT: 46 | vbase_offset (-136) +// CHECK-NEXT: 47 | vbase_offset (-16) +// CHECK-NEXT: 48 | vbase_offset (128) +// CHECK-NEXT: 49 | vbase_offset (-64) +// CHECK-NEXT: 50 | vbase_offset (-36) +// CHECK-NEXT: 51 | vbase_offset (-32) +// CHECK-NEXT: 52 | offset_to_top (-184) +// CHECK-NEXT: 53 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 184) vtable address -- +// CHECK-NEXT: -- (Test1::C4, 184) vtable address -- +// CHECK-NEXT: -- (Test1::C7, 184) vtable address -- +// CHECK-NEXT: -- (Test1::C8, 184) vtable address -- +// CHECK-NEXT: 54 | vbase_offset (-88) +// CHECK-NEXT: 55 | vbase_offset (-40) +// CHECK-NEXT: 56 | vbase_offset (-60) +// CHECK-NEXT: 57 | vbase_offset (-56) +// CHECK-NEXT: 58 | offset_to_top (-208) +// CHECK-NEXT: 59 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 208) vtable address -- +// CHECK-NEXT: -- (Test1::C5, 208) vtable address -- +// CHECK-NEXT: 60 | vbase_offset (-76) +// CHECK-NEXT: 61 | offset_to_top (-224) +// CHECK-NEXT: 62 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C1, 224) vtable address -- +// CHECK-NEXT: 63 | vbase_offset (-92) +// CHECK-NEXT: 64 | vbase_offset (-88) +// CHECK-NEXT: 65 | offset_to_top (-240) +// CHECK-NEXT: 66 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 240) vtable address -- +// CHECK-NEXT: -- (Test1::C3, 240) vtable address -- +// CHECK-NEXT: 67 | vbase_offset (-124) +// CHECK-NEXT: 68 | offset_to_top (-272) +// CHECK-NEXT: 69 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C1, 272) vtable address -- +// CHECK-NEXT: 70 | vbase_offset (-140) +// CHECK-NEXT: 71 | vbase_offset (-136) +// CHECK-NEXT: 72 | offset_to_top (-288) +// CHECK-NEXT: 73 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 288) vtable address -- +// CHECK-NEXT: 74 | vbase_offset (-192) +// CHECK-NEXT: 75 | vbase_offset (-144) +// CHECK-NEXT: 76 | vbase_offset (-164) +// CHECK-NEXT: 77 | vbase_offset (-160) +// CHECK-NEXT: 78 | offset_to_top (-312) +// CHECK-NEXT: 79 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C2, 312) vtable address -- +// CHECK-NEXT: -- (Test1::C5, 312) vtable address -- +// CHECK-NEXT: 80 | vbase_offset (-180) +// CHECK-NEXT: 81 | offset_to_top (-328) +// CHECK-NEXT: 82 | Test1::C9 RTTI +// CHECK-NEXT: -- (Test1::C1, 328) vtable address -- +// CHECK-NEXT: 83 | vbase_offset (-196) +// CHECK-NEXT: 84 | vbase_offset (-192) +// CHECK-NEXT: 85 | offset_to_top (-344) +// CHECK-NEXT: 86 | Test1::C9 RTTI +class C9 + : virtual public C6 + , public C2 + , public C4 + , virtual public C8 +{ + int k0; + int k1; + int k2; + int k3; + virtual void f(); +}; +void C9::f() { } + +} diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index 8fbe486..a65af6e 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -365,3 +365,674 @@ struct B : virtual A1, virtual A2 { void B::f() { } } + +namespace Test10 { + +// Test for a bug where we would not emit secondary vtables for bases +// of a primary base. +struct A1 { virtual void a1(); }; +struct A2 { virtual void a2(); }; + +// CHECK: Vtable for 'Test10::C' (7 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test10::C RTTI +// CHECK-NEXT: -- (Test10::A1, 0) vtable address -- +// CHECK-NEXT: -- (Test10::B, 0) vtable address -- +// CHECK-NEXT: -- (Test10::C, 0) vtable address -- +// CHECK-NEXT: 2 | void Test10::A1::a1() +// CHECK-NEXT: 3 | void Test10::C::f() +// CHECK-NEXT: 4 | offset_to_top (-8) +// CHECK-NEXT: 5 | Test10::C RTTI +// CHECK-NEXT: -- (Test10::A2, 8) vtable address -- +// CHECK-NEXT: 6 | void Test10::A2::a2() +struct B : A1, A2 { + int b; +}; + +struct C : B { + virtual void f(); +}; +void C::f() { } + +} + +namespace Test11 { + +// Very simple test of vtables for virtual bases. +struct A1 { int a; }; +struct A2 { int b; }; + +struct B : A1, virtual A2 { + int b; +}; + +// CHECK: Vtable for 'Test11::C' (8 entries). +// CHECK-NEXT: 0 | vbase_offset (24) +// CHECK-NEXT: 1 | vbase_offset (8) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test11::C RTTI +// CHECK-NEXT: -- (Test11::C, 0) vtable address -- +// CHECK-NEXT: 4 | void Test11::C::f() +// CHECK-NEXT: 5 | vbase_offset (16) +// CHECK-NEXT: 6 | offset_to_top (-8) +// CHECK-NEXT: 7 | Test11::C RTTI +struct C : virtual B { + virtual void f(); +}; +void C::f() { } + +} + +namespace Test12 { + +// Test that the right vcall offsets are generated in the right order. + +// CHECK: Vtable for 'Test12::B' (19 entries). +// CHECK-NEXT: 0 | vbase_offset (8) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test12::B RTTI +// CHECK-NEXT: -- (Test12::B, 0) vtable address -- +// CHECK-NEXT: 3 | void Test12::B::f() +// CHECK-NEXT: 4 | void Test12::B::a() +// CHECK-NEXT: 5 | vcall_offset (32) +// CHECK-NEXT: 6 | vcall_offset (16) +// CHECK-NEXT: 7 | vcall_offset (-8) +// CHECK-NEXT: 8 | vcall_offset (0) +// CHECK-NEXT: 9 | offset_to_top (-8) +// CHECK-NEXT: 10 | Test12::B RTTI +// CHECK-NEXT: -- (Test12::A, 8) vtable address -- +// CHECK-NEXT: -- (Test12::A1, 8) vtable address -- +// CHECK-NEXT: 11 | void Test12::A1::a1() +// CHECK-NEXT: 12 | void Test12::B::a() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-NEXT: 13 | offset_to_top (-24) +// CHECK-NEXT: 14 | Test12::B RTTI +// CHECK-NEXT: -- (Test12::A2, 24) vtable address -- +// CHECK-NEXT: 15 | void Test12::A2::a2() +// CHECK-NEXT: 16 | offset_to_top (-40) +// CHECK-NEXT: 17 | Test12::B RTTI +// CHECK-NEXT: -- (Test12::A3, 40) vtable address -- +// CHECK-NEXT: 18 | void Test12::A3::a3() +struct A1 { + virtual void a1(); + int a; +}; + +struct A2 { + virtual void a2(); + int a; +}; + +struct A3 { + virtual void a3(); + int a; +}; + +struct A : A1, A2, A3 { + virtual void a(); + int i; +}; + +struct B : virtual A { + virtual void f(); + + virtual void a(); +}; +void B::f() { } + +} + +namespace Test13 { + +// Test that we don't try to emit a vtable for 'A' twice. +struct A { + virtual void f(); +}; + +struct B : virtual A { + virtual void f(); +}; + +// CHECK: Vtable for 'Test13::C' (6 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vbase_offset (0) +// CHECK-NEXT: 2 | vcall_offset (0) +// CHECK-NEXT: 3 | offset_to_top (0) +// CHECK-NEXT: 4 | Test13::C RTTI +// CHECK-NEXT: -- (Test13::A, 0) vtable address -- +// CHECK-NEXT: -- (Test13::B, 0) vtable address -- +// CHECK-NEXT: -- (Test13::C, 0) vtable address -- +// CHECK-NEXT: 5 | void Test13::C::f() +struct C : virtual B, virtual A { + virtual void f(); +}; +void C::f() { } + +} + +namespace Test14 { + +// Verify that we handle A being a non-virtual base of B, which is a virtual base. + +struct A { + virtual void f(); +}; + +struct B : A { }; + +struct C : virtual B { }; + +// CHECK: Vtable for 'Test14::D' (5 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test14::D RTTI +// CHECK-NEXT: -- (Test14::A, 0) vtable address -- +// CHECK-NEXT: -- (Test14::B, 0) vtable address -- +// CHECK-NEXT: -- (Test14::C, 0) vtable address -- +// CHECK-NEXT: -- (Test14::D, 0) vtable address -- +// CHECK-NEXT: 4 | void Test14::D::f() +struct D : C, virtual B { + virtual void f(); +}; +void D::f() { } + +} + +namespace Test15 { + +// Test that we don't emit an extra vtable for B since it's a primary base of C. +struct A { virtual void a(); }; +struct B { virtual void b(); }; + +struct C : virtual B { }; + +// CHECK: Vtable for 'Test15::D' (11 entries). +// CHECK-NEXT: 0 | vbase_offset (8) +// CHECK-NEXT: 1 | vbase_offset (8) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test15::D RTTI +// CHECK-NEXT: -- (Test15::A, 0) vtable address -- +// CHECK-NEXT: -- (Test15::D, 0) vtable address -- +// CHECK-NEXT: 4 | void Test15::A::a() +// CHECK-NEXT: 5 | void Test15::D::f() +// CHECK-NEXT: 6 | vbase_offset (0) +// CHECK-NEXT: 7 | vcall_offset (0) +// CHECK-NEXT: 8 | offset_to_top (-8) +// CHECK-NEXT: 9 | Test15::D RTTI +// CHECK-NEXT: -- (Test15::B, 8) vtable address -- +// CHECK-NEXT: -- (Test15::C, 8) vtable address -- +// CHECK-NEXT: 10 | void Test15::B::b() +struct D : A, virtual B, virtual C { + virtual void f(); +}; +void D::f() { } + +} + +namespace Test16 { + +// Test that destructors share vcall offsets. + +struct A { virtual ~A(); }; +struct B { virtual ~B(); }; + +struct C : A, B { virtual ~C(); }; + +// CHECK: Vtable for 'Test16::D' (15 entries). +// CHECK-NEXT: 0 | vbase_offset (8) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test16::D RTTI +// CHECK-NEXT: -- (Test16::D, 0) vtable address -- +// CHECK-NEXT: 3 | void Test16::D::f() +// CHECK-NEXT: 4 | Test16::D::~D() [complete] +// CHECK-NEXT: 5 | Test16::D::~D() [deleting] +// CHECK-NEXT: 6 | vcall_offset (-8) +// CHECK-NEXT: 7 | offset_to_top (-8) +// CHECK-NEXT: 8 | Test16::D RTTI +// CHECK-NEXT: -- (Test16::A, 8) vtable address -- +// CHECK-NEXT: -- (Test16::C, 8) vtable address -- +// CHECK-NEXT: 9 | Test16::D::~D() [complete] +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 10 | Test16::D::~D() [deleting] +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 11 | offset_to_top (-16) +// CHECK-NEXT: 12 | Test16::D RTTI +// CHECK-NEXT: -- (Test16::B, 16) vtable address -- +// CHECK-NEXT: 13 | Test16::D::~D() [complete] +// CHECK-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset] +// CHECK-NEXT: 14 | Test16::D::~D() [deleting] +// CHECK-NEXT: [this adjustment: -8 non-virtual, -24 vcall offset offset] +struct D : virtual C { + virtual void f(); +}; +void D::f() { } + +} + +namespace Test17 { + +// Test that we don't mark E::f in the C-in-E vtable as unused. +struct A { virtual void f(); }; +struct B : virtual A { virtual void f(); }; +struct C : virtual A { virtual void f(); }; +struct D : virtual B, virtual C { virtual void f(); }; + +// CHECK: Vtable for 'Test17::E' (13 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vbase_offset (8) +// CHECK-NEXT: 2 | vbase_offset (0) +// CHECK-NEXT: 3 | vbase_offset (0) +// CHECK-NEXT: 4 | vcall_offset (0) +// CHECK-NEXT: 5 | offset_to_top (0) +// CHECK-NEXT: 6 | Test17::E RTTI +// CHECK-NEXT: -- (Test17::A, 0) vtable address -- +// CHECK-NEXT: -- (Test17::B, 0) vtable address -- +// CHECK-NEXT: -- (Test17::D, 0) vtable address -- +// CHECK-NEXT: -- (Test17::E, 0) vtable address -- +// CHECK-NEXT: 7 | void Test17::E::f() +// CHECK-NEXT: 8 | vbase_offset (-8) +// CHECK-NEXT: 9 | vcall_offset (-8) +// CHECK-NEXT: 10 | offset_to_top (-8) +// CHECK-NEXT: 11 | Test17::E RTTI +// CHECK-NEXT: -- (Test17::A, 8) vtable address -- +// CHECK-NEXT: -- (Test17::C, 8) vtable address -- +// CHECK-NEXT: 12 | void Test17::E::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +class E : virtual D { + virtual void f(); +}; +void E::f() {} + +} + +namespace Test18 { + +// Test that we compute the right 'this' adjustment offsets. + +struct A { + virtual void f(); + virtual void g(); +}; + +struct B : virtual A { + virtual void f(); +}; + +struct C : A, B { + virtual void g(); +}; + +// CHECK: Vtable for 'Test18::D' (24 entries). +// CHECK-NEXT: 0 | vbase_offset (8) +// CHECK-NEXT: 1 | vbase_offset (0) +// CHECK-NEXT: 2 | vbase_offset (0) +// CHECK-NEXT: 3 | vcall_offset (8) +// CHECK-NEXT: 4 | vcall_offset (0) +// CHECK-NEXT: 5 | offset_to_top (0) +// CHECK-NEXT: 6 | Test18::D RTTI +// CHECK-NEXT: -- (Test18::A, 0) vtable address -- +// CHECK-NEXT: -- (Test18::B, 0) vtable address -- +// CHECK-NEXT: -- (Test18::D, 0) vtable address -- +// CHECK-NEXT: 7 | void Test18::D::f() +// CHECK-NEXT: 8 | void Test18::C::g() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-NEXT: 9 | void Test18::D::h() +// CHECK-NEXT: 10 | vcall_offset (0) +// CHECK-NEXT: 11 | vcall_offset (-8) +// CHECK-NEXT: 12 | vbase_offset (-8) +// CHECK-NEXT: 13 | offset_to_top (-8) +// CHECK-NEXT: 14 | Test18::D RTTI +// CHECK-NEXT: -- (Test18::A, 8) vtable address -- +// CHECK-NEXT: -- (Test18::C, 8) vtable address -- +// CHECK-NEXT: 15 | void Test18::D::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -32 vcall offset offset] +// CHECK-NEXT: 16 | void Test18::C::g() +// CHECK-NEXT: 17 | vbase_offset (-16) +// CHECK-NEXT: 18 | vcall_offset (-8) +// CHECK-NEXT: 19 | vcall_offset (-16) +// CHECK-NEXT: 20 | offset_to_top (-16) +// CHECK-NEXT: 21 | Test18::D RTTI +// CHECK-NEXT: -- (Test18::A, 16) vtable address -- +// CHECK-NEXT: -- (Test18::B, 16) vtable address -- +// CHECK-NEXT: 22 | void Test18::D::f() +// CHECK-NEXT: [this adjustment: -8 non-virtual, -32 vcall offset offset] +// CHECK-NEXT: 23 | [unused] void Test18::C::g() +struct D : virtual B, virtual C, virtual A +{ + virtual void f(); + virtual void h(); +}; +void D::f() {} + +} + +namespace Test19 { + +// Another 'this' adjustment test. + +struct A { + int a; + + virtual void f(); +}; + +struct B : A { + int b; + + virtual void g(); +}; + +struct C { + virtual void c(); +}; + +// CHECK: Vtable for 'Test19::D' (13 entries). +// CHECK-NEXT: 0 | vbase_offset (24) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test19::D RTTI +// CHECK-NEXT: -- (Test19::C, 0) vtable address -- +// CHECK-NEXT: -- (Test19::D, 0) vtable address -- +// CHECK-NEXT: 3 | void Test19::C::c() +// CHECK-NEXT: 4 | void Test19::D::f() +// CHECK-NEXT: 5 | offset_to_top (-8) +// CHECK-NEXT: 6 | Test19::D RTTI +// CHECK-NEXT: -- (Test19::A, 8) vtable address -- +// CHECK-NEXT: -- (Test19::B, 8) vtable address -- +// CHECK-NEXT: 7 | void Test19::D::f() +// CHECK-NEXT: [this adjustment: -8 non-virtual] +// CHECK-NEXT: 8 | void Test19::B::g() +// CHECK-NEXT: 9 | vcall_offset (-24) +// CHECK-NEXT: 10 | offset_to_top (-24) +// CHECK-NEXT: 11 | Test19::D RTTI +// CHECK-NEXT: -- (Test19::A, 24) vtable address -- +// CHECK-NEXT: 12 | void Test19::D::f() +// CHECK-NEXT: [this adjustment: 0 non-virtual, -24 vcall offset offset] +struct D : C, B, virtual A { + virtual void f(); +}; +void D::f() { } + +} + +namespace Test20 { + +// pure virtual member functions should never have 'this' adjustments. + +struct A { + virtual void f() = 0; + virtual void g(); +}; + +struct B : A { }; + +// CHECK: Vtable for 'Test20::C' (9 entries). +// CHECK-NEXT: 0 | offset_to_top (0) +// CHECK-NEXT: 1 | Test20::C RTTI +// CHECK-NEXT: -- (Test20::A, 0) vtable address -- +// CHECK-NEXT: -- (Test20::C, 0) vtable address -- +// CHECK-NEXT: 2 | void Test20::C::f() [pure] +// CHECK-NEXT: 3 | void Test20::A::g() +// CHECK-NEXT: 4 | void Test20::C::h() +// CHECK-NEXT: 5 | offset_to_top (-8) +// CHECK-NEXT: 6 | Test20::C RTTI +// CHECK-NEXT: -- (Test20::A, 8) vtable address -- +// CHECK-NEXT: -- (Test20::B, 8) vtable address -- +// CHECK-NEXT: 7 | void Test20::C::f() [pure] +// CHECK-NEXT: 8 | void Test20::A::g() +struct C : A, B { + virtual void f() = 0; + virtual void h(); +}; +void C::h() { } + +} + +namespace Test21 { + +// Test that we get vbase offsets right in secondary vtables. +struct A { + virtual void f(); +}; + +struct B : virtual A { }; +class C : virtual B { }; +class D : virtual C { }; + +class E : virtual C { }; + +// CHECK: Vtable for 'Test21::F' (16 entries). +// CHECK-NEXT: 0 | vbase_offset (8) +// CHECK-NEXT: 1 | vbase_offset (0) +// CHECK-NEXT: 2 | vbase_offset (0) +// CHECK-NEXT: 3 | vbase_offset (0) +// CHECK-NEXT: 4 | vbase_offset (0) +// CHECK-NEXT: 5 | vcall_offset (0) +// CHECK-NEXT: 6 | offset_to_top (0) +// CHECK-NEXT: 7 | Test21::F RTTI +// CHECK-NEXT: -- (Test21::A, 0) vtable address -- +// CHECK-NEXT: -- (Test21::B, 0) vtable address -- +// CHECK-NEXT: -- (Test21::C, 0) vtable address -- +// CHECK-NEXT: -- (Test21::D, 0) vtable address -- +// CHECK-NEXT: -- (Test21::F, 0) vtable address -- +// CHECK-NEXT: 8 | void Test21::F::f() +// CHECK-NEXT: 9 | vbase_offset (-8) +// CHECK-NEXT: 10 | vbase_offset (-8) +// CHECK-NEXT: 11 | vbase_offset (-8) +// CHECK-NEXT: 12 | vcall_offset (-8) +// CHECK-NEXT: 13 | offset_to_top (-8) +// CHECK-NEXT: 14 | Test21::F RTTI +// CHECK-NEXT: -- (Test21::A, 8) vtable address -- +// CHECK-NEXT: -- (Test21::B, 8) vtable address -- +// CHECK-NEXT: -- (Test21::C, 8) vtable address -- +// CHECK-NEXT: -- (Test21::E, 8) vtable address -- +// CHECK-NEXT: 15 | [unused] void Test21::F::f() +class F : virtual D, virtual E { + virtual void f(); +}; +void F::f() { } + +} + +namespace Test22 { + +// Very simple construction vtable test. +struct V1 { + int v1; +}; + +struct V2 : virtual V1 { + int v2; +}; + +// CHECK: Vtable for 'Test22::C' (8 entries). +// CHECK-NEXT: 0 | vbase_offset (16) +// CHECK-NEXT: 1 | vbase_offset (12) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test22::C RTTI +// CHECK-NEXT: -- (Test22::C, 0) vtable address -- +// CHECK-NEXT: 4 | void Test22::C::f() +// CHECK-NEXT: 5 | vbase_offset (-4) +// CHECK-NEXT: 6 | offset_to_top (-16) +// CHECK-NEXT: 7 | Test22::C RTTI +// CHECK-NEXT: -- (Test22::V2, 16) vtable address -- + +// CHECK: Construction vtable for ('Test22::V2', 16) in 'Test22::C' (3 entries). +// CHECK-NEXT: 0 | vbase_offset (-4) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test22::V2 RTTI + +struct C : virtual V1, virtual V2 { + int c; + virtual void f(); +}; +void C::f() { } + +} + +namespace Test23 { + +struct A { + int a; +}; + +struct B : virtual A { + int b; +}; + +struct C : A, virtual B { + int c; +}; + +// CHECK: Vtable for 'Test23::D' (7 entries). +// CHECK-NEXT: 0 | vbase_offset (20) +// CHECK-NEXT: 1 | vbase_offset (24) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test23::D RTTI +// CHECK-NEXT: -- (Test23::C, 0) vtable address -- +// CHECK-NEXT: -- (Test23::D, 0) vtable address -- +// CHECK-NEXT: 4 | vbase_offset (-4) +// CHECK-NEXT: 5 | offset_to_top (-24) +// CHECK-NEXT: 6 | Test23::D RTTI +// CHECK-NEXT: -- (Test23::B, 24) vtable address -- + +// CHECK: Construction vtable for ('Test23::C', 0) in 'Test23::D' (7 entries). +// CHECK-NEXT: 0 | vbase_offset (20) +// CHECK-NEXT: 1 | vbase_offset (24) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test23::C RTTI +// CHECK-NEXT: -- (Test23::C, 0) vtable address -- +// CHECK-NEXT: 4 | vbase_offset (-4) +// CHECK-NEXT: 5 | offset_to_top (-24) +// CHECK-NEXT: 6 | Test23::C RTTI +// CHECK-NEXT: -- (Test23::B, 24) vtable address -- + +// CHECK: Construction vtable for ('Test23::B', 24) in 'Test23::D' (3 entries). +// CHECK-NEXT: 0 | vbase_offset (-4) +// CHECK-NEXT: 1 | offset_to_top (0) +// CHECK-NEXT: 2 | Test23::B RTTI +// CHECK-NEXT: -- (Test23::B, 24) vtable address -- + +struct D : virtual A, virtual B, C { + int d; + + void f(); +}; +void D::f() { } + +} + +namespace Test24 { + +// Another construction vtable test. + +struct A { + virtual void f(); +}; + +struct B : virtual A { }; +struct C : virtual A { }; + +// CHECK: Vtable for 'Test24::D' (10 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test24::D RTTI +// CHECK-NEXT: -- (Test24::A, 0) vtable address -- +// CHECK-NEXT: -- (Test24::B, 0) vtable address -- +// CHECK-NEXT: -- (Test24::D, 0) vtable address -- +// CHECK-NEXT: 4 | void Test24::D::f() +// CHECK-NEXT: 5 | vbase_offset (-8) +// CHECK-NEXT: 6 | vcall_offset (-8) +// CHECK-NEXT: 7 | offset_to_top (-8) +// CHECK-NEXT: 8 | Test24::D RTTI +// CHECK-NEXT: -- (Test24::A, 8) vtable address -- +// CHECK-NEXT: -- (Test24::C, 8) vtable address -- +// CHECK-NEXT: 9 | [unused] void Test24::D::f() + +// CHECK: Construction vtable for ('Test24::B', 0) in 'Test24::D' (5 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test24::B RTTI +// CHECK-NEXT: -- (Test24::A, 0) vtable address -- +// CHECK-NEXT: -- (Test24::B, 0) vtable address -- +// CHECK-NEXT: 4 | void Test24::A::f() + +// CHECK: Construction vtable for ('Test24::C', 8) in 'Test24::D' (9 entries). +// CHECK-NEXT: 0 | vbase_offset (-8) +// CHECK-NEXT: 1 | vcall_offset (-8) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test24::C RTTI +// CHECK-NEXT: -- (Test24::A, 8) vtable address -- +// CHECK-NEXT: -- (Test24::C, 8) vtable address -- +// CHECK-NEXT: 4 | [unused] void Test24::A::f() +// CHECK-NEXT: 5 | vcall_offset (0) +// CHECK-NEXT: 6 | offset_to_top (8) +// CHECK-NEXT: 7 | Test24::C RTTI +// CHECK-NEXT: -- (Test24::A, 0) vtable address -- +// CHECK-NEXT: 8 | void Test24::A::f() +struct D : B, C { + virtual void f(); +}; +void D::f() { } + +} + +namespace Test25 { + +// This mainly tests that we don't assert on this class hierarchy. + +struct V { + virtual void f(); +}; + +struct A : virtual V { }; +struct B : virtual V { }; + +// CHECK: Vtable for 'Test25::C' (11 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test25::C RTTI +// CHECK-NEXT: -- (Test25::A, 0) vtable address -- +// CHECK-NEXT: -- (Test25::C, 0) vtable address -- +// CHECK-NEXT: -- (Test25::V, 0) vtable address -- +// CHECK-NEXT: 4 | void Test25::V::f() +// CHECK-NEXT: 5 | void Test25::C::g() +// CHECK-NEXT: 6 | vbase_offset (-8) +// CHECK-NEXT: 7 | vcall_offset (-8) +// CHECK-NEXT: 8 | offset_to_top (-8) +// CHECK-NEXT: 9 | Test25::C RTTI +// CHECK-NEXT: -- (Test25::B, 8) vtable address -- +// CHECK-NEXT: -- (Test25::V, 8) vtable address -- +// CHECK-NEXT: 10 | [unused] void Test25::V::f() + +// CHECK: Construction vtable for ('Test25::A', 0) in 'Test25::C' (5 entries). +// CHECK-NEXT: 0 | vbase_offset (0) +// CHECK-NEXT: 1 | vcall_offset (0) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test25::A RTTI +// CHECK-NEXT: -- (Test25::A, 0) vtable address -- +// CHECK-NEXT: -- (Test25::V, 0) vtable address -- +// CHECK-NEXT: 4 | void Test25::V::f() + +// CHECK: Construction vtable for ('Test25::B', 8) in 'Test25::C' (9 entries). +// CHECK-NEXT: 0 | vbase_offset (-8) +// CHECK-NEXT: 1 | vcall_offset (-8) +// CHECK-NEXT: 2 | offset_to_top (0) +// CHECK-NEXT: 3 | Test25::B RTTI +// CHECK-NEXT: -- (Test25::B, 8) vtable address -- +// CHECK-NEXT: -- (Test25::V, 8) vtable address -- +// CHECK-NEXT: 4 | [unused] void Test25::V::f() +// CHECK-NEXT: 5 | vcall_offset (0) +// CHECK-NEXT: 6 | offset_to_top (8) +// CHECK-NEXT: 7 | Test25::B RTTI +// CHECK-NEXT: -- (Test25::V, 0) vtable address -- +// CHECK-NEXT: 8 | void Test25::V::f() +struct C : A, virtual V, B { + virtual void g(); +}; +void C::g() { } + +} diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp index 92e0117..75620ab 100644 --- a/test/CodeGenCXX/vtable-pointer-initialization.cpp +++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp @@ -19,14 +19,14 @@ struct A : Base { Field field; }; -// CHECK: define void @_ZN1AC1Ev( +// CHECK: define void @_ZN1AC2Ev( // CHECK: call void @_ZN4BaseC2Ev( // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) // CHECK: call void @_ZN5FieldC1Ev( // CHECK: ret void A::A() { } -// CHECK: define void @_ZN1AD1Ev( +// CHECK: define void @_ZN1AD2Ev( // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( @@ -42,13 +42,16 @@ struct B : Base { void f() { B b; } // CHECK: define linkonce_odr void @_ZN1BC1Ev( -// CHECK: call void @_ZN4BaseC2Ev( -// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) -// CHECK: call void @_ZN5FieldC1Ev -// CHECK: ret void +// CHECK: call void @_ZN1BC2Ev( // CHECK: define linkonce_odr void @_ZN1BD1Ev( // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) // CHECK: call void @_ZN5FieldD1Ev( // CHECK: call void @_ZN4BaseD2Ev( // CHECK: ret void + +// CHECK: define linkonce_odr void @_ZN1BC2Ev( +// CHECK: call void @_ZN4BaseC2Ev( +// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2) +// CHECK: call void @_ZN5FieldC1Ev +// CHECK: ret void diff --git a/test/CodeGenObjC/messages-2.m b/test/CodeGenObjC/messages-2.m index 2a6e3dc..05e30ab 100644 --- a/test/CodeGenObjC/messages-2.m +++ b/test/CodeGenObjC/messages-2.m @@ -136,4 +136,7 @@ typedef struct { x.height *= 2; return x; } +-(const float) returnAConstFloat { + return 5; +} @end diff --git a/test/CodeGenObjC/stand-alone-implementation.m b/test/CodeGenObjC/stand-alone-implementation.m new file mode 100644 index 0000000..a519495 --- /dev/null +++ b/test/CodeGenObjC/stand-alone-implementation.m @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-X86-64 %s + +// radar 7547942 +// Allow injection of ivars into implementation's implicit class. + +@implementation INTFSTANDALONE // expected-warning {{cannot find interface declaration for 'INTFSTANDALONE'}} +{ + id IVAR1; + id IVAR2; +} +- (id) Meth { return IVAR1; } +@end + +// CHECK-X86-64: @"OBJC_IVAR_$_INTFSTANDALONE.IVAR1" +// CHECK-X86-64: @"OBJC_IVAR_$_INTFSTANDALONE.IVAR2" + diff --git a/test/Driver/clang-c-as-cxx.c b/test/Driver/clang-c-as-cxx.c new file mode 100644 index 0000000..0e28178 --- /dev/null +++ b/test/Driver/clang-c-as-cxx.c @@ -0,0 +1,6 @@ +// RUN: %clangxx -### %s 2>&1 | FileCheck %s +// +// PR5803 +// +// CHECK: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated +// CHECK: "-cc1" {{.*}} "-x" "c++" diff --git a/test/Index/Inputs/cindex-from-source.h b/test/Index/Inputs/cindex-from-source.h new file mode 100644 index 0000000..d13d397 --- /dev/null +++ b/test/Index/Inputs/cindex-from-source.h @@ -0,0 +1 @@ +typedef int t0; diff --git a/test/Index/annotate-tokens.c b/test/Index/annotate-tokens.c index ef0069c..7fbf9cc 100644 --- a/test/Index/annotate-tokens.c +++ b/test/Index/annotate-tokens.c @@ -61,4 +61,5 @@ void f(void *ptr) { // CHECK: Literal: ""Hello"" [9:24 - 9:31] // CHECK: Punctuation: ";" [9:31 - 9:32] // CHECK: Punctuation: "}" [10:1 - 10:2] - +// RUN: c-index-test -test-annotate-tokens=%s:4:1:165:32 %s | FileCheck %s +// RUN: c-index-test -test-annotate-tokens=%s:4:1:165:38 %s | FileCheck %s diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m index cd0c868..5b2f86e 100644 --- a/test/Index/c-index-api-loadTU-test.m +++ b/test/Index/c-index-api-loadTU-test.m @@ -3,8 +3,9 @@ @interface Foo { + __attribute__((iboutlet)) id myoutlet; } - +- (void) __attribute__((ibaction)) myMessage:(id)msg; - foo; + fooC; @@ -53,79 +54,71 @@ int main (int argc, const char * argv[]) { main(someEnum, (const char **)bee); } -// CHECK: <invalid loc>:0:0: TypedefDecl=__int128_t:0:0 (Definition) -// CHECK: <invalid loc>:0:0: TypedefDecl=__uint128_t:0:0 (Definition) -// CHECK: <invalid loc>:0:0: TypedefDecl=SEL:0:0 (Definition) -// CHECK: <invalid loc>:0:0: TypeRef=SEL:0:0 -// CHECK: <invalid loc>:0:0: TypedefDecl=id:0:0 (Definition) -// CHECK: <invalid loc>:0:0: TypedefDecl=Class:0:0 (Definition) -// CHECK: <invalid loc>:87:16: StructDecl=__va_list_tag:87:16 (Definition) -// CHECK: <invalid loc>:87:42: FieldDecl=gp_offset:87:42 (Definition) -// CHECK: <invalid loc>:87:63: FieldDecl=fp_offset:87:63 (Definition) -// CHECK: <invalid loc>:87:81: FieldDecl=overflow_arg_area:87:81 (Definition) -// CHECK: <invalid loc>:87:107: FieldDecl=reg_save_area:87:107 (Definition) -// CHECK: <invalid loc>:87:123: TypedefDecl=__va_list_tag:87:123 (Definition) -// CHECK: <invalid loc>:87:16: TypeRef=struct __va_list_tag:87:16 -// CHECK: <invalid loc>:87:159: TypedefDecl=__builtin_va_list:87:159 (Definition) -// CHECK: <invalid loc>:87:145: TypeRef=__va_list_tag:87:123 -// CHECK: <invalid loc>:87:177: UnexposedExpr= -// CHECK: c-index-api-loadTU-test.m:4:12: ObjCInterfaceDecl=Foo:4:12 Extent=[4:1 - 11:5] -// CHECK: c-index-api-loadTU-test.m:8:1: ObjCInstanceMethodDecl=foo:8:1 Extent=[8:1 - 8:7] -// CHECK: c-index-api-loadTU-test.m:9:1: ObjCClassMethodDecl=fooC:9:1 Extent=[9:1 - 9:8] -// CHECK: c-index-api-loadTU-test.m:13:12: ObjCInterfaceDecl=Bar:13:12 Extent=[13:1 - 17:5] -// CHECK: c-index-api-loadTU-test.m:13:18: ObjCSuperClassRef=Foo:4:12 Extent=[13:18 - 13:21] -// CHECK: c-index-api-loadTU-test.m:19:12: ObjCCategoryDecl=FooCat:19:12 Extent=[19:1 - 22:5] -// CHECK: c-index-api-loadTU-test.m:19:12: ObjCClassRef=Foo:4:12 Extent=[19:12 - 19:15] -// CHECK: c-index-api-loadTU-test.m:20:1: ObjCInstanceMethodDecl=catMethodWithFloat::20:1 Extent=[20:1 - 20:41] -// CHECK: c-index-api-loadTU-test.m:20:36: ParmDecl=fArg:20:36 (Definition) Extent=[20:29 - 20:40] -// CHECK: c-index-api-loadTU-test.m:21:1: ObjCInstanceMethodDecl=floatMethod:21:1 Extent=[21:1 - 21:23] -// CHECK: c-index-api-loadTU-test.m:24:1: ObjCProtocolDecl=Proto:24:1 (Definition) Extent=[24:1 - 26:5] -// CHECK: c-index-api-loadTU-test.m:25:1: ObjCInstanceMethodDecl=pMethod:25:1 Extent=[25:1 - 25:11] -// CHECK: c-index-api-loadTU-test.m:28:1: ObjCProtocolDecl=SubP:28:1 (Definition) Extent=[28:1 - 30:5] -// CHECK: c-index-api-loadTU-test.m:28:17: ObjCProtocolRef=Proto:24:1 Extent=[28:17 - 28:22] -// CHECK: c-index-api-loadTU-test.m:29:1: ObjCInstanceMethodDecl=spMethod:29:1 Extent=[29:1 - 29:12] -// CHECK: c-index-api-loadTU-test.m:32:12: ObjCInterfaceDecl=Baz:32:12 Extent=[32:1 - 39:5] -// CHECK: c-index-api-loadTU-test.m:32:18: ObjCSuperClassRef=Bar:13:12 Extent=[32:18 - 32:21] -// CHECK: c-index-api-loadTU-test.m:32:23: ObjCProtocolRef=SubP:28:1 Extent=[32:23 - 32:27] -// CHECK: c-index-api-loadTU-test.m:34:9: ObjCIvarDecl=_anIVar:34:9 (Definition) Extent=[34:9 - 34:16] -// CHECK: c-index-api-loadTU-test.m:37:1: ObjCInstanceMethodDecl=bazMethod:37:1 Extent=[37:1 - 37:21] -// CHECK: c-index-api-loadTU-test.m:41:1: EnumDecl=:41:1 (Definition) Extent=[41:1 - 43:2] -// CHECK: c-index-api-loadTU-test.m:42:3: EnumConstantDecl=someEnum:42:3 (Definition) Extent=[42:3 - 42:11] -// CHECK: c-index-api-loadTU-test.m:45:5: FunctionDecl=main:45:5 (Definition) Extent=[45:5 - 54:2] -// CHECK: c-index-api-loadTU-test.m:45:15: ParmDecl=argc:45:15 (Definition) Extent=[45:11 - 45:19] -// CHECK: c-index-api-loadTU-test.m:45:34: ParmDecl=argv:45:34 (Definition) Extent=[45:27 - 45:38] -// CHECK: c-index-api-loadTU-test.m:45:5: UnexposedStmt= Extent=[45:42 - 54:2] -// CHECK: c-index-api-loadTU-test.m:45:5: UnexposedStmt= Extent=[46:2 - 46:12] -// CHECK: c-index-api-loadTU-test.m:46:8: VarDecl=bee:46:8 (Definition) Extent=[46:2 - 46:11] -// CHECK: c-index-api-loadTU-test.m:46:2: ObjCClassRef=Baz:32:12 Extent=[46:2 - 46:5] -// CHECK: c-index-api-loadTU-test.m:46:8: UnexposedStmt= Extent=[47:2 - 47:19] -// CHECK: c-index-api-loadTU-test.m:47:5: VarDecl=a:47:5 (Definition) Extent=[47:2 - 47:18] -// CHECK: c-index-api-loadTU-test.m:47:2: TypeRef=id:0:0 Extent=[47:2 - 47:4] -// CHECK: c-index-api-loadTU-test.m:47:9: ObjCMessageExpr=foo:8:1 Extent=[47:9 - 47:18] -// CHECK: c-index-api-loadTU-test.m:47:10: DeclRefExpr=bee:46:8 Extent=[47:10 - 47:13] -// CHECK: c-index-api-loadTU-test.m:47:5: UnexposedStmt= Extent=[48:2 - 48:27] -// CHECK: c-index-api-loadTU-test.m:48:12: VarDecl=c:48:12 (Definition) Extent=[48:2 - 48:26] +// CHECK: c-index-api-loadTU-test.m:4:12: ObjCInterfaceDecl=Foo:4:12 Extent=[4:1 - 12:5] +// CHECK: c-index-api-loadTU-test.m:6:32: ObjCIvarDecl=myoutlet:6:32 (Definition) Extent=[6:32 - 6:40] +// CHECK: c-index-api-loadTU-test.m:6:32: attribute(iboutlet)= Extent=[6:32 - 6:40] +// CHECK: c-index-api-loadTU-test.m:6:29: TypeRef=id:0:0 Extent=[6:29 - 6:31] +// CHECK: c-index-api-loadTU-test.m:8:1: ObjCInstanceMethodDecl=myMessage::8:1 Extent=[8:1 - 8:54] +// CHECK: c-index-api-loadTU-test.m:8:1: attribute(ibaction)= Extent=[8:1 - 8:54] +// CHECK: c-index-api-loadTU-test.m:8:50: ParmDecl=msg:8:50 (Definition) Extent=[8:47 - 8:53] +// CHECK: c-index-api-loadTU-test.m:8:47: TypeRef=id:0:0 Extent=[8:47 - 8:49] +// CHECK: c-index-api-loadTU-test.m:9:1: ObjCInstanceMethodDecl=foo:9:1 Extent=[9:1 - 9:7] +// CHECK: c-index-api-loadTU-test.m:10:1: ObjCClassMethodDecl=fooC:10:1 Extent=[10:1 - 10:8] +// CHECK: c-index-api-loadTU-test.m:14:12: ObjCInterfaceDecl=Bar:14:12 Extent=[14:1 - 18:5] +// CHECK: c-index-api-loadTU-test.m:14:18: ObjCSuperClassRef=Foo:4:12 Extent=[14:18 - 14:21] +// CHECK: c-index-api-loadTU-test.m:20:12: ObjCCategoryDecl=FooCat:20:12 Extent=[20:1 - 23:5] +// CHECK: c-index-api-loadTU-test.m:20:12: ObjCClassRef=Foo:4:12 Extent=[20:12 - 20:15] +// CHECK: c-index-api-loadTU-test.m:21:1: ObjCInstanceMethodDecl=catMethodWithFloat::21:1 Extent=[21:1 - 21:41] +// CHECK: c-index-api-loadTU-test.m:21:36: ParmDecl=fArg:21:36 (Definition) Extent=[21:29 - 21:40] +// CHECK: c-index-api-loadTU-test.m:22:1: ObjCInstanceMethodDecl=floatMethod:22:1 Extent=[22:1 - 22:23] +// CHECK: c-index-api-loadTU-test.m:25:1: ObjCProtocolDecl=Proto:25:1 (Definition) Extent=[25:1 - 27:5] +// CHECK: c-index-api-loadTU-test.m:26:1: ObjCInstanceMethodDecl=pMethod:26:1 Extent=[26:1 - 26:11] +// CHECK: c-index-api-loadTU-test.m:29:1: ObjCProtocolDecl=SubP:29:1 (Definition) Extent=[29:1 - 31:5] +// CHECK: c-index-api-loadTU-test.m:29:17: ObjCProtocolRef=Proto:25:1 Extent=[29:17 - 29:22] +// CHECK: c-index-api-loadTU-test.m:30:1: ObjCInstanceMethodDecl=spMethod:30:1 Extent=[30:1 - 30:12] +// CHECK: c-index-api-loadTU-test.m:33:12: ObjCInterfaceDecl=Baz:33:12 Extent=[33:1 - 40:5] +// CHECK: c-index-api-loadTU-test.m:33:18: ObjCSuperClassRef=Bar:14:12 Extent=[33:18 - 33:21] +// CHECK: c-index-api-loadTU-test.m:33:23: ObjCProtocolRef=SubP:29:1 Extent=[33:23 - 33:27] +// CHECK: c-index-api-loadTU-test.m:35:9: ObjCIvarDecl=_anIVar:35:9 (Definition) Extent=[35:9 - 35:16] +// CHECK: c-index-api-loadTU-test.m:38:1: ObjCInstanceMethodDecl=bazMethod:38:1 Extent=[38:1 - 38:21] +// CHECK: c-index-api-loadTU-test.m:42:1: EnumDecl=:42:1 (Definition) Extent=[42:1 - 44:2] +// CHECK: c-index-api-loadTU-test.m:43:3: EnumConstantDecl=someEnum:43:3 (Definition) Extent=[43:3 - 43:11] +// CHECK: c-index-api-loadTU-test.m:46:5: FunctionDecl=main:46:5 (Definition) Extent=[46:5 - 55:2] +// CHECK: c-index-api-loadTU-test.m:46:15: ParmDecl=argc:46:15 (Definition) Extent=[46:11 - 46:19] +// CHECK: c-index-api-loadTU-test.m:46:34: ParmDecl=argv:46:34 (Definition) Extent=[46:27 - 46:38] +// CHECK: c-index-api-loadTU-test.m:46:5: UnexposedStmt= Extent=[46:42 - 55:2] +// CHECK: c-index-api-loadTU-test.m:46:5: UnexposedStmt= Extent=[47:2 - 47:12] +// CHECK: c-index-api-loadTU-test.m:47:8: VarDecl=bee:47:8 (Definition) Extent=[47:2 - 47:11] +// CHECK: c-index-api-loadTU-test.m:47:2: ObjCClassRef=Baz:33:12 Extent=[47:2 - 47:5] +// CHECK: c-index-api-loadTU-test.m:47:8: UnexposedStmt= Extent=[48:2 - 48:19] +// CHECK: c-index-api-loadTU-test.m:48:5: VarDecl=a:48:5 (Definition) Extent=[48:2 - 48:18] // CHECK: c-index-api-loadTU-test.m:48:2: TypeRef=id:0:0 Extent=[48:2 - 48:4] -// CHECK: c-index-api-loadTU-test.m:48:6: ObjCProtocolRef=SubP:28:1 Extent=[48:6 - 48:10] -// CHECK: c-index-api-loadTU-test.m:48:16: UnexposedExpr=fooC:9:1 Extent=[48:16 - 48:26] -// CHECK: c-index-api-loadTU-test.m:48:16: ObjCMessageExpr=fooC:9:1 Extent=[48:16 - 48:26] -// CHECK: c-index-api-loadTU-test.m:48:12: UnexposedStmt= Extent=[49:2 - 49:15] -// CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 (Definition) Extent=[49:2 - 49:14] +// CHECK: c-index-api-loadTU-test.m:48:9: ObjCMessageExpr=foo:9:1 Extent=[48:9 - 48:18] +// CHECK: c-index-api-loadTU-test.m:48:10: DeclRefExpr=bee:47:8 Extent=[48:10 - 48:13] +// CHECK: c-index-api-loadTU-test.m:48:5: UnexposedStmt= Extent=[49:2 - 49:27] +// CHECK: c-index-api-loadTU-test.m:49:12: VarDecl=c:49:12 (Definition) Extent=[49:2 - 49:26] // CHECK: c-index-api-loadTU-test.m:49:2: TypeRef=id:0:0 Extent=[49:2 - 49:4] -// CHECK: c-index-api-loadTU-test.m:49:6: ObjCProtocolRef=Proto:24:1 Extent=[49:6 - 49:11] -// CHECK: c-index-api-loadTU-test.m:50:2: UnexposedExpr= Extent=[50:2 - 50:7] -// CHECK: c-index-api-loadTU-test.m:50:2: DeclRefExpr=d:49:13 Extent=[50:2 - 50:3] -// CHECK: c-index-api-loadTU-test.m:50:6: UnexposedExpr=c:48:12 Extent=[50:6 - 50:7] -// CHECK: c-index-api-loadTU-test.m:50:6: DeclRefExpr=c:48:12 Extent=[50:6 - 50:7] -// CHECK: c-index-api-loadTU-test.m:51:2: ObjCMessageExpr=pMethod:25:1 Extent=[51:2 - 51:13] -// CHECK: c-index-api-loadTU-test.m:51:3: DeclRefExpr=d:49:13 Extent=[51:3 - 51:4] -// CHECK: c-index-api-loadTU-test.m:52:2: ObjCMessageExpr=catMethodWithFloat::20:1 Extent=[52:2 - 52:44] -// CHECK: c-index-api-loadTU-test.m:52:3: DeclRefExpr=bee:46:8 Extent=[52:3 - 52:6] -// CHECK: c-index-api-loadTU-test.m:52:26: ObjCMessageExpr=floatMethod:21:1 Extent=[52:26 - 52:43] -// CHECK: c-index-api-loadTU-test.m:52:27: DeclRefExpr=bee:46:8 Extent=[52:27 - 52:30] -// CHECK: c-index-api-loadTU-test.m:53:3: CallExpr=main:45:5 Extent=[53:3 - 53:37] -// CHECK: c-index-api-loadTU-test.m:53:3: UnexposedExpr=main:45:5 Extent=[53:3 - 53:7] -// CHECK: c-index-api-loadTU-test.m:53:3: DeclRefExpr=main:45:5 Extent=[53:3 - 53:7] -// CHECK: c-index-api-loadTU-test.m:53:8: DeclRefExpr=someEnum:42:3 Extent=[53:8 - 53:16] -// CHECK: c-index-api-loadTU-test.m:53:18: UnexposedExpr=bee:46:8 Extent=[53:18 - 53:36] -// CHECK: c-index-api-loadTU-test.m:53:33: DeclRefExpr=bee:46:8 Extent=[53:33 - 53:36] +// CHECK: c-index-api-loadTU-test.m:49:6: ObjCProtocolRef=SubP:29:1 Extent=[49:6 - 49:10] +// CHECK: c-index-api-loadTU-test.m:49:16: UnexposedExpr=fooC:10:1 Extent=[49:16 - 49:26] +// CHECK: c-index-api-loadTU-test.m:49:16: ObjCMessageExpr=fooC:10:1 Extent=[49:16 - 49:26] +// CHECK: c-index-api-loadTU-test.m:49:12: UnexposedStmt= Extent=[50:2 - 50:15] +// CHECK: c-index-api-loadTU-test.m:50:13: VarDecl=d:50:13 (Definition) Extent=[50:2 - 50:14] +// CHECK: c-index-api-loadTU-test.m:50:2: TypeRef=id:0:0 Extent=[50:2 - 50:4] +// CHECK: c-index-api-loadTU-test.m:50:6: ObjCProtocolRef=Proto:25:1 Extent=[50:6 - 50:11] +// CHECK: c-index-api-loadTU-test.m:51:2: UnexposedExpr= Extent=[51:2 - 51:7] +// CHECK: c-index-api-loadTU-test.m:51:2: DeclRefExpr=d:50:13 Extent=[51:2 - 51:3] +// CHECK: c-index-api-loadTU-test.m:51:6: UnexposedExpr=c:49:12 Extent=[51:6 - 51:7] +// CHECK: c-index-api-loadTU-test.m:51:6: DeclRefExpr=c:49:12 Extent=[51:6 - 51:7] +// CHECK: c-index-api-loadTU-test.m:52:2: ObjCMessageExpr=pMethod:26:1 Extent=[52:2 - 52:13] +// CHECK: c-index-api-loadTU-test.m:52:3: DeclRefExpr=d:50:13 Extent=[52:3 - 52:4] +// CHECK: c-index-api-loadTU-test.m:53:2: ObjCMessageExpr=catMethodWithFloat::21:1 Extent=[53:2 - 53:44] +// CHECK: c-index-api-loadTU-test.m:53:3: DeclRefExpr=bee:47:8 Extent=[53:3 - 53:6] +// CHECK: c-index-api-loadTU-test.m:53:26: ObjCMessageExpr=floatMethod:22:1 Extent=[53:26 - 53:43] +// CHECK: c-index-api-loadTU-test.m:53:27: DeclRefExpr=bee:47:8 Extent=[53:27 - 53:30] +// CHECK: c-index-api-loadTU-test.m:54:3: CallExpr=main:46:5 Extent=[54:3 - 54:37] +// CHECK: c-index-api-loadTU-test.m:54:3: UnexposedExpr=main:46:5 Extent=[54:3 - 54:7] +// CHECK: c-index-api-loadTU-test.m:54:3: DeclRefExpr=main:46:5 Extent=[54:3 - 54:7] +// CHECK: c-index-api-loadTU-test.m:54:8: DeclRefExpr=someEnum:43:3 Extent=[54:8 - 54:16] +// CHECK: c-index-api-loadTU-test.m:54:18: UnexposedExpr=bee:47:8 Extent=[54:18 - 54:36] +// CHECK: c-index-api-loadTU-test.m:54:33: DeclRefExpr=bee:47:8 Extent=[54:33 - 54:36] + diff --git a/test/Index/cindex-from-source.m b/test/Index/cindex-from-source.m index 6c5d936..86e794d 100644 --- a/test/Index/cindex-from-source.m +++ b/test/Index/cindex-from-source.m @@ -1,5 +1,5 @@ -// RUN: echo 'typedef int t0;' > %t.pfx.h -// RUN: %clang -x objective-c-header %t.pfx.h -o %t.pfx.h.gch + +// RUN: %clang -x objective-c-header %S/Inputs/cindex-from-source.h -o %t.pfx.h.gch // RUN: c-index-test -test-load-source local %s -include %t.pfx.h > %t // RUN: FileCheck %s < %t // CHECK: cindex-from-source.m:{{.*}}:{{.*}}: StructDecl=s0:{{.*}}:{{.*}} diff --git a/test/Index/cindex-on-invalid.m b/test/Index/cindex-on-invalid.m index 651c40a..7e190eb 100644 --- a/test/Index/cindex-on-invalid.m +++ b/test/Index/cindex-on-invalid.m @@ -1,6 +1,5 @@ // RUN: not c-index-test -test-load-source local %s > %t 2> %t.err // RUN: FileCheck %s < %t.err - // CHECK: error: expected identifier or '(' // CHECK: Unable to load translation unit! diff --git a/test/Index/code-complete-errors.c b/test/Index/code-complete-errors.c index 520a8c8..29c2a86 100644 --- a/test/Index/code-complete-errors.c +++ b/test/Index/code-complete-errors.c @@ -7,7 +7,7 @@ struct s { struct s s0 = { y: 5 }; // CHECK: code-complete-errors.c:7:20: warning: use of GNU old-style field designator extension // CHECK: FIX-IT: Replace [7:17 - 7:19] with ".y = " int f(int *ptr1, float *ptr2) { - return ptr1 != ptr2; // CHECK: code-complete-errors.c:10:15:[10:10 - 10:14][10:18 - 10:22]: warning: comparison of distinct pointer types ('int *' and 'float *') + return ptr1 != ptr2; // CHECK: code-complete-errors.c:10:15:{10:10-10:14}{10:18-10:22}: warning: comparison of distinct pointer types ('int *' and 'float *') } void g() { } diff --git a/test/Index/linkage.c b/test/Index/linkage.c new file mode 100644 index 0000000..b597c26 --- /dev/null +++ b/test/Index/linkage.c @@ -0,0 +1,23 @@ +// RUN: c-index-test -test-print-linkage-source %s | FileCheck %s + +enum Baz { Qux = 0 }; +int x; +void foo(); +static int w; +void bar(int y) { + static int z; + int k; +} +extern int n; + +// CHECK: EnumDecl=Baz:3:6 (Definition)linkage=External +// CHECK: EnumConstantDecl=Qux:3:12 (Definition)linkage=External +// CHECK: VarDecl=x:4:5linkage=External +// CHECK: FunctionDecl=foo:5:6linkage=External +// CHECK: VarDecl=w:6:12linkage=External +// CHECK: FunctionDecl=bar:7:6 (Definition)linkage=External +// CHECK: ParmDecl=y:7:14 (Definition)linkage=External +// CHECK: VarDecl=z:8:14 (Definition)linkage=External +// CHECK: VarDecl=k:9:7 (Definition)linkage=External +// CHECK: VarDecl=n:11:12 + diff --git a/test/Lexer/constants.c b/test/Lexer/constants.c index 104a3a2..b833e7b 100644 --- a/test/Lexer/constants.c +++ b/test/Lexer/constants.c @@ -38,20 +38,20 @@ char f = 'abcd'; // ignored. float t0[] = { 1.9e20f, 1.9e-20f, - 1.9e50f, // expected-error {{too large}} - 1.9e-50f, // expected-error {{too small}} + 1.9e50f, // expected-warning {{too large}} + 1.9e-50f, // expected-warning {{too small}} -1.9e20f, -1.9e-20f, - -1.9e50f, // expected-error {{too large}} - -1.9e-50f // expected-error {{too small}} + -1.9e50f, // expected-warning {{too large}} + -1.9e-50f // expected-warning {{too small}} }; double t1[] = { 1.9e50, 1.9e-50, - 1.9e500, // expected-error {{too large}} - 1.9e-500, // expected-error {{too small}} + 1.9e500, // expected-warning {{too large}} + 1.9e-500, // expected-warning {{too small}} -1.9e50, -1.9e-50, - -1.9e500, // expected-error {{too large}} - -1.9e-500 // expected-error {{too small}} + -1.9e500, // expected-warning {{too large}} + -1.9e-500 // expected-warning {{too small}} }; diff --git a/test/PCH/Inputs/namespaces.h b/test/PCH/Inputs/namespaces.h new file mode 100644 index 0000000..1bab746 --- /dev/null +++ b/test/PCH/Inputs/namespaces.h @@ -0,0 +1,13 @@ +// Header for PCH test namespaces.cpp + +namespace N1 { + typedef int t1; +} + +namespace N1 { + typedef int t2; +} + +namespace N2 { + typedef float t1; +} diff --git a/test/PCH/namespaces.cpp b/test/PCH/namespaces.cpp new file mode 100644 index 0000000..eef9e06 --- /dev/null +++ b/test/PCH/namespaces.cpp @@ -0,0 +1,14 @@ +// Test this without pch. +// RUN: %clang_cc1 -x c++ -include %S/Inputs/namespaces.h -fsyntax-only %s + +// Test with pch. +// RUN: %clang_cc1 -x c++ -emit-pch -o %t %S/Inputs/namespaces.h +// RUN: %clang_cc1 -x c++ -include-pch %t -fsyntax-only %s + +int int_val; +N1::t1 *ip1 = &int_val; +N1::t2 *ip2 = &int_val; + +float float_val; +namespace N2 { } +N2::t1 *fp1 = &float_val; diff --git a/test/Parser/MicrosoftExtensions.c b/test/Parser/MicrosoftExtensions.c index 082929f..0b2733e 100644 --- a/test/Parser/MicrosoftExtensions.c +++ b/test/Parser/MicrosoftExtensions.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -fms-extensions -x objective-c++ %s +// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify -fms-extensions -x objective-c++ %s __stdcall int func0(); int __stdcall func(); typedef int (__cdecl *tptr)(); diff --git a/test/Parser/cxx-decl.cpp b/test/Parser/cxx-decl.cpp index f37604c..c8f2c0b 100644 --- a/test/Parser/cxx-decl.cpp +++ b/test/Parser/cxx-decl.cpp @@ -58,3 +58,7 @@ struct test4 { int y; int z // expected-error {{expected ';' at end of declaration list}} }; + +// PR5825 +struct test5 {}; +::new(static_cast<void*>(0)) test5; // expected-error {{expected unqualified-id}} diff --git a/test/Parser/cxx-template-argument.cpp b/test/Parser/cxx-template-argument.cpp index 80389a0..532b4c9 100644 --- a/test/Parser/cxx-template-argument.cpp +++ b/test/Parser/cxx-template-argument.cpp @@ -5,5 +5,5 @@ template<typename T> struct A {}; // Check for template argument lists followed by junk // FIXME: The diagnostics here aren't great... A<int+> int x; // expected-error {{expected '>'}} expected-error {{expected unqualified-id}} -A<int x; // expected-error {{expected '>'}} expected-error {{C++ requires a type specifier for all declarations}} +A<int x; // expected-error {{expected '>'}} diff --git a/test/Parser/knr_parameter_attributes.c b/test/Parser/knr_parameter_attributes.c new file mode 100644 index 0000000..fb975cb --- /dev/null +++ b/test/Parser/knr_parameter_attributes.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -W -Wall -Werror -verify %s + +int f(int i __attribute__((__unused__))) +{ + return 0; +} +int g(i) + int i __attribute__((__unused__)); +{ + return 0; +} diff --git a/test/Preprocessor/directive-invalid.c b/test/Preprocessor/directive-invalid.c new file mode 100644 index 0000000..86cd253 --- /dev/null +++ b/test/Preprocessor/directive-invalid.c @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -E -verify %s +// rdar://7683173 + +#define r_paren ) +#if defined( x r_paren // expected-error {{missing ')' after 'defined'}} \ + // expected-note {{to match this '('}} +#endif diff --git a/test/Rewriter/dllimport-typedef.c b/test/Rewriter/dllimport-typedef.c new file mode 100644 index 0000000..28d2e29 --- /dev/null +++ b/test/Rewriter/dllimport-typedef.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-NEG %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-POS %s + +// Do not report an error with including dllimport in the typedef when -fms-extensions is specified. +// Addresses <rdar://problem/7653870>. +typedef __declspec(dllimport) int CB(void); + +// This function is added just to trigger a diagnostic. This way we can test how many +// diagnostics we expect. +void bar() { return 1; } + +// CHECK-NEG: warning: void function 'bar' should not return a value +// CHECK-NEG: 1 diagnostic generated +// CHECK-POS: warning: 'dllimport' attribute only applies to variable and function type +// CHECK-POS: warning: void function 'bar' should not return a value +// CHECK-POS: 2 diagnostics generated + diff --git a/test/Rewriter/missing-dllimport.c b/test/Rewriter/missing-dllimport.c new file mode 100644 index 0000000..d2356bd --- /dev/null +++ b/test/Rewriter/missing-dllimport.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-NEG %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-POS %s + +// Do not report that 'foo()' is redeclared without dllimport attribute with -fms-extensions +// specified. Addresses <rdar://problem/7653912>. + +__declspec(dllimport) int __cdecl foo(void); +inline int __cdecl foo() { return 0; } + +// This function is added just to trigger a diagnostic. This way we can test how many +// diagnostics we expect. +void bar() { return 1; } + +// CHECK-NEG: warning: void function 'bar' should not return a value +// CHECK-NEG: 1 diagnostic generated +// CHECK-POS: warning: 'foo' redeclared without dllimport attribute: previous dllimport ignored +// CHECK-POS: warning: void function 'bar' should not return a value +// CHECK-POS: 2 diagnostics generated + diff --git a/test/Rewriter/rewrite-block-pointer.mm b/test/Rewriter/rewrite-block-pointer.mm index b03b7a9..212b236 100644 --- a/test/Rewriter/rewrite-block-pointer.mm +++ b/test/Rewriter/rewrite-block-pointer.mm @@ -1,7 +1,10 @@ // RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp -// RUN: FileCheck -check-prefix LP --input-file=%t-rw.cpp %s +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp // radar 7638400 +typedef void * id; +void *sel_registerName(const char *); + @interface X @end @@ -13,4 +16,45 @@ static void enumerateIt(void (^block)(id, id, char *)) { } @end -// CHECK-LP: static void enumerateIt(void (*)(id, id, char *)); +// radar 7651312 +void apply(void (^block)(int)); + +static void x(int (^cmp)(int, int)) { + x(cmp); +} + +static void y(int (^cmp)(int, int)) { + apply(^(int sect) { + x(cmp); + }); +} + +// radar 7659483 +void *_Block_copy(const void *aBlock); +void x(void (^block)(void)) { + block = ((__typeof(block))_Block_copy((const void *)(block))); +} + +// radar 7682763 +@interface Y { +@private + id _private; +} +- (void (^)(void))f; +@end + +typedef void (^void_block_t)(void); + +@interface YY { + void_block_t __completion; +} +@property (copy) void_block_t f; +@end + +@implementation Y +- (void (^)(void))f { + return [_private f]; +} + +@end + diff --git a/test/Rewriter/rewrite-byref-in-nested-blocks.mm b/test/Rewriter/rewrite-byref-in-nested-blocks.mm new file mode 100644 index 0000000..a8f5b14 --- /dev/null +++ b/test/Rewriter/rewrite-byref-in-nested-blocks.mm @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// radar 7692350 + +void f(void (^block)(void)); + +@interface X { + int y; +} +- (void)foo; +@end + +@implementation X +- (void)foo { + __block int kerfluffle; + // radar 7692183 + __block x; + f(^{ + f(^{ + y = 42; + kerfluffle = 1; + x = 2; + }); + }); +} +@end diff --git a/test/Rewriter/rewrite-implementation.mm b/test/Rewriter/rewrite-implementation.mm index 608707c..c1d89a3 100644 --- a/test/Rewriter/rewrite-implementation.mm +++ b/test/Rewriter/rewrite-implementation.mm @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp -// RUN: %clang_cc1 -DSEL="void *" -S %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp // radar 7649577 @interface a diff --git a/test/Rewriter/rewrite-nested-blocks-1.mm b/test/Rewriter/rewrite-nested-blocks-1.mm new file mode 100644 index 0000000..582f5f4 --- /dev/null +++ b/test/Rewriter/rewrite-nested-blocks-1.mm @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// radar 7696893 + +void *sel_registerName(const char *); + +void f(void (^block)(void)); +void f2(id); +void f3(int); +char f4(id, id); + +@interface Baz +- (void)b:(void (^)(void))block; +@end + +@interface Bar +@end + +@interface Foo { + int _x; +} +@end + +@implementation Foo +- (void)method:(Bar *)up { + Baz *down; + int at; + id cq; + __block char didit = 'a'; + __block char upIsFinished = 'b'; + f(^{ + id old_cq; + f2(cq); + [down b:^{ + [down b:^{ + f(^{ + didit = f4(up, down); + upIsFinished = 'c'; + self->_x++; + }); + }]; + }]; + f2(old_cq); + f3(at); + }); +} +@end diff --git a/test/Rewriter/rewrite-nested-blocks.mm b/test/Rewriter/rewrite-nested-blocks.mm new file mode 100644 index 0000000..1a6bcdd --- /dev/null +++ b/test/Rewriter/rewrite-nested-blocks.mm @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// radar 7682149 + + +void f(void (^block)(void)); + +@interface X { + int y; +} +- (void)foo; +@end + +@implementation X +- (void)foo { + f(^{ + f(^{ + f(^{ + y=42; + }); + }); +}); + +} +@end + +struct S { + int y; +}; + +void foo () { + struct S *SELF; + f(^{ + f(^{ + SELF->y = 42; + }); + }); +} + +// radar 7692419 +@interface Bar +@end + +void f(Bar *); +void q(void (^block)(void)); + +void x() { + void (^myblock)(Bar *b) = ^(Bar *b) { + q(^{ + f(b); + }); + }; + + Bar *b = (Bar *)42; + myblock(b); +} diff --git a/test/Rewriter/rewrite-property-attributes.mm b/test/Rewriter/rewrite-property-attributes.mm new file mode 100644 index 0000000..41f457c --- /dev/null +++ b/test/Rewriter/rewrite-property-attributes.mm @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// radar 7214439 + +typedef void (^void_block_t)(void); + +@interface Y { + void_block_t __completion; + Y* YVAR; + id ID; +} +@property (copy) void_block_t completionBlock; +@property (retain) Y* Yblock; +@property (copy) id ID; +@end + +@implementation Y +@synthesize completionBlock=__completion; +@synthesize Yblock = YVAR; +@synthesize ID; +@end + diff --git a/test/Rewriter/rewrite-qualified-id.mm b/test/Rewriter/rewrite-qualified-id.mm new file mode 100644 index 0000000..fe3607d --- /dev/null +++ b/test/Rewriter/rewrite-qualified-id.mm @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// radar 7680953 + +typedef void * id; + +@protocol foo +@end + +@interface CL +{ + id <foo> changeSource; + CL <foo>* changeSource1; +} +@end + +typedef struct x +{ + id <foo> changeSource; +} x; + diff --git a/test/Rewriter/rewrite-rewritten-initializer.mm b/test/Rewriter/rewrite-rewritten-initializer.mm new file mode 100644 index 0000000..80ad7fc --- /dev/null +++ b/test/Rewriter/rewrite-rewritten-initializer.mm @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp +// radar 7669784 + +typedef void * id; +void *sel_registerName(const char *); + +@interface NSMutableString +- (NSMutableString *)string; +@end + +@interface Z +@end + +@implementation Z + +- (void)x { + id numbers; + int i, numbersCount = 42; + __attribute__((__blocks__(byref))) int blockSum = 0; + void (^add)(id n, int idx, char *stop) = ^(id n, int idx, char *stop) { }; + [numbers enumerateObjectsUsingBlock:add]; + NSMutableString *forwardAppend = [NSMutableString string]; + __attribute__((__blocks__(byref))) NSMutableString *blockAppend = [NSMutableString string]; +} + +@end + diff --git a/test/Rewriter/rewrite-unique-block-api.mm b/test/Rewriter/rewrite-unique-block-api.mm index 780a3f0..130f514 100644 --- a/test/Rewriter/rewrite-unique-block-api.mm +++ b/test/Rewriter/rewrite-unique-block-api.mm @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -x objective-c++ -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp -// RUN: FileCheck -check-prefix LP --input-file=%t-rw.cpp %s +// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp // radar 7630551 void f(void (^b)(char c)); @@ -23,9 +23,3 @@ void f(void (^b)(char c)); f(^(char x) { }); } @end - -// CHECK-LP: struct __a__processStuff_block_impl_0 -// CHECK-LP: static void __a__processStuff_block_func_0 - -// CHECK-LP: struct __b__processStuff_block_impl_0 -// CHECK-LP: static void __b__processStuff_block_func_0 diff --git a/test/Sema/align-x86.c b/test/Sema/align-x86.c index f67adec..c9a6398 100644 --- a/test/Sema/align-x86.c +++ b/test/Sema/align-x86.c @@ -12,3 +12,9 @@ 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]; + +// PR6362 +struct __attribute__((packed)) {unsigned int a} g4; +short chk1[__alignof__(g4) == 1 ? 1 : -1]; +short chk2[__alignof__(g4.a) == 1 ? 1 : -1]; + diff --git a/test/Sema/arg-duplicate.c b/test/Sema/arg-duplicate.c index ca091eb..feeb458 100644 --- a/test/Sema/arg-duplicate.c +++ b/test/Sema/arg-duplicate.c @@ -2,7 +2,8 @@ int f3(y, x, x) // expected-error {{redefinition of parameter}} - int y, x, + int y, + x, // expected-note {{previous declaration is here}} x; // expected-error {{redefinition of parameter}} { return x + y; diff --git a/test/Sema/block-args.c b/test/Sema/block-args.c index a07c82e..970c60d 100644 --- a/test/Sema/block-args.c +++ b/test/Sema/block-args.c @@ -6,7 +6,8 @@ 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, // expected-note {{previous declaration is here}} + int x){}); // expected-error {{redefinition of parameter 'x'}} take(^(int x) { return x+1; }); diff --git a/test/Sema/callingconv.c b/test/Sema/callingconv.c index 0752606..92a2057 100644 --- a/test/Sema/callingconv.c +++ b/test/Sema/callingconv.c @@ -36,3 +36,11 @@ void (__attribute__((cdecl)) *pctest2)() = ctest2; typedef void (__attribute__((fastcall)) *Handler) (float *); Handler H = foo; +// PR6361 +void ctest3(); +void __attribute__((cdecl)) ctest3() {} + +// PR6408 +typedef __attribute__((stdcall)) void (*PROC)(); +PROC __attribute__((cdecl)) ctest4(const char *x) {} + diff --git a/test/Sema/conversion.c b/test/Sema/conversion.c index 8b93a46..addedd9 100644 --- a/test/Sema/conversion.c +++ b/test/Sema/conversion.c @@ -279,3 +279,11 @@ void test_7631400(void) { // This should show up despite the caret being inside a macro substitution char s = LONG_MAX; // expected-warning {{implicit cast loses integer precision: 'long' to 'char'}} } + +// <rdar://problem/7676608>: assertion for compound operators with non-integral RHS +void f7676608(int); +void test_7676608(void) { + float q = 0.7f; + char c = 5; + f7676608(c *= q); +} diff --git a/test/Sema/declspec.c b/test/Sema/declspec.c index d9f4157..1c87a0e 100644 --- a/test/Sema/declspec.c +++ b/test/Sema/declspec.c @@ -31,3 +31,8 @@ struct test1 { void test2() {} + +// PR6423 +struct test3s { +} // expected-error {{expected ';' after struct}} +typedef int test3g; diff --git a/test/Sema/dllimport-dllexport.c b/test/Sema/dllimport-dllexport.c index a1e7a18..eea2f6f 100644 --- a/test/Sema/dllimport-dllexport.c +++ b/test/Sema/dllimport-dllexport.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple i386-mingw32 -fsyntax-only -verify %s inline void __attribute__((dllexport)) foo1(){} // expected-warning{{dllexport attribute ignored}} inline void __attribute__((dllimport)) foo2(){} // expected-warning{{dllimport attribute ignored}} @@ -16,3 +16,21 @@ typedef int __attribute__((dllimport)) type7; // expected-warning{{'dllimport' a void __attribute__((dllimport)) foo6(); void foo6(){} // expected-warning {{'foo6' redeclared without dllimport attribute: previous dllimport ignored}} + +// PR6269 +inline void __declspec(dllexport) foo7(){} // expected-warning{{dllexport attribute ignored}} +inline void __declspec(dllimport) foo8(){} // expected-warning{{dllimport attribute ignored}} + +void __declspec(dllimport) foo9(){} // expected-error{{dllimport attribute can be applied only to symbol declaration}} + +void __declspec(dllimport) __declspec(dllexport) foo10(); // expected-warning{{dllimport attribute ignored}} + +void __declspec(dllexport) foo11(); +void __declspec(dllimport) foo11(); // expected-warning{{dllimport attribute ignored}} + +typedef int __declspec(dllexport) type1; // expected-warning{{'dllexport' attribute only applies to variable and function types}} + +typedef int __declspec(dllimport) type2; // expected-warning{{'dllimport' attribute only applies to variable and function}} + +void __declspec(dllimport) foo12(); +void foo12(){} // expected-warning {{'foo12' redeclared without dllimport attribute: previous dllimport ignored}} diff --git a/test/Sema/enum.c b/test/Sema/enum.c index 9b46500..6177edf 100644 --- a/test/Sema/enum.c +++ b/test/Sema/enum.c @@ -9,7 +9,8 @@ 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'}} + f = 2147483648, // expected-warning {{ISO C restricts enumerator values to range of 'int'}} + i = 0xFFFF0000 // expected-warning {{too large}} }; // minll maxull diff --git a/test/Sema/format-strings.c b/test/Sema/format-strings.c index f1fa658..4db775f 100644 --- a/test/Sema/format-strings.c +++ b/test/Sema/format-strings.c @@ -55,7 +55,7 @@ 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}} - printf("yes" ?: "no %d", 1); // expected-warning{{more data arguments than format specifiers}} + printf("yes" ?: "no %d", 1); // expected-warning{{data argument not used by format string}} } void check_writeback_specifier() @@ -145,6 +145,7 @@ void torture(va_list v8) { } void test10(int x, float f, int i, long long lli) { + printf("%s"); // expected-warning{{more '%' conversions than data arguments}} printf("%@", 12); // expected-warning{{invalid conversion specifier '@'}} printf("\0"); // expected-warning{{format string contains '\0' within the string body}} printf("xs\0"); // expected-warning{{format string contains '\0' within the string body}} @@ -155,7 +156,7 @@ void test10(int x, float f, int i, long long lli) { printf("%**\n"); // expected-warning{{invalid conversion specifier '*'}} printf("%n", &i); // expected-warning{{use of '%n' in format string discouraged (potentially insecure)}} printf("%d%d\n", x); // expected-warning{{more '%' conversions than data arguments}} - printf("%d\n", x, x); // expected-warning{{more data arguments than format specifiers}} + printf("%d\n", x, x); // expected-warning{{data argument not used by format string}} printf("%W%d%Z\n", x, x, x); // expected-warning{{invalid conversion specifier 'W'}} expected-warning{{invalid conversion specifier 'Z'}} printf("%"); // expected-warning{{incomplete format specifier}} printf("%.d", x); // no-warning @@ -169,6 +170,8 @@ void test10(int x, float f, int i, long long lli) { printf("%d", (long long) 10); // expected-warning{{conversion specifies type 'int' but the argument has type 'long long'}} printf("%Lf\n", (long double) 1.0); // no-warning printf("%f\n", (long double) 1.0); // expected-warning{{conversion specifies type 'double' but the argument has type 'long double'}} + // The man page says that a zero precision is okay. + printf("%.0Lf", (long double) 1.0); // no-warning } void test11(void *p, char *s) { @@ -204,3 +207,34 @@ void test_asl(aslclient asl) { // <rdar://problem/7595366> typedef enum { A } int_t; void f0(int_t x) { printf("%d\n", x); } + +// Unicode test cases. These are possibly specific to Mac OS X. If so, they should +// eventually be moved into a separate test. +typedef __WCHAR_TYPE__ wchar_t; + +void test_unicode_conversions(wchar_t *s) { + printf("%S", s); // no-warning + printf("%s", s); // expected-warning{{conversion specifies type 'char *' but the argument has type 'wchar_t *'}} + printf("%C", s[0]); // no-warning + printf("%c", s[0]); + // FIXME: This test reports inconsistent results. On Windows, '%C' expects + // 'unsigned short'. + // printf("%C", 10); + // FIXME: we report the expected type as 'int*' instead of 'wchar_t*' + printf("%S", "hello"); // expected-warning{{but the argument has type 'char *'}} +} + +// Mac OS X supports positional arguments in format strings. +// This is an IEEE extension (IEEE Std 1003.1). +// FIXME: This is probably not portable everywhere. +void test_positional_arguments() { + printf("%0$", (int)2); // expected-warning{{position arguments in format strings start counting at 1 (not 0)}} + printf("%1$*0$d", (int) 2); // expected-warning{{position arguments in format strings start counting at 1 (not 0)}} + printf("%1$d", (int) 2); // no-warning + printf("%1$d", (int) 2, 2); // expected-warning{{data argument not used by format string}} + printf("%1$d%1$f", (int) 2); // expected-warning{{conversion specifies type 'double' but the argument has type 'int'}} + printf("%1$2.2d", (int) 2); // no-warning + printf("%2$*1$.2d", (int) 2, (int) 3); // no-warning + printf("%2$*8$d", (int) 2, (int) 3); // expected-warning{{specified field width is missing a matching 'int' argument}} +} + diff --git a/test/Sema/inline.c b/test/Sema/inline.c index 3c99f24..b4795d3 100644 --- a/test/Sema/inline.c +++ b/test/Sema/inline.c @@ -1,6 +1,22 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=gnu89 -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}} + +// PR5253 +// GNU Extension: check that we can redefine an extern inline function +extern inline int f(int a) {return a;} +int f(int b) {return b;} // expected-note{{previous definition is here}} +// And now check that we can't redefine a normal function +int f(int c) {return c;} // expected-error{{redefinition of 'f'}} + +// Check that we can redefine an extern inline function as a static function +extern inline int g(int a) {return a;} +static int g(int b) {return b;} + +// Check that we ensure the types of the two definitions are the same +extern inline int h(int a) {return a;} // expected-note{{previous definition is here}} +int h(short b) {return b;} // expected-error{{conflicting types for 'h'}} + diff --git a/test/Sema/overloadable-complex.c b/test/Sema/overloadable-complex.c index e8dbf3a..770a972 100644 --- a/test/Sema/overloadable-complex.c +++ b/test/Sema/overloadable-complex.c @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -char *foo(float) __attribute__((__overloadable__)); // expected-note 3 {{candidate function}} +char *foo(float) __attribute__((__overloadable__)); void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) { char *cp1 = foo(fv); @@ -9,20 +9,20 @@ void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) { char *cp4 = foo(dc); } -int *foo(float _Complex) __attribute__((__overloadable__)); // expected-note 3 {{candidate function}} +int *foo(float _Complex) __attribute__((__overloadable__)); 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:}} + char *cp2 = foo(dv); int *ip = foo(fc); - int *lp = foo(dc); // expected-error{{call to 'foo' is ambiguous; candidates are:}} + int *lp = foo(dc); } -long *foo(double _Complex) __attribute__((__overloadable__)); // expected-note {{candidate function}} +long *foo(double _Complex) __attribute__((__overloadable__)); 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:}} + char *cp2 = foo(dv); int *ip = foo(fc); long *lp = foo(dc); } diff --git a/test/Sema/static-init.c b/test/Sema/static-init.c index 8011943..b4de927 100644 --- a/test/Sema/static-init.c +++ b/test/Sema/static-init.c @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 -triple i386-pc-linux-gnu -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s -#include <stdint.h> +typedef __typeof((int*) 0 - (int*) 0) intptr_t; static int f = 10; static int b = f; // expected-error {{initializer element is not a compile-time constant}} diff --git a/test/Sema/switch.c b/test/Sema/switch.c index 2690ad2..e63a194 100644 --- a/test/Sema/switch.c +++ b/test/Sema/switch.c @@ -223,3 +223,41 @@ void test12() { break; } } + +// <rdar://problem/7643909> +typedef enum { + val1, + val2, + val3 +} my_type_t; + +int test13(my_type_t t) { + switch(t) { // expected-warning{{enumeration value 'val3' not handled in switch}} + case val1: + return 1; + case val2: + return 2; + } + return -1; +} + +// <rdar://problem/7658121> +enum { + EC0 = 0xFFFF0000, + EC1 = 0xFFFF0001, +}; + +int test14(int a) { + switch(a) { + case EC0: return 0; + case EC1: return 1; + } + return 0; +} + +void f1(unsigned x) { + switch (x) { + case -1: break; + default: break; + } +} diff --git a/test/Sema/warn-unreachable.c b/test/Sema/warn-unreachable.c index 1eef637..10ed696 100644 --- a/test/Sema/warn-unreachable.c +++ b/test/Sema/warn-unreachable.c @@ -35,8 +35,8 @@ void test2() { dead(); // expected-warning {{will never be executed}} case 3: - live() - + // expected-warning {{will never be executed}} + live() // expected-warning {{will never be executed}} + + halt(); dead(); diff --git a/test/Sema/warn-unused-function.c b/test/Sema/warn-unused-function.c index 178527f..b52f676 100644 --- a/test/Sema/warn-unused-function.c +++ b/test/Sema/warn-unused-function.c @@ -13,4 +13,18 @@ extern void f3() { } // expected-warning{{unused}} // FIXME: This will trigger a warning when it should not. // Update once PR6281 is fixed. //inline static void f4(); -//void f4() { }
\ No newline at end of file +//void f4() { } + +static void __attribute__((used)) f5() {} +static void f6(); +static void __attribute__((used)) f6(); +static void f6() {}; + +static void f7(void); +void f8(void(*a0)(void)); +void f9(void) { f8(f7); } +static void f7(void) {} + +__attribute__((unused)) static void bar(void); +void bar(void) { } + diff --git a/test/Sema/warn-unused-variables.c b/test/Sema/warn-unused-variables.c index 3661506..58e52b1 100644 --- a/test/Sema/warn-unused-variables.c +++ b/test/Sema/warn-unused-variables.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wunused-variable -fblocks -verify %s struct s0 { unsigned int i; @@ -17,3 +17,16 @@ void f1(void) { (void)sizeof(i); return; } + +// PR5933 +int f2() { + int X = 4; // Shouldn't have a bogus 'unused variable X' warning. + return Y + X; // expected-error {{use of undeclared identifier 'Y'}} +} + +int f3() { + int X1 = 4; + (void)(Y1 + X1); // expected-error {{use of undeclared identifier 'Y1'}} + (void)(^() { int X = 4; }); // expected-warning{{unused}} + (void)(^() { int X = 4; return Y + X; }); // expected-error {{use of undeclared identifier 'Y'}} +} diff --git a/test/Sema/x86-attr-force-align-arg-pointer.c b/test/Sema/x86-attr-force-align-arg-pointer.c index 9609fad..b406a77 100644 --- a/test/Sema/x86-attr-force-align-arg-pointer.c +++ b/test/Sema/x86-attr-force-align-arg-pointer.c @@ -14,5 +14,8 @@ void d(void); void __attribute__((force_align_arg_pointer)) d(void) {} // Attribute is ignored on function pointer types. -void (__attribute__((force_align_arg_pointer)) *p)(); //expected-warning{{force_align_arg_pointer used on function pointer; attribute ignored}} +void (__attribute__((force_align_arg_pointer)) *p)(); +typedef void (__attribute__((__force_align_arg_pointer__)) *p2)(); +// Attribute is also ignored on function typedefs. +typedef void __attribute__((force_align_arg_pointer)) e(void); diff --git a/test/SemaCXX/address-of-temporary.cpp b/test/SemaCXX/address-of-temporary.cpp new file mode 100644 index 0000000..decdc95 --- /dev/null +++ b/test/SemaCXX/address-of-temporary.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -Wno-error=address-of-temporary -verify %s +struct X { + X(); + X(int); + X(int, int); +}; + +void *f0() { return &X(); } // expected-warning{{taking the address of a temporary object}} +void *f1() { return &X(1); } // expected-warning{{taking the address of a temporary object}} +void *f2() { return &X(1, 2); } // expected-warning{{taking the address of a temporary object}} +void *f3() { return &(X)1; } // expected-warning{{taking the address of a temporary object}} + diff --git a/test/SemaCXX/attr-weakref.cpp b/test/SemaCXX/attr-weakref.cpp new file mode 100644 index 0000000..5773acc --- /dev/null +++ b/test/SemaCXX/attr-weakref.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// GCC will accept anything as the argument of weakref. Should we +// check for an existing decl? +static int a1() __attribute__((weakref ("foo"))); +static int a2() __attribute__((weakref, alias ("foo"))); + +static int a3 __attribute__((weakref ("foo"))); +static int a4 __attribute__((weakref, alias ("foo"))); + +// gcc rejects, clang accepts +static int a5 __attribute__((alias ("foo"), weakref)); + +// this is pointless, but accepted by gcc. We reject it. +static int a6 __attribute__((weakref)); //expected-error {{weakref declaration of 'a6' must also have an alias attribute}} + +// gcc warns, clang rejects +void f(void) { + static int a __attribute__((weakref ("v2"))); // expected-error {{declaration of 'a' must be in a global context}} +} + +// both gcc and clang reject +class c { + static int a __attribute__((weakref ("v2"))); // expected-error {{declaration of 'a' must be in a global context}} + static int b() __attribute__((weakref ("f3"))); // expected-error {{declaration of 'b' must be in a global context}} +}; +int a7() __attribute__((weakref ("f1"))); // expected-error {{declaration of 'a7' must be static}} +int a8 __attribute__((weakref ("v1"))); // expected-error {{declaration of 'a8' must be static}} + +// gcc accepts this +int a9 __attribute__((weakref)); // expected-error {{declaration of 'a9' must be static}} diff --git a/test/SemaCXX/blocks-1.cpp b/test/SemaCXX/blocks-1.cpp new file mode 100644 index 0000000..d93997a --- /dev/null +++ b/test/SemaCXX/blocks-1.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -fblocks + +extern "C" int exit(int); + +typedef struct { + unsigned long ps[30]; + int qs[30]; +} BobTheStruct; + +int main (int argc, const char * argv[]) { + BobTheStruct inny; + BobTheStruct outty; + BobTheStruct (^copyStruct)(BobTheStruct); + int i; + + for(i=0; i<30; i++) { + inny.ps[i] = i * i * i; + inny.qs[i] = -i * i * i; + } + + copyStruct = ^(BobTheStruct aBigStruct){ return aBigStruct; }; // pass-by-value intrinsically copies the argument + + outty = copyStruct(inny); + + if ( &inny == &outty ) { + exit(1); + } + for(i=0; i<30; i++) { + if ( (inny.ps[i] != outty.ps[i]) || (inny.qs[i] != outty.qs[i]) ) { + exit(1); + } + } + + return 0; +} diff --git a/test/SemaCXX/complex-overload.cpp b/test/SemaCXX/complex-overload.cpp index 3378755..2c057ac 100644 --- a/test/SemaCXX/complex-overload.cpp +++ b/test/SemaCXX/complex-overload.cpp @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -char *foo(float); // expected-note 3 {{candidate function}} +char *foo(float); void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) { char *cp1 = foo(fv); @@ -9,20 +9,20 @@ void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) { char *cp4 = foo(dc); } -int *foo(float _Complex); // expected-note 3 {{candidate function}} +int *foo(float _Complex); 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:}} + char *cp2 = foo(dv); int *ip = foo(fc); - int *lp = foo(dc); // expected-error{{call to 'foo' is ambiguous; candidates are:}} + int *lp = foo(dc); } -long *foo(double _Complex); // expected-note {{candidate function}} +long *foo(double _Complex); 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:}} + char *cp2 = foo(dv); int *ip = foo(fc); long *lp = foo(dc); } diff --git a/test/SemaCXX/composite-pointer-type.cpp b/test/SemaCXX/composite-pointer-type.cpp index fdf838f..e8b0920 100644 --- a/test/SemaCXX/composite-pointer-type.cpp +++ b/test/SemaCXX/composite-pointer-type.cpp @@ -50,3 +50,11 @@ typedef double Matrix4[4][4]; bool f(Matrix4 m1, const Matrix4 m2) { return m1 != m2; } + +// PR6346 +bool f1(bool b, void **p, const void **q) { + if (p == q) // expected-warning{{comparison of distinct pointer types ('void **' and 'void const **') uses non-standard composite pointer type 'void const *const *'}} + return false; + + return b? p : q; // expected-warning{{incompatible operand types ('void **' and 'void const **') use non-standard composite pointer type 'void const *const *'}} +} diff --git a/test/SemaCXX/condition.cpp b/test/SemaCXX/condition.cpp index fe802d0..b3e862d 100644 --- a/test/SemaCXX/condition.cpp +++ b/test/SemaCXX/condition.cpp @@ -18,7 +18,8 @@ void test() { while (struct S {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{value of type 'struct S' is not contextually convertible to 'bool'}} expected-note{{candidate constructor (the implicit copy constructor)}} while (struct {} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{no viable conversion}} expected-error {{value of type 'struct <anonymous>' is not contextually convertible to 'bool'}} expected-note{{candidate constructor (the implicit copy constructor)}} - switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}} + switch (enum {E} x=0) ; // expected-error {{types may not be defined in conditions}} expected-error {{cannot initialize}} \ + // expected-warning{{enumeration value 'E' not handled in switch}} if (int x=0) { // expected-note 2 {{previous definition is here}} int x; // expected-error {{redefinition of 'x'}} diff --git a/test/SemaCXX/copy-constructor-error.cpp b/test/SemaCXX/copy-constructor-error.cpp index 9cae775..9809bfc 100644 --- a/test/SemaCXX/copy-constructor-error.cpp +++ b/test/SemaCXX/copy-constructor-error.cpp @@ -10,3 +10,16 @@ void g() { S a( f() ); } +namespace PR6064 { + struct A { + A() { } + inline A(A&, int); + }; + + A::A(A&, int = 0) { } + + void f() { + A const a; + A b(a); + } +} diff --git a/test/SemaCXX/dcl_init_aggr.cpp b/test/SemaCXX/dcl_init_aggr.cpp index 861eb3d..461c60b 100644 --- a/test/SemaCXX/dcl_init_aggr.cpp +++ b/test/SemaCXX/dcl_init_aggr.cpp @@ -38,7 +38,7 @@ char cv[4] = { 'a', 's', 'd', 'f', 0 }; // expected-error{{excess elements in ar // C++ [dcl.init.aggr]p7 struct TooFew { int a; char* b; int c; }; -TooFew too_few = { 1, "asdf" }; // okay +TooFew too_few = { 1, "asdf" }; // expected-warning{{conversion from string literal to 'char *' is deprecated}} struct NoDefaultConstructor { // expected-note 3 {{candidate constructor (the implicit copy constructor)}} \ // expected-note{{declared here}} diff --git a/test/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp index d2c44bd..e674260 100644 --- a/test/SemaCXX/default2.cpp +++ b/test/SemaCXX/default2.cpp @@ -16,7 +16,8 @@ void i() } -int f1(int i, int i, int j) { // expected-error {{redefinition of parameter 'i'}} +int f1(int i, // expected-note {{previous declaration is here}} + int i, int j) { // expected-error {{redefinition of parameter 'i'}} i = 17; return j; } diff --git a/test/SemaCXX/destructor.cpp b/test/SemaCXX/destructor.cpp index 6837cd4..ab3c809 100644 --- a/test/SemaCXX/destructor.cpp +++ b/test/SemaCXX/destructor.cpp @@ -40,9 +40,9 @@ struct F { ~F(); // expected-error {{destructor cannot be redeclared}} }; -~; // expected-error {{expected the class name after '~' to name a destructor}} +~; // expected-error {{expected a class name after '~' to name a destructor}} ~undef(); // expected-error {{expected the class name after '~' to name a destructor}} -~operator+(int, int); // expected-error {{expected the class name after '~' to name a destructor}} +~operator+(int, int); // expected-error {{expected a class name after '~' to name a destructor}} ~F(){} // expected-error {{destructor must be a non-static member function}} struct G { @@ -61,3 +61,20 @@ struct X {}; struct Y { ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}} }; + +namespace PR6421 { + class T; // expected-note{{forward declaration}} + + class QGenericArgument + { + template<typename U> + void foo(T t) // expected-error{{variable has incomplete type}} + { } + + void disconnect() + { + T* t; + bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} + } + }; +} diff --git a/test/SemaCXX/i-c-e-cxx.cpp b/test/SemaCXX/i-c-e-cxx.cpp index 4f2f197..e8275d4 100644 --- a/test/SemaCXX/i-c-e-cxx.cpp +++ b/test/SemaCXX/i-c-e-cxx.cpp @@ -37,3 +37,8 @@ namespace pr6206 { return str[0]; } } + +// PR6373: default arguments don't count. +void pr6373(const unsigned x = 0) { + unsigned max = 80 / x; +} diff --git a/test/SemaCXX/implicit-virtual-member-functions.cpp b/test/SemaCXX/implicit-virtual-member-functions.cpp index 4ae9eae..1bb5adb 100644 --- a/test/SemaCXX/implicit-virtual-member-functions.cpp +++ b/test/SemaCXX/implicit-virtual-member-functions.cpp @@ -15,9 +15,9 @@ void B::f() { // expected-note {{implicit default destructor for 'struct B' firs struct C : A { // expected-error {{no suitable member 'operator delete' in 'C'}} C(); void operator delete(void *, int); // expected-note {{'operator delete' declared here}} -}; // expected-note {{implicit default destructor for 'struct C' first required here}} +}; -C::C() { } +C::C() { } // expected-note {{implicit default destructor for 'struct C' first required here}} struct D : A { // expected-error {{no suitable member 'operator delete' in 'D'}} void operator delete(void *, int); // expected-note {{'operator delete' declared here}} diff --git a/test/SemaCXX/invalid-member-expr.cpp b/test/SemaCXX/invalid-member-expr.cpp index 666595c..7b17afb 100644 --- a/test/SemaCXX/invalid-member-expr.cpp +++ b/test/SemaCXX/invalid-member-expr.cpp @@ -6,7 +6,7 @@ void test() { X x; x.int; // expected-error{{expected unqualified-id}} - x.~int(); // expected-error{{expected the class name}} + x.~int(); // expected-error{{expected a class name}} x.operator; // expected-error{{missing type specifier after 'operator'}} x.operator typedef; // expected-error{{missing type specifier after 'operator'}} } @@ -15,7 +15,7 @@ void test2() { X *x; x->int; // expected-error{{expected unqualified-id}} - x->~int(); // expected-error{{expected the class name}} + x->~int(); // expected-error{{expected a class name}} x->operator; // expected-error{{missing type specifier after 'operator'}} x->operator typedef; // expected-error{{missing type specifier after 'operator'}} } diff --git a/test/SemaCXX/local-classes.cpp b/test/SemaCXX/local-classes.cpp new file mode 100644 index 0000000..6799e58 --- /dev/null +++ b/test/SemaCXX/local-classes.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR6382 { + int foo() + { + goto error; + { + struct BitPacker { + BitPacker() {} + }; + BitPacker packer; + } + + error: + return -1; + } +} + +namespace PR6383 { + void test (bool gross) + { + struct compare_and_set + { + void operator() (const bool inner, const bool gross = false) + { + // the code + } + } compare_and_set2; + + compare_and_set2 (false, gross); + } +} diff --git a/test/SemaCXX/member-name-lookup.cpp b/test/SemaCXX/member-name-lookup.cpp index ff14416..94296e1 100644 --- a/test/SemaCXX/member-name-lookup.cpp +++ b/test/SemaCXX/member-name-lookup.cpp @@ -2,7 +2,7 @@ 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}} + static int c; // expected-note 2{{member found by ambiguous name lookup}} enum E { enumerator }; @@ -75,7 +75,7 @@ struct B2 : virtual A { }; struct C2 : virtual A { - int c; // expected-note 2{{member found by ambiguous name lookup}} + int c; int d; // expected-note 2{{member found by ambiguous name lookup}} enum E3 { enumerator3_2 }; // expected-note 2{{member found by ambiguous name lookup}} @@ -93,7 +93,7 @@ struct G : F, D2 { 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}} + (void)d2.c; // okay d2.d; // expected-error{{member 'd' found in multiple base classes of different types}} d2.f(0); // okay d2.static_f(0); // okay @@ -112,7 +112,7 @@ void test_virtual_lookup(D2 d2, G g) { void D2::test_virtual_lookup() { (void)a; (void)b; - c; // expected-error{{member 'c' found in multiple base classes of different types}} + (void)c; // okay d; // expected-error{{member 'd' found in multiple base classes of different types}} f(0); // okay static_f(0); // okay diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp index 3d9d5b5e..d6050cd 100644 --- a/test/SemaCXX/member-pointer.cpp +++ b/test/SemaCXX/member-pointer.cpp @@ -12,8 +12,7 @@ int A::*pdi1; int (::A::*pdi2); int (A::*pfi)(int); -int B::*pbi; // expected-error {{expected a class or namespace}} \ - // expected-error{{does not point into a class}} +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 member pointer to a reference}} diff --git a/test/SemaCXX/nested-name-spec.cpp b/test/SemaCXX/nested-name-spec.cpp index 8a217b3..247e91b 100644 --- a/test/SemaCXX/nested-name-spec.cpp +++ b/test/SemaCXX/nested-name-spec.cpp @@ -13,8 +13,9 @@ namespace A { } A:: ; // expected-error {{expected unqualified-id}} -::A::ax::undef ex3; // expected-error {{no member named}} -A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} +// FIXME: redundant errors +::A::ax::undef ex3; // expected-error {{no member named}} expected-error {{unknown type name}} +A::undef1::undef2 ex4; // expected-error {{no member named 'undef1'}} expected-error {{unknown type name}} int A::C::Ag1() { return 0; } diff --git a/test/SemaCXX/new-delete.cpp b/test/SemaCXX/new-delete.cpp index acd4a23..68323d8 100644 --- a/test/SemaCXX/new-delete.cpp +++ b/test/SemaCXX/new-delete.cpp @@ -159,12 +159,10 @@ void loadEngineFor() { } template <class T> struct TBase { - void* operator new(T size, int); // expected-error {{'operator new' cannot take a dependent type as first parameter; use size_t}}\ - // expected-error {{'operator new' takes type size_t}} + void* operator new(T size, int); // expected-error {{'operator new' cannot take a dependent type as first parameter; use size_t}} }; -// FIXME: We should not try to instantiate operator new, since it is invalid. -TBase<int> t1; // expected-note {{in instantiation of template class 'struct TBase<int>' requested here}} +TBase<int> t1; class X6 { public: diff --git a/test/SemaCXX/overload-call.cpp b/test/SemaCXX/overload-call.cpp index e2a4fd8..77e0908 100644 --- a/test/SemaCXX/overload-call.cpp +++ b/test/SemaCXX/overload-call.cpp @@ -53,7 +53,7 @@ int* k(char*); double* k(bool); void test_k() { - int* ip1 = k("foo"); + int* ip1 = k("foo"); // expected-warning{{conversion from string literal to 'char *' is deprecated}} double* dp1 = k(L"foo"); } @@ -61,7 +61,7 @@ int* l(wchar_t*); double* l(bool); void test_l() { - int* ip1 = l(L"foo"); + int* ip1 = l(L"foo"); // expected-warning{{conversion from string literal to 'wchar_t *' is deprecated}} double* dp1 = l("foo"); } @@ -79,7 +79,7 @@ class E; void test_n(E* e) { char ca[7]; int* ip1 = n(ca); - int* ip2 = n("foo"); + int* ip2 = n("foo"); // expected-warning{{conversion from string literal to 'char *' is deprecated}} float fa[7]; double* dp1 = n(fa); @@ -359,3 +359,30 @@ namespace DerivedToBaseVsVoid { int &ir = f(b); } } + +// PR 6398 + PR 6421 +namespace test4 { + class A; + class B { + static void foo(); // expected-note {{not viable}} + static void foo(int*); // expected-note {{not viable}} + static void foo(long*); // expected-note {{not viable}} + + void bar(A *a) { + foo(a); // expected-error {{no matching function for call}} + } + }; +} + +namespace DerivedToBase { + struct A { }; + struct B : A { }; + struct C : B { }; + + int &f0(const A&); + float &f0(B); + + void g() { + float &fr = f0(C()); + } +} diff --git a/test/SemaCXX/pseudo-destructors.cpp b/test/SemaCXX/pseudo-destructors.cpp index 15e37c5..472e5b4 100644 --- a/test/SemaCXX/pseudo-destructors.cpp +++ b/test/SemaCXX/pseudo-destructors.cpp @@ -5,21 +5,23 @@ enum Foo { F }; typedef Foo Bar; typedef int Integer; +typedef double Double; void g(); namespace N { typedef Foo Wibble; + typedef int OtherInteger; } -void f(A* a, Foo *f, int *i) { +void f(A* a, Foo *f, int *i, double *d) { a->~A(); a->A::~A(); a->~foo(); // expected-error{{identifier 'foo' in pseudo-destructor expression does not name a type}} - // FIXME: the type printed below isn't wonderful - a->~Bar(); // expected-error{{no member named}} + // FIXME: the diagnostic below isn't wonderful + a->~Bar(); // expected-error{{does not name a type}} f->~Bar(); f->~Foo(); @@ -28,9 +30,17 @@ void f(A* a, Foo *f, int *i) { g().~Bar(); // expected-error{{non-scalar}} f->::~Bar(); - f->N::~Wibble(); + f->N::~Wibble(); // FIXME: technically, Wibble isn't a class-name f->::~Bar(17, 42); // expected-error{{cannot have any arguments}} + + i->~Integer(); + i->Integer::~Integer(); + i->N::~OtherInteger(); + i->N::OtherInteger::~OtherInteger(); + i->N::OtherInteger::~Integer(); // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}} + i->N::~Integer(); // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}} + i->Integer::~Double(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('Double' (aka 'double')) in pseudo-destructor expression}} } typedef int Integer; diff --git a/test/SemaCXX/statements.cpp b/test/SemaCXX/statements.cpp index 3698258..852086e 100644 --- a/test/SemaCXX/statements.cpp +++ b/test/SemaCXX/statements.cpp @@ -1,5 +1,17 @@ -// RUN: %clang_cc1 %s -fsyntax-only -pedantic +// RUN: %clang_cc1 %s -fsyntax-only -pedantic -verify void foo() { return foo(); } + +// PR6451 - C++ Jump checking +struct X { + X(); +}; + +void test2() { + goto later; // expected-error {{illegal goto into protected scope}} + X x; // expected-note {{jump bypasses variable initialization}} +later: + ; +} diff --git a/test/SemaCXX/type-convert-construct.cpp b/test/SemaCXX/type-convert-construct.cpp index d786a9a..8f92a03 100644 --- a/test/SemaCXX/type-convert-construct.cpp +++ b/test/SemaCXX/type-convert-construct.cpp @@ -11,7 +11,7 @@ void f() { int *p; bool v6 = T(0) == p; char *str; - str = "a string"; + str = "a string"; // expected-warning{{conversion from string literal to 'char *' is deprecated}} wchar_t *wstr; - wstr = L"a wide string"; + wstr = L"a wide string"; // expected-warning{{conversion from string literal to 'wchar_t *' is deprecated}} } diff --git a/test/SemaCXX/warn-unreachable.cpp b/test/SemaCXX/warn-unreachable.cpp index a7ed91d..01b36de 100644 --- a/test/SemaCXX/warn-unreachable.cpp +++ b/test/SemaCXX/warn-unreachable.cpp @@ -52,8 +52,8 @@ void test4() { int mem; } s; S &foor(); - halt(), foor() - .mem; // expected-warning {{will never be executed}} + halt(), foor()// expected-warning {{will never be executed}} + .mem; } void test5() { diff --git a/test/SemaObjC/category-1.m b/test/SemaObjC/category-1.m index 33e4646..24324f8 100644 --- a/test/SemaObjC/category-1.m +++ b/test/SemaObjC/category-1.m @@ -73,3 +73,7 @@ @implementation MultipleCat_I // expected-warning {{incomplete implementation}}, expected-warning {{method definition for 'im0' not found}} @end + +// <rdar://problem/7680391> - Handle nameless categories with no name that refer +// to an undefined class +@interface RDar7680391 () @end // expected-error{{cannot find interface declaration}} diff --git a/test/SemaObjC/conditional-expr-7.m b/test/SemaObjC/conditional-expr-7.m new file mode 100644 index 0000000..3ddf3d7 --- /dev/null +++ b/test/SemaObjC/conditional-expr-7.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// radar 7682116 + +@interface Super @end + +@interface NSArray : Super @end +@interface NSSet : Super @end + +@protocol MyProtocol +- (void)myMethod; +@end + +@protocol MyProtocol2 <MyProtocol> +- (void)myMethod2; +@end + +@interface NSArray() <MyProtocol2> +@end + +@interface NSSet() <MyProtocol> +@end + +int main (int argc, const char * argv[]) { + NSArray *array = (void*)0; + NSSet *set = (void*)0; + id <MyProtocol> instance = (argc) ? array : set; + instance = (void*)0; + return 0; +} + diff --git a/test/SemaObjC/duplicate-ivar-in-class-extension.m b/test/SemaObjC/duplicate-ivar-in-class-extension.m new file mode 100644 index 0000000..b66736f --- /dev/null +++ b/test/SemaObjC/duplicate-ivar-in-class-extension.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi2 -verify %s + +@interface Root @end + +@interface SuperClass : Root +{ + int iSuper; // expected-note {{previous declaration is here}} +} +@end + +@interface SubClass : SuperClass { + int ivar; // expected-error {{duplicate member 'ivar'}} + int another_ivar; // expected-error {{duplicate member 'another_ivar'}} + int iSuper; // expected-error {{duplicate member 'iSuper'}} +} +@end + +@interface SuperClass () { + int ivar; // expected-note {{previous declaration is here}} +} +@end + +@interface Root () { + int another_ivar; // expected-note {{previous declaration is here}} +} +@end + +@implementation SubClass +-(int) method { + return self->ivar; // would be ambiguous if the duplicate ivar were allowed +} +@end diff --git a/test/SemaObjC/format-strings-objc.m b/test/SemaObjC/format-strings-objc.m index 7abfe96..1fcc34f 100644 --- a/test/SemaObjC/format-strings-objc.m +++ b/test/SemaObjC/format-strings-objc.m @@ -50,3 +50,8 @@ void rdar_7068334() { printf("%i ",test); // expected-warning{{conversion specifies type 'int' but the argument has type 'long long'}} NSLog(@"%i ",test); // expected-warning{{conversion specifies type 'int' but the argument has type 'long long'}} } + +// <rdar://problem/7697748> +void rdar_7697748() { + NSLog(@"%@!"); // expected-warning{{more '%' conversions than data arguments}} +} diff --git a/test/SemaObjC/ivar-in-class-extension.m b/test/SemaObjC/ivar-in-class-extension.m new file mode 100644 index 0000000..683a78f --- /dev/null +++ b/test/SemaObjC/ivar-in-class-extension.m @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi2 -verify %s + +@interface SomeClass @end + +int fn1(SomeClass *obj) { + obj->privateIvar = 1; // expected-error {{'SomeClass' does not have a member named 'privateIvar}} + return obj->publicIvar; // expected-error {{'SomeClass' does not have a member named 'publicIvar'}} +} + +@interface SomeClass () { +// @private by default + int privateIvar; +@public + int publicIvar; +} +@end + +int fn2(SomeClass *obj) { + obj->publicIvar = 1; + return obj->publicIvar // ok + + obj->privateIvar; // expected-error {{instance variable 'privateIvar' is private}} +} + +@implementation SomeClass + +int fn3(SomeClass *obj) { + obj->privateIvar = 2; + return obj->publicIvar // ok + + obj->privateIvar; // ok + } +@end + +@interface SomeClass (Category) + { // expected-error {{ivar may be placed in a class extension}} + int categoryIvar; + } +@end + +@interface SomeClass (Category1) + { // expected-error {{ivar may be placed in a class extension}} + } +@end diff --git a/test/SemaObjC/ivar-in-implementations.m b/test/SemaObjC/ivar-in-implementations.m new file mode 100644 index 0000000..32d3c35 --- /dev/null +++ b/test/SemaObjC/ivar-in-implementations.m @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi2 -verify %s + +@interface Super @end + +@interface INTFSTANDALONE : Super +{ + id IVAR; // expected-note {{previous definition is here}} +} + +@end + +@implementation INTFSTANDALONE : Super // expected-warning {{class implementation may not have super class}} +{ +@private + id IVAR1; +@protected + id IVAR2; // expected-error {{only private ivars may be declared in implementation}} +@private + id IVAR3; + int IVAR; // expected-error {{instance variable is already declared}} +} +@end diff --git a/test/SemaObjC/method-warn-unused-attribute.m b/test/SemaObjC/method-warn-unused-attribute.m new file mode 100644 index 0000000..d9dcf99 --- /dev/null +++ b/test/SemaObjC/method-warn-unused-attribute.m @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsyntax-only -Wunused-value -verify %s + +@interface INTF +// Currently this is rejected by both GCC and Clang (and Clang was crashing on it). +- (id) foo __attribute__((warn_unused_result)); // expected-warning{{warning: 'warn_unused_result' attribute only applies to function types}} +@end + + diff --git a/test/SemaObjC/property-and-class-extension.m b/test/SemaObjC/property-and-class-extension.m new file mode 100644 index 0000000..51bf8de --- /dev/null +++ b/test/SemaObjC/property-and-class-extension.m @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi2 -verify %s + +/** +When processing @synthesize, treat ivars in a class extension the same as ivars in the class @interface, +and treat ivars in a superclass extension the same as ivars in the superclass @interface. +In particular, when searching for an ivar to back an @synthesize, do look at ivars in the class's own class +extension but ignore any ivars in superclass class extensions. +*/ + +@interface Super { + int ISA; +} +@end + +@interface Super() { + int Property; // expected-note {{previously declared 'Property' here}} +} +@end + +@interface SomeClass : Super { + int interfaceIvar1; + int interfaceIvar2; +} +@property int Property; +@property int Property1; +@end + +@interface SomeClass () { + int Property1; +} +@end + +@implementation SomeClass +@synthesize Property; // expected-error {{property 'Property' attempting to use ivar 'Property' declared in super class 'Super'}} +@synthesize Property1; // OK +@end diff --git a/test/SemaObjC/property-user-setter.m b/test/SemaObjC/property-user-setter.m index babccee..9479bc6 100644 --- a/test/SemaObjC/property-user-setter.m +++ b/test/SemaObjC/property-user-setter.m @@ -70,7 +70,7 @@ static int g_val; { int setterOnly; } -- (void) setSetterOnly:(int)value; +- (void) setSetterOnly:(int)value; // expected-note {{or because setter is declared here, but no getter method 'setterOnly' is found}} @end @implementation Subclass @@ -82,7 +82,7 @@ static int g_val; @interface C {} // - (int)Foo; -- (void)setFoo:(int)value; +- (void)setFoo:(int)value; // expected-note 2 {{or because setter is declared here, but no getter method 'Foo' is found}} @end void g(int); diff --git a/test/SemaObjC/stand-alone-implementation.m b/test/SemaObjC/stand-alone-implementation.m new file mode 100644 index 0000000..c33b66a --- /dev/null +++ b/test/SemaObjC/stand-alone-implementation.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// radar 7547942 +// Allow injection of ivars into implementation's implicit class. + +@implementation INTFSTANDALONE // expected-warning {{cannot find interface declaration for 'INTFSTANDALONE'}} +{ + id IVAR1; + id IVAR2; +} +- (id) Meth { return IVAR1; } +@end + diff --git a/test/SemaObjC/unused.m b/test/SemaObjC/unused.m index 7fdb801..e994188 100644 --- a/test/SemaObjC/unused.m +++ b/test/SemaObjC/unused.m @@ -7,19 +7,14 @@ int printf(const char *, ...); @end @implementation Greeter -+ (void) hello { - printf("Hello, World!\n"); -} ++ (void) hello { printf("Hello, World!\n"); } @end - int test1(void) { [Greeter hello]; return 0; } - - @interface NSObject @end @interface NSString : NSObject - (int)length; @@ -29,10 +24,6 @@ void test2() { @"pointless example call for test purposes".length; // expected-warning {{property access result unused - getters should not have side effects}} } - - - - @interface foo - (int)meth: (int)x: (int)y: (int)z ; @end @@ -42,3 +33,13 @@ void test2() { (int)y: // expected-warning{{unused}} (int) __attribute__((unused))z { return x; } @end + +//===------------------------------------------------------------------------=== +// The next test shows how clang accepted attribute((unused)) on ObjC +// instance variables, which GCC does not. +//===------------------------------------------------------------------------=== + +@interface TestUnusedIvar { + id x __attribute__((unused)); // no-warning +} +@end diff --git a/test/SemaObjCXX/message.mm b/test/SemaObjCXX/message.mm new file mode 100644 index 0000000..93a600a --- /dev/null +++ b/test/SemaObjCXX/message.mm @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +@interface I1 +- (void)method; +@end + +@implementation I1 +- (void)method { + struct x { }; + [x method]; // expected-error{{invalid receiver to message expression}} +} +@end + +typedef struct { int x; } ivar; + +@interface I2 { + id ivar; +} +- (void)method; ++ (void)method; +@end + +@implementation I2 +- (void)method { + [ivar method]; +} ++ (void)method { + [ivar method]; // expected-error{{invalid receiver to message expression}} +} +@end diff --git a/test/SemaObjCXX/vla.mm b/test/SemaObjCXX/vla.mm new file mode 100644 index 0000000..9c6fc54 --- /dev/null +++ b/test/SemaObjCXX/vla.mm @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +@interface Data +- (unsigned)length; +- (void)getData:(void*)buffer; +@end + +void test(Data *d) { + char buffer[[d length]]; // expected-error{{variable length arrays are not permitted in C++}} + [d getData:buffer]; +} + diff --git a/test/SemaTemplate/dependent-base-classes.cpp b/test/SemaTemplate/dependent-base-classes.cpp index 80d20b0..08d4de5 100644 --- a/test/SemaTemplate/dependent-base-classes.cpp +++ b/test/SemaTemplate/dependent-base-classes.cpp @@ -57,7 +57,6 @@ namespace PR6031 { int foo() { class NoDepBase::Nested nested; // expected-error{{'Nested' does not name a tag member in the specified scope}} typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \ - // FIXME: expected-error{{expected an identifier or template-id after '::'}} \ // FIXME: expected-error{{unqualified-id}} return NoDepBase::a; // expected-error{{no member named 'a' in 'struct PR6031::NoDepBase'}} } @@ -110,3 +109,27 @@ namespace PR6081 { } }; } + +namespace PR6413 { + template <typename T> class Base_A { }; + + class Base_B { }; + + template <typename T> + class Derived + : public virtual Base_A<T> + , public virtual Base_B + { }; +} + +namespace PR5812 { + template <class T> struct Base { + Base* p; + }; + + template <class T> struct Derived: public Base<T> { + typename Derived::Base* p; // meaning Derived::Base<T> + }; + + Derived<int> di; +} diff --git a/test/SemaTemplate/destructor-template.cpp b/test/SemaTemplate/destructor-template.cpp index b5ad967..83b1bee 100644 --- a/test/SemaTemplate/destructor-template.cpp +++ b/test/SemaTemplate/destructor-template.cpp @@ -17,3 +17,18 @@ void destroy_me(T me) { } template void destroy_me(Incomplete*); + +namespace PR6152 { + template<typename T> struct X { void f(); }; + template<typename T> struct Y { }; + template<typename T> + void X<T>::f() { + Y<T> *y; + y->template Y<T>::~Y(); + y->template Y<T>::~Y<T>(); + y->~Y(); + } + + template struct X<int>; +} + diff --git a/test/SemaTemplate/explicit-specialization-member.cpp b/test/SemaTemplate/explicit-specialization-member.cpp index 06dd382..cb0a39a 100644 --- a/test/SemaTemplate/explicit-specialization-member.cpp +++ b/test/SemaTemplate/explicit-specialization-member.cpp @@ -9,3 +9,15 @@ struct X0 { template<> void X0<char>::f0(char); template<> void X0<char>::f1(type); + +namespace PR6161 { + template<typename _CharT> + class numpunct : public locale::facet // expected-error{{use of undeclared identifier 'locale'}} \ + // expected-error{{expected class name}} \ + // expected-note{{attempt to specialize declaration here}} + { + static locale::id id; // expected-error{{use of undeclared identifier}} FIXME: expected-error {{unknown type name}} + }; + numpunct<char>::~numpunct(); // expected-error{{template specialization requires 'template<>'}} \ + // expected-error{{specialization of member 'PR6161::numpunct<char>::~numpunct' does not specialize an instantiated member}} +} diff --git a/test/SemaTemplate/instantiate-complete.cpp b/test/SemaTemplate/instantiate-complete.cpp index 183fefa..0ae13b9 100644 --- a/test/SemaTemplate/instantiate-complete.cpp +++ b/test/SemaTemplate/instantiate-complete.cpp @@ -66,3 +66,20 @@ struct X3 { void enum_constructors(X1<float> &x1) { X3<X1<float> > x3 = x1; } + +namespace PR6376 { + template<typename T, typename U> struct W { }; + + template<typename T> + struct X { + template<typename U> + struct apply { + typedef W<T, U> type; + }; + }; + + template<typename T, typename U> + struct Y : public X<T>::template apply<U>::type { }; + + template struct Y<int, float>; +} diff --git a/test/SemaTemplate/instantiate-enum.cpp b/test/SemaTemplate/instantiate-enum.cpp index 6f9aa4b..5353a92 100644 --- a/test/SemaTemplate/instantiate-enum.cpp +++ b/test/SemaTemplate/instantiate-enum.cpp @@ -9,3 +9,19 @@ struct adder { }; int array1[adder<long, 3, 4>::value == 7? 1 : -1]; + +namespace PR6375 { + template<typename T> + void f() { + enum Enum + { + enumerator1 = 0xFFFFFFF, + enumerator2 = enumerator1 - 1 + }; + + int xb1 = enumerator1; + int xe1 = enumerator2; + } + + template void f<int>(); +} diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp index d1b05f6..37145b6 100644 --- a/test/SemaTemplate/instantiate-expr-1.cpp +++ b/test/SemaTemplate/instantiate-expr-1.cpp @@ -137,3 +137,36 @@ void test_asm() { int b; test_asm(b); // expected-note {{in instantiation of function template specialization 'test_asm<int>' requested here}} } + +namespace PR6424 { + template<int I> struct X { + X() { + int *ip = I; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + } + }; + + template<int> struct Y { + typedef X<7> X7; + + void f() { X7(); } // expected-note{{instantiation}} + }; + + template void Y<3>::f(); + + template<int I> + struct X2 { + void *operator new(__SIZE_TYPE__) { + int *ip = I; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} + return ip; + } + }; + + template<int> struct Y2 { + typedef X2<7> X; + void f() { + new X(); // expected-note{{instantiation of}} + } + }; + + template void Y2<3>::f(); +} diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp index 543b3cc..144c630 100644 --- a/test/SemaTemplate/instantiate-function-1.cpp +++ b/test/SemaTemplate/instantiate-function-1.cpp @@ -177,9 +177,11 @@ template<typename T> struct IndirectGoto0 { goto *x; // expected-error{{incompatible}} prior: - T prior_label = &&prior; + T prior_label; + prior_label = &&prior; - T later_label = &&later; + T later_label; + later_label = &&later; later: (void)(1+1); diff --git a/test/SemaTemplate/instantiate-init.cpp b/test/SemaTemplate/instantiate-init.cpp index 8a10a87..16ecc47 100644 --- a/test/SemaTemplate/instantiate-init.cpp +++ b/test/SemaTemplate/instantiate-init.cpp @@ -26,3 +26,14 @@ void test_f1(X0 *x0, int *ip, float *fp, double *dp) { f1(x0, ip, dp); // expected-note{{instantiation}} } +namespace PR6457 { + template <typename T> struct X { explicit X(T* p = 0) { }; }; + template <typename T> struct Y { Y(int, const T& x); }; + struct A { }; + template <typename T> + struct B { + B() : y(0, X<A>()) { } + Y<X<A> > y; + }; + B<int> b; +} diff --git a/test/SemaTemplate/instantiate-invalid.cpp b/test/SemaTemplate/instantiate-invalid.cpp new file mode 100644 index 0000000..b8a5901 --- /dev/null +++ b/test/SemaTemplate/instantiate-invalid.cpp @@ -0,0 +1,52 @@ +// RUN: not %clang_cc1 -fsyntax-only %s +namespace PR6375 { + template<class Conv> class rasterizer_sl_clip Conv::xi(x2), Conv::yi(y2)); +namespace agg +{ + template<class Clip=rasterizer_sl_clip_int> class rasterizer_scanline_aa + { + template<class Scanline> bool sweep_scanline(Scanline& sl) + { + unsigned num_cells = m_outline.scanline_num_cells(m_scan_y); + while(num_cells) { } + } + } + class scanline_u8 {} + template<class PixelFormat> class renderer_base { } +} + template<class Rasterizer, class Scanline, class BaseRenderer, class ColorT> + void render_scanlines_aa_solid(Rasterizer& ras, Scanline& sl, BaseRenderer& ren, const ColorT& color) + { + while(ras.sweep_scanline(sl)) + { + } + }; +namespace agg +{ + struct rgba8 + { + }; + template<class Rasterizer, class Scanline, class Renderer, class Ctrl> + void render_ctrl(Rasterizer& ras, Scanline& sl, Renderer& r, Ctrl& c) + { + unsigned i; + render_scanlines_aa_solid(ras, sl, r, c.color(i)); + } + template<class ColorT> class rbox_ctrl : public rbox_ctrl_impl + { + const ColorT& color(unsigned i) const { return *m_colors[i]; } + } +class the_application : public agg::platform_support +{ + agg::rbox_ctrl<agg::rgba8> m_polygons; + virtual void on_init() + { + typedef agg::renderer_base<pixfmt_type> base_ren_type; + base_ren_type ren_base(pf); + agg::scanline_u8 sl; + agg::rasterizer_scanline_aa<> ras; + agg::render_ctrl(ras, sl, ren_base, m_polygons); + } +}; +} +} diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp index 789fe3d..fda2b9ea 100644 --- a/test/SemaTemplate/instantiate-static-var.cpp +++ b/test/SemaTemplate/instantiate-static-var.cpp @@ -92,3 +92,26 @@ struct SizeOf { void MyTest3() { Y3().Foo(X3<SizeOf<char>::value>()); } + +namespace PR6449 { + template<typename T> + struct X0 { + static const bool var = false; + }; + + template<typename T> + const bool X0<T>::var; + + template<typename T> + struct X1 : public X0<T> { + static const bool var = false; + }; + + template<typename T> + const bool X1<T>::var; + + template class X0<char>; + template class X1<char>; + +} + diff --git a/test/SemaTemplate/member-access-expr.cpp b/test/SemaTemplate/member-access-expr.cpp index 116e837..24db791 100644 --- a/test/SemaTemplate/member-access-expr.cpp +++ b/test/SemaTemplate/member-access-expr.cpp @@ -63,11 +63,13 @@ void test_convert(X2 x2) { template<typename T> void destruct(T* ptr) { ptr->~T(); + ptr->T::~T(); } template<typename T> void destruct_intptr(int *ip) { ip->~T(); + ip->T::~T(); } void test_destruct(X2 *x2p, int *ip) { diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp index 704b8cf..1691db7 100644 --- a/test/SemaTemplate/nested-name-spec-template.cpp +++ b/test/SemaTemplate/nested-name-spec-template.cpp @@ -49,6 +49,5 @@ struct ::N::A<int>::X { template<typename T> struct TestA { typedef typename N::template B<T>::type type; // expected-error{{'B' following the 'template' keyword does not refer to a template}} \ - // expected-error{{identifier or template-id}} \ // expected-error{{expected member name}} }; diff --git a/test/SemaTemplate/temp_arg.cpp b/test/SemaTemplate/temp_arg.cpp index 3c9fcb5..80bbda7 100644 --- a/test/SemaTemplate/temp_arg.cpp +++ b/test/SemaTemplate/temp_arg.cpp @@ -10,3 +10,10 @@ 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'}} + +namespace test0 { + template <class t> class foo {}; + template <class t> class bar { + bar(::test0::foo<tee> *ptr) {} // FIXME(redundant): expected-error 2 {{use of undeclared identifier 'tee'}} + }; +} diff --git a/test/SemaTemplate/template-decl-fail.cpp b/test/SemaTemplate/template-decl-fail.cpp index a298c6d..eca0f58 100644 --- a/test/SemaTemplate/template-decl-fail.cpp +++ b/test/SemaTemplate/template-decl-fail.cpp @@ -1,3 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s template<typename T> typedef T X; // expected-error{{typedef cannot be a template}} + +template<typename T> +enum t0 { A = T::x }; // expected-error{{enumeration cannot be a template}} \ + // expected-error{{declaration does not declare anything}} + diff --git a/test/SemaTemplate/virtual-member-functions.cpp b/test/SemaTemplate/virtual-member-functions.cpp index db24313..58ac08c 100644 --- a/test/SemaTemplate/virtual-member-functions.cpp +++ b/test/SemaTemplate/virtual-member-functions.cpp @@ -14,7 +14,7 @@ template<class T> int A<T>::a(T x) { } void f(A<int> x) { - x.anchor(); + x.anchor(); // expected-note{{in instantiation of member function 'PR5557::A<int>::anchor' requested here}} } template<typename T> @@ -36,10 +36,10 @@ struct Base { template<typename T> struct Derived : Base<T> { - virtual void foo() { } + virtual void foo() { } // expected-note {{in instantiation of member function 'Base<int>::~Base' requested here}} }; -template struct Derived<int>; // expected-note{{instantiation}} +template struct Derived<int>; template<typename T> struct HasOutOfLineKey { @@ -52,4 +52,4 @@ T *HasOutOfLineKey<T>::f(float *fp) { return fp; // expected-error{{cannot initialize return object of type 'int *' with an lvalue of type 'float *'}} } -HasOutOfLineKey<int> out_of_line; +HasOutOfLineKey<int> out_of_line; // expected-note{{in instantiation of member function 'HasOutOfLineKey<int>::HasOutOfLineKey' requested here}} diff --git a/test/lit.cfg b/test/lit.cfg index 4d7a17a..beb8ae0 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -123,12 +123,15 @@ config.clang = inferClang(config.environment['PATH']) if not lit.quiet: lit.note('using clang: %r' % config.clang) config.substitutions.append( ('%clang_cc1', config.clang + ' -cc1') ) +config.substitutions.append( ('%clangxx', ' ' + config.clang + ' -ccc-cxx')) config.substitutions.append( ('%clang', ' ' + config.clang + ' ') ) # FIXME: Find nicer way to prohibit this. config.substitutions.append( (' clang ', """*** Do not use 'clang' in tests, use '%clang'. ***""") ) config.substitutions.append( + (' clang++ ', """*** Do not use 'clang++' in tests, use '%clangxx'. ***""")) +config.substitutions.append( (' clang-cc ', """*** Do not use 'clang-cc' in tests, use '%clang_cc1'. ***""") ) config.substitutions.append( |