【问题标题】:Why are distinct Type objects being generated by Clang's parser for the same type?为什么 Clang 的解析器会为同一类型生成不同的 Type 对象?
【发布时间】:2015-04-27 16:37:06
【问题描述】:

我正在使用 Clang 的 API 为我正在编写的工具解析以下 sn-p:

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,而不是例如 X(这要归功于 using 指令)。为什么不更仔细地研究非规范类型(可能在调试器中)以查看它存储了哪些信息?

标签: c++ types clang abstract-syntax-tree


【解决方案1】:

原因在于 clang 如何解释你的函数的返回类型

NS::X foo();
^^^^^

According to the documentationElaboratedType

表示使用详细类型关键字(例如 struct S)或通过限定名称(例如 N::M::type 或两者兼有)引用的类型。

这意味着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();
};

您会收到所有三个指针的相同地址。

这种区别是设计使然,与符号的可见性无关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-13
    • 1970-01-01
    • 2018-01-29
    • 1970-01-01
    相关资源
    最近更新 更多