Translate C/C++ programs to equivalent Dafny code while preserving semantics and ensuring verification. Use when users ask to convert, translate, or port C/C++ code to Dafny, or when they need to formally verify C/C++ algorithms using Dafny's verification capabilities. Handles functions, structs, pointers, arrays, memory management, and ensures the generated Dafny code is well-typed, executable, verifiable, and can successfully run.
npx skills add https://github.com/ArabelaTso/Skills-4-SE --skill cpp-to-dafny-translator
Translate C/C++ programs into equivalent, verifiable Dafny code while preserving program semantics and ensuring memory safety.
This skill provides systematic guidance for translating C/C++ code to Dafny, handling memory management, pointer semantics, type conversions, and ensuring well-typed, verifiable output with appropriate specifications.
C/C++ Input → Analyze Structure → Map Types & Memory → Translate → Add Specifications → Verify
├─ Identify types, pointers, memory patterns
├─ Map C/C++ constructs to Dafny equivalents
├─ Handle memory safety and ownership
├─ Add preconditions, postconditions, invariants
└─ Validate executability and verification
Dafny enforces memory safety. Every translation must:
The translated code must maintain the same computational behavior, preserve function contracts, keep algorithmic complexity, and handle all edge cases including error conditions.
Generated Dafny code must include specifications (preconditions, postconditions, invariants), be verifiable by Dafny's verifier, compile and execute correctly, and follow Dafny idioms.
| C/C++ Type | Dafny Type | Notes |
|-----------|-----------|-------|
| int, long | int | Unbounded integers in Dafny |
| unsigned int | nat | Natural numbers (≥ 0) |
| char | char | Single character |
| bool | bool | Direct mapping |
| float, double | real | Exact rationals in Dafny |
| void | () | Unit type |
| NULL | Use Option or bounds checks | No null pointers |
| C/C++ Type | Dafny Type | Notes |
|-----------|-----------|-------|
| int arr[] | array<int> | Fixed-size arrays |
| int* ptr | array<int> or seq<int> | Depends on usage |
| struct | class or datatype | Mutable vs immutable |
| enum | datatype | Algebraic data types |
| union | datatype with variants | Tagged unions |
For detailed mappings, see references/type_mappings.md.
Simple C function:
int add(int a, int b) {
return a + b;
}
Dafny:
function add(a: int, b: int): int
{
a + b
}
Function with side effects:
void increment(int* x) {
(*x)++;
}
Dafny (using method):
method increment(x: array<int>, index: nat)
requires index < x.Length
modifies x
ensures x[index] == old(x[index]) + 1
{
x[index] := x[index] + 1;
}
C array access:
int sum_array(int* arr, int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
return sum;
}
Dafny:
method sumArray(arr: array<int>) returns (sum: int)
ensures sum == arraySum(arr[..])
{
sum := 0;
var i := 0;
while i < arr.Length
invariant 0 <= i <= arr.Length
invariant sum == arraySum(arr[..i])
{
sum := sum + arr[i];
i := i + 1;
}
}
function arraySum(s: seq<int>): int
{
if |s| == 0 then 0 else s[0] + arraySum(s[1..])
}
C struct:
struct Point {
int x;
int y;
};
int distance_squared(struct Point* p) {
return p->x * p->x + p->y * p->y;
}
Dafny:
class Point {
var x: int
var y: int
constructor(x0: int, y0: int)
ensures x == x0 && y == y0
{
x := x0;
y := y0;
}
}
function distanceSquared(p: Point): int
reads p
{
p.x * p.x + p.y * p.y
}
If-else:
int max(int a, int b) {
if (a > b) return a;
else return b;
}
Dafny:
function max(a: int, b: int): int
{
if a > b then a else b
}
Loops with invariants:
int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
Dafny:
method factorial(n: nat) returns (result: nat)
ensures result == fact(n)
{
result := 1;
var i := 1;
while i <= n
invariant 1 <= i <= n + 1
invariant result == fact(i - 1)
{
result := result * i;
i := i + 1;
}
}
function fact(n: nat): nat
{
if n == 0 then 1 else n * fact(n - 1)
}
Challenge: C allows pointer arithmetic; Dafny doesn't.
Solution: Use array indices instead:
// C
int* ptr = arr + 5;
*ptr = 10;
// Dafny
arr[5] := 10;
Challenge: C uses malloc/free; Dafny has automatic memory management.
Solution: Use arrays or sequences:
// C
int* arr = (int*)malloc(n * sizeof(int));
// ... use arr ...
free(arr);
// Dafny
var arr := new int[n];
// ... use arr ...
// No explicit free needed
Challenge: C allows NULL; Dafny doesn't have null references.
Solution: Use Option types or ensure non-null:
// C
int* find(int* arr, int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) return &arr[i];
}
return NULL;
}
// Dafny
method find(arr: array<int>, target: int) returns (index: int)
ensures index == -1 || (0 <= index < arr.Length && arr[index] == target)
{
var i := 0;
while i < arr.Length
invariant 0 <= i <= arr.Length
{
if arr[i] == target {
return i;
}
i := i + 1;
}
return -1;
}
Challenge: C has mutable everything; Dafny distinguishes functions (pure) from methods (with side effects).
Solution:
function for pure computationsmethod for operations with side effectsreads clauses for functions that read object fieldsmodifies clauses for methods that modify stateChallenge: Dafny requires specifications for verification.
Solution: Add preconditions, postconditions, and loop invariants:
method binarySearch(arr: array<int>, target: int) returns (index: int)
requires forall i, j :: 0 <= i < j < arr.Length ==> arr[i] <= arr[j] // sorted
ensures index == -1 || (0 <= index < arr.Length && arr[index] == target)
{
var low := 0;
var high := arr.Length;
while low < high
invariant 0 <= low <= high <= arr.Length
invariant forall i :: 0 <= i < low ==> arr[i] < target
invariant forall i :: high <= i < arr.Length ==> arr[i] > target
{
var mid := (low + high) / 2;
if arr[mid] < target {
low := mid + 1;
} else if arr[mid] > target {
high := mid;
} else {
return mid;
}
}
return -1;
}
Identify all functions, structs, and global variables. Analyze pointer usage and memory patterns. Identify side effects and state modifications. Note any unsafe operations.
Map C/C++ types to Dafny types. Decide how to handle pointers (arrays, sequences, or references). Plan struct translations (class vs datatype). Identify what needs specifications.
Start with data structures (structs → classes/datatypes). Translate pure functions first. Convert functions with side effects to methods. Add memory safety checks. Include necessary specifications.
Add preconditions (requires). Add postconditions (ensures). Add loop invariants. Add frame conditions (reads, modifies). Add termination measures (decreases).
Run Dafny verifier. Fix verification errors. Test with concrete examples. Ensure executability.
C code:
int is_sorted(int* arr, int n) {
for (int i = 0; i < n - 1; i++) {
if (arr[i] > arr[i + 1]) {
return 0;
}
}
return 1;
}
void bubble_sort(int* arr, int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
Dafny:
predicate isSorted(arr: array<int>)
reads arr
{
forall i, j :: 0 <= i < j < arr.Length ==> arr[i] <= arr[j]
}
method bubbleSort(arr: array<int>)
modifies arr
ensures isSorted(arr)
ensures multiset(arr[..]) == multiset(old(arr[..]))
{
var i := 0;
while i < arr.Length - 1
invariant 0 <= i <= arr.Length
invariant forall k, l :: 0 <= k < i <= l < arr.Length ==> arr[k] <= arr[l]
invariant multiset(arr[..]) == multiset(old(arr[..]))
{
var j := 0;
while j < arr.Length - i - 1
invariant 0 <= j <= arr.Length - i - 1
invariant forall k :: 0 <= k < j ==> arr[k] <= arr[j]
invariant multiset(arr[..]) == multiset(old(arr[..]))
{
if arr[j] > arr[j + 1] {
arr[j], arr[j + 1] := arr[j + 1], arr[j];
}
j := j + 1;
}
i := i + 1;
}
}
Main methods to test concrete examplesBefore finalizing translation:
For complex translations, refer to:
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when the user asks to run Codex CLI (codex exec, codex resume) or references OpenAI Codex for code analysis, refactoring, or automated editing. Uses GPT-5.2 by default for state-of-the-art software engineering.
Implement memory-safe programming with RAII, ownership, smart pointers, and resource management across Rust, C++, and C. Use when writing safe systems code, managing resources, or preventing memory bugs.
Python/HTSlib workflows for genomic files. Use when reading, querying, filtering, or writing SAM/BAM/CRAM, VCF/BCF, FASTA/FASTQ, or tabix data with pysam, including pileup, coverage, indexing, and CRAM references.
Evaluate scientific claims and evidence quality. Use for assessing experimental design validity, identifying biases and confounders, applying evidence grading frameworks (GRADE, Cochrane Risk of Bias), or teaching critical analysis. Best for understanding evidence quality, identifying flaws. For formal peer review writing use peer-review.
Use when a user asks to debug or fix failing GitHub PR checks that run in GitHub Actions; use `gh` to inspect checks and logs, summarize failure context, draft a fix plan, and implement only after explicit approval. Treat external providers (for example Buildkite) as out of scope and report only the details URL.
> Create, build, deploy, and localize declarative agents for M365 Copilot and Teams. USE THIS SKILL for ANY task involving a declarative agent — including localization, scaffolding, editing manifests, adding capabilities, and deploying. Localization requires tokenized manifests and language files that only this skill knows how to produce. "scaffold an agent", "new agent project", "add a capability", "add a plugin", "configure my agent", "deploy my agent", "fix my agent manifest", "edit my agent", "localize my agent", "add localization", "translate my agent", "multi-language agent", "add an API plugin", "add an MCP plugin", "add OAuth to my plugin", "review instructions", "improve instructions", "fix my instructions"
Documentation generation workflow covering API docs, architecture docs, README files, code comments, and technical writing.
Take arabelatso/cpp-to-dafny-translator from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.