versioner: add support for __VERSIONER_NO_GUARD.

Add an attribute that tells the preprocessor not to guard a
declaration, primarily for use with symbols that get reexported by
libc++ of the form `namespace std { using ::wctrans; }`.

Bug: http://b/28178111
Change-Id: I08c8751214797e37e8f26e7f7416a19e81c2bb4c
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
index 88f7b55..02383bb 100644
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ b/tools/versioner/src/DeclarationDatabase.cpp
@@ -84,6 +84,7 @@
     std::string declaration_name = getDeclName(named_decl);
     bool is_extern = named_decl->getFormalLinkage() == ExternalLinkage;
     bool is_definition = false;
+    bool no_guard = false;
 
     if (auto function_decl = dyn_cast<FunctionDecl>(decl)) {
       declaration_type = DeclarationType::function;
@@ -140,7 +141,9 @@
     // Find and parse __ANDROID_AVAILABILITY_DUMP__ annotations.
     for (const AnnotateAttr* attr : decl->specific_attrs<AnnotateAttr>()) {
       llvm::StringRef annotation = attr->getAnnotation();
-      if (annotation == "introduced_in_future") {
+      if (annotation == "versioner_no_guard") {
+        no_guard = true;
+      } else if (annotation == "introduced_in_future") {
         // Tag the compiled-for arch, since this can vary across archs.
         availability.arch_availability[type.arch].future = true;
       } else {
@@ -200,11 +203,13 @@
       declaration.location = location;
       declaration.is_extern = is_extern;
       declaration.is_definition = is_definition;
+      declaration.no_guard = no_guard;
       declaration.availability.insert(std::make_pair(type, availability));
       symbol_it->second.declarations.insert(std::make_pair(location, declaration));
     } else {
       if (declaration_it->second.is_extern != is_extern ||
-          declaration_it->second.is_definition != is_definition) {
+          declaration_it->second.is_definition != is_definition ||
+          declaration_it->second.no_guard != no_guard) {
         errx(1, "varying declaration of '%s' at %s:%u:%u", declaration_name.c_str(),
              location.filename.c_str(), location.start.line, location.start.column);
       }
diff --git a/tools/versioner/src/DeclarationDatabase.h b/tools/versioner/src/DeclarationDatabase.h
index b130ca9..8f43d79 100644
--- a/tools/versioner/src/DeclarationDatabase.h
+++ b/tools/versioner/src/DeclarationDatabase.h
@@ -148,6 +148,7 @@
 
   bool is_extern;
   bool is_definition;
+  bool no_guard;
   std::map<CompilationType, DeclarationAvailability> availability;
 
   bool calculateAvailability(DeclarationAvailability* output) const;
@@ -161,6 +162,9 @@
 
     fprintf(out, "%s ", is_extern ? "extern" : "static");
     fprintf(out, "%s ", is_definition ? "definition" : "declaration");
+    if (no_guard) {
+      fprintf(out, "no_guard ");
+    }
     fprintf(out, "@ %s:%u:%u", StripPrefix(location.filename, base_path).str().c_str(),
             location.start.line, location.start.column);
 
diff --git a/tools/versioner/src/Preprocessor.cpp b/tools/versioner/src/Preprocessor.cpp
index 8d0b943..3c86486 100644
--- a/tools/versioner/src/Preprocessor.cpp
+++ b/tools/versioner/src/Preprocessor.cpp
@@ -452,6 +452,11 @@
       const Location& location = decl_it.first;
       const Declaration& decl = decl_it.second;
 
+      if (decl.no_guard) {
+        // No guard required.
+        continue;
+      }
+
       DeclarationAvailability macro_guard = calculateRequiredGuard(decl);
       if (!macro_guard.empty()) {
         guards[location.filename][location] = macro_guard;
diff --git a/tools/versioner/tests/preprocessor_no_guard/expected/foo.h b/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
new file mode 100644
index 0000000..2bf1dbf
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_no_guard/expected/foo.h
@@ -0,0 +1 @@
+int foo() __VERSIONER_NO_GUARD __INTRODUCED_IN(14);
diff --git a/tools/versioner/tests/preprocessor_no_guard/headers/foo.h b/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
new file mode 100644
index 0000000..2bf1dbf
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_no_guard/headers/foo.h
@@ -0,0 +1 @@
+int foo() __VERSIONER_NO_GUARD __INTRODUCED_IN(14);
diff --git a/tools/versioner/tests/preprocessor_no_guard/run.sh b/tools/versioner/tests/preprocessor_no_guard/run.sh
new file mode 100644
index 0000000..1b0aae2
--- /dev/null
+++ b/tools/versioner/tests/preprocessor_no_guard/run.sh
@@ -0,0 +1,4 @@
+rm -rf out
+set -e
+versioner headers -i -o out
+diff -q -w -B out expected