#include "c-pragma.h"
#include "tree-dump.h"
#include "intl.h"
+#include "gimple.h"
extern cpp_reader *parse_in;
if (array_expr == error_mark_node || index_exp == error_mark_node)
error ("ambiguous conversion for array subscript");
- expr = build_array_ref (array_expr, index_exp);
+ expr = build_array_ref (array_expr, index_exp, input_location);
}
if (processing_template_decl && expr != error_mark_node)
return build_min_non_dep (ARRAY_REF, expr, orig_array_expr, orig_index_exp,
return OVL_CURRENT (fndecls);
}
- error ("prototype for %q#D does not match any in class %qT",
- function, ctype);
+ error_at (DECL_SOURCE_LOCATION (function),
+ "prototype for %q#D does not match any in class %qT",
+ function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
if (is_conv_op)
VEC_safe_push (tree, gc, pending_statics, decl);
if (LOCAL_CLASS_P (current_class_type))
- permerror ("local class %q#T shall not have static data member %q#D",
+ permerror (input_location, "local class %q#T shall not have static data member %q#D",
current_class_type, decl);
/* Static consts need not be initialized in the class definition. */
value = push_template_decl (value);
if (attrlist)
- cplus_decl_attributes (&value, attrlist, 0);
+ {
+ int attrflags = 0;
+
+ /* If this is a typedef that names the class for linkage purposes
+ (7.1.3p8), apply any attributes directly to the type. */
+ if (TAGGED_TYPE_P (TREE_TYPE (value))
+ && value == TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+ attrflags = ATTR_FLAG_TYPE_IN_PLACE;
+
+ cplus_decl_attributes (&value, attrlist, attrflags);
+ }
return value;
}
DECL_DEFAULTED_FN (value) = 1;
DECL_INITIALIZED_IN_CLASS_P (value) = 1;
DECL_DECLARED_INLINE_P (value) = 1;
- DECL_INLINE (value) = 1;
}
}
else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
continue;
if (TREE_CODE (field) != FIELD_DECL)
{
- permerror ("%q+#D invalid; an anonymous union can only "
+ permerror (input_location, "%q+#D invalid; an anonymous union can only "
"have non-static data members", field);
continue;
}
if (TREE_PRIVATE (field))
- permerror ("private member %q+#D in anonymous union", field);
+ permerror (input_location, "private member %q+#D in anonymous union", field);
else if (TREE_PROTECTED (field))
- permerror ("protected member %q+#D in anonymous union", field);
+ permerror (input_location, "protected member %q+#D in anonymous union", field);
if (processing_template_decl)
ref = build_min_nt (COMPONENT_REF, object,
e = 2;
if (e == 2)
- permerror ("%<operator new%> takes type %<size_t%> (%qT) "
+ permerror (input_location, "%<operator new%> takes type %<size_t%> (%qT) "
"as first parameter", size_type_node);
switch (e)
guard_value = integer_one_node;
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
guard_value = convert (TREE_TYPE (guard), guard_value);
- guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value,
+ guard = cp_build_binary_op (input_location,
+ BIT_AND_EXPR, guard, guard_value,
tf_warning_or_error);
}
guard_value = integer_zero_node;
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
guard_value = convert (TREE_TYPE (guard), guard_value);
- return cp_build_binary_op (EQ_EXPR, guard, guard_value,
+ return cp_build_binary_op (input_location,
+ EQ_EXPR, guard, guard_value,
tf_warning_or_error);
}
type);
TREE_PUBLIC (ssdf_decl) = 0;
DECL_ARTIFICIAL (ssdf_decl) = 1;
- DECL_INLINE (ssdf_decl) = 1;
/* Put this function in the list of functions to be called from the
static constructors and destructors. */
|| DECL_ONE_ONLY (decl) \
|| DECL_WEAK (decl)))
+/* Called from one_static_initialization_or_destruction(),
+ via walk_tree.
+ Walks the initializer list of a global variable and looks for
+ temporary variables (DECL_NAME() == NULL and DECL_ARTIFICIAL != 0)
+ and that have their DECL_CONTEXT() == NULL.
+ For each such temporary variable, set their DECL_CONTEXT() to
+ the current function. This is necessary because otherwise
+ some optimizers (enabled by -O2 -fprofile-arcs) might crash
+ when trying to refer to a temporary variable that does not have
+ it's DECL_CONTECT() properly set. */
+static tree
+fix_temporary_vars_context_r (tree *node,
+ int *unused ATTRIBUTE_UNUSED,
+ void *unused1 ATTRIBUTE_UNUSED)
+{
+ gcc_assert (current_function_decl);
+
+ if (TREE_CODE (*node) == BIND_EXPR)
+ {
+ tree var;
+
+ for (var = BIND_EXPR_VARS (*node); var; var = TREE_CHAIN (var))
+ if (TREE_CODE (var) == VAR_DECL
+ && !DECL_NAME (var)
+ && DECL_ARTIFICIAL (var)
+ && !DECL_CONTEXT (var))
+ DECL_CONTEXT (var) = current_function_decl;
+ }
+
+ return NULL_TREE;
+}
+
/* Set up to handle the initialization or destruction of DECL. If
INITP is nonzero, we are initializing the variable. Otherwise, we
are destroying it. */
information. */
input_location = DECL_SOURCE_LOCATION (decl);
+ /* Make sure temporary variables in the initialiser all have
+ their DECL_CONTEXT() set to a value different from NULL_TREE.
+ This can happen when global variables initialisers are built.
+ In that case, the DECL_CONTEXT() of the global variables _AND_ of all
+ the temporary variables that might have been generated in the
+ accompagning initialisers is NULL_TREE, meaning the variables have been
+ declared in the global namespace.
+ What we want to do here is to fix that and make sure the DECL_CONTEXT()
+ of the temporaries are set to the current function decl. */
+ cp_walk_tree_without_duplicates (&init,
+ fix_temporary_vars_context_r,
+ NULL);
+
/* Because of:
[class.access.spec]
last to destroy the variable. */
else if (initp)
guard_cond
- = cp_build_binary_op (EQ_EXPR,
+ = cp_build_binary_op (input_location,
+ EQ_EXPR,
cp_build_unary_op (PREINCREMENT_EXPR,
- guard,
- /*noconvert=*/1,
- tf_warning_or_error),
+ guard,
+ /*noconvert=*/1,
+ tf_warning_or_error),
integer_one_node,
tf_warning_or_error);
else
guard_cond
- = cp_build_binary_op (EQ_EXPR,
+ = cp_build_binary_op (input_location,
+ EQ_EXPR,
cp_build_unary_op (PREDECREMENT_EXPR,
- guard,
- /*noconvert=*/1,
- tf_warning_or_error),
+ guard,
+ /*noconvert=*/1,
+ tf_warning_or_error),
integer_zero_node,
tf_warning_or_error);
/* Build the outer if-stmt to check for initialization or destruction. */
init_if_stmt = begin_if_stmt ();
cond = initp ? integer_one_node : integer_zero_node;
- cond = cp_build_binary_op (EQ_EXPR,
+ cond = cp_build_binary_op (input_location,
+ EQ_EXPR,
initialize_p_decl,
cond,
tf_warning_or_error);
/* Conditionalize this initialization on being in the right priority
and being initializing/finalizing appropriately. */
priority_if_stmt = begin_if_stmt ();
- cond = cp_build_binary_op (EQ_EXPR,
+ cond = cp_build_binary_op (input_location,
+ EQ_EXPR,
priority_decl,
build_int_cst (NULL_TREE, priority),
tf_warning_or_error);
reconsider = true;
}
- if (!DECL_SAVED_TREE (decl))
+ if (!gimple_body (decl))
continue;
/* We lie to the back end, pretending that some functions
TREE_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DELETED_FN (decl))
+ {
+ error ("deleted function %q+D", decl);
+ error ("used here");
+ }
/* If we don't need a value, then we don't need to synthesize DECL. */
if (skip_evaluation)
return;
+
+ /* If within finish_function, defer the rest until that function
+ finishes, otherwise it might recurse. */
+ if (defer_mark_used_calls)
+ {
+ VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
+ return;
+ }
+
/* Normally, we can wait until instantiation-time to synthesize
DECL. However, if DECL is a static data member initialized with
a constant, we need the value right now because a reference to
/* If we've already synthesized the method we don't need to
do the instantiation test below. */
}
- else if (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DELETED_FN (decl))
- {
- error ("deleted function %q+D", decl);
- error ("used here");
- }
else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& (!DECL_EXPLICIT_INSTANTIATION (decl)