I'm trying to iterator over the predecessors of a basic block and I'm getting using the following code:
for (::llvm::PredIterator PI = pred_begin(post_block); PI != pred_end(post_block); PI++)
{
::llvm::BasicBlock *pred = *PI;
if (pred != exec_block)
{ ...
In the line with the if statement, I'm getting the following error:
In instantiation of ‘llvm::PredIterator<Ptr, USE_iterator>::reference llvm::PredIterator<Ptr, USE_iterator>::operator*() const [with Ptr = llvm::BasicBlock; USE_iterator = llvm::Value::use_iterator_impl<llvm::Use>; llvm::PredIterator<Ptr, USE_iterator>::reference = llvm::BasicBlock*]’:LLVMTC.cpp:1489:31:
required from here /usr/local/include/llvm/Support/CFG.h:56:5: error: ‘const class llvm::Value::use_iterator_impl<llvm::Use>’ has no member named ‘atEnd’
assert(!It.atEnd() && "pred_iterator out of range!");
Does anyone have any ideas what might be causing this problem? I'm basing my code off of: http://llvm.org/docs/ProgrammersManual.html#iterating-over-predecessors-successors-of-blocks.
Thanks!
First it's important to address the difference between your approach and the one in the example you're referencing.
In the example, they're define an instance of the pred_iterator type, rather than the PredIterator class you've used, which is defined as
typedef PredIterator<BasicBlock, Value::user_iterator> pred_iterator
and then using the calling pred_begin which returns an instance of pred_iterator(BB) where BB is the basic block you pass.
In your case, you're creating an instance of the PredIterator class and assigning it to the BB pointer, then attempting to dereference upon which it hits this assert:
inline reference operator*() const {
assert(!It.atEnd() && "pred_iterator out of range!");
return cast<TerminatorInst>(*It)->getParent();
}
As an initial solution it might be helpful to try and completely mimic the method used by the example, and then if you still need to use your method, try and diagnose the problem by observing how the typing for PredIterator is defined.
I've been looking though the svn history, Since LLVM 3.5, CFG.h has been moved from include/llvm/Support to include/llvm/IR. So you may want to use the following
#include "llvm/IR/CFG.h"
instead of
#include "llvm/Support/CFG.h"
Related
Is there a way to conditionally add arguments to a constructor? I'd also like to know what this type of construction is called so I can search it myself.
I'm creating a boost::process::child using a constructor where I can pass any properties and things are mostly working great:
m_proc = new boost::process::child(
m_context,
boost::process::exe = m_config.exe,
boost::process::args = m_config.args,
boost::process::env = m_config.Environment,
boost::process::start_dir = m_config.WorkingDirectory,
boost::process::std_out > m_stdout_pipe,
boost::process::std_err > m_stderr_pipe,
boost::process::on_exit = [this](int i, auto e){OnProcExit(i, e);},
boost::process::extend::on_setup = [this](auto&){OnProcSetup();},
boost::process::extend::on_success = [this](auto&){OnProcSuccess();},
boost::process::extend::on_error = [this](auto&, auto ec){OnProcError(ec);}
);
UNTIL I call ls with no arguments. Then it returns
/usr/bin/ls: cannot access '': No such file or directory
Process Exited (code:2)
If m_config.args is empty, I want to avoid passing it. I tried:
m_proc = new boost::process::child(
...
boost::process::exe = m_config.exe,
m_config.args.empty() ? (void) : (boost::process::args = m_config.args),
...
);
but that gives:
error: expected primary-expression before ‘void’
I tried:
m_proc = new boost::process::child(
...
boost::process::exe = m_config.exe,
boost::process::args = m_config.args.empty() ? {} : m_config.args,
...
But that gives:
initializer list cannot be used on the right hand side of operator ?
error: expected primary-expression before ‘{’ token
I understand that for this particular case, I could combine exe and args to make a cmd, but I'd also like to conditionally add other arguments like boost::process::shell or boost::process::stdin.
If I need to call different constructor code for every set of options, I would need to write N! calls to constructors where N is the number of options and that grows fast.
This is ugly.
C++ isn't python, there isn't any named parameters in C++, so this solution makes use of global variables (boost::process::args) which are fundamentally not thread safe and prone to usage errors as you experienced.
In the boost documentation they state you don't need to use the global vars, so you can directly use the your config members here:
m_proc = new boost::process::child(
m_context,
m_config.exe,
m_config.args,
m_config.Environment,
[...]
By the way, the error you're reporting isn't due to a bad empty list passing (you can have m_config.args = {}) but probably to a wrong command argument list creation (if the list is empty, the boost::process::child code should create an non-empty string for the process's argument list, containing the executable name as the first argument).
The error you are reporting:
/usr/bin/ls: cannot access '': No such file or directory
is likely due to the wrong argument list being generated by boost and it's not due to your (empty) args array.
So I would put a debug breakpoint on the Popen syscall here and walk backward until I figure out what went wrong in building the argument string.
Using a global variable like a parameter here is syntax candy, but it means operator overloading to an unspecified object (as stated in the documentation), so you actually don't know what's going on here (a = b when a is unknown can be anything in C++, like a crazy making b set to the value of a as in T& operator =(T & b) { b = *this; return *this; }). You'll need to debug what's going on here to figure out what is happening. As a short advice, try to avoid using undefined object if it's not required and unclear, and stick to usual C++ practices.
This is my first experience with downcasting in C++ and I just can't understand the problem.
AInstruction and CInstruction inherit from AssemblerInstruction.
Parser takes the info in its ctor and creates one of those derived instruction types for its mInstruction member (accessed by getInstruction). In the program, a method of the base AssemblerInstruction class is used, for happy polymorphism.
But when I want to test that the Parser has created the correct instruction, I need to query the derived instruction members, which means I need to downcast parser.getInstruction() to an AInstruction or CInstruction.
As far as I can tell this needs to be done using a bunch of pointers and references. This is how I can get the code to compile:
TEST(ParserA, parsesBuiltInConstants)
{
AssemblerInstruction inst = Parser("#R3", 0).getInstruction();
EXPECT_EQ(inst.getInstructionType(), AssemblerInstruction::InstructionType::A);
AssemblerInstruction* i = &(inst);
AInstruction* a = dynamic_cast<AInstruction*>(i);
EXPECT_EQ(a->getLine(), "R3");
}
Running this gives this error:
unknown file: error: SEH exception with code 0xc0000005 thrown in the test body.
And stepping through the code, when the debugger is on the final line of the function, a is pointing to
0x00000000 <NULL>.
I imagine this is an instance where I don't have a full enough understanding of C++, meaning that I could be making a n00b mistake. Or maybe it's some bigger crazy problem. Help?
Update
I've been able to make this work by making mInstruction into a (dumb) pointer:
// in parser, when parsing
mInstructionPtr = new AInstruction(assemblyCode.substr(1), lineNumber);
// elsewhere in AssemblerInstruction.cpp
AssemblerInstruction* AssemblyParser::getInstructionPtr() { return mInstructionPtr; }
TEST(ParserA, parsesBuiltInConstants)
{
auto ptr = Parser("#R3", 0).getInstructionPtr();
AInstruction* a = dynamic_cast<AInstruction*>(ptr);
EXPECT_EQ(a->getLine(), "R3");
}
However I have trouble implementing it with a unique_ptr:
(I'm aware that mInstruction (non-pointer) is redundant, as are two types of pointers. I'll get rid of it later when I clean all this up)
class AssemblyParser
{
public:
AssemblyParser(std::string assemblyCode, unsigned int lineNumber);
AssemblerInstruction getInstruction();
std::unique_ptr<AssemblerInstruction> getUniqueInstructionPtr();
AssemblerInstruction* getInstructionPtr();
private:
AssemblerInstruction mInstruction;
std::unique_ptr<AssemblerInstruction> mUniqueInstructionPtr;
AssemblerInstruction* mInstructionPtr;
};
// in AssemblyParser.cpp
// in parser as in example above. this works fine.
mUniqueInstructionPtr = make_unique<AInstruction>(assemblyCode.substr(1), lineNumber);
// this doesn't compile!!!
unique_ptr<AssemblerInstruction> AssemblyParser::getUniqueInstructionPtr()
{
return mUniqueInstructionPtr;
}
In getUniqueInstructionPtr, there is a squiggle under mUniqueInstructionPtr with this error:
'std::unique_ptr<AssemblerInstruction,std::default_delete>::unique_ptr(const std::unique_ptr<AssemblerInstruction,std::default_delete> &)': attempting to reference a deleted function
What!? I haven't declared any functions as deleted or defaulted!
You can not downcast an object to something which doesn't match it's dynamic type. In your code,
AssemblerInstruction inst = Parser("#R3", 0).getInstruction();
inst has a fixed type, which is AssemblerInstruction. Downcasting it to AInstruction leads to undefined behavior - manifested as crash - because that is not what it is.
If you want your getInstruction to return a dynamically-typed object, it has to return a [smart] pointer to base class, while constructing an object of derived class. Something like that (pseudo code):
std::unique_ptr<AssemblerInstruction> getInstruction(...) {
return std::make_unique<AInstruction>(...);
}
Also, if you see yourself in need of downcasting object based on a value of a class, you are doing something wrong, as you are trying to home-brew polymorphism. Most of the times it does indicate a design flaw, and should instead be done using built-in C++ polymorphic support - namely, virtual functions.
I was porting some legacy code to VS 2015 when this compiler error halted the build:
error C3867: 'OptDlg::GetFullModel': non-standard syntax; use '&' to create a pointer to member
Going to the corresponding file and line, I saw this:
Manager mgr = GetDocument()->GetManager();
OptDlg dlg;
...
mgr->SetFullModel(dlg.GetFullModel);
if ( dlg.GetFullModel )
mgr->SetSymm(...
GetFullModeland SetFullModel are the getter/setter pair for a member variable in two different classes:
class Manager {
...
bool GetFullModel() { return m_bFullModel; }
void SetFullModel(bool bFlag) { m_bFullModel = bFlag; }
....
};
class OptDlg {
...
void GetFullModel() { return m_bFullModel; }
void SetFullModel(bool bValue) { m_bFullModel = bValue; if ( bValue ) m_bInside = 0;}
Yep, something's wrong. Was dlg.GetFullModel supposed to be a pointer to a member function? I thought those use the class name, not an instance. Not to mention what that would mean for execution semantics...
C++ is still relatively new to me, so I tried Google. It had a lot on function pointers, but they all looked different from what I had:
&OptDlg::GetFullModel // Standard-compliant
vs
OptDlg::GetFullModel // The "normal" way to mess up getting a pointer to member, it seems
vs
dlg.GetFullModel // ?
Is dlg.GetFullModel just another way of getting a pointer to member function? If not, what is the "standard C++ version", if there is one? Is this just another one of those VS 6 "extensions"?
&OptDlg::GetFullModel // Standard-compliant
If your parameter types were supposed to be taking member functions, that's what you'd use. But they take booleans. It looks like you're just missing parentheses on your function calls, and it should be:
mgr->SetFullModel(dlg.GetFullModel());
if (dlg.GetFullModel())
mgr->SetSymm(...
Probably someone was ignoring warnings (or didn't have them on) and hence a pointer value (being produced through whatever shady means) was always being interpreted as non-NULL, hence boolean true.
Is this just another one of those VS 6 "extensions"?
It would appear to be the case, although this comment is the only documented evidence I can find it was an intentional/advertised "feature". Don't see any formal announcement of it being added or taken out.
It strongly looks to me like someone mis-typed dlg.GetFullModel() (which would call the function), not that they were trying to get a member function pointer.
Presumably the legacy compiler let it slide, taking the address of the function without using & and converting the non-null function pointer to bool (with value true) to pass into the set function.
I'm not going to get into too much of the details on the Excel side of things, I essentially took code from this example:
C++ app automates Excel (CppAutomateExcel)
solution1.cpp
So I've tried this code in MSVC and it compiles:
class foo { public: virtual void bar(){} };
int main()
{
void (foo::*p)() = &foo::bar;
}
But similar code to capture the address of the move function in Excel does not work:
int main()
{
Excel::_ApplicationPtr spXlApp;
HRESULT hr = spXlApp.CreateInstance(__uuidof(Excel::Application));
Excel::WorkbooksPtr spXlBooks = spXlApp->Workbooks;
Excel::_WorkbookPtr spXlBook = spXlBooks->Add();
Excel::_WorksheetPtr spXlSheet = spXlBook->ActiveSheet;
HRESULT(Excel::_Worksheet::*pMove)(...) = &spXlSheet->Excel::_Worksheet::Move;
<... irrelevant code ...>
return 0;
}
This has the following compiler error:
error C2276: '&': illegal operation on bound member function expression
If I remove the &, it says I should add it back:
error C3867: 'Excel::_Worksheet::Move': non-standard syntax; use '&' to create a pointer to member
Any help on what to do here would be greatly appreciated.
You say in your question "but similar code..." and then you show code in which you do not do the same thing. Try using the same syntax for setting pMove as you used for setting p in your smaller example. Try something like &Excel::_Worksheet::Move; (without the "spXlSheet->").
If you can specify the specific instance of the object for which to call the function pointer at the time that you set the function pointer as you have there, I'm not aware of such a capability. After dropping spXlSheet-> from where you set the variable, use it instead where you want to call the function pointer.
You need to declare the method pointer like this instead:
// or whatever parameter type Move() actually uses...
void (Excel::_Worksheet::*pMove)(tagVARIANT, tagVARIANT) = &Excel::_Worksheet::Move;
Then, to actually call pMove(), you would have to do something like this:
Excel::_WorksheetPtr spXlSheet = ...;
(spXlSheet.Get()->*pMove)(...);
I 'm trying to create a function in llvm IR which re-assigns all llvm::GlobalVariable to their initial values.
I tried to tackle the problem by first iterating over all llvm::GlobalVariable of an llvm::Module and then, for each llvm::GlobalVariable which has an initializer and isn't a constant, to add to my new function an llvm::StoreInst which will perform the assignment.
My problem is that llvm::GlobalVariable::getInitializer() returns an *llvm::Constant which is a base class and I am unsure of how to get access to the initialization values especially for custom structs and classes. Should I use some sort of downcasting or is there any cleaner solution ?
This is my code so far which compiles well but crashes on runtime: (Assertion `getOperand(1)->getType()->isPointerTy() && "Ptr must have pointer type!"' failed.)
Module::GlobalListType* glist = &M.getGlobalList();
for(auto it=glist->begin(); it!=glist->end(); ++it){
if(it->hasInitializer() && !it->isConstant()){
Constant* con = it->getInitializer();
StoreInst(it, con, RET);//RET is a pointer to an existing instruction.
}
}
Thanks for your time!