*/
+extern bool processing_constexpr_decl;
+
tree c_global_trees[CTI_MAX];
\f
/* Switches common to the C front ends. */
/* The result is a pointer of the same type that is being added. */
tree result_type = TREE_TYPE (ptrop);
- if (flag_sanitize & SANITIZE_UI_OVERFLOW)
+ if ((flag_sanitize & SANITIZE_UI_OVERFLOW)
+ && !((current_function_decl && DECL_LANG_FLAG_8 (current_function_decl))
+ || processing_constexpr_decl))
{
/* First, try to avoid FPs if INTOP is negative constant. */
if (tree_fits_shwi_p (intop))
intop = wide_int_to_tree (TREE_TYPE (intop), intop);
}
- if (flag_sanitize & SANITIZE_UI_OVERFLOW)
+ /* Doing this for constexpr will cause an error, even without ISAN
+ instrumentation: ‘*(const char*)(((long unsigned int)ptr) +
+ ((long unsigned int)index))’ is not a constant expression. So, just disable
+ pointer convertion for constexpr. */
+ if ((flag_sanitize & SANITIZE_UI_OVERFLOW)
+ && !((current_function_decl && DECL_LANG_FLAG_8 (current_function_decl))
+ || processing_constexpr_decl))
{
tree tmp = NULL_TREE;
/* First, try to avoid FPs if INTOP is negative constant. */
/* Variables. */
+extern bool processing_constexpr_decl;
+
/* The stream to which debugging output should be written. */
static FILE *cp_lexer_debug_stream;
bool range_for_decl_p = false;
bool saved_default_arg_ok_p = parser->default_arg_ok_p;
location_t tmp_init_loc = UNKNOWN_LOCATION;
+ processing_constexpr_decl = false;
/* Gather the attributes that were provided with the
decl-specifiers. */
arguments. So right here we only handle the latter. */
if (!member_p && processing_template_decl)
start_lambda_scope (decl);
+
+ /* Save info about constexpr declaration, in case we have
+ constexpr unsigned *p = ptr + index, current_function_decl
+ does not work for us. */
+ if (decl && DECL_DECLARED_CONSTEXPR_P (decl))
+ processing_constexpr_decl = true;
+
initializer = cp_parser_initializer (parser,
&is_direct_init,
&is_non_constant_init);
}
if ((flag_sanitize & SANITIZE_UI_OVERFLOW)
- && (doing_plus || doing_minus || doing_mul)
- && !processing_template_decl)
+ && (doing_plus || doing_minus || doing_mul) && !processing_template_decl
+ && !(current_function_decl
+ && DECL_DECLARED_CONSTEXPR_P (current_function_decl)))
{
op0 = cp_save_expr (op0);
op1 = cp_save_expr (op1);
constexpr int foo (int i) {
return std::__lg (i);
}
+
+constexpr const char *string = "string";
+
+constexpr unsigned int str2int(const char *str, int h = 0) {
+ return !str[h] ? 5381 : (str2int(str, h + 1) * 33) ^ str[h];
+}
+
+constexpr unsigned int arr[] = {1, 2, 3, 4, 5};
+
+constexpr unsigned int index = 1;
+
+class A
+{
+ static constexpr const unsigned int *ptr = arr + index;
+};
+
+int main ()
+{
+ constexpr unsigned int result_value = str2int (string);
+ A a;
+}
/* True if we don't need a backend (e.g. preprocessing only). */
static bool no_backend;
+/* True if processing constexpr declaration.
+ Could not be use to verify function declaration.
+ Only usable for constexpr pointer.
+ Example:
+ constexpr unsigned *pointer = ptr + index. */
+bool processing_constexpr_decl = false;
+
/* Length of line when printing switch values. */
#define MAX_LINE 75