Jakie są kanoniczne typy w Clang?
Mam prosty Parser nagłówka oparty na clang i dostaję typedefs z jakiegoś źródła.
struct _poire {
int g;
tomate rouge;
};
typedef struct _poire kudamono;
Po przetworzeniu tego mam clang::TypedefDecl
potem dostaję clang::QualType
z typedef z clang::TypedefDecl::getUnderlyingType()
Z QualType
jeśli użyję metody getAsString
mogę znaleźć "struct _poire" std::string
. Wszystko jest w porządku.
Problem polega na tym, że jeśli spróbuję sprawdzić, czy ten typ jest typem kanonicznym, z QualType::isCanonical()
, zwróci false.
Więc staram się uzyskać Typ kanoniczny z QualType::getCanonicalType().getAsString()
i zwraca ten sam ciąg "struct _poire".
Zgodnie z odniesieniem clang na typ http://clang.llvm.org/docs/InternalsManual.html#canonical-types , myślałem, że iscanonical () powinien zwrócić prawda, gdy nie występuje typedef.
Więc jakie są tak naprawdę typy kanoniczne?
2 answers
Po dalszych badaniach i Pytaniu na liście dyskusyjnej clang, myślę, że wiem, co to jest typ kanoniczny.
Po pierwsze ważne jest, aby nie skupiać się na QualType, aby zrozumieć typ kanoniczny. Look this (code /pseudocode):
Plik źródłowy:
typedef struct _poire kudamono;
Kod Clang:
QualType t = clang::TypedefDecl::getUnderlyingType()
t.getAsString() // "struct _poire"
t.isCanonical() // false
t.getTypePtr()->getTypeClassName() // ElaboredType
c = t.getCanonicalType()
c.getAsString() // "struct _poire"
c.isCanonical() // true
c.getTypePtr()->getTypeClassName() // RecordType
C i t nie są tym samym QualType, nawet jeśli mają taką samą reprezentację łańcuchową. Qualtype są używane do kojarzenia kwalifikatorów ("const", "volatile"...) z Typ clang. Istnieje wiele klas typów Clang, ponieważ clang musi przechowywać ślady typów określonych przez użytkownika do diagnostyki.( http://clang.llvm.org/docs/InternalsManual.html#the-type-class-and-its-subclasses i http://clang.llvm.org/doxygen/classclang_1_1Type.html )
Używane typy clang w dużej mierze zależą od cukrów składniowych lub modyfikatorów powiązanych z typami C / C++ w pliku źródłowym.
W exemple powyżej, QualType t jest związany z opracowanym typem. Ten typ pozwala na śledzenie nazwy typu zapisanej w kodzie źródłowym. Ale kanoniczny Typ QualType jest związany z typem RecordType.
Inny przykład: plik źródłowy:
typedef struct _poire kudamono;
typedef kudamono tabemono;
Kod Clang:
QualType t = clang::TypedefDecl::getUnderlyingType()
t.getAsString() // "kudamono"
t.isCanonical() // false
t.getTypePtr()->getTypeClassName() // TypedefType
c = t.getCanonicalType()
c.getAsString() // "struct _poire"
c.isCanonical() // true
c.getTypePtr()->getTypeClassName() // RecordType
Tutaj widzimy, że podstawowy typ typedef jest zapisywany jako" kudamono "TypedefType, a nie" struct _poire " rozwinięty Typ.
Typ kanoniczny dla TypedefType "kudamono" to typ rekordowy "struct _poire".
Kolejny przykład, który miałem z listy dyskusyjnej clang ( http://article.gmane.org/gmane.comp.compilers.clang.devel/38371/match=canonical + typ ):
Rozważmy:
int (x);
Typ x nie jest typem wbudowanym; jest to typ rodzica, którego kanonicznym typem jest typ Wbudowany. I podane
struct X { int n; };
struct X x;
Typ x będzie prawdopodobnie reprezentowany jako rozwinięty Typ, którego kanonicznym typem jest typ rekordu.
Więc kanonicznym typem w clang są klasy typów, które nie są powiązane z żadnymi cukrami składni, modyfikatorami lub typedef (jak BuiltinType lub RecordType). Inne klasy typów (jak ParentType, TypedefType lub ElaboratedType) służą do przechowywania ścieżek typu użytkownika do diagnostyki (komunikat o błędzie ...).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-13 19:54:00
Wygląda na to, że poruszyłeś interesującą kwestię. Coś wymyśliłem, ale skoro nie mogę teraz przetestować intuicji, nie mogę być w 100% pewien. W każdym razie oto co bym zrobił:
Jeśli przeanalizuję Twój kod (z małym rozszerzeniem, aby zadeklarować zmienną kudamono), oto co mogę powiedzieć z tego:
struct _poire {
int g;
char rouge; // tomate is probably one of your classes so I just changed the type of the field.
};
typedef struct _poire kudamono;
int maFonction(){
kudamono une_poire;
return 0;
}
Gdy typedef jest parsowany, oto, co otrzymujemy:
-TypedefDecl 0x23b4620 <line:5:1, col:23> kudamono 'struct _poire':'struct _poire'
Kiedy deklaruję zmienną typu kudamono
, Oto poniżej jej AST-dump:
-VarDecl 0x2048040 <col:2, col:11> une_poire 'kudamono':'struct _poire'
NB: możesz uzyskać zrzut AST swojego kodu za pomocą tej linii poleceń, może to być naprawdę przydatne, aby zrozumieć, jak kod będzie przetwarzany:
Clang-Xclang-AST-dump-std=c++11-fsyntax-tylko test.cpp (po prostu usuń -std = c++11, jeśli chcesz skompilować nazwa_pliku.C plik)
Teraz, z tego co rozumiem, zrobię porównanie pomiędzy VarDecl
i TypedefDecl
:
1°) to VarDecl
nazywa się une_poire i ma typ kudamono , który jest a typedef Z Typu struct _poire .
2°) to TypedefDecl
jest nazwane kudamono i ma typ struct _poire który jest a typedef Z Typu struct _poire
Zauważ, że próbowałem zrobić typedef z Typ Zwykły:
typedef int numbers;
I tym razem AST-dump daje:
TypedefDecl 0x25d9680 <line:7:1, col:13> numbers 'int'
, więc myślę, że parser może mieć pewne problemy z Handmade typów (zazwyczaj struktury).
Widzę jeden brudny sposób, aby wiedzieć, czy twój typ jest kanoniczny, czy nie (bez uzyskania fałszywych pozytywów lub fałszywych negatywów): {]}
Sprawdź, czy qualtype i kanoniczny QualType nie są tymi samymi
Nie wiem, czy proste ' = ' pomiędzy Qualtype
da false pozytywne lub fałszywe negatywy (ponieważ nie mogę przetestować), ale nadal można porównać nazwy typów z strcmp
Więc, podsumowując trochę:
- Twoje rozumienie kanonicznego typu jest w porządku.
- Clang wydaje się mieć pewne problemy z ręcznie robionymi typami, ale powinno być dobrze z Typedefem ze zwykłych typów(takich jak
typedef int int32_t
). - jeśli chcesz wiedzieć, czy typ jest kanoniczny, czy nie, możesz porównać nazwę typu i nazwę Typ kanoniczny, ale jest dość brudny. Na zwykłym typie, isCanonical () działa dobrze.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-11 13:08:06