return ret;
}
-/* Process "using SCOPE::NAME" in a class scope. Return the
- USING_DECL created. */
+/* Process and lookup a using decl SCOPE::lookup.name, filling in
+ lookup.values & lookup.type. Return true if ok. */
-tree
-do_class_using_decl (tree scope, tree name)
+static bool
+lookup_using_decl (tree scope, name_lookup &lookup)
{
- if (name == error_mark_node)
- return NULL_TREE;
+ tree current = current_scope ();
+ bool dependent_p = false;
- if (!scope || !TYPE_P (scope))
+ if (TREE_CODE (scope) == NAMESPACE_DECL)
{
- error ("using-declaration for non-member at class scope");
- return NULL_TREE;
- }
+ /* Naming a namespace member. */
+ if (TYPE_P (current))
+ {
+ error ("using-declaration for non-member at class scope");
+ return false;
+ }
- /* Make sure the name is not invalid */
- if (TREE_CODE (name) == BIT_NOT_EXPR)
- {
- error ("%<%T::%D%> names destructor", scope, name);
- return NULL_TREE;
+ qualified_namespace_lookup (scope, &lookup);
}
-
- /* Using T::T declares inheriting ctors, even if T is a typedef. */
- if (MAYBE_CLASS_TYPE_P (scope)
- && (name == TYPE_IDENTIFIER (scope)
- || constructor_name_p (name, scope)))
+ else if (TREE_CODE (scope) == ENUMERAL_TYPE)
{
- maybe_warn_cpp0x (CPP0X_INHERITING_CTORS);
- name = ctor_identifier;
- CLASSTYPE_NON_AGGREGATE (current_class_type) = true;
- TYPE_HAS_USER_CONSTRUCTOR (current_class_type) = true;
+ error ("using-declaration may not name enumerator %<%E::%D%>",
+ scope, lookup.name);
+ return false;
}
-
- /* Cannot introduce a constructor name. */
- if (constructor_name_p (name, current_class_type))
+ else
{
- error ("%<%T::%D%> names constructor in %qT",
- scope, name, current_class_type);
- return NULL_TREE;
- }
+ /* Naming a class member. */
+ if (!TYPE_P (current))
+ {
+ error ("using-declaration for member at non-class scope");
+ return false;
+ }
- /* From [namespace.udecl]:
+ /* Make sure the name is not invalid */
+ if (TREE_CODE (lookup.name) == BIT_NOT_EXPR)
+ {
+ error ("%<%T::%D%> names destructor", scope, lookup.name);
+ return false;
+ }
- A using-declaration used as a member-declaration shall refer to a
- member of a base class of the class being defined.
+ /* Using T::T declares inheriting ctors, even if T is a typedef. */
+ if (MAYBE_CLASS_TYPE_P (scope)
+ && (lookup.name == TYPE_IDENTIFIER (scope)
+ || constructor_name_p (lookup.name, scope)))
+ {
+ maybe_warn_cpp0x (CPP0X_INHERITING_CTORS);
+ lookup.name = ctor_identifier;
+ CLASSTYPE_NON_AGGREGATE (current) = true;
+ TYPE_HAS_USER_CONSTRUCTOR (current) = true;
+ }
+
+ /* Cannot introduce a constructor name. */
+ if (constructor_name_p (lookup.name, current))
+ {
+ error ("%<%T::%D%> names constructor in %qT",
+ scope, lookup.name, current);
+ return false;
+ }
- In general, we cannot check this constraint in a template because
- we do not know the entire set of base classes of the current
- class type. Morover, if SCOPE is dependent, it might match a
- non-dependent base. */
+ /* Member using decls finish processing when completing the
+ class. */
+ /* From [namespace.udecl]:
- tree decl = NULL_TREE;
- if (!dependent_scope_p (scope))
- {
- base_kind b_kind;
- tree binfo = lookup_base (current_class_type, scope, ba_any, &b_kind,
- tf_warning_or_error);
- if (b_kind < bk_proper_base)
+ A using-declaration used as a member-declaration shall refer
+ to a member of a base class of the class being defined.
+
+ In general, we cannot check this constraint in a template
+ because we do not know the entire set of base classes of the
+ current class type. Morover, if SCOPE is dependent, it might
+ match a non-dependent base. */
+
+ dependent_p = dependent_scope_p (scope);
+ if (!dependent_p)
{
- /* If there are dependent bases, scope might resolve at
- instantiation time, even if it isn't exactly one of the
- dependent bases. */
- if (b_kind == bk_same_type || !any_dependent_bases_p ())
+ base_kind b_kind;
+ tree binfo = lookup_base (current, scope, ba_any, &b_kind,
+ tf_warning_or_error);
+ if (b_kind < bk_proper_base)
+ {
+ /* If there are dependent bases, scope might resolve at
+ instantiation time, even if it isn't exactly one of
+ the dependent bases. */
+ if (b_kind == bk_same_type || !any_dependent_bases_p ())
+ {
+ error_not_base_type (scope, current);
+ return false;
+ }
+ /* Treat as-if dependent. */
+ dependent_p = true;
+ }
+ else if (lookup.name == ctor_identifier && !binfo_direct_p (binfo))
{
- error_not_base_type (scope, current_class_type);
- return NULL_TREE;
+ error ("cannot inherit constructors from indirect base %qT",
+ scope);
+ return false;
}
+ else if (IDENTIFIER_CONV_OP_P (lookup.name)
+ && dependent_type_p (TREE_TYPE (lookup.name)))
+ dependent_p = true;
+ else
+ lookup.value = lookup_member (binfo, lookup.name, 0,
+ false, tf_warning_or_error);
}
- else if (name == ctor_identifier && !binfo_direct_p (binfo))
+ }
+
+ if (!dependent_p)
+ {
+ if (!lookup.value)
{
- error ("cannot inherit constructors from indirect base %qT", scope);
- return NULL_TREE;
+ error ("%qD has not been declared in %qE", lookup.name, scope);
+ return false;
}
- else if (!IDENTIFIER_CONV_OP_P (name)
- || !dependent_type_p (TREE_TYPE (name)))
+
+ if (TREE_CODE (lookup.value) == TREE_LIST
+ /* We can (independently) have ambiguous implicit typedefs. */
+ || (lookup.type && TREE_CODE (lookup.type) == TREE_LIST))
{
- decl = lookup_member (binfo, name, 0, false, tf_warning_or_error);
- if (!decl)
- {
- error ("no members matching %<%T::%D%> in %q#T", scope, name,
- scope);
- return NULL_TREE;
- }
+ error ("reference to %qD is ambiguous", lookup.name);
+ print_candidates (TREE_CODE (lookup.value) == TREE_LIST
+ ? lookup.value : lookup.type);
+ return false;
+ }
- /* The binfo from which the functions came does not matter. */
- if (BASELINK_P (decl))
- decl = BASELINK_FUNCTIONS (decl);
+ if (TREE_CODE (lookup.value) == NAMESPACE_DECL)
+ {
+ error ("using-declaration may not name namespace %qD", lookup.value);
+ return false;
}
}
- tree value = build_lang_decl (USING_DECL, name, NULL_TREE);
- USING_DECL_DECLS (value) = decl;
- USING_DECL_SCOPE (value) = scope;
- DECL_DEPENDENT_P (value) = !decl;
+ return true;
+}
+
+/* Process "using SCOPE::NAME" in a class scope. Return the
+ USING_DECL created. */
+
+tree
+do_class_using_decl (tree scope, tree name)
+{
+ if (name == error_mark_node
+ || scope == error_mark_node)
+ return NULL_TREE;
+
+ name_lookup lookup (name, 0);
+ if (!lookup_using_decl (scope, lookup))
+ return NULL_TREE;
+
+ tree found = lookup.value;
+ if (found && BASELINK_P (found))
+ /* The binfo from which the functions came does not matter. */
+ found = BASELINK_FUNCTIONS (found);
+
+ tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
+ USING_DECL_SCOPE (using_decl) = scope;
+ USING_DECL_DECLS (using_decl) = found;
+ DECL_DEPENDENT_P (using_decl) = !found;
- return value;
+ return using_decl;
}
\f
finish_nonmember_using_decl (tree scope, tree name)
{
gcc_checking_assert (current_binding_level->kind != sk_class);
- gcc_checking_assert (identifier_p (name));
- name_lookup lookup (name, 0);
-
- if (TREE_CODE (scope) != NAMESPACE_DECL)
- {
- error ("%qE is not a namespace or unscoped enum", scope);
- return;
- }
-
- qualified_namespace_lookup (scope, &lookup);
-
- if (!lookup.value)
- {
- error ("%qD has not been declared in %qE", name, scope);
- return;
- }
+ if (scope == error_mark_node || name == error_mark_node)
+ return;
- if (TREE_CODE (lookup.value) == TREE_LIST
- /* But we can (independently) have ambiguous implicit typedefs. */
- || (lookup.type && TREE_CODE (lookup.type) == TREE_LIST))
- {
- error ("reference to %qD is ambiguous", name);
- print_candidates (TREE_CODE (lookup.value) == TREE_LIST
- ? lookup.value : lookup.type);
- return;
- }
+ name_lookup lookup (name, 0);
- if (TREE_CODE (lookup.value) == NAMESPACE_DECL)
- {
- error ("using-declaration may not name namespace %qD", lookup.value);
- return;
- }
+ if (!lookup_using_decl (scope, lookup))
+ return;
/* Emit debug info. */
if (!processing_template_decl)
}
else
{
- tree using_decl = build_lang_decl (USING_DECL, name, NULL_TREE);
+ tree using_decl = build_lang_decl (USING_DECL, lookup.name, NULL_TREE);
USING_DECL_SCOPE (using_decl) = scope;
add_decl_expr (using_decl);
set_identifier_type_value (name, type);
}
}
-
}
/* Return the declarations that are members of the namespace NS. */