我有一个基于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。
那么什么是真正的规范类型?
答案 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-subclasses和http://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 文件)
现在,根据我的理解,我会在VarDecl
和TypedefDecl
之间进行比较:
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}进行比较}}
所以,总结一下:
typedef int int32_t
)应该没问题。