[PATCH] D33499: [PPC] PPC32/Darwin ABI info

2017-06-22 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

This seems like a reasonable start, and is a step forward.
For the VAArgs, this will be self-consistent, but to be compliant with the 
system ABI, I think you'll need to account the different padding rules for 
small aggregates, as per pp14 of "Mac_OS_X_ABI_Function_Calls".  Specifically, 
1 and 2 byte aggregates are right-aligned and padded on the left, but sizes 3 
and above are left-aligned and padded on the right.

I have a more complete ABIInfo implementation, but it needs forward-porting to 
trunk.  Will let you know when that's done.


Repository:
  rL LLVM

https://reviews.llvm.org/D33499



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D33499: [PPC] PPC32/Darwin ABI info

2018-12-29 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

Since that's my understanding too - I am (slowly) bringing my patches forward 
to 7.0 - at the moment testing the MC layer changes on powerpc-darwin9 (looking 
reasonable, as an assembler for GCC, so far).   When things are "ready" (at 
least not broken as far as I can tell) - will push them to my github (iains).

I think the parting comment was that if /when it's coherent enough to warrant 
re-inclusion (or there are enough developer cycles to maintain it)... then that 
could be discussed.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D33499/new/

https://reviews.llvm.org/D33499



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128328: [C++20][Modules] Improve handing of Private Module Fragment diagnostics.

2022-06-27 Thread Iain Sandoe via Phabricator via cfe-commits
iains planned changes to this revision.
iains added a comment.

In D128328#3611194 , @ChuanqiXu wrote:

> From the discussion, it looks like the 'export' part is not necessary here 
> and we don't need to care about linkage in this revision.

Indeed.

> In D128328#3609827 , @vsapsai wrote:
>
>> Sorry for changing my mind. I've thought about the errors more and 
>> especially about the case mentioned by Chuanqi
>>
>>   export module A;
>>   [export] inline void func();
>>
>> I'm afraid it can complicate the implementation but we can achieve some 
>> consistency with errors like
>>
>>   export module A;
>>   export inline void func(); // error: no definition for exported inline 
>> function 'func' in module 'A'
>>
>> and
>>
>>   export module A;
>>   export inline void func(); // error: no definition for exported inline 
>> function 'func' in module 'A'
>>   //...
>>   module :private;
>>   void func() {}  // note: definition here is not reachable as it is private
>>
>> I think it is useful to have connection between declaration and definition 
>> and to explain why the definition is no good.
>>
>> Specific wording around "no definition | missing definition | definition 
>> required" is flexible.
>
> It makes sense to me.

So I will re-work this patch to deal with the two changes (I think that the 
proposed merge of changes to the example should be enough to go on).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128328/new/

https://reviews.llvm.org/D128328

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D126189: [C++20][Modules] Build module static initializers per P1874R1.

2022-06-29 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D126189#3617850 , @ChuanqiXu wrote:

> @iains may I ask what's the issue to not land this? It looks like you're 
> waiting for the behavior to be consistency with GCC?
>
> Since this patch could fix https://github.com/llvm/llvm-project/issues/51873, 
> which breaks the users to compile a hello world example.

I need to make some typo corrections; there is no issue (I'm not waiting for 
anything) just prioritising posting patches to complete C++20 support .. will 
land this soon.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126189/new/

https://reviews.llvm.org/D126189

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D126694: [C++20][Modules] Implementation of GMF decl elision.

2022-06-29 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 440915.
iains marked an inline comment as done.
iains added a comment.

rebased after D113545  was landed and removed 
that as a parent.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126694/new/

https://reviews.llvm.org/D126694

Files:
  clang/include/clang/AST/DeclBase.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/Decl.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaLambda.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/lib/Sema/SemaOpenMP.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaStmtAsm.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/lib/Serialization/ASTReaderDecl.cpp
  clang/test/AST/ast-dump-decl.c
  clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
  clang/test/Modules/cxx-templates.cpp
  clang/test/Modules/cxx20-10-4-ex2.cpp

Index: clang/test/Modules/cxx20-10-4-ex2.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-10-4-ex2.cpp
@@ -0,0 +1,60 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 std-10-4-ex2-interface.cpp \
+// RUN:  -emit-module-interface -o M.pcm -Wno-unused-value
+// RUN: %clang_cc1 -std=c++20 std-10-4-ex2-implementation.cpp \
+// RUN:  -fmodule-file=M.pcm -fsyntax-only -verify
+//--- std-10-4-ex2.h
+
+namespace N {
+struct X {};
+int d();
+int e();
+inline int f(X, int = d()) { return e(); }
+int g(X);
+int h(X);
+} // namespace N
+
+//--- std-10-4-ex2-interface.cpp
+
+module;
+
+#include "std-10-4-ex2.h"
+
+export module M;
+
+template  int use_f() {
+  N::X x;   // N::X, N, and  ::  are decl-reachable from use_f
+  return f(x, 123); // N::f is decl-reachable from use_f,
+// N::e is indirectly decl-reachable from use_f
+//   because it is decl-reachable from N::f, and
+// N::d is decl-reachable from use_f
+//   because it is decl-reachable from N::f
+//   even though it is not used in this call
+}
+
+template  int use_g() {
+  N::X x; // N::X, N, and :: are decl-reachable from use_g
+  return g((T(), x)); // N::g is not decl-reachable from use_g
+}
+
+template  int use_h() {
+  N::X x; // N::X, N, and :: are decl-reachable from use_h
+  return h((T(), x)); // N::h is not decl-reachable from use_h, but
+  // N::h is decl-reachable from use_h
+}
+
+int k = use_h();
+// use_h is decl-reachable from k, so
+// N::h is decl-reachable from k
+
+//--- std-10-4-ex2-implementation.cpp
+
+module M;
+
+int a = use_f();
+int b = use_g(); // expected-er...@std-10-4-ex2-interface.cpp:20 {{use of undeclared identifier 'g'}}
+  // expected-note@-1 {{in instantiation of function template specialization 'use_g' requested here}}
+int c = use_h();
Index: clang/test/Modules/cxx-templates.cpp
===
--- clang/test/Modules/cxx-templates.cpp
+++ clang/test/Modules/cxx-templates.cpp
@@ -252,7 +252,7 @@
 // CHECK-DUMP:  ClassTemplateDecl {{.*}} <{{.*[/\\]}}cxx-templates-common.h:1:1, {{.*}}>  col:{{.*}} in cxx_templates_common SomeTemplate
 // CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
 // CHECK-DUMP-NEXT: TemplateArgument type 'char[2]'
-// CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
+// CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} SomeTemplate Visible definition
 // CHECK-DUMP-NEXT: DefinitionData
 // CHECK-DUMP-NEXT:   DefaultConstructor
 // CHECK-DUMP-NEXT:   CopyConstructor
@@ -263,7 +263,7 @@
 // CHECK-DUMP-NEXT: TemplateArgument type 'char[2]'
 // CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
 // CHECK-DUMP-NEXT: TemplateArgument type 'char[1]'
-// CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
+// CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} SomeTemplate Visible definition
 // CHECK-DUMP-NEXT: DefinitionData
 // CHECK-DUMP-NEXT:   DefaultConstructor
 // CHECK-DUMP-NEXT:   CopyConstructor
