2017-07-17 1 views
0

J'écris un passage LLVM qui renomme des fonctions parmi d'autres choses. J'ai ce petit morceau de codePourquoi cet alias de type provoque-t-il une erreur de compilation (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); 
} 

La ligne Arguments.push_back(Arg) provoque une erreur de compilation:

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&’.

Cependant, dans le fichier d'en-tête llvm/IR/Function.h (source), arg_iterator est déclarée comme un alias pour le type Argument * et les fonctions arg_begin() et arg_end() appelées par une instance Function, retourner un type arg_iterator(). Alors, pourquoi ai-je l'erreur de type? Cela a-t-il quelque chose à voir avec l'utilisation du mot-clé auto?

+0

Vous * savez * utiliser les itérateurs? Qu'est-ce que vous obtenez quand (par exemple) vous * déréférencer * un itérateur? –

+2

@Someprogrammerdude lorsque l'itérateur est de type 'Argument *', vous obtenez le 'Argument' pointé comme lvalue. Mais la question est de savoir pourquoi le type de 'auto Arg = F.arg_begin()' n'est pas 'arg_iterator' (==' Argument * ') comme déclaré dans l'en-tête mais quelque chose d'autre. UnchartedWaters: Créez un [mcve]. Votre exemple est incomplet. – user2079303

Répondre

0

Essayez de déréférencer votre 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); 
} 

Cela ne fonctionnera que si les magasins F objets tels que Argument*

1

Vérifiez la version des fichiers que vous utilisez sur votre lecteur. Si vous ne l'utilisez pas directement depuis le GitHub, mais que vos fichiers arrivent avec l'installation de LLVM, vérifiez les fichiers que vous construisez.

Le « blâme » sur les spectacles GitHub, qu'il y avait un changement dans les arg_begin/arg_end types de retour de ArgumentListType::iterator à Argument * il y a environ 4 mois (commit), de sorte que vous pourriez construire contre l'ancienne version, qui a encore le type d'itérateur complexe d'origine.

0

Pour éviter l'erreur de compilation, comme solution possible est la suivante

// 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); 
} 

Mon problème a surgi de mon incompréhension de pointeurs vs références en C++ (voir here pour plus de détails).

Je ne sais pas pourquoi arg_iterator != Argument * au moment de la compilation - c'est peut-être à cause de certaines fonctionnalités spécifiques au LLVM. Dans tous les cas, nous devons déréférencer Arg afin d'obtenir un type Argument, puis prendre l'adresse du type Argument (avec l'opérateur &) afin d'obtenir un pointeur vers ce type Argument.

+0

Je pense que votre confusion est entre les itérateurs et les pointeurs, pas les références et les pointeurs – Useless

+0

Le code devrait aussi fonctionner dans la version originale, mais seulement si le type de retour 'arg_begin' est vraiment' Argument * ', ie si vous utilisez le récent version de GitHub - il y avait un changement, voir ma réponse. – axalis