Skip to content

[clang] Adding an API to create a CXStringSet from a Vector of StringRefs #136773

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

Closed
wants to merge 5 commits into from

Conversation

qiongsiwu
Copy link
Contributor

@qiongsiwu qiongsiwu commented Apr 22, 2025

The newly added API avoids converting StringRefs to std::strings when the input is a vector of StringRef.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:as-a-library libclang and C++ API labels Apr 22, 2025
@qiongsiwu qiongsiwu requested a review from jansvoboda11 April 22, 2025 21:20
@llvmbot
Copy link
Member

llvmbot commented Apr 22, 2025

@llvm/pr-subscribers-clang

Author: Qiongsi Wu (qiongsiwu)

Changes

The newly added API avoids converting StringRefs to std::strings when the input is a vector of StringRef.


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

2 Files Affected:

  • (modified) clang/tools/libclang/CXString.cpp (+9-1)
  • (modified) clang/tools/libclang/CXString.h (+3)
diff --git a/clang/tools/libclang/CXString.cpp b/clang/tools/libclang/CXString.cpp
index aaa8f8eeb67a1..7e46fcc3b8e69 100644
--- a/clang/tools/libclang/CXString.cpp
+++ b/clang/tools/libclang/CXString.cpp
@@ -107,7 +107,8 @@ CXString createCXString(CXStringBuf *buf) {
   return Str;
 }
 
-CXStringSet *createSet(const std::vector<std::string> &Strings) {
+template <typename StringTy>
+static CXStringSet *createSetImpl(const std::vector<StringTy> &Strings) {
   CXStringSet *Set = new CXStringSet;
   Set->Count = Strings.size();
   Set->Strings = new CXString[Set->Count];
@@ -116,6 +117,13 @@ CXStringSet *createSet(const std::vector<std::string> &Strings) {
   return Set;
 }
 
+CXStringSet *createSet(const std::vector<std::string> &Strings) {
+  return createSetImpl(Strings);
+}
+
+CXStringSet *createSet(const std::vector<StringRef> &Strings) {
+  return createSetImpl(Strings);
+}
 
 //===----------------------------------------------------------------------===//
 // String pools.
diff --git a/clang/tools/libclang/CXString.h b/clang/tools/libclang/CXString.h
index 809bdec3d677f..24c4092a9a2c0 100644
--- a/clang/tools/libclang/CXString.h
+++ b/clang/tools/libclang/CXString.h
@@ -67,7 +67,10 @@ CXString createRef(std::string String) = delete;
 /// Create a CXString object that is backed by a string buffer.
 CXString createCXString(CXStringBuf *buf);
 
+/// Create a CXStringSet object owns the strings. Such an object should be
+/// disposed with clang_disposeStringSet.
 CXStringSet *createSet(const std::vector<std::string> &Strings);
+CXStringSet *createSet(const std::vector<StringRef> &Strings);
 
 /// A string pool used for fast allocation/deallocation of strings.
 class CXStringPool {

@qiongsiwu qiongsiwu requested a review from jansvoboda11 April 23, 2025 15:25
Copy link
Contributor

@jansvoboda11 jansvoboda11 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks! I left a couple of comments for your consideration, but don't feel obligated to incorporate them.

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is this new API expected to be used?

@qiongsiwu
Copy link
Contributor Author

Where is this new API expected to be used?

An intended use can be found here swiftlang#10524, where we try to pass up a collection of strings to the user, and we try not to create copies of the strings.

@AaronBallman
Copy link
Collaborator

Where is this new API expected to be used?

An intended use can be found here swiftlang#10524, where we try to pass up a collection of strings to the user, and we try not to create copies of the strings.

Okay, thanks! Given there are no in-tree uses, this really needs some test coverage so nobody comes along and removes the API as being unused (it's part of the internal APIs, not the external ones).

@qiongsiwu
Copy link
Contributor Author

Where is this new API expected to be used?

An intended use can be found here swiftlang#10524, where we try to pass up a collection of strings to the user, and we try not to create copies of the strings.

Okay, thanks! Given there are no in-tree uses, this really needs some test coverage so nobody comes along and removes the API as being unused (it's part of the internal APIs, not the external ones).

Ah good point! Makes sense to me. I did not find a straightforward place to piggy-back on to add a test (e.g. the c-index tests do not seem quite fitting). I will go find a way to add a unit test. Does this sound reasonable? Adding a unit test also feels a bit weird, since I am not seeing that we test for c interfaces in clang unit tests at a glance, but I might be missing some examples when looking.

@jansvoboda11
Copy link
Contributor

How about clang/unittests/libclang/LibclangTest.cpp?

@qiongsiwu
Copy link
Contributor Author

Hi @AaronBallman ! Again I appreciate your suggestion. I ran into some complexities when adding a test. It is precisely that this is a very internal API that is giving me some trouble. Since clang/tools/libclang/CXString.h is not an exposed header, I cannot really even add it to the clang unit tests, unless I expose (some of) the header's content through a more public API (not necessarily the C-APIs).

Do you have suggestions other than landing this PR as is? One possible alternative is to move clang/tools/libclang/CXString.h into a directory in clang/include/clang/, and then we can add the unit test. The problem with this alternative is that it seems to be too big a change for what we are aiming for here.

@AaronBallman
Copy link
Collaborator

Hi @AaronBallman ! Again I appreciate your suggestion. I ran into some complexities when adding a test. It is precisely that this is a very internal API that is giving me some trouble. Since clang/tools/libclang/CXString.h is not an exposed header, I cannot really even add it to the clang unit tests, unless I expose (some of) the header's content through a more public API (not necessarily the C-APIs).

Do you have suggestions other than landing this PR as is? One possible alternative is to move clang/tools/libclang/CXString.h into a directory in clang/include/clang/, and then we can add the unit test. The problem with this alternative is that it seems to be too big a change for what we are aiming for here.

If the only use is in a downstream of Clang, do we need to upstream the changes at all? We could always upstream once there's an in-tree need for the functionality.

@qiongsiwu
Copy link
Contributor Author

If the only use is in a downstream of Clang, do we need to upstream the changes at all? We could always upstream once there's an in-tree need for the functionality.

No, we don't need to upstream. I don't have a strong feeling - I am upstreaming it because functionally this belongs to the CXString related methods, and it feels weird not having it upstream. Upstreaming it also has the benefit of allowing others to take advantage of it.

Since it is hard to test let me move this downstream. We can upstream when it matures more.

@qiongsiwu
Copy link
Contributor Author

Closing this PR since we will have the changes in swiftlang#10524.

@qiongsiwu qiongsiwu closed this Apr 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:as-a-library libclang and C++ API clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants