[clang] Stmt zu BinaryOperator downcasten

  • C++

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Trade.

    [clang] Stmt zu BinaryOperator downcasten

    Hi,

    ich erweitere grade ein Plugin, das auf clang basiert. Ich erhalte aus dem Clang Control Flow Graph die zugehörige Basic-Block-Struktur und traversiere diese. Für einen Block (clang.llvm.org/doxygen/classclang_1_1CFGBlock.html) möchte ich dann dessen Terminator abrufen. Dazu gibt es die Methode getTerminatorStmt, welche ich auch nutze und welche ein allgemeines Stmt-Objekt zurückgibt. Problem ist nun, dass ich wissen will, wenn es sich bei diesem um einen BinaryOperator handelt, dass ich das zwar (auf andere Weise über strcmp) prüfen kann (unschön), aber dann so oder so keine Möglichkeit sehe, das Objekt auch als solches zu behandeln. Habe natürlich versucht mit 'nem dynamic_cast daraus einen BinaryOperator* zu machen, aber in Stmt sind keinerlei Funktionen virtuell markiert, sodass der Typ nicht polymorph ist und das nicht funktioniert. Habe auch keine Template-Methoden gefunden, die mir ein Casten erlauben o.ä. Wisst Ihr da vllt., was ich machen könnte?

    Das wäre quasi mein Ziel:

    C-Quellcode

    1. CFGBlock *current = ...;
    2. auto terminatorStmt = current->getTerminatorStmt();
    3. auto binaryOp = dynamic_cast<clang::BinaryOperator*>(terminatorStmt);
    4. bool isLogicalBinaryOperator = binaryOp && binaryOp->isLogicalOp();


    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Trade“ () aus folgendem Grund: Codetag getestet

    Bist du sicher das die nicht polymorph sind? Eigentlich ist es Quatsch ohne virtuelle Funktionen von etwas zu erben. dynamic_cast<> ist nur für polymorphe Typen gültig. Ansonsten gibt's da glaube ich keine Möglichkeit wenn clang nichts vorgesehen hat. std::is_same<>, is_base_of<> & Co arbeiten alle zur Compile-Time.

    Gonger96 schrieb:

    Bist du sicher das die nicht polymorph sind?
    Ich habe mir den Quellcode angesehen und dort ist nichts als virtual markiert. Und dynamic_cast sagt mir auch genau dasselbe, dass der Typparameter polymorph sein muss und es aber nicht ist.
    Ich verstehe bloß nicht, was die Autoren sich dann gedacht haben dabei. Was bringt mir dann die Vererbungskette und vor allem die Terminatorfunktion, wenn ich mit dem Objekt nicht arbeiten kann. ?(
    Die Typprüfung kann ich ja vornehmen über den Klassennamen (auch wenn das 'n ​char* ist), aber ich brauche das konkrete Objekt.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Dafür gibt es eine Funktion in ​Stmt.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Die Typenprüfung mit char* ist ein bisschen doof (nimm übrigens std::string und Operator == anstatt strcmp). Die verwenden intern anscheinend Bitfields StmtBits.sClass. Vielleicht gibt's ne Methode um den zu bekommen, dann kannst du einfach einen int vergleichen.
    Um dann den Typ zu casten sollte static_cast<> reichen.
    Oh man. static_cast war auch meine Idee, aber als ich es probiert hatte, hat VS gemeckert (bzw. ReSharper), dass er es nicht casten kann. Jetzt grad nochmal probiert und es geht. Dann ist es kein Stress mehr, weil wenn ich den Typ ja weiß, kann ich sicher casten. Verstehe nur nicht, warum es jetzt geht. Komisch. Trotzdem könnte clang es einfach polymorph machen, wär schöner. War scheinbar auch mal so, da ich einen Ausschnitt von StackOverflow gefunden habe, wo das angewandt wurde. Ist aber schon älter.

    Aber das mit ​std::string ist nice. Hatte ich nicht auf dem Schirm, dass die das ja wrappen. Dann kann ich ja da optimal C++-konform bleiben.
    Danke Dir.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Habe gerade gesehen das llvm intern dyn_cast verwendet um ein Stmt pointer in einen BinaryOperator zu casten.

    C-Quellcode

    1. if (auto bo = dyn_cast<BinaryOperator>(stmt))
    2. {}


    Laut mehrehren Aussagen ist dyn_cast llvm's Art nicht virtuelle Klassen zu downcasten.

    Nachtrag:
    Im übrigen scheint Clang auch den visitor-pattern zu verwenden.

    C-Quellcode

    1. class MeinVisitor : public StmtVisitor<MeinVisitor>
    2. {
    3. public:
    4. void VisitStmtName(StmtName *stmt)
    5. {
    6. // code wenn dieses statement
    7. }
    8. }
    9. // verwendung
    10. StmtVisitor<MeinVisitor>::Visit(statementVar);
    ----------------------------------------------------------------------------------------------------------------------

    Hier könnte meine Signatur stehen, aber die ist mir abfußen gekommen.

    ----------------------------------------------------------------------------------------------------------------------

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Elanda“ ()

    Elanda schrieb:

    Habe gerade gesehen das llvm intern dyn_cast verwendet um ein Stmt pointer in einen BinaryOperator zu casten.
    Cool, sowas hatte ich in clang/LLVM gesucht, aber nicht gefunden. Dann macht das auch Sinn, warum die keine virtuellen Member deklarieren. Dann kann ich das ja sogar angenehm prüfen und casten. Wie hast Du das gefunden?

    Elanda schrieb:

    Im übrigen scheint Clang auch den visitor-pattern zu verwenden.
    Ja.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!: