我有以下代码段,正在使用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_typereturn_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 docsthe 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/

10-11 00:20