[cfe-dev] Checking Datatype of ParmVarDecl

Tobi Popoola via cfe-dev cfe-dev at lists.llvm.org
Wed Jul 8 16:12:31 PDT 2020


Awesome, thanks!

Tobi

On Wed, Jul 8, 2020 at 4:48 PM David Rector <davrecthreads at gmail.com> wrote:

> I’ll show you exactly how to do what I believe you want below, but first
> at the top here I want to make a point for those who design the Type
> interface how I think we could make it easier to use and understand:
>
>   1. We need the GetBaseType() function I reference below to become a
> public Type method
>   2. We probably should get rid of methods like getPointeeCXXRecordDecl(),
> which just add clutter and are straightforward to do with getAs<T>() and
> getDecl().
>   3. Type::getAs<T>() should be expanded to the following to make it more
> flexible:
>
> class Type {
>   //…
>   template<typename T,
>            bool LookThroughSemantics = false> //PROPOSED
>   T *getAs() {
>     // First, desugar as usual, looking for T as you go.
>     // Then if you haven’t found T and LookThroughSemantics==true,
>     // you call e.g. getPointeeType(), getElementType(), etc. if
>     // the type is some kind of canonical wrapper type, then keep looking
>     // through until you run out of both sugar and pointer/array/other
>     // simple wrapper types (i.e. are down to a BuiltinType or a TagType).
>   }
> };
>
>
> (Side note: if the previously-proposed Expr::getAs<T>() ever gets off the
> ground, we can make corresponding adjustments to make it more flexible as
> well:)
>
> class Expr : public Stmt {
>   //…
>   //PROPOSED:
>   template<typename T,
>   bool LookThroughSemantics = true,
>   bool LookThroughParens = true,
>   bool LookThroughUnaryOps = false>
>   T *getAs() {
>     // peel of implicit semantics, and/or ParenExprs etc and/or unary ops
> or whatever,
>     // depending on options, looking for T as you go.
>   }
> };
>
>
>   4. I think we should even allow someType->getAs<CXXRecordDecl>(), which
> would just call
> dyn_cast<CXXRecordDecl>(someType->getAs<RecordType>()->getDecl()).  I.e.
> allow getAs<T>() to go between node categories, whenever it is
> straightforward and unambiguous to do so.  Could really simplify the
> interface if you always knew to just try getAs<T>() as a multi-purpose tool
> to get one thing as another, with bool template params to specify what kind
> of stuff you’re okay discarding in the search for T.
>
>
>>
> Now, onto solving your problem, if I understand it correctly:
>
> If you know your VarDecl *VD has a pointer or reference type, and you just
> want to know if the pointee type, after removing const/volatile/etc.
> qualifiers, is a struct named "foo", this should do it:
>
> bool hasPointeeRecordTypeNamedFoo(VarDecl *VD) {
>   QualType PointeeType = VD->getType()->getPointeeType();
>   assert(!PointeeType.isNull() && "Expected VD’s type had a pointee type");
>   if (RecordType *RT = PointeeType->getAs<RecordType>()) {
>     if (RT->getDecl()->getName() == "foo")
>       return true;
>   }
>   return false;
> }
>
>
> If however you are not sure whether the type of VD is a pointer type, or a
> pointer to a pointer type, or an array, or an array of pointers etc, and
> really you just want to know if the base type after removing all the
> pointers and arrays and whatever. is "struct foo", this static method in
> clang/lib/AST/DeclPrinter.cpp helps:
>
> //From clang/lib/AST/DeclPrinter.cpp:
> static QualType GetBaseType(QualType T) {
>   // FIXME: This should be in the Type class!
>   QualType BaseType = T;
>   while (!BaseType->isSpecifierType()) {
>     if (const PointerType *PTy = BaseType->getAs<PointerType>())
>       BaseType = PTy->getPointeeType();
>     else if (const BlockPointerType *BPy =
> BaseType->getAs<BlockPointerType>())
>       BaseType = BPy->getPointeeType();
>     else if (const ArrayType* ATy = dyn_cast<ArrayType>(BaseType))
>       BaseType = ATy->getElementType();
>     else if (const FunctionType* FTy = BaseType->getAs<FunctionType>())
>       BaseType = FTy->getReturnType();
>     else if (const VectorType *VTy = BaseType->getAs<VectorType>())
>       BaseType = VTy->getElementType();
>     else if (const ReferenceType *RTy = BaseType->getAs<ReferenceType>())
>       BaseType = RTy->getPointeeType();
>     else if (const AutoType *ATy = BaseType->getAs<AutoType>())
>       BaseType = ATy->getDeducedType();
>     else if (const ParenType *PTy = BaseType->getAs<ParenType>())
>       BaseType = PTy->desugar();
>     else
>       // This must be a syntax error.
>       break;
>   }
>   return BaseType;
> }
> bool hasBaseRecordTypeNamedFoo(VarDecl *VD) {
>   QualType BaseType = GetBaseType(VD->getType());
>   if (BaseType->getAs<RecordType>()) {
>     if (RT->getDecl()->getName() == "foo")
>       return true;
>   }
>   else
>     assert(isa<BuiltinType>(BaseType.getTypePtr()) ||
>            isa<EnumType>(BaseType.getTypePtr() &&
>            "Fix GetBaseType, it did not unwrap this as expected…");
>   return false;
> }
>
>
> Hope that helps, good luck,
>
> Dave
>
> On Jul 8, 2020, at 3:08 PM, Tobi Popoola via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
> Hi,
>
>
> Is there a way to check the struct type of a ParmVarDecl object.  Here is
> a snippet of what I have been trying to do so far
>
>
> auto ParamStructType =
> VarDecl->getOriginalType().getPointeeCXXRecordDec();
>
> // trying to check if ParamStructType is some 'struct foo’
>
>
> Tobi
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
> --
Regards,
Tobi Goodness Popoola
President,
*National Society of Black Engineers (NSBE)*

*Boise State University*
tobipopoola at u.boisestate.edu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200708/408f0163/attachment.html>


More information about the cfe-dev mailing list