2016-05-25 37 views
7

Czy można użyć clang matchers do identyfikacji sekwencji wzorców w programie?Używanie uchwytów klangowych do wykrywania sekwencji wzorców

Na przykład muszę znaleźć przypadki, w których wzór 1 ma miejsce przed wzorzec2.

Na przykład:

Wzorzec1 = przypisanie wartości do wskaźnika P
pattern2 = dereferencji wskaźnik P

mogę zidentyfikować przypadki, że wzorzec1 i pattern2 wydarzy się w kodzie, ale jest to możliwe, aby określić zamawianie? (powiedzmy, że pattern1 musi się zdarzyć przed pattern2 i pasuje tylko do tych przypadków) Dzięki!

Odpowiedz

1

Prawidłowe odpowiedzi

w rzeczywistości ASTs postępowe dla sekwencji wzornictwo (który jest podstawą analizy statycznej) nie jest to właściwe podejście, ponieważ nie wiem, czy sprawozdanie pattern1 jest rzeczywiście się wydarzy przed pattern2

Rozważmy

int foo() { 
     int a = 0; 
     int *b; 
     int c = -1; 
     if(c < 0) goto fixit; 
nowhat: 
     b = &a; 
fixit: 
     c = *b; 
     goto nowhat; 
} 

Jak widać AST nie pomoże tu jednak CFG jest właściwa rzecz do użycia.

nieco z odpowiedzią wykorzystaniem ASTs

Jeśli spojrzeć na przemierzanie dopasowujących w AST (V6.0.0) są, prawie, hierarchiczny charakter. Chcesz rozszerzyć dopasowanie, aby szukać rodzeństwa.

Wiele z tego, co zamierzam przyjąć, zakłada, że ​​wiesz, jak zaimplementować niestandardowy matematyczny system AST. Jeśli nie, wyjaśniono to dość ładnie przez Manu Sáncheza w jego poście na blogu Writing AST Matchers for libclang.

Nie wiem, czy on dostanie się faktycznie pisanie dopasowywania rodzeństwo, ale on przychodzi bardzo blisko niego, więc zacząć tam i wtedy trzeba zaimplementować coś podobnego do tego:

powiedzmy podany kod:

class P {}; class Q {}; class R {}; 

Chcemy być w stanie zrobić coś takiego:

(matcher = recordDecl(hasName("P"), \ 
     hasNextSibling(recordDecl(hasName("R"))))` 

można łączyć matchesChild i matchesParent w AstMatchFinder i przechodzą przez dzieci rodzica aktualnego kursora (będą to rodzeństwo: P). Przeczytaj przypisy, ponieważ musisz zaimplementować BoundCursors, aby uniknąć zbierania rekursji.