I'm using boost::uuids inside maps (labeled_graph, actually), so I need a properly working operator <. Unfortunately it isn't, if BOOST_UUID_USE_SSE2 is enabled (and thus, uuid_x86.hpp is used).
Here is example code:
#include <boost/uuid/nil_generator.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <string>
#include <sstream>
#include <iostream>
#include <assert.h>
#define CHECK(x) do { if(x) { std::cout << #x << "\n"; } } while(0)
static inline boost::uuids::uuid StringToUuid(const std::string &str)
{
boost::uuids::uuid u = boost::uuids::nil_uuid();
std::stringstream uuidstring(str);
uuidstring >> u;
return u;
}
int main() {
boost::uuids::uuid vmi_uuid = StringToUuid("00000000-0000-0000-0000-000000000001");
boost::uuids::uuid vmi2_uuid = StringToUuid("00000000-0000-0000-0000-000000000002");
CHECK(vmi_uuid != vmi2_uuid);
CHECK(vmi_uuid < vmi2_uuid);
CHECK(vmi2_uuid < vmi_uuid);
return 0;
}
When uuid_x86.hpp is used, operator< is incosistent -- returns false in both cases:
vmi_uuid != vmi2_uuid
Disabling intrinsic-based header returns things back to normal:
vmi_uuid != vmi2_uuid
vmi_uuid < vmi2_uuid
This is reproducable only with special UUIDs (1 and 2), having totally random ids doesn't reveal this problem.
I have Ubuntu Xenial with libboost 1.58. CPU is i7-6600U if it matters.
Am I missing something?
Related
Let's say I want to compile a C++ string on the fly:
llvm::LLVMContext context;
std::unique_ptr<clang::CodeGenAction> action = std::make_unique<clang::EmitLLVMOnlyAction>(&context);
clang::tooling::runToolOnCode/*WithArgs*/(action.get(), "int foo(int x){ return ++x;}");
std::unique_ptr<llvm::Module> module = action->takeModule();
Unfortunately, it seems that when LLVM tries to transform the IR, there is an exception saying that the Triple is not set (https://clang.llvm.org/docs/CrossCompilation.html#target-triple).
Is it possible to use libtooling or libclang for this purpose?
Unfortunately, it's difficult to use these interfaces to create a proper LLVM module. The only way is even to create a file and compile the file, setting all the include paths:
First there are lots of includes to add:
#include <clang/AST/ASTContext.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/Basic/DiagnosticOptions.h>
#include <clang/Basic/Diagnostic.h>
#include <clang/Basic/FileManager.h>
#include <clang/Basic/FileSystemOptions.h>
#include <clang/Basic/LangOptions.h>
#include <clang/Basic/MemoryBufferCache.h>
#include <clang/Basic/SourceManager.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/Lex/HeaderSearch.h>
#include <clang/Lex/HeaderSearchOptions.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Lex/PreprocessorOptions.h>
#include <clang/Parse/ParseAST.h>
#include <clang/Sema/Sema.h>
Then we need to set up all the engines around the compiler instance:
clang::DiagnosticOptions diagnosticOptions;
std::unique_ptr<clang::TextDiagnosticPrinter> textDiagnosticPrinter =
std::make_unique<clang::TextDiagnosticPrinter>(llvm::outs(),
&diagnosticOptions);
llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs;
std::unique_ptr<clang::DiagnosticsEngine> diagnosticsEngine =
std::make_unique<clang::DiagnosticsEngine>(diagIDs, &diagnosticOptions, textDiagnosticPrinter.get());
clang::CompilerInstance compilerInstance;
auto& compilerInvocation = compilerInstance.getInvocation();
This is where we can set the triple and also the type of langage we want:
std::stringstream ss;
ss << "-triple=" << llvm::sys::getDefaultTargetTriple();
ss << " -x c++"; // to activate C++
ss << " -fcxx-exceptions";
ss << " -std=c++17";
std::istream_iterator<std::string> begin(ss);
std::istream_iterator<std::string> end;
std::istream_iterator<std::string> i = begin;
std::vector<const char*> itemcstrs;
std::vector<std::string> itemstrs;
while (i != end) {
itemstrs.push_back(*i);
++i;
}
for (unsigned idx = 0; idx < itemstrs.size(); idx++) {
// note: if itemstrs is modified after this, itemcstrs will be full
// of invalid pointers! Could make copies, but would have to clean up then...
itemcstrs.push_back(itemstrs[idx].c_str());
}
clang::CompilerInvocation::CreateFromArgs(compilerInvocation, itemcstrs.data(), itemcstrs.data() + itemcstrs.size(),
*diagnosticsEngine.release());
We can check then options that were set (changing options just here is not enough) and add verbosity:
auto* languageOptions = compilerInvocation.getLangOpts();
auto& preprocessorOptions = compilerInvocation.getPreprocessorOpts();
auto& targetOptions = compilerInvocation.getTargetOpts();
auto& frontEndOptions = compilerInvocation.getFrontendOpts();
#ifdef DEBUG
frontEndOptions.ShowStats = true;
#endif
auto& headerSearchOptions = compilerInvocation.getHeaderSearchOpts();
Let's add all include header path:
constexpr std::string_view paths[] = {"/usr/include/c++/8",
"/usr/include/x86_64-linux-gnu/c++/8",
"/usr/include/c++/8/backward",
"/usr/include/clang/6.0.0/include",
"/usr/local/include",
"/usr/include/x86_64-linux-gnu",
"/usr/include"};
for(auto path: paths)
{
headerSearchOptions.AddPath(std::string(path), clang::frontend::IncludeDirGroup::Angled, false, false);
}
#ifdef DEBUG
headerSearchOptions.Verbose = true;
#endif
auto& codeGenOptions = compilerInvocation.getCodeGenOpts();
There should be here a way of setting a file-like string (not using FrontendInputFile), but unfortunately in LLVM 7, there is a check ensuring it's a real file...
frontEndOptions.Inputs.clear();
frontEndOptions.Inputs.push_back(clang::FrontendInputFile(filename, clang::InputKind::CXX));
targetOptions.Triple = llvm::sys::getDefaultTargetTriple();
compilerInstance.createDiagnostics(textDiagnosticPrinter.get(), false);
LLVM::Context context;
Create now the code generator action and make the compiler instance execute the action:
std::unique_ptr<clang::CodeGenAction> action = std::make_unique<clang::EmitLLVMOnlyAction>(&context);
if (!compilerInstance.ExecuteAction(*action))
{
// Failed to compile, and should display on cout the result of the compilation
}
I am new to c++ and I want to include an array of Enum values, and I am getting a syntax error in Microsoft Visual Studio. I am not sure why this is the case any help much appreciated. The error number is C2061 and it states "syntax error: identifier 'VerboseBinary'. Here is the code:
Header file verbose_binary.h
#pragma once
#include <bitset>
enum class VerboseBinary : int {
One,
Two,
Four,
Eight,
Sixteen,
Null,
};
void convert(std::bitset<5> bs, VerboseBinary aVB[6]);
verbose_binary.cpp
#include "verbose_binary.h"
#include "stdafx.h"
#include <bitset>
#include <string>
#include <iostream>
void convert(std::bitset<5> bs, VerboseBinary aVB[6]) {
VerboseBinary VBArray[6] = {
VerboseBinary:: One,
VerboseBinary:: Two,
VerboseBinary:: Four,
VerboseBinary:: Eight,
VerboseBinary:: Sixteen,
VerboseBinary:: Null
};
for (int i = 0; i < 5; i++) {
if (bs.test(i)) {
aVB[i] = VBArray[i];
}
else {
aVB[i] = VerboseBinary::Null;
}
}
aVB[5] = VerboseBinary::Null;
}
Main
#include "stdafx.h"
#include <iostream>
#include <iostream>
#include <bitset>
#include "verbose_binary.h"
int main() {
int a, b;
std::bitset<5> aBs, bBs;
std::cout << "Enter two numbers between 0-31:" << std::endl;
std::cin >> a >> b;
if (a<0 || a>31) return -1;
if (b<0 || b>31) return -2;
aBs = static_cast<std::bitset<5>>(a);
bBs = static_cast<std::bitset<5>>(b);
// std::cout << aBs << " " << bBs << std::endl;
VerboseBinary aVB[6];
VerboseBinary bVB[6];
convert(aBs, aVB);
convert(bBs, bVB);
return 0;
}
Lol, so it looks like one of these issues was resposible for the error:
What version of Visual Studio are you using? enum with class became available with VS 2012.
Also, there is a stray comma at the end of your enum's definition.
Also, stdafx.h should appear before any other includes in verbose_binary.cpp.
Main has a benign double-inclusion for <iostream>
I started to work with threads recently and I tried to run a simple program that uses threads but I get really strange output.
The program writes the prime numbers in the given range with N(parameter to the function)number of threads into the file "PRIMES.txt", if the range <= 1000 the output is fine but if the range is bigger, then the output is something like :
‰‱′″‵‷ㄱㄠ″㜱ㄠ‹㌲㈠‹ㄳ㌠‷ㄴ㐠″㜴㔠″㤵㘠‱㜶㜠‱㌷㜠‹㌸㠠‹㜹ㄠㄠ㌰ㄠ㜰ㄠ㤰ㄠ㌱ㄠ㜲ㄠㄳㄠ㜳ㄠ㤳ㄠ㤴ㄠㄵㄠ㜵ㄠ㌶ㄠ㜶ㄠ㌷ㄠ㤷... (much longer)
What would be the problem?
Here is my code :
threads.h :
#include <fstream>
#include <string>
#include <iostream>
#include <thread>
using namespace std;
void writePrimesToFile(int begin, int end, ofstream& file);
void callWritePrimesMultipleThreads(int begin, int end, string filePath, int N);
threads.cpp :
#include "Threads.h"
#include <iostream>
#include <string>
#include <fstream>
#include <thread>
#include <mutex>
#include <vector>
mutex mtx;
void PrimesToFile(int begin, int end, ofstream& file)
{
bool isPrime;
string Primes;
int count = 0;
mtx.lock();
cout << "Thread is running" << endl;
for (int i = begin; i < end; i++)
{
isPrime = true;
for (int j = 2; j < i; j++)
{
if (i%j == 0)
isPrime = false;
}
if (isPrime)
{
Primes.append(to_string(i));
Primes.append(" ");
}
}
file.write(Primes.c_str(), Primes.length());
mtx.unlock();
}
void WritePrimesMultipleThreads(int begin, int end, string filePath, int N)
{
ofstream OP;
OP.open(filePath);
int lastPos = 0;
int destPos = end / N;
thread* TV = new thread[N];
for (int i = 0; i < N; i++)
{
TV[i] = thread(PrimesToFile, lastPos, destPos, ref(OP));
lastPos = destPos;
destPos += end / N;
}
for (int i = 0; i < N; i++)
TV[i].join();
}
Starting point :
#include "Threads.h"
#include <iostream>
#include <string>
#include <fstream>
#include <thread>
void main()
{
WritePrimesMultipleThreads(1, 10000, "PRIMES.txt", 5);
system("PAUSE");
}
Thanks!
Hours of debugging turned out to be in wrong implementation of std::ofstream. Just outputting at the beginning OP << "\n" solved the problem. Compiler is MSVC 2015 update 1. More about about it here. Additionally, you have resource leak, single threading when it is not really intended to, not efficient algorithm of finding primes in a range, compiling errors in your posted code, unnecessary writePrimesToFile function and header files in your header file, you're using using namespace std and may be more problems. I recommend you posting your code at codereview.stackexchange.com to make the code better, because solving this problem is not enough to solve the original problem.
EDIT: You need to flush the stream every time you done writing something.
I'm trying to find the if-conditions in a C-code using Clang.
What I've learned till now is to find the declarations using HandleTopLevelDecl().
What I'm trying to do now is to find a function that is similar to HandleTopLevelDecl() but handles the If-Conditions.
My question is, am I on the right path? is there a function that can do this?
And if not, what do you advice me to do?
Thanks.
With the help of this awesome course: http://swtv.kaist.ac.kr/courses/cs453-fall13
Specially this tutorial: http://swtv.kaist.ac.kr/courses/cs453-fall13/Clang%20tutorial%20v4.pdf
I have solved the problem.
I needed to create a RecursiveASTVisitor and handle the If-Statements while visiting the Statements.
class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
{
public:
bool VisitStmt(Stmt *s) {
// Search for If-Statements
if(isa<IfStmt>(s))
{
cerr << "Found IF" << endl;
}
return true;
}
bool VisitFunctionDecl(FunctionDecl *f) {
// Print function name
cerr << f->getNameAsString().c_str() << endl;
return true;
}
};
And here are the complete code:
#include <cstdio>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <utility>
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/Rewriters.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
using namespace clang;
using namespace std;
// CompilerInstance
CompilerInstance TheCompInst;
class MyASTVisitor : public RecursiveASTVisitor<MyASTVisitor>
{
public:
bool VisitStmt(Stmt *s) {
// Search for If-Statements
if(isa<IfStmt>(s))
{
SourceManager &srcmgr = TheCompInst.getSourceManager();
SourceLocation startLocation = s->getLocStart();
unsigned int start_lineNum = srcmgr.getExpansionLineNumber(startLocation);
cerr << "Found IF # Line: " << start_lineNum << endl;
}
return true;
}
bool VisitFunctionDecl(FunctionDecl *f) {
// Print function name
cerr << f->getNameAsString().c_str() << endl;
return true;
}
};
class MyASTConsumer : public ASTConsumer
{
public:
MyASTConsumer()
: Visitor() //initialize MyASTVisitor
{}
virtual bool HandleTopLevelDecl(DeclGroupRef DR) {
for (DeclGroupRef::iterator b = DR.begin(), e = DR.end(); b != e; ++b) {
// Travel each function declaration using MyASTVisitor
Visitor.TraverseDecl(*b);
}
return true;
}
private:
MyASTVisitor Visitor;
};
int main(int argc, char *argv[])
{
if (argc != 2) {
llvm::errs() << "Usage: kcov-branch-identify <filename>\n";
return 1;
}
// Diagnostics manage problems and issues in compile
TheCompInst.createDiagnostics(NULL, false);
// Set target platform options
// Initialize target info with the default triple for our platform.
TargetOptions *TO = new TargetOptions();
TO->Triple = llvm::sys::getDefaultTargetTriple();
TargetInfo *TI = TargetInfo::CreateTargetInfo(TheCompInst.getDiagnostics(), TO);
TheCompInst.setTarget(TI);
// FileManager supports for file system lookup, file system caching, and directory search management.
TheCompInst.createFileManager();
FileManager &FileMgr = TheCompInst.getFileManager();
// SourceManager handles loading and caching of source files into memory.
TheCompInst.createSourceManager(FileMgr);
SourceManager &SourceMgr = TheCompInst.getSourceManager();
// Prreprocessor runs within a single source file
TheCompInst.createPreprocessor();
// ASTContext holds long-lived AST nodes (such as types and decls) .
TheCompInst.createASTContext();
// A Rewriter helps us manage the code rewriting task.
Rewriter TheRewriter;
TheRewriter.setSourceMgr(SourceMgr, TheCompInst.getLangOpts());
// Set the main file handled by the source manager to the input file.
const FileEntry *FileIn = FileMgr.getFile(argv[1]);
SourceMgr.createMainFileID(FileIn);
// Inform Diagnostics that processing of a source file is beginning.
TheCompInst.getDiagnosticClient().BeginSourceFile(TheCompInst.getLangOpts(),&TheCompInst.getPreprocessor());
// Create an AST consumer instance which is going to get called by ParseAST.
MyASTConsumer TheConsumer;
// Parse the file to AST, registering our consumer as the AST consumer.
ParseAST(TheCompInst.getPreprocessor(), &TheConsumer, TheCompInst.getASTContext());
return 0;
}
There are specific functions in clang for all kinds of Stmts and Decls. For this particular case, it is going to be VisitIfStmt. Check IfStmt being included in RecusiveASTVisitor.h.
RecursiveASTVisitor.h -
#define STMT(CLASS, PARENT) \
bool WalkUpFrom##CLASS(CLASS *S) { \
TRY_TO(WalkUpFrom##PARENT(S)); \
TRY_TO(Visit##CLASS(S)); \
return true; \
} \
bool Visit##CLASS(CLASS *S) { return true; }
#include "clang/AST/StmtNodes.inc"
clang/AST/StmtNodes.inc -
#ifndef IFSTMT
# define IFSTMT(Type, Base) STMT(Type, Base)
#endif
IFSTMT(IfStmt, Stmt)
#undef IFSTMT
These, together create the function VisitIfStmt(IfStmt*) in the class.
Using Linux OpenSUSE 12.3 32-bit
I'm going through Bartosz Milewski's c++11 concurrency videos on youtube. In part 5 he uses his own filesystem.h file in an example where multiple threads are spawned to read all the files in a directory and its sub-directories. So I decided to use boost's filesystem methods since I don't have access to his. I can't figure out how to call is_directory on a directory_iterator.
In fact I don't seem to have any of the regular methods for a directory iterator. I'm using boost version 1.54 downloaded source from site. I'm also using Qt Creator (2.8.1) and its auto-completion for a directory_iterator doesn't show any useful functions. I've used boost to get file_size() of a file, so I assume it was installed correctly. I've also taken a look at what was deprecated and can't seem to find anything on directory_iterator.
I've tried
itr.is_directory
*itr.is_directory
boost::filesystem::is_directory(itr->status()) //doesn't have the member function status
boost::filesystem::is_directory(boost::filesystem::status(itr))
itr.status();
itr->status();
This is the code from Bartosz Milewski's example (not quite finished yet)
test2.cpp
#include <iostream>
#include <string>
#include <thread>
#include <future>
#include <chrono>
#include <vector>
#include <boost/filesystem.hpp>
typedef std::vector<std::string> string_vector;
namespace fs=boost::filesystem;
string_vector listDirectory(std::string && dir)
{
string_vector listing;
std::string dirStr("\n> ");
dirStr += dir;
dirStr += ":\n";
listing.push_back(dirStr);
std::vector<std::future<string_vector>> futures;
for (fs::directory_iterator itr(dir); itr !=fs::directory_iterator(); ++itr)
{
if (itr.is_directory); this is where I need to find if its a directory
{
}
else
{
}
}
return listing;
}
int main()
{
std::string root= "/home/craig/";
auto ftr = std::async(std::launch::async, &listDirectory, root);
try
{
string_vector listing = ftr.get();
}
}
auto-completion shows the following in Qt Creator (auto complete in brackets)
itr-> [mref, operator ->,operator Reference *,proxy]
Try like this:
if (itr->status().type() == boost::filesystem::directory_file) {
// ...
}
while I don't know how to get qt creator to auto-complete boost's filesystem directory_iterator, I wanted to post the working example program in case someone else ends up here. Also note that root was changed to /home/craig/Documents since the directory above it resulted in too many threads to be able to run correctly ( Resource temporarily unavailable ) I think in the next part (part 6) Bartosz limits how many threads can be produced.
#include <iostream>
#include <string>
#include <thread>
#include <future>
#include <chrono> //don't need this, for this program, but is in the example
#include <vector>
#include <boost/filesystem.hpp>
typedef std::vector<std::string> string_vector;
namespace fs=boost::filesystem;
string_vector listDirectory(std::string && dir)
{
string_vector listing;
std::string dirStr("\n> ");
dirStr += dir;
dirStr += ":\n";
listing.push_back(dirStr);
std::vector<std::future<string_vector>> futures;
for (fs::directory_iterator itr(dir); itr !=fs::directory_iterator(); ++itr)
{
if (fs::is_directory(itr->status()))
{
auto ftr =std::async(std::launch::async,&listDirectory,std::move(itr->path().string()));
futures.push_back(std::move(ftr));
}
else
{
listing.push_back(std::move(itr->path().filename().string()));
}
}
for(auto &ftr:futures)
{
string_vector lst = ftr.get();
std::move(lst.begin(),lst.end(),std::back_inserter(listing));
}
return listing;
}
int main()
{
std::string root= "/home/craig/Documents/";
auto ftr = std::async(std::launch::async, &listDirectory, std::move(root));
try
{
string_vector listing = ftr.get();
for (auto &s:listing)
{
std::cout << s << " ";
}
}
catch(std::exception & e)
{
std::cout << e.what() << std::endl;
}
catch(...)
{
std::cout << "unknown exception" <<std::endl;
}
}