+2011-05-20 Jason Merrill <jason@redhat.com>
+
+ PR c++/24163
+ PR c++/29131
+ * pt.c (tsubst_copy_and_build) [CALL_EXPR]: Avoid repeating
+ unqualified lookup.
+ * semantics.c (perform_koenig_lookup): Add complain parm.
+ * cp-tree.h: Adjust.
+ * parser.c (cp_parser_postfix_expression): Adjust.
+ (cp_parser_perform_range_for_lookup): Adjust.
+
2011-05-20 Jason Merrill <jason@redhat.com>
* semantics.c (finish_call_expr): SET_EXPR_LOCATION.
extern tree finish_stmt_expr (tree, bool);
extern tree stmt_expr_value_expr (tree);
bool empty_expr_stmt_p (tree);
-extern tree perform_koenig_lookup (tree, VEC(tree,gc) *, bool);
+extern tree perform_koenig_lookup (tree, VEC(tree,gc) *, bool,
+ tsubst_flags_t);
extern tree finish_call_expr (tree, VEC(tree,gc) **, bool,
bool, tsubst_flags_t);
extern tree finish_increment_expr (tree, enum tree_code);
if (!any_type_dependent_arguments_p (args))
postfix_expression
= perform_koenig_lookup (postfix_expression, args,
- /*include_std=*/false);
+ /*include_std=*/false,
+ tf_warning_or_error);
}
else
postfix_expression
if (!any_type_dependent_arguments_p (args))
postfix_expression
= perform_koenig_lookup (postfix_expression, args,
- /*include_std=*/false);
+ /*include_std=*/false,
+ tf_warning_or_error);
}
}
}
VEC_safe_push (tree, gc, vec, range);
member_begin = perform_koenig_lookup (id_begin, vec,
- /*include_std=*/true);
+ /*include_std=*/true,
+ tf_warning_or_error);
*begin = finish_call_expr (member_begin, &vec, false, true,
tf_warning_or_error);
member_end = perform_koenig_lookup (id_end, vec,
- /*include_std=*/true);
+ /*include_std=*/true,
+ tf_warning_or_error);
*end = finish_call_expr (member_end, &vec, false, true,
tf_warning_or_error);
/*done=*/false,
/*address_p=*/false);
}
+ else if (koenig_p && TREE_CODE (function) == IDENTIFIER_NODE)
+ {
+ /* Do nothing; calling tsubst_copy_and_build on an identifier
+ would incorrectly perform unqualified lookup again.
+
+ Note that we can also have an IDENTIFIER_NODE if the earlier
+ unqualified lookup found a member function; in that case
+ koenig_p will be false and we do want to do the lookup
+ again to find the instantiated member function.
+
+ FIXME but doing that causes c++/15272, so we need to stop
+ using IDENTIFIER_NODE in that situation. */
+ qualified_p = false;
+ }
else
{
if (TREE_CODE (function) == COMPONENT_REF)
into a non-dependent call. */
&& type_dependent_expression_p_push (t)
&& !any_type_dependent_arguments_p (call_args))
- function = perform_koenig_lookup (function, call_args, false);
+ function = perform_koenig_lookup (function, call_args, false,
+ tf_none);
if (TREE_CODE (function) == IDENTIFIER_NODE
- && !processing_template_decl)
+ && !any_type_dependent_arguments_p (call_args))
{
- unqualified_name_lookup_error (function);
- release_tree_vector (call_args);
- return error_mark_node;
+ if (koenig_p && (complain & tf_warning_or_error))
+ {
+ /* For backwards compatibility and good diagnostics, try
+ the unqualified lookup again if we aren't in SFINAE
+ context. */
+ tree unq = (tsubst_copy_and_build
+ (function, args, complain, in_decl, true,
+ integral_constant_expression_p));
+ if (unq != function)
+ {
+ tree fn = unq;
+ if (TREE_CODE (fn) == COMPONENT_REF)
+ fn = TREE_OPERAND (fn, 1);
+ if (is_overloaded_fn (fn))
+ fn = get_first_fn (fn);
+ permerror (EXPR_LOC_OR_HERE (t),
+ "%qD was not declared in this scope, "
+ "and no declarations were found by "
+ "argument-dependent lookup at the point "
+ "of instantiation", function);
+ if (DECL_CLASS_SCOPE_P (fn))
+ {
+ inform (EXPR_LOC_OR_HERE (t),
+ "declarations in dependent base %qT are "
+ "not found by unqualified lookup",
+ DECL_CLASS_CONTEXT (fn));
+ if (current_class_ptr)
+ inform (EXPR_LOC_OR_HERE (t),
+ "use %<this->%D%> instead", function);
+ else
+ inform (EXPR_LOC_OR_HERE (t),
+ "use %<%T::%D%> instead",
+ TYPE_IDENTIFIER (current_class_type),
+ function);
+ }
+ else
+ inform (0, "%q+D declared here, later in the "
+ "translation unit", fn);
+ function = unq;
+ }
+ }
+ if (TREE_CODE (function) == IDENTIFIER_NODE)
+ {
+ unqualified_name_lookup_error (function);
+ release_tree_vector (call_args);
+ return error_mark_node;
+ }
}
/* Remember that there was a reference to this entity. */
Returns the functions to be considered by overload resolution. */
tree
-perform_koenig_lookup (tree fn, VEC(tree,gc) *args, bool include_std)
+perform_koenig_lookup (tree fn, VEC(tree,gc) *args, bool include_std,
+ tsubst_flags_t complain)
{
tree identifier = NULL_TREE;
tree functions = NULL_TREE;
{
fn = lookup_arg_dependent (identifier, functions, args, include_std);
if (!fn)
- /* The unqualified name could not be resolved. */
- fn = unqualified_fn_lookup_error (identifier);
+ {
+ /* The unqualified name could not be resolved. */
+ if (complain)
+ fn = unqualified_fn_lookup_error (identifier);
+ else
+ fn = identifier;
+ }
}
if (fn && template_id)
+2011-05-20 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/template/koenig9.C: New.
+ * g++.dg/opt/pr47615.C: Fix.
+ * g++.dg/overload/defarg1.C: Fix.
+ * g++.dg/tc1/dr213.C: Remove xfail.
+ * g++.dg/torture/pr34850.C: Fix.
+ * g++.dg/torture/pr39362.C: Fix.
+ * g++.old-deja/g++.brendan/crash56.C: Fix.
+ * g++.old-deja/g++.pt/memtemp47.C: Fix.
+
2011-05-20 Richard Guenther <rguenther@suse.de>
PR tree-optimization/49079
{
{
{
- rotate_right (p_nd);
+ this->rotate_right (p_nd);
}
}
}
template<typename T>
int foo (T t, int = foo(T()));
+struct A { };
+
int main()
{
- foo(0); // { dg-error "default argument" }
+ foo(A()); // { dg-error "default argument" }
}
template <class T> struct A : T {
void h(T t) {
f(t);
- g(t); // { dg-error "" "" { xfail *-*-* } }
+ g(t); // { dg-message "" }
}
};
int main()
{
- A<B> ab; // { dg-error "" "" { xfail *-*-* } }
+ A<B> ab;
B b;
- ab.h(b);
+ ab.h(b); // { dg-message "instantiated" }
}
--- /dev/null
+// PR c++/29131
+// int has no associated namespaces, so arg-dep lookup doesn't find g(int).
+
+template <class T> int f() { return g(T()); } // { dg-error "argument-dependent" }
+int g(int); // { dg-message "declared here" }
+int i = f<int>();
+
+// PR c++/24163
+// Unqualified lookup doesn't find names from dependent bases.
+
+template <class T>
+struct A
+{
+ static void h(T);
+};
+
+template <class T> struct B: A<T>
+{
+ void f() { h(T()); } // { dg-error "argument-dependent" }
+ static void g() { h(T()); } // { dg-error "argument-dependent" }
+};
+
+int main()
+{
+ B<int> b;
+ b.f();
+ b.g();
+}
+
+// { dg-message "dependent base .A.int" "" { target *-*-* } 19 }
+// { dg-message "this->h" "" { target *-*-* } 19 }
+// { dg-message "dependent base .A.int" "" { target *-*-* } 20 }
+// { dg-message "B::h" "" { target *-*-* } 20 }
template<typename T> class SecureVector : public MemoryRegion<T> {
public:
SecureVector<T>& operator=(const MemoryRegion<T>& in) {
- if(this != &in) set(in);
+ if(this != &in) this->set(in);
}
};
class OctetString {
template <typename T> struct I <T, 0> : H <T>
{
I (int capacity) { allocateBuffer (capacity); }
- ~I () { deallocateBuffer (buffer ()); }
+ ~I () { this->deallocateBuffer (buffer ()); }
using H <T>::allocateBuffer;
H <T>::buffer;
};
SetLD<T>::add(const T& item)
{
if ( ! contains(item) )
- append(item);
+ this->append(item);
}
template<class T>
void
{
template <class U>
void f(U u)
- { printf ("In T::f(U)\n"); g(u); }
+ { printf ("In T::f(U)\n"); this->g(u); }
};
int main()
+2011-05-20 Jason Merrill <jason@redhat.com>
+
+ * include/ext/pb_ds/assoc_container.hpp: Explicitly qualify calls to
+ functions from dependent bases.
+ * include/ext/pb_ds/detail/rb_tree_map_/erase_fn_imps.hpp: Likewise.
+ * include/ext/pb_ds/detail/rb_tree_map_/
+ split_join_fn_imps.hpp: Likewise.
+ * include/ext/pb_ds/detail/splay_tree_/erase_fn_imps.hpp: Likewise.
+ * include/ext/pb_ds/detail/splay_tree_/insert_fn_imps.hpp: Likewise.
+ * include/ext/pb_ds/detail/splay_tree_/splay_fn_imps.hpp: Likewise.
+ * include/ext/pb_ds/detail/splay_tree_/
+ split_join_fn_imps.hpp: Likewise.
+ * include/ext/pb_ds/detail/tree_policy/
+ order_statistics_imp.hpp: Likewise.
+ * include/ext/pb_ds/detail/trie_policy/
+ prefix_search_node_update_imp.hpp: Likewise.
+ * include/ext/rc_string_base.h: Likewise.
+ * include/ext/rope: Likewise.
+ * include/ext/ropeimpl.h: Likewise.
+ * testsuite/util/exception/safety.h: Likewise.
+ * testsuite/util/native_type/native_priority_queue.hpp: Likewise.
+ * testsuite/util/testsuite_io.h: Likewise.
+ * include/std/functional: Declare mem_fn earlier.
+ * include/tr1/functional: Likewise.
+ * include/tr1/exp_integral.tcc: Declare __expint_E1 earlier.
+
2011-05-19 Paolo Carlini <paolo.carlini@oracle.com>
* include/std/tuple (tuple_element<__i, const _Tp>,
template<typename It>
cc_hash_table(It first, It last, const hash_fn& h)
: base_type(h)
- { copy_from_range(first, last); }
+ { this->copy_from_range(first, last); }
// Constructor taking __iterators to a range of value_types and
// some policy objects The value_types between first_it and
template<typename It>
cc_hash_table(It first, It last, const hash_fn& h, const eq_fn& e)
: base_type(h, e)
- { copy_from_range(first, last); }
+ { this->copy_from_range(first, last); }
// Constructor taking __iterators to a range of value_types and
// some policy objects The value_types between first_it and
cc_hash_table(It first, It last, const hash_fn& h, const eq_fn& e,
const comb_hash_fn& ch)
: base_type(h, e, ch)
- { copy_from_range(first, last); }
+ { this->copy_from_range(first, last); }
// Constructor taking __iterators to a range of value_types and
// some policy objects The value_types between first_it and
cc_hash_table(It first, It last, const hash_fn& h, const eq_fn& e,
const comb_hash_fn& ch, const resize_policy& rp)
: base_type(h, e, ch, rp)
- { copy_from_range(first, last); }
+ { this->copy_from_range(first, last); }
cc_hash_table(const cc_hash_table& other)
: base_type((const base_type&)other)
PB_DS_CLASS_C_DEC::
erase(const_key_reference r_key)
{
- point_iterator it = find(r_key);
+ point_iterator it = this->find(r_key);
if (it == base_type::end())
return false;
erase(it);
PB_DS_CLASS_C_DEC::
remove_node(node_pointer p_z)
{
- update_min_max_for_erased_node(p_z);
+ this->update_min_max_for_erased_node(p_z);
node_pointer p_y = p_z;
node_pointer p_x = 0;
node_pointer p_new_x_parent = 0;
p_y = p_z;
}
- update_to_top(p_new_x_parent, (node_update* )this);
+ this->update_to_top(p_new_x_parent, (node_update* )this);
if (p_y->m_red)
return;
p_w->m_p_right->m_red = false;
base_type::rotate_left(p_new_x_parent);
- update_to_top(p_new_x_parent, (node_update* )this);
+ this->update_to_top(p_new_x_parent, (node_update* )this);
break;
}
}
p_w->m_p_left->m_red = false;
base_type::rotate_right(p_new_x_parent);
- update_to_top(p_new_x_parent, (node_update* )this);
+ this->update_to_top(p_new_x_parent, (node_update* )this);
break;
}
}
PB_DS_STRUCT_ONLY_ASSERT_VALID((*this))
PB_DS_STRUCT_ONLY_ASSERT_VALID(other)
- node_pointer p_nd = upper_bound(r_key).m_p_nd;
+ node_pointer p_nd = this->upper_bound(r_key).m_p_nd;
do
{
node_pointer p_next_nd = p_nd->m_p_parent;
if (p_l != 0)
p_l->m_p_parent = p_parent;
- update_to_top(p_parent, (node_update* )this);
+ this->update_to_top(p_parent, (node_update* )this);
if (!p_nd->m_red)
remove_fixup(p_l, p_parent);
if (p_l != 0)
p_l->m_p_parent = p_target_r;
PB_DS_ASSERT_VALID((*this))
- apply_update(p_target_r, (node_update* )this);
+ this->apply_update(p_target_r, (node_update* )this);
}
PB_DS_CLASS_T_DEC
while (p_nd->m_p_right != 0)
p_nd = p_nd->m_p_right;
- return std::make_pair(insert_leaf_new(r_value, p_nd, false), true);
+ return std::make_pair(this->insert_leaf_new(r_value, p_nd, false), true);
}
if (p_nd->m_p_parent == base_type::m_p_head)
base_type::m_p_head->m_p_parent = p_nd;
- apply_update(p_grandparent, (node_update* )this);
- apply_update(p_parent, (node_update* )this);
- apply_update(p_nd, (node_update* )this);
+ this->apply_update(p_grandparent, (node_update* )this);
+ this->apply_update(p_parent, (node_update* )this);
+ this->apply_update(p_nd, (node_update* )this);
PB_DS_ASSERT_BASE_NODE_CONSISTENT(p_nd)
}
base_type::m_p_head->m_p_parent = p_target_r;
p_target_r->m_p_parent = base_type::m_p_head;
- apply_update(p_target_r, (node_update* )this);
+ this->apply_update(p_target_r, (node_update* )this);
base_type::join_finish(other);
return;
}
- node_pointer p_upper_bound = upper_bound(r_key).m_p_nd;
+ node_pointer p_upper_bound = this->upper_bound(r_key).m_p_nd;
_GLIBCXX_DEBUG_ASSERT(p_upper_bound != 0);
splay(p_upper_bound);
other.m_p_head->m_p_parent = p_upper_bound;
p_upper_bound->m_p_parent = other.m_p_head;
p_upper_bound->m_p_left = 0;
- apply_update(p_upper_bound, (node_update* )this);
+ this->apply_update(p_upper_bound, (node_update* )this);
base_type::split_finish(other);
PB_DS_ASSERT_VALID((*this))
{
const_node_iterator l_it = it.get_l_child();
- if (r_cmp_fn(r_key, extract_key(*(*it))))
+ if (r_cmp_fn(r_key, this->extract_key(*(*it))))
it = l_it;
- else if (r_cmp_fn(extract_key(*(*it)), r_key))
+ else if (r_cmp_fn(this->extract_key(*(*it)), r_key))
{
ord += (l_it == end_it)?
if (common_range_length >= given_range_length)
{
- iterator ret_b = leftmost_it(nd_it);
+ iterator ret_b = this->leftmost_it(nd_it);
- iterator ret_e = rightmost_it(nd_it);
+ iterator ret_e = this->rightmost_it(nd_it);
return (std::make_pair(ret_b, ++ret_e));
}
__alloc);
if (_M_info._M_length)
- _S_copy(__r->_M_refdata(), _M_refdata(), _M_info._M_length);
+ __rc_string_base::_S_copy(__r->_M_refdata(), _M_refdata(), _M_info._M_length);
__r->_M_set_length(_M_info._M_length);
return __r->_M_refdata();
// Check for out_of_range and length_error exceptions.
_Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
__try
- { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
+ { __rc_string_base::_S_copy_chars(__r->_M_refdata(), __beg, __end); }
__catch(...)
{
__r->_M_destroy(__a);
// Check for out_of_range and length_error exceptions.
_Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
if (__n)
- _S_assign(__r->_M_refdata(), __n, __c);
+ __rc_string_base::_S_assign(__r->_M_refdata(), __n, __c);
__r->_M_set_length(__n);
return __r->_M_refdata();
_M_capacity(), _M_get_allocator());
if (__pos)
- _S_copy(__r->_M_refdata(), _M_data(), __pos);
+ this->_S_copy(__r->_M_refdata(), _M_data(), __pos);
if (__s && __len2)
- _S_copy(__r->_M_refdata() + __pos, __s, __len2);
+ this->_S_copy(__r->_M_refdata() + __pos, __s, __len2);
if (__how_much)
- _S_copy(__r->_M_refdata() + __pos + __len2,
+ this->_S_copy(__r->_M_refdata() + __pos + __len2,
_M_data() + __pos + __len1, __how_much);
_M_dispose();
_M_get_allocator());
if (__pos)
- _S_copy(__r->_M_refdata(), _M_data(), __pos);
+ this->_S_copy(__r->_M_refdata(), _M_data(), __pos);
if (__how_much)
- _S_copy(__r->_M_refdata() + __pos,
+ this->_S_copy(__r->_M_refdata() + __pos,
_M_data() + __pos + __n, __how_much);
_M_dispose();
else if (__how_much && __n)
{
// Work in-place.
- _S_move(_M_data() + __pos,
+ this->_S_move(_M_data() + __pos,
_M_data() + __pos + __n, __how_much);
}
if (_M_data != this->_M_c_string)
this->_M_free_c_string();
- __STL_FREE_STRING(_M_data, this->_M_size, this->_M_get_allocator());
+ this->__STL_FREE_STRING(_M_data, this->_M_size, this->_M_get_allocator());
}
#endif
protected:
operator*()
{
if (0 == this->_M_buf_ptr)
- _S_setcache(*this);
+ this->_S_setcache(*this);
return *this->_M_buf_ptr;
}
_M_root_rope(__r)
{ _RopeRep::_S_ref(this->_M_root);
if (!(__r -> empty()))
- _S_setcache(*this);
+ this->_S_setcache(*this);
}
void _M_check();
_Rope_RopeLeaf<_CharT, _Alloc>* __l
= (_Rope_RopeLeaf<_CharT, _Alloc>*)this;
__l->_Rope_RopeLeaf<_CharT, _Alloc>::~_Rope_RopeLeaf();
- _L_deallocate(__l, 1);
+ this->_L_deallocate(__l, 1);
break;
}
case __detail::_S_concat:
= (_Rope_RopeConcatenation<_CharT, _Alloc>*)this;
__c->_Rope_RopeConcatenation<_CharT, _Alloc>::
~_Rope_RopeConcatenation();
- _C_deallocate(__c, 1);
+ this->_C_deallocate(__c, 1);
break;
}
case __detail::_S_function:
_Rope_RopeFunction<_CharT, _Alloc>* __f
= (_Rope_RopeFunction<_CharT, _Alloc>*)this;
__f->_Rope_RopeFunction<_CharT, _Alloc>::~_Rope_RopeFunction();
- _F_deallocate(__f, 1);
+ this->_F_deallocate(__f, 1);
break;
}
case __detail::_S_substringfn:
(_Rope_RopeSubstring<_CharT, _Alloc>*)this;
__ss->_Rope_RopeSubstring<_CharT, _Alloc>::
~_Rope_RopeSubstring();
- _S_deallocate(__ss, 1);
+ this->_S_deallocate(__ss, 1);
break;
}
}
{
size_t __old_len = __r->_M_size;
_CharT* __new_data = (_CharT*)
- _Data_allocate(_S_rounded_up_size(__old_len + __len));
+ rope::_Data_allocate(_S_rounded_up_size(__old_len + __len));
_RopeLeaf* __result;
uninitialized_copy_n(__r->_M_data, __old_len, __new_data);
}
__catch(...)
{
- _C_deallocate(__result,1);
+ rope::_C_deallocate(__result,1);
__throw_exception_again;
}
// In case of exception, we need to deallocate
if (__result_len > __lazy_threshold)
goto lazy;
__section = (_CharT*)
- _Data_allocate(_S_rounded_up_size(__result_len));
+ rope::_Data_allocate(_S_rounded_up_size(__result_len));
__try
{ (*(__f->_M_fn))(__start, __result_len, __section); }
__catch(...)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ template<typename _MemberPointer>
+ class _Mem_fn;
+ template<typename _Tp, typename _Class>
+ _Mem_fn<_Tp _Class::*>
+ mem_fn(_Tp _Class::*);
+
_GLIBCXX_HAS_NESTED_TYPE(result_type)
/// If we have found a result_type, extract it.
// @} group functors
- template<typename _MemberPointer>
- class _Mem_fn;
-
/**
* Derives from @c unary_function or @c binary_function, or perhaps
* nothing, depending on the number of arguments provided. The
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
+ template<typename _Tp> _Tp __expint_E1(const _Tp);
+
/**
* @brief Return the exponential integral @f$ E_1(x) @f$
* by series summation. This should be good
template<typename _MemberPointer>
class _Mem_fn;
+ template<typename _Tp, typename _Class>
+ _Mem_fn<_Tp _Class::*>
+ mem_fn(_Tp _Class::*);
/**
* Actual implementation of _Has_result_type, which uses SFINAE to
// constructor or assignment operator of value_type throws.
if (!traits<container_type>::has_throwing_erase::value)
{
- _M_erasep(_M_container);
- _M_eraser(_M_container);
+ this->_M_erasep(_M_container);
+ this->_M_eraser(_M_container);
}
- _M_popf(_M_container);
- _M_popb(_M_container);
+ this->_M_popf(_M_container);
+ this->_M_popb(_M_container);
- _M_iops(_M_container);
- _M_ciops(_M_container);
+ this->_M_iops(_M_container);
+ this->_M_ciops(_M_container);
- _M_swap(_M_container);
+ this->_M_swap(_M_container);
// Last.
- _M_clear(_M_container);
+ this->_M_clear(_M_container);
}
}
};
modify(const_reference r_old, const_reference r_new)
{
erase(r_old);
- push(r_new);
+ this->push(r_new);
}
void
{
p[0] = char_type('s');
p[1] = char_type();
- setg(p, p, p + 1);
+ this->setg(p, p, p + 1);
}
virtual int_type underflow()