if (check_for_bare_parameter_packs (expr))
return error_mark_node;
if (TREE_CODE (expr) != DEFERRED_NOEXCEPT
- && !value_dependent_expression_p (expr))
+ && !instantiation_dependent_expression_p (expr))
{
expr = build_converted_constant_bool_expr (expr, complain);
expr = instantiate_non_dependent_expr_sfinae (expr, complain);
static cp_expr
cp_parser_parenthesized_expression_list_elt (cp_parser *parser, bool cast_p,
bool allow_expansion_p,
- bool fold_expr_p,
bool *non_constant_p)
{
cp_expr expr (NULL_TREE);
else
expr = cp_parser_assignment_expression (parser, /*pidk=*/NULL, cast_p);
- if (fold_expr_p)
- expr = instantiate_non_dependent_expr (expr);
-
/* If we have an ellipsis, then this is an expression expansion. */
if (allow_expansion_p
&& cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
false,
/*allow_exp_p=*/
true,
- /*fold_expr_p=*/
- false,
/*non_cst_p=*/
NULL);
bool wrap_locations_p)
{
vec<tree, va_gc> *expression_list;
- bool fold_expr_p = is_attribute_list != non_attr;
tree identifier = NULL_TREE;
bool saved_greater_than_is_operator_p;
expr
= cp_parser_parenthesized_expression_list_elt (parser, cast_p,
allow_expansion_p,
- fold_expr_p,
non_constant_p);
if (wrap_locations_p)
tree hi = tsubst_copy_and_build (ohi, args, complain, in_decl,
false/*fn*/, true/*int_cst*/);
- if (value_dependent_expression_p (hi))
+ if (instantiation_dependent_expression_p (hi))
{
if (hi != ohi)
{
/* The actual substitution part of instantiate_non_dependent_expr_sfinae,
to be used when the caller has already checked
- (processing_template_decl
- && !instantiation_dependent_expression_p (expr)
- && potential_constant_expression (expr))
+ !instantiation_dependent_uneval_expression_p (expr)
and cleared processing_template_decl. */
tree
/*integral_constant_expression_p=*/true);
}
-/* Simplify EXPR if it is a non-dependent expression. Returns the
- (possibly simplified) expression. */
+/* Instantiate the non-dependent expression EXPR. */
tree
instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
if (expr == NULL_TREE)
return NULL_TREE;
- /* If we're in a template, but EXPR isn't value dependent, simplify
- it. We're supposed to treat:
-
- template <typename T> void f(T[1 + 1]);
- template <typename T> void f(T[2]);
-
- as two declarations of the same function, for example. */
- if (processing_template_decl
- && is_nondependent_constant_expression (expr))
+ if (processing_template_decl)
{
+ /* The caller should have checked this already. */
+ gcc_checking_assert (!instantiation_dependent_uneval_expression_p (expr));
processing_template_decl_sentinel s;
expr = instantiate_non_dependent_expr_internal (expr, complain);
}
return instantiate_non_dependent_expr_sfinae (expr, tf_error);
}
-/* Like instantiate_non_dependent_expr, but return NULL_TREE rather than
- an uninstantiated expression. */
+/* Like instantiate_non_dependent_expr, but return NULL_TREE if the
+ expression is dependent or non-constant. */
tree
instantiate_non_dependent_or_null (tree expr)
/* decltype is an unevaluated context. */
cp_unevaluated u;
+ processing_template_decl_sentinel ptds (/*reset=*/false);
+
/* Depending on the resolution of DR 1172, we may later need to distinguish
instantiation-dependent but not type-dependent expressions so that, say,
A<decltype(sizeof(T))>::U doesn't require 'typename'. */
expr = instantiate_non_dependent_expr_sfinae (expr, complain);
if (expr == error_mark_node)
return error_mark_node;
+ /* Keep processing_template_decl cleared for the rest of the function
+ (for sake of the call to lvalue_kind below, which handles templated
+ and non-templated COND_EXPR differently). */
+ processing_template_decl = 0;
}
/* The type denoted by decltype(e) is defined as follows: */
--- /dev/null
+// PR c++/104823
+// { dg-do compile { target c++11 } }
+
+struct S { S(int); };
+double id(double);
+template<class> auto f(double v) -> decltype(S{id(v)}); // { dg-error "narrowing" }
--- /dev/null
+// Verify we correctly handle the non-dependent attribute expression which
+// which we used to reject due to double folding.
+// { dg-do compile { target { c++11 } } }
+
+struct A {
+ constexpr int f() const { return __alignof__(int); };
+};
+
+template<class...>
+void f() {
+ int a __attribute__((aligned(A{}.f())));
+}
+
+template void f();