the definition of container_of macro - macros

instead of defining container_of as:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
Why won't this simply work :
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) - offsetof(type,member) );})
what's the usage of first line in the definition?

It adds some level of type safety. With your second version, I could pass anything in for ptr and it would compile fine. With the kernel's version, you'll at least get a warning if you pass in a pointer for ptr that doesn't match the type of type.member.

Related

Error: passing 'const xxx' as 'this' argument discards qualifiers

I am trying to implement bigint class in c++, it's not completed yet, i have encountered some errors that i am unable understand.
I have erased all other functions (as they are unnecessary in this case)
and karatsuba is not yet completed (but that should't pose a problem in this case).
In the multiply function (overloaded * ) my compiler gives an error:
passing 'const BigInt' as 'this' argument discards qualifiers [-fpermissive]
at line
ans.a = karatsuba(n,m);
I understand that this would occur when i am trying to change a constant object or object passed to a constant function, in my case i am merely creating a new vector and passing it to karatsuba function.
Removing const from overloded * gets rid of this error.
So,does this mean that a constant function can't change anything at all? (including local variables?)
class BigInt {
typedef long long int ll;
typedef vector<int> vi;
#define p10 1000000000;
#define range 9
vi a;
bool sign;
public:
BigInt operator * (const BigInt &num) const
{
vi n(a.begin(),a.end()),m(num.a.begin(),num.a.end());
BigInt ans;
ans.sign = !(sign ^ num.sign);
while(n.size()<m.size()) n.push_back(0);
while(n.size()>m.size()) m.push_back(0);
ans.a = karatsuba(n,m);
return ans;
}
vi karatsuba(vi a,vi b)
{
int n = a.size();
if(n <= 16)
{
// some code
}
// some code
return a;
}
};
Ok so after googling a bit more, i realized that this pointer is implicitly passed to the oveloaded * and then on to karatsuba (as it is a member function of the class), and as karatsuba is not a constant function, there is no guarantee that it won't change the object contents, hence this error is triggered.
One solution is to declare karatsuba as static, as static member functions don't receive this pointer (they can even be called with out a class object simply using :: operator) , read more about them from here Static data members and member functions.
All that is needed to be changed is :-
static vi karatsuba(vi a,vi b)
{
int n = a.size();
if(n <= 16)
{
// some code
}
// some code
return a;
}

Ordering macro argument execution

I'm using a library for string interning (string-cache), that uses macros to efficient create elements (atom!). However for simplification here is a similar macro that demonstrates the problem
macro_rules! string_intern {
("d") => ("Found D");
}
say I need to call this macro from another macro and give it a string version of an identifier.
macro_rules! print_ident {
($id:ident) => (
string_intern!(stringify!($id));
);
}
However calling this macro
fn main() {
print_ident!(d);
}
Fails with error:
error: no rules expected the token `stringify`
--> <anon>:7:24
|
7 | string_intern!(stringify!($id));
| ^^^^^^^^^
Playground link
I know stringify! correctly converts to identifier d to string "d", because giving it to println! works as expected. Is there a way to pass the identifier I want turned into string to string_intern?
println! lets you do this because it uses format_args! under the covers, which is a compiler-provided "intrinsic" that forcibly evaluates its first argument before using it. You cannot do this from a user-defined macro; you'd have to write a compiler plugin (which requires a nightly compiler and no guarantee of stability).
So, yeah; you can't. Sorry. The only thing you can do is redefine the macro in such a way that you don't need an actual string literal, or change how you invoke it.
Your definition of string_intern! is expecting a literal "d" and nothing else, but you are passing in these tokens: stringify, !, ... which why it fails. The definition of string_intern! that you want is probably:
macro_rules! string_intern {
($e:expr) => {
match $e {
"d" => "Found D",
_ => "Not found",
}
}
}
which can accept any expression that evaluates to a string type.

Systemverilog const ref arg position when constructing an object

I am creating a class that needs a reference to the test bench's configuration object. Since the configuration must be intact throughout the simulation, I pass it as a const ref object. Here is a sudo code that I want to run:
class tb_config;
int unsigned rate;
int unsigned chnls[];
const int unsigned nb_chnls;
function new (int unsigned rate, int unsigned nb_chnls);
this.rate = rate;
this.nb_chnls = nb_chnls;
chnls = new[nb_chnls];
endfunction
endclass
class tx_phy;
static int phy_id;
tb_config cfg;
function new (int unsigned phy_id, const ref tb_config cfg);
this.phy_id = phy_id;
this.cfg = cfg;
endfunction
endclass
module test;
tb_config cfg = new(100, 4);
tx_phy phy = new( 1234, cfg);
endmodule
The code above works perfectly fine and it meets my expectation. But if I change the arguments in tx_phy::new to function new (const ref tb_config cfg, int unsigned phy_id); and pass the values to the constructor accordingly I get the following error in Cadence Incisive:
invalid ref argument usage because actual argument is not a variable.
Also same thing happens when I test it with Aldec in edaplayground: https://www.edaplayground.com/x/5PWV
I assume this is a language limitation, but is there any other reason for that??
The reason for this is because the argument kind is implicit if not specified. You specified const ref for the first argument, but nothing for the second argument, so it is also implicitly const ref. Adding input to the second argument declaration fixes this.
function new (const ref tb_config cfg, input int unsigned phy_id);
I also want to add const ref tb_config cfg is equivalent to writing
function new (tb_config cfg, int unsigned phy_id);
Both of these arguments are implicitly input arguments, which means they are copied upon entry.
A class variable is already a reference. Passing a class variable by ref means that you can update the handle the class variable has from within the function. Making the argument a const ref means you will not be able to update the class variable, but you can still update members of the class the variable references. There is no mechanism to prevent updating members of class object if you have a handle to it other than by declaring them protected or local.
The only place it makes sense to pass function arguments by ref in SystemVerilog is as an optimization when the arguments are large data structures like an array, and you only need to access a few of the elements of the array. You can use task ref arguments when the arguments need to be updated during the lifetime of the task (i.e. passing a clock as an argument).

Possible to check a value is a compile time constant in Rust?

There are cases when inline functions or macros will expand into a lot of code. However, when used with constants, dead branches can be optimized away.
I could add a comment in the code:
// foo arg is always a constant, dead branches will be removed
But I'd rather add some kind of static assertion to ensure this is always the case.
Is there a way in Rust to check if a value is a compile time constant?
Something like GCC's __builtin_constant_p?
If the type of the value or expression is fixed and known in advance, you can define a local constant and initialize it with the value or expression. If you don't otherwise use the constant, prefix its name with an underscore to suppress compiler warnings about the constant being unused. This only works with macros, though.
const _ASSERT_COMPILE_TIME_CONSTANT: i32 = $arg;
The nightly compiler also supports defining "const functions", i.e. functions that can be used in contexts where the compiler requires an expression that can be evaluated at compile time. The body of those functions are subject to restrictions, but call sites of const functions that don't need to be evaluated at compile time can pass expressions that cannot be evaluated at compile time as arguments, so defining a const function doesn't provide the guarantee you're asking for.
If the type of the value or expression cannot be specified in the macro, then we can't omit it, as const requires that the type be specified. However, we can use a generic const function that returns a fixed type in a const initializer!
// at the beginning of the crate
#![feature(const_fn)]
// in the macro's body
const fn _swallow<T>(_x: T) { () }
const _ASSERT_COMPILE_TIME_CONSTANT: () = _swallow($arg);
To add to #Francis answer, this is a macro that can be used to ensure constant value.
macro_rules! ensure_const_expr {
($value:expr, $t:ty) => {
{
const _IGNORE: $t = $value;
}
}
}
// in a functions body
ensure_const_expr!(some_variable, i32);
Note the extra braces are needed so multiple uses don't fail with:
error: a value named `_IGNORE` has already been defined in this block

PostgreSQL + lexical definition of GROUP_P

Where can I find lexical definitions of all PostgreSQL keywords / tokens, like GROUP_P?
GROUP_P is not a keyword, it's a symbol in the context of the C compiler and it doesn't have lexical significance outside of the C source code.
In this declaration from parser/kwlist.h:
PG_KEYWORD("group", GROUP_P, RESERVED_KEYWORD)
it is the first argument "group" that is the keyword, the 2nd argument GROUP_P being typically an enum field or a #define (it's up to the includer).
The header file src/include/parser/keywords.h provides a struct type ScanKeyword that can be directly mapped to the PG_KEYWORD macro, field by field:
typedef struct ScanKeyword
{
const char *name; /* in lower case */
int16 value; /* grammar's token code */
int16 category; /* see codes above */
} ScanKeyword;
For a concrete example of use, see how ECPG does it in src/interfaces/ecpg/preproc/keywords.c