2017-07-17 6 views
0

Ich schreibe einen LLVM-Pass, der Funktionen unter anderem umbenennt. Ich habe dieses kleine Stück CodeWarum verursacht dieser Typalias einen Kompilierungsfehler (C++)?

// Get function arguments 
std::vector<Argument*> Arguments; 
for (auto Arg = F.arg_begin(); Arg != F.arg_end(); ++Arg) 
{ 
    Type *ArgTy = Arg->getType(); 

    if (ArgTy->isFloatingPointTy()) 
    { 
    errs() << "Cannot test function: " << F.getName() << " (floating point arguments)\n"; 
    return false; 
    } 
    Arguments.push_back(Arg); 
} 

Die Linie Arguments.push_back(Arg) einen Übersetzungsfehler verursacht:

no known conversion for argument 1 from ‘llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Argument, false, false, void>, false, false>’ to ‘llvm::Argument* const&’.

jedoch in der Header-Datei llvm/IR/Function.h (source), arg_iterator als Alias ​​für den Typen deklariert wird Argument *, und die Funktionen arg_begin() und arg_end() durch eine Function Instanz aufgerufen, gibt einen arg_iterator() Typen. Warum bekomme ich den Typfehler? Hat es etwas mit der Verwendung des Schlüsselwortes auto zu tun?

+0

Sie * können * Iteratoren verwenden? Was bekommen Sie, wenn Sie zB einen Iterator * dereferenzieren? –

+2

@Someprogrammerdude Wenn der Iterator vom Typ 'Argument *' ist, erhalten Sie das spitze 'Argument' als Lvalue. Aber die Frage ist, warum der Typ von 'auto Arg = F.arg_begin() 'nicht' arg_iterator' (== 'Argument *') ist, wie im Header deklariert, sondern etwas anderes. UnchartedWaters: Erstelle ein [mcve]. Ihr Beispiel ist unvollständig. – user2079303

Antwort

0

Versuchen zu dereferenzieren Ihre Iterator:

std::vector<Argument*> Arguments; 
for (auto Arg = F.arg_begin(); Arg != F.arg_end(); ++Arg) 
{ 
    auto *ArgTy = Arg->getType(); 

    if (ArgTy->isFloatingPointTy()) 
    { 
    errs() << "Cannot test function: " << F.getName() << " (floating point arguments)\n"; 
    return false; 
    } 
    Arguments.push_back(*Arg); 
} 

Dies funktioniert nur, wenn F speichert Objekte wie Argument*

1

die Version der Dateien überprüfen, die Sie auf Ihrem Laufwerk verwenden. Wenn Sie es nicht direkt vom GitHub verwenden, aber vielleicht Ihre Dateien mit der LLVM-Installation kommen, überprüfen Sie die tatsächlichen Dateien, mit denen Sie arbeiten.

Die „Schuld“ an dem GitHub zeigt, dass eine Änderung der arg_begin/arg_end Rückgabetypen ArgumentListType::iterator-Argument * etwa 4 Monate (commit) gibt es, so dass Sie gegen die alte Version bauen könnten, die noch der ursprüngliche komplexe Iteratortyp.

0

die Kompilierung-Fehler zu vermeiden, wie mögliche Lösung

wie folgt ist
// Get function arguments 
std::vector<Argument*> Arguments; 
for (auto Arg = F.arg_begin(); Arg != F.arg_end(); ++Arg) 
{ 
    Type *ArgTy = Arg->getType(); 

    if (ArgTy->isFloatingPointTy()) 
    { 
    errs() << "Cannot test function: " << F.getName() << " (floating point arguments)\n"; 
    return false; 
    } 
    // Grab a pointer to the argument reference 
    Argument *ArgPtr = &*Arg; 
    Arguments.push_back(ArgPtr); 
} 

Mein Problem von meinem Missverständnis von Zeigern vs Referenzen in C++ entstand (here für weitere Einzelheiten sehen).

Ich bin mir nicht sicher, warum arg_iterator != Argument * zur Kompilierzeit - es ist vielleicht wegen einiger LLVM spezifische Funktionalität. In jedem Fall müssen wir Arg dereferenzieren, um einen Argument Typ zu erhalten, und dann die Adresse des Argument Typs (mit dem Operator &) nehmen, um einen Zeiger auf diesen Argument Typ zu erhalten.

+0

Ich denke, Ihre Verwirrung ist zwischen Iteratoren und Zeigern, nicht Referenzen und Zeigern – Useless

+0

Der Code sollte auch in der ursprünglichen Version funktionieren, aber nur, wenn der 'arg_begin' Rückgabetyp wirklich' Argument * 'ist, dh wenn Sie den letzten verwenden Version von GitHub - da war eine Veränderung, siehe meine Antwort. – axalis

Verwandte Themen