summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-01-13 17:31:36 +0000
committerDouglas Gregor <dgregor@apple.com>2010-01-13 17:31:36 +0000
commit9de54ea41bdcf97f238ba9c4a1fa1d091d5813d9 (patch)
treecba2865d8d63cf45bf9270ea576c1e68bd757a88 /clang/test
parentb89b99f1f267237d68712b728b4aa5c90907cb48 (diff)
downloadbcm5719-llvm-9de54ea41bdcf97f238ba9c4a1fa1d091d5813d9.tar.gz
bcm5719-llvm-9de54ea41bdcf97f238ba9c4a1fa1d091d5813d9.zip
Reimplement constructor declarator parsing to cope with template-ids
that name constructors, the endless joys of out-of-line constructor definitions, and various other corner cases that the previous hack never imagined. Fixes PR5688 and tightens up semantic analysis for constructor names. Additionally, fixed a problem where we wouldn't properly enter the declarator scope of a parenthesized declarator. We were entering the scope, then leaving it when we saw the ")"; now, we re-enter the declarator scope before parsing the parameter list. Note that we are forced to perform some tentative parsing within a class (call it C) to tell the difference between C(int); // constructor and C (f)(int); // member function which is rather unfortunate. And, although it isn't necessary for correctness, we use the same tentative-parsing mechanism for out-of-line constructors to improve diagnostics in icky cases like: C::C C::f(int); // error: C::C refers to the constructor name, but // we complain nicely and recover by treating it as // a type. llvm-svn: 93322
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp27
-rw-r--r--clang/test/CXX/special/class.ctor/p1.cpp42
-rw-r--r--clang/test/SemaTemplate/injected-class-name.cpp6
-rw-r--r--clang/test/SemaTemplate/instantiate-member-class.cpp4
4 files changed, 72 insertions, 7 deletions
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
new file mode 100644
index 00000000000..7ecedd5a6a0
--- /dev/null
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+struct X0 {
+ X0 f1();
+ X0 f2();
+};
+
+template<typename T>
+struct X1 {
+ X1<T>(int);
+ (X1<T>)(float);
+ X1 f2();
+ X1 f2(int);
+ X1 f2(float);
+};
+
+// Error recovery: out-of-line constructors whose names have template arguments.
+template<typename T> X1<T>::X1<T>(int) { } // expected-error{{out-of-line constructor for 'X1' cannot have template arguments}}
+template<typename T> (X1<T>::X1<T>)(float) { } // expected-error{{out-of-line constructor for 'X1' cannot have template arguments}}
+
+// Error recovery: out-of-line constructor names intended to be types
+X0::X0 X0::f1() { return X0(); } // expected-error{{qualified reference to 'X0' is a constructor name rather than a type wherever a constructor can be declared}}
+
+struct X0::X0 X0::f2() { return X0(); }
+
+template<typename T> X1<T>::X1<T> X1<T>::f2() { } // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name wherever a constructor can be declared}}
+template<typename T> X1<T>::X1<T> (X1<T>::f2)(int) { } // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name wherever a constructor can be declared}}
+template<typename T> struct X1<T>::X1<T> (X1<T>::f2)(float) { }
diff --git a/clang/test/CXX/special/class.ctor/p1.cpp b/clang/test/CXX/special/class.ctor/p1.cpp
new file mode 100644
index 00000000000..9500a7d2346
--- /dev/null
+++ b/clang/test/CXX/special/class.ctor/p1.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+struct X0 {
+ struct type { };
+
+ X0();
+ X0(int);
+ (X0)(float);
+ X0 (f0)(int);
+ X0 (f0)(type);
+
+ X0 f1();
+ X0 f1(double);
+};
+
+X0::X0() { }
+(X0::X0)(int) { }
+
+X0 (X0::f0)(int) { return X0(); }
+
+template<typename T>
+struct X1 {
+ struct type { };
+
+ X1<T>();
+ X1<T>(int);
+ (X1<T>)(float);
+ X1(float, float);
+ (X1)(double);
+ X1<T> (f0)(int);
+ X1<T> (f0)(type);
+ X1 (f1)(int);
+ X1 (f1)(type);
+
+ template<typename U> X1(U);
+ X1 f2();
+ X1 f2(int);
+};
+
+template<typename T> X1<T>::X1() { }
+template<typename T> (X1<T>::X1)(double) { }
+template<typename T> X1<T> X1<T>::f1(int) { return 0; }
+template<typename T> X1<T> (X1<T>::f1)(type) { return 0; }
diff --git a/clang/test/SemaTemplate/injected-class-name.cpp b/clang/test/SemaTemplate/injected-class-name.cpp
index 1a65aeb3d6c..482eae14ba5 100644
--- a/clang/test/SemaTemplate/injected-class-name.cpp
+++ b/clang/test/SemaTemplate/injected-class-name.cpp
@@ -11,11 +11,7 @@ struct X<int***> {
typedef X<int***> *ptr;
};
-// FIXME: EDG rejects this in their strict-conformance mode, but I
-// don't see any wording making this ill-formed. Actually,
-// [temp.local]p2 might make it ill-formed. Are we "in the scope of
-// the class template specialization?"
-X<float>::X<int> xi = x;
+X<float>::X<int> xi = x; // expected-error{{qualified reference to 'X' is a constructor name rather than a template name wherever a constructor can be declared}}
// [temp.local]p1:
diff --git a/clang/test/SemaTemplate/instantiate-member-class.cpp b/clang/test/SemaTemplate/instantiate-member-class.cpp
index 8a19d74cdde..742abcc569c 100644
--- a/clang/test/SemaTemplate/instantiate-member-class.cpp
+++ b/clang/test/SemaTemplate/instantiate-member-class.cpp
@@ -14,8 +14,8 @@ public:
X<int>::C *c1;
X<float>::C *c2;
-X<int>::X *xi;
-X<float>::X *xf;
+X<int>::X *xi; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}}
+X<float>::X *xf; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}}
void test_naming() {
c1 = c2; // expected-error{{incompatible type assigning 'X<float>::C *', expected 'X<int>::C *'}}
OpenPOWER on IntegriCloud