[llvm-dev] Multiple Inheritance with dyn_cast

Craig Topper via llvm-dev llvm-dev at lists.llvm.org
Wed Jun 28 21:00:17 PDT 2017


That should have said DeclBase.h

On Wed, Jun 28, 2017 at 6:46 PM Craig Topper <craig.topper at gmail.com> wrote:

> I think the magic for Decl/DeclContext is the overrides of "doit" at the
> bottom of DeclBase. This is replacing the default casting implementation to
> make this work. Unfortunately I'm on my phone so I can't get a lot more
> details.
>
> On Wed, Jun 28, 2017 at 6:04 PM Riley Dulin via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> Hello,
>>
>>
>>
>> I recently ran into an issue where I wanted to use dyn_cast with a
>> Multiple Inheritance hierarchy. LLVM’s help page on RTTI claims that it can
>> be done, and that Clang’s Decl and DeclContext implement it; however, when
>> I try to use it I run into odd behavior. Here’s my sample code which
>> doesn’t work:
>>
>>
>>
>> ```
>>
>> struct Base {
>>
>>   void *ptr;
>>
>>   bool hasInfo;
>>
>> };
>>
>>
>>
>> struct Info {
>>
>>   int size;
>>
>>
>>
>>   static bool classof(const Base *b) { return b->hasInfo; };
>>
>> };
>>
>>
>>
>> struct Child : public Base {
>>
>>   Child() {
>>
>>     this->ptr = this;
>>
>>     this->hasInfo = false;
>>
>>   }
>>
>> };
>>
>> struct ChildWithInfo : public Base, public Info {
>>
>>   ChildWithInfo() {
>>
>>     this->ptr = this;
>>
>>     this->hasInfo = true;
>>
>>     this->size = 10;
>>
>>   }
>>
>> };
>>
>>
>>
>> int main() {
>>
>>   Base *c = new Child();
>>
>>   Base *i = new ChildWithInfo();
>>
>>   try {
>>
>>     if (Info *inf = llvm::dyn_cast<Info>(c)) {
>>
>>       throw std::string("Casted a child to an info incorrectly");
>>
>>     }
>>
>>     if (Info *inf = llvm::dyn_cast<Info>(i)) {
>>
>>       if (inf->size != 10) {
>>
>>         std::ostringstream str;
>>
>>         str << "Object was sliced: expected 10 but got " << inf->size;
>>
>>         throw str.str();
>>
>>       }
>>
>>     } else {
>>
>>       throw std::string("Couldn't cast child with info to info");
>>
>>     }
>>
>>   } catch (std::string &msg) {
>>
>>     std::cout << msg << std::endl;
>>
>>  }
>>
>>   delete c;
>>
>>   delete i;
>>
>> }
>>
>> ```
>>
>>
>>
>> Basically the error is that when a `Base` is cast to an `Info`, it starts
>> reading out of the same offset where `ptr` is stored instead of `size`.
>>
>> How can I modify my class setup so that I can use this scheme safely?
>>
>>
>>
>> Looking at `Decl` and `DeclContext`, it is unclear to me how they set
>> things up so that the field offsets are correct, although I have a feeling
>>
>> It has something to do with the `LLVM_ALIGNAS` in the class declaration
>> of `Decl`.
>>
>> Regards,
>>
>> Riley Dulin
>>
>>
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
> --
> ~Craig
>
-- 
~Craig
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170629/7838820e/attachment.html>


More information about the llvm-dev mailing list