Index: clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
===
--- clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
+++ clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
@@ -29,9 +29,8 @@
 #endif
 
 void test_early() {
-  in_header = 1; // expected-error {{missing '#include "foo.h"'; 'in_header' must be declared before it is used}}
-  // expected-note@* {{not visible}}
-
+  in_header = 1;  // expected-error {{m

[PATCH] D126694: [C++20][Modules] Implementation of GMF decl elision.

2022-06-29 Thread Iain Sandoe via Phabricator via cfe-commits
iains added inline comments.



Comment at: clang/include/clang/AST/DeclBase.h:624
   bool isModulePrivate() const {
 return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate;
   }

ChuanqiXu wrote:
> According to the opinion from @rsmith, the discarded declaration is private 
> too.
I guess you mean `>=`  ... however Discardable is a stronger constraint than 
Private 

If a decl remains marked Discardable (after the processing to determine 
reachable ones) that means it is both unreachable and invisible.
So it must not participate in any processing (with the one exception of 
diagnostic output).  I would be concerned that the change you suggest above 
could cause a  Discardable decl to be considered in merging  or lookup and we 
would then need (maybe a lot) of logic like:

```
 if (D->isModulePrivate() && !D->isModuleDiscardable())
...
```

I will take a look on the next iteration.



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126694/new/

https://reviews.llvm.org/D126694

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D126189: [C++20][Modules] Build module static initializers per P1874R1.

2022-06-29 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 440924.
iains added a comment.

rebased, corrected some spellings.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126189/new/

https://reviews.llvm.org/D126189

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/Basic/Module.h
  clang/include/clang/Sema/Sema.h
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Parse/ParseAST.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/CodeGen/module-intializer-pmf.cpp
  clang/test/CodeGen/module-intializer.cpp

Index: clang/test/CodeGen/module-intializer.cpp
===
--- /dev/null
+++ clang/test/CodeGen/module-intializer.cpp
@@ -0,0 +1,186 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 N.cpp \
+// RUN:-emit-module-interface -o N.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 N.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-N
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.cpp \
+// RUN:-emit-module-interface -o O.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-O
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.cpp \
+// RUN:-emit-module-interface -o M-part.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.pcm -S \
+// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-P
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.cpp \
+// RUN: -fmodule-file=N.pcm -fmodule-file=O.pcm -fmodule-file=M-part.pcm \
+// RUN:-emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-M
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 useM.cpp \
+// RUN: -fmodule-file=M.pcm -S -emit-llvm  -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK-USE
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-impl.cpp \
+// RUN: -fmodule-file=M.pcm -S -emit-llvm  -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK-IMPL
+
+//--- N-h.h
+
+struct Oink {
+  Oink(){};
+};
+
+Oink Hog;
+
+//--- N.cpp
+
+module;
+#include "N-h.h"
+
+export module N;
+
+export struct Quack {
+  Quack(){};
+};
+
+export Quack Duck;
+
+// CHECK-N: define internal void @__cxx_global_var_init
+// CHECK-N: call void @_ZN4OinkC1Ev
+// CHECK-N: define internal void @__cxx_global_var_init
+// CHECK-N: call void @_ZNW1N5QuackC1Ev
+// CHECK-N: define void @_ZGIW1N
+// CHECK-N: store i8 1, ptr @_ZGIW1N__in_chrg
+// CHECK-N: call void @__cxx_global_var_init
+// CHECK-N: call void @__cxx_global_var_init
+
+//--- O-h.h
+
+struct Meow {
+  Meow(){};
+};
+
+Meow Cat;
+
+//--- O.cpp
+
+module;
+#include "O-h.h"
+
+export module O;
+
+export struct Bark {
+  Bark(){};
+};
+
+export Bark Dog;
+
+// CHECK-O: define internal void @__cxx_global_var_init
+// CHECK-O: call void @_ZN4MeowC2Ev
+// CHECK-O: define internal void @__cxx_global_var_init
+// CHECK-O: call void @_ZNW1O4BarkC1Ev
+// CHECK-O: define void @_ZGIW1O
+// CHECK-O: store i8 1, ptr @_ZGIW1O__in_chrg
+// CHECK-O: call void @__cxx_global_var_init
+// CHECK-O: call void @__cxx_global_var_init
+
+//--- P-h.h
+
+struct Croak {
+  Croak(){};
+};
+
+Croak Frog;
+
+//--- M-part.cpp
+
+module;
+#include "P-h.h"
+
+module M:Part;
+
+struct Squawk {
+  Squawk(){};
+};
+
+Squawk parrot;
+
+// CHECK-P: define internal void @__cxx_global_var_init
+// CHECK-P: call void @_ZN5CroakC1Ev
+// CHECK-P: define internal void @__cxx_global_var_init
+// CHECK-P: call void @_ZNW1M6SquawkC1Ev
+// CHECK-P: define void @_ZGIW1MWP4Part
+// CHECK-P: store i8 1, ptr @_ZGIW1MWP4Part__in_chrg
+// CHECK-P: call void @__cxx_global_var_init
+// CHECK-P: call void @__cxx_global_var_init
+
+//--- M-h.h
+
+struct Moo {
+  Moo(){};
+};
+
+Moo Cow;
+
+//--- M.cpp
+
+module;
+#include "M-h.h"
+
+export module M;
+import N;
+export import O;
+import :Part;
+
+export struct Baa {
+  int x;
+  Baa(){};
+  Baa(int x) : x(x) {}
+  int getX() { return x; }
+};
+
+export Baa Sheep(10);
+
+// CHECK-M: define internal void @__cxx_global_var_init
+// CHECK-M: call void @_ZN3MooC1Ev
+// CHECK-M: define internal void @__cxx_global_var_init
+// CHECK-M: call void @_ZNW1M3BaaC1Ei
+// CHECK-M: declare void @_ZGIW1O()
+// CHECK-M: declare void @_ZGIW1N()
+// CHECK-M: declare void @_ZGIW1MWP4Part()
+// CHECK-M: define void @_ZGIW1M
+// CHECK-M: store i8 1, ptr @_ZGIW1M__in_chrg
+// CHECK-M: call void @_ZGIW1O()
+// CHECK-M: call void @_ZGIW1N()
+// CHECK-M: call void @_ZGIW1MWP4Part()
+// CHECK-M: call void @__cxx_global_var_init
+// CHECK-M: call void @__cxx_global_var_init
+
+//--- useM.cpp
+
+import M;
+
+int main() {
+  return Sheep.getX();
+}
+
+// CHECK-USE: declare void @_ZGIW1M
+// CHECK-USE: de

[PATCH] D126189: [C++20][Modules] Build module static initializers per P1874R1.

2022-06-29 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D126189#3598568 , @urnathan wrote:

> please sed /initialiser/initializer/, I noticed a few had crept in.

should be done now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126189/new/

https://reviews.llvm.org/D126189

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128981: [C++20][Modules] Implement include translation.

2022-07-01 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a project: All.
iains requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This addresses [cpp.include]/7

(when encountering #include header-name)

If the header identified by the header-name denotes an importable header, it
is implementation-defined whether the #include preprocessing directive is
instead replaced by an import directive.

In this implementation, include translation is performed _only_ for headers
in the Global Module fragment, so:

  module;
   #include "will-be-translated.h" // IFF the header unit is available.
  
  export module M;
   #include "will-not-be-translated.h" // even if the header unit is available

The reasoning is that, in general, includes in the module purview would not
be validly translatable (they would have to immediately follow the module
decl and without any other intervening decls).  Otherwise that would violate
the rules on contiguous import directives.

This would be quite complex to track in the preprocessor, and for relatively
little gain (the user can 'import "will-not-be-translated.h";' instead.)

TODO: This is one area where it becomes increasingly difficult to disambiguate
clang modules in C++ from C++ standard modules.  That needs to be addressed in
both the driver and the FE.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D128981

Files:
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/Preprocessor.cpp
  clang/lib/Parse/Parser.cpp
  clang/test/Modules/cxx20-include-translation.cpp

Index: clang/test/Modules/cxx20-include-translation.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-include-translation.cpp
@@ -0,0 +1,58 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h1.h -emit-header-unit -o h1.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h2.h -emit-header-unit -o h2.pcm
+
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface -o Xlate.pcm \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm \
+// RUN: -fsyntax-only -Wauto-import -verify
+
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm \
+// RUN: -E | FileCheck %s
+
+// The content of the headers is not terribly important, we just want to check
+// whether they are textually included or include-translated.
+//--- h1.h
+#ifndef H1_GUARD
+#define H1_GUARD
+
+#define ONE 1
+
+void foo();
+
+#endif // H1_GUARD
+
+//--- h2.h
+#ifndef H2_GUARD
+#define H2_GUARD
+
+#define TWO 2
+
+void bar();
+
+#endif // H2_GUARD
+
+//--- Xlate.cpp
+/* some comment ...
+  ... */
+module /*nothing here*/;
+
+// This should be include-translated, when the header unit for h1 is available.
+#include "h1.h" // expected-warning {{treating #include as an import of module './h1.h'}}
+
+export module Xlate;
+
+// This should *not* be include-translated, even if header unit for h2 is
+// available.
+#include "h2.h"
+export void charlie() {
+  foo();
+  bar();
+}
+
+// CHECK: #pragma clang module import "./h1.h"
+// CHECK-NOT: #pragma clang module import "./h2.h"
Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -663,12 +663,23 @@
 return false;
   }
 
-  case tok::annot_module_include:
-Actions.ActOnModuleInclude(Tok.getLocation(),
-   reinterpret_cast(
-   Tok.getAnnotationValue()));
+  case tok::annot_module_include: {
+auto Loc = Tok.getLocation();
+Module *Mod = reinterpret_cast(Tok.getAnnotationValue());
+// FIXME: We need a better way to disambiguate C++ clang modules and
+// standard C++ modules.
+if (!getLangOpts().CPlusPlusModules || !Mod->isHeaderUnit() ||
+getLangOpts().ModulesTS)
+  Actions.ActOnModuleInclude(Loc, Mod);
+else {
+  DeclResult Import =
+  Actions.ActOnModuleImport(Loc, SourceLocation(), Loc, Mod);
+  Decl *ImportDecl = Import.isInvalid() ? nullptr : Import.get();
+  Result = Actions.ConvertDeclToDeclGroup(ImportDecl);
+}
 ConsumeAnnotationToken();
 return false;
+  }
 
   case tok::annot_module_begin:
 Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast(
Index: clang/lib/Lex/Preprocessor.cpp
===
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -929,6 +929,9 @@
 
   // Update ImportSeqState to track our position within a C++20 import-seq
   // if this token is being produced as a result of phase 4 of translation.
+  // Update TrackGMFState to decide if we are currently in a Global Module
+  // Fragment. GMF state updates should precede ImportSeq ones, since GMF state
+  // de

[PATCH] D128981: [C++20][Modules] Implement include translation.

2022-07-02 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 441871.
iains added a comment.

fix a state transition after include translation.

This update fixes an (apparently pre-existing) bug in handling:

  module;
   #include "translated-header.h"
   import "header-unit.h";

The translation process pushes a tok::annot_module_include which was being
handled as "misc" in the state machine, leading to the wrong starting state
for processing the 'import' following.  The change here treats this token
as if it were the ';' that is notionally injected as part of the translation.

Updated the test case to test cases where header units can be imported.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128981/new/

https://reviews.llvm.org/D128981

Files:
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/Preprocessor.cpp
  clang/lib/Parse/Parser.cpp
  clang/test/Modules/cxx20-include-translation.cpp

Index: clang/test/Modules/cxx20-include-translation.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-include-translation.cpp
@@ -0,0 +1,90 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h1.h -emit-header-unit -o h1.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h2.h -emit-header-unit -o h2.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h3.h -emit-header-unit -o h3.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h4.h -emit-header-unit -o h4.pcm
+
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface -o Xlate.pcm \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm -fmodule-file=h3.pcm \
+// RUN: -fmodule-file=h4.pcm -fsyntax-only -Wauto-import -verify
+
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm -fmodule-file=h3.pcm \
+// RUN: -fmodule-file=h4.pcm  -E -undef | FileCheck %s
+
+// The content of the headers is not terribly important, we just want to check
+// whether they are textually included or include-translated.
+//--- h1.h
+#ifndef H1_GUARD
+#define H1_GUARD
+
+#define ONE 1
+
+void foo();
+
+#endif // H1_GUARD
+
+//--- h2.h
+#ifndef H2_GUARD
+#define H2_GUARD
+
+#define TWO 2
+
+void bar();
+
+#endif // H2_GUARD
+
+//--- h3.h
+#ifndef H3_GUARD
+#define H3_GUARD
+
+#define THREE 3
+
+void baz();
+
+#endif // H3_GUARD
+
+//--- h4.h
+#ifndef H4_GUARD
+#define H4_GUARD
+
+#define FOUR 4
+
+void boo();
+
+#endif // H4_GUARD
+
+//--- Xlate.cpp
+/* some comment ...
+  ... */
+module /*nothing here*/;
+
+// This should be include-translated, when the header unit for h1 is available.
+#include "h1.h" // expected-warning {{treating #include as an import of module './h1.h'}}
+// Import of a header unit is allowed, named modules are not.
+import "h2.h";
+
+export module Xlate;
+
+// This is OK, the import immediately follows the module decl.
+import "h3.h";
+
+// This should *not* be include-translated, even if header unit for h4 is
+// available.
+#include "h4.h"
+
+export void charlie() {
+  foo();
+  bar();
+  baz();
+  boo();
+}
+
+// CHECK: #pragma clang module import "./h1.h"
+// CHECK: import ./h2.h
+// CHECK: import ./h3.h
+// CHECK-NOT: #pragma clang module import "./h2.h"
Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -663,12 +663,23 @@
 return false;
   }
 
-  case tok::annot_module_include:
-Actions.ActOnModuleInclude(Tok.getLocation(),
-   reinterpret_cast(
-   Tok.getAnnotationValue()));
+  case tok::annot_module_include: {
+auto Loc = Tok.getLocation();
+Module *Mod = reinterpret_cast(Tok.getAnnotationValue());
+// FIXME: We need a better way to disambiguate C++ clang modules and
+// standard C++ modules.
+if (!getLangOpts().CPlusPlusModules || !Mod->isHeaderUnit() ||
+getLangOpts().ModulesTS)
+  Actions.ActOnModuleInclude(Loc, Mod);
+else {
+  DeclResult Import =
+  Actions.ActOnModuleImport(Loc, SourceLocation(), Loc, Mod);
+  Decl *ImportDecl = Import.isInvalid() ? nullptr : Import.get();
+  Result = Actions.ConvertDeclToDeclGroup(ImportDecl);
+}
 ConsumeAnnotationToken();
 return false;
+  }
 
   case tok::annot_module_begin:
 Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast(
Index: clang/lib/Lex/Preprocessor.cpp
===
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -929,6 +929,9 @@
 
   // Update ImportSeqState to track our position within a C++20 import-seq
   // if this token is being produced as a result of phase 4 of translation.
+  // Update TrackGMFState to decide if we are currently in a Global Module
+  // Fragment. GMF state update

[PATCH] D129045: [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-03 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a project: All.
iains added reviewers: urnathan, ChuanqiXu.
iains added a subscriber: clang-modules.
iains published this revision for review.
iains added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

the other provisions of P1779  are handled 
elsewhere:

1. private module fragment (which is also under discussion in core) and
2. implicit inline status for constexpr/consteval which has been implemented 
elsewhere (and is not modules-dependent).


This provides updates to
[class.mfct]:
Pre C++20 [class.mfct]p2:

  A member function may be defined (8.4) in its class definition, in
  which case it is an inline member function (7.1.2)

Post C++20 [class.mfct]p1:

  If a member function is attached to the global module and is defined
  in its class definition, it is inline.

and
[class.friend]:
Pre-C++20 [class.friend]p5

  A function can be defined in a friend declaration of a
  class . . . . Such a function is implicitly inline.

Post C++20 [class.friend]p7

  Such a function is implicitly an inline function if it is attached
  to the global module.

We add the output of implicit-inline to the TextNodeDumper, and amend
a couple of existing tests to account for this, plus add tests for the
cases covered above.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129045

Files:
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/AST/ast-dump-constant-expr.cpp
  clang/test/AST/ast-dump-lambda.cpp
  clang/test/CXX/class/class.friend/p7-cxx20.cpp
  clang/test/CXX/class/class.mfct/p1-cxx20.cpp

Index: clang/test/CXX/class/class.mfct/p1-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/class/class.mfct/p1-cxx20.cpp
@@ -0,0 +1,42 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 no-modules.cpp -fsyntax-only -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-NM %s
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header header-unit.h -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-HU %s
+// RUN: %clang_cc1 -std=c++20 module.cpp -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-MOD %s
+
+//--- no-modules.cpp
+
+class X {
+  void x(){};
+};
+
+// CHECK-NM: `-CXXRecordDecl {{.*}}  line:2:7 class X definition
+// CHECK-NM:   |-CXXRecordDecl {{.*}}  col:7 implicit class X
+// CHECK-NM-NEXT: `-CXXMethodDecl {{.*}}  col:8 x 'void ()' implicit-inline
+
+//--- header-unit.h
+
+class Y {
+  void y(){};
+};
+
+// CHECK-HU: `-CXXRecordDecl {{.*}} <./header-unit.h:2:1, line:4:1> line:2:7 class Y definition
+// CHECK-HU: |-CXXRecordDecl {{.*}}  col:7 implicit class Y
+// CHECK-HU-NEXT: `-CXXMethodDecl {{.*}}  col:8 y 'void ()' implicit-inline
+
+//--- module.cpp
+export module M;
+
+class Z {
+  void z(){};
+};
+
+// CHECK-MOD: `-CXXRecordDecl {{.*}}  line:3:7 in M hidden class Z{{( ReachableWhenImported)?}} definition
+// CHECK-MOD: |-CXXRecordDecl {{.*}}  col:7 in M hidden implicit class Z{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-CXXMethodDecl {{.*}}  col:8 in M hidden z 'void ()'{{( ReachableWhenImported)?}}
Index: clang/test/CXX/class/class.friend/p7-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/class/class.friend/p7-cxx20.cpp
@@ -0,0 +1,45 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 no-modules.cpp -fsyntax-only -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-NM %s
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header header-unit.h -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-HU %s
+// RUN: %clang_cc1 -std=c++20 module.cpp -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-MOD %s
+
+//--- no-modules.cpp
+
+class X {
+  friend void x(){};
+};
+
+// CHECK-NM: `-CXXRecordDecl {{.*}}  line:2:7 class X definition
+// CHECK-NM:   |-CXXRecordDecl {{.*}}  col:7 implicit class X
+// CHECK-NM-NEXT: `-FriendDecl {{.*}}  col:15
+// CHECK-NM-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 x 'void ()' implicit-inline
+
+//--- header-unit.h
+
+class Y {
+  friend void y(){};
+};
+
+// CHECK-HU: `-CXXRecordDecl {{.*}} <./header-unit.h:2:1, line:4:1> line:2:7 class Y definition
+// CHECK-HU: |-CXXRecordDecl {{.*}}  col:7 implicit class Y
+// CHECK-HU-NEXT: `-FriendDecl {{.*}}  col:15
+// CHECK-HU-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 y 'void ()' implicit-inline
+
+//--- module.cpp
+export module M;
+
+class Z {
+  friend void z(){};
+};
+
+// CHECK-MOD: `-CXXRecordDecl {{.*}}  line:3:7 in M hidden class Z{{( ReachableWhenImported)?}} definition
+// CHECK-MOD: |-CXXRecordDecl {{.*}}  col:7 in M hidden implicit class Z{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-FriendDecl 

[PATCH] D129045: [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-03 Thread Iain Sandoe via Phabricator via cfe-commits
iains marked 4 inline comments as done.
iains added inline comments.



Comment at: clang/lib/AST/TextNodeDumper.cpp:1723-1725
+  if (!D->isInlineSpecified() && D->isInlined()) {
+OS << " implicit-inline";
+  }

ChuanqiXu wrote:
> Is this necessary to this revision?
yes, to test it



Comment at: clang/lib/Sema/SemaDecl.cpp:9362
+  //   to the global module.
+  if (getLangOpts().CPlusPlus20 || getLangOpts().CPlusPlus2b) {
+Module *M = NewFD->getOwningModule();

ChuanqiXu wrote:
> If I remember correctly, when we run `-std=c++2b`, 
> `getLangOpts().CPlusPlus20` would be true too. So we could check 
> `getLangOpts().CPlusPlus20` only here.
will double-check.



Comment at: clang/lib/Sema/SemaDecl.cpp:9363-9365
+Module *M = NewFD->getOwningModule();
+if (!M || M->isGlobalModule())
+  NewFD->setImplicitlyInline();

ChuanqiXu wrote:
> nit: this is not  required.
well, the logic is required ;) .. you have suggested a different way to write..



Comment at: clang/lib/Sema/SemaDecl.cpp:9657
+  //   in its class definition, it is inline.
+  if (getLangOpts().CPlusPlus20 || getLangOpts().CPlusPlus2b) {
+Module *M = NewFD->getOwningModule();

ChuanqiXu wrote:
> ditto
likewise.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129045/new/

https://reviews.llvm.org/D129045

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129045: [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-04 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 442029.
iains marked 4 inline comments as done.
iains added a comment.

rebased, factored code to address comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129045/new/

https://reviews.llvm.org/D129045

Files:
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/AST/ast-dump-constant-expr.cpp
  clang/test/AST/ast-dump-lambda.cpp
  clang/test/CXX/class/class.friend/p7-cxx20.cpp
  clang/test/CXX/class/class.mfct/p1-cxx20.cpp

Index: clang/test/CXX/class/class.mfct/p1-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/class/class.mfct/p1-cxx20.cpp
@@ -0,0 +1,42 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 no-modules.cpp -fsyntax-only -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-NM %s
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header header-unit.h -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-HU %s
+// RUN: %clang_cc1 -std=c++20 module.cpp -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-MOD %s
+
+//--- no-modules.cpp
+
+class X {
+  void x(){};
+};
+
+// CHECK-NM: `-CXXRecordDecl {{.*}}  line:2:7 class X definition
+// CHECK-NM:   |-CXXRecordDecl {{.*}}  col:7 implicit class X
+// CHECK-NM-NEXT: `-CXXMethodDecl {{.*}}  col:8 x 'void ()' implicit-inline
+
+//--- header-unit.h
+
+class Y {
+  void y(){};
+};
+
+// CHECK-HU: `-CXXRecordDecl {{.*}} <./header-unit.h:2:1, line:4:1> line:2:7 class Y definition
+// CHECK-HU: |-CXXRecordDecl {{.*}}  col:7 implicit class Y
+// CHECK-HU-NEXT: `-CXXMethodDecl {{.*}}  col:8 y 'void ()' implicit-inline
+
+//--- module.cpp
+export module M;
+
+class Z {
+  void z(){};
+};
+
+// CHECK-MOD: `-CXXRecordDecl {{.*}}  line:3:7 in M hidden class Z{{( ReachableWhenImported)?}} definition
+// CHECK-MOD: |-CXXRecordDecl {{.*}}  col:7 in M hidden implicit class Z{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-CXXMethodDecl {{.*}}  col:8 in M hidden z 'void ()'{{( ReachableWhenImported)?}}
Index: clang/test/CXX/class/class.friend/p7-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/class/class.friend/p7-cxx20.cpp
@@ -0,0 +1,45 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 no-modules.cpp -fsyntax-only -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-NM %s
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header header-unit.h -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-HU %s
+// RUN: %clang_cc1 -std=c++20 module.cpp -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-MOD %s
+
+//--- no-modules.cpp
+
+class X {
+  friend void x(){};
+};
+
+// CHECK-NM: `-CXXRecordDecl {{.*}}  line:2:7 class X definition
+// CHECK-NM:   |-CXXRecordDecl {{.*}}  col:7 implicit class X
+// CHECK-NM-NEXT: `-FriendDecl {{.*}}  col:15
+// CHECK-NM-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 x 'void ()' implicit-inline
+
+//--- header-unit.h
+
+class Y {
+  friend void y(){};
+};
+
+// CHECK-HU: `-CXXRecordDecl {{.*}} <./header-unit.h:2:1, line:4:1> line:2:7 class Y definition
+// CHECK-HU: |-CXXRecordDecl {{.*}}  col:7 implicit class Y
+// CHECK-HU-NEXT: `-FriendDecl {{.*}}  col:15
+// CHECK-HU-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 y 'void ()' implicit-inline
+
+//--- module.cpp
+export module M;
+
+class Z {
+  friend void z(){};
+};
+
+// CHECK-MOD: `-CXXRecordDecl {{.*}}  line:3:7 in M hidden class Z{{( ReachableWhenImported)?}} definition
+// CHECK-MOD: |-CXXRecordDecl {{.*}}  col:7 in M hidden implicit class Z{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-FriendDecl {{.*}}  col:15 in M{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 in M hidden z 'void ()'{{( ReachableWhenImported)?}}
Index: clang/test/AST/ast-dump-lambda.cpp
===
--- clang/test/AST/ast-dump-lambda.cpp
+++ clang/test/AST/ast-dump-lambda.cpp
@@ -51,7 +51,7 @@
 // CHECK-NEXT:|   | |-MoveAssignment exists simple trivial needs_implicit
 // CHECK-NEXT:|   | `-Destructor simple irrelevant trivial needs_implicit
 // CHECK-NEXT:|   |-CXXRecordDecl {{.*}}  col:10{{( imported)?}} implicit struct V
-// CHECK-NEXT:|   `-CXXMethodDecl {{.*}}  line:17:10{{( imported)?}} f 'void ()'
+// CHECK-NEXT:|   `-CXXMethodDecl {{.*}}  line:17:10{{( imported)?}} f 'void ()' implicit-inline
 // CHECK-NEXT:| `-CompoundStmt {{.*}} 
 // CHECK-NEXT:|   |-LambdaExpr {{.*}}  '(lambda at {{.*}}ast-dump-lambda.cpp:18:7)'
 // CHECK-NEXT:|   | |-CXXRecordDecl {{.*}}  col:7{{( imported)?}} implicit{{( )?}} class definition
Index: clang/test/AST/ast-dump-constant-expr.cpp
=

[PATCH] D129045: [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-04 Thread Iain Sandoe via Phabricator via cfe-commits
iains added inline comments.



Comment at: clang/lib/Sema/SemaDecl.cpp:9363-9365
+Module *M = NewFD->getOwningModule();
+if (!M || M->isGlobalModule())
+  NewFD->setImplicitlyInline();

iains wrote:
> ChuanqiXu wrote:
> > nit: this is not  required.
> well, the logic is required ;) .. you have suggested a different way to 
> write..
actually, I think you meant `!NewFD->getOwningModule() || 
NewFD->getOwningModule()->isGlobalModule()` but I've pulled the test out so 
that it's only done once.



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129045/new/

https://reviews.llvm.org/D129045

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128981: [C++20][Modules] Implement include translation.

2022-07-04 Thread Iain Sandoe via Phabricator via cfe-commits
iains marked 3 inline comments as done.
iains added inline comments.



Comment at: clang/include/clang/Lex/Preprocessor.h:434
+/// Saw a 'module' identifier.
+void handleModule(bool ATLTS) {
+  // This was the first module identifier and not preceded by any token

ChuanqiXu wrote:
> What's the meaning of `ATLTS`?
`AfterTopLevelTokenSeq` I guess it seemed a rather long name (but I do not mind 
to spell it out if that makes sense).




Comment at: clang/lib/Lex/PPDirectives.cpp:2226-2227
+
+  // FIXME: We do not have a good way to disambiguate C++ clang modules from
+  // C++ standard modules (other than use/non-use of Header Units).
+  Module *SM = SuggestedModule.getModule();

ChuanqiXu wrote:
> From what @rsmith said in https://reviews.llvm.org/D113391, it looks like the 
> ideal direction is to use C++ clang modules and C++ standard modules 
> together. So it looks like we couldn't disambiguate them from command line 
> options.
Well, I think there is some more debate to have around how to solve this 
problem (i.e. it might be intended that clang++ modules and standard c++ 
modules converge but as things stand we still need to support the cases that 
they have different behaviour, or break existing users) 
 ... - but please let us not have that debate in this patch :-)




Comment at: clang/test/Modules/cxx20-include-translation.cpp:10
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h4.h -emit-header-unit -o 
h4.pcm
+
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface -o Xlate.pcm \

ChuanqiXu wrote:
> Maybe we need an example `h5.h` which is not pre-compiled  as a header unit 
> and it would be handled correctly.
I am not sure if you mean that the un-converted header would be included in the 
GMF or in the module purview - IMO we already have test-cases that cover this, 
but I do not mind adding something extra if there's a missing case?



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128981/new/

https://reviews.llvm.org/D128981

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129045: [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-04 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D129045#3627856 , @ChuanqiXu wrote:

> It looks like the tests lack the cast that the methods are attached to the 
> global module fragment.

(maybe I misunderstand what you are saying here)

  bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlus20 ||
 !NewFD->getOwningModule() ||
 NewFD->getOwningModule()->isGlobalModule();

We are in the global module if there is no owning module, or if the owning 
module is the GMF. 
 We always set this to true before C++20, matching the unconditional true 
default argument it the setImplicitlyInline() method.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129045/new/

https://reviews.llvm.org/D129045

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129045: [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-04 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 442072.
iains added a comment.

updated testcases to fix a missing new line and add included header in a GMF.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129045/new/

https://reviews.llvm.org/D129045

Files:
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/AST/ast-dump-constant-expr.cpp
  clang/test/AST/ast-dump-lambda.cpp
  clang/test/CXX/class/class.friend/p7-cxx20.cpp
  clang/test/CXX/class/class.mfct/p1-cxx20.cpp

Index: clang/test/CXX/class/class.mfct/p1-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/class/class.mfct/p1-cxx20.cpp
@@ -0,0 +1,57 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 no-modules.cpp -fsyntax-only -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-NM %s
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header header-unit.h -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-HU %s
+// RUN: %clang_cc1 -std=c++20 module.cpp -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-MOD %s
+
+//--- no-modules.cpp
+
+class X {
+  void x(){};
+};
+
+// CHECK-NM: `-CXXRecordDecl {{.*}}  line:2:7 class X definition
+// CHECK-NM:   |-CXXRecordDecl {{.*}}  col:7 implicit class X
+// CHECK-NM-NEXT: `-CXXMethodDecl {{.*}}  col:8 x 'void ()' implicit-inline
+
+// A header unit header
+//--- header-unit.h
+
+class Y {
+  void y(){};
+};
+
+// CHECK-HU: `-CXXRecordDecl {{.*}} <./header-unit.h:2:1, line:4:1> line:2:7 class Y definition
+// CHECK-HU: |-CXXRecordDecl {{.*}}  col:7 implicit class Y
+// CHECK-HU-NEXT: `-CXXMethodDecl {{.*}}  col:8 y 'void ()' implicit-inline
+
+// A textually-included header
+//--- header.h
+
+class A {
+  void a(){};
+};
+
+//--- module.cpp
+module;
+#include "header.h"
+
+export module M;
+
+class Z {
+  void z(){};
+};
+
+// CHECK-MOD: |-CXXRecordDecl {{.*}} <./header.h:2:1, line:4:1> line:2:7 in M. hidden class A definition
+// CHECK-MOD: | |-CXXRecordDecl {{.*}}  col:7 in M. hidden implicit class A
+// CHECK-MOD-NEXT: | `-CXXMethodDecl {{.*}}  col:8 in M. hidden a 'void ()' implicit-inline
+
+// CHECK-MOD: `-CXXRecordDecl {{.*}}  line:6:7 in M hidden class Z{{( ReachableWhenImported)?}} definition
+// CHECK-MOD: |-CXXRecordDecl {{.*}}  col:7 in M hidden implicit class Z{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-CXXMethodDecl {{.*}}  col:8 in M hidden z 'void ()'{{( ReachableWhenImported)?}}
Index: clang/test/CXX/class/class.friend/p7-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/class/class.friend/p7-cxx20.cpp
@@ -0,0 +1,59 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 no-modules.cpp -fsyntax-only -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-NM %s
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header header-unit.h -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-HU %s
+// RUN: %clang_cc1 -std=c++20 module.cpp -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-MOD %s
+
+//--- no-modules.cpp
+
+class X {
+  friend void x(){};
+};
+
+// CHECK-NM: `-CXXRecordDecl {{.*}}  line:2:7 class X definition
+// CHECK-NM:   |-CXXRecordDecl {{.*}}  col:7 implicit class X
+// CHECK-NM-NEXT: `-FriendDecl {{.*}}  col:15
+// CHECK-NM-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 x 'void ()' implicit-inline
+
+//--- header-unit.h
+
+class Y {
+  friend void y(){};
+};
+
+// CHECK-HU: `-CXXRecordDecl {{.*}} <./header-unit.h:2:1, line:4:1> line:2:7 class Y definition
+// CHECK-HU: |-CXXRecordDecl {{.*}}  col:7 implicit class Y
+// CHECK-HU-NEXT: `-FriendDecl {{.*}}  col:15
+// CHECK-HU-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 y 'void ()' implicit-inline
+
+// A textually-included header
+//--- header.h
+
+class A {
+  friend void a(){};
+};
+
+//--- module.cpp
+module;
+#include "header.h"
+
+export module M;
+
+class Z {
+  friend void z(){};
+};
+// CHECK-MOD: |-CXXRecordDecl {{.*}} <./header.h:2:1, line:4:1> line:2:7 in M. hidden class A definition
+// CHECK-MOD: | |-CXXRecordDecl {{.*}}  col:7 in M. hidden implicit class A
+// CHECK-MOD-NEXT: | `-FriendDecl {{.*}}  col:15 in M.
+// CHECK-MOD-NEXT: |   `-FunctionDecl {{.*}} parent {{.*}}  col:15 in M. hidden a 'void ()' implicit-inline
+
+// CHECK-MOD: `-CXXRecordDecl {{.*}}  line:6:7 in M hidden class Z{{( ReachableWhenImported)?}} definition
+// CHECK-MOD: |-CXXRecordDecl {{.*}}  col:7 in M hidden implicit class Z{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-FriendDecl {{.*}}  col:15 in M{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 in M hidden z 'void ()'{{( ReachableWhenImported)?}}
Index: clang/test/AST/ast-dump-lambda.cpp
==

[PATCH] D129045: [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-04 Thread Iain Sandoe via Phabricator via cfe-commits
iains marked an inline comment as done.
iains added a comment.

In D129045#3627901 , @ChuanqiXu wrote:

> In D129045#3627878 , @iains wrote:
>
>> In D129045#3627856 , @ChuanqiXu 
>> wrote:
>>
>>> It looks like the tests lack the cast that the methods are attached to the 
>>> global module fragment.
>>
>> (maybe I misunderstand what you are saying here)



> I mean the tests instead of the implementation. It looks like there is no GMF 
> in the tests.

added.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129045/new/

https://reviews.llvm.org/D129045

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128981: [C++20][Modules] Implement include translation.

2022-07-04 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 442085.
iains marked 7 inline comments as done.
iains added a comment.

rebased, addressed review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128981/new/

https://reviews.llvm.org/D128981

Files:
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/Preprocessor.cpp
  clang/lib/Parse/Parser.cpp
  clang/test/Modules/cxx20-include-translation.cpp

Index: clang/test/Modules/cxx20-include-translation.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-include-translation.cpp
@@ -0,0 +1,109 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h1.h -emit-header-unit -o h1.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h2.h -emit-header-unit -o h2.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h3.h -emit-header-unit -o h3.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h4.h -emit-header-unit -o h4.pcm
+
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface -o Xlate.pcm \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm -fmodule-file=h3.pcm \
+// RUN: -fmodule-file=h4.pcm -fsyntax-only -Wauto-import -verify
+
+// Check that we do the intended translation and not more.
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm -fmodule-file=h3.pcm \
+// RUN: -fmodule-file=h4.pcm  -E -undef | FileCheck %s
+
+// We expect no diagnostics here, the used functions should all be available.
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm -fmodule-file=h3.pcm \
+// RUN: -fmodule-file=h4.pcm -fsyntax-only
+
+// The content of the headers is not terribly important, we just want to check
+// whether they are textually included or include-translated.
+//--- h1.h
+#ifndef H1_GUARD
+#define H1_GUARD
+
+#define ONE 1
+
+void foo();
+
+#endif // H1_GUARD
+
+//--- h2.h
+#ifndef H2_GUARD
+#define H2_GUARD
+
+#define TWO 2
+
+void bar();
+
+#endif // H2_GUARD
+
+//--- h3.h
+#ifndef H3_GUARD
+#define H3_GUARD
+
+#define THREE 3
+
+void baz();
+
+#endif // H3_GUARD
+
+//--- h4.h
+#ifndef H4_GUARD
+#define H4_GUARD
+
+#define FOUR 4
+
+void boo();
+
+#endif // H4_GUARD
+
+//--- h5.h
+#ifndef H5_GUARD
+#define H5_GUARD
+
+#define FIVE 5
+
+void five();
+
+#endif // H4_GUARD
+
+//--- Xlate.cpp
+/* some comment ...
+  ... */
+module /*nothing here*/;
+
+// This should be include-translated, when the header unit for h1 is available.
+#include "h1.h" // expected-warning {{treating #include as an import of module './h1.h'}}
+// Import of a header unit is allowed, named modules are not.
+import "h2.h";
+// A regular, untranslated, header
+#include "h5.h"
+
+export module Xlate;
+
+// This is OK, the import immediately follows the module decl.
+import "h3.h";
+
+// This should *not* be include-translated, even if header unit for h4 is
+// available.
+#include "h4.h"
+
+export void charlie() {
+  foo();
+  bar();
+  baz();
+  boo();
+  five();
+}
+
+// CHECK: #pragma clang module import "./h1.h"
+// CHECK: import ./h2.h
+// CHECK: import ./h3.h
+// CHECK-NOT: #pragma clang module import "./h4.h"
Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -663,12 +663,23 @@
 return false;
   }
 
-  case tok::annot_module_include:
-Actions.ActOnModuleInclude(Tok.getLocation(),
-   reinterpret_cast(
-   Tok.getAnnotationValue()));
+  case tok::annot_module_include: {
+auto Loc = Tok.getLocation();
+Module *Mod = reinterpret_cast(Tok.getAnnotationValue());
+// FIXME: We need a better way to disambiguate C++ clang modules and
+// standard C++ modules.
+if (!getLangOpts().CPlusPlusModules || !Mod->isHeaderUnit() ||
+getLangOpts().ModulesTS)
+  Actions.ActOnModuleInclude(Loc, Mod);
+else {
+  DeclResult Import =
+  Actions.ActOnModuleImport(Loc, SourceLocation(), Loc, Mod);
+  Decl *ImportDecl = Import.isInvalid() ? nullptr : Import.get();
+  Result = Actions.ConvertDeclToDeclGroup(ImportDecl);
+}
 ConsumeAnnotationToken();
 return false;
+  }
 
   case tok::annot_module_begin:
 Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast(
Index: clang/lib/Lex/Preprocessor.cpp
===
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -941,6 +941,9 @@
 
   // Update ImportSeqState to track our position within a C++20 import-seq
   // if this token is being produced as a result of phase 4 of translation.
+  // Update TrackGMFState to decide if we are currently in a Global Module
+  // Fragment. GMF state updates should preced

[PATCH] D128981: [C++20][Modules] Implement include translation.

2022-07-04 Thread Iain Sandoe via Phabricator via cfe-commits
iains marked an inline comment as done.
iains added inline comments.



Comment at: clang/lib/Lex/PPDirectives.cpp:2226-2227
+
+  // FIXME: We do not have a good way to disambiguate C++ clang modules from
+  // C++ standard modules (other than use/non-use of Header Units).
+  Module *SM = SuggestedModule.getModule();

ChuanqiXu wrote:
> iains wrote:
> > ChuanqiXu wrote:
> > > From what @rsmith said in https://reviews.llvm.org/D113391, it looks like 
> > > the ideal direction is to use C++ clang modules and C++ standard modules 
> > > together. So it looks like we couldn't disambiguate them from command 
> > > line options.
> > Well, I think there is some more debate to have around how to solve this 
> > problem (i.e. it might be intended that clang++ modules and standard c++ 
> > modules converge but as things stand we still need to support the cases 
> > that they have different behaviour, or break existing users) 
> >  ... - but please let us not have that debate in this patch :-)
> > 
> It is not good to break existing users. Generally, a breaking change patch 
> could be reverted directly... We must care about it to avoid unnecessary 
> efforts. And it looks like the current implementation wouldn't break any 
> existing users, right? Since it uses `isHeaderUnit()`. I remember 
> `HeaderUnit` is introduced by  you so it shouldn't conflict with clang 
> modules.
> 
> BTW, may I ask the behavior is consistency with GCC?
> It is not good to break existing users. Generally, a breaking change patch 
> could be reverted directly... We must care about it to avoid unnecessary 
> efforts. And it looks like the current implementation wouldn't break any 
> existing users, right? Since it uses `isHeaderUnit()`. I remember 
> `HeaderUnit` is introduced by  you so it shouldn't conflict with clang 
> modules.

correct, in this case, the fact that Header Units are specific to the  C++20 
implementation (they are quite different from clang header modules) allows us 
to tell the difference.

> BTW, may I ask the behavior is consistency with GCC?

yes, I discussed this with @urnathan (especially that it is very difficult to 
get consistent behaviour if we were to include-translate in the module purview).



Comment at: clang/lib/Lex/PPDirectives.cpp:2335
+ IsFirstIncludeOfFile)) {
+// standard modules:
+// If we are not in the GMF, then we textually include only

ChuanqiXu wrote:
> nit: It looks like we prefer to use `C++20 modules` over `standard modules`, 
> although `standard modules` must be the right term.
since we are heading for C++23  ... perhaps now would be a good time to start 
using "standard modules"? (I can change to C++20 modules if there's objection).




Comment at: clang/lib/Parse/Parser.cpp:672
+if (!getLangOpts().CPlusPlusModules || !Mod->isHeaderUnit() ||
+getLangOpts().ModulesTS)
+  Actions.ActOnModuleInclude(Loc, Mod);

ChuanqiXu wrote:
> I think we could ignore `getLangOpts().ModulesTS` here.
well, we agreed that (for the present) we would try to avoid changing the 
behaviour w.r.t modules-ts (but spend no effort to complete the implementation) 
- and to remove it from comments; we can then take a pass through to remove the 
modules-ts behaviour (assuming that no-one is using it!)



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128981/new/

https://reviews.llvm.org/D128981

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D126694: [C++20][Modules] Implementation of GMF decl elision.

2022-07-05 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D126694#3629094 , @ChuanqiXu wrote:

> BTW, after I applied the patch, the compiler crashes at 
> https://github.com/ChuanqiXu9/stdmodules.

That link points to a project - is there (say) a gist of the crash information?

> I would try to add more tests about C++20 Modules.

of course, more tests can be useful, but it would be better to try to be 
specific - it does not crash for any of the tests in the clang test suite.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126694/new/

https://reviews.llvm.org/D126694

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128981: [C++20][Modules] Implement include translation.

2022-07-05 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 442242.
iains added a comment.

addressed review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128981/new/

https://reviews.llvm.org/D128981

Files:
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/Lex/PPDirectives.cpp
  clang/lib/Lex/Preprocessor.cpp
  clang/lib/Parse/Parser.cpp
  clang/test/Modules/cxx20-include-translation.cpp

Index: clang/test/Modules/cxx20-include-translation.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-include-translation.cpp
@@ -0,0 +1,109 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h1.h -emit-header-unit -o h1.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h2.h -emit-header-unit -o h2.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h3.h -emit-header-unit -o h3.pcm
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header h4.h -emit-header-unit -o h4.pcm
+
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface -o Xlate.pcm \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm -fmodule-file=h3.pcm \
+// RUN: -fmodule-file=h4.pcm -fsyntax-only -Wauto-import -verify
+
+// Check that we do the intended translation and not more.
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm -fmodule-file=h3.pcm \
+// RUN: -fmodule-file=h4.pcm  -E -undef | FileCheck %s
+
+// We expect no diagnostics here, the used functions should all be available.
+// RUN: %clang_cc1 -std=c++20 Xlate.cpp -emit-module-interface \
+// RUN: -fmodule-file=h1.pcm -fmodule-file=h2.pcm -fmodule-file=h3.pcm \
+// RUN: -fmodule-file=h4.pcm -fsyntax-only
+
+// The content of the headers is not terribly important, we just want to check
+// whether they are textually included or include-translated.
+//--- h1.h
+#ifndef H1_GUARD
+#define H1_GUARD
+
+#define ONE 1
+
+void foo();
+
+#endif // H1_GUARD
+
+//--- h2.h
+#ifndef H2_GUARD
+#define H2_GUARD
+
+#define TWO 2
+
+void bar();
+
+#endif // H2_GUARD
+
+//--- h3.h
+#ifndef H3_GUARD
+#define H3_GUARD
+
+#define THREE 3
+
+void baz();
+
+#endif // H3_GUARD
+
+//--- h4.h
+#ifndef H4_GUARD
+#define H4_GUARD
+
+#define FOUR 4
+
+void boo();
+
+#endif // H4_GUARD
+
+//--- h5.h
+#ifndef H5_GUARD
+#define H5_GUARD
+
+#define FIVE 5
+
+void five();
+
+#endif // H4_GUARD
+
+//--- Xlate.cpp
+/* some comment ...
+  ... */
+module /*nothing here*/;
+
+// This should be include-translated, when the header unit for h1 is available.
+#include "h1.h" // expected-warning {{treating #include as an import of module './h1.h'}}
+// Import of a header unit is allowed, named modules are not.
+import "h2.h";
+// A regular, untranslated, header
+#include "h5.h"
+
+export module Xlate;
+
+// This is OK, the import immediately follows the module decl.
+import "h3.h";
+
+// This should *not* be include-translated, even if header unit for h4 is
+// available.
+#include "h4.h"
+
+export void charlie() {
+  foo();
+  bar();
+  baz();
+  boo();
+  five();
+}
+
+// CHECK: #pragma clang module import "./h1.h"
+// CHECK: import ./h2.h
+// CHECK: import ./h3.h
+// CHECK-NOT: #pragma clang module import "./h4.h"
Index: clang/lib/Parse/Parser.cpp
===
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -663,12 +663,22 @@
 return false;
   }
 
-  case tok::annot_module_include:
-Actions.ActOnModuleInclude(Tok.getLocation(),
-   reinterpret_cast(
-   Tok.getAnnotationValue()));
+  case tok::annot_module_include: {
+auto Loc = Tok.getLocation();
+Module *Mod = reinterpret_cast(Tok.getAnnotationValue());
+// FIXME: We need a better way to disambiguate C++ clang modules and
+// standard C++ modules.
+if (!getLangOpts().CPlusPlusModules || !Mod->isHeaderUnit())
+  Actions.ActOnModuleInclude(Loc, Mod);
+else {
+  DeclResult Import =
+  Actions.ActOnModuleImport(Loc, SourceLocation(), Loc, Mod);
+  Decl *ImportDecl = Import.isInvalid() ? nullptr : Import.get();
+  Result = Actions.ConvertDeclToDeclGroup(ImportDecl);
+}
 ConsumeAnnotationToken();
 return false;
+  }
 
   case tok::annot_module_begin:
 Actions.ActOnModuleBegin(Tok.getLocation(), reinterpret_cast(
Index: clang/lib/Lex/Preprocessor.cpp
===
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -941,6 +941,9 @@
 
   // Update ImportSeqState to track our position within a C++20 import-seq
   // if this token is being produced as a result of phase 4 of translation.
+  // Update TrackGMFState to decide if we are currently in a Global Module
+  // Fragment. GMF state updates should precede ImportSeq ones, since GMF state
+  // depends on the prevailing ImportSeq state in 

[PATCH] D129174: [C++20][Modules] Invalidate internal-linkage functions in overload sets [P1815R2 part 1]

2022-07-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a project: All.
iains added reviewers: urnathan, ChuanqiXu.
iains added a subscriber: clang-modules.
iains published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This is an implementation of the first part of P1815 
 (and includes the testcase for
[basic.def.odr]/ p10).

If a function is in a different modular TU, and has internal-linkage, we 
invalidate its
entry in an overload set.

In [basic.lookup.argdep] p5 ex 2, we now correctly reject the use of `R::g` in 
the attempted
instantiation of 'apply' in TU #3.

Note that clang (and GCC) also rejects `f(x)` in the same TU, where the example 
currently
states it should be OK.  A clarification question has been sent to core about 
this.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129174

Files:
  clang/include/clang/Sema/Overload.h
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/basic/basic.link/p10-ex2.cpp
  clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp

Index: clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
===
--- /dev/null
+++ clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 N.cpp -emit-module-interface -o N.pcm \
+// RUN:   -fmodule-file=M.pcm
+// RUN: %clang_cc1 -std=c++20 Q.cpp -emit-module-interface -o Q.pcm
+// RUN: %clang_cc1 -std=c++20 Q-impl.cpp -fsyntax-only -fmodule-file=Q.pcm \
+// RUN:   -fmodule-file=N.pcm -verify
+
+//--- M.cpp
+export module M;
+namespace R {
+export struct X {};
+export void f(X);
+} // namespace R
+namespace S {
+export void f(R::X, R::X);
+}
+
+//--- N.cpp
+export module N;
+import M;
+export R::X make();
+namespace R {
+static int g(X);
+}
+export template 
+void apply(T t, U u) {
+  f(t, u);
+  g(t);
+}
+
+//--- Q.cpp
+export module Q;
+
+//--- Q-impl.cpp
+module Q;
+import N;
+
+namespace S {
+struct Z {
+  template  operator T();
+};
+} // namespace S
+void test() {
+  // OK, decltype(x) is R::X in module M
+  auto x = make();
+
+  // error: R and R::f are not visible here
+  R::f(x); // expected-error {{declaration of 'R' must be imported from module 'N' before it is required}}
+  // expected-n...@n.cpp:4 {{declaration here is not visible}}
+  // expected-error@-2 {{no type named 'f' in namespace 'R'}}
+
+  // Not OK, R::f from interface of M is reachable, but not visible to lookup.
+  f(x); // expected-error {{use of undeclared identifier 'f'}}
+
+  // error: S::f in module M not considered even though S is an associated
+  // namespace
+  f(x, S::Z()); // expected-error {{use of undeclared identifier 'f'}}
+
+  // error: S::f is visible in instantiation context, but  R::g has internal
+  // linkage and cannot be used outside N.cpp
+  apply(x, S::Z()); // expected-er...@n.cpp:10 {{no matching function for call to 'g'}}
+// expected-note@-1 {{in instantiation of function template specialization 'apply' requested here}}
+}
Index: clang/test/CXX/basic/basic.link/p10-ex2.cpp
===
--- /dev/null
+++ clang/test/CXX/basic/basic.link/p10-ex2.cpp
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -fsyntax-only -DTEST_INTERFACE -verify
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M.pcm -verify
+
+//--- decls.h
+int f(); // #1, attached to the global module
+int g(); // #2, attached to the global module
+
+//--- M.cpp
+module;
+#include "decls.h"
+export module M;
+export using ::f; // OK, does not declare an entity, exports #1
+#if TEST_INTERFACE
+// error: matches #2, but attached to M
+int g(); // expected-error {{declaration of 'g' in module M follows declaration in the global module}}
+// expected-note@decls.h:2 {{previous declaration is here}}
+#endif
+export int h(); // #3
+export int k(); // #4
+
+//--- useM.cpp
+import M;
+// error: matches #3
+static int h(); // expected-error {{static declaration of 'h' follows non-static declaration}}
+// expected-n...@m.cpp:10 {{previous declaration is here}}
+
+// error: matches #4
+int k(); // expected-error {{declaration of 'k' in the global module follows declaration in module M}}
+// expected-n...@m.cpp:11 {{previous declaration is here}}
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -6400,6 +6400,16 @@
 return;
   }
 
+  // Functions with internal linkage are only viable in the same module.
+  if (auto *MF = Function

[PATCH] D129138: [clang] [docs] Update the changes of C++20 Modules in clang15

2022-07-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

Perhaps we could be a little more bold about the completeness of the 
implementation (at least, w.r.t the base paper `P1103`) - we pass the relevant 
test cases.

As for the follow-on papers, I think we have more that can be added notes below:
There are some test cases to be posted to phab for some of these (so maybe 
allow me a few more days to get the list fully correct).

(it will also depend on what we can land before 26th - however some of the 
stuff below is already approved, so it's a matter of finding some time to push 
the patches and watch the bots...)

@ChuanqiXu if you think that more is needed on any of these (other than `P1815` 
which is known partial), please let me know.

(Please also add any relevant phab reviews from your side)

-

P1779R3: ABI isolation for member functions

- Paper applied to WP.

Change [dcl.inline]/7 (as edited by P1815R1):

- This is being addressed by D128328 

(although we have somewhat of a moving target since some clarifications were 
requested from core).

Change [dcl.fct.def.default]/3:

- Already handled in the constexpr/consteval code, there is no actual change 
for modular cases.

Change [class.mfct]/1:
Change [class.friend]/7:

- D129045 , including tests.

--

P1979R0: Resolution to US086

- Paper applied to WP.
- Current implementation complies: test case to be posted 
CXX/module/module.import/p7.cpp

--

P1811R0 Relaxing redefinition restrictions for re-exportation robustness

- Paper applied to WP - note there are on-going discussions in core/ext about 
exports that might affect this.

Note that there are a lot of changes here, but that the draft that includes 
them is what we are working to, so it is expected that (mostly) we will need to 
identify tests and/or queries about how to verify.

Change in 6.2 [basic.def.odr] paragraph 1:
Change in 6.2 [basic.def.odr] paragraph 12:

- no action required, these changes restore pre-P1103 behaviour (and the 
paragraph 12 changes have been subsumed in following updates).

Change in 10.5 [module.context] paragraph 7:

  test: CXX/module/module.context/p7.cpp

Change in 10.6 [module.reach] paragraph 3:

- D126694  and D128328 


Change in 15.2 [cpp.include] paragraph 7:

- D128981  provides conditional include 
translation that follows the same scheme as GCC.

Feature test macro

- already implemented.

---

[Partial] P1815R2: Translation-unit-local entities

Change [basic.def.odr]/10:

- implementation complies, example provided.

Insert before [basic.def.odr]/11

- D128328  + ongoing core/ext discussions.

Change [basic.lookup.argdep]/5:
D129174  - overload changes.  example added 
 Question to core on TU#3  f(x).

---

P2115R0: US069: Merging of multiple definitions for unnamed unscoped 
enumerations

- merged to WP, but ongoing discussions in core/ext might cause re-work

testcase to be posted to phab.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129138/new/

https://reviews.llvm.org/D129138

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129138: [clang] [docs] Update the changes of C++20 Modules in clang15

2022-07-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

I would not expect to add all this information to the release notes, or any of 
the phab links - just single lines to say that paper numbers are implemented

- the details are just to help us track the situation up to 26th July.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129138/new/

https://reviews.llvm.org/D129138

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129174: [C++20][Modules] Invalidate internal-linkage functions in overload sets [P1815R2 part 1]

2022-07-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains marked 2 inline comments as done.
iains added inline comments.



Comment at: clang/lib/Sema/SemaOverload.cpp:6406
+if (Function->getFormalLinkage() <= Linkage::InternalLinkage &&
+getLangOpts().CPlusPlus20 && MF != getCurrentModule()) {
+  Candidate.Viable = false;

ChuanqiXu wrote:
> The current implementation may reject following two cases:
> ```
> module;
> static void foo(int); // Ignore header
> ...
> export module A;
> void bar() { foo(5); } // Should it be invalid?
> ```
> and
> ```
> export module A;
> static void foo(int);
> ...
> module :private;
> void bar() { foo(5); } // Should it be invalid?
> ```
> 
> I mean in the above examples, the function of `foo(int)` is defined in the 
> same TU but the call to it might be rejected.
> The current implementation may reject following two cases:
> ```
> module;
> static void foo(int); // Ignore header
> ...
> export module A;
> void bar() { foo(5); } // Should it be invalid?
> ```
> and
> ```
> export module A;
> static void foo(int);
> ...
> module :private;
> void bar() { foo(5); } // Should it be invalid?
> ```
> 
> I mean in the above examples, the function of `foo(int)` is defined in the 
> same TU but the call to it might be rejected.





Comment at: clang/lib/Sema/SemaOverload.cpp:6406
+if (Function->getFormalLinkage() <= Linkage::InternalLinkage &&
+getLangOpts().CPlusPlus20 && MF != getCurrentModule()) {
+  Candidate.Viable = false;

iains wrote:
> ChuanqiXu wrote:
> > The current implementation may reject following two cases:
> > ```
> > module;
> > static void foo(int); // Ignore header
> > ...
> > export module A;
> > void bar() { foo(5); } // Should it be invalid?
> > ```
> > and
> > ```
> > export module A;
> > static void foo(int);
> > ...
> > module :private;
> > void bar() { foo(5); } // Should it be invalid?
> > ```
> > 
> > I mean in the above examples, the function of `foo(int)` is defined in the 
> > same TU but the call to it might be rejected.
> > The current implementation may reject following two cases:
> > ```
> > module;
> > static void foo(int); // Ignore header
> > ...
> > export module A;
> > void bar() { foo(5); } // Should it be invalid?
> > ```
> > and
> > ```
> > export module A;
> > static void foo(int);
> > ...
> > module :private;
> > void bar() { foo(5); } // Should it be invalid?
> > ```
> > 
> > I mean in the above examples, the function of `foo(int)` is defined in the 
> > same TU but the call to it might be rejected.
> 
> 
> The current implementation may reject following two cases:
> ```
> module;
> static void foo(int); // Ignore header
> ...

Actually, I have a note to check on the global module case, since we have 
special rules that allow merging of items there,


> export module A;
> void bar() { foo(5); } // Should it be invalid?
> ```
> and
> ```
> export module A;
> static void foo(int);
> ...
> module :private;
> void bar() { foo(5); } // Should it be invalid?
> ```
> 
> I mean in the above examples, the function of `foo(int)` is defined in the 
> same TU but the call to it might be rejected.

otherwise, agreed, these cases should be ok -  I guess we need a second test 
case with lookups that should succeed.




Comment at: clang/test/CXX/basic/basic.link/p10-ex2.cpp:10-35
+//--- decls.h
+int f(); // #1, attached to the global module
+int g(); // #2, attached to the global module
+
+//--- M.cpp
+module;
+#include "decls.h"

ChuanqiXu wrote:
> I feel like the test is irrelevant with the revision, isn't it? If yes, I 
> think we could land this as a separate NFC patch.
well, it is related to the paper mentioned, but yes we can make this separate.




Comment at: 
clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp:36-41
+//--- Q.cpp
+export module Q;
+
+//--- Q-impl.cpp
+module Q;
+import N;

ChuanqiXu wrote:
> This looks more consistent with the example.
This changes the example so that M is directly included in the implementation 
rather than transitively (the example does specifically use a different module 
name for the implementation)

I am not sure what you mean by "more consistent"
 (the example will fail to reject some of the lookups with this change).





Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129174/new/

https://reviews.llvm.org/D129174

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129174: [C++20][Modules] Invalidate internal-linkage functions in overload sets [P1815R2 part 1]

2022-07-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 442505.
iains marked 4 inline comments as done.
iains added a comment.

address review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129174/new/

https://reviews.llvm.org/D129174

Files:
  clang/include/clang/Sema/Overload.h
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/basic/basic.link/p10-ex2.cpp
  clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp

Index: clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
===
--- /dev/null
+++ clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 N.cpp -emit-module-interface -o N.pcm \
+// RUN:   -fmodule-file=M.pcm
+// RUN: %clang_cc1 -std=c++20 Q.cpp -emit-module-interface -o Q.pcm
+// RUN: %clang_cc1 -std=c++20 Q-impl.cpp -fsyntax-only -fmodule-file=Q.pcm \
+// RUN:   -fmodule-file=N.pcm -verify
+
+//--- M.cpp
+export module M;
+namespace R {
+export struct X {};
+export void f(X);
+} // namespace R
+namespace S {
+export void f(R::X, R::X);
+}
+
+//--- N.cpp
+export module N;
+import M;
+export R::X make();
+namespace R {
+static int g(X);
+}
+export template 
+void apply(T t, U u) {
+  f(t, u);
+  g(t);
+}
+
+//--- Q.cpp
+export module Q;
+
+//--- Q-impl.cpp
+module Q;
+import N;
+
+namespace S {
+struct Z {
+  template  operator T();
+};
+} // namespace S
+void test() {
+  // OK, decltype(x) is R::X in module M
+  auto x = make();
+
+  // error: R and R::f are not visible here
+  R::f(x); // expected-error {{declaration of 'R' must be imported from module 'N' before it is required}}
+  // expected-n...@n.cpp:4 {{declaration here is not visible}}
+  // expected-error@-2 {{no type named 'f' in namespace 'R'}}
+
+  // Not OK, R::f from interface of M is reachable, but not visible to lookup.
+  f(x); // expected-error {{use of undeclared identifier 'f'}}
+
+  // error: S::f in module M not considered even though S is an associated
+  // namespace
+  f(x, S::Z()); // expected-error {{use of undeclared identifier 'f'}}
+
+  // error: S::f is visible in instantiation context, but  R::g has internal
+  // linkage and cannot be used outside N.cpp
+  apply(x, S::Z()); // expected-er...@n.cpp:10 {{no matching function for call to 'g'}}
+// expected-note@-1 {{in instantiation of function template specialization 'apply' requested here}}
+}
Index: clang/test/CXX/basic/basic.link/p10-ex2.cpp
===
--- /dev/null
+++ clang/test/CXX/basic/basic.link/p10-ex2.cpp
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -fsyntax-only -DTEST_INTERFACE -verify
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M.pcm -verify
+
+//--- decls.h
+int f(); // #1, attached to the global module
+int g(); // #2, attached to the global module
+
+//--- M.cpp
+module;
+#include "decls.h"
+export module M;
+export using ::f; // OK, does not declare an entity, exports #1
+#if TEST_INTERFACE
+// error: matches #2, but attached to M
+int g(); // expected-error {{declaration of 'g' in module M follows declaration in the global module}}
+// expected-note@decls.h:2 {{previous declaration is here}}
+#endif
+export int h(); // #3
+export int k(); // #4
+
+//--- useM.cpp
+import M;
+// error: matches #3
+static int h(); // expected-error {{static declaration of 'h' follows non-static declaration}}
+// expected-n...@m.cpp:10 {{previous declaration is here}}
+
+// error: matches #4
+int k(); // expected-error {{declaration of 'k' in the global module follows declaration in module M}}
+// expected-n...@m.cpp:11 {{previous declaration is here}}
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -6400,6 +6400,17 @@
 return;
   }
 
+  // Functions with internal linkage are only viable in the same module unit.
+  if (auto *MF = Function->getOwningModule()) {
+if (Function->getFormalLinkage() <= Linkage::InternalLinkage &&
+getLangOpts().CPlusPlusModules &&
+MF->getTopLevelModule() != getCurrentModule()->getTopLevelModule()) {
+  Candidate.Viable = false;
+  Candidate.FailureKind = ovl_fail_module_mismatched;
+  return;
+}
+  }
+
   if (Function->isMultiVersion() && Function->hasAttr() &&
   !Function->getAttr()->isDefaultVersion()) {
 Candidate.Viable = false;
Index: clang/include/clang/Sema/Overload.h
===
--- clang/include/clang/Sema

[PATCH] D129174: [C++20][Modules] Invalidate internal-linkage functions in overload sets [P1815R2 part 1]

2022-07-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

TODO: second test-case for cases that should succeed, split out basic-link / 
p10-ex2 test case.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129174/new/

https://reviews.llvm.org/D129174

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D126694: [C++20][Modules] Implementation of GMF decl elision.

2022-07-07 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 442849.
iains marked 25 inline comments as done.
iains added a comment.

rebased, addressed review comments, added another test.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126694/new/

https://reviews.llvm.org/D126694

Files:
  clang/include/clang/AST/DeclBase.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/Decl.cpp
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/lib/Sema/SemaLambda.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/lib/Sema/SemaOpenMP.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaStmtAsm.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/lib/Serialization/ASTReaderDecl.cpp
  clang/test/AST/ast-dump-decl.c
  clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp
  clang/test/CXX/module/module.global.frag/cxx20-10-4-ex2.cpp
  clang/test/CXX/module/module.global.frag/p3-p4.cpp
  clang/test/Modules/cxx-templates.cpp

Index: clang/test/Modules/cxx-templates.cpp
===
--- clang/test/Modules/cxx-templates.cpp
+++ clang/test/Modules/cxx-templates.cpp
@@ -252,7 +252,7 @@
 // CHECK-DUMP:  ClassTemplateDecl {{.*}} <{{.*[/\\]}}cxx-templates-common.h:1:1, {{.*}}>  col:{{.*}} in cxx_templates_common SomeTemplate
 // CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
 // CHECK-DUMP-NEXT: TemplateArgument type 'char[2]'
-// CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
+// CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} SomeTemplate Visible definition
 // CHECK-DUMP-NEXT: DefinitionData
 // CHECK-DUMP-NEXT:   DefaultConstructor
 // CHECK-DUMP-NEXT:   CopyConstructor
@@ -263,7 +263,7 @@
 // CHECK-DUMP-NEXT: TemplateArgument type 'char[2]'
 // CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} prev {{.*}} SomeTemplate
 // CHECK-DUMP-NEXT: TemplateArgument type 'char[1]'
-// CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} SomeTemplate definition
+// CHECK-DUMP:ClassTemplateSpecializationDecl {{.*}} SomeTemplate Visible definition
 // CHECK-DUMP-NEXT: DefinitionData
 // CHECK-DUMP-NEXT:   DefaultConstructor
 // CHECK-DUMP-NEXT:   CopyConstructor
Index: clang/test/CXX/module/module.global.frag/p3-p4.cpp
===
--- /dev/null
+++ clang/test/CXX/module/module.global.frag/p3-p4.cpp
@@ -0,0 +1,54 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 M.cpp -ast-dump | FileCheck --match-full-lines %s
+// RUN: %clang_cc1 -std=c++20 M-impl.cpp -fmodule-file=M.pcm -fsyntax-only -verify
+
+//--- p3-p4.h
+int f();
+int g();
+int h();
+int j();
+typedef int GMFInt;
+
+//--- M.cpp
+module;
+#include "p3-p4.h"
+
+export module M;
+
+export int use_f() { return f(); }
+
+export using ::h;
+
+namespace N {
+export using ::j;
+}
+
+GMFInt k(int);
+
+// CHECK: |-FunctionDecl {{.*}} <./p3-p4.h:1:1, col:7> col:5 in M. hidden used f 'int ()' ReachableWhenImported
+// CHECK: |-FunctionDecl {{.*}}  col:5 in M. hidden g 'int ()' ModuleDiscardable
+// CHECK: |-FunctionDecl {{.*}}  col:5 in M. hidden h 'int ()' ReachableWhenImported
+// CHECK: |-FunctionDecl {{.*}}  col:5 in M. hidden j 'int ()' ReachableWhenImported
+// CHECK: |-TypedefDecl {{.*}}  col:13 in M. hidden referenced GMFInt 'int' ReachableWhenImported
+
+// CHECK: |-ExportDecl {{.*}}  col:1 in M
+// CHECK-NEXT: | `-FunctionDecl {{.*}}  col:12 in M hidden use_f 'int ()' VisibleWhenImported
+
+// CHECK: |-ExportDecl {{.*}}  col:1 in M
+// CHECK-NEXT: | |-UsingDecl {{.*}}  col:16 in M hidden ::h VisibleWhenImported
+// CHECK-NEXT: | `-UsingShadowDecl {{.*}}  col:16 in M hidden implicit Function {{.*}} 'h' 'int ()' VisibleWhenImported
+
+// CHECK: |-NamespaceDecl {{.*}}  line:10:11 in M hidden N
+// CHECK-NEXT: | `-ExportDecl {{.*}}  col:1 in M
+// CHECK-NEXT: |   |-UsingDecl {{.*}}  col:16 in M hidden ::j VisibleWhenImported
+// CHECK-NEXT: |   `-UsingShadowDecl {{.*}}  col:16 in M hidden implicit Function {{.*}} 'j' 'int ()' VisibleWhenImported
+
+//--- M-impl.cpp
+import M;
+int a = j();// expected-error {{missing '#include'; 'j' must be declared before it is used}}
+// expected-note@p3-p4.h:4 {{declaration here is not visible}}
+int b = N::j(); // should be OK, UsingShadowDecl is visible
Index: clang/test/CXX/module/module.global.frag/cxx20-10-4-ex2.cpp
===
--- /dev/null
+++ clang/test/CXX/module/module.global.frag/cxx20-10-4-ex2.cpp
@@ -0,0 +1,60 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c

[PATCH] D126694: [C++20][Modules] Implementation of GMF decl elision.

2022-07-07 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

@rsmith, @ChuanqiXu apologies for the multiple revisions, this has turned out 
to be much more involved than I imagined from the standard's text.

In D126694#3629254 , @ChuanqiXu wrote:

> In D126694#3629251 , @iains wrote:
>
>> In D126694#3629094 , @ChuanqiXu 
>> wrote:
>>
>>> BTW, after I applied the patch, the compiler crashes at 
>>> https://github.com/ChuanqiXu9/stdmodules.
>>
>> That link points to a project - is there (say) a gist of the crash 
>> information?
>
> Here is the crash log:

this code now compiles without error,




Comment at: clang/include/clang/AST/DeclBase.h:624
   bool isModulePrivate() const {
 return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate;
   }

iains wrote:
> ChuanqiXu wrote:
> > According to the opinion from @rsmith, the discarded declaration is private 
> > too.
> I guess you mean `>=`  ... however Discardable is a stronger constraint than 
> Private 
> 
> If a decl remains marked Discardable (after the processing to determine 
> reachable ones) that means it is both unreachable and invisible.
> So it must not participate in any processing (with the one exception of 
> diagnostic output).  I would be concerned that the change you suggest above 
> could cause a  Discardable decl to be considered in merging  or lookup and we 
> would then need (maybe a lot) of logic like:
> 
> ```
>  if (D->isModulePrivate() && !D->isModuleDiscardable())
> ...
> ```
> 
> I will take a look on the next iteration.
> 
I did try this and there are a number of regressions - when I looked into these 
there is some interaction with the changes made in D113545, so I think we 
should make these changes in a follow-one patch to avoid having two purposes in 
this one.



Comment at: clang/include/clang/Sema/Sema.h:2275-2276
 
+  llvm::SmallPtrSet SeenDecls;
+  llvm::SmallPtrSet SeenTypes;
+

rsmith wrote:
> These names seem too general to live directly in `Sema`.
(revised we only need to track the type pointers)

On the basis that the name is poor, for its intended purpose, I revised. 



Comment at: clang/include/clang/Sema/Sema.h:2273
+  void HandleGMFReachability(Decl *D) {
+if (D->isModuleUnreachable() && isCurrentModulePurview()) {
+  
D->setModuleOwnershipKind(Decl::ModuleOwnershipKind::ReachableWhenImported);

ChuanqiXu wrote:
> iains wrote:
> > ChuanqiXu wrote:
> > > I feel better if we would check if D lives in GMF. (We need to insert a 
> > > check in isDiscardedInGlobalModuleFragment)
> > If the consensus is to add an extra test, OK.
> > 
> > However, as above, specifically to avoid making more and more tests in code 
> > that is executed very frequently - as the design currently stands, the only 
> > place that  `ModuleUnreachable` is set is in the GMF.
> Yeah, my opinion is the same as above. Although it is the design, it is more 
> semantically clear and robust to add a additional check. I am just afraid it 
> would confuse and block other readers or contributors.
this has now been revised and a check is applied before any change is made to 
discardable decls.



Comment at: clang/lib/AST/TextNodeDumper.cpp:1622
+  if (D->isModuleUnreachable())
+OS << " ModuleUnreachable";
 }

ChuanqiXu wrote:
> iains wrote:
> > ChuanqiXu wrote:
> > > It may be better to keep the consistent style.
> > I don't think that is a matter of style `__module_private__` is a keyword 
> > used elsewhere?
> > 
> > If you look though the file you will see mostly that the printed output 
> > does not prepend or append underscores.
> > 
> > BTW, similar changes are probably needed in other node printers, this was 
> > done early to add debug.
> Oh, I found `__module_private__ ` is a keyword in clang modules. I didn't 
> recognize it. Even in this case, I still prefer to keep the style 
> consistently. I think users would be more comfortable to read consistent 
> symbols. Also I think it is acceptable to keep `ModuleUnreachable` since it 
> doesn't matter a lot to me.
OK we now have more fine-grained output for the module ownership in the dumps 
which allows specific tests to be constructed.  At present, the naming is as 
per decl.h (with the single exception of __module_private__ which has a 
user-facing representation).



Comment at: clang/lib/Sema/Sema.cpp:1130
 DiagnoseUseOfUnimplementedSelectors();
 
+// For C++20 modules, we are permitted to elide decls in the Global

ChuanqiXu wrote:
> I prefer to wrap this logic to a function to make it easier to read.
I think the comment refers to an older version of the changes.



Comment at: clang/lib/Sema/Sema.cpp:1131-1133
+// For C++20 modules, we are permitted to elide decls in the Global
+// Mo

[PATCH] D128328: [C++20][Modules] Improve handing of Private Module Fragment diagnostics.

2022-07-07 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 442942.
iains marked 3 inline comments as done.
iains added a comment.

rebased, reworked

- to follow the changes proposed by core
- to make the diagnostics follow that and a compromise for the proposed 
revision before the core amendment.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128328/new/

https://reviews.llvm.org/D128328

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/Modules/Reachability-Private.cpp
  clang/test/Modules/cxx20-10-5-ex1.cpp

Index: clang/test/Modules/cxx20-10-5-ex1.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-10-5-ex1.cpp
@@ -0,0 +1,53 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface std-10-5-ex1-interface.cpp \
+// RUN: -DBAD_FWD_DECL  -fsyntax-only -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface std-10-5-ex1-interface.cpp \
+// RUN: -o A.pcm
+
+// RUN: %clang_cc1 -std=c++20 std-10-5-ex1-use.cpp  -fmodule-file=A.pcm \
+// RUN:-fsyntax-only -verify
+
+//--- std-10-5-ex1-interface.cpp
+
+export module A;
+#ifdef BAD_FWD_DECL
+export inline void fn_e(); // expected-error {{exported inline function not defined before the private module fragment}}
+   // expected-n...@std-10-5-ex1-interface.cpp:21 {{private module fragment begins here}}
+#endif
+export inline void ok_fn() {}
+export inline void ok_fn2();
+#ifdef BAD_FWD_DECL
+inline void fn_m(); // expected-error {{un-exported inline function not defined before the private module fragment}}
+// expected-n...@std-10-5-ex1-interface.cpp:21 {{private module fragment begins here}}
+#endif
+static void fn_s();
+export struct X;
+export void g(X *x) {
+  fn_s();
+}
+export X *factory();
+void ok_fn2() {}
+
+module :private;
+struct X {};
+X *factory() {
+  return new X();
+}
+
+void fn_e() {}
+void fn_m() {}
+void fn_s() {}
+
+//--- std-10-5-ex1-use.cpp
+
+import A;
+
+void foo() {
+  X x; // expected-error 1+{{missing '#include'; 'X' must be defined before it is used}}
+   // expected-n...@std-10-5-ex1-interface.cpp:22 1+{{definition here is not reachable}}
+  X *p = factory();
+}
Index: clang/test/Modules/Reachability-Private.cpp
===
--- clang/test/Modules/Reachability-Private.cpp
+++ clang/test/Modules/Reachability-Private.cpp
@@ -4,18 +4,25 @@
 // RUN: mkdir -p %t
 // RUN: split-file %s %t
 //
-// RUN: %clang_cc1 -std=c++20 %t/Private.cppm -emit-module-interface -o %t/Private.pcm
-// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify -fsyntax-only
+// RUN: %clang_cc1 -std=c++20 %t/Private.cppm -emit-module-interface \
+// RUN: -o %t/Private.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp \
+// RUN: -DTEST_BADINLINE -verify -fsyntax-only
 
 //--- Private.cppm
 export module Private;
-inline void fn_m(); // OK, module-linkage inline function
+#ifdef TEST_BADINLINE
+inline void fn_m(); // expected-error {{un-exported inline function not defined before the private module fragment}}
+// expected-n...@private.cppm:13 {{private module fragment begins here}}
+#endif
 static void fn_s();
 export struct X;
 
 export void g(X *x) {
   fn_s(); // OK, call to static function in same translation unit
-  fn_m(); // OK, call to module-linkage inline function
+#ifdef TEST_BADINLINE
+  fn_m(); // fn_m is not OK.
+#endif
 }
 export X *factory(); // OK
 
@@ -30,10 +37,8 @@
 //--- Use.cpp
 import Private;
 void foo() {
-  X x; // expected-error {{definition of 'X' must be imported from module 'Private.' before it is required}}
-   // expected-error@-1 {{definition of 'X' must be imported from module 'Private.' before it is required}}
-   // expected-note@* {{definition here is not reachable}}
-   // expected-note@* {{definition here is not reachable}}
+  X x; // expected-error 1+{{missing '#include'; 'X' must be defined before it is used}}
+   // expected-n...@private.cppm:18 1+{{definition here is not reachable}}
   auto _ = factory();
   auto *__ = factory();
   X *___ = factory();
Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -901,6 +901,17 @@
 diagExportedUnnamedDecl(*this, UnnamedDeclKind::Context, Child,
 BlockStart);
   }
+  if (auto *FD = dyn_cast(Child)) {
+// [dcl.inline]/7
+// If an inline function or variable that is attached to a named module
+// is declared in a definition domain, it shall be defined in that
+// domain.
+// S

[PATCH] D128328: [C++20][Modules] Improve handing of Private Module Fragment diagnostics.

2022-07-07 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

the revised diagnostics look like this:

` error: {un-}exported inline function not defined before the private module 
fragment`

with 
` note: private module fragment begins here` pointing to the start of the PMF

If there is no PMF then we just say:

` error: {un-}exported inline function not defined `




Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:11155
+def err_export_inline_not_defined : Error<
+  "exported inline functions must be defined within the module purview"
+  " and before any private module fragment">;

iains wrote:
> ChuanqiXu wrote:
> > iains wrote:
> > > iains wrote:
> > > > ChuanqiXu wrote:
> > > > > From my reading, 'exported' is not emphasized.
> > > > it is here:
> > > > https://eel.is/c++draft/module#private.frag-2.1
> > > > ( I agree it is somewhat confusing, but the export makes the linkage 
> > > > external, which the example treats differently from the fn_m() case 
> > > > which has module linkage).
> > > > 
> > > > It is possible that we might need to pull together several pieces of 
> > > > the std and maybe ask core for clarification?
> > > > it is here:
> > > > https://eel.is/c++draft/module#private.frag-2.1
> > > > ( I agree it is somewhat confusing, but the export makes the linkage 
> > > > external, which the example treats differently from the fn_m() case 
> > > > which has module linkage).
> > > 
> > > hmm... my linkage comment is wrong - however the distinction between 
> > > exported and odr-used seems to be made here (fn_m() and fn_e()).
> > > > 
> > > > It is possible that we might need to pull together several pieces of 
> > > > the std and maybe ask core for clarification?
> > > 
> > > 
> > What I read is:
> > > [dcl.inline]p7: https://eel.is/c++draft/dcl.inline#7
> > > If an inline function or variable that is attached to a named module 
> > > is declared in a definition domain, it shall be defined in that domain.
> > 
> > and the definition of `definition domain` is:
> > > [basic.def.odr]p12: https://eel.is/c++draft/basic#def.odr-12
> > >   A definition domain is a private-module-fragment or the portion of 
> > > a translation unit excluding its private-module-fragment (if any).
> > 
> > The definition of "attached to a named module" is:
> > > [module.unit]p7: https://eel.is/c++draft/module.unit#7
> > >  A module is either a named module or the global module. A 
> > > declaration is attached to a module as follows: ...
> > 
> > So it is clearly not consistency with [module.private.frag]p2.1. I would 
> > send this to WG21.
> Yes, that was what I found - maybe we are  missing something about the export 
> that changes those rules.
> .
I think that we can consider this closed by the question to the ext reflector 
and the amendment proposed by core.



Comment at: clang/test/Modules/cxx20-10-5-ex1.cpp:25-28
+export void g(X *x) {
+  fn_s();
+  fn_m();
+}

ChuanqiXu wrote:
> vsapsai wrote:
> > Can `export inline` function call other non-`export inline` functions? 
> > Sorry if it is tested somewhere else. Curious what are the transitive 
> > restrictions, so we test edge cases.
> I guess it is not tested. But a non-export function wouldn't be exported if 
> it is called by export function from the perspective of std. Although more 
> tests should be fine all the time, the current test case should come from the 
> example in the standard. We could send another test if we want.
I've changed the example to match the proposed amendment to the standard.

If you think we should have some other test case (additional to 
Modules/Reachability-Private), that's fine - would you like to propose one (or 
maybe add to an existing)?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128328/new/

https://reviews.llvm.org/D128328

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D128328: [C++20][Modules] Improve handing of Private Module Fragment diagnostics.

2022-07-08 Thread Iain Sandoe via Phabricator via cfe-commits
iains added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:11155
+def err_export_inline_not_defined : Error<
+  "exported inline functions must be defined within the module purview"
+  " and before any private module fragment">;

ChuanqiXu wrote:
> iains wrote:
> > iains wrote:
> > > ChuanqiXu wrote:
> > > > iains wrote:
> > > > > iains wrote:
> > > > > > ChuanqiXu wrote:
> > > > > > > From my reading, 'exported' is not emphasized.
> > > > > > it is here:
> > > > > > https://eel.is/c++draft/module#private.frag-2.1
> > > > > > ( I agree it is somewhat confusing, but the export makes the 
> > > > > > linkage external, which the example treats differently from the 
> > > > > > fn_m() case which has module linkage).
> > > > > > 
> > > > > > It is possible that we might need to pull together several pieces 
> > > > > > of the std and maybe ask core for clarification?
> > > > > > it is here:
> > > > > > https://eel.is/c++draft/module#private.frag-2.1
> > > > > > ( I agree it is somewhat confusing, but the export makes the 
> > > > > > linkage external, which the example treats differently from the 
> > > > > > fn_m() case which has module linkage).
> > > > > 
> > > > > hmm... my linkage comment is wrong - however the distinction between 
> > > > > exported and odr-used seems to be made here (fn_m() and fn_e()).
> > > > > > 
> > > > > > It is possible that we might need to pull together several pieces 
> > > > > > of the std and maybe ask core for clarification?
> > > > > 
> > > > > 
> > > > What I read is:
> > > > > [dcl.inline]p7: https://eel.is/c++draft/dcl.inline#7
> > > > > If an inline function or variable that is attached to a named 
> > > > > module is declared in a definition domain, it shall be defined in 
> > > > > that domain.
> > > > 
> > > > and the definition of `definition domain` is:
> > > > > [basic.def.odr]p12: https://eel.is/c++draft/basic#def.odr-12
> > > > >   A definition domain is a private-module-fragment or the portion 
> > > > > of a translation unit excluding its private-module-fragment (if any).
> > > > 
> > > > The definition of "attached to a named module" is:
> > > > > [module.unit]p7: https://eel.is/c++draft/module.unit#7
> > > > >  A module is either a named module or the global module. A 
> > > > > declaration is attached to a module as follows: ...
> > > > 
> > > > So it is clearly not consistency with [module.private.frag]p2.1. I 
> > > > would send this to WG21.
> > > Yes, that was what I found - maybe we are  missing something about the 
> > > export that changes those rules.
> > > .
> > I think that we can consider this closed by the question to the ext 
> > reflector and the amendment proposed by core.
> I prefer `inline function attached to a named module not defined %select{| 
> before the private module fragment}1`. Since the `export` part is not 
> important here and the important part is whether or not they are attached to 
> a named module.
I took the error message from here:
https://github.com/cplusplus/draft/pull/5537
which was prepared after the dicussion that you started on the ext reflector.  
Actually, I do not have a strong feeling either way.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128328/new/

https://reviews.llvm.org/D128328

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D126694: [C++20][Modules] Implementation of GMF decl elision.

2022-07-08 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D126694#3637690 , @ChuanqiXu wrote:

> In D126694#3635207 , @iains wrote:
>
>> @rsmith, @ChuanqiXu apologies for the multiple revisions, this has turned 
>> out to be much more involved than I imagined from the standard's text.
>>
>> In D126694#3629254 , @ChuanqiXu 
>> wrote:
>>
>>> In D126694#3629251 , @iains wrote:
>>>
 In D126694#3629094 , @ChuanqiXu 
 wrote:

> BTW, after I applied the patch, the compiler crashes at 
> https://github.com/ChuanqiXu9/stdmodules.

 That link points to a project - is there (say) a gist of the crash 
 information?
>>>
>>> Here is the crash log:
>>
>> this code now compiles without error,
>
> Thanks for looking into it!
>
> My personal plan for this revision is to review the details after we add more 
> large tests (at least we have a more complete std modules implementation and 
> I am trying for it. But I find another bug now). So we might need to wait for 
> a while for this patch. How do you think about it?

Well, the difficulty there is that "add more large tests" is not a very 
specific objective.
I will be first to say that we can tell that the implementation here is 
necessary, but we cannot tell if it is sufficient - however, IMO we need to 
find a more definite way to make progress.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126694/new/

https://reviews.llvm.org/D126694

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D129174: [C++20][Modules] Update ADL to handle basic.lookup.argdep p4 [P1815R2 part 1]

2022-07-08 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 443194.
iains retitled this revision from "[C++20][Modules] Invalidate internal-linkage 
functions in overload sets [P1815R2 part 1]" to "[C++20][Modules] Update ADL to 
handle basic.lookup.argdep p4 [P1815R2 part 1]".
iains edited the summary of this revision.
iains added a comment.

updated after clarification of the provisions of basic.lookup.argdep p4


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129174/new/

https://reviews.llvm.org/D129174

Files:
  clang/include/clang/Sema/Overload.h
  clang/lib/Sema/SemaLookup.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CXX/basic/basic.link/p10-ex2.cpp
  clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp

Index: clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
===
--- /dev/null
+++ clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp
@@ -0,0 +1,68 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 N.cpp -emit-module-interface -o N.pcm \
+// RUN:   -fmodule-file=M.pcm
+// RUN: %clang_cc1 -std=c++20 Q.cpp -emit-module-interface -o Q.pcm
+// RUN: %clang_cc1 -std=c++20 Q-impl.cpp -fsyntax-only -fmodule-file=Q.pcm \
+// RUN:   -fmodule-file=N.pcm -verify
+
+//--- M.cpp
+export module M;
+namespace R {
+export struct X {};
+export void f(X);
+} // namespace R
+namespace S {
+export void f(R::X, R::X);
+}
+
+//--- N.cpp
+export module N;
+import M;
+export R::X make();
+namespace R {
+static int g(X);
+}
+export template 
+void apply(T t, U u) {
+  f(t, u);
+  g(t);
+}
+
+//--- Q.cpp
+export module Q;
+
+//--- Q-impl.cpp
+module Q;
+import N;
+
+namespace S {
+struct Z {
+  template  operator T();
+};
+} // namespace S
+void test() {
+  // OK, decltype(x) is R::X in module M
+  auto x = make();
+
+  // error: R and R::f are not visible here
+  R::f(x); // expected-error {{declaration of 'R' must be imported from module 'N' before it is required}}
+  // expected-n...@n.cpp:4 {{declaration here is not visible}}
+  // expected-error@-2 {{no type named 'f' in namespace 'R'}}
+
+  f(x); // Found by [basic.lookup.argdep] / p4.3
+
+  // error: S::f in module M not considered even though S is an associated
+  // namespace, since the entity Z is in a different module from f.
+  f(x, S::Z()); // expected-error {{no matching function for call to 'f'}}
+  // expected-n...@m.cpp:4 {{candidate function not viable: requires 1 argument, but 2 were provided}}
+
+  // error: S::f is visible in instantiation context, but  R::g has internal
+  // linkage and cannot be used outside N.cpp
+  apply(x, S::Z()); // expected-er...@n.cpp:10 {{no matching function for call to 'g'}}
+// expected-note@-1 {{in instantiation of function template specialization 'apply' requested here}}
+}
Index: clang/test/CXX/basic/basic.link/p10-ex2.cpp
===
--- /dev/null
+++ clang/test/CXX/basic/basic.link/p10-ex2.cpp
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 M.cpp -fsyntax-only -DTEST_INTERFACE -verify
+// RUN: %clang_cc1 -std=c++20 M.cpp -emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -std=c++20 useM.cpp -fsyntax-only -fmodule-file=M.pcm -verify
+
+//--- decls.h
+int f(); // #1, attached to the global module
+int g(); // #2, attached to the global module
+
+//--- M.cpp
+module;
+#include "decls.h"
+export module M;
+export using ::f; // OK, does not declare an entity, exports #1
+#if TEST_INTERFACE
+// error: matches #2, but attached to M
+int g(); // expected-error {{declaration of 'g' in module M follows declaration in the global module}}
+// expected-note@decls.h:2 {{previous declaration is here}}
+#endif
+export int h(); // #3
+export int k(); // #4
+
+//--- useM.cpp
+import M;
+// error: matches #3
+static int h(); // expected-error {{static declaration of 'h' follows non-static declaration}}
+// expected-n...@m.cpp:10 {{previous declaration is here}}
+
+// error: matches #4
+int k(); // expected-error {{declaration of 'k' in the global module follows declaration in module M}}
+// expected-n...@m.cpp:11 {{previous declaration is here}}
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -6400,6 +6400,17 @@
 return;
   }
 
+  // Functions with internal linkage are only viable in the same module unit.
+  if (auto *MF = Function->getOwningModule()) {
+if (Function->getFormalLinkage() <= Linkage::InternalLinkage &&
+getLangOpts().CPlusPlusModules &&
+MF->getTopLevelModule() != getCurrentModule()->getTopLevelModule()) {
+  Candidate.Viable = false;
+  Ca

[PATCH] D127624: [C++20][Modules] Allow for redeclarations in partitions.

2022-07-08 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGbc2a6defc853: [C++20][Modules] Allow for redeclarations in 
partitions. (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D127624/new/

https://reviews.llvm.org/D127624

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Modules/cxx20-partition-redeclarations.cpp


Index: clang/test/Modules/cxx20-partition-redeclarations.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-partition-redeclarations.cpp
@@ -0,0 +1,55 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 A-intf-part.cpp -emit-module-interface \
+// RUN:  -o A-PubPart.pcm
+// RUN: %clang_cc1 -std=c++20 A-interface.cpp -emit-module-interface \
+// RUN:   -fmodule-file=A-PubPart.pcm -o A.pcm
+
+// RUN: %clang_cc1 -std=c++20 A-impl-top.cpp -fsyntax-only -fmodule-file=A.pcm
+// RUN: %clang_cc1 -std=c++20 A-impl-part.cpp -fsyntax-only -fmodule-file=A.pcm
+// RUN: %clang_cc1 -std=c++20 A-impl-1.cpp -fsyntax-only -fmodule-file=A.pcm
+// RUN: %clang_cc1 -std=c++20 A-impl-2.cpp -fsyntax-only -fmodule-file=A.pcm
+
+//--- A-interface.cpp
+export module A;
+
+export import :PubPart;
+
+export void do_something();
+
+void helper1();
+void helper3();
+
+//--- A-intf-part.cpp
+export module A:PubPart;
+
+void helper2();
+
+//--- A-impl-top.cpp
+
+module A;
+
+void do_something() {
+  helper1();
+  helper2();
+  helper3();
+}
+
+//--- A-impl-part.cpp
+module A:Secret;
+
+import A;
+
+void helper3() {}
+
+//--- A-impl-1.cpp
+module A;
+
+void helper1() {}
+
+//--- A-impl-2.cpp
+module A;
+
+void helper2() {}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -1625,22 +1625,20 @@
   Module *NewM = New->getOwningModule();
   Module *OldM = Old->getOwningModule();
 
-  if (NewM && NewM->Kind == Module::PrivateModuleFragment)
+  if (NewM && NewM->isPrivateModule())
 NewM = NewM->Parent;
-  if (OldM && OldM->Kind == Module::PrivateModuleFragment)
+  if (OldM && OldM->isPrivateModule())
 OldM = OldM->Parent;
 
-  // If we have a decl in a module partition, it is part of the containing
-  // module (which is the only thing that can be importing it).
-  if (NewM && OldM &&
-  (OldM->Kind == Module::ModulePartitionInterface ||
-   OldM->Kind == Module::ModulePartitionImplementation)) {
-return false;
-  }
-
   if (NewM == OldM)
 return false;
 
+  // Partitions are part of the module, but a partition could import another
+  // module, so verify that the PMIs agree.
+  if (NewM && OldM && (NewM->isModulePartition() || OldM->isModulePartition()))
+return NewM->getPrimaryModuleInterfaceName() ==
+   OldM->getPrimaryModuleInterfaceName();
+
   bool NewIsModuleInterface = NewM && NewM->isModulePurview();
   bool OldIsModuleInterface = OldM && OldM->isModulePurview();
   if (NewIsModuleInterface || OldIsModuleInterface) {


Index: clang/test/Modules/cxx20-partition-redeclarations.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-partition-redeclarations.cpp
@@ -0,0 +1,55 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 A-intf-part.cpp -emit-module-interface \
+// RUN:  -o A-PubPart.pcm
+// RUN: %clang_cc1 -std=c++20 A-interface.cpp -emit-module-interface \
+// RUN:   -fmodule-file=A-PubPart.pcm -o A.pcm
+
+// RUN: %clang_cc1 -std=c++20 A-impl-top.cpp -fsyntax-only -fmodule-file=A.pcm
+// RUN: %clang_cc1 -std=c++20 A-impl-part.cpp -fsyntax-only -fmodule-file=A.pcm
+// RUN: %clang_cc1 -std=c++20 A-impl-1.cpp -fsyntax-only -fmodule-file=A.pcm
+// RUN: %clang_cc1 -std=c++20 A-impl-2.cpp -fsyntax-only -fmodule-file=A.pcm
+
+//--- A-interface.cpp
+export module A;
+
+export import :PubPart;
+
+export void do_something();
+
+void helper1();
+void helper3();
+
+//--- A-intf-part.cpp
+export module A:PubPart;
+
+void helper2();
+
+//--- A-impl-top.cpp
+
+module A;
+
+void do_something() {
+  helper1();
+  helper2();
+  helper3();
+}
+
+//--- A-impl-part.cpp
+module A:Secret;
+
+import A;
+
+void helper3() {}
+
+//--- A-impl-1.cpp
+module A;
+
+void helper1() {}
+
+//--- A-impl-2.cpp
+module A;
+
+void helper2() {}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -1625,22 +1625,20 @@
   Module *NewM = New->getOwningModule();
   Module *OldM = Old->getOwningModule();
 
-  if (NewM && NewM->Kind == Module::PrivateModuleFragment)
+  if (NewM && NewM->isPrivateModule())
 NewM = NewM->Parent;
-  if (OldM && OldM->Kind == Module::PrivateModuleFragment)
+  if (OldM && OldM->isPrivateModule())

[PATCH] D126189: [C++20][Modules] Build module static initializers per P1874R1.

2022-07-09 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGac507102d258: [C++20][Modules] Build module static 
initializers per P1874R1. (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D126189/new/

https://reviews.llvm.org/D126189

Files:
  clang/include/clang/AST/ASTContext.h
  clang/include/clang/Basic/Module.h
  clang/include/clang/Sema/Sema.h
  clang/lib/CodeGen/CGDeclCXX.cpp
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Parse/ParseAST.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/CodeGen/module-intializer-pmf.cpp
  clang/test/CodeGen/module-intializer.cpp

Index: clang/test/CodeGen/module-intializer.cpp
===
--- /dev/null
+++ clang/test/CodeGen/module-intializer.cpp
@@ -0,0 +1,186 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 N.cpp \
+// RUN:-emit-module-interface -o N.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 N.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-N
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.cpp \
+// RUN:-emit-module-interface -o O.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-O
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.cpp \
+// RUN:-emit-module-interface -o M-part.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-part.pcm -S \
+// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-P
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.cpp \
+// RUN: -fmodule-file=N.pcm -fmodule-file=O.pcm -fmodule-file=M-part.pcm \
+// RUN:-emit-module-interface -o M.pcm
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M.pcm -S -emit-llvm \
+// RUN:  -o - | FileCheck %s --check-prefix=CHECK-M
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 useM.cpp \
+// RUN: -fmodule-file=M.pcm -S -emit-llvm  -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK-USE
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 M-impl.cpp \
+// RUN: -fmodule-file=M.pcm -S -emit-llvm  -o - \
+// RUN: | FileCheck %s --check-prefix=CHECK-IMPL
+
+//--- N-h.h
+
+struct Oink {
+  Oink(){};
+};
+
+Oink Hog;
+
+//--- N.cpp
+
+module;
+#include "N-h.h"
+
+export module N;
+
+export struct Quack {
+  Quack(){};
+};
+
+export Quack Duck;
+
+// CHECK-N: define internal void @__cxx_global_var_init
+// CHECK-N: call void @_ZN4OinkC1Ev
+// CHECK-N: define internal void @__cxx_global_var_init
+// CHECK-N: call void @_ZNW1N5QuackC1Ev
+// CHECK-N: define void @_ZGIW1N
+// CHECK-N: store i8 1, ptr @_ZGIW1N__in_chrg
+// CHECK-N: call void @__cxx_global_var_init
+// CHECK-N: call void @__cxx_global_var_init
+
+//--- O-h.h
+
+struct Meow {
+  Meow(){};
+};
+
+Meow Cat;
+
+//--- O.cpp
+
+module;
+#include "O-h.h"
+
+export module O;
+
+export struct Bark {
+  Bark(){};
+};
+
+export Bark Dog;
+
+// CHECK-O: define internal void @__cxx_global_var_init
+// CHECK-O: call void @_ZN4MeowC2Ev
+// CHECK-O: define internal void @__cxx_global_var_init
+// CHECK-O: call void @_ZNW1O4BarkC1Ev
+// CHECK-O: define void @_ZGIW1O
+// CHECK-O: store i8 1, ptr @_ZGIW1O__in_chrg
+// CHECK-O: call void @__cxx_global_var_init
+// CHECK-O: call void @__cxx_global_var_init
+
+//--- P-h.h
+
+struct Croak {
+  Croak(){};
+};
+
+Croak Frog;
+
+//--- M-part.cpp
+
+module;
+#include "P-h.h"
+
+module M:Part;
+
+struct Squawk {
+  Squawk(){};
+};
+
+Squawk parrot;
+
+// CHECK-P: define internal void @__cxx_global_var_init
+// CHECK-P: call void @_ZN5CroakC1Ev
+// CHECK-P: define internal void @__cxx_global_var_init
+// CHECK-P: call void @_ZNW1M6SquawkC1Ev
+// CHECK-P: define void @_ZGIW1MWP4Part
+// CHECK-P: store i8 1, ptr @_ZGIW1MWP4Part__in_chrg
+// CHECK-P: call void @__cxx_global_var_init
+// CHECK-P: call void @__cxx_global_var_init
+
+//--- M-h.h
+
+struct Moo {
+  Moo(){};
+};
+
+Moo Cow;
+
+//--- M.cpp
+
+module;
+#include "M-h.h"
+
+export module M;
+import N;
+export import O;
+import :Part;
+
+export struct Baa {
+  int x;
+  Baa(){};
+  Baa(int x) : x(x) {}
+  int getX() { return x; }
+};
+
+export Baa Sheep(10);
+
+// CHECK-M: define internal void @__cxx_global_var_init
+// CHECK-M: call void @_ZN3MooC1Ev
+// CHECK-M: define internal void @__cxx_global_var_init
+// CHECK-M: call void @_ZNW1M3BaaC1Ei
+// CHECK-M: declare void @_ZGIW1O()
+// CHECK-M: declare void @_ZGIW1N()
+// CHECK-M: declare void @_ZGIW1MWP4Part()
+// CHECK-M: define void @_ZGIW1M
+// CHECK-M: store i8 1, ptr @_ZGIW1M__in_chrg
+// CHECK-M: call void @_ZGIW1O()
+// CHECK-M: call void @_ZGIW1N()
+// CHECK-M: call void @_ZGIW1MWP4Part()
+// CHECK-M: call void @__cxx_global_var_init
+// CHECK-M: call void @__cxx_gl

[PATCH] D129045: [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-09 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGef0fa9f0ef3e: [C++20][Modules] Update handling of implicit 
inlines [P1779R3] (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129045/new/

https://reviews.llvm.org/D129045

Files:
  clang/lib/AST/TextNodeDumper.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/AST/ast-dump-constant-expr.cpp
  clang/test/AST/ast-dump-lambda.cpp
  clang/test/CXX/class/class.friend/p7-cxx20.cpp
  clang/test/CXX/class/class.mfct/p1-cxx20.cpp

Index: clang/test/CXX/class/class.mfct/p1-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/class/class.mfct/p1-cxx20.cpp
@@ -0,0 +1,57 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 no-modules.cpp -fsyntax-only -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-NM %s
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header header-unit.h -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-HU %s
+// RUN: %clang_cc1 -std=c++20 module.cpp -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-MOD %s
+
+//--- no-modules.cpp
+
+class X {
+  void x(){};
+};
+
+// CHECK-NM: `-CXXRecordDecl {{.*}}  line:2:7 class X definition
+// CHECK-NM:   |-CXXRecordDecl {{.*}}  col:7 implicit class X
+// CHECK-NM-NEXT: `-CXXMethodDecl {{.*}}  col:8 x 'void ()' implicit-inline
+
+// A header unit header
+//--- header-unit.h
+
+class Y {
+  void y(){};
+};
+
+// CHECK-HU: `-CXXRecordDecl {{.*}} <./header-unit.h:2:1, line:4:1> line:2:7 class Y definition
+// CHECK-HU: |-CXXRecordDecl {{.*}}  col:7 implicit class Y
+// CHECK-HU-NEXT: `-CXXMethodDecl {{.*}}  col:8 y 'void ()' implicit-inline
+
+// A textually-included header
+//--- header.h
+
+class A {
+  void a(){};
+};
+
+//--- module.cpp
+module;
+#include "header.h"
+
+export module M;
+
+class Z {
+  void z(){};
+};
+
+// CHECK-MOD: |-CXXRecordDecl {{.*}} <./header.h:2:1, line:4:1> line:2:7 in M. hidden class A definition
+// CHECK-MOD: | |-CXXRecordDecl {{.*}}  col:7 in M. hidden implicit class A
+// CHECK-MOD-NEXT: | `-CXXMethodDecl {{.*}}  col:8 in M. hidden a 'void ()' implicit-inline
+
+// CHECK-MOD: `-CXXRecordDecl {{.*}}  line:6:7 in M hidden class Z{{( ReachableWhenImported)?}} definition
+// CHECK-MOD: |-CXXRecordDecl {{.*}}  col:7 in M hidden implicit class Z{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-CXXMethodDecl {{.*}}  col:8 in M hidden z 'void ()'{{( ReachableWhenImported)?}}
Index: clang/test/CXX/class/class.friend/p7-cxx20.cpp
===
--- /dev/null
+++ clang/test/CXX/class/class.friend/p7-cxx20.cpp
@@ -0,0 +1,59 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 no-modules.cpp -fsyntax-only -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-NM %s
+// RUN: %clang_cc1 -std=c++20 -xc++-user-header header-unit.h -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-HU %s
+// RUN: %clang_cc1 -std=c++20 module.cpp -ast-dump | \
+// RUN: FileCheck --match-full-lines --check-prefix=CHECK-MOD %s
+
+//--- no-modules.cpp
+
+class X {
+  friend void x(){};
+};
+
+// CHECK-NM: `-CXXRecordDecl {{.*}}  line:2:7 class X definition
+// CHECK-NM:   |-CXXRecordDecl {{.*}}  col:7 implicit class X
+// CHECK-NM-NEXT: `-FriendDecl {{.*}}  col:15
+// CHECK-NM-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 x 'void ()' implicit-inline
+
+//--- header-unit.h
+
+class Y {
+  friend void y(){};
+};
+
+// CHECK-HU: `-CXXRecordDecl {{.*}} <./header-unit.h:2:1, line:4:1> line:2:7 class Y definition
+// CHECK-HU: |-CXXRecordDecl {{.*}}  col:7 implicit class Y
+// CHECK-HU-NEXT: `-FriendDecl {{.*}}  col:15
+// CHECK-HU-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 y 'void ()' implicit-inline
+
+// A textually-included header
+//--- header.h
+
+class A {
+  friend void a(){};
+};
+
+//--- module.cpp
+module;
+#include "header.h"
+
+export module M;
+
+class Z {
+  friend void z(){};
+};
+// CHECK-MOD: |-CXXRecordDecl {{.*}} <./header.h:2:1, line:4:1> line:2:7 in M. hidden class A definition
+// CHECK-MOD: | |-CXXRecordDecl {{.*}}  col:7 in M. hidden implicit class A
+// CHECK-MOD-NEXT: | `-FriendDecl {{.*}}  col:15 in M.
+// CHECK-MOD-NEXT: |   `-FunctionDecl {{.*}} parent {{.*}}  col:15 in M. hidden a 'void ()' implicit-inline
+
+// CHECK-MOD: `-CXXRecordDecl {{.*}}  line:6:7 in M hidden class Z{{( ReachableWhenImported)?}} definition
+// CHECK-MOD: |-CXXRecordDecl {{.*}}  col:7 in M hidden implicit class Z{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-FriendDecl {{.*}}  col:15 in M{{( ReachableWhenImported)?}}
+// CHECK-MOD-NEXT: `-FunctionDecl {{.*}} parent {{.*}}  col:15 in M hidden z 'void ()'{

[PATCH] D122394: [C++20][Modules] Correct an assert for modules-ts.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a project: All.
iains added a reviewer: urnathan.
iains published this revision for review.
iains added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

somewhat on the trivial side.


When adding the support for modules partitions we added an assert that the
actual status of Global Module Fragments matches the state machine that is
driven by the module; keyword.

That does not apply to the modules-ts case, where there is an implicit GMF.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122394

Files:
  clang/lib/Sema/SemaModule.cpp


Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -173,7 +173,7 @@
   ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment)
 GlobalModuleFragment = ModuleScopes.back().Module;
 
-  assert((!getLangOpts().CPlusPlusModules ||
+  assert((!getLangOpts().CPlusPlusModules || getLangOpts().ModulesTS ||
   SeenGMF == (bool)GlobalModuleFragment) &&
  "mismatched global module state");
 


Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -173,7 +173,7 @@
   ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment)
 GlobalModuleFragment = ModuleScopes.back().Module;
 
-  assert((!getLangOpts().CPlusPlusModules ||
+  assert((!getLangOpts().CPlusPlusModules || getLangOpts().ModulesTS ||
   SeenGMF == (bool)GlobalModuleFragment) &&
  "mismatched global module state");
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D122394: [C++20][Modules] Correct an assert for modules-ts.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D122394#3405338 , @urnathan wrote:

> Is this because of history that ModulesTS option != p1103 modules?  I thought 
> we wanted to make the former become the latter (i.e. ModuleTS is the same as 
> CPlusPlusModules)  This seems to be moving in the wrong direction.

This is because we are not removing the fmodules-ts flag (nor. at this point, 
the code that it changes) - as I understand things.  So I have now to fix (next 
patch) the problem that we currently generate wrong code for static vars and 
lambdas in modules since the linkage is defaulting to the modules-ts "module 
internal" model.

So, unless we shift priorities such that we take a detour to remove the 
modules-ts support, I need to make this change to avoid the assert firing for 
-fmodules-ts (it seems we have limited testing - since nothing fired until I 
tried to make other changes form my patchset).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122394/new/

https://reviews.llvm.org/D122394

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D122413: [C++20][Modules] Limit ModuleInternalLinkage to modules-ts.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a project: All.
iains added reviewers: urnathan, dblaikie, Bigcheese, rsmith, ChuanqiXu.
iains published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

At present, we are generating wrong code for C++20 modules entities which
should have internal linkage.  This is because we are assigning
'ModuleInternalLinkage' unconditionally to such entities.  However this mode
is only applicable to the modules-ts.

This change makes the special linkage mode conditional on fmodules-ts and
adds a unit test to verify that we generate the correct linkage.

Currently, static variables and functions in module purview are emitted into
object files as external. On some platforms, lambdas are emitted as global
weak defintions (on Windows this causes a mangler crash).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122413

Files:
  clang/lib/AST/Decl.cpp
  clang/unittests/AST/DeclTest.cpp


Index: clang/unittests/AST/DeclTest.cpp
===
--- clang/unittests/AST/DeclTest.cpp
+++ clang/unittests/AST/DeclTest.cpp
@@ -194,3 +194,50 @@
   EXPECT_EQ(TemplateF->getLinkageInternal(),
 SpecializedF->getLinkageInternal());
 }
+
+TEST(Decl, ModuleAndInternalLinkage) {
+  llvm::Annotations Code(R"(
+export module M;
+static int a;
+static int f(int x);
+
+int b;
+int g(int x);)");
+
+  auto AST =
+  tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{"-std=c++20"});
+  ASTContext &Ctx = AST->getASTContext();
+
+  const auto *a =
+  selectFirst("a", match(varDecl(hasName("a")).bind("a"), Ctx));
+  const auto *f = selectFirst(
+  "f", match(functionDecl(hasName("f")).bind("f"), Ctx));
+
+  EXPECT_EQ(a->getLinkageInternal(), InternalLinkage);
+  EXPECT_EQ(f->getLinkageInternal(), InternalLinkage);
+
+  const auto *b =
+  selectFirst("b", match(varDecl(hasName("b")).bind("b"), Ctx));
+  const auto *g = selectFirst(
+  "g", match(functionDecl(hasName("g")).bind("g"), Ctx));
+
+  EXPECT_EQ(b->getLinkageInternal(), ModuleLinkage);
+  EXPECT_EQ(g->getLinkageInternal(), ModuleLinkage);
+
+  AST = tooling::buildASTFromCodeWithArgs(
+  Code.code(), /*Args=*/{"-std=c++20", "-fmodules-ts"});
+  ASTContext &CtxTS = AST->getASTContext();
+  a = selectFirst("a", match(varDecl(hasName("a")).bind("a"), CtxTS));
+  f = selectFirst(
+  "f", match(functionDecl(hasName("f")).bind("f"), CtxTS));
+
+  EXPECT_EQ(a->getLinkageInternal(), ModuleInternalLinkage);
+  EXPECT_EQ(f->getLinkageInternal(), ModuleInternalLinkage);
+
+  b = selectFirst("b", match(varDecl(hasName("b")).bind("b"), CtxTS));
+  g = selectFirst(
+  "g", match(functionDecl(hasName("g")).bind("g"), CtxTS));
+
+  EXPECT_EQ(b->getLinkageInternal(), ModuleLinkage);
+  EXPECT_EQ(g->getLinkageInternal(), ModuleLinkage);
+}
Index: clang/lib/AST/Decl.cpp
===
--- clang/lib/AST/Decl.cpp
+++ clang/lib/AST/Decl.cpp
@@ -596,11 +596,12 @@
 }
 
 static LinkageInfo getInternalLinkageFor(const NamedDecl *D) {
-  // Internal linkage declarations within a module interface unit are modeled
-  // as "module-internal linkage", which means that they have internal linkage
-  // formally but can be indirectly accessed from outside the module via inline
-  // functions and templates defined within the module.
-  if (isInModulePurview(D))
+  // (for the modules ts) Internal linkage declarations within a module
+  // interface unit are modeled as "module-internal linkage", which means that
+  // they have internal linkage formally but can be indirectly accessed from
+  // outside the module via inline functions and templates defined within the
+  // module.
+  if (isInModulePurview(D) && D->getASTContext().getLangOpts().ModulesTS)
 return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false);
 
   return LinkageInfo::internal();


Index: clang/unittests/AST/DeclTest.cpp
===
--- clang/unittests/AST/DeclTest.cpp
+++ clang/unittests/AST/DeclTest.cpp
@@ -194,3 +194,50 @@
   EXPECT_EQ(TemplateF->getLinkageInternal(),
 SpecializedF->getLinkageInternal());
 }
+
+TEST(Decl, ModuleAndInternalLinkage) {
+  llvm::Annotations Code(R"(
+export module M;
+static int a;
+static int f(int x);
+
+int b;
+int g(int x);)");
+
+  auto AST =
+  tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{"-std=c++20"});
+  ASTContext &Ctx = AST->getASTContext();
+
+  const auto *a =
+  selectFirst("a", match(varDecl(hasName("a")).bind("a"), Ctx));
+  const auto *f = selectFirst(
+  "f", match(functionDecl(hasName("f")).bind("f"), Ctx));
+
+  EXPECT_EQ(a->getLinkageInternal(), InternalLinkage);
+  EXPECT_EQ(f->getLinkageInternal(), InternalLinkage);
+
+  const auto *b =
+  selectFirst("b", match(varDecl(hasName("b")).bind("b"), Ctx

[PATCH] D122119: [C++20][Modules] Adjust handling of exports of namespaces and using-decls.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D122119#3400267 , @dblaikie wrote:

> SOrry, I don't have much context here - the more informative (module/internal 
> linkage) diagnostic does seem better to me than saying "is not exported", 
> even if it's a bit esoteric for some users. We do have other diagnostics that 
> mention linkage, I'm sure (because it's necessary/useful to describe certain 
> things).
>
> Without much context on this patch: is the diagnostic change a necessary part 
> of the patch? (is the diagnostic new regardless of which wording option is 
> chosen? or is this affecting an existing diagnostic?) - if it's possible to 
> separate the diagnostic change from the rest of the patch that's probably a 
> good thing to do regardless of the choice. If not, yeah, I think going with 
> the more explicit/nuanced diagnostic wording seems better to me at a glance.

The diagnostic change was made so that the test cases introduced by the patch 
could have (diagnostic) wording that reflected the examples in the standard.  
As such, it seemed reasonable to make the change at the same time.  I can split 
it out of course if that still seems better given the clarification.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122119/new/

https://reviews.llvm.org/D122119

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D122119: [C++20][Modules] Adjust handling of exports of namespaces and using-decls.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418038.
iains marked 3 inline comments as done.
iains added a comment.

rebased, addressed review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122119/new/

https://reviews.llvm.org/D122119

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/CXX/module/module.interface/p3.cpp
  clang/test/CXX/module/module.interface/p5.cpp
  clang/test/CXX/module/module.interface/p6.cpp
  clang/test/Modules/cxx20-10-2-ex1.cpp
  clang/test/Modules/cxx20-10-2-ex3.cpp
  clang/test/Modules/cxx20-10-2-ex4.cpp
  clang/test/Modules/cxx20-10-2-ex5.cpp
  clang/test/Modules/cxx20-10-2-ex6.cpp
  clang/test/Modules/cxx20-10-2-ex7.cpp

Index: clang/test/Modules/cxx20-10-2-ex7.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-10-2-ex7.cpp
@@ -0,0 +1,9 @@
+// Based on C++20 10.2 example 6.
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o M.pcm
+
+export module M;
+export namespace N {
+int x; // OK
+static_assert(1 == 1); // expected-error {{static_assert declaration cannot be exported}}
+} // namespace N
Index: clang/test/Modules/cxx20-10-2-ex6.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-10-2-ex6.cpp
@@ -0,0 +1,21 @@
+// Based on C++20 10.2 example 6.
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o M.pcm
+
+export module M;
+
+static int f();  // expected-note {{previous declaration is here}} #1
+ // error: #1 gives internal linkage
+export int f();  // expected-error {{cannot export redeclaration 'f' here since the previous declaration has internal linkage}}
+struct S;// expected-note {{previous declaration is here}} #2
+ // error: #2 gives module linkage
+export struct S; // expected-error {{cannot export redeclaration 'S' here since the previous declaration has module linkage}}
+
+namespace {
+namespace N {
+extern int x; // expected-note {{previous declaration is here}} #3
+}
+} // namespace
+  // error: #3 gives internal linkage
+export int N::x; // expected-error {{cannot export redeclaration 'x' here since the previous declaration has internal linkage}}
+ // expected-error@-1 {{declaration of 'x' with internal linkage cannot be exported}}
Index: clang/test/Modules/cxx20-10-2-ex5.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-10-2-ex5.cpp
@@ -0,0 +1,54 @@
+// Based on C++20 10.2 example 5.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std-10-2-ex5-tu1.cpp \
+// RUN:  -o  %t/M.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu2.cpp \
+// RUN:  -fmodule-file=%t/M.pcm -o  %t/tu-2.o
+
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/std-10-2-ex5-tu3.cpp \
+// RUN:  -fmodule-file=%t/M.pcm -verify -o %t/main.o
+
+//--- std-10-2-ex5-tu1.cpp
+export module M;
+export struct X {
+  static void f();
+  struct Y {};
+};
+namespace {
+struct S {};
+} // namespace
+export void f(S); // OK
+struct T {};
+export T id(T);  // OK
+export struct A; // A exported as incomplete
+
+export auto rootFinder(double a) {
+  return [=](double x) { return (x + a / x) / 2; };
+}
+export const int n = 5; // OK, n has external linkage
+
+//--- std-10-2-ex5-tu2.cpp
+
+module M;
+struct A {
+  int value;
+};
+
+//--- std-10-2-ex5-tu3.cpp
+
+import M;
+
+int main() {
+  X::f(); // OK, X is exported and definition of X is reachable
+  X::Y y; // OK, X::Y is exported as a complete type
+  auto f = rootFinder(2); // OK
+  // error: A is incomplete
+  return A{45}.value; // expected-error {{invalid use of incomplete type 'A'}}
+  // expected-error@-1 {{member access into incomplete type 'A'}}
+  // expected-n...@std-10-2-ex5-tu1.cpp:12 2{{forward declaration of 'A'}}
+}
Index: clang/test/Modules/cxx20-10-2-ex4.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-10-2-ex4.cpp
@@ -0,0 +1,12 @@
+// Based on C++20 10.2 example 4.
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %s -verify -o M.pcm
+
+export module M;
+
+struct S { // expected-note {{previous declaration is here}}
+  int n;
+};
+typedef S S;
+export typedef S S; // OK, does not redeclare an entity
+export struct S;// expected-error {{cannot export redeclaration 'S' here since the previous declaration has module linkage}}
Index: clang/test/Modules/cxx20-10-2-ex3.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-10-2-ex3.cpp
@@ -0,0 +1,9 @@
+// Based on C++20 10.2 example 3.
+
+// RUN: %clan

[PATCH] D122119: [C++20][Modules] Adjust handling of exports of namespaces and using-decls.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains added inline comments.



Comment at: clang/lib/Sema/SemaModule.cpp:814-815
+diagExportedUnnamedDecl(S, UnnamedDeclKind::Namespace, D, BlockStart);
+  else
+; // We allow an empty named namespace decl.
+} else if (DC->getRedeclContext()->isFileContext() && !isa(D))

ChuanqiXu wrote:
> I think we should remove it. So that the above `if` could be further merged.
we can remove the else ; but we cannot merge the !HasName into the if (that 
changes the logic of the expression such that empty & unnamed namespace decls 
get passed to checkExportedDeclContext()) - which emits a diagnostic not 
expected by the standard.

For me, the 'else ;' makes it clear what the alternative is doing (and there's 
a comment as well) - but if the general opinions is to remove it, that's also 
fine.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122119/new/

https://reviews.llvm.org/D122119

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121095: [C++20][Modules][HU 1/5] Introduce header units as a module type.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418041.
iains added a comment.

rebased, renamed helper method.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121095/new/

https://reviews.llvm.org/D121095

Files:
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Basic/Module.h
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/FrontendActions.h
  clang/include/clang/Frontend/FrontendOptions.h
  clang/include/clang/Lex/ModuleMap.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/Decl.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
  clang/lib/Lex/ModuleMap.cpp
  clang/lib/Parse/Parser.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/Modules/cxx20-hu-01.cpp

Index: clang/test/Modules/cxx20-hu-01.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-01.cpp
@@ -0,0 +1,104 @@
+// Test generation and import of simple C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-01.h \
+// RUN:  -o %t/hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info %t/hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-01.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -o %t/B.pcm -Rmodule-import 2>&1  | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-02.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -o %t/C.pcm -Rmodule-import 2>&1  | \
+// RUN: FileCheck --check-prefix=CHECK-GMF-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-02.h \
+// RUN:  -o %t/hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-03.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -fmodule-file=%t/hu-02.pcm -o %t/D.pcm \
+// RUN: -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-BOTH %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-03.h \
+// RUN: -fmodule-file=%t/hu-01.pcm  -o %t/hu-03.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info %t/hu-03.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-04.cpp \
+// RUN:  -fmodule-file=%t/hu-03.pcm -o %t/E.pcm -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-NESTED %s -DTDIR=%t
+
+//--- hu-01.h
+int foo(int);
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit '[[TDIR]]/hu-01.h' is the Primary Module at index #1
+
+//--- imp-hu-01.cpp
+export module B;
+import "hu-01.h";
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-IMP: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// expected-no-diagnostics
+
+//--- imp-hu-02.cpp
+module;
+import "hu-01.h";
+
+export module C;
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-GMF-IMP: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// expected-no-diagnostics
+
+//--- hu-02.h
+int baz(int);
+
+//--- imp-hu-03.cpp
+module;
+export import "hu-01.h";
+
+export module D;
+import "hu-02.h";
+
+int bar(int x) {
+  return foo(x) + baz(x);
+}
+// CHECK-BOTH: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// CHECK-BOTH: remark: importing module '[[TDIR]]/hu-02.h' from '[[TDIR]]/hu-02.pcm'
+// expected-no-diagnostics
+
+//--- hu-03.h
+export import "hu-01.h";
+int baz(int);
+// CHECK-HU-HU:  == C++20 Module structure ==
+// CHECK-HU-HU-NEXT:  Header Unit '[[TDIR]]/hu-03.h' is the Primary Module at index #2
+// CHECK-HU-HU-NEXT:   Exports:
+// CHECK-HU-HU-NEXT:Header Unit '[[TDIR]]/hu-01.h' is at index #1
+
+// expected-no-diagnostics
+
+//--- imp-hu-04.cpp
+module;
+import "hu-03.h";
+
+export module E;
+
+int bar(int x) {
+  return foo(x) + baz(x);
+}
+// CHECK-NESTED: remark: importing module '[[TDIR]]/hu-03.h' from '[[TDIR]]/hu-03.pcm'
+// expected-no-diagnostics
Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -97,6 +97,38 @@
   return nullptr;
 }
 
+void Sema::HandleStartOfHeaderUnit() {
+  assert(getLangOpts().CPlusPlusModules &&
+ "Header units are only valid for C++20 modules");
+  SourceLocation StartOfTU =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+
+  StringRef HUName = getLangOpts().CurrentModule;
+  if (HUName.empty()) {
+HUName = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())->getName();
+const_cast(getLangOpts()).CurrentModule = HUName.str();
+  }
+
+  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
+  // TODO: Make the C++

[PATCH] D121096: [C++20][Modules][HU 2/5] Support searching Header Units in user or system search paths.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418079.
iains added a comment.

rebased, added a testcase for multiple inputs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121096/new/

https://reviews.llvm.org/D121096

Files:
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Frontend/FrontendOptions.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/FrontendAction.cpp
  clang/test/Modules/cxx20-hu-02.cpp
  clang/test/Modules/cxx20-hu-03.cpp
  clang/test/Modules/cxx20-hu-bad-input.cpp

Index: clang/test/Modules/cxx20-hu-bad-input.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-bad-input.cpp
@@ -0,0 +1,19 @@
+// Test generation and import of simple C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: not %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN:  -xc++-header-unit-header hu-01.hh \
+// RUN:  -xc++-header-unit-header hu-02.hh \
+// RUN:  -o hu-01.pcm -verify  2>&1 | FileCheck %s
+
+// CHECK: (frontend): multiple inputs are not valid for header units (first extra 'hu-02.hh')
+
+//--- hu-01.hh
+int foo(int);
+
+//--- hu-02.hh
+int bar(int);
Index: clang/test/Modules/cxx20-hu-03.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-03.cpp
@@ -0,0 +1,57 @@
+// Test check that processing headers as C++20 units allows #pragma once.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-01.h \
+// RUN: -Werror -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -fmodule-file=%t/hu-01.pcm -o hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-01.cpp \
+// RUN: -fmodule-file=%t/hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-02.cpp \
+// RUN: -fmodule-file=%t/hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-03.cpp \
+// RUN: -fmodule-file=%t/hu-02.pcm
+
+//--- hu-01.h
+#pragma once
+struct HU {
+  int a;
+};
+// expected-no-diagnostics
+
+//--- hu-02.h
+export import "hu-01.h";
+// expected-no-diagnostics
+
+//--- imports-01.cpp
+import "hu-01.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
+
+//--- imports-02.cpp
+import "hu-02.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
+
+//--- imports-03.cpp
+import "hu-01.h";
+import "hu-02.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
Index: clang/test/Modules/cxx20-hu-02.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-02.cpp
@@ -0,0 +1,77 @@
+// Test generation and import of user and system C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// check user path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -I user \
+// RUN: -xc++-user-header hu-01.h -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface imp-hu-01.cpp \
+// RUN:  -I user -fmodule-file=hu-01.pcm -o B.pcm -Rmodule-import \
+// RUN: 2>&1  | FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// check system path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -isystem system \
+// RUN: -xc++-system-header hu-02.h -o hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-02.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU2 %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface imp-hu-02.cpp \
+// RUN:  -isystem system -fmodule-file=hu-02.pcm -o C.pcm \
+// RUN: -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-SYS-IMP %s -DTDIR=%t
+
+// check absolute path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit  \
+// RUN: -xc++-header-unit-header %t/hu-03.h -o hu-03.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-03.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU3 %s -DTDIR=%t
+
+//--- user/hu-01.h
+int foo(int);
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit 'user{{[/\\]}}hu-01.h' is the Primary Module at index #1
+
+//--- imp-hu-01.cpp
+export module B;
+import "hu-01.h";
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-IMP: remark: importing module 'user{{[/\\]}}hu-01.h' from 'hu-01.pcm'
+// expected-no-diagnostics
+
+//--- system/hu-02.h
+int baz(int);
+
+// CHECK-HU2:  == C++20 Module structure ==
+// CHECK-HU2-NEXT:  Header Unit 'system{{[/\\]}}hu-02.h' is the Primary Module at index #1
+
+//--- imp-hu-02.cpp
+module;
+import ;
+
+export module C;
+
+int bar(int x) {
+  return baz(x);
+}
+// CHECK-SYS-IMP: remark: importing module 'system{{[/\\]}}hu-02.h' from 'hu-02.pcm'
+// expected-no-diagnostics
+
+//--- hu-03.h
+int c

[PATCH] D121097: [C++20][Modules][HU 3/5] Emit module macros for header units.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418081.
iains added a comment.

rebased


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121097/new/

https://reviews.llvm.org/D121097

Files:
  clang/include/clang/Basic/Module.h
  clang/include/clang/Serialization/ASTWriter.h
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/Modules/cxx20-hu-04.cpp

Index: clang/test/Modules/cxx20-hu-04.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-04.cpp
@@ -0,0 +1,105 @@
+// Test macro preservation in C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-01.h \
+// RUN: -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -DFOO -fmodule-file=hu-01.pcm -o hu-02.pcm  -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-02.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU2 %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface importer-01.cpp \
+// RUN:  -fmodule-file=hu-02.pcm -o B.pcm -DTDIR=%t -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface importer-02.cpp \
+// RUN:  -fmodule-file=hu-02.pcm -o C.pcm -DTDIR=%t -Rmodule-import 2>&1 | \
+// RUN:  FileCheck --check-prefix=CHECK-IMP-HU2 %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+// expected-no-diagnostics
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit './hu-01.h' is the Primary Module at index #1
+
+//--- hu-02.h
+export import "hu-01.h";
+#if !defined(FORTYTWO) || FORTYTWO != 42
+#error FORTYTWO missing in hu-02
+#endif
+
+#ifndef __GUARD
+#error __GUARD missing in hu-02
+#endif
+
+#ifdef SHOULD_NOT_BE_DEFINED
+#error SHOULD_NOT_BE_DEFINED is visible
+#endif
+
+#define KAP 6174
+
+#ifdef FOO
+#define FOO_BRANCH(X) (X) + 1
+inline int foo(int x) {
+  if (x == FORTYTWO)
+return FOO_BRANCH(x);
+  return FORTYTWO;
+}
+#else
+#define BAR_BRANCH(X) (X) + 2
+inline int bar(int x) {
+  if (x == FORTYTWO)
+return BAR_BRANCH(x);
+  return FORTYTWO;
+}
+#endif
+
+// CHECK-IMP: remark: importing module './hu-01.h' from 'hu-01.pcm'
+// CHECK-HU2:  == C++20 Module structure ==
+// CHECK-HU2-NEXT:  Header Unit './hu-02.h' is the Primary Module at index #2
+// CHECK-HU2-NEXT:   Exports:
+// CHECK-HU2-NEXT:Header Unit './hu-01.h' is at index #1
+// expected-no-diagnostics
+
+//--- importer-01.cpp
+export module B;
+import "hu-02.h";
+
+int success(int x) {
+  return foo(FORTYTWO + x + KAP);
+}
+
+int fail(int x) {
+  return bar(FORTYTWO + x + KAP); // expected-error {{use of undeclared identifier 'bar'}}
+  // expected-note@* {{'baz' declared here}}
+}
+
+//--- importer-02.cpp
+export module C;
+import "hu-02.h";
+
+int success(int x) {
+  return foo(FORTYTWO + x + KAP);
+}
+
+// CHECK-IMP-HU2: remark: importing module './hu-02.h' from 'hu-02.pcm'
+// CHECK-IMP-HU2: remark: importing module './hu-01.h' into './hu-02.h' from '[[TDIR]]{{[/\\]}}hu-01.pcm'
Index: clang/lib/Serialization/ASTWriter.cpp
===
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -2352,13 +2352,22 @@
 uint64_t StartOffset = Stream.GetCurrentBitNo() - MacroOffsetsBase;
 assert((StartOffset >> 32) == 0 && "Macro identifiers offset too large");
 
-// Emit the macro directives in reverse source order.
-for (; MD; MD = MD->getPrevious()) {
-  // Once we hit an ignored macro, we're done: the rest of the chain
-  // will all be ignored macros.
-  if (shouldIgnoreMacro(MD, IsModule, PP))
-break;
-
+// Write out any exported module macros.
+bool EmittedModuleMacros = false;
+// C+=20 Header Units are compiled module interfaces, but they preserve
+// macros that are live (i.e. have a defined value) at the end of the
+// compilation.  So when writing a header unit, we preserve only the final
+// value of each macro (and discard any that are undefined).  Header units
+// do not have sub-modules (although they might import other header units).
+// PCH files, conversely, retain the history of each macro's define/undef
+// and of leaf macros in sub modules.
+if (IsModule && WritingModule->isHeaderUnit()) {
+  // This is for the main TU when it is a C++20 header unit.
+  // We preserve the final state of defined macros, and we do not emit ones
+  // that are undefined.
+  if (!MD || shouldIgnoreMacro(MD, IsModule, PP) ||
+  MD->getKind

[PATCH] D121098: [C++20][Modules][HU 4/5] Handle pre-processed header units.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418082.
iains added a comment.

rebased


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121098/new/

https://reviews.llvm.org/D121098

Files:
  clang/lib/Frontend/FrontendAction.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/Modules/cxx20-hu-05.cpp


Index: clang/test/Modules/cxx20-hu-05.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-05.cpp
@@ -0,0 +1,32 @@
+// Test macro preservation in C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// Produce a pre-processed file.
+// RUN: %clang_cc1 -std=c++20 -E -xc++-user-header hu-01.h -o hu-01.iih
+
+// consume that to produce the heder unit.
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN: -xc++-header-unit-header-cpp-output hu-01.iih -o hu-01.pcm
+
+// check that the header unit is named for the original file, not the .iih.
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit './hu-01.h' is the Primary Module at index #1
Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -109,10 +109,18 @@
 const_cast(getLangOpts()).CurrentModule = HUName.str();
   }
 
-  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   // TODO: Make the C++20 header lookup independent.
-  Module::Header H{getLangOpts().CurrentModule, getLangOpts().CurrentModule,
-   SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())};
+  // When the input is pre-processed source, we need a file ref to the original
+  // file for the header map.
+  auto F = SourceMgr.getFileManager().getFile(HUName);
+  // For the sake of error recovery (if someone has moved the original header
+  // after creating the pre-processed output) fall back to obtaining the file
+  // ref for the input file, which must be present.
+  if (!F)
+F = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+  assert(F && "failed to find the header unit source?");
+  Module::Header H{HUName.str(), HUName.str(), *F};
+  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);
   assert(Mod && "module creation should not fail");
   ModuleScopes.push_back({}); // No GMF
Index: clang/lib/Frontend/FrontendAction.cpp
===
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -843,6 +843,21 @@
   if (!CI.InitializeSourceManager(Input))
 return false;
 
+  if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&
+  Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) {
+// We have an input filename like foo.iih, but we want to find the right
+// module name (and original file, to build the map entry).
+// Check if the first line specifies the original source file name with a
+// linemarker.
+std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());
+ReadOriginalFileName(CI, PresumedInputFile);
+// Unless the user overrides this, the module name is the name by which the
+// original file was known.
+if (CI.getLangOpts().ModuleName.empty())
+  CI.getLangOpts().ModuleName = std::string(PresumedInputFile);
+CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;
+  }
+
   // For module map files, we first parse the module map and synthesize a
   // "" buffer before more conventional processing.
   if (Input.getKind().getFormat() == InputKind::ModuleMap) {


Index: clang/test/Modules/cxx20-hu-05.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-05.cpp
@@ -0,0 +1,32 @@
+// Test macro preservation in C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// Produce a pre-processed file.
+// RUN: %clang_cc1 -std=c++20 -E -xc++-user-header hu-01.h -o hu-01.iih
+
+// consume that to produce the heder unit.
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN: -xc++-header-unit-header-cpp-output hu-01.iih -o hu-01.pcm
+
+// check that the header unit is named for the original file, not the .iih.
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+
+//

[PATCH] D121099: [C++20][Modules][HU 5/5] Add fdirectives-only mode for preprocessing output.

2022-03-24 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418083.
iains added a comment.

rebased


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121099/new/

https://reviews.llvm.org/D121099

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/PreprocessorOutputOptions.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/test/Modules/cxx20-hu-06.cpp

Index: clang/test/Modules/cxx20-hu-06.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-06.cpp
@@ -0,0 +1,68 @@
+// Test check that consuming -E -fdirectives-only output produces the expected
+// header unit.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -E -fdirectives-only -xc++-user-header hu-01.h \
+// RUN: -o hu-01.iih
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN: -xc++-user-header-cpp-output hu-01.iih -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -DFOO -fmodule-file=hu-01.pcm -o hu-02.pcm -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+// expected-no-diagnostics
+
+//--- hu-02.h
+export import "hu-01.h";
+#if !defined(FORTYTWO) || FORTYTWO != 42
+#error FORTYTWO missing in hu-02
+#endif
+
+#ifndef __GUARD
+#error __GUARD missing in hu-02
+#endif
+
+#ifdef SHOULD_NOT_BE_DEFINED
+#error SHOULD_NOT_BE_DEFINED is visible
+#endif
+
+// Make sure that we have not discarded macros from the builtin file.
+#ifndef __cplusplus
+#error we dropped a defined macro
+#endif
+
+#define KAP 6174
+
+#ifdef FOO
+#define FOO_BRANCH(X) (X) + 1
+inline int foo(int x) {
+  if (x == FORTYTWO)
+return FOO_BRANCH(x);
+  return FORTYTWO;
+}
+#else
+#define BAR_BRANCH(X) (X) + 2
+inline int bar(int x) {
+  if (x == FORTYTWO)
+return BAR_BRANCH(x);
+  return FORTYTWO;
+}
+#endif
+// CHECK-IMP: remark: importing module './hu-01.h' from 'hu-01.pcm'
Index: clang/lib/Frontend/PrintPreprocessedOutput.cpp
===
--- clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -96,6 +96,7 @@
   bool UseLineDirectives;
   bool IsFirstFileEntered;
   bool MinimizeWhitespace;
+  bool DirectivesOnly;
 
   Token PrevTok;
   Token PrevPrevTok;
@@ -103,12 +104,13 @@
 public:
   PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers,
bool defines, bool DumpIncludeDirectives,
-   bool UseLineDirectives, bool MinimizeWhitespace)
+   bool UseLineDirectives, bool MinimizeWhitespace,
+   bool DirectivesOnly)
   : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
 DisableLineMarkers(lineMarkers), DumpDefines(defines),
 DumpIncludeDirectives(DumpIncludeDirectives),
 UseLineDirectives(UseLineDirectives),
-MinimizeWhitespace(MinimizeWhitespace) {
+MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly) {
 CurLine = 0;
 CurFilename += "";
 EmittedTokensOnThisLine = false;
@@ -467,12 +469,21 @@
 void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
 const MacroDirective *MD) {
   const MacroInfo *MI = MD->getMacroInfo();
-  // Only print out macro definitions in -dD mode.
-  if (!DumpDefines ||
+  // Print out macro definitions in -dD mode and when we have -fdirectives-only
+  // for C++20 header units.
+  if ((!DumpDefines && !DirectivesOnly) ||
   // Ignore __FILE__ etc.
-  MI->isBuiltinMacro()) return;
+  MI->isBuiltinMacro())
+return;
 
-  MoveToLine(MI->getDefinitionLoc(), /*RequireStartOfLine=*/true);
+  SourceLocation DefLoc = MI->getDefinitionLoc();
+  if (DirectivesOnly && !MI->isUsed()) {
+SourceManager &SM = PP.getSourceManager();
+if (SM.isWrittenInBuiltinFile(DefLoc) ||
+SM.isWrittenInCommandLineFile(DefLoc))
+  return;
+  }
+  MoveToLine(DefLoc, /*RequireStartOfLine=*/true);
   PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS);
   setEmittedDirectiveOnThisLine();
 }
@@ -480,8 +491,10 @@
 void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
   const MacroDefinition &MD,
   const MacroDirective *Undef) {
-  // Only print out macro definitions in -dD mode.
-  if (!DumpDefines) return;
+  // Print out macro definitions in -dD mode and when we have -fdirectives-only
+  // for C++20 header units.
+  if (!DumpDefines && !DirectivesOnly)
+return;
 
   MoveToLine

[PATCH] D121095: [C++20][Modules][HU 1/5] Introduce header units as a module type.

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG6c0e60e884a2: [C++20][Modules][HU 1/5] Introduce header 
units as a module type. (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121095/new/

https://reviews.llvm.org/D121095

Files:
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Basic/Module.h
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/FrontendActions.h
  clang/include/clang/Frontend/FrontendOptions.h
  clang/include/clang/Lex/ModuleMap.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/Decl.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
  clang/lib/Lex/ModuleMap.cpp
  clang/lib/Parse/Parser.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/Modules/cxx20-hu-01.cpp

Index: clang/test/Modules/cxx20-hu-01.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-01.cpp
@@ -0,0 +1,104 @@
+// Test generation and import of simple C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-01.h \
+// RUN:  -o %t/hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info %t/hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-01.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -o %t/B.pcm -Rmodule-import 2>&1  | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-02.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -o %t/C.pcm -Rmodule-import 2>&1  | \
+// RUN: FileCheck --check-prefix=CHECK-GMF-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-02.h \
+// RUN:  -o %t/hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-03.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -fmodule-file=%t/hu-02.pcm -o %t/D.pcm \
+// RUN: -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-BOTH %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-03.h \
+// RUN: -fmodule-file=%t/hu-01.pcm  -o %t/hu-03.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info %t/hu-03.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-04.cpp \
+// RUN:  -fmodule-file=%t/hu-03.pcm -o %t/E.pcm -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-NESTED %s -DTDIR=%t
+
+//--- hu-01.h
+int foo(int);
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit '[[TDIR]]/hu-01.h' is the Primary Module at index #1
+
+//--- imp-hu-01.cpp
+export module B;
+import "hu-01.h";
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-IMP: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// expected-no-diagnostics
+
+//--- imp-hu-02.cpp
+module;
+import "hu-01.h";
+
+export module C;
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-GMF-IMP: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// expected-no-diagnostics
+
+//--- hu-02.h
+int baz(int);
+
+//--- imp-hu-03.cpp
+module;
+export import "hu-01.h";
+
+export module D;
+import "hu-02.h";
+
+int bar(int x) {
+  return foo(x) + baz(x);
+}
+// CHECK-BOTH: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// CHECK-BOTH: remark: importing module '[[TDIR]]/hu-02.h' from '[[TDIR]]/hu-02.pcm'
+// expected-no-diagnostics
+
+//--- hu-03.h
+export import "hu-01.h";
+int baz(int);
+// CHECK-HU-HU:  == C++20 Module structure ==
+// CHECK-HU-HU-NEXT:  Header Unit '[[TDIR]]/hu-03.h' is the Primary Module at index #2
+// CHECK-HU-HU-NEXT:   Exports:
+// CHECK-HU-HU-NEXT:Header Unit '[[TDIR]]/hu-01.h' is at index #1
+
+// expected-no-diagnostics
+
+//--- imp-hu-04.cpp
+module;
+import "hu-03.h";
+
+export module E;
+
+int bar(int x) {
+  return foo(x) + baz(x);
+}
+// CHECK-NESTED: remark: importing module '[[TDIR]]/hu-03.h' from '[[TDIR]]/hu-03.pcm'
+// expected-no-diagnostics
Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -97,6 +97,38 @@
   return nullptr;
 }
 
+void Sema::HandleStartOfHeaderUnit() {
+  assert(getLangOpts().CPlusPlusModules &&
+ "Header units are only valid for C++20 modules");
+  SourceLocation StartOfTU =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+
+  StringRef HUName = getLangOpts().CurrentModule;
+  if (HUName.empty()) {
+HUName = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())->getName();
+const_cast(getLangOpts()).CurrentModule = HUName.

[PATCH] D121589: [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418171.
iains added a comment.
Herald added a subscriber: MaskRay.

rebased, fix testcase for windows, add command line options to docs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121589/new/

https://reviews.llvm.org/D121589

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-02.cpp

Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -0,0 +1,32 @@
+// Test user-facing command line options to generate C++20 header units.
+
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-system-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header %S/Inputs/header-unit-01.hh \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-ABS %s -DTDIR=%S/Inputs
+
+// CHECK-USER: "-emit-header-unit"
+// CHECK-USER-SAME: "-o" "foo.pcm"
+// CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
+
+// CHECK-SYS1: "-emit-header-unit"
+// CHECK-SYS1-SAME: "-o" "foo.pcm"
+// CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
+
+// CHECK-SYS2: "-emit-header-unit"
+// CHECK-SYS2-SAME: "-o" "vector.pcm"
+// CHECK-SYS2-SAME: "-x" "c++-system-header" "vector"
+
+// CHECK-ABS: "-emit-header-unit"
+// CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
+// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -189,7 +189,9 @@
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr VFS)
 : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
-  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
+  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
+  CXX20HeaderType(HeaderMode_None), ModulesModeCXX20(false),
+  LTOMode(LTOK_None),
   ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
   DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
   CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
@@ -335,8 +337,12 @@
 FinalPhase = phases::Preprocess;
 
   // --precompile only runs up to precompilation.
+  // Options that cause the output of C++20 compiled module interfaces or
+  // header units have the same effect.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
+options::OPT_fmodule_header_EQ))) {
 FinalPhase = phases::Precompile;
 // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
@@ -1246,6 +1252,37 @@
   BitcodeEmbed = static_cast(Model);
   }
 
+  // Setting up the jobs for some precompile cases depends on whether we are
+  // treating them as PCH, implicit modules or C++20 ones.
+  // TODO: inferring the mode like this seems fragile (it meets the objective
+  // of not requiring anything new for operation, however).
+  const Arg *Std = Args.getLastArg(options::OPT_std_EQ);
+  ModulesModeCXX20 =
+  !Args.hasArg(options::OPT_fmodules) && Std &&
+  (Std->containsValue("c++20") || Std->containsValue("c++2b") ||
+   Std->containsValue("c++2a") || Std->containsValue("c++latest"));
+
+  // Process -fmodule-header{=} flags.
+  if (Arg *A = Args.getLastArg(options::OPT_fmodule_header_EQ,
+   options::OPT_fmodule_header)) {
+// These flags force C++20 handling of headers.
+ModulesModeCXX20 = true;
+if (A->getOption().matches(options::OPT_fmodule_header))
+  CXX20HeaderType = HeaderMode_Default;
+else {
+  StringRef ArgName = A->getValue();
+  unsigned Kind = llvm::StringSwitch(ArgName)
+  .Case("user", HeaderMode_User)
+  .Case("system", HeaderMode_System)
+  .Default(~0U);
+  if (Kind == ~0U) {
+Diags.Report(diag::err_drv_invalid_value)
+<< A->getAsString(Args) << ArgName;
+  } else
+CXX20HeaderType = static

[PATCH] D121589: [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418172.
iains added a comment.

fix some formatting.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121589/new/

https://reviews.llvm.org/D121589

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-02.cpp

Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -0,0 +1,32 @@
+// Test user-facing command line options to generate C++20 header units.
+
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-system-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header %S/Inputs/header-unit-01.hh \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-ABS %s -DTDIR=%S/Inputs
+
+// CHECK-USER: "-emit-header-unit"
+// CHECK-USER-SAME: "-o" "foo.pcm"
+// CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
+
+// CHECK-SYS1: "-emit-header-unit"
+// CHECK-SYS1-SAME: "-o" "foo.pcm"
+// CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
+
+// CHECK-SYS2: "-emit-header-unit"
+// CHECK-SYS2-SAME: "-o" "vector.pcm"
+// CHECK-SYS2-SAME: "-x" "c++-system-header" "vector"
+
+// CHECK-ABS: "-emit-header-unit"
+// CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
+// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -189,13 +189,14 @@
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr VFS)
 : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
-  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
-  ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
-  DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
-  CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
-  CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc),
-  CheckInputsExist(true), GenReproducer(false),
-  SuppressMissingInputWarning(false) {
+  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
+  CXX20HeaderType(HeaderMode_None), ModulesModeCXX20(false),
+  LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
+  SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false),
+  CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+  CCGenDiagnostics(false), CCPrintProcessStats(false),
+  TargetTriple(TargetTriple), Saver(Alloc), CheckInputsExist(true),
+  GenReproducer(false), SuppressMissingInputWarning(false) {
   // Provide a sane fallback if no VFS is specified.
   if (!this->VFS)
 this->VFS = llvm::vfs::getRealFileSystem();
@@ -334,9 +335,13 @@
   CCGenDiagnostics) {
 FinalPhase = phases::Preprocess;
 
-  // --precompile only runs up to precompilation.
+// --precompile only runs up to precompilation.
+// Options that cause the output of C++20 compiled module interfaces or
+// header units have the same effect.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
+options::OPT_fmodule_header_EQ))) {
 FinalPhase = phases::Precompile;
 // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
@@ -1246,6 +1251,37 @@
   BitcodeEmbed = static_cast(Model);
   }
 
+  // Setting up the jobs for some precompile cases depends on whether we are
+  // treating them as PCH, implicit modules or C++20 ones.
+  // TODO: inferring the mode like this seems fragile (it meets the objective
+  // of not requiring anything new for operation, however).
+  const Arg *Std = Args.getLastArg(options::OPT_std_EQ);
+  ModulesModeCXX20 =
+  !Args.hasArg(options::OPT_fmodules) && Std &&
+  (Std->containsValue("c++20") || Std->containsValue("c++2b") ||
+   Std->containsValue("c++2a") || Std->containsValue("c++latest"));
+
+  // Process -fmodule-header{=} flags.
+  if (Arg *A = Args.getLastArg(options::OPT_fmodule_header_EQ,
+  

[PATCH] D121589: [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418187.
iains added a comment.

amend filecheck match to avoid quoting windows pathnames.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121589/new/

https://reviews.llvm.org/D121589

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-01.cpp
  clang/test/Driver/cxx20-header-units-02.cpp

Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -0,0 +1,32 @@
+// Test user-facing command line options to generate C++20 header units.
+
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-system-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header %S/Inputs/header-unit-01.hh \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-ABS %s -DTDIR=%S/Inputs
+
+// CHECK-USER: "-emit-header-unit"
+// CHECK-USER-SAME: "-o" "foo.pcm"
+// CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
+
+// CHECK-SYS1: "-emit-header-unit"
+// CHECK-SYS1-SAME: "-o" "foo.pcm"
+// CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
+
+// CHECK-SYS2: "-emit-header-unit"
+// CHECK-SYS2-SAME: "-o" "vector.pcm"
+// CHECK-SYS2-SAME: "-x" "c++-system-header" "vector"
+
+// CHECK-ABS: "-emit-header-unit"
+// CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
+// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
Index: clang/test/Driver/cxx20-header-units-01.cpp
===
--- clang/test/Driver/cxx20-header-units-01.cpp
+++ clang/test/Driver/cxx20-header-units-01.cpp
@@ -16,4 +16,4 @@
 // CHECK-SYSTEM-SAME: "-x" "c++-system-header" "vector"
 // CHECK-ABS: "-emit-header-unit"
 // CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
-// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
+// CHECK-ABS-SAME: -x c++-header-unit-header [[TDIR]]/header-unit-01.hh
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -189,13 +189,14 @@
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr VFS)
 : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
-  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
-  ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
-  DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
-  CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
-  CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc),
-  CheckInputsExist(true), GenReproducer(false),
-  SuppressMissingInputWarning(false) {
+  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
+  CXX20HeaderType(HeaderMode_None), ModulesModeCXX20(false),
+  LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
+  SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false),
+  CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+  CCGenDiagnostics(false), CCPrintProcessStats(false),
+  TargetTriple(TargetTriple), Saver(Alloc), CheckInputsExist(true),
+  GenReproducer(false), SuppressMissingInputWarning(false) {
   // Provide a sane fallback if no VFS is specified.
   if (!this->VFS)
 this->VFS = llvm::vfs::getRealFileSystem();
@@ -334,9 +335,13 @@
   CCGenDiagnostics) {
 FinalPhase = phases::Preprocess;
 
-  // --precompile only runs up to precompilation.
+// --precompile only runs up to precompilation.
+// Options that cause the output of C++20 compiled module interfaces or
+// header units have the same effect.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
+options::OPT_fmodule_header_EQ))) {
 FinalPhase = phases::Precompile;
 // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
@@ -1246,6 +1251,37 @@
   BitcodeEmbed = static_cast(Model);
   }
 
+  // Setting up the jobs for some precompile cases depends o

[PATCH] D121589: [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418188.
iains added a comment.

amend second testcase for windows


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121589/new/

https://reviews.llvm.org/D121589

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-01.cpp
  clang/test/Driver/cxx20-header-units-02.cpp

Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -0,0 +1,32 @@
+// Test user-facing command line options to generate C++20 header units.
+
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-system-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header %S/Inputs/header-unit-01.hh \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-ABS %s -DTDIR=%S/Inputs
+
+// CHECK-USER: "-emit-header-unit"
+// CHECK-USER-SAME: "-o" "foo.pcm"
+// CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
+
+// CHECK-SYS1: "-emit-header-unit"
+// CHECK-SYS1-SAME: "-o" "foo.pcm"
+// CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
+
+// CHECK-SYS2: "-emit-header-unit"
+// CHECK-SYS2-SAME: "-o" "vector.pcm"
+// CHECK-SYS2-SAME: "-x" "c++-system-header" "vector"
+
+// CHECK-ABS: "-emit-header-unit"
+// CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
+// CHECK-ABS-SAME: -x c++-header-unit-header [[TDIR]]/header-unit-01.hh
Index: clang/test/Driver/cxx20-header-units-01.cpp
===
--- clang/test/Driver/cxx20-header-units-01.cpp
+++ clang/test/Driver/cxx20-header-units-01.cpp
@@ -16,4 +16,4 @@
 // CHECK-SYSTEM-SAME: "-x" "c++-system-header" "vector"
 // CHECK-ABS: "-emit-header-unit"
 // CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
-// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
+// CHECK-ABS-SAME: -x c++-header-unit-header [[TDIR]]/header-unit-01.hh
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -189,13 +189,14 @@
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr VFS)
 : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
-  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
-  ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
-  DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
-  CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
-  CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc),
-  CheckInputsExist(true), GenReproducer(false),
-  SuppressMissingInputWarning(false) {
+  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
+  CXX20HeaderType(HeaderMode_None), ModulesModeCXX20(false),
+  LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
+  SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false),
+  CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+  CCGenDiagnostics(false), CCPrintProcessStats(false),
+  TargetTriple(TargetTriple), Saver(Alloc), CheckInputsExist(true),
+  GenReproducer(false), SuppressMissingInputWarning(false) {
   // Provide a sane fallback if no VFS is specified.
   if (!this->VFS)
 this->VFS = llvm::vfs::getRealFileSystem();
@@ -334,9 +335,13 @@
   CCGenDiagnostics) {
 FinalPhase = phases::Preprocess;
 
-  // --precompile only runs up to precompilation.
+// --precompile only runs up to precompilation.
+// Options that cause the output of C++20 compiled module interfaces or
+// header units have the same effect.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
+options::OPT_fmodule_header_EQ))) {
 FinalPhase = phases::Precompile;
 // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
@@ -1246,6 +1251,37 @@
   BitcodeEmbed = static_cast(Model);
   }
 
+  // Setting up the jobs for some precompile cases depends on whether we are
+  // treatin

[PATCH] D121589: [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418196.
iains added a comment.

another tweak to the second testcase for windows
*sigh* ... I will get the recipe right eventually.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121589/new/

https://reviews.llvm.org/D121589

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-01.cpp
  clang/test/Driver/cxx20-header-units-02.cpp

Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -0,0 +1,32 @@
+// Test user-facing command line options to generate C++20 header units.
+
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-system-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header %/S/Inputs/header-unit-01.hh \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-ABS %s -DTDIR=%/S/Inputs
+
+// CHECK-USER: "-emit-header-unit"
+// CHECK-USER-SAME: "-o" "foo.pcm"
+// CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
+
+// CHECK-SYS1: "-emit-header-unit"
+// CHECK-SYS1-SAME: "-o" "foo.pcm"
+// CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
+
+// CHECK-SYS2: "-emit-header-unit"
+// CHECK-SYS2-SAME: "-o" "vector.pcm"
+// CHECK-SYS2-SAME: "-x" "c++-system-header" "vector"
+
+// CHECK-ABS: "-emit-header-unit"
+// CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
+// CHECK-ABS-SAME: -x c++-header-unit-header [[TDIR]]/header-unit-01.hh
Index: clang/test/Driver/cxx20-header-units-01.cpp
===
--- clang/test/Driver/cxx20-header-units-01.cpp
+++ clang/test/Driver/cxx20-header-units-01.cpp
@@ -16,4 +16,4 @@
 // CHECK-SYSTEM-SAME: "-x" "c++-system-header" "vector"
 // CHECK-ABS: "-emit-header-unit"
 // CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
-// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
+// CHECK-ABS-SAME: -x c++-header-unit-header [[TDIR]]/header-unit-01.hh
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -189,13 +189,14 @@
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr VFS)
 : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
-  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
-  ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
-  DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
-  CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
-  CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc),
-  CheckInputsExist(true), GenReproducer(false),
-  SuppressMissingInputWarning(false) {
+  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
+  CXX20HeaderType(HeaderMode_None), ModulesModeCXX20(false),
+  LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
+  SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false),
+  CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+  CCGenDiagnostics(false), CCPrintProcessStats(false),
+  TargetTriple(TargetTriple), Saver(Alloc), CheckInputsExist(true),
+  GenReproducer(false), SuppressMissingInputWarning(false) {
   // Provide a sane fallback if no VFS is specified.
   if (!this->VFS)
 this->VFS = llvm::vfs::getRealFileSystem();
@@ -334,9 +335,13 @@
   CCGenDiagnostics) {
 FinalPhase = phases::Preprocess;
 
-  // --precompile only runs up to precompilation.
+// --precompile only runs up to precompilation.
+// Options that cause the output of C++20 compiled module interfaces or
+// header units have the same effect.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
+options::OPT_fmodule_header_EQ))) {
 FinalPhase = phases::Precompile;
 // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
@@ -1246,6 +1251,37 @@
   BitcodeEmbed = static_cast(Model);
   }
 
