如何找出一个成员函数是const或volatile与libcla

如何找出一个成员函数是const或volatile与libcla

本文介绍了如何找出一个成员函数是const或volatile与libclang?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有种 CXCursor 的实例 CXCursor_CXXMethod 。我想了解该功能是否适用常量挥发性,例如:

I have an instance of CXCursor of kind CXCursor_CXXMethod. I want to find out if the function is const or volatile, for example:

class Foo {
public:
    void bar() const;
    void baz() volatile;
    void qux() const volatile;
};

我找不到任何libclang的文档中非常有用。我试图 clang_isConstQualifiedType clang_isVolatileQualifiedType 但这些似乎总是返回 0 在C ++成员函数的类型。

I could not find anything useful in the documentation of libclang. I tried clang_isConstQualifiedType and clang_isVolatileQualifiedType but these always seem to return 0 on C++ member function types.

推荐答案

我能想到的两种方法:

使用 libclang 词法分析器

Using the libclang lexer

出现在对我的作品;它使用了 libclang 标记生成器,以打散方法声明,然后记录的方法括号之外的任何关键字。

The code which appears in this SO answer works for me; it uses the libclang tokenizer to break a method declaration apart, and then records any keywords outside of the method parentheses.

它做的的访问code的AST,并尽可能我可以告诉不涉及语法分析器都没有。如果你确信code您调查是正确的C ++,我认为这种做法是安全的。

It does not access the AST of the code, and as far as I can tell doesn't involve the parser at all. If you are sure the code you investigate is proper C++, I believe this approach is safe.

劣势的:该解决方案似乎没有考虑到preprocessing指令,因此code必须首先处理(例如,通过通过CPP )。

Disadvantages: This solution does not appear to take into account preprocessing directives, so the code has to be processed first (e.g., passed through cpp).

举例code(解析必须是第一个参数到您的程序,例如文件 ./ a.out的bla.cpp

Example code (the file to parse must be the first argument to your program, e.g. ./a.out bla.cpp):

#include "clang-c/Index.h"
#include <string>
#include <set>
#include <iostream>

std::string GetClangString(CXString str)
{
  const char* tmp = clang_getCString(str);
  if (tmp == NULL) {
    return "";
  } else {
    std::string translated = std::string(tmp);
    clang_disposeString(str);
    return translated;
  }
}

void GetMethodQualifiers(CXTranslationUnit translationUnit,
                         std::set<std::string>& qualifiers,
                         CXCursor cursor) {
  qualifiers.clear();

  CXSourceRange range = clang_getCursorExtent(cursor);
  CXToken* tokens;
  unsigned int numTokens;
  clang_tokenize(translationUnit, range, &tokens, &numTokens);

  bool insideBrackets = false;
  for (unsigned int i = 0; i < numTokens; i++) {
    std::string token = GetClangString(clang_getTokenSpelling(translationUnit, tokens[i]));
    if (token == "(") {
      insideBrackets = true;
    } else if (token == "{" || token == ";") {
      break;
    } else if (token == ")") {
      insideBrackets = false;
    } else if (clang_getTokenKind(tokens[i]) == CXToken_Keyword &&
             !insideBrackets) {
      qualifiers.insert(token);
    }
  }

  clang_disposeTokens(translationUnit, tokens, numTokens);
}

int main(int argc, char *argv[]) {
  CXIndex Index = clang_createIndex(0, 0);
  CXTranslationUnit TU = clang_parseTranslationUnit(Index, 0,
          argv, argc, 0, 0, CXTranslationUnit_None);

  // Set the file you're interested in, and the code location:
  CXFile file = clang_getFile(TU, argv[1]);
  int line = 5;
  int column = 6;
  CXSourceLocation location = clang_getLocation(TU, file, line, column);
  CXCursor cursor = clang_getCursor(TU, location);

  std::set<std::string> qualifiers;
  GetMethodQualifiers(TU, qualifiers, cursor);

  for (std::set<std::string>::const_iterator i = qualifiers.begin(); i != qualifiers.end(); ++i) {
    std::cout << *i << std::endl;
  }

  clang_disposeTranslationUnit(TU);
  clang_disposeIndex(Index);
  return 0;
}

使用的 libclang 统一符号解析(USR)

Using libclang's Unified Symbol Resolution (USR)

该方法包括使用解析器,并提取从AST预选赛信息。

This approach involves using the parser itself, and extracting qualifier information from the AST.

优点的:似乎为code。与preprocessor指令,至少对于简单的情况下工作。

Advantages: Seems to work for code with preprocessor directives, at least for simple cases.

劣势的:我的解决方案解析USR,这是无证,并在未来可能会改变。不过,这是很容易编写单元测试,以防止这一点。

Disadvantages: My solution parses the USR, which is undocumented, and might change in the future. Still, it's easy to write a unit-test to guard against that.

看看 $(CLANG_SRC)/tool​​s/libclang/CIndexUSRs.cpp ,它包含了code,它生成一个USR,因此,所包含的信息解析字符串USR要求。具体来说,线523-529(LLVM中3.1的源代码从下载)为预选赛的一部分。

Take a look at $(CLANG_SRC)/tools/libclang/CIndexUSRs.cpp, it contains the code that generates a USR, and therefore contains the information required to parse the USR string. Specifically, lines 523-529 (in LLVM 3.1's source downloaded from www.llvm.org) for the qualifier part.

某处添加以下功能:

void parseUsrString(const std::string& usrString, bool* isVolatile, bool* isConst, bool *isRestrict) {
  size_t bangLocation = usrString.find("#");
  if (bangLocation == std::string::npos || bangLocation == usrString.length() - 1) {
    *isVolatile = *isConst = *isRestrict = false;
    return;
  }
  bangLocation++;
  int x = usrString[bangLocation];

  *isConst = x & 0x1;
  *isVolatile = x & 0x4;
  *isRestrict = x & 0x2;
}

的main()

CXString usr = clang_getCursorUSR(cursor);
const char *usr_string = clang_getCString(usr);
std::cout << usr_string << "\n";
bool isVolatile, isConst, isRestrict;
parseUsrString(usr_string, &isVolatile, &isConst, &isRestrict);
printf("restrict, volatile, const: %d %d %d\n", isRestrict, isVolatile, isConst);
clang_disposeString(usr);

运行在美孚:: qux()

#define BLA const

class Foo {
public:
    void bar() const;
    void baz() volatile;
    void qux() BLA volatile;
};

产生的预期效果。

produces the expected result of

c:@C@Foo@F@qux#5
restrict, volatile, const: 0 1 1

买者的:你可能已经注意到了 libclang 的源suggets我的code应该 isVolatile = X'放大器; 0X2 ,而不是为0x4 ,所以它可能是你应该0X2替换为0x4的情况。这是可能我的实现(OS X)已经取代他们。

Caveat: you might have noticed that libclang's source suggets my code should be isVolatile = x & 0x2 and not 0x4, so it might be the case you should replace 0x4 with 0x2. It's possible my implementation (OS X) has them replaced.

这篇关于如何找出一个成员函数是const或volatile与libclang?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 19:22