Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang] [unittest] Add a test for Generic_GCC::GCCVersion::Parse #69078

Merged
merged 1 commit into from
Oct 18, 2023

Conversation

mstorsjo
Copy link
Member

This adds actual test cases for all the cases that are listed in a code comment in the implementation of this function; having such test coverage eases doing further modifications to the function.

@mstorsjo mstorsjo added the clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' label Oct 14, 2023
@mstorsjo mstorsjo requested a review from MaskRay October 14, 2023 21:02
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Oct 14, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 14, 2023

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-driver

Author: Martin Storsjö (mstorsjo)

Changes

This adds actual test cases for all the cases that are listed in a code comment in the implementation of this function; having such test coverage eases doing further modifications to the function.


Full diff: https://github.com/llvm/llvm-project/pull/69078.diff

2 Files Affected:

  • (modified) clang/unittests/Driver/CMakeLists.txt (+1)
  • (added) clang/unittests/Driver/GCCVersionTest.cpp (+48)
diff --git a/clang/unittests/Driver/CMakeLists.txt b/clang/unittests/Driver/CMakeLists.txt
index e37c158d7137a88..752037f78fb147d 100644
--- a/clang/unittests/Driver/CMakeLists.txt
+++ b/clang/unittests/Driver/CMakeLists.txt
@@ -9,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
 add_clang_unittest(ClangDriverTests
   DistroTest.cpp
   DXCModeTest.cpp
+  GCCVersionTest.cpp
   ToolChainTest.cpp
   ModuleCacheTest.cpp
   MultilibBuilderTest.cpp
diff --git a/clang/unittests/Driver/GCCVersionTest.cpp b/clang/unittests/Driver/GCCVersionTest.cpp
new file mode 100644
index 000000000000000..ef05a0b4fe734e5
--- /dev/null
+++ b/clang/unittests/Driver/GCCVersionTest.cpp
@@ -0,0 +1,48 @@
+//===- unittests/Driver/GCCVersionTest.cpp --- GCCVersion parser tests ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for Generic_GCC::GCCVersion
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../lib/Driver/ToolChains/Gnu.h"
+#include "gtest/gtest.h"
+
+using namespace clang::driver;
+using namespace clang;
+
+struct VersionParseTest {
+  std::string Text;
+
+  int Major, Minor, Patch;
+  std::string MajorStr, MinorStr, PatchSuffix;
+};
+
+const VersionParseTest TestCases[] = {
+    {"5", 5, -1, -1, "5", "", ""},
+    {"4.4", 4, 4, -1, "4", "4", ""},
+    {"4.4-patched", 4, 4, -1, "4", "4", "-patched"},
+    {"4.4.0", 4, 4, 0, "4", "4", ""},
+    {"4.4.x", 4, 4, -1, "4", "4", ""},
+    {"4.4.2-rc4", 4, 4, 2, "4", "4", "-rc4"},
+    {"4.4.x-patched", 4, 4, -1, "4", "4", ""},
+    {"not-a-version", -1, -1, -1, "", "", ""},
+};
+
+TEST(GCCVersionTest, Parse) {
+  for (const auto &TC : TestCases) {
+    auto V = toolchains::Generic_GCC::GCCVersion::Parse(TC.Text);
+    ASSERT_EQ(V.Text, TC.Text);
+    ASSERT_EQ(V.Major, TC.Major);
+    ASSERT_EQ(V.Minor, TC.Minor);
+    ASSERT_EQ(V.Patch, TC.Patch);
+    ASSERT_EQ(V.MajorStr, TC.MajorStr);
+    ASSERT_EQ(V.MinorStr, TC.MinorStr);
+    ASSERT_EQ(V.PatchSuffix, TC.PatchSuffix);
+  }
+}

clang/unittests/Driver/GCCVersionTest.cpp Outdated Show resolved Hide resolved
This adds actual test cases for all the cases that are listed in
a code comment in the implementation of this function; having such
test coverage eases doing further modifications to the function.
@mstorsjo mstorsjo force-pushed the clang-gccversion-test branch from 2b12720 to 1aac071 Compare October 18, 2023 08:14
@mstorsjo
Copy link
Member Author

Thanks, I applied the suggested changes - will push in a little while.

@mstorsjo mstorsjo merged commit b4b35a5 into llvm:main Oct 18, 2023
2 checks passed
@mstorsjo mstorsjo deleted the clang-gccversion-test branch October 18, 2023 09:36
@tbaederr
Copy link
Contributor

This doesn't build for me locally:

mold: error: undefined symbol: tools/clang/unittests/Driver/CMakeFiles/ClangDriverTests.dir/GCCVersionTest.cpp.o: clang::driver::toolchains::Generic_GCC::GCCVersion::Parse(llvm::StringRef)

@asb
Copy link
Contributor

asb commented Oct 18, 2023

@tbaederr Just came to report the same thing!

@mstorsjo This broke builds that use -DBUILD_SHARED_LIBS=True. The problem seems to be that the Generic_GCC class has the LLVM_LIBRARY_VISIBILITY attribute meaning the clang::driver::toolchains::Generic_GCC::GCCVersion::Parse(llvm::StringRef) symbol is hidden. Removing that attribute fixes the build. It would be good for someone more familiar with this part of the codebase to confirm if that's an acceptable fix however.

@mstorsjo
Copy link
Member Author

@tbaederr Just came to report the same thing!

@mstorsjo This broke builds that use -DBUILD_SHARED_LIBS=True.

Thanks! That was my guess as well, I was running a build with that enabled to try to reproduce @tbaederr 's issue.

The problem seems to be that the Generic_GCC class has the LLVM_LIBRARY_VISIBILITY attribute meaning the clang::driver::toolchains::Generic_GCC::GCCVersion::Parse(llvm::StringRef) symbol is hidden. Removing that attribute fixes the build. It would be good for someone more familiar with this part of the codebase to confirm if that's an acceptable fix however.

Thanks for the analysis! I guess that sounds reasonable, although I wonder how these unit test, that test internals within libclang are meant to work in this configuration. The number of extra exported symbols by removing LLVM_LIBRARY_VISIBILITY probably isn't that bad, I wonder if it has other implications wrt ABI of the shared libs?

I guess it's safest to revert this for now, so we can figure out the best path forward here without a rush?

mstorsjo added a commit that referenced this pull request Oct 18, 2023
…rse (#69078)"

This reverts commit b4b35a5.

That commit broke builds with -DBUILD_SHARED_LIBS=ON. The reason
is that clang::driver::toolchains::Generic_GCC::GCCVersion::Parse
isn't visible outside of the shared library, because
the Generic_GCC class is marked with LLVM_LIBRARY_VISIBILITY.
@jroelofs
Copy link
Contributor

Perhaps this belongs in the ABI-breaking-checks build?

@mstorsjo
Copy link
Member Author

mstorsjo commented Oct 19, 2023

Perhaps this belongs in the ABI-breaking-checks build?

Hmm, ideally I think it should be included in any build - let’s hope we don’t need to resort to that.

@tstellar @MaskRay Do either of you happen to know about this; would it be ok ABI wise to remove LLVM_LIBRARY_VISIBILITY from clang::driver::toolchains::Generic_GCC in order to be able to access it from unit tests in shared or dylib builds?

@MaskRay
Copy link
Member

MaskRay commented Oct 20, 2023

I hope that we do not drop LLVM_LIBRARY_VISIBILITY arbitrarily from clang::driver::toolchains::* classes, just because some unittests need to reference the symbols in a shared object.

#if !defined(LLVM_BUILD_SHARED_LIBS)

is not great but is not too bad. -DBUILD_SHARED_LIBS=on modes are slow to execute tests and are not used often for Release builds.

@mstorsjo
Copy link
Member Author

I hope that we do not drop LLVM_LIBRARY_VISIBILITY arbitrarily from clang::driver::toolchains::* classes, just because some unittests need to reference the symbols in a shared object.

That’s a reasonable point.

#if !defined(LLVM_BUILD_SHARED_LIBS)

is not great but is not too bad. -DBUILD_SHARED_LIBS=on modes are slow to execute tests and are not used often for Release builds.

I guess that’s a reasonable tradeoff. We’d need to do the same for dylib mode as well, which probably is used a bit more. But the main point is that whoever is working on modifying that implementation can run the tests fairly easy, and that they get run somewhere in some configurations at least.

@tbaederr
Copy link
Contributor

FWIW this failed for me locally as well but I'm not using BUILD_SHARED_LIBS. I am linking with the clang dylib though, which has the same problem I think.

mstorsjo added a commit that referenced this pull request Oct 20, 2023
…se (#69078)

This adds actual test cases for all the cases that are listed in a code
comment in the implementation of this function; having such test
coverage eases doing further modifications to the function.

This relands b4b35a5. This time,
the new test is excluded if building with dylibs or shared libraries
enabled, as the clang::toolchains::Generic_GCC class is marked
LLVM_LIBRARY_VISIBILITY, giving it hidden visibility in such builds,
making it unreferencable outside of the dylib/shared library.
@mstorsjo
Copy link
Member Author

#if !defined(LLVM_BUILD_SHARED_LIBS)

is not great but is not too bad. -DBUILD_SHARED_LIBS=on modes are slow to execute tests and are not used often for Release builds.

I went ahead and relanded this now, in 538b7ba, with #if !defined(LLVM_BUILD_LLVM_DYLIB) && !defined(LLVM_BUILD_SHARED_LIBS). Not great, but probably the least bad compromise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants