What is invalid SourceLocation in clang and how to interact with it? - c++

I need to replace some variable declarations with others.
For example
int a = 5;
becomes
T<int> a = 5;
More generic
X a = _const;
becomes
T<X> a = _const;
I tried to implement an ASTVisitor descendant in clang:
bool VisitVarDecl(Decl *f) {
if (VarDecl* VD = dyn_cast_or_null<VarDecl>(f)){
Expr* init = VD->getInit();
SourceRange definition = VD->getDefinition()->getSourceRange();
FullSourceLoc exprLoc = ctx.getFullLoc(init->getLocStart());
FullSourceLoc vLoc = ctx.getFullLoc(VD->getLocStart());
...
I want to replace the definition of variable in the next way:
TheRewriter.ReplaceText(VD->getLocStart(), exprLoc.getSpellingColumnNumber()-vLoc.getSpellingColumnNumber(), someSting);
But any call exprLoc.getSpellingColumnNumber() leads to segmentation fault. For example I just try to print exprLoc.getSpellingColumnNumber():
llvm::outs()<< "init start at "
<<exprLoc.getSpellingColumnNumber(&isValid)
<<" is "<<(isValid?"valid ":"invalid ")
<<", decl start at "
<<vLoc.getSpellingColumnNumber()
<<".\n";
And output is
init start at 9 is invalid , decl start at 1.
<…>
Segmentation fault
What does it mean “invalid” SourceLocation and how to interact with it?

Related

how to log size of array with ilog

I have this code and just want to log size of array :
auto owner = abi_data["owner"].as<chain::authority>();
auto arrSize = std::size(owner.keys);
ilog(arrSize);
But have an error :
error: no matching constructor for initialization of 'fc::log_message'
How can i fix it?
I understand that the c ++ methodology is very specific. Therefore, I will expand my question and thus grope the way.
how to get public key string from auto owner.
i tried :
std::string k = owner.keys[0].key
error: no viable conversion from 'eosio::chain::public_key_type' (aka 'fc::crypto::public_key') to 'std::string'
I don’t understand how I should transform all this for correct work and get correct public key and replace hardcoded old_account_name .
full code :
else if (action.name == N(newaccount)) {
auto new_account_name = abi_data["newact"].as<chain::name>().to_string();
auto creator = abi_data["creator"].as<chain::name>().to_string();
std::string old_account_name = "EOS7ea3Dj15nUkKz3diU7BmE5FV5aNKsBKL6WScwEaKzNwDp41SSU";
auto owner = abi_data["owner"].as<chain::authority>();
auto active = abi_data["active"].as<chain::authority>();
ilog("new_account_name: " + new_account_name + " ,creator: " + creator);
*m_session << "UPDATE user_address SET address = :nan WHERE crypto_currency_asset_id = :ai AND address = :oan",
soci::use(new_account_name, "nan"),
soci::use(old_account_name, "oan"),
soci::use(asset_id, "ai");
}
FIXED!
auto arrSize = sizeof(owner.keys)/sizeof(owner.keys[0]);
auto ownerPK = static_cast<std::string>(owner.keys[0].key);

Keep Lua state in a C++ environment to limit context switches

I'm having fun coding simple OpenGL demos and I recently decided to use Lua with my C++ engine in order to change the rendering dynamically without having to recompile on and on my project. Thus I can tweak more easily the rendering algorithm. But I know that my current rendering update functions are probably far from being efficient.
For the moment, I'm transfering a matrix from C++ to Lua, modifying it in a Lua script and sending it back to my C++ rendering engine. But I'm reloading the Lua script each time I get an update call from the C++ engine, and I'm losing all of the variable context. That means I'm always starting from scratch and my rendering is far from being smooth. I include some code sample below to explain what I'm doing. I am currently learning Lua with C++ embedding, so I know I still don't have the best practices.
update.lua
function transform(m)
amplitude = 1.5
frequency = 500
phase = 0.0
r = {}
for i = 1, #m do
r[i] = {}
for j = 1, #m[i] do
if (i % 2) then
r[i][j] = amplitude * math.sin(m[i][j] + phase)
else
r[i][j] = -amplitude * math.sin(m[i][j] + phase)
end
phase = phase + 0.001
end
end
return r
end
-- called by c++
function update()
m = pull()
r = transform(m)
push(r)
end
matrix.cpp
// pull matrix from lua point of view
static int pull(lua_State * _L)
{
_push(_L, &_m);
return 1;
}
// push matrix from lua point of view
static int push(lua_State * _L)
{
// get number of arguments
int n = lua_gettop(_L);
if(1 == n) {
_pull(_L, 1, &_m);
}
return 1;
}
void matrix::load_file(char * file, char * function)
{
int status;
// load the file containing the script we are going to run
status = luaL_loadfile(_L, file);
switch (status) {
case LUA_OK:
break;
case LUA_ERRFILE:
std::cout << "LUA_ERRFILE: " << lua_error(_L) << std::endl;
break;
case LUA_ERRSYNTAX:
std::cout << "LUA_ERRSYNTAX: " << lua_error(_L) << std::endl;
break;
default:
std::cout << lua_error(_L) << std::endl;
}
lua_getglobal(_L, function);
status = lua_pcall(_L, 1, 1, 0);
if (status != LUA_OK) {
std::cout << "error running file" << lua_error(_L) << std::endl;
}
}
void matrix::update()
{
load_file("lua/update.lua", "update");
}
I'm thinking of passing some arguments when calling the update() function, but I'm wondering if the C++ to Lua then back to C++ approach is correct and efficient. Especially considering the fact that I might transfer and modify huge matrix in Lua. I probably lack some embedded Lua knowledge to keep context while loading a script. Do you have some general advice on how I would improve my code ? I know that my current approach is overly complicated.
A quick fix would be to only load the file if it has been modified since the last frame:
static time_t last_modified = 0;
struct stat sbuf;
stat(file, &sbuf);
if (sbuf.st_mtime > last_modified) {
last_modified = sbuf.st_mtime;
status = luaL_loadfile(_L, file);
// etc
}
// Now call the function
lua_getglobal(_L, function);
status = lua_pcall(_L, 1, 1, 0);
OK, loading the chunk of the update() function into a global variable and having a global parameter table in the Lua script is the way to go. I achieved this using the following guidelines, and I will post the detailed steps below. Basically, loading the script entirely first ensures that all global variables are stored in the C++ context. Then storing the wanted function as an index allows us to run it again, while keeping the global variables in the script evolving on their own.
Step 1
First call luaL_loadfile once at init
Step 2
Run the script once using lua_pcall(_L, 0, 0, 0);
This ensures that the global variables, which are used as parameters in the Lua script are in memory.
Step 3
Store the Lua function. I managed to do it with the following C++ code:
void matrix::store(char * function)
{
lua_newtable(_L); // create table for functions
_idx = luaL_ref(_L, LUA_REGISTRYINDEX); // store said table in pseudo-registry
lua_rawgeti(_L, LUA_REGISTRYINDEX, _idx); // retrieve table for functions
lua_getglobal(_L, function); // retrieve function to store
if (lua_isfunction(_L, -1)) {
_f = luaL_ref(_L, -2); // store a function in the function table
}
else {
lua_pop(_L, 1);
std::cout << "can't find " << function << std::endl;
}
// table is two places up the current stack counter
lua_pop(_L, 1); // we are done with the function table, so pop it
std::cout << "idx: " << _idx << ", function: " << _f << std::endl;
}
Step 4
Call the stored function again when rendering using the following C++ function:
void matrix::run()
{
int status;
if (_f == -1) {
std::cout << "invalid function index " << _f << std::endl;
}
else {
lua_rawgeti(_L, LUA_REGISTRYINDEX, _idx); // retrieve function table
lua_rawgeti(_L, -1, _f); // retrieve function
//use function
status = lua_pcall(_L, 0, 0, 0); // 0 arguments, 0 results
if (status != LUA_OK) {
std::cout << "error running function" << lua_error(_L) << std::endl;
}
//don't forget to pop the function table from the stack
lua_pop(_L, 1);
}
}
Step 5 (optional)
If we set all the Lua parameters in a global table, we can retrieve them dynamically in C++ using the following piece of code:
void matrix::get_params(char * p)
{
lua_getglobal(_L, p);
lua_pushnil(_L);
int i = 0;
while(lua_next(_L,-2))
{
const char * key = lua_tostring(_L,-2);
double value = lua_tonumber(_L,-1);
lua_pop(_L,1);
std::cout << key << " = " << value << std::endl;
_h[i].key.assign(key);
_h[i].value = value;
i++;
}
lua_pop(_L, 1);
}
Where _his a simple dynamic structure defined as such:
typedef struct {
std::string key;
float value;
} hash;
I only use float, so this simple structure is convenient enough for my needs, and allows me to add lots of variables in my Lua script without bothering with a structure definition in C++. This way I can add as many parameters in my Lua table and do the maths when updating.
Step 6
Tweak the Lua script forever ! Et voila:
p = {
amplitude = 1.5,
frequency = 500,
phase = 0.0
}
function transform(m)
r = {}
for i = 1, #m do
r[i] = {}
for j = 1, #m[i] do
if (i % 2) then
r[i][j] = p.amplitude * math.sin(m[i][j] + p.phase)
else
r[i][j] = -p.amplitude * math.sin(m[i][j] + p.phase)
end
p.phase = p.phase + 0.001
end
end
return r
end
-- called by c++
function update()
m = pull()
r = transform(m)
push(r)
end
This solution fits my needs, but seems very complicated and inefficient. But it was a fine hacking session anyway.

Clang Tool: rewrite ObjCMessageExpr

I want to rewrite all messages in my code,
I need replace only selectors, but I need be able to replace nested expressions
f. e. :
[super foo:[someInstance someMessage:#""] foo2:[someInstance someMessage2]];
I tried do it with clang::Rewriter replaceText and just generate new string,
but there is a problem: It would not be work if I change selectors length, because I replace nested messages with those old positions.
So, I assumed that I need to use clang::Rewriter ReplaceStmt(originalStatement, newStatement);
I am using RecursiveASTVisitor to visit all messages, and I want to copy those messages objects, and replace selectors:
How can I do that?
I tried use ObjCMessageExpr::Create but there is so meny args, I don't know how to get ASTContext &Context and ArrayRef<SourceLocation> SeLocs and Expr *Receiver parameters from the original message.
What is the proper way to replace selectors in nested messages using clang tool (clang tooling interface)?
Update:
Should I use ReplaceStmtWithStmt callback and ASTMatchFinder ?
Update:
I am using following function to rewrite text in file:
void ReplaceText(SourceLocation start, unsigned originalLength, StringRef string) {
m_rewriter.ReplaceText(start, originalLength, string);
m_rewriter.overwriteChangedFiles();
}
And I want to replace all messageExpr in code with new selector f.e:
how it was:
[object someMessage:[object2 someMessage:obj3 calculate:obj4]];
how it should be:
[object newSelector:[object2 newSelector:obj3 newSelector:obj4]];
I am using ReqoursiveASTVisitor:
bool VisitStmt(Stmt *statement) {
if (ObjCMessageExpr *messageExpr = dyn_cast<ObjCMessageExpr>(statement)) {
ReplaceMessage(*messageExpr)
}
return true;
}
I created method for generating new message expr string:
string StringFromObjCMessageExpr(ObjCMessageExpr& messageExpression) {
std::ostringstream stringStream;
const string selectorString = messageExpression.getSelector().getAsString();
cout << selectorString << endl;
vector<string> methodParts;
split(selectorString, ParametersDelimiter, methodParts);
stringStream << "[" ;
const string receiver = GetStringFromLocations(m_compiler, messageExpression.getReceiverRange().getBegin(), messageExpression.getSelectorStartLoc());
stringStream << receiver;
clang::ObjCMessageExpr::arg_iterator argIterator = messageExpression.arg_begin();
for (vector<string>::const_iterator partsIterator = methodParts.begin();
partsIterator != methodParts.end();
++partsIterator) {
stringStream << "newSelector";
if (messageExpression.getNumArgs() != 0) {
const clang::Stmt *argument = *argIterator;
stringStream << ":" << GetStatementString(*argument) << " ";
++argIterator;
}
}
stringStream << "]";
return stringStream.str();
}
void ReplaceMessage(ObjCMessageExpr& messageExpression) {
SourceLocation locStart = messageExpression.getLocStart();
SourceLocation locEnd = messageExpression.getLocEnd();
string newExpr = StringFromObjCMessageExpr(messageExpression);
const int exprStringLegth = m_rewriter.getRangeSize(SourceRange(locStart, locEnd));
ReplaceText(locStart, exprStringLegth, newExpr);
}
The problem occurs when I try to replace nested messages, like that:
[simpleClass doSomeActionWithString:string3 andAnotherString:string4];
[simpleClass doSomeActionWithString:str andAnotherString:str2];
[simpleClass doSomeActionWithString:#"" andAnotherString:#"asdasdsad"];
[simpleClass setSimpleClassZAZAZAZAZAZAZAZA:[simpleClass getSimpleClassZAZAZAZAZAZAZAZA]];
the result is:
[simpleClass newSelector:string3 newSelector:string4 ];
[simpleClass newSelector:str newSelector:str2 ];
[simpleClass newSelector:#"" newSelector:#"asdasdsad" ];
[simpleClass newSelector:[simpleClass getSimp[simpleClass newSelector]];
because messageExpression has "old" value of getLocStart(); and getLocEnd(); How can I fix it?
You can rewrite selector name by replacing only continuous parts of selector name. For example, replace only underlined parts
[object someMessage:[object2 someMessage:obj3 calculate:obj4]];
^~~~~~~~~~~ ^~~~~~~~~~~ ^~~~~~~~~
To achieve this you require only
number of selector parts - ObjCMessageExpr::getNumSelectorLocs()
their locations - ObjCMessageExpr::getSelectorLoc(index)
their lengths - ObjCMessageExpr::getSelector().getNameForSlot(index).size().
Overall, you can rewrite ObjCMessageExpr with the following RecursiveASTVisitor:
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Rewrite/Core/Rewriter.h"
namespace clang_tooling
{
using clang::SourceLocation;
class RewritingVisitor : public clang::ASTConsumer,
public clang::RecursiveASTVisitor<RewritingVisitor>
{
public:
// You can obtain SourceManager and LangOptions from CompilerInstance when
// you are creating visitor (which is also ASTConsumer) in
// clang::ASTFrontendAction::CreateASTConsumer.
RewritingVisitor(clang::SourceManager &sourceManager,
const clang::LangOptions &langOptions)
: _sourceManager(sourceManager), _rewriter(sourceManager, langOptions)
{}
virtual void HandleTranslationUnit(clang::ASTContext &context)
{
TraverseDecl(context.getTranslationUnitDecl());
_rewriter.overwriteChangedFiles();
}
bool VisitObjCMessageExpr(clang::ObjCMessageExpr *messageExpr)
{
if (_sourceManager.isInMainFile(messageExpr->getLocStart()))
{
clang::Selector selector = messageExpr->getSelector();
for (unsigned i = 0, end = messageExpr->getNumSelectorLocs();
i < end; ++i)
{
SourceLocation selectorLoc = messageExpr->getSelectorLoc(i);
_rewriter.ReplaceText(selectorLoc,
selector.getNameForSlot(i).size(),
"newSelector");
}
}
return Base::VisitObjCMessageExpr(messageExpr);
}
private:
typedef clang::RecursiveASTVisitor<RewritingVisitor> Base;
clang::SourceManager &_sourceManager;
clang::Rewriter _rewriter;
};
} // end namespace clang_tooling

CML code not giving output

How to view the output of following code?
fun daughter () = let
val daughter_tid = getTid();
in
print ("DAUGHTER : my tid = " ^ (tidToString daughter_tid) ^ "\n")
end;
fun mother () =
let
val mother_tid = getTid();
val daughter_tid = spawn daughter;
in
print("MOTHER : my Tid = " ^ (tidToString mother_tid) ^ "Daughter's tid = " ^ (tidToString daughter_tid) ^ "\n")
end;
RunCML.doit(mother, SOME(Time.fromMilliseconds 10));
The code compiles fine and suppose to provide output as follows :
DAUGHTER : my tid = [0004]
MOTHER : my tid [0003] DAUGHETR's Tid = [0004]
You must use TextIO.print instead of print to get the right output. Without such an explicit reference, the CML version of TextIO does not get loaded when your program is compiled and the print function resolves to the SML/NJ version; since this version of print is not thread safe, problems will result. You can see CML FAQ for more details.

1 [main] 972 exception::handle: Exception: STATUS_ACCESS_VIOLATION explanation and how to fix

To ask as simply as possible can anyone explain why this code:
LinkedListByGrade::LinkedListByGrade(vector<Node> myNodes) {
int lowestGradeFound = myNodes[0].getGrade();
Node *pFristNode = new Node();
cout << "New node created" << endl;
for (size_t i = 0; i <= myNodes.size(); i++) {
if (myNodes[i].getGrade() < lowestGradeFound) {
cout << "if triggered" << endl;
lowestGradeFound = myNodes[i].getGrade();
pFristNode->reassasignNode(myNodes[i].getFristName(),
myNodes[i].getLastName(), myNodes[i].getId(),
myNodes[i].getGrade());
cout << "int reassassigned" << endl;
}
Is giving me this error:
1 [main] Project 972 exception::handle: Exception: STATUS_ACCESS_VIOLATION
2130 [main] Project 972 open_stackdumpfile: Dumping stack trace to Project.exe.stackdump
and ideas on how to fix it?
(Sorry I left in the diagnostic print statements.)
Also this is the only code that affects myNodes:
vector<Node> Students;
Node node1("Bobby", "zilch",28,55);
Node node2("Evil", "Dentist",308,55);
Node node3("Raz", "Buton",10,55);
Students.push_back(node1);
Students.push_back(node2);
Students.push_back(node3);
cout<<"stuff"<<endl;
LinkedListByGrade myList = LinkedListByGrade(Students);
I can't say that for sure, but you're accessing memory that is not allocated to you, so it's likely you're running over the boundary of myNodes. You will be able to determine this by using your debugger.
What I can say for sure is that in the first line of your function you call:
int lowestGradeFound = myNodes[0].getGrade();
If there are no items in myNodes, then this should cause an access violation.
And you're certainly running over the end of myNodes in your for-loop because you're accessing myNodes[myNodes.size()].
Try something like this:
LinkedListByGrade::LinkedListByGrade(vector<Node> const& myNodes) {
// Pass by const-reference! ------------------^
// Set this to something high. Don't access the vector, in case there are no
// elements therein:
int lowestGradeFound = std::numeric_limits<int>::max();
// Where is this deleted?
Node *pFirstNode = new Node();
// Use iterators, not indices for looping over a container...
for (vector<Node>::iterator i = myNodes.begin(), end = myNodes.end(); != end; ++i)
{
// Access element by `i->`
if (i->getGrade() < lowestGradeFound)
{
// Now you can assign this safely...
lowestGradeFound = i->getGrade();
pFirstNode->reassasignNode(
i->getFirstName(),
i->getLastName(),
i->getId(),
i->getGrade());
}
}
// [...]
}
But you really, really need to learn to use your debugger!