No more ConstantArray::get(Context&, char*&, bool)? - llvm

Look at the LLVM Demo, the offical way to create a constant string is:
Constant* consStr = ConstantArray::get(mod->getContext(), "hello", true);
However, it doesn't work! I aways get compile error about:
test.cc:860:78: error: no matching function for call to llvm::ConstantArray::get(llvm::LLVMContext&, char*&, bool)’
/remote/vgrnd66/wli/Tools/llvm-3.1/include/llvm/Constants.h:354:20: note: candidate is: static llvm::Constant* llvm::ConstantArray::get(llvm::ArrayType*, llvm::ArrayRef<llvm::Constant*>)
Look at the llvm source code, there is no member function to support
llvm::ConstantArray::get(llvm::LLVMContext&, char*&, bool)
I am using llvm3.1.
Is there anything wrong with my code or this constructor has been removed in new source?
Here is the LLVM source code difference.
LLVM2.8
class ConstantArray : public Constant {
// ConstantArray accessors
static Constant *get(const ArrayType *T, const std::vector<Constant*> &V);
static Constant *get(const ArrayType *T, Constant *const *Vals,
unsigned NumVals);
/// This method constructs a ConstantArray and initializes it with a text
/// string. The default behavior (AddNull==true) causes a null terminator to
/// be placed at the end of the array. This effectively increases the length
/// of the array by one (you've been warned). However, in some situations
/// this is not desired so if AddNull==false then the string is copied without
/// null termination.
static Constant *get(LLVMContext &Context, StringRef Initializer,
bool AddNull = true);
}
LLVM3.1
class ConstantArray : public Constant {
public:
// ConstantArray accessors
static Constant *get(ArrayType *T, ArrayRef<Constant*> V);
}
Apparently, there are 3 constructor in 2.8 but only one constructor in 3.1 for ConstantArray. Now I don't know how to create a constant string... :(
Any help is appreicated!
Thanks!

OK. I found it has been moved to ConstantDataArray. It seems the LLVM demo cgi is out-of-date:).
class ConstantDataArray : public ConstantDataSequential {
/// getString - This method constructs a CDS and initializes it with a text
/// string. The default behavior (AddNull==true) causes a null terminator to
/// be placed at the end of the array (increasing the length of the string by
/// one more than the StringRef would normally indicate. Pass AddNull=false
/// to disable this behavior.
static Constant *getString(LLVMContext &Context, StringRef Initializer,
bool AddNull = true);
}

Related

The proper way to initialize array of char with constant string

I use a struct to transfer data over TCP-IP and I have to stick with certain packet size, so I use char array of fixed size for text data. Due to the fact that I can't initialize it otherwise, I forced to copy string to that array in constructor using simple function (based on strcpy). The problem is: analyzer (clang-tidy Ubuntu LLVM 14.0.0) tells me
warning: constructor does not initialize these fields: receiver [cppcoreguidelines-pro-type-member-init]
but in fact that is not true. Tell me, please, how do I change my code to suppress those warnings messages? I understand, that I can initialize those arrays with zeros using {} and than fill them with the needed data, but it looks like double work..
inline void copyName(char *dst, const char *src) {
strncpy(dst, src, MAX_NAME_LENGTH);
}
struct Header {
const MessageType type;
char receiver[MAX_NAME_LENGTH];
static uint32_t messageId;
Header();
Header(MessageType type, const char* receiver);
};
Header::Header(const MessageType type, const char *receiverName)
: type(type) // the warning is here
{
copyName(receiver, receiverName);
Header::messageId++;
}
P.S> Found some workaround (which, of course, not the answer to the actual question): there is the option IgnoreArrays for that warning which, when set to true, suppresses those warnings
The warning is a false positive. The clang-tidy docs for the warning you got say:
The check takes assignment of fields in the constructor body into account but generates false positives for fields initialized in methods invoked in the constructor body.
https://releases.llvm.org/10.0.0/tools/clang/tools/extra/docs/clang-tidy/checks/cppcoreguidelines-pro-type-member-init.html
Seems like a poor check to me, but if you want to keep it enabled you might be able to suppress this one instance of it using the magic // NOLINT comment...somewhere?

why the function cleanup_str must be qualified with 'static' key word?

I am new programmer of c++. I have encountered a proble and I cannot understand this. Could you please help me figure out it? This is an example of the book,<c++ primer>.
class TextQuery {
public:
using line_no = std::vector<std::string>::size_type;
TextQuery(std::ifstream &);
QueryResult query(const std::string &) const;
private:
std::shared_ptr<std::vector<std::string>> file;
std::map<std::string,std::shared_ptr<std::set<line_no>>> wm;
//static std::string cleanup_str(const std::string &); // the book example uses 'static'
std::string cleanup_str(const std::string &); // I think 'static' key word is not needed.so i remove it.
};//class declearation ends here.
std::string TextQuery::cleanup_str(const std::string &word) {
string ret;
for(auto it = word.begin();it != word.end();++it){
if(!ispunct(*it))
ret += tolower(*it);
}
return ret;
}
QueryResult TextQuery::query(const std::string &sought) const
{
static shared_ptr<set<line_no>> nodata(new set<line_no>); //line 66
auto loc = wm.find(cleanup_str(sought)); //line 67
if(loc == wm.end())
return QueryResult(sought,nodata,file);
else
{
return QueryResult(sought,loc->second,file);
}
}
I cannot unstandard the difference between the version of removing 'static' key word and that does not. The compile error is:
passing 'const TextQuery' as 'this' argument discards qualifiers [-fpermissive],67
the object has type qualifiers that are not compatible with the member function "TextQuery::cleanup_str" -- object type is: const TextQuery,67
I have tried two ways that can work correctly:
add 'static' to the function cleanup_str. I cannot unstand why it can pass.
The other way I tried is: remove the last 'const' key word of function QueryResult TextQuery::query(const std::string &sought) const, make it become: QueryResult TextQuery::query(const std::string &sought) . And this method works, I also cannot understand this reason.
const method has a contract - it does not change internal state of an instance of the class. Technically it is implemented the way that hidden parameter this has type const TextQuery * - pointer to constant (non modifiable) object of TextQuery. To follow that contract you cannot call non constant method, it may modify internal state and brake contract of original, const method. Now -
add 'static' to the function cleanup_str. I cannot unstand why it can pass.
Static method does not work with an instance, it just belongs to that class (it does not have hidden parameter this at all) hence it is safe to call such method from const method, contract would not be broken. If you remove static then that method becomes regular non const method and it is not safe to call it anymore from const one.
The other way I tried is: remove the last 'const' key word of function QueryResult
Now your method query becomes non constant (type of this is TextQuery *) so it is safe to call non constant or static method from it. So your compiler error disappear.

LevelDB --- Code in C++

The below given code is taken from LevelDB. I am giving two blocks of code for better understanding. I am unable to understand what is happening.
ThreadState is a structure and I have written here to make it easy for the reader.
struct ThreadState {
int tid; // 0..n-1 when running in n threads
Random rand; // Has different seeds for different threads
Stats stats;
SharedState* shared;
ThreadState(int index)
: tid(index),
rand(1000 + index) {
}
};
Is the marked code below an object instantiation of class Benchmark? What is happening in the marked code below?
void Run() {
PrintHeader();
Open();
const char* benchmarks = FLAGS_benchmarks;
while (benchmarks != NULL) {
{
//code ommitted
}
// Reset parameters that may be overriddden bwlow
***void (Benchmark::*method)(ThreadState*) = NULL;*** // What does this code line mean? // Benchmark is a class.
bool fresh_db = false;
int num_threads = FLAGS_threads;
if (name == Slice("fillseq")) {
fresh_db = true;
method = &Benchmark::WriteSeq;
}
If required, I can give detailed implementation of Benchmark as well.
Thanks a lot for the help!
void (Benchmark::*method)(ThreadState*) = NULL;
// What does this code line mean?
// Benchmark is a class.
The above is a pointer to a member function. Since member functions are not like regular functions (they can only be called on a valid object), you cannot take their address it the same way you would for a free function.
Therefore the above syntax is introduced. It is similar to a regular function pointer except the class specifier Benchmark::. This is essentially the type of the implicit this pointer.
In your case, method is a pointer to a member function that takes ThreadState* as a parameter, and has a void return type. The reason for using it is most probably to simplify the call. First, and based on various parameters, a member function is chosen to be called, and its "address" stored in method. After all the checks are done, there is only a single call to the chosen function via the pointer to member.
Incidentally, &Benchmark::WriteSeq is how the code obtains the "address" of the member function WriteSeq. You must use the address-of operator on the qualified function name.

How to set a value to void * argument of a mock method in google mock testing?

I want to pass a string "Device Name" to a void * pointer argument of a method and retrieve it to a character array later.
For this I've done as shown below.
Here I have created an action to achieve this.
ACTION_P(SetArg2ToChar, value) {*static_cast<char*>(arg2) = *value; }
Actual method to be called/mocked
bool getDictItem(WORD wIndex, BYTE bSubIndex, void * pObjData, DWORD dwLength, CSdo& sdo)
My mock method
MOCK_METHOD5(getDictItem,
bool(WORD wIndex, BYTE bSubIndex, void * pObjData, DWORD dwLength, CSdo& sdo));
in code it is called as
if( !can.getDictItem(wIndex, bSubIndex, pObjData, dwLength, tSdo) )
I want to pass a string to this pObjData (3rd argument in the list).
In my google tests, I'm doing like this.
char szDeviceName[30]= {0};
snprintf(szDeviceName, sizeof(szDeviceName), "%s", "Device Name" );
EXPECT_CALL( mockCan, getDictItem(_,_,_,_,_) )
.WillOnce(DoAll(SetArg2ToChar(szDeviceName),
Return(true)))
.RetiresOnSaturation();
/* Call a real method within which this mock method is called */
If I try to set this argument(pObjData) using "SetArgPointee<2>" directly, I get the below error.
error: 'void' is not a pointer-to-object type*
Hence I'm trying with ACTION_P
Now with this implementation, I only get the first letter of the szDeviceName variable (into this pObjData) i.e., "D" followed by 29 0's in the real code flow after this mock object is called.
I want to get the full string name set into this void * arguement.
I refered to this below question and was able progress this far. But I'm not able to pass the full string. How to set, in google mock, a void* argument to a set of values?
Any information regarding this will be helpful.
Rather then doing that, you could invoke a function (or a method) and copy the parameter.
Something like this in the source file where the test is :
int invokedPObjData;
bool FakeGetDictItem(WORD wIndex, BYTE bSubIndex, void * pObjData, DWORD dwLength, CSdo& sdo)
{
// copy data. here I assumed it is an int
invokedPObjData = *static_cast< int* >( pObjData );
return true; // or whatever makes sense
}
in test :
EXPECT_CALL( mockCan, getDictItem(_,_,_,_,_) )
.WillOnce(Call(FakeGetDictItem))
.RetiresOnSaturation();
then later in test check what needs to be checked.
The ACTION_P approach is basically OK. But as you are dealing with a C string, you can't just use the assignment operation (which just copies the first character) but instead you should use a string copy function like ACTION_P(SetArg2ToCharWithSizeArg3, value) { strcpy_s(static_cast<char*>(arg2), arg3, value); } (I couldn't resist to slightly rename the action).
I recently had a similar need and came up with this as a generic solution. It's based on the built-in SetArgPointee and has the same syntax:
template <size_t N, typename A>
class SetArgumentPointeeVoidAction {
public:
explicit SetArgumentPointeeVoidAction(const A& value) : value_(value) {}
void operator=(SetArgumentPointeeVoidAction const&) = delete;
template <typename Result, typename ArgumentTuple>
void Perform(const ArgumentTuple& args) const
{
::testing::StaticAssertTypeEq<void, Result>();
::testing::StaticAssertTypeEq<void*,
std::decay<decltype(::testing::get<N>(args))>::type>();
*static_cast<A*>(::testing::get<N>(args)) = value_;
}
private:
const A value_;
};
/**
* \brief Sets a \c void* output argument to the contents of the
* supplied object. It's on you to ensure this is safe.
* \tparam N The argument index.
* \tparam T The real argument type.
* \param x The argument to assign to the output argument.
* \return A GMock Action that performs the requested assignment.
* \note Use \c SetArgPointee when it's not a \c void*.
*/
template <size_t N, typename T>
::testing::PolymorphicAction< SetArgumentPointeeVoidAction<N, T> >
SetArgPointeeVoid(const T& x)
{
return ::testing::MakePolymorphicAction(
SetArgumentPointeeVoidAction<N, T>(x));
}
It will give you a compile error if you try to use this on an argument that isn't a void*, so it should be relatively safe as long as you ensure you supply the correct argument.
It's also possible to implement this using ACTION_TEMPLATE, which is a bit shorter, but it generates unused argument warnings, which can be irritating.
(In older versions of GMock you might have to use ::std::tr1::get instead of ::testing::get.)
Left as an exercise for the reader: it's possible to enhance this with perfect forwarding to allow this to move-construct and move-assign for a slight efficiency boost. Although if you're passing anything other than PODs around as void*s then you're probably doing it wrong.
Here is an example using ACTION_TEMPLATE allowing a string to be assigned to a void *, for reference...
ACTION_TEMPLATE(StrCpyArgToVoidPointer,
HAS_1_TEMPLATE_PARAMS(int, k),
AND_2_VALUE_PARAMS(value, size))
{
strncpy(static_cast<char *>(::testing::get<k>(args)), value, size);
return;
}
Please find the steps to set Void Pointer variable in class using invoke Method.
//Actual Function under Test
void testFunction(void)
{
uint16 Frequency;
uint8 PwmId;
uint8 DutyCycle;
Frequency = PORTEXTENDER_ZERO;
PwmId = PORTEXTENDER_ZERO;
DutyCycle = PORTEXTENDER_ZERO;
//for this mock is available and we need to set value of Ex. PwmId
IncCom_ReceiveSignal(SCC_PORT_EXTENDER_PWM_C_SET_PWM_Id, &PwmId);
if((PwmId <= PORTEXTENDER_NUM_PWM_CHANNELS) && (DutyCycle <= 100))
{
}
// Actual Defination of mock ..where we have to set void pointer
void mock_defination(PortExtender_C_SignalId_e SignalId, void* SignalDataPtr)
{
}
//cpp Test class
class testClass : public :: testing :: Test
{
protected:
/* Fixture tear down */
virtual void TearDown()
{
}
uint8 testval1{1};
public:
void setTestvalue(uint8 val) // if we want to set multiple time
{
testval1= val;
}
void test1(PortExtender_C_SignalId_e SignalId, void* SignalDataPtr) //this is method to invoke from test_F
{
* (uint8*)SignalDataPtr =testval1;
}
}
//Test Case
TEST_F(testClass,
testcase_PortExtender_CompStatusResponse_ifConditionSatisfied)
{
setTestvalue(1); //To Set Value
EXPECT_CALL(m_portExtender_SomeIpMock,m_C_Signal(SCC_PORT_EXTENDER_C_COMPONENT_STATUS_HostApplStat,_))
.WillOnce(Invoke(this,&testClass::test1));
}

Associative array .remove[] calling core.stdc.stdio.remove in dmd 2.0

I have the following code in D
import std.stdio;
class Thing
{
// Fields
private string Name;
// Accessors
public string name() { return Name; }
}
class Place: Thing
{
// Fields
private Place[string] Attached;
// Modifiers
public void attach(Place place) { Attached[place.name()] = place; }
public void detach(Place place) { Attached.remove[place.name()]; } // error line
}
Whenever I try to compile with dmd2.0 I get the following errors
Error: function core.stdc.stdio.remove (in const(char*) filename) is not callable using argument types (Place[string])
Error: cannot implicitly convert expression (this.Attached) of type Place[string] to const(char*)
Error: remove((__error)) must be an array or pointer type, not int
The current D2.0 documentation advices to use array.remove[key] for what I'm trying to do, but it looks like the compiler thinks I'm trying to call a std.c(stdc?) function. Why would this be occurring? Is this just a bug in dmd2.0?
Try using
Attached.remove(place.name());
Notice the use of parentheses instead of square brackets. Square brackets are used for indexing only.