Clang Const Qualified C++ Method

2019-04-29 22:31发布

问题:

How would I test if a c++ method is const qualified in clang?

For example::

class Inner{
public:
    int i;
    Inner();
    float inner_method() const;
};

I am using the clang-c library and I have tried using clang_isConstQualifiedType on the inner_method node. however this returns false.

I don't mind if the answer uses the clang c++ headers.

回答1:

In the C++ interface, the way to check this is using CXXMethodDecl::getTypeQualifiers(), or using FunctionProtoType::getTypeQuals() (depending on whether you have the declaration or the type). The Qualifiers::Const bit indicates whether the method (or method type) is const.

In the libclang C API, this information seems to only be used in the implementation of getCursorUSR, whose result is not intended to be parsed, so using the C++ API or submitting a patch to add this functionality to the C API are the best options.



回答2:

I had the same problem, but I needed to do this without the C++ API. I put my solution below for future reference. The idea is to use the libclang tokenization feature to loop over all the qualifiers of the method:

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);
}

Whether a method indexed by cursor is declared const can then be checked through the following commands:

std::set<std::string> qualifiers;
GetMethodQualifiers(translationUnit, qualifiers, cursor);
bool isConstant = (qualifiers.find("const") != qualifiers.end());


回答3:

I have provided code in this SO answer which contains parsing code for clang_getCursorUSR (based on the source code of LLVM 3.1).



标签: clang