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?

Author: usr2564301, 2014-08-10

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 ...).

 14
Author: cedlemo,
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

Więc ta dziwna część jest tutaj. struct _poire {[30] } jest uważany za typedef z 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.
 1
Author: Marc-O,
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