Commit 3ad6a8e1 by Douglas Gregor Committed by Doug Gregor

typeck.c (structural_comptypes): Compare DECLTYPE_TYPE nodes.

2007-07-27  Douglas Gregor  <doug.gregor@gmail.com>

	* typeck.c (structural_comptypes): Compare DECLTYPE_TYPE nodes.
	* cp-tree.def (DECLTYPE_TYPE): New.
	* error.c (dump_type): Dump DECLTYPE_TYPE nodes.
	(dump_type_prefix): Ditto.
	(dump_type_suffix): Ditto.
	* tree.c (DECLTYPE_TYPE): Walk DECLTYPE_TYPE nodes.
	* mangle.c (write_type): Handle DECLTYPE_TYPE.
	* cp-tree.h (IS_AGGR_TYPE): DECLTYPE_TYPE nodes can be aggregate
	types.
	(DECLTYPE_TYPE_EXPR): New.
	(DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P): New.
	(finish_declared_type): Declare.
	* cxx-pretty-print.c (pp_cxx_type_specifier_seq): Print
	DECLTYPE_TYPE nodes.
	(pp_cxx_type_id): Ditto.
	* pt.c (for_each_template_parm_r): Walk DECLTYPE_TYPE children.
	(tsubst): Substitute into a DECLTYPE_TYPE node.
	(tsubst_copy): Ditto.
	(unify): Cannot deduce anything from TYPEOF_TYPE or DECLTYPE_TYPE
	nodes.
	(dependent_type_p_r): DECLTYPE_TYPE types are always dependent.
	* semantics.c (finish_typeof): TYPEOF_TYPE types need to use
	structural equality (because we can't hash the expressions).
	(finish_declared_type): New.
	* lex.c (reswords): Add "decltype" keyword.
	* parser.c cp_lexer_next_token_is_decl_specifier_keyword
	(cp_parser_postfix_expression): Add member_access_only_p to
	restrict postfix expression to member access expressions.
	(cp_parser_unary_expression): Update call to
	cp_parser_postfix_expression to reflect new parameter.
	(cp_parser_declared_type): New.
	(cp_parser_simple_type_specifier): Parse decltype types.

2007-07-27  Douglas Gregor  <doug.gregor@gmail.com>
	
       * c-common.h (enum rid): Add RID_DECLTYPE, update RID_LAST_CXX0X.

2007-07-27  Douglas Gregor  <doug.gregor@gmail.com>

	* g++.dg/cpp0x/decltype1.C: New.
	* g++.dg/cpp0x/decltype2.C: New.
	* g++.dg/cpp0x/decltype3.C: New.
	* g++.dg/cpp0x/decltype4.C: New.
	* g++.dg/cpp0x/decltype5.C: New.
	* g++.dg/cpp0x/decltype6.C: New.

From-SVN: r126991
parent 8a67955f
2007-07-27 Douglas Gregor <doug.gregor@gmail.com>
* c-common.h (enum rid): Add RID_DECLTYPE, update RID_LAST_CXX0X.
2007-07-26 Kenneth Zadeck <zadeck@naturalbridge.com>
PR middle-end/32749
......
......@@ -101,7 +101,7 @@ enum rid
RID_IS_UNION,
/* C++0x */
RID_STATIC_ASSERT,
RID_STATIC_ASSERT, RID_DECLTYPE,
/* Objective-C */
RID_AT_ENCODE, RID_AT_END,
......@@ -119,7 +119,7 @@ enum rid
RID_LAST_MODIFIER = RID_ONEWAY,
RID_FIRST_CXX0X = RID_STATIC_ASSERT,
RID_LAST_CXX0X = RID_STATIC_ASSERT,
RID_LAST_CXX0X = RID_DECLTYPE,
RID_FIRST_AT = RID_AT_ENCODE,
RID_LAST_AT = RID_AT_IMPLEMENTATION,
RID_FIRST_PQ = RID_IN,
......
2007-07-27 Douglas Gregor <doug.gregor@gmail.com>
* typeck.c (structural_comptypes): Compare DECLTYPE_TYPE nodes.
* cp-tree.def (DECLTYPE_TYPE): New.
* error.c (dump_type): Dump DECLTYPE_TYPE nodes.
(dump_type_prefix): Ditto.
(dump_type_suffix): Ditto.
* tree.c (DECLTYPE_TYPE): Walk DECLTYPE_TYPE nodes.
* mangle.c (write_type): Handle DECLTYPE_TYPE.
* cp-tree.h (IS_AGGR_TYPE): DECLTYPE_TYPE nodes can be aggregate
types.
(DECLTYPE_TYPE_EXPR): New.
(DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P): New.
(finish_declared_type): Declare.
* cxx-pretty-print.c (pp_cxx_type_specifier_seq): Print
DECLTYPE_TYPE nodes.
(pp_cxx_type_id): Ditto.
* pt.c (for_each_template_parm_r): Walk DECLTYPE_TYPE children.
(tsubst): Substitute into a DECLTYPE_TYPE node.
(tsubst_copy): Ditto.
(unify): Cannot deduce anything from TYPEOF_TYPE or DECLTYPE_TYPE
nodes.
(dependent_type_p_r): DECLTYPE_TYPE types are always dependent.
* semantics.c (finish_typeof): TYPEOF_TYPE types need to use
structural equality (because we can't hash the expressions).
(finish_declared_type): New.
* lex.c (reswords): Add "decltype" keyword.
* parser.c cp_lexer_next_token_is_decl_specifier_keyword
(cp_parser_postfix_expression): Add member_access_only_p to
restrict postfix expression to member access expressions.
(cp_parser_unary_expression): Update call to
cp_parser_postfix_expression to reflect new parameter.
(cp_parser_declared_type): New.
(cp_parser_simple_type_specifier): Parse decltype types.
2007-07-27 Mark Mitchell <mark@codesourcery.com>
PR c++/32346
......
......@@ -427,6 +427,13 @@ DEFTREECODE (ARGUMENT_PACK_SELECT, "argument_pack_select", tcc_exceptional, 0)
/* Represents a trait expression during template expansion. */
DEFTREECODE (TRAIT_EXPR, "trait_expr", tcc_exceptional, 0)
/* The declared type of an expression. This is a C++0x extension.
DECLTYPE_TYPE_EXPR is the expression whose type we are computing.
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P states whether the
expression was parsed as an id-expression or a member access
expression. When false, it was parsed as a full expression. */
DEFTREECODE (DECLTYPE_TYPE, "decltype_type", tcc_type, 0)
/*
Local variables:
mode:c
......
......@@ -977,6 +977,7 @@ enum languages { lang_c, lang_cplusplus, lang_java };
|| TREE_CODE (T) == TYPENAME_TYPE \
|| TREE_CODE (T) == TYPEOF_TYPE \
|| TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM \
|| TREE_CODE (T) == DECLTYPE_TYPE \
|| TYPE_LANG_FLAG_5 (T))
/* Set IS_AGGR_TYPE for T to VAL. T must be a class, struct, or
......@@ -2921,6 +2922,15 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
/* The expression in question for a TYPEOF_TYPE. */
#define TYPEOF_TYPE_EXPR(NODE) (TYPEOF_TYPE_CHECK (NODE))->type.values
/* The expression in question for a DECLTYPE_TYPE. */
#define DECLTYPE_TYPE_EXPR(NODE) (DECLTYPE_TYPE_CHECK (NODE))->type.values
/* Whether the DECLTYPE_TYPE_EXPR of NODE was originally parsed as an
id-expression or a member-access expression. When false, it was
parsed as a full expression. */
#define DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P(NODE) \
(DECLTYPE_TYPE_CHECK (NODE))->type.string_flag
/* Nonzero for VAR_DECL and FUNCTION_DECL node means that `extern' was
specified in its declaration. This can also be set for an
erroneously declared PARM_DECL. */
......@@ -4657,6 +4667,7 @@ extern bool cxx_omp_privatize_by_reference (tree);
extern tree baselink_for_fns (tree);
extern void finish_static_assert (tree, tree, location_t,
bool);
extern tree finish_decltype_type (tree, bool);
extern tree finish_trait_expr (enum cp_trait_kind, tree, tree);
/* in tree.c */
......
......@@ -1198,6 +1198,13 @@ pp_cxx_type_specifier_seq (cxx_pretty_printer *pp, tree t)
pp_cxx_nested_name_specifier (pp, TYPE_METHOD_BASETYPE (t));
break;
case DECLTYPE_TYPE:
pp_cxx_identifier (pp, "decltype");
pp_cxx_left_paren (pp);
pp_cxx_expression (pp, DECLTYPE_TYPE_EXPR (t));
pp_cxx_right_paren (pp);
break;
default:
if (!(TREE_CODE (t) == FUNCTION_DECL && DECL_CONSTRUCTOR_P (t)))
pp_c_specifier_qualifier_list (pp_c_base (pp), t);
......@@ -1581,6 +1588,7 @@ pp_cxx_type_id (cxx_pretty_printer *pp, tree t)
case TEMPLATE_PARM_INDEX:
case TEMPLATE_DECL:
case TYPEOF_TYPE:
case DECLTYPE_TYPE:
case TEMPLATE_ID_EXPR:
pp_cxx_type_specifier_seq (pp, t);
break;
......
......@@ -408,6 +408,14 @@ dump_type (tree t, int flags)
}
break;
case DECLTYPE_TYPE:
pp_cxx_identifier (cxx_pp, "decltype");
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
dump_expr (DECLTYPE_TYPE_EXPR (t), flags & ~TFF_EXPR_IN_PARENS);
pp_cxx_right_paren (cxx_pp);
break;
default:
pp_unsupported_tree (cxx_pp, t);
/* Fall through to error. */
......@@ -611,6 +619,7 @@ dump_type_prefix (tree t, int flags)
case COMPLEX_TYPE:
case VECTOR_TYPE:
case TYPEOF_TYPE:
case DECLTYPE_TYPE:
dump_type (t, flags);
pp_base (cxx_pp)->padding = pp_before;
break;
......@@ -707,6 +716,7 @@ dump_type_suffix (tree t, int flags)
case COMPLEX_TYPE:
case VECTOR_TYPE:
case TYPEOF_TYPE:
case DECLTYPE_TYPE:
break;
default:
......
......@@ -197,6 +197,7 @@ static const struct resword reswords[] =
{ "__complex__", RID_COMPLEX, 0 },
{ "__const", RID_CONST, 0 },
{ "__const__", RID_CONST, 0 },
{ "__decltype", RID_DECLTYPE, 0 },
{ "__extension__", RID_EXTENSION, 0 },
{ "__func__", RID_C99_FUNCTION_NAME, 0 },
{ "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, 0 },
......@@ -244,6 +245,7 @@ static const struct resword reswords[] =
{ "const", RID_CONST, 0 },
{ "const_cast", RID_CONSTCAST, 0 },
{ "continue", RID_CONTINUE, 0 },
{ "decltype", RID_DECLTYPE, D_CXX0X },
{ "default", RID_DEFAULT, 0 },
{ "delete", RID_DELETE, 0 },
{ "do", RID_DO, 0 },
......
......@@ -1544,6 +1544,9 @@ write_local_name (const tree function, const tree local_entity,
C++0x extensions
<type> ::= RR <type> # rvalue reference-to
<type> ::= Dt <expression> # decltype of an id-expression or
# class member access
<type> ::= DT <expression> # decltype of an expression
TYPE is a type node. */
......@@ -1674,6 +1677,16 @@ write_type (tree type)
write_type (PACK_EXPANSION_PATTERN (type));
break;
case DECLTYPE_TYPE:
write_char ('D');
if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type))
write_char ('t');
else
write_char ('T');
write_expression (DECLTYPE_TYPE_EXPR (type));
write_char ('E');
break;
default:
gcc_unreachable ();
}
......
......@@ -9058,6 +9058,22 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
complain);
}
case DECLTYPE_TYPE:
{
tree type;
type =
finish_decltype_type (tsubst_expr
(DECLTYPE_TYPE_EXPR (t), args,
complain, in_decl,
/*integral_constant_expression_p=*/false),
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t));
return cp_build_qualified_type_real (type,
cp_type_quals (t)
| cp_type_quals (type),
complain);
}
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
{
......@@ -9621,6 +9637,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case TYPENAME_TYPE:
case UNBOUND_CLASS_TEMPLATE:
case TYPEOF_TYPE:
case DECLTYPE_TYPE:
case TYPE_DECL:
return tsubst (t, args, complain, in_decl);
......@@ -12824,6 +12841,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
break;
case TYPEOF_TYPE:
case DECLTYPE_TYPE:
/* Cannot deduce anything from TYPEOF_TYPE or DECLTYPE_TYPE
nodes. */
return 0;
default:
gcc_assert (EXPR_P (parm));
......@@ -14888,10 +14911,11 @@ dependent_type_p_r (tree type)
(INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
return true;
/* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
expression is not type-dependent, then it should already been
have resolved. */
if (TREE_CODE (type) == TYPEOF_TYPE)
/* All TYPEOF_TYPEs and DECLTYPE_TYPEs are dependent; if the
argument of the `typeof' expression is not type-dependent, then
it should already been have resolved. */
if (TREE_CODE (type) == TYPEOF_TYPE
|| TREE_CODE (type) == DECLTYPE_TYPE)
return true;
/* A template argument pack is dependent if any of its packed
......
......@@ -2935,6 +2935,7 @@ finish_typeof (tree expr)
{
type = make_aggr_type (TYPEOF_TYPE);
TYPEOF_TYPE_EXPR (type) = expr;
SET_TYPE_STRUCTURAL_EQUALITY (type);
return type;
}
......@@ -4036,6 +4037,169 @@ finish_static_assert (tree condition, tree message, location_t location,
input_location = saved_loc;
}
}
/* Implements the C++0x decltype keyword. Returns the type of EXPR,
suitable for use as a type-specifier.
ID_EXPRESSION_OR_MEMBER_ACCESS_P is true when EXPR was parsed as an
id-expression or a class member access, FALSE when it was parsed as
a full expression. */
tree
finish_decltype_type (tree expr, bool id_expression_or_member_access_p)
{
tree orig_expr = expr;
tree type;
if (type_dependent_expression_p (expr))
{
type = make_aggr_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type)
= id_expression_or_member_access_p;
SET_TYPE_STRUCTURAL_EQUALITY (type);
return type;
}
/* The type denoted by decltype(e) is defined as follows: */
if (id_expression_or_member_access_p)
{
/* If e is an id-expression or a class member access (5.2.5
[expr.ref]), decltype(e) is defined as the type of the entity
named by e. If there is no such entity, or e names a set of
overloaded functions, the program is ill-formed. */
if (TREE_CODE (expr) == IDENTIFIER_NODE)
expr = lookup_name (expr);
if (TREE_CODE (expr) == INDIRECT_REF)
/* This can happen when the expression is, e.g., "a.b". Just
look at the underlying operand. */
expr = TREE_OPERAND (expr, 0);
if (TREE_CODE (expr) == OFFSET_REF
|| TREE_CODE (expr) == MEMBER_REF)
/* We're only interested in the field itself. If it is a
BASELINK, we will need to see through it in the next
step. */
expr = TREE_OPERAND (expr, 1);
if (TREE_CODE (expr) == BASELINK)
/* See through BASELINK nodes to the underlying functions. */
expr = BASELINK_FUNCTIONS (expr);
if (TREE_CODE (expr) == OVERLOAD)
{
if (OVL_CHAIN (expr))
{
error ("%qE refers to a set of overloaded functions", orig_expr);
return error_mark_node;
}
else
/* An overload set containing only one function: just look
at that function. */
expr = OVL_FUNCTION (expr);
}
switch (TREE_CODE (expr))
{
case FIELD_DECL:
if (DECL_C_BIT_FIELD (expr))
{
type = DECL_BIT_FIELD_TYPE (expr);
break;
}
/* Fall through for fields that aren't bitfields. */
case FUNCTION_DECL:
case VAR_DECL:
case CONST_DECL:
case PARM_DECL:
case RESULT_DECL:
type = TREE_TYPE (expr);
break;
case ERROR_MARK:
type = error_mark_node;
break;
case COMPONENT_REF:
type = is_bitfield_expr_with_lowered_type (expr);
if (!type)
type = TREE_TYPE (TREE_OPERAND (expr, 1));
break;
case BIT_FIELD_REF:
gcc_unreachable ();
case INTEGER_CST:
/* We can get here when the id-expression refers to an
enumerator. */
type = TREE_TYPE (expr);
break;
default:
gcc_assert (TYPE_P (expr) || DECL_P (expr));
error ("argument to decltype must be an expression");
return error_mark_node;
}
}
else
{
tree fndecl;
if (TREE_CODE (expr) == CALL_EXPR
&& (fndecl = get_callee_fndecl (expr))
&& (fndecl != error_mark_node))
/* If e is a function call (5.2.2 [expr.call]) or an
invocation of an overloaded operator (parentheses around e
are ignored), decltype(e) is defined as the return type of
that function. */
type = TREE_TYPE (TREE_TYPE (fndecl));
else
{
type = is_bitfield_expr_with_lowered_type (expr);
if (type)
{
/* Bitfields are special, because their type encodes the
number of bits they store. If the expression referenced a
bitfield, TYPE now has the declared type of that
bitfield. */
type = cp_build_qualified_type (type,
cp_type_quals (TREE_TYPE (expr)));
if (real_lvalue_p (expr))
type = build_reference_type (type);
}
else
{
/* Otherwise, where T is the type of e, if e is an lvalue,
decltype(e) is defined as T&, otherwise decltype(e) is
defined as T. */
type = TREE_TYPE (expr);
if (expr == current_class_ptr)
/* If the expression is just "this", we want the
cv-unqualified pointer for the "this" type. */
type = TYPE_MAIN_VARIANT (type);
else if (real_lvalue_p (expr))
{
if (TREE_CODE (type) != REFERENCE_TYPE)
type = build_reference_type (type);
}
else
type = non_reference (type);
}
}
}
if (!type || type == unknown_type_node)
{
error ("type of %qE is unknown", expr);
return error_mark_node;
}
return type;
}
/* Called from trait_expr_value to evaluate either __has_nothrow_assign or
__has_nothrow_copy, depending on assign_p. */
......
......@@ -2380,6 +2380,12 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
*walk_subtrees_p = 0;
break;
case DECLTYPE_TYPE:
WALK_SUBTREE (DECLTYPE_TYPE_EXPR (*tp));
*walk_subtrees_p = 0;
break;
default:
return NULL_TREE;
}
......
......@@ -1080,6 +1080,14 @@ structural_comptypes (tree t1, tree t2, int strict)
return same_type_p (PACK_EXPANSION_PATTERN (t1),
PACK_EXPANSION_PATTERN (t2));
case DECLTYPE_TYPE:
if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1)
!= DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t2)
|| !cp_tree_equal (DECLTYPE_TYPE_EXPR (t1),
DECLTYPE_TYPE_EXPR (t2)))
return false;
break;
default:
return false;
}
......
2007-07-27 Douglas Gregor <doug.gregor@gmail.com>
* g++.dg/cpp0x/decltype1.C: New.
* g++.dg/cpp0x/decltype2.C: New.
* g++.dg/cpp0x/decltype3.C: New.
* g++.dg/cpp0x/decltype4.C: New.
* g++.dg/cpp0x/decltype5.C: New.
* g++.dg/cpp0x/decltype6.C: New.
2007-07-27 Rask Ingemann Lambertsen <rask@sygehus.dk>
* gcc.dg/torture/pr27743.c (bar): Use an integer of exactly 32 bits
// { dg-do "compile" }
// { dg-options "-std=gnu++0x" }
template<typename T, typename U>
struct is_same
{
static const bool value = false;
};
template<typename T>
struct is_same<T, T>
{
static const bool value = true;
};
const int& foo();
int i;
struct A { double x; };
const A* a = new A();
static_assert(is_same<decltype(foo()), const int&>::value,
"type should be const int&");
static_assert(is_same<decltype(i), int>::value,
"type should be int");
static_assert(is_same<decltype(a->x), double>::value,
"type should be double");
static_assert(is_same<decltype((a->x)), const double&>::value,
"type should be const double&");
// { dg-do "compile" }
// { dg-options "-std=gnu++0x" }
template<typename T, typename U>
struct is_same
{
static const bool value = false;
};
template<typename T>
struct is_same<T, T>
{
static const bool value = true;
};
#define CHECK_DECLTYPE(DECLTYPE,RESULT) \
static_assert(is_same< DECLTYPE , RESULT >::value, #RESULT)
struct A {};
int a;
int& b = a;
const int& c = a;
const int d = 5;
const A e = A();
CHECK_DECLTYPE(decltype(a), int);
CHECK_DECLTYPE(decltype(b), int&);
CHECK_DECLTYPE(decltype(c), const int&);
CHECK_DECLTYPE(decltype(d), const int);
CHECK_DECLTYPE(decltype(e), const A);
CHECK_DECLTYPE(decltype(a), int);
CHECK_DECLTYPE(decltype((a)), int&);
void foo_check(int a, int& b, float& c, int* d)
{
CHECK_DECLTYPE(decltype(a), int);
CHECK_DECLTYPE(decltype(b), int&);
CHECK_DECLTYPE(decltype(c), float&);
CHECK_DECLTYPE(decltype(d), int*);
}
int foo(char);
int bar(char);
int bar(int);
CHECK_DECLTYPE(decltype(foo), int(char));
decltype(bar) z; // { dg-error "overload" }
// { dg-error "invalid type" "" { target *-*-* } 48 }
CHECK_DECLTYPE(decltype(&foo), int(*)(char));
CHECK_DECLTYPE(decltype(*&foo), int(&)(char));
void array_types()
{
int a[10];
CHECK_DECLTYPE(decltype(a), int[10]);
}
// { dg-do "compile" }
// { dg-options "-std=gnu++0x" }
template<typename T, typename U>
struct is_same
{
static const bool value = false;
};
template<typename T>
struct is_same<T, T>
{
static const bool value = true;
};
#define CHECK_DECLTYPE(DECLTYPE,RESULT) \
static_assert(is_same< DECLTYPE , RESULT >::value, #DECLTYPE " should be " #RESULT)
class A {
public:
int a;
int& b;
static int c;
A(int& b) : b(b) { }
void foo() {
CHECK_DECLTYPE(decltype(a), int);
CHECK_DECLTYPE(decltype(this->a), int);
CHECK_DECLTYPE(decltype((*this).a), int);
CHECK_DECLTYPE(decltype(b), int&);
CHECK_DECLTYPE(decltype(c), int);
}
void bar() const {
CHECK_DECLTYPE(decltype(a), int);
CHECK_DECLTYPE(decltype(b), int&);
CHECK_DECLTYPE(decltype(c), int);
}
};
int b;
A aa(b);
const A& caa = aa;
CHECK_DECLTYPE(decltype(aa.a), int);
CHECK_DECLTYPE(decltype(aa.b), int&);
CHECK_DECLTYPE(decltype(caa.a), int);
class B {
public:
int a; // { dg-error "invalid use" }
enum B_enum { b };
decltype(a) c; // { dg-error "from this location" }
decltype(a) foo() { } // { dg-error "from this location" }
decltype(b) enums_are_in_scope() { return b; } // ok
};
CHECK_DECLTYPE(decltype(aa.*&A::a), int&);
decltype(aa.*&A::b) zz; // { dg-error "cannot create pointer to reference member" }
// { dg-error "invalid type" "" { target *-*-* } 58 }
CHECK_DECLTYPE(decltype(caa.*&A::a), const int&);
class X {
void foo() {
CHECK_DECLTYPE(decltype(this), X*);
CHECK_DECLTYPE(decltype(*this), X&);
}
void bar() const {
CHECK_DECLTYPE(decltype(this), const X*);
CHECK_DECLTYPE(decltype(*this), const X&);
}
};
// { dg-do "compile" }
// { dg-options "-std=gnu++0x" }
template<typename T, typename U>
struct is_same
{
static const bool value = false;
};
template<typename T>
struct is_same<T, T>
{
static const bool value = true;
};
#define CHECK_DECLTYPE(DECLTYPE,RESULT) \
static_assert(is_same< DECLTYPE , RESULT >::value, #DECLTYPE " should be " #RESULT)
struct A {
int x;
int& y;
int foo(char);
int& bar() const;
};
CHECK_DECLTYPE(decltype(&A::x), int A::*);
decltype(&A::y) Ay; // { dg-error "cannot create pointer to reference member|invalid type" }
CHECK_DECLTYPE(decltype(&A::foo), int (A::*) (char));
CHECK_DECLTYPE(decltype(&A::bar), int& (A::*) () const);
CHECK_DECLTYPE(decltype("decltype"), const char(&)[9]);
CHECK_DECLTYPE(decltype(1), int);
int an_int = 5;
int& i = an_int;
const int j = an_int;
CHECK_DECLTYPE(decltype(i)&, int&);
CHECK_DECLTYPE(const decltype(j), const int);
int foo();
CHECK_DECLTYPE(decltype(foo()), int);
float& bar(int);
CHECK_DECLTYPE(decltype (bar(1)), float&);
const A bar();
CHECK_DECLTYPE(decltype (bar()), const A);
const A& bar2();
CHECK_DECLTYPE(decltype (bar2()), const A&);
void wibble() {
CHECK_DECLTYPE(decltype(1+2), int);
int* p;
CHECK_DECLTYPE(decltype(*p), int&);
int a[10];
CHECK_DECLTYPE(decltype(a[3]), int&);
int i; int& j = i;
CHECK_DECLTYPE(decltype (i = 5), int&);
CHECK_DECLTYPE(decltype (j = 5), int&);
CHECK_DECLTYPE(decltype (++i), int&);
CHECK_DECLTYPE(decltype (i++), int);
}
struct B {
int bit : 2;
const int cbit : 3;
void foo()
{
CHECK_DECLTYPE(decltype(bit), int);
CHECK_DECLTYPE(decltype((bit)), int&);
CHECK_DECLTYPE(decltype(cbit), const int);
CHECK_DECLTYPE(decltype((cbit)), const int&); // { dg-bogus "static assertion failed" "GCC gets the actual type of this expression wrong" { xfail *-*-* } 73 }
}
};
B b;
const B& bc = b;
CHECK_DECLTYPE(decltype(b.bit), int);
CHECK_DECLTYPE(decltype(bc.bit), int);
CHECK_DECLTYPE(decltype((b.bit)), int&);
CHECK_DECLTYPE(decltype((bc.bit)), const int&);
// { dg-do "compile" }
// { dg-options "-std=gnu++0x" }
template<typename T, typename U>
struct is_same
{
static const bool value = false;
};
template<typename T>
struct is_same<T, T>
{
static const bool value = true;
};
#define CHECK_DECLTYPE(DECLTYPE,RESULT) \
static_assert(is_same< DECLTYPE , RESULT >::value, #RESULT)
template<typename F> F create_a();
template<typename F, typename T1>
decltype(create_a<F&>()(create_a<const T1&>())) forward(F f, const T1& a1)
{
return f(a1);
}
struct identity {
template<typename T>
const T& operator()(const T& x) { return x; }
};
identity id;
int i;
float f;
CHECK_DECLTYPE(decltype(forward(id, i)), const int&);
CHECK_DECLTYPE(decltype(forward(id, f)), const float&);
// { dg-do "compile" }
// { dg-options "-std=gnu++0x" }
template<typename T, typename U>
struct is_same
{
static const bool value = false;
};
template<typename T>
struct is_same<T, T>
{
static const bool value = true;
};
template<typename T> const T& foo();
int i;
template<typename T>
struct A
{
double x;
};
const A<double>* a = new A<double>();
static_assert(is_same<decltype(foo<int>()), const int&>::value,
"type should be const int&");
static_assert(is_same<decltype(i), int>::value,
"type should be int");
static_assert(is_same<decltype(a->x), double>::value,
"type should be double");
static_assert(is_same<decltype((a->x)), const double&>::value,
"type should be const double&");
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment