diff options
author | Josh Gao <jmgao@google.com> | 2017-11-06 17:15:47 -0800 |
---|---|---|
committer | Josh Gao <jmgao@google.com> | 2017-11-06 17:23:36 -0800 |
commit | 8e13b67c64df389ce72bcb02ab3e1888da48f254 (patch) | |
tree | 267672ca0200e822e6139271abd404893880e754 /tools/versioner/src/DeclarationDatabase.cpp | |
parent | db4f3346958684424815720ca00a56c75fc536e0 (diff) |
versioner: properly handle extern "C", "C++".
extern "C" and "C++" are parsed as a LinkageSpecDecl with the real Decl
as a child node. This leads to the preprocessor sticking its guard
between the extern specifier and the declaration.
Update the AST visitor to add a special-case for calculating the
SourceRange on a LinkageSpecDecl, and add a test.
Bug: https://github.com/android-ndk/ndk/issues/440
Test: python run_tests.py
Change-Id: I76445fe366cef46cfd2f16fb93d534d410c5edca
Diffstat (limited to 'tools/versioner/src/DeclarationDatabase.cpp')
-rw-r--r-- | tools/versioner/src/DeclarationDatabase.cpp | 67 |
1 files changed, 51 insertions, 16 deletions
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp index 44438340e..19c2f0d0a 100644 --- a/tools/versioner/src/DeclarationDatabase.cpp +++ b/tools/versioner/src/DeclarationDatabase.cpp @@ -90,7 +90,7 @@ class Visitor : public RecursiveASTVisitor<Visitor> { return "<unnamed>"; } - bool VisitDecl(Decl* decl) { + bool VisitDeclaratorDecl(DeclaratorDecl* decl, SourceRange range) { // Skip declarations inside of functions (function arguments, variable declarations inside of // inline functions, etc). if (decl->getParentFunctionOrMethod()) { @@ -143,21 +143,6 @@ class Visitor : public RecursiveASTVisitor<Visitor> { return true; } - auto start_loc = src_manager.getPresumedLoc(decl->getLocStart()); - auto end_loc = src_manager.getPresumedLoc(decl->getLocEnd()); - - Location location = { - .filename = start_loc.getFilename(), - .start = { - .line = start_loc.getLine(), - .column = start_loc.getColumn(), - }, - .end = { - .line = end_loc.getLine(), - .column = end_loc.getColumn(), - } - }; - DeclarationAvailability availability; // Find and parse __ANDROID_AVAILABILITY_DUMP__ annotations. @@ -215,6 +200,24 @@ class Visitor : public RecursiveASTVisitor<Visitor> { std::tie(symbol_it, dummy) = database.symbols.insert({ declaration_name, symbol }); } + auto expansion_range = src_manager.getExpansionRange(range); + auto filename = src_manager.getFilename(expansion_range.getBegin()); + if (filename != src_manager.getFilename(expansion_range.getEnd())) { + errx(1, "expansion range filenames don't match"); + } + + Location location = { + .filename = filename, + .start = { + .line = src_manager.getExpansionLineNumber(expansion_range.getBegin()), + .column = src_manager.getExpansionColumnNumber(expansion_range.getBegin()), + }, + .end = { + .line = src_manager.getExpansionLineNumber(expansion_range.getEnd()), + .column = src_manager.getExpansionColumnNumber(expansion_range.getEnd()), + } + }; + // Find or insert an entry for the declaration. if (auto declaration_it = symbol_it->second.declarations.find(location); declaration_it != symbol_it->second.declarations.end()) { @@ -238,6 +241,38 @@ class Visitor : public RecursiveASTVisitor<Visitor> { return true; } + + bool VisitDeclaratorDecl(DeclaratorDecl* decl) { + return VisitDeclaratorDecl(decl, decl->getSourceRange()); + } + + bool TraverseLinkageSpecDecl(LinkageSpecDecl* decl) { + // Make sure that we correctly calculate the SourceRange of a declaration that has a non-braced + // extern "C"/"C++". + if (!decl->hasBraces()) { + DeclaratorDecl* child = nullptr; + for (auto child_decl : decl->decls()) { + if (child != nullptr) { + errx(1, "LinkageSpecDecl has multiple children"); + } + + if (DeclaratorDecl* declarator_decl = dyn_cast<DeclaratorDecl>(child_decl)) { + child = declarator_decl; + } else { + errx(1, "child of LinkageSpecDecl is not a DeclaratorDecl"); + } + } + + return VisitDeclaratorDecl(child, decl->getSourceRange()); + } + + for (auto child : decl->decls()) { + if (!TraverseDecl(child)) { + return false; + } + } + return true; + } }; bool DeclarationAvailability::merge(const DeclarationAvailability& other) { |