Fixture 135
cpp rtti
C++ · 4 functions · 4 lanes · 0 of 14 function-lanes behave identically
4 of 4 lanes have a function that returns a different result after decompilation: clang-O0 (0/4), clang-O2 (0/3), gcc-O0 (0/4), gcc-O2 (0/3).
RTTI: dynamic_cast consults a type_info record reachable from the vtable and walks the inheritance graph at runtime, returning null on failure. typeid compares those records. Neither is expressible as a static offset, so both are real calls into the runtime (__dynamic_cast) that a decompiler must not fold into a constant.
/* 135_cpp_rtti.cpp
*
* RTTI: `dynamic_cast` consults a type_info record reachable from the vtable and
* walks the inheritance graph at runtime, returning null on failure. `typeid`
* compares those records. Neither is expressible as a static offset, so both are
* real calls into the runtime (__dynamic_cast) that a decompiler must not fold
* into a constant.
*/
#include <stdint.h>
#include <typeinfo>
namespace {
class Animal {
public:
virtual ~Animal() {}
virtual int32_t sound() const { return 0; }
};
class Dog : public Animal {
public:
int32_t sound() const override { return 1; }
virtual int32_t fetch() const { return 10; }
};
class Cat : public Animal {
public:
int32_t sound() const override { return 2; }
};
class Puppy : public Dog {
public:
int32_t sound() const override { return 3; }
int32_t fetch() const override { return 11; }
};
} // namespace
extern "C" int32_t cpp_dynamic_cast_succeeds(int32_t which) {
Puppy puppy;
Cat cat;
Animal *animal = (which & 1) ? static_cast<Animal *>(&puppy)
: static_cast<Animal *>(&cat);
/* Succeeds only for the Dog lineage; null otherwise. */
Dog *dog = dynamic_cast<Dog *>(animal);
return (dog != 0) ? dog->fetch() : -1;
}
extern "C" int32_t cpp_dynamic_cast_fails(int32_t which) {
Dog dog;
Cat cat;
Animal *animal = (which & 1) ? static_cast<Animal *>(&dog)
: static_cast<Animal *>(&cat);
Puppy *puppy = dynamic_cast<Puppy *>(animal);
return (puppy != 0) ? 1 : 0;
}
extern "C" int32_t cpp_typeid_compare(int32_t which) {
Dog dog;
Puppy puppy;
Cat cat;
const Animal *left;
const Animal *right;
switch (which & 3) {
case 0: left = &dog; right = &dog; break;
case 1: left = &dog; right = &puppy; break;
case 2: left = &puppy; right = &puppy; break;
default: left = &dog; right = &cat; break;
}
return (typeid(*left) == typeid(*right)) ? 1 : 0;
} Recovered C
Generated by glaurung decompile --style decbench at b47f6b43.
baseline.json records the result after recompiling the C and calling it beside the
original with seeded inputs.
clang -O0
0/4_ZNKSt9type_infoeqERKS_ structural 37 lines
// glaurung: _ZNKSt9type_infoeqERKS_ @ 0x1730
typedef struct type_info type_info;
bool _ZNKSt9type_infoeqERKS_(const type_info * arg0, long * arg1) {
extern int strcmp(const char *, const char *);
signed char local_11;
signed char local_21;
long t11;
long t145;
long var1;
int var11;
int var16;
long var6;
long var8;
// x86-64 prologue: save rbp, frame 48 bytes
var1 = *(long *)(((long)arg0 + 0x8));
t11 = *(long *)(((long)arg1 + 0x8));
local_11 = 1;
if ((var1 == t11)) {
var6 = ((unsigned long)((unsigned char)(local_11)) & 255);
t145 = (var6 & 1);
var8 = (t145 & 255);
// x86-64 epilogue: restore rbp
return ((unsigned char)((unsigned int)((unsigned char)((var8 & 255)))) != 0);
}
var11 = (int)((signed char)(*(char *)(*(long *)(((long)arg0 + 0x8)))));
local_21 = 0;
if (((unsigned long)((unsigned int)(var11)) != 42)) {
var16 = strcmp((const char *)(*(long *)(((long)arg0 + 0x8))), (const char *)(*(long *)(((long)arg1 + 0x8))));
local_21 = ((unsigned long)((unsigned int)(var16)) == 0);
}
local_11 = local_21;
var6 = ((unsigned long)((unsigned char)(local_11)) & 255);
t145 = (var6 & 1);
var8 = (t145 & 255);
// x86-64 epilogue: restore rbp
return ((unsigned char)((unsigned int)((unsigned char)((var8 & 255)))) != 0);
} cpp_dynamic_cast_fails fail 41 lines
// glaurung: cpp_dynamic_cast_fails @ 0x1340
typedef struct Animal Animal;
typedef struct Puppy Puppy;
struct Cat;
struct Dog;
__attribute__((no_stack_protector)) int32_t cpp_dynamic_cast_fails(int32_t arg0) {
extern void _ZN12_GLOBAL__N_13CatC2Ev(struct Cat *);
extern void _ZN12_GLOBAL__N_13CatD2Ev(struct Cat *);
extern void _ZN12_GLOBAL__N_13DogC2Ev(struct Dog *);
extern void _ZN12_GLOBAL__N_13DogD2Ev(struct Dog *);
extern long __dynamic_cast(long, long, long, int);
unsigned char animal[8];
unsigned char puppy[8];
unsigned char local_10[8];
unsigned char local_18[8];
void * local_30;
long local_38;
long local_40;
int local_44;
long var13;
long var6;
// x86-64 prologue: save rbp, frame 80 bytes
((void (*)(char *))_ZN12_GLOBAL__N_13DogC2Ev)((char *)(&local_10[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13CatC2Ev)((char *)(&local_18[0]));
local_30 = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 1))) == 0) ? &local_18[0] : &local_10[0]);
*(long *)(&animal[0]) = (long)((long)local_30);
var6 = *(long *)(&animal[0]);
local_38 = var6;
if ((var6 == 0)) {
local_40 = 0;
} else {
var13 = __dynamic_cast(local_38, 0x3ce8, 0x3d10, 0);
local_40 = var13;
}
*(long *)(&puppy[0]) = local_40;
local_44 = ((*(long *)(&puppy[0]) != 0) ? 1 : 0);
((void (*)(char *))_ZN12_GLOBAL__N_13CatD2Ev)((char *)(&local_18[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13DogD2Ev)((char *)(&local_10[0]));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_44);
} cpp_dynamic_cast_succeeds fail 51 lines
// glaurung: cpp_dynamic_cast_succeeds @ 0x1160
typedef struct Animal Animal;
typedef struct Dog Dog;
struct Cat;
struct Puppy;
__attribute__((no_stack_protector)) int32_t cpp_dynamic_cast_succeeds(int32_t arg0) {
extern void _ZN12_GLOBAL__N_13CatC2Ev(struct Cat *);
extern void _ZN12_GLOBAL__N_13CatD2Ev(struct Cat *);
extern void _ZN12_GLOBAL__N_15PuppyC2Ev(struct Puppy *);
extern void _ZN12_GLOBAL__N_15PuppyD2Ev(struct Puppy *);
extern long __dynamic_cast(long, long, long, int);
unsigned char animal[8];
unsigned char dog[8];
unsigned char local_10[8];
unsigned char local_18[8];
void * local_40;
long local_48;
long local_50;
int local_54;
int local_58;
int local_5c;
long var26;
long var6;
long var9;
// x86-64 prologue: save rbp, frame 96 bytes
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyC2Ev)((char *)(&local_10[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13CatC2Ev)((char *)(&local_18[0]));
local_40 = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 1))) != 0) ? &local_10[0] : &local_18[0]);
*(long *)(&animal[0]) = (long)((long)local_40);
var6 = *(long *)(&animal[0]);
local_48 = var6;
if ((var6 != 0)) {
var9 = __dynamic_cast(local_48, 0x3ce8, 0x3cf8, 0);
local_50 = var9;
} else {
local_50 = 0;
}
*(long *)(&dog[0]) = local_50;
if ((*(long *)(&dog[0]) == 0)) {
local_58 = 0xffffffff;
} else {
var26 = ((long (*)(void))(*(long *)((*(long *)(*(long *)(&dog[0])) + 24))))();
local_54 = var26;
local_58 = local_54;
}
local_5c = local_58;
((void (*)(char *))_ZN12_GLOBAL__N_13CatD2Ev)((char *)(&local_18[0]));
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyD2Ev)((char *)(&local_10[0]));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_5c);
} cpp_typeid_compare fail 99 lines
// glaurung: cpp_typeid_compare @ 0x1470
typedef struct Animal Animal;
struct Cat;
struct Dog;
struct Puppy;
__attribute__((no_stack_protector)) int32_t cpp_typeid_compare(int32_t arg0) {
extern void _ZN12_GLOBAL__N_13CatC2Ev(struct Cat *);
extern void _ZN12_GLOBAL__N_13CatD2Ev(struct Cat *);
extern void _ZN12_GLOBAL__N_13DogC2Ev(struct Dog *);
extern void _ZN12_GLOBAL__N_13DogD2Ev(struct Dog *);
extern void _ZN12_GLOBAL__N_15PuppyC2Ev(struct Puppy *);
extern void _ZN12_GLOBAL__N_15PuppyD2Ev(struct Puppy *);
extern int _ZNKSt9type_infoeqERKS_(char *, long *);
extern long __cxa_bad_typeid(void);
unsigned char left[8];
unsigned char right[8];
unsigned char local_10[8];
unsigned char local_18[8];
unsigned char local_20[8];
int local_40;
long local_48;
long local_50;
long local_58;
int local_5c;
long t159;
long t76;
int var1;
long var17;
long var18;
long var23;
long var25;
int var26;
long var28;
long var29;
long var30;
long var34;
long var35;
int var37;
// x86-64 prologue: save rbp, frame 96 bytes
((void (*)(char *))_ZN12_GLOBAL__N_13DogC2Ev)((char *)(&local_10[0]));
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyC2Ev)((char *)(&local_18[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13CatC2Ev)((char *)(&local_20[0]));
var1 = ((unsigned int)(arg0) & 3);
local_40 = var1;
if (((unsigned long)((unsigned int)(var1)) == 0)) {
*(long *)(&left[0]) = (long)((long)(&local_10[0]));
*(long *)(&right[0]) = (long)((long)(&local_10[0]));
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_40)) - 1))) == 0)) {
*(long *)(&left[0]) = (long)((long)(&local_10[0]));
*(long *)(&right[0]) = (long)((long)(&local_18[0]));
} else {
if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_40)) - 2))) == 0)) {
*(long *)(&left[0]) = (long)((long)(&local_18[0]));
*(long *)(&right[0]) = (long)((long)(&local_18[0]));
} else {
*(long *)(&left[0]) = (long)((long)(&local_10[0]));
*(long *)(&right[0]) = (long)((long)(&local_20[0]));
}
}
}
var17 = *(long *)(&left[0]);
local_48 = var17;
if ((var17 == 0)) {
var18 = __cxa_bad_typeid();
}
local_58 = *(long *)((*(long *)(local_48) - 8));
var23 = *(long *)(&right[0]);
local_50 = var23;
if ((var23 != 0)) {
var25 = *(long *)(local_50);
var26 = _ZNKSt9type_infoeqERKS_((char *)(local_58), (long *)(*(long *)((var25 - 0x8))));
t76 = ((unsigned long)((unsigned int)(var26)) & 255);
var28 = (var29 & -256);
var30 = (var28 | (t76 & 255));
t159 = (var30 & 1);
var34 = (((unsigned long)((unsigned char)(t159)) != 0) ? 1 : 0);
local_5c = var34;
((void (*)(char *))_ZN12_GLOBAL__N_13CatD2Ev)((char *)(&local_20[0]));
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyD2Ev)((char *)(&local_18[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13DogD2Ev)((char *)(&local_10[0]));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_5c);
}
var35 = __cxa_bad_typeid();
var25 = *(long *)(local_50);
var37 = _ZNKSt9type_infoeqERKS_((char *)(local_58), (long *)(*(long *)((var25 - 0x8))));
t76 = ((unsigned long)((unsigned int)(var37)) & 255);
var28 = (var29 & -256);
var30 = (var28 | (t76 & 255));
t159 = (var30 & 1);
var34 = (((unsigned long)((unsigned char)(t159)) != 0) ? 1 : 0);
local_5c = var34;
((void (*)(char *))_ZN12_GLOBAL__N_13CatD2Ev)((char *)(&local_20[0]));
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyD2Ev)((char *)(&local_18[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13DogD2Ev)((char *)(&local_10[0]));
// x86-64 epilogue: restore rbp
return (unsigned int)(local_5c);
} clang -O2
0/3cpp_dynamic_cast_fails fail 17 lines
// glaurung: cpp_dynamic_cast_fails @ 0x1190
typedef struct Animal Animal;
typedef struct Puppy Puppy;
__attribute__((no_stack_protector)) int32_t cpp_dynamic_cast_fails(int32_t arg0) {
extern long __dynamic_cast(long, long, long, int);
Animal * animal;
Puppy * puppy;
unsigned char local_10[16];
long rsp;
long var5;
rsp = (rsp - 24);
*(long *)((&local_10[0] + 8)) = 0x3d90;
*(long *)(&local_10[0]) = 0x3dc0;
var5 = __dynamic_cast((((unsigned long)((unsigned char)((arg0 & 1))) == 0) ? (long)(&local_10[0]) : (long)((rsp + 16))), 0x3d10, 0x3d38, 0);
// x86-64 epilogue: tear down frame
return (var5 != 0);
} cpp_dynamic_cast_succeeds fail 23 lines
// glaurung: cpp_dynamic_cast_succeeds @ 0x1130
typedef struct Animal Animal;
typedef struct Dog Dog;
__attribute__((no_stack_protector)) int32_t cpp_dynamic_cast_succeeds(int32_t arg0) {
extern long __dynamic_cast(long, long, long, int);
Animal * animal;
Dog * dog;
unsigned char local_10[16];
int ret;
long rsp;
long var5;
rsp = (rsp - 24);
*(long *)((&local_10[0] + 8)) = 0x3d60;
*(long *)(&local_10[0]) = 0x3dc0;
var5 = __dynamic_cast((((unsigned long)((unsigned char)((arg0 & 1))) == 0) ? (long)(&local_10[0]) : (long)((rsp + 16))), 0x3d10, 0x3d20, 0);
if ((var5 == 0)) {
// x86-64 epilogue: tear down frame
return 0xffffffff;
}
ret = ((int (*)(long))(*(long *)((*(long *)((var5)) + 24))))(var5);
// x86-64 epilogue: tear down frame
return ret;
} cpp_typeid_compare fail 48 lines
// glaurung: cpp_typeid_compare @ 0x11f0
typedef struct Animal Animal;
__attribute__((no_stack_protector)) int32_t cpp_typeid_compare(int32_t arg0) {
extern int strcmp(const char *, const char *);
const Animal * right;
const Animal * left;
unsigned char local_10[16];
long local_18;
long ret;
long rsp;
long var19;
int var22;
long var4;
rsp = (rsp - 24);
local_18 = 0x3d90;
*(long *)(&local_10[0]) = 0x3d60;
*(long *)((&local_10[0] + 8)) = 0x3dc0;
var4 = (unsigned long)((unsigned int)((arg0 & 3)));
if (((unsigned long)((unsigned int)(var4)) == 2)) {
right = (const Animal *)&local_10[0];
left = (const Animal *)&local_10[0];
} else {
if (((unsigned long)((unsigned int)(var4)) == 1)) {
right = (const Animal *)&local_10[0];
left = (const Animal *)(rsp);
} else {
if (((unsigned long)((unsigned int)(var4)) != 0)) {
right = (const Animal *)((&local_10[0] + 8));
left = (const Animal *)(rsp);
} else {
right = (const Animal *)(rsp);
left = (const Animal *)(rsp);
}
}
}
var19 = *(long *)((*(long *)((*(long *)(((long)left)) - 8)) + 8));
if ((var19 == *(long *)((*(long *)((*(long *)(((long)right)) - 8)) + 8)))) {
// x86-64 epilogue: tear down frame
return 1;
}
ret = 0;
if (((unsigned long)((unsigned char)(*(char *)((var19)))) != 42)) {
var22 = ((int (*)(void))strcmp)();
ret = ((unsigned long)((unsigned int)(var22)) == 0);
}
// x86-64 epilogue: tear down frame
return ret;
} gcc -O0
0/4_ZNKSt9type_infoeqERKS_ structural 21 lines
// glaurung: _ZNKSt9type_infoeqERKS_ @ 0x16e2
typedef struct type_info type_info;
bool _ZNKSt9type_infoeqERKS_(const type_info * arg0, long * arg1) {
extern int strcmp(const char *, const char *);
int var11;
if ((*(long *)(((long)arg0 + 0x8)) == *(long *)(((long)arg1 + 0x8)))) {
// x86-64 epilogue: restore rbp
return 1;
}
if (((unsigned long)((unsigned char)(((unsigned int)((unsigned char)(*(char *)(*(long *)(((long)arg0 + 0x8))))) & 255))) == 42)) {
// x86-64 epilogue: restore rbp
return 0;
}
var11 = strcmp((const char *)(*(long *)(((long)arg0 + 0x8))), (const char *)(*(long *)(((long)arg1 + 0x8))));
if (((unsigned long)((unsigned int)(var11)) != 0)) {
// x86-64 epilogue: restore rbp
return 0;
}
// x86-64 epilogue: restore rbp
return 1;
} cpp_dynamic_cast_fails fail 43 lines
// glaurung: cpp_dynamic_cast_fails @ 0x1400
typedef struct Animal Animal;
typedef struct Puppy Puppy;
struct Cat;
struct Dog;
int32_t cpp_dynamic_cast_fails(int32_t arg0) {
extern void _ZN12_GLOBAL__N_13CatD1Ev(const struct Cat *);
extern void _ZN12_GLOBAL__N_13DogD2Ev(const struct Dog *);
extern long __dynamic_cast(char *, long, long, int);
extern __attribute__((noreturn)) void __stack_chk_fail(void);
Animal * animal;
Puppy * puppy;
long local_18;
unsigned char local_30[8];
unsigned char local_38[8];
long ret;
long var10;
long var17;
int var21;
char * var9;
// x86-64 prologue: save rbp, frame 8 bytes
local_18 = (long)(0x28);
*(long *)(&local_38[0]) = 0x3d60;
*(long *)(&local_30[0]) = 0x3d38;
animal = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 1))) == 0) ? (Animal *)&local_30[0] : (Animal *)&local_38[0]);
var9 = (char *)animal;
if ((animal == 0)) {
var10 = 0;
} else {
var17 = __dynamic_cast(var9, 0x3df0, 0x3da8, 0);
var10 = var17;
}
puppy = (Puppy *)(var10);
var21 = ((puppy == 0) ? 0 : 1);
((void (*)(char *))_ZN12_GLOBAL__N_13CatD1Ev)((char *)(&local_30[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13DogD2Ev)((char *)(&local_38[0]));
ret = (unsigned long)((unsigned int)(var21));
if ((local_18 != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: restore rbp
return ret;
} cpp_dynamic_cast_succeeds fail 59 lines
// glaurung: cpp_dynamic_cast_succeeds @ 0x12fd
typedef struct Animal Animal;
typedef struct Dog Dog;
struct Cat;
struct Puppy;
int32_t cpp_dynamic_cast_succeeds(int32_t arg0) {
extern __attribute__((noreturn)) long _Unwind_Resume(long);
extern void _ZN12_GLOBAL__N_13CatD1Ev(const struct Cat *);
extern void _ZN12_GLOBAL__N_15PuppyD1Ev(const struct Puppy *);
extern long __dynamic_cast(char *, long, long, int);
extern __attribute__((noreturn)) void __stack_chk_fail(void);
Animal * animal;
Dog * dog;
long local_18;
unsigned char local_30[8];
unsigned char local_38[8];
long ret;
long var10;
long var11;
long var21;
long var28;
long var29;
long var35;
long var39;
char * var9;
// x86-64 prologue: save rbp, frame 8 bytes
local_18 = (long)(0x28);
*(long *)(&local_38[0]) = 0x3d08;
*(long *)(&local_30[0]) = 0x3d38;
animal = (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 1))) != 0) ? (Animal *)&local_38[0] : (Animal *)&local_30[0]);
var9 = (char *)animal;
if ((animal != 0)) {
var10 = __dynamic_cast(var9, 0x3df0, 0x3dd8, 0);
var11 = var10;
} else {
var11 = 0;
}
dog = (Dog *)(var11);
if ((dog == 0)) {
var21 = 0xffffffff;
} else {
var28 = ((long (*)(char *))(*(long *)((*(long *)((long)dog) + 24))))((char *)((long)dog));
var29 = var28;
var21 = (unsigned long)((unsigned int)(var28));
}
((void (*)(char *))_ZN12_GLOBAL__N_13CatD1Ev)((char *)(&local_30[0]));
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyD1Ev)((char *)(&local_38[0]));
ret = (unsigned long)((unsigned int)(var21));
if ((local_18 == 0x28)) {
// x86-64 epilogue: restore rbp
return ret;
}
__stack_chk_fail();
// __glaurung_eh_landing_13cb
var35 = var29;
((void (*)(char *))_ZN12_GLOBAL__N_13CatD1Ev)((char *)(&local_30[0]));
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyD1Ev)((char *)(&local_38[0]));
var39 = _Unwind_Resume(var35);
} cpp_typeid_compare fail 98 lines
// glaurung: cpp_typeid_compare @ 0x14c3
typedef struct Animal Animal;
struct Cat;
struct Dog;
struct Puppy;
int32_t cpp_typeid_compare(int32_t arg0) {
extern __attribute__((noreturn)) long _Unwind_Resume(long);
extern void _ZN12_GLOBAL__N_13CatD1Ev(const struct Cat *);
extern void _ZN12_GLOBAL__N_13DogD2Ev(const struct Dog *);
extern void _ZN12_GLOBAL__N_15PuppyD1Ev(const struct Puppy *);
extern int _ZNKSt9type_infoeqERKS_(char *, long *);
extern long __cxa_bad_typeid(int);
extern __attribute__((noreturn)) void __stack_chk_fail(void);
const Animal * left;
const Animal * right;
long local_18;
unsigned char local_30[8];
unsigned char local_38[8];
unsigned char local_40[8];
long ret;
char * var17;
long var18;
long var19;
long var20;
long var21;
int var24;
int var26;
long var31;
long var40;
long var45;
long var8;
// x86-64 prologue: save rbp, frame 8 bytes
local_18 = (long)(0x28);
*(long *)(&local_40[0]) = 0x3d60;
*(long *)(&local_38[0]) = 0x3d08;
*(long *)(&local_30[0]) = 0x3d38;
var8 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 3)));
if (((unsigned long)((unsigned int)(var8)) == 2)) {
left = (const Animal *)&local_38[0];
right = (const Animal *)&local_38[0];
} else {
if (((((unsigned long)((unsigned int)(var8)) == 2) | ((long)((int)(var8)) < 2)) == 0)) {
L_1554: ;
left = (const Animal *)&local_40[0];
right = (const Animal *)&local_30[0];
} else {
if (((unsigned long)((unsigned int)(var8)) == 0)) {
left = (const Animal *)&local_40[0];
right = (const Animal *)&local_40[0];
} else {
if (((unsigned long)((unsigned int)(var8)) == 1)) {
left = (const Animal *)&local_40[0];
right = (const Animal *)&local_38[0];
} else {
goto L_1554;
}
}
}
}
var17 = (char *)right;
if ((right == 0)) {
var18 = __cxa_bad_typeid(arg0);
var19 = var18;
var20 = var21;
L_1585: ;
var24 = _ZNKSt9type_infoeqERKS_((char *)(*(long *)((*(long *)((var19)) - 8))), (long *)(var20));
if (((unsigned long)((unsigned char)((var24 & 255))) == 0)) {
var26 = 0;
} else {
L_15a2: ;
var26 = 1;
}
} else {
var20 = *(long *)((*(long *)((var17)) - 8));
var19 = (long)left;
if ((left == 0)) {
var31 = __cxa_bad_typeid(arg0);
goto L_15a2;
} else {
goto L_1585;
}
}
((void (*)(char *))_ZN12_GLOBAL__N_13CatD1Ev)((char *)(&local_30[0]));
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyD1Ev)((char *)(&local_38[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13DogD2Ev)((char *)(&local_40[0]));
ret = (unsigned long)((unsigned int)(var26));
if ((local_18 == 0x28)) {
// x86-64 epilogue: restore rbp
return ret;
}
__stack_chk_fail();
// __glaurung_eh_landing_15e5
var40 = ret;
((void (*)(char *))_ZN12_GLOBAL__N_13CatD1Ev)((char *)(&local_30[0]));
((void (*)(char *))_ZN12_GLOBAL__N_15PuppyD1Ev)((char *)(&local_38[0]));
((void (*)(char *))_ZN12_GLOBAL__N_13DogD2Ev)((char *)(&local_40[0]));
var45 = _Unwind_Resume(var40);
} gcc -O2
0/3cpp_dynamic_cast_fails fail 26 lines
// glaurung: cpp_dynamic_cast_fails @ 0x12c0
typedef struct Animal Animal;
typedef struct Puppy Puppy;
int32_t cpp_dynamic_cast_fails(int32_t arg0) {
extern long __dynamic_cast(long, long, long, int, long);
extern __attribute__((noreturn)) void __stack_chk_fail(void);
Animal * animal;
Puppy * puppy;
long local_10;
unsigned char local_18[8];
unsigned char local_20[8];
long rsp;
long var11;
long var8;
rsp = (rsp - 40);
local_10 = (long)(0x28);
*(long *)(&local_20[0]) = 0x3d40;
*(long *)(&local_18[0]) = 0x3d70;
var8 = __dynamic_cast((((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 1))) == 0) ? (long)(&local_18[0]) : (long)((rsp + 8))), 0x3db8, 0x3df8, 0, (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 1))));
var11 = (var8 != 0);
if ((local_10 != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: tear down frame
return (unsigned int)((unsigned char)((var11 & 255)));
} cpp_dynamic_cast_succeeds fail 33 lines
// glaurung: cpp_dynamic_cast_succeeds @ 0x1230
typedef struct Animal Animal;
typedef struct Dog Dog;
int32_t cpp_dynamic_cast_succeeds(int32_t arg0) {
extern long __dynamic_cast(long, long, long, int, long);
extern __attribute__((noreturn)) void __stack_chk_fail(void);
Dog * dog;
Animal * animal;
long local_10;
unsigned char local_18[8];
unsigned char local_20[8];
long ret;
long rsp;
long var12;
long var8;
rsp = (rsp - 40);
local_10 = (long)(0x28);
*(long *)(&local_20[0]) = 0x3d98;
*(long *)(&local_18[0]) = 0x3d70;
var8 = __dynamic_cast((((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 1))) == 0) ? (long)(&local_18[0]) : (long)((rsp + 8))), 0x3db8, 0x3dc8, 0, (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 1))));
dog = (Dog *)(var8);
if ((var8 == 0)) {
ret = 0xffffffff;
} else {
var12 = ((long (*)(char *))(*(long *)((*(long *)((var8)) + 24))))((char *)((long)dog));
ret = var12;
}
if ((local_10 != 0x28)) {
__stack_chk_fail();
}
// x86-64 epilogue: tear down frame
return ret;
} cpp_typeid_compare fail 30 lines
// glaurung: cpp_typeid_compare @ 0x1340
int32_t cpp_typeid_compare(int32_t arg0) {
extern int strcmp(const char *, const char *);
long ret;
long var1;
int var10;
long var2;
long var3;
long var8;
var1 = (unsigned long)((unsigned int)((arg0 & 3)));
var2 = 0x3d40;
var3 = 0x3d98;
if (((unsigned long)((unsigned int)(var1)) != 1)) {
var2 = var3;
if (((unsigned long)((unsigned int)(var1)) != 2)) {
var2 = 0x3d40;
var3 = (((unsigned long)((unsigned int)(var1)) == 0) ? 0x3d40 : 0x3d70);
}
}
var8 = *(long *)((*(long *)((var2 - 0x8)) + 8));
ret = 1;
if ((var8 != *(long *)((*(long *)((var3 - 0x8)) + 8)))) {
ret = 0;
if (((unsigned long)((unsigned char)(*(char *)((var8)))) != 42)) {
var10 = ((int (*)(void))strcmp)();
return ((unsigned long)((unsigned int)(var10)) == 0);
}
}
return ret;
}