Skip to content

Commit

Permalink
Fix incorrect mutation of comma expressions in C++
Browse files Browse the repository at this point in the history
Fixes #237.
  • Loading branch information
JamesLee-Jones authored Jul 8, 2024
1 parent 5179861 commit 7064f1c
Show file tree
Hide file tree
Showing 13 changed files with 619 additions and 12 deletions.
24 changes: 12 additions & 12 deletions src/libdredd/src/mutation_replace_expr.cc
Original file line number Diff line number Diff line change
Expand Up @@ -560,18 +560,18 @@ void MutationReplaceExpr::ReplaceExprWithFunctionCall(
suffix.append("; }");
}

if (!ast_context.getLangOpts().CPlusPlus) {
if (expr_->isLValue() && input_type.ends_with('*')) {
prefix.append("&(");
suffix.append(")");
} else if (const auto* binary_expr =
llvm::dyn_cast<clang::BinaryOperator>(expr_)) {
// The comma operator requires special care in C, to avoid it appearing to
// provide multiple parameters for an enclosing function call.
if (binary_expr->isCommaOp()) {
prefix.append("(");
suffix.append(")");
}
if (!ast_context.getLangOpts().CPlusPlus && expr_->isLValue() &&
input_type.ends_with('*')) {
prefix.append("&(");
suffix = ")" + suffix;
}

if (const auto* binary_expr = llvm::dyn_cast<clang::BinaryOperator>(expr_)) {
// The comma operator requires special care to avoid it appearing to
// provide multiple parameters for an enclosing function call.
if (binary_expr->isCommaOp()) {
prefix.append("(");
suffix = ")" + suffix;
}
}

Expand Down
3 changes: 3 additions & 0 deletions test/single_file/comma_initialization.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int main() {
int x = (1,0);
}
60 changes: 60 additions & 0 deletions test/single_file/comma_initialization.c.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#ifdef _MSC_VER
#define thread_local __declspec(thread)
#elif __APPLE__
#define thread_local __thread
#else
#include <threads.h>
#endif

static thread_local int __dredd_some_mutation_enabled = 1;
static int __dredd_enabled_mutation(int local_mutation_id) {
static thread_local int initialized = 0;
static thread_local uint64_t enabled_bitset[1];
if (!initialized) {
int some_mutation_enabled = 0;
const char* dredd_environment_variable = getenv("DREDD_ENABLED_MUTATION");
if (dredd_environment_variable) {
char* temp = malloc(strlen(dredd_environment_variable) + 1);
strcpy(temp, dredd_environment_variable);
char* token;
token = strtok(temp, ",");
while(token) {
int value = atoi(token);
int local_value = value - 0;
if (local_value >= 0 && local_value < 7) {
enabled_bitset[local_value / 64] |= (1 << (local_value % 64));
some_mutation_enabled = 1;
}
token = strtok(NULL, ",");
}
free(temp);
}
initialized = 1;
__dredd_some_mutation_enabled = some_mutation_enabled;
}
return enabled_bitset[local_mutation_id / 64] & (1 << (local_mutation_id % 64));
}

static int __dredd_replace_expr_int_zero(int arg, int local_mutation_id) {
if (!__dredd_some_mutation_enabled) return arg;
if (__dredd_enabled_mutation(local_mutation_id + 0)) return 1;
if (__dredd_enabled_mutation(local_mutation_id + 1)) return -1;
return arg;
}

static int __dredd_replace_expr_int_one(int 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 0;
if (__dredd_enabled_mutation(local_mutation_id + 2)) return -1;
return arg;
}

int main() {
int x = (__dredd_replace_expr_int_zero((__dredd_replace_expr_int_one(1, 0),__dredd_replace_expr_int_zero(0, 3)), 5));
}
56 changes: 56 additions & 0 deletions test/single_file/comma_initialization.c.noopt.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#ifdef _MSC_VER
#define thread_local __declspec(thread)
#elif __APPLE__
#define thread_local __thread
#else
#include <threads.h>
#endif

static thread_local int __dredd_some_mutation_enabled = 1;
static int __dredd_enabled_mutation(int local_mutation_id) {
static thread_local int initialized = 0;
static thread_local uint64_t enabled_bitset[1];
if (!initialized) {
int some_mutation_enabled = 0;
const char* dredd_environment_variable = getenv("DREDD_ENABLED_MUTATION");
if (dredd_environment_variable) {
char* temp = malloc(strlen(dredd_environment_variable) + 1);
strcpy(temp, dredd_environment_variable);
char* token;
token = strtok(temp, ",");
while(token) {
int value = atoi(token);
int local_value = value - 0;
if (local_value >= 0 && local_value < 24) {
enabled_bitset[local_value / 64] |= (1 << (local_value % 64));
some_mutation_enabled = 1;
}
token = strtok(NULL, ",");
}
free(temp);
}
initialized = 1;
__dredd_some_mutation_enabled = some_mutation_enabled;
}
return enabled_bitset[local_mutation_id / 64] & (1 << (local_mutation_id % 64));
}

static int __dredd_replace_expr_int(int 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 -(arg);
if (__dredd_enabled_mutation(local_mutation_id + 3)) return 0;
if (__dredd_enabled_mutation(local_mutation_id + 4)) return 1;
if (__dredd_enabled_mutation(local_mutation_id + 5)) return -1;
return arg;
}

int main() {
int x = __dredd_replace_expr_int((__dredd_replace_expr_int((__dredd_replace_expr_int(1, 0),__dredd_replace_expr_int(0, 6)), 12)), 18);
}
3 changes: 3 additions & 0 deletions test/single_file/comma_initialization.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int main() {
int b((1,0));
}
62 changes: 62 additions & 0 deletions test/single_file/comma_initialization.cc.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <cinttypes>
#include <cstddef>
#include <functional>
#include <string>


#ifdef _MSC_VER
#define thread_local __declspec(thread)
#elif __APPLE__
#define thread_local __thread
#endif

static thread_local bool __dredd_some_mutation_enabled = true;
static bool __dredd_enabled_mutation(int local_mutation_id) {
static thread_local bool initialized = false;
static thread_local uint64_t enabled_bitset[1];
if (!initialized) {
bool some_mutation_enabled = false;
const char* dredd_environment_variable = std::getenv("DREDD_ENABLED_MUTATION");
if (dredd_environment_variable != nullptr) {
std::string contents(dredd_environment_variable);
while (true) {
size_t pos = contents.find(",");
std::string token = (pos == std::string::npos ? contents : contents.substr(0, pos));
if (!token.empty()) {
int value = std::stoi(token);
int local_value = value - 0;
if (local_value >= 0 && local_value < 7) {
enabled_bitset[local_value / 64] |= (1 << (local_value % 64));
some_mutation_enabled = true;
}
}
if (pos == std::string::npos) {
break;
}
contents.erase(0, pos + 1);
}
}
initialized = true;
__dredd_some_mutation_enabled = some_mutation_enabled;
}
return (enabled_bitset[local_mutation_id / 64] & (1 << (local_mutation_id % 64))) != 0;
}

static int __dredd_replace_expr_int_zero(int arg, int local_mutation_id) {
if (!__dredd_some_mutation_enabled) return arg;
if (__dredd_enabled_mutation(local_mutation_id + 0)) return 1;
if (__dredd_enabled_mutation(local_mutation_id + 1)) return -1;
return arg;
}

static int __dredd_replace_expr_int_one(int 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 0;
if (__dredd_enabled_mutation(local_mutation_id + 2)) return -1;
return arg;
}

int main() {
int b((__dredd_replace_expr_int_zero((__dredd_replace_expr_int_one(1, 0),__dredd_replace_expr_int_zero(0, 3)), 5)));
}
58 changes: 58 additions & 0 deletions test/single_file/comma_initialization.cc.noopt.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <cinttypes>
#include <cstddef>
#include <functional>
#include <string>


#ifdef _MSC_VER
#define thread_local __declspec(thread)
#elif __APPLE__
#define thread_local __thread
#endif

static thread_local bool __dredd_some_mutation_enabled = true;
static bool __dredd_enabled_mutation(int local_mutation_id) {
static thread_local bool initialized = false;
static thread_local uint64_t enabled_bitset[1];
if (!initialized) {
bool some_mutation_enabled = false;
const char* dredd_environment_variable = std::getenv("DREDD_ENABLED_MUTATION");
if (dredd_environment_variable != nullptr) {
std::string contents(dredd_environment_variable);
while (true) {
size_t pos = contents.find(",");
std::string token = (pos == std::string::npos ? contents : contents.substr(0, pos));
if (!token.empty()) {
int value = std::stoi(token);
int local_value = value - 0;
if (local_value >= 0 && local_value < 24) {
enabled_bitset[local_value / 64] |= (1 << (local_value % 64));
some_mutation_enabled = true;
}
}
if (pos == std::string::npos) {
break;
}
contents.erase(0, pos + 1);
}
}
initialized = true;
__dredd_some_mutation_enabled = some_mutation_enabled;
}
return (enabled_bitset[local_mutation_id / 64] & (1 << (local_mutation_id % 64))) != 0;
}

static int __dredd_replace_expr_int(int 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 -(arg);
if (__dredd_enabled_mutation(local_mutation_id + 3)) return 0;
if (__dredd_enabled_mutation(local_mutation_id + 4)) return 1;
if (__dredd_enabled_mutation(local_mutation_id + 5)) return -1;
return arg;
}

int main() {
int b(__dredd_replace_expr_int((__dredd_replace_expr_int((__dredd_replace_expr_int(1, 0),__dredd_replace_expr_int(0, 6)), 12)), 18));
}
4 changes: 4 additions & 0 deletions test/single_file/comma_side_effects.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
int main() {
int x = 0;
x = (0, x++);
}
89 changes: 89 additions & 0 deletions test/single_file/comma_side_effects.c.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#ifdef _MSC_VER
#define thread_local __declspec(thread)
#elif __APPLE__
#define thread_local __thread
#else
#include <threads.h>
#endif

static thread_local int __dredd_some_mutation_enabled = 1;
static int __dredd_enabled_mutation(int local_mutation_id) {
static thread_local int initialized = 0;
static thread_local uint64_t enabled_bitset[1];
if (!initialized) {
int some_mutation_enabled = 0;
const char* dredd_environment_variable = getenv("DREDD_ENABLED_MUTATION");
if (dredd_environment_variable) {
char* temp = malloc(strlen(dredd_environment_variable) + 1);
strcpy(temp, dredd_environment_variable);
char* token;
token = strtok(temp, ",");
while(token) {
int value = atoi(token);
int local_value = value - 0;
if (local_value >= 0 && local_value < 32) {
enabled_bitset[local_value / 64] |= (1 << (local_value % 64));
some_mutation_enabled = 1;
}
token = strtok(NULL, ",");
}
free(temp);
}
initialized = 1;
__dredd_some_mutation_enabled = some_mutation_enabled;
}
return enabled_bitset[local_mutation_id / 64] & (1 << (local_mutation_id % 64));
}

static int __dredd_replace_unary_operator_PostInc_int(int* 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 -(*arg);
if (__dredd_enabled_mutation(local_mutation_id + 3)) return !(*arg);
if (__dredd_enabled_mutation(local_mutation_id + 4)) return (*arg);
return (*arg)++;
}

static int __dredd_replace_expr_int_zero(int arg, int local_mutation_id) {
if (!__dredd_some_mutation_enabled) return arg;
if (__dredd_enabled_mutation(local_mutation_id + 0)) return 1;
if (__dredd_enabled_mutation(local_mutation_id + 1)) return -1;
return arg;
}

static int __dredd_replace_expr_int(int 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 -(arg);
if (__dredd_enabled_mutation(local_mutation_id + 3)) return 0;
if (__dredd_enabled_mutation(local_mutation_id + 4)) return 1;
if (__dredd_enabled_mutation(local_mutation_id + 5)) return -1;
return arg;
}

static int __dredd_replace_binary_operator_Assign_arg1_int_arg2_int(int* arg1, int arg2, int local_mutation_id) {
if (!__dredd_some_mutation_enabled) return (*arg1) = arg2;
if (__dredd_enabled_mutation(local_mutation_id + 0)) return (*arg1) += arg2;
if (__dredd_enabled_mutation(local_mutation_id + 1)) return (*arg1) &= arg2;
if (__dredd_enabled_mutation(local_mutation_id + 2)) return (*arg1) /= arg2;
if (__dredd_enabled_mutation(local_mutation_id + 3)) return (*arg1) *= arg2;
if (__dredd_enabled_mutation(local_mutation_id + 4)) return (*arg1) |= arg2;
if (__dredd_enabled_mutation(local_mutation_id + 5)) return (*arg1) %= arg2;
if (__dredd_enabled_mutation(local_mutation_id + 6)) return (*arg1) <<= arg2;
if (__dredd_enabled_mutation(local_mutation_id + 7)) return (*arg1) >>= arg2;
if (__dredd_enabled_mutation(local_mutation_id + 8)) return (*arg1) -= arg2;
if (__dredd_enabled_mutation(local_mutation_id + 9)) return (*arg1) ^= arg2;
return (*arg1) = arg2;
}

int main() {
int x = __dredd_replace_expr_int_zero(0, 0);
if (!__dredd_enabled_mutation(31)) { __dredd_replace_binary_operator_Assign_arg1_int_arg2_int(&(x) , (__dredd_replace_expr_int((__dredd_replace_expr_int_zero(0, 2), __dredd_replace_expr_int(__dredd_replace_unary_operator_PostInc_int(&(x), 4), 9)), 15)), 21); }
}
Loading

0 comments on commit 7064f1c

Please sign in to comment.