else
t = NULL_TREE;
- if ((!t || TREE_CODE (t) == TREE_LIST) && dependent_type_p (context))
+ if ((!t || TREE_CODE (t) == TREE_LIST) && dependentish_scope_p (context))
return build_typename_type (context, name, fullname, tag_type);
want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
; /* We already complained. */
else if (TYPE_P (scope))
{
- if (!COMPLETE_TYPE_P (scope))
+ if (!COMPLETE_TYPE_P (scope)
+ && !currently_open_class (scope))
error_at (location, "incomplete type %qT used in nested name specifier",
scope);
else if (TREE_CODE (decl) == TREE_LIST)
else if (TYPE_P (parser->scope))
{
auto_diagnostic_group d;
- if (!COMPLETE_TYPE_P (parser->scope))
+ if (!COMPLETE_TYPE_P (parser->scope)
+ && !currently_open_class (parser->scope))
cxx_incomplete_type_error (location_of (id), NULL_TREE,
parser->scope);
else if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
In order to see that `I' is a type-name in the definition, we
must be in the scope of `S'. */
- if (saved_scope)
+ if (saved_scope
+ /* In A<T>::operator I(), we don't want to enter A<T> if we're
+ in an expression rather than declaration context. */
+ && adjust_type_for_entering_scope (saved_scope) == saved_scope)
pushed_scope = push_scope (saved_scope);
/* Parse the conversion-type-id. */
type = cp_parser_conversion_type_id (parser);
/* If the scope is a dependent type and either we deferred lookup or
we did lookup but didn't find the name, rememeber the name. */
if (decl == error_mark_node && TYPE_P (parser->scope)
- && dependent_type_p (parser->scope))
+ && dependentish_scope_p (parser->scope))
{
if (tag_type)
{
/* Name lookup failed. */
if (scope
&& (!TYPE_P (scope)
- || (!dependent_type_p (scope)
+ || (!dependentish_scope_p (scope)
&& !(identifier_p (id_expression)
&& IDENTIFIER_CONV_OP_P (id_expression)
&& dependent_type_p (TREE_TYPE (id_expression))))))
afi.maybe_suggest_accessor (TYPE_READONLY (object_type));
if (member == NULL_TREE)
{
- if (dependent_type_p (object_type))
+ if (dependentish_scope_p (object_type))
/* Try again at instantiation time. */
goto dependent;
if (complain & tf_error)
template <typename T> struct S {
using U = S;
- // FIXME: This is ill-formed; see PR90847.
- void fn() alignas(U::X);
+ void fn() alignas(U::X); // { dg-error "not a member" }
};
template <typename T>
class D3
{
- enum D3::A { foo } c; // { dg-error "extra qualification not allowed" }
+ enum D3::A { foo } c; // { dg-error "does not name an enumeration" }
};
template <typename T>
class D4
{
- enum D4<T>::A { foo } c; // { dg-error "extra qualification not allowed" }
+ enum D4<T>::A { foo } c; // { dg-error "does not name an enumeration" }
};
template <typename T>
{
class D6
{
- enum D6::A { foo } c; // { dg-error "extra qualification not allowed" }
+ enum D6::A { foo } c; // { dg-error "does not name an enumeration" }
};
};
template <typename> struct A
{
+ struct E { static int V; };
A::E::V; // { dg-warning "access decl" }
enum { V }; // { dg-error "conflicts with a previous decl" }
};
template<typename> struct A
{
- enum A::B::C {}; // { dg-error "has not been declared" }
+ enum A::B::C {}; // { dg-error "" }
};
template <typename T>
struct IP
{
- static const bool r = IP<T>::r; // { dg-error "depth" }
+ static const bool r = IP<T*>::r; // { dg-error "depth" }
};
template <typename T> struct V
{
template <typename T>
struct IP
{
- static const bool r = IP<T>::r; // { dg-error "depth" }
+ static const bool r = IP<T*>::r; // { dg-error "depth" }
};
template <typename T>
struct V
{
- static const bool r = IP<T>::r;
+ static const bool r = IP<T*>::r;
VI<r> vi;
};
struct X;
template <typename> struct A
{
- template <typename> A(typename A::X) {} // { dg-error "incomplete" }
+ template <typename> A(typename A::X) {} // { dg-error "does not name a type" }
};
-// We currently don't give the "no match" error because we don't add the
-// invalid constructor template to TYPE_METHODS.
-A<void> a; // { dg-message "required" }
+A<void> a; // { dg-error "no match" }
template<int> struct A
{
static int i;
+ ~A();
};
template<int N> int A<N>::i = { A::~A }; // { dg-error "36:invalid use of non-static member function" }
{
template<void (A::*)()> struct B {};
void ::foo(); // { dg-error "10:invalid use" }
- B<&A::foo> b; // { dg-error "incomplete type|template argument" }
+ B<&A::foo> b; // { dg-error "'foo' is not a member of 'A'|template argument" }
};
--- /dev/null
+// Verify we diagnose failed qualified lookup into the current
+// instantiation ahead of time.
+
+namespace without_dependent_base {
+template<class T>
+struct A {
+ void f(A& other) {
+ A::x; // { dg-error "'x' is not a member" }
+ this->x; // { dg-error "no member named 'x'" }
+ other.y; // { dg-error "no member named 'y'" }
+ typename A::type z; // { dg-error "does not name a type" }
+
+ struct B {
+ void g(A& other) {
+ A::x; // { dg-error "'x' is not a member" }
+ this->x; // { dg-error "no member named 'x'" }
+ other.y; // { dg-error "no member named 'y'" }
+ typename A::type z; // { dg-error "does not name a type" }
+ }
+ };
+ }
+};
+}
+
+namespace with_dependent_base {
+template<class T>
+struct A : T {
+ void f(A& other) {
+ A::x;
+ this->x;
+ other.y;
+ typename A::type z;
+
+ struct B : T {
+ void g(A& other) {
+ A::x;
+ this->x;
+ other.y;
+ typename A::type z;
+ }
+ };
+ }
+};
+}
static const int i2;
};
-template <int N> const int A<N>::i1(A<N>::i);
-template <int N> const int A<N>::i2(3, A<N>::i); // { dg-error "expression list" }
+template <int N> const int A<N>::i1(A<N>::i1);
+template <int N> const int A<N>::i2(3, A<N>::i2); // { dg-error "expression list" }
struct Z;
expand me; // { dg-error "'expand' does not name a type" }
void foo(struct A::e);
- void foo(struct A::z); // { dg-error "incomplete" }
+ void foo(struct A::z); // { dg-error "does not name a type" }
};
struct Q;
// XXX ??? ^^^^^^^
{
// XXX ??? this->init(std::addressof(_M_sb));
- this->set_rbduf(std::addressof(_M_sb));
+ this->set_rdbuf(std::addressof(_M_sb));
}
template<typename... _Args>
bool
_M_is_proper_subset_of(const __dynamic_bitset_base& __b) const noexcept
{
- if (this->is_subset_of(__b))
+ if (this->_M_is_subset_of(__b))
{
if (*this == __b)
return false;