aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2019-02-08 14:49:58 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2019-02-08 14:49:58 +0000
commit2a97dfc988a695e44f759099f74e4a18c01fa9a5 (patch)
treea99d997fc75cef2fe2d7d6f97c8cfa6d6492b017
parentb9f36e31dfed155959f17dcc85ba7cd09fe13fd6 (diff)
PR c++/88752 - ICE with lambda and constexpr if.
* cp-tree.h (LAMBDA_EXPR_INSTANTIATED): New. * pt.c (tsubst_lambda_expr): Set it. (instantiated_lambda_fn_p): Check it. (enclosing_instantiation_of): Use it. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-8-branch@268701 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/pt.c22
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/constexpr-if26.C28
4 files changed, 60 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6dc807a938a..e0cff40cfa2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2019-02-08 Jason Merrill <jason@redhat.com>
+ PR c++/88752 - ICE with lambda and constexpr if.
+ * cp-tree.h (LAMBDA_EXPR_INSTANTIATED): New.
+ * pt.c (tsubst_lambda_expr): Set it.
+ (instantiated_lambda_fn_p): Check it.
+ (enclosing_instantiation_of): Use it.
+
PR c++/86943 - wrong code converting generic lambda to pointer.
* pt.c (tsubst_copy_and_build): Don't propagate CALL_FROM_THUNK_P.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 0f24b4fc945..f15b74279a2 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -416,6 +416,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE)
CONSTRUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR)
OVL_NESTED_P (in OVERLOAD)
+ LAMBDA_EXPR_INSTANTIATED (in LAMBDA_EXPR)
4: IDENTIFIER_MARKED (IDENTIFIER_NODEs)
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
CALL_EXPR, or FIELD_DECL).
@@ -1272,6 +1273,10 @@ enum cp_lambda_default_capture_mode_type {
#define LAMBDA_EXPR_CAPTURE_OPTIMIZED(NODE) \
TREE_LANG_FLAG_2 (LAMBDA_EXPR_CHECK (NODE))
+/* True iff this LAMBDA_EXPR was generated in tsubst_lambda_expr. */
+#define LAMBDA_EXPR_INSTANTIATED(NODE) \
+ TREE_LANG_FLAG_3 (LAMBDA_EXPR_CHECK (NODE))
+
/* True if this TREE_LIST in LAMBDA_EXPR_CAPTURE_LIST is for an explicit
capture. */
#define LAMBDA_CAPTURE_EXPLICIT_P(NODE) \
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 93177ac0893..aa57811d7b7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -13269,6 +13269,19 @@ lambda_fn_in_template_p (tree fn)
return CLASSTYPE_TEMPLATE_INFO (closure) != NULL_TREE;
}
+/* True if FN is the substitution (via tsubst_lambda_expr) of a function for
+ which the above is true. */
+
+bool
+instantiated_lambda_fn_p (tree fn)
+{
+ if (!fn || !LAMBDA_FUNCTION_P (fn))
+ return false;
+ tree closure = DECL_CONTEXT (fn);
+ tree lam = CLASSTYPE_LAMBDA_EXPR (closure);
+ return LAMBDA_EXPR_INSTANTIATED (lam);
+}
+
/* We're instantiating a variable from template function TCTX. Return the
corresponding current enclosing scope. This gets complicated because lambda
functions in templates are regenerated rather than instantiated, but generic
@@ -13288,13 +13301,19 @@ enclosing_instantiation_of (tree otctx)
{
tree ofn = fn;
int flambda_count = 0;
- for (; flambda_count < lambda_count && fn && LAMBDA_FUNCTION_P (fn);
+ for (; fn && instantiated_lambda_fn_p (fn);
fn = decl_function_context (fn))
++flambda_count;
if ((fn && DECL_TEMPLATE_INFO (fn))
? most_general_template (fn) != most_general_template (tctx)
: fn != tctx)
continue;
+ if (flambda_count != lambda_count)
+ {
+ gcc_assert (flambda_count > lambda_count);
+ for (; flambda_count > lambda_count; --flambda_count)
+ ofn = decl_function_context (ofn);
+ }
gcc_assert (DECL_NAME (ofn) == DECL_NAME (otctx)
|| DECL_CONV_FN_P (ofn));
return ofn;
@@ -17560,6 +17579,7 @@ tsubst_lambda_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (r)
= LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (t);
LAMBDA_EXPR_MUTABLE_P (r) = LAMBDA_EXPR_MUTABLE_P (t);
+ LAMBDA_EXPR_INSTANTIATED (r) = true;
if (LAMBDA_EXPR_EXTRA_SCOPE (t) == NULL_TREE)
/* A lambda in a default argument outside a class gets no
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if26.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if26.C
new file mode 100644
index 00000000000..e85dcdc7f77
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if26.C
@@ -0,0 +1,28 @@
+// PR c++/88752
+// { dg-do compile { target c++17 } }
+
+template <int a> struct b { static constexpr int c = a; };
+class d;
+template <typename> struct e { typedef d f; };
+template <typename g> using h = typename e<g>::f;
+template <typename> constexpr bool i = b<true>::c;
+class d {
+public:
+ using j = float;
+};
+template <typename> void k();
+int main() { k<d>(); }
+template <class l> l m;
+template <class, class r> void n(r o) {
+ [](int) {}(o(m<d>));
+}
+template <typename> void k() {
+ n<int>([](auto inputs) {
+ auto p(inputs);
+ using s = h<decltype(p)>;
+ s q;
+ if constexpr (i<typename s::j>)
+ [&] { return q; }();
+ return 42;
+ });
+}