What's the canonical way of using `TypeAttr` in a *.td file?

Hi,

I’m trying to get rid of using namespace mlir; from Flang headers (in particular, this one). However, that leads to build errors:

tools/flang/include/flang/Optimizer/Dialect/FIROps.h.inc:3401:117: error: unknown type name 'TypeAttr'; did you mean 'mlir::TypeAttr'?
  static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::TypeRange resultTypes, TypeAttr in_type);
                                                                                                                    ^~~~~~~~
                                                                                                                    mlir::TypeAttr

I’ve tried editing references to TypeAttr in FIROps.td, but to no avail. I experimented with "mlir::AttrType" and a few other variants, but that led to:

error: undefined type for argument #0 

Thanks!
-Andrzej

Hmmm, the TypeAttr definition in OpBase.td looks like it is properly namespaced (to my tired eyes). Which FIR op is this failing on?

(I assume as part of the updates you properly namespaces the TypeAttr here to be mlir::TypeAttr?)

– River

I’m not familiar enough with tablegen outside of option parsing to say the canonically correct way of doing this. But to scope the type import down to just TypeAttr, you can use this instead:

using mlir::TypeAttr;

That’s not really much better in a header file, but at least the entire namespace isn’t being imported.

Which FIR op is this failing on?

Your question made me realise that using TypeAttr in TableGen is actually fine (e.g. TypeAttr:$in_type). For example, for fir_AllocMemOp I get:

::mlir::TypeAttr getInTypeAttr();

That’s legit. However, for fir_GenTypeDescOp I get this instead:

TypeAttr getInTypeAttr();

In fact, I am getting a lot of similar build failures for other attributes too (i.e. error: unknown type name 'TypeAttr'; did you mean 'mlir::TypeAttr'). I just got fixated on this particular one. My bad, sorry! Now I need to figure out why one of them is correctly namespaced and the other one is not. Any suggestions?

But to scope the type import down to just TypeAttr , you can use this instead:

Good point! But there’s quite a few of them (again, I didn’t pay attention earlier) :confused:

Thanks both, this is a step forward for me after a rather unproductive afternoon!

EDIT
I’m guessing that there’s an issue with FortranTypeAttr, which is used in let arguments = (ins FortranTypeAttr:$in_type);. Just not sure what the problem is.

That op uses FortranTypeAttr, which looks like it uses TypeAttr under the hood. Did you update each of the TypeAttr there to be mlir::TypeAttr?

Did you update each of the TypeAttr there to be mlir::TypeAttr ?

I was missing this change:

  • original:let storageType = [{ TypeAttr }];
  • new: let storageType = [{ ::mlir::TypeAttr }];

Thanks a ton @River707 ! Now I need to repeat the exercise for other Ops that fail.

How can I know when to use:

  • TypeAttr, vs
  • "mlir::TypeAttr", vs
  • ::mlir::TypeAttr?

I guess that the first one is only for TableGen context. The 2nd one is for inline C++, right? The 3rd one - no clue.

Technically the last one is the fully qualified one: you can always use it (in C++ context). The second one work as well in most case, but could break if there is a nested mlir namespace in one of the enclosing namespaces I think.