dtolnay / clang-ast

Deserialization logic for efficiently processing Clang's `-ast-dump=json` format
Apache License 2.0
132 stars 13 forks source link

Reset threadlocal vars when finished deserializing Node #5

Closed dtolnay closed 3 years ago

dtolnay commented 3 years ago

Without this, data can bleed over from one top-level deserialization to the next, resulting in the same input being deserialized inconsistently in different ways. For example previously the assertion in the following repro fails, meaning deserializing the same input object twice produced two unequal results:

use clang_ast::SourceLocation;
use serde::Deserialize;
use serde_json::json;

type Node = clang_ast::Node<Clang>;

#[derive(Deserialize, Debug)]
struct Clang {
    loc: Option<SourceLocation>,
}

fn main() {
    let j = json!({
        "id": "0x1",
        "kind": "TranslationUnitDecl",
        "inner": [
            {
                "id": "0x2",
                "kind": "CXXUnresolvedConstructExpr",
                "loc": {
                    "offset": 1,
                    "col": 0,
                    "tokLen": 0,
                },
            },
            {
                "id": "0x3",
                "kind": "CXXUnresolvedConstructExpr",
                "loc": {
                    "offset": 1,
                    "line": 1,
                    "col": 0,
                    "tokLen": 0,
                },
            },
        ],
    });

    let first = Node::deserialize(&j).unwrap();
    let second = Node::deserialize(&j).unwrap();
    println!("{:#?}\n{:#?}", first, second);
    assert_eq!(
        first.inner[0].kind.loc.as_ref().unwrap().spelling_loc.as_ref().unwrap().line,
        second.inner[0].kind.loc.as_ref().unwrap().spelling_loc.as_ref().unwrap().line,
    );
}