Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mutation of expression used in initializer list results in ill-formed program #270

Closed
JonathanFoo0523 opened this issue Jul 11, 2024 · 5 comments · Fixed by #278
Closed
Assignees
Labels
bug Something isn't working

Comments

@JonathanFoo0523
Copy link
Collaborator

Applying Dredd to

#include <initializer_list>
#include <cstdint>

template <typename T> class foo {
public:
  foo(std::initializer_list<T>) {}
};

int main() { 
    foo<uint64_t>{+2}; 
}

change the sole statement in main() to

if (!__dredd_enabled_mutation(5)) { foo<uint64_t>{+__dredd_replace_expr_int_constant(2, 0)}; } 

This causes the following compilation error:

non-constant-expression cannot be narrowed from type 'int' to 'unsigned long' in initializer list
@JonathanFoo0523 JonathanFoo0523 added the bug Something isn't working label Jul 11, 2024
@JonathanFoo0523
Copy link
Collaborator Author

Note that + in +2 is required to replicate the issue. Otherwise, Dredd will not mutate the expression 2, and thus avoid this issue.

@JonathanFoo0523
Copy link
Collaborator Author

JonathanFoo0523 commented Jul 11, 2024

While we can reduce this bug by avoiding mutation of expression in such case, I think this approach will further reduce the number of mutants.

Is it possible to change the prelude function to a templated version

template <typename T> 
static T __dredd_replace_expr_int_like_constant(T arg, int local_mutation_id) {
  if (!__dredd_some_mutation_enabled) return arg;
  if (__dredd_enabled_mutation(local_mutation_id + 0)) return ~(arg);
  if (__dredd_enabled_mutation(local_mutation_id + 1)) return -(arg);
  if (__dredd_enabled_mutation(local_mutation_id + 2)) return 0;
  if (__dredd_enabled_mutation(local_mutation_id + 3)) return 1;
  if (__dredd_enabled_mutation(local_mutation_id + 4)) return -1;
  return arg;
}

and mutate the fault-causing expression to:

+__dredd_replace_expr_int_like_constant<uint64_t>(2, 0)

@afd
Copy link
Member

afd commented Jul 11, 2024

I am worried that having templated mutator functions may end up getting very complicated and leading to unexpected issues. On the other hand, it might actually turn out to provide a simple and elegant solution to certain issues. @JonathanFoo0523 can you experiment with the template idea?

If it turns out to be non-trivial then I would prefer to work around this by detecting the special case and avoiding a mutation in that special case, and opening a "stretch goal" issue to consider a better solution in the longer term.

@JonathanFoo0523
Copy link
Collaborator Author

A slightly simpler example

#include <initializer_list>

class foo {
public:
  foo(std::initializer_list<unsigned int>) {}
};

int main() { 
    foo{+2}; 
}

@JonathanFoo0523
Copy link
Collaborator Author

Another Example:

struct a {
  short b;
};
a c() { return {6 * 4}; }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants