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.
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.
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());
I have provided code in this SO answer which contains parsing code for clang_getCursorUSR
(based on the source code of LLVM 3.1).