es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Obtener el SourceRange de las instancias explícitas de plantillas utilizando la biblioteca AST de clang.

En el archivo de origen de C++ siguiente:

//file my_func.cpp
void template<typename bar=""> foo(Bar& bar) {
    // some code
}
template void foo<double>(double&);

Quiero obtener el comienzo y el final de la instanciación explícita de la plantilla de función foo en forma de una clang::SourceLocation.

He intentado lo siguiente:

clang::FunctionDecl* FS; //el nodo AST para la función foo<double> obtenido por algún matcher AST
if(const clang::FunctionTemplateSpecializationInfo* TSI = FS->getTemplateSpecializationInfo()) {
    clang::SourceLocation = TSI->getPointOfInstantiation();
}

Este lugar será la línea 5 y columna 15 (el comienzo de “foo”).
No he encontrado una forma de obtener el comienzo y el final completos de la instanciación explícita.
¿Existe alguna manera de lograr esto?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Como experto en TI especializado en c++, árbol de sintaxis abstracta y libtooling, aquí está mi respuesta a la pregunta:

    Desafortunadamente, no hay una forma directa de obtener el comienzo y el final de la instantiación explícita completa de una plantilla de función en Clang. Sin embargo, puedes intentar utilizar algunos métodos alternativos para lograr esto.

    Una posible solución es utilizar la API de Tokens de Clang para obtener los tokens que representan la instantiación explícita y luego utilizar sus ubicaciones de origen para obtener el comienzo y el final de la instantiación.

    Aquí hay un ejemplo de implementación:

    clang::FunctionDecl* FS; //el nodo AST para la función foo<double> obtenida por algún matcher AST
    
    if (const clang::FunctionTemplateSpecializationInfo* TSI = FS->getTemplateSpecializationInfo()) {
        // obtén los tokens para la instantiación explícita
        clang::SourceManager& SM = TheRewriter.getSourceMgr();
        clang::Token BeginToken = clang::Lexer::findNextToken(TSI->getTemplate()->getLocation(), SM, TheRewriter.getLangOpts());
        clang::Token EndToken = clang::Lexer::findNextToken(TSI->getPointOfInstantiation(), SM, TheRewriter.getLangOpts());
    
        // obtén las ubicaciones de origen de los tokens
        clang::SourceLocation BeginLoc = BeginToken.getLocation();
        clang::SourceLocation EndLoc = EndToken.getLocation().getLocWithOffset(EndToken.getLength());
    
        // muestra los resultados
        llvm::outs() << "Comienzo de la instantiación explícita: " << SM.getFilename(BeginLoc) << ":" << SM.getSpellingLineNumber(BeginLoc) << ":" << SM.getSpellingColumnNumber(BeginLoc) << "\n";
        llvm::outs() << "Fin de la instantiación explícita: " << SM.getFilename(EndLoc) << ":" << SM.getSpellingLineNumber(EndLoc) << ":" << SM.getSpellingColumnNumber(EndLoc) << "\n";
    }
    

    Esta implementación utiliza la utilidad Lexer de Clang para obtener los tokens de la instantiación explícita y luego utiliza sus ubicaciones de origen para obtener el comienzo y el final de la instantiación. Ten en cuenta que el parámetro TheRewriter es una instancia de la clase Rewriter de Clang utilizada para reescribir código, por lo que tendrás que adaptar esta implementación a tu caso de uso específico.

    ¡Espero que esto ayude!

Comments are closed.