#include "dwarf2out.h"
#include "dwarfout.h"
+#if USE_CPPLIB
+#include "cpplib.h"
+extern cpp_reader parse_in;
+extern cpp_options parse_options;
+static int cpp_initialized;
+#endif
+
static tree get_sentry PROTO((tree));
static void mark_vtable_entries PROTO((tree));
static void import_export_template PROTO((tree));
static void add_using_namespace PROTO((tree, tree, int));
static tree ambiguous_decl PROTO((tree, tree, tree));
static tree build_anon_union_vars PROTO((tree, tree*, int, int));
+static void check_decl_namespace PROTO((void));
extern int current_class_depth;
int warn_implicit = 1;
+/* Nonzero means warn about usage of long long when `-pedantic'. */
+
+int warn_long_long = 1;
+
/* Nonzero means warn when all ctors or dtors are private, and the class
has no friends. */
int flag_use_repository;
+/* Nonzero if we want to issue diagnostics that the standard says are not
+ required. */
+
+int flag_optional_diags = 1;
+
/* Nonzero means give string constants the type `const char *'
to get extra warnings from them. These warnings will be too numerous
to be useful, except in thoroughly ANSIfied programs. */
int warn_cast_qual;
-/* Nonzero means warn that dbx info for template class methods isn't fully
- supported yet. */
-
-int warn_template_debugging;
-
/* Nonzero means warn about sizeof(function) or addition/subtraction
of function pointers. */
/* Warn about #pragma directives that are not recognised. */
-int warn_unknown_pragmas = 0; /* Tri state variable. */
+int warn_unknown_pragmas; /* Tri state variable. */
+
+/* Nonzero means warn about use of multicharacter literals. */
+
+int warn_multichar = 1;
/* Nonzero means `$' can be in an identifier. */
{"nonansi-builtins", &flag_no_nonansi_builtin, 0},
{"gnu-keywords", &flag_no_gnu_keywords, 0},
{"operator-names", &flag_operator_names, 1},
+ {"optional-diags", &flag_optional_diags, 1},
{"check-new", &flag_check_new, 1},
{"repo", &flag_use_repository, 1},
{"for-scope", &flag_new_for_scope, 2},
};
/* Decode the string P as a language-specific option.
- Return 1 if it is recognized (and handle it);
- return 0 if not recognized. */
+ Return the number of strings consumed for a valid option.
+ Otherwise return 0. */
int
-lang_decode_option (p)
- char *p;
+lang_decode_option (argc, argv)
+ int argc;
+ char **argv;
+
{
+ int strings_processed;
+ char *p = argv[0];
+#if USE_CPPLIB
+ if (! cpp_initialized)
+ {
+ cpp_reader_init (&parse_in);
+ parse_in.data = &parse_options;
+ cpp_options_init (&parse_options);
+ cpp_initialized = 1;
+ }
+ strings_processed = cpp_handle_option (&parse_in, argc, argv);
+#else
+ strings_processed = 0;
+#endif /* ! USE_CPPLIB */
+
if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional"))
flag_writable_strings = 1,
flag_this_is_variable = 1, flag_new_for_scope = 0;
if (!strcmp (p, "implicit"))
warn_implicit = setting;
+ else if (!strcmp (p, "long-long"))
+ warn_long_long = setting;
else if (!strcmp (p, "return-type"))
warn_return_type = setting;
else if (!strcmp (p, "ctor-dtor-privacy"))
warn_sign_promo = setting;
else if (!strcmp (p, "old-style-cast"))
warn_old_style_cast = setting;
+ else if (!strcmp (p, "overloaded-virtual"))
+ warn_overloaded_virtual = setting;
+ else if (!strcmp (p, "multichar"))
+ warn_multichar = setting;
else if (!strcmp (p, "unknown-pragmas"))
/* Set to greater than 1, so that even unknown pragmas in
system headers will be warned about. */
warn_sign_compare = setting;
warn_extern_inline = setting;
warn_nonvdtor = setting;
+ warn_multichar = setting;
/* We save the value of warn_uninitialized, since if they put
-Wuninitialized on the command line, we need to generate a
warning about not using it without also specifying -O. */
if (warn_uninitialized != 1)
warn_uninitialized = (setting ? 2 : 0);
- warn_template_debugging = setting;
warn_reorder = setting;
warn_sign_promo = setting;
/* Only warn about unknown pragmas that are not in system
headers. */
warn_unknown_pragmas = 1;
}
-
- else if (!strcmp (p, "overloaded-virtual"))
- warn_overloaded_virtual = setting;
- else return 0;
+ else return strings_processed;
}
else if (!strcmp (p, "-ansi"))
flag_no_nonansi_builtin = 1, flag_ansi = 1,
spew_debug = 1;
#endif
else
- return 0;
+ return strings_processed;
return 1;
}
{
/* Only do access checking here; we'll be calling op delete
from the destructor. */
- tree tmp = build_op_delete_call (DELETE_EXPR, t,
- size_zero_node, LOOKUP_NORMAL);
+ tree tmp = build_op_delete_call (DELETE_EXPR, t, size_zero_node,
+ LOOKUP_NORMAL, NULL_TREE);
if (tmp == error_mark_node)
return error_mark_node;
}
if (! global_bindings_p () || current_class_type)
return;
+ check_decl_namespace ();
+
start_time = get_run_time ();
/* Otherwise, GDB can get confused, because in only knows
import_export_decl (decl);
}
+ mark_all_runtime_matches ();
+
/* Now write out inline functions which had their addresses taken and
which were not declared virtual and which were not declared `extern
inline'. */
switch (TREE_CODE (t))
{
case IDENTIFIER_NODE:
- return do_identifier (t, 0);
+ return do_identifier (t, 0, NULL_TREE);
case LOOKUP_EXPR:
if (LOOKUP_EXPR_GLOBAL (t))
return do_scoped_id (TREE_OPERAND (t, 0), 0);
else
- return do_identifier (TREE_OPERAND (t, 0), 0);
+ return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
case TEMPLATE_ID_EXPR:
return (lookup_template_function
else
{
tree name = TREE_OPERAND (t, 0);
- if (TREE_CODE (name) == TEMPLATE_ID_EXPR
+ tree id;
+ tree args = build_expr_from_tree (TREE_OPERAND (t, 1));
+ if (args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
+ && !LOOKUP_EXPR_GLOBAL (name)
+ && TREE_CODE ((id = TREE_OPERAND (name, 0))) == IDENTIFIER_NODE
+ && (!current_class_type
+ || !lookup_member (current_class_type, id, 0, 0)))
+ {
+ /* Do Koenig lookup if there are no class members. */
+ name = do_identifier (id, 0, args);
+ }
+ else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
- return build_x_function_call
- (name, build_expr_from_tree (TREE_OPERAND (t, 1)),
- current_class_ref);
+ return build_x_function_call (name, args, current_class_ref);
}
case COND_EXPR:
return 1;
if (child == global_namespace)
return 0;
- return is_namespace_ancestor (root, DECL_CONTEXT (child));
+ return is_namespace_ancestor (root, CP_DECL_CONTEXT (child));
}
}
/* Add the bindings of name in used namespaces to val.
- The using list is defined by current, and the lookup goes to scope.
+ The using list is defined by usings, and the lookup goes to scope.
Returns zero on errors. */
int
-lookup_using_namespace (name, val, current, scope)
- tree name, val, current, scope;
+lookup_using_namespace (name, val, usings, scope)
+ tree name, val, usings, scope;
{
tree iter;
tree val1;
- /* Iterate over all namespaces from current to scope. */
- while (val != error_mark_node)
- {
- /* Iterate over all used namespaces in current, searching for
- using directives of scope. */
- for (iter = DECL_NAMESPACE_USING (current);
- iter; iter = TREE_CHAIN (iter))
- if (TREE_VALUE (iter) == scope)
- {
- val1 = binding_for_name (name, TREE_PURPOSE (iter));
- /* Resolve ambiguities. */
- val = ambiguous_decl (name, val, val1);
- }
- if (current == scope)
- break;
- current = DECL_CONTEXT (current);
- }
+ /* Iterate over all used namespaces in current, searching for using
+ directives of scope. */
+ for (iter = usings; iter; iter = TREE_CHAIN (iter))
+ if (TREE_VALUE (iter) == scope)
+ {
+ val1 = binding_for_name (name, TREE_PURPOSE (iter));
+ /* Resolve ambiguities. */
+ val = ambiguous_decl (name, val, val1);
+ }
return val != error_mark_node;
}
usings = TREE_CHAIN (usings))
/* If this was a real directive, and we have not seen it. */
if (!TREE_INDIRECT_USING (usings)
- && !purpose_member (seen, TREE_PURPOSE (usings)))
+ && !purpose_member (TREE_PURPOSE (usings), seen))
todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
if (todo)
{
if (!is_namespace_ancestor (current_namespace, scope))
cp_error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
- DECL_CONTEXT (decl) = scope;
+ DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
if (scope != current_namespace)
{
/* See whether this has been declared in the namespace. */
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd', 390);
}
- /* We should always find the namespace. */
- my_friendly_abort (390);
- return NULL_TREE;
+ return global_namespace;
}
/* Return the namespace where the current declaration is declared. */
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
+static void
+check_decl_namespace ()
+{
+ my_friendly_assert (decl_namespace_list == NULL_TREE, 980711);
+}
+
/* [basic.lookup.koenig] */
/* A non-zero return value in the functions below indicates an error.
All nodes allocated in the procedure are on the scratch obstack. */
if (arg_assoc_type (k, DECL_CLASS_CONTEXT (n)))
return 1;
return 0;
+ case TEMPLATE_DECL:
+ /* XXX Type of a function template in the context of Koenig lookup?
+ Assume that template parameters are non-deduced for the moment. */
+ n = DECL_RESULT (n);
+ continue;
+ case ERROR_MARK:
+ return 0;
default:
cp_error ("sorry, Koenig lookup for `%s' of type `%T' failed",
tree_code_name [(int)TREE_CODE (n)], TREE_TYPE (n));
/* Build the alias. */
alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
DECL_NAMESPACE_ALIAS (alias) = namespace;
- DECL_CONTEXT (alias) = current_namespace;
+ DECL_CONTEXT (alias) = FROB_CONTEXT (current_namespace);
BINDING_VALUE (binding) = alias;
}
}
-/* Process a using-declaration not appearing in class or local scope. */
+/* Check a non-member using-declaration. Return the name and scope
+ being used, and the USING_DECL, or NULL_TREE on failure. */
-void
-do_toplevel_using_decl (decl)
+static tree
+validate_nonmember_using_decl (decl, scope, name)
tree decl;
+ tree *scope;
+ tree *name;
{
- tree scope, name, binding, decls, newval, newtype;
- struct tree_binding _decls;
-
if (TREE_CODE (decl) == SCOPE_REF
&& TREE_OPERAND (decl, 0) == std_node)
- return;
+ return NULL_TREE;
if (TREE_CODE (decl) == SCOPE_REF)
{
- scope = TREE_OPERAND (decl, 0);
- name = TREE_OPERAND (decl, 1);
+ *scope = TREE_OPERAND (decl, 0);
+ *name = TREE_OPERAND (decl, 1);
}
else if (TREE_CODE (decl) == IDENTIFIER_NODE
|| TREE_CODE (decl) == TYPE_DECL)
{
- scope = global_namespace;
- name = decl;
+ *scope = global_namespace;
+ *name = decl;
}
else
my_friendly_abort (382);
- if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
- name = DECL_NAME (name);
+ if (TREE_CODE_CLASS (TREE_CODE (*name)) == 'd')
+ *name = DECL_NAME (*name);
/* Make a USING_DECL. */
- decl = push_using_decl (scope, name);
- if (!decl)
- return;
-
- binding = binding_for_name (name, current_namespace);
+ return push_using_decl (*scope, *name);
+}
+
+/* Process local and global using-declarations. */
+
+static void
+do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
+ tree scope, name;
+ tree oldval, oldtype;
+ tree *newval, *newtype;
+{
+ tree decls;
+ struct tree_binding _decls;
+
+ *newval = *newtype = NULL_TREE;
decls = binding_init (&_decls);
if (!qualified_lookup_using_namespace (name, scope, decls))
/* Lookup error */
cp_error ("`%D' not declared", name);
return;
}
- newval = newtype = NULL_TREE;
/* Check for using functions. */
if (BINDING_VALUE (decls) && is_overloaded_fn (BINDING_VALUE (decls)))
{
- tree oldval = BINDING_VALUE (binding);
tree tmp, tmp1;
- newval = oldval;
+ *newval = oldval;
for (tmp = BINDING_VALUE (decls); tmp; tmp = OVL_NEXT (tmp))
{
if (tmp1)
continue;
- newval = build_overload (OVL_CURRENT (tmp), newval);
- if (TREE_CODE (newval) != OVERLOAD)
- newval = ovl_cons (newval, NULL_TREE);
- OVL_USED (newval) = 1;
+ *newval = build_overload (OVL_CURRENT (tmp), *newval);
+ if (TREE_CODE (*newval) != OVERLOAD)
+ *newval = ovl_cons (*newval, NULL_TREE);
+ OVL_USED (*newval) = 1;
}
}
else
{
- tree oldval = BINDING_VALUE (binding);
- newval = BINDING_VALUE (decls);
- if (oldval && oldval != newval && !duplicate_decls (newval, oldval))
- newval = oldval;
+ *newval = BINDING_VALUE (decls);
+ if (oldval && oldval != *newval && !duplicate_decls (*newval, oldval))
+ *newval = oldval;
}
- newtype = BINDING_TYPE (decls);
- if (BINDING_TYPE (binding) && newtype && BINDING_TYPE (binding) != newtype)
+ *newtype = BINDING_TYPE (decls);
+ if (oldtype && *newtype && oldtype != *newtype)
{
cp_error ("using directive `%D' introduced ambiguous type `%T'",
- name, BINDING_TYPE (decls));
+ name, oldtype);
return;
}
+}
+
+/* Process a using-declaration not appearing in class or local scope. */
+
+void
+do_toplevel_using_decl (decl)
+ tree decl;
+{
+ tree scope, name, binding;
+ tree oldval, oldtype, newval, newtype;
+
+ decl = validate_nonmember_using_decl (decl, &scope, &name);
+ if (decl == NULL_TREE)
+ return;
+
+ binding = binding_for_name (name, current_namespace);
+
+ oldval = BINDING_VALUE (binding);
+ oldtype = BINDING_TYPE (binding);
+
+ do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
+
/* Copy declarations found. */
if (newval)
BINDING_VALUE (binding) = newval;
return;
}
+void
+do_local_using_decl (decl)
+ tree decl;
+{
+ tree scope, name;
+ tree oldval, oldtype, newval, newtype;
+ decl = validate_nonmember_using_decl (decl, &scope, &name);
+ if (decl == NULL_TREE)
+ return;
+
+ /* XXX nested values */
+ oldval = IDENTIFIER_LOCAL_VALUE (name);
+ /* XXX get local type */
+ oldtype = NULL_TREE;
+
+ do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
+
+ if (newval)
+ /* XXX update bindings */
+ IDENTIFIER_LOCAL_VALUE (name) = newval;
+ /* XXX type */
+}
+
tree
do_class_using_decl (decl)
tree decl;
{
if (namespace == std_node)
return;
- if (!toplevel_bindings_p ())
- {
- sorry ("using directives inside functions");
- return;
- }
/* using namespace A::B::C; */
if (TREE_CODE (namespace) == SCOPE_REF)
namespace = TREE_OPERAND (namespace, 1);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
- /* direct usage */
- add_using_namespace (current_namespace, namespace, 0);
+ if (!toplevel_bindings_p ())
+ push_using_directive
+ (namespace, namespace_ancestor (current_decl_namespace(),
+ current_namespace));
+ else
+ /* direct usage */
+ add_using_namespace (current_namespace, namespace, 0);
}
void