Clang中的规范类型是什么?
What are canonical types in Clang?
我有一个基于clang的简单头解析器,我从一些来源获得类型定义。
struct _poire {
int g;
tomate rouge;
};
typedef struct _poire kudamono;
解析后,我有一个clang::TypedefDecl
,然后我得到clang::TypedefDecl::getUnderlyingType()
类型定义的clang::QualType
与QualType
,如果我使用getAsString
方法,我可以找到"struct _poire"std::string
。这一切都很好。
问题是,如果我尝试查看该类型是否为规范类型,使用QualType::isCanonical()
,它返回false。
所以我尝试用QualType::getCanonicalType().getAsString()
获得规范类型,它返回相同的字符串"struct _poire"。
根据对http://clang.llvm.org/docs/InternalsManual.html#canonical-types类型的clang引用,我认为isCanonical()应该返回当不涉及typedef时为True。
那么什么是真正的规范类型呢?
经过进一步的调查和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-subclasses and http://clang.llvm.org/doxygen/classclang_1_1Type.html)
所使用的clang类型在很大程度上取决于源文件中与C/c++类型相关的合成糖或修饰符。
在上面的例子中,QualType t与一个detailatedtype相关联。这种类型允许跟踪源代码中所写的类型名称。但是规范的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的底层类型被记录为TypedefType中的"kudamono",而不是struct _poire中的"explatedtype"。
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的类型将可能被表示为一个标准类型为RecordType的elaboration type。
所以clang中的规范类型是不与任何语法糖或修饰符或类型定义(如BuiltinType或RecordType)相关联的类型类。其他类型类(如ParentType、TypedefType或elaboration type)用于跟踪用户类型以进行诊断(错误消息…)。
看来你提出了一个有趣的观点。我已经弄明白了一些事情,但由于我现在无法测试我的直觉,所以我不能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;
}
解析typepedef时,得到的结果如下:
-TypedefDecl 0x23b4620 <line:5:1, col:23> kudamono 'struct _poire':'struct _poire'
当我声明一个kudamono
类型的变量时,下面是它的AST-dump:
-VarDecl 0x2048040 <col:2, col:11> une_poire 'kudamono':'struct _poire'
注意:你可以使用这个命令行获得代码的AST转储,它可以非常方便地理解你的代码将如何被解析:
clang -Xclang -ast-dump -std=c++11 -fsyntax-only test.cpp(如果要编译file_name.c文件,只需删除-std=c++11)
现在,根据我的理解,我将VarDecl
和TypedefDecl
进行比较:
1°)这个VarDecl
被命名为une_poire,并且具有类型kudamono,这是从类型struct _poire派生的类型。
TypedefDecl
被命名为kudamono,并且具有类型struct _poire,这是从类型struct _poire
派生的类型。所以,奇怪的部分在这里。struct _poire被认为是来自struct _poire的类型定义。
你会注意到,我试图用通常的类型创建一个typedef:
typedef int numbers;
这一次,AST-dump产生:
TypedefDecl 0x25d9680 <line:7:1, col:13> numbers 'int'
,所以我猜解析器可能有一些手工类型(通常是结构体)的麻烦。
我可以看到一个肮脏的方法来知道你的类型是否规范(不得到假阳性或假阴性):
检查QualType和标准的QualType是否相同
我不知道Qualtype
之间的简单'='是否会产生假阳性或假阴性(因为我无法测试),但您仍然可以将类型的名称与strcmp
那么,总结一下:
- 你对规范类型的理解很好。
- Clang似乎有一些手工类型的麻烦,但它应该是好的从通常的类型(如
typedef int int32_t
) Typedef。 - 当您想知道一个类型是否规范时,您可以比较类型的名称和规范类型的名称,但这是相当肮脏的。对于通常的类型,isCanonical()工作得很好。
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- 如何声明一个标准::提升直方图的向量?提升直方图的类型是什么?
- 类名后跟括号的类型是什么
- std::chrono::duration::count函数的实际结果类型是什么
- c++运算符重载-我实际返回的操作数类型是什么
- 运算符和返回类型是什么意思?
- 指向 2D 数组的指针的类型是什么?
- RSA_verify中预期的数据类型是什么,无法验证从 Java 生成的签名
- 共享_ptr中多功能数组的类型是什么
- 构造函数的类型是什么?
- 字符串中单个字符作为数组的数据类型是什么
- 该结构继承的类型是什么
- 如果我获得Integer和Double的产品,输出的数据类型是什么
- C 中被视为可可的类型是什么
- 当函数采用右值引用时,函数中该变量的类型是什么?
- STD :: SETW,STD :: SETFILL等的真实返回类型是什么?
- 模板类中引用的引用的类型是什么
- const自动参考绑定到(NULL)指针 - 实际类型是什么
- 包含通过引用捕获的 lambda 函数的"variable"的类型是什么?
- 通过插座发送的内容的数据类型是什么