summaryrefslogtreecommitdiff
path: root/test/CXX
diff options
context:
space:
mode:
Diffstat (limited to 'test/CXX')
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp27
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp73
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp42
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp18
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp65
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp41
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp25
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp35
-rw-r--r--test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp4
-rw-r--r--test/CXX/basic/basic.start/basic.start.main/p2a.cpp8
-rw-r--r--test/CXX/basic/basic.start/basic.start.main/p2b.cpp8
-rw-r--r--test/CXX/basic/basic.start/basic.start.main/p2c.cpp4
-rw-r--r--test/CXX/basic/basic.start/basic.start.main/p2d.cpp4
-rw-r--r--test/CXX/basic/basic.start/basic.start.main/p2e.cpp4
-rw-r--r--test/CXX/basic/basic.start/basic.start.main/p2f.cpp7
-rw-r--r--test/CXX/basic/basic.start/basic.start.main/p2g.cpp4
-rw-r--r--test/CXX/basic/basic.stc/basic.stc.dynamic/p2-nodef.cpp7
-rw-r--r--test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp25
-rw-r--r--test/CXX/class.derived/class.virtual/p12.cpp19
-rw-r--r--test/CXX/class/class.friend/p1-ambiguous.cpp37
-rw-r--r--test/CXX/class/class.friend/p1.cpp76
-rw-r--r--test/CXX/class/class.friend/p2.cpp10
-rw-r--r--test/CXX/class/class.friend/p6.cpp10
-rw-r--r--test/CXX/class/class.local/p3.cpp2
-rw-r--r--test/CXX/class/class.local/p4.cpp2
-rw-r--r--test/CXX/class/class.nest/p1.cpp14
-rw-r--r--test/CXX/class/class.nested.type/p1.cpp4
-rw-r--r--test/CXX/class/class.union/p1.cpp105
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp15
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp20
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp12
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp8
-rw-r--r--test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp15
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp4
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp10
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp13
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp60
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p10.cpp16
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p2.cpp9
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp13
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp55
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p5.cpp18
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp32
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp7
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p8.cpp4
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp3
-rw-r--r--test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp26
-rw-r--r--test/CXX/expr/p3.cpp15
-rw-r--r--test/CXX/expr/p8.cpp18
-rw-r--r--test/CXX/expr/p9.cpp50
-rw-r--r--test/CXX/lex/lex.trigraph/p1.cpp19
-rw-r--r--test/CXX/lex/lex.trigraph/p2.cpp3
-rw-r--r--test/CXX/lex/lex.trigraph/p3.cpp8
-rw-r--r--test/CXX/over/over.match/over.match.best/p1.cpp16
-rw-r--r--test/CXX/over/over.over/p1.cpp94
-rw-r--r--test/CXX/over/over.over/p2.cpp10
-rw-r--r--test/CXX/over/over.over/p4.cpp23
-rw-r--r--test/CXX/temp/temp.decls/temp.class.spec/p6.cpp20
-rw-r--r--test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp16
-rw-r--r--test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp25
-rw-r--r--test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp26
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp27
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp28
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp68
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp17
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp17
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp28
-rw-r--r--test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp26
-rw-r--r--test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp23
-rw-r--r--test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp12
-rw-r--r--test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp6
-rw-r--r--test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp16
-rw-r--r--test/CXX/temp/temp.decls/temp.friend/p1.cpp56
-rw-r--r--test/CXX/temp/temp.decls/temp.friend/p3.cpp13
-rw-r--r--test/CXX/temp/temp.decls/temp.friend/p5.cpp11
-rw-r--r--test/CXX/temp/temp.decls/temp.mem/p1.cpp16
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp2
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp32
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp36
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp30
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp44
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp22
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp22
-rw-r--r--test/CXX/temp/temp.param/p1.cpp3
-rw-r--r--test/CXX/temp/temp.res/temp.dep/p3.cpp43
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp99
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp7
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp8
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp6
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp42
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp22
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp26
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp12
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp20
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp30
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp239
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp14
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp30
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp14
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp59
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp61
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp56
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp14
103 files changed, 2706 insertions, 14 deletions
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp
new file mode 100644
index 0000000000000..e2c76f9183362
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2-template-id.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace N1 {
+ struct X { };
+ int& f(void*);
+}
+
+namespace N2 {
+ template<typename T> struct Y { };
+}
+
+namespace N3 {
+ void test() {
+ int &ir = f((N2::Y<N1::X>*)0);
+ }
+}
+
+int g(void *);
+long g(N1::X);
+
+namespace N1 {
+ void h(int (*)(void *));
+}
+
+void test() {
+ h((&g));
+}
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp
new file mode 100644
index 0000000000000..677df8284a72c
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p2.cpp
@@ -0,0 +1,73 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace N {
+ struct X { };
+
+ X operator+(X, X);
+
+ void f(X);
+ void g(X); // expected-note{{candidate function}}
+
+ void test_multiadd(X x) {
+ (void)(x + x);
+ }
+}
+
+namespace M {
+ struct Y : N::X { };
+}
+
+void f();
+
+void test_operator_adl(N::X x, M::Y y) {
+ (void)(x + x);
+ (void)(y + y);
+}
+
+void test_func_adl(N::X x, M::Y y) {
+ f(x);
+ f(y);
+ (f)(x); // expected-error{{too many arguments to function call}}
+ ::f(x); // expected-error{{too many arguments to function call}}
+}
+
+namespace N {
+ void test_multiadd2(X x) {
+ (void)(x + x);
+ }
+}
+
+
+void test_func_adl_only(N::X x) {
+ g(x);
+}
+
+namespace M {
+ int g(N::X); // expected-note{{candidate function}}
+
+ void test(N::X x) {
+ g(x); // expected-error{{call to 'g' is ambiguous; candidates are:}}
+ int i = (g)(x);
+
+ int g(N::X);
+ g(x); // okay; calls locally-declared function, no ADL
+ }
+}
+
+
+void test_operator_name_adl(N::X x) {
+ (void)operator+(x, x);
+}
+
+struct Z { };
+int& f(Z);
+
+namespace O {
+ char &f();
+ void test_global_scope_adl(Z z) {
+ {
+ int& ir = f(z);
+ }
+ }
+}
+
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
new file mode 100644
index 0000000000000..8f0bed8789fe6
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp
@@ -0,0 +1,42 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace A {
+ class A {
+ friend void func(A);
+ friend A operator+(A,A);
+ };
+}
+
+namespace B {
+ class B {
+ static void func(B);
+ };
+ B operator+(B,B);
+}
+
+namespace D {
+ class D {};
+}
+
+namespace C {
+ class C {};
+ void func(C);
+ C operator+(C,C);
+ D::D operator+(D::D,D::D);
+}
+
+namespace D {
+ using namespace C;
+}
+
+namespace Test {
+ void test() {
+ func(A::A());
+ func(B::B()); // expected-error {{ no matching function for call to 'func' }}
+ func(C::C());
+ A::A() + A::A();
+ B::B() + B::B();
+ C::C() + C::C();
+ D::D() + D::D(); // expected-error {{ invalid operands to binary expression ('D::D' and 'D::D') }}
+ }
+}
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp b/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp
new file mode 100644
index 0000000000000..cb9d942ba6f69
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.elab/templateid.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// elaborated-type-specifier:
+// class-key '::'? nested-name-specifier? 'template'? simple-template-id
+// Tests that this form is accepted by the compiler but does not follow
+// the elaborated lookup rules of [basic.lookup.elab].
+
+template <typename> class Ident {}; // expected-note {{previous use is here}}
+
+namespace A {
+ template <typename> void Ident();
+
+ class Ident<int> AIdent; // expected-error {{refers to a function template}}
+ class ::Ident<int> AnotherIdent;
+}
+
+class Ident<int> GlobalIdent;
+union Ident<int> GlobalIdent; // expected-error {{ tag type that does not match }}
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
new file mode 100644
index 0000000000000..b32948b4a608f
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p2.cpp
@@ -0,0 +1,65 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace Ints {
+ int zero = 0; // expected-note {{candidate found by name lookup is 'Ints::zero'}}
+ void f(int); // expected-note 3 {{candidate function}}
+ void g(int);
+}
+
+namespace Floats {
+ float zero = 0.0f; // expected-note {{candidate found by name lookup is 'Floats::zero'}}
+ void f(float); // expected-note 3 {{candidate function}}
+ void g(float);
+}
+
+namespace Numbers {
+ using namespace Ints;
+ using namespace Floats;
+}
+
+void test() {
+ int i = Ints::zero;
+ Ints::f(i);
+
+ float f = Floats::zero;
+ Floats::f(f);
+
+ double n = Numbers::zero; // expected-error {{reference to 'zero' is ambiguous}}
+ Numbers::f(n); // expected-error{{call to 'f' is ambiguous}}
+ Numbers::f(i);
+ Numbers::f(f);
+}
+
+namespace Numbers {
+ struct Number {
+ explicit Number(double d) : d(d) {}
+ double d;
+ };
+ Number zero(0.0f);
+ void g(Number);
+}
+
+void test2() {
+ Numbers::Number n = Numbers::zero;
+ Numbers::f(n); // expected-error {{no matching function for call to 'f'}}
+ Numbers::g(n);
+}
+
+namespace Numbers2 {
+ using Numbers::f;
+ using Numbers::g;
+}
+
+void test3() {
+ Numbers::Number n = Numbers::zero;
+ Numbers2::f(n); // expected-error {{no matching function for call to 'f'}}
+ Numbers2::g(n);
+
+ int i = Ints::zero;
+ Numbers2::f(i);
+ Numbers2::g(i); // expected-error {{incompatible type passing 'int'}}
+
+ float f = Floats::zero;
+ Numbers2::f(f);
+ Numbers2::g(f); // expected-error {{incompatible type passing 'float'}}
+}
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp
new file mode 100644
index 0000000000000..7a51a7bb1df07
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p3.cpp
@@ -0,0 +1,41 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// This is basically paraphrased from the standard.
+
+namespace Root {
+ int i = 0;
+ void f();
+}
+
+namespace A {
+ using namespace Root;
+}
+
+namespace B {
+ using namespace Root;
+}
+
+namespace AB {
+ using namespace A;
+ using namespace B;
+}
+
+void test() {
+ if (AB::i)
+ AB::f();
+}
+
+namespace C {
+ using Root::i;
+ using Root::f;
+}
+
+namespace AC {
+ using namespace A;
+ using namespace C;
+}
+
+void test2() {
+ if (AC::i)
+ AC::f();
+}
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp
new file mode 100644
index 0000000000000..2c0ce80d8ce69
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p4.cpp
@@ -0,0 +1,25 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace A {
+ int a;
+}
+
+namespace C {
+ int c;
+}
+
+namespace B {
+ using namespace C;
+ int b;
+}
+
+namespace C {
+ using namespace B;
+ using namespace A;
+}
+
+void test() {
+ C::a++;
+ C::b++;
+ C::c++;
+}
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp
new file mode 100644
index 0000000000000..78af521c91030
--- /dev/null
+++ b/test/CXX/basic/basic.lookup/basic.lookup.qual/namespace.qual/p5.cpp
@@ -0,0 +1,35 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace A {
+ struct x {}; // expected-note {{candidate found by name lookup is 'A::x'}}
+ int x; // expected-note {{candidate found by name lookup is 'A::x'}}
+
+ struct y {}; // expected-note {{type declaration hidden}}
+
+ struct z;
+ void z(float);
+}
+
+namespace B {
+ struct x {}; // expected-note {{candidate found by name lookup is 'B::x'}}
+ float x; // expected-note {{candidate found by name lookup is 'B::x'}}
+
+ float y; // expected-note {{declaration hides type}}
+
+ void z(int);
+}
+
+namespace AB {
+ using namespace A;
+ using namespace B;
+}
+
+void test() {
+ struct AB::x foo; // expected-error {{reference to 'x' is ambiguous}}
+ int i = AB::x; // expected-error {{reference to 'x' is ambiguous}}
+
+ struct AB::y bar;
+ float f = AB::y; // expected-error {{a type named 'y' is hidden by a declaration in a different namespace}}
+ AB::z(i);
+ AB::z(f);
+}
diff --git a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
index 1daf0ddec6c05..7fd1b53c2cb0e 100644
--- a/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
+++ b/test/CXX/basic/basic.lookup/basic.lookup.unqual/p3.cpp
@@ -1,9 +1,7 @@
// RUN: clang-cc -fsyntax-only -verify %s
-// XFAIL
-// FIXME: This part is here to demonstrate the failure in looking up 'f', it can
-// be removed once the whole test passes.
typedef int f;
+
namespace N0 {
struct A {
friend void f();
diff --git a/test/CXX/basic/basic.start/basic.start.main/p2a.cpp b/test/CXX/basic/basic.start/basic.start.main/p2a.cpp
new file mode 100644
index 0000000000000..a6a758798949f
--- /dev/null
+++ b/test/CXX/basic/basic.start/basic.start.main/p2a.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef int Int;
+typedef char Char;
+typedef Char* Carp;
+
+Int main(Int argc, Carp argv[]) {
+}
diff --git a/test/CXX/basic/basic.start/basic.start.main/p2b.cpp b/test/CXX/basic/basic.start/basic.start.main/p2b.cpp
new file mode 100644
index 0000000000000..caecf60608817
--- /dev/null
+++ b/test/CXX/basic/basic.start/basic.start.main/p2b.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef int Int;
+typedef char Char;
+typedef Char* Carp;
+
+Int main(Int argc, Carp argv[], Char *env[]) {
+}
diff --git a/test/CXX/basic/basic.start/basic.start.main/p2c.cpp b/test/CXX/basic/basic.start/basic.start.main/p2c.cpp
new file mode 100644
index 0000000000000..8587d8cec791b
--- /dev/null
+++ b/test/CXX/basic/basic.start/basic.start.main/p2c.cpp
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+int main() {
+}
diff --git a/test/CXX/basic/basic.start/basic.start.main/p2d.cpp b/test/CXX/basic/basic.start/basic.start.main/p2d.cpp
new file mode 100644
index 0000000000000..777b5ceb743a3
--- /dev/null
+++ b/test/CXX/basic/basic.start/basic.start.main/p2d.cpp
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+static int main() { // expected-error {{'main' is not allowed to be declared static}}
+}
diff --git a/test/CXX/basic/basic.start/basic.start.main/p2e.cpp b/test/CXX/basic/basic.start/basic.start.main/p2e.cpp
new file mode 100644
index 0000000000000..087cf77476ad4
--- /dev/null
+++ b/test/CXX/basic/basic.start/basic.start.main/p2e.cpp
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+inline int main() { // expected-error {{'main' is not allowed to be declared inline}}
+}
diff --git a/test/CXX/basic/basic.start/basic.start.main/p2f.cpp b/test/CXX/basic/basic.start/basic.start.main/p2f.cpp
new file mode 100644
index 0000000000000..b7845b13e9a4b
--- /dev/null
+++ b/test/CXX/basic/basic.start/basic.start.main/p2f.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void // expected-error {{error: 'main' must return 'int'}}
+main( // expected-error {{error: first argument of 'main' should be of type 'int'}}
+ float a
+) {
+}
diff --git a/test/CXX/basic/basic.start/basic.start.main/p2g.cpp b/test/CXX/basic/basic.start/basic.start.main/p2g.cpp
new file mode 100644
index 0000000000000..4cedcdb916573
--- /dev/null
+++ b/test/CXX/basic/basic.start/basic.start.main/p2g.cpp
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+int main(int argc, const char* const* argv) {
+}
diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-nodef.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-nodef.cpp
new file mode 100644
index 0000000000000..ff653d5fef08f
--- /dev/null
+++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2-nodef.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+int *use_new(int N) {
+ return new int [N];
+}
+
+int std = 17;
diff --git a/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp
new file mode 100644
index 0000000000000..f3499e4286bcc
--- /dev/null
+++ b/test/CXX/basic/basic.stc/basic.stc.dynamic/p2.cpp
@@ -0,0 +1,25 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+int *use_new(int N) {
+ if (N == 1)
+ return new int;
+
+ return new int [N];
+}
+
+void use_delete(int* ip, int N) {
+ if (N == 1)
+ delete ip;
+ else
+ delete [] ip;
+}
+
+namespace std {
+ class bad_alloc { };
+
+ typedef __SIZE_TYPE__ size_t;
+}
+
+void* operator new(std::size_t) throw(std::bad_alloc);
+void* operator new[](std::size_t) throw(std::bad_alloc);
+void operator delete(void*) throw();
+void operator delete[](void*) throw();
diff --git a/test/CXX/class.derived/class.virtual/p12.cpp b/test/CXX/class.derived/class.virtual/p12.cpp
new file mode 100644
index 0000000000000..b5974a0211807
--- /dev/null
+++ b/test/CXX/class.derived/class.virtual/p12.cpp
@@ -0,0 +1,19 @@
+// RUN: clang-cc -ast-print %s | FileCheck %s
+
+// CHECK: test12_A::foo()
+struct test12_A {
+ virtual void foo();
+
+ void bar() {
+ test12_A::foo();
+ }
+};
+
+// CHECK: xp->test24_B::wibble()
+struct test24_B {
+ virtual void wibble();
+};
+
+void foo(test24_B *xp) {
+ xp->test24_B::wibble();
+}
diff --git a/test/CXX/class/class.friend/p1-ambiguous.cpp b/test/CXX/class/class.friend/p1-ambiguous.cpp
new file mode 100644
index 0000000000000..a02bc53375220
--- /dev/null
+++ b/test/CXX/class/class.friend/p1-ambiguous.cpp
@@ -0,0 +1,37 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Make sure that friend declarations don't introduce ambiguous
+// declarations.
+
+// Test case courtesy of Shantonu Sen.
+// Bug 4784.
+
+class foo;
+
+extern "C" {
+ int c_func(foo *a);
+};
+int cpp_func(foo *a);
+
+class foo {
+public:
+ friend int c_func(foo *a);
+ friend int cpp_func(foo *a);
+ int caller();
+private:
+ int x;
+};
+
+int c_func(foo *a) {
+ return a->x;
+}
+
+int cpp_func(foo *a) {
+ return a->x;
+}
+
+int foo::caller() {
+ c_func(this);
+ cpp_func(this);
+ return 0;
+}
diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp
new file mode 100644
index 0000000000000..7065a7e917fd7
--- /dev/null
+++ b/test/CXX/class/class.friend/p1.cpp
@@ -0,0 +1,76 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct Outer {
+ struct Inner {
+ int intfield;
+ };
+};
+
+struct Base {
+ void base_member();
+
+ typedef int Int;
+ Int typedeffed_member();
+};
+
+struct Derived : public Base {
+};
+
+int myglobal;
+
+void global_function();
+extern "C" {
+ void global_c_function();
+}
+
+class A {
+ class AInner {
+ };
+
+ friend class PreDeclared;
+ friend class Outer::Inner;
+ friend int Outer::Inner::intfield; // expected-error {{ friends can only be classes or functions }}
+ friend int Outer::Inner::missing_field; //expected-error {{ friends can only be classes or functions }}
+ friend int myoperation(float); // okay
+ friend int myglobal; // expected-error {{ friends can only be classes or functions }}
+
+ friend void global_function();
+ friend void global_c_function();
+
+ friend class UndeclaredSoFar;
+ UndeclaredSoFar x; // expected-error {{ unknown type name 'UndeclaredSoFar' }}
+
+ void a_member();
+ friend void A::a_member(); // expected-error {{ friends cannot be members of the declaring class }}
+ friend void a_member(); // okay (because we ignore class scopes when looking up friends)
+ friend class A::AInner; // this is okay as an extension
+ friend class AInner; // okay, refers to ::AInner
+
+ friend void Derived::missing_member(); // expected-error {{ no function named 'missing_member' with type 'void ()' was found in the specified scope }}
+
+ friend void Derived::base_member(); // expected-error {{ no function named 'base_member' with type 'void ()' was found in the specified scope }}
+
+ friend int Base::typedeffed_member(); // okay: should look through typedef
+
+ // These test that the friend is properly not being treated as a
+ // member function.
+ friend A operator|(const A& l, const A& r); // okay
+ friend A operator|(const A& r); // expected-error {{ overloaded 'operator|' must be a binary operator (has 1 parameter) }}
+
+ friend operator bool() const; // expected-error {{ must use a qualified name when declaring a conversion operator as a friend }}
+
+ typedef void ftypedef();
+ friend ftypedef typedeffed_function; // okay (because it's not declared as a member)
+
+ class facet;
+ friend class facet; // should not assert
+ class facet {};
+};
+
+A::UndeclaredSoFar y; // expected-error {{no type named 'UndeclaredSoFar' in 'class A'}}
+
+class PreDeclared;
+
+int myoperation(float f) {
+ return (int) f;
+}
diff --git a/test/CXX/class/class.friend/p2.cpp b/test/CXX/class/class.friend/p2.cpp
new file mode 100644
index 0000000000000..98be2049e7566
--- /dev/null
+++ b/test/CXX/class/class.friend/p2.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct B0;
+
+class A {
+ friend class B {}; // expected-error {{cannot define a type in a friend declaration}}
+ friend int; // expected-error {{friends can only be classes or functions}}
+ friend B0; // expected-error {{must specify 'struct' to befriend}}
+ friend class C; // okay
+};
diff --git a/test/CXX/class/class.friend/p6.cpp b/test/CXX/class/class.friend/p6.cpp
new file mode 100644
index 0000000000000..2e8153c6c0471
--- /dev/null
+++ b/test/CXX/class/class.friend/p6.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class A {
+ friend static class B; // expected-error {{'static' is invalid in friend declarations}}
+ friend extern class C; // expected-error {{'extern' is invalid in friend declarations}}
+ friend auto class D; // expected-error {{'auto' is invalid in friend declarations}}
+ friend register class E; // expected-error {{'register' is invalid in friend declarations}}
+ friend mutable class F; // expected-error {{'mutable' is invalid in friend declarations}}
+ friend typedef class G; // expected-error {{'typedef' is invalid in friend declarations}}
+};
diff --git a/test/CXX/class/class.local/p3.cpp b/test/CXX/class/class.local/p3.cpp
index d888a6d936330..9c625d18c95c2 100644
--- a/test/CXX/class/class.local/p3.cpp
+++ b/test/CXX/class/class.local/p3.cpp
@@ -27,4 +27,4 @@ void f3(int a) { // expected-note{{'a' declared here}}
int f() { return a; } // expected-error{{reference to local variable 'a' declared in enclosed function 'f3'}}
};
};
-} \ No newline at end of file
+}
diff --git a/test/CXX/class/class.local/p4.cpp b/test/CXX/class/class.local/p4.cpp
index 40702ad968993..f2432ec973932 100644
--- a/test/CXX/class/class.local/p4.cpp
+++ b/test/CXX/class/class.local/p4.cpp
@@ -7,4 +7,4 @@ void f() {
static void f() { }
};
-} \ No newline at end of file
+}
diff --git a/test/CXX/class/class.nest/p1.cpp b/test/CXX/class/class.nest/p1.cpp
new file mode 100644
index 0000000000000..bbc49f9e95e7b
--- /dev/null
+++ b/test/CXX/class/class.nest/p1.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class Outer {
+ int x;
+ static int sx;
+
+ // C++0x will likely relax this rule in this specific case, but
+ // we'll still need to enforce it in C++03 mode. See N2253 (or
+ // successor).
+ class Inner {
+ static char a[sizeof(x)]; // expected-error {{ invalid use of nonstatic data member 'x' }}
+ static char b[sizeof(sx)]; // okay
+ };
+};
diff --git a/test/CXX/class/class.nested.type/p1.cpp b/test/CXX/class/class.nested.type/p1.cpp
index 33bf4b4473e50..61ccd281ca937 100644
--- a/test/CXX/class/class.nested.type/p1.cpp
+++ b/test/CXX/class/class.nested.type/p1.cpp
@@ -1,3 +1,5 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
class X {
public:
typedef int I;
@@ -8,4 +10,4 @@ public:
I b; // expected-error{{unknown type name 'I'}}
Y c; // expected-error{{unknown type name 'Y'}}
X::Y d;
-X::I e; \ No newline at end of file
+X::I e;
diff --git a/test/CXX/class/class.union/p1.cpp b/test/CXX/class/class.union/p1.cpp
new file mode 100644
index 0000000000000..15c2634673675
--- /dev/null
+++ b/test/CXX/class/class.union/p1.cpp
@@ -0,0 +1,105 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void abort() __attribute__((noreturn));
+
+class Okay {
+ int a_;
+};
+
+class Virtual {
+ virtual void foo() { abort(); } // expected-note 3 {{because type 'class Virtual' has a virtual member function}}
+};
+
+class VirtualBase : virtual Okay { // expected-note 3 {{because type 'class VirtualBase' has a virtual base class}}
+};
+
+class Ctor {
+ Ctor() { abort(); } // expected-note 3 {{because type 'class Ctor' has a user-declared constructor}}
+};
+
+class CopyCtor {
+ CopyCtor(CopyCtor &cc) { abort(); } // expected-note 3 {{because type 'class CopyCtor' has a user-declared copy constructor}}
+};
+
+// FIXME: this should eventually trigger on the operator's declaration line
+class CopyAssign { // expected-note 3 {{because type 'class CopyAssign' has a user-declared copy assignment operator}}
+ CopyAssign& operator=(CopyAssign& CA) { abort(); }
+};
+
+class Dtor {
+ ~Dtor() { abort(); } // expected-note 3 {{because type 'class Dtor' has a user-declared destructor}}
+};
+
+union U1 {
+ Virtual v; // expected-error {{union member 'v' has a non-trivial copy constructor}}
+ VirtualBase vbase; // expected-error {{union member 'vbase' has a non-trivial copy constructor}}
+ Ctor ctor; // expected-error {{union member 'ctor' has a non-trivial constructor}}
+ CopyCtor copyctor; // expected-error {{union member 'copyctor' has a non-trivial copy constructor}}
+ CopyAssign copyassign; // expected-error {{union member 'copyassign' has a non-trivial copy assignment operator}}
+ Dtor dtor; // expected-error {{union member 'dtor' has a non-trivial destructor}}
+ Okay okay;
+};
+
+union U2 {
+ struct {
+ Virtual v; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}}
+ } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}}
+ struct {
+ VirtualBase vbase; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}}
+ } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}}
+ struct {
+ Ctor ctor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial constructor}}
+ } m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
+ struct {
+ CopyCtor copyctor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy constructor}}
+ } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
+ struct {
+ CopyAssign copyassign; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial copy assignment operator}}
+ } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}}
+ struct {
+ Dtor dtor; // expected-note {{because type 'struct U2::<anonymous>' has a member with a non-trivial destructor}}
+ } m6; // expected-error {{union member 'm6' has a non-trivial destructor}}
+ struct {
+ Okay okay;
+ } m7;
+};
+
+union U3 {
+ struct s1 : Virtual { // expected-note {{because type 'struct U3::s1' has a base class with a non-trivial copy constructor}}
+ } m1; // expected-error {{union member 'm1' has a non-trivial copy constructor}}
+ struct s2 : VirtualBase { // expected-note {{because type 'struct U3::s2' has a base class with a non-trivial copy constructor}}
+ } m2; // expected-error {{union member 'm2' has a non-trivial copy constructor}}
+ struct s3 : Ctor { // expected-note {{because type 'struct U3::s3' has a base class with a non-trivial constructor}}
+ } m3; // expected-error {{union member 'm3' has a non-trivial constructor}}
+ struct s4 : CopyCtor { // expected-note {{because type 'struct U3::s4' has a base class with a non-trivial copy constructor}}
+ } m4; // expected-error {{union member 'm4' has a non-trivial copy constructor}}
+ struct s5 : CopyAssign { // expected-note {{because type 'struct U3::s5' has a base class with a non-trivial copy assignment operator}}
+ } m5; // expected-error {{union member 'm5' has a non-trivial copy assignment operator}}
+ struct s6 : Dtor { // expected-note {{because type 'struct U3::s6' has a base class with a non-trivial destructor}}
+ } m6; // expected-error {{union member 'm6' has a non-trivial destructor}}
+ struct s7 : Okay {
+ } m7;
+};
+
+template <class A, class B> struct Either {
+ bool tag;
+ union {
+ A a;
+ B b;
+ };
+
+ Either(A& a) : tag(true), a(a) {}
+ Either(B& b) : tag(false), b(b) {}
+};
+
+/* FIXME: this should work, but crashes in template code.
+void fred() {
+ Either<int,Virtual> virt(0);
+ Either<int,VirtualBase> vbase(0);
+ Either<int,Ctor> ctor(0);
+ Either<int,CopyCtor> copyctor(0);
+ Either<int,CopyAssign> copyassign(0);
+ Either<int,Dtor> dtor(0);
+ Either<int,Okay> okay(0);
+}
+ */
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
new file mode 100644
index 0000000000000..2ca7165aad487
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.def/namespace.memdef/p3.cpp
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T> struct X0 { };
+struct X1 { };
+
+struct Y {
+ template<typename T> union X0;
+ template<typename T> friend union X0;
+
+ union X1;
+ friend union X1;
+};
+
+
+// FIXME: Woefully inadequate for testing
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
new file mode 100644
index 0000000000000..d701f885fba1e
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// C++0x N2914.
+
+struct B {
+ void f(char);
+ void g(char);
+ enum E { e };
+ union { int x; };
+};
+
+class C {
+ int g();
+};
+
+class D2 : public B {
+ using B::f;
+ using B::e;
+ using B::x;
+ using C::g; // expected-error{{using declaration refers into 'C::', which is not a base class of 'D2'}}
+};
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp
new file mode 100644
index 0000000000000..63e5c3cd27b0a
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p5-cxx0x.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// C++0x N2914.
+
+struct A {
+ template<class T> void f(T);
+ template<class T> struct X { };
+};
+
+struct B : A {
+ using A::f<double>; // expected-error{{using declaration can not refer to template specialization}}
+ using A::X<int>; // expected-error{{using declaration can not refer to template specialization}}
+}; \ No newline at end of file
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp
new file mode 100644
index 0000000000000..f86f8fb579072
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// C++0x N2914.
+
+namespace A {
+ namespace B { }
+}
+
+using A::B; // expected-error{{using declaration can not refer to namespace}}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
new file mode 100644
index 0000000000000..59137eb8c9d8e
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// C++0x N2914.
+
+struct X {
+ int i;
+ static int a;
+};
+
+using X::i; // expected-error{{using declaration can not refer to class member}}
+using X::s; // expected-error{{using declaration can not refer to class member}}
+
+void f() {
+ using X::i; // expected-error{{using declaration can not refer to class member}}
+ using X::s; // expected-error{{using declaration can not refer to class member}}
+}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp
index 5d9f9e7a51c57..907a91a86ec44 100644
--- a/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p9.cpp
@@ -2,11 +2,11 @@
struct S; // expected-note {{forward declaration of 'struct S'}}
extern S a;
-extern S f();
+extern S f(); // expected-note {{'f' declared here}}
extern void g(S a); // expected-note {{candidate function}}
void h() {
// FIXME: This diagnostic could be better.
g(a); // expected-error {{no matching function for call to 'g'}}
- f(); // expected-error {{return type of called function ('struct S') is incomplete}}
+ f(); // expected-error {{calling 'f' with incomplete return type 'struct S'}}
}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
new file mode 100644
index 0000000000000..6bdea20df6bda
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+void f() {
+ auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}}
+}
+
+void g() {
+ auto a; // expected-error{{declaration of variable 'a' with type 'auto' requires an initializer}}
+
+ auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}}
+}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
new file mode 100644
index 0000000000000..fa3101c6736c6
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+void f() {
+ auto a = a; // expected-error{{variable 'a' declared with 'auto' type cannot appear in its own initializer}}
+}
+
+struct S { auto a; }; // expected-error{{'auto' not allowed in struct member}}
+
+void f(auto a) // expected-error{{'auto' not allowed in function prototype}}
+{
+ try { } catch (auto a) { } // expected-error{{'auto' not allowed in exception declaration}}
+}
+
+template <auto a = 10> class C { }; // expected-error{{'auto' not allowed in template parameter}}
diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
new file mode 100644
index 0000000000000..b9cdb52f11a1c
--- /dev/null
+++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
@@ -0,0 +1,60 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class A {}; // expected-note 3 {{previous use is here}}
+
+void a1(struct A);
+void a2(class A);
+void a3(union A); // expected-error {{use of 'A' with tag type that does not match previous declaration}}
+void a4(enum A); // expected-error {{use of 'A' with tag type that does not match previous declaration}}
+
+class A1 {
+ friend struct A;
+ friend class A;
+ friend union A; // expected-error {{use of 'A' with tag type that does not match previous declaration}}
+
+ friend enum A; // expected-error {{ISO C++ forbids forward references to 'enum' types}} \
+ // expected-error {{enum types cannot be friends}}
+};
+
+template <class T> struct B { // expected-note {{previous use is here}}
+ class Member {}; // expected-note 2 {{previous use is here}}
+};
+
+template <> class B<int> {
+ // no type Member
+};
+
+template <> struct B<A> {
+ // FIXME: the error here should be associated with the use at "void foo..."
+ union Member { // expected-note 4 {{previous use is here}} expected-error {{tag type that does not match previous declaration}}
+ void* a;
+ };
+};
+
+void b1(struct B<float>);
+void b2(class B<float>);
+void b3(union B<float>); // expected-error {{use of 'B<float>' with tag type that does not match previous declaration}}
+//void b4(enum B<float>); // this just doesn't parse; you can't template an enum directly
+
+void c1(struct B<float>::Member);
+void c2(class B<float>::Member);
+void c3(union B<float>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
+void c4(enum B<float>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
+
+void d1(struct B<int>::Member); // expected-error {{'Member' does not name a tag member in the specified scope}}
+void d2(class B<int>::Member); // expected-error {{'Member' does not name a tag member in the specified scope}}
+void d3(union B<int>::Member); // expected-error {{'Member' does not name a tag member in the specified scope}}
+void d4(enum B<int>::Member); // expected-error {{'Member' does not name a tag member in the specified scope}}
+
+void e1(struct B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
+void e2(class B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
+void e3(union B<A>::Member);
+void e4(enum B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
+
+template <class T> struct C {
+ void foo(class B<T>::Member); // expected-error{{no type named 'Member' in 'B<int>'}}
+};
+
+C<float> f1;
+C<int> f2; // expected-note {{in instantiation of template class}}
+C<A> f3; // expected-note {{in instantiation of template class}}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p10.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p10.cpp
new file mode 100644
index 0000000000000..82f526745dc69
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p10.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct A {
+ virtual void f(int a = 7);
+};
+
+struct B : public A {
+ void f(int a);
+};
+
+void m() {
+ B* pb = new B;
+ A* pa = pb;
+ pa->f(); // OK, calls pa->B::f(7)
+ pb->f(); // expected-error{{too few arguments}}
+}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p2.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p2.cpp
new file mode 100644
index 0000000000000..143a0caf82b2a
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p2.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void point(int = 3, int = 4);
+
+void test_point() {
+ point(1,2);
+ point(1);
+ point();
+}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp
new file mode 100644
index 0000000000000..ea16f641dba0a
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p3.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void nondecl(int (*f)(int x = 5)) // {expected-error {{default arguments can only be specified}}}
+{
+ void (*f2)(int = 17) // {expected-error {{default arguments can only be specified}}}
+ = (void (*)(int = 42))f; // {expected-error {{default arguments can only be specified}}}
+}
+
+struct X0 {
+ int (*f)(int = 17); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
+
+ void mem8(int (*fp)(int) = (int (*)(int = 17))0); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
+};
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
new file mode 100644
index 0000000000000..bbfaf909392a1
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p4.cpp
@@ -0,0 +1,55 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void f0(int i, int j, int k = 3);
+void f0(int i, int j, int k);
+void f0(int i, int j = 2, int k);
+void f0(int i, int j, int k);
+void f0(int i = 1, // expected-note{{previous definition}}
+ int j, int k);
+void f0(int i, int j, int k);
+
+namespace N0 {
+ void f0(int, int, int); // expected-note{{candidate}}
+
+ void test_f0_inner_scope() {
+ f0(); // expected-error{{no matching}}
+ }
+}
+
+void test_f0_outer_scope() {
+ f0(); // okay
+}
+
+void f0(int i = 1, // expected-error{{redefinition of default argument}}
+ int, int);
+
+template<typename T> void f1(T); // expected-note{{previous}}
+
+template<typename T>
+void f1(T = T()); // expected-error{{cannot be added}}
+
+
+namespace N1 {
+ // example from C++03 standard
+ // FIXME: make these "f2"s into "f"s, then fix our scoping issues
+ void f2(int, int);
+ void f2(int, int = 7);
+ void h() {
+ f2(3); // OK, calls f(3, 7)
+ void f(int = 1, int); // expected-error{{missing default argument}}
+ }
+
+ void m()
+ {
+ void f(int, int); // expected-note{{candidate}}
+ f(4); // expected-error{{no matching}}
+ void f(int, int = 5); // expected-note{{previous definition}}
+ f(4); // okay
+ void f(int, int = 5); // expected-error{{redefinition of default argument}}
+ }
+
+ void n()
+ {
+ f2(6); // okay
+ }
+} \ No newline at end of file
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p5.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p5.cpp
new file mode 100644
index 0000000000000..894c9b5a877a0
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p5.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+float global_f;
+
+void f0(int *ip = &global_f); // expected-error{{incompatible}}
+
+// Example from C++03 standard
+int a = 1;
+int f(int);
+int g(int x = f(a));
+
+void h() {
+ a = 2;
+ {
+ int *a = 0;
+ g(); // FIXME: check that a is called with a value of 2
+ }
+}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp
new file mode 100644
index 0000000000000..ef00e7b705340
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p6.cpp
@@ -0,0 +1,32 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+class C {
+ void f(int i = 3); // expected-note{{here}}
+ void g(int i, int j = 99);
+};
+
+void C::f(int i = 3) { } // expected-error{{redefinition of default argument}}
+
+void C::g(int i = 88, int j) { }
+
+void test_C(C c) {
+ c.f();
+ c.g();
+}
+
+template<typename T>
+struct X0 {
+ void f(int);
+
+ struct Inner {
+ void g(int);
+ };
+};
+
+// DR217
+template<typename T>
+void X0<T>::f(int = 17) { } // expected-error{{cannot be added}}
+
+// DR217 + DR205 (reading tea leaves)
+template<typename T>
+void X0<T>::Inner::g(int = 17) { } // expected-error{{cannot be added}}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
new file mode 100644
index 0000000000000..9c1d3a91c9bd3
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+void h()
+{
+ int i;
+ extern void h2(int x = sizeof(i)); // expected-error {{default argument references local variable 'i' of enclosing function}}
+}
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p8.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p8.cpp
new file mode 100644
index 0000000000000..574237ee557da
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p8.cpp
@@ -0,0 +1,4 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+class A {
+ void f(A* p = this) { } // expected-error{{invalid use of 'this'}}
+};
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp
new file mode 100644
index 0000000000000..6f71978c4e464
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p3.cpp
@@ -0,0 +1,3 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+void f(int) { } // expected-note {{previous definition is here}}
+void f(const int) { } // expected-error {{redefinition of 'f'}} \ No newline at end of file
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp
new file mode 100644
index 0000000000000..101d75fc0f486
--- /dev/null
+++ b/test/CXX/dcl.decl/dcl.meaning/dcl.mptr/p3.cpp
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -verify %t
+class A {
+public:
+ int& i;
+
+ A(int& i) : i(i) { }
+
+ static int s;
+};
+
+template<typename T> void ft(T& t) {
+ t.*&T::i = 10; // expected-error{{cannot form a pointer-to-member to member 'i' of reference type 'int &'}}
+}
+
+void f() {
+ int b;
+ A a(b);
+
+ int A::*ip = &A::s; // expected-error {{incompatible type initializing 'int *', expected 'int class A::*'}}
+ a.*&A::s = 10; // expected-error{{right hand operand to .* has non pointer-to-member type 'int *'}}
+
+ a.*&A::i = 10; // expected-error{{cannot form a pointer-to-member to member 'i' of reference type 'int &'}}
+ ft(a); // expected-note{{in instantiation of function template specialization 'ft' requested here}}
+
+ void A::*p = 0; // expected-error{{'p' declared as a member pointer to void}}
+}
diff --git a/test/CXX/expr/p3.cpp b/test/CXX/expr/p3.cpp
new file mode 100644
index 0000000000000..40fe052f63429
--- /dev/null
+++ b/test/CXX/expr/p3.cpp
@@ -0,0 +1,15 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+double operator +(double, double); // expected-error{{overloaded 'operator+' must have at least one parameter of class or enumeration type}}
+
+struct A
+{
+ operator int();
+};
+
+int main()
+{
+ A a, b;
+ int i0 = a + 1;
+ int i1 = a + b;
+}
diff --git a/test/CXX/expr/p8.cpp b/test/CXX/expr/p8.cpp
new file mode 100644
index 0000000000000..4f02497486c88
--- /dev/null
+++ b/test/CXX/expr/p8.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+int a0;
+const volatile int a1;
+int a2[16];
+int a3();
+
+void f0(int);
+void f1(int *);
+void f2(int (*)());
+
+int main()
+{
+ f0(a0);
+ f0(a1);
+ f1(a2);
+ f2(a3);
+}
diff --git a/test/CXX/expr/p9.cpp b/test/CXX/expr/p9.cpp
new file mode 100644
index 0000000000000..1eec3cf0b9f9e
--- /dev/null
+++ b/test/CXX/expr/p9.cpp
@@ -0,0 +1,50 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// floating-point overloads
+
+__typeof__(0 + 0.0L) ld0;
+long double &ldr = ld0;
+
+__typeof__(0 + 0.0) d0;
+double &dr = d0;
+
+__typeof__(0 + 0.0f) f0;
+float &fr = f0;
+
+// integral promotions
+
+signed char c0;
+__typeof__(c0 + c0) c1;
+int &cr = c1;
+
+unsigned char uc0;
+__typeof__(uc0 + uc0) uc1;
+int &ucr = uc1;
+
+short s0;
+__typeof__(s0 + s0) s1;
+int &sr = s1;
+
+unsigned short us0;
+__typeof__(us0 + us0) us1;
+int &usr = us1;
+
+// integral overloads
+
+__typeof__(0 + 0UL) ul0;
+unsigned long &ulr = ul0;
+
+template<bool T> struct selector;
+template<> struct selector<true> { typedef long type; };
+template<> struct selector<false> {typedef unsigned long type; };
+__typeof__(0U + 0L) ui_l0;
+selector<(sizeof(long) > sizeof(unsigned int))>::type &ui_lr = ui_l0;
+
+__typeof__(0 + 0L) l0;
+long &lr = l0;
+
+__typeof__(0 + 0U) u0;
+unsigned &ur = u0;
+
+__typeof__(0 + 0) i0;
+int &ir = i0;
diff --git a/test/CXX/lex/lex.trigraph/p1.cpp b/test/CXX/lex/lex.trigraph/p1.cpp
new file mode 100644
index 0000000000000..2a9a34b87eed4
--- /dev/null
+++ b/test/CXX/lex/lex.trigraph/p1.cpp
@@ -0,0 +1,19 @@
+// RUN: clang-cc -fsyntax-only -trigraphs -Wtrigraphs -verify %s
+
+??=pragma // expected-warning {{trigraph converted to '#' character}}
+
+int a = '??/0'; // expected-warning {{trigraph converted to '\' character}}
+
+int b = 1 ??' 0; // expected-warning {{trigraph converted to '^' character}}
+
+int c ??(1]; // expected-warning {{trigraph converted to '[' character}}
+
+int d [1??); // expected-warning {{trigraph converted to ']' character}}
+
+int e = 1 ??! 0; // expected-warning {{trigraph converted to '|' character}}
+
+void f() ??<} // expected-warning {{trigraph converted to '{' character}}
+
+void g() {??> // expected-warning {{trigraph converted to '}' character}}
+
+int h = ??- 0; // expected-warning {{trigraph converted to '~' character}}
diff --git a/test/CXX/lex/lex.trigraph/p2.cpp b/test/CXX/lex/lex.trigraph/p2.cpp
new file mode 100644
index 0000000000000..5be2d46b9189b
--- /dev/null
+++ b/test/CXX/lex/lex.trigraph/p2.cpp
@@ -0,0 +1,3 @@
+// RUN: clang-cc -fsyntax-only -trigraphs -Wtrigraphs -verify %s
+
+??=define arraycheck(a,b) a??(b??) ??!??! b??(a??) // expected-warning {{trigraph converted to '#' character}} expected-warning {{trigraph converted to '[' character}} expected-warning {{trigraph converted to ']' character}} expected-warning {{trigraph converted to '|' character}} expected-warning {{trigraph converted to '|' character}} expected-warning {{trigraph converted to '[' character}} expected-warning {{trigraph converted to ']' character}}
diff --git a/test/CXX/lex/lex.trigraph/p3.cpp b/test/CXX/lex/lex.trigraph/p3.cpp
new file mode 100644
index 0000000000000..f32af49994afe
--- /dev/null
+++ b/test/CXX/lex/lex.trigraph/p3.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -trigraphs -Wtrigraphs -verify %s
+
+char a[] =
+"?? ??\"??#??$??%??&??*??+??,??.??0??1??2??3??4??5??6"
+"??7??8??9??:??;?????@??A??B??C??D??E??F??G??H??I??J"
+"??K??L??M??N??O??P??Q??R??S??T??U??V??W??X??Y??Z??["
+"??\\??]??^??_??`??a??b??c??d??e??f??g??h??i??j??k??l"
+"??m??n??o??p??q??r??s??t??u??v??w??x??y??z??{??|??}??~";
diff --git a/test/CXX/over/over.match/over.match.best/p1.cpp b/test/CXX/over/over.match/over.match.best/p1.cpp
new file mode 100644
index 0000000000000..df5198357d7ba
--- /dev/null
+++ b/test/CXX/over/over.match/over.match.best/p1.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> int &f0(T*, int);
+float &f0(void*, int);
+
+void test_f0(int* ip, void *vp) {
+ // One argument is better...
+ int &ir = f0(ip, 0);
+
+ // Prefer non-templates to templates
+ float &fr = f0(vp, 0);
+}
+
+// Partial ordering of function template specializations will be tested
+// elsewhere
+// FIXME: Initialization by user-defined conversion is tested elsewhere
diff --git a/test/CXX/over/over.over/p1.cpp b/test/CXX/over/over.over/p1.cpp
new file mode 100644
index 0000000000000..e7f7d18c69e3c
--- /dev/null
+++ b/test/CXX/over/over.over/p1.cpp
@@ -0,0 +1,94 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T> T f0(T);
+int f0(int);
+
+// -- an object or reference being initialized
+struct S {
+ int (*f0)(int);
+ float (*f1)(float);
+};
+
+void test_init_f0() {
+ int (*f0a)(int) = f0;
+ int (*f0b)(int) = &f0;
+ int (*f0c)(int) = (f0);
+ float (*f0d)(float) = f0;
+ float (*f0e)(float) = &f0;
+ float (*f0f)(float) = (f0);
+ int (&f0g)(int) = f0;
+ int (&f0h)(int) = (f0);
+ float (&f0i)(float) = f0;
+ float (&f0j)(float) = (f0);
+ S s = { f0, f0 };
+}
+
+// -- the left side of an assignment (5.17),
+void test_assign_f0() {
+ int (*f0a)(int) = 0;
+ float (*f0b)(float) = 0;
+
+ f0a = f0;
+ f0a = &f0;
+ f0a = (f0);
+ f0b = f0;
+ f0b = &f0;
+ f0b = (f0);
+}
+
+// -- a parameter of a function (5.2.2),
+void eat_f0(int a(int), float (*b)(float), int (&c)(int), float (&d)(float));
+
+void test_pass_f0() {
+ eat_f0(f0, f0, f0, f0);
+ eat_f0(&f0, &f0, (f0), (f0));
+}
+
+// -- a parameter of a user-defined operator (13.5),
+struct X { };
+void operator+(X, int(int));
+void operator-(X, float(*)(float));
+void operator*(X, int (&)(int));
+void operator/(X, float (&)(float));
+
+void test_operator_pass_f0(X x) {
+ x + f0;
+ x + &f0;
+ x - f0;
+ x - &f0;
+ x * f0;
+ x * (f0);
+ x / f0;
+ x / (f0);
+}
+
+// -- the return value of a function, operator function, or conversion (6.6.3),
+int (*test_return_f0_a())(int) { return f0; }
+int (*test_return_f0_b())(int) { return &f0; }
+int (*test_return_f0_c())(int) { return (f0); }
+float (*test_return_f0_d())(float) { return f0; }
+float (*test_return_f0_e())(float) { return &f0; }
+float (*test_return_f0_f())(float) { return (f0); }
+
+// -- an explicit type conversion (5.2.3, 5.2.9, 5.4), or
+void test_convert_f0() {
+ (void)((int (*)(int))f0);
+ (void)((int (*)(int))&f0);
+ (void)((int (*)(int))(f0));
+ (void)((float (*)(float))f0);
+ (void)((float (*)(float))&f0);
+ (void)((float (*)(float))(f0));
+}
+
+// -- a non-type template-parameter(14.3.2).
+template<int(int)> struct Y0 { };
+template<float(float)> struct Y1 { };
+template<int (&)(int)> struct Y2 { };
+template<float (&)(float)> struct Y3 { };
+
+Y0<f0> y0;
+Y0<&f0> y0a;
+Y1<f0> y1;
+Y1<&f0> y1a;
+Y2<f0> y2;
+Y3<f0> y3;
diff --git a/test/CXX/over/over.over/p2.cpp b/test/CXX/over/over.over/p2.cpp
new file mode 100644
index 0000000000000..9ab0260618935
--- /dev/null
+++ b/test/CXX/over/over.over/p2.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> T f0(T, T);
+
+void test_f0() {
+ int (*f0a)(int, int) = f0;
+ int (*f0b)(int, int) = &f0;
+ int (*f0c)(int, float) = f0; // expected-error{{incompatible type}}
+ // FIXME: poor error message above!
+}
diff --git a/test/CXX/over/over.over/p4.cpp b/test/CXX/over/over.over/p4.cpp
new file mode 100644
index 0000000000000..a05dbaebb71df
--- /dev/null
+++ b/test/CXX/over/over.over/p4.cpp
@@ -0,0 +1,23 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> T f0(T);
+int f0(int); // expected-note{{candidate function}}
+
+void test_f0() {
+ int (*fp0)(int) = f0;
+ int (*fp1)(int) = &f0;
+ float (*fp2)(float) = &f0;
+}
+
+namespace N {
+ int f0(int); // expected-note{{candidate function}}
+}
+
+int f0(int);
+
+void test_f0_2() {
+ using namespace N;
+ int (*fp0)(int) = f0; // expected-error{{ambiguous}} \
+ // expected-error{{initializing}}
+ float (*fp1)(float) = f0;
+}
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
new file mode 100644
index 0000000000000..afe6ab2b968e4
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class.spec/p6.cpp
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ template<typename U> struct Inner0 {
+ static const unsigned value = 0;
+ };
+
+ template<typename U> struct Inner0<U*> {
+ static const unsigned value = 1;
+ };
+};
+
+template<typename T> template<typename U>
+struct X0<T>::Inner0<const U*> {
+ static const unsigned value = 2;
+};
+
+// FIXME: Test instantiation of these partial specializations (once they are
+// implemented).
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp b/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp
new file mode 100644
index 0000000000000..b3b7635106c5a
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class.spec/temp.class.order/p2.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<int I, int J, class T> class X {
+ static const int value = 0;
+};
+
+template<int I, int J> class X<I, J, int> {
+ static const int value = 1;
+};
+
+template<int I> class X<I, I, int> {
+ static const int value = 2;
+};
+
+int array0[X<0, 0, float>::value == 0? 1 : -1];
+int array1[X<0, 1, int>::value == 1? 1 : -1];
+int array2[X<0, 0, int>::value == 2? 1 : -1];
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp b/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
new file mode 100644
index 0000000000000..47cf8379c3196
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
@@ -0,0 +1,25 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, int N>
+struct A;
+
+template<typename T> // expected-note{{previous template declaration}}
+struct A<T*, 2> {
+ void f0();
+ void f1();
+ void f2();
+};
+
+template<>
+struct A<int, 1> {
+ void g0();
+};
+
+// FIXME: We should probably give more precise diagnostics here, but the
+// diagnostics we give aren't terrible.
+// FIXME: why not point to the first parameter that's "too many"?
+template<typename T, int N> // expected-error{{too many template parameters}}
+void A<T*, 2>::f0() { }
+
+template<typename T, int N>
+void A<T, N>::f1() { } // expected-error{{out-of-line definition}}
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp b/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp
new file mode 100644
index 0000000000000..b63c56c40fe8d
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1.cpp
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, int N>
+struct A;
+
+template<typename T>
+struct A<T*, 2> {
+ A(T);
+ ~A();
+
+ void f(T*);
+
+ operator T*();
+
+ static T value;
+};
+
+template<class X> void A<X*, 2>::f(X*) { }
+
+template<class X> X A<X*, 2>::value;
+
+template<class X> A<X*, 2>::A(X) { value = 0; }
+
+template<class X> A<X*, 2>::~A() { }
+
+template<class X> A<X*, 2>::operator X*() { return 0; }
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp b/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp
new file mode 100644
index 0000000000000..bc4bb5da40118
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.mem.class/p1.cpp
@@ -0,0 +1,27 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, typename U>
+struct X0 {
+ struct Inner;
+};
+
+template<typename T, typename U>
+struct X0<T, U>::Inner {
+ T x;
+ U y;
+
+ void f() { x = y; } // expected-error{{incompatible}}
+};
+
+
+void test(int i, float f) {
+ X0<int, float>::Inner inner;
+ inner.x = 5;
+ inner.y = 3.4;
+ inner.f();
+
+ X0<int*, float *>::Inner inner2;
+ inner2.x = &i;
+ inner2.y = &f;
+ inner2.f(); // expected-note{{instantiation}}
+}
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp b/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp
new file mode 100644
index 0000000000000..fd3fb0bc7a7d8
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1-retmem.cpp
@@ -0,0 +1,28 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> struct X1 { };
+
+template<typename T>
+struct X0 {
+ typedef int size_type;
+ typedef T value_type;
+
+ size_type f0() const;
+ value_type *f1();
+ X1<value_type*> f2();
+};
+
+template<typename T>
+typename X0<T>::size_type X0<T>::f0() const {
+ return 0;
+}
+
+template<typename U>
+typename X0<U>::value_type *X0<U>::f1() {
+ return 0;
+};
+
+template<typename U>
+X1<typename X0<U>::value_type*> X0<U>::f2() {
+ return 0;
+};
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp b/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp
new file mode 100644
index 0000000000000..725b61c271624
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1.cpp
@@ -0,0 +1,68 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, typename U> // expected-note{{previous template}}
+class X0 {
+public:
+ typedef int size_type;
+
+ X0(int);
+ ~X0();
+
+ void f0(const T&, const U&);
+
+ T& operator[](int i) const;
+
+ void f1(size_type) const;
+ void f2(size_type) const;
+ void f3(size_type) const;
+ void f4() ;
+
+ operator T*() const;
+
+ T value;
+};
+
+template<typename T, typename U>
+void X0<T, U>::f0(const T&, const U&) { // expected-note{{previous definition}}
+}
+
+template<class X, class Y>
+X& X0<X, Y>::operator[](int i) const {
+ (void)i;
+ return value;
+}
+
+template<class X, class Y>
+void X0<X, Y>::f1(int) const { }
+
+template<class X, class Y>
+void X0<X, Y>::f2(size_type) const { }
+
+template<class X, class Y, class Z> // expected-error{{too many template parameters}}
+void X0<X, Y>::f3(size_type) const {
+}
+
+template<class X, class Y>
+void X0<Y, X>::f4() { } // expected-error{{does not refer}}
+
+// FIXME: error message should probably say, "redefinition of 'X0<T, U>::f0'"
+// rather than just "redefinition of 'f0'"
+template<typename T, typename U>
+void X0<T, U>::f0(const T&, const U&) { // expected-error{{redefinition}}
+}
+
+// Test out-of-line constructors, destructors
+template<typename T, typename U>
+X0<T, U>::X0(int x) : value(x) { }
+
+template<typename T, typename U>
+X0<T, U>::~X0() { }
+
+// Test out-of-line conversion functions.
+template<typename T, typename U>
+X0<T, U>::operator T*() const {
+ return &value;
+}
+
+namespace N { template <class X> class A {void a();}; }
+namespace N { template <class X> void A<X>::a() {} }
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp b/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp
new file mode 100644
index 0000000000000..a09d0efa297f2
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.mem.func/p1inst.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// Test instantiation of member functions of class templates defined out-of-line
+template<typename T, typename U>
+struct X0 {
+ void f(T *t, const U &u);
+ void f(T *);
+};
+
+template<typename T, typename U>
+void X0<T, U>::f(T *t, const U &u) {
+ *t = u; // expected-error{{not assignable}}
+}
+
+void test_f(X0<float, int> xfi, X0<void, int> xvi, float *fp, void *vp, int i) {
+ xfi.f(fp, i);
+ xvi.f(vp, i); // expected-note{{instantiation}}
+}
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp b/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp
new file mode 100644
index 0000000000000..602fd374c2ab5
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.mem.func/pr5056.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+extern "C" void * malloc(int);
+
+template <typename T> struct A {
+ void *malloc(int);
+};
+
+template <typename T>
+inline void *A<T>::malloc(int)
+{
+ return 0;
+}
+
+void f() {
+ malloc(10);
+}
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp b/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp
new file mode 100644
index 0000000000000..2ddb8eac6c0ad
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.static/p1-inst.cpp
@@ -0,0 +1,28 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Test instantiation of static data members declared out-of-line.
+
+template<typename T>
+struct X {
+ static T value;
+};
+
+template<typename T>
+ T X<T>::value = 17; // expected-error{{initialize}}
+
+struct InitOkay {
+ InitOkay(int) { }
+};
+
+struct CannotInit { };
+
+int &returnInt() { return X<int>::value; }
+float &returnFloat() { return X<float>::value; }
+
+InitOkay &returnInitOkay() { return X<InitOkay>::value; }
+
+unsigned long sizeOkay() { return sizeof(X<CannotInit>::value); }
+
+CannotInit &returnError() {
+ return X<CannotInit>::value; // expected-note{{instantiation}}
+}
diff --git a/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp b/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
new file mode 100644
index 0000000000000..949a8b0a72c7b
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class/temp.static/p1.cpp
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ static T value;
+};
+
+template<typename T>
+T X0<T>::value = 0; // expected-error{{initialize}}
+
+struct X1 {
+ X1(int);
+};
+
+struct X2 { };
+
+int& get_int() { return X0<int>::value; }
+X1& get_X1() { return X0<X1>::value; }
+
+double*& get_double_ptr() { return X0<int*>::value; } // expected-error{{initialized}}
+
+X2& get_X2() {
+ return X0<X2>::value; // expected-note{{instantiation}}
+}
+
+template<typename T> T x; // expected-error{{variable 'x' declared as a template}}
diff --git a/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp
new file mode 100644
index 0000000000000..fe42ba41d81e8
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p4.cpp
@@ -0,0 +1,23 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<class T> struct A { A(); };
+template<class T> int &f(T);
+template<class T> float &f(T*);
+template<class T> double &f(const T*);
+
+template<class T> void g(T); // expected-note{{candidate}}
+template<class T> void g(T&); // expected-note{{candidate}}
+
+template<class T> int &h(const T&);
+template<class T> float &h(A<T>&);
+
+void m() {
+ const int *p;
+ double &dr1 = f(p);
+ float x;
+ g(x); // expected-error{{ambiguous}}
+ A<int> z;
+ float &fr1 = h(z);
+ const A<int> z2;
+ int &ir1 = h(z2);
+}
diff --git a/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp
new file mode 100644
index 0000000000000..27e4426b90820
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.fct/temp.func.order/p5.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<class T> int &f(T);
+template<class T> float &f(T*, int=1);
+
+template<class T> int &g(T);
+template<class T> float &g(T*, ...);
+
+int main() {
+ int* ip;
+ float &fr1 = f(ip);
+ float &fr2 = g(ip);
+}
diff --git a/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp b/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp
index b482955818cb4..399dcc4bed760 100644
--- a/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp
+++ b/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p4-neg.cpp
@@ -17,11 +17,11 @@ template<typename T>
struct MetaFun;
template<typename T>
- typename MetaFun<T*>::type f0(const T&) { } // expected-note{{previous}}
+ typename MetaFun<T*>::type f0(const T&) { while (1) {} } // expected-note{{previous}}
template<class U>
- typename MetaFun<U*>::type f0(const U&) { } // expected-error{{redefinition}}
+ typename MetaFun<U*>::type f0(const U&) { while (1) {} } // expected-error{{redefinition}}
// FIXME: We need canonicalization of expressions for this to work
// template<int> struct A { };
// template<int I> void f0(A<I>) { } // Xpected-note{{previous}}
-// template<int J> void f0(A<J>) { } // Xpected-error{{redefinition}} \ No newline at end of file
+// template<int J> void f0(A<J>) { } // Xpected-error{{redefinition}}
diff --git a/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp b/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp
new file mode 100644
index 0000000000000..2571e45c5cde2
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.fct/temp.over.link/p6.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<int N, int M>
+struct A0 {
+ void g0();
+};
+
+template<int X, int Y> void f0(A0<X, Y>) { } // expected-note{{previous}}
+template<int N, int M> void f0(A0<M, N>) { }
+template<int V1, int V2> void f0(A0<V1, V2>) { } // expected-error{{redefinition}}
+
+template<int X, int Y> void f1(A0<0, (X + Y)>) { } // expected-note{{previous}}
+template<int X, int Y> void f1(A0<0, (X - Y)>) { }
+template<int A, int B> void f1(A0<0, (A + B)>) { } // expected-error{{redefinition}}
+
+template<int X, int Y> void A0<X, Y>::g0() { }
diff --git a/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/test/CXX/temp/temp.decls/temp.friend/p1.cpp
new file mode 100644
index 0000000000000..fc392da00acfb
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.friend/p1.cpp
@@ -0,0 +1,56 @@
+// RUN: clang-cc -emit-llvm-only %s
+
+template <typename T> struct Num {
+ T value_;
+
+public:
+ Num(T value) : value_(value) {}
+ T get() const { return value_; }
+
+ template <typename U> struct Rep {
+ U count_;
+ Rep(U count) : count_(count) {}
+
+ friend Num operator*(const Num &a, const Rep &n) {
+ Num x = 0;
+ for (U count = n.count_; count; --count)
+ x += a;
+ return x;
+ }
+ };
+
+ friend Num operator+(const Num &a, const Num &b) {
+ return a.value_ + b.value_;
+ }
+
+ Num& operator+=(const Num& b) {
+ value_ += b.value_;
+ return *this;
+ }
+
+ class Representation {};
+ friend class Representation;
+};
+
+class A {
+ template <typename T> friend bool iszero(const A &a) throw();
+};
+
+template <class T> class B_iterator;
+template <class T> class B {
+ friend class B_iterator<T>;
+};
+
+int calc1() {
+ Num<int> left = -1;
+ Num<int> right = 1;
+ Num<int> result = left + right;
+ return result.get();
+}
+
+int calc2() {
+ Num<int> x = 3;
+ Num<int>::Rep<char> n = (char) 10;
+ Num<int> result = x * n;
+ return result.get();
+}
diff --git a/test/CXX/temp/temp.decls/temp.friend/p3.cpp b/test/CXX/temp/temp.decls/temp.friend/p3.cpp
new file mode 100644
index 0000000000000..4615bebe711fa
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.friend/p3.cpp
@@ -0,0 +1,13 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template <class T> class A {
+ typedef int Member;
+};
+
+class B {
+ template <class T> friend class A;
+ template <class T> friend class Undeclared;
+
+ // FIXME: Diagnostic below could be (and was) better.
+ template <class T> friend typename A<T>::Member; // expected-error {{classes or functions}}
+};
diff --git a/test/CXX/temp/temp.decls/temp.friend/p5.cpp b/test/CXX/temp/temp.decls/temp.friend/p5.cpp
new file mode 100644
index 0000000000000..f1142a4129b25
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.friend/p5.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template <class T> class A {
+ class Member {
+ };
+};
+
+class B {
+ template <class T> friend class A<T>::Member;
+};
+
diff --git a/test/CXX/temp/temp.decls/temp.mem/p1.cpp b/test/CXX/temp/temp.decls/temp.mem/p1.cpp
new file mode 100644
index 0000000000000..80b18467a364e
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.mem/p1.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template <class T> struct A {
+ static T cond;
+
+ template <class U> struct B {
+ static T twice(U value) {
+ return (cond ? value + value : value);
+ }
+ };
+};
+
+int foo() {
+ A<bool>::cond = true;
+ return A<bool>::B<int>::twice(4);
+}
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 f4970b89f693e..01030b2a8a20a 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
@@ -8,4 +8,4 @@ void g() {
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}}
-} \ No newline at end of file
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
index c014c663598cc..dbe2ff3e18fb2 100644
--- a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
@@ -1,4 +1,4 @@
-// RUN: clang-cc -fsyntax-only %s
+// RUN: clang-cc -fsyntax-only -verify %s
template<typename T> struct A { };
@@ -57,4 +57,32 @@ void test_f3(int ***ip, volatile int ***vip) {
A<volatile int> a1 = f3(vip);
}
-// FIXME: the next bullet requires a lot of effort.
+// - If P is a class, and P has the form template-id, then A can be a
+// derived class of the deduced A. Likewise, if P is a pointer to a class
+// of the form template-id, A can be a pointer to a derived class pointed
+// to by the deduced A.
+template<typename T, int I> struct C { };
+
+struct D : public C<int, 1> { };
+struct E : public D { };
+struct F : A<float> { };
+struct G : A<float>, C<int, 1> { };
+
+template<typename T, int I>
+ C<T, I> *f4a(const C<T, I>&);
+template<typename T, int I>
+ C<T, I> *f4b(C<T, I>);
+template<typename T, int I>
+ C<T, I> *f4c(C<T, I>*);
+int *f4c(...);
+
+void test_f4(D d, E e, F f, G g) {
+ C<int, 1> *ci1a = f4a(d);
+ C<int, 1> *ci2a = f4a(e);
+ C<int, 1> *ci1b = f4b(d);
+ C<int, 1> *ci2b = f4b(e);
+ C<int, 1> *ci1c = f4c(&d);
+ C<int, 1> *ci2c = f4c(&e);
+ C<int, 1> *ci3c = f4c(&g);
+ int *ip1 = f4c(&f);
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp
new file mode 100644
index 0000000000000..7d175781c2d94
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p2.cpp
@@ -0,0 +1,36 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// FIXME: [temp.deduct.conv]p2 bullets 1 and 2 can't actually happen without
+// references?
+// struct ConvertibleToArray {
+// // template<typename T, unsigned N>
+// // operator T(()[]) const;
+
+// private:
+// typedef int array[17];
+
+// operator array() const;
+// };
+
+// void test_array(ConvertibleToArray cta) {
+// int *ip = cta;
+// ip = cta;
+// const float *cfp = cta;
+// }
+
+// bullet 2
+// struct ConvertibleToFunction {
+// template<typename T, typename A1, typename A2>
+// operator T(A1, A2) const () { };
+// };
+
+// bullet 3
+struct ConvertibleToCVQuals {
+ template<typename T>
+ operator T* const() const;
+};
+
+void test_cvqual_conv(ConvertibleToCVQuals ctcv) {
+ int *ip = ctcv;
+ const int *icp = ctcv;
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp
new file mode 100644
index 0000000000000..95bd7fe121595
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p3.cpp
@@ -0,0 +1,30 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+struct AnyPtr {
+ template<typename T>
+ operator T*() const;
+};
+
+// If A is a cv-qualified type, the top level cv-qualifiers of A's type
+// are ignored for type deduction.
+void test_cvquals(AnyPtr ap) {
+ int* const ip = ap;
+ const float * const volatile fp = ap;
+}
+
+// If A is a reference type, the type referred to by A is used for
+// type deduction.
+void test_ref_arg(AnyPtr ap) {
+ const int* const &ip = ap;
+ double * const &dp = ap;
+}
+
+struct AnyRef {
+ template<typename T>
+ operator T&() const;
+};
+
+void test_ref_param(AnyRef ar) {
+ int &ir = ar;
+ const float &fr = ar;
+ int i = ar;
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
new file mode 100644
index 0000000000000..50d31fb2f851f
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.conv/p4.cpp
@@ -0,0 +1,44 @@
+// RUN: clang-cc -fsyntax-only %s
+
+struct AnyT {
+ template<typename T>
+ operator T();
+};
+
+void test_cvqual_ref(AnyT any) {
+ const int &cir = any;
+}
+
+struct AnyThreeLevelPtr {
+ template<typename T>
+ operator T***() const
+ {
+ T x = 0;
+ // FIXME: looks like we get this wrong, too!
+ // x = 0; // will fail if T is deduced to a const type
+ // (EDG and GCC get this wrong)
+ return 0;
+ }
+};
+
+struct X { };
+
+void test_deduce_with_qual(AnyThreeLevelPtr a3) {
+ int * const * const * const ip = a3;
+}
+
+struct AnyPtrMem {
+ template<typename Class, typename T>
+ operator T Class::*() const
+ {
+ T x = 0;
+ // FIXME: looks like we get this wrong, too!
+ // x = 0; // will fail if T is deduced to a const type.
+ // (EDG and GCC get this wrong)
+ return 0;
+ }
+};
+
+void test_deduce_ptrmem_with_qual(AnyPtrMem apm) {
+ const float X::* pm = apm;
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp
new file mode 100644
index 0000000000000..86a34500ad415
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp
@@ -0,0 +1,22 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T>
+ T f0(T, int);
+
+void test_f0() {
+ int (*f0a)(int, int) = f0;
+ int (*f0b)(int, int) = &f0;
+ float (*f0c)(float, int) = &f0;
+}
+
+template<typename T> T f1(T, int);
+template<typename T> T f1(T);
+
+void test_f1() {
+ float (*f1a)(float, int) = f1;
+ float (*f1b)(float, int) = &f1;
+ float (*f1c)(float) = f1;
+ float (*f1d)(float) = (f1);
+ float (*f1e)(float) = &f1;
+ float (*f1f)(float) = (&f1);
+}
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp
new file mode 100644
index 0000000000000..072789c7d5799
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p11.cpp
@@ -0,0 +1,22 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template <class T> T* f(int); // #1
+template <class T, class U> T& f(U); // #2
+
+void g() {
+ int *ip = f<int>(1); // calls #1
+}
+
+template<typename T>
+struct identity {
+ typedef T type;
+};
+
+template <class T>
+ T* f2(int, typename identity<T>::type = 0); // expected-note{{candidate}}
+template <class T, class U>
+ T& f2(U, typename identity<T>::type = 0); // expected-note{{candidate}}
+
+void g2() {
+ f2<int>(1); // expected-error{{ambiguous}}
+}
diff --git a/test/CXX/temp/temp.param/p1.cpp b/test/CXX/temp/temp.param/p1.cpp
index 488c3a07429ac..a6638b4f60f2a 100644
--- a/test/CXX/temp/temp.param/p1.cpp
+++ b/test/CXX/temp/temp.param/p1.cpp
@@ -1 +1,4 @@
+// Suppress 'no run line' failure.
+// RUN: true
+
// Paragraph 1 is descriptive, and therefore requires no tests.
diff --git a/test/CXX/temp/temp.res/temp.dep/p3.cpp b/test/CXX/temp/temp.res/temp.dep/p3.cpp
new file mode 100644
index 0000000000000..d47f0d6835144
--- /dev/null
+++ b/test/CXX/temp/temp.res/temp.dep/p3.cpp
@@ -0,0 +1,43 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+struct A0 {
+ struct K { };
+};
+
+template <typename T> struct B0: A0 {
+ static void f() {
+ K k;
+ }
+};
+
+namespace E1 {
+ typedef double A;
+
+ template<class T> class B {
+ typedef int A;
+ };
+
+ template<class T>
+ struct X : B<T> {
+ A* blarg(double *dp) {
+ return dp;
+ }
+ };
+}
+
+namespace E2 {
+ struct A {
+ struct B;
+ int *a;
+ int Y;
+ };
+
+ int a;
+ template<class T> struct Y : T {
+ struct B { /* ... */ };
+ B b;
+ void f(int i) { a = i; }
+ Y* p;
+ };
+
+ Y<A> ya;
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp
new file mode 100644
index 0000000000000..239b8aeb04e40
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp
@@ -0,0 +1,99 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// This test creates cases where implicit instantiations of various entities
+// would cause a diagnostic, but provides expliict specializations for those
+// entities that avoid the diagnostic. The intent is to verify that
+// implicit instantiations do not occur (because the explicit specialization
+// is used instead).
+struct NonDefaultConstructible {
+ NonDefaultConstructible(int);
+};
+
+
+// C++ [temp.expl.spec]p1:
+// An explicit specialization of any of the following:
+
+// -- function template
+template<typename T> void f0(T) {
+ T t;
+}
+
+template<> void f0(NonDefaultConstructible) { }
+
+void test_f0(NonDefaultConstructible NDC) {
+ f0(NDC);
+}
+
+// -- class template
+template<typename T>
+struct X0 {
+ static T member;
+
+ void f1(T t) {
+ t = 17;
+ }
+
+ struct Inner : public T { };
+
+ template<typename U>
+ struct InnerTemplate : public T { };
+
+ template<typename U>
+ void ft1(T t, U u);
+};
+
+template<typename T>
+template<typename U>
+void X0<T>::ft1(T t, U u) {
+ t = u;
+}
+
+template<typename T> T X0<T>::member;
+
+template<> struct X0<void> { };
+X0<void> test_X0;
+
+
+// -- member function of a class template
+template<> void X0<void*>::f1(void *) { }
+
+void test_spec(X0<void*> xvp, void *vp) {
+ xvp.f1(vp);
+}
+
+// -- static data member of a class template
+template<>
+NonDefaultConstructible X0<NonDefaultConstructible>::member = 17;
+
+NonDefaultConstructible &get_static_member() {
+ return X0<NonDefaultConstructible>::member;
+}
+
+// -- member class of a class template
+template<>
+struct X0<void*>::Inner { };
+
+X0<void*>::Inner inner0;
+
+// -- member class template of a class template
+template<>
+template<>
+struct X0<void*>::InnerTemplate<int> { };
+
+X0<void*>::InnerTemplate<int> inner_template0;
+
+// -- member function template of a class template
+template<>
+template<>
+void X0<void*>::ft1(void*, const void*) { }
+
+void test_func_template(X0<void *> xvp, void *vp, const void *cvp) {
+ xvp.ft1(vp, cvp);
+}
+
+// example from the standard:
+template<class T> class stream;
+template<> class stream<char> { /* ... */ };
+template<class T> class Array { /* ... */ };
+template<class T> void sort(Array<T>& v) { /* ... */ }
+template<> void sort<char*>(Array<char*>&) ;
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp
new file mode 100644
index 0000000000000..61f1710a6b9ed
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p10.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<class T> class X;
+template<> class X<int>; // expected-note{{forward}}
+X<int>* p;
+
+X<int> x; // expected-error{{incomplete type}}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp
new file mode 100644
index 0000000000000..e794e67a5ef34
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p11.cpp
@@ -0,0 +1,8 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<class T> class Array { /* ... */ };
+template<class T> void sort(Array<T>& v);
+
+// explicit specialization for sort(Array<int>&)
+// with deduced template-argument of type int
+template<> void sort(Array<int>&);
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp
new file mode 100644
index 0000000000000..63cf9f5e50d12
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p13.cpp
@@ -0,0 +1,6 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T> void f(T);
+
+template<> void f(int) { }
+void f(int) { }
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp
new file mode 100644
index 0000000000000..a5d5b9e3c41e2
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p14.cpp
@@ -0,0 +1,42 @@
+// RUN: clang-cc -emit-llvm -o - %s | FileCheck %s
+
+template<class T> void f(T) { /* ... */ }
+template<class T> inline void g(T) { /* ... */ }
+
+// CHECK: define void @_Z1gIiEvT_
+template<> void g<>(int) { /* ... */ }
+
+template<class T>
+struct X {
+ void f() { }
+ void g();
+ void h();
+};
+
+template<class T>
+void X<T>::g() {
+}
+
+template<class T>
+inline void X<T>::h() {
+}
+
+// CHECK: define void @_ZN1XIiE1fEv
+template<> void X<int>::f() { }
+
+// CHECK: define void @_ZN1XIiE1hEv
+template<> void X<int>::h() { }
+
+// CHECK: define linkonce_odr void @_Z1fIiEvT_
+template<> inline void f<>(int) { /* ... */ }
+
+// CHECK: define linkonce_odr void @_ZN1XIiE1gEv
+template<> inline void X<int>::g() { }
+
+void test(X<int> xi) {
+ f(17);
+ g(17);
+ xi.f();
+ xi.g();
+ xi.h();
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp
new file mode 100644
index 0000000000000..840f566362ed8
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp
@@ -0,0 +1,22 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct NonDefaultConstructible {
+ NonDefaultConstructible(const NonDefaultConstructible&);
+};
+
+template<typename T, typename U>
+struct X {
+ static T member;
+};
+
+template<typename T, typename U>
+T X<T, U>::member; // expected-error{{no matching constructor}}
+
+// Okay; this is a declaration, not a definition.
+template<>
+NonDefaultConstructible X<NonDefaultConstructible, long>::member;
+
+NonDefaultConstructible &test(bool b) {
+ return b? X<NonDefaultConstructible, int>::member // expected-note{{instantiation}}
+ : X<NonDefaultConstructible, long>::member;
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp
new file mode 100644
index 0000000000000..ce40afd402253
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p16.cpp
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only %s
+template<class T> struct A {
+ void f(T);
+ template<class X1> void g1(T, X1);
+ template<class X2> void g2(T, X2);
+ void h(T) { }
+};
+
+// specialization
+template<> void A<int>::f(int);
+
+// out of class member template definition
+template<class T> template<class X1> void A<T>::g1(T, X1) { }
+
+// member template specialization
+template<> template<class X1> void A<int>::g1(int, X1);
+
+// member template specialization
+template<> template<>
+ void A<int>::g1(int, char); // X1 deduced as char
+
+template<> template<>
+ void A<int>::g2<char>(int, char); // X2 specified as char
+ // member specialization even if defined in class definition
+
+template<> void A<int>::h(int) { }
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp
new file mode 100644
index 0000000000000..883cb71d5686c
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<class T1>
+class A {
+ template<class T2> class B {
+ void mf();
+ };
+};
+
+template<> template<> class A<int>::B<double>;
+template<> template<> void A<char>::B<char>::mf();
+
+template<> void A<char>::B<int>::mf(); // expected-error{{requires 'template<>'}}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp
new file mode 100644
index 0000000000000..a5877d281d741
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p18.cpp
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<class T1> class A {
+ template<class T2> class B {
+ template<class T3> void mf1(T3);
+ void mf2();
+ };
+};
+
+template<> template<class X>
+class A<long>::B { };
+
+template<> template<> template<class T>
+ void A<int>::B<double>::mf1(T t) { }
+
+template<> template<> template<class T>
+void A<long>::B<double>::mf1(T t) { } // expected-error{{does not match}}
+
+// FIXME: This diagnostic could probably be better.
+template<class Y> template<>
+ void A<Y>::B<double>::mf2() { } // expected-error{{does not refer}}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp
new file mode 100644
index 0000000000000..1f38e5a2c17d2
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p19.cpp
@@ -0,0 +1,30 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X {
+ template<typename U> struct Inner { };
+
+ template<typename U> void f(T, U) { }
+};
+
+template<> template<typename U>
+struct X<int>::Inner {
+ U member;
+};
+
+template<> template<typename U>
+void X<int>::f(int x, U y) {
+ x = y; // expected-error{{incompatible type}}
+}
+
+void test(X<int> xi, X<long> xl, float *fp) {
+ X<int>::Inner<float*> xii;
+ xii.member = fp;
+ xi.f(17, 25);
+ xi.f(17, 3.14159);
+ xi.f(17, fp); // expected-note{{instantiation}}
+ X<long>::Inner<float*> xli;
+
+ xli.member = fp; // expected-error{{no member}}
+ xl.f(17, fp); // okay
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
new file mode 100644
index 0000000000000..64856605a0a75
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp
@@ -0,0 +1,239 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// This test creates cases where implicit instantiations of various entities
+// would cause a diagnostic, but provides expliict specializations for those
+// entities that avoid the diagnostic. The specializations are alternately
+// declarations and definitions, and the intent of this test is to verify
+// that we allow specializations only in the appropriate namespaces (and
+// nowhere else).
+struct NonDefaultConstructible {
+ NonDefaultConstructible(int);
+};
+
+
+// C++ [temp.expl.spec]p1:
+// An explicit specialization of any of the following:
+
+// -- function template
+namespace N0 {
+ template<typename T> void f0(T) { // expected-note{{here}}
+ T t;
+ }
+
+ template<> void f0(NonDefaultConstructible) { }
+
+ void test_f0(NonDefaultConstructible NDC) {
+ f0(NDC);
+ }
+
+ template<> void f0(int);
+ template<> void f0(long);
+}
+
+template<> void N0::f0(int) { } // okay
+
+namespace N1 {
+ template<> void N0::f0(long) { } // expected-error{{not in a namespace enclosing}}
+}
+
+template<> void N0::f0(double) { } // expected-error{{originally be declared}}
+
+struct X1 {
+ template<typename T> void f(T);
+
+ template<> void f(int); // expected-error{{in class scope}}
+};
+
+// -- class template
+namespace N0 {
+
+template<typename T>
+struct X0 { // expected-note 2{{here}}
+ static T member; // expected-note{{here}}
+
+ void f1(T t) { // expected-note{{explicitly specialized declaration is here}}
+ t = 17;
+ }
+
+ struct Inner : public T { }; // expected-note 3{{here}}
+
+ template<typename U>
+ struct InnerTemplate : public T { }; // expected-note 2{{explicitly specialized}} \
+ // expected-error{{base specifier}}
+
+ template<typename U>
+ void ft1(T t, U u); // expected-note{{explicitly specialized}}
+};
+
+}
+
+template<typename T>
+template<typename U>
+void N0::X0<T>::ft1(T t, U u) {
+ t = u;
+}
+
+template<typename T> T N0::X0<T>::member;
+
+template<> struct N0::X0<void> { }; // expected-error{{originally}}
+N0::X0<void> test_X0;
+
+namespace N1 {
+ template<> struct N0::X0<const void> { }; // expected-error{{originally}}
+}
+
+namespace N0 {
+ template<> struct X0<volatile void>;
+}
+
+template<> struct N0::X0<volatile void> {
+ void f1(void *);
+};
+
+// -- member function of a class template
+template<> void N0::X0<void*>::f1(void *) { } // expected-error{{member function specialization}}
+
+void test_spec(N0::X0<void*> xvp, void *vp) {
+ xvp.f1(vp);
+}
+
+namespace N0 {
+ template<> void X0<volatile void>::f1(void *) { } // expected-error{{no function template matches}}
+
+ template<> void X0<const volatile void*>::f1(const volatile void*);
+}
+
+void test_x0_cvvoid(N0::X0<const volatile void*> x0, const volatile void *cvp) {
+ x0.f1(cvp); // okay: we've explicitly specialized
+}
+
+// -- static data member of a class template
+namespace N0 {
+ // This actually tests p15; the following is a declaration, not a definition.
+ template<>
+ NonDefaultConstructible X0<NonDefaultConstructible>::member;
+
+ template<> long X0<long>::member = 17;
+
+ template<> float X0<float>::member;
+
+ template<> double X0<double>::member;
+}
+
+NonDefaultConstructible &get_static_member() {
+ return N0::X0<NonDefaultConstructible>::member;
+}
+
+template<> int N0::X0<int>::member; // expected-error{{originally}}
+
+template<> float N0::X0<float>::member = 3.14f;
+
+namespace N1 {
+ template<> double N0::X0<double>::member = 3.14; // expected-error{{not in a namespace enclosing}}
+}
+
+// -- member class of a class template
+namespace N0 {
+
+ template<>
+ struct X0<void*>::Inner { };
+
+ template<>
+ struct X0<int>::Inner { };
+
+ template<>
+ struct X0<unsigned>::Inner;
+
+ template<>
+ struct X0<float>::Inner;
+
+ template<>
+ struct X0<double>::Inner; // expected-note{{forward declaration}}
+}
+
+template<>
+struct N0::X0<long>::Inner { }; // expected-error{{originally}}
+
+template<>
+struct N0::X0<float>::Inner { };
+
+namespace N1 {
+ template<>
+ struct N0::X0<unsigned>::Inner { }; // expected-error{{member class specialization}}
+
+ template<>
+ struct N0::X0<unsigned long>::Inner { }; // expected-error{{member class specialization}}
+};
+
+N0::X0<void*>::Inner inner0;
+N0::X0<int>::Inner inner1;
+N0::X0<long>::Inner inner2;
+N0::X0<float>::Inner inner3;
+N0::X0<double>::Inner inner4; // expected-error{{incomplete}}
+
+// -- member class template of a class template
+namespace N0 {
+ template<>
+ template<>
+ struct X0<void*>::InnerTemplate<int> { };
+
+ template<> template<>
+ struct X0<int>::InnerTemplate<int>; // expected-note{{forward declaration}}
+
+ template<> template<>
+ struct X0<int>::InnerTemplate<long>;
+
+ template<> template<>
+ struct X0<int>::InnerTemplate<double>;
+}
+
+template<> template<>
+struct N0::X0<int>::InnerTemplate<long> { }; // okay
+
+template<> template<>
+struct N0::X0<int>::InnerTemplate<float> { }; // expected-error{{class template specialization}}
+
+namespace N1 {
+ template<> template<>
+ struct N0::X0<int>::InnerTemplate<double> { }; // expected-error{{enclosing}}
+}
+
+N0::X0<void*>::InnerTemplate<int> inner_template0;
+N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
+N0::X0<int>::InnerTemplate<long> inner_template2;
+N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
+
+// -- member function template of a class template
+namespace N0 {
+ template<>
+ template<>
+ void X0<void*>::ft1(void*, const void*) { }
+
+ template<> template<>
+ void X0<void*>::ft1(void *, int);
+
+ template<> template<>
+ void X0<void*>::ft1(void *, unsigned);
+
+ template<> template<>
+ void X0<void*>::ft1(void *, long);
+}
+
+template<> template<>
+void N0::X0<void*>::ft1(void *, unsigned) { } // okay
+
+template<> template<>
+void N0::X0<void*>::ft1(void *, float) { } // expected-error{{function template specialization}}
+
+namespace N1 {
+ template<> template<>
+ void N0::X0<void*>::ft1(void *, long) { } // expected-error{{enclosing}}
+}
+
+
+void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
+ int i, unsigned u) {
+ xvp.ft1(vp, cvp);
+ xvp.ft1(vp, i);
+ xvp.ft1(vp, u);
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp
new file mode 100644
index 0000000000000..d270b8167a167
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p20.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T>
+void f(T);
+
+template<typename T>
+struct A { };
+
+struct X {
+ template<> friend void f<int>(int); // expected-error{{in class scope}}
+ template<> friend class A<int>; // expected-error{{cannot be a friend}}
+
+ friend void f<float>(float); // okay
+ friend class A<float>; // okay
+};
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp
new file mode 100644
index 0000000000000..9dae3eb5190b0
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p21.cpp
@@ -0,0 +1,30 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X {
+ void mf1(T);
+ template<typename U> void mf2(T, U); // expected-note{{previous}}
+};
+
+template<>
+void X<int>::mf1(int i = 17) // expected-error{{default}}
+{
+}
+
+template<> template<>
+void X<int>::mf2(int, int = 17) // expected-error{{default}}
+{ }
+
+template<> template<typename U>
+void X<int>::mf2(int, U = U()) // expected-error{{default}}
+{
+}
+
+template<>
+struct X<float> {
+ void mf1(float);
+};
+
+void X<float>::mf1(float = 3.14f) // okay
+{
+}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
new file mode 100644
index 0000000000000..2bd1400faefb0
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p3.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace N {
+ template<class T> class X;
+}
+
+// FIXME: this diagnostic is terrible (PR3844).
+template<> class X<int> { /* ... */ }; // expected-error {{unqualified-id}}
+
+namespace N {
+
+template<> class X<char*> { /* ... */ }; // OK: X is a template
+
+} \ No newline at end of file
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp
new file mode 100644
index 0000000000000..8d91068f9b993
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p4.cpp
@@ -0,0 +1,59 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct IntHolder { // expected-note{{here}}
+ IntHolder(int);
+};
+
+template<typename T, typename U>
+struct X { // expected-note{{here}}
+ void f() {
+ T t; // expected-error{{no matching}}
+ }
+
+ void g() { }
+
+ struct Inner {
+ T value; // expected-note {{member is declared here}}
+ };
+
+ static T value;
+};
+
+template<typename T, typename U>
+T X<T, U>::value; // expected-error{{no matching constructor}}
+
+IntHolder &test_X_IntHolderInt(X<IntHolder, int> xih) {
+ xih.g(); // okay
+ xih.f(); // expected-note{{instantiation}}
+
+ // FIXME: diagnostic here has incorrect reason (PR5154)
+ X<IntHolder, int>::Inner inner; // expected-error{{implicit default}}
+
+ return X<IntHolder, int>::value; // expected-note{{instantiation}}
+}
+
+// Explicitly specialize the members of X<IntHolder, long> to not cause
+// problems with instantiation.
+template<>
+void X<IntHolder, long>::f() { }
+
+template<>
+struct X<IntHolder, long>::Inner {
+ Inner() : value(17) { }
+ IntHolder value;
+};
+
+template<>
+IntHolder X<IntHolder, long>::value = 17;
+
+IntHolder &test_X_IntHolderInt(X<IntHolder, long> xih) {
+ xih.g(); // okay
+ xih.f(); // okay, uses specialization
+
+ X<IntHolder, long>::Inner inner; // okay, uses specialization
+
+ return X<IntHolder, long>::value; // okay, uses specialization
+}
+
+template<>
+X<IntHolder, long>::X() { } // expected-error{{instantiated member}}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp
new file mode 100644
index 0000000000000..58682c786f959
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p5.cpp
@@ -0,0 +1,61 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct IntHolder {
+ IntHolder(int);
+};
+
+template<typename T, typename U>
+struct X {
+ void f() {
+ T t;
+ }
+
+ void g() { }
+
+ struct Inner {
+ T value;
+ };
+
+ static T value;
+};
+
+template<typename T, typename U>
+T X<T, U>::value;
+
+// Explicitly specialize the members of X<IntHolder, long> to not cause
+// problems with instantiation, but only provide declarations (not definitions).
+template<>
+void X<IntHolder, long>::f();
+
+template<>
+struct X<IntHolder, long>::Inner; // expected-note{{forward declaration}}
+
+template<>
+IntHolder X<IntHolder, long>::value;
+
+IntHolder &test_X_IntHolderInt(X<IntHolder, long> xih) {
+ xih.g(); // okay
+ xih.f(); // okay, uses specialization
+
+ X<IntHolder, long>::Inner inner; // expected-error {{incomplete}}
+
+ return X<IntHolder, long>::value; // okay, uses specialization
+}
+
+
+template<class T> struct A {
+ void f(T) { /* ... */ }
+};
+
+template<> struct A<int> {
+ void f(int);
+};
+
+void h() {
+ A<int> a;
+ a.f(16); // A<int>::f must be defined somewhere
+}
+
+// explicit specialization syntax not used for a member of
+// explicitly specialized class template specialization
+void A<int>::f(int) { /* ... */ }
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp
new file mode 100644
index 0000000000000..e92d3f0a88835
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p6.cpp
@@ -0,0 +1,56 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ void f();
+
+ template<typename U>
+ void g(U);
+
+ struct Nested {
+ };
+
+ static T member;
+};
+
+int &use_X0_int(X0<int> x0i, // expected-note{{implicit instantiation first required here}}
+ int i) {
+ x0i.f(); // expected-note{{implicit instantiation first required here}}
+ x0i.g(i); // expected-note{{implicit instantiation first required here}}
+ X0<int>::Nested nested; // expected-note{{implicit instantiation first required here}}
+ return X0<int>::member; // expected-note{{implicit instantiation first required here}}
+}
+
+template<>
+void X0<int>::f() { // expected-error{{after instantiation}}
+}
+
+template<> template<>
+void X0<int>::g(int) { // expected-error{{after instantiation}}
+}
+
+template<>
+struct X0<int>::Nested { }; // expected-error{{after instantiation}}
+
+template<>
+int X0<int>::member = 17; // expected-error{{after instantiation}}
+
+template<>
+struct X0<int> { }; // expected-error{{after instantiation}}
+
+// Example from the standard
+template<class T> class Array { /* ... */ };
+
+template<class T> void sort(Array<T>& v) { /* ... */ }
+
+struct String {};
+
+void f(Array<String>& v) {
+
+ sort(v); // expected-note{{required}}
+ // use primary template
+ // sort(Array<T>&), T is String
+}
+
+template<> void sort<String>(Array<String>& v); // // expected-error{{after instantiation}}
+template<> void sort<>(Array<char*>& v); // OK: sort<char*> not yet used
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp
new file mode 100644
index 0000000000000..49481d2e6d7ae
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p9.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace N {
+ template<class T> class X { /* ... */ };
+ template<class T> class Y { /* ... */ };
+ template<> class X<int> { /* ... */ };
+ template<> class Y<double>;
+
+ const unsigned NumElements = 17;
+}
+
+template<> class N::Y<double> {
+ int array[NumElements];
+};