Skip to content

Conversation

Bigcheese
Copy link
Contributor

import:(type)name is a method argument decl in ObjC, but the C++20 preprocessing rules say this is a preprocessing line.

Because the dependency directive scanner is not language dependent, this patch extends the C++20 rule to exclude module : (which is never a valid module decl anyway), and import : that is not followed by an identifier.

This is ok to do because in C++20 mode the compiler will later error on lines like this anyway, and the dependencies the scanner returns are still correct.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jul 3, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 3, 2024

@llvm/pr-subscribers-clang

Author: Michael Spencer (Bigcheese)

Changes

import:(type)name is a method argument decl in ObjC, but the C++20 preprocessing rules say this is a preprocessing line.

Because the dependency directive scanner is not language dependent, this patch extends the C++20 rule to exclude module : (which is never a valid module decl anyway), and import : that is not followed by an identifier.

This is ok to do because in C++20 mode the compiler will later error on lines like this anyway, and the dependencies the scanner returns are still correct.


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

2 Files Affected:

  • (modified) clang/lib/Lex/DependencyDirectivesScanner.cpp (+12-1)
  • (added) clang/test/ClangScanDeps/scanner-objc-compat.m (+28)
diff --git a/clang/lib/Lex/DependencyDirectivesScanner.cpp b/clang/lib/Lex/DependencyDirectivesScanner.cpp
index 0971daa1f3666..bd2a8d5115c81 100644
--- a/clang/lib/Lex/DependencyDirectivesScanner.cpp
+++ b/clang/lib/Lex/DependencyDirectivesScanner.cpp
@@ -660,7 +660,18 @@ bool Scanner::lexModule(const char *&First, const char *const End) {
   // an import.
 
   switch (*First) {
-  case ':':
+  case ':': {
+    // `module :` is never the start of a valid module declaration.
+    if (Id == "module") {
+      skipLine(First, End);
+      return false;
+    }
+    // `import:(type)name` is a valid ObjC method decl, so check one more token.
+    (void)lexToken(First, End);
+    if (!tryLexIdentifierOrSkipLine(First, End))
+      return false;
+    break;
+  }
   case '<':
   case '"':
     break;
diff --git a/clang/test/ClangScanDeps/scanner-objc-compat.m b/clang/test/ClangScanDeps/scanner-objc-compat.m
new file mode 100644
index 0000000000000..302988f1f51d6
--- /dev/null
+++ b/clang/test/ClangScanDeps/scanner-objc-compat.m
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: clang-scan-deps -format experimental-full -- \
+// RUN:   %clang -c %t/main.m -o %t/main.o -fmodules -I %t > %t/deps.db
+// RUN: cat %t/deps.db | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t
+
+// Verify that the scanner does not treat ObjC method decls with arguments named
+// module or import as module/import decls.
+
+// CHECK: "module-name": "A"
+
+//--- A.h
+
+@interface SomeObjcClass
+  - (void)func:(int)otherData
+          module:(int)module
+          import:(int)import;
+@end
+
+//--- module.modulemap
+
+module A {
+  header "A.h"
+}
+
+//--- main.m
+
+#include "A.h"

Copy link
Member

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

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

LGTM as it looks like not affecting C++20 modules.

@akyrtzi
Copy link
Contributor

akyrtzi commented Jul 5, 2024

Could you test the change with a unit test in DependencyDirectivesScannerTest.cpp instead? It would be orders of magnitude more lightweight, execution wise, than a whole new lit test.

@Bigcheese Bigcheese force-pushed the dev/module-kw-scan branch from dd1ab40 to 1e8ecb5 Compare July 11, 2024 23:32
@Bigcheese
Copy link
Contributor Author

Updated the test to be a unit test.

`import:(type)name` is a method argument decl in ObjC, but the C++20
preprocessing rules say this is a preprocessing line.

Because the dependency directive scanner is not language dependent,
this patch extends the C++20 rule to exclude `module :` (which is
never a valid module decl anyway), and `import :` that is not followed
by an identifier.

This is ok to do because in C++20 mode the compiler will later error
on lines like this anyway, and the dependencies the scanner returns
are still correct.
@Bigcheese Bigcheese merged commit 4272847 into llvm:main Jul 18, 2024
@Bigcheese Bigcheese deleted the dev/module-kw-scan branch July 18, 2024 20:37
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
Summary:
`import:(type)name` is a method argument decl in ObjC, but the C++20
preprocessing rules say this is a preprocessing line.

Because the dependency directive scanner is not language dependent, this
patch extends the C++20 rule to exclude `module :` (which is never a
valid module decl anyway), and `import :` that is not followed by an
identifier.

This is ok to do because in C++20 mode the compiler will later error on
lines like this anyway, and the dependencies the scanner returns are
still correct.

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60250834
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants