summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-20 03:25:26 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-11-20 03:25:26 +0000
commitc8a9f04cede6b53babac327d35d592b101c7896e (patch)
tree4e02eacae240a2fb6eb263ef634db37cd98148ac
parentb06698ce552743533d35fed2593277b1f541e39c (diff)
downloadgcc-c8a9f04cede6b53babac327d35d592b101c7896e.tar.gz
PR c++/56041
* cp-tree.h (struct processing_template_decl_sentinel): New. * pt.c (instantiate_non_dependent_expr_internal): Split out from... (instantiate_non_dependent_expr_sfinae): Here. (convert_nontype_argument): Use them. * constexpr.c (fold_non_dependent_expr): Use them. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@217823 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/constexpr.c13
-rw-r--r--gcc/cp/cp-tree.h23
-rw-r--r--gcc/cp/pt.c45
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-conv1.C34
5 files changed, 96 insertions, 26 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8f21d8b1146..09781410a19 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,12 @@
2014-11-19 Jason Merrill <jason@redhat.com>
+ PR c++/56041
+ * cp-tree.h (struct processing_template_decl_sentinel): New.
+ * pt.c (instantiate_non_dependent_expr_internal): Split out from...
+ (instantiate_non_dependent_expr_sfinae): Here.
+ (convert_nontype_argument): Use them.
+ * constexpr.c (fold_non_dependent_expr): Use them.
+
PR c++/63885
* constexpr.c (cxx_eval_constant_expression) [PARM_DECL]: Don't
complain yet about a reference.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 41867b8dc28..2678223a603 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3506,17 +3506,8 @@ fold_non_dependent_expr (tree t)
if (!instantiation_dependent_expression_p (t)
&& potential_constant_expression (t))
{
- HOST_WIDE_INT saved_processing_template_decl;
-
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- t = tsubst_copy_and_build (t,
- /*args=*/NULL_TREE,
- tf_none,
- /*in_decl=*/NULL_TREE,
- /*function_p=*/false,
- /*integral_constant_expression_p=*/true);
- processing_template_decl = saved_processing_template_decl;
+ processing_template_decl_sentinel s;
+ t = instantiate_non_dependent_expr_internal (t, tf_none);
if (type_unknown_p (t)
|| BRACE_ENCLOSED_INITIALIZER_P (t))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1e09629b4af..b3781ab7a72 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1082,6 +1082,8 @@ struct GTY(()) saved_scope {
struct saved_scope *prev;
};
+extern GTY(()) struct saved_scope *scope_chain;
+
/* The current open namespace. */
#define current_namespace scope_chain->old_namespace
@@ -1123,6 +1125,24 @@ struct GTY(()) saved_scope {
#define processing_specialization scope_chain->x_processing_specialization
#define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation
+/* RAII sentinel to handle clearing processing_template_decl and restoring
+ it when done. */
+
+struct processing_template_decl_sentinel
+{
+ int saved;
+ processing_template_decl_sentinel (bool reset = true)
+ : saved (processing_template_decl)
+ {
+ if (reset)
+ processing_template_decl = 0;
+ }
+ ~processing_template_decl_sentinel()
+ {
+ processing_template_decl = saved;
+ }
+};
+
/* The cached class binding level, from the most recently exited
class, or NULL if none. */
@@ -1140,8 +1160,6 @@ struct GTY(()) saved_scope {
/* A list of private types mentioned, for deferred access checking. */
-extern GTY(()) struct saved_scope *scope_chain;
-
struct GTY((for_user)) cxx_int_tree_map {
unsigned int uid;
tree to;
@@ -5716,6 +5734,7 @@ extern void make_args_non_dependent (vec<tree, va_gc> *);
extern bool reregister_specialization (tree, tree, tree);
extern tree instantiate_non_dependent_expr (tree);
extern tree instantiate_non_dependent_expr_sfinae (tree, tsubst_flags_t);
+extern tree instantiate_non_dependent_expr_internal (tree, tsubst_flags_t);
extern bool alias_type_or_template_p (tree);
extern bool alias_template_specialization_p (const_tree);
extern bool dependent_alias_template_spec_p (const_tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0b8fd7fd37f..05ca7062865 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5212,6 +5212,24 @@ redeclare_class_template (tree type, tree parms)
return true;
}
+/* 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))
+ and cleared processing_template_decl. */
+
+tree
+instantiate_non_dependent_expr_internal (tree expr, tsubst_flags_t complain)
+{
+ return tsubst_copy_and_build (expr,
+ /*args=*/NULL_TREE,
+ complain,
+ /*in_decl=*/NULL_TREE,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/true);
+}
+
/* Simplify EXPR if it is a non-dependent expression. Returns the
(possibly simplified) expression. */
@@ -5232,17 +5250,8 @@ instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
&& !instantiation_dependent_expression_p (expr)
&& potential_constant_expression (expr))
{
- HOST_WIDE_INT saved_processing_template_decl;
-
- saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- expr = tsubst_copy_and_build (expr,
- /*args=*/NULL_TREE,
- complain,
- /*in_decl=*/NULL_TREE,
- /*function_p=*/false,
- /*integral_constant_expression_p=*/true);
- processing_template_decl = saved_processing_template_decl;
+ processing_template_decl_sentinel s;
+ expr = instantiate_non_dependent_expr_internal (expr, complain);
}
return expr;
}
@@ -5736,11 +5745,15 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
so that access checking can be performed when the template is
instantiated -- but here we need the resolved form so that we can
convert the argument. */
+ bool non_dep = false;
if (TYPE_REF_OBJ_P (type)
&& has_value_dependent_address (expr))
/* If we want the address and it's value-dependent, don't fold. */;
- else if (!type_unknown_p (expr))
- expr = instantiate_non_dependent_expr_sfinae (expr, complain);
+ else if (!type_unknown_p (expr)
+ && processing_template_decl
+ && !instantiation_dependent_expression_p (expr)
+ && potential_constant_expression (expr))
+ non_dep = true;
if (error_operand_p (expr))
return error_mark_node;
expr_type = TREE_TYPE (expr);
@@ -5749,6 +5762,12 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
else
expr = mark_rvalue_use (expr);
+ /* If the argument is non-dependent, perform any conversions in
+ non-dependent context as well. */
+ processing_template_decl_sentinel s (non_dep);
+ if (non_dep)
+ expr = instantiate_non_dependent_expr_internal (expr, complain);
+
/* 14.3.2/5: The null pointer{,-to-member} conversion is applied
to a non-type argument of "nullptr". */
if (expr == nullptr_node && TYPE_PTR_OR_PTRMEM_P (type))
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-conv1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-conv1.C
new file mode 100644
index 00000000000..fd34f23f9ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-conv1.C
@@ -0,0 +1,34 @@
+// PR c++/56041
+// { dg-do compile { target c++11 } }
+
+template< class T, T v >
+struct integral_constant
+{
+ using type = integral_constant<T,v>;
+ using value_type = T;
+ static constexpr T value = v;
+ constexpr operator T ( ) noexcept { return value; }
+};
+
+using true_type = integral_constant<bool, true>;
+using false_type = integral_constant<bool, false>;
+
+template< bool b, class T = void > struct enable_if { using type = T; };
+template< class T > struct enable_if<false, T> { };
+
+
+template< class T,
+ class = typename enable_if< true_type{} // should compile; doesn't
+ , T>::type
+ >
+T try_it( ) { return T{}; }
+
+int main( )
+{
+ static_assert( true_type{} , "failed test 1!" );
+ static_assert( true_type{} , "failed test 2!" );
+ static_assert( ! false_type{} , "failed test 3!" );
+ static_assert( !! true_type{} , "failed test 4!" );
+
+ return try_it<int>();
+}