Cleanup and test C++ default arguments. Improvements include:
- Diagnose attempts to add default arguments to templates (or member
functions of templates) after the initial declaration (DR217).
- Improve diagnostics when a default argument is redefined. Now, the
note will always point at the place where the default argument was
previously defined, rather than pointing to the most recent
declaration of the function.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81548 91177308-0d34-0410-b5e6-96231b3b80d8
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 0000000..82f5267
--- /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 0000000..143a0ca
--- /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 0000000..ea16f64
--- /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 0000000..bbfaf90
--- /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 0000000..894c9b5
--- /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 0000000..ef00e7b
--- /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 0000000..9c1d3a9
--- /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 0000000..574237e
--- /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/SemaCXX/default2.cpp b/test/SemaCXX/default2.cpp
index dc83ac4..1834520 100644
--- a/test/SemaCXX/default2.cpp
+++ b/test/SemaCXX/default2.cpp
@@ -24,20 +24,8 @@
int x;
void g(int x, int y = x); // expected-error {{default argument references parameter 'x'}}
-void h()
-{
- int i;
- extern void h2(int x = sizeof(i)); // expected-error {{default argument references local variable 'i' of enclosing function}}
-}
-
void g2(int x, int y, int z = x + y); // expected-error {{default argument references parameter 'x'}} expected-error {{default argument references parameter 'y'}}
-void nondecl(int (*f)(int x = 5)) // {expected-error {{default arguments can only be specified}}}
-{
- void (*f2)(int = 17) // {expected-error {{default arguments can only be specified}}}
- = (void (*)(int = 42))f; // {expected-error {{default arguments can only be specified}}}
-}
-
class X {
void f(X* x = this); // expected-error{{invalid use of 'this' outside of a nonstatic member function}}
@@ -82,10 +70,6 @@
};
static int b;
-
- int (*f)(int = 17); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
-
- void mem8(int (*fp)(int) = (int (*)(int = 17))0); // expected-error{{default arguments can only be specified for parameters in a function declaration}}
};
int Y::mem3(int i = b) { return i; } // OK; use X::b
diff --git a/test/SemaTemplate/default-expr-arguments.cpp b/test/SemaTemplate/default-expr-arguments.cpp
index d689cc8..01d0e60 100644
--- a/test/SemaTemplate/default-expr-arguments.cpp
+++ b/test/SemaTemplate/default-expr-arguments.cpp
@@ -45,5 +45,26 @@
void s(G<int> flags = 10) { }
+// Test default arguments
+template<typename T>
+struct X0 {
+ void f(T = T()); // expected-error{{no matching}}
+};
+template<typename U>
+void X0<U>::f(U) { }
+void test_x0(X0<int> xi) {
+ xi.f();
+ xi.f(17);
+}
+
+struct NotDefaultConstructible { // expected-note{{candidate}}
+ NotDefaultConstructible(int); // expected-note{{candidate}}
+};
+
+void test_x0_not_default_constructible(X0<NotDefaultConstructible> xn) {
+ xn.f(NotDefaultConstructible(17));
+ xn.f(42);
+ xn.f(); // expected-note{{in instantiation of default function argument}}
+}