ltcmelo / psychec

A compiler frontend for the C programming language
BSD 3-Clause "New" or "Revised" License
529 stars 39 forks source link
c c-language clanguage compiler compiler-frontend language-semantics parser parsing parsing-library program-analysis static-analysis type-inference

C language (draft) proposal Enabling Generic Functions and Parametric Types in C; prototype available here.

Psyche-C

Psyche-C is a compiler frontend for the C language. It is designed as a library, with a focus on the implementation of static analysis tools of C programs, without requiring understanding of their build setup. Bellow are the main characteristics of Psyche-C:

Library and API

Psyche-C's native API is in C++, but APIs for other languages are planned.

void analyse(const SourceText& srcText, const FileInfo& fi)
{
    ParseOptions parseOpts;
    parseOpts.setAmbiguityMode(AmbiguityMode::DisambiguateAlgorithmically);

    auto tree = SyntaxTree::parseText(srcText,
                                      TextPreprocessingState::Preprocessed,
                                      TextCompleteness::Fragment,
                                      parseOpts,
                                      fi.fileName());

    auto compilation = Compilation::create("code-analysis");
    compilation->addSyntaxTree(tree.get());

    AnalysisVisitor analysis(tree.get(), compilation->semanticModel(tree.get()));
    analysis.run(tree->translationUnitRoot());
}
SyntaxVisitor::Action AnalysisVisitor::visitFunctionDefinition(const FunctionDefinitionSyntax* node) override
{
    const sym = semaModel->declaredSymbol(node);
    if (sym->kind() == SymbolKind::Function) {
        const FunctionSymbol* funSym = sym->asFunction();
        // ...
    }
    return Action::Skip;
}

The cnippet Driver

Psyche-C comes with the cnippet driver and it can be used as an ordinary parser for C snippets. For instance, if you compile the snippet below with cnippet, you'll see a diagnostic similar to the one you'd see with GCC or Clang.

void f()
{
    int ;
}
~ cnip test.c
test.c:4:4 error: declaration does not declare anything
int ;
    ^

Type Inference

Psyche-C can optionally (so far only available in the original branch) infer the missing types of a C snippet. For instance, for the snippet below, Psyche-C can infer a (compilable) declaration for T an synthesize it during compilation.

void f()
{
    T v = 0;
    v->value = 42;
    v->next = v;
}
typedef struct TYPE_2__ TYPE_1__;
struct TYPE_2__ 
{
    int value;
    struct TYPE_2__* next;
} ;
typedef TYPE_1__* T;

You might want to use this functionality to:

Documentation and Resources

Building and Testing

Except for type inference, which is written in Haskell, Psyche-C is written in C++17; cnippet is written in Python 3.

To build:

cmake CMakeLists.txt && make -j 4

To run the tests:

./test-suite

Related Publications

Of Psyche-C itself:

That use Psyche-C: