Clang的规范类型是什么?

时间:2014-08-10 17:12:49

标签: c++ c clang llvm clang++

我有一个基于clang的简单头解析器,我从某个源获取typedef。

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

解析完后,我有一个clang::TypedefDecl然后我得到clang::QualType的{​​{1}} {/ 1}}

使用clang::TypedefDecl::getUnderlyingType()如果我使用QualType方法,我可以找到“struct _poire”getAsString。这一切都很好。

问题是,如果我尝试查看此类型是否为规范类型,使用std::string,则返回false。

所以我尝试使用QualType::isCanonical()获取规范类型,并返回相同的字符串“struct _poire”。

根据类型http://clang.llvm.org/docs/InternalsManual.html#canonical-types的clang引用,我认为isCanonical()应该返回 如果不涉及typedef,则为true。

那么什么是真正的规范类型?

2 个答案:

答案 0 :(得分:17)

经过进一步的调查和clang邮件列表中的问题后,我想我已经弄清楚什么是规范类型。

首先,重点关注QualType以了解Canonical Type是非常重要的。看这个(代码/伪代码):

源文件:

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和t不是相同的QualType,即使它们具有相同的字符串表示形式。 QualType用于将限定符(" const"," volatile" ...)与clang类型相关联。有很多Clang Types类,因为clang需要跟踪用户指定的类型以进行诊断。(http://clang.llvm.org/docs/InternalsManual.html#the-type-class-and-its-subclasseshttp://clang.llvm.org/doxygen/classclang_1_1Type.html

使用的clang类型在很大程度上取决于源文件中与C / C ++类型相关的语法糖或修饰符。

在上面的例子中,QualType t与ElaboratedType相关联。此类型允许跟踪源代码中编写的类型名称。但规范的QualType与RecordType相关联。

另一个例子: 源文件:

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

在这里我们可以看到typedef的基础类型被记录为" kudamono"一个TypedefType而不是" struct _poire" ElaboratedType。

TypedefType" kudamono"的规范类型是一个RecordType" struct _poire"。

我从clang邮件列表(http://article.gmane.org/gmane.comp.compilers.clang.devel/38371/match=canonical+type)获得的另一个例子:

考虑:

int (x);

x的类型不是BuiltinType;它是一个ParenType,其规范类型是BuiltinType。并给出了

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

x的类型可能表示为ElaboratedType,其规范类型为RecordType。

因此,clang中的规范类型是与任何语法糖或修饰符或typedef(如BuiltinType或RecordType)无关的类型类。其他类型的类型(如ParentType,TypedefType或ElaboratedType)用于保存用户类型的跟踪以进行诊断(错误消息...)。

答案 1 :(得分:1)

似乎你提出了一个有趣的观点。我已经找到了一些东西,但由于我现在无法真正测试我的直觉,所以我无法100%肯定。无论如何,这就是我要做的事情:

如果我解析你的代码(稍微扩展一下来声明一个kudamono变量),我可以这样说:

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;
}

解析typedef时,以下是产生的结果:

-TypedefDecl 0x23b4620 <line:5:1, col:23> kudamono 'struct _poire':'struct _poire'

当我声明类型为kudamono的变量时,这里的AST转储下面是

-VarDecl 0x2048040 <col:2, col:11> une_poire 'kudamono':'struct _poire'

注意:您可以使用此命令行获取代码的AST转储,了解如何解析代码非常方便:

clang -Xclang -ast-dump -std = c ++ 11 -fsyntax-only test.cpp (如果要编译,只需删除-std = c ++ 11 file_name.c 文件)

现在,根据我的理解,我会在VarDeclTypedefDecl之间进行比较:

1°)此VarDecl名为 une_poire ,其类型为 kudamono a typedef 来自 > struct _poire

2°)此TypedefDecl名为 kudamono ,类型为 struct _poire a typedef 来自< em> struct _poire

所以,奇怪的部分就在这里。 struct _poire 被视为来自 struct _poire 的typedef。

你会注意到我尝试使用通常的类型制作一个typedef:

typedef int numbers;

而这一次,AST-dump产生了:

TypedefDecl 0x25d9680 <line:7:1, col:13> numbers 'int',所以我猜解析器可能会遇到手工类型(通常是结构)的麻烦。

我可以看到一种肮脏的方式来知道你的类型是否规范(没有得到误报或漏报):

检查QualType和规范QualType是否相同

我不知道Qualtype之间的简单'='是否会产生误报或漏报(因为我无法测试),但您仍然可以将类型的名称与{{3}进行比较}}

所以,总结一下:

  • 您对规范类型的理解很好。
  • Clang似乎在手工制作的类型上遇到了一些麻烦,但对于普通类型的Typedef(例如typedef int int32_t)应该没问题。
  • 当您想知道类型是否规范时,您可以比较类型的名称和规范类型的名称,但它非常脏。在通常的类型上,isCanonical()效果很好。