I'm new to clang and I want to rename member variable name using ASTMatcher. For example:
class Person
{
public:
....
private:
char m_genger;
^^^^^^^^ => rename to gender_
int m_age;
^^^^^^ => rename to age_
};
After reading some tutorials now I found how to use ASTMatcher, so that I can access location to be modified.
But I got a Seg. Fault right after calling clang::Rewriter::ReplaceText or InsertText.
My ASTMatcher Program
DeclarationMatcher FieldDeclMatcher =
clang::ast_matchers::fieldDecl().bind("field_decl");
clang::Rewriter rewriter;
class MyMatcher : public MatchFinder::MatchCallback
{
public :
MyMatcher(clang::Rewriter& rewrite) : m_rewriter(rewrite) {}
virtual void run(const MatchFinder::MatchResult& result)
{
if (const clang::FieldDecl* fs
= result.Nodes.getNodeAs<clang::FieldDecl>("field_decl"))
{
std::cout << "===== found: FieldDecl =====" << std::endl;
fs->dump();
std::cout << std::endl;
// seg. fault occurs here.
m_rewriter.InsertText(fs->getLocStart(), "/* comment */", true, true);
}
}
private:
clang::Rewriter& m_rewriter;
};
int main(int argc, const char **argv)
{
CommonOptionsParser OptionsParser(argc, argv, MyToolCategory);
ClangTool Tool(OptionsParser.getCompilations(),
OptionsParser.getSourcePathList());
MyMatcher matcher(rewriter);
clang::ast_matchers::MatchFinder finder;
finder.addMatcher(FieldDeclMatcher, &matcher);
return Tool.run(newFrontendActionFactory(&finder).get());
}
Output of gdb backtrace
#0 0x0000000000a52153 in clang::Rewriter::getLocationOffsetAndFileID(clang::SourceLocation, clang::FileID&) const ()
#1 0x0000000000a5516a in clang::Rewriter::InsertText(clang::SourceLocation, llvm::StringRef, bool, bool) ()
#2 0x0000000000422f0d in MyMatcher::run(clang::ast_matchers::MatchFinder::MatchResult const&) () at ex03.cc:68
Thanks.
After reading Eli Bendersky's post, I found the answer.
It seems like that I can't rewrite codes only using ASTMatcher, To modify code, we need not only ASTFrontendAction and ASTConsumer but ASTMatcher.
(please correct me, if I'm wroing)
You can get Eli's code his github repository.
Related
I have a class called stackTester that is trying to inherit from another class stackofChars. The methods defined in stackofChars that I am trying to use in stackTester are all virtual, but when I try to use them in stackTester, I get an error
request for member which is of non-class type
Here is my stackofChars.h file:
#define STACK_OF_CHARS_H
#include "node.h"
class stackofChars
{
private:
node* m_top;
public:
//constructor for the stack, takes in no paramaters
stackofChars();
//copy constructor, takes in a referance to the original stack
stackofChars(const stackofChars& orig);
//destructor for the stack, no parameters
~stackofChars();
//destructor for the copy, takes in a referance to the copy
void operator=(const stackofChars& rhs);
//pushes the stack back and creates a new node at the stop, takes in an entry, returns nothing
virtual void push(char entry);
//deletes the top entry and pushes the stack up, takes in nothing, returns nothing
virtual void pop();
//peeks at the top entry, takes in nothing, returns a char, const because nothing is changed
virtual char peek() const;
//checks if the stack is empty, takes in no parameters, returns nothing, const because nothing is changed
virtual bool isEmpty() const;
};
#endif
Here is my stackTester.h file:
#ifndef STACK_TESTER_H
#define STACK_TESTER_H
#include "stackofChars.h"
class stackTester : public stackofChars
{
public:
stackTester();
//This will call all your test methods
void runTests();
private:
//Creates an empty stack and verifies isEmpty() returns true
void test1();
//Creates an empty stack pushes 1 value, verifies isEmpty() returns false
void test2();
//Creates an empty stack, then pushes once, pops once, and verifies isEmpty returns true
void test3();
//more test methods as needed
};
#endif
If needed, here is my stackTester.cpp file:
#include "stackTester.h"
#include "stackofChars.h"
#include <iostream>
void stackTester::test1()
{
stackofChars test();
std::cout << "Test#1: Newly created stack is empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
void stackTester::test2()
{
stackofChars test();
test.push(???);
std::cout << "Test#2: Push on empty stack makes it non-empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
void stackTester::test3()
{
stackofChars test();
test.push(???);
test.pop();
std::cout << "Test#3: Popping all elements makes stack empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
Can someone tell me why I am getting this error?
stackofChars test(); is wrong.The right way to declare a class object should be: stackofChars test; or stackofChars test{};
There is an explanation here enter link description here
I'm using pocoXML functions in a managed DLL, which is used by another managed C++ project. The managed DLL compiles perfectly. But when calling a DLL-function which uses a poco function, I get a Debug Assertion Fail (is_block_type_valid) in debug_heap.cpp.
//managed DLL code:
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
class __declspec(dllexport) log
{
public:
static void Log(const char* source, const char* file, const char* function, const std::string& str = "");
}
void log::Debug(const char* file, const char* function, const std::string& str)
{
const Poco::Timestamp now;
const std::string time = Poco::DateTimeFormatter::format(now, Poco::DateTimeFormat::ISO8601_FRAC_FORMAT);
std::stringstream log;
log << "[" << time.c_str() << "; Debug]: " << methodname(file, function) << " - " << str;
std::string str = log.str();
fprintf(stdout, "%s\n", str.c_str());
}
//call from managed C++:
log::Debug(__FILE__, __FUNCTION__, "message");
What am I doing wrong?
Thanks!
Seems, that Poco Lib was compiled for Windows SDK 8.1 instead of 10.
A recompilation with right SDK set solved the problem.
I have a Java program that is using JNA to call a Go Func. Here's the Interface to the Go func in Java:
public interface GPG extends Library {
// GoString class maps to: C type struct { const char *p; GoInt n; }
public class GoString extends Structure {
public static class ByValue extends GoString implements Structure.ByValue {}
public String p;
public long n;
protected List getFieldOrder(){
return Arrays.asList(new String[]{"p","n"});
}
}
// Foreign functions
public GoString.ByValue decrypt(GoString.ByValue encString, GoString.ByValue secretKeyring, GoString.ByValue passphrase);
}
The func signature in Go is:
func decrypt(encString string, secretKeyring string, passphrase string) string
The Go generated C header has:
/* Created by "go tool cgo" - DO NOT EDIT. */
/* package command-line-arguments */
#line 1 "cgo-builtin-prolog"
#include <stddef.h> /* for ptrdiff_t below */
#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
#endif
/* Start of preamble from import "C" comments. */
/* End of preamble from import "C" comments. */
/* Start of boilerplate cgo prologue. */
#line 1 "cgo-gcc-export-header-prolog"
#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H
typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
/*
static assertion to make sure the file is being used on architecture
at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
typedef _GoString_ GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
#endif
/* End of boilerplate cgo prologue. */
#ifdef __cplusplus
extern "C" {
#endif
extern GoString decrypt(GoString p0, GoString p1, GoString p2);
#ifdef __cplusplus
}
#endif
I call the Go Func from Java using this code:
GPG gpg = (GPG) Native.loadLibrary("C:/lib/gpg.dll", GPG.class);
GPG.GoString.ByValue encString = new GPG.GoString.ByValue();
encString.p = value;
encString.n = encString.p.length();
GPG.GoString.ByValue secretKeyring = new GPG.GoString.ByValue();
secretKeyring.p = "c:/gnupg/secring.gpg";
secretKeyring.n = secretKeyring.p.length();
GPG.GoString.ByValue passphrase = new GPG.GoString.ByValue();
passphrase.p = "SecretPassPhrase";
passphrase.n = passphrase.p.length();
GPG.GoString.ByValue decValue = gpg.decrypt(encString, secretKeyring, passphrase);
Clearly the func is being called and processes up to the return of the result string. But it then produces: "panic: runtime error: cgo result has Go pointer"
How do I get a String result back from Go?
Using go version go1.10 windows/amd64, JNA 4.5.1, Java 1.8.0_152
Your GO function should looks like this:
//export decrypt
func decrypt(encString string, secretKeyring string, passphrase string) *C.char {
//... your code here
var str string = "returning string"
return C.CString(str)
}
Java Interface:
public String decrypt(GoString.ByValue encString, GoString.ByValue secretKeyring, GoString.ByValue passphrase);
Your const char * in _GoString_ should use a Pointer instead, then use Pointer.getString() with the provided offset to obtain the actual string.
If Go itself is rejecting a string return value, you'll likely have to instead populate a buffer provided by the caller.
I was reading this Q/A here and as my question is similar but different I would like to know how to do the following:
Let's say I have a basic non template non inherited class called Storage.
class Storage {};
I would like for this class to have a single container (unordered multimap) is where I'm leaning towards... That will hold a std::string for a name id to a variable type T. The class itself will not be template. However a member function to add in elements would be. A member function to add might look like this:
template<T>
void addElement( const std::string& name, T& t );
This function will then populate the unorderd multimap. However each time this function is called each type could be different. So my map would look something like:
"Hotdogs", 8 // here 8 is int
"Price", 4.85f // here 4.8f is float.
How would I declare such an unorderd multimap using templates, variadic parameters, maybe even tuple, any or variant... without the class itself being a template? I prefer not to use boost or other libraries other than the standard.
I tried something like this:
class Storage {
private:
template<class T>
typedef std::unorderd_multimap<std::string, T> DataTypes;
template<class... T>
typedef std::unordered_multimap<std::vector<std::string>, std::tuple<T...>> DataTypes;
};
But I can not seem to get the typedefs correct so that I can declare them like this:
{
DataTypes mDataTypes;
}
You tagged C++17, so you could use std::any (or std::variant if the T type can be a limited and know set of types`).
To store the values is simple.
#include <any>
#include <unordered_map>
class Storage
{
private:
using DataTypes = std::unordered_multimap<std::string, std::any>;
DataTypes mDataTypes;
public:
template <typename T>
void addElement (std::string const & name, T && t)
{ mDataTypes.emplace(name, std::forward<T>(t)); }
};
int main()
{
Storage s;
s.addElement("Hotdogs", 8);
s.addElement("Price", 4.85f);
// but how extract the values ?
}
But the problem is that now you have a element with "Hotdogs" and "Price" keys in the map, but you have no info about the type of the value.
So you have to save, in some way, a info about the type of th value (transform the value in a std::pair with some id-type and the std::any?) to extract it when you need it.
I've done something along those lines, the actual solution is very specific to your problem.
That being said, I'm doing this on a vector, but the principle applies to maps, too.
If you're not building an API and hence know all classes that will be involved you could use std::variant something along the lines of this:
#include <variant>
#include <vector>
#include <iostream>
struct ex1 {};
struct ex2 {};
using storage_t = std::variant<ex1, ex2>;
struct unspecific_operation {
void operator()(ex1 arg) { std::cout << "got ex1\n";}
void operator()(ex2 arg) { std::cout << "got ex2\n";}
};
int main() {
auto storage = std::vector<storage_t>{};
storage.push_back(ex1{});
storage.push_back(ex2{});
auto op = unspecific_operation{};
for(const auto& content : storage) {
std::visit(op, content);
}
return 0;
}
which will output:
got ex1
got ex2
If I remember correctly, using std::any will enable RTTI, which can get quite expensive; might be wrong tho.
If you provide more specifics about what you actually want to do with it, I can give you a more specific solution.
for an example with the unordered map:
#include <variant>
#include <unordered_map>
#include <string>
#include <iostream>
struct ex1 {};
struct ex2 {};
using storage_t = std::variant<ex1, ex2>;
struct unspecific_operation {
void operator()(ex1 arg) { std::cout << "got ex1\n";}
void operator()(ex2 arg) { std::cout << "got ex2\n";}
};
class Storage {
private:
using map_t = std::unordered_multimap<std::string, storage_t>;
map_t data;
public:
Storage() : data{map_t{}}
{}
void addElement(std::string name, storage_t elem) {
data.insert(std::make_pair(name, elem));
}
void doSomething() {
auto op = unspecific_operation{};
for(const auto& content : data) {
std::visit(op, content.second);
}
}
};
int main() {
auto storage = Storage{};
storage.addElement("elem1", ex1{});
storage.addElement("elem2", ex2{});
storage.addElement("elem3", ex1{});
storage.doSomething();
return 0;
}
For a user-lever thread library, I need to figure out jumping to a function by modifying PC value stored in jmp_buf.
This is what I have written:
jmp_buf env;
void print (void) {
printf("\nHello World!");
}
static int ptr_mangle(int p) {
unsigned int ret;
asm(" movl %1, %%eax;\n"
" xorl %%gs:0x18, %%eax;"
" roll $0x9, %%eax;"
" movl %%eax, %0;"
: "=r"(ret)
: "r"(p)
: "%eax"
);
return ret;
}
int main() {
int i = setjmp(env);
env[0].__jmpbuf[5] = ptr_mangle(print);
longjmp(env, 2);
return 0;
}
I am trying to modify PC in jmp_buf by setting it to the address of the function I am trying to jump to.
I am getting a segmentation fault.
I am unable to figure out what exactly needs to be done. Do I need to modify SP as well?
Any help would be very much appreciated.
What are you trying to do? Are you not checking for the return value of setjmp? I don't think you are doing this correctly. Have a look at the sample code below to see what would be the output be:
#include <stdio.h>
#include <setjmp.h>
#include <stdlib.h>
void subroutine(jmp_buf);
int main(void)
{
int value;
jmp_buf jumper;
value = setjmp(jumper);
if (value != 0)
{
printf("Longjmp with value %d\n", value);
exit(value);
}
printf("About to call subroutine ... \n");
subroutine(jumper);
return 0;
}
void subroutine(jmp_buf jumper)
{
longjmp(jumper,1);
}
The output would be:
About to call subroutine...
Longjmp with a value of 1.
Which begs the question - why are you trying to modify the IP? It sounds like you overwrote something or the code 'jumped' off into the woods and trampled something and came back with a hard landing i.e. segfault.
The variable env is specifically a struct, do not use an array subscript as you have done. I suspect that is why you got a segfault...
Hope this helps,
Best regards,
Tom.