+  // Setting up the jo

[PATCH] D121589: [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418220.
iains added a comment.

we need the quotes around the components.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121589/new/

https://reviews.llvm.org/D121589

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-02.cpp

Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -0,0 +1,32 @@
+// Test user-facing command line options to generate C++20 header units.
+
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-system-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang -### -std=c++20 -fmodule-header %/S/Inputs/header-unit-01.hh \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-ABS %s -DTDIR=%/S/Inputs
+
+// CHECK-USER: "-emit-header-unit"
+// CHECK-USER-SAME: "-o" "foo.pcm"
+// CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
+
+// CHECK-SYS1: "-emit-header-unit"
+// CHECK-SYS1-SAME: "-o" "foo.pcm"
+// CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
+
+// CHECK-SYS2: "-emit-header-unit"
+// CHECK-SYS2-SAME: "-o" "vector.pcm"
+// CHECK-SYS2-SAME: "-x" "c++-system-header" "vector"
+
+// CHECK-ABS: "-emit-header-unit"
+// CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
+// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -189,13 +189,14 @@
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr VFS)
 : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
-  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
-  ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
-  DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
-  CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
-  CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc),
-  CheckInputsExist(true), GenReproducer(false),
-  SuppressMissingInputWarning(false) {
+  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
+  CXX20HeaderType(HeaderMode_None), ModulesModeCXX20(false),
+  LTOMode(LTOK_None), ClangExecutable(ClangExecutable),
+  SysRoot(DEFAULT_SYSROOT), DriverTitle(Title), CCCPrintBindings(false),
+  CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false),
+  CCGenDiagnostics(false), CCPrintProcessStats(false),
+  TargetTriple(TargetTriple), Saver(Alloc), CheckInputsExist(true),
+  GenReproducer(false), SuppressMissingInputWarning(false) {
   // Provide a sane fallback if no VFS is specified.
   if (!this->VFS)
 this->VFS = llvm::vfs::getRealFileSystem();
@@ -334,9 +335,13 @@
   CCGenDiagnostics) {
 FinalPhase = phases::Preprocess;
 
-  // --precompile only runs up to precompilation.
+// --precompile only runs up to precompilation.
+// Options that cause the output of C++20 compiled module interfaces or
+// header units have the same effect.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT__precompile)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_extract_api))) {
+ (PhaseArg = DAL.getLastArg(options::OPT_extract_api)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_fmodule_header,
+options::OPT_fmodule_header_EQ))) {
 FinalPhase = phases::Precompile;
 // -{fsyntax-only,-analyze,emit-ast} only run up to the compiler.
   } else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
