ArcsinX created this revision.
ArcsinX added reviewers: sammccall, kadircet.
Herald added subscribers: usaxena95, arphaman.
ArcsinX requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.

Clang uses 4.2.1 as a default GCC version.
For projects that rely on the GCC version, this can be a problem, e.g.

  #if __GNUC__ < 5
  #error "Incompatible compiler"
  #endif

This patch extracts the GCC version from the driver output and adds 
-fgnuc-version=<extracted version> compile option to unsure that the values of 
GCC macros are correct.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D107304

Files:
  clang-tools-extra/clangd/QueryDriverDatabase.cpp
  clang-tools-extra/clangd/test/system-include-extractor.test

Index: clang-tools-extra/clangd/test/system-include-extractor.test
===================================================================
--- clang-tools-extra/clangd/test/system-include-extractor.test
+++ clang-tools-extra/clangd/test/system-include-extractor.test
@@ -16,6 +16,7 @@
 # RUN: echo 'echo " $* " | grep " --sysroot /my/sysroot/path " || exit' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'echo line to ignore >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'printf "Target: arm-linux-gnueabihf\r\n" >&2' >> %t.dir/bin/my_driver.sh
+# RUN: echo 'printf "gcc version 8.3.0 (Rev2)\r\n" >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'printf "#include <...> search starts here:\r\n" >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'echo %t.dir/my/dir/ >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'echo %t.dir/my/dir2/ >&2' >> %t.dir/bin/my_driver.sh
@@ -49,7 +50,7 @@
       "uri": "file://INPUT_DIR/the-file.cpp",
       "languageId":"cpp",
       "version":1,
-      "text":"#include <a.h>\n#include <b.h>\n#if !defined(__ARM_ARCH) || !defined(__gnu_linux__)\n#error \"Invalid target\"\n#endif"
+      "text":"#include <a.h>\n#include <b.h>\n#if !defined(__ARM_ARCH) || !defined(__gnu_linux__)\n#error \"Invalid target\"\n#endif\n#if !defined(__GNUC__) || __GNUC__ != 8\n#error \"Incorrect GCC version\"\n#endif"
     }
   }
 }
Index: clang-tools-extra/clangd/QueryDriverDatabase.cpp
===================================================================
--- clang-tools-extra/clangd/QueryDriverDatabase.cpp
+++ clang-tools-extra/clangd/QueryDriverDatabase.cpp
@@ -62,6 +62,7 @@
 struct DriverInfo {
   std::vector<std::string> SystemIncludes;
   std::string Target;
+  std::string GccVersion;
 };
 
 bool isValidTarget(llvm::StringRef Triple) {
@@ -79,6 +80,7 @@
   const char SIS[] = "#include <...> search starts here:";
   const char SIE[] = "End of search list.";
   const char TS[] = "Target: ";
+  const char VS[] = "gcc version ";
   llvm::SmallVector<llvm::StringRef> Lines;
   Output.split(Lines, '\n', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
 
@@ -89,6 +91,7 @@
   } State = Initial;
   bool SeenIncludes = false;
   bool SeenTarget = false;
+  bool SeenVersion = false;
   for (auto *It = Lines.begin(); State != Done && It != Lines.end(); ++It) {
     auto Line = *It;
     switch (State) {
@@ -109,6 +112,17 @@
           vlog("System include extraction: target extracted: \"{0}\"",
                TargetLine);
         }
+      } else if (!SeenVersion && Line.trim().startswith(VS)) {
+        SeenVersion = true;
+        llvm::StringRef GccVersionLine = Line.trim();
+        GccVersionLine.consume_front(VS);
+        Info.GccVersion = GccVersionLine
+                              .take_while([](unsigned char C) {
+                                return C == '.' || std::isdigit(C);
+                              })
+                              .str();
+        vlog("System include extraction: GCC version extracted: \"{0}\"",
+             Info.GccVersion);
       }
       break;
     case IncludesExtracting:
@@ -231,8 +245,11 @@
   if (!Info)
     return llvm::None;
   log("System includes extractor: successfully executed {0}\n\tgot includes: "
-      "\"{1}\"\n\tgot target: \"{2}\"",
-      Driver, llvm::join(Info->SystemIncludes, ", "), Info->Target);
+      "\"{1}\"\n\tgot target: \"{2}\"{3}",
+      Driver, llvm::join(Info->SystemIncludes, ", "), Info->Target,
+      Info->GccVersion.empty()
+          ? std::string()
+          : llvm::formatv("\n\tgot GCC version: \"{0}\"", Info->GccVersion));
   return Info;
 }
 
@@ -260,6 +277,19 @@
   return Cmd;
 }
 
+tooling::CompileCommand &setGccVersion(tooling::CompileCommand &Cmd,
+                                       const std::string &GccVersion) {
+  if (!GccVersion.empty()) {
+    // We do not want to override existing GCC version with extracted one.
+    for (llvm::StringRef Arg : Cmd.CommandLine) {
+      if (Arg.startswith("-fgnuc-version"))
+        return Cmd;
+    }
+    Cmd.CommandLine.push_back("-fgnuc-version=" + GccVersion);
+  }
+  return Cmd;
+}
+
 /// Converts a glob containing only ** or * into a regex.
 std::string convertGlobToRegex(llvm::StringRef Glob) {
   std::string RegText;
@@ -345,7 +375,9 @@
               return extractSystemIncludesAndTarget(
                   Driver, Lang, Cmd->CommandLine, QueryDriverRegex);
             })) {
-      setTarget(addSystemIncludes(*Cmd, Info->SystemIncludes), Info->Target);
+      setGccVersion(setTarget(addSystemIncludes(*Cmd, Info->SystemIncludes),
+                              Info->Target),
+                    Info->GccVersion);
     }
     return Cmd;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to