What are canonical types in Clang?

后端 未结 2 1453
长情又很酷
长情又很酷 2021-01-30 22:55

I have a simple header parser based on clang and I get the typedefs from some source.

struct _poire {
int g;
tomate rouge;
};
typedef struct _poire kudamono;
         


        
2条回答
  •  情深已故
    2021-01-30 23:46

    After further investigations and a question in the clang mailing list, I think I have figured out what is a canonical type.

    Firstly it 's important to not focus on the QualType in order to understand Canonical Type. Look this (code /pseudocode):

    source file :

    typedef struct _poire kudamono; 
    

    clang code :

    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 and t are not the same QualType even if they have the same string representation. QualType are used to associate qualifiers ("const", "volatile"...) with a clang type. There are a lot of Clang Types classes because clang needs to keep tracks of the user-specified types for diagnostics.( http://clang.llvm.org/docs/InternalsManual.html#the-type-class-and-its-subclasses and http://clang.llvm.org/doxygen/classclang_1_1Type.html )

    The clang types used depends heavily on the syntaxic sugars or modifiers associated with the C/C++ types in the source file.

    In the exemple above, the QualType t is associated with an ElaboratedType. This type allows to keep track of the type name as written in the source code. But the canonical QualType is associated with a RecordType.

    Another example: source file:

    typedef struct _poire kudamono;
    typedef kudamono tabemono;
    

    clang code :

    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
    

    Here we can see that the underlying type of the typedef is recorded as "kudamono" a TypedefType and not "struct _poire" an ElaboratedType.

    The canonical type for the TypedefType "kudamono" is a RecordType "struct _poire".

    Another examples that I have had from the clang mailing-list ( http://article.gmane.org/gmane.comp.compilers.clang.devel/38371/match=canonical+type ):

    Consider:

    int (x);
    

    The type of x is not a BuiltinType; it's a ParenType whose canonical type is a BuiltinType. And given

    struct X { int n; };
    struct X x;
    

    the type of x will probably be represented as an ElaboratedType whose canonical type is a RecordType.

    So the canonical Type in clang are classes of types that are not associated with any syntaxic sugars or modifiers or typedef (like BuiltinType or RecordType). Other classes of types (like ParentType, TypedefType or ElaboratedType) are used to keep tracks of the user type for diagnostics (error message ...).

提交回复
热议问题