I'm trying to use the DependencyCollector class of Clang in my Tool to list all the dependencies in a file, lets say test.cpp
Here is my program:
#include "stdafx.h"
#include <iostream>
#include "clang/Frontend/FrontendActions.h"
#include "clang/Tooling/CommonOptionsParser.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/CommandLine.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/Utils.h"
using namespace std;
using namespace clang::tooling;
using namespace clang;
using namespace llvm;
static cl::OptionCategory MyToolCategory("my-tool options");
static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage);
static cl::extrahelp MoreHelp("\nMore help text...");
class myDependencyCollector : public DependencyCollector {
private:
public:
bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing) {
if (Filename == "stdafx.h" || IsSystem) {
return false;
} else {
return true;
}
}
bool needSystemDependencies() {
return false;
}
};
class DependencyAction : public PreprocessOnlyAction {
private:
myDependencyCollector *col;
public:
virtual bool usesPreprocessOnly() const {
return true;
}
bool BeginSourceFileAction(CompilerInstance &ci) {
Preprocessor &pp = ci.getPreprocessor();
col = new myDependencyCollector();
col->attachToPreprocessor(pp);
return true;
}
void ExecuteAction() {
}
virtual void EndSourceFileAction() {
llvm::ArrayRef<string> arr = col->getDependencies();
int size = arr.size();
for (int i = 0; i < size; i = i+1) {
cout << arr[i] << endl;
}
}
};
int main(int argc, const char **argv)
{
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(), OptionsParser.getSourcePathList());
int result = Tool.run(newFrontendActionFactory<DependencyAction>().get());
return result;
}
Now, if I run the program on, for example the file test.cpp:
#include <iostream>
#include "test.h"
void do_math(int *x) {
*x += 5;
}
int main(void) {
int result = -1, val = 4;
do_math(&val);
return result;
}
The program doesn't find any includes.
It would be great if anybody could help me because I have not been able to find an answer after hours of searching on the internet.
The problem is that you overwrite the ExecuteAction() method from class PreprocessOnlyAction with an empty body.
If you delete the line:
void ExecuteAction() {}
everything works as expected.
Related
I am a C ++ beginner and I am working with classes and modules. When I try to run the app, the app gives me the following error: zsh: bus error /Users/****/Documents/jacoProject/App. On the internet I searched a lot, but I found things that I didn't understand and that I couldn't apply to my code.
Should I implement a destructor? If so how can I implement it with my class? Thanks in advance
func.cxx
module;
#include <string>
export module airline_ticket;
export class AirlineTicket
{
public:
AirlineTicket();
double calculatePriceInDollars();
std::string getPassengerName();
void setPassengerName(std::string name);
int getNumberOfMiles();
void setNumberOfMiles(int miles);
bool hasEliteSuperRewardsStatus();
void setHasEliteSuperRewardsStatus(bool status);
private:
std::string q_passengerName;
int q_numberOfMiles;
bool q_hasEliteSuperRewardsStatus;
};
func_impl.cxx
module;
#include <string>
module airline_ticket;
AirlineTicket::AirlineTicket()
{
q_passengerName = "..not";
q_numberOfMiles = 0;
q_hasEliteSuperRewardsStatus = false;
}
double AirlineTicket::calculatePriceInDollars()
{
if (hasEliteSuperRewardsStatus())
{
return 0;
}
else
{
return getNumberOfMiles() * 0.1;
}
}
std::string AirlineTicket::getPassengerName()
{
return q_passengerName;
}
void AirlineTicket::setPassengerName(std::string name)
{
q_passengerName = name;
}
int AirlineTicket::getNumberOfMiles()
{
return q_numberOfMiles;
}
void AirlineTicket::setNumberOfMiles(int miles)
{
q_numberOfMiles = miles;
}
bool AirlineTicket::hasEliteSuperRewardsStatus()
{
return q_hasEliteSuperRewardsStatus;
}
void AirlineTicket::setHasEliteSuperRewardsStatus(bool status)
{
q_hasEliteSuperRewardsStatus = status;
}
main.cpp
#include <iostream>
import airline_ticket;
int main()
{
AirlineTicket myTicket;
myTicket.setPassengerName("Will SMith");
myTicket.setNumberOfMiles(450);
double ticketCost {myTicket.calculatePriceInDollars()};
std::cout << ticketCost << std::endl;
return 0;
}
I define a ThreadPoolclass, and it has a memeber: std::array<Worker, ThreadNum> Workerlist.
The code is as follows:
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <pthread.h>
#include <memory>
#include "Worker.h"
#include <vector>
#include <array>
const int MAX_THREAD_NUM = 16;
class ThreadPool
{
private:
const unsigned int ThreadNum;
std::shared_ptr<EventLoop> MainLoop;
std::array<std::shared_ptr<Worker>, ThreadNum> WorkerList;
std::array<std::shared_ptr<EventLoop>, ThreadNum> EventLoopList;
unsigned int NextLoopIndex;
public:
ThreadPool(std::shared_ptr<EventLoop> loop, int threadNum = 12);
~ThreadPool();
void RunThreadPool();
std::shared_ptr<EventLoop> GetNextEventLoop();
}
#endif
ThreadPool.cpp
ThreadPool::ThreadPool(std::shared_ptr<EventLoop> loop, int threadNum): MainLoop(loop), ThreadNum(threadNum), NextLoopIndex(0)
{
if (ThreadNum<=0 || ThreadNum> MAX_THREADS)
{
LOG << "The num of threads is out of range.\n";
}
}
ThreadPool::~ThreadPool() {}
void ThreadPool::RunThreadPool()
{
WorkerList.fill(std::make_shared<Worker>());
for (auto i = 0; i < ThreadNum; i++)
{
EventLoopList.at(i) = WorkerList.at(i)->ReturnEventLoopPtr();
}
}
std::shared_ptr<EventLoop> ThreadPool::GetNextEventLoop()
{
if (!EventLoopList.empty())
{
std::shared_ptr<EventLoop> nextLoop = EventLoopList[NextLoopIndex];
NextLoopIndex = (NextLoopIndex + 1) % ThreadNum;
return nextLoop;
}
return;
}
The error message is:
invalid use of data member ThreadPool::ThreadNum
In my opinion, the template parameter ThreadNum should be a constant, but now I need to infer its value when the class is constructed. Any solutions? Thank you very much.
I need to provide a CFG class in a separate file, but I'm unsure how to compile it together with the associated .h and the main program.
I've #includeed the .h file and I've asked for both files at the command line, but I'm not sure why this is wrong for compiling them together.
Thoughts?
CFG.cpp:
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
class CFG
{
public:
string code[25];
char startNT;
//private:
CFG(string inCode[], int stringLen)
{
for (int a = 0; a < stringLen; a++)
{
//cout << inCode[a] << endl;
this->code[a] = inCode[a];
}
for (int a = 0; a < stringLen; a++)
{
cout << this->code[a] << endl;
}
}
char getStartNT()
{
return startNT;
}
void setStartNT(char stNT)
{
startNT = stNT;
}
bool processData(string inString, string wkString)
{
//Our recursive function
return true;
}
void garbage()
{
return;
}
};
CFG.h:
#ifndef _cfg_h_
#define _cfg_h_
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
class CFG
{
public:
string code[25];
char startNT;
CFG(string inCode[], int stringLen);
char getStartNT();
void setStartNT(char stNT);
bool ProcessData(string inString, string wkString);
void garbage();
};
#endif
cfg_entry.cpp:
#include <stdio.h>
#include <iostream>
#include "cfg.h"
using namespace std;
int main()
{
string inArray[5];
inArray[0] = "test0";
inArray[1] = "test1";
inArray[2] = "test2";
inArray[3] = "test3";
inArray[4] = "test4";
CFG * cfg1 = new CFG(inArray, 5);
cfg1->garbage();
return 0;
}
Compile errors:
art#tv:~/Dropbox/Weber/CS 4110/Individual Assignment 2$ g++ -g -std=c++11 -Wall -o cfg_entry cfg.cpp cfg_entry.cpp
/tmp/ccICQEd0.o: In function `main':
/home/art/Dropbox/Weber/CS 4110/Individual Assignment 2/cfg_entry.cpp:15: undefined reference to `CFG::CFG(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, int)'
/home/art/Dropbox/Weber/CS 4110/Individual Assignment 2/cfg_entry.cpp:16: undefined reference to `CFG::garbage()'
collect2: error: ld returned 1 exit status
I found my issue. In my case, the header file was defining the class and the .cpp file was re-defining it again, trying to create 2 instances of the CFG class. The .h needed to handle the class declaration and variable instantiation while the .cpp handles only the function definitions.
cfg.h:
#ifndef _cfg_h_
#define _cfg_h_
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
class CFG
{
private:
string code[25];
char startNT;
public:
CFG(string inCode[], int stringLen);
char getStartNT();
void setStartNT(char stNT);
bool processData(string inString, string wkString);
void garbage();
};
#endif
cfg.cpp:
#include <iostream>
#include <stdio.h>
#include <string>
#include "cfg.h"
using namespace std;
CFG::CFG(string inCode[], int stringLen)
{
for (int a = 0; a < stringLen; a++)
{
//cout << inCode[a] << endl;
this->code[a] = inCode[a];
}
for (int a = 0; a < stringLen; a++)
{
cout << this->code[a] << endl;
}
}
char CFG::getStartNT()
{
return startNT;
}
void CFG::setStartNT(char stNT)
{
startNT = stNT;
}
bool CFG::processData(string inString, string wkString)
{
//Our recursive function
return true;
}
void CFG::garbage()
{
return;
}
In the code sample below, class Die is just a base class that AttackDie inherits. When AttackDie is instantiated, it needs data stored in an instance of class StatSys and an integer value. As a result, the constructor for AttackDie has been designed to take an instance of StatSys and a integer as inputs. However, the compiler is throwing a C2511 error on the line containing AttackDie::AttackDie(StatSys * LocalSystem, int Type)
The error is as follows:
AttackDie::AttackDie(StatSys *,int)': overloaded member function not found in 'AttackDie
I don't understand why this error is showing up. I've checked the header and source. The declaration and implementation interfaces both seem to match. Could someone direct me to the problem?
Code Samples
Dice.cpp
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <Dice.h>
#include <StatisticsSystem.h>
using namespace std;
AttackDie::AttackDie(StatSys * LocalSystem, int Type)
{
DataIntegrity = true;
if (Type > -1)
{
switch (Type)
{
case 0:
DieType = "Red";
DieClass = "Damage";
break;
case 1:
DieType = "Green";
DieClass = "Balanced";
break;
case 2:
DieType = "Blue";
DieClass = "Accuracy";
break;
case 3:
DieType = "Yellow";
DieClass = "Surge";
break;
default:
cout << "Unrecognized TypeNum value (>). Initialization of key AttackDie variables failed./n";
DieType = "Error";
DieClass = "Error";
DataIntegrity = false;
}
}
else
{
cout << "Unrecognized TypeNum value (<). Initialization of key AttackDie variables failed./n";
DieType = "Error";
DieClass = "Error";
DataIntegrity = false;
}
if (DataIntegrity)
{
const int GROUP_SIZE = 3;
int Iterator = 0;
int Test[3];
bool CSVDataValid = true;
for (int OuterCounter = 0; OuterCounter <= LocalSystem->NUM_OF_SIDES - 1; OuterCounter++)
{
Test[0] = LocalSystem->AccessCSVData(Type, Iterator);
Test[1] = LocalSystem->AccessCSVData(Type, Iterator + 1);
Test[2] = LocalSystem->AccessCSVData(Type, Iterator + 2);
Iterator += GROUP_SIZE;
if (Test[0] <= -1 || Test[1] <= -1 || Test[2] <= -1)
{
CSVDataValid = false;
}
else
{
Sides[OuterCounter].Damage = Test[0];
Sides[OuterCounter].Surges = Test[1];
Sides[OuterCounter].Accuracy = Test[2];
}
}
if (!CSVDataValid)
{
cout << "Side specific parameters were not set. CSV data not valid.";
DataIntegrity = false;
}
else
{
Total = { 0, 0, 0 };
for (int SideCounter = 0; SideCounter <= 5; SideCounter++)
{
Total.Damage += Sides[SideCounter].Damage;
Total.Surges += Sides[SideCounter].Surges;
Total.Accuracy += Sides[SideCounter].Accuracy;
}
Averages.Damage = Total.Damage / LocalSystem->NUM_OF_SIDES;
Averages.Surges = Total.Surges / LocalSystem->NUM_OF_SIDES;
Averages.Accuracy = Total.Accuracy / LocalSystem->NUM_OF_SIDES;
}
}
}
Dice.h
#pragma once
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <cmath>
using namespace std;
struct AttackStatAverages
{
double Damage;
double Surges;
double Accuracy;
};
struct DefenseStatAverages
{
double Blocks;
double Evades;
int Dodges;
};
class Die
{
public:
string GetDieType();
string GetDieClass();
protected:
string DieType;
string DieClass;
bool DataIntegrity;
};
class AttackDie : public Die
{
public:
AttackDie(StatSys * LocalSystem, int Type);
int GetSides(int SideNum, int Parameter);
double GetAverages(int Parameter);
int GetTotal(int Parameter);
~AttackDie();
private:
AttackStats Sides[6];
AttackStatAverages Averages;
AttackStats Total;
};
StatisticsSystem.h
#pragma once
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <cmath>
#include <Dice.h>
#include <vector>
using namespace std;
struct DicePackage
{
int Mode;
int Quantity;
int NumberOfPossibilities;
bool Error;
AttackDie* AttackDice[4];
DefenseDie* DefenseDice[3];
};
class StatSys
{
friend class AttackDie;
friend class DefenseDie;
public:
StatSys();
~StatSys();
const double VERSION = 0.1;
int AccessCSVData(int Row, int Column);
private:
static const int MAX_NUM_OF_DICE = 4;
const int METHOD_ERROR_SIZE = 10;
const int NUM_OF_SIDES = 6;
const int GROUP_SIZE = 3;
const int DAMAGE = 0;
const int SURGES = 1;
const int ACCURACY = 2;
const int BLOCKS = 0;
const int EVADES = 1;
const int DODGE = 2;
const int ITERATIONS = 3;
DicePackage DiceSet;
bool CSVDataState;
bool ErrorDataState;
int CSVData[6][18];
vector<string> Errors;
vector<string> ErrorDescriptions;
int StringToInt(string Value);
void LoadCSV();
#include <Dice.h>
#include <StatisticsSystem.h>
should be
#include "Dice.h"
#include "StatisticsSystem.h"
<> is primarily for system headers
"" are for header files in the same directory
Looks like user4581301 was correct. Adding #include <StatisticsSystem.h> to Dice.h fixed the issue since Dice.h does in fact need data from that header.
Im receiving this error when trying to compile my code.
$ g++ -o BangBangControlTest BangBangControl.o BangBangControlTest.o
ld: duplicate symbol _heating_unit in BangBangControlTest.o and BangBangControl.o for architecture x86_64
collect2: ld returned 1 exit status
I am new to C++ and can't find out what is wrong. I've searched through many tutorials and looked at similar error messages received by other stack users. Here are my classes.
"BangBangControlTest.cpp"
// Test function
#include <iostream>
#include "BangBangControl.h"
using namespace std;
int main(){
BangBangControl control(50, true, 75);
for(int i = 0; i < 50; i++){
std::cout << "Temp = " << control.update() << endl;
}
return 0;
}
"BangBangControl.cpp"
#include <iostream>
#include "BangBangControl.h"
using namespace std;
BangBangControl::BangBangControl(int temp, bool isOn, int initialTemp){
heating_unit = HeatingUnit(isOn, initialTemp);
temp_to_maintain = temp;
}
void BangBangControl::setTemp(int temp){temp_to_maintain = temp;}
int BangBangControl::getTemp(){return temp_to_maintain;}
int BangBangControl::update(){
int b=heating_unit.tick();
if (b > temp_to_maintain + 2) heating_unit.turnOff(); if (b < temp_to_maintain - 2) heating_unit.turnOn();
return b;
}
"BangBangControl.h"
// BangBangControl header
#include <iostream>
#include "HeatingUnit.h"
using namespace std;
HeatingUnit heating_unit;
int temp_to_maintain;
class BangBangControl{
public:
BangBangControl(int, bool, int);
void setTemp(int);
int getTemp();
int update();
};
"HeatingUnit.cpp"
// HeatingUnit class implementation
#include <iostream>
#include "HeatingUnit.h"
using namespace std;
HeatingUnit::HeatingUnit(bool a, int b){
isOn = a;
temp = b;
}
void HeatingUnit::turnOn(){isOn = true;}
void HeatingUnit::turnOff(){isOn = false;}
int HeatingUnit::tick(){
if(isOn && temp <= 100){
return ++temp;
}
else if((!isOn) && temp >= 0){
return --temp;
}
else{
return temp;
}
}
"HeatingUnit.h"
#include <iostream>
using namespace std;
class HeatingUnit{
public:
bool isOn;
int temp;
HeatingUnit();
HeatingUnit(bool, int);
void turnOn();
void turnOff();
int tick();
};
You see that HeatingUnit heating_unit; in your header file? You need to put extern in front of it, and copy the original version without the extern to the .cpp file, optionally specifying an initial value there.
You can read more about this here: How do I use extern to share variables between source files?