c++cclangclang++libclang

Why does libclang mis-parse C++ headers with a .h prefix?


I tried to parse a c++ header with libclang, but the parser only parsed the class name - and show its type as VarDec1. When the file extension changed from .h to .cpp, it just works fine. I couldn't find the answer after days of searching, can anyone help me to solve this problem?

the following is parser.cpp:

#include <iostream>
#include <clang-c/Index.h>  // This is libclang.
using namespace std;

ostream& operator<<(ostream& stream, const CXString& str)
{
  stream << clang_getCString(str);
  clang_disposeString(str);
  return stream;
}

int main()
{
  CXIndex index = clang_createIndex(0, 0);
  CXTranslationUnit unit = clang_parseTranslationUnit(
    index,
    "tt.h", nullptr, 0,
    nullptr, 0,
    CXTranslationUnit_None);
  if (unit == nullptr)
  {
    cerr << "Unable to parse translation unit. Quitting." << endl;
    exit(-1);
  }

  CXCursor cursor = clang_getTranslationUnitCursor(unit);
  clang_visitChildren(
    cursor,
    [](CXCursor c, CXCursor parent, CXClientData client_data)
    {
      cout << "Cursor '" << (clang_getCursorSpelling(c)) << "' of kind '"
        <<(clang_getCursorKindSpelling(clang_getCursorKind(c))) << "'\n";
      return CXChildVisit_Recurse;
    },
    nullptr);

  clang_disposeTranslationUnit(unit);
  clang_disposeIndex(index);
  fgetc(stdin);
}

and the following is tt.h:

class MyClass
{
public:
  int field;
  virtual void method() const = 0;

  static const int static_field;
  static int static_method(int a1);
};

class MyClass2
{
public:
  int field;
  virtual void method() const = 0;

  static const string static_field;
  static int static_method(int a1, string a2);
};

And I use the following compile command:

clang++ main.cpp -lclang

When the file extension is .h: parse header

When the file extension is .cpp: enter image description here


Solution

  • tt.h is considered by libclang to be a C file, not a C++ file, since the filetype is strictly based on the extension. If you want it to be parsed as a C++ file, you need to use an extension that libclang recognizes as a C++ extension (I suppose .hh would work), or you need to explicitly set the extension using the command_line_args/num_command_line_args parameters:

    /* Untested */
    const char *command_line_args[] = {"-x", "c++", 0};
    CXTranslationUnit unit = clang_parseTranslationUnit(
        index,
        "tt.h", 
        command_line_args,
        (sizeof command_line_args / sizeof *command_line_args) - 1,
        nullptr, 0,
        CXTranslationUnit_None);
    

    You might also want to extract and print the diagnostic messages from the CXTranslationUnit. Probably, that would have given you a good clue about what was going on. See clang_getDiagnostic.