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
28 lines
1.2 KiB
C++
28 lines
1.2 KiB
C++
// 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) { }
|