[cfe-dev] Matching Indirect base classes

Daniel Jasper djasper at google.com
Tue Nov 19 06:31:03 PST 2013


On Tue, Nov 19, 2013 at 6:11 AM, Pedro Delgado Perez
<pedro.delgado at uca.es>wrote:

>  Hi again,
>
> I came across with a problem using this approach. In my message, I made
> the following question:
>
> class HVD : public MatchFinder::MatchCallback {
>  ...
>
> static bool collect(const CXXRecordDecl *Base, void *OpaqueData) {
>       HVD *Data = reinterpret_cast<HVD*>(OpaqueData);
>       Data->Bases.insert(Base);
>       return true;
>   }
>
>  virtual void run(const MatchFinder::MatchResult &Result) {
>       ... ....
>      if (const CXXRecordDecl *FS =
> Result.Nodes.getNodeAs<clang::CXXRecordDecl>("var")){
>          if(FS->forallBases(collect, this)){
>               for(llvm::SmallPtrSet<const CXXRecordDecl*,
> 4>::const_iterator i = Bases.begin(); i != Bases.end(); i++){
>                   ... ...
>               }
>         }
>      }
>   }
> };
>
> 1 - To tell you the truth, I have no idea what I have to do with
> OpaqueData. Is what I put above correct?
>
> And you told me:
>
> The OpaqueData part seems correct.
>
> However, I have found that every class that is inherited from another
> class is added in the set of base classes, and not only the base classes
> inherited from the class calling *forallBases*. To illustrate what I'm
> saying, here I put an example:
>
> class A;
> class B: public A;
> class C;
> class D: public C;
> class E: public D;
>
> If I call "E"->forallBases(collect, this), what I want is that the classes
> C and D are found, but the class A is also being added because it is
> inherited from B. I guess the problem is in the second parameter passed to
> forAllBases ("this") or with "HVD *Data =
> reinterpret_cast<HVD*>(OpaqueData);" inside "collect", but I'm not so
> expert using these libraries.
>
The usage of OpaqueData still seems correct to me and I very much doubt
that forallBases behaves in the way you are describing. Look at the
implementation:
http://clang.llvm.org/doxygen/CXXInheritance_8cpp_source.html#l00136

It basically iterates of all base classes of the class you are passing in
and is then recursively called on these. Are you clearing your "Bases" set
between callback invocations (e.g. right before the call to forallBases)?

> Please, I need some help to finally solve this matter.
>
> Thanks in advance,
>
> Pedro.
> *El día 11 nov 2013 16:43, Daniel Jasper <djasper at google.com
> <djasper at google.com>> escribió:*
>
>
>
>
> On Mon, Nov 11, 2013 at 2:04 AM, Pedro Delgado Perez <pedro.delgado at uca.es
> > wrote:
>
>> Well, using as reference what you named of Sema::CheckUsingDeclQualifier,
>> I tried the following;
>>
>> DeclarationMatcher I_Matcher = recordDecl().bind("var");
>>
>> class HVD : public MatchFinder::MatchCallback {
>> public :
>>
>>   llvm::SmallPtrSet<const CXXRecordDecl*, 4> Bases;
>>
>>   static bool collect(const CXXRecordDecl *Base, void *OpaqueData) {
>>       HVD *Data = reinterpret_cast<HVD*>(OpaqueData);
>>       Data->Bases.insert(Base);
>>       return true;
>>   }
>>
>>   virtual void run(const MatchFinder::MatchResult &Result) {
>>       ... ....
>>      if (const CXXRecordDecl *FS =
>> Result.Nodes.getNodeAs<clang::CXXRecordDecl>("var")){
>>          if(FS->forallBases(collect, this)){
>>               for(llvm::SmallPtrSet<const CXXRecordDecl*,
>> 4>::const_iterator i = Bases.begin(); i != Bases.end(); i++){
>>                   ... ...
>>               }
>>         }
>>      }
>>   }
>> };
>>
>> 1 - To tell you the truth, I have no idea what I have to do with
>> OpaqueData. Is what I put above correct?
>>
> The OpaqueData part seems correct.
>
>> 2 - I got an error doing this and I can't understand the problem.
>>
>> IHD_operator:
>> /home/pedro/clang-llvm/llvm/tools/clang/include/clang/AST/DeclCXX.h:558:
>> const clang::CXXRecordDecl::DefinitionData& clang::CXXRecordDecl::data()
>> const: Assertion `DefinitionData && "queried property of class with no
>> definition"' failed.
>> Stack dump:
>> 0.    <eof> parser at end of file
>>
> As per its comment, forallBases needs to be called on a CXXRecordDecl that
> is a definition (not e.g. a forward declaration or an injected class name).
> Thus, you will need to ensure that FS->getDefinition() is not NULL and then
> call it on that.
>
>> 3. Once inside the for loop, how can I get each object CXXRecordDecl
>> through SmallPtrSetIterator.<http://llvm.org/docs/doxygen/html/classllvm_1_1SmallPtrSetIterator.html#ac931fc62430140f2cce08d72e5f27c82>
>>
> I think you just need to dereference it:
> const CXXRecordDecl *Base = *i;
>
>> Thanks for your time,
>>
>> Pedro.
>>
> No problem, I hope this helps,
> Daniel
>
>
>> *El día 08 nov 2013 18:30, Daniel Jasper <djasper at google.com
>> <djasper at google.com>> escribió:*
>>
>> Yes, sorry, lookupInBases() is what I meant. You'll need forAllBases().
>> You can pass in a ForallBasesCallback, which is basically a callback
>> function executed for each base class.
>> I have not used this myself, but for an example, look at:
>> CXXRecordDecl::isProvablyNotDerivedFrom defined in
>> lib/AST/CXXInheritance.cpp.
>>
>> Also lib/Sema/SemaDeclCXX.cpp has an example close to the bottom
>> of Sema::CheckUsingDeclQualifier()
>> that collects all of the bases into a SmallPtrSet.
>>
>>
>> On Fri, Nov 8, 2013 at 9:16 AM, Pedro Delgado Perez <pedro.delgado at uca.es
>> > wrote:
>>
>>> Hi,
>>>
>>> Thanks Daniel, I suppose you mean CXXRecordDecl::lookupInBases() instead
>>> CXXRecordDecl::findInBases().
>>>
>>> Have you ever used one of these methods? I don't understand quite well
>>> how can I use them for my purpose. What I need is that, given an object
>>> CXXRecordDecl, I can analyze something in particular in each one of its
>>> base classes (direct or indirect). Thus, I need to get each one of these
>>> classes to process them, but the methods you refer only return a *bool*.
>>>
>>> Could you please show me an example using these methods? Mainly, with
>>> respect the arguments passed to these methdos.
>>>
>>> Thanks,
>>>
>>> Pedro.
>>> *El día 08 nov 2013 15:32, Daniel Jasper <djasper at google.com
>>> <djasper at google.com>> escribió:*
>>>
>>> Take a look at CXXRecordDecl::forallBases() and
>>> CXXRecordDecl::findInBases(). Dependent on what you want to do, one of them
>>> might do what you need.
>>> Cheers,
>>> Daniel
>>>
>>>
>>> On Fri, Nov 8, 2013 at 2:39 AM, Pedro Delgado Perez <
>>> pedro.delgado at uca.es> wrote:
>>>
>>>> Hello,
>>>>
>>>> Please, I need some help with an issue I noticed a few days ago and I
>>>> am not able to solve.
>>>>
>>>> To illustrate my problem, I show this piece of code:
>>>>
>>>> class A{
>>>>     public:
>>>>         A(): a(1) {};
>>>>         int a;
>>>> };
>>>>
>>>> class B: public A{
>>>>     public:
>>>>         B(): b(2){};
>>>>         int b;
>>>> };
>>>>
>>>> class C: public B{
>>>>     public:
>>>>         C(): c(3){};
>>>>         int b;
>>>>         int a;
>>>> };
>>>>
>>>> We have three classes, where:
>>>> B  inherits directly from A
>>>> C  inherits directly from B and INDIRECTLY from A
>>>>
>>>> Using CXXRecordDecl::base_class_iterator, the classes indirectly
>>>> inherited are not visited. Please, can someone explain me how to take into
>>>> account these indirectly inherited base classes? I've been thinking on
>>>> recursion (use base_class_iterator on each class directly inherited), but
>>>> I'm sure there should be another simpler way to do this.
>>>>
>>>> Thanks in advance,
>>>>
>>>> Pedro.
>>>>
>>>> _______________________________________________
>>>> cfe-dev mailing list
>>>> cfe-dev at cs.uiuc.edu
>>>>
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131119/bceceb6a/attachment.html>


More information about the cfe-dev mailing list