Modifying Anonymous Structs and Unions in Clang's AST - clang

I'm attempting to write an external Clang AST modifier that translates anonymous struct and union definitions to a different form. For example, I have:
typedef struct test_case_t {
struct {
int value;
} first[1];
int second;
int third[1];
} test_case_t;
I would like to transform this to:
struct test_case_t {
struct first{
int value;
};
struct first first[1];
int second;
int third[1];
};
typedef struct test_case_t test_case_t;
However, the transform seems to drop the struct first declaration, so this is what I get instead:
struct test_case_t {
struct{ // this should be "struct first"
int value;
};
struct first first[1];
int second;
int third[1];
};
typedef struct test_case_t test_case_t;
How do I go about modifying the struct definition in place and add the first declaration name? I have the RecordDecl of the first variable definition, but I can't seem to figure out how to transform the struct definition.

Ultimately, this is a rather interesting idiosyncrasy of Clang's AST. When representing nested sets of structs and unions, the nested declarations and definitions are split into unique FieldDecls. The struct declaration is lexically parsed first then the variable definition is parsed. This requires that you save off a reference to the struct/union declaration and match it downstream to subsequent variable definitions. This process can be rather tricky, but mimics the following. Specifically, we're looking for struct declarations that match are not isFreeStanding()
for(RecordDecl::decl_iterator iter = RD->decls_begin(), end =
RD->decls_end(); iter != end; ++iter) {
Decl *StructDecl = nullptr;
if(FieldDecl *FD = dyn_cast_or_null<FieldDecl>(*iter)) {
// create new FD
if(const ElaboratedType * NET =
dyn_cast<ElaboratedType>(SemaRef.Context.getBaseElementType(NewFD->getType())))
{
if( StructDecl ){
RecordDecl *MyDecl = dyn_cast<RecordDecl>(StructDecl);
if( MyDecl )
MyDecl->setDeclName(FD->getDeclName());
}
}
}
}else if(TagDecl *TD = dyn_cast<TagDecl>(*iter)){
if(TD->isThisDeclarationADefinition() && !TD->isFreeStanding()){
// save StructDecl
}
}
}

Related

type safe create Lua tables in Haxe without runtime overhead and without boilerplate

I am trying to write some externs to some Lua libraries that require to pass dictionary tables and I want to make them type safe.
So far, I have been declaring abstract classes with public inline constructors, but this gets tedious really fast:
abstract JobOpts(Table<String, Dynamic>) {
public inline function new(command:String, args:Array<String>) {
this = Table.create(null, {
command: command,
arguments: Table.create(args)
});
}
}
Is there a better way that allows me to keep things properly typed but that does not require that much boilerplate?
Please note that typedefs and anonymous structures are not valid options, because they introduce nasty fields in the created table and also do a function execution to assign a metatable to them:
--typedef X = {cmd: String}
_hx_o({__fields__={cmd=true},cmd="Yo"})
My abstract code example compiles to a clean lua table, but it is a lot of boilerplate
Some targets support #:nativeGen to strip Haxe-specific metadata from objects, but this does not seem to be the case for typedefs on Lua target. Fortunately, Haxe has a robust macro system so you can make the code write itself. Say,
Test.hx:
import lua.Table;
class Test {
public static function main() {
var q = new JobOpts("cmd", ["a", "b"]);
Sys.println(q);
}
}
#:build(TableBuilder.build())
abstract JobOpts(Table<String, Dynamic>) {
extern public inline function new(command:String, args:Array<String>) this = throw "no macro!";
}
TableBuilder.hx:
import haxe.macro.Context;
import haxe.macro.Expr;
class TableBuilder {
public static macro function build():Array<Field> {
var fields = Context.getBuildFields();
for (field in fields) {
if (field.name != "_new") continue; // look for new()
var f = switch (field.kind) { // ... that's a function
case FFun(_f): _f;
default: continue;
}
// abstract "constructors" transform `this = val;`
// into `{ var this; this = val; return this; }`
var val = switch (f.expr.expr) {
case EBlock([_decl, macro this = $x, _ret]): x;
default: continue;
}
//
var objFields:Array<ObjectField> = [];
for (arg in f.args) {
var expr = macro $i{arg.name};
if (arg.type.match(TPath({ name: "Array", pack: [] } ))) {
// if the argument's an array, make an unwrapper for it
expr = macro lua.Table.create($expr, null);
}
objFields.push({ field: arg.name, expr: expr });
}
var objExpr:Expr = { expr: EObjectDecl(objFields), pos: Context.currentPos() };
val.expr = (macro lua.Table.create(null, $objExpr)).expr;
}
return fields;
}
}
And thus...
Test.main = function()
local this1 = ({command = "cmd", args = ({"a","b"})});
local q = this1;
_G.print(Std.string(q));
end
Do note, however, that Table.create is a bit of a risky function - you will only be able to pass in array literals, not variables containing arrays. This can be remedied by making a separate "constructor" function with the same logic but without array➜Table.create unwrapping.

clang DeclContext::getParent() not returning parent RecordDecl for nested structs

I'm using the following code get parent struct of a nested struct using clang libtooling.
bool VisitRecordDecl(clang::RecordDecl *RD) {
llvm::outs() <<"\n\tTrying to get parents of "<<RD->getNameAsString()<<"\n\n";
clang::RecordDecl *Parent = dyn_cast<clang::RecordDecl>(RD->getParent());
if(!Parent) {
llvm::outs()<<"NULL RecordDecl with dyn_cast\n";
clang::DeclContext *DParent = RD->getParent(); // trying to find what did getParent return
llvm::outs()<<DParent->getDeclKindName()<<"\n"; // prints TransaltionUnit
DParent->dumpDeclContext(); // prints whole source file
}
else{
Parent->dump();
}
return true;
}
This is the source file in which I run the code
struct outer{
struct inner{
int ia;
int ib;
struct deep{
int da;
}dobj;
}iobj;
int oa;
}oboj;
int main(){
return 0;
}
For each invocation of VisitRecordDecl, getParent returns a TranslationUnit which cannot be casted into RecordDecl to get parent struct of inner or deep struct. getLexicalParent() returns RecordDecl correctly but why is getParent() not working?

How to create a table of linker-resolved data in non-dirty memory

I would like to create a table of data, and keep it in non-dirty memory (so that the table doesn't contribute to them memory usage of the app on iOS and related platforms (tvOS/watchOS)).
The table is an array of two pieces of data: Objective-C class and a numeric value:
#include <Foundation/Foundation.h>
struct TypeMap {
Class class;
int value;
};
I'd like to do something like this:
struct TypeMap map [] = {
{ [NSObject class], 0x1234 }
};
but that obviously doesn't work, clang complains with:
test.m:9:4: error: initializer element is not a compile-time constant
{ [NSObject class], 0x1234 }
^~~~~~~~~~~~~~~~
which makes total sense of course, since [NSObject class] is not a compile-time constant.
But there is a symbol that the dynamic loader is able to resolve: _OBJC_CLASS_$_NSObject, which leads me to something like this:
extern Class OBJC_CLASS_$_NSObject;
struct TypeMap map [] = {
{ OBJC_CLASS_$_NSObject, 0x1234 }
};
The idea being that the dynamic linker can resolve the symbol at runtime, and then mark the memory as read-only (the same way it works for normal code).
Unfortunately it runs into the same problem:
test.m:11:4: error: initializer element is not a compile-time constant
{ OBJC_CLASS_$_NSObject, 0x1234 }
^~~~~~~~~~~~~~~~~~~~~
I'm certain I can express this in assembly code, but I'd like to avoid assembly if possible and stick with Objective-C (no need to implement it once per platform).
Am I completely off track here? Is this even possible?
UPDATE
Working version:
// clang test.m -framework Foundation
#include <Foundation/Foundation.h>
#include <objc/objc.h>
#include <objc/runtime.h>
struct TypeMap {
Class class;
int value;
};
extern void* OBJC_CLASS_$_NSObject;
const struct TypeMap map [] = {
{ (Class) &OBJC_CLASS_$_NSObject, 0x1234 },
};
int main ()
{
printf ("%s %p %i\n", class_getName (map[0].class), map [0].class, map [0].value);
return 0;
}
If I understand correctly, a Class in Objective-C is an aggregate type, in the sense in which the C standard uses that term. Then, given
struct TypeMap {
Class class;
int value;
};
extern Class OBJC_CLASS_$_NSObject;
struct TypeMap map [] = {
{ OBJC_CLASS_$_NSObject, 0x1234 }
};
you are asking the dynamic loader to copy the aggregate into your data structure, at load time, which is not a feature that it has.
What you should be able to do instead is have your TypeMap contain pointers to the OBJC_CLASS_$_... symbols:
struct TypeMap {
Class *class;
int value;
};
extern Class OBJC_CLASS_$_NSObject;
const struct TypeMap map[] = {
{ &OBJC_CLASS_$_NSObject, 0x1234 },
// ...
};
Give that a whirl and see how it goes.
(Note the added const on the declaration of map — you need that to get this data structure put in the read-only data segment in the first place.)

Implement opApply with nogc and inferred parameters

Note: I initially posted an over-simplified version of my problem. A more
accurate description follows:
I have the following struct:
struct Thing(T) {
T[3] values;
int opApply(scope int delegate(size_t, ref T) dg) {
int res = 0;
foreach(idx, ref val; values) {
res = dg(idx, val);
if (res) break;
}
return res;
}
}
Foreach can be used like so:
unittest {
Thing!(size_t[]) thing;
foreach(i, ref val ; thing) val ~= i;
}
However, it is not #nogc friendly:
#nogc unittest {
Thing!size_t thing;
foreach(i, ref val ; thing) val = i;
}
If I change the signature to
int opApply(scope int delegate(size_t, ref T) #nogc dg) { ... }
It works for the #nogc case, but fails to compile for non-#nogc cases.
The solutions I have tried are:
Cast the delegate
int opApply(scope int delegate(size_t, ref T) dg) {
auto callme = cast(int delegate(size_t, ref T) #nogc) dg;
// use callme instead of dg to support nogc
This seems wrong as I am willfully casting a #nogc attribute even onto
functions that do may not support it.
Use opSlice instead of opApply:
I'm not sure how to return an (index, ref value) tuple from my range. Even if
I could, I think it would have to contain a pointer to my static array, which
could have a shorter lifetime than the returned range.
Use a templated opApply:
All attempts to work with this have failed to automatically determine the
foreach argument types. For example, I needed to specify:
foreach(size_t idx, ref int value ; thing)
Which I see as a significant hindrance to the API.
Sorry for underspecifying my problem before. For total transparency,
Enumap is the "real-world" example. It
currently uses opSlice, which does not support ref access to values. My
attempts to support 'foreach with ref' while maintaining #nogc support is what
prompted this question.
Instead of overloading the opApplyoperator you can implement an input range for your type. Input ranges work automatically as the agregate argument in foreach statements:
struct Thing(K,V) {
import std.typecons;
#nogc bool empty(){return true;}
#nogc auto front(){return tuple(K.init, V.init);}
#nogc void popFront(){}
}
unittest {
Thing!(int, int) w;
foreach(val ; w) {
int[] i = [1,2,3]; // spurious allocation
}
}
#nogc unittest {
Thing!(int, int) w;
foreach(idx, val ; w) { assert(idx == val); }
}
This solves the problem caused by the allocation of the delegate used in foreach.
Note that the example is shitty (the range doesn't work at all, and usually ranges are provided via opSlice, etc) but you should get the idea.

In MQL4 Assigning from a received struct

Does somebody know how to assign a value inside a method from a field of a received struct parameter?
struct SOME_STRUCT {
int someValue;
};
void someFunction(SOME_STRUCT &someStruct) {
int someValue = someStruct[0].someValue;
}
The assignation fails with:
‘[‘ array required
I fail in the way passing the array structure. This is correct:
void someFunction(SOME_STRUCT &someStruct[])

Resources