summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Chimento <philip.chimento@gmail.com>2019-12-11 17:55:11 -0800
committerPhilip Chimento <philip.chimento@gmail.com>2019-12-16 15:39:34 -0500
commit5ff697b4d9d173f1c131811b0c30b4eeb3dbc26d (patch)
treec9ffa38e39d7a0734ce9e5a6a588e7fc5c0c7c4c
parent737bbd25665b7993604d0ceda35184aea6a264ac (diff)
clang-plugin: Support LLVM 8.0
The main API difference between Clang 7 and 8 that is relevant to us is the rename of Expr::getLocStart() and Decl::getLocStart() to getBeginLoc().
-rw-r--r--clang-plugin/gerror-checker.cpp2
-rw-r--r--clang-plugin/gir-attributes.cpp14
-rw-r--r--clang-plugin/gsignal-checker.cpp100
-rw-r--r--clang-plugin/gvariant-checker.cpp144
-rw-r--r--clang-plugin/nullability-checker.cpp49
-rw-r--r--clang-plugin/plugin.cpp10
-rw-r--r--configure.ac5
7 files changed, 281 insertions, 43 deletions
diff --git a/clang-plugin/gerror-checker.cpp b/clang-plugin/gerror-checker.cpp
index 5d12fa4..8301a44 100644
--- a/clang-plugin/gerror-checker.cpp
+++ b/clang-plugin/gerror-checker.cpp
@@ -616,9 +616,11 @@ void
GErrorChecker::checkDeadSymbols (SymbolReaper &symbol_reaper,
CheckerContext &context) const
{
+#ifndef HAVE_LLVM_8_0
if (!symbol_reaper.hasDeadSymbols ()) {
return;
}
+#endif
ProgramStateRef state = context.getState ();
diff --git a/clang-plugin/gir-attributes.cpp b/clang-plugin/gir-attributes.cpp
index d38e515..49dd9ae 100644
--- a/clang-plugin/gir-attributes.cpp
+++ b/clang-plugin/gir-attributes.cpp
@@ -442,7 +442,12 @@ GirAttributesChecker::_handle_function_decl (FunctionDecl& func)
"return value of function %0() (already has a "
"const modifier).",
this->_compiler,
- func.getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ func.getBeginLoc ()
+#else
+ func.getLocStart ()
+#endif
+ )
<< func.getNameAsString ();
} else if (return_transfer == GI_TRANSFER_NOTHING &&
_type_should_be_const (return_transfer,
@@ -453,7 +458,12 @@ GirAttributesChecker::_handle_function_decl (FunctionDecl& func)
"function %0() (already has a (transfer none) "
"annotation).",
this->_compiler,
- func.getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ func.getBeginLoc ()
+#else
+ func.getLocStart ()
+#endif
+ )
<< func.getNameAsString ();
}
diff --git a/clang-plugin/gsignal-checker.cpp b/clang-plugin/gsignal-checker.cpp
index 74db5c4..5f7dfda 100644
--- a/clang-plugin/gsignal-checker.cpp
+++ b/clang-plugin/gsignal-checker.cpp
@@ -579,6 +579,7 @@ _is_gtype_subclass (GIBaseInfo *a, GIBaseInfo *b)
* MSVC++), so we cannot use C++ methods for callbacks with swapped
* parameters.
* • Microsoft vectorcall: Same.
+ * - aarch64: vectorcall is assumed to be unsafe as it is on x86.
*
* References:
* [1]: http://en.wikipedia.org/wiki/X86_calling_conventions
@@ -631,6 +632,9 @@ calling_convention_is_safe (CallingConv conv)
case CC_X86ThisCall:
case CC_X86Pascal:
case CC_X86VectorCall:
+#ifdef HAVE_LLVM_8_0
+ case CC_AArch64VectorCall:
+#endif
return false;
case CC_IntelOclBicc:
/* Intel OpenCL Built-Ins. I can’t find any documentation about
@@ -696,7 +700,13 @@ _check_signal_callback_type (const Expr *expr,
"for signal ‘%0::%1’. Callback "
"function declaration does not "
"contain parameter types.",
- compiler, expr->getLocStart ())
+ compiler,
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
<< decl_range;
@@ -783,7 +793,13 @@ _check_signal_callback_type (const Expr *expr,
Debug::emit_error ("Incorrect number of arguments in signal "
"handler for signal ‘%0::%1’. Expected %2 "
"but saw %3.",
- compiler, expr->getLocStart ())
+ compiler,
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
<< n_signal_args
@@ -843,7 +859,12 @@ _check_signal_callback_type (const Expr *expr,
"signal ‘%1::%2’. Cannot "
"find type with name "
"‘%3’.", compiler,
- expr->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< arg_name
<< c_type
<< g_base_info_get_name (signal_info)
@@ -894,7 +915,12 @@ _check_signal_callback_type (const Expr *expr,
"for signal ‘%1::%2’. It "
"should be ‘%3’ but is "
"currently ‘%4’.", compiler,
- expr->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< arg_name
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
@@ -908,7 +934,12 @@ _check_signal_callback_type (const Expr *expr,
"for signal ‘%1::%2’. It "
"should be ‘%3’ but is "
"currently ‘%4’.", compiler,
- expr->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< arg_name
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
@@ -972,7 +1003,12 @@ _check_signal_callback_type (const Expr *expr,
"signal ‘%1::%2’. Cannot "
"find type with name "
"‘%3’.", compiler,
- expr->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< arg_name
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
@@ -1003,7 +1039,12 @@ _check_signal_callback_type (const Expr *expr,
"in swapped signal handler for "
"signal ‘%1::%2’. Expected ‘%3’ but "
"saw ‘%4’.", compiler,
- expr->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< arg_name
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
@@ -1020,7 +1061,12 @@ _check_signal_callback_type (const Expr *expr,
"in signal handler for signal "
"‘%1::%2’. Expected ‘%3’ but saw "
"‘%4’.", compiler,
- expr->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< arg_name
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
@@ -1044,7 +1090,12 @@ _check_signal_callback_type (const Expr *expr,
Debug::emit_warning ("Failed to resolve return type in signal "
"handler for signal ‘%0::%1’. Cannot find "
"type with name ‘%2’.", compiler,
- expr->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
<< g_base_info_get_name (&expected_type_info)
@@ -1059,7 +1110,13 @@ _check_signal_callback_type (const Expr *expr,
/* TODO: Emit expected type of signal callback? */
Debug::emit_error ("Incorrect return type from signal handler "
"for signal ‘%0::%1’. Expected ‘%2’ but saw "
- "‘%3’.", compiler, expr->getLocStart ())
+ "‘%3’.", compiler,
+#ifdef HAVE_LLVM_8_0
+ expr->getBeginLoc ()
+#else
+ expr->getLocStart ()
+#endif
+ )
<< gir_manager.get_c_name_for_type (static_instance_info)
<< g_base_info_get_name (signal_info)
<< expected_type.getAsString ()
@@ -1219,7 +1276,13 @@ _check_gsignal_callback_type (const CallExpr &call,
Debug::emit_warning ("Non-string literal passed to signal "
"name parameter. This is not an error "
"but is highly unusual.",
- compiler, signal_name_arg->getLocStart ());
+ compiler,
+#ifdef HAVE_LLVM_8_0
+ signal_name_arg->getBeginLoc ()
+#else
+ signal_name_arg->getLocStart ()
+#endif
+ );
return false;
}
@@ -1258,7 +1321,12 @@ _check_gsignal_callback_type (const CallExpr &call,
"%1() to the specific class defining the "
"signal. Ensure a GIR file defining that "
"class is loaded.", compiler,
- call.getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ call.getBeginLoc ()
+#else
+ call.getLocStart ()
+#endif
+ )
<< signal_name
<< func_info->func_name
<< gobject_arg->getSourceRange ()
@@ -1289,7 +1357,13 @@ _check_gsignal_callback_type (const CallExpr &call,
"typecast to the GObject parameter of "
"%2() to the specific class defining the "
"signal. Ensure a GIR file defining that "
- "class is loaded.", compiler, call.getLocStart ())
+ "class is loaded.", compiler,
+#ifdef HAVE_LLVM_8_0
+ call.getBeginLoc ()
+#else
+ call.getLocStart ()
+#endif
+ )
<< signal_name
<< gir_manager.get_c_name_for_type (dynamic_instance_info)
<< func_info->func_name
diff --git a/clang-plugin/gvariant-checker.cpp b/clang-plugin/gvariant-checker.cpp
index ac539a2..1557235 100644
--- a/clang-plugin/gvariant-checker.cpp
+++ b/clang-plugin/gvariant-checker.cpp
@@ -322,7 +322,12 @@ _consume_variadic_argument (QualType expected_type,
if (*args_begin == *args_end) {
Debug::emit_error ("Expected a GVariant variadic argument of "
"type %0 but there wasn’t one.", compiler,
- format_arg_str->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ )
<< expected_type;
return false;
@@ -351,7 +356,12 @@ _consume_variadic_argument (QualType expected_type,
expected_type->isPointerType ()) {
Debug::emit_error ("Expected a GVariant variadic argument of "
"type %0 but saw NULL instead.", compiler,
- arg->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ arg->getBeginLoc ()
+#else
+ arg->getLocStart ()
+#endif
+ )
<< expected_type;
return false;
@@ -367,7 +377,13 @@ _consume_variadic_argument (QualType expected_type,
"argument of type %0 but saw one "
"of type %1. These types are not "
"compatible on every architecture.",
- compiler, arg->getLocStart ())
+ compiler,
+#ifdef HAVE_LLVM_8_0
+ arg->getBeginLoc ()
+#else
+ arg->getLocStart ()
+#endif
+ )
<< expected_type
<< actual_type;
@@ -376,7 +392,12 @@ _consume_variadic_argument (QualType expected_type,
Debug::emit_error ("Expected a GVariant variadic "
"argument of type %0 but saw one "
"of type %1.", compiler,
- arg->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ arg->getBeginLoc ()
+#else
+ arg->getLocStart ()
+#endif
+ )
<< expected_type
<< actual_type;
@@ -455,7 +476,12 @@ _check_basic_type_string (const gchar **type_str,
default:
Debug::emit_error ("Expected a GVariant basic type string but "
"saw ‘%0’.", compiler,
- format_arg_str->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ )
<< std::string (1, **type_str);
return false;
@@ -573,7 +599,12 @@ _check_type_string (const gchar **type_str,
Debug::emit_error ("Invalid GVariant type string: "
"tuple did not end with ‘)’.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
}
@@ -593,7 +624,12 @@ _check_type_string (const gchar **type_str,
"Invalid GVariant type string: dict did not "
"contain exactly two elements.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
} else if (!_check_basic_type_string (type_str, args_begin,
args_end,
@@ -608,7 +644,12 @@ _check_type_string (const gchar **type_str,
"Invalid GVariant type string: dict did not "
"contain exactly two elements.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
} else if (!_check_type_string (type_str, args_begin, args_end,
flags, compiler,
@@ -622,14 +663,24 @@ _check_type_string (const gchar **type_str,
"Invalid GVariant type string: dict "
"did not end with ‘}’.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
} else if (**type_str != '}') {
Debug::emit_error (
"Invalid GVariant type string: dict "
"contains more than two elements.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
}
@@ -741,7 +792,12 @@ _check_basic_format_string (const gchar **format_str,
"convenience operator ‘^’ was not followed by "
"a recognized convenience conversion.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
}
#undef CONVENIENCE_FORMAT
@@ -823,7 +879,12 @@ _check_format_string (const gchar **format_str,
"Invalid GVariant format string: tuple "
"did not end with ‘)’.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
}
@@ -838,7 +899,12 @@ _check_format_string (const gchar **format_str,
"Invalid GVariant format string: dict did not "
"contain exactly two elements.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
} else if (!_check_basic_format_string (format_str, args_begin,
args_end,
@@ -854,7 +920,12 @@ _check_format_string (const gchar **format_str,
"Invalid GVariant format string: dict did not "
"contain exactly two elements.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
} else if (!_check_format_string (format_str, args_begin,
args_end,
@@ -869,14 +940,24 @@ _check_format_string (const gchar **format_str,
"Invalid GVariant format string: dict "
"did not end with ‘}’.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
} else if (**format_str != '}') {
Debug::emit_error (
"Invalid GVariant format string: dict "
"contains more than two elements.",
compiler,
- format_arg_str->getLocStart ());
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ );
return false;
}
@@ -996,7 +1077,12 @@ _check_gvariant_format_param (const CallExpr& call,
"Cannot check format string correctness. Instead "
"of a non-literal format string, use GVariantBuilder.",
compiler,
- format_arg->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ format_arg->getBeginLoc ()
+#else
+ format_arg->getLocStart ()
+#endif
+ )
<< func.getNameAsString ();
return false;
}
@@ -1046,7 +1132,13 @@ _check_gvariant_format_param (const CallExpr& call,
"with unpaired arguments. If using multiple "
"format strings, they should be enclosed in "
"brackets to create a tuple (e.g. ‘(%1)’).",
- compiler, format_arg_str->getLocStart ())
+ compiler,
+#ifdef HAVE_LLVM_8_0
+ format_arg_str->getBeginLoc ()
+#else
+ format_arg_str->getLocStart ()
+#endif
+ )
<< format_str
<< whole_format_str;
@@ -1076,7 +1168,13 @@ _check_gvariant_format_param (const CallExpr& call,
"(or other valid) GVariant format "
"string should be added to the "
"format argument to use it.",
- compiler, arg->getLocStart ())
+ compiler,
+#ifdef HAVE_LLVM_8_0
+ arg->getBeginLoc ()
+#else
+ arg->getLocStart ()
+#endif
+ )
<< arg->getType ()
<< error_format_str;
} else {
@@ -1090,7 +1188,13 @@ _check_gvariant_format_param (const CallExpr& call,
"type, so the argument must be "
"serialized to a "
"GVariant-representable type first.",
- compiler, arg->getLocStart ())
+ compiler,
+#ifdef HAVE_LLVM_8_0
+ arg->getBeginLoc ()
+#else
+ arg->getLocStart ()
+#endif
+ )
<< arg->getType ();
}
diff --git a/clang-plugin/nullability-checker.cpp b/clang-plugin/nullability-checker.cpp
index 2bdd05b..d7dfaa9 100644
--- a/clang-plugin/nullability-checker.cpp
+++ b/clang-plugin/nullability-checker.cpp
@@ -236,7 +236,12 @@ NullabilityVisitor::TraverseFunctionDecl (FunctionDecl* func)
"annotation on the ‘%0’ parameter "
"of function %1().",
this->_compiler,
- parm_decl->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ parm_decl->getBeginLoc ()
+#else
+ parm_decl->getLocStart ()
+#endif
+ )
<< parm_decl->getNameAsString ()
<< func->getNameAsString ();
} else if (has_nullable && has_assertion) {
@@ -246,7 +251,12 @@ NullabilityVisitor::TraverseFunctionDecl (FunctionDecl* func)
"non-NULL precondition assertion on the ‘%0’ "
"parameter of function %1().",
this->_compiler,
- parm_decl->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ parm_decl->getBeginLoc ()
+#else
+ parm_decl->getLocStart ()
+#endif
+ )
<< parm_decl->getNameAsString ()
<< func->getNameAsString ();
} else if (!has_nullable && !has_assertion) {
@@ -259,7 +269,12 @@ NullabilityVisitor::TraverseFunctionDecl (FunctionDecl* func)
"(already has a nonnull attribute or "
"no non-NULL precondition assertion).",
this->_compiler,
- parm_decl->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ parm_decl->getBeginLoc ()
+#else
+ parm_decl->getLocStart ()
+#endif
+ )
<< parm_decl->getNameAsString ()
<< func->getNameAsString ();
break;
@@ -270,7 +285,12 @@ NullabilityVisitor::TraverseFunctionDecl (FunctionDecl* func)
"non-NULL precondition assertion on "
"the ‘%0’ parameter of function %1().",
this->_compiler,
- parm_decl->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ parm_decl->getBeginLoc ()
+#else
+ parm_decl->getLocStart ()
+#endif
+ )
<< parm_decl->getNameAsString ()
<< func->getNameAsString ();
break;
@@ -283,7 +303,12 @@ NullabilityVisitor::TraverseFunctionDecl (FunctionDecl* func)
"(optional) or (allow-none) "
"annotation).",
this->_compiler,
- parm_decl->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ parm_decl->getBeginLoc ()
+#else
+ parm_decl->getLocStart ()
+#endif
+ )
<< parm_decl->getNameAsString ()
<< func->getNameAsString ();
break;
@@ -296,7 +321,12 @@ NullabilityVisitor::TraverseFunctionDecl (FunctionDecl* func)
"non-NULL precondition annotation on the ‘%0’ "
"parameter of function %1().",
this->_compiler,
- parm_decl->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ parm_decl->getBeginLoc ()
+#else
+ parm_decl->getLocStart ()
+#endif
+ )
<< parm_decl->getNameAsString ()
<< func->getNameAsString ();
} else if (has_nonnull == MAYBE && has_assertion) {
@@ -307,7 +337,12 @@ NullabilityVisitor::TraverseFunctionDecl (FunctionDecl* func)
"parameter of function %1() (already has a "
"non-NULL precondition assertion).",
this->_compiler,
- parm_decl->getLocStart ())
+#ifdef HAVE_LLVM_8_0
+ parm_decl->getBeginLoc ()
+#else
+ parm_decl->getLocStart ()
+#endif
+ )
<< parm_decl->getNameAsString ()
<< func->getNameAsString ();
}
diff --git a/clang-plugin/plugin.cpp b/clang-plugin/plugin.cpp
index 8e8b5b8..1a94e0f 100644
--- a/clang-plugin/plugin.cpp
+++ b/clang-plugin/plugin.cpp
@@ -23,7 +23,11 @@
#include "config.h"
#include <clang/Frontend/FrontendPluginRegistry.h>
+#ifdef HAVE_LLVM_8_0
+#include <clang/StaticAnalyzer/Frontend/CheckerRegistry.h>
+#else
#include <clang/StaticAnalyzer/Core/CheckerRegistry.h>
+#endif
#include <clang/AST/AST.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/Frontend/CompilerInstance.h>
@@ -341,7 +345,11 @@ void clang_registerCheckers (ento::CheckerRegistry &registry);
extern "C"
void clang_registerCheckers (ento::CheckerRegistry &registry) {
registry.addChecker<GErrorChecker> ("tartan.GErrorChecker",
- "Check GError API usage");
+ "Check GError API usage"
+#ifdef HAVE_LLVM_8_0
+ , "http://www.freedesktop.org/software/tartan/"
+#endif
+ );
}
extern "C"
diff --git a/configure.ac b/configure.ac
index 1c26797..89ef86a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,6 +87,11 @@ AC_SUBST([LLVM_VERSION])
AC_DEFINE_UNQUOTED([LLVM_CONFIG_VERSION],"$llvm_version",
[Configured LLVM version])
+# LLVM-specific version definitions
+AS_IF([test "$major" -ge 8],[
+ AC_DEFINE([HAVE_LLVM_8_0], [1], [Whether LLVM ≥ 8.0 is available])
+])
+
# Clang dependency (e.g. the clang-devel package on Fedora)
AC_LANG_PUSH([C++])
old_cppflags="$CPPFLAGS"