===================================================================
@@ -11781,11 +11781,12 @@ tsubst (tree t, tree args, tsubst_flags_t complain
case DECLTYPE_TYPE:
{
tree type;
+ tree expr = DECLTYPE_TYPE_EXPR (t);
++cp_unevaluated_operand;
++c_inhibit_evaluation_warnings;
- type = tsubst_copy_and_build (DECLTYPE_TYPE_EXPR (t), args,
+ type = tsubst_copy_and_build (expr, args,
complain|tf_decltype, in_decl,
/*function_p*/false,
/*integral_constant_expression*/false);
@@ -11801,12 +11802,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain
else
{
bool id = DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t);
- if (id && TREE_CODE (DECLTYPE_TYPE_EXPR (t)) == BIT_NOT_EXPR
- && EXPR_P (type))
- /* In a template ~id could be either a complement expression
- or an unqualified-id naming a destructor; if instantiating
- it produces an expression, it's not an id-expression or
- member access. */
+ /* In a template ~id could be either a complement expression
+ or an unqualified-id naming a destructor; if instantiating
+ it produces an expression, it's not an id-expression or
+ member access. Likewise, if a COMPONENT_REF becomes upon
+ instantiation a COMPOUND_EXPR, it's actually a static data
+ member. */
+ if (id && ((TREE_CODE (expr) == BIT_NOT_EXPR
+ && EXPR_P (type))
+ || (TREE_CODE (expr) == COMPONENT_REF
+ && TREE_CODE (type) == COMPOUND_EXPR)))
id = false;
type = finish_decltype_type (type, id, complain);
}
===================================================================
@@ -0,0 +1,39 @@
+// PR c++/56450
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+T&& declval();
+
+template<bool, typename T = void>
+struct enable_if { };
+
+template<typename T>
+struct enable_if<true, T>
+{ typedef T type; };
+
+template<typename, typename>
+struct is_same
+{ static constexpr bool value = false; };
+
+template<typename T>
+struct is_same<T, T>
+{ static constexpr bool value = true; };
+
+template< typename, typename = void >
+struct has_const_int_dummy
+{ static constexpr bool value = false; };
+
+template< typename T >
+struct has_const_int_dummy< T, typename enable_if< is_same< decltype(
+declval< T >().dummy ), const int >::value >::type >
+{ static constexpr bool value = true; };
+
+struct A0 { const int dummy; };
+struct A1 {};
+struct A2 { int dummy(); };
+struct A3 { static const int dummy = 0; };
+
+static_assert( has_const_int_dummy< A0 >::value, "A0" );
+static_assert( !has_const_int_dummy< A1 >::value, "A1" );
+static_assert( !has_const_int_dummy< A2 >::value, "A2" );
+static_assert( !has_const_int_dummy< A3 >::value, "A3" ); // ICE