2016-11-15 Jason Merrill <jason@redhat.com>
+ PR c++/78358
+ * semantics.c (finish_decltype_type): Strip references for a tuple
+ decomposition.
+ * cp-tree.h (DECL_DECOMPOSITION_P): False for non-variables.
+
* decl2.c (decl_maybe_constant_var_p): References qualify.
* constexpr.c (non_const_var_error): Handle references.
* init.c (constant_value_1): Always check decl_constant_var_p.
(DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE))->u.base.var_declared_inline_p \
= true)
-/* Nonzero if NODE is the artificial VAR_DECL for decomposition
+/* Nonzero if NODE is an artificial VAR_DECL for a C++17 decomposition
declaration. */
#define DECL_DECOMPOSITION_P(NODE) \
- (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (NODE)) \
+ (VAR_P (NODE) && DECL_LANG_SPECIFIC (NODE) \
? DECL_LANG_SPECIFIC (NODE)->u.base.decomposition_p \
: false)
#define SET_DECL_DECOMPOSITION_P(NODE) \
if (identifier_p (expr))
expr = lookup_name (expr);
- /* The decltype rules for decomposition are different from the rules for
- member access; in particular, the decomposition decl gets
- cv-qualifiers from the aggregate object, whereas decltype of a member
- access expr ignores the object. */
- if (VAR_P (expr) && DECL_DECOMPOSITION_P (expr)
- && DECL_HAS_VALUE_EXPR_P (expr))
- return unlowered_expr_type (DECL_VALUE_EXPR (expr));
-
if (INDIRECT_REF_P (expr))
/* This can happen when the expression is, e.g., "a.b". Just
look at the underlying operand. */
/* See through BASELINK nodes to the underlying function. */
expr = BASELINK_FUNCTIONS (expr);
+ /* decltype of a decomposition name drops references in the tuple case
+ (unlike decltype of a normal variable) and keeps cv-qualifiers from
+ the containing object in the other cases (unlike decltype of a member
+ access expression). */
+ if (DECL_DECOMPOSITION_P (expr))
+ {
+ if (DECL_HAS_VALUE_EXPR_P (expr))
+ /* Expr is an array or struct subobject proxy, handle
+ bit-fields properly. */
+ return unlowered_expr_type (expr);
+ else
+ /* Expr is a reference variable for the tuple case. */
+ return non_reference (TREE_TYPE (expr));
+ }
+
switch (TREE_CODE (expr))
{
case FIELD_DECL:
--- /dev/null
+// PR c++/78358
+// { dg-do run }
+// { dg-options -std=c++1z }
+
+#include <tuple>
+
+template <typename, typename> struct same_type;
+template <typename T> struct same_type<T, T> {};
+
+int main() {
+ std::tuple tuple = { 1, 'a', 2.3, true };
+ auto[i, c, d, b] = tuple;
+ same_type<std::tuple_element<0, decltype(tuple)>::type, decltype(i)>{};
+ same_type<decltype(i), int>{};
+ same_type<decltype(c), char>{};
+ same_type<decltype(d), double>{};
+ same_type<decltype(b), bool>{};
+ if (i != 1 || c != 'a' || d != 2.3 || b != true)
+ __builtin_abort ();
+}