[clang] [clang][modules-driver] Add scanner to detect C++20 module presence (PR #145220)
Michael Spencer via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 3 13:47:54 PDT 2025
================
@@ -4403,6 +4411,174 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
}
}
+static void skipWhitespace(const char *&Ptr) {
+ while (isWhitespace(*Ptr))
+ ++Ptr;
+}
+
+// Returns the length of EOL, either 0 (no end-of-line), 1 (\n) or 2 (\r\n).
+static unsigned isEOL(const char *Ptr) {
+ if (*Ptr == '\0')
+ return 0;
+ if (*(Ptr + 1) != '\0' && isVerticalWhitespace(Ptr[0]) &&
+ isVerticalWhitespace(Ptr[1]) && Ptr[0] != Ptr[1])
+ return 2;
+ return !!isVerticalWhitespace(Ptr[0]);
+}
+
+static void skipLine(const char *&Ptr) {
+ for (;;) {
+ char LastNonWhitespace = ' ';
+ while (!isVerticalWhitespace(*Ptr) && *Ptr != '\0') {
+ if (!isHorizontalWhitespace(*Ptr))
+ LastNonWhitespace = *Ptr;
+ ++Ptr;
+ }
+
+ const unsigned Len = isEOL(Ptr);
+ if (!Len)
+ return;
+
+ Ptr += Len;
+ if (LastNonWhitespace != '\\')
+ break;
+ }
+}
+
+// Returns the length of a line splice sequence (including trailing
+// whitespace), or 0 if no line splice is found.
+static unsigned isLineSplice(const char *Start) {
+ if (*Start != '\\')
+ return 0;
+
+ const char *Ptr = Start + 1;
+ while (isHorizontalWhitespace(*Ptr))
+ ++Ptr;
+
+ if (unsigned Len = isEOL(Ptr))
+ return Ptr - Start + Len;
+ return 0;
+}
+
+static bool trySkipLineSplice(const char *&Ptr) {
+ if (unsigned Len = isLineSplice(Ptr); Len) {
+ Ptr += Len;
+ return true;
+ }
+ return false;
+}
+
+static bool trySkipDirective(const char *&Ptr) {
+ if (*Ptr != '#')
+ return false;
+
+ ++Ptr;
+ skipLine(Ptr);
+ return true;
+}
+
+static bool trySkipLineComment(const char *&Ptr) {
+ if (Ptr[0] != '/' || Ptr[1] != '/')
+ return false;
+
+ Ptr += 2;
+ skipLine(Ptr);
+ return true;
+}
+
+static bool trySkipBlockComment(const char *&Ptr) {
+ if (Ptr[0] != '/' || Ptr[1] != '*')
+ return false;
+
+ Ptr += 2;
+ while (*Ptr != '\0') {
+ if (Ptr[0] == '*' && Ptr[1] == '/') {
+ Ptr += 2; // '*/'
+ return true;
+ }
+ ++Ptr;
+ }
+ return true;
+}
+
+static bool trySkipComment(const char *&Ptr) {
+ return trySkipLineComment(Ptr) || trySkipBlockComment(Ptr);
+}
+
+// Skipps over comments and (non-module) directives
+static void skipToRelevantCXXModuleText(const char *&Ptr) {
+ while (*Ptr != '\0') {
+ skipWhitespace(Ptr);
+ if (trySkipComment(Ptr) || trySkipDirective(Ptr) || trySkipLineSplice(Ptr))
+ continue;
+ break; // Found relevant text!
+ }
+}
+
+static bool scanBufferForCXXModuleUsage(const llvm::MemoryBuffer &Buffer) {
+ const char *Ptr = Buffer.getBufferStart();
+ skipToRelevantCXXModuleText(Ptr);
+
+ // Check if buffer has enough bytes left to check for the module-related
+ // declaration fragment we want to check without making potentially
----------------
Bigcheese wrote:
```suggestion
// declaration fragment we want to check without making the potentially
```
https://github.com/llvm/llvm-project/pull/145220
More information about the cfe-commits
mailing list