2015-01-20 9 views
13

Ich erzeuge AST mit Clang. Ich habe folgende Datei (lambda.cpp) bekam zu analysieren:Wie kann man Header von AST im Clang ausschließen?

#include <iostream> 

void my_lambda() 
{ 
    auto lambda = [](auto x, auto y) {return x + y;}; 
    std::cout << "fabricati diem"; 
} 

ich dies mit folgendem Befehl bin Parsen:

clang -Xclang -ast-dump -fsyntax-only lambda.cpp 

Das Problem ist, dass Klappern parst auch Header Inhalt. Als Ergebnis habe ich ziemlich große (~ 3000 Zeilen) Datei mit nutzlosem (für mich) Inhalt.

Wie Kopfzeilen auszuschließen, wenn AST generiert wird?

+0

Was möchten Sie tun, wenn ein Name/eine Definition/etc aus der Kopfzeile benötigt wird, um den AST für die Quelldatei zu generieren? –

+0

@MarkB Ich muss mich schlecht ausgedrückt haben. Ich möchte, dass clang Header beim Parsen verwendet, aber nur AST mit meiner Datei zeigt - ohne AST von den Headern. – Kao

+0

Würde Header_gurads diesen Job nicht tun? – dhein

Antwort

13

clang-check in der Sache nützlich sein könnten, hat clang-check Option -ast-dump-filter=<string> dokumentiert als

-ast-dump-filter = <String> folgen - Verwenden Sie mit -ast-Dump oder -ast-print-Dump/Nur AST-Deklarationsknoten mit einer bestimmten Teilzeichenfolge in einem qualifizierten Namen drucken. Verwenden Sie -ast-list, um alle Namen des filterbaren Deklarationsknotens aufzulisten.

wenn clang-check Lauf mit -ast-dump-filter=my_lambda auf dem Probencode (lambda.cpp)

#include <iostream> 

void my_lambda() 
{ 
    auto lambda = [](auto x, auto y) {return x + y;}; 
    std::cout << "fabricati diem"; 
} 

es nur Deklarationsknoten FunctionDecl my_lambda 'void (void)'

Hier abgestimmt Dumps sind die Befehlszeilenargumente und einige Zeilen von Ausgang.

$ 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> 
+1

clang-check scheint ordentlich! – BeyelerStudios

1

Dies ist ein Problem mit C++ nicht mit Clang: Es gibt keine Dateien in C++, es gibt nur die Kompilierungseinheit. Wenn Sie eine Datei in die Datei #include einfügen, müssen Sie alle Definitionen in dieser Datei (rekursiv) in Ihre Übersetzungseinheit aufnehmen, und es gibt keine Möglichkeit, sie zu unterscheiden (das erwartet der Standard von Ihrem Compiler).

ein anderes Szenario Stellen Sie sich vor:

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

Ihre foobar.cpp erklärt eine Struktur namens Foo und eine Funktion namens foobar aber headertmp.h selbst definiert keine Foo es sei denn A oder B definiert sind. Nur in der Kompilationseinheit von foobar, wo die beiden zusammenkommen, ergibt sich ein Sinn von headertmp.h.

Wenn Sie an einer Teilmenge der Deklarationen innerhalb einer Kompilierungseinheit interessiert sind, müssen Sie die erforderlichen Informationen direkt aus dem generierten AST extrahieren (ähnlich wie ein Linker beim Verknüpfen verschiedener Kompilierungseinheiten vorgehen muss). Natürlich können Sie dann den AST dieser Kompilierungseinheit nach beliebigen Metadaten filtern, die Ihr Parser extrahiert.

+0

Obwohl es wahr ist, dass während der vollständigen Kompilierung einer Übersetzungseinheit kein Unterschied zwischen Code in einer Header-Datei und Code in einer Nicht-Header-Datei wahrgenommen werden sollte, handelt es sich bei dieser Frage um eine Begrenzung der AST-Extraktion, und es gibt keinen Grund, warum dies nicht der Fall wäre nicht möglich (wie aus der anderen Antwort ersichtlich). –

+0

@KyleStrand Bitte lesen Sie meinen letzten Absatz, der genau den Punkt Ihres Kommentars ausdrückt: Sie können die Extraktion/den Dump auf einen Teil der Kompilierungseinheit beschränken, im Gegensatz zu * ohne spezifische Headerdateien * (da es kein solches Konzept im AST gibt)) – BeyelerStudios

+0

Ihre Antwort sagt nicht nur, dass Header-Dateien nicht übersprungen werden können; es besagt, dass die darin enthaltenen Definitionen nicht von den Definitionen direkt in der Datei unterschieden werden können. Dies gilt für die Kompilierung, aber nicht unbedingt für die rohe AST-Extraktion. –

0

Filtering auf einer spezifischen Kennung ist in Ordnung, -ast-dump-filter verwenden. Aber was, wenn Sie von alle Bezeichner in einer Datei möchten?

kam ich auf die folgende Lösung:

In einer erkennbaren Linie nach der umfasst:

#include <iostream> 
int XX_MARKER_XX = 123234; // marker line for ast-dump 
void my_lambda() 
... 

Dann werfen den ast mit

clang-check -extra-arg=-std=c++1y -ast-dump lambda.cpp > ast.txt 

Sie können alle von Material geschnitten, bevor XX_MARKER_XX weg mit sed:

cat ast.txt | sed -n '/XX_MARKER_XX/,$p' | less 

Immer noch viel, aber viel nützlicher mit größeren Dateien.

Verwandte Themen