From 4d05a974b7f15b438cc39fb2b421e35ba6b378b1 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Mon, 20 May 2019 16:46:44 +0000 Subject: [PATCH] Dump macro expansion information as needed when outputting the AST to JSON. llvm-svn: 361172 --- clang/include/clang/AST/JSONNodeDumper.h | 6 + clang/lib/AST/JSONNodeDumper.cpp | 28 +++- clang/test/AST/ast-dump-macro-json.c | 179 +++++++++++++++++++++++ 3 files changed, 210 insertions(+), 3 deletions(-) create mode 100644 clang/test/AST/ast-dump-macro-json.c diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h index 283147517d65..85b60ec8db16 100644 --- a/clang/include/clang/AST/JSONNodeDumper.h +++ b/clang/include/clang/AST/JSONNodeDumper.h @@ -132,6 +132,12 @@ class JSONNodeDumper JOS.attribute(Key, Value); } + // Creates a single SourceLocation JSON representation of the given location. + llvm::json::Object createBareSourceLocation(SourceLocation Loc); + // Creates a JSON representation of a SourceLocation based on its presumed + // spelling location. If the given location represents a macro invocation, + // this outputs two sub-objects: one for the spelling and one for the + // expansion location. llvm::json::Object createSourceLocation(SourceLocation Loc); llvm::json::Object createSourceRange(SourceRange R); std::string createPointerRepresentation(const void *Ptr); diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index ce003ad7c377..37040eaaab7d 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -146,9 +146,9 @@ void JSONNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) { attributeOnlyIfTrue("selected", A.isSelected()); } -llvm::json::Object JSONNodeDumper::createSourceLocation(SourceLocation Loc) { - SourceLocation Spelling = SM.getSpellingLoc(Loc); - PresumedLoc Presumed = SM.getPresumedLoc(Spelling); +llvm::json::Object +JSONNodeDumper::createBareSourceLocation(SourceLocation Loc) { + PresumedLoc Presumed = SM.getPresumedLoc(Loc); if (Presumed.isInvalid()) return llvm::json::Object{}; @@ -158,6 +158,28 @@ llvm::json::Object JSONNodeDumper::createSourceLocation(SourceLocation Loc) { {"col", Presumed.getColumn()}}; } +llvm::json::Object JSONNodeDumper::createSourceLocation(SourceLocation Loc) { + SourceLocation Spelling = SM.getSpellingLoc(Loc); + SourceLocation Expansion = SM.getExpansionLoc(Loc); + + llvm::json::Object SLoc = createBareSourceLocation(Spelling); + if (Expansion != Spelling) { + // If the expansion and the spelling are different, output subobjects + // describing both locations. + llvm::json::Object ELoc = createBareSourceLocation(Expansion); + + // If there is a macro expansion, add extra information if the interesting + // bit is the macro arg expansion. + if (SM.isMacroArgExpansion(Loc)) + ELoc["isMacroArgExpansion"] = true; + + return llvm::json::Object{{"spellingLoc", std::move(SLoc)}, + {"expansionLoc", std::move(ELoc)}}; + } + + return SLoc; +} + llvm::json::Object JSONNodeDumper::createSourceRange(SourceRange R) { return llvm::json::Object{{"begin", createSourceLocation(R.getBegin())}, {"end", createSourceLocation(R.getEnd())}}; diff --git a/clang/test/AST/ast-dump-macro-json.c b/clang/test/AST/ast-dump-macro-json.c new file mode 100644 index 000000000000..14b88adcfaae --- /dev/null +++ b/clang/test/AST/ast-dump-macro-json.c @@ -0,0 +1,179 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump=json %s | FileCheck %s + +#define FOO frobble +#define BAR FOO + +void FOO(void); +void BAR(void); + +#define BING(x) x + +void BING(quux)(void); + +#define BLIP(x, y) x ## y +#define BLAP(x, y) BLIP(x, y) + +void BLAP(foo, __COUNTER__)(void); +void BLAP(foo, __COUNTER__)(void); + + +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "expansionLoc": { +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "spellingLoc": { +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 6 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 14, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 6 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "frobble", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void)" +// CHECK-NEXT: } +// CHECK-NEXT: } + + +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "expansionLoc": { +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 7 +// CHECK-NEXT: }, +// CHECK-NEXT: "spellingLoc": { +// CHECK-NEXT: "col": 13, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 7 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 14, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 7 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "previousDecl": "0x{{.*}}", +// CHECK-NEXT: "name": "frobble", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void)" +// CHECK-NEXT: } +// CHECK-NEXT: } + + +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "expansionLoc": { +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "isMacroArgExpansion": true, +// CHECK-NEXT: "line": 11 +// CHECK-NEXT: }, +// CHECK-NEXT: "spellingLoc": { +// CHECK-NEXT: "col": 11, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 11 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 11 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 21, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 11 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "quux", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void)" +// CHECK-NEXT: } +// CHECK-NEXT: } + + +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "expansionLoc": { +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 16 +// CHECK-NEXT: }, +// CHECK-NEXT: "spellingLoc": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "", +// CHECK-NEXT: "line": 3 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 16 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 33, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 16 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "foo0", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void)" +// CHECK-NEXT: } +// CHECK-NEXT: } + + +// CHECK: "kind": "FunctionDecl", +// CHECK-NEXT: "loc": { +// CHECK-NEXT: "expansionLoc": { +// CHECK-NEXT: "col": 6, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 17 +// CHECK-NEXT: }, +// CHECK-NEXT: "spellingLoc": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "", +// CHECK-NEXT: "line": 5 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "range": { +// CHECK-NEXT: "begin": { +// CHECK-NEXT: "col": 1, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 17 +// CHECK-NEXT: }, +// CHECK-NEXT: "end": { +// CHECK-NEXT: "col": 33, +// CHECK-NEXT: "file": "{{.*}}", +// CHECK-NEXT: "line": 17 +// CHECK-NEXT: } +// CHECK-NEXT: }, +// CHECK-NEXT: "name": "foo1", +// CHECK-NEXT: "type": { +// CHECK-NEXT: "qualType": "void (void)" +// CHECK-NEXT: } +// CHECK-NEXT: }