@@ -1246,6 +1251,37 @@
   BitcodeEmbed = static_cast(Model);
   }
 
+  // Setting up the jobs for some precompile cases depends on whether we are
+  // treating them as PCH, implicit modules or C++20 ones.
+  // TODO: inferring the mode like this seems fragile (it meets the objective
+  // of not requiring anything new for operation, however).
+  const Arg *Std = Args.getLastArg(options::OPT_std_EQ);
+  ModulesModeCXX20 =
+  !Args.hasArg(options::OPT_fmodules) && Std &&
+  (Std->containsValue("c++20") || Std->containsValue("c++2b") ||
+   Std->containsValue("c++2a") || Std->containsValue("c++latest"));
+
+  // Process -fmodule-header{=} flags.
+  if (Arg *A = Args.getLastArg(options::OPT_fmo

[PATCH] D122394: [C++20][Modules] Correct an assert for modules-ts.

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGcf396c56e7df: [C++20][Modules] Correct an assert for 
modules-ts. (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122394/new/

https://reviews.llvm.org/D122394

Files:
  clang/lib/Sema/SemaModule.cpp


Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -206,7 +206,7 @@
   ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment)
 GlobalModuleFragment = ModuleScopes.back().Module;
 
-  assert((!getLangOpts().CPlusPlusModules ||
+  assert((!getLangOpts().CPlusPlusModules || getLangOpts().ModulesTS ||
   SeenGMF == (bool)GlobalModuleFragment) &&
  "mismatched global module state");
 


Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -206,7 +206,7 @@
   ModuleScopes.back().Module->Kind == Module::GlobalModuleFragment)
 GlobalModuleFragment = ModuleScopes.back().Module;
 
-  assert((!getLangOpts().CPlusPlusModules ||
+  assert((!getLangOpts().CPlusPlusModules || getLangOpts().ModulesTS ||
   SeenGMF == (bool)GlobalModuleFragment) &&
  "mismatched global module state");
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121590: [C++20][Modules][Driver][HU 3/N] Handle foo.h with -fmodule-header and/or C++ invocation.

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418267.
iains added a comment.
Herald added a subscriber: MaskRay.

rebased, addrssed review comment, amend testcase for windows.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121590/new/

https://reviews.llvm.org/D121590

Files:
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-02.cpp


Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- clang/test/Driver/cxx20-header-units-02.cpp
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -3,7 +3,10 @@
 // RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-USER %s
 
-// RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.h  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER1 %s
+
+// RUN: %clang++ -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
 
 // RUN: %clang -### -std=c++20 -fmodule-header=system \
@@ -19,6 +22,10 @@
 // CHECK-USER-SAME: "-o" "foo.pcm"
 // CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
 
+// CHECK-USER1: "-emit-header-unit"
+// CHECK-USER1-SAME: "-o" "foo.pcm"
+// CHECK-USER1-SAME: "-x" "c++-user-header" "foo.h"
+
 // CHECK-SYS1: "-emit-header-unit"
 // CHECK-SYS1-SAME: "-o" "foo.pcm"
 // CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2432,7 +2432,9 @@
 types::ID OldTy = Ty;
 Ty = types::lookupCXXTypeForCType(Ty);
 
-if (Ty != OldTy)
+// Do not complain about foo.h, when we are known to be processing
+// it as a C++20 header unit.
+if (Ty != OldTy && !(OldTy == types::TY_CHeader && 
hasHeaderMode()))
   Diag(clang::diag::warn_drv_treating_input_as_cxx)
   << getTypeName(OldTy) << getTypeName(Ty);
   }
@@ -2457,8 +2459,11 @@
 }
 
 // Disambiguate headers that are meant to be header units from those
-// intended to be PCH.
-if (Ty == types::TY_CXXHeader && hasHeaderMode())
+// intended to be PCH.  Avoid missing '.h' cases that are counted as
+// C headers by default - we know we are in C++ mode and we do not
+// want to issue a complaint about compiling things in the wrong mode.
+if ((Ty == types::TY_CXXHeader || Ty == types::TY_CHeader) &&
+hasHeaderMode())
   Ty = CXXHeaderUnitType(CXX20HeaderType);
   } else {
 assert(InputTypeArg && "InputType set w/o InputTypeArg");


Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- clang/test/Driver/cxx20-header-units-02.cpp
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -3,7 +3,10 @@
 // RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-USER %s
 
-// RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.h  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER1 %s
+
+// RUN: %clang++ -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
 
 // RUN: %clang -### -std=c++20 -fmodule-header=system \
@@ -19,6 +22,10 @@
 // CHECK-USER-SAME: "-o" "foo.pcm"
 // CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
 
+// CHECK-USER1: "-emit-header-unit"
+// CHECK-USER1-SAME: "-o" "foo.pcm"
+// CHECK-USER1-SAME: "-x" "c++-user-header" "foo.h"
+
 // CHECK-SYS1: "-emit-header-unit"
 // CHECK-SYS1-SAME: "-o" "foo.pcm"
 // CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2432,7 +2432,9 @@
 types::ID OldTy = Ty;
 Ty = types::lookupCXXTypeForCType(Ty);
 
-if (Ty != OldTy)
+// Do not complain about foo.h, when we are known to be processing
+// it as a C++20 header unit.
+if (Ty != OldTy && !(OldTy == types::TY_CHeader && hasHeaderMode()))
   Diag(clang::diag::warn_drv_treating_input_as_cxx)
   << getTypeName(OldTy) << getTypeName(Ty);
   }
@@ -2457,8 +2459,11 @@
 }
 
 // Disambiguate headers that are meant to be header units from those
-// intended to be PCH.
-if (Ty == types::TY_CXXHeader && hasHeaderMode())
+// intended to be PCH.  Avoid missing '.h' cases that are counted as
+// C headers by default - we know we are in C++ mode and we do not
+// want to issue a complaint about compiling things in the wrong mode.
+

[PATCH] D121590: [C++20][Modules][Driver][HU 3/N] Handle foo.h with -fmodule-header and/or C++ invocation.

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418268.
iains added a comment.

another testcase ajustment for windows.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121590/new/

https://reviews.llvm.org/D121590

Files:
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-02.cpp


Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- clang/test/Driver/cxx20-header-units-02.cpp
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -3,6 +3,9 @@
 // RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-USER %s
 
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.h  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER1 %s
+
 // RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
 
@@ -19,6 +22,10 @@
 // CHECK-USER-SAME: "-o" "foo.pcm"
 // CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
 
+// CHECK-USER1: "-emit-header-unit"
+// CHECK-USER1-SAME: "-o" "foo.pcm"
+// CHECK-USER1-SAME: "-x" "c++-user-header" "foo.h"
+
 // CHECK-SYS1: "-emit-header-unit"
 // CHECK-SYS1-SAME: "-o" "foo.pcm"
 // CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2432,7 +2432,9 @@
 types::ID OldTy = Ty;
 Ty = types::lookupCXXTypeForCType(Ty);
 
-if (Ty != OldTy)
+// Do not complain about foo.h, when we are known to be processing
+// it as a C++20 header unit.
+if (Ty != OldTy && !(OldTy == types::TY_CHeader && 
hasHeaderMode()))
   Diag(clang::diag::warn_drv_treating_input_as_cxx)
   << getTypeName(OldTy) << getTypeName(Ty);
   }
@@ -2457,8 +2459,11 @@
 }
 
 // Disambiguate headers that are meant to be header units from those
-// intended to be PCH.
-if (Ty == types::TY_CXXHeader && hasHeaderMode())
+// intended to be PCH.  Avoid missing '.h' cases that are counted as
+// C headers by default - we know we are in C++ mode and we do not
+// want to issue a complaint about compiling things in the wrong mode.
+if ((Ty == types::TY_CXXHeader || Ty == types::TY_CHeader) &&
+hasHeaderMode())
   Ty = CXXHeaderUnitType(CXX20HeaderType);
   } else {
 assert(InputTypeArg && "InputType set w/o InputTypeArg");


Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- clang/test/Driver/cxx20-header-units-02.cpp
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -3,6 +3,9 @@
 // RUN: %clang -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-USER %s
 
+// RUN: %clang -### -std=c++20 -fmodule-header=user foo.h  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER1 %s
+
 // RUN: %clang -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
 
@@ -19,6 +22,10 @@
 // CHECK-USER-SAME: "-o" "foo.pcm"
 // CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
 
+// CHECK-USER1: "-emit-header-unit"
+// CHECK-USER1-SAME: "-o" "foo.pcm"
+// CHECK-USER1-SAME: "-x" "c++-user-header" "foo.h"
+
 // CHECK-SYS1: "-emit-header-unit"
 // CHECK-SYS1-SAME: "-o" "foo.pcm"
 // CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2432,7 +2432,9 @@
 types::ID OldTy = Ty;
 Ty = types::lookupCXXTypeForCType(Ty);
 
-if (Ty != OldTy)
+// Do not complain about foo.h, when we are known to be processing
+// it as a C++20 header unit.
+if (Ty != OldTy && !(OldTy == types::TY_CHeader && hasHeaderMode()))
   Diag(clang::diag::warn_drv_treating_input_as_cxx)
   << getTypeName(OldTy) << getTypeName(Ty);
   }
@@ -2457,8 +2459,11 @@
 }
 
 // Disambiguate headers that are meant to be header units from those
-// intended to be PCH.
-if (Ty == types::TY_CXXHeader && hasHeaderMode())
+// intended to be PCH.  Avoid missing '.h' cases that are counted as
+// C headers by default - we know we are in C++ mode and we do not
+// want to issue a complaint about compiling things in the wrong mode.
+if ((Ty == types::TY_CXXHeader || Ty == types::TY_CHeader) &&
+hasHeaderMode())
   Ty = CXXHeaderUnitType(CXX20HeaderType);
   } else {
 assert(InputTypeArg && "InputType set w/o InputTypeArg");
___
cfe-commits mailing list
cfe-commits@

[PATCH] D121591: [C++20][Modules][Driver][HU 4/N] Add fdirectives-only mode for preprocessing output.

2022-03-25 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 418274.
iains added a comment.
Herald added a subscriber: MaskRay.

rebased, adjusted testcases to avoid using clang++.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121591/new/

https://reviews.llvm.org/D121591

Files:
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cxx20-fdirectives-only.cpp


Index: clang/test/Driver/cxx20-fdirectives-only.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-fdirectives-only.cpp
@@ -0,0 +1,20 @@
+// Test -fdirectives-only cases.
+
+// We can manullay specify fdirectives-only, for any pre-processor job.
+// RUN: %clang -### -std=c++20 -E -fdirectives-only foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-NON-HU %s
+
+// Check that we automatically append -fdirectives-only for header-unit
+// preprocessor jobs.
+// RUN: %clang -### -std=c++20 -E -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-HU %s
+
+// CHECK-NON-HU: "-E"
+// CHECK-NON-HU-SAME: "-fdirectives-only"
+// CHECK-NON-HU-SAME: "-o" "-"
+// CHECK-NON-HU-SAME: "-x" "c++-header" "foo.hh"
+
+// CHECK-HU: "-E"
+// CHECK-HU-SAME: "-fdirectives-only"
+// CHECK-HU-SAME: "-o" "-"
+// CHECK-HU-SAME: "-x" "c++-user-header" "foo.hh"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4618,6 +4618,8 @@
   if (Args.hasArg(options::OPT_rewrite_objc) &&
   !Args.hasArg(options::OPT_g_Group))
 CmdArgs.push_back("-P");
+  else if (JA.getType() == types::TY_PP_CXXHeaderUnit)
+CmdArgs.push_back("-fdirectives-only");
 }
   } else if (isa(JA)) {
 CmdArgs.push_back("-emit-obj");
@@ -6769,6 +6771,10 @@
   if (RewriteImports)
 CmdArgs.push_back("-frewrite-imports");
 
+  if (Args.hasFlag(options::OPT_fdirectives_only,
+   options::OPT_fno_directives_only, false))
+CmdArgs.push_back("-fdirectives-only");
+
   // Enable rewrite includes if the user's asked for it or if we're generating
   // diagnostics.
   // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -4279,10 +4279,14 @@
   OutputTy = types::TY_Dependencies;
 } else {
   OutputTy = Input->getType();
+  // For these cases, the preprocessor is only translating forms, the 
Output
+  // still needs preprocessing.
   if (!Args.hasFlag(options::OPT_frewrite_includes,
 options::OPT_fno_rewrite_includes, false) &&
   !Args.hasFlag(options::OPT_frewrite_imports,
 options::OPT_fno_rewrite_imports, false) &&
+  !Args.hasFlag(options::OPT_fdirectives_only,
+options::OPT_fno_directives_only, false) &&
   !CCGenDiagnostics)
 OutputTy = types::getPreprocessedType(OutputTy);
   assert(OutputTy != types::TY_INVALID &&


Index: clang/test/Driver/cxx20-fdirectives-only.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-fdirectives-only.cpp
@@ -0,0 +1,20 @@
+// Test -fdirectives-only cases.
+
+// We can manullay specify fdirectives-only, for any pre-processor job.
+// RUN: %clang -### -std=c++20 -E -fdirectives-only foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-NON-HU %s
+
+// Check that we automatically append -fdirectives-only for header-unit
+// preprocessor jobs.
+// RUN: %clang -### -std=c++20 -E -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-HU %s
+
+// CHECK-NON-HU: "-E"
+// CHECK-NON-HU-SAME: "-fdirectives-only"
+// CHECK-NON-HU-SAME: "-o" "-"
+// CHECK-NON-HU-SAME: "-x" "c++-header" "foo.hh"
+
+// CHECK-HU: "-E"
+// CHECK-HU-SAME: "-fdirectives-only"
+// CHECK-HU-SAME: "-o" "-"
+// CHECK-HU-SAME: "-x" "c++-user-header" "foo.hh"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4618,6 +4618,8 @@
   if (Args.hasArg(options::OPT_rewrite_objc) &&
   !Args.hasArg(options::OPT_g_Group))
 CmdArgs.push_back("-P");
+  else if (JA.getType() == types::TY_PP_CXXHeaderUnit)
+CmdArgs.push_back("-fdirectives-only");
 }
   } else if (isa(JA)) {
 CmdArgs.push_back("-emit-obj");
@@ -6769,6 +6771,10 @@
   if (RewriteImports)
 CmdArgs.push_back("-frewrite-imports");
 
+  if (Args.hasFlag(options::OPT_fdirectives_only,
+   options::OPT_fno_directives_only, false))
+CmdArgs.push_back("-fdirectives-only");
+
   // Enable rewrite includes if the us

[PATCH] D121096: [C++20][Modules][HU 2/5] Support searching Header Units in user or system search paths.

2022-03-26 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0687578728ea: [C++20][Modules][HU 2/5] Support searching 
Header Units in user or system… (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121096/new/

https://reviews.llvm.org/D121096

Files:
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Frontend/FrontendOptions.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/FrontendAction.cpp
  clang/test/Modules/cxx20-hu-02.cpp
  clang/test/Modules/cxx20-hu-03.cpp
  clang/test/Modules/cxx20-hu-bad-input.cpp

Index: clang/test/Modules/cxx20-hu-bad-input.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-bad-input.cpp
@@ -0,0 +1,19 @@
+// Test generation and import of simple C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: not %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN:  -xc++-header-unit-header hu-01.hh \
+// RUN:  -xc++-header-unit-header hu-02.hh \
+// RUN:  -o hu-01.pcm -verify  2>&1 | FileCheck %s
+
+// CHECK: (frontend): multiple inputs are not valid for header units (first extra 'hu-02.hh')
+
+//--- hu-01.hh
+int foo(int);
+
+//--- hu-02.hh
+int bar(int);
Index: clang/test/Modules/cxx20-hu-03.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-03.cpp
@@ -0,0 +1,57 @@
+// Test check that processing headers as C++20 units allows #pragma once.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-01.h \
+// RUN: -Werror -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -fmodule-file=%t/hu-01.pcm -o hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-01.cpp \
+// RUN: -fmodule-file=%t/hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-02.cpp \
+// RUN: -fmodule-file=%t/hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-03.cpp \
+// RUN: -fmodule-file=%t/hu-02.pcm
+
+//--- hu-01.h
+#pragma once
+struct HU {
+  int a;
+};
+// expected-no-diagnostics
+
+//--- hu-02.h
+export import "hu-01.h";
+// expected-no-diagnostics
+
+//--- imports-01.cpp
+import "hu-01.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
+
+//--- imports-02.cpp
+import "hu-02.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
+
+//--- imports-03.cpp
+import "hu-01.h";
+import "hu-02.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
Index: clang/test/Modules/cxx20-hu-02.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-02.cpp
@@ -0,0 +1,77 @@
+// Test generation and import of user and system C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// check user path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -I user \
+// RUN: -xc++-user-header hu-01.h -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface imp-hu-01.cpp \
+// RUN:  -I user -fmodule-file=hu-01.pcm -o B.pcm -Rmodule-import \
+// RUN: 2>&1  | FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// check system path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -isystem system \
+// RUN: -xc++-system-header hu-02.h -o hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-02.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU2 %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface imp-hu-02.cpp \
+// RUN:  -isystem system -fmodule-file=hu-02.pcm -o C.pcm \
+// RUN: -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-SYS-IMP %s -DTDIR=%t
+
+// check absolute path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit  \
+// RUN: -xc++-header-unit-header %t/hu-03.h -o hu-03.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-03.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU3 %s -DTDIR=%t
+
+//--- user/hu-01.h
+int foo(int);
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit 'user{{[/\\]}}hu-01.h' is the Primary Module at index #1
+
+//--- imp-hu-01.cpp
+export module B;
+import "hu-01.h";
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-IMP: remark: importing module 'user{{[/\\]}}hu-01.h' from 'hu-01.pcm'
+// expected-no-diagnostics
+
+//--- system/hu-02.h
+int baz(int);
+
+// CHECK-HU2:  == C++20 Module structure ==
+// CHECK-HU2-NEXT:  Header Unit 'system{{[/\\]}}hu-02.h' is the Primary Module at index #1
+
+//--- imp-hu-02.cpp
+module;
+import ;
+
+export module C;
+
+int bar(int x) {
+  return baz(x);
+}
+// CHECK-SYS-IMP: remark: importing module 'syst

[PATCH] D121097: [C++20][Modules][HU 3/5] Emit module macros for header units.

2022-03-26 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf8846229c41f: [C++20][Modules][HU 3/5] Emit module macros 
for header units. (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121097/new/

https://reviews.llvm.org/D121097

Files:
  clang/include/clang/Basic/Module.h
  clang/include/clang/Serialization/ASTWriter.h
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/Modules/cxx20-hu-04.cpp

Index: clang/test/Modules/cxx20-hu-04.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-04.cpp
@@ -0,0 +1,105 @@
+// Test macro preservation in C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-01.h \
+// RUN: -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -DFOO -fmodule-file=hu-01.pcm -o hu-02.pcm  -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-02.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU2 %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface importer-01.cpp \
+// RUN:  -fmodule-file=hu-02.pcm -o B.pcm -DTDIR=%t -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface importer-02.cpp \
+// RUN:  -fmodule-file=hu-02.pcm -o C.pcm -DTDIR=%t -Rmodule-import 2>&1 | \
+// RUN:  FileCheck --check-prefix=CHECK-IMP-HU2 %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+// expected-no-diagnostics
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit './hu-01.h' is the Primary Module at index #1
+
+//--- hu-02.h
+export import "hu-01.h";
+#if !defined(FORTYTWO) || FORTYTWO != 42
+#error FORTYTWO missing in hu-02
+#endif
+
+#ifndef __GUARD
+#error __GUARD missing in hu-02
+#endif
+
+#ifdef SHOULD_NOT_BE_DEFINED
+#error SHOULD_NOT_BE_DEFINED is visible
+#endif
+
+#define KAP 6174
+
+#ifdef FOO
+#define FOO_BRANCH(X) (X) + 1
+inline int foo(int x) {
+  if (x == FORTYTWO)
+return FOO_BRANCH(x);
+  return FORTYTWO;
+}
+#else
+#define BAR_BRANCH(X) (X) + 2
+inline int bar(int x) {
+  if (x == FORTYTWO)
+return BAR_BRANCH(x);
+  return FORTYTWO;
+}
+#endif
+
+// CHECK-IMP: remark: importing module './hu-01.h' from 'hu-01.pcm'
+// CHECK-HU2:  == C++20 Module structure ==
+// CHECK-HU2-NEXT:  Header Unit './hu-02.h' is the Primary Module at index #2
+// CHECK-HU2-NEXT:   Exports:
+// CHECK-HU2-NEXT:Header Unit './hu-01.h' is at index #1
+// expected-no-diagnostics
+
+//--- importer-01.cpp
+export module B;
+import "hu-02.h";
+
+int success(int x) {
+  return foo(FORTYTWO + x + KAP);
+}
+
+int fail(int x) {
+  return bar(FORTYTWO + x + KAP); // expected-error {{use of undeclared identifier 'bar'}}
+  // expected-note@* {{'baz' declared here}}
+}
+
+//--- importer-02.cpp
+export module C;
+import "hu-02.h";
+
+int success(int x) {
+  return foo(FORTYTWO + x + KAP);
+}
+
+// CHECK-IMP-HU2: remark: importing module './hu-02.h' from 'hu-02.pcm'
+// CHECK-IMP-HU2: remark: importing module './hu-01.h' into './hu-02.h' from '[[TDIR]]{{[/\\]}}hu-01.pcm'
Index: clang/lib/Serialization/ASTWriter.cpp
===
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -2352,13 +2352,22 @@
 uint64_t StartOffset = Stream.GetCurrentBitNo() - MacroOffsetsBase;
 assert((StartOffset >> 32) == 0 && "Macro identifiers offset too large");
 
-// Emit the macro directives in reverse source order.
-for (; MD; MD = MD->getPrevious()) {
-  // Once we hit an ignored macro, we're done: the rest of the chain
-  // will all be ignored macros.
-  if (shouldIgnoreMacro(MD, IsModule, PP))
-break;
-
+// Write out any exported module macros.
+bool EmittedModuleMacros = false;
+// C+=20 Header Units are compiled module interfaces, but they preserve
+// macros that are live (i.e. have a defined value) at the end of the
+// compilation.  So when writing a header unit, we preserve only the final
+// value of each macro (and discard any that are undefined).  Header units
+// do not have sub-modules (although they might import other header units).
+// PCH files, conversely, retain the history of each macro's define/undef
+// and of leaf macros in sub modules.
+if (IsModule && WritingModule->isHeaderUnit()) {
+  // This is for the main TU when it is a C++20 header unit.
+  // We preserve the final state of defined macros, and we do not emit 

[PATCH] D119409: [C++20] [Modules] Remain dynamic initializing internal-linkage variables in module interface unit

2022-03-26 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

I think that this problem might well be a consequence of the bug which is fixed 
by D122413 .

We have been generating code with module internal entities (always) given the 
special ModuleInternalLinkage (which means that, although the linkage is 
formally 'internal', the entities are made global when emitted.  We should only 
be doing this for fmodules-ts, not for regular standard modules.

If you apply D122413  (which I hope to land 
soon), then I would expect that iostream should work as expected (with one 
internal instance of std::__ioinit in each TU that includes iostream).

IFF (after applying D122413  ) you add to the 
command line -fmodules-ts, then the patch here (D119409 
) would, presumably, be needed to work around 
multiple instances of the globalised std::__ioinit.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119409/new/

https://reviews.llvm.org/D119409

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D119409: [C++20] [Modules] Remain dynamic initializing internal-linkage variables in module interface unit

2022-03-26 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

addendum: note we still have work to do on the module initialisers - those are 
not correct yet (so probably some nesting of modules might not work).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119409/new/

https://reviews.llvm.org/D119409

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121098: [C++20][Modules][HU 4/5] Handle pre-processed header units.

2022-03-27 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGd9cea8d3a8ff: [C++20][Modules][HU 4/5] Handle pre-processed 
header units. (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121098/new/

https://reviews.llvm.org/D121098

Files:
  clang/lib/Frontend/FrontendAction.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/Modules/cxx20-hu-05.cpp


Index: clang/test/Modules/cxx20-hu-05.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-05.cpp
@@ -0,0 +1,32 @@
+// Test macro preservation in C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// Produce a pre-processed file.
+// RUN: %clang_cc1 -std=c++20 -E -xc++-user-header hu-01.h -o hu-01.iih
+
+// consume that to produce the heder unit.
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN: -xc++-header-unit-header-cpp-output hu-01.iih -o hu-01.pcm
+
+// check that the header unit is named for the original file, not the .iih.
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit './hu-01.h' is the Primary Module at index #1
Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -109,10 +109,18 @@
 const_cast(getLangOpts()).CurrentModule = HUName.str();
   }
 
-  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   // TODO: Make the C++20 header lookup independent.
-  Module::Header H{getLangOpts().CurrentModule, getLangOpts().CurrentModule,
-   SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())};
+  // When the input is pre-processed source, we need a file ref to the original
+  // file for the header map.
+  auto F = SourceMgr.getFileManager().getFile(HUName);
+  // For the sake of error recovery (if someone has moved the original header
+  // after creating the pre-processed output) fall back to obtaining the file
+  // ref for the input file, which must be present.
+  if (!F)
+F = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+  assert(F && "failed to find the header unit source?");
+  Module::Header H{HUName.str(), HUName.str(), *F};
+  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);
   assert(Mod && "module creation should not fail");
   ModuleScopes.push_back({}); // No GMF
Index: clang/lib/Frontend/FrontendAction.cpp
===
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -843,6 +843,21 @@
   if (!CI.InitializeSourceManager(Input))
 return false;
 
+  if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&
+  Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) {
+// We have an input filename like foo.iih, but we want to find the right
+// module name (and original file, to build the map entry).
+// Check if the first line specifies the original source file name with a
+// linemarker.
+std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());
+ReadOriginalFileName(CI, PresumedInputFile);
+// Unless the user overrides this, the module name is the name by which the
+// original file was known.
+if (CI.getLangOpts().ModuleName.empty())
+  CI.getLangOpts().ModuleName = std::string(PresumedInputFile);
+CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;
+  }
+
   // For module map files, we first parse the module map and synthesize a
   // "" buffer before more conventional processing.
   if (Input.getKind().getFormat() == InputKind::ModuleMap) {


Index: clang/test/Modules/cxx20-hu-05.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-05.cpp
@@ -0,0 +1,32 @@
+// Test macro preservation in C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// Produce a pre-processed file.
+// RUN: %clang_cc1 -std=c++20 -E -xc++-user-header hu-01.h -o hu-01.iih
+
+// consume that to produce the heder unit.
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN: -xc++-header-unit-header-cpp-output hu-01.iih -o hu-01.pcm
+
+// check that the header unit is named for the original file, not the .iih.
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+

[PATCH] D121099: [C++20][Modules][HU 5/5] Add fdirectives-only mode for preprocessing output.

2022-03-27 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG85b1354098ba: [C++20][Modules][HU 5/5] Add fdirectives-only 
mode for preprocessing output. (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121099/new/

https://reviews.llvm.org/D121099

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/PreprocessorOutputOptions.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/test/Modules/cxx20-hu-06.cpp

Index: clang/test/Modules/cxx20-hu-06.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-06.cpp
@@ -0,0 +1,68 @@
+// Test check that consuming -E -fdirectives-only output produces the expected
+// header unit.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -E -fdirectives-only -xc++-user-header hu-01.h \
+// RUN: -o hu-01.iih
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN: -xc++-user-header-cpp-output hu-01.iih -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -DFOO -fmodule-file=hu-01.pcm -o hu-02.pcm -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+// expected-no-diagnostics
+
+//--- hu-02.h
+export import "hu-01.h";
+#if !defined(FORTYTWO) || FORTYTWO != 42
+#error FORTYTWO missing in hu-02
+#endif
+
+#ifndef __GUARD
+#error __GUARD missing in hu-02
+#endif
+
+#ifdef SHOULD_NOT_BE_DEFINED
+#error SHOULD_NOT_BE_DEFINED is visible
+#endif
+
+// Make sure that we have not discarded macros from the builtin file.
+#ifndef __cplusplus
+#error we dropped a defined macro
+#endif
+
+#define KAP 6174
+
+#ifdef FOO
+#define FOO_BRANCH(X) (X) + 1
+inline int foo(int x) {
+  if (x == FORTYTWO)
+return FOO_BRANCH(x);
+  return FORTYTWO;
+}
+#else
+#define BAR_BRANCH(X) (X) + 2
+inline int bar(int x) {
+  if (x == FORTYTWO)
+return BAR_BRANCH(x);
+  return FORTYTWO;
+}
+#endif
+// CHECK-IMP: remark: importing module './hu-01.h' from 'hu-01.pcm'
Index: clang/lib/Frontend/PrintPreprocessedOutput.cpp
===
--- clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -96,6 +96,7 @@
   bool UseLineDirectives;
   bool IsFirstFileEntered;
   bool MinimizeWhitespace;
+  bool DirectivesOnly;
 
   Token PrevTok;
   Token PrevPrevTok;
@@ -103,12 +104,13 @@
 public:
   PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers,
bool defines, bool DumpIncludeDirectives,
-   bool UseLineDirectives, bool MinimizeWhitespace)
+   bool UseLineDirectives, bool MinimizeWhitespace,
+   bool DirectivesOnly)
   : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
 DisableLineMarkers(lineMarkers), DumpDefines(defines),
 DumpIncludeDirectives(DumpIncludeDirectives),
 UseLineDirectives(UseLineDirectives),
-MinimizeWhitespace(MinimizeWhitespace) {
+MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly) {
 CurLine = 0;
 CurFilename += "";
 EmittedTokensOnThisLine = false;
@@ -467,12 +469,21 @@
 void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
 const MacroDirective *MD) {
   const MacroInfo *MI = MD->getMacroInfo();
-  // Only print out macro definitions in -dD mode.
-  if (!DumpDefines ||
+  // Print out macro definitions in -dD mode and when we have -fdirectives-only
+  // for C++20 header units.
+  if ((!DumpDefines && !DirectivesOnly) ||
   // Ignore __FILE__ etc.
-  MI->isBuiltinMacro()) return;
+  MI->isBuiltinMacro())
+return;
 
-  MoveToLine(MI->getDefinitionLoc(), /*RequireStartOfLine=*/true);
+  SourceLocation DefLoc = MI->getDefinitionLoc();
+  if (DirectivesOnly && !MI->isUsed()) {
+SourceManager &SM = PP.getSourceManager();
+if (SM.isWrittenInBuiltinFile(DefLoc) ||
+SM.isWrittenInCommandLineFile(DefLoc))
+  return;
+  }
+  MoveToLine(DefLoc, /*RequireStartOfLine=*/true);
   PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS);
   setEmittedDirectiveOnThisLine();
 }
@@ -480,8 +491,10 @@
 void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
   const MacroDefinition &MD,
   const MacroDirective *Undef) {
-  // Only print out macro definitions in -dD mode.
-  if (!DumpDefines) return;
+  // Print out macro definitions in -dD mode and 

[PATCH] D119409: [C++20] [Modules] Remain dynamic initializing internal-linkage variables in module interface unit

2022-03-28 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D119409#3410474 , @ChuanqiXu wrote:

> In D119409#3409806 , @iains wrote:
>
>> I think that this problem might well be a consequence of the bug which is 
>> fixed by D122413 .
>>
>> We have been generating code with module internal entities (always) given 
>> the special ModuleInternalLinkage (which means that, although the linkage is 
>> formally 'internal', the entities are made global when emitted.  We should 
>> only be doing this for fmodules-ts, not for regular standard modules.
>>
>> If you apply D122413  (which I hope to 
>> land soon), then I would expect that iostream should work as expected (with 
>> one internal instance of std::__ioinit in each TU that includes iostream).
>>
>> IFF (after applying D122413  ) you add to 
>> the command line -fmodules-ts, then the patch here (D119409 
>> ) would, presumably, be needed to work 
>> around multiple instances of the globalised std::__ioinit.
>
> Sadly it wouldn't work after D122413  
> applied. Since the  is lived in GlobalModuleFragment, the 
> calculated linkage wouldn't affect them. So I met the same segfault as before.

Is this because we are not creating an initialiser for a static entity in the 
GMF ?

- I did a quick test and that seemed to be the case.

(module initialisers need quite some work, it seems)

>> addendum: note we still have work to do on the module initialisers - those 
>> are not correct yet (so probably some nesting of modules might not work).
>
> What does the nesting of modules mean?

If we have an import of a module that imports another - then we should be 
running the module initializers for the imported stack (in the correct order) 
.. at present, we do not do this.
As noted above, we have some work to do here.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119409/new/

https://reviews.llvm.org/D119409

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D120874: [C++20] [Modules] Use '-' as the separator of partitions when searching in filesystems

2022-03-30 Thread Iain Sandoe via Phabricator via cfe-commits
iains accepted this revision.
iains added a comment.
This revision is now accepted and ready to land.

In D120874#3416130 , @arames wrote:

> I was was asked to chime in to assess whether this patch could be a problem 
> for
> the prebuilt-implicit clang modules workflow. No problem here.
> With prebuilt modules, the output file name has to be specified manually. So 
> the
> mapping does not change the existing requirement of managing the file names to
> avoid collissions.
> Even in the future with implicit modules - as noted by others - `:` and `-` 
> are
> not allowed in the clang module name in the `.modulemap`, so there cannot be 
> any
> conflict.

great.

> A couple comments on the way. Take them with a grain of salt, since I don't 
> much
> about how this is going to be used or what stage of the work this is.
>
> I see the mapping is only applied on the "prebuilt" code path, and not the
> "implicit" and "prebuilt implicit" code paths. I suppose at some point, module
> generation will be implicit. So any particular handling of `ModuleName` to be
> appended to the filesystem path will need to be done on different code paths. 
> So
> I would already abstract this away in a helper.

At this time I do not think that the 'implicit' pathways are in use for 'C++ 
standard'
modules, (and it might be some time before we get to that point)

> Without much of an informed opinion, I find @iains makes a valid point. Does
> this kind of mapping (semantic module name to name being used for filesystem
> search/storage) belong at a higher level ? Maybe that's to be answered or 
> worked
> on later as well.

Yes, the generalisation is in the short-is queue for things to be applied (it 
is a precursor
to support for P1184 ).

However, I think that this patch can go ahead in the mean time, to help 
short-term
workflows.

So this LGTM as it is.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D120874/new/

https://reviews.llvm.org/D120874

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121271: [C++20] [Modules] Don't generate strong function of a partition in importing modules

2022-03-30 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

it looks like the first part of the C++20 mangling was just landed, so perhaps 
you can revisit this?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121271/new/

https://reviews.llvm.org/D121271

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121271: [C++20] [Modules] Don't generate strong function of a partition in importing modules

2022-03-31 Thread Iain Sandoe via Phabricator via cfe-commits
iains accepted this revision.
iains added a comment.
This revision is now accepted and ready to land.

LGTM, thanks.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121271/new/

https://reviews.llvm.org/D121271

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D122413: [C++20][Modules] Limit ModuleInternalLinkage to modules-ts.

2022-04-01 Thread Iain Sandoe via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc7ed65b4bcbd: [C++20][Modules] Limit ModuleInternalLinkage 
to modules-ts. (authored by iains).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122413/new/

https://reviews.llvm.org/D122413

Files:
  clang/lib/AST/Decl.cpp
  clang/unittests/AST/DeclTest.cpp


Index: clang/unittests/AST/DeclTest.cpp
===
--- clang/unittests/AST/DeclTest.cpp
+++ clang/unittests/AST/DeclTest.cpp
@@ -194,3 +194,50 @@
   EXPECT_EQ(TemplateF->getLinkageInternal(),
 SpecializedF->getLinkageInternal());
 }
+
+TEST(Decl, ModuleAndInternalLinkage) {
+  llvm::Annotations Code(R"(
+export module M;
+static int a;
+static int f(int x);
+
+int b;
+int g(int x);)");
+
+  auto AST =
+  tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{"-std=c++20"});
+  ASTContext &Ctx = AST->getASTContext();
+
+  const auto *a =
+  selectFirst("a", match(varDecl(hasName("a")).bind("a"), Ctx));
+  const auto *f = selectFirst(
+  "f", match(functionDecl(hasName("f")).bind("f"), Ctx));
+
+  EXPECT_EQ(a->getLinkageInternal(), InternalLinkage);
+  EXPECT_EQ(f->getLinkageInternal(), InternalLinkage);
+
+  const auto *b =
+  selectFirst("b", match(varDecl(hasName("b")).bind("b"), Ctx));
+  const auto *g = selectFirst(
+  "g", match(functionDecl(hasName("g")).bind("g"), Ctx));
+
+  EXPECT_EQ(b->getLinkageInternal(), ModuleLinkage);
+  EXPECT_EQ(g->getLinkageInternal(), ModuleLinkage);
+
+  AST = tooling::buildASTFromCodeWithArgs(
+  Code.code(), /*Args=*/{"-std=c++20", "-fmodules-ts"});
+  ASTContext &CtxTS = AST->getASTContext();
+  a = selectFirst("a", match(varDecl(hasName("a")).bind("a"), CtxTS));
+  f = selectFirst(
+  "f", match(functionDecl(hasName("f")).bind("f"), CtxTS));
+
+  EXPECT_EQ(a->getLinkageInternal(), ModuleInternalLinkage);
+  EXPECT_EQ(f->getLinkageInternal(), ModuleInternalLinkage);
+
+  b = selectFirst("b", match(varDecl(hasName("b")).bind("b"), CtxTS));
+  g = selectFirst(
+  "g", match(functionDecl(hasName("g")).bind("g"), CtxTS));
+
+  EXPECT_EQ(b->getLinkageInternal(), ModuleLinkage);
+  EXPECT_EQ(g->getLinkageInternal(), ModuleLinkage);
+}
Index: clang/lib/AST/Decl.cpp
===
--- clang/lib/AST/Decl.cpp
+++ clang/lib/AST/Decl.cpp
@@ -596,11 +596,12 @@
 }
 
 static LinkageInfo getInternalLinkageFor(const NamedDecl *D) {
-  // Internal linkage declarations within a module interface unit are modeled
-  // as "module-internal linkage", which means that they have internal linkage
-  // formally but can be indirectly accessed from outside the module via inline
-  // functions and templates defined within the module.
-  if (isInModulePurview(D))
+  // (for the modules ts) Internal linkage declarations within a module
+  // interface unit are modeled as "module-internal linkage", which means that
+  // they have internal linkage formally but can be indirectly accessed from
+  // outside the module via inline functions and templates defined within the
+  // module.
+  if (isInModulePurview(D) && D->getASTContext().getLangOpts().ModulesTS)
 return LinkageInfo(ModuleInternalLinkage, DefaultVisibility, false);
 
   return LinkageInfo::internal();


Index: clang/unittests/AST/DeclTest.cpp
===
--- clang/unittests/AST/DeclTest.cpp
+++ clang/unittests/AST/DeclTest.cpp
@@ -194,3 +194,50 @@
   EXPECT_EQ(TemplateF->getLinkageInternal(),
 SpecializedF->getLinkageInternal());
 }
+
+TEST(Decl, ModuleAndInternalLinkage) {
+  llvm::Annotations Code(R"(
+export module M;
+static int a;
+static int f(int x);
+
+int b;
+int g(int x);)");
+
+  auto AST =
+  tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{"-std=c++20"});
+  ASTContext &Ctx = AST->getASTContext();
+
+  const auto *a =
+  selectFirst("a", match(varDecl(hasName("a")).bind("a"), Ctx));
+  const auto *f = selectFirst(
+  "f", match(functionDecl(hasName("f")).bind("f"), Ctx));
+
+  EXPECT_EQ(a->getLinkageInternal(), InternalLinkage);
+  EXPECT_EQ(f->getLinkageInternal(), InternalLinkage);
+
+  const auto *b =
+  selectFirst("b", match(varDecl(hasName("b")).bind("b"), Ctx));
+  const auto *g = selectFirst(
+  "g", match(functionDecl(hasName("g")).bind("g"), Ctx));
+
+  EXPECT_EQ(b->getLinkageInternal(), ModuleLinkage);
+  EXPECT_EQ(g->getLinkageInternal(), ModuleLinkage);
+
+  AST = tooling::buildASTFromCodeWithArgs(
+  Code.code(), /*Args=*/{"-std=c++20", "-fmodules-ts"});
+  ASTContext &CtxTS = AST->getASTContext();
+  a = selectFirst("a", match(varDecl(hasName("a")).bind("a"), CtxTS));
+  f = selectFirst(
+  "f", match(functionDecl(hasName("f")).bind("f"), CtxTS));
+
+  EXPECT_EQ(a->getLinkageInternal(), ModuleInternalLinkage);
+  EXPECT_E

[PATCH] D121097: [C++20][Modules][HU 3/5] Emit module macros for header units.

2022-04-01 Thread Iain Sandoe via Phabricator via cfe-commits
iains added inline comments.



Comment at: clang/test/Modules/cxx20-hu-04.cpp:22
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface importer-01.cpp \
+// RUN:  -fmodule-file=hu-02.pcm -o B.pcm -DTDIR=%t -verify
+

hvdijk wrote:
> On Windows, when the path starts with `C:\Users\...`, I am seeing
> ```
> error: 'warning' diagnostics seen but not expected: 
> 
>   Line 1: \U used with no following hex digits; treating as '\' followed by 
> identifier
> 
> 1 error generated.
> ```
> Looking at this test, `TDIR` is only used as a FileCheck variable, can it 
> just be removed from this line?
Sorry about that,  Yes, I think that change should be fine - I will take care 
of it,


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121097/new/

https://reviews.llvm.org/D121097

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121097: [C++20][Modules][HU 3/5] Emit module macros for header units.

2022-04-03 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

applied [C++20][Modules] Fix a testcase warning on Windows [NFC].
https://github.com/llvm/llvm-project/commit/1f0b8ba47ab0f1dc678099d4830d0cc0d10850b6
should be fixed now.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121097/new/

https://reviews.llvm.org/D121097

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D122885: [clang] Draft: Implement P1703R1

2022-04-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

FWIW probably these 5 patches are pretty independent of changes to the 
preprocessor...
...  the first four of those are extremely unlikely to clash - since they are 
concerned with the driver.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122885/new/

https://reviews.llvm.org/D122885

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D122119: [C++20][Modules] Adjust handling of exports of namespaces and using-decls.

2022-04-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

@dblaikie - is the explanation for the change in diagnostics at the same time 
OK? (if not I can split the patch, but either way I'd like to land what is 
acceptable soonish).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122119/new/

https://reviews.llvm.org/D122119

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D119409: [C++20] [Modules] Remain dynamic initializing internal-linkage variables in module interface unit

2022-04-06 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D119409#3410893 , @ChuanqiXu wrote:

> In D119409#3410868 , @iains wrote:
>
>> In D119409#3410474 , @ChuanqiXu 
>> wrote:
>>
>>> In D119409#3409806 , @iains wrote:
>>>
 I think that this problem might well be a consequence of the bug which is 
 fixed by D122413 .

 We have been generating code with module internal entities (always) given 
 the special ModuleInternalLinkage (which means that, although the linkage 
 is formally 'internal', the entities are made global when emitted.  We 
 should only be doing this for fmodules-ts, not for regular standard 
 modules.

 If you apply D122413  (which I hope to 
 land soon), then I would expect that iostream should work as expected 
 (with one internal instance of std::__ioinit in each TU that includes 
 iostream).

 IFF (after applying D122413  ) you add 
 to the command line -fmodules-ts, then the patch here (D119409 
 ) would, presumably, be needed to work 
 around multiple instances of the globalised std::__ioinit.
>>>
>>> Sadly it wouldn't work after D122413  
>>> applied. Since the  is lived in GlobalModuleFragment, the 
>>> calculated linkage wouldn't affect them. So I met the same segfault as 
>>> before.
>>
>> Is this because we are not creating an initialiser for a static entity in 
>> the GMF ?
>>
>> - I did a quick test and that seemed to be the case.
>
> I think we need this one finally, It would create the initialiser after the 
> patch applied. And I think we couldn't do that without the patch. Since from 
> the code we could see that the static variable wouldn't be generated in the 
> current strategies.
>
>> (module initialisers need quite some work, it seems)
>
> The initialiser above I said is the initialiser in that TU. What you mean 
> `module initializer` ? Do you mean the one module could have only module 
> initializer?
>
 addendum: note we still have work to do on the module initialisers - those 
 are not correct yet (so probably some nesting of modules might not work).
>>>
>>> What does the nesting of modules mean?
>>
>> If we have an import of a module that imports another - then we should be 
>> running the module initializers for the imported stack (in the correct 
>> order) .. at present, we do not do this.
>> As noted above, we have some work to do here.
>
> I am not familiar with the history here. But I found 
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1874r1.html#solution.
>  It says clang already has a simple fix. So I am wondering if this one is 
> already fixed or we are not talking about the same thing?

Sorry for slow response - was hoping to have a patch to show by now
... I am currently finishing off an implementation for 1874 + elision of unused 
GMF decls.  The "simple fix" in clang actually pulls all the initialisers into 
one list in the top-level module (which is slightly different from the intent 
of the paper, as implemented in GCC) - that implementation also does not fix 
the issue of a module interface where there is no explicit "import" for the 
sub-modules.

The patch in progress will build a per module initialiser (which will handle 
sub-module initialisers and calling module initialisers for direct imports).  I 
think that will fix the iostreams problem (it is a motivating example from the 
paper).


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D119409/new/

https://reviews.llvm.org/D119409

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130871: [C++20] [Modules] Handle initializer for Header Units

2022-08-01 Thread Iain Sandoe via Phabricator via cfe-commits
iains accepted this revision.
iains added a comment.
This revision is now accepted and ready to land.

LGTM, one small point about the test,




Comment at: clang/test/CodeGenCXX/module-initializer-header.cppm:5-7
+// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu 
-xc++-user-header -emit-header-unit %t/header.h -o %t/header.pcm
+// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu 
-fmodule-file=%t/header.pcm %t/M.cppm -S -emit-llvm -o - | FileCheck %t/M.cppm
+// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu 
-fmodule-file=%t/header.pcm %t/Use.cpp -S -emit-llvm -o - | FileCheck %t/Use.cpp

you could use `-triple %itanium_abi_triple` which would increase the test 
coverage to other titanium platforms.



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130871/new/

https://reviews.llvm.org/D130871

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D130864: [NFC] Introduce ASTContext::isInSameModule()

2022-08-02 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D130864#3693022 , @ChuanqiXu wrote:

> In D130864#3693019 , @ilya-biryukov 
> wrote:
>
>> Thanks for working on this. I have a few major concerns here:
>>
>> - Do we know that it's a bottleneck in practice? E.g. if the module name 
>> have different sizes, comparing strings is actually fast. If the module 
>> names are short, we are also in a pretty good situation. Having some 
>> benchmarks numbers would help to quantify whether the change is needed.
>
> No, we don't know it is a bottleneck in practice. (Currently there shouldn't 
> be many users for C++20 Modules). The reason to do this is that we (Iain and 
> me) feel bad to compare string frequently. Benchmarks would be good but I am 
> afraid I can't. Since there are not enough existing benchmarks and it looks 
> costful to construct the meaningful benchmarks. Let's not make the perfect to 
> be the enemy of better.

We do not have benchmarks, it is true - initially, it seemed that the problem 
would be confined to the case of checking for the parent of a module partition 
which would be no concern - since it is one check per TU).   However, in later 
parts of the implementation it has become necessary to check when merging or 
comparing individual decls - and that is a concern.

>> - `llvm::hash_value` is not a crypto hash, so we should expect collisions 
>> from it. OTOH, doing an extra string comparison when hashes match defeats 
>> the purpose of this optimization. Collisions are rare, but if someone hits 
>> one after the compiler is released there are literally no workarounds.  
>> Instead we can use `llvm::SHA1` or `llvm::SHA256`. (possibly truncated to 
>> 128 bits? it's hard to tell how much this is needed without benchmarks.)
>> - Why not store the hash directly inside `Module` and compute it on 
>> construction after setting name? If we want these comparisons to be fast, we 
>> probably want to avoid even the overhead of hash table access.
>
> Good idea. Will try to do.

+1.
if the string is stored locally to the Module, then would it not be sufficient 
to compare the address?


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130864/new/

https://reviews.llvm.org/D130864

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131062: [docs] Add "C++20 Modules"

2022-08-08 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

@h-vetinari you are right, this has become difficult to review - I will try and 
do some more later - just the one comment for now.




Comment at: clang/docs/CPlusPlus20Modules.rst:676-678
+So the final answer for why we don't reuse the interface of Clang modules for 
header units is that
+we've see some differences between header units and Clang modules and we think 
the differences may
+be too large to be acceptable in the future.

h-vetinari wrote:
> ChuanqiXu wrote:
> > h-vetinari wrote:
> > > 
> > Since it says `in the future`, if it is better to use `may be` or `will be` 
> > than `are` ?
> > Since it says `in the future`, if it is better to use `may be` or `will be` 
> > than `are` ?
> 
> The "we think" already contains built-in subjectiveness, so the "may be" is 
> redundant in terms of uncertainty. It's not a big deal, but in general: 
> either "they may be" or "we think they are".
> 
> It would also be possible to say something like:
> 
> > So the final answer for why we don't reuse the interface of Clang modules 
> > for header units is that
> > there are some differences between header units and Clang modules and that 
> > ignoring those
> > differences now would likely become a problem in the future.
> 
Is it not simpler than this?

Since clang header modules have different semantics from c++20 header units, if 
we were to force c++20 semantics on clang header modules, that would break 
existing code (and therefore to support existing code, we would expect clang 
header modules to be retained indefinitely).



CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131062/new/

https://reviews.llvm.org/D131062

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131388: [docs] Add "C++20 Modules"

2022-08-08 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

general comment.

Do we encourage contractions (don't, can't) etc. in documentation?
I would suggest that to assist in any translation process it is better to write 
"do not" or "can not" instead (but that's just an opinion, not a matter of 
correctness).




Comment at: clang/docs/CPlusPlus20Modules.rst:20-22
+more about the general idea of modules. Due to the C++20 modules having very
+different semantics, it might be more friendly for users who care about C++20
+modules only to create a new page.

I do not think we need to justify the existence of the page, just identify its 
purpose - maybe like:

"Since C++20 modules have different semantics (and work flows) from `Clang 
modules this page describes the background and use of Clang with C++20 modules."



Comment at: clang/docs/CPlusPlus20Modules.rst:25-26
+Although the term ``modules`` has a unique meaning in C++20 Language 
Specification,
+when people talk about C++20 modules, they may refer to another C++20 feature:
+header units. Therefore, this document will try to cover header units as well.
+

this also includes `C++20 header units`, which are also covered in this 
document.




Comment at: clang/docs/CPlusPlus20Modules.rst:57
+A module consists of one or more module units. A module unit is a special
+translation unit. Every module unit should have a module declaration. The 
syntax
+of the module declaration is:

must



Comment at: clang/docs/CPlusPlus20Modules.rst:219
+Currently, C++20 Modules are enabled automatically if the language standard is 
``-std=c++20`` or newer.
+The ``-fmodules-ts`` option is deprecated and is planned to be removed.
+

procedural point: do we ever actually remove an existing option - or does it 
just become a "NOP"?



Comment at: clang/docs/CPlusPlus20Modules.rst:259
+
+Remember to linking module files
+

link



Comment at: clang/docs/CPlusPlus20Modules.rst:458
+
+The declarations in module unit which are not in global module fragment would 
get new linkage names.
+

The declarations in a module unit which are not in global module fragment have 
new linkage names.



Comment at: clang/docs/CPlusPlus20Modules.rst:592
+
+But what's different is that we can't use ``-fprebuilt-module-path`` to search 
the module file for header units.
+

With the existing implementation ``-fprebuilt-module-path`` cannot be used for 
header units (since they are nominally anonymous).  For header units use  
``-fmodule-file`` to include the relevant PCM file for each header unit.



Comment at: clang/docs/CPlusPlus20Modules.rst:594-595
+
+(This may be an implementation defect. Although we could argue that header 
units have no name according to the spec,
+it is natural that we couldn't search it. But this is not user friendly 
enough.)
+

Notes ( we have an internal implementation name, which can be used by planned 
tooling and/or mapping changes)

--- so maybe:

this is expect to be solved in future editions of the compiler either by the 
tooling finding and specifying the -fmodule-file or by the use of a 
module-mapper that understands how to map the header name to their PCMs.




Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131388/new/

https://reviews.llvm.org/D131388

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D131388: [docs] Add "C++20 Modules"

2022-08-08 Thread Iain Sandoe via Phabricator via cfe-commits
iains added inline comments.



Comment at: clang/docs/CPlusPlus20Modules.rst:673-674
+
+Another reason is that there are proposals to introduce module mappers to the 
C++ standard (for example, https://wg21.link/p1184r2).
+If we decide to reuse Clang's modulemap, we may get in trouble once we need to 
introduce another module mapper.
+

as an aside : 

there is an open question in the implementation of p1184r2 as to whether one 
form of input that the module mapper could consume would be module map files 
(but, obviously, producing C++20 compliant output).

I wonder if this section is adding information that is useful to the user ? 
(perhaps it is more documentation of implementation decisions?)

As noted before `semantics of clang module headers != semantics of C++20 header 
units` seems a sufficient reason for keeping them separate?

I am not sure what could change in the future to alter this, since existing 
code will have the current semantics, even //if// some change is later made to 
the semantics of clang header modules ?



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D131388/new/

https://reviews.llvm.org/D131388

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121096: [C++20][Modules][HU 2/5] Support searching Header Units in user or system search paths.

2022-03-08 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D121096#3368996 , @ChuanqiXu wrote:

> BTW, all the tests uses ``clang_cc1`. How should the users do with `clang`? 
> Could them use `-Xclang` only?

The driver changes are in separate patches (they will make the same user-facing 
interface options as used by GCC).  I wanted to have the FE implementation 
available so that the driver has something to drive.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121096/new/

https://reviews.llvm.org/D121096

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121271: [C++20] [Modules] Don't generate strong function of a partition in importing modules

2022-03-09 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

thanks, this looks OK to me, but I would leave some time for other comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121271/new/

https://reviews.llvm.org/D121271

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121095: [C++20][Modules][HU 1/5] Introduce header units as a module type.

2022-03-12 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 414888.
iains marked 4 inline comments as done.
iains added a comment.

rebased, address review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121095/new/

https://reviews.llvm.org/D121095

Files:
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Basic/LangOptions.h
  clang/include/clang/Basic/Module.h
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/FrontendActions.h
  clang/include/clang/Frontend/FrontendOptions.h
  clang/include/clang/Lex/ModuleMap.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/Decl.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
  clang/lib/Lex/ModuleMap.cpp
  clang/lib/Parse/Parser.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaModule.cpp
  clang/test/Modules/cxx20-hu-01.cpp

Index: clang/test/Modules/cxx20-hu-01.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-01.cpp
@@ -0,0 +1,104 @@
+// Test generation and import of simple C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-01.h \
+// RUN:  -o %t/hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info %t/hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-01.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -o %t/B.pcm -Rmodule-import 2>&1  | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-02.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -o %t/C.pcm -Rmodule-import 2>&1  | \
+// RUN: FileCheck --check-prefix=CHECK-GMF-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-02.h \
+// RUN:  -o %t/hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-03.cpp \
+// RUN:  -fmodule-file=%t/hu-01.pcm -fmodule-file=%t/hu-02.pcm -o %t/D.pcm \
+// RUN: -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-BOTH %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-header %t/hu-03.h \
+// RUN: -fmodule-file=%t/hu-01.pcm  -o %t/hu-03.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info %t/hu-03.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/imp-hu-04.cpp \
+// RUN:  -fmodule-file=%t/hu-03.pcm -o %t/E.pcm -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-NESTED %s -DTDIR=%t
+
+//--- hu-01.h
+int foo(int);
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit '[[TDIR]]/hu-01.h' is the Primary Module at index #1
+
+//--- imp-hu-01.cpp
+export module B;
+import "hu-01.h";
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-IMP: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// expected-no-diagnostics
+
+//--- imp-hu-02.cpp
+module;
+import "hu-01.h";
+
+export module C;
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-GMF-IMP: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// expected-no-diagnostics
+
+//--- hu-02.h
+int baz(int);
+
+//--- imp-hu-03.cpp
+module;
+export import "hu-01.h";
+
+export module D;
+import "hu-02.h";
+
+int bar(int x) {
+  return foo(x) + baz(x);
+}
+// CHECK-BOTH: remark: importing module '[[TDIR]]/hu-01.h' from '[[TDIR]]/hu-01.pcm'
+// CHECK-BOTH: remark: importing module '[[TDIR]]/hu-02.h' from '[[TDIR]]/hu-02.pcm'
+// expected-no-diagnostics
+
+//--- hu-03.h
+export import "hu-01.h";
+int baz(int);
+// CHECK-HU-HU:  == C++20 Module structure ==
+// CHECK-HU-HU-NEXT:  Header Unit '[[TDIR]]/hu-03.h' is the Primary Module at index #2
+// CHECK-HU-HU-NEXT:   Exports:
+// CHECK-HU-HU-NEXT:Header Unit '[[TDIR]]/hu-01.h' is at index #1
+
+// expected-no-diagnostics
+
+//--- imp-hu-04.cpp
+module;
+import "hu-03.h";
+
+export module E;
+
+int bar(int x) {
+  return foo(x) + baz(x);
+}
+// CHECK-NESTED: remark: importing module '[[TDIR]]/hu-03.h' from '[[TDIR]]/hu-03.pcm'
+// expected-no-diagnostics
Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -97,6 +97,38 @@
   return nullptr;
 }
 
+void Sema::ActOnStartOfHeaderUnit() {
+  assert(getLangOpts().CPlusPlusModules &&
+ "Header units are only valid for C++20 modules");
+  SourceLocation StartOfTU =
+  SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
+
+  StringRef HUName = getLangOpts().CurrentModule;
+  if (HUName.empty()) {
+HUName = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())->getName();
+const_cast(getLangOpts()).CurrentModule = HUName.str();
+  }
+
+  auto &Map = PP.getHeaderSearchInfo()

[PATCH] D121095: [C++20][Modules][HU 1/5] Introduce header units as a module type.

2022-03-12 Thread Iain Sandoe via Phabricator via cfe-commits
iains added inline comments.



Comment at: clang/include/clang/Sema/Sema.h:2978-2980
+  /// The parser has begun a translation unit to be compiled as a C++20
+  /// Header Unit.
+  void ActOnStartOfHeaderUnit();

ChuanqiXu wrote:
> From the implementation, I think it should be called only in 
> `ActOnStartOfTranslationUnit`. So it would be better to move this function to 
> private section to avoid accident calls. We should add such constraint as 
> assumption or at least comment to tell it should be called by 
> `ActOnStartOfTranslationUnit`.
> 
> ---
> 
> The name `ActOnStartOf*` implies there should be a corresponding 
> `ActOnEndOf*`  methods. But there isn't one. So I would suggest to give 
> another name to avoid ambiguity.
> From the implementation, I think it should be called only in 
> `ActOnStartOfTranslationUnit`. So it would be better to move this function to 
> private section to avoid accident calls. We should add such constraint as 
> assumption or at least comment to tell it should be called by 
> `ActOnStartOfTranslationUnit`.

OK, I've made this private and updated the comment to note that this is a 
helper for ActOnStartOfTranslationUnit

> ---
> 
> The name `ActOnStartOf*` implies there should be a corresponding 
> `ActOnEndOf*`  methods. But there isn't one. So I would suggest to give 
> another name to avoid ambiguity.

Is this a rule?

I think that the name `ActOnStartOfHeaderUnit()` says exactly what we are 
doing, of course, at some time we might need an `ActOnEndOfHeaderUnit()` - but 
we should not add an empty function for that reason.

(this is not a sticking point; if consensus is that the name is confusing, I 
will change it).




Comment at: clang/lib/AST/Decl.cpp:1573-1574
   InternalLinkage = isInAnonymousNamespace();
-return InternalLinkage ? M->Parent : nullptr;
+return InternalLinkage ? M->Kind == Module::ModuleHeaderUnit ? M : 
M->Parent
+   : nullptr;
   }

ChuanqiXu wrote:
> How about
> ```
> return InternalLinkage ? M->getTopLevelModule() : nullptr; 
> ```
that would alter the behaviour of the existing code.

getTopLevelModule() will return the ultimate parent:
```
  const Module *Result = this;
  while (Result->Parent)
Result = Result->Parent;
```
where the existing code only returns the immediate parent (perhaps that is 
unintended, but it should be fixed separately if so).




Comment at: clang/lib/Parse/Parser.cpp:2476
 // We can only have pre-processor directives in the global module
 // fragment.  We can, however have a header unit import here.
+if (!HeaderUnit || HeaderUnit->Kind != 
Module::ModuleKind::ModuleHeaderUnit)

ChuanqiXu wrote:
> The comment is not accurate. `header unit import` is pre-processor too. 
> http://eel.is/c++draft/cpp.import
> The comment is not accurate. `header unit import` is pre-processor too. 

the pre-processor 'import' is a pre-processor directive. 

https://eel.is/c++draft/cpp.pre#1

I amended to clarify that we cannot import a named module in this position - 
only a header unit.



Comment at: clang/lib/Sema/SemaModule.cpp:519
+ (ModuleScopes.back().ModuleInterface ||
+  ModuleScopes.back().Module->isGlobalModule())) {
 // Re-export the module if the imported module is exported.

ChuanqiXu wrote:
> I would feel better if we add an assertion below to assert 
> `ModuleScopes.back().Module->isGlobalModule()` is true only if Mod is Header 
> Unit.
> 
OK, done.
I also added a check for CPlusPlus modules, since modules-ts has an implicit 
GMF and slightly different rules.



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121095/new/

https://reviews.llvm.org/D121095

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121096: [C++20][Modules][HU 2/5] Support searching Header Units in user or system search paths.

2022-03-12 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 414889.
iains marked 6 inline comments as done.
iains added a comment.

rebased, address review comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121096/new/

https://reviews.llvm.org/D121096

Files:
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Frontend/FrontendOptions.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/FrontendAction.cpp
  clang/test/Modules/cxx20-hu-02.cpp
  clang/test/Modules/cxx20-hu-03.cpp

Index: clang/test/Modules/cxx20-hu-03.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-03.cpp
@@ -0,0 +1,57 @@
+// Test check that processing headers as C++20 units allows #pragma once.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-01.h \
+// RUN: -Werror -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -fmodule-file=%t/hu-01.pcm -o hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-01.cpp \
+// RUN: -fmodule-file=%t/hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-02.cpp \
+// RUN: -fmodule-file=%t/hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only imports-03.cpp \
+// RUN: -fmodule-file=%t/hu-02.pcm
+
+//--- hu-01.h
+#pragma once
+struct HU {
+  int a;
+};
+// expected-no-diagnostics
+
+//--- hu-02.h
+export import "hu-01.h";
+// expected-no-diagnostics
+
+//--- imports-01.cpp
+import "hu-01.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
+
+//--- imports-02.cpp
+import "hu-02.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
+
+//--- imports-03.cpp
+import "hu-01.h";
+import "hu-02.h";
+
+HU foo(int x) {
+  return {x};
+}
+// expected-no-diagnostics
Index: clang/test/Modules/cxx20-hu-02.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-02.cpp
@@ -0,0 +1,77 @@
+// Test generation and import of user and system C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// check user path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -I user \
+// RUN: -xc++-user-header hu-01.h -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface imp-hu-01.cpp \
+// RUN:  -I user -fmodule-file=hu-01.pcm -o B.pcm -Rmodule-import \
+// RUN: 2>&1  | FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// check system path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -isystem system \
+// RUN: -xc++-system-header hu-02.h -o hu-02.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-02.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU2 %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface imp-hu-02.cpp \
+// RUN:  -isystem system -fmodule-file=hu-02.pcm -o C.pcm \
+// RUN: -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-SYS-IMP %s -DTDIR=%t
+
+// check absolute path
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit  \
+// RUN: -xc++-header-unit-header %t/hu-03.h -o hu-03.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-03.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU3 %s -DTDIR=%t
+
+//--- user/hu-01.h
+int foo(int);
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit 'user/hu-01.h' is the Primary Module at index #1
+
+//--- imp-hu-01.cpp
+export module B;
+import "hu-01.h";
+
+int bar(int x) {
+  return foo(x);
+}
+// CHECK-IMP: remark: importing module 'user/hu-01.h' from 'hu-01.pcm'
+// expected-no-diagnostics
+
+//--- system/hu-02.h
+int baz(int);
+
+// CHECK-HU2:  == C++20 Module structure ==
+// CHECK-HU2-NEXT:  Header Unit 'system/hu-02.h' is the Primary Module at index #1
+
+//--- imp-hu-02.cpp
+module;
+import ;
+
+export module C;
+
+int bar(int x) {
+  return baz(x);
+}
+// CHECK-SYS-IMP: remark: importing module 'system/hu-02.h' from 'hu-02.pcm'
+// expected-no-diagnostics
+
+//--- hu-03.h
+int curly(int);
+
+// CHECK-HU3:  == C++20 Module structure ==
+// CHECK-HU3-NEXT:  Header Unit '[[TDIR]]/hu-03.h' is the Primary Module at index #1
+// expected-no-diagnostics
Index: clang/lib/Frontend/FrontendAction.cpp
===
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -798,7 +798,48 @@
&CI.getPreprocessor());
   HasBegunSourceFile = true;
 
-  // Initialize the main file entry.
+  // Handle C++20 header units.
+  // Here, the user has the option to specify that the header name should be
+  // looked up in the pre-processor search paths (and the main filename as
+  // passed by the driver m

[PATCH] D121096: [C++20][Modules][HU 2/5] Support searching Header Units in user or system search paths.

2022-03-12 Thread Iain Sandoe via Phabricator via cfe-commits
iains added inline comments.



Comment at: clang/include/clang/Frontend/FrontendOptions.h:157
+  unsigned HeaderUnit : 3;
+  unsigned Header : 1;
 

ChuanqiXu wrote:
> I prefer `IsHeader`
OK.



Comment at: clang/include/clang/Frontend/FrontendOptions.h:252
+  bool isHeader() const { return Kind.isHeader(); }
+  InputKind::HeaderUnitKind getHeaderUnit() const {
+return Kind.getHeaderUnit();

ChuanqiXu wrote:
> How about `getHeaderUnitKind` ?
OK. I prefer more descriptive names, but they do get rather long sometimes.



Comment at: clang/lib/Frontend/CompilerInvocation.cpp:2788-2791
+  HUK =
+  XValue.consume_back("-header-unit") ? InputKind::HeaderUnit_Abs : 
HUK;
+  HUK = XValue.consume_back("-system") ? InputKind::HeaderUnit_System : 
HUK;
+  HUK = XValue.consume_back("-user") ? InputKind::HeaderUnit_User : HUK;

ChuanqiXu wrote:
> How do you think about the suggested changes? I feel it is less confusing.
OK, 



Comment at: clang/lib/Frontend/CompilerInvocation.cpp:2796-2797
+// not intended to be a module map or header unit.
+IsHeaderFile = IsHeader && !Preprocessed && !ModuleMap &&
+   HUK == InputKind::HeaderUnit_None;
 

ChuanqiXu wrote:
> Oh, now I find `Header` and `HeaderUnit` might be a little bit confusing. It 
> looks like `Header` should include `HeaderUnit` at the first sight. It is not 
> true. But I don't have only suggestions...
We have an amount of existing handling specific to "generic headers".
 (header unit = none, header = true)

The intention is that HeaderUnitKind is used to disambiguate the cases we are 
dealing with C+=20 header units.

I am not sure it would be worth the code churn to replace all uses of header 
with a HUK.



Comment at: clang/lib/Frontend/CompilerInvocation.cpp:2855-2857
+  assert((DashX.getHeaderUnit() == InputKind::HeaderUnit_None ||
+  Inputs.size() == 1) &&
+ "Expected only one input file for header unit");

ChuanqiXu wrote:
> So the compiler would crash if there is multiple inputs for header unit? I 
> feel it is not most friendly. How about emitting an error here?
well the driver is supposed to catch these problems (in the case of C++20 
modules mode it will generate several compile jobs, one per header).

I added an error for this tho.



Comment at: clang/lib/Frontend/FrontendAction.cpp:814-816
+  const DirectoryEntry *Dir = nullptr;
+  if (auto DirOrErr = CI.getFileManager().getDirectory("."))
+Dir = *DirOrErr;

ChuanqiXu wrote:
> Is it same as the suggested?
not quite because getDirectory() is "llvm::ErrorOr" ... 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121096/new/

https://reviews.llvm.org/D121096

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121097: [C++20][Modules][HU 3/5] Emit module macros for header units.

2022-03-12 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 414890.
iains added a comment.

rebased.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121097/new/

https://reviews.llvm.org/D121097

Files:
  clang/include/clang/Serialization/ASTWriter.h
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/Modules/cxx20-hu-04.cpp

Index: clang/test/Modules/cxx20-hu-04.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-04.cpp
@@ -0,0 +1,105 @@
+// Test macro preservation in C++20 Header Units.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-01.h \
+// RUN: -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-01.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -DFOO -fmodule-file=hu-01.pcm -o hu-02.pcm  -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -module-file-info hu-02.pcm | \
+// RUN: FileCheck --check-prefix=CHECK-HU2 %s -DTDIR=%t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface importer-01.cpp \
+// RUN:  -fmodule-file=hu-02.pcm -o B.pcm -DTDIR=%t -verify
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface importer-02.cpp \
+// RUN:  -fmodule-file=hu-02.pcm -o C.pcm -DTDIR=%t -Rmodule-import 2>&1 | \
+// RUN:  FileCheck --check-prefix=CHECK-IMP-HU2 %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+// expected-no-diagnostics
+
+// CHECK-HU:  == C++20 Module structure ==
+// CHECK-HU-NEXT:  Header Unit './hu-01.h' is the Primary Module at index #1
+
+//--- hu-02.h
+export import "hu-01.h";
+#if !defined(FORTYTWO) || FORTYTWO != 42
+#error FORTYTWO missing in hu-02
+#endif
+
+#ifndef __GUARD
+#error __GUARD missing in hu-02
+#endif
+
+#ifdef SHOULD_NOT_BE_DEFINED
+#error SHOULD_NOT_BE_DEFINED is visible
+#endif
+
+#define KAP 6174
+
+#ifdef FOO
+#define FOO_BRANCH(X) (X) + 1
+inline int foo(int x) {
+  if (x == FORTYTWO)
+return FOO_BRANCH(x);
+  return FORTYTWO;
+}
+#else
+#define BAR_BRANCH(X) (X) + 2
+inline int bar(int x) {
+  if (x == FORTYTWO)
+return BAR_BRANCH(x);
+  return FORTYTWO;
+}
+#endif
+
+// CHECK-IMP: remark: importing module './hu-01.h' from 'hu-01.pcm'
+// CHECK-HU2:  == C++20 Module structure ==
+// CHECK-HU2-NEXT:  Header Unit './hu-02.h' is the Primary Module at index #2
+// CHECK-HU2-NEXT:   Exports:
+// CHECK-HU2-NEXT:Header Unit './hu-01.h' is at index #1
+// expected-no-diagnostics
+
+//--- importer-01.cpp
+export module B;
+import "hu-02.h";
+
+int success(int x) {
+  return foo(FORTYTWO + x + KAP);
+}
+
+int fail(int x) {
+  return bar(FORTYTWO + x + KAP); // expected-error {{use of undeclared identifier 'bar'}}
+  // expected-note@* {{'baz' declared here}}
+}
+
+//--- importer-02.cpp
+export module C;
+import "hu-02.h";
+
+int success(int x) {
+  return foo(FORTYTWO + x + KAP);
+}
+
+// CHECK-IMP-HU2: remark: importing module './hu-02.h' from 'hu-02.pcm'
+// CHECK-IMP-HU2: remark: importing module './hu-01.h' into './hu-02.h' from '[[TDIR]]/hu-01.pcm'
Index: clang/lib/Serialization/ASTWriter.cpp
===
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -2284,7 +2284,8 @@
 
 /// Writes the block containing the serialized form of the
 /// preprocessor.
-void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) {
+void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule,
+  Module *Mod) {
   uint64_t MacroOffsetsBase = Stream.GetCurrentBitNo();
 
   PreprocessingRecord *PPRec = PP.getPreprocessingRecord();
@@ -2353,13 +2354,15 @@
 uint64_t StartOffset = Stream.GetCurrentBitNo() - MacroOffsetsBase;
 assert((StartOffset >> 32) == 0 && "Macro identifiers offset too large");
 
-// Emit the macro directives in reverse source order.
-for (; MD; MD = MD->getPrevious()) {
-  // Once we hit an ignored macro, we're done: the rest of the chain
-  // will all be ignored macros.
-  if (shouldIgnoreMacro(MD, IsModule, PP))
-break;
-
+// Write out any exported module macros.
+bool EmittedModuleMacros = false;
+if (IsHeaderUnit) {
+  // This is for the main TU when it is a C++20 header unit.
+  // We preserve the final state of defined macros, and we do not emit ones
+  // that are undefined.
+  if (!MD || shouldIgnoreMacro(MD, IsModule, PP) ||
+  MD->getKind() == MacroDirective::MD_Undefine)
+continue;
   AddSourceLocation(MD->getLocation(), Record);
   Record.push_back(MD->getKind());
   if (auto *D

[PATCH] D121098: [C++20][Modules][HU 4/5] Handle pre-processed header units.

2022-03-12 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 414891.
iains added a comment.

rebased.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121098/new/

https://reviews.llvm.org/D121098

Files:
  clang/lib/Frontend/FrontendAction.cpp
  clang/lib/Sema/SemaModule.cpp


Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -109,10 +109,18 @@
 const_cast(getLangOpts()).CurrentModule = HUName.str();
   }
 
-  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   // TODO: Make the C++20 header lookup independent.
-  Module::Header H{getLangOpts().CurrentModule, getLangOpts().CurrentModule,
-   SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())};
+  // When the input is pre-processed source, we need a file ref to the original
+  // file for the header map.
+  auto F = SourceMgr.getFileManager().getFile(HUName);
+  // For the sake of error recovery (if someone has moved the original header
+  // after creating the pre-processed output) fall back to obtaining the file
+  // ref for the input file, which must be present.
+  if (!F)
+F = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+  assert(F && "failed to find the header unit source?");
+  Module::Header H{HUName.str(), HUName.str(), *F};
+  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);
   assert(Mod && "module creation should not fail");
   ModuleScopes.push_back({}); // No GMF
Index: clang/lib/Frontend/FrontendAction.cpp
===
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -843,6 +843,21 @@
   if (!CI.InitializeSourceManager(Input))
 return false;
 
+  if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&
+  Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) {
+// We have an input filename like foo.iih, but we want to find the right
+// module name (and original file, to build the map entry).
+// Check if the first line specifies the original source file name with a
+// linemarker.
+std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());
+ReadOriginalFileName(CI, PresumedInputFile);
+// Unless the user overrides this, the module name is the name by which the
+// original file was known.
+if (CI.getLangOpts().ModuleName.empty())
+  CI.getLangOpts().ModuleName = std::string(PresumedInputFile);
+CI.getLangOpts().CurrentModule = CI.getLangOpts().ModuleName;
+  }
+
   // For module map files, we first parse the module map and synthesize a
   // "" buffer before more conventional processing.
   if (Input.getKind().getFormat() == InputKind::ModuleMap) {


Index: clang/lib/Sema/SemaModule.cpp
===
--- clang/lib/Sema/SemaModule.cpp
+++ clang/lib/Sema/SemaModule.cpp
@@ -109,10 +109,18 @@
 const_cast(getLangOpts()).CurrentModule = HUName.str();
   }
 
-  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   // TODO: Make the C++20 header lookup independent.
-  Module::Header H{getLangOpts().CurrentModule, getLangOpts().CurrentModule,
-   SourceMgr.getFileEntryForID(SourceMgr.getMainFileID())};
+  // When the input is pre-processed source, we need a file ref to the original
+  // file for the header map.
+  auto F = SourceMgr.getFileManager().getFile(HUName);
+  // For the sake of error recovery (if someone has moved the original header
+  // after creating the pre-processed output) fall back to obtaining the file
+  // ref for the input file, which must be present.
+  if (!F)
+F = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
+  assert(F && "failed to find the header unit source?");
+  Module::Header H{HUName.str(), HUName.str(), *F};
+  auto &Map = PP.getHeaderSearchInfo().getModuleMap();
   Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);
   assert(Mod && "module creation should not fail");
   ModuleScopes.push_back({}); // No GMF
Index: clang/lib/Frontend/FrontendAction.cpp
===
--- clang/lib/Frontend/FrontendAction.cpp
+++ clang/lib/Frontend/FrontendAction.cpp
@@ -843,6 +843,21 @@
   if (!CI.InitializeSourceManager(Input))
 return false;
 
+  if (CI.getLangOpts().CPlusPlusModules && Input.getKind().isHeaderUnit() &&
+  Input.getKind().isPreprocessed() && !usesPreprocessorOnly()) {
+// We have an input filename like foo.iih, but we want to find the right
+// module name (and original file, to build the map entry).
+// Check if the first line specifies the original source file name with a
+// linemarker.
+std::string PresumedInputFile = std::string(getCurrentFileOrBufferName());
+ReadOriginalFileName(CI, PresumedIn

[PATCH] D121099: [C++20][Modules][HU 5/5] Add fdirectives-only mode for preprocessing output.

2022-03-12 Thread Iain Sandoe via Phabricator via cfe-commits
iains updated this revision to Diff 414892.
iains added a comment.

rebased.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121099/new/

https://reviews.llvm.org/D121099

Files:
  clang/include/clang/Driver/Options.td
  clang/include/clang/Frontend/PreprocessorOutputOptions.h
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/lib/Frontend/PrintPreprocessedOutput.cpp
  clang/test/Modules/cxx20-hu-05.cpp

Index: clang/test/Modules/cxx20-hu-05.cpp
===
--- /dev/null
+++ clang/test/Modules/cxx20-hu-05.cpp
@@ -0,0 +1,68 @@
+// Test check that consuming -E -fdirectives-only output produces the expected
+// header unit.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -E -fdirectives-only -xc++-user-header hu-01.h \
+// RUN: -o hu-01.iih
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit \
+// RUN: -xc++-user-header-cpp-output hu-01.iih -o hu-01.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -xc++-user-header hu-02.h \
+// RUN: -DFOO -fmodule-file=hu-01.pcm -o hu-02.pcm -Rmodule-import 2>&1 | \
+// RUN: FileCheck --check-prefix=CHECK-IMP %s -DTDIR=%t
+
+//--- hu-01.h
+#ifndef __GUARD
+#define __GUARD
+
+int baz(int);
+#define FORTYTWO 42
+
+#define SHOULD_NOT_BE_DEFINED -1
+#undef SHOULD_NOT_BE_DEFINED
+
+#endif // __GUARD
+// expected-no-diagnostics
+
+//--- hu-02.h
+export import "hu-01.h";
+#if !defined(FORTYTWO) || FORTYTWO != 42
+#error FORTYTWO missing in hu-02
+#endif
+
+#ifndef __GUARD
+#error __GUARD missing in hu-02
+#endif
+
+#ifdef SHOULD_NOT_BE_DEFINED
+#error SHOULD_NOT_BE_DEFINED is visible
+#endif
+
+// Make sure that we have not discarded macros from the builtin file.
+#ifndef __cplusplus
+#error we dropped a defined macro
+#endif
+
+#define KAP 6174
+
+#ifdef FOO
+#define FOO_BRANCH(X) (X) + 1
+inline int foo(int x) {
+  if (x == FORTYTWO)
+return FOO_BRANCH(x);
+  return FORTYTWO;
+}
+#else
+#define BAR_BRANCH(X) (X) + 2
+inline int bar(int x) {
+  if (x == FORTYTWO)
+return BAR_BRANCH(x);
+  return FORTYTWO;
+}
+#endif
+// CHECK-IMP: remark: importing module './hu-01.h' from 'hu-01.pcm'
Index: clang/lib/Frontend/PrintPreprocessedOutput.cpp
===
--- clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -96,6 +96,7 @@
   bool UseLineDirectives;
   bool IsFirstFileEntered;
   bool MinimizeWhitespace;
+  bool DirectivesOnly;
 
   Token PrevTok;
   Token PrevPrevTok;
@@ -103,12 +104,13 @@
 public:
   PrintPPOutputPPCallbacks(Preprocessor &pp, raw_ostream &os, bool lineMarkers,
bool defines, bool DumpIncludeDirectives,
-   bool UseLineDirectives, bool MinimizeWhitespace)
+   bool UseLineDirectives, bool MinimizeWhitespace,
+   bool DirectivesOnly)
   : PP(pp), SM(PP.getSourceManager()), ConcatInfo(PP), OS(os),
 DisableLineMarkers(lineMarkers), DumpDefines(defines),
 DumpIncludeDirectives(DumpIncludeDirectives),
 UseLineDirectives(UseLineDirectives),
-MinimizeWhitespace(MinimizeWhitespace) {
+MinimizeWhitespace(MinimizeWhitespace), DirectivesOnly(DirectivesOnly) {
 CurLine = 0;
 CurFilename += "";
 EmittedTokensOnThisLine = false;
@@ -467,12 +469,21 @@
 void PrintPPOutputPPCallbacks::MacroDefined(const Token &MacroNameTok,
 const MacroDirective *MD) {
   const MacroInfo *MI = MD->getMacroInfo();
-  // Only print out macro definitions in -dD mode.
-  if (!DumpDefines ||
+  // Print out macro definitions in -dD mode and when we have -fdirectives-only
+  // for C++20 header units.
+  if ((!DumpDefines && !DirectivesOnly) ||
   // Ignore __FILE__ etc.
-  MI->isBuiltinMacro()) return;
+  MI->isBuiltinMacro())
+return;
 
-  MoveToLine(MI->getDefinitionLoc(), /*RequireStartOfLine=*/true);
+  SourceLocation DefLoc = MI->getDefinitionLoc();
+  if (DirectivesOnly && !MI->isUsed()) {
+SourceManager &SM = PP.getSourceManager();
+if (SM.isWrittenInBuiltinFile(DefLoc) ||
+SM.isWrittenInCommandLineFile(DefLoc))
+  return;
+  }
+  MoveToLine(DefLoc, /*RequireStartOfLine=*/true);
   PrintMacroDefinition(*MacroNameTok.getIdentifierInfo(), *MI, PP, OS);
   setEmittedDirectiveOnThisLine();
 }
@@ -480,8 +491,10 @@
 void PrintPPOutputPPCallbacks::MacroUndefined(const Token &MacroNameTok,
   const MacroDefinition &MD,
   const MacroDirective *Undef) {
-  // Only print out macro definitions in -dD mode.
-  if (!DumpDefines) return;
+  // Print out macro definitions in -dD mode and when we have -fdirectives-only
+  // for C++20 header units.
+  if (!DumpDefines && !DirectivesOnly)
+return;
 
   MoveToLin

[PATCH] D121588: [C++20][Modules][Driver][HU 1/N] Initial handling for -xc++-{system,user}-header.

2022-03-14 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a project: All.
iains added reviewers: rsmith, urnathan, ChuanqiXu.
iains added a subscriber: clang-modules.
iains published this revision for review.
iains added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This is a set of 4 patches that adds the driver-side support for C++20 header 
modules.

We use the same user-facing options as the existing implementation in GCC 
(there seems no engineering reason to deviate from this and it makes things 
easier for users and build system alike).

1/4 - this patch introduces file types for header unit headers to be searched 
for in the user or system paths (or to be given an absolute pathname).
2/4 - adds the -fmoduke-header{.=} command line options
3/4 - is a user-convenience change that allows "foo.h" without complaining 
about C code used in C++ compilations (since we know that the user has already 
specified the intent).
4/4 - adds the -fdirectives-only command that produces pre-processor output 
which retains the macro definitions/undefs that will be present in the built 
header unit.


This adds file types and handling for three input types, representing a C++20
header unit source:

1. When provided with a complete pathname for the header.
2. For a header to be looked up (by the frontend) in the user search paths
3. For a header to be looked up in the system search paths.

We also add a pre-processed file type (although that is a single type, 
regardless
of the original input type).

These types may be specified with -xc++-{user,system,header-unit}-header .

These types allow us to disambiguate header unit jobs from PCH ones, and thus
we handle these differently from other header jobs in two ways:

1. The job construction is altered to build a C++20 header unit (rather than a 
PCH file, as would be the case for other headers).
2. When the type is "user" or "system" we defer checking for the file until the 
front end is run, since we need to look up the header in the relevant paths 
which are not known at this point.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121588

Files:
  clang/include/clang/Driver/Types.def
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Driver/Types.cpp
  clang/lib/Frontend/FrontendOptions.cpp
  clang/test/Driver/Inputs/header-unit-01.hh
  clang/test/Driver/cxx20-header-units-01.cpp

Index: clang/test/Driver/cxx20-header-units-01.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-header-units-01.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang++ -### -std=c++20 -xc++-user-header foo.h 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER %s
+
+// RUN: %clang++ -### -std=c++20 -xc++-system-header vector 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-SYSTEM %s
+
+// RUN: %clang++ -### -std=c++20 -xc++-header-unit-header %S/Inputs/header-unit-01.hh 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-ABS %s -DTDIR=%S/Inputs
+
+// CHECK-USER: "-emit-header-unit"
+// CHECK-USER-SAME: "-o" "foo.pcm"
+// CHECK-USER-SAME: "-x" "c++-user-header" "foo.h"
+// CHECK-SYSTEM: "-emit-header-unit"
+// CHECK-SYSTEM-SAME: "-o" "vector.pcm"
+// CHECK-SYSTEM-SAME: "-x" "c++-system-header" "vector"
+// CHECK-ABS: "-emit-header-unit"
+// CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
+// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
Index: clang/lib/Frontend/FrontendOptions.cpp
===
--- clang/lib/Frontend/FrontendOptions.cpp
+++ clang/lib/Frontend/FrontendOptions.cpp
@@ -27,6 +27,7 @@
   .Cases("C", "cc", "cp", Language::CXX)
   .Cases("cpp", "CPP", "c++", "cxx", "hpp", "hxx", Language::CXX)
   .Case("cppm", Language::CXX)
+  .Case("iih", InputKind(Language::CXX).getPreprocessed())
   .Case("iim", InputKind(Language::CXX).getPreprocessed())
   .Case("cl", Language::OpenCL)
   .Case("clcpp", Language::OpenCLCXX)
Index: clang/lib/Driver/Types.cpp
===
--- clang/lib/Driver/Types.cpp
+++ clang/lib/Driver/Types.cpp
@@ -65,9 +65,16 @@
   return Id == TY_CXXModule || Id == TY_PP_CXXModule;
 }
 
+static bool isPreprocessedHeaderUnitType(ID Id) {
+  return Id == TY_CXXSHeader || Id == TY_CXXUHeader || Id == TY_CXXHUHeader ||
+ Id == TY_PP_CXXHeaderUnit;
+}
+
 types::ID types::getPrecompiledType(ID Id) {
   if (isPreprocessedModuleType(Id))
 return TY_ModuleFile;
+  if (isPreprocessedHeaderUnitType(Id))
+return TY_HeaderUnit;
   if (onlyPrecompileType(Id))
 return TY_PCH;
   return TY_INVALID;
@@ -139,6 +146,10 @@
   case TY_CLHeader:
   case TY_ObjCHeader: case TY_PP_ObjCHeader:
   case TY_CXXHeader: case TY_PP_CXXHeader:
+  case TY_CXXSHeader:
+  case TY_CXXUHeader:
+  case TY_CXXHUHeader:
+  case TY_PP_CXXHeaderUnit:
   case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader:
   case TY_CXXMod

[PATCH] D121589: [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-03-14 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a subscriber: dang.
Herald added a project: All.
iains added reviewers: rsmith, urnathan, ChuanqiXu.
iains published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

These command-line flags are alternates to providing the -x
c++-*-header indicators that we are building a header unit.

Act on fmodule-header= for headers on the c/l:

If we have x.hh -fmodule-header, then we should treat that header
as a header unit input (equivalent to -xc++-header-unit-header x.hh).

Likewise, for fmodule-header={user,system} the source should be now
recognised as a header unit input (since this can affect the job list
that we need).

It's not practical to recognise a header without any suffix so
-fmodule-header=system foo isn't going to happen. Although
-fmodule-header=system foo.hh will work OK.  However we can make it
work if the user indicates that the item without a suffix is a valid
header. (so -fmodule-header=system -xc++-header vector)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121589

Files:
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-02.cpp

Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -0,0 +1,32 @@
+// Test user-facing command line options to generate C++20 header units.
+
+// RUN: %clang++ -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER %s
+
+// RUN: %clang++ -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
+
+// RUN: %clang++ -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-system-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang++ -### -std=c++20 -fmodule-header=system \
+// RUN: -xc++-header vector 2>&1 | FileCheck -check-prefix=CHECK-SYS2 %s
+
+// RUN: %clang++ -### -std=c++20 -fmodule-header %S/Inputs/header-unit-01.hh \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-ABS %s -DTDIR=%S/Inputs
+
+// CHECK-USER: "-emit-header-unit"
+// CHECK-USER-SAME: "-o" "foo.pcm"
+// CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
+
+// CHECK-SYS1: "-emit-header-unit"
+// CHECK-SYS1-SAME: "-o" "foo.pcm"
+// CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
+
+// CHECK-SYS2: "-emit-header-unit"
+// CHECK-SYS2-SAME: "-o" "vector.pcm"
+// CHECK-SYS2-SAME: "-x" "c++-system-header" "vector"
+
+// CHECK-ABS: "-emit-header-unit"
+// CHECK-ABS-SAME: "-o" "header-unit-01.pcm"
+// CHECK-ABS-SAME: "-x" "c++-header-unit-header" "[[TDIR]]/header-unit-01.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -188,7 +188,8 @@
DiagnosticsEngine &Diags, std::string Title,
IntrusiveRefCntPtr VFS)
 : Diags(Diags), VFS(std::move(VFS)), Mode(GCCMode),
-  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone), LTOMode(LTOK_None),
+  SaveTemps(SaveTempsNone), BitcodeEmbed(EmbedNone),
+  CXX20HeaderType(HeaderMode_None), LTOMode(LTOK_None),
   ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
   DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
   CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false),
@@ -1241,6 +1242,37 @@
   BitcodeEmbed = static_cast(Model);
   }
 
+  // Setting up the jobs for some precompile cases depends on whether we are
+  // treating them as PCH, implicit modules or C++20 ones.
+  // TODO: inferring the mode like this seems fragile (it meets the objective
+  // of not requiring anything new for operation, however).
+  const Arg *Std = Args.getLastArg(options::OPT_std_EQ);
+  ModulesModeCXX20 =
+  !Args.hasArg(options::OPT_fmodules) && Std &&
+  (Std->containsValue("c++20") || Std->containsValue("c++2b") ||
+   Std->containsValue("c++2a") || Std->containsValue("c++latest"));
+
+  // Process -fmodule-header{=} flags.
+  if (Arg *A = Args.getLastArg(options::OPT_fmodule_header_EQ,
+   options::OPT_fmodule_header)) {
+// These flags force C++20 handling of headers.
+ModulesModeCXX20 = true;
+if (A->getOption().matches(options::OPT_fmodule_header))
+  CXX20HeaderType = HeaderMode_Default;
+else {
+  StringRef ArgName = A->getValue();
+  unsigned Kind = llvm::StringSwitch(ArgName)
+  .Case("user", HeaderMode_User)
+  .Case("system", HeaderMode_System)
+  .Default(~0U);
+  if (Kind == ~0U) {
+Diags.Report(diag::err_drv_invalid_value)
+<< A->getAsString(Args) << ArgName;
+  } else
+CXX20HeaderType = static_cast(Kind);
+}
+  }
+
   std::unique_

[PATCH] D121590: [C++20][Modules][Driver][HU 3/N] Handle foo.h with -fmodule-header and/or C++ invocation.

2022-03-14 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a project: All.
iains added reviewers: rsmith, urnathan, ChuanqiXu.
iains published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Allow an invocation like clang -fmodule-header bar.h (which will be a C++
compilation, but using a header which will be recognised as a C one).

Also  we do not want to produce:
 "treating 'c-header' input as 'c++-header' when in C++ mode"
diagnostics when the user has been specific about the intent.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121590

Files:
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/cxx20-header-units-02.cpp


Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- clang/test/Driver/cxx20-header-units-02.cpp
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -3,6 +3,9 @@
 // RUN: %clang++ -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-USER %s
 
+// RUN: %clang++ -### -std=c++20 -fmodule-header=user foo.h  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER1 %s
+
 // RUN: %clang++ -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
 
@@ -19,6 +22,10 @@
 // CHECK-USER-SAME: "-o" "foo.pcm"
 // CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
 
+// CHECK-USER1: "-emit-header-unit"
+// CHECK-USER1-SAME: "-o" "foo.pcm"
+// CHECK-USER1-SAME: "-x" "c++-user-header" "foo.h"
+
 // CHECK-SYS1: "-emit-header-unit"
 // CHECK-SYS1-SAME: "-o" "foo.pcm"
 // CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2415,7 +2415,9 @@
 types::ID OldTy = Ty;
 Ty = types::lookupCXXTypeForCType(Ty);
 
-if (Ty != OldTy)
+// Do not complain about foo.h, when we are known to be processing
+// it as a C++20 header unit.
+if (Ty != OldTy && !(OldTy == types::TY_CHeader && 
hasHeaderMode()))
   Diag(clang::diag::warn_drv_treating_input_as_cxx)
   << getTypeName(OldTy) << getTypeName(Ty);
   }
@@ -2440,8 +2442,11 @@
 }
 
 // Disambiguate headers that are meant to be header units from those
-// intended to be PCH.
-if (Ty == types::TY_CXXHeader && hasHeaderMode())
+// intended to be PCH.  Avoid missing '.h' cases that are  counted as
+// C headers by default - we know we are in C++ mode and we do not
+// want to issue a complaint about compiling things in the wrong mode.
+if ((Ty == types::TY_CXXHeader || Ty == types::TY_CHeader) &&
+hasHeaderMode())
   Ty = CXXHeaderUnitType(CXX20HeaderType);
   } else {
 assert(InputTypeArg && "InputType set w/o InputTypeArg");


Index: clang/test/Driver/cxx20-header-units-02.cpp
===
--- clang/test/Driver/cxx20-header-units-02.cpp
+++ clang/test/Driver/cxx20-header-units-02.cpp
@@ -3,6 +3,9 @@
 // RUN: %clang++ -### -std=c++20 -fmodule-header=user foo.hh  2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-USER %s
 
+// RUN: %clang++ -### -std=c++20 -fmodule-header=user foo.h  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-USER1 %s
+
 // RUN: %clang++ -### -std=c++20 -fmodule-header=system foo.hh 2>&1 | \
 // RUN:   FileCheck -check-prefix=CHECK-SYS1 %s
 
@@ -19,6 +22,10 @@
 // CHECK-USER-SAME: "-o" "foo.pcm"
 // CHECK-USER-SAME: "-x" "c++-user-header" "foo.hh"
 
+// CHECK-USER1: "-emit-header-unit"
+// CHECK-USER1-SAME: "-o" "foo.pcm"
+// CHECK-USER1-SAME: "-x" "c++-user-header" "foo.h"
+
 // CHECK-SYS1: "-emit-header-unit"
 // CHECK-SYS1-SAME: "-o" "foo.pcm"
 // CHECK-SYS1-SAME: "-x" "c++-system-header" "foo.hh"
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -2415,7 +2415,9 @@
 types::ID OldTy = Ty;
 Ty = types::lookupCXXTypeForCType(Ty);
 
-if (Ty != OldTy)
+// Do not complain about foo.h, when we are known to be processing
+// it as a C++20 header unit.
+if (Ty != OldTy && !(OldTy == types::TY_CHeader && hasHeaderMode()))
   Diag(clang::diag::warn_drv_treating_input_as_cxx)
   << getTypeName(OldTy) << getTypeName(Ty);
   }
@@ -2440,8 +2442,11 @@
 }
 
 // Disambiguate headers that are meant to be header units from those
-// intended to be PCH.
-if (Ty == types::TY_CXXHeader && hasHeaderMode())
+// intended to be PCH.  Avoid missing '.h' cases that are  counted as
+// C headers by default - we know we are in C++ mode and we do not
+// want to issue a complain

[PATCH] D121591: [C++20][Modules][Driver][HU 4/N] Add fdirectives-only mode for preprocessing output.

2022-03-14 Thread Iain Sandoe via Phabricator via cfe-commits
iains created this revision.
Herald added a project: All.
iains added reviewers: rsmith, urnathan, ChuanqiXu.
iains published this revision for review.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

When the -fdirectives-only option is used together with -E, the preprocessor
output reflects evaluation of if/then/else directives.

Thus it preserves macros that are still live after such processing.
This output can be consumed by a second compilation to produce a header unit.

We automatically invoke this (with -E) when we know that the job produces a
header unit so that the preprocessed output reflects the macros that will be
defined when the binary HU is emitted.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121591

Files:
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cxx20-fdirectives-only.cpp


Index: clang/test/Driver/cxx20-fdirectives-only.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-fdirectives-only.cpp
@@ -0,0 +1,20 @@
+// Test -fdirectives-only cases.
+
+// We can manullay specify fdirectives-only, for any pre-processor job.
+// RUN: %clang++ -### -std=c++20 -E -fdirectives-only foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-NON-HU %s
+
+// Check that we automatically append -fdirectives-only for header-unit
+// preprocessor jobs.
+// RUN: %clang++ -### -std=c++20 -E -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-HU %s
+
+// CHECK-NON-HU: "-E"
+// CHECK-NON-HU-SAME: "-fdirectives-only"
+// CHECK-NON-HU-SAME: "-o" "-"
+// CHECK-NON-HU-SAME: "-x" "c++-header" "foo.hh"
+
+// CHECK-HU: "-E"
+// CHECK-HU-SAME: "-fdirectives-only"
+// CHECK-HU-SAME: "-o" "-"
+// CHECK-HU-SAME: "-x" "c++-user-header" "foo.hh"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4592,6 +4592,8 @@
   if (Args.hasArg(options::OPT_rewrite_objc) &&
   !Args.hasArg(options::OPT_g_Group))
 CmdArgs.push_back("-P");
+  else if (JA.getType() == types::TY_PP_CXXHeaderUnit)
+CmdArgs.push_back("-fdirectives-only");
 }
   } else if (isa(JA)) {
 CmdArgs.push_back("-emit-obj");
@@ -6739,6 +6741,10 @@
   if (RewriteImports)
 CmdArgs.push_back("-frewrite-imports");
 
+  if (Args.hasFlag(options::OPT_fdirectives_only,
+   options::OPT_fno_directives_only, false))
+CmdArgs.push_back("-fdirectives-only");
+
   // Enable rewrite includes if the user's asked for it or if we're generating
   // diagnostics.
   // TODO: Once -module-dependency-dir works with -frewrite-includes it'd be
Index: clang/lib/Driver/Driver.cpp
===
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -4251,10 +4251,14 @@
   OutputTy = types::TY_Dependencies;
 } else {
   OutputTy = Input->getType();
+  // For these cases, the preprocessor is only translating forms, the 
Output
+  // still needs preprocessing.
   if (!Args.hasFlag(options::OPT_frewrite_includes,
 options::OPT_fno_rewrite_includes, false) &&
   !Args.hasFlag(options::OPT_frewrite_imports,
 options::OPT_fno_rewrite_imports, false) &&
+  !Args.hasFlag(options::OPT_fdirectives_only,
+options::OPT_fno_directives_only, false) &&
   !CCGenDiagnostics)
 OutputTy = types::getPreprocessedType(OutputTy);
   assert(OutputTy != types::TY_INVALID &&


Index: clang/test/Driver/cxx20-fdirectives-only.cpp
===
--- /dev/null
+++ clang/test/Driver/cxx20-fdirectives-only.cpp
@@ -0,0 +1,20 @@
+// Test -fdirectives-only cases.
+
+// We can manullay specify fdirectives-only, for any pre-processor job.
+// RUN: %clang++ -### -std=c++20 -E -fdirectives-only foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-NON-HU %s
+
+// Check that we automatically append -fdirectives-only for header-unit
+// preprocessor jobs.
+// RUN: %clang++ -### -std=c++20 -E -fmodule-header=user foo.hh  2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-HU %s
+
+// CHECK-NON-HU: "-E"
+// CHECK-NON-HU-SAME: "-fdirectives-only"
+// CHECK-NON-HU-SAME: "-o" "-"
+// CHECK-NON-HU-SAME: "-x" "c++-header" "foo.hh"
+
+// CHECK-HU: "-E"
+// CHECK-HU-SAME: "-fdirectives-only"
+// CHECK-HU-SAME: "-o" "-"
+// CHECK-HU-SAME: "-x" "c++-user-header" "foo.hh"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4592,6 +4592,8 @@
   if (Args.hasArg(options::OPT_rewrite_objc) &&
   !Args.hasArg(options::OPT_g_Group))
 CmdArgs.push_b

[PATCH] D120540: [Driver] Enable to use C++20 modules standalone by -fcxx-modules

2022-03-15 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

I am still concerned that there is an expectation that. the fcxx-modules option 
is connected with clang modules.
.. see, for example:

https://github.com/llvm/llvm-project/blob/d90d45fc9029cc7dbb6d44798f51131df6b2eef1/clang/lib/Driver/ToolChains/Clang.cpp#L3579

and

https://github.com/llvm/llvm-project/blob/875782bd9ea322445dd41213ca6bbf70169e741d/clang/include/clang/Driver/Options.td#L5549

(those are the two places that the option currently appears in the code; test 
cases that have the option seem to be connected with clang/implicit modules).

So I will defer to other folks to comment further.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D120540/new/

https://reviews.llvm.org/D120540

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121588: [C++20][Modules][Driver][HU 1/N] Initial handling for -xc++-{system,user}-header.

2022-03-15 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

note: I do not plan to fix the formatting issue in clang/lib/Driver/Types.cpp, 
since I am adding one line and the format change would mean ≈ 110 lines of 
changes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121588/new/

https://reviews.llvm.org/D121588

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121589: [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-03-15 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D121589#3381343 , @ChuanqiXu wrote:

>> It's not practical to recognise a header without any suffix so
>
> -fmodule-header=system foo isn't going to happen.
>
> May I ask the reason? It looks not so good with `-fmodule-header=system 
> -xc++-header vector`

OK. One should never say "never" ;) , it would be nicer if we could avoid this.

... it would require a policy change in the driver - since we cannot recognise 
files like 'vector' as headers, they are currently unclaimed (which means that 
they default to being considered as linker inputs).

This is a long-standing (forever, I suspect) situation;
Although we could make it so that if we see certain options, all unknown inputs 
get claimed as source files (or headers) I wonder how much build system code 
that might break.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121589/new/

https://reviews.llvm.org/D121589

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D120540: [Driver] Enable to use C++20 modules standalone by -fcxx-modules

2022-03-15 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

I'm not sure it is exactly chaos, but it is certainly fragile and somewhat 
hard(er than necessary) to maintain.

We (@ChuanqiXu  and I at least) agree that there should be some way to make 
"which modules mode" unambiguous in both the driver and the compiler (I think 
we're only debating how/which flag to use)

The end game objective is that "when the compiler is processing for C++20 or 
later, then it should default to C++20+ modules". 
IMO, knowing "which modules mode" is in force does not alter this - if anything 
it ought to simplify checking whether we have completed migration (whatever 
that ends up meaning).

Presumably, we are never going to delete the other options (e.g. -fmodules etc) 
they would (perhaps) become deprecated and then "do nothing". OTOH, perhaps 
that mode will be needed by existing users for some considerable time.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D120540/new/

https://reviews.llvm.org/D120540

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D121098: [C++20][Modules][HU 4/5] Handle pre-processed header units.

2022-03-15 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D121098#3378375 , @ChuanqiXu wrote:

> It lacks tests. This is not NFC, right?

Right, (there are tests with the next patch which introduces the mechanism for 
producing the pre-processed output) 
but, I will find a suitable one for this...

> ---
>
> I am a little bit confused for the intuition. Couldn't we just import the 
> pre-processed header? What's the problem? Could you elaborate on this?

We cannot import a pre-processed file; the preprocessed file is still source 
code, not a CMI.

In addition, the pre-processor output for a header unit requires further 
pre-processing on read.
This is because a header unit actually preserves some of the pre-processor 
information [macro definitions] (which would normally be discarded after phase 
4).

Header units are identifiable by a name (in common with GCC, we make the name 
== the path by which the header is specified) -- that name is intentionally not 
a  legal named module name (neither is it, in general, a legal identifier).


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D121098/new/

https://reviews.llvm.org/D121098

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D120540: [Driver] Enable to use C++20 modules standalone by -fcxx-modules

2022-03-16 Thread Iain Sandoe via Phabricator via cfe-commits
iains added a comment.

In D120540#3384644 , @ChuanqiXu wrote:

> @rsmith told me that the ideal situation would combine C++20 modules and 
> clang modules together in D113391 

Maybe I understand something slightly different; that we should migrate to a 
situation where compiling C++ code //**with no other contradicting options**//, 
would produce C++20 modules.  Preferably, for most users that means no special 
options would be needed for the standardised modules.

> I think the most important thing here is to get in consensus for the module 
> status. Here might be some helpful questions for the goal:
>
> - Should C++20 modules and Clang modules be exclusive from each other?
>   - If yes, we could take the idea ` -fmodules= {clang, c++20, none...} ` and 
> forbid the combination of `-fmodules  -std=c++20`. And we could use variable 
> `Modules` to indicate clang modules and `CPlusPlusModules` to indicate c++20 
> modules.
> - If no, it implies that we could use c++20 modules and clang modules 
> together. So the combination of `-fmodules -std=c++20` or even `-fmodules 
> -fcxxmodules` makes sense. It implies that we could use the grammar of clang 
> module extension or c++20 modules. This is decision from D113391 
> . Here are some further questions:

In my input, there was no intention to forbid `-fmodules  -std=c++20`,  quite 
the opposite (it would be OK).
I am suggesting that  the presence of `fmodules` on the command line would be a 
statement that the user wanted `clang modules` (and that would be perfectly OK 
in conjunction with C++20). 
... But that would switch off C++20 modules mode because there are 
incompatibilities at present (in particular it means treating headers 
differently - and possibly sub-module visibility).  There might come a time 
when clang modules are identical to C++20 ones, but I could imagine that would 
be some considerable time in the future - because end users would have to 
migrate.

> - Would it be very hard to implement or maintain?

once we have a firm plan for which things are allowed together it is not hard 
to maintain - what is hard to maintain is a situation in which we are not sure 
of exactly what we should be producing ...

> - We lack a variable to indicate clang modules only. Currently, we couldn't 
> use `Modules` to indicate clang modules since `Modules` is true if we turned 
> C++20 modules on. `Modules` indicate either clang module or c++20 module is 
> enabled. Or we could think it means the common parts of the two features.

we could make such a variable easily - if the decision was made to do it (what 
could be a little harder is to separate out the modules command line options 
into mutually-exclusive groups).

> The most important technical question might be `Would it be very hard to 
> implement or maintain?`. From my experience, I think it is implementable. But 
> I **feel** it is not easy to maintain. We don't have the experience since 
> C++20 modules are not in the state of maintaining now.
>
> I don't have strong opinions for the concrete decision. But I think it is 
> very important to get in consensus. @iains @Bigcheese

In this processes, I am not a major stakeholder - just an interested party as a 
coder and user - the call is down to @rsmtih and @Bigcheese.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D120540/new/

https://reviews.llvm.org/D120540

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


  1   2   3   4   5   >