Get list of methods in class using clang - c++

In common IDEs (pick one) you often have an outline view showing you the list of methods for a specific class.
Suppose I have a C++ interface class in IFoo.h that looks like this:
#ifndef IFOO_H_
#define IFOO_H_
class IFoo {
public:
virtual ~IFoo() {}
virtual void bar() = 0;
};
#endif
How (programmatically) can I get such an IDE outliner list for my IFoo.h file above using maybe the clang libraries? For a first start, it would help if I can get a list of names of functions.
I specifically intend to use clang, so any help on how to analyze the my header file with clang would be really appreciated.
Meanwhile I will have a look at the clang tutorial here: https://github.com/loarabia/Clang-tutorial
Thanks in advance for your help.

I went through this tutorial http://clang.llvm.org/docs/LibASTMatchersTutorial.html and found some pretty helpful stuff there, this is what I came up with:
I had to rename my file from IFoo.h to IFoo.hpp to be detected as Cxx and not C code.
I had to call my program with -x c++ to have my IFoo.h file being recognized as C++ code rather than C code (clang interprets *.h files as C by default:
~/Development/llvm-build/bin/mytool ~/IFoo.h -- -x c++
This is my code to dump all virtual functions from the provided class:
// Declares clang::SyntaxOnlyAction.
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "clang/ASTMatchers/ASTMatchers.h"
// Declares llvm::cl::extrahelp.
#include "llvm/Support/CommandLine.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include <cstdio>
using namespace clang;
using namespace clang::ast_matchers;
using namespace clang::tooling;
using namespace llvm;
DeclarationMatcher methodMatcher = methodDecl(isVirtual()).bind("methods");
class MethodPrinter : public MatchFinder::MatchCallback {
public :
virtual void run(const MatchFinder::MatchResult &Result) {
if (const CXXMethodDecl *md = Result.Nodes.getNodeAs<clang::CXXMethodDecl>("methods")) {
md->dump();
}
}
};
// CommonOptionsParser declares HelpMessage with a description of the common
// command-line options related to the compilation database and input files.
// It's nice to have this help message in all tools.
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
// A help message for this specific tool can be added afterwards.
static cl::extrahelp MoreHelp("\nMore help text...");
int main(int argc, const char **argv) {
cl::OptionCategory cat("myname", "mydescription");
CommonOptionsParser optionsParser(argc, argv, cat, 0);
ClangTool tool(optionsParser.getCompilations(), optionsParser.getSourcePathList());
MethodPrinter printer;
MatchFinder finder;
finder.addMatcher(methodMatcher, &printer);
return tool.run(newFrontendActionFactory(&finder));
}
The output looks like this, when passed the IFoo.h file:
CXXDestructorDecl 0x1709c30 <~/IFoo.h:5:3, col:20> ~IFoo 'void (void)' virtual
`-CompoundStmt 0x1758128 <col:19, col:20>
CXXMethodDecl 0x1757e60 <~/IFoo.h:6:3, col:24> bar 'void (void)' virtual pure

Related

VSCode C++ : triggering creation of class member function definition automatically

Consider Main.cpp:
//Main.cpp
#include "Main.h"
int main(){
class SIMPLE smpl;
smpl.setval(10);
smpl.setname();
smpl.printname();
}
and Main.h thus:
//Main.h
#pragma once
#include <iostream>
#include <string>
#include <vector>
class SIMPLE {
public:
int retval() const { return val; }
void setval(int i) { val = i; }
void setname();
void printname();
private:
int val;
std::string name;
};
The member functions setname() and printname() are missing definitions. VSCode Intellisense does not seem to be able to warn the user about this. See figure below which does not have any squiggles:
Visual Studio IDE, on the other hand, is able to point out the missing definitions via squiggles and allows for creation of the definition in the implementation file directly from the header file. See gif image below:
Is there a way to have VSCode cpptools extension provide these features via some settings, perhaps?

Calling parent's method

I'm kinda newbie to all this c++ stuff, so this probably is a beginner's problem:
ListScreen.h
#ifndef _LISTSCREEN_H_
#define _LISTSCREEN_H_
#include "MAUI/Screen.h"
namespace CoolPlaces {
namespace Views {
using namespace MAUI;
class ListScreen : public Screen {
public:
ListScreen();
~ListScreen();
void keyPressEvent(int keyCode, int nativeCode) {}
void keyReleaseEvent(int keyCode, int nativeCode) {}
void pointerPressEvent(MAPoint2d point) {}
void pointerReleaseEvent(MAPoint2d point) {}
void pointerMoveEvent(MAPoint2d point) {}
void show();
};
}
}
#endif //_LISTSCREEN_H_
ListScreen.cpp
#include "MAUI/Screen.h"
#include "ListScreen.h"
using namespace MAUI;
using namespace CoolPlaces::Views;
void ListScreen::show() {
Screen::show();
};
I'm getting this error: D:\MosyncProjects\Views\ListScreen.cpp:22: Error: Unresolved symbol '__ZN4MAUI6Screen4showEv' line 22 in this Screen::show(); call (for purpose of this topic I removed some code). So what exactly am I doing wrong here?
You're including the header file, which tells that the function Screen::show() exists, but probably not linking the library, which has the implementation.
See this page: http://www.mosync.com/docs/sdk/cpp/guides/libs/working-with-mosync-libraries/index.html
Specifically:
As well as referencing the header files in your application code, you also need to specify the actual libraries that you want to use in the project's Build Settings (Project > Properties > MoSync Project > Build Settings):
It looks like maui.lib should contain the screen code.

'Error: expected a type' creating a new instance

I have a problem and I hope you can help me.
I'm creating a C++ program which is running on linux.
I have defined two classes, where the main one is called Downloader and looks like this:
#ifndef __DOWNLOADER_H__
#define __DOWNLOADER_H__
#include "configDownloader.h"
#include "mailServer.h"
#include <logger.h>
using namespace ObjectModel;
namespace Downloader
{
class Downloader
{
private:
...
MailServer *m_mailServer;
public:
Downloader(char* configFileName);
...
};
}
#endif
In the constructor of this class, I have tried to create a new instance of the class MailServer, which I defined into the same Namespace. The code of MailServer looks this way:
#ifndef __MAILSERVER_H__
#define __MAILSERVER_H__
#include <stdio.h>
#include <list>
#include <mail.h>
using namespace std;
using namespace ObjectModel;
namespace Downloader
{
class MailServer
{
private:
list<Mail> m_mails;
char *m_username;
char *m_password;
public:
MailServer();
~MailServer();
void Open(char *username,char *password);
bool SaveEmails(char *pathFiles);
void Close();
};
}
#endif
The constructor of this class is defined correctly into the .cpp file and everything seems correct.
The problem is that when I try to create a new instance of MailServer inside the constructor of Downloader, the compiler says "error: expected a type"
#include <stdio.h>
#include "downloader.h"
#include <unistd.h>
namespace Downloader
{
Downloader::Downloader(char* fileName)
{
this->m_config = new ConfigDownloader(fileName);
this->m_log = new Logger("Log",LOG_LEVEL_INFO,0);
this->m_mailServer = new MailServer();//the compiler shows the error right here
}
...
any ideas? I read somewhere that it could be that the compiler is too old, but I don't feel really comfortably coding inside the makefile.
I found the solution! I'm sorry because i didn't see it. The problem was that i defined a public getter to return the private field like this:
class Downloader
{
private:
ConfigDownloader* m_config;
Logger* m_log;
MailServer *m_mailServer;
public:
MailServer *MailServer();
being that both was define into the same scope, the compiler could be confused about the constructor of the class and the method, because both were called with the same name. The problem was mine! But everyone should take care about this, because intellisense doesn't tells you anything about it

#include don't really include the code in C++

I have a class defined as follow:
Mirf.h
class Mirf{
public:
void init(void);
};
Mirf.cpp
#include <Mirf.h>
Mirf mirf = Mirf();
Mirf::init(){
[Some Code Here]
}
The class Wireless uses the Mirf instance:
Wireless.h
#include <Mirf.h>
class Wireless {
public:
void init(void);
};
Wireless.cpp
#include <Wireless.h>
#include <Mirf.h>
Wireless::init(){
mirf.init();
}
My main method:
Main.cpp
#include <Wireless.h>
#include <Mirf.h>
Wireless wireless = Wireless();
int main(){
wireless.init();
}
The code compiles normally but the [Some Code Here] in Mirf.cpp doesn't called:
What's is wrong in my code?
Just because code is #included doesn't mean that it will be called. Only the main function is called automatically, any other functions need to be referenced inside expressions or they won't run.

linux ubuntu c++ .h and .cpp file

I have a my.h file:
#ifndef __MY__
#define __MY__
#include <string>
#include <time.h>
class S
{
public: S();
std::string myname;
};
#endif
my.cpp
#include "my.h";
#include<string>
#include<iostream>
using namespace std;
S::S()
{
// .. code
}
I want to create an so file. There is no error when creating it. But when I compile the .h file it says: string:No such file or directory. If I pus string.h instead of string I have the error: expected '=',',',';','asm', before S (at class S) in my.h.
In the .cpp file (if i change the string with string.h) i have after i compile error: string in namespace std does not name a type. WHERE AM I WRONG?
Well, first, it seems that you come from java because when you typed:
class S
{
public: S();
std::string myname;
};
I guess you actually meant:
class S
{
public:
S();
private:
std::string myname;
};
In the .cpp file, you typed s instead of S: note that C++ is case-sensitive regarding classes names.
Also, regarding your problem, I suspect you are currently using a C compiler and not a C++ compiler. Without knowing the used command-line, I can't say much more on that.
Try this
#ifndef MY_H
#define MY_H
#include <string>
#include <time.h>
class S
{
public: S();
std::string myname;
};
#endif
#include "my.h"
#include<string>
#include<iostream>
using namespace std;
S::S()
{
//code
}