[clang] [Serialization] Load Specializations Lazily (PR #76774)

2024-03-29 Thread Iain Sandoe via cfe-commits

https://github.com/iains commented:

I am happy to defer to @vgvassilev et al. on this one.

https://github.com/llvm/llvm-project/pull/76774
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce -fexperimental-modules-reduced-bmi (PR #85050)

2024-03-29 Thread Iain Sandoe via cfe-commits

iains wrote:

> Got it. I've renamed the flag as `-fexperimental-modules-reduced-bmi`.

Thanks.

> I feel the suggestion like let users to use `-Xclang` options look odd..

I think the point here is that we want **expert** users to try this out (with 
understanding that it might not behave exactly as they expect).  Because it is 
experimental, it is not yet ready for "end users" - I would expect expert users 
to be able to deal with -Xclang x  (but I will not insist, it's just a 
suggestion)


https://github.com/llvm/llvm-project/pull/85050
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] [Itanium ABI] Generate the vtable in the module unit of dynamic classes (PR #75912)

2024-03-29 Thread Iain Sandoe via cfe-commits

https://github.com/iains commented:

I am going to defer to @rjmccall and @dwblaikie on this one (the comments so 
far seem reasonable to me).


https://github.com/llvm/llvm-project/pull/75912
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce -fmodules-reduced-bmi (PR #85050)

2024-03-26 Thread Iain Sandoe via cfe-commits

iains wrote:

> > > @iains @dwblaikie Understood. And I thought the major problem is that 
> > > there are a lot flags from clang modules. And it is indeed confusing. But 
> > > given we have to introduce new flags in this case, probably we can only 
> > > try to make it more clear by better documents.
> > 
> > 
> > So you do not think it possible to restrict the new flag to be "internal" 
> > (i.e. cc1-only) and to put some _temporary_ driver processing to handle 
> > that? (I agree that this is an unusual mechanism, but the idea is to 
> > recognise that the driver-side processing is only expected to me temporary).
> 
> I have no idea how can we make that. We still need the users to provide 
> something to enable reduced BMI. And I think it is symmetric to a new flag.

What I mean is that (a) we need the internal 'cc1' flag permanently; but (b) we 
do not expect to need a user-facing driver flag permanently.  and (c) We want 
to allow users to try this out.

I am suggesting we could say "to try this out use -Xclang 
-fmodules-reduced-bmi" and have _temporary_ code in the driver to deal with the 
changes needed to phasing.

If this is not possible. then I suppose I am a bit sad that we keep saying 
'there are too many modules options' - but yet still add more.   however - we 
need to make progress, so if the suggestion here is really a non-starter .. 
then such is life.

Perhaps the second suggestion (-fexperimental-x options) could be discussed 
at the project level.


https://github.com/llvm/llvm-project/pull/85050
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce -fgen-reduced-bmi (PR #85050)

2024-03-25 Thread Iain Sandoe via cfe-commits

https://github.com/iains edited https://github.com/llvm/llvm-project/pull/85050
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce -fgen-reduced-bmi (PR #85050)

2024-03-25 Thread Iain Sandoe via cfe-commits


@@ -3031,6 +3032,11 @@ defm skip_odr_check_in_gmf : BoolOption<"f", 
"skip-odr-check-in-gmf",
   "Perform ODR checks for decls in the global module fragment.">>,
   Group;
 
+def gen_reduced_bmi : Flag<["-"], "fgen-reduced-bmi">,

iains wrote:

If this is going to be a user-facing flag (even for a few releases) then I 
think it should be spelled in a way that make it modules-relatated (e.g. 
-fmodules-reduce-bmi, or -fmodules-minimise-bmi),  as you know I'm not a fan of 
increasing the already huge number of modules-related user-facing options... 
(but I'll comment on that separately)

https://github.com/llvm/llvm-project/pull/85050
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce -fgen-reduced-bmi (PR #85050)

2024-03-25 Thread Iain Sandoe via cfe-commits

https://github.com/iains commented:


I have no issue with the general intention or phasing here; my main concern is 
that we are introducing [yet] another user-facing modules option that actually 
we intend will become irrelevant after a few releases.

In practice, removing user-facing options is not very easy.

So:
  1. Perhaps we could have only the cc1 option and you could introduce some 
temporary handling in the driver to recognise it and amend the --precompile 
behaviour?
  2. Maybe the project could introduce something like -fexperimental-- 
with a clear statement that fexperimental flags cannot be relied on to be 
stable (or even present) in any future release)?

https://github.com/llvm/llvm-project/pull/85050
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce reduced BMI (PR #75894)

2024-03-06 Thread Iain Sandoe via cfe-commits

iains wrote:

I have no further comments so LGTM if there are no objections from the other 
reviewers this week.

https://github.com/llvm/llvm-project/pull/75894
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce reduced BMI (PR #75894)

2024-03-05 Thread Iain Sandoe via cfe-commits

iains wrote:

Do you expect to make any changes to type streaming?


https://github.com/llvm/llvm-project/pull/75894
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce reduced BMI (PR #75894)

2024-03-05 Thread Iain Sandoe via cfe-commits


@@ -830,6 +843,19 @@ class PCHGenerator : public SemaConsumer {
   bool hasEmittedPCH() const { return Buffer->IsComplete; }
 };
 
+class ReducedBMIGenerator : public PCHGenerator {
+public:
+  ReducedBMIGenerator(const Preprocessor , InMemoryModuleCache ,
+  StringRef OutputFile, std::shared_ptr Buffer,
+  bool IncludeTimestamps);
+
+  void HandleTranslationUnit(ASTContext ) override;
+};
+
+/// If the definition may impact the ABI. If yes, we're allowed to eliminate
+/// the definition of D in reduced BMI.
+bool MayDefAffectABI(const Decl *D);

iains wrote:

Perhaps this would be better named ShouldElideDecl?
I also find the comment a bit confusing - normally if something affects ABI we 
cannot change it (so I think we really mean that this would introduce a break 
into the 'module interface ABI').  Maybe the comment could better refer to the 
bug and/or descriiption of the issue.

https://github.com/llvm/llvm-project/pull/75894
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce reduced BMI (PR #75894)

2024-03-05 Thread Iain Sandoe via cfe-commits

iains wrote:


* I do not want to block progress, so let's move forward with this patch for 
now.

* It seems to me (as we found with GMF decl elision) that the process is quite 
a bit more complex than simply omitting a decl.  We need to elide other decls 
that are then unused (e.g. decls local to an elided function body) and also 
avoid emitting types that are now no longer existent.

The process seems to me to be either one of:
 - rewriting the AST (which is why my patch set picked the use of the plugin 
API since that is the purpose there).
 - walking the AST and marking entities as used / not used / elided.
 
 It still feels to me to be better to have clear separation of this work from 
the work of streaming - but if we can make clear layers within the streaming, 
then maybe the maintenance will not be too hard.


https://github.com/llvm/llvm-project/pull/75894
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce reduced BMI (PR #75894)

2024-01-04 Thread Iain Sandoe via cfe-commits

iains wrote:


> Like I said in the commit message, this patch itself doesn't involve anything 
> relevant to user interfaces. I left it to the latter patches.

Are you in a position to post the next patch (at least as a draft)?  That would 
help me see the direction.

> > * I was concerned from earlier conversations that this design might require 
> > a codegen back end to be instantiated to allow the reduced BMI (which would 
> > be bad for --precompile/-fmodule-only type jobs). Any comments?
> 
> I am not sure if I understand this. What does it mean "require a codegen back 
> end to be instantiated to allow the reduced BMI "? Do you mean to not touch 
> CodeGen part or to not touch the CodeGen action? My local patch touched the 
> code gen action without touching any real CodeGen related things.

> > the reduced BMI (which would be bad for --precompile/-fmodule-only type 
> > jobs)
> 
> For `--precompile/-fmodule-only` type jobs, I'll create another action to 
> make it (Similar to existing `GenerateModuleInterfaceAction`). Then both of 
> the actions will try to reuse the same consumer `ReducedBMIGenerator` to 
> avoid repeated works.

OK, that answers my concern (which was that we might have to add the code-gen 
backend to a --precompile if that was the mechanism used to do the BMI 
reduction).

> > * It would be better to avoid introducing more layering violations but, as 
> > we discussed in face-to-face meetings, I have less concern on the output 
> > side.  It still seems to me that the best model is one where we have AST 
> > transforms (that very likely need Sema to be correct) and then the 
> > serializer is a simple as possible.
> 
> Yeah, it should be less concerned. BTW, currently the simpler 
> serializer/deserializer should be ASTRecordWriter/ASTRecordReader. And the 
> current ASTReader/ASTWriter takes some semantical job.

... and, on the reader side, that already gives us some big problems (as I say, 
I am less concerned on the writer side, but who can see the whole future?).

> > so something like
> > ```
> > raw AST + > codegen (when required)
> > |
> > + => AST transforms > BMI output.
> > ```
> > As I understand the patch you are combining the transform with the output?
> 
> On the one hand, the **current** patch doesn't do that. The current patch is 
> almost a NFC patch. It belongs to the following patch. On the other hand, the 
> answer may be yes. Probably I did the `AST transforms` you said in the AST 
> Writer. I don't feel it is so awful.

Maybe not for the short-term relatively simple tasks - but we should also take 
a view on the medium and longer term (for example, GMF decl elision is likely 
to be helpful to users in reducing both the size of the BMI and the number of 
decls that need merging on input).

We need the AST in this path to be mutable (including removal of decls); that 
way each transform can be maintained as a separate entity - I think that if we 
end up doing "many transforms" as part of the output, it will become very 
confusing.

_(although, to be clear, i**n the short-term we might agree to do the work in 
the output** - I really do think it would be bad to make that the long term 
mechanism)._

> Given all of us loves reduced BMI, I suggest we can fosus on current patch 
> then discuss user interfaces related things in the next patch after this got 
> landed.

We do all want to produce the reduced BMI, I agree; but we also always have 
limited resources to do the work, so that it would be good to try and pick an 
implementation that will be smooth for the future work too.

I understand the purpose of the current patch better now - and will try to take 
a more detailed look over the next few days - as noted above, it would help 
very much to have a preview of the next patch in the series.


https://github.com/llvm/llvm-project/pull/75894
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Introduce reduced BMI (PR #75894)

2024-01-03 Thread Iain Sandoe via cfe-commits

iains wrote:

@ChuanqiXu9 very sorry for the slow review.  It would help me if the design was 
described in the commit message instead of trying to deduce it from the patch 
(maybe it's in a thread somewhere - so a cross-reference would help).

two immediate questions and one observation:

- I see you are using a multiplex consumer (actually, for some reason, I 
thought you were objecting to that part of my design); does this mean that your 
proposed solution can emit both the object and the reduced BMI from a single 
compilation job?

- I was concerned from earlier conversations that this design might require a 
codegen back end to be instantiated to allow the reduced BMI (which would be 
bad for --precompile/-fmodule-only type jobs). Any comments?

- It would be better to avoid introducing more layering violations but, as we 
discussed in face-to-face meetings, I have less concern on the output side.  It 
still seems to me that the best model is one where we have AST transforms (that 
very likely need Sema to be correct) and then the serializer is a simple as 
possible.

so  something like

raw AST   > codegen (when required)
   +
   + => AST transforms > BMI output.

As I understand the patch you are combining the transform with the output?


https://github.com/llvm/llvm-project/pull/75894
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Llvm modules on demand bmi (PR #71773)

2023-11-09 Thread Iain Sandoe via cfe-commits

iains wrote:

> > > > > > Whether we re-use wrapper code or make some new code is an 
> > > > > > implementation detail.
> > > > > > It does not actually prevent you from taking the two-phase approach 
> > > > > > ( currently , --precompile will be unchanged in action).
> > > > > 
> > > > > 
> > > > > It doesn't prevent the two-phase compilation model indeed. But it 
> > > > > introduces a new way about how we produce BMIs.
> > > > 
> > > > 
> > > > It allows us to produce a new kind of BMI - that carries a minimised 
> > > > content, applicable to the interface, otherwise it is no different to 
> > > > the case where two command lines are needed to produce an object and 
> > > > BMI..
> > > 
> > > 
> > > This is what thin BMI or interface BMI does.
> > 
> > 
> > Agreed - but the actual process of producing the interface BMI means taking 
> > the "full" AST (which is necessary to generate the object) and reducing it 
> > by applying suitable filters [like in my diagram].
> > This is done in an instance of the front end - it has either to be provided 
> > with the full AST or have a multiplexer that puts the full AST to code-gen 
> > and then applies filtering to the other path.
> 
> Yeah, the full AST is necessary to produce the object file. And the 
> ASTWriters can choose to not write parts of the AST to disk.

I am still strongly against making the filters part of the serialization 
process, we have learned that this is often a long-term mistake (e.g. doing 
decl merging in the AST reader).

The filtering should be thought of as as AST -> AST transform and the AST 
serializer should just write what is being given to it.

but, in either case this implies that the original AST is split into two paths 
- one going to the code-gen and one going to the BMI output;  that is what this 
patch series is doing, I believe.

> > > > The difficulty that I have pointed out is that if we preserve the 
> > > > existing scheme but want an Interface BMI - we then have to produce a 
> > > > third compile line in the driver that takes the Implementation BMI and 
> > > > produces the Interface BMI from it. We cannot avoid producing the 
> > > > intermediate BMI here because the jobs are created by the driver and 
> > > > executed by the compiler and we need to Implementation BMI to produce 
> > > > the object.
> > > 
> > > 
> > > Oh, this may be the root of the divergence here. In my mind, we can make 
> > > it without producing new compile jobs. I've already looked at the code. 
> > > We can avoid producing the intermediate BMI by skipping some phases in 
> > > the drivers.
> > 
> > 
> > I still do not understand the point here: the driver is not doing the work; 
> > the driver is preparing cc1 command lines - skipping phases does not 
> > achieve anything unless the front end is capable of producing both the BMI 
> > and object at the same time (any other solution means materialising the 
> > full BMI as an entity).
> 
> My point is that we need to introduce a new frontend action. And the driver's 
> job is to create the new frontend action.

It is not one action since a BMI could be combined with any other code-gen 
action.  Perhaps all that is needed is for the driver to add a `--bmi` flag to 
cc1 jobs that code-gen ?

Actually, since the FE can decide if a BMI is required from the source / AST 
there is actually no need to provide this (except, perhaps to disable it undeer 
some cases).



https://github.com/llvm/llvm-project/pull/71773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Llvm modules on demand bmi (PR #71773)

2023-11-09 Thread Iain Sandoe via cfe-commits

iains wrote:

> > > > Whether we re-use wrapper code or make some new code is an 
> > > > implementation detail.
> > > > It does not actually prevent you from taking the two-phase approach ( 
> > > > currently , --precompile will be unchanged in action).
> > > 
> > > 
> > > It doesn't prevent the two-phase compilation model indeed. But it 
> > > introduces a new way about how we produce BMIs.
> > 
> > 
> > It allows us to produce a new kind of BMI - that carries a minimised 
> > content, applicable to the interface, otherwise it is no different to the 
> > case where two command lines are needed to produce an object and BMI..
> 
> This is what thin BMI or interface BMI does.

Agreed - but the actual process of producing the interface BMI means taking the 
"full" AST (which is necessary to generate the object) and reducing it by 
applying suitable filters [like in my diagram].

This is done in an instance of the front end - it has either to be provided 
with the full AST or have a multiplexer that puts the full AST to code-gen and 
then applies filtering to the other path.

> > The difficulty that I have pointed out is that if we preserve the existing 
> > scheme but want an Interface BMI - we then have to produce a third compile 
> > line in the driver that takes the Implementation BMI and produces the 
> > Interface BMI from it. We cannot avoid producing the intermediate BMI here 
> > because the jobs are created by the driver and executed by the compiler and 
> > we need to Implementation BMI to produce the object.
> 
> Oh, this may be the root of the divergence here. In my mind, we can make it 
> without producing new compile jobs. I've already looked at the code. We can 
> avoid producing the intermediate BMI by skipping some phases in the drivers.

I still do not understand the point here: the driver is not doing the work; the 
driver is preparing cc1 command lines - skipping phases does not achieve 
anything unless the front end is capable of producing both the BMI and object 
at the same time (any other solution means materialising the full BMI as an 
entity).


https://github.com/llvm/llvm-project/pull/71773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Llvm modules on demand bmi (PR #71773)

2023-11-09 Thread Iain Sandoe via cfe-commits

iains wrote:


> > Whether we re-use wrapper code or make some new code is an implementation 
> > detail.
> > It does not actually prevent you from taking the two-phase approach ( 
> > currently , --precompile will be unchanged in action).
> 
> It doesn't prevent the two-phase compilation model indeed. But it introduces 
> a new way about how we produce BMIs.

It allows us to produce a new kind of BMI - that carries a minimised content, 
applicable to the interface, otherwise it is no different to the case where two 
command lines are needed to produce an object and BMI..

We can also produce the old "full implementation content" BMI if there is some 
reason to do so.

> The new way skipped the part of jobs we did in drivers for `.cppm`. Then this 
> is the divergence that I am concerning too.

I'm a bit confused by what you are saying here; the driver does not do any of 
the work, it simply prepares cc1 commands that are then executed by the 
compiler.  In the current case, we prepare two command lines one that builds an 
Implementation BMI and one that consumes that to produce an object.

We can simplify the driver because now it only needs to prepare one command 
line (even in the case that we decide to emulate the existing scheme by 
executing a `--precompile` followed by a `-c`.)

The difficulty that I have pointed out is that if we preserve the existing 
scheme but want an Interface BMI - we then have to produce a third compile line 
in the driver that takes the Implementation BMI and produces the Interface BMI 
from it.  We cannot avoid producing the intermediate BMI here because the jobs 
are created by the driver and executed by the compiler and we need to 
Implementation BMI to produce the object.

> In my mind, the proper solution is to introduce a new frontend action that 
> combines GenerateModuleInterfaceAction and CodeGenAction.

Initially, that seems like a great idea - until you look at how many possible 
compile jobs can combine with production of a BMI - for example, `-save-temps`, 
`-S`, `-emit-llvm` .. it would be a bad user experience if the only one that 
works was `-c`, right?

> Then in the driver part, we generate the new action in the precompile phase 
> for some combination of the input then we can skip the `Compile` phase.

We no longer need the driver to try to generate multiple steps, so it does not 
need to skip anything.
```
-- optimiize - codegen [obj]
  /
 [src] => preprocess = > parse => sema [full BMI]
  \
-- filter [Interface BMI]
--precompile ^ 
```



https://github.com/llvm/llvm-project/pull/71773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Llvm modules on demand bmi (PR #71773)

2023-11-09 Thread Iain Sandoe via cfe-commits

iains wrote:

> > clang++  -std=c++20 foo.cpp -c -fmodule-file=X=some/dir/X.pcm
> 
> Hm, according to https://clang.llvm.org/docs/StandardCPlusPlusModules.html 
> this can already be achieved with the `-fmodule-output` option (and which I 
> was about to try in `build2`). Is there a reason a different option is used 
> for what seems to be the same functionality. Or am I missing something here?
> 
> > This is the main point of the patch - to do this efficiently.
> 
> Again, just want to clarify: as I understand it, this patch solves the 
> scaling issue Ben reported (#60996) but without the thin/fat BMI 
> complications, correct?

That is the intent.

https://github.com/llvm/llvm-project/pull/71773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Llvm modules on demand bmi (PR #71773)

2023-11-09 Thread Iain Sandoe via cfe-commits

iains wrote:

Let us try to determine fundamental constraints.

To produce a BMI (David's ImplementationBMI) that can generate the object file, 
it must contain all the AST.

this is equivalent to hypothetical  ` clang++ -x c++-module foo.cpp 
--prepcompile  -fmodule-file=X=X-implementation.pcm` 

We can now take that pcm and generate both and object and an InterfaceBMI - by 
applying filters to the content and writing out a new BMI with the reduced 
content.

(hypothetical command lines)
` clang++ X-implementation.pcm -fmodule-interfacee  X.pcm`
` clang++ X-implementation.pcm -c -o foo.o`

>From my perspective that seems to be requiring now three process launches to 
>generate two artefacts, plus we have to save the Implementation.pcm and 
>probably distribute it to different build nodes.

The proposition of the patches here is (in the most common general case) to 
remove the step of generating the ImplementationBMI and to pipeline the 
filtering to the AST consumer that generates the Interface BMI.  Whether we 
re-use wrapper code or make some new code is an implementation detail.

It does not actually prevent you from taking the two-phase approach ( currently 
, `--precompile` will be unchanged in action).

We might also have a version where the implementation PCM could be consumed to 
generate both object and Interface PCM from a single invocation - but that is 
still two processes + resources and saving the intermediate Impl. PCM

I am generally concerned that we seem to be coming up with designs that require 
more and more process launches and corresponding memory footprint etc.


https://github.com/llvm/llvm-project/pull/71773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Llvm modules on demand bmi (PR #71773)

2023-11-08 Thread Iain Sandoe via cfe-commits

iains wrote:


> There are 2 things in the patch. One is to generate the BMI and the object 
> file in one phase (phase here means preprocess, precompile, compile, ...). 

This is the main point of the patch - to do this efficiently.

>Another is to allow us to generate BMI from a `.cpp` file. (Currently we only 
>do this for `.cppm` file or `-x c++-module` file).

Please do not become distracted by this, it is a side-effect of the main 
purpose, if the community wants to have modular files with some specific 
suffix, the patch still works the same.

> But after we introduced thin BMI, it looks inefficient to write the AST 
> twice. So it is on my TODO list after we land the thin BMI patch. BTW, I 
> think we should do thin in CodeGen action instead of hacking on 
> WrappedASTConsumer.

I am curious as to why you think that the multiplex AST consumer is a hack - it 
seems to be designed exactly for this purpose and existed already (i.e. not 
part of this patch).


> For the second thing, I am curious that if it is necessary now? Or what will 
> it block? I mean, the build systems or the cmake, require to mark the module 
> unit ahead of time. Then the build systems will pass `-x c++-module` now for 
> module units. Then the suffixes are not a thing for users.

I think you are getting distracted by the suffix; that is only a side-effect of 
this patch, not its primary purpose.


> And to me, the current mechanism for `.cppm` (or `-x c++-module`) in the 
> driver side works pretty well. 

I have always viewed that as a temporary work-around because we could not 
generate both artefacts from one compiler invocation.

>And if we introduce the mechanism to produce BMI for `.cpp`, it implies that 
>we need to maintain both paths. It is super embracing to me.

We do not need two mechanisms, .cppm can take the same path as any other suffix.

> > in the AST consumer on the BMI side doing suitable filtering to eliminate 
> > the content that is not part of the interface, that is either not needed 
> > (or in some cases positively unhelpful to consumers).

 
> I believe we should do this in ASTWriters.

I am strongly against doing more semantic work in the AST reader/writer; that 
is just compounding existing layering violations that are already hurting us.

> Also this should be part of thin BMI.

I am not sure what you mean here - the full AST is required for code-gen - we 
can only thin AST either on a separate path (as in this patch) or as a separate 
step.


https://github.com/llvm/llvm-project/pull/71773
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Llvm modules on demand bmi (PR #71773)

2023-11-08 Thread Iain Sandoe via cfe-commits

https://github.com/iains created https://github.com/llvm/llvm-project/pull/71773

Here is a **draft** of the patch series that allows for emitting both an object 
and a BMI from the same compiler invocation.

Because of point 1) below it's fairly limited in the command lines supported, 
you can do things like:

` clang++  -std=c++20 foo.cpp -c -fmodule-file=X=some/dir/X,pcm `
which will generate `foo.o` in the `CWD` and `X.pcm`  in `CWD/some/dir`

Note that, like GCC's impl you no longer need to have a special name for module 
files, any C++ suffix should work (actually, I'm not 100% sure if the .cppm 
will work without some driver-side mods)

In terms of the mechanism to do the split, I'd hope it's pretty close.

Where more development will be required:
 1. in the process(es) used for finding the BMI name
 2. in the AST consumer on the BMI side doing suitable filtering to eliminate 
the content that is not part of the interface, that is either not needed (or in 
some cases positively unhelpful to consumers).

However, neither 1 or 2 should prevent this being a first step

I"m interested in feedback on the impl.

@ChuanqiXu9 @dwblaikie @Bigcheese @mathstuf @boris-kolpackov @tahonermann 

>From 0918c5ac02c0452092e457313996da2232fbcdf5 Mon Sep 17 00:00:00 2001
From: Iain Sandoe 
Date: Sat, 29 Jan 2022 16:55:24 +
Subject: [PATCH 1/4] [Modules] A utility to identify compilations that produce
 BMIs.

We want to be able to decide if a given compilation should emit a
BMI if an appropriate module line is found.  We must not confuse
these cases with an implementation that implicitly pulls in its
respective interface.

Differential Revision: https://reviews.llvm.org/D118895
---
 clang/include/clang/Sema/Sema.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index a8c41492b61ac4c..44234d982e379f3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2389,6 +2389,11 @@ class Sema final {
 
   bool isModuleVisible(const Module *M, bool ModulePrivate = false);
 
+  /// Determine if the current module scope is the implementation.
+  bool isModuleImplementation() const {
+return ModuleScopes.empty() ? false : !ModuleScopes.back().ModuleInterface;
+  }
+
   // When loading a non-modular PCH files, this is used to restore module
   // visibility.
   void makeModuleVisible(Module *Mod, SourceLocation ImportLoc) {

>From ee75fb36b85b29d3bbec9e99c5fa5a1e69137373 Mon Sep 17 00:00:00 2001
From: Iain Sandoe 
Date: Sat, 29 Jan 2022 16:39:01 +
Subject: [PATCH 2/4] [Modules] Allow outputing BMIs in the same job as other
 artefacts.

This provides a base implementation for the ability to emit binary
module interfaces in the same compilation as generating object or
other output.

This part defers opening the BMI PCM file until it is actually needed.
At this point we will have parsed the TU and therefore can determine
if this job should emit both the BMI and some other artefact (in many
cases an object file).

This initial implementation assumes that the output filename for the
potential BMI will be known when the job is created.

Differential Revision: https://reviews.llvm.org/D118896
---
 .../ObjectFilePCHContainerOperations.h|  6 +++
 clang/include/clang/Serialization/ASTWriter.h |  3 +-
 .../Serialization/PCHContainerOperations.h| 16 ++
 .../ObjectFilePCHContainerOperations.cpp  | 10 
 clang/lib/Serialization/GeneratePCH.cpp   | 36 ++---
 .../Serialization/PCHContainerOperations.cpp  | 51 +++
 6 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h 
b/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
index 7a02d8725885a48..e09a45d76dd7866 100644
--- a/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
+++ b/clang/include/clang/CodeGen/ObjectFilePCHContainerOperations.h
@@ -27,6 +27,12 @@ class ObjectFilePCHContainerWriter : public 
PCHContainerWriter {
   const std::string ,
   std::unique_ptr OS,
   std::shared_ptr Buffer) const 
override;
+
+  std::unique_ptr CreatePCHDeferredContainerGenerator(
+  CompilerInstance , const std::string ,
+  const std::string ,
+  std::unique_ptr OS,
+  std::shared_ptr Buffer) const override;
 };
 
 /// A PCHContainerReader implementation that uses LLVM to
diff --git a/clang/include/clang/Serialization/ASTWriter.h 
b/clang/include/clang/Serialization/ASTWriter.h
index 3019bbc2ddc9cc7..3dc3d00b9eafca9 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -807,6 +807,7 @@ class PCHGenerator : public SemaConsumer {
   ASTWriter Writer;
   bool AllowASTWithErrors;
   bool ShouldCacheASTInMemory;
+  bool IsForBMI;
 
 protected:
   ASTWriter () { return Writer; }
@@ -820,7 

[clang] [C++20] [Modules] Introduce thin BMI (PR #71622)

2023-11-07 Thread Iain Sandoe via cfe-commits

iains wrote:

perhaps in the context we can use "sparse" instead of "thin" - but I do not 
have a good short word replace 'fat'.

https://github.com/llvm/llvm-project/pull/71622
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] [Driver] Don't enable -fdelayed-template-parsing by default on windows with C++20 modules (PR #69431)

2023-10-19 Thread Iain Sandoe via cfe-commits

iains wrote:

> I still support disabling delayed template parsing by default in all 
> configurations. Ultimately, this feature is a source of bugs, and we should 
> start the clock on its deprecation and removal. This, of course, involves 
> real work, and I haven't allocated any time (mine or others') to it.

So @ChuanqiXu9 's patch is at least a conservative step towards that (limiting 
the change to C++20 modules where we know there is a problem) - we could then 
extend that to C++20, in general (as per @zero9178 's comment above).  As you 
say deprecation and removal is more work.


https://github.com/llvm/llvm-project/pull/69431
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Warn if we found #include in module purview (PR #69555)

2023-10-19 Thread Iain Sandoe via cfe-commits

https://github.com/iains edited https://github.com/llvm/llvm-project/pull/69555
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Warn if we found #include in module purview (PR #69555)

2023-10-19 Thread Iain Sandoe via cfe-commits

iains wrote:

> > When I suggested this, it was an intention to limit it to C++ std library 
> > headers. Do we not have some existing mechanism that knows which headers 
> > are in this category (for typo correction etc?)
> 
> As far as I can reach, we don't have such a mechanism. 

Ah, that's unfortunate, if we could limit the initial warning to items within 
the language and only expand it if there are reported problems elsewhere it 
would be easier.

>I was wondering if we can do this by using `# pragma GCC system_header`. But 
>it shows that the libcxx don't always use this pragma.

agree that this would seem unreliable/unusable.

> Also I feel it makes sense to not include other system headers. e.g., in our 
> coding standards, we need `<>` to include boost headers and the sys headers 
> (e.g., #include )

yeah - that is both a good case for making it more general and also a warning 
that project policies could do something unexpected.

> > My concern with making it more general is that it then covers things like 
> > frameworks which are also included like `` (of course, it's 
> > also probably not what was intended there as well)
> > Let's add @Bigcheese to the reviewers, for an opinion on Frameworks
> 
> What do you mean by frameworks? Do you mean something used in apple modules? 
> If yes, the current implementation shouldn't cover that. Since I add this 
> warning only after we handled import.

(in this context) Framework headers are like system (or user headers) but 
searched by a different mechanism (so they are `#include-`ed).In principle, 
the same constraints should apply - `` indicates a "system" 
header and _**probably**_ should not be included in the module purview.


https://github.com/llvm/llvm-project/pull/69555
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Warn if we found #include in module purview (PR #69555)

2023-10-19 Thread Iain Sandoe via cfe-commits


@@ -922,6 +922,10 @@ def err_header_import_semi_in_macro : Error<
 def err_header_import_not_header_unit : Error<
   "header file %0 (aka '%1') cannot be imported because "
   "it is not known to be a header unit">;
+def warn_pp_include_angled_in_module_purview : Warning<
+  "'#include ' in the module purview appears to be erroneous; "

iains wrote:

I agree in general that limiting it to '<...>' seems a reasonable filter; 
either people should be `import`-ing or `#include "..." ` - but let's also get 
Michael's opinion.

text-wise - maybe something like:
`#include  attaches the declarations to the named module 'M', which is 
not usually intended;` (where we can name M in the message).


https://github.com/llvm/llvm-project/pull/69555
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] [Driver] Don't enable -fdelayed-template-parsing by default on windows with C++20 modules (PR #69431)

2023-10-19 Thread Iain Sandoe via cfe-commits

https://github.com/iains commented:

Is delayed template parsing an optimisation or a correctness measure?
If it's an optimisation, then it seems that we should disable it for modules 
(because that then makes the modules cases correct).  If it's needed for 
correctness, then we have more of a problem - do we know how MSVC makes the two 
interact?


https://github.com/llvm/llvm-project/pull/69431
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Warn if we found #include in module purview (PR #69555)

2023-10-19 Thread Iain Sandoe via cfe-commits

https://github.com/iains commented:

When I suggested this, it was an intention to limit it to C++ std library 
headers.  Do we not have some existing mechanism that knows which headers are 
in this category (for typo correction etc?)

My concern with making it more general is that it then covers things like 
frameworks which are also included like `` (of course, it's 
also probably not what was intended there as well)

Let's add @Bigcheese to the reviewers, for an opinion on Frameworks


https://github.com/llvm/llvm-project/pull/69555
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Warn if we found #include in module purview (PR #69555)

2023-10-19 Thread Iain Sandoe via cfe-commits


@@ -922,6 +922,10 @@ def err_header_import_semi_in_macro : Error<
 def err_header_import_not_header_unit : Error<
   "header file %0 (aka '%1') cannot be imported because "
   "it is not known to be a header unit">;
+def warn_pp_include_angled_in_module_purview : Warning<
+  "'#include ' in the module purview appears to be erroneous; "

iains wrote:

'appears to be erroneous' seems a bit strong (since we know there are valid 
cases to do this).  Maybe we can think of a way to explain the actual problem 
without ending up with too many words (or perhaps have a short warning message 
and attach a note with explanation)?

https://github.com/llvm/llvm-project/pull/69555
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MBD] set up module build daemon infrastructure (PR #67562)

2023-10-09 Thread Iain Sandoe via cfe-commits

https://github.com/iains commented:

I had a couple of questions.  I  guess my main concern here is that the TODO 
for portability might turn out to be quite heavy lifting.  Perhaps we should be 
looking to abstract the socket-like interface at a lower level.


https://github.com/llvm/llvm-project/pull/67562
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MBD] set up module build daemon infrastructure (PR #67562)

2023-10-09 Thread Iain Sandoe via cfe-commits

https://github.com/iains edited https://github.com/llvm/llvm-project/pull/67562
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MBD] set up module build daemon infrastructure (PR #67562)

2023-10-09 Thread Iain Sandoe via cfe-commits


@@ -3738,6 +3737,19 @@ static bool RenderModulesOptions(Compilation , const 
Driver ,
Std->containsValue("c++latest") || Std->containsValue("gnu++latest"));
   bool HaveModules = HaveStdCXXModules;
 
+  // -fmodule-build-daemon enables module build daemon functionality
+  if (Args.hasArg(options::OPT_fmodule_build_daemon))
+Args.AddLastArg(CmdArgs, options::OPT_fmodule_build_daemon);
+
+  // by default module build daemon socket address and output files are saved
+  // under /tmp/ but that can be overridden by providing the

iains wrote:

is that a VFS /tmp - i.e. it will be available on all supported platforms?


https://github.com/llvm/llvm-project/pull/67562
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MBD] set up module build daemon infrastructure (PR #67562)

2023-10-09 Thread Iain Sandoe via cfe-commits


@@ -0,0 +1,134 @@
+//===- SocketMsgSupport.h 
-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLING_MODULEBUILDDAEMON_SOCKETMSGSUPPORT_H
+#define LLVM_CLANG_TOOLING_MODULEBUILDDAEMON_SOCKETMSGSUPPORT_H
+
+#include "clang/Tooling/ModuleBuildDaemon/Client.h"
+#include "clang/Tooling/ModuleBuildDaemon/SocketSupport.h"
+
+using namespace clang;
+using namespace llvm;
+
+namespace cc1modbuildd {
+
+enum class ActionType { HANDSHAKE };
+enum class StatusType { REQUEST, SUCCESS, FAILURE };
+
+struct BaseMsg {
+  ActionType MsgAction;
+  StatusType MsgStatus;
+
+  BaseMsg() = default;
+  BaseMsg(ActionType Action, StatusType Status)
+  : MsgAction(Action), MsgStatus(Status) {}
+};
+
+struct HandshakeMsg : public BaseMsg {
+  HandshakeMsg() = default;
+  HandshakeMsg(ActionType Action, StatusType Status)
+  : BaseMsg(Action, Status) {}
+};
+
+template  std::string getBufferFromSocketMsg(T Msg) {
+  static_assert(std::is_base_of::value,
+"T must inherit from cc1modbuildd::BaseMsg");
+
+  std::string Buffer;
+  llvm::raw_string_ostream OS(Buffer);
+  llvm::yaml::Output YamlOut(OS);
+
+  YamlOut << Msg;
+  return Buffer;
+}
+
+template  Expected getSocketMsgFromBuffer(StringRef Buffer) {
+  static_assert(std::is_base_of::value,
+"T must inherit from cc1modbuildd::BaseMsg");
+
+  T ClientRequest;
+  llvm::yaml::Input YamlIn(Buffer);
+  YamlIn >> ClientRequest;
+
+  if (YamlIn.error()) {
+std::string Msg = "Syntax or semantic error during YAML parsing";

iains wrote:

is there any additional information that can be provided to help the user 
figure out what the actual issue is?

https://github.com/llvm/llvm-project/pull/67562
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MBD] set up module build daemon infrastructure (PR #67562)

2023-10-09 Thread Iain Sandoe via cfe-commits


@@ -0,0 +1,41 @@
+//===-- Client.h 
--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLING_MODULEBUILDDAEMON_CLIENT_H
+#define LLVM_CLANG_TOOLING_MODULEBUILDDAEMON_CLIENT_H
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/YAMLParser.h"
+#include "llvm/Support/YAMLTraits.h"
+
+using namespace clang;
+using namespace llvm;
+
+namespace cc1modbuildd {
+
+// Returns where to store log files and socket address. Of the format
+// /tmp/clang-/

iains wrote:

`BLAKE3HashOfClagnFullVersion` typo for Clang?

https://github.com/llvm/llvm-project/pull/67562
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Don't emit function bodies which is noinline and av… (PR #68501)

2023-10-09 Thread Iain Sandoe via cfe-commits

https://github.com/iains approved this pull request.

I think it would be better to have a coherent plan to deal with the underlying 
issue; starting with separating the AST used for code-gen from that used for 
interfaces.  Having said that, this LGTM (it will be interesting to see what 
performance gains are seen in practice).


https://github.com/llvm/llvm-project/pull/68501
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MBD] set up module build daemon infrastructure (PR #67562)

2023-10-08 Thread Iain Sandoe via cfe-commits

iains wrote:

A possible mechanism might be to have a watchdog process, with which instances 
of the server are registered with a time-to-live.  I guess this might be easier 
to construct as a scheme for test-suites than for end-user.


https://github.com/llvm/llvm-project/pull/67562
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Don't generate call to an imported module that dont init anything (PR #67638)

2023-09-28 Thread Iain Sandoe via cfe-commits

https://github.com/iains approved this pull request.

thanks, LGTM

https://github.com/llvm/llvm-project/pull/67638
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-repl] Emit const variables only once (PR #65257)

2023-09-28 Thread Iain Sandoe via cfe-commits

https://github.com/iains commented:

(still getting used to the revised system)
I have no comments on this patch.


https://github.com/llvm/llvm-project/pull/65257
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [C++20] [Modules] Don't generate call to an imported module that dont init anything (PR #67638)

2023-09-28 Thread Iain Sandoe via cfe-commits

https://github.com/iains commented:

Thanks for working on this.

Generally, this LGTM, but perhaps we can choose names that are unambiguously 
related to state - the current one could be read like an action.

maybe something like:

`NamedModuleHasNoInit`
and
`namedModuleHasNoInit()`

(or I'm open to other suggestions) .. 


https://github.com/llvm/llvm-project/pull/67638
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] b37233a - [C++20][Modules] Complete implementation of module.import p7.

2023-06-25 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-06-25T08:33:39+01:00
New Revision: b37233a253f30e4bd5f040d598826df443293bee

URL: 
https://github.com/llvm/llvm-project/commit/b37233a253f30e4bd5f040d598826df443293bee
DIFF: 
https://github.com/llvm/llvm-project/commit/b37233a253f30e4bd5f040d598826df443293bee.diff

LOG: [C++20][Modules] Complete implementation of module.import p7.

The following test fails to compile TU b.cpp because we are not making the 
transitively imported modules visible (per [module.import]/p7)

```
a.cppm:
export module a;

export int foo() {
   return 42;
}

b.cppm:
export module b;
import a;

export int bar();

b.cpp:
module b;

int bar() {
   return foo();
}

clang++ -c -std=c++2b -fmodule-output a.cppm
clang++ -c -std=c++2b -fmodule-output -fprebuilt-module-path=. b.cppm
clang++ -c -std=c++2b -fprebuilt-module-path=. b.cpp
b.cpp:4:12: error: declaration of 'foo' must be imported from module 'a' before 
it is required
   return foo();
```

This is fixed by the following patch (which also addresses a FIXME in 
basic.def.odr/p6.cppm).

Differential Revision: https://reviews.llvm.org/D152746

Added: 
clang/test/CXX/module/module.import/p7.cpp

Modified: 
clang/include/clang/Basic/Module.h
clang/lib/Basic/Module.cpp
clang/lib/Sema/SemaModule.cpp
clang/test/CXX/module/basic/basic.def.odr/p6.cppm

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index 399ed92a325e5..b3b5376160107 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -822,6 +822,11 @@ class VisibleModuleSet {
   ConflictCallback Cb = [](ArrayRef, Module *,
StringRef) {});
 
+  /// Make transitive imports visible for [module.import]/7.
+  void makeTransitiveImportsVisible(
+  Module *M, SourceLocation Loc, VisibleCallback Vis = [](Module *) {},
+  ConflictCallback Cb = [](ArrayRef, Module *, StringRef) {});
+
 private:
   /// Import locations for each visible module. Indexed by the module's
   /// VisibilityID.

diff  --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp
index 3f9b8d0c775b9..2bdbe8d2b110d 100644
--- a/clang/lib/Basic/Module.cpp
+++ b/clang/lib/Basic/Module.cpp
@@ -695,6 +695,14 @@ void VisibleModuleSet::setVisible(Module *M, 
SourceLocation Loc,
   VisitModule({M, nullptr});
 }
 
+void VisibleModuleSet::makeTransitiveImportsVisible(Module *M,
+SourceLocation Loc,
+VisibleCallback Vis,
+ConflictCallback Cb) {
+  for (auto *I : M->Imports)
+setVisible(I, Loc, Vis, Cb);
+}
+
 ASTSourceDescriptor::ASTSourceDescriptor(Module )
 : Signature(M.Signature), ClangModule() {
   if (M.Directory)

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 9b2982e7fa4df..2ffb0dbddd537 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -397,6 +397,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
   if (Interface) {
 
 VisibleModules.setVisible(Interface, ModuleLoc);
+VisibleModules.makeTransitiveImportsVisible(Interface, ModuleLoc);
 
 // Make the import decl for the interface in the impl module.
 ImportDecl *Import = ImportDecl::Create(Context, CurContext, ModuleLoc,

diff  --git a/clang/test/CXX/module/basic/basic.def.odr/p6.cppm 
b/clang/test/CXX/module/basic/basic.def.odr/p6.cppm
index d84c05ce32cda..8e7917dc63ea5 100644
--- a/clang/test/CXX/module/basic/basic.def.odr/p6.cppm
+++ b/clang/test/CXX/module/basic/basic.def.odr/p6.cppm
@@ -17,9 +17,8 @@
 //
 // RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-emit-module-interface -o %t/N.pcm -DMODULE_INTERFACE -DNO_ERRORS
 // RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-fmodule-file=N=%t/N.pcm -verify
-// FIXME: Once we start importing "import" declarations properly, this should
-// be rejected (-verify should be added to the following line).
-// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-fmodule-file=N=%t/N.pcm -DNO_IMPORT
+//
+// RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-fmodule-file=N=%t/N.pcm -DNO_IMPORT -verify
 //
 // RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-emit-module-interface -o %t/N-no-M.pcm -DMODULE_INTERFACE -DNO_ERRORS 
-DNO_IMPORT
 // RUN: %clang_cc1 -std=c++20 %t/module-vs-module.cpp -fmodule-file=M=%t/M.pcm 
-fmodule-file=N=%t/N-no-M.pcm -verify

diff  --git a/clang/test/CXX/module/module.import/p7.cpp 
b/clang/test/CXX/module/module.import/p7.cpp
new file mode 100644
index 0..2de6f0bd65c27
--- /dev/null
+++ b/clang/test/CXX/module/module.import/p7.cpp
@@ -0,0 

[clang] e5c7904 - [C++20][Modules] Implement P2615R1 revised export diagnostics.

2023-06-24 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-06-24T09:01:59+01:00
New Revision: e5c7904fa0bfa5a24f192cfa7b9116560e1f5d43

URL: 
https://github.com/llvm/llvm-project/commit/e5c7904fa0bfa5a24f192cfa7b9116560e1f5d43
DIFF: 
https://github.com/llvm/llvm-project/commit/e5c7904fa0bfa5a24f192cfa7b9116560e1f5d43.diff

LOG: [C++20][Modules] Implement P2615R1 revised export diagnostics.

It has been reported to that the current clang  errors for, specifically,
static_assert in export contexts are a serious blocker to adoption of
modules in some cases.

There is also implementation divergence with GCC and MSVC allowing the
constructs mentioned below where clang currently rejects them with an
error.

The category of errors [for declarations in an exported context] is:
(unnamed, static_assert, empty and asm decls). These are now permitted
after P2615R1 which was approved by WG21 as a DR (and thus should be
applied to C++20 as well).

This patch removes these diagnostics and amends the testsuite accordingly.

Differential Revision: https://reviews.llvm.org/D152946

Added: 


Modified: 
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaModule.cpp
clang/test/CXX/module/module.interface/p3.cpp
clang/test/Modules/cxx20-10-2-ex1.cpp
clang/test/Modules/cxx20-10-2-ex7.cpp
clang/test/SemaCXX/modules.cppm

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a215095d540ae..3f0b7a54d8890 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11262,22 +11262,11 @@ def note_global_module_introducer_missing : Note<
 def err_export_within_anonymous_namespace : Error<
   "export declaration appears within anonymous namespace">;
 def note_anonymous_namespace : Note<"anonymous namespace begins here">;
-def ext_export_no_name_block : ExtWarn<
-  "ISO C++20 does not permit %select{an empty|a static_assert}0 declaration "
-  "to appear in an export block">, InGroup;
-def ext_export_no_names : ExtWarn<
-  "ISO C++20 does not permit a declaration that does not introduce any names "
-  "to be exported">, InGroup;
-def introduces_no_names : Error<
-  "declaration does not introduce any names to be exported">;
 def note_export : Note<"export block begins here">;
-def err_export_no_name : Error<
-  "%select{empty|static_assert|asm}0 declaration cannot be exported">;
-def ext_export_using_directive : ExtWarn<
-  "ISO C++20 does not permit using directive to be exported">,
-  InGroup>;
 def err_export_within_export : Error<
   "export declaration appears within another export declaration">;
+def err_export_anon_ns_internal : Error<
+  "anonymous namespaces cannot be exported">;
 def err_export_internal : Error<
   "declaration of %0 with internal linkage cannot be exported">;
 def err_export_using_internal : Error<

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 5ce5330b09466..9b2982e7fa4df 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -814,76 +814,22 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation 
ExportLoc,
   return D;
 }
 
-static bool checkExportedDeclContext(Sema , DeclContext *DC,
- SourceLocation BlockStart);
-
-namespace {
-enum class UnnamedDeclKind {
-  Empty,
-  StaticAssert,
-  Asm,
-  UsingDirective,
-  Namespace,
-  Context
-};
-}
-
-static std::optional getUnnamedDeclKind(Decl *D) {
-  if (isa(D))
-return UnnamedDeclKind::Empty;
-  if (isa(D))
-return UnnamedDeclKind::StaticAssert;
-  if (isa(D))
-return UnnamedDeclKind::Asm;
-  if (isa(D))
-return UnnamedDeclKind::UsingDirective;
-  // Everything else either introduces one or more names or is ill-formed.
-  return std::nullopt;
-}
-
-unsigned getUnnamedDeclDiag(UnnamedDeclKind UDK, bool InBlock) {
-  switch (UDK) {
-  case UnnamedDeclKind::Empty:
-  case UnnamedDeclKind::StaticAssert:
-// Allow empty-declarations and static_asserts in an export block as an
-// extension.
-return InBlock ? diag::ext_export_no_name_block : diag::err_export_no_name;
-
-  case UnnamedDeclKind::UsingDirective:
-// Allow exporting using-directives as an extension.
-return diag::ext_export_using_directive;
-
-  case UnnamedDeclKind::Namespace:
-// Anonymous namespace with no content.
-return diag::introduces_no_names;
-
-  case UnnamedDeclKind::Context:
-// Allow exporting DeclContexts that transitively contain no declarations
-// as an extension.
-return diag::ext_export_no_names;
-
-  case UnnamedDeclKind::Asm:
-return diag::err_export_no_name;
-  }
-  llvm_unreachable("unknown kind");
-}
+static bool checkExportedDecl(Sema &, Decl *, SourceLocation);
 
-static void diagExportedUnnamedDecl(Sema , UnnamedDeclKind UDK, Decl *D,
-

[clang] 6e4f870 - re-land [C++20][Modules] Introduce an implementation module.

2023-03-28 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-03-29T08:52:28+05:30
New Revision: 6e4f870a21e344fdcd61fe613b0aeeafb8a84ed2

URL: 
https://github.com/llvm/llvm-project/commit/6e4f870a21e344fdcd61fe613b0aeeafb8a84ed2
DIFF: 
https://github.com/llvm/llvm-project/commit/6e4f870a21e344fdcd61fe613b0aeeafb8a84ed2.diff

LOG: re-land [C++20][Modules] Introduce an implementation module.

We need to be able to distinguish individual TUs from the same module in cases
where TU-local entities either need to be hidden (or, for some cases of ADL in
template instantiation, need to be detected as exposures).

This creates a module type for the implementation which implicitly imports its
primary module interface per C++20:
[module.unit/8] 'A module-declaration that contains neither an export-keyword
nor a module-partition implicitly imports the primary module interface unit of
the module as if by a module-import-declaration.

Implementation modules are never serialized (-emit-module-interface for an
implementation unit is diagnosed and rejected).

Differential Revision: https://reviews.llvm.org/D126959

Added: 


Modified: 
clang/include/clang/Basic/Module.h
clang/include/clang/Lex/ModuleMap.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/Decl.cpp
clang/lib/CodeGen/CGDeclCXX.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Frontend/FrontendActions.cpp
clang/lib/Lex/ModuleMap.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaModule.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/CXX/module/basic/basic.def.odr/p4.cppm
clang/test/CXX/module/basic/basic.link/p2.cppm
clang/test/CodeGenCXX/module-intializer.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index 387ce4d6e9b17..c0c99eb8b6d62 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -103,16 +103,22 @@ class alignas(8) Module {
   /// The location of the module definition.
   SourceLocation DefinitionLoc;
 
+  // FIXME: Consider if reducing the size of this enum (having Partition and
+  // Named modules only) then representing interface/implementation separately
+  // is more efficient.
   enum ModuleKind {
 /// This is a module that was defined by a module map and built out
 /// of header files.
 ModuleMapModule,
 
+/// This is a C++ 20 header unit.
+ModuleHeaderUnit,
+
 /// This is a C++20 module interface unit.
 ModuleInterfaceUnit,
 
-/// This is a C++ 20 header unit.
-ModuleHeaderUnit,
+/// This is a C++20 module implementation unit.
+ModuleImplementationUnit,
 
 /// This is a C++ 20 module partition interface.
 ModulePartitionInterface,
@@ -169,9 +175,16 @@ class alignas(8) Module {
   /// Does this Module scope describe part of the purview of a standard named
   /// C++ module?
   bool isModulePurview() const {
-return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface ||
-   Kind == ModulePartitionImplementation ||
-   Kind == PrivateModuleFragment;
+switch (Kind) {
+case ModuleInterfaceUnit:
+case ModuleImplementationUnit:
+case ModulePartitionInterface:
+case ModulePartitionImplementation:
+case PrivateModuleFragment:
+  return true;
+default:
+  return false;
+}
   }
 
   /// Does this Module scope describe a fragment of the global module within
@@ -561,6 +574,11 @@ class alignas(8) Module {
Kind == ModulePartitionImplementation;
   }
 
+  /// Is this a module implementation.
+  bool isModuleImplementation() const {
+return Kind == ModuleImplementationUnit;
+  }
+
   /// Is this module a header unit.
   bool isHeaderUnit() const { return Kind == ModuleHeaderUnit; }
   // Is this a C++20 module interface or a partition.

diff  --git a/clang/include/clang/Lex/ModuleMap.h 
b/clang/include/clang/Lex/ModuleMap.h
index a0ddd13c11bfd..f155c609b06cb 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -560,6 +560,11 @@ class ModuleMap {
   Module *createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
   SourceLocation Loc);
 
+  /// Create a new C++ module with the specified kind, and reparent any pending
+  /// global module fragment(s) to it.
+  Module *createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
+   Module::ModuleKind Kind);
+
   /// Create a new module for a C++ module interface unit.
   /// The module must not already exist, and will be configured for the current
   /// compilation.
@@ -569,6 +574,13 @@ class ModuleMap {
   /// \returns The newly-created module.
   Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name);
 
+  /// Create a new module for a C++ module implementation unit.
+  /// The interface module for this implementation 

[clang] c6e9823 - [C++20][Modules] Introduce an implementation module.

2023-03-23 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-03-23T12:47:44Z
New Revision: c6e9823724ef6bdfee262289ee34d162db436af0

URL: 
https://github.com/llvm/llvm-project/commit/c6e9823724ef6bdfee262289ee34d162db436af0
DIFF: 
https://github.com/llvm/llvm-project/commit/c6e9823724ef6bdfee262289ee34d162db436af0.diff

LOG: [C++20][Modules] Introduce an implementation module.

We need to be able to distinguish individual TUs from the same module in cases
where TU-local entities either need to be hidden (or, for some cases of ADL in
template instantiation, need to be detected as exposures).

This creates a module type for the implementation which implicitly imports its
primary module interface per C++20:
[module.unit/8] 'A module-declaration that contains neither an export-keyword
nor a module-partition implicitly imports the primary module interface unit of
the module as if by a module-import-declaration.

Implementation modules are never serialized (-emit-module-interface for an
implementation unit is diagnosed and rejected).

Differential Revision: https://reviews.llvm.org/D126959

Added: 


Modified: 
clang/include/clang/Basic/Module.h
clang/include/clang/Lex/ModuleMap.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/Decl.cpp
clang/lib/CodeGen/CGDeclCXX.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Frontend/FrontendActions.cpp
clang/lib/Lex/ModuleMap.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaModule.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/CXX/module/basic/basic.def.odr/p4.cppm
clang/test/CXX/module/basic/basic.link/p2.cppm
clang/test/CodeGenCXX/module-intializer.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index 387ce4d6e9b17..c0c99eb8b6d62 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -103,16 +103,22 @@ class alignas(8) Module {
   /// The location of the module definition.
   SourceLocation DefinitionLoc;
 
+  // FIXME: Consider if reducing the size of this enum (having Partition and
+  // Named modules only) then representing interface/implementation separately
+  // is more efficient.
   enum ModuleKind {
 /// This is a module that was defined by a module map and built out
 /// of header files.
 ModuleMapModule,
 
+/// This is a C++ 20 header unit.
+ModuleHeaderUnit,
+
 /// This is a C++20 module interface unit.
 ModuleInterfaceUnit,
 
-/// This is a C++ 20 header unit.
-ModuleHeaderUnit,
+/// This is a C++20 module implementation unit.
+ModuleImplementationUnit,
 
 /// This is a C++ 20 module partition interface.
 ModulePartitionInterface,
@@ -169,9 +175,16 @@ class alignas(8) Module {
   /// Does this Module scope describe part of the purview of a standard named
   /// C++ module?
   bool isModulePurview() const {
-return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface ||
-   Kind == ModulePartitionImplementation ||
-   Kind == PrivateModuleFragment;
+switch (Kind) {
+case ModuleInterfaceUnit:
+case ModuleImplementationUnit:
+case ModulePartitionInterface:
+case ModulePartitionImplementation:
+case PrivateModuleFragment:
+  return true;
+default:
+  return false;
+}
   }
 
   /// Does this Module scope describe a fragment of the global module within
@@ -561,6 +574,11 @@ class alignas(8) Module {
Kind == ModulePartitionImplementation;
   }
 
+  /// Is this a module implementation.
+  bool isModuleImplementation() const {
+return Kind == ModuleImplementationUnit;
+  }
+
   /// Is this module a header unit.
   bool isHeaderUnit() const { return Kind == ModuleHeaderUnit; }
   // Is this a C++20 module interface or a partition.

diff  --git a/clang/include/clang/Lex/ModuleMap.h 
b/clang/include/clang/Lex/ModuleMap.h
index a0ddd13c11bfd..f155c609b06cb 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -560,6 +560,11 @@ class ModuleMap {
   Module *createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
   SourceLocation Loc);
 
+  /// Create a new C++ module with the specified kind, and reparent any pending
+  /// global module fragment(s) to it.
+  Module *createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
+   Module::ModuleKind Kind);
+
   /// Create a new module for a C++ module interface unit.
   /// The module must not already exist, and will be configured for the current
   /// compilation.
@@ -569,6 +574,13 @@ class ModuleMap {
   /// \returns The newly-created module.
   Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name);
 
+  /// Create a new module for a C++ module implementation unit.
+  /// The interface module for this implementation (implicitly 

[clang] 62a16d5 - [C++2x][Modules] Amend module purview constant linkage [P2788R0].

2023-03-19 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-03-19T16:25:56Z
New Revision: 62a16d5e2069542351c164aa0e3b216dc8e153c4

URL: 
https://github.com/llvm/llvm-project/commit/62a16d5e2069542351c164aa0e3b216dc8e153c4
DIFF: 
https://github.com/llvm/llvm-project/commit/62a16d5e2069542351c164aa0e3b216dc8e153c4.diff

LOG: [C++2x][Modules] Amend module purview constant linkage [P2788R0].

This paper has been applied to the working draft and is believed to be
a DR against C++20, so that the patch here makes the change unconditionally.

for:
```
export module A;

const int mod_cst = 10;
```
Before the change, mod_cst would have internal linkage; after the change it
has module linkage.

Differential Revision: https://reviews.llvm.org/D145886

Added: 


Modified: 
clang/lib/AST/Decl.cpp
clang/test/CXX/module/basic/basic.def.odr/p4.cppm
clang/test/CXX/module/basic/basic.link/p3.cppm

Removed: 




diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 484a4a294aa5e..56042e5fd252f 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -600,6 +600,12 @@ static bool isExportedFromModuleInterfaceUnit(const 
NamedDecl *D) {
   llvm_unreachable("unexpected module ownership kind");
 }
 
+static bool isDeclaredInModuleInterfaceOrPartition(const NamedDecl *D) {
+  if (auto *M = D->getOwningModule())
+return M->isInterfaceOrPartition();
+  return false;
+}
+
 static LinkageInfo getInternalLinkageFor(const NamedDecl *D) {
   return LinkageInfo::internal();
 }
@@ -642,15 +648,15 @@ LinkageComputer::getLVForNamespaceScopeDecl(const 
NamedDecl *D,
   if (const auto *Var = dyn_cast(D)) {
 // - a non-template variable of non-volatile const-qualified type, unless
 //   - it is explicitly declared extern, or
-//   - it is inline or exported, or
+//   - it is declared in the purview of a module interface unit
+// (outside the private-module-fragment, if any) or module partition, 
or
+//   - it is inline, or
 //   - it was previously declared and the prior declaration did not have
 // internal linkage
 // (There is no equivalent in C99.)
-if (Context.getLangOpts().CPlusPlus &&
-Var->getType().isConstQualified() &&
-!Var->getType().isVolatileQualified() &&
-!Var->isInline() &&
-!isExportedFromModuleInterfaceUnit(Var) &&
+if (Context.getLangOpts().CPlusPlus && Var->getType().isConstQualified() &&
+!Var->getType().isVolatileQualified() && !Var->isInline() &&
+!isDeclaredInModuleInterfaceOrPartition(Var) &&
 !isa(Var) &&
 !Var->getDescribedVarTemplate()) {
   const VarDecl *PrevVar = Var->getPreviousDecl();

diff  --git a/clang/test/CXX/module/basic/basic.def.odr/p4.cppm 
b/clang/test/CXX/module/basic/basic.def.odr/p4.cppm
index b8f24d3ed5c8a..1542e532c635a 100644
--- a/clang/test/CXX/module/basic/basic.def.odr/p4.cppm
+++ b/clang/test/CXX/module/basic/basic.def.odr/p4.cppm
@@ -5,9 +5,9 @@
 // RUN: %clang_cc1 -std=c++20 %t/Module.cppm -triple %itanium_abi_triple 
-emit-llvm -o - | FileCheck %t/Module.cppm --implicit-check-not unused
 //
 // RUN: %clang_cc1 -std=c++20 %t/Module.cppm -triple %itanium_abi_triple 
-emit-module-interface -o %t/Module.pcm
-// RUN: %clang_cc1 -std=c++20 %t/module.cpp -triple %itanium_abi_triple 
-fmodule-file=%t/Module.pcm -emit-llvm -o - | FileCheck %t/module.cpp 
--implicit-check-not=unused --implicit-check-not=global_module
+// RUN: %clang_cc1 -std=c++20 %t/module.cpp -triple %itanium_abi_triple 
-fmodule-file=Module=%t/Module.pcm -emit-llvm -o - | FileCheck %t/module.cpp 
--implicit-check-not=unused --implicit-check-not=global_module
 //
-// RUN: %clang_cc1 -std=c++20 %t/user.cpp -triple %itanium_abi_triple 
-fmodule-file=%t/Module.pcm -emit-llvm -o - | FileCheck %t/user.cpp 
--implicit-check-not=unused --implicit-check-not=global_module
+// RUN: %clang_cc1 -std=c++20 %t/user.cpp -triple %itanium_abi_triple 
-fmodule-file=Module=%t/Module.pcm -emit-llvm -o - | FileCheck %t/user.cpp 
--implicit-check-not=unused --implicit-check-not=global_module
 
 //--- Module.cppm
 // CHECK-DAG: @extern_var_global_module = external {{(dso_local )?}}global
@@ -30,7 +30,7 @@
 // permitted to run the initializer for this variable.
 // CHECK-DAG: @_ZW6Module25inline_var_module_linkage = linkonce_odr 
{{(dso_local )?}}global
 // CHECK-DAG: @_ZL25static_var_module_linkage = internal
-// CHECK-DAG: @_ZL24const_var_module_linkage = internal
+// CHECK-DAG: @_ZW6Module24const_var_module_linkage = {{(dso_local )?}}constant
 //
 // CHECK-DAG: @_ZW6Module25unused_var_module_linkage = {{(dso_local )?}}global 
i32 4
 
@@ -129,7 +129,7 @@ void f(a::b, a::c) {}
 // CHECK-DAG: @_ZW6Module25extern_var_module_linkage = external {{(dso_local 
)?}}global
 // CHECK-DAG: @_ZW6Module25inline_var_module_linkage = linkonce_odr 
{{(dso_local )?}}global
 // CHECK-DAG: @_ZL25static_var_module_linkage = internal {{(dso_local 

Re: [PATCH] D126959: [C++20][Modules] Introduce an implementation module.

2023-03-17 Thread Iain Sandoe via cfe-commits
Hi Chuanqi

> On 17 Mar 2023, at 02:49, Chuanqi Xu via Phabricator 
>  wrote:
> 
> ChuanqiXu added a comment.
> 
> (I don't why I can't send emails in the original mail address. It told me 
> that your email addressed is not recorded by MX, while I don't know what is 
> MX. So I tried to reply your email here)

No idea, you have replied to emails to this address before.

> This FIXME was added 6 years ago for Modules TS. 
> (https://github.com/llvm/llvm-project/commit/becb92dec85924969ac0c3b049e0a74def431453).
> And I moved the test simply without modifying it actually.
> 
> And I guess it may refer to the problem we are discussing. The spec says the 
> implementation unit will import the primary module interface implicitly.

Also “as if imported”.

.. and https://reviews.llvm.org/D126959 actually completes that by adding an 
import decl and adding the primary module interface to the imported modules.

Let’s deal with D126959 separately since we already have a review thread.

> But the current implementation doesn't **import** it actually but loading it. 
> This is inconsistent with the wording and it is not consistent with the 
> design intention in clang.
> It resulted some problems we saw.

OK.  that answers this (it’s just that the FIXME was touched quite recently 
according to git blame, which is why I asked).

thanks
Iain

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


[clang] cdd44e2 - [C++20][Modules] Handle template declarations in header units.

2023-02-02 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-02-02T10:51:08Z
New Revision: cdd44e2c85542d152aef19cfd1d2ad451d774935

URL: 
https://github.com/llvm/llvm-project/commit/cdd44e2c85542d152aef19cfd1d2ad451d774935
DIFF: 
https://github.com/llvm/llvm-project/commit/cdd44e2c85542d152aef19cfd1d2ad451d774935.diff

LOG: [C++20][Modules] Handle template declarations in header units.

This addresses part of https://github.com/llvm/llvm-project/issues/60079

The test for external functions was not considering function templates.

Differential Revision: https://reviews.llvm.org/D142704

Added: 


Modified: 
clang/lib/Sema/SemaDecl.cpp
clang/test/CXX/module/module.import/p6.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0cfabed8c7dc..b2bece4d9db0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13090,9 +13090,10 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
   // C++ [module.import/6] external definitions are not permitted in header
   // units.
   if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
-  VDecl->isThisDeclarationADefinition() &&
+  !VDecl->isInvalidDecl() && VDecl->isThisDeclarationADefinition() &&
   VDecl->getFormalLinkage() == Linkage::ExternalLinkage &&
-  !VDecl->isInline()) {
+  !VDecl->isInline() && !VDecl->isTemplated() &&
+  !isa(VDecl)) {
 Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit);
 VDecl->setInvalidDecl();
   }
@@ -15261,9 +15262,10 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope 
*FnBodyScope, Decl *D,
   // FIXME: Consider an alternate location for the test where the inlined()
   // state is complete.
   if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
+  !FD->isInvalidDecl() && !FD->isInlined() &&
+  BodyKind != FnBodyKind::Delete && BodyKind != FnBodyKind::Default &&
   FD->getFormalLinkage() == Linkage::ExternalLinkage &&
-  !FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete &&
-  BodyKind != FnBodyKind::Default && !FD->isInlined()) {
+  !FD->isTemplated() && !FD->isTemplateInstantiation()) {
 assert(FD->isThisDeclarationADefinition());
 Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);
 FD->setInvalidDecl();

diff  --git a/clang/test/CXX/module/module.import/p6.cpp 
b/clang/test/CXX/module/module.import/p6.cpp
index 4360d3e67385..0ed8b5958dff 100644
--- a/clang/test/CXX/module/module.import/p6.cpp
+++ b/clang/test/CXX/module/module.import/p6.cpp
@@ -22,6 +22,8 @@ int ok_var_decl;
 
 int bad_var_definition = 3;  // expected-error {{non-inline external 
definitions are not permitted in C++ header units}}
 
+/* The cases below should compile without diagnostics.  */
+
 class A {
 public:
 // This is a declaration instead of definition.
@@ -36,3 +38,32 @@ struct S {
   S(S&);
 };
 S::S(S&) = default;
+
+template 
+_X tmpl_var_ok_0 = static_cast<_X>(-1);
+
+template 
+constexpr _T tmpl_var_ok_1 = static_cast<_T>(42);
+
+inline int a = tmpl_var_ok_1;
+
+template  class _T>
+constexpr int tmpl_var_ok_2 = _T<_Tp>::value ? 42 : 6174 ;
+
+template
+int tmpl_OK (_Ep) { return 0; }
+
+template 
+bool
+operator==(_T1& , _T1& ) { return false; }
+
+constexpr long one_k = 1000L;
+
+template 
+void* tmpl_fn_ok
+(_Args ...__args) { return nullptr; }
+
+inline int foo (int a) {
+  return tmpl_OK (a);
+}



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


[clang] 53a1314 - [C++20][Modules] Fix named module import diagnostics.

2023-01-22 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-01-22T10:22:36Z
New Revision: 53a1314ed1b5021822071d3c7a751a5ec52619b7

URL: 
https://github.com/llvm/llvm-project/commit/53a1314ed1b5021822071d3c7a751a5ec52619b7
DIFF: 
https://github.com/llvm/llvm-project/commit/53a1314ed1b5021822071d3c7a751a5ec52619b7.diff

LOG: [C++20][Modules] Fix named module import diagnostics.

We have been incorrectly disallowing imports of named modules in the
global and private module fragments.

This addresses: https://github.com/llvm/llvm-project/issues/59688

Differential Revision: https://reviews.llvm.org/D140927

Added: 
clang/test/Modules/cxx20-import-diagnostics-b.cpp

Modified: 
clang/include/clang/Sema/Sema.h
clang/lib/Parse/Parser.cpp
clang/lib/Sema/SemaModule.cpp
clang/test/Modules/cxx20-import-diagnostics-a.cpp

Removed: 




diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7fbd8ef7e229e..3e3fb2b0cc56d 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3146,12 +3146,15 @@ class Sema final {
   /// fragments and imports.  If we are not parsing a C++20 TU, or we find
   /// an error in state transition, the state is set to NotACXX20Module.
   enum class ModuleImportState {
-FirstDecl,   ///< Parsing the first decl in a TU.
-GlobalFragment,  ///< after 'module;' but before 'module X;'
-ImportAllowed,   ///< after 'module X;' but before any non-import decl.
-ImportFinished,  ///< after any non-import decl.
-PrivateFragment, ///< after 'module :private;'.
-NotACXX20Module  ///< Not a C++20 TU, or an invalid state was found.
+FirstDecl,  ///< Parsing the first decl in a TU.
+GlobalFragment, ///< after 'module;' but before 'module X;'
+ImportAllowed,  ///< after 'module X;' but before any non-import decl.
+ImportFinished, ///< after any non-import decl.
+PrivateFragmentImportAllowed,  ///< after 'module :private;' but before any
+   ///< non-import decl.
+PrivateFragmentImportFinished, ///< after 'module :private;' but a
+   ///< non-import decl has already been seen.
+NotACXX20Module ///< Not a C++20 TU, or an invalid state was found.
   };
 
 private:

diff  --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 104836aca4a94..6db3dc3156fdf 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -750,6 +750,10 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy ,
 else if (ImportState == Sema::ModuleImportState::ImportAllowed)
   // Non-imports disallow further imports.
   ImportState = Sema::ModuleImportState::ImportFinished;
+else if (ImportState ==
+ Sema::ModuleImportState::PrivateFragmentImportAllowed)
+  // Non-imports disallow further imports.
+  ImportState = Sema::ModuleImportState::PrivateFragmentImportFinished;
   }
   return false;
 }
@@ -2427,7 +2431,9 @@ Parser::ParseModuleDecl(Sema::ModuleImportState 
) {
 SourceLocation PrivateLoc = ConsumeToken();
 DiagnoseAndSkipCXX11Attributes();
 ExpectAndConsumeSemi(diag::err_private_module_fragment_expected_semi);
-ImportState = Sema::ModuleImportState::PrivateFragment;
+ImportState = ImportState == Sema::ModuleImportState::ImportAllowed
+  ? Sema::ModuleImportState::PrivateFragmentImportAllowed
+  : Sema::ModuleImportState::PrivateFragmentImportFinished;
 return Actions.ActOnPrivateModuleFragmentDecl(ModuleLoc, PrivateLoc);
   }
 
@@ -2544,23 +2550,28 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc,
   SeenError = false;
 break;
   case Sema::ModuleImportState::GlobalFragment:
-// We can only have pre-processor directives in the global module
-// fragment.  We cannot import a named modules here, however we have a
-// header unit import.
-if (!HeaderUnit || HeaderUnit->Kind != 
Module::ModuleKind::ModuleHeaderUnit)
-  Diag(ImportLoc, diag::err_import_in_wrong_fragment) << IsPartition << 0;
+  case Sema::ModuleImportState::PrivateFragmentImportAllowed:
+// We can only have pre-processor directives in the global module fragment
+// which allows pp-import, but not of a partition (since the global module
+// does not have partitions).
+// We cannot import a partition into a private module fragment, since
+// [module.private.frag]/1 disallows private module fragments in a multi-
+// TU module.
+if (IsPartition || (HeaderUnit && HeaderUnit->Kind !=
+  
Module::ModuleKind::ModuleHeaderUnit))
+  Diag(ImportLoc, diag::err_import_in_wrong_fragment)
+  << IsPartition
+  << (ImportState == Sema::ModuleImportState::GlobalFragment ? 0 : 1);
 else
   SeenError = false;
 break;
   case Sema::ModuleImportState::ImportFinished:
+  case 

[clang] ff70e22 - [C++20][Modules] Handle defaulted and deleted functions in header units.

2023-01-21 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-01-21T12:55:52Z
New Revision: ff70e22f08d9a289c707ef192d7d4c5968e54b51

URL: 
https://github.com/llvm/llvm-project/commit/ff70e22f08d9a289c707ef192d7d4c5968e54b51
DIFF: 
https://github.com/llvm/llvm-project/commit/ff70e22f08d9a289c707ef192d7d4c5968e54b51.diff

LOG: [C++20][Modules] Handle defaulted and deleted functions in header units.

Address part of https://github.com/llvm/llvm-project/issues/60079.

Deleted and Defaulted functions are implicitly inline, but that state
is not set at the point that we perform the diagnostic checks for externally-
visible non-inline functions; check the function body type explicitly in the
diagnostic.

Differential Revision: https://reviews.llvm.org/D141908

Added: 


Modified: 
clang/lib/Sema/SemaDecl.cpp
clang/test/CXX/module/module.import/p6.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3ae3e33a6704..e2b921bfe78f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15254,9 +15254,15 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope 
*FnBodyScope, Decl *D,
   }
 
   // C++ [module.import/6] external definitions are not permitted in header
-  // units.
+  // units.  Deleted and Defaulted functions are implicitly inline (but the
+  // inline state is not set at this point, so check the BodyKind explicitly).
+  // FIXME: Consider an alternate location for the test where the inlined()
+  // state is complete.
   if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
-  FD->getFormalLinkage() == Linkage::ExternalLinkage && !FD->isInlined()) {
+  FD->getFormalLinkage() == Linkage::ExternalLinkage &&
+  !FD->isInvalidDecl() && BodyKind != FnBodyKind::Delete &&
+  BodyKind != FnBodyKind::Default && !FD->isInlined()) {
+assert(FD->isThisDeclarationADefinition());
 Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);
 FD->setInvalidDecl();
   }

diff  --git a/clang/test/CXX/module/module.import/p6.cpp 
b/clang/test/CXX/module/module.import/p6.cpp
index 7d8632786d9e..4360d3e67385 100644
--- a/clang/test/CXX/module/module.import/p6.cpp
+++ b/clang/test/CXX/module/module.import/p6.cpp
@@ -28,3 +28,11 @@ class A {
 static const int value = 43; 
 };
 
+void deleted_fn_ok (void) = delete;
+
+struct S {
+   ~S() noexcept(false) = default;
+private:
+  S(S&);
+};
+S::S(S&) = default;



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


[clang] 335668b - [C++20][Modules] Do not allow non-inline external definitions in header units.

2023-01-08 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2023-01-08T12:19:23Z
New Revision: 335668b116439d13c7555616e126acdc608ce59e

URL: 
https://github.com/llvm/llvm-project/commit/335668b116439d13c7555616e126acdc608ce59e
DIFF: 
https://github.com/llvm/llvm-project/commit/335668b116439d13c7555616e126acdc608ce59e.diff

LOG: [C++20][Modules] Do not allow non-inline external definitions in header 
units.

[module.import/6] last sentence:
A header unit shall not contain a definition of a non-inline function or
variable whose name has external linkage.

Differential Revision: https://reviews.llvm.org/D140261

Added: 
clang/test/CXX/module/module.import/p6.cpp

Modified: 
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaDecl.cpp
clang/test/CodeGenCXX/module-initializer-header.cppm

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 91cb9049bcb4b..b623d260dbb30 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -187,6 +187,11 @@ code bases.
 - ``-p`` is rejected for all targets which are not AIX or OpenBSD. ``-p`` led
   to an ``-Wunused-command-line-argument`` warning in previous releases.
 
+- Clang now diagnoses non-inline externally-visible definitions in C++
+  standard header units as per ``[module.import/6]``.  Previously, in Clang-15,
+  these definitions were allowed.  Note that such definitions are ODR
+  violations if the header is included more than once.
+
 What's New in Clang |release|?
 ==
 Some of the major new features and improvements to Clang are listed

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d1bffc7e3e9c6..7154a8bcbde47 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11236,6 +11236,8 @@ def note_not_module_interface_add_export : Note<
   "add 'export' here if this is intended to be a module interface unit">;
 def err_invalid_module_name : Error<
   "%0 is %select{an invalid|a reserved}1 name for a module">;
+def err_extern_def_in_header_unit : Error<
+  "non-inline external definitions are not permitted in C++ header units">;
 
 def ext_equivalent_internal_linkage_decl_in_modules : ExtWarn<
   "ambiguous use of internal linkage declaration %0 defined in multiple 
modules">,

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1cbbcfd855121..4714b8b7cbde6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2325,6 +2325,12 @@ class Sema final {
 return ModuleScopes.empty() ? false : ModuleScopes.back().ModuleInterface;
   }
 
+  /// Is the module scope we are in a C++ Header Unit?
+  bool currentModuleIsHeaderUnit() const {
+return ModuleScopes.empty() ? false
+: ModuleScopes.back().Module->isHeaderUnit();
+  }
+
   /// Get the module owning an entity.
   Module *getOwningModule(const Decl *Entity) {
 return Entity->getOwningModule();

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a1bfb57168c8a..d25f513591bcc 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -13071,6 +13071,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr 
*Init, bool DirectInit) {
   VDecl->setInvalidDecl();
   }
 
+  // C++ [module.import/6] external definitions are not permitted in header
+  // units.
+  if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
+  VDecl->getFormalLinkage() == Linkage::ExternalLinkage &&
+  !VDecl->isInline()) {
+Diag(VDecl->getLocation(), diag::err_extern_def_in_header_unit);
+VDecl->setInvalidDecl();
+  }
+
   // If adding the initializer will turn this declaration into a definition,
   // and we already have a definition for this variable, diagnose or otherwise
   // handle the situation.
@@ -15224,6 +15233,14 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope 
*FnBodyScope, Decl *D,
 }
   }
 
+  // C++ [module.import/6] external definitions are not permitted in header
+  // units.
+  if (getLangOpts().CPlusPlusModules && currentModuleIsHeaderUnit() &&
+  FD->getFormalLinkage() == Linkage::ExternalLinkage && !FD->isInlined()) {
+Diag(FD->getLocation(), diag::err_extern_def_in_header_unit);
+FD->setInvalidDecl();
+  }
+
   // Ensure that the function's exception specification is instantiated.
   if (const FunctionProtoType *FPT = FD->getType()->getAs())
 ResolveExceptionSpec(D->getLocation(), FPT);

diff  --git a/clang/test/CXX/module/module.import/p6.cpp 
b/clang/test/CXX/module/module.import/p6.cpp
new file mode 100644
index 0..25c195038eb63
--- /dev/null
+++ b/clang/test/CXX/module/module.import/p6.cpp
@@ -0,0 +1,24 @@
+// RUN: mkdir -p %t
+// RUN: 

[clang] bd7f4c5 - [C++20][Modules] Elide unused guard variables in Itanium ABI module initializers.

2022-12-18 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-12-18T09:16:27Z
New Revision: bd7f4c561f5e2385ebe5500a044efe0de30cccaa

URL: 
https://github.com/llvm/llvm-project/commit/bd7f4c561f5e2385ebe5500a044efe0de30cccaa
DIFF: 
https://github.com/llvm/llvm-project/commit/bd7f4c561f5e2385ebe5500a044efe0de30cccaa.diff

LOG: [C++20][Modules] Elide unused guard variables in Itanium ABI module 
initializers.

For the Itanium ABI, we emit an initializer for each module.  This is 
responsible
for handling initialization of global vars.  Relates to P1874R1.

The initializer has a known mangling and is automatically called from any TU 
that
imports a module. Since, at present, the importer has no way to determine that 
an
imported module does not require an initializer, we generate the initializer for
all cases (even when it is empty).

Initializers must be run once, with the ordering guaranteed by the import graph
and this is ensured in the current code by addition of a guard variable.

In the case that a module has no requirement for global initializers, and also 
does
not import any other modules, we can elide the guard variable.

Differential Revision: https://reviews.llvm.org/D134589

Added: 
clang/test/CodeGenCXX/module-initializer-guard-elision.cpp

Modified: 
clang/lib/CodeGen/CGDeclCXX.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 009749b38509b..dcd811ea257b3 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -640,7 +640,12 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() {
 
 /* Build the initializer for a C++20 module:
This is arranged to be run only once regardless of how many times the module
-   might be included transitively.  This arranged by using a control variable.
+   might be included transitively.  This arranged by using a guard variable.
+
+   If there are no initalizers at all (and also no imported modules) we reduce
+   this to an empty function (since the Itanium ABI requires that this function
+   be available to a caller, which might be produced by a 
diff erent
+   implementation).
 
First we call any initializers for imported modules.
We then call initializers for the Global Module Fragment (if present)
@@ -652,13 +657,10 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module 
*Primary) {
   while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
 CXXGlobalInits.pop_back();
 
-  // We create the function, even if it is empty, since an importer of this
-  // module will refer to it unconditionally (for the current implementation
-  // there is no way for the importer to know that an importee does not need
-  // an initializer to be run).
-
+  // As noted above, we create the function, even if it is empty.
   // Module initializers for imported modules are emitted first.
-  // Collect the modules that we import
+
+  // Collect all the modules that we import
   SmallVector AllImports;
   // Ones that we export
   for (auto I : Primary->Exports)
@@ -685,7 +687,6 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
 FTy, llvm::Function::ExternalLinkage, FnName.str(), ());
 ModuleInits.push_back(Fn);
   }
-  AllImports.clear();
 
   // Add any initializers with specified priority; this uses the same  approach
   // as EmitCXXGlobalInitFunc().
@@ -703,13 +704,11 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module 
*Primary) {
   for (; I < PrioE; ++I)
 ModuleInits.push_back(I->second);
 }
-PrioritizedCXXGlobalInits.clear();
   }
 
   // Now append the ones without specified priority.
   for (auto *F : CXXGlobalInits)
 ModuleInits.push_back(F);
-  CXXGlobalInits.clear();
 
   llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
   const CGFunctionInfo  = getTypes().arrangeNullaryFunction();
@@ -719,7 +718,6 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
   // each init is run just once (even though a module might be imported
   // multiple times via nested use).
   llvm::Function *Fn;
-  llvm::GlobalVariable *Guard = nullptr;
   {
 SmallString<256> InitFnName;
 llvm::raw_svector_ostream Out(InitFnName);
@@ -729,18 +727,26 @@ void CodeGenModule::EmitCXXModuleInitFunc(Module 
*Primary) {
 FTy, llvm::Twine(InitFnName), FI, SourceLocation(), false,
 llvm::GlobalVariable::ExternalLinkage);
 
-Guard = new llvm::GlobalVariable(getModule(), Int8Ty, /*isConstant=*/false,
- llvm::GlobalVariable::InternalLinkage,
- llvm::ConstantInt::get(Int8Ty, 0),
- InitFnName.str() + "__in_chrg");
+// If we have a completely empty initializer then we do not want to create
+// the guard variable.
+ConstantAddress GuardAddr = ConstantAddress::invalid();
+if (!AllImports.empty() || !PrioritizedCXXGlobalInits.empty() ||
+ 

[clang] fee3ccc - [C++20][Modules] Improve handing of Private Module Fragment diagnostics.

2022-08-21 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-08-21T10:19:46+01:00
New Revision: fee36cdabdeddc688cf7a15b144c814dd93d

URL: 
https://github.com/llvm/llvm-project/commit/fee36cdabdeddc688cf7a15b144c814dd93d
DIFF: 
https://github.com/llvm/llvm-project/commit/fee36cdabdeddc688cf7a15b144c814dd93d.diff

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

This adds a check for exported inline functions, that there is a definition in
the definition domain (which, in practice, can only be the module purview but
before any PMF starts) since the PMF definition domain cannot contain exports.

This is:
[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.

The patch also amends diagnostic output by excluding the PMF sub-module from the
set considered as sources of missing decls.  There is no point in telling the 
user
that the import of a PMF object is missing - since such objects are never 
reachable
to an importer.  We still show the definition (as unreachable), to help point 
out
this.

Differential Revision: https://reviews.llvm.org/D128328

Added: 
clang/test/Modules/cxx20-10-5-ex1.cpp

Modified: 
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

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e4e7d7b7338a4..791ef9d71dec8 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11141,6 +11141,8 @@ def err_export_using_internal : Error<
 def err_export_not_in_module_interface : Error<
   "export declaration can only be used within a module interface unit"
   "%select{ after the module declaration|}0">;
+def err_export_inline_not_defined : Error<
+  "inline function not defined%select{| before the private module fragment}0">;
 def err_export_partition_impl : Error<
   "module partition implementations cannot be exported">;
 def err_export_in_private_module_fragment : Error<

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 28a47a2eea8b8..14bb2b1d2beed 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2258,6 +2258,11 @@ class Sema final {
   /// Namespace definitions that we will export when they finish.
   llvm::SmallPtrSet DeferredExportedNamespaces;
 
+  /// In a C++ standard module, inline declarations require a definition to be
+  /// present at the end of a definition domain.  This set holds the decls to
+  /// be checked at the end of the TU.
+  llvm::SmallPtrSet PendingInlineFuncDecls;
+
   /// Helper function to judge if we are in module purview.
   /// Return false if we are not in a module.
   bool isCurrentModulePurview() const {

diff  --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 1d27f74f00e56..04100324c786e 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1251,6 +1251,33 @@ void Sema::ActOnEndOfTranslationUnit() {
 emitAndClearUnusedLocalTypedefWarnings();
   }
 
+  // C++ standard modules. Diagnose cases where a function is declared inline
+  // in the module purview but has no definition before the end of the TU or
+  // the start of a Private Module Fragment (if one is present).
+  if (!PendingInlineFuncDecls.empty()) {
+for (auto *D : PendingInlineFuncDecls) {
+  if (auto *FD = dyn_cast(D)) {
+bool DefInPMF = false;
+if (auto *FDD = FD->getDefinition()) {
+  assert(FDD->getOwningModule() &&
+ FDD->getOwningModule()->isModulePurview());
+  DefInPMF = FDD->getOwningModule()->isPrivateModule();
+  if (!DefInPMF)
+continue;
+}
+Diag(FD->getLocation(), diag::err_export_inline_not_defined)
+<< DefInPMF;
+// If we have a PMF it should be at the end of the ModuleScopes.
+if (DefInPMF &&
+ModuleScopes.back().Module->Kind == Module::PrivateModuleFragment) 
{
+  Diag(ModuleScopes.back().BeginLoc,
+   diag::note_private_module_fragment);
+}
+  }
+}
+PendingInlineFuncDecls.clear();
+  }
+
   // C99 6.9.2p2:
   //   A declaration of an identifier for an object that has file
   //   scope without an initializer, and without a storage-class

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 33b49482c6e55..004c1ffd81b9f 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9838,6 +9838,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
   

[clang] a2dd613 - [clang][Modules] Fix a regression in handling missing framework headers.

2022-08-19 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-08-19T09:13:22+01:00
New Revision: a2dd6130d49777d63c2d1b641bd8e56f26fa0822

URL: 
https://github.com/llvm/llvm-project/commit/a2dd6130d49777d63c2d1b641bd8e56f26fa0822
DIFF: 
https://github.com/llvm/llvm-project/commit/a2dd6130d49777d63c2d1b641bd8e56f26fa0822.diff

LOG: [clang][Modules] Fix a regression in handling missing framework headers.

The commit of af2d11b1d5c1508b506825df460656e0151cd3b0 missed a case where
the value of a suggested module needed to be reset to nullptr.  Fixed thus
and added a testcase to cover the circumstance.

Added: 
clang/test/Modules/missing-framework-header.cpp

Modified: 
clang/lib/Lex/PPDirectives.cpp

Removed: 




diff  --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 08ac45710e048..97d0bba1ea2e1 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -2286,6 +2286,7 @@ Preprocessor::ImportAction 
Preprocessor::HandleHeaderIncludeOrImport(
   // actual module containing it exists (because the umbrella header is
   // incomplete).  Treat this as a textual inclusion.
   SuggestedModule = ModuleMap::KnownHeader();
+  SM = nullptr;
 } else if (Imported.isConfigMismatch()) {
   // On a configuration mismatch, enter the header textually. We still know
   // that it's part of the corresponding module.

diff  --git a/clang/test/Modules/missing-framework-header.cpp 
b/clang/test/Modules/missing-framework-header.cpp
new file mode 100644
index 0..b618451bd3214
--- /dev/null
+++ b/clang/test/Modules/missing-framework-header.cpp
@@ -0,0 +1,27 @@
+// RUN: rm -rf %t && mkdir %t
+// RUN: split-file %s %t
+
+//--- frameworks/FW.framework/Modules/module.modulemap
+framework module FW {
+   umbrella header "FW.h"
+   module * { export * }
+}
+
+//--- frameworks/FW.framework/Headers/FW.h
+#include "One.h"
+//--- frameworks/FW.framework/Headers/One.h
+//--- frameworks/FW.framework/Headers/Two.h
+
+//--- module.modulemap
+module Mod { header "Mod.h" }
+//--- Mod.h
+#include "FW/Two.h"
+//--- from_module.m
+#include "Mod.h"
+
+// RUN: %clang -fmodules -fmodules-cache-path=%t/cache \
+// RUN: -iframework %t/frameworks -c %t/from_module.m -o %t/from_module.o \
+// RUN:  2>&1 | FileCheck %s
+
+// CHECK: warning: missing submodule 'FW.Two'
+



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


[clang] 25558a1 - [C++20][Modules] Update ADL to handle basic.lookup.argdep p4 [P1815R2 part 1]

2022-07-25 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-25T14:28:59+01:00
New Revision: 25558a1bfd79e03bed74873ab83ccfc3650fb64f

URL: 
https://github.com/llvm/llvm-project/commit/25558a1bfd79e03bed74873ab83ccfc3650fb64f
DIFF: 
https://github.com/llvm/llvm-project/commit/25558a1bfd79e03bed74873ab83ccfc3650fb64f.diff

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

This includes the revised provisions of [basic.lookup.argdep] p4

1. ADL is amended to handle p 4.3 where functions in trasitively imported 
modules may
become visible when they are exported in the same namespace as a visible type.

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

[basic.lookup.argdep] p5 ex 2 now passes.

Differential Revision: https://reviews.llvm.org/D129174

Added: 
clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp

Modified: 
clang/include/clang/Sema/Overload.h
clang/lib/Sema/SemaLookup.cpp
clang/lib/Sema/SemaOverload.cpp

Removed: 




diff  --git a/clang/include/clang/Sema/Overload.h 
b/clang/include/clang/Sema/Overload.h
index 48997e186ef69..fb4812675d9a3 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -795,6 +795,10 @@ class Sema;
 /// This candidate was not viable because its associated constraints were
 /// not satisfied.
 ovl_fail_constraints_not_satisfied,
+
+/// This candidate was not viable because it has internal linkage and is
+/// from a 
diff erent module unit than the use.
+ovl_fail_module_mismatched,
   };
 
   /// A list of implicit conversion sequences for the arguments of an

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 242e1f81d75c0..66e0efccb4b47 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3838,6 +3838,12 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, 
SourceLocation Loc,
 //associated classes are visible within their respective
 //namespaces even if they are not visible during an ordinary
 //lookup (11.4).
+//
+// C++20 [basic.lookup.argdep] p4.3
+// -- are exported, are attached to a named module M, do not appear
+//in the translation unit containing the point of the lookup, and
+//have the same innermost enclosing non-inline namespace scope as
+//a declaration of an associated entity attached to M.
 DeclContext::lookup_result R = NS->lookup(Name);
 for (auto *D : R) {
   auto *Underlying = D;
@@ -3858,6 +3864,36 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, 
SourceLocation Loc,
   if (isVisible(D)) {
 Visible = true;
 break;
+  } else if (getLangOpts().CPlusPlusModules &&
+ D->isInExportDeclContext()) {
+// C++20 [basic.lookup.argdep] p4.3 .. are exported ...
+Module *FM = D->getOwningModule();
+// exports are only valid in module purview and outside of any
+// PMF (although a PMF should not even be present in a module
+// with an import).
+assert(FM && FM->isModulePurview() && !FM->isPrivateModule() &&
+   "bad export context");
+// .. are attached to a named module M, do not appear in the
+// translation unit containing the point of the lookup..
+if (!isModuleUnitOfCurrentTU(FM) &&
+llvm::any_of(AssociatedClasses, [&](auto *E) {
+  // ... and have the same innermost enclosing non-inline
+  // namespace scope as a declaration of an associated entity
+  // attached to M
+  if (!E->hasOwningModule() ||
+  E->getOwningModule()->getTopLevelModuleName() !=
+  FM->getTopLevelModuleName())
+return false;
+  // TODO: maybe this could be cached when generating the
+  // associated namespaces / entities.
+  DeclContext *Ctx = E->getDeclContext();
+  while (!Ctx->isFileContext() || Ctx->isInlineNamespace())
+Ctx = Ctx->getParent();
+  return Ctx == NS;
+})) {
+  Visible = true;
+  break;
+}
   }
 } else if (D->getFriendObjectKind()) {
   auto *RD = cast(D->getLexicalDeclContext());

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index c226ed6254790..65dae00345f6d 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -6400,6 +6400,17 @@ void Sema::AddOverloadCandidate(
 return;
   }
 
+  // Functions with internal linkage are only viable in the same module unit.
+  if (auto *MF = 

[clang] b826567 - [C++20][Modules] Add a testcase for [basic.link] p10 [NFC].

2022-07-25 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-25T12:20:02+01:00
New Revision: b826567136e391095b7731d5121e2be2a8fdc9ee

URL: 
https://github.com/llvm/llvm-project/commit/b826567136e391095b7731d5121e2be2a8fdc9ee
DIFF: 
https://github.com/llvm/llvm-project/commit/b826567136e391095b7731d5121e2be2a8fdc9ee.diff

LOG: [C++20][Modules] Add a testcase for [basic.link] p10 [NFC].

This adds a testcase based on example 2 from the basic.link section of the
standard.

Added: 
clang/test/CXX/basic/basic.link/p10-ex2.cpp

Modified: 


Removed: 




diff  --git a/clang/test/CXX/basic/basic.link/p10-ex2.cpp 
b/clang/test/CXX/basic/basic.link/p10-ex2.cpp
new file mode 100644
index 0..322785ecbbf12
--- /dev/null
+++ b/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}}



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


[clang] afda39a - re-land [C++20][Modules] Build module static initializers per P1874R1.

2022-07-22 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-22T08:38:07+01:00
New Revision: afda39a566d9b076bbcbeac1a6a1d4f6aecb3274

URL: 
https://github.com/llvm/llvm-project/commit/afda39a566d9b076bbcbeac1a6a1d4f6aecb3274
DIFF: 
https://github.com/llvm/llvm-project/commit/afda39a566d9b076bbcbeac1a6a1d4f6aecb3274.diff

LOG: re-land [C++20][Modules] Build module static initializers per P1874R1.

The re-land fixes module map module dependencies seen on Greendragon, but
not in the clang test suite.

---

Currently we only implement this for the Itanium ABI since the correct
mangling for the initializers in other ABIs is not yet known.

Intended result:

For a module interface [which includes partition interface and implementation
units] (instead of the generic CXX initializer) we emit a module init that:

 - wraps the contained initializations in a control variable to ensure that
   the inits only happen once, even if a module is imported many times by
   imports of the main unit.

 - calls module initializers for imported modules first.  Note that the
   order of module import is not significant, and therefore neither is the
   order of imported module initializers.

 - We then call initializers for the Global Module Fragment (if present)
 - We then call initializers for the current module.
 - We then call initializers for the Private Module Fragment (if present)

For a module implementation unit, or a non-module TU that imports at least one
module we emit a regular CXX init that:

 - Calls the initializers for any imported modules first.
 - Then proceeds as normal with remaining inits.

For all module unit kinds we include a global constructor entry, this allows
for the (in most cases unusual) possibility that a module object could be
included in a final binary without a specific call to its initializer.

Implementation:

 - We provide the module pointer in the AST Context so that CodeGen can act
   on it and its sub-modules.

 - We need to account for module build lines like this:
  ` clang -cc1 -std=c++20 Foo.pcm -emit-obj -o Foo.o` or
  ` clang -cc1 -std=c++20 -xc++-module Foo.cpp -emit-obj -o Foo.o`

 - in order to do this, we add to ParseAST to set the module pointer in
   the ASTContext, once we establish that this is a module build and we
   know the module pointer. To be able to do this, we make the query for
   current module public in Sema.

 - In CodeGen, we determine if the current build requires a CXX20-style module
   init and, if so, we defer any module initializers during the "Eagerly
   Emitted" phase.

 - We then walk the module initializers at the end of the TU but before
   emitting deferred inits (which adds any hidden and static ones, fixing
   https://github.com/llvm/llvm-project/issues/51873 ).

 - We then proceed to emit the deferred inits and continue to emit the CXX
   init function.

Differential Revision: https://reviews.llvm.org/D126189

Added: 
clang/test/CodeGen/module-intializer-pmf.cpp
clang/test/CodeGen/module-intializer.cpp

Modified: 
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

Removed: 




diff  --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 85eba45e4de6e..9536b3faa02da 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -473,6 +473,9 @@ class ASTContext : public RefCountedBase {
   };
   llvm::DenseMap ModuleInitializers;
 
+  /// For module code-gen cases, this is the top-level module we are building.
+  Module *TopLevelModule = nullptr;
+
   static constexpr unsigned ConstantArrayTypesLog2InitSize = 8;
   static constexpr unsigned GeneralTypesLog2InitSize = 9;
   static constexpr unsigned FunctionProtoTypesLog2InitSize = 12;
@@ -1076,6 +1079,12 @@ class ASTContext : public RefCountedBase {
   /// Get the initializations to perform when importing a module, if any.
   ArrayRef getModuleInitializers(Module *M);
 
+  /// Set the (C++20) module we are building.
+  void setModuleForCodeGen(Module *M) { TopLevelModule = M; }
+
+  /// Get module under construction, nullptr if this is not a C++20 module.
+  Module *getModuleForCodeGen() const { return TopLevelModule; }
+
   TranslationUnitDecl *getTranslationUnitDecl() const {
 return TUDecl->getMostRecentDecl();
   }

diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index a1778baa04530..47d736a3b4557 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -665,6 +665,18 @@ class Module {
   Module *findSubmodule(StringRef Name) const;
   Module *findOrInferSubmodule(StringRef Name);
 
+  /// Get the Global Module Fragment (sub-module) for this 

[clang] 97af17c - re-land [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-21 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-21T09:17:01+01:00
New Revision: 97af17c5cae64f5fd5e89806e8cf20f50fec30ec

URL: 
https://github.com/llvm/llvm-project/commit/97af17c5cae64f5fd5e89806e8cf20f50fec30ec
DIFF: 
https://github.com/llvm/llvm-project/commit/97af17c5cae64f5fd5e89806e8cf20f50fec30ec.diff

LOG: re-land [C++20][Modules] Update handling of implicit inlines [P1779R3]

re-land fixes an unwanted interaction with module-map modules, seen in
Greendragon testing.

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.

Differential Revision: https://reviews.llvm.org/D129045

Added: 
clang/test/CXX/class/class.friend/p7-cxx20.cpp
clang/test/CXX/class/class.mfct/p1-cxx20.cpp

Modified: 
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

Removed: 




diff  --git a/clang/lib/AST/TextNodeDumper.cpp 
b/clang/lib/AST/TextNodeDumper.cpp
index 79e9fa6ab86fc..22643d4edbecb 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1720,6 +1720,9 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl 
*D) {
 }
   }
 
+  if (!D->isInlineSpecified() && D->isInlined()) {
+OS << " implicit-inline";
+  }
   // Since NumParams comes from the FunctionProtoType of the FunctionDecl and
   // the Params are set later, it is possible for a dump during debugging to
   // encounter a FunctionDecl that has been created but hasn't been assigned

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5a546503ccedc..736c299f38bb8 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9411,15 +9411,27 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 NewFD->setLocalExternDecl();
 
   if (getLangOpts().CPlusPlus) {
+// The rules for implicit inlines changed in C++20 for methods and friends
+// with an in-class definition (when such a definition is not attached to
+// the global module).  User-specified 'inline' overrides this (set when
+// the function decl is created above).
+// FIXME: We need a better way to separate C++ standard and clang modules.
+bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlusModules ||
+   !NewFD->getOwningModule() ||
+   NewFD->getOwningModule()->isGlobalModule() ||
+   NewFD->getOwningModule()->isModuleMapModule();
 bool isInline = D.getDeclSpec().isInlineSpecified();
 bool isVirtual = D.getDeclSpec().isVirtualSpecified();
 bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier();
 isFriend = D.getDeclSpec().isFriendSpecified();
 if (isFriend && !isInline && D.isFunctionDefinition()) {
-  // C++ [class.friend]p5
+  // Pre-C++20 [class.friend]p5
   //   A function can be defined in a friend declaration of a
   //   class . . . . Such a function is implicitly inline.
-  NewFD->setImplicitlyInline();
+  // Post C++20 [class.friend]p7
+  //   Such a function is implicitly an inline function if it is attached
+  //   to the global module.
+  NewFD->setImplicitlyInline(ImplicitInlineCXX20);
 }
 
 // If this is a method defined in an __interface, and is not a constructor
@@ -9702,11 +9714,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 }
 
 if (isa(NewFD) && DC == CurContext &&
-D.isFunctionDefinition()) {
-  // C++ [class.mfct]p2:
+D.isFunctionDefinition() && !isInline) {
+  // 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)
-  NewFD->setImplicitlyInline();
+  // 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.
+  NewFD->setImplicitlyInline(ImplicitInlineCXX20);
 }
 
 if (SC == SC_Static && isa(NewFD) &&

diff  --git a/clang/test/AST/ast-dump-constant-expr.cpp 
b/clang/test/AST/ast-dump-constant-expr.cpp
index 

[clang] b19d3ee - Revert "[C++20][Modules] Build module static initializers per P1874R1."

2022-07-11 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-11T19:50:31+01:00
New Revision: b19d3ee7120bff4a84db7c9fa8f86c9b6ec3b1cf

URL: 
https://github.com/llvm/llvm-project/commit/b19d3ee7120bff4a84db7c9fa8f86c9b6ec3b1cf
DIFF: 
https://github.com/llvm/llvm-project/commit/b19d3ee7120bff4a84db7c9fa8f86c9b6ec3b1cf.diff

LOG: Revert "[C++20][Modules] Build module static initializers per P1874R1."

This reverts commit ac507102d258b6fc0cb57eb60c9dfabd57ff562f.

reverting while we figuere out why one of the green dragon lldb test fails.

Added: 


Modified: 
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

Removed: 
clang/test/CodeGen/module-intializer-pmf.cpp
clang/test/CodeGen/module-intializer.cpp



diff  --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index db7ae9a0b55c9..87b5a6053f1f2 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -472,9 +472,6 @@ class ASTContext : public RefCountedBase {
   };
   llvm::DenseMap ModuleInitializers;
 
-  /// For module code-gen cases, this is the top-level module we are building.
-  Module *TopLevelModule = nullptr;
-
   static constexpr unsigned ConstantArrayTypesLog2InitSize = 8;
   static constexpr unsigned GeneralTypesLog2InitSize = 9;
   static constexpr unsigned FunctionProtoTypesLog2InitSize = 12;
@@ -1078,12 +1075,6 @@ class ASTContext : public RefCountedBase {
   /// Get the initializations to perform when importing a module, if any.
   ArrayRef getModuleInitializers(Module *M);
 
-  /// Set the (C++20) module we are building.
-  void setModuleForCodeGen(Module *M) { TopLevelModule = M; }
-
-  /// Get module under construction, nullptr if this is not a C++20 module.
-  Module *getModuleForCodeGen() const { return TopLevelModule; }
-
   TranslationUnitDecl *getTranslationUnitDecl() const {
 return TUDecl->getMostRecentDecl();
   }

diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index 47d736a3b4557..a1778baa04530 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -665,18 +665,6 @@ class Module {
   Module *findSubmodule(StringRef Name) const;
   Module *findOrInferSubmodule(StringRef Name);
 
-  /// Get the Global Module Fragment (sub-module) for this module, it there is
-  /// one.
-  ///
-  /// \returns The GMF sub-module if found, or NULL otherwise.
-  Module *getGlobalModuleFragment() { return findSubmodule(""); }
-
-  /// Get the Private Module Fragment (sub-module) for this module, it there is
-  /// one.
-  ///
-  /// \returns The PMF sub-module if found, or NULL otherwise.
-  Module *getPrivateModuleFragment() { return findSubmodule(""); }
-
   /// Determine whether the specified module would be visible to
   /// a lookup at the end of this module.
   ///

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7dafb1b84af07..75a2e7eb31d19 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2281,11 +2281,6 @@ class Sema final {
 return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
   }
 
-  /// Is the module scope we are an interface?
-  bool currentModuleIsInterface() const {
-return ModuleScopes.empty() ? false : ModuleScopes.back().ModuleInterface;
-  }
-
   /// Get the module owning an entity.
   Module *getOwningModule(const Decl *Entity) {
 return Entity->getOwningModule();

diff  --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 98b630617f26f..de5cb913220a0 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -618,127 +618,6 @@ void CodeGenModule::EmitCXXThreadLocalInitFunc() {
   CXXThreadLocals.clear();
 }
 
-/* Build the initializer for a C++20 module:
-   This is arranged to be run only once regardless of how many times the module
-   might be included transitively.  This arranged by using a control variable.
-
-   First we call any initializers for imported modules.
-   We then call initializers for the Global Module Fragment (if present)
-   We then call initializers for the current module.
-   We then call initializers for the Private Module Fragment (if present)
-*/
-
-void CodeGenModule::EmitCXXModuleInitFunc(Module *Primary) {
-  while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
-CXXGlobalInits.pop_back();
-
-  // We create the function, even if it is empty, since an importer of this
-  // module will refer to it unconditionally (for the current implementation
-  // there is no way for the importer to know that an importee does not need
-  // an initializer to be run).
-
-  // Module initializers 

[clang] e7c8ded - Revert "[C++20][Modules] Fix two tests for CTORs that return pointers [NFC]."

2022-07-11 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-11T19:49:48+01:00
New Revision: e7c8ded6df6d38b019a1de268535d2dd73e7adaf

URL: 
https://github.com/llvm/llvm-project/commit/e7c8ded6df6d38b019a1de268535d2dd73e7adaf
DIFF: 
https://github.com/llvm/llvm-project/commit/e7c8ded6df6d38b019a1de268535d2dd73e7adaf.diff

LOG: Revert "[C++20][Modules] Fix two tests for CTORs that return pointers 
[NFC]."

This reverts commit 4328b960176f4394416093e640ad4265bde65ad7.

reverting while we figure out why one of the Greendragon lldb tests fails.

Added: 


Modified: 
clang/test/CodeGen/module-intializer-pmf.cpp
clang/test/CodeGen/module-intializer.cpp

Removed: 




diff  --git a/clang/test/CodeGen/module-intializer-pmf.cpp 
b/clang/test/CodeGen/module-intializer-pmf.cpp
index e513b280b0a75..082dda19fea09 100644
--- a/clang/test/CodeGen/module-intializer-pmf.cpp
+++ b/clang/test/CodeGen/module-intializer-pmf.cpp
@@ -29,11 +29,11 @@ struct InPMF {
 InPMF P;
 
 // CHECK: define internal void @__cxx_global_var_init
-// CHECK: call {{.*}} @_ZN4GlobC1Ev
+// CHECK: call void @_ZN4GlobC1Ev
 // CHECK: define internal void @__cxx_global_var_init
-// CHECK: call {{.*}} @_ZNW6HasPMF5InPMFC1Ev
+// CHECK: call void @_ZNW6HasPMF5InPMFC1Ev
 // CHECK: define internal void @__cxx_global_var_init
-// CHECK: call {{.*}} @_ZNW6HasPMF5InModC1Ev
+// CHECK: call void @_ZNW6HasPMF5InModC1Ev
 // CHECK: define void @_ZGIW6HasPMF
 // CHECK: store i8 1, ptr @_ZGIW6HasPMF__in_chrg
 // CHECK: call void @__cxx_global_var_init

diff  --git a/clang/test/CodeGen/module-intializer.cpp 
b/clang/test/CodeGen/module-intializer.cpp
index 0b48e87f9ea7c..df2f0a5d17da6 100644
--- a/clang/test/CodeGen/module-intializer.cpp
+++ b/clang/test/CodeGen/module-intializer.cpp
@@ -53,9 +53,9 @@ export struct Quack {
 export Quack Duck;
 
 // CHECK-N: define internal void @__cxx_global_var_init
-// CHECK-N: call {{.*}} @_ZN4OinkC1Ev
+// CHECK-N: call void @_ZN4OinkC1Ev
 // CHECK-N: define internal void @__cxx_global_var_init
-// CHECK-N: call {{.*}} @_ZNW1N5QuackC1Ev
+// 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
@@ -83,9 +83,9 @@ export struct Bark {
 export Bark Dog;
 
 // CHECK-O: define internal void @__cxx_global_var_init
-// CHECK-O: call {{.*}} @_ZN4MeowC2Ev
+// CHECK-O: call void @_ZN4MeowC2Ev
 // CHECK-O: define internal void @__cxx_global_var_init
-// CHECK-O: call {{.*}} @_ZNW1O4BarkC1Ev
+// 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
@@ -113,9 +113,9 @@ struct Squawk {
 Squawk parrot;
 
 // CHECK-P: define internal void @__cxx_global_var_init
-// CHECK-P: call {{.*}} @_ZN5CroakC1Ev
+// CHECK-P: call void @_ZN5CroakC1Ev
 // CHECK-P: define internal void @__cxx_global_var_init
-// CHECK-P: call {{.*}} @_ZNW1M6SquawkC1Ev
+// 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
@@ -149,9 +149,9 @@ export struct Baa {
 export Baa Sheep(10);
 
 // CHECK-M: define internal void @__cxx_global_var_init
-// CHECK-M: call {{.*}} @_ZN3MooC1Ev
+// CHECK-M: call void @_ZN3MooC1Ev
 // CHECK-M: define internal void @__cxx_global_var_init
-// CHECK-M: call {{.*}} @_ZNW1M3BaaC1Ei
+// CHECK-M: call void @_ZNW1M3BaaC1Ei
 // CHECK-M: declare void @_ZGIW1O()
 // CHECK-M: declare void @_ZGIW1N()
 // CHECK-M: declare void @_ZGIW1MWP4Part()



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


[clang] af2d11b - [C++20][Modules] Implement include translation.

2022-07-10 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-10T11:06:51+01:00
New Revision: af2d11b1d5c1508b506825df460656e0151cd3b0

URL: 
https://github.com/llvm/llvm-project/commit/af2d11b1d5c1508b506825df460656e0151cd3b0
DIFF: 
https://github.com/llvm/llvm-project/commit/af2d11b1d5c1508b506825df460656e0151cd3b0.diff

LOG: [C++20][Modules] Implement include translation.

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.

Differential Revision: https://reviews.llvm.org/D128981

Added: 
clang/test/Modules/cxx20-include-translation.cpp

Modified: 
clang/include/clang/Lex/Preprocessor.h
clang/lib/Lex/PPDirectives.cpp
clang/lib/Lex/Preprocessor.cpp
clang/lib/Parse/Parser.cpp

Removed: 




diff  --git a/clang/include/clang/Lex/Preprocessor.h 
b/clang/include/clang/Lex/Preprocessor.h
index d130aba3ee3a2..8fc24c7310358 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -385,6 +385,7 @@ class Preprocessor {
 
 bool atTopLevel() { return S <= 0; }
 bool afterImportSeq() { return S == AfterImportSeq; }
+bool afterTopLevelSeq() { return S == AfterTopLevelTokenSeq; }
 
   private:
 State S;
@@ -397,6 +398,67 @@ class Preprocessor {
   /// Our current position within a C++20 import-seq.
   ImportSeq ImportSeqState = ImportSeq::AfterTopLevelTokenSeq;
 
+  /// Track whether we are in a Global Module Fragment
+  class TrackGMF {
+  public:
+enum GMFState : int {
+  GMFActive = 1,
+  MaybeGMF = 0,
+  BeforeGMFIntroducer = -1,
+  GMFAbsentOrEnded = -2,
+};
+
+TrackGMF(GMFState S) : S(S) {}
+
+/// Saw a semicolon.
+void handleSemi() {
+  // If it is immediately after the first instance of the module keyword,
+  // then that introduces the GMF.
+  if (S == MaybeGMF)
+S = GMFActive;
+}
+
+/// Saw an 'export' identifier.
+void handleExport() {
+  // The presence of an 'export' keyword always ends or excludes a GMF.
+  S = GMFAbsentOrEnded;
+}
+
+/// Saw an 'import' identifier.
+void handleImport(bool AfterTopLevelTokenSeq) {
+  // If we see this before any 'module' kw, then we have no GMF.
+  if (AfterTopLevelTokenSeq && S == BeforeGMFIntroducer)
+S = GMFAbsentOrEnded;
+}
+
+/// Saw a 'module' identifier.
+void handleModule(bool AfterTopLevelTokenSeq) {
+  // This was the first module identifier and not preceded by any token
+  // that would exclude a GMF.  It could begin a GMF, but only if directly
+  // followed by a semicolon.
+  if (AfterTopLevelTokenSeq && S == BeforeGMFIntroducer)
+S = MaybeGMF;
+  else
+S = GMFAbsentOrEnded;
+}
+
+/// Saw any other token.
+void handleMisc() {
+  // We saw something other than ; after the 'module' kw, so not a GMF.
+  if (S == MaybeGMF)
+S = GMFAbsentOrEnded;
+}
+
+bool inGMF() { return S == GMFActive; }
+
+  private:
+/// Track the transitions into and out of a Global Module Fragment,
+/// if one is present.
+GMFState S;
+  };
+
+  TrackGMF TrackGMFState = TrackGMF::BeforeGMFIntroducer;
+
   /// Whether the module import expects an identifier next. Otherwise,
   /// it expects a '.' or ';'.
   bool ModuleImportExpectsIdentifier = false;
@@ -2414,6 +2476,7 @@ class Preprocessor {
   None,
   ModuleBegin,
   ModuleImport,
+  HeaderUnitImport,
   SkippedModuleImport,
   Failure,
 } Kind;

diff  --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index 4dcef01e3e4c4..352e1f2178193 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -1983,6 +1983,10 @@ void Preprocessor::HandleIncludeDirective(SourceLocation 
HashLoc,
 EnterAnnotationToken(SourceRange(HashLoc, EndLoc),
 

[clang] ef0fa9f - [C++20][Modules] Update handling of implicit inlines [P1779R3]

2022-07-09 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-09T16:06:32+01:00
New Revision: ef0fa9f0ef3e530a9d600c0f6a21e68b098df7ed

URL: 
https://github.com/llvm/llvm-project/commit/ef0fa9f0ef3e530a9d600c0f6a21e68b098df7ed
DIFF: 
https://github.com/llvm/llvm-project/commit/ef0fa9f0ef3e530a9d600c0f6a21e68b098df7ed.diff

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

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.

Differential Revision: https://reviews.llvm.org/D129045

Added: 
clang/test/CXX/class/class.friend/p7-cxx20.cpp
clang/test/CXX/class/class.mfct/p1-cxx20.cpp

Modified: 
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

Removed: 




diff  --git a/clang/lib/AST/TextNodeDumper.cpp 
b/clang/lib/AST/TextNodeDumper.cpp
index 79e9fa6ab86fc..22643d4edbecb 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1720,6 +1720,9 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl 
*D) {
 }
   }
 
+  if (!D->isInlineSpecified() && D->isInlined()) {
+OS << " implicit-inline";
+  }
   // Since NumParams comes from the FunctionProtoType of the FunctionDecl and
   // the Params are set later, it is possible for a dump during debugging to
   // encounter a FunctionDecl that has been created but hasn't been assigned

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 927d81826425b..c5005accc6961 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9405,15 +9405,25 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 NewFD->setLocalExternDecl();
 
   if (getLangOpts().CPlusPlus) {
+// The rules for implicit inlines changed in C++20 for methods and friends
+// with an in-class definition (when such a definition is not attached to
+// the global module).  User-specified 'inline' overrides this (set when
+// the function decl is created above).
+bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlus20 ||
+   !NewFD->getOwningModule() ||
+   NewFD->getOwningModule()->isGlobalModule();
 bool isInline = D.getDeclSpec().isInlineSpecified();
 bool isVirtual = D.getDeclSpec().isVirtualSpecified();
 bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier();
 isFriend = D.getDeclSpec().isFriendSpecified();
 if (isFriend && !isInline && D.isFunctionDefinition()) {
-  // C++ [class.friend]p5
+  // Pre-C++20 [class.friend]p5
   //   A function can be defined in a friend declaration of a
   //   class . . . . Such a function is implicitly inline.
-  NewFD->setImplicitlyInline();
+  // Post C++20 [class.friend]p7
+  //   Such a function is implicitly an inline function if it is attached
+  //   to the global module.
+  NewFD->setImplicitlyInline(ImplicitInlineCXX20);
 }
 
 // If this is a method defined in an __interface, and is not a constructor
@@ -9696,11 +9706,14 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator , 
DeclContext *DC,
 }
 
 if (isa(NewFD) && DC == CurContext &&
-D.isFunctionDefinition()) {
-  // C++ [class.mfct]p2:
+D.isFunctionDefinition() && !isInline) {
+  // 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)
-  NewFD->setImplicitlyInline();
+  // 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.
+  NewFD->setImplicitlyInline(ImplicitInlineCXX20);
 }
 
 if (SC == SC_Static && isa(NewFD) &&

diff  --git a/clang/test/AST/ast-dump-constant-expr.cpp 
b/clang/test/AST/ast-dump-constant-expr.cpp
index 79cdfc639af5b..302f562eadd96 100644
--- a/clang/test/AST/ast-dump-constant-expr.cpp
+++ b/clang/test/AST/ast-dump-constant-expr.cpp
@@ -58,7 +58,7 @@ struct Test {
 
 // CHECK:Dumping Test:
 // CHECK-NEXT:CXXRecordDecl {{.*}} <{{.*}}ast-dump-constant-expr.cpp:43:1, 
line:57:1> 

[clang] 4328b96 - [C++20][Modules] Fix two tests for CTORs that return pointers [NFC].

2022-07-09 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-09T11:23:20+01:00
New Revision: 4328b960176f4394416093e640ad4265bde65ad7

URL: 
https://github.com/llvm/llvm-project/commit/4328b960176f4394416093e640ad4265bde65ad7
DIFF: 
https://github.com/llvm/llvm-project/commit/4328b960176f4394416093e640ad4265bde65ad7.diff

LOG: [C++20][Modules] Fix two tests for CTORs that return pointers [NFC].

The test are to check that we call the correctly mangled CTORs, so that
the return values from them are irrelevant.  I forgot that some targets
return a pointer, apologies for the breakage.

Added: 


Modified: 
clang/test/CodeGen/module-intializer-pmf.cpp
clang/test/CodeGen/module-intializer.cpp

Removed: 




diff  --git a/clang/test/CodeGen/module-intializer-pmf.cpp 
b/clang/test/CodeGen/module-intializer-pmf.cpp
index 082dda19fea09..e513b280b0a75 100644
--- a/clang/test/CodeGen/module-intializer-pmf.cpp
+++ b/clang/test/CodeGen/module-intializer-pmf.cpp
@@ -29,11 +29,11 @@ struct InPMF {
 InPMF P;
 
 // CHECK: define internal void @__cxx_global_var_init
-// CHECK: call void @_ZN4GlobC1Ev
+// CHECK: call {{.*}} @_ZN4GlobC1Ev
 // CHECK: define internal void @__cxx_global_var_init
-// CHECK: call void @_ZNW6HasPMF5InPMFC1Ev
+// CHECK: call {{.*}} @_ZNW6HasPMF5InPMFC1Ev
 // CHECK: define internal void @__cxx_global_var_init
-// CHECK: call void @_ZNW6HasPMF5InModC1Ev
+// CHECK: call {{.*}} @_ZNW6HasPMF5InModC1Ev
 // CHECK: define void @_ZGIW6HasPMF
 // CHECK: store i8 1, ptr @_ZGIW6HasPMF__in_chrg
 // CHECK: call void @__cxx_global_var_init

diff  --git a/clang/test/CodeGen/module-intializer.cpp 
b/clang/test/CodeGen/module-intializer.cpp
index df2f0a5d17da6..0b48e87f9ea7c 100644
--- a/clang/test/CodeGen/module-intializer.cpp
+++ b/clang/test/CodeGen/module-intializer.cpp
@@ -53,9 +53,9 @@ export struct Quack {
 export Quack Duck;
 
 // CHECK-N: define internal void @__cxx_global_var_init
-// CHECK-N: call void @_ZN4OinkC1Ev
+// CHECK-N: call {{.*}} @_ZN4OinkC1Ev
 // CHECK-N: define internal void @__cxx_global_var_init
-// CHECK-N: call void @_ZNW1N5QuackC1Ev
+// CHECK-N: call {{.*}} @_ZNW1N5QuackC1Ev
 // CHECK-N: define void @_ZGIW1N
 // CHECK-N: store i8 1, ptr @_ZGIW1N__in_chrg
 // CHECK-N: call void @__cxx_global_var_init
@@ -83,9 +83,9 @@ export struct Bark {
 export Bark Dog;
 
 // CHECK-O: define internal void @__cxx_global_var_init
-// CHECK-O: call void @_ZN4MeowC2Ev
+// CHECK-O: call {{.*}} @_ZN4MeowC2Ev
 // CHECK-O: define internal void @__cxx_global_var_init
-// CHECK-O: call void @_ZNW1O4BarkC1Ev
+// CHECK-O: call {{.*}} @_ZNW1O4BarkC1Ev
 // CHECK-O: define void @_ZGIW1O
 // CHECK-O: store i8 1, ptr @_ZGIW1O__in_chrg
 // CHECK-O: call void @__cxx_global_var_init
@@ -113,9 +113,9 @@ struct Squawk {
 Squawk parrot;
 
 // CHECK-P: define internal void @__cxx_global_var_init
-// CHECK-P: call void @_ZN5CroakC1Ev
+// CHECK-P: call {{.*}} @_ZN5CroakC1Ev
 // CHECK-P: define internal void @__cxx_global_var_init
-// CHECK-P: call void @_ZNW1M6SquawkC1Ev
+// CHECK-P: call {{.*}} @_ZNW1M6SquawkC1Ev
 // CHECK-P: define void @_ZGIW1MWP4Part
 // CHECK-P: store i8 1, ptr @_ZGIW1MWP4Part__in_chrg
 // CHECK-P: call void @__cxx_global_var_init
@@ -149,9 +149,9 @@ export struct Baa {
 export Baa Sheep(10);
 
 // CHECK-M: define internal void @__cxx_global_var_init
-// CHECK-M: call void @_ZN3MooC1Ev
+// CHECK-M: call {{.*}} @_ZN3MooC1Ev
 // CHECK-M: define internal void @__cxx_global_var_init
-// CHECK-M: call void @_ZNW1M3BaaC1Ei
+// CHECK-M: call {{.*}} @_ZNW1M3BaaC1Ei
 // CHECK-M: declare void @_ZGIW1O()
 // CHECK-M: declare void @_ZGIW1N()
 // CHECK-M: declare void @_ZGIW1MWP4Part()



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


[clang] ac50710 - [C++20][Modules] Build module static initializers per P1874R1.

2022-07-09 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-09T09:09:09+01:00
New Revision: ac507102d258b6fc0cb57eb60c9dfabd57ff562f

URL: 
https://github.com/llvm/llvm-project/commit/ac507102d258b6fc0cb57eb60c9dfabd57ff562f
DIFF: 
https://github.com/llvm/llvm-project/commit/ac507102d258b6fc0cb57eb60c9dfabd57ff562f.diff

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

Currently we only implement this for the Itanium ABI since the correct
mangling for the initializers in other ABIs is not yet known.

Intended result:

For a module interface [which includes partition interface and implementation
units] (instead of the generic CXX initializer) we emit a module init that:

 - wraps the contained initializations in a control variable to ensure that
   the inits only happen once, even if a module is imported many times by
   imports of the main unit.

 - calls module initializers for imported modules first.  Note that the
   order of module import is not significant, and therefore neither is the
   order of imported module initializers.

 - We then call initializers for the Global Module Fragment (if present)
 - We then call initializers for the current module.
 - We then call initializers for the Private Module Fragment (if present)

For a module implementation unit, or a non-module TU that imports at least one
module we emit a regular CXX init that:

 - Calls the initializers for any imported modules first.
 - Then proceeds as normal with remaining inits.

For all module unit kinds we include a global constructor entry, this allows
for the (in most cases unusual) possibility that a module object could be
included in a final binary without a specific call to its initializer.

Implementation:

 - We provide the module pointer in the AST Context so that CodeGen can act
   on it and its sub-modules.

 - We need to account for module build lines like this:
  ` clang -cc1 -std=c++20 Foo.pcm -emit-obj -o Foo.o` or
  ` clang -cc1 -std=c++20 -xc++-module Foo.cpp -emit-obj -o Foo.o`

 - in order to do this, we add to ParseAST to set the module pointer in
   the ASTContext, once we establish that this is a module build and we
   know the module pointer. To be able to do this, we make the query for
   current module public in Sema.

 - In CodeGen, we determine if the current build requires a CXX20-style module
   init and, if so, we defer any module initializers during the "Eagerly
   Emitted" phase.

 - We then walk the module initializers at the end of the TU but before
   emitting deferred inits (which adds any hidden and static ones, fixing
   https://github.com/llvm/llvm-project/issues/51873 ).

 - We then proceed to emit the deferred inits and continue to emit the CXX
   init function.

Differential Revision: https://reviews.llvm.org/D126189

Added: 
clang/test/CodeGen/module-intializer-pmf.cpp
clang/test/CodeGen/module-intializer.cpp

Modified: 
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

Removed: 




diff  --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 87b5a6053f1f2..db7ae9a0b55c9 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -472,6 +472,9 @@ class ASTContext : public RefCountedBase {
   };
   llvm::DenseMap ModuleInitializers;
 
+  /// For module code-gen cases, this is the top-level module we are building.
+  Module *TopLevelModule = nullptr;
+
   static constexpr unsigned ConstantArrayTypesLog2InitSize = 8;
   static constexpr unsigned GeneralTypesLog2InitSize = 9;
   static constexpr unsigned FunctionProtoTypesLog2InitSize = 12;
@@ -1075,6 +1078,12 @@ class ASTContext : public RefCountedBase {
   /// Get the initializations to perform when importing a module, if any.
   ArrayRef getModuleInitializers(Module *M);
 
+  /// Set the (C++20) module we are building.
+  void setModuleForCodeGen(Module *M) { TopLevelModule = M; }
+
+  /// Get module under construction, nullptr if this is not a C++20 module.
+  Module *getModuleForCodeGen() const { return TopLevelModule; }
+
   TranslationUnitDecl *getTranslationUnitDecl() const {
 return TUDecl->getMostRecentDecl();
   }

diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index a1778baa04530..47d736a3b4557 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -665,6 +665,18 @@ class Module {
   Module *findSubmodule(StringRef Name) const;
   Module *findOrInferSubmodule(StringRef Name);
 
+  /// Get the Global Module Fragment (sub-module) for this module, it there is
+  /// one.
+  ///
+  /// \returns The GMF sub-module if found, or NULL otherwise.
+  Module 

[clang] bc2a6de - [C++20][Modules] Allow for redeclarations in partitions.

2022-07-08 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-07-08T19:02:59+01:00
New Revision: bc2a6defc853553b3896cb853bb84fe663f6bfd0

URL: 
https://github.com/llvm/llvm-project/commit/bc2a6defc853553b3896cb853bb84fe663f6bfd0
DIFF: 
https://github.com/llvm/llvm-project/commit/bc2a6defc853553b3896cb853bb84fe663f6bfd0.diff

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

The existing provision is not sufficient, it did not allow for the cases
where an implementation partition includes the primary module interface,
or for the case that an exported interface partition is contains a decl
that is then implemented in a regular implementation unit.

It is somewhat unfortunate that we have to compare top level module names
to achieve this, since built modules are not necessarily available.

TODO: It might be useful to cache a hash of the primary module name if
this test proves to be a  significant load.

Differential Revision: https://reviews.llvm.org/D127624

Added: 
clang/test/Modules/cxx20-partition-redeclarations.cpp

Modified: 
clang/lib/Sema/SemaDecl.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1139088ecde27..d6c89d525cdc2 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1625,22 +1625,20 @@ bool Sema::CheckRedeclarationModuleOwnership(NamedDecl 
*New, NamedDecl *Old) {
   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) {

diff  --git a/clang/test/Modules/cxx20-partition-redeclarations.cpp 
b/clang/test/Modules/cxx20-partition-redeclarations.cpp
new file mode 100644
index 0..f99ef009a79af
--- /dev/null
+++ b/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() {}



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


[clang] 9dc9b21 - [C++20][Modules][Driver][HU 4/N] Add fdirectives-only mode for preprocessing output.

2022-04-23 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-23T14:43:07+01:00
New Revision: 9dc9b21488ee2bbf54e20807585a74a17a33fceb

URL: 
https://github.com/llvm/llvm-project/commit/9dc9b21488ee2bbf54e20807585a74a17a33fceb
DIFF: 
https://github.com/llvm/llvm-project/commit/9dc9b21488ee2bbf54e20807585a74a17a33fceb.diff

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

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.

Differential Revision: https://reviews.llvm.org/D121591

Added: 
clang/test/Driver/cxx20-fdirectives-only.cpp

Modified: 
clang/lib/Driver/Driver.cpp
clang/lib/Driver/ToolChains/Clang.cpp

Removed: 




diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index b453e24769571..2bb6680cf5961 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -4303,10 +4303,14 @@ Action *Driver::ConstructPhaseAction(
   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 &&

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index ddc9559f0d950..0fd639da45ddf 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4594,6 +4594,8 @@ void Clang::ConstructJob(Compilation , const JobAction 
,
   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");
@@ -6707,6 +6709,10 @@ void Clang::ConstructJob(Compilation , const JobAction 
,
   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

diff  --git a/clang/test/Driver/cxx20-fdirectives-only.cpp 
b/clang/test/Driver/cxx20-fdirectives-only.cpp
new file mode 100644
index 0..96dc4fdaa07ac
--- /dev/null
+++ b/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"



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


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

2022-04-23 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-23T09:50:31+01:00
New Revision: 5996306c24badac0e04c1cead1aed4b106a3bdae

URL: 
https://github.com/llvm/llvm-project/commit/5996306c24badac0e04c1cead1aed4b106a3bdae
DIFF: 
https://github.com/llvm/llvm-project/commit/5996306c24badac0e04c1cead1aed4b106a3bdae.diff

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

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.

Differential Revision: https://reviews.llvm.org/D121590

Added: 


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

Removed: 




diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 0da079b1deb38..b453e24769571 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2437,7 +2437,9 @@ void Driver::BuildInputs(const ToolChain , 
DerivedArgList ,
 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);
   }
@@ -2462,8 +2464,11 @@ void Driver::BuildInputs(const ToolChain , 
DerivedArgList ,
 }
 
 // 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");

diff  --git a/clang/test/Driver/cxx20-header-units-02.cpp 
b/clang/test/Driver/cxx20-header-units-02.cpp
index aab999cda2276..7b7a40f9e831f 100644
--- a/clang/test/Driver/cxx20-header-units-02.cpp
+++ b/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"



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


[clang] 4c4ff00 - [C++20][Modules][Driver][HU 2/N] Add fmodule-header, fmodule-header=

2022-04-22 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-22T14:14:19+01:00
New Revision: 4c4ff004a2702b9b7538efd569bb621a5efac8f3

URL: 
https://github.com/llvm/llvm-project/commit/4c4ff004a2702b9b7538efd569bb621a5efac8f3
DIFF: 
https://github.com/llvm/llvm-project/commit/4c4ff004a2702b9b7538efd569bb621a5efac8f3.diff

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

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)

Differential Revision: https://reviews.llvm.org/D121589

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

Modified: 
clang/docs/ClangCommandLineReference.rst
clang/include/clang/Driver/Driver.h
clang/include/clang/Driver/Options.td
clang/lib/Driver/Driver.cpp

Removed: 




diff  --git a/clang/docs/ClangCommandLineReference.rst 
b/clang/docs/ClangCommandLineReference.rst
index 1a0e4805bc263..33f9a55f62484 100644
--- a/clang/docs/ClangCommandLineReference.rst
+++ b/clang/docs/ClangCommandLineReference.rst
@@ -1176,6 +1176,14 @@ Validate the system headers that a module depends on 
when loading the module
 
 Specify the prebuilt module path
 
+.. option:: -fmodule-header
+
+Build a C++20 header unit from a header specified.
+
+.. option:: -fmodule-header=\[user,system\]
+
+Build a C++20 header unit, but search for the header in the user or system 
header search paths respectively.
+
 .. option:: --hip-path=
 
 HIP runtime installation path, used for finding HIP version and adding HIP 
include path.

diff  --git a/clang/include/clang/Driver/Driver.h 
b/clang/include/clang/Driver/Driver.h
index b33b64cd9e6a2..f68f281f0e931 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -56,6 +56,16 @@ enum LTOKind {
   LTOK_Unknown
 };
 
+/// Whether headers used to construct C++20 module units should be looked
+/// up by the path supplied on the command line, or in the user or system
+/// search paths.
+enum ModuleHeaderMode {
+  HeaderMode_None,
+  HeaderMode_Default,
+  HeaderMode_User,
+  HeaderMode_System
+};
+
 /// Driver - Encapsulate logic for constructing compilation processes
 /// from a set of gcc-driver-like command line arguments.
 class Driver {
@@ -84,6 +94,13 @@ class Driver {
 EmbedBitcode
   } BitcodeEmbed;
 
+  /// Header unit mode set by -fmodule-header={user,system}.
+  ModuleHeaderMode CXX20HeaderType;
+
+  /// Set if we should process inputs and jobs with C++20 module
+  /// interpretation.
+  bool ModulesModeCXX20;
+
   /// LTO mode selected via -f(no-)?lto(=.*)? options.
   LTOKind LTOMode;
 
@@ -574,6 +591,12 @@ class Driver {
   /// ShouldEmitStaticLibrary - Should the linker emit a static library.
   bool ShouldEmitStaticLibrary(const llvm::opt::ArgList ) const;
 
+  /// Returns true if the user has indicated a C++20 header unit mode.
+  bool hasHeaderMode() const { return CXX20HeaderType != HeaderMode_None; }
+
+  /// Get the mode for handling headers as set by fmodule-header{=}.
+  ModuleHeaderMode getModuleHeaderMode() const { return CXX20HeaderType; }
+
   /// Returns true if we are performing any kind of LTO.
   bool isUsingLTO(bool IsOffload = false) const {
 return getLTOMode(IsOffload) != LTOK_None;

diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 8c013e3fe5b19..8e3611cff2d63 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2296,6 +2296,11 @@ defm implicit_modules : BoolFOption<"implicit-modules",
   NegFlag, PosFlag, 
BothFlags<[NoXarchOption,CoreOption]>>;
 def fretain_comments_from_system_headers : Flag<["-"], 
"fretain-comments-from-system-headers">, Group, Flags<[CC1Option]>,
   MarshallingInfoFlag>;
+def fmodule_header : Flag <["-"], "fmodule-header">, Group,
+  Flags<[NoXarchOption]>, HelpText<"Build a C++20 Header Unit from a header.">;
+def fmodule_header_EQ : Joined<["-"], "fmodule-header=">, Group,
+  Flags<[NoXarchOption]>, MetaVarName<"">,
+  HelpText<"Build a C++20 Header Unit from a header that should be found in 
the user (fmodule-header=user) or system (fmodule-header=system) search path.">;
 
 def fno_knr_functions : Flag<["-"], "fno-knr-functions">, Group,
   MarshallingInfoFlag>,

diff 

[clang] 5c6a146 - [C++20][Modules][Driver][HU 1/N] Initial handling for -xc++-{system,user}-header.

2022-04-22 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-22T09:24:29+01:00
New Revision: 5c6a14649843ccd2c50ed9e2fcacaa8ebd820ae8

URL: 
https://github.com/llvm/llvm-project/commit/5c6a14649843ccd2c50ed9e2fcacaa8ebd820ae8
DIFF: 
https://github.com/llvm/llvm-project/commit/5c6a14649843ccd2c50ed9e2fcacaa8ebd820ae8.diff

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

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.

Differential Revision: https://reviews.llvm.org/D121588

Added: 
clang/test/Driver/Inputs/header-unit-01.hh
clang/test/Driver/cxx20-header-units-01.cpp

Modified: 
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

Removed: 




diff  --git a/clang/include/clang/Driver/Types.def 
b/clang/include/clang/Driver/Types.def
index 94041b183add2..0cf265e05fedc 100644
--- a/clang/include/clang/Driver/Types.def
+++ b/clang/include/clang/Driver/Types.def
@@ -64,7 +64,11 @@ TYPE("objective-c-header-cpp-output", PP_ObjCHeader, 
INVALID,   "mi", phases
 TYPE("objective-c-header",   ObjCHeader,   PP_ObjCHeader,   "h",  
phases::Preprocess, phases::Precompile)
 TYPE("c++-header-cpp-output",PP_CXXHeader, INVALID, "ii", 
phases::Precompile)
 TYPE("c++-header",   CXXHeader,PP_CXXHeader,"hh", 
phases::Preprocess, phases::Precompile)
-TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID, "mii",  
phases::Precompile)
+TYPE("c++-header-unit-cpp-output", PP_CXXHeaderUnit,INVALID,"iih",
phases::Precompile)
+TYPE("c++-header-unit-header",   CXXHUHeader,  PP_CXXHeaderUnit,"hh", 
phases::Preprocess, phases::Precompile)
+TYPE("c++-system-header",CXXSHeader,   PP_CXXHeaderUnit,"hh", 
phases::Preprocess, phases::Precompile)
+TYPE("c++-user-header",  CXXUHeader,   PP_CXXHeaderUnit,"hh", 
phases::Preprocess, phases::Precompile)
+TYPE("objective-c++-header-cpp-output", PP_ObjCXXHeader, INVALID,"mii",   
phases::Precompile)
 TYPE("objective-c++-header", ObjCXXHeader, PP_ObjCXXHeader, "h",  
phases::Preprocess, phases::Precompile)
 TYPE("c++-module",   CXXModule,PP_CXXModule,"cppm",   
phases::Preprocess, phases::Precompile, phases::Compile, phases::Backend, 
phases::Assemble, phases::Link)
 TYPE("c++-module-cpp-output",PP_CXXModule, INVALID, "iim",
phases::Precompile, phases::Compile, phases::Backend, phases::Assemble, 
phases::Link)
@@ -89,6 +93,7 @@ TYPE("ast",  AST,  INVALID,   
  "ast",phases
 TYPE("ifs",  IFS,  INVALID, "ifs",
phases::IfsMerge)
 TYPE("ifs-cpp",  IFS_CPP,  INVALID, "ifs",
phases::Compile, phases::IfsMerge)
 TYPE("pcm",  ModuleFile,   INVALID, "pcm",
phases::Compile, phases::Backend, phases::Assemble, phases::Link)
+TYPE("header-unit",  HeaderUnit,   INVALID, "pcm",
phases::Compile, phases::Backend, phases::Assemble, phases::Link)
 TYPE("plist",Plist,INVALID, "plist",  
phases::Compile, phases::Backend, phases::Assemble, phases::Link)
 TYPE("rewritten-objc",   RewrittenObjC,INVALID, "cpp",
phases::Compile, phases::Backend, phases::Assemble, phases::Link)
 TYPE("rewritten-legacy-objc",RewrittenLegacyObjC,INVALID,   "cpp",
phases::Compile, phases::Backend, phases::Assemble, phases::Link)

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 1c5fb22026e26..6fa95a8834a2c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -2219,6 +2219,11 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList 
, StringRef Value,
   if (Value == "-")
 return true;
 
+  // If it's a header to be found in the system or user search path, then defer
+  // complaints 

[clang] bdadf1c - [C++20][Modules] Add testcases from section 10.2 dependent on header units.

2022-04-11 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-11T11:30:45+01:00
New Revision: bdadf1c2ecb452ca41f23caa87415bc1f9a8431b

URL: 
https://github.com/llvm/llvm-project/commit/bdadf1c2ecb452ca41f23caa87415bc1f9a8431b
DIFF: 
https://github.com/llvm/llvm-project/commit/bdadf1c2ecb452ca41f23caa87415bc1f9a8431b.diff

LOG: [C++20][Modules] Add testcases from section 10.2 dependent on header units.

This adds in testcases reflecting the remaining example in section 10.2
of the C++20 standard.

Differential Revision: https://reviews.llvm.org/D122124

Added: 
clang/test/Modules/cxx20-10-2-ex2.cpp

Modified: 


Removed: 




diff  --git a/clang/test/Modules/cxx20-10-2-ex2.cpp 
b/clang/test/Modules/cxx20-10-2-ex2.cpp
new file mode 100644
index 0..1b0a02c6f91f9
--- /dev/null
+++ b/clang/test/Modules/cxx20-10-2-ex2.cpp
@@ -0,0 +1,42 @@
+// Based on C++20 10.2 example 2.
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-header-unit -I %t \
+// RUN: -xc++-user-header std-10-2-ex2-c.h -o %t/std-10-2-ex2-c.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std-10-2-ex2-tu1.cpp \
+// RUN:  -o  %t/X.pcm
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std-10-2-ex2-tu2.cpp \
+// RUN: -fmodule-file=%t/std-10-2-ex2-c.pcm -fmodule-file=%t/X.pcm \
+// RUN: -pedantic-errors -verify -o  %t/M.pcm
+
+//--- std-10-2-ex2-b.h
+int f();
+
+//--- std-10-2-ex2-c.h
+int g();
+
+//--- std-10-2-ex2-tu1.cpp
+export module X;
+export int h();
+
+//--- std-10-2-ex2-tu2.cpp
+module;
+#include "std-10-2-ex2-b.h"
+
+export module M;
+import "std-10-2-ex2-c.h";
+import X;
+export using ::f, ::g, ::h; // OK
+struct S;   // expected-note {{target of using declaration}}
+export using ::S;   // expected-error {{using declaration referring to 
'S' with module linkage cannot be exported}}
+
+namespace N {
+export int h();
+static int h(int); // expected-note {{target of using declaration}}
+} // namespace N
+export using N::h; // expected-error {{using declaration referring to 'h' with 
internal linkage cannot be exported}}



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


[clang] 92fed06 - [C++20][Modules] Remove an empty statement [NFC].

2022-04-11 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-11T10:06:23+01:00
New Revision: 92fed06f800aa2d0fd29f9e3eac8323cba64b167

URL: 
https://github.com/llvm/llvm-project/commit/92fed06f800aa2d0fd29f9e3eac8323cba64b167
DIFF: 
https://github.com/llvm/llvm-project/commit/92fed06f800aa2d0fd29f9e3eac8323cba64b167.diff

LOG: [C++20][Modules] Remove an empty statement [NFC].

This addresses a post commit review comment by removing an unused and empty
'else' (replaced with a comment).

Added: 


Modified: 
clang/lib/Sema/SemaModule.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index a9d3540e2ef6e..b0e7d30526a3c 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -858,8 +858,7 @@ static bool checkExportedDecl(Sema , Decl *D, 
SourceLocation BlockStart) {
 // We don't allow an empty anonymous namespace (we don't allow decls
 // in them either, but that's handled in the recursion).
 diagExportedUnnamedDecl(S, UnnamedDeclKind::Namespace, D, BlockStart);
-  else
-; // We allow an empty named namespace decl.
+  // We allow an empty named namespace decl.
 } else if (DC->getRedeclContext()->isFileContext() && !isa(D))
   return checkExportedDeclContext(S, DC, BlockStart);
   }



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


[clang] f60dc3c - [C++20][Modules] Adjust handling of exports of namespaces and using-decls.

2022-04-08 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-08T08:57:37+01:00
New Revision: f60dc3caa67374c0e2941ee3866b5eaef0c6ffe6

URL: 
https://github.com/llvm/llvm-project/commit/f60dc3caa67374c0e2941ee3866b5eaef0c6ffe6
DIFF: 
https://github.com/llvm/llvm-project/commit/f60dc3caa67374c0e2941ee3866b5eaef0c6ffe6.diff

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

This adjusts the handling for:

export module  M;

export namespace {};

export namespace N {};
export using namespace N;

In the first case, we were allowing empty anonymous namespaces
as part of an extension allowing empty top-level entities, but that seems
inappropriate in this case, since the linkage would be internal for the
anonymous namespace.  We now report an error for this.

The second case was producing a warning diagnostic that this was
accepted as an extension - however the C++20 standard does allow this
as well-formed.

In the third case we keep the current practice that this is accepted with a
warning (as an extension). The C++20 standard says it's an error.

We also ensure that using decls are only applied to items with external linkage.

This adjusts error messages for exports involving redeclarations in modules to
be more specific about the reason that the decl has been rejected.

Differential Revision: https://reviews.llvm.org/D122119

Added: 
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

Modified: 
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

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 96cd00c8bb2a1..20b5f1e972471 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7853,8 +7853,8 @@ def err_invalid_declarator_scope : Error<"cannot define 
or redeclare %0 here "
 def err_export_non_namespace_scope_name : Error<
   "cannot export %0 as it is not at namespace scope">;
 def err_redeclaration_non_exported : Error <
-  "cannot export redeclaration %0 here since the previous declaration is not "
-  "exported">;
+  "cannot export redeclaration %0 here since the previous declaration "
+  "%select{is not exported|has internal linkage|has module linkage}1">;
 def err_invalid_declarator_global_scope : Error<
   "definition or redeclaration of %0 cannot name the global scope">;
 def err_invalid_declarator_in_function : Error<
@@ -11071,6 +11071,8 @@ def ext_export_no_name_block : ExtWarn<
 def ext_export_no_names : ExtWarn<
   "ISO C++20 does not permit a declaration that does not introduce any names "
   "to be exported">, InGroup;
+def introduces_no_names : Error<
+  "declaration does not introduce any names to be exported">;
 def note_export : Note<"export block begins here">;
 def err_export_no_name : Error<
   "%select{empty|static_assert|asm}0 declaration cannot be exported">;
@@ -11082,7 +11084,8 @@ def err_export_within_export : Error<
 def err_export_internal : Error<
   "declaration of %0 with internal linkage cannot be exported">;
 def err_export_using_internal : Error<
-  "using declaration referring to %0 with internal linkage cannot be 
exported">;
+  "using declaration referring to %1 with %select{internal|module|unknown}0 "
+  "linkage cannot be exported">;
 def err_export_not_in_module_interface : Error<
   "export declaration can only be used within a module interface unit"
   "%select{ after the module declaration|}0">;

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a2d3722f2efb8..427b25766bc73 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1679,7 +1679,13 @@ bool Sema::CheckRedeclarationExported(NamedDecl *New, 
NamedDecl *Old) {
 
   assert(IsNewExported);
 
-  Diag(New->getLocation(), diag::err_redeclaration_non_exported) << New;
+  auto Lk = Old->getFormalLinkage();
+  int S = 0;
+  if (Lk == Linkage::InternalLinkage)
+S = 1;
+  else if (Lk == Linkage::ModuleLinkage)
+S = 2;
+  Diag(New->getLocation(), diag::err_redeclaration_non_exported) << New << S;
   Diag(Old->getLocation(), diag::note_previous_declaration);
   return true;
 }

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 893b913194aae..a9d3540e2ef6e 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -762,6 +762,7 @@ enum class UnnamedDeclKind {
   StaticAssert,
   Asm,
   UsingDirective,
+  Namespace,
   Context
 };
 }
@@ -791,6 +792,10 @@ unsigned 

[clang] 1f0b8ba - [C++20][Modules] Fix a testcase warning on Windows [NFC].

2022-04-03 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-03T11:39:00+01:00
New Revision: 1f0b8ba47ab0f1dc678099d4830d0cc0d10850b6

URL: 
https://github.com/llvm/llvm-project/commit/1f0b8ba47ab0f1dc678099d4830d0cc0d10850b6
DIFF: 
https://github.com/llvm/llvm-project/commit/1f0b8ba47ab0f1dc678099d4830d0cc0d10850b6.diff

LOG: [C++20][Modules] Fix a testcase warning on Windows [NFC].

As reported, using "-DTDIR=%t" with a path name of 'C:\Users\...' causes
a warning to be emitted about the use of \U without following hex digits.

Since the value is only required for the FileCheck cases resolve this by
omitting the -D from the compile lines.

Added: 


Modified: 
clang/test/Modules/cxx20-hu-04.cpp

Removed: 




diff  --git a/clang/test/Modules/cxx20-hu-04.cpp 
b/clang/test/Modules/cxx20-hu-04.cpp
index 1de8ceff3e7f5..da6056d4d47ed 100644
--- a/clang/test/Modules/cxx20-hu-04.cpp
+++ b/clang/test/Modules/cxx20-hu-04.cpp
@@ -19,10 +19,10 @@
 // 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:  -fmodule-file=hu-02.pcm -o B.pcm -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:  -fmodule-file=hu-02.pcm -o C.pcm -Rmodule-import 2>&1 | \
 // RUN:  FileCheck --check-prefix=CHECK-IMP-HU2 %s -DTDIR=%t
 
 //--- hu-01.h



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


[clang] c7ed65b - [C++20][Modules] Limit ModuleInternalLinkage to modules-ts.

2022-04-01 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-04-01T09:10:30+01:00
New Revision: c7ed65b4bcbd8c26704efc4193243831e3c13d3c

URL: 
https://github.com/llvm/llvm-project/commit/c7ed65b4bcbd8c26704efc4193243831e3c13d3c
DIFF: 
https://github.com/llvm/llvm-project/commit/c7ed65b4bcbd8c26704efc4193243831e3c13d3c.diff

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

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).

Differential Revision: https://reviews.llvm.org/D122413

Added: 


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

Removed: 




diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 46c888430bb07..6af7a37dfc7b2 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -596,11 +596,12 @@ static bool isExportedFromModuleInterfaceUnit(const 
NamedDecl *D) {
 }
 
 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();

diff  --git a/clang/unittests/AST/DeclTest.cpp 
b/clang/unittests/AST/DeclTest.cpp
index 7c227d40af86b..560c6b3ddf434 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -194,3 +194,50 @@ TEST(Decl, InConsistLinkageForTemplates) {
   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  = 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  = 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);
+}



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


[clang] 85b1354 - [C++20][Modules][HU 5/5] Add fdirectives-only mode for preprocessing output.

2022-03-28 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-03-28T07:38:22+01:00
New Revision: 85b1354098ba0a665fdd47204d0e53e63d09d9ab

URL: 
https://github.com/llvm/llvm-project/commit/85b1354098ba0a665fdd47204d0e53e63d09d9ab
DIFF: 
https://github.com/llvm/llvm-project/commit/85b1354098ba0a665fdd47204d0e53e63d09d9ab.diff

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

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

As such, it preserves defines and undefs of macros that are still live after
such processing.  The intent is that this output could be consumed as input
to generate considered a C++20 header unit.

We strip out any (unused) defines that come from built-in, built-in-file or
command line; these are re-added when the preprocessed source is consumed.

Differential Revision: https://reviews.llvm.org/D121099

Added: 
clang/test/Modules/cxx20-hu-06.cpp

Modified: 
clang/include/clang/Driver/Options.td
clang/include/clang/Frontend/PreprocessorOutputOptions.h
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Frontend/PrintPreprocessedOutput.cpp

Removed: 




diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 488692e16145f..ac2f479f159eb 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1873,6 +1873,8 @@ defm rewrite_includes : BoolFOption<"rewrite-includes",
   PreprocessorOutputOpts<"RewriteIncludes">, DefaultFalse,
   PosFlag, NegFlag>;
 
+defm directives_only : OptInCC1FFlag<"directives-only", "">;
+
 defm delete_null_pointer_checks : BoolFOption<"delete-null-pointer-checks",
   CodeGenOpts<"NullPointerIsValid">, DefaultFalse,
   NegFlag,

diff  --git a/clang/include/clang/Frontend/PreprocessorOutputOptions.h 
b/clang/include/clang/Frontend/PreprocessorOutputOptions.h
index 257538ee06065..d542032431b14 100644
--- a/clang/include/clang/Frontend/PreprocessorOutputOptions.h
+++ b/clang/include/clang/Frontend/PreprocessorOutputOptions.h
@@ -25,6 +25,7 @@ class PreprocessorOutputOptions {
   unsigned RewriteIncludes : 1;///< Preprocess include directives only.
   unsigned RewriteImports  : 1;///< Include contents of 
transitively-imported modules.
   unsigned MinimizeWhitespace : 1; ///< Ignore whitespace from input.
+  unsigned DirectivesOnly : 1; ///< Process directives but do not expand 
macros.
 
 public:
   PreprocessorOutputOptions() {
@@ -38,6 +39,7 @@ class PreprocessorOutputOptions {
 RewriteIncludes = 0;
 RewriteImports = 0;
 MinimizeWhitespace = 0;
+DirectivesOnly = 0;
   }
 };
 

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 5bb480a599713..b222119889522 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -4413,6 +4413,8 @@ static void GeneratePreprocessorOutputArgs(
 GenerateArg(Args, OPT_dM, SA);
   if (!Generate_dM && Opts.ShowMacros)
 GenerateArg(Args, OPT_dD, SA);
+  if (Opts.DirectivesOnly)
+GenerateArg(Args, OPT_fdirectives_only, SA);
 }
 
 static bool ParsePreprocessorOutputArgs(PreprocessorOutputOptions ,
@@ -4435,6 +4437,7 @@ static bool 
ParsePreprocessorOutputArgs(PreprocessorOutputOptions ,
 
   Opts.ShowCPP = isStrictlyPreprocessorAction(Action) && !Args.hasArg(OPT_dM);
   Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
+  Opts.DirectivesOnly = Args.hasArg(OPT_fdirectives_only);
 
   return Diags.getNumErrors() == NumErrorsBefore;
 }

diff  --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp 
b/clang/lib/Frontend/PrintPreprocessedOutput.cpp
index e2fc862849ad1..7737d043043d5 100644
--- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp
+++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp
@@ -96,6 +96,7 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
   bool UseLineDirectives;
   bool IsFirstFileEntered;
   bool MinimizeWhitespace;
+  bool DirectivesOnly;
 
   Token PrevTok;
   Token PrevPrevTok;
@@ -103,12 +104,13 @@ class PrintPPOutputPPCallbacks : public PPCallbacks {
 public:
   PrintPPOutputPPCallbacks(Preprocessor , raw_ostream , 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 

[clang] d9cea8d - [C++20][Modules][HU 4/5] Handle pre-processed header units.

2022-03-27 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-03-27T09:38:06+01:00
New Revision: d9cea8d3a8fff86672174780312674871729578c

URL: 
https://github.com/llvm/llvm-project/commit/d9cea8d3a8fff86672174780312674871729578c
DIFF: 
https://github.com/llvm/llvm-project/commit/d9cea8d3a8fff86672174780312674871729578c.diff

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

We wish to support emitting a pre-processed output for an importable
header unit, that can be consumed to produce the same header units as
the original source.

This means that ee need to find the original filename used to produce
the re-preprocessed output, so that it can be assigned as the module
name.  This is peeked from the first line of the pre-processed source
when the action sets up the files.

Differential Revision: https://reviews.llvm.org/D121098

Added: 
clang/test/Modules/cxx20-hu-05.cpp

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

Removed: 




diff  --git a/clang/lib/Frontend/FrontendAction.cpp 
b/clang/lib/Frontend/FrontendAction.cpp
index 68b823252130c..45245f3f0fef4 100644
--- a/clang/lib/Frontend/FrontendAction.cpp
+++ b/clang/lib/Frontend/FrontendAction.cpp
@@ -843,6 +843,21 @@ bool FrontendAction::BeginSourceFile(CompilerInstance ,
   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) {

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index e28de8c79b273..893b913194aae 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -109,10 +109,18 @@ void Sema::HandleStartOfHeaderUnit() {
 const_cast(getLangOpts()).CurrentModule = HUName.str();
   }
 
-  auto  = 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  = PP.getHeaderSearchInfo().getModuleMap();
   Module *Mod = Map.createHeaderUnit(StartOfTU, HUName, H);
   assert(Mod && "module creation should not fail");
   ModuleScopes.push_back({}); // No GMF

diff  --git a/clang/test/Modules/cxx20-hu-05.cpp 
b/clang/test/Modules/cxx20-hu-05.cpp
new file mode 100644
index 0..b0d7c0f3c9e76
--- /dev/null
+++ b/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



___
cfe-commits 

[clang] f884622 - [C++20][Modules][HU 3/5] Emit module macros for header units.

2022-03-26 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-03-26T16:30:40Z
New Revision: f8846229c41f3e4aede3bd06921772a209b4993a

URL: 
https://github.com/llvm/llvm-project/commit/f8846229c41f3e4aede3bd06921772a209b4993a
DIFF: 
https://github.com/llvm/llvm-project/commit/f8846229c41f3e4aede3bd06921772a209b4993a.diff

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

For header units we build the top level module directly from the header
that it represents and macros defined in this TU need to be emitted (when
such a definition is live at the end of the TU).

Differential Revision: https://reviews.llvm.org/D121097

Added: 
clang/test/Modules/cxx20-hu-04.cpp

Modified: 
clang/include/clang/Basic/Module.h
clang/include/clang/Serialization/ASTWriter.h
clang/lib/Serialization/ASTWriter.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index 9752ff61e4a27..4500c78ec6824 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -527,6 +527,9 @@ class Module {
Kind == ModulePartitionImplementation;
   }
 
+  /// Is this module a header unit.
+  bool isHeaderUnit() const { return Kind == ModuleHeaderUnit; }
+
   /// Get the primary module interface name from a partition.
   StringRef getPrimaryModuleInterfaceName() const {
 if (isModulePartition()) {

diff  --git a/clang/include/clang/Serialization/ASTWriter.h 
b/clang/include/clang/Serialization/ASTWriter.h
index e455e4d4d96a5..6cbf3dd20017a 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -18,6 +18,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/LLVM.h"
+#include "clang/Basic/Module.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Sema/Sema.h"
 #include "clang/Sema/SemaConsumer.h"

diff  --git a/clang/lib/Serialization/ASTWriter.cpp 
b/clang/lib/Serialization/ASTWriter.cpp
index c06cbb251c408..90e7fb1714f40 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -2352,13 +2352,22 @@ void ASTWriter::WritePreprocessor(const Preprocessor 
, bool IsModule) {
 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() == MacroDirective::MD_Undefine)
+continue;
   AddSourceLocation(MD->getLocation(), Record);
   Record.push_back(MD->getKind());
   if (auto *DefMD = dyn_cast(MD)) {
@@ -2366,35 +2375,51 @@ void ASTWriter::WritePreprocessor(const Preprocessor 
, bool IsModule) {
   } else if (auto *VisMD = dyn_cast(MD)) {
 Record.push_back(VisMD->isPublic());
   }
-}
+  ModuleMacroRecord.push_back(getSubmoduleID(WritingModule));
+  ModuleMacroRecord.push_back(getMacroRef(MD->getMacroInfo(), Name));
+  Stream.EmitRecord(PP_MODULE_MACRO, ModuleMacroRecord);
+  ModuleMacroRecord.clear();
+  EmittedModuleMacros = true;
+} else {
+  // 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;
+AddSourceLocation(MD->getLocation(), Record);
+Record.push_back(MD->getKind());
+if (auto *DefMD = dyn_cast(MD)) {
+  Record.push_back(getMacroRef(DefMD->getInfo(), Name));
+} else if (auto *VisMD = dyn_cast(MD)) {
+  Record.push_back(VisMD->isPublic());
+}
+  }
 
-// Write out any exported module macros.
-bool 

[clang] 0687578 - [C++20][Modules][HU 2/5] Support searching Header Units in user or system search paths.

2022-03-26 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-03-26T10:17:17Z
New Revision: 0687578728ea1985cbab0de14d4eeb4e89cdf210

URL: 
https://github.com/llvm/llvm-project/commit/0687578728ea1985cbab0de14d4eeb4e89cdf210
DIFF: 
https://github.com/llvm/llvm-project/commit/0687578728ea1985cbab0de14d4eeb4e89cdf210.diff

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

This is support for the user-facing options to create importable header units
from headers in the user or system search paths (or to be given an absolute 
path).

This means that an incomplete header path will be passed by the driver and the
lookup carried out using the search paths present when the front end is run.

To support this, we introduce file fypes for 
c++-{user,system,header-unit}-header.
These terms are the same as the ones used by GCC, to minimise the differences 
for
tooling (and users).

The preprocessor checks for headers before issuing a warning for
"#pragma once" in a header build.  We ensure that the importable header units
are recognised as headers in order to avoid such warnings.

Differential Revision: https://reviews.llvm.org/D121096

Added: 
clang/test/Modules/cxx20-hu-02.cpp
clang/test/Modules/cxx20-hu-03.cpp
clang/test/Modules/cxx20-hu-bad-input.cpp

Modified: 
clang/include/clang/Basic/DiagnosticDriverKinds.td
clang/include/clang/Frontend/FrontendOptions.h
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Frontend/FrontendAction.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td 
b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 59862555cc8f6..63913b933c8fb 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -266,6 +266,8 @@ def err_drv_cc_print_options_failure : Error<
 def err_drv_lto_without_lld : Error<"LTO requires -fuse-ld=lld">;
 def err_drv_preamble_format : Error<
 "incorrect format for -preamble-bytes=N,END">;
+def err_drv_header_unit_extra_inputs : Error<
+"multiple inputs are not valid for header units (first extra '%0')">;
 def warn_invalid_ios_deployment_target : Warning<
   "invalid iOS deployment version '%0', iOS 10 is the maximum deployment "
   "target for 32-bit targets">, InGroup,

diff  --git a/clang/include/clang/Frontend/FrontendOptions.h 
b/clang/include/clang/Frontend/FrontendOptions.h
index 160dc71505e2f..ff5a9c5c77f4d 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -153,6 +153,8 @@ class InputKind {
   Language Lang;
   unsigned Fmt : 3;
   unsigned Preprocessed : 1;
+  unsigned HeaderUnit : 3;
+  unsigned IsHeader : 1;
 
 public:
   /// The input file format.
@@ -162,13 +164,29 @@ class InputKind {
 Precompiled
   };
 
+  // If we are building a header unit, what kind it is; this affects whether
+  // we look for the file in the user or system include search paths before
+  // flagging a missing input.
+  enum HeaderUnitKind {
+HeaderUnit_None,
+HeaderUnit_User,
+HeaderUnit_System,
+HeaderUnit_Abs
+  };
+
   constexpr InputKind(Language L = Language::Unknown, Format F = Source,
-  bool PP = false)
-  : Lang(L), Fmt(F), Preprocessed(PP) {}
+  bool PP = false, HeaderUnitKind HU = HeaderUnit_None,
+  bool HD = false)
+  : Lang(L), Fmt(F), Preprocessed(PP), HeaderUnit(HU), IsHeader(HD) {}
 
   Language getLanguage() const { return static_cast(Lang); }
   Format getFormat() const { return static_cast(Fmt); }
+  HeaderUnitKind getHeaderUnitKind() const {
+return static_cast(HeaderUnit);
+  }
   bool isPreprocessed() const { return Preprocessed; }
+  bool isHeader() const { return IsHeader; }
+  bool isHeaderUnit() const { return HeaderUnit != HeaderUnit_None; }
 
   /// Is the input kind fully-unknown?
   bool isUnknown() const { return Lang == Language::Unknown && Fmt == Source; }
@@ -179,11 +197,23 @@ class InputKind {
   }
 
   InputKind getPreprocessed() const {
-return InputKind(getLanguage(), getFormat(), true);
+return InputKind(getLanguage(), getFormat(), true, getHeaderUnitKind(),
+ isHeader());
+  }
+
+  InputKind getHeader() const {
+return InputKind(getLanguage(), getFormat(), isPreprocessed(),
+ getHeaderUnitKind(), true);
+  }
+
+  InputKind withHeaderUnit(HeaderUnitKind HU) const {
+return InputKind(getLanguage(), getFormat(), isPreprocessed(), HU,
+ isHeader());
   }
 
   InputKind withFormat(Format F) const {
-return InputKind(getLanguage(), F, isPreprocessed());
+return InputKind(getLanguage(), F, isPreprocessed(), getHeaderUnitKind(),
+ isHeader());
   }
 };
 
@@ -218,6 +248,10 @@ class FrontendInputFile {
   bool isFile() const { return !isBuffer(); }
   bool 

[clang] cf396c5 - [C++20][Modules] Correct an assert for modules-ts.

2022-03-25 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-03-25T14:55:13Z
New Revision: cf396c56e7df756d460a456f99ceab1b5d2c2e37

URL: 
https://github.com/llvm/llvm-project/commit/cf396c56e7df756d460a456f99ceab1b5d2c2e37
DIFF: 
https://github.com/llvm/llvm-project/commit/cf396c56e7df756d460a456f99ceab1b5d2c2e37.diff

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

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.

Differential Revision: https://reviews.llvm.org/D122394

Added: 


Modified: 
clang/lib/Sema/SemaModule.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index a115834d334c4..e28de8c79b273 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -206,7 +206,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
   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


[clang] 6c0e60e - [C++20][Modules][HU 1/5] Introduce header units as a module type.

2022-03-25 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-03-25T09:17:14Z
New Revision: 6c0e60e884a20016ccc0d7c7e6f06df089a0de86

URL: 
https://github.com/llvm/llvm-project/commit/6c0e60e884a20016ccc0d7c7e6f06df089a0de86
DIFF: 
https://github.com/llvm/llvm-project/commit/6c0e60e884a20016ccc0d7c7e6f06df089a0de86.diff

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

This is the first in a series of patches that introduce C++20 importable
header units.

These differ from clang header modules in that:
 (a) they are identifiable by an internal name
 (b) they represent the top level source for a single header - although
 that might include or import other headers.

We name importable header units with the path by which they are specified
(although that need not be the absolute path for the file).

So "foo/bar.h" would have a name "foo/bar.h".  Header units are made a
separate module type so that we can deal with diagnosing places where they
are permitted but a named module is not.

Differential Revision: https://reviews.llvm.org/D121095

Added: 
clang/test/Modules/cxx20-hu-01.cpp

Modified: 
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

Removed: 




diff  --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 3745740d3d29c..05b9691142998 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -166,7 +166,7 @@ BENIGN_LANGOPT(HeinousExtensions , 1, 0, "extensions that 
we really don't like a
 LANGOPT(Modules   , 1, 0, "modules semantics")
 COMPATIBLE_LANGOPT(ModulesTS  , 1, 0, "C++ Modules TS syntax")
 COMPATIBLE_LANGOPT(CPlusPlusModules, 1, 0, "C++ modules syntax")
-BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None,
+BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 3, CMK_None,
 "compiling a module interface")
 BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch")
 BENIGN_LANGOPT(BuildingPCHWithObjectFile, 1, 0, "building a pch which has a 
corresponding object file")

diff  --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 6aa24d2facc2a..96fd6049efeca 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -90,6 +90,9 @@ class LangOptions : public LangOptionsBase {
 /// Compiling a module from a list of header files.
 CMK_HeaderModule,
 
+/// Compiling a module header unit.
+CMK_HeaderUnit,
+
 /// Compiling a C++ modules TS module interface unit.
 CMK_ModuleInterface,
   };

diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index 3d1af45c48f3d..9752ff61e4a27 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -109,6 +109,9 @@ class Module {
 /// This is a C++20 module interface unit.
 ModuleInterfaceUnit,
 
+/// This is a C++ 20 header unit.
+ModuleHeaderUnit,
+
 /// This is a C++ 20 module partition interface.
 ModulePartitionInterface,
 

diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 6ed87f9a464d0..784751a1a6863 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5640,6 +5640,8 @@ def emit_module_interface : Flag<["-"], 
"emit-module-interface">,
   HelpText<"Generate pre-compiled module file from a C++ module interface">;
 def emit_header_module : Flag<["-"], "emit-header-module">,
   HelpText<"Generate pre-compiled module file from a set of header files">;
+def emit_header_unit : Flag<["-"], "emit-header-unit">,
+  HelpText<"Generate C++20 header units from header files">;
 def emit_pch : Flag<["-"], "emit-pch">,
   HelpText<"Generate pre-compiled header file">;
 def emit_llvm_bc : Flag<["-"], "emit-llvm-bc">,

diff  --git a/clang/include/clang/Frontend/FrontendActions.h 
b/clang/include/clang/Frontend/FrontendActions.h
index 9b5b757034a6a..ae829d741152a 100644
--- a/clang/include/clang/Frontend/FrontendActions.h
+++ b/clang/include/clang/Frontend/FrontendActions.h
@@ -168,6 +168,15 @@ class GenerateHeaderModuleAction : public 
GenerateModuleAction {
   CreateOutputFile(CompilerInstance , StringRef InFile) override;
 };
 
+class GenerateHeaderUnitAction : public 

[clang] 17ce549 - [C++20][Modules] Improve efficiency of isModulePartition method.

2022-03-02 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-03-02T08:31:46Z
New Revision: 17ce5497aa016707b31a2e99a05ec7451ba4014d

URL: 
https://github.com/llvm/llvm-project/commit/17ce5497aa016707b31a2e99a05ec7451ba4014d
DIFF: 
https://github.com/llvm/llvm-project/commit/17ce5497aa016707b31a2e99a05ec7451ba4014d.diff

LOG: [C++20][Modules] Improve efficiency of isModulePartition method.

The original implementation of this used the presence of a ":" in the module
name as the key, but since we now generate modules with the correct kind, we
can just test that.

Differential Revision: https://reviews.llvm.org/D120764

Added: 


Modified: 
clang/include/clang/Basic/Module.h

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index ac3bb1b3ef109..5b97044524553 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -515,12 +515,14 @@ class Module {
   }
 
   /// Is this a module partition.
-  bool isModulePartition() const { return Name.find(':') != std::string::npos; 
}
+  bool isModulePartition() const {
+return Kind == ModulePartitionInterface ||
+   Kind == ModulePartitionImplementation;
+  }
 
   /// Get the primary module interface name from a partition.
   StringRef getPrimaryModuleInterfaceName() const {
-if (Kind == ModulePartitionInterface ||
-Kind == ModulePartitionImplementation) {
+if (isModulePartition()) {
   auto pos = Name.find(':');
   return StringRef(Name.data(), pos);
 }



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


[clang] a29f8db - [C++20][Modules][8/8] Amend module visibility rules for partitions.

2022-03-01 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-03-01T08:29:05Z
New Revision: a29f8dbb7f3e816344a7be75996eea3ab5a0b5a3

URL: 
https://github.com/llvm/llvm-project/commit/a29f8dbb7f3e816344a7be75996eea3ab5a0b5a3
DIFF: 
https://github.com/llvm/llvm-project/commit/a29f8dbb7f3e816344a7be75996eea3ab5a0b5a3.diff

LOG: [C++20][Modules][8/8] Amend module visibility rules for partitions.

Implementation partitions bring two extra cases where we have
visibility of module-private data.

1) When we import a module implementation partition.
2) When a partition implementation imports the primary module intertace.

We maintain a record of direct imports into the current module since
partition decls from direct imports (but not trasitive ones) are visible.

The rules on decl-reachability are much more relaxed (with the standard
giving permission for an implementation to load dependent modules and for
the decls there to be reachable, but not visible).

Differential Revision: https://reviews.llvm.org/D118599

Added: 


Modified: 
clang/lib/Sema/SemaLookup.cpp
clang/test/Modules/cxx20-10-1-ex2.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 13320497c4b4b..65f5112afee3e 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1687,8 +1687,8 @@ bool LookupResult::isVisibleSlow(Sema , NamedDecl 
*D) {
   Module *DeclModule = SemaRef.getOwningModule(D);
   assert(DeclModule && "hidden decl has no owning module");
 
-  // If the owning module is visible, the decl is visible.
   if (SemaRef.isModuleVisible(DeclModule, D->isModulePrivate()))
+// If the owning module is visible, the decl is visible.
 return true;
 
   // Determine whether a decl context is a file context for the purpose of
@@ -1762,6 +1762,22 @@ bool Sema::isModuleVisible(const Module *M, bool 
ModulePrivate) {
   if (ModulePrivate) {
 if (isInCurrentModule(M, getLangOpts()))
   return true;
+else if (M->Kind == Module::ModuleKind::ModulePartitionImplementation &&
+ isModuleDirectlyImported(M))
+  // Unless a partition implementation is directly imported it is not
+  // counted as visible for lookup, although the contained decls might
+  // still be reachable.  It's a partition, so it must be part of the
+  // current module to be a valid import.
+  return true;
+else if (getLangOpts().CPlusPlusModules && !ModuleScopes.empty() &&
+ ModuleScopes[0].Module->Kind ==
+ Module::ModuleKind::ModulePartitionImplementation &&
+ ModuleScopes[0].Module->getPrimaryModuleInterfaceName() ==
+ M->Name &&
+ isModuleDirectlyImported(M))
+  // We are building a module implementation partition and the TU imports
+  // the primary module interface unit.
+  return true;
   } else {
 if (VisibleModules.isVisible(M))
   return true;

diff  --git a/clang/test/Modules/cxx20-10-1-ex2.cpp 
b/clang/test/Modules/cxx20-10-1-ex2.cpp
index 66323fc9d6460..6b47fb0f41eec 100644
--- a/clang/test/Modules/cxx20-10-1-ex2.cpp
+++ b/clang/test/Modules/cxx20-10-1-ex2.cpp
@@ -12,9 +12,8 @@
 // RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu3.cpp \
 // RUN:   -o %t/B_X1.pcm -verify
 
-// Not expected to work yet.
-//  %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu4.cpp \
-//   -fmodule-file=%t/B.pcm  -o %t/B_X2.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu4.cpp \
+// RUN:-fmodule-file=%t/B.pcm  -o %t/B_X2.pcm
 
 // RUN: %clang_cc1 -std=c++20 -emit-obj %t/std10-1-ex2-tu5.cpp \
 // RUN:  -fmodule-file=%t/B.pcm  -o %t/b_tu5.o
@@ -22,9 +21,8 @@
 // RUN: %clang_cc1 -std=c++20 -S %t/std10-1-ex2-tu6.cpp \
 // RUN:  -fmodule-file=%t/B.pcm  -o %t/b_tu6.s -verify
 
-// Not expected to work yet.
-//  %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu7.cpp \
-//   -fmodule-file=%t/B_X2.pcm  -o %t/B_X3.pcm -verify
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/std10-1-ex2-tu7.cpp \
+// RUN: -fmodule-file=%t/B_X2.pcm  -o %t/B_X3.pcm -verify
 
 //--- std10-1-ex2-tu1.cpp
 module B:Y;



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


[clang] b3fcfcb - [C++20][Modules][7/8] Find the primary interface name for a module.

2022-02-28 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-28T08:50:25Z
New Revision: b3fcfcb9464b90dd56a591e6269d33b124b96fee

URL: 
https://github.com/llvm/llvm-project/commit/b3fcfcb9464b90dd56a591e6269d33b124b96fee
DIFF: 
https://github.com/llvm/llvm-project/commit/b3fcfcb9464b90dd56a591e6269d33b124b96fee.diff

LOG: [C++20][Modules][7/8] Find the primary interface name for a module.

When we are building modules, there are cases where the only way to determine
validity of access is by comparing primary interface names.  This is because we 
need
to be able to associate a primary interface name with an imported partition, but
before the primary interface module is complete - so that textual comparison is
necessary.

If this turns out to be needed many times, we could cache the result, but it 
seems
unlikely to be significant (at this time); cases with very many imported 
partitions
would seem unusual.

Differential Revision: https://reviews.llvm.org/D118598

Added: 


Modified: 
clang/include/clang/Basic/Module.h
clang/lib/Sema/SemaModule.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index b05d3c654e726..ac3bb1b3ef109 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -517,6 +517,16 @@ class Module {
   /// Is this a module partition.
   bool isModulePartition() const { return Name.find(':') != std::string::npos; 
}
 
+  /// Get the primary module interface name from a partition.
+  StringRef getPrimaryModuleInterfaceName() const {
+if (Kind == ModulePartitionInterface ||
+Kind == ModulePartitionImplementation) {
+  auto pos = Name.find(':');
+  return StringRef(Name.data(), pos);
+}
+return Name;
+  }
+
   /// Retrieve the full name of this module, including the path from
   /// its top-level module.
   /// \param AllowStringLiterals If \c true, components that might not be

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index a829693fafebc..6bb886bfe53c6 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -382,17 +382,10 @@ DeclResult Sema::ActOnModuleImport(SourceLocation 
StartLoc,
 // We already checked that we are in a module purview in the parser.
 assert(!ModuleScopes.empty() && "in a module purview, but no module?");
 Module *NamedMod = ModuleScopes.back().Module;
-if (ModuleScopes.back().IsPartition) {
-  // We're importing a partition into a partition, find the name of the
-  // owning named module.
-  size_t P = NamedMod->Name.find_first_of(":");
-  ModuleName = NamedMod->Name.substr(0, P + 1);
-} else {
-  // We're importing a partition into the named module itself (either the
-  // interface or an implementation TU).
-  ModuleName = NamedMod->Name;
-  ModuleName += ":";
-}
+// If we are importing into a partition, find the owning named module,
+// otherwise, the name of the importing named module.
+ModuleName = NamedMod->getPrimaryModuleInterfaceName().str();
+ModuleName += ":";
 ModuleName += stringFromPath(Partition);
 ModuleNameLoc = {PP.getIdentifierInfo(ModuleName), Partition[0].second};
 Partition = ModuleIdPath(ModuleNameLoc);



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


[clang] 853ca54 - [C++20][Modules][6/8] Record direct module imports.

2022-02-27 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-27T10:07:11Z
New Revision: 853ca5472314e109b98e46f0985f27f79e17d2bd

URL: 
https://github.com/llvm/llvm-project/commit/853ca5472314e109b98e46f0985f27f79e17d2bd
DIFF: 
https://github.com/llvm/llvm-project/commit/853ca5472314e109b98e46f0985f27f79e17d2bd.diff

LOG: [C++20][Modules][6/8] Record direct module imports.

This is a small cache to avoid having to check both Exports and
Imports.

Differential Revision: https://reviews.llvm.org/D118589

Added: 


Modified: 
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaModule.cpp

Removed: 




diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0b872c48482db..9937846e05658 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2219,6 +2219,9 @@ class Sema final {
   /// The global module fragment of the current translation unit.
   clang::Module *GlobalModuleFragment = nullptr;
 
+  /// The modules we imported directly.
+  llvm::SmallPtrSet DirectModuleImports;
+
   /// Namespace definitions that we will export when they finish.
   llvm::SmallPtrSet DeferredExportedNamespaces;
 
@@ -2246,6 +2249,10 @@ class Sema final {
 return Entity->getOwningModule();
   }
 
+  bool isModuleDirectlyImported(const Module *M) {
+return DirectModuleImports.contains(M);
+  }
+
   /// Make a merged definition of an existing hidden definition \p ND
   /// visible at the specified location.
   void makeMergedDefinitionVisible(NamedDecl *ND);

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 0606b3a4edae8..a829693fafebc 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -514,6 +514,11 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
 assert(ThisModule && "was expecting a module if building one");
   }
 
+  // In some cases we need to know if an entity was present in a directly-
+  // imported module (as opposed to a transitive import).  This avoids
+  // searching both Imports and Exports.
+  DirectModuleImports.insert(Mod);
+
   return Import;
 }
 



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


[clang] 1a76d25 - [C++20][Modules][5/8] Diagnose wrong import/export for partition CMIs.

2022-02-26 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-26T11:27:08Z
New Revision: 1a76d2563940e6b4bfcb9e77b8a4d1d3f0cc7d30

URL: 
https://github.com/llvm/llvm-project/commit/1a76d2563940e6b4bfcb9e77b8a4d1d3f0cc7d30
DIFF: 
https://github.com/llvm/llvm-project/commit/1a76d2563940e6b4bfcb9e77b8a4d1d3f0cc7d30.diff

LOG: [C++20][Modules][5/8] Diagnose wrong import/export for partition CMIs.

We cannot export partition implementation CMIs, but we can export the content
of partition interface CMIs.

Differential Revision: https://reviews.llvm.org/D118588

Added: 
clang/test/Modules/cxx20-10-3-ex1.cpp
clang/test/Modules/cxx20-10-3-ex2.cpp

Modified: 
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaModule.cpp
clang/test/Modules/cxx20-import-diagnostics-a.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 15487260eb732..2528777678571 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10991,6 +10991,8 @@ def ext_module_import_not_at_top_level_noop : ExtWarn<
 def note_module_import_not_at_top_level : Note<"%0 begins here">;
 def err_module_self_import : Error<
   "import of module '%0' appears within same top-level module '%1'">;
+def err_module_self_import_cxx20 : Error<
+  "import of module '%0' appears within its own 
%select{interface|implementation}1">;
 def err_module_import_in_implementation : Error<
   "@import of module '%0' in implementation of '%1'; use #import">;
 
@@ -11024,6 +11026,8 @@ def err_export_using_internal : Error<
 def err_export_not_in_module_interface : Error<
   "export declaration can only be used within a module interface unit"
   "%select{ after the module declaration|}0">;
+def err_export_partition_impl : Error<
+  "module partition implementations cannot be exported">;
 def err_export_in_private_module_fragment : Error<
   "export declaration cannot be used in a private module fragment">;
 def note_private_module_fragment : Note<

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index b2515075a7f23..0606b3a4edae8 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -403,10 +403,16 @@ DeclResult Sema::ActOnModuleImport(SourceLocation 
StartLoc,
   }
 
   // Diagnose self-import before attempting a load.
+  // [module.import]/9
+  // A module implementation unit of a module M that is not a module partition
+  // shall not contain a module-import-declaration nominating M.
+  // (for an implementation, the module interface is imported implicitly,
+  //  but that's handled in the module decl code).
+
   if (getLangOpts().CPlusPlusModules && isCurrentModulePurview() &&
   getCurrentModule()->Name == ModuleName) {
-Diag(ImportLoc, diag::err_module_self_import)
-<< ModuleName << getLangOpts().CurrentModule;
+Diag(ImportLoc, diag::err_module_self_import_cxx20)
+<< ModuleName << !ModuleScopes.back().ModuleInterface;
 return true;
   }
 
@@ -440,8 +446,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
   // of the same top-level module. Until we do, make it an error rather than
   // silently ignoring the import.
   // FIXME: Should we warn on a redundant import of the current module?
-  if (!getLangOpts().CPlusPlusModules &&
-  Mod->getTopLevelModuleName() == getLangOpts().CurrentModule &&
+  if (Mod->getTopLevelModuleName() == getLangOpts().CurrentModule &&
   (getLangOpts().isCompilingModule() || !getLangOpts().ModulesTS)) {
 Diag(ImportLoc, getLangOpts().isCompilingModule()
 ? diag::err_module_self_import
@@ -482,7 +487,12 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
   if (!ModuleScopes.empty())
 Context.addModuleInitializer(ModuleScopes.back().Module, Import);
 
-  if (!ModuleScopes.empty() && ModuleScopes.back().ModuleInterface) {
+  // A module (partition) implementation unit shall not be exported.
+  if (getLangOpts().CPlusPlusModules && Mod && ExportLoc.isValid() &&
+  Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) {
+Diag(ExportLoc, diag::err_export_partition_impl)
+<< SourceRange(ExportLoc, Path.back().second);
+  } else if (!ModuleScopes.empty() && ModuleScopes.back().ModuleInterface) {
 // Re-export the module if the imported module is exported.
 // Note that we don't need to add re-exported module to Imports field
 // since `Exports` implies the module is imported already.
@@ -494,7 +504,9 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
 // [module.interface]p1:
 // An export-declaration shall inhabit a namespace scope and appear in the
 // purview of a module interface unit.
-Diag(ExportLoc, diag::err_export_not_in_module_interface) << 0;
+Diag(ExportLoc, 

[clang] 6114491 - [C++20][Modules][4/8] Handle generation of partition implementation CMIs.

2022-02-25 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-25T09:33:14Z
New Revision: 6114491441700cc8a614d284407e9a6e9bf74751

URL: 
https://github.com/llvm/llvm-project/commit/6114491441700cc8a614d284407e9a6e9bf74751
DIFF: 
https://github.com/llvm/llvm-project/commit/6114491441700cc8a614d284407e9a6e9bf74751.diff

LOG: [C++20][Modules][4/8] Handle generation of partition implementation CMIs.

Partition implementations are special, they generate a CMI, but it
does not have an 'export' line, and we cannot export anything from the
it [that is it can only make decls available to other members of the
owning module, not to importers of that].

Add initial testcases for partition handling, derived from the examples in
Section 10 of the C++20 standard, which identifies what should be accepted
and/or rejected.

Differential Revision: https://reviews.llvm.org/D118587

Added: 
clang/test/Modules/cxx20-10-1-ex1.cpp
clang/test/Modules/cxx20-10-1-ex2.cpp

Modified: 
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaModule.cpp
clang/test/Modules/cxx20-import-diagnostics-a.cpp

Removed: 




diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 436718a54640e..0b872c48482db 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2943,8 +2943,10 @@ class Sema final {
   SourceLocation SemiLoc);
 
   enum class ModuleDeclKind {
-Interface,  ///< 'export module X;'
-Implementation, ///< 'module X;'
+Interface,   ///< 'export module X;'
+Implementation,  ///< 'module X;'
+PartitionInterface,  ///< 'export module X:Y;'
+PartitionImplementation, ///< 'module X:Y;'
   };
 
   /// An enumeration to represent the transition of states in parsing module

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index a797644754b59..b2515075a7f23 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -110,9 +110,24 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
   // module state;
   ImportState = ModuleImportState::NotACXX20Module;
 
-  // A module implementation unit requires that we are not compiling a module
-  // of any kind. A module interface unit requires that we are not compiling a
-  // module map.
+  bool IsPartition = !Partition.empty();
+  if (IsPartition)
+switch (MDK) {
+case ModuleDeclKind::Implementation:
+  MDK = ModuleDeclKind::PartitionImplementation;
+  break;
+case ModuleDeclKind::Interface:
+  MDK = ModuleDeclKind::PartitionInterface;
+  break;
+default:
+  llvm_unreachable("how did we get a partition type set?");
+}
+
+  // A (non-partition) module implementation unit requires that we are not
+  // compiling a module of any kind.  A partition implementation emits an
+  // interface (and the AST for the implementation), which will subsequently
+  // be consumed to emit a binary.
+  // A module interface unit requires that we are not compiling a module map.
   switch (getLangOpts().getCompilingModule()) {
   case LangOptions::CMK_None:
 // It's OK to compile a module interface as a normal translation unit.
@@ -123,7 +138,7 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
   break;
 
 // We were asked to compile a module interface unit but this is a module
-// implementation unit. That indicates the 'export' is missing.
+// implementation unit.
 Diag(ModuleLoc, diag::err_module_interface_implementation_mismatch)
   << FixItHint::CreateInsertion(ModuleLoc, "export ");
 MDK = ModuleDeclKind::Interface;
@@ -180,7 +195,6 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
   // modules, the dots here are just another character that can appear in a
   // module name.
   std::string ModuleName = stringFromPath(Path);
-  bool IsPartition = !Partition.empty();
   if (IsPartition) {
 ModuleName += ":";
 ModuleName += stringFromPath(Partition);
@@ -202,7 +216,8 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
   Module *Mod;
 
   switch (MDK) {
-  case ModuleDeclKind::Interface: {
+  case ModuleDeclKind::Interface:
+  case ModuleDeclKind::PartitionInterface: {
 // We can't have parsed or imported a definition of this module or parsed a
 // module map defining it already.
 if (auto *M = Map.findModule(ModuleName)) {
@@ -219,36 +234,36 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
 // Create a Module for the module that we're defining.
 Mod = Map.createModuleForInterfaceUnit(ModuleLoc, ModuleName,
GlobalModuleFragment);
-if (IsPartition)
+if (MDK == ModuleDeclKind::PartitionInterface)
   Mod->Kind = Module::ModulePartitionInterface;
 assert(Mod && "module creation 

[clang] 69350e5 - [C++20][Modules][3/8] Initial handling for module partitions.

2022-02-24 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-24T09:01:09Z
New Revision: 69350e569dc47f871590243b5e46a68520640dcd

URL: 
https://github.com/llvm/llvm-project/commit/69350e569dc47f871590243b5e46a68520640dcd
DIFF: 
https://github.com/llvm/llvm-project/commit/69350e569dc47f871590243b5e46a68520640dcd.diff

LOG: [C++20][Modules][3/8] Initial handling for module partitions.

This implements the parsing and recognition of module partition CMIs
and removes the FIXMEs in the parser.

Module partitions are recognised in the base computation of visibility,
however additional amendments to visibility follow in subsequent patches.

Differential Revision: https://reviews.llvm.org/D118586

Added: 
clang/test/Modules/cxx20-multiple-partitions.cpp
clang/test/Modules/cxx20-partition-diagnostics-a.cpp

Modified: 
clang/include/clang/AST/Decl.h
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Parse/Parser.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaLookup.cpp
clang/lib/Sema/SemaModule.cpp
clang/test/CXX/module/module.unit/p3.cpp
clang/test/CXX/module/module.unit/p8.cpp

Removed: 




diff  --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 7611bac83419d..926426b5470d2 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -4467,6 +4467,16 @@ class CapturedDecl final
 ///   @import std.vector;
 /// \endcode
 ///
+/// A C++20 module import declaration imports the named module or partition.
+/// Periods are permitted in C++20 module names, but have no semantic meaning.
+/// For example:
+/// \code
+///   import NamedModule;
+///   import :SomePartition; // Must be a partition of the current module.
+///   import Names.Like.this; // Allowed.
+///   import :and.Also.Partition.names;
+/// \endcode
+///
 /// Import declarations can also be implicitly generated from
 /// \#include/\#import directives.
 class ImportDecl final : public Decl,

diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index f7d9a685e8b92..92ae27d6212a0 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1541,9 +1541,11 @@ def err_private_module_fragment_expected_semi : Error<
   "expected ';' after private module fragment declaration">;
 def err_missing_before_module_end : Error<"expected %0 at end of module">;
 def err_unsupported_module_partition : Error<
-  "sorry, module partitions are not yet supported">;
+  "module partitions are only supported for C++20 onwards">;
 def err_import_not_allowed_here : Error<
   "imports must immediately follow the module declaration">;
+def err_partition_import_outside_module : Error<
+  "module partition imports must be within a module purview">;
 def err_import_in_wrong_fragment : Error<
   "module%select{| partition}0 imports cannot be in the 
%select{global|private}1 module fragment">;
 

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 94283e2412a98..436718a54640e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2210,6 +2210,7 @@ class Sema final {
 SourceLocation BeginLoc;
 clang::Module *Module = nullptr;
 bool ModuleInterface = false;
+bool IsPartition = false;
 bool ImplicitGlobalModuleFragment = false;
 VisibleModuleSet OuterVisibleModules;
   };
@@ -2962,7 +2963,7 @@ class Sema final {
   /// of a module interface or implementation.
   DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc,
  SourceLocation ModuleLoc, ModuleDeclKind MDK,
- ModuleIdPath Path,
+ ModuleIdPath Path, ModuleIdPath Partition,
  ModuleImportState );
 
   /// The parser has processed a global-module-fragment declaration that begins
@@ -2983,10 +2984,12 @@ class Sema final {
   ///could be the location of an '@', 'export', or 'import'.
   /// \param ExportLoc The location of the 'export' keyword, if any.
   /// \param ImportLoc The location of the 'import' keyword.
-  /// \param Path The module access path.
+  /// \param Path The module toplevel name as an access path.
+  /// \param Partition The module partition name as an access path.
   DeclResult ActOnModuleImport(SourceLocation StartLoc,
SourceLocation ExportLoc,
-   SourceLocation ImportLoc, ModuleIdPath Path);
+   SourceLocation ImportLoc, ModuleIdPath Path,
+   ModuleIdPath Partition = {});
   DeclResult ActOnModuleImport(SourceLocation StartLoc,
SourceLocation ExportLoc,
SourceLocation ImportLoc, Module *M,

diff  --git 

[clang] e0f1dd0 - [C++20][Modules] Rework testcase to use split file [NFC].

2022-02-23 Thread Iain Sandoe via cfe-commits

Author: iains
Date: 2022-02-23T11:07:36Z
New Revision: e0f1dd018e0f94a7d694bc615975c3a7d26d9e50

URL: 
https://github.com/llvm/llvm-project/commit/e0f1dd018e0f94a7d694bc615975c3a7d26d9e50
DIFF: 
https://github.com/llvm/llvm-project/commit/e0f1dd018e0f94a7d694bc615975c3a7d26d9e50.diff

LOG: [C++20][Modules] Rework testcase to use split file [NFC].

This switches the testcase committed for initial C++20 modules import tracking 
to
use split-file rather than preprocessor directives.

Differential Revision: https://reviews.llvm.org/D120352

Added: 


Modified: 
clang/test/Modules/cxx20-import-diagnostics-a.cpp

Removed: 




diff  --git a/clang/test/Modules/cxx20-import-diagnostics-a.cpp 
b/clang/test/Modules/cxx20-import-diagnostics-a.cpp
index fd4085bcb4713..8e2940a432e6d 100644
--- a/clang/test/Modules/cxx20-import-diagnostics-a.cpp
+++ b/clang/test/Modules/cxx20-import-diagnostics-a.cpp
@@ -1,42 +1,43 @@
 // RUN: rm -rf %t
 // RUN: mkdir -p %t
+// RUN: split-file %s %t
 
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -D TU=0 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/import-diags-tu1.cpp \
 // RUN:  -o %t/B.pcm
 
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -D TU=1 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/import-diags-tu2.cpp \
 // RUN:  -o %t/C.pcm
 
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -D TU=2 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/import-diags-tu3.cpp \
 // RUN:  -fmodule-file=%t/B.pcm -fmodule-file=%t/C.pcm -o %t/AOK1.pcm
 
-// RUN: %clang_cc1 -std=c++20 -S -D TU=3 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu4.cpp \
 // RUN:  -fmodule-file=%t/AOK1.pcm -o %t/tu_3.s -verify
 
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -D TU=4 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/import-diags-tu5.cpp \
 // RUN:  -fmodule-file=%t/B.pcm -fmodule-file=%t/C.pcm -o %t/BC.pcm -verify
 
-// RUN: %clang_cc1 -std=c++20 -S -D TU=5 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu6.cpp \
 // RUN:  -fmodule-file=%t/B.pcm -fmodule-file=%t/C.pcm -o %t/tu_5.s -verify
 
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -D TU=6 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/import-diags-tu7.cpp \
 // RUN:  -fmodule-file=%t/B.pcm -o %t/D.pcm -verify
 
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -D TU=7 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/import-diags-tu8.cpp \
 // RUN:  -fmodule-file=%t/B.pcm -o %t/D.pcm -verify
 
-// RUN: %clang_cc1 -std=c++20 -S -D TU=8 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -S %t/import-diags-tu9.cpp \
 // RUN:  -fmodule-file=%t/B.pcm -o %t/tu_8.s -verify
 
-// RUN: %clang_cc1 -std=c++20 -emit-module-interface -D TU=9 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/import-diags-tu10.cpp \
 // RUN:  -o %t/B.pcm -verify
 
-// RUN: %clang_cc1 -std=c++20 -emit-obj -D TU=10 -x c++ %s \
+// RUN: %clang_cc1 -std=c++20 -emit-obj %t/import-diags-tu11.cpp \
 // RUN:  -fmodule-file=%t/C.pcm  -o %t/impl.o
 
 // Test diagnostics for incorrect module import sequences.
 
-#if TU == 0
+//--- import-diags-tu1.cpp
 
 export module B;
 
@@ -44,7 +45,7 @@ int foo ();
 
 // expected-no-diagnostics
 
-#elif TU == 1
+//--- import-diags-tu2.cpp
 
 export module C;
 
@@ -52,7 +53,7 @@ int bar ();
 
 // expected-no-diagnostics
 
-#elif TU == 2
+//--- import-diags-tu3.cpp
 
 export module AOK1;
 
@@ -63,7 +64,7 @@ export int theAnswer ();
 
 // expected-no-diagnostics
 
-#elif TU == 3
+//--- import-diags-tu4.cpp
 
 module;
 
@@ -73,7 +74,7 @@ export import C; // expected-error {{export declaration can 
only be used within
 
 int theAnswer () { return 42; }
 
-#elif TU == 4
+//--- import-diags-tu5.cpp
 
 export module BC;
 
@@ -83,7 +84,7 @@ int foo () { return 10; }
 
 import C; // expected-error {{imports must immediately follow the module 
declaration}}
 
-#elif TU == 5
+//--- import-diags-tu6.cpp
 
 module B; // implicitly imports B.
 
@@ -91,7 +92,7 @@ int foo () { return 10; }
 
 import C; // expected-error {{imports must immediately follow the module 
declaration}}
 
-#elif TU == 6
+//--- import-diags-tu7.cpp
 
 module;
 // We can only have preprocessor commands here, which could include an include
@@ -103,7 +104,7 @@ export module D;
 
 int delta ();
 
-#elif TU == 7
+//--- import-diags-tu8.cpp
 
 export module D;
 
@@ -113,19 +114,19 @@ module :private;
 
 import B; // expected-error {{module imports cannot be in the private module 
fragment}}
 
-#elif TU == 8
+//--- import-diags-tu9.cpp
 
 module B;
 
 import B; // expected-error {{import of module 'B' appears within same 
top-level module 'B'}}
 
-#elif TU == 9
+//--- import-diags-tu10.cpp
 
 export module B;
 
 import B; // expected-error {{import of module 'B' appears within same 
top-level module 'B'}}
 

[clang] 5a74e6a - [Modules] Add module structure output to -module-file-info.

2022-02-23 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-23T10:26:42Z
New Revision: 5a74e6a21c9520e0619c98a66815fc8b5117e321

URL: 
https://github.com/llvm/llvm-project/commit/5a74e6a21c9520e0619c98a66815fc8b5117e321
DIFF: 
https://github.com/llvm/llvm-project/commit/5a74e6a21c9520e0619c98a66815fc8b5117e321.diff

LOG: [Modules] Add module structure output to -module-file-info.

It is useful to be able to visualise the C++20 modules content of a PCM file
both for inspection and for testing.  In particular, when adding more module
types to support C++20 Partitions and Header Units, we would like to be able
to confirm that the output PCM has the intended structure.

The existing scheme for dumping data is restricted to the content of the AST
file control block, which does not include structural data beyond imports.

The change here makes use of the AST unit that is set up by BeginSourceFile
to query for the information on the primary and sub-modules.  We can then
inspect each of these in turn, accounting for Global, Private, Imported and
Exported modules/fragments and then showing the sub-stucture of the main
module(s).

The disadvantage of this mechanism is that it has no easy method to control
the granularity of the output.  Perhaps more detailed inspection would be
better handled by a stand-alone module inspection tool.

Differential Revision: https://reviews.llvm.org/D119823

Added: 
clang/test/Modules/cxx20-module-file-info.cpp

Modified: 
clang/lib/Frontend/FrontendActions.cpp

Removed: 




diff  --git a/clang/lib/Frontend/FrontendActions.cpp 
b/clang/lib/Frontend/FrontendActions.cpp
index ad2e6039477f8..baf3ac34db620 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -11,6 +11,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/LangStandard.h"
+#include "clang/Basic/Module.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Frontend/ASTConsumers.h"
 #include "clang/Frontend/CompilerInstance.h"
@@ -24,6 +25,7 @@
 #include "clang/Sema/TemplateInstCallback.h"
 #include "clang/Serialization/ASTReader.h"
 #include "clang/Serialization/ASTWriter.h"
+#include "clang/Serialization/ModuleFile.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -806,7 +808,25 @@ bool 
DumpModuleInfoAction::BeginInvocation(CompilerInstance ) {
   return true;
 }
 
+static StringRef ModuleKindName(Module::ModuleKind MK) {
+  switch (MK) {
+  case Module::ModuleMapModule:
+return "Module Map Module";
+  case Module::ModuleInterfaceUnit:
+return "Interface Unit";
+  case Module::ModulePartitionInterface:
+return "Partition Interface";
+  case Module::ModulePartitionImplementation:
+return "Partition Implementation";
+  case Module::GlobalModuleFragment:
+return "Global Module Fragment";
+  case Module::PrivateModuleFragment:
+return "Private Module Fragment";
+  }
+}
+
 void DumpModuleInfoAction::ExecuteAction() {
+  assert(isCurrentFileAST() && "dumping non-AST?");
   // Set up the output file.
   std::unique_ptr OutFile;
   StringRef OutputFileName = 
getCompilerInstance().getFrontendOpts().OutputFile;
@@ -827,8 +847,87 @@ void DumpModuleInfoAction::ExecuteAction() {
 
   Preprocessor  = getCompilerInstance().getPreprocessor();
   DumpModuleInfoListener Listener(Out);
-  HeaderSearchOptions  =
-  PP.getHeaderSearchInfo().getHeaderSearchOpts();
+  HeaderSearchOptions  = PP.getHeaderSearchInfo().getHeaderSearchOpts();
+
+  // The FrontendAction::BeginSourceFile () method loads the AST so that much
+  // of the information is already available and modules should have been
+  // loaded.
+
+  const LangOptions  = getCurrentASTUnit().getLangOpts();
+  if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) {
+
+ASTReader *R = getCurrentASTUnit().getASTReader().get();
+unsigned SubModuleCount = R->getTotalNumSubmodules();
+serialization::ModuleFile  = R->getModuleManager().getPrimaryModule();
+Out << "  == C++20 Module structure ==\n";
+
+if (MF.ModuleName != LO.CurrentModule)
+  Out << "  Mismatched module names : " << MF.ModuleName << " and "
+  << LO.CurrentModule << "\n";
+
+struct SubModInfo {
+  unsigned Idx;
+  Module *Mod;
+  Module::ModuleKind Kind;
+  std::string 
+  bool Seen;
+};
+std::map SubModMap;
+auto PrintSubMapEntry = [&](std::string Name, Module::ModuleKind Kind) {
+  Out << "" << ModuleKindName(Kind) << " '" << Name << "'";
+  auto I = SubModMap.find(Name);
+  if (I == SubModMap.end())
+Out << " was not found in the sub modules!\n";
+  else {
+I->second.Seen = true;
+Out << " is at index #" << I->second.Idx << "\n";
+  }
+};
+Module *Primary = nullptr;
+for (unsigned Idx = 0; Idx <= SubModuleCount; ++Idx) {
+  Module 

[clang] c9cc803 - [C++20][Modules][2/8] Add enumerations for partition modules and stream them.

2022-02-22 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-22T10:08:15Z
New Revision: c9cc8035eb4fbf5d20a73ec7e0870e6195012a71

URL: 
https://github.com/llvm/llvm-project/commit/c9cc8035eb4fbf5d20a73ec7e0870e6195012a71
DIFF: 
https://github.com/llvm/llvm-project/commit/c9cc8035eb4fbf5d20a73ec7e0870e6195012a71.diff

LOG: [C++20][Modules][2/8] Add enumerations for partition modules and stream 
them.

This is an initial enabling patch for module partition support.
We add enumerations for partition interfaces/implementations.

This means that the module kind enumeration now occupies three
bits, so the AST streamer is adjusted for this.  Adding one bit there
seems preferable to trying to overload the meanings of existing
kinds (and we will also want to add a C++20 header unit case later).

Differential Revision: https://reviews.llvm.org/D114714

Added: 


Modified: 
clang/include/clang/Basic/Module.h
clang/lib/AST/Decl.cpp
clang/lib/Sema/SemaModule.cpp
clang/lib/Serialization/ASTWriter.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index de7857347bc2..b05d3c654e72 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -106,9 +106,15 @@ class Module {
 /// of header files.
 ModuleMapModule,
 
-/// This is a C++ Modules TS module interface unit.
+/// This is a C++20 module interface unit.
 ModuleInterfaceUnit,
 
+/// This is a C++ 20 module partition interface.
+ModulePartitionInterface,
+
+/// This is a C++ 20 module partition implementation.
+ModulePartitionImplementation,
+
 /// This is a fragment of the global module within some C++ module.
 GlobalModuleFragment,
 
@@ -150,7 +156,9 @@ class Module {
 
   /// Does this Module scope describe part of the purview of a named C++ 
module?
   bool isModulePurview() const {
-return Kind == ModuleInterfaceUnit || Kind == PrivateModuleFragment;
+return Kind == ModuleInterfaceUnit || Kind == ModulePartitionInterface ||
+   Kind == ModulePartitionImplementation ||
+   Kind == PrivateModuleFragment;
   }
 
   /// Does this Module scope describe a fragment of the global module within
@@ -506,6 +514,9 @@ class Module {
 Parent->SubModules.push_back(this);
   }
 
+  /// Is this a module partition.
+  bool isModulePartition() const { return Name.find(':') != std::string::npos; 
}
+
   /// Retrieve the full name of this module, including the path from
   /// its top-level module.
   /// \param AllowStringLiterals If \c true, components that might not be

diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 030da7f55fac..82c4412296db 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1550,6 +1550,8 @@ Module *Decl::getOwningModuleForLinkage(bool 
IgnoreLinkage) const {
 return nullptr;
 
   case Module::ModuleInterfaceUnit:
+  case Module::ModulePartitionInterface:
+  case Module::ModulePartitionImplementation:
 return M;
 
   case Module::GlobalModuleFragment: {

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 9bed3cb769f7..bd5b900e5d38 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -261,6 +261,8 @@ Sema::ActOnPrivateModuleFragmentDecl(SourceLocation 
ModuleLoc,
: ModuleScopes.back().Module->Kind) {
   case Module::ModuleMapModule:
   case Module::GlobalModuleFragment:
+  case Module::ModulePartitionImplementation:
+  case Module::ModulePartitionInterface:
 Diag(PrivateLoc, diag::err_private_module_fragment_not_module);
 return nullptr;
 

diff  --git a/clang/lib/Serialization/ASTWriter.cpp 
b/clang/lib/Serialization/ASTWriter.cpp
index a126e12bcbd9..cf42e529a8d6 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -2674,7 +2674,7 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
   Abbrev->Add(BitCodeAbbrevOp(SUBMODULE_DEFINITION));
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ID
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Parent
-  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Kind
+  Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Kind
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFramework
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsExplicit
   Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsSystem



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


[clang] ab28488 - [C++20][Modules][1/8] Track valid import state.

2022-02-21 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-21T09:09:37Z
New Revision: ab28488efe6de6f8fa856a1dfd8c0320d41d7608

URL: 
https://github.com/llvm/llvm-project/commit/ab28488efe6de6f8fa856a1dfd8c0320d41d7608
DIFF: 
https://github.com/llvm/llvm-project/commit/ab28488efe6de6f8fa856a1dfd8c0320d41d7608.diff

LOG: [C++20][Modules][1/8] Track valid import state.

In C++20 modules imports must be together and at the start of the module.
Rather than growing more ad-hoc flags to test state, this keeps track of the
phase of of a valid module TU (first decl, global module frag, module,
private module frag).  If the phasing is broken (with some diagnostic) the
pattern does not conform to a valid C++20 module, and we set the state
accordingly.

We can thus issue diagnostics when imports appear in the wrong places and
decouple the C++20 modules state from other module variants (modules-ts and
clang modules).  Additionally, we attempt to diagnose wrong imports before
trying to find the module where possible (the latter will generally emit an
unhelpful diagnostic about the module not being available).

Although this generally simplifies the handling of C++20 module import
diagnostics, the motivation was that, in particular, it allows detecting
invalid imports like:

import module A;

int some_decl();

import module B;

where being in a module purview is insufficient to identify them.

Differential Revision: https://reviews.llvm.org/D118893

Added: 
clang/test/Modules/cxx20-import-diagnostics-a.cpp

Modified: 
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/lib/Interpreter/IncrementalParser.cpp
clang/lib/Parse/ParseAST.cpp
clang/lib/Parse/ParseObjc.cpp
clang/lib/Parse/Parser.cpp
clang/lib/Sema/SemaModule.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index e23810f402365..f21e841bcdd38 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1539,6 +1539,10 @@ def err_private_module_fragment_expected_semi : Error<
 def err_missing_before_module_end : Error<"expected %0 at end of module">;
 def err_unsupported_module_partition : Error<
   "sorry, module partitions are not yet supported">;
+def err_import_not_allowed_here : Error<
+  "imports must immediately follow the module declaration">;
+def err_import_in_wrong_fragment : Error<
+  "module%select{| partition}0 imports cannot be in the 
%select{global|private}1 module fragment">;
 
 def err_export_empty : Error<"export declaration cannot be empty">;
 }

diff  --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 981800a7e2356..08d492a7ec721 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -464,14 +464,17 @@ class Parser : public CodeCompletionHandler {
   void Initialize();
 
   /// Parse the first top-level declaration in a translation unit.
-  bool ParseFirstTopLevelDecl(DeclGroupPtrTy );
+  bool ParseFirstTopLevelDecl(DeclGroupPtrTy ,
+  Sema::ModuleImportState );
 
   /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
   /// the EOF was encountered.
-  bool ParseTopLevelDecl(DeclGroupPtrTy , bool IsFirstDecl = false);
+  bool ParseTopLevelDecl(DeclGroupPtrTy ,
+ Sema::ModuleImportState );
   bool ParseTopLevelDecl() {
 DeclGroupPtrTy Result;
-return ParseTopLevelDecl(Result);
+Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module;
+return ParseTopLevelDecl(Result, IS);
   }
 
   /// ConsumeToken - Consume the current 'peek token' and lex the next one.
@@ -3491,8 +3494,9 @@ class Parser : public CodeCompletionHandler {
 
   
//======//
   // Modules
-  DeclGroupPtrTy ParseModuleDecl(bool IsFirstDecl);
-  Decl *ParseModuleImport(SourceLocation AtLoc);
+  DeclGroupPtrTy ParseModuleDecl(Sema::ModuleImportState );
+  Decl *ParseModuleImport(SourceLocation AtLoc,
+  Sema::ModuleImportState );
   bool parseMisplacedModuleImport();
   bool tryParseMisplacedModuleImport() {
 tok::TokenKind Kind = Tok.getKind();

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c1e846c55dee7..dfa12ad40b72a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2949,11 +2949,24 @@ class Sema final {
 Implementation, ///< 'module X;'
   };
 
+  /// An enumeration to represent the transition of states in parsing module
+  /// fragments and imports.  If we are not parsing a C++20 TU, or we find
+  /// an error in state transition, the state is set to 

[clang] 6738792 - Revert "[C++20][Modules][1/8] Track valid import state."

2022-02-20 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-20T10:22:07Z
New Revision: 673879249d4d1c4e6d763a6db4a4812d721b41b6

URL: 
https://github.com/llvm/llvm-project/commit/673879249d4d1c4e6d763a6db4a4812d721b41b6
DIFF: 
https://github.com/llvm/llvm-project/commit/673879249d4d1c4e6d763a6db4a4812d721b41b6.diff

LOG: Revert "[C++20][Modules][1/8] Track valid import state."

This reverts commit 8a3f9a584ad43369cf6a034dc875ebfca76d9033.

need to investigate build failures that do not show on CI or local
testing.

Added: 


Modified: 
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/lib/Interpreter/IncrementalParser.cpp
clang/lib/Parse/ParseAST.cpp
clang/lib/Parse/ParseObjc.cpp
clang/lib/Parse/Parser.cpp
clang/lib/Sema/SemaModule.cpp

Removed: 
clang/test/Modules/cxx20-import-diagnostics-a.cpp



diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index f21e841bcdd38..e23810f402365 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1539,10 +1539,6 @@ def err_private_module_fragment_expected_semi : Error<
 def err_missing_before_module_end : Error<"expected %0 at end of module">;
 def err_unsupported_module_partition : Error<
   "sorry, module partitions are not yet supported">;
-def err_import_not_allowed_here : Error<
-  "imports must immediately follow the module declaration">;
-def err_import_in_wrong_fragment : Error<
-  "module%select{| partition}0 imports cannot be in the 
%select{global|private}1 module fragment">;
 
 def err_export_empty : Error<"export declaration cannot be empty">;
 }

diff  --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 08d492a7ec721..981800a7e2356 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -464,17 +464,14 @@ class Parser : public CodeCompletionHandler {
   void Initialize();
 
   /// Parse the first top-level declaration in a translation unit.
-  bool ParseFirstTopLevelDecl(DeclGroupPtrTy ,
-  Sema::ModuleImportState );
+  bool ParseFirstTopLevelDecl(DeclGroupPtrTy );
 
   /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
   /// the EOF was encountered.
-  bool ParseTopLevelDecl(DeclGroupPtrTy ,
- Sema::ModuleImportState );
+  bool ParseTopLevelDecl(DeclGroupPtrTy , bool IsFirstDecl = false);
   bool ParseTopLevelDecl() {
 DeclGroupPtrTy Result;
-Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module;
-return ParseTopLevelDecl(Result, IS);
+return ParseTopLevelDecl(Result);
   }
 
   /// ConsumeToken - Consume the current 'peek token' and lex the next one.
@@ -3494,9 +3491,8 @@ class Parser : public CodeCompletionHandler {
 
   
//======//
   // Modules
-  DeclGroupPtrTy ParseModuleDecl(Sema::ModuleImportState );
-  Decl *ParseModuleImport(SourceLocation AtLoc,
-  Sema::ModuleImportState );
+  DeclGroupPtrTy ParseModuleDecl(bool IsFirstDecl);
+  Decl *ParseModuleImport(SourceLocation AtLoc);
   bool parseMisplacedModuleImport();
   bool tryParseMisplacedModuleImport() {
 tok::TokenKind Kind = Tok.getKind();

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index dfa12ad40b72a..c1e846c55dee7 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2949,24 +2949,11 @@ class Sema final {
 Implementation, ///< 'module X;'
   };
 
-  /// An enumeration to represent the transition of states in parsing module
-  /// fragments and imports.  If we are not parsing a C++20 TU, or we find
-  /// an error in state transition, the state is set to NotACXX20Module.
-  enum class ModuleImportState {
-FirstDecl,   ///< Parsing the first decl in a TU.
-GlobalFragment,  ///< after 'module;' but before 'module X;'
-ImportAllowed,   ///< after 'module X;' but before any non-import decl.
-ImportFinished,  ///< after any non-import decl.
-PrivateFragment, ///< after 'module :private;'.
-NotACXX20Module  ///< Not a C++20 TU, or an invalid state was found.
-  };
-
   /// The parser has processed a module-declaration that begins the definition
   /// of a module interface or implementation.
   DeclGroupPtrTy ActOnModuleDecl(SourceLocation StartLoc,
  SourceLocation ModuleLoc, ModuleDeclKind MDK,
- ModuleIdPath Path,
- ModuleImportState );
+ ModuleIdPath Path, bool IsFirstDecl);
 
   /// The parser has processed a global-module-fragment declaration that begins
   /// the definition of the global 

[clang] 8a3f9a5 - [C++20][Modules][1/8] Track valid import state.

2022-02-20 Thread Iain Sandoe via cfe-commits

Author: Iain Sandoe
Date: 2022-02-20T10:13:57Z
New Revision: 8a3f9a584ad43369cf6a034dc875ebfca76d9033

URL: 
https://github.com/llvm/llvm-project/commit/8a3f9a584ad43369cf6a034dc875ebfca76d9033
DIFF: 
https://github.com/llvm/llvm-project/commit/8a3f9a584ad43369cf6a034dc875ebfca76d9033.diff

LOG: [C++20][Modules][1/8] Track valid import state.

In C++20 modules imports must be together and at the start of the module.
Rather than growing more ad-hoc flags to test state, this keeps track of the
phase of of a valid module TU (first decl, global module frag, module,
private module frag).  If the phasing is broken (with some diagnostic) the
pattern does not conform to a valid C++20 module, and we set the state
accordingly.

We can thus issue diagnostics when imports appear in the wrong places and
decouple the C++20 modules state from other module variants (modules-ts and
clang modules).  Additionally, we attempt to diagnose wrong imports before
trying to find the module where possible (the latter will generally emit an
unhelpful diagnostic about the module not being available).

Although this generally simplifies the handling of C++20 module import
diagnostics, the motivation was that, in particular, it allows detecting
invalid imports like:

import module A;

int some_decl();

import module B;

where being in a module purview is insufficient to identify them.

Differential Revision: https://reviews.llvm.org/D118893

Added: 
clang/test/Modules/cxx20-import-diagnostics-a.cpp

Modified: 
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/lib/Interpreter/IncrementalParser.cpp
clang/lib/Parse/ParseAST.cpp
clang/lib/Parse/ParseObjc.cpp
clang/lib/Parse/Parser.cpp
clang/lib/Sema/SemaModule.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index e23810f402365..f21e841bcdd38 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1539,6 +1539,10 @@ def err_private_module_fragment_expected_semi : Error<
 def err_missing_before_module_end : Error<"expected %0 at end of module">;
 def err_unsupported_module_partition : Error<
   "sorry, module partitions are not yet supported">;
+def err_import_not_allowed_here : Error<
+  "imports must immediately follow the module declaration">;
+def err_import_in_wrong_fragment : Error<
+  "module%select{| partition}0 imports cannot be in the 
%select{global|private}1 module fragment">;
 
 def err_export_empty : Error<"export declaration cannot be empty">;
 }

diff  --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 981800a7e2356..08d492a7ec721 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -464,14 +464,17 @@ class Parser : public CodeCompletionHandler {
   void Initialize();
 
   /// Parse the first top-level declaration in a translation unit.
-  bool ParseFirstTopLevelDecl(DeclGroupPtrTy );
+  bool ParseFirstTopLevelDecl(DeclGroupPtrTy ,
+  Sema::ModuleImportState );
 
   /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if
   /// the EOF was encountered.
-  bool ParseTopLevelDecl(DeclGroupPtrTy , bool IsFirstDecl = false);
+  bool ParseTopLevelDecl(DeclGroupPtrTy ,
+ Sema::ModuleImportState );
   bool ParseTopLevelDecl() {
 DeclGroupPtrTy Result;
-return ParseTopLevelDecl(Result);
+Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module;
+return ParseTopLevelDecl(Result, IS);
   }
 
   /// ConsumeToken - Consume the current 'peek token' and lex the next one.
@@ -3491,8 +3494,9 @@ class Parser : public CodeCompletionHandler {
 
   
//======//
   // Modules
-  DeclGroupPtrTy ParseModuleDecl(bool IsFirstDecl);
-  Decl *ParseModuleImport(SourceLocation AtLoc);
+  DeclGroupPtrTy ParseModuleDecl(Sema::ModuleImportState );
+  Decl *ParseModuleImport(SourceLocation AtLoc,
+  Sema::ModuleImportState );
   bool parseMisplacedModuleImport();
   bool tryParseMisplacedModuleImport() {
 tok::TokenKind Kind = Tok.getKind();

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index c1e846c55dee7..dfa12ad40b72a 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2949,11 +2949,24 @@ class Sema final {
 Implementation, ///< 'module X;'
   };
 
+  /// An enumeration to represent the transition of states in parsing module
+  /// fragments and imports.  If we are not parsing a C++20 TU, or we find
+  /// an error in state transition, the state is set to NotACXX20Module.
+  enum class ModuleImportState {
+FirstDecl,   

[clang] 2370977 - [clang] Remove a duplicate action kind table entry.

2022-02-15 Thread Iain Sandoe via cfe-commits

Author: iains
Date: 2022-02-15T11:19:09Z
New Revision: 2370977bdd0254d9d5424713513aeee233c647e4

URL: 
https://github.com/llvm/llvm-project/commit/2370977bdd0254d9d5424713513aeee233c647e4
DIFF: 
https://github.com/llvm/llvm-project/commit/2370977bdd0254d9d5424713513aeee233c647e4.diff

LOG: [clang] Remove a duplicate action kind table entry.

We have two entries for OPT_emit_codegen_only in the frontend action kind
table, delete one.

Differential Revision: https://reviews.llvm.org/D119826

Added: 


Modified: 
clang/lib/Frontend/CompilerInvocation.cpp

Removed: 




diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 1b7448feb472b..1014147451091 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2406,7 +2406,6 @@ static const auto () {
   {frontend::EmitLLVM, OPT_emit_llvm},
   {frontend::EmitLLVMOnly, OPT_emit_llvm_only},
   {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
-  {frontend::EmitCodeGenOnly, OPT_emit_codegen_only},
   {frontend::EmitObj, OPT_emit_obj},
   {frontend::ExtractAPI, OPT_extract_api},
 



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


Re: r295156 - Add a definition for __STRUCT_PARM_ALIGN__ for elfv2 and 64-bit darwin platforms to match what other compilers produce.

2017-03-20 Thread Iain Sandoe via cfe-commits

> On 16 Mar 2017, at 22:43, Eric Christopher  wrote:
> 
> ... and ppc64 darwin preprocessor stuff isn't tested at all. We should really 
> just delete ppc darwin support at some point. Adding Iain here since he's 
> said that he's working on the platform :)

Indeed I am, and hope to have a set of MC layer patches that make a working 32 
and 64 b assembler before euroLLVM.

I’m still working on getting an ABI match for ppc64 on Darwin, so it’s hard to 
comment except to state that the intention of the ABI is that entities are 
naturally aligned, so the 64b port ought to behave in a similar way to most 
others.

The alignment rules for Darwin32 ABI (especially embedded aggregate content) is 
somewhat special (inherited from the system on which it was based), however 
those are the subject of later patches (and therefore any changes needed could 
be accommodated along with them).

iain

> 
> At any rate I added a single test in r298006
> 
> -eric
> 
> On Wed, Feb 15, 2017 at 12:13 AM Eric Christopher  wrote:
> The PPC one should inherit from this. You're right I should have tested it 
> though. Mostly ppc Darwin isn't well supported.
> 
> 
> On Wed, Feb 15, 2017, 12:06 AM Tim Shen  wrote:
> On Wed, Feb 15, 2017, 00:01 Eric Christopher via cfe-commits 
>  wrote:
> Author: echristo
> Date: Wed Feb 15 01:50:11 2017
> New Revision: 295156
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=295156=rev
> Log:
> Add a definition for __STRUCT_PARM_ALIGN__ for elfv2 and 64-bit darwin 
> platforms to match what other compilers produce.
> 
> Modified:
> cfe/trunk/lib/Basic/Targets.cpp
> cfe/trunk/test/Preprocessor/init.c
> 
> Modified: cfe/trunk/lib/Basic/Targets.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=295156=295155=295156=diff
> ==
> --- cfe/trunk/lib/Basic/Targets.cpp (original)
> +++ cfe/trunk/lib/Basic/Targets.cpp Wed Feb 15 01:50:11 2017
> @@ -1232,6 +1232,11 @@ void PPCTargetInfo::getTargetDefines(con
>if (LongDoubleWidth == 128)
>  Builder.defineMacro("__LONG_DOUBLE_128__");
> 
> +  // Define this for elfv2 (64-bit only) or 64-bit darwin.
> +  if (ABI == "elfv2" ||
> +  (getTriple().getOS() == llvm::Triple::Darwin && PointerWidth == 64))
> 
> I also see a "DarwinTargetInfo". Maybe this should be put there as well?
> 
> +Builder.defineMacro("__STRUCT_PARM_ALIGN__", "16");
> +
>if (Opts.AltiVec) {
>  Builder.defineMacro("__VEC__", "10206");
>  Builder.defineMacro("__ALTIVEC__");
> 
> Modified: cfe/trunk/test/Preprocessor/init.c
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/init.c?rev=295156=295155=295156=diff
> ==
> --- cfe/trunk/test/Preprocessor/init.c (original)
> +++ cfe/trunk/test/Preprocessor/init.c Wed Feb 15 01:50:11 2017
> @@ -5635,6 +5635,7 @@
>  // PPC64LE:#define __SIZE_MAX__ 18446744073709551615UL
>  // PPC64LE:#define __SIZE_TYPE__ long unsigned int
>  // PPC64LE:#define __SIZE_WIDTH__ 64
> +// PPC64LE:#define __STRUCT_PARM_ALIGN__ 16
>  // PPC64LE:#define __UINT16_C_SUFFIX__
>  // PPC64LE:#define __UINT16_MAX__ 65535
>  // PPC64LE:#define __UINT16_TYPE__ unsigned short
> 
> 
> ___
> cfe-commits mailing list
> cfe-commits@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

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