Merge "versioner: properly handle extern "C", "C++"."

This commit is contained in:
Treehugger Robot 2017-11-07 04:31:31 +00:00 committed by Gerrit Code Review
commit 691758c1c2
6 changed files with 127 additions and 22 deletions

View file

@ -63,11 +63,8 @@ char* strchr(const char* __s, int __ch) __attribute_pure__ __overloadable __RENA
char* __strchr_chk(const char* __s, int __ch, size_t __n) __INTRODUCED_IN(18);
#if defined(__USE_GNU)
#if defined(__cplusplus)
/* The versioner doesn't handle C++ blocks yet, so manually guarded. */
#if __ANDROID_API__ >= 24
extern "C++" char* strchrnul(char* __s, int __ch) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
extern "C++" const char* strchrnul(const char* __s, int __ch) __RENAME(strchrnul) __attribute_pure__ __INTRODUCED_IN(24);
#endif /* __ANDROID_API__ >= 24 */
#else
char* strchrnul(const char* __s, int __ch) __attribute_pure__ __INTRODUCED_IN(24);
#endif
@ -136,11 +133,8 @@ size_t strxfrm_l(char* __dst, const char* __src, size_t __n, locale_t __l) __INT
* It doesn't modify its argument, and in C++ it's const-correct.
*/
#if defined(__cplusplus)
/* The versioner doesn't handle C++ blocks yet, so manually guarded. */
#if __ANDROID_API__ >= 23
extern "C++" char* basename(char* __path) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
extern "C++" const char* basename(const char* __path) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
#endif /* __ANDROID_API__ >= 23 */
#else
char* basename(const char* __path) __RENAME(__gnu_basename) __INTRODUCED_IN(23);
#endif

View file

@ -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) {

View file

@ -0,0 +1,27 @@
#define __RENAME(x) asm(#x)
#if defined(__cplusplus)
#if __ANDROID_API__ >= 24
extern "C++" const char* strchrnul(const char*, int) __RENAME(strchrnul) __INTRODUCED_IN(24);
#endif /* __ANDROID_API__ >= 24 */
#endif
#if defined(__cplusplus)
extern "C" int foo();
#endif
#if defined(__cplusplus)
extern "C" {
#endif
#if __ANDROID_API__ >= 24
char* strchrnul(char*, int) __INTRODUCED_IN(24);
#endif /* __ANDROID_API__ >= 24 */
#if defined(__cplusplus)
}
#endif

View file

@ -0,0 +1,19 @@
#define __RENAME(x) asm(#x)
#if defined(__cplusplus)
extern "C++" const char* strchrnul(const char*, int) __RENAME(strchrnul) __INTRODUCED_IN(24);
#endif
#if defined(__cplusplus)
extern "C" int foo();
#endif
#if defined(__cplusplus)
extern "C" {
#endif
char* strchrnul(char*, int) __INTRODUCED_IN(24);
#if defined(__cplusplus)
}
#endif

View file

@ -0,0 +1,29 @@
set -e
function run_test {
SRC=$1
DST=$2
rm -rf $2
versioner -a 9 -a 12 -a 13 -a 14 -a 15 $1 -i -o $2
diff -q -w -B $2 expected
}
run_test headers out
run_test headers/ out
run_test headers out/
run_test headers/ out/
run_test `pwd`/headers out
run_test `pwd`/headers/ out
run_test `pwd`/headers out/
run_test `pwd`/headers/ out/
run_test headers `pwd`/out
run_test headers/ `pwd`/out
run_test headers `pwd`/out/
run_test headers/ `pwd`/out/
run_test `pwd`/headers `pwd`/out
run_test `pwd`/headers/ `pwd`/out
run_test `pwd`/headers `pwd`/out/
run_test `pwd`/headers/ `pwd`/out/