[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