summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-04-24 07:30:51 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-04-24 07:30:51 +0200
commit430d1036e57ac7ce502079e245a01e3969c9e300 (patch)
tree0a1696cae1dc65d0d97218789e715d76bb448a14
parent1e653e1b10f19454cd2dac621fd5bb1f19a7aeac (diff)
Reimplement has_lt_operator check without full instantiation
The full instantiation caused a segfault in certain cases with GCC 11.4.0 from Ubuntu 22.04 (but not from Debian).
-rw-r--r--odb/odb/odb.cxx33
-rw-r--r--odb/odb/validator.cxx5
2 files changed, 32 insertions, 6 deletions
diff --git a/odb/odb/odb.cxx b/odb/odb/odb.cxx
index 701f6e1..39079ea 100644
--- a/odb/odb/odb.cxx
+++ b/odb/odb/odb.cxx
@@ -981,13 +981,34 @@ main (int argc, char* argv[])
// operator< test, used in validator.
//
+ // Note that typeof() cannot be used in the function signature
+ // directly so we have to go though lt_operator_type. This means
+ // we get diagnostics from the compiler (followed by ours) but
+ // it's doesn't look bad plus C++98 support is on its way out.
+ //
os << "template <typename T>" << endl
- << "bool" << endl
- << "has_lt_operator (const T& x, const T& y)" << endl
- << "{" << endl
- << "bool r (x < y);" << endl
- << "return r;" << endl
- << "}" << endl;
+ << "const T&" << endl
+ << "instance ();" << endl
+ << endl;
+
+ if (ops.std () == cxx_version::cxx98)
+ {
+ os << "template <typename T>" << endl
+ << "struct lt_operator_type" << endl
+ << "{" << endl
+ << "typedef __typeof__ (instance<T> () < instance<T> ()) R;" << endl
+ << "};" << endl
+ << endl
+ << "template <typename T>" << endl
+ << "typename lt_operator_type<T>::R" << endl
+ << "has_lt_operator ();" << endl;
+ }
+ else
+ {
+ os << "template <typename T>" << endl
+ << "decltype (instance<T> () < instance<T> ())" << endl
+ << "has_lt_operator ();" << endl;
+ }
os << "}" << endl
<< "}" << endl;
diff --git a/odb/odb/validator.cxx b/odb/odb/validator.cxx
index bf9aa6b..aa45294 100644
--- a/odb/odb/validator.cxx
+++ b/odb/odb/validator.cxx
@@ -1644,6 +1644,10 @@ namespace
bool v (inst != error_mark_node);
+ // Old version of has_lt_operator() relied on full instantiation
+ // while the new one is based on SFINAE.
+ //
+#if 0
if (v &&
DECL_TEMPLATE_INSTANTIATION (inst) &&
!DECL_TEMPLATE_INSTANTIATED (inst))
@@ -1667,6 +1671,7 @@ namespace
global_dc->printer->buffer->stream = s;
v = (ec == errorcount);
}
+#endif
if (!v)
{