{"id":26345369,"url":"https://github.com/plasma-umass/cwhy","last_synced_at":"2025-05-15T23:03:58.253Z","repository":{"id":150843218,"uuid":"623566947","full_name":"plasma-umass/cwhy","owner":"plasma-umass","description":"\"See why!\" Explains and suggests fixes for compile-time errors for C, C++, C#, Go, Java, LaTeX, PHP, Python, Ruby, Rust, and TypeScript","archived":false,"fork":false,"pushed_at":"2025-01-14T12:34:50.000Z","size":767,"stargazers_count":287,"open_issues_count":2,"forks_count":7,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-04-13T12:48:51.582Z","etag":null,"topics":["c-plus-plus","c-programming","csharp","golang","java","latex","python","ruby","rust","typescript"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/plasma-umass.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-04-04T16:19:08.000Z","updated_at":"2025-03-04T00:06:33.000Z","dependencies_parsed_at":"2024-02-05T19:48:40.831Z","dependency_job_id":"abf76041-98dd-4b6e-84dd-445434141087","html_url":"https://github.com/plasma-umass/cwhy","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plasma-umass%2Fcwhy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plasma-umass%2Fcwhy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plasma-umass%2Fcwhy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/plasma-umass%2Fcwhy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/plasma-umass","download_url":"https://codeload.github.com/plasma-umass/cwhy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254436944,"owners_count":22070946,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-plus-plus","c-programming","csharp","golang","java","latex","python","ruby","rust","typescript"],"created_at":"2025-03-16T06:18:09.852Z","updated_at":"2025-05-15T23:03:58.235Z","avatar_url":"https://github.com/plasma-umass.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CWhy\n\nby [Emery Berger](https://emeryberger.com),\n[Nicolas van Kempen](https://nvankempen.com/),\nand [Bryce Adelstein Lelbach](https://twitter.com/blelbach).\n\n[![PyPI](https://img.shields.io/pypi/v/cwhy.svg)](https://pypi.org/project/cwhy/)\n[![downloads](https://static.pepy.tech/badge/cwhy)](https://pepy.tech/project/cwhy)\n[![downloads/month](https://static.pepy.tech/badge/cwhy/month)](https://pepy.tech/project/cwhy)\n\n(\"See why\")\n\nExplains and suggests fixes for compiler error messages for a wide range of programming languages, including C, C++, C#,\nGo, Java, LaTeX, PHP, Python, Ruby, Rust, Swift, and TypeScript.\n\n## Installation\n\n \u003e  [!NOTE]\n \u003e\n \u003e  CWhy needs to be connected to an [OpenAI account](https://openai.com/api/).\n \u003e  _Your account will need to have a positive balance for this to work_\n \u003e  ([check your OpenAI balance](https://platform.openai.com/usage)).\n \u003e  [Get an OpenAI key here](https://platform.openai.com/api-keys).\n \u003e \n \u003e  You may need to purchase $0.50 - $1 in OpenAI credits depending on when your API account was created.\n \u003e \n \u003e  Once you have an API key, set it as an environment variable called `OPENAI_API_KEY`.\n \u003e \n \u003e  ```bash\n \u003e  # On Linux/MacOS:\n \u003e  export OPENAI_API_KEY=\u003cyour-api-key\u003e\n \u003e  \n \u003e  # On Windows:\n \u003e  $env:OPENAI_API_KEY=\u003cyour-api-key\u003e\n \u003e  ```\n \n```bash\npython3 -m pip install cwhy\n```\n\n### Other LLMs\n\nWe mostly test with OpenAI, but other LLMs can be made to work with CWhy. Please report any bug you may encounter.\n\n#### OpenAI API Compatible\n\nIf your provider supports OpenAI style API calls, you can simply specify the `OPENAI_BASE_URL` environment variable to\nselect a different URL to send requests to. For example, this will work great with [Ollama](https://ollama.com/):\n\n```bash\ndocker run -d --gpus=all -v ollama:/root/.ollama -p 11434:11434 --rm --name ollama ollama/ollama\ndocker exec -it ollama ollama pull llama3.1:70b\nexport OPENAI_BASE_URL=http://localhost:11434/v1\ncwhy --llm llama3.1:70b --- clang++ tests/c++/missing-hash.cpp\n```\n\n#### LiteLLM Proxy\n\nIf your provider does not support OpenAI style API calls, such as AWS Bedrock which we used to support, we recommend\nusing the [LiteLLM Proxy Server](https://docs.litellm.ai/docs/simple_proxy).\n\n```bash\npip install 'litellm[proxy]'\n# Set AWS_ACCESS_KEY_ID, AWS_REGION_NAME, and AWS_SECRET_ACCESS_KEY.\nlitellm --model bedrock/anthropic.claude-v2\nexport OPENAI_BASE_URL=http://0.0.0.0:4000\ncwhy --- clang++ tests/c++/missing-hash.cpp\n```\n\nNote that when using the LiteLLM Proxy, CWhy's `--llm` argument will be ignored completely.\n\n## Usage \n\n### Linux/MacOS\n\nThe wrapper mode is now default and mandatory, with a slightly modified interface.\nCWhy can either be used standalone by passing the full command after the triple dashes `---`, or as part of a build tool\nby creating a short executable script wrapping the compiler command.\n\n```bash\n# Invoking the compiler directly.\ncwhy --- g++ mycode.cpp\n\n# Using CWhy with Java and an increased timeout.\ncwhy --timeout 180 --- javac MyCode.java\n\n# Invoking with GNU Make, using GPT-3.5.\nCXX=`cwhy --llm=gpt-3.5-turbo --wrapper --- c++` make\n\n# Invoking with CMake, using GPT-4 and clang++.\nCWHY_DISABLE=1 cmake -DCMAKE_CXX_COMPILER=`cwhy --llm=gpt-4 --wrapper --- clang++` ...\n```\n\nConfiguration tools such as CMake or Autoconf will occasionally invoke the compiler to check for features, which will\nfail and invoke CWhy unnecessarily if not available on the machine. To circumvent this, `CWHY_DISABLE` can be set in\nthe environment to disable CWhy at configuration time.\n\n```bash\nCWHY_DISABLE='ON' cmake -DCMAKE_CXX_COMPILER=`cwhy --wrapper --- c++` ...\n```\n\n### Windows\n\nWindows support has been tested using Powershell. On the command line, using Ninja is required as MSBuild / `.vcxproj`\nwill override any option set.\n\n```bash\n$env:CWHY_DISABLE='ON'\ncmake -G Ninja -DCMAKE_CXX_COMPILER=\"$(python -m cwhy --wrapper --- cl)\"  ...\n$env:CWHY_DISABLE=''\n```\n\n### Continuous Integration\n\nCI using GitHub actions is straightforward on both Linux and MacOs. On Windows, Ninja is not installed by default on the\nimage, and `cl` is not bound to the compiler. We recommend using `choco install ninja` and\n[ilammy/msvc-dev-cmd](https://github.com/ilammy/msvc-dev-cmd) to work around these two issues.\n\nAn example action YAML file covering all three platforms\n[can be found here](https://github.com/nicovank/litterer/blob/master/.github/workflows/ci.yml).\n\n**Important**: Set the `CWHY_DISABLE` environment variable at configure-time to save money and cycles.\n\n### Options\n\nThese options can be displayed with `cwhy --help`.\n\n -  `--llm`: pick a specific OpenAI LLM. CWhy has been tested with `gpt-3.5-turbo` and `gpt-4`.\n -  `--timeout`: pick a different timeout than the default for API calls.\n -  `--show-prompt` (debug): print prompts before calling the API.\n\n## Examples\n\n### C++\n\nThis highlighted example is [missing-hash.cpp](tests/c++/missing-hash.cpp), which is one of the first cases we\nexperimented with.\n\n\u003cdetails\u003e\n\u003csummary\u003e\nExpand to see the original (pretty obscure) error message:\n\u003c/summary\u003e\n\n```\n% clang++ --std=c++20 -c missing-hash.cpp\nmissing-hash.cpp:13:45: error: call to implicitly-deleted default constructor of 'std::unordered_set\u003cstd::pair\u003cint, int\u003e\u003e'\n    std::unordered_set\u003cstd::pair\u003cint, int\u003e\u003e visited;\n                                            ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unordered_set.h:135:7: note: explicitly defaulted function was implicitly deleted here\n      unordered_set() = default;\n      ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unordered_set.h:100:18: note: default constructor of 'unordered_set\u003cstd::pair\u003cint, int\u003e\u003e' is implicitly deleted because field '_M_h' has a deleted default constructor\n      _Hashtable _M_h;\n                 ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:451:7: note: explicitly defaulted function was implicitly deleted here\n      _Hashtable() = default;\n      ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:174:7: note: default constructor of '_Hashtable\u003cstd::pair\u003cint, int\u003e, std::pair\u003cint, int\u003e, std::allocator\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Identity, std::equal_to\u003cstd::pair\u003cint, int\u003e\u003e, std::hash\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits\u003ctrue, true, true\u003e\u003e' is implicitly deleted because base class '__detail::_Hashtable_base\u003cpair\u003cint, int\u003e, pair\u003cint, int\u003e, _Identity, equal_to\u003cpair\u003cint, int\u003e\u003e, hash\u003cpair\u003cint, int\u003e\u003e, _Mod_range_hashing, _Default_ranged_hash, _Hashtable_traits\u003ctrue, true, true\u003e\u003e' has a deleted default constructor\n    : public __detail::_Hashtable_base\u003c_Key, _Value, _ExtractKey, _Equal,\n      ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1791:5: note: explicitly defaulted function was implicitly deleted here\n    _Hashtable_base() = default;\n    ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1726:5: note: default constructor of '_Hashtable_base\u003cstd::pair\u003cint, int\u003e, std::pair\u003cint, int\u003e, std::__detail::_Identity, std::equal_to\u003cstd::pair\u003cint, int\u003e\u003e, std::hash\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Hashtable_traits\u003ctrue, true, true\u003e\u003e' is implicitly deleted because base class '_Hash_code_base\u003cpair\u003cint, int\u003e, pair\u003cint, int\u003e, _Identity, hash\u003cpair\u003cint, int\u003e\u003e, _Mod_range_hashing, _Default_ranged_hash, _Hashtable_traits\u003ctrue, true, true\u003e::__hash_cached::value\u003e' has a deleted default constructor\n  : public _Hash_code_base\u003c_Key, _Value, _ExtractKey, _H1, _H2, _Hash,\n    ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1368:7: note: explicitly defaulted function was implicitly deleted here\n      _Hash_code_base() = default;\n      ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1344:7: note: default constructor of '_Hash_code_base\u003cstd::pair\u003cint, int\u003e, std::pair\u003cint, int\u003e, std::__detail::_Identity, std::hash\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true\u003e' is implicitly deleted because base class '_Hashtable_ebo_helper\u003c1, hash\u003cpair\u003cint, int\u003e\u003e\u003e' has a deleted default constructor\n      private _Hashtable_ebo_helper\u003c1, _H1\u003e,\n      ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1112:7: note: explicitly defaulted function was implicitly deleted here\n      _Hashtable_ebo_helper() = default;\n      ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1110:7: note: default constructor of '_Hashtable_ebo_helper\u003c1, std::hash\u003cstd::pair\u003cint, int\u003e\u003e, true\u003e' is implicitly deleted because base class 'std::hash\u003cstd::pair\u003cint, int\u003e\u003e' has a deleted default constructor\n    : private _Tp\n      ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/functional_hash.h:101:19: note: default constructor of 'hash\u003cstd::pair\u003cint, int\u003e\u003e' is implicitly deleted because base class '__hash_enum\u003cpair\u003cint, int\u003e\u003e' has no default constructor\n    struct hash : __hash_enum\u003c_Tp\u003e\n                  ^\nIn file included from missing-hash.cpp:1:\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:61:\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/unordered_map:46:\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:35:\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1377:2: error: static assertion failed due to requirement 'std::__is_invocable\u003cconst std::hash\u003cstd::pair\u003cint, int\u003e\u003e \u0026, const std::pair\u003cint, int\u003e \u0026\u003e{}': hash function must be invocable with an argument of key type\n        static_assert(__is_invocable\u003cconst _H1\u0026, const _Key\u0026\u003e{},\n        ^             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:1675:29: note: in instantiation of member function 'std::__detail::_Hash_code_base\u003cstd::pair\u003cint, int\u003e, std::pair\u003cint, int\u003e, std::__detail::_Identity, std::hash\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true\u003e::_M_hash_code' requested here\n        __hash_code __code = this-\u003e_M_hash_code(__k);\n                                   ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:788:11: note: in instantiation of function template specialization 'std::_Hashtable\u003cstd::pair\u003cint, int\u003e, std::pair\u003cint, int\u003e, std::allocator\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Identity, std::equal_to\u003cstd::pair\u003cint, int\u003e\u003e, std::hash\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits\u003ctrue, true, true\u003e\u003e::_M_emplace\u003cconst std::pair\u003cint, int\u003e \u0026\u003e' requested here\n        { return _M_emplace(__unique_keys(), std::forward\u003c_Args\u003e(__args)...); }\n                 ^\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/unordered_set.h:377:16: note: in instantiation of function template specialization 'std::_Hashtable\u003cstd::pair\u003cint, int\u003e, std::pair\u003cint, int\u003e, std::allocator\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Identity, std::equal_to\u003cstd::pair\u003cint, int\u003e\u003e, std::hash\u003cstd::pair\u003cint, int\u003e\u003e, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits\u003ctrue, true, true\u003e\u003e::emplace\u003cconst std::pair\u003cint, int\u003e \u0026\u003e' requested here\n        { return _M_h.emplace(std::forward\u003c_Args\u003e(__args)...); }\n                      ^\nmissing-hash.cpp:20:44: note: in instantiation of function template specialization 'std::unordered_set\u003cstd::pair\u003cint, int\u003e\u003e::emplace\u003cconst std::pair\u003cint, int\u003e \u0026\u003e' requested here\n        const auto [_, inserted] = visited.emplace(n-\u003eposition);\n                                           ^\nIn file included from missing-hash.cpp:1:\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/functional:61:\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/unordered_map:46:\nIn file included from /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable.h:35:\n/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/bits/hashtable_policy.h:1379:9: error: type 'const std::hash\u003cstd::pair\u003cint, int\u003e\u003e' does not provide a call operator\n        return _M_h1()(__k);\n               ^~~~~~~\n3 errors generated.\n```\n\u003c/details\u003e\n\nAnd here's the English-language explanation from `cwhy`:\n\n````\n% cwhy --- clang++ --std=c++20 -c missing-hash.cpp\nThe problem is that you are attempting to use `std::unordered_set`\nwith `std::pair\u003cint, int\u003e` as the key type. However, the standard\nlibrary does not provide a hash function specialization for\n`std::pair` out of the box, so the default constructor of the\nunordered set is deleted.\n\nTo resolve this, you'll need to provide a custom hash function for\n`std::pair\u003cint, int\u003e`. Here's an example of how you can define one:\n\n```cpp\nstruct PairHash {\n    template \u003ctypename T1, typename T2\u003e\n    std::size_t operator()(const std::pair\u003cT1, T2\u003e\u0026 pair) const {\n        std::hash\u003cT1\u003e hash1;\n        std::hash\u003cT2\u003e hash2;\n        return hash1(pair.first) ^ (hash2(pair.second) \u003c\u003c 1);\n    }\n};\n```\n\nThen, when instantiating the `std::unordered_set`, you can specify the\ncustom hash function:\n\n```cpp\nstd::unordered_set\u003cstd::pair\u003cint, int\u003e, PairHash\u003e visited;\n```\n\nWith this change, the code should now compile and work as expected.\n````\n\n\n### Rust\n\n```\n% cwhy --- cargo build\nThere are three issues:  1. There are two unused variables `x` in the\ncode.  2. The variable `x` is used after it has already been moved in\nthe call to `f(x)`, which takes ownership of `x`. 3. The function\n`f(x)` takes ownership of `x`, which may not be necessary and could be\nchanged to borrow the value instead.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplasma-umass%2Fcwhy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplasma-umass%2Fcwhy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplasma-umass%2Fcwhy/lists"}