我有以下代码段,正在使用Clang的API对其所编写的工具进行解析:
namespace NS
{
struct X
{
};
}
struct Y
{
NS::X foo();
};
I use a (type that derives from)
RecursiveASTVisitor
to visit the AST。当VisitCXXRecordDecl()
函数被调用时,我可以获得指向已声明的Type
对象的指针:bool VisitCXXRecordDecl(CXXRecordDecl* const decl)
{
auto declared_type = decl->getTypeForDecl();
// ...
}
同样,当调用
VisitCXXMethodDecl()
函数时,我可以得到一个指向函数返回Type
的指针,如下所示:bool VisitCXXMethodDecl(CXXMethodDecl* const func)
{
auto return_type = func->getReturnType().getTypePtr();
// ...
}
令我惊讶的是,以上两个函数中的变量
declared_type
和return_type
没有指向相同的Type
对象。现在,我确实知道规范类型,并且确实,如果我在
VisitCXXMethodDecl()
中编写以下内容,我将获得一个指向相同Type
对象declared_type
的指针:auto canonical_type = return_type->getCanonicalTypeInternal().getTypePtr();
// Now `canonical_type` holds a pointer to the same Type object as the
// `declared_type` variable inside VisitCXXRecordDecl().
但是,我认为仅当涉及类型别名时,类型才具有与自身不同的规范类型(至少这是我从the Doxygen docs和the CFE Internals Manual收集的信息)。我不确定在这里创建两个
Type
对象的原因是什么,这使我相信我不了解Type
对象和规范类型在Clang设计中的作用。 最佳答案
原因是由于clang如何解释函数的返回类型
NS::X foo();
^^^^^
According to the documentation,一个
ElaboratedType
这意味着
declared_type
指向RecordType
对象,但return_type
实际上指向ElaboratedType
。如果您已将此源代码传递给访问者:
namespace NS
{
struct X
{
};
}
using namespace NS;
// struct NS::X -> heavily sugar'd
// NS::X -> sugar'd
// struct X -> sugar'd
// X -> not sugar'd
struct Y
{
X foo();
};
您将为所有三个指针收到相同的地址。
这种区别是设计使然,与符号的可见性无关。
关于c++ - 为什么Clang的解析器会针对同一类型生成不同的Type对象?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29901376/