gcc_assert (concept_check_p (check));
+ /* We don't want any declarations instantiated from a concept evaluation
+ to enter the binding table for the current scope, such as lambdas, so
+ leave that scope. But maintain the access context (PR104111). */
+ tree scope = current_scope ();
+ if (CLASS_TYPE_P (scope))
+ scope = TYPE_MAIN_DECL (scope);
+ else if (TREE_CODE (scope) != FUNCTION_DECL)
+ scope = NULL_TREE;
+
+ push_to_top_level ();
+ if (scope)
+ push_access_scope (scope);
+
/* Check for satisfaction without diagnostics. */
sat_info quiet (tf_none, NULL_TREE);
- return constraint_satisfaction_value (check, /*args=*/NULL_TREE, quiet);
+ tree r = constraint_satisfaction_value (check, /*args=*/NULL_TREE, quiet);
+
+ if (scope)
+ pop_access_scope (scope);
+ pop_from_top_level ();
+ return r;
}
/* Evaluate the requires-expression T, returning either boolean_true_node
return error_mark_node;
}
- if (LAMBDA_EXPR_EXTRA_SCOPE (t))
+ if (LAMBDA_EXPR_EXTRA_SCOPE (t)
+ /* When evaluating a concept we instantiate any lambda bodies
+ in the context of the evaluation. For ABI reasons don't
+ record a scope for this instantiated lambda so we don't
+ throw off the scope counter. */
+ && TREE_CODE (LAMBDA_EXPR_EXTRA_SCOPE (t)) != CONCEPT_DECL)
record_lambda_scope (r);
if (TYPE_NAMESPACE_SCOPE_P (TREE_TYPE (t)))
/* If we're pushed into another scope (PR105652), fix it. */
--- /dev/null
+// PR c++/123075
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fkeep-inline-functions" }
+
+template <typename T>
+concept r = []{ return true; }();
+
+template <typename T, typename U>
+inline auto foo() {
+ static_assert(r<T>);
+ r<U>;
+ return []{ return false; };
+}
+
+template <typename T>
+struct S {
+ static_assert(r<T>);
+ decltype([]{ return true; }) l;
+};
+S<char> s;
+
+bool use = (foo<int, double>()() || s.l());
+
+// There should only be one lambda keyed to 'foo()' and 'S::l'
+// { dg-final { scan-assembler {_ZZ3fooIidEDavENKUlvE_clEv:} } }
+// { dg-final { scan-assembler {_ZNK1SIcEUlvE_clEv:} } }
+// { dg-final { scan-assembler-not {_ZZ3fooIidEDavENKUlvE0_clEv:} } }
+// { dg-final { scan-assembler-not {_ZNK1SIcEUlvE0_clEv:} } }
--- /dev/null
+// PR c++/123075
+
+template <typename T>
+concept r = []{ return true; }();
+
+template <typename T>
+inline void foo() {
+ static_assert(r<T>);
+}
+
+template void foo<int>();
+
+template <typename T>
+struct S {
+ static_assert(r<T>);
+};
+
+template struct S<double>;
+
+enum E {
+ X = r<E>,
+};
--- /dev/null
+// PR c++/123075
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#include "lambda-13.h"
--- /dev/null
+// PR c++/123075
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-fmodules -fno-module-lazy" }
+
+#include "lambda-13.h"
+import "lambda-13_a.H";