2 Stimmen

Was sind "abgesenkte vtable-Referenzen"?

Clang's eigene Diagnose-Propaganda enthält diesen Auszug:

Da Clang über eine Bereichshervorhebung verfügt, muss es Ihren Code nie schön ausgeben. Dies ist besonders schlecht in G++ (das oft Fehler, die herabgesetzte vtable-Referenzen enthalten ), aber sogar GCC kann in einigen Fällen unerklärliche Fehlermeldungen produzieren, wenn er versucht, dies zu tun.

Wenn man diesen Begriff googelt, findet man nichts Hilfreiches, und das folgende Beispiel hat nichts damit zu tun.

Kann jemand bitte ein Beispiel dafür geben, wovon die Rede ist?

Gracias.

5voto

Chris Lattner Punkte 796

Hier ist ein Beispiel:

struct a {
  virtual int bar();
};

struct foo : public virtual a {
};

void test(foo *P) {
  return P->bar()+*P;
}

Clang produziert:

t.cc:9:18: error: invalid operands to binary expression ('int' and 'foo')
  return P->bar()+*P;
         ~~~~~~~~^~~

GCC 4.2 produziert:

t.cc: In function ‘void test(foo*)’:
t.cc:9: error: no match for ‘operator+’ in ‘(((a*)P) + (*(long int*)(P->foo::<anonymous>.a::_vptr$a + -0x00000000000000020)))->a::bar() + * P’
t.cc:9: error: return-statement with a value, in function returning 'void'

GCC tut dies, weil sein C++-Frontend in vielen Fällen auf das C-Frontend aufgeschraubt ist. Anstatt C++-spezifische Abstract Syntax Trees (ASTs) für verschiedene C++-Operationen zu erstellen, setzt der Parser sie einfach direkt auf ihre C-Entsprechung herunter. In diesem Fall synthetisiert der GCC eine struct, die die vtable enthält, und die Zeigerdereferenz auf bar wird dann in eine Reihe von C-Zeigerdereferenzen, Casts, Zeigerarithmetik usw. heruntergebrochen.

Clang hat dieses Problem nicht, da es einen sehr sauberen AST hat, der direkt den Quellcode darstellt. Wenn Sie das Beispiel ändern in:

struct a {
  virtual int bar();
};

struct foo : public virtual a {
};

void test(foo *P) {
  P->bar();
}

so dass der Code gültig ist, dann fragen Sie Clang zu dump seine ast mit "clang -cc1 -ast-dump t.cc", erhalten Sie:

...
void test(foo *P)
(CompoundStmt 0x10683cae8 <t.cc:8:19, line:10:1>
  (CXXMemberCallExpr 0x10683ca78 <line:9:3, col:10> 'int'
    (MemberExpr 0x10683ca40 <col:3, col:6> '<bound member function type>' ->bar 0x10683bef0
      (ImplicitCastExpr 0x10683cac8 <col:3> 'struct a *' <UncheckedDerivedToBase (virtual a)>
        (ImplicitCastExpr 0x10683ca28 <col:3> 'struct foo *' <LValueToRValue>
          (DeclRefExpr 0x10683ca00 <col:3> 'struct foo *' lvalue ParmVar 0x10683c8a0 'P' 'struct foo *'))))))

-Chris

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X