c++ - ¿Cómo excluir encabezados de AST en clang?
abstract-syntax-tree (3)
El filtrado de un identificador específico está bien, usando -ast-dump-filter
. Pero, ¿y si quieres ast de todos los identificadores en un archivo ?
Se me ocurrió la siguiente solución:
Añadir una línea reconocible después de los incluye:
#include <iostream>
int XX_MARKER_XX = 123234; // marker line for ast-dump
void my_lambda()
...
Luego tira el ast con
clang-check -extra-arg=-std=c++1y -ast-dump lambda.cpp > ast.txt
Puedes cortar fácilmente todas las cosas antes de XX_MARKER_XX
con sed
:
cat ast.txt | sed -n ''/XX_MARKER_XX/,$p'' | less
Todavía mucho, pero mucho más útil con archivos más grandes.
Estoy generando AST usando clang. Tengo el siguiente archivo (lambda.cpp) para analizar:
#include <iostream>
void my_lambda()
{
auto lambda = [](auto x, auto y) {return x + y;};
std::cout << "fabricati diem";
}
Estoy analizando esto usando el siguiente comando:
clang -Xclang -ast-dump -fsyntax-only lambda.cpp
El problema es que Clang analiza también los encabezados de contenido. Como resultado, tengo un archivo bastante grande (~ 3000 líneas) con contenido inútil (para mí).
¿Cómo excluir encabezados al generar AST?
Este es un problema con C ++ no con Clang: no hay archivos en C ++, solo está la unidad de compilación. Cuando #include
un archivo, incluye todas las definiciones en dicho archivo (recursivamente) en su unidad de compilación y no hay manera de diferenciarlas (es lo que el estándar espera que haga su compilador).
Imagina un escenario diferente:
/////////////////////////////
// headertmp.h
#if defined(A)
struct Foo {
int bar;
};
#elif defined(B)
struct Foo {
short bar;
};
#endif
/////////////////////////////
// foobar.cpp
#ifndef A
# define B
#endif
#include "headertmp.h"
void foobar(Foo foo) {
// do stuff to foo.bar
}
Su foobar.cpp declara una estructura llamada Foo
y una función llamada foobar
pero headertmp.h
no define ningún Foo
menos que A
o B
estén definidos. Solo en la unidad de compilación de foobar donde los dos se juntan puede dar sentido a headertmp.h
.
Si está interesado en un subconjunto de las declaraciones dentro de una unidad de compilación, tendrá que extraer la información necesaria del AST generado directamente (similar a lo que tiene que hacer un enlazador al vincular diferentes unidades de compilación). Por supuesto, luego puede filtrar el AST de esta unidad de compilación en cualquier metadata que extraiga su analizador.
clang-check
puede ser útil al respecto, clang-check
tiene la opción -ast-dump-filter=<string>
documentada como sigue
-ast-dump-filter = <string> - Use con -ast-dump o -ast-print para volcar / imprimir solo los nodos de declaración AST que tengan una determinada subcadena en un nombre calificado. Utilice -ast-list para enumerar todos los nombres de nodo de declaración filtrables.
cuando clang-check
ejecuta con -ast-dump-filter=my_lambda
en el código de ejemplo (lambda.cpp)
#include <iostream>
void my_lambda()
{
auto lambda = [](auto x, auto y) {return x + y;};
std::cout << "fabricati diem";
}
Vuelca solo el nodo de declaración coincidente FunctionDecl my_lambda ''void (void)''
Aquí están los argumentos de línea de comando y algunas líneas de salida.
$ clang-check -extra-arg=-std=c++1y -ast-dump -ast-dump-filter=my_lambda lambda.cpp --
FunctionDecl 0x2ddf630 <lambda.cpp:3:1, line:7:1> line:3:6 my_lambda ''void (void)''
`-CompoundStmt 0x2de1558 <line:4:1, line:7:1>
|-DeclStmt 0x2de0960 <line:5:9, col:57>