2011-07-06 6 views
9

necesito para preprocesar algunos C++ archivos para insertar automáticamente el código para la prueba y perfiles, y tengo que hacerlo con la API de sonido metálico .Handle C++ con funciones API de sonido metálico para insertar código

Por ahora, quiero ser capaz de hacer lo siguiente: Si hay una función:

int SomeFn(int a, int b, int c) { 
    doStuff(); 
} 

Quiero preproceso ella, que se ve así:

int SomeFn(int a, int b, int c) { 
    cout << "SomeFn is invoked with the following arguments: a=" << a << ", b=" << b << ", c=" << c << endl; 
    doStuff(); 
} 

He intentado extender ASTConsumer y usar los métodos HandleTopLevelDecl y HandleTopLevelSingleDecl y verificar si el Decls pasado es y bajarlos, así puedo obtener sus nombres y ubicaciones corporales. Pero no puedo manejar los métodos de clase de esa manera, solo las funciones globales.

Encontré una función en la clase ASTConsumerHandleTagDeclDefinition(TagDecl* D). La documentación dice:

Esta devolución de llamada se invoca cada vez que un TagDecl (por ejemplo, estructura, unión, enumeración, clase) se ha completado.

Pero parece que este método ni siquiera se invoca cuando lo pruebo.

Entonces mi pregunta es, ¿cuál sería la forma correcta de hacer esta tarea? ¿Y cómo se representan las clases de C++ en la API de clang? Tal vez alguien lo sepa, donde puedo encontrar ejemplos porque la API de clang está poco documentada.


ACTUALIZACIÓN:

Sé que también es el concepto de Visitors y no hay un método VisitRecordDecl(RecordDecl *D). La documentación dice que RecordDecl representa las clases. Así que extendí RecursiveASTVisitor e implementé VisitRecordDecl(RecordDecl *D) pero parece que este método tampoco se invoca. En su lugar se invoca VisitVarDecl, cuando se encuentra una definición de clase, como si se viera como una declaración de variable. Así que estoy un poco confundido. Espero que alguien pueda ayudar ...


Update2:

Me trataron de analizar otro archivo de sonido metálico y esta vez encontró una RecordDecl. Pero el archivo definió una estructura y dos clases, así que creo que mi código clang analiza C en lugar de C++. ¿Hay alguna configuración para cambiar entre C y C++?

+5

Re "porque la API de clang está poco documentada". Para el software de código abierto, la documentación es bastante buena. Hay un manual de usuario en http://clang.llvm.org/docs/UsersManual.html y la API está en autogenerado por doxygen en http://clang.llvm.org/doxygen/index.html. ¿Qué más podrías querer? –

+2

El manual es para el compilador, que no necesito, y el doxygen doc es útil, si sabes cómo funciona el clang, pero yo no. –

+0

En este documento técnico se describe un enfoque que no es Clang que podría ser conceptualmente más fácil de entender: "Cobertura de sucursales simplificada" http://www.semanticdesigns.com/Company/Publications/TestCoverage.pdf La cobertura de sucursales es un tipo de prueba cobertura; el documento discute cómo hacer perfiles utilizando las mismas ideas. –

Respuesta

10

¿Hay alguna configuración para cambiar entre C y C++?

fin he encontrado la manera de manejar esto:

que se extendía desde ASTConsumer y RecursiveASTVisitor<MyConsumer> para atravesar el AST y VisitCXXRecordDecl(CXXRecordDecl* D) implementado. Luego tuve que configurar el parámetro LangOptions para el preprocesador, por lo que analiza C++.

langOpts.CPlusPlus = 1; 

Mi culpa fue pensar que sería analizar C++ de inmediato, pero que no era el caso, se analiza C por defecto y así no reconoce clases.

1

Acepto que la documentación de CLang podría faltar en algún área. Desafortunadamente, esta es la forma en que funciona el código abierto: faltará hasta que alguien lo necesite, se da cuenta y decide contribuir con sus hallazgos.

Para su problema específico le sugiero que publique en la lista de correo de Clang Dev (o comience por sifting through the archives).Las preguntas sobre ASTConsumers u otro análisis de transformación son bastante frecuentes y generalmente se responden rápidamente.

Y luego, cuando hayas aprendido lo que estabas buscando, qué piensa acerca de la actualización de la documentación;)

3

me pregunto por qué usted quiere hacer esta transformación sobre la marcha (si entiendo la derecha) Esto es especialmente complicado con los métodos de C++ definidos en la clase, ya que están compilados como si estuvieran definidos fuera de la clase (es decir, todos los miembros de la clase son utilizables, incluso aquellos no declarados aún).

De todos modos, cuando tiene un RecordDecl, puede acceder a sus miembros a través de field_begin.

Obviamente, cuando encuentre clases nexted, tendrá que enumerarlas también. De hecho, dado que puede definir métodos en clases de funciones, deberá verificar las declaraciones anidadas en casi todas partes.

+0

Entonces, ¿cómo obtengo un 'RecordDecl'? Supongo que tengo que bajar de Decl, pero ¿en qué método de manejo? 'HandleTagDeclDefinition (TagDecl * D)'? –

+0

Bueno, las estadísticas generales estarían en el nivel superior (y podrías encontrarlas ¿no?), Y para las clases anidadas las encontrarás dentro de las funciones y otras clases. No sé sobre lambda, son demasiado nuevos. – MSalters

+0

Implementé 'VisitRecordDecl (RecordDecl * D)', pero no se invoca en absoluto, aunque hay una definición de clase en mi código. En cambio, se invoca 'VisitVarDecl' ... –

Cuestiones relacionadas