[cfe-dev] Matching Indirect base classes

Pedro Delgado Perez pedro.delgado at uca.es
Thu Nov 21 11:00:01 PST 2013


 
Sorry, I was clearing the set of bases incorrectly. Effectively, I was also puzzled with this behavior, but I didn't notice my mistake.

Thanks for everything,

Pedro.


El día 19 nov 2013 15:31, Daniel Jasper <djasper at google.com> escribió:
> 
> 
> 
> 
> 
> On Tue, Nov 19, 2013 at 6:11 AM, Pedro Delgado Perez <pedro.delgado at uca.es [ mailto: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 [ 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 [ mailto:djasper at google.com ]> escribió:





On Mon, Nov 11, 2013 at 2:04 AM, Pedro Delgado Perez <pedro.delgado at uca.es [ mailto: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 [ mailto: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 [ mailto: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 [ mailto: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 [ mailto: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 [ mailto:cfe-dev at cs.uiuc.edu ]

http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev [ 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/20131121/433f72b6/attachment.html>


More information about the cfe-dev mailing list