[clang] d352705 - [NFC] Edit the comment for the return type of await_suspend

2020-07-28 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2020-07-29T10:20:55+08:00
New Revision: d3527052fc2a952d752f82ffbe39220bad33fc8d

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

LOG: [NFC] Edit the comment for the return type of await_suspend

Added: 


Modified: 
clang/lib/Sema/SemaCoroutine.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaCoroutine.cpp 
b/clang/lib/Sema/SemaCoroutine.cpp
index 992cccac6405..990ab2633520 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -449,7 +449,8 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, 
VarDecl *CoroPromise,
   if (!AwaitSuspend->getType()->isDependentType()) {
 // [expr.await]p3 [...]
 //   - await-suspend is the expression e.await_suspend(h), which shall be
-// a prvalue of type void or bool.
+// a prvalue of type void, bool, or std::coroutine_handle for some
+// type Z.
 QualType RetType = AwaitSuspend->getCallReturnType(S.Context);
 
 // Experimental support for coroutine_handle returning await_suspend.



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


[clang] b1d5af8 - [docs] Add "Standard C++ Modules"

2022-08-30 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-08-31T11:09:46+08:00
New Revision: b1d5af81249dc7e5697faf9ee33f86012ccd8668

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

LOG: [docs] Add "Standard C++ Modules"

We get some standard C++ module things done in clang15.x. But we lack a
user documentation for it. The implementation of standard C++ modules
share a big part of codes with clang modules. But they have very
different semantics and user interfaces, so I think it is necessary to
add a document for Standard C++ modules. Previously, there were also
some people ask the document for standard C++ Modules and I couldn't
offer that time.

Reviewed By: iains, Mordante, h-vetinari, ruoso, dblaikie, JohelEGP,
aaronmondal

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

Added: 
clang/docs/StandardCPlusPlusModules.rst

Modified: 
clang/docs/index.rst

Removed: 




diff  --git a/clang/docs/StandardCPlusPlusModules.rst 
b/clang/docs/StandardCPlusPlusModules.rst
new file mode 100644
index ..ae434b14ef50
--- /dev/null
+++ b/clang/docs/StandardCPlusPlusModules.rst
@@ -0,0 +1,876 @@
+
+Standard C++ Modules
+
+
+.. contents::
+   :local:
+
+Introduction
+
+
+The term ``modules`` has a lot of meanings. For the users of Clang, modules may
+refer to ``Objective-C Modules``, ``Clang C++ Modules`` (or ``Clang Header 
Modules``,
+etc.) or ``Standard C++ Modules``. The implementation of all these kinds of 
modules in Clang
+has a lot of shared code, but from the perspective of users, their semantics 
and
+command line interfaces are very 
diff erent. This document focuses on
+an introduction of how to use standard C++ modules in Clang.
+
+There is already a detailed document about `Clang modules `_, it
+should be helpful to read `Clang modules `_ if you want to know
+more about the general idea of modules. Since standard C++ modules have 
diff erent semantics
+(and work flows) from `Clang modules`, this page describes the background and 
use of
+Clang with standard C++ modules.
+
+Modules exist in two forms in the C++ Language Specification. They can refer to
+either "Named Modules" or to "Header Units". This document covers both forms.
+
+Standard C++ Named modules
+==
+
+This document was intended to be a manual first and foremost, however, we 
consider it helpful to
+introduce some language background here for readers who are not familiar with
+the new language feature. This document is not intended to be a language
+tutorial; it will only introduce necessary concepts about the
+structure and building of the project.
+
+Background and terminology
+--
+
+Modules
+~~~
+
+In this document, the term ``Modules``/``modules`` refers to standard C++ 
modules
+feature if it is not decorated by ``Clang``.
+
+Clang Modules
+~
+
+In this document, the term ``Clang Modules``/``Clang modules`` refer to Clang
+c++ modules extension. These are also known as ``Clang header modules``,
+``Clang module map modules`` or ``Clang c++ modules``.
+
+Module and module unit
+~~
+
+A module consists of one or more module units. A module unit is a special
+translation unit. Every module unit must have a module declaration. The syntax
+of the module declaration is:
+
+.. code-block:: c++
+
+  [export] module module_name[:partition_name];
+
+Terms enclosed in ``[]`` are optional. The syntax of ``module_name`` and 
``partition_name``
+in regex form corresponds to ``[a-zA-Z_][a-zA-Z_0-9\.]*``. In particular, a 
literal dot ``.``
+in the name has no semantic meaning (e.g. implying a hierarchy).
+
+In this document, module units are classified into:
+
+* Primary module interface unit.
+
+* Module implementation unit.
+
+* Module interface partition unit.
+
+* Internal module partition unit.
+
+A primary module interface unit is a module unit whose module declaration is
+``export module module_name;``. The ``module_name`` here denotes the name of 
the
+module. A module should have one and only one primary module interface unit.
+
+A module implementation unit is a module unit whose module declaration is
+``module module_name;``. A module could have multiple module implementation
+units with the same declaration.
+
+A module interface partition unit is a module unit whose module declaration is
+``export module module_name:partition_name;``. The ``partition_name`` should be
+unique within any given module.
+
+An internal module partition unit is a module unit whose module declaration
+is ``module module_name:partition_name;``. The ``partition_name`` should be
+unique within any given module.
+
+In this document, we use the following umbrella terms:
+
+* A ``module interface unit`` refers to e

[clang] fed71b0 - [NFC] Add an invalid test case for clang/test/CXX/module/module.reach/ex1.cpp

2022-08-30 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-08-31T13:02:00+08:00
New Revision: fed71b04fb3cc6b1a5a21f64c26104962d816300

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

LOG: [NFC] Add an invalid test case for 
clang/test/CXX/module/module.reach/ex1.cpp

Added: 


Modified: 
clang/test/CXX/module/module.reach/ex1.cpp

Removed: 




diff  --git a/clang/test/CXX/module/module.reach/ex1.cpp 
b/clang/test/CXX/module/module.reach/ex1.cpp
index 00f87607dc1d8..a1e38c4c88a28 100644
--- a/clang/test/CXX/module/module.reach/ex1.cpp
+++ b/clang/test/CXX/module/module.reach/ex1.cpp
@@ -41,3 +41,6 @@ B b3; // expected-error {{definition of 'B' must be imported 
from module 'M:B' b
   // expected-note@* {{definition here is not reachable}} expected-note@* 
{{}}
 // FIXME: We should emit an error for unreachable definition of B.
 void g() { f(); }
+void g1() { f(B()); } // expected-error 1+{{definition of 'B' must be imported 
from module 'M:B' before it is required}}
+  // expected-note@* 1+{{definition here is not reachable}}
+  // expected-n...@m.cppm:5 {{passing argument to 
parameter 'b' here}}



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


[clang] 7e19d53 - [NFC] Emit builtin coroutine calls uniforally

2022-09-01 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-01T16:31:51+08:00
New Revision: 7e19d53da44942de9b373028828c276648a8f2a4

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

LOG: [NFC] Emit builtin coroutine calls uniforally

All the coroutine builtins were emitted in EmitCoroutineIntrinsic except
__builtin_coro_size. This patch tries to emit all the corotine builtins
uniformally.

Added: 


Modified: 
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/CodeGen/CGCoroutine.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index f2d0b20c00c4..cc3cf9ab46b5 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4647,14 +4647,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
   case Builtin::BI__fastfail:
 return RValue::get(EmitMSVCBuiltinExpr(MSVCIntrin::__fastfail, E));
 
-  case Builtin::BI__builtin_coro_size: {
-auto & Context = getContext();
-auto SizeTy = Context.getSizeType();
-auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
-Function *F = CGM.getIntrinsic(Intrinsic::coro_size, T);
-return RValue::get(Builder.CreateCall(F));
-  }
-
   case Builtin::BI__builtin_coro_id:
 return EmitCoroutineIntrinsic(E, Intrinsic::coro_id);
   case Builtin::BI__builtin_coro_promise:
@@ -4679,6 +4671,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 return EmitCoroutineIntrinsic(E, Intrinsic::coro_end);
   case Builtin::BI__builtin_coro_suspend:
 return EmitCoroutineIntrinsic(E, Intrinsic::coro_suspend);
+  case Builtin::BI__builtin_coro_size:
+return EmitCoroutineIntrinsic(E, Intrinsic::coro_size);
 
   // OpenCL v2.0 s6.13.16.2, Built-in pipe read and write functions
   case Builtin::BIread_pipe:

diff  --git a/clang/lib/CodeGen/CGCoroutine.cpp 
b/clang/lib/CodeGen/CGCoroutine.cpp
index 177d85ff699c..c0fcd632ea0d 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -676,6 +676,13 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const 
CallExpr *E,
 auto NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
 return RValue::get(NullPtr);
   }
+  case llvm::Intrinsic::coro_size: {
+auto &Context = getContext();
+auto SizeTy = Context.getSizeType();
+auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
+llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);
+return RValue::get(Builder.CreateCall(F));
+  }
   // The following three intrinsics take a token parameter referring to a token
   // returned by earlier call to @llvm.coro.id. Since we cannot represent it in
   // builtins, we patch it up here.



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


[clang] 1334e12 - [cmake] Append CLANG_LIBDIR_SUFFIX to scan-build-py installation destination

2022-09-02 Thread Chuanqi Xu via cfe-commits

Author: Sinan Lin
Date: 2022-09-02T16:18:15+08:00
New Revision: 1334e129a39cb427e7b855e9a711a3e7604e50e5

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

LOG: [cmake] Append CLANG_LIBDIR_SUFFIX to scan-build-py installation 
destination

met this issue when building llvm with config LLVM_LIBDIR_SUFFIX=64, and
the installation destination of scan-build-py does not respect the given
suffix.

Reviewed By: phosek

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

Added: 


Modified: 
clang/tools/scan-build-py/CMakeLists.txt

Removed: 




diff  --git a/clang/tools/scan-build-py/CMakeLists.txt 
b/clang/tools/scan-build-py/CMakeLists.txt
index 061dc7ef4dd9e..a087f87974cb8 100644
--- a/clang/tools/scan-build-py/CMakeLists.txt
+++ b/clang/tools/scan-build-py/CMakeLists.txt
@@ -88,7 +88,7 @@ foreach(lib ${LibScanbuild})
  DEPENDS 
${CMAKE_CURRENT_SOURCE_DIR}/lib/libscanbuild/${lib})
   list(APPEND Depends ${CMAKE_BINARY_DIR}/lib/libscanbuild/${lib})
   install(PROGRAMS lib/libscanbuild/${lib}
-  DESTINATION lib/libscanbuild
+  DESTINATION lib${CLANG_LIBDIR_SUFFIX}/libscanbuild
   COMPONENT scan-build-py)
 endforeach()
 
@@ -106,7 +106,7 @@ foreach(resource ${LibScanbuildResources})
  DEPENDS 
${CMAKE_CURRENT_SOURCE_DIR}/lib/libscanbuild/resources/${resource})
   list(APPEND Depends 
${CMAKE_BINARY_DIR}/lib/libscanbuild/resources/${resource})
   install(PROGRAMS lib/libscanbuild/resources/${resource}
-  DESTINATION lib/libscanbuild/resources
+  DESTINATION lib${CLANG_LIBDIR_SUFFIX}/libscanbuild/resources
   COMPONENT scan-build-py)
 endforeach()
 
@@ -122,7 +122,7 @@ foreach(lib ${LibEar})
  DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/lib/libear/${lib})
   list(APPEND Depends ${CMAKE_BINARY_DIR}/lib/libear/${lib})
   install(PROGRAMS lib/libear/${lib}
-  DESTINATION lib/libear
+  DESTINATION lib${CLANG_LIBDIR_SUFFIX}/libear
   COMPONENT scan-build-py)
 endforeach()
 



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


[clang] 085e8cd - [NFC] Cleanup lookup for coroutine allocation/deallocation

2022-09-02 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-02T17:24:52+08:00
New Revision: 085e8cd8d32c9104abbc2c1345a1483f19d25d36

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

LOG: [NFC] Cleanup lookup for coroutine allocation/deallocation

Added: 


Modified: 
clang/lib/Sema/SemaCoroutine.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaCoroutine.cpp 
b/clang/lib/Sema/SemaCoroutine.cpp
index a738befdd6ce..1fca15a31951 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1031,10 +1031,8 @@ static Expr *buildStdNoThrowDeclRef(Sema &S, 
SourceLocation Loc) {
 }
 
 // Find an appropriate delete for the promise.
-static FunctionDecl *findDeleteForPromise(Sema &S, SourceLocation Loc,
-  QualType PromiseType) {
-  FunctionDecl *OperatorDelete = nullptr;
-
+static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType 
PromiseType,
+ FunctionDecl *&OperatorDelete) {
   DeclarationName DeleteName =
   S.Context.DeclarationNames.getCXXOperatorName(OO_Delete);
 
@@ -1046,25 +1044,31 @@ static FunctionDecl *findDeleteForPromise(Sema &S, 
SourceLocation Loc,
   // scope of the promise type. If nothing is found, a search is performed in
   // the global scope.
   if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
-return nullptr;
+return false;
 
-  // FIXME: We didn't implement following selection:
   // [dcl.fct.def.coroutine]p12
   //   If both a usual deallocation function with only a pointer parameter and 
a
   //   usual deallocation function with both a pointer parameter and a size
   //   parameter are found, then the selected deallocation function shall be 
the
   //   one with two parameters. Otherwise, the selected deallocation function
   //   shall be the function with one parameter.
-
   if (!OperatorDelete) {
 // Look for a global declaration.
-const bool CanProvideSize = S.isCompleteType(Loc, PromiseType);
+// Coroutines can always provide their required size.
+const bool CanProvideSize = true;
 const bool Overaligned = false;
+// Sema::FindUsualDeallocationFunction will try to find the one with two
+// parameters first. It will return the deallocation function with one
+// parameter if failed.
 OperatorDelete = S.FindUsualDeallocationFunction(Loc, CanProvideSize,
  Overaligned, DeleteName);
+
+if (!OperatorDelete)
+  return false;
   }
+
   S.MarkFunctionReferenced(Loc, OperatorDelete);
-  return OperatorDelete;
+  return true;
 }
 
 
@@ -1319,8 +1323,6 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // lvalue that denotes the parameter copy corresponding to p_i.
 
   FunctionDecl *OperatorNew = nullptr;
-  FunctionDecl *OperatorDelete = nullptr;
-  FunctionDecl *UnusedResult = nullptr;
   bool PassAlignment = false;
   SmallVector PlacementArgs;
 
@@ -1344,11 +1346,13 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
 // is performed in the global scope.
 Sema::AllocationFunctionScope NewScope =
 PromiseContainsNew ? Sema::AFS_Class : Sema::AFS_Global;
+FunctionDecl *UnusedResult = nullptr;
 S.FindAllocationFunctions(Loc, SourceRange(),
   NewScope,
   /*DeleteScope*/ Sema::AFS_Both, PromiseType,
   /*isArray*/ false, PassAlignment, PlacementArgs,
-  OperatorNew, UnusedResult, /*Diagnose*/ false);
+  OperatorNew, UnusedResult,
+  /*Diagnose*/ false);
   };
 
   // We don't expect to call to global operator new with (size, p0, …, pn).
@@ -1379,6 +1383,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   return false;
 PlacementArgs = {StdNoThrow};
 OperatorNew = nullptr;
+FunctionDecl *UnusedResult = nullptr;
 S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Both,
   /*DeleteScope*/ Sema::AFS_Both, PromiseType,
   /*isArray*/ false, PassAlignment, PlacementArgs,
@@ -1404,7 +1409,8 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
 }
   }
 
-  if ((OperatorDelete = findDeleteForPromise(S, Loc, PromiseType)) == nullptr) 
{
+  FunctionDecl *OperatorDelete = nullptr;
+  if (!findDeleteForPromise(S, Loc, PromiseType, OperatorDelete)) {
 // FIXME: We should add an error here. According to:
 // [dcl.fct.def.coroutine]p12
 //   If no usual deallocation function is found, the program is ill-formed.



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org

[clang] baa9eae - [NFC] fix incorrect indentation in docs

2022-09-04 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-05T11:05:23+08:00
New Revision: baa9eae279c1639f406015734ebbf4c429b15c21

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

LOG: [NFC] fix incorrect indentation in docs

Added: 


Modified: 
clang/docs/StandardCPlusPlusModules.rst

Removed: 




diff  --git a/clang/docs/StandardCPlusPlusModules.rst 
b/clang/docs/StandardCPlusPlusModules.rst
index ae434b14ef50c..86ba6f44dbb02 100644
--- a/clang/docs/StandardCPlusPlusModules.rst
+++ b/clang/docs/StandardCPlusPlusModules.rst
@@ -481,19 +481,19 @@ Then it is problematic if we remove ``foo.h`` before 
import `foo` module.
 
 .. code-block:: console
 
-  clang++ -std=c++20 foo.cppm --precompile  -o foo.pcm
-   mv foo.h foo.orig.h
+  $ clang++ -std=c++20 foo.cppm --precompile  -o foo.pcm
+  $ mv foo.h foo.orig.h
   # The following one is rejected
-   clang++ -std=c++20 Use.cpp -fmodule-file=foo.pcm -c
+  $ clang++ -std=c++20 Use.cpp -fmodule-file=foo.pcm -c
 
 The above case will rejected. And we're still able to workaround it by 
``-Xclang -fmodules-embed-all-files`` option:
 
 .. code-block:: console
 
-  clang++ -std=c++20 foo.cppm --precompile  -Xclang -fmodules-embed-all-files 
-o foo.pcm
-   mv foo.h foo.orig.h
-   clang++ -std=c++20 Use.cpp -fmodule-file=foo.pcm -c -o Use.o
-   clang++ Use.o foo.pcm
+  $ clang++ -std=c++20 foo.cppm --precompile  -Xclang 
-fmodules-embed-all-files -o foo.pcm
+  $ mv foo.h foo.orig.h
+  $ clang++ -std=c++20 Use.cpp -fmodule-file=foo.pcm -c -o Use.o
+  $ clang++ Use.o foo.pcm
 
 ABI Impacts
 ---



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


[clang] 69e920d - [Coroutines] Use LookupAllocationFunction to find allocation functions for coroutines consistently

2022-09-05 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-05T15:20:09+08:00
New Revision: 69e920d42677872ac39d3475312092404193bf24

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

LOG: [Coroutines] Use LookupAllocationFunction to find allocation functions for 
coroutines consistently

Previously we may call Sema::FindAllocationFunctions directly to lookup
allocation functions directly instead of using our wrapped lambda
LookupAllocationFunction, which is slightly incosnsistent. It will be
helpful to refactor this for further changes.

Also previously, when we lookup 'operator new(std::size_t, std::nothrow_t)' in
case we found `get_­return_­object_­on_­allocation_­failure` in the
promise_type, the compiler will try to look at the allocation function
in promise_type. However, this is not wanted actually. According to
[dcl.fct.def.coroutine]p10:

> if a global allocation function is selected, the
> ::operator new(size_­t, nothrow_­t) form is used.

So we should only lookup for `::operator (size_t, nothrow_t)` for the
global allocation function. For the allocation function in the
promise_type, the requirement is that it shouldn't throw, which has
already been checked.

Given users generally include headers from standard libs so it will
generally include the  header, so this change should be a trivial
one and shouldn't affect almost any user.

Added: 
clang/test/SemaCXX/coroutine-alloc-2.cpp
clang/test/SemaCXX/coroutine-alloc-3.cpp

Modified: 
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaCoroutine.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f6e89b5219f83..66cf0d8107934 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11272,6 +11272,9 @@ def warn_always_inline_coroutine : Warning<
 def err_coroutine_unusable_new : Error<
   "'operator new' provided by %0 is not usable with the function signature of 
%1"
 >;
+def err_coroutine_unfound_nothrow_new : Error <
+  "unable to find '::operator new(size_­t, nothrow_­t)' for %0"
+>;
 } // end of coroutines issue category
 
 let CategoryName = "Documentation Issue" in {

diff  --git a/clang/lib/Sema/SemaCoroutine.cpp 
b/clang/lib/Sema/SemaCoroutine.cpp
index 1fca15a319515..933b9188a8ae7 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1326,7 +1326,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   bool PassAlignment = false;
   SmallVector PlacementArgs;
 
-  bool PromiseContainsNew = [this, &PromiseType]() -> bool {
+  const bool PromiseContainsNew = [this, &PromiseType]() -> bool {
 DeclarationName NewName =
 S.getASTContext().DeclarationNames.getCXXOperatorName(OO_New);
 LookupResult R(S, NewName, Loc, Sema::LookupOrdinaryName);
@@ -1337,22 +1337,22 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
 return !R.empty() && !R.isAmbiguous();
   }();
 
-  auto LookupAllocationFunction = [&]() {
+  auto LookupAllocationFunction = [&](Sema::AllocationFunctionScope NewScope =
+  Sema::AFS_Both) {
 // [dcl.fct.def.coroutine]p9
 //   The allocation function's name is looked up by searching for it in the
 // scope of the promise type.
 // - If any declarations are found, ...
 // - If no declarations are found in the scope of the promise type, a 
search
 // is performed in the global scope.
-Sema::AllocationFunctionScope NewScope =
-PromiseContainsNew ? Sema::AFS_Class : Sema::AFS_Global;
+if (NewScope == Sema::AFS_Both)
+  NewScope = PromiseContainsNew ? Sema::AFS_Class : Sema::AFS_Global;
+
 FunctionDecl *UnusedResult = nullptr;
-S.FindAllocationFunctions(Loc, SourceRange(),
-  NewScope,
+S.FindAllocationFunctions(Loc, SourceRange(), NewScope,
   /*DeleteScope*/ Sema::AFS_Both, PromiseType,
   /*isArray*/ false, PassAlignment, PlacementArgs,
-  OperatorNew, UnusedResult,
-  /*Diagnose*/ false);
+  OperatorNew, UnusedResult, /*Diagnose*/ false);
   };
 
   // We don't expect to call to global operator new with (size, p0, …, pn).
@@ -1383,16 +1383,14 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   return false;
 PlacementArgs = {StdNoThrow};
 OperatorNew = nullptr;
-FunctionDecl *UnusedResult = nullptr;
-S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Both,
-  /*DeleteScope*/ Sema::AFS_Both, PromiseType,
-  /*isArray*/ false, PassAlignment, Plac

[clang] 7628f19 - [NFC] Remove invisible character in Diagnostic message and tests

2022-09-05 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-06T11:08:42+08:00
New Revision: 7628f19262e441b438a69176ec5229d8ccb96124

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

LOG: [NFC] Remove invisible character in Diagnostic message and tests

Added: 


Modified: 
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/test/SemaCXX/coroutine-alloc-3.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 66cf0d8107934..15a4e2aefdb79 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11273,7 +11273,7 @@ def err_coroutine_unusable_new : Error<
   "'operator new' provided by %0 is not usable with the function signature of 
%1"
 >;
 def err_coroutine_unfound_nothrow_new : Error <
-  "unable to find '::operator new(size_­t, nothrow_­t)' for %0"
+  "unable to find '::operator new(size_t, nothrow_t)' for %0"
 >;
 } // end of coroutines issue category
 

diff  --git a/clang/test/SemaCXX/coroutine-alloc-3.cpp 
b/clang/test/SemaCXX/coroutine-alloc-3.cpp
index 6e47d36712f3f..629ac88a3df8e 100644
--- a/clang/test/SemaCXX/coroutine-alloc-3.cpp
+++ b/clang/test/SemaCXX/coroutine-alloc-3.cpp
@@ -46,6 +46,6 @@ struct std::coroutine_traits {
   };
 };
 
-extern "C" int f(promise_on_alloc_failure_tag) { // expected-error 1+{{unable 
to find '::operator new(size_­t, nothrow_­t)' for 'f'}}
+extern "C" int f(promise_on_alloc_failure_tag) { // expected-error 1+{{unable 
to find '::operator new(size_t, nothrow_t)' for 'f'}}
 co_return;
 }



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


[clang] 4954196 - [NFC] Add test of sized deallocation for coroutines

2022-09-05 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-06T14:44:16+08:00
New Revision: 495419628bbab1a99cfc00d0c44b877bfc8e4a14

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

LOG: [NFC] Add test of sized deallocation for coroutines

[dcl.fct.def.coroutine]p12 says:

> If both a usual deallocation function with only a pointer parameter
> and a usual deallocation function with both a pointer parameter and a
> size parameter are found, then the selected deallocation function
> shall be the one with two parameters.

However, the sized deallocation function is disabled by default for ABI
reasons. This leads the sentence never get tested and covered. This
commit tries to add a test for it

Added: 
clang/test/CodeGenCoroutines/coro-dealloc.cpp

Modified: 


Removed: 




diff  --git a/clang/test/CodeGenCoroutines/coro-dealloc.cpp 
b/clang/test/CodeGenCoroutines/coro-dealloc.cpp
new file mode 100644
index 0..1f7d04b3689eb
--- /dev/null
+++ b/clang/test/CodeGenCoroutines/coro-dealloc.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
+// RUN:   -S -emit-llvm %s -o - -disable-llvm-passes \
+// RUN:   -fsized-deallocation \
+// RUN:   | FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+namespace std {
+typedef __SIZE_TYPE__ size_t;
+enum class align_val_t : size_t {};
+}
+
+struct task {
+  struct promise_type {
+auto initial_suspend() { return std::suspend_always{}; }
+auto final_suspend() noexcept { return std::suspend_always{}; }
+auto get_return_object() { return task{}; }
+void unhandled_exception() {}
+void return_value(int) {}
+  };
+};
+
+// Test the compiler will chose sized deallocation correctly.
+// This is only enabled with `-fsized-deallocation` which is off by default.
+void operator delete(void *ptr, std::size_t size) noexcept;
+
+// CHECK: define{{.*}}@_Z1fv
+// CHECK: %[[coro_free:.+]] = call{{.*}}@llvm.coro.free
+// CHECK: coro.free:
+// CHECK: %[[coro_size:.+]] = call{{.*}}@llvm.coro.size
+// CHECK: call{{.*}}void @_ZdlPvm(ptr{{.*}}%[[coro_free]], 
i64{{.*}}%[[coro_size]])
+
+task f() {
+  co_return 43;
+}



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


[clang] f65f06d - [NFC] [Coroutines] Add tests for looking up deallocation

2022-09-06 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-06T14:57:01+08:00
New Revision: f65f06d63f6a0e40c33a9d77eeb381f1b2a8a524

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

LOG: [NFC] [Coroutines] Add tests for looking up deallocation

According to [dcl.fct.def.coroutine]p12, the program should be
ill-formed if the promise_type contains operator delete but none of them
are available. But this behavior was not tested before. This commit adds
the tests for it.

Added: 
clang/test/SemaCXX/coroutine-dealloc.cpp
clang/test/SemaCXX/coroutine-no-valid-dealloc.cpp

Modified: 


Removed: 




diff  --git a/clang/test/SemaCXX/coroutine-dealloc.cpp 
b/clang/test/SemaCXX/coroutine-dealloc.cpp
new file mode 100644
index ..6eca1e6f42f8
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-dealloc.cpp
@@ -0,0 +1,27 @@
+// Tests that the behavior will be good if there are multiple operator delete 
in the promise_type.
+// RUN: %clang_cc1 %s -std=c++20 %s -fsyntax-only -verify
+// expected-no-diagnostics
+
+#include "Inputs/std-coroutine.h"
+
+namespace std {
+typedef __SIZE_TYPE__ size_t;
+enum class align_val_t : size_t {};
+}
+
+struct task {
+  struct promise_type {
+auto initial_suspend() { return std::suspend_always{}; }
+auto final_suspend() noexcept { return std::suspend_always{}; }
+auto get_return_object() { return task{}; }
+void unhandled_exception() {}
+void return_value(int) {}
+
+void operator delete(void *ptr, void *meaningless_placeholder);
+void operator delete(void *ptr);
+  };
+};
+
+task f() {
+  co_return 43;
+}

diff  --git a/clang/test/SemaCXX/coroutine-no-valid-dealloc.cpp 
b/clang/test/SemaCXX/coroutine-no-valid-dealloc.cpp
new file mode 100644
index ..a5727d6f003b
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-no-valid-dealloc.cpp
@@ -0,0 +1,26 @@
+// Test that if the compiler will emit error message if the promise_type 
contain
+// operator delete but none of them are available. This is required by the 
standard.
+// RUN: %clang_cc1 %s -std=c++20 %s -fsyntax-only -verify
+
+#include "Inputs/std-coroutine.h"
+
+namespace std {
+typedef __SIZE_TYPE__ size_t;
+enum class align_val_t : size_t {};
+}
+
+struct task {
+  struct promise_type {
+auto initial_suspend() { return std::suspend_always{}; }
+auto final_suspend() noexcept { return std::suspend_always{}; }
+auto get_return_object() { return task{}; }
+void unhandled_exception() {}
+void return_value(int) {}
+
+void operator delete(void *ptr, void *meaningless_placeholder); // 
expected-note {{member 'operator delete' declared here}}
+  };
+};
+
+task f() { // expected-error 1+{{no suitable member 'operator delete' in 
'promise_type'}}
+  co_return 43;
+}



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


[clang] 5f571ee - [NFC] [Frontend] Correct the use of 'auto' in SemaCoroutine and CGCoroutine

2022-09-06 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-07T10:45:01+08:00
New Revision: 5f571eeb3f764c6d97b81822464ea420adef2cf7

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

LOG: [NFC] [Frontend] Correct the use of 'auto' in SemaCoroutine and CGCoroutine

We should only use 'auto' in case we can know the type from the right
hand side of the expression. Also we need keep '*' around if the type is
a pointer actually. Few uses of 'auto' in SemaCoroutine.cpp and
CGCoroutine.cpp violates the rule. This commit tries to fix it.

Added: 


Modified: 
clang/lib/CodeGen/CGCoroutine.cpp
clang/lib/Sema/SemaCoroutine.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGCoroutine.cpp 
b/clang/lib/CodeGen/CGCoroutine.cpp
index c0fcd632ea0d7..abe8d2644a1f3 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -539,7 +539,7 @@ void CodeGenFunction::EmitCoroutineBody(const 
CoroutineBodyStmt &S) {
 EHStack.pushCleanup(NormalAndEHCleanup, S.getDeallocate());
 
 // Create mapping between parameters and copy-params for coroutine 
function.
-auto ParamMoves = S.getParamMoves();
+llvm::ArrayRef ParamMoves = S.getParamMoves();
 assert(
 (ParamMoves.size() == 0 || (ParamMoves.size() == FnArgs.size())) &&
 "ParamMoves and FnArgs should be the same size for coroutine 
function");
@@ -673,13 +673,13 @@ RValue CodeGenFunction::EmitCoroutineIntrinsic(const 
CallExpr *E,
 }
 CGM.Error(E->getBeginLoc(), "this builtin expect that __builtin_coro_begin 
"
 "has been used earlier in this function");
-auto NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
+auto *NullPtr = llvm::ConstantPointerNull::get(Builder.getInt8PtrTy());
 return RValue::get(NullPtr);
   }
   case llvm::Intrinsic::coro_size: {
 auto &Context = getContext();
-auto SizeTy = Context.getSizeType();
-auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
+CanQualType SizeTy = Context.getSizeType();
+llvm::IntegerType *T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
 llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);
 return RValue::get(Builder.CreateCall(F));
   }

diff  --git a/clang/lib/Sema/SemaCoroutine.cpp 
b/clang/lib/Sema/SemaCoroutine.cpp
index 933b9188a8ae7..31a79e11f21f6 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1698,7 +1698,7 @@ bool Sema::buildCoroutineParameterMoves(SourceLocation 
Loc) {
 // [dcl.fct.def.coroutine]p13
 //   The initialization and destruction of each parameter copy occurs in 
the
 //   context of the called coroutine.
-auto D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
+auto *D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());
 AddInitializerToDecl(D, CExpr, /*DirectInit=*/true);
 
 // Convert decl to a statement.
@@ -1728,7 +1728,8 @@ ClassTemplateDecl 
*Sema::lookupCoroutineTraits(SourceLocation KwLoc,
 // discovered.
 // TODO: Become stricter when  is removed.
 
-auto const &TraitIdent = PP.getIdentifierTable().get("coroutine_traits");
+IdentifierInfo const &TraitIdent =
+PP.getIdentifierTable().get("coroutine_traits");
 
 NamespaceDecl *StdSpace = getStdNamespace();
 LookupResult ResStd(*this, &TraitIdent, FuncLoc, LookupOrdinaryName);
@@ -1746,7 +1747,7 @@ ClassTemplateDecl 
*Sema::lookupCoroutineTraits(SourceLocation KwLoc,
 }
 
 // Prefer ::std to std::experimental.
-auto &Result = InStd ? ResStd : ResExp;
+LookupResult &Result = InStd ? ResStd : ResExp;
 CoroTraitsNamespaceCache = InStd ? StdSpace : ExpSpace;
 
 // coroutine_traits is required to be a class template.
@@ -1763,7 +1764,7 @@ ClassTemplateDecl 
*Sema::lookupCoroutineTraits(SourceLocation KwLoc,
   Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
   << "coroutine_traits";
   ResExp.suppressDiagnostics();
-  auto *Found = *ResExp.begin();
+  NamedDecl *Found = *ResExp.begin();
   Diag(Found->getLocation(), diag::note_entity_declared_at) << Found;
 
   if (InStd &&



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


[clang] 79fa0ec - [C++20] [Modules] Make member functions with a in-class definition in HU implicitly inline

2022-09-12 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-13T13:11:56+08:00
New Revision: 79fa0ec8c4bfeeb21f7b44ebd9a66e7ec9781798

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

LOG: [C++20] [Modules] Make member functions with a in-class definition in HU 
implicitly inline

According to [dcl.inline]p7/note4,

> In the global module, a function defined within a class definition is
> implicitly inline.

And the declarations in the header unit are attached to the global
module fragment. So the function defined within a class definition in
header units should be implicitly inline too.

This fixes https://github.com/llvm/llvm-project/issues/57571.

Added: 
clang/test/CodeGenCXX/header-unit-friend-within-class-linkage.cpp
clang/test/CodeGenCXX/header-unit-member-func-linkage.cpp

Modified: 
clang/lib/Sema/SemaDecl.cpp
clang/unittests/AST/DeclTest.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9d0e6769f0875..b1c453951f064 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9503,7 +9503,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
 bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlusModules ||
!NewFD->getOwningModule() ||
NewFD->getOwningModule()->isGlobalModule() ||
-   NewFD->getOwningModule()->isModuleMapModule();
+   NewFD->getOwningModule()->isHeaderLikeModule();
 bool isInline = D.getDeclSpec().isInlineSpecified();
 bool isVirtual = D.getDeclSpec().isVirtualSpecified();
 bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier();

diff  --git a/clang/test/CodeGenCXX/header-unit-friend-within-class-linkage.cpp 
b/clang/test/CodeGenCXX/header-unit-friend-within-class-linkage.cpp
new file mode 100644
index 0..cfee317ba6b2d
--- /dev/null
+++ b/clang/test/CodeGenCXX/header-unit-friend-within-class-linkage.cpp
@@ -0,0 +1,27 @@
+// Tests that the friend function with-in an class definition in the header 
unit is still implicit inline.
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -xc++-user-header 
-emit-header-unit %t/foo.h -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple 
-fmodule-file=%t/foo.pcm %t/user.cpp \
+// RUN:   -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/user.cpp
+
+//--- foo.h
+class foo {
+int value;
+public:
+foo(int v) : value(v) {}
+
+friend int getFooValue(foo f) {
+return f.value;
+}
+};
+
+//--- user.cpp
+import "foo.h";
+int use() {
+foo f(43);
+return getFooValue(f);
+}
+
+// CHECK: define{{.*}}linkonce_odr{{.*}}@_Z11getFooValue3foo

diff  --git a/clang/test/CodeGenCXX/header-unit-member-func-linkage.cpp 
b/clang/test/CodeGenCXX/header-unit-member-func-linkage.cpp
new file mode 100644
index 0..5ab15dff01589
--- /dev/null
+++ b/clang/test/CodeGenCXX/header-unit-member-func-linkage.cpp
@@ -0,0 +1,24 @@
+// Tests that the member function with-in an class definition in the header 
unit is still implicit inline.
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple -xc++-user-header 
-emit-header-unit %t/foo.h -o %t/foo.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple 
-fmodule-file=%t/foo.pcm %t/user.cpp \
+// RUN:   -S -emit-llvm -disable-llvm-passes -o - | FileCheck %t/user.cpp
+
+//--- foo.h
+class foo {
+public:
+int getValue() {
+return 43;
+}
+};
+
+//--- user.cpp
+import "foo.h";
+int use() {
+foo f;
+return f.getValue();
+}
+
+// CHECK: define{{.*}}linkonce_odr{{.*}}@_ZN3foo8getValueEv

diff  --git a/clang/unittests/AST/DeclTest.cpp 
b/clang/unittests/AST/DeclTest.cpp
index 7fe715db52979..43a3798867f49 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -311,3 +311,46 @@ TEST(Decl, MemberFunctionInModules) {
   EXPECT_TRUE(bar->isInlined());
 }
 
+TEST(Decl, MemberFunctionInHeaderUnit) {
+  llvm::Annotations Code(R"(
+class foo {
+public:
+  int memFn() {
+return 43;
+  }
+};
+)");
+
+  auto AST = tooling::buildASTFromCodeWithArgs(
+  Code.code(), {"-std=c++20", " -xc++-user-header ", "-emit-header-unit"});
+  ASTContext &Ctx = AST->getASTContext();
+
+  auto *memFn = selectFirst(
+  "memFn", match(functionDecl(hasName("memFn")).bind("memFn"), Ctx));
+
+  EXPECT_TRUE(memFn->isInlined());
+}
+
+TEST(Decl, FriendFunctionWithinClassInHeaderUnit) {
+  llvm::Annotations Code(R"(
+class foo {
+  int value;
+public:
+  foo(int v) : value(v) {}
+
+  friend int getFooValue(foo f) {
+return f.value;
+ 

[clang] 1c0a90f - [C++20] [Coroutines] Prefer sized deallocation in promise_type

2022-09-14 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-09-14T15:07:31+08:00
New Revision: 1c0a90fd47bded1a6d5f31091e32cd79434bf4d4

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

LOG: [C++20] [Coroutines] Prefer sized deallocation in promise_type

Now when the compiler can't find the sized deallocation function
correctly in promise_type if there are multiple deallocation function
overloads there.

According to [dcl.fct.def.coroutine]p12:
> If both a usual deallocation function with only a pointer parameter
> and a usual deallocation function with both a pointer parameter and a
> size parameter are found, then the selected deallocation function
> shall be the one with two parameters.

So when there are multiple deallocation functions, the compiler should
choose the sized one instead of the unsized one. The patch fixes this.

Added: 


Modified: 
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaCoroutine.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/CodeGenCoroutines/coro-alloc.cpp

Removed: 




diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 459c1109b852e..44c4f92592b06 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6646,8 +6646,8 @@ class Sema final {
ArrayRef Params);
 
   bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
-DeclarationName Name, FunctionDecl* &Operator,
-bool Diagnose = true);
+DeclarationName Name, FunctionDecl *&Operator,
+bool Diagnose = true, bool WantSize = false);
   FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
   bool CanProvideSize,
   bool Overaligned,

diff  --git a/clang/lib/Sema/SemaCoroutine.cpp 
b/clang/lib/Sema/SemaCoroutine.cpp
index 31a79e11f21f6..34ed416da3dd6 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1043,7 +1043,8 @@ static bool findDeleteForPromise(Sema &S, SourceLocation 
Loc, QualType PromiseTy
   // The deallocation function's name is looked up by searching for it in the
   // scope of the promise type. If nothing is found, a search is performed in
   // the global scope.
-  if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
+  if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete,
+ /*Diagnose*/ true, /*WantSize*/ true))
 return false;
 
   // [dcl.fct.def.coroutine]p12

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index bc950ab7c4a7a..1c4e2e968d6c0 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3176,7 +3176,8 @@ FunctionDecl 
*Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc,
 
 bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
 DeclarationName Name,
-FunctionDecl *&Operator, bool Diagnose) {
+FunctionDecl *&Operator, bool Diagnose,
+bool WantSize) {
   LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
   // Try to find operator delete/operator delete[] in class scope.
   LookupQualifiedName(Found, RD);
@@ -3192,7 +3193,7 @@ bool Sema::FindDeallocationFunction(SourceLocation 
StartLoc, CXXRecordDecl *RD,
   //   If the deallocation functions have class scope, the one without a
   //   parameter of type std::size_t is selected.
   llvm::SmallVector Matches;
-  resolveDeallocationOverload(*this, Found, /*WantSize*/ false,
+  resolveDeallocationOverload(*this, Found, /*WantSize*/ WantSize,
   /*WantAlign*/ Overaligned, &Matches);
 
   // If we could find an overload, use it.

diff  --git a/clang/test/CodeGenCoroutines/coro-alloc.cpp 
b/clang/test/CodeGenCoroutines/coro-alloc.cpp
index adcf7a1254f60..c16af68664e72 100644
--- a/clang/test/CodeGenCoroutines/coro-alloc.cpp
+++ b/clang/test/CodeGenCoroutines/coro-alloc.cpp
@@ -243,3 +243,32 @@ extern "C" int f4(promise_on_alloc_failure_tag) {
   // CHECK:   ret i32 %[[LoadRet]]
   co_return;
 }
+
+struct promise_sized_delete_tag2 {};
+
+template <>
+struct std::coroutine_traits {
+  struct promise_type {
+// Tests that the compiler can choose the correct operator delete
+// when we have multiple operator delete
+void operator delete(void*, unsigned long);
+void operator delete(void*);
+void get_return_object() {}
+suspend_always initial_suspend() { return {}; }
+suspend_always fi

[clang] [C++20] [Modules] Don't import function bodies from other module units even with optimizations (PR #71031)

2023-11-06 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

I'd like to land this change later since the existing behavior violates our 
expectations for ABI.

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


[clang] d0c778c - [NFC] Remove unused member function 'Error' from PCHValidator

2023-11-06 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-11-07T14:13:33+08:00
New Revision: d0c778c882f117182f8a43d0f986cc8c2cfbb688

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

LOG: [NFC] Remove unused member function 'Error' from PCHValidator

As the title suggested.

Added: 


Modified: 
clang/include/clang/Serialization/ASTReader.h
clang/include/clang/Serialization/ASTRecordReader.h

Removed: 




diff  --git a/clang/include/clang/Serialization/ASTReader.h 
b/clang/include/clang/Serialization/ASTReader.h
index bafbe779d60acff..7eefdca6815cdad 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -312,9 +312,6 @@ class PCHValidator : public ASTReaderListener {
StringRef SpecificModuleCachePath,
bool Complain) override;
   void ReadCounter(const serialization::ModuleFile &M, unsigned Value) 
override;
-
-private:
-  void Error(const char *Msg);
 };
 
 /// ASTReaderListenter implementation to set SuggestedPredefines of

diff  --git a/clang/include/clang/Serialization/ASTRecordReader.h 
b/clang/include/clang/Serialization/ASTRecordReader.h
index d643e54e3d923a7..80a1359fd16aa02 100644
--- a/clang/include/clang/Serialization/ASTRecordReader.h
+++ b/clang/include/clang/Serialization/ASTRecordReader.h
@@ -370,10 +370,6 @@ struct SavedStreamPosition {
   uint64_t Offset;
 };
 
-inline void PCHValidator::Error(const char *Msg) {
-  Reader.Error(Msg);
-}
-
 } // namespace clang
 
 #endif



___
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 import function bodies from other module units even with optimizations (PR #71031)

2023-11-07 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/71031

>From 427c1e1960d48e8803e235b4d5beb437ea21c942 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Thu, 2 Nov 2023 15:19:58 +0800
Subject: [PATCH 1/2] [C++20] [Modules] Don't import function bodies from other
 module units even with optimizations

Close https://github.com/llvm/llvm-project/issues/60996.

Previously, clang will try to import function bodies from other module
units to get more optimization oppotunities as much as possible. Then
the motivation becomes the direct cause of the above issue.

However, according to the discussion in SG15, the behavior of importing
function bodies from other module units breaks the ABI compatibility. It
is unwanted. So the original behavior of clang is incorrect. This patch
choose to not import function bodies from other module units in all
cases to follow the expectation.

Note that the desired optimized BMI idea is discarded too. Since it will
still break the ABI compatibility after we import function bodies
seperately.

The release note will be added seperately.

There is a similar issue for variable definitions. I'll try to handle
that in a different commit.
---
 clang/lib/CodeGen/CodeGenModule.cpp   |  9 +++
 .../CodeGenCXX/module-funcs-from-imports.cppm | 10 +--
 clang/test/CodeGenCXX/partitions.cpp  |  5 +-
 .../cxx20-importing-function-bodies.cppm  | 72 +++
 clang/test/Modules/no-import-func-body.cppm   |  4 +-
 5 files changed, 91 insertions(+), 9 deletions(-)
 create mode 100644 clang/test/Modules/cxx20-importing-function-bodies.cppm

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index cc81a68b15c4324..893e7643a447033 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3856,10 +3856,19 @@ CodeGenModule::isTriviallyRecursive(const FunctionDecl 
*FD) {
 bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
   if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
 return true;
+
   const auto *F = cast(GD.getDecl());
   if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr())
 return false;
 
+  // We don't import function bodies from other named module units since that
+  // behavior may break ABI compatibility of the current unit.
+  Module *M = F->getOwningModule();
+  if (M && M->isModulePurview() &&
+  getContext().getCurrentNamedModule() != M->getTopLevelModule() &&
+  !F->hasAttr())
+return false;
+
   if (F->hasAttr())
 return false;
 
diff --git a/clang/test/CodeGenCXX/module-funcs-from-imports.cppm 
b/clang/test/CodeGenCXX/module-funcs-from-imports.cppm
index 3b415bd9c457291..33cdf437110a9e8 100644
--- a/clang/test/CodeGenCXX/module-funcs-from-imports.cppm
+++ b/clang/test/CodeGenCXX/module-funcs-from-imports.cppm
@@ -64,13 +64,13 @@ int use() {
 // CHECK-O0-NOT: non_exported_func_not_called
 // CHECK-O0-NOT: func_not_called
 
-// Checks that all the potentially called function in the importees are 
generated in the importer's code
-// with available_externally attribute.
+// Checks that the generated code within optimizations keep the same behavior 
with
+// O0 to keep consistent ABI.
 // CHECK-O1: define{{.*}}_Z3usev(
-// CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M13exported_funcv(
+// CHECK-O1: declare{{.*}}_ZW1M13exported_funcv(
 // CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M18always_inline_funcv(
-// CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M17non_exported_funcv(
-// CHECK-O1: define{{.*}}available_externally{{.*}}_Z11func_in_gmfv(
+// CHECK-O1-NOT: func_in_gmf
 // CHECK-O1-NOT: func_in_gmf_not_called
+// CHECK-O1-NOT: non_exported_func
 // CHECK-O1-NOT: non_exported_func_not_called
 // CHECK-O1-NOT: func_not_called
diff --git a/clang/test/CodeGenCXX/partitions.cpp 
b/clang/test/CodeGenCXX/partitions.cpp
index 865af5f161eff11..b58e88fafdc6b15 100644
--- a/clang/test/CodeGenCXX/partitions.cpp
+++ b/clang/test/CodeGenCXX/partitions.cpp
@@ -39,6 +39,7 @@ export int use() {
   return foo() + bar() + a + b;
 }
 
+// FIXME: The definition of the variables shouldn't be exported too.
 // CHECK: @_ZW3mod1a = available_externally global
 // CHECK: @_ZW3mod1b = available_externally global
 // CHECK: declare{{.*}} i32 @_ZW3mod3foov
@@ -46,5 +47,5 @@ export int use() {
 
 // CHECK-OPT: @_ZW3mod1a = available_externally global
 // CHECK-OPT: @_ZW3mod1b = available_externally global
-// CHECK-OPT: define available_externally{{.*}} i32 @_ZW3mod3foov
-// CHECK-OPT: define available_externally{{.*}} i32 @_ZW3mod3barv
+// CHECK-OPT: declare{{.*}} i32 @_ZW3mod3foov
+// CHECK-OPT: declare{{.*}} i32 @_ZW3mod3barv
diff --git a/clang/test/Modules/cxx20-importing-function-bodies.cppm 
b/clang/test/Modules/cxx20-importing-function-bodies.cppm
new file mode 100644
index 000..f1b8f9a8f0c9118
--- /dev/null
+++ b/clang/test/Modules/cxx20-importing-function-bodies.cppm
@@ -0,0 +1,72 

[clang] [C++20] [Modules] Don't import function bodies from other module units even with optimizations (PR #71031)

2023-11-07 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/71031

>From 82173f3556d40fc1c6e106820ad281b928a2c7fe Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Thu, 2 Nov 2023 15:19:58 +0800
Subject: [PATCH] [C++20] [Modules] Don't import function bodies from other
 module units even with optimizations

Close https://github.com/llvm/llvm-project/issues/60996.

Previously, clang will try to import function bodies from other module
units to get more optimization oppotunities as much as possible. Then
the motivation becomes the direct cause of the above issue.

However, according to the discussion in SG15, the behavior of importing
function bodies from other module units breaks the ABI compatibility. It
is unwanted. So the original behavior of clang is incorrect. This patch
choose to not import function bodies from other module units in all
cases to follow the expectation.

Note that the desired optimized BMI idea is discarded too. Since it will
still break the ABI compatibility after we import function bodies
seperately.

The release note will be added seperately.

There is a similar issue for variable definitions. I'll try to handle
that in a different commit.
---
 clang/lib/CodeGen/CodeGenModule.cpp   |  9 +++
 .../CodeGenCXX/module-funcs-from-imports.cppm | 10 +--
 clang/test/CodeGenCXX/partitions.cpp  |  5 +-
 .../cxx20-importing-function-bodies.cppm  | 72 +++
 clang/test/Modules/no-import-func-body.cppm   |  4 +-
 5 files changed, 91 insertions(+), 9 deletions(-)
 create mode 100644 clang/test/Modules/cxx20-importing-function-bodies.cppm

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index f72101799d31e4c..2e96fff808113ba 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3851,10 +3851,19 @@ CodeGenModule::isTriviallyRecursive(const FunctionDecl 
*FD) {
 bool CodeGenModule::shouldEmitFunction(GlobalDecl GD) {
   if (getFunctionLinkage(GD) != llvm::Function::AvailableExternallyLinkage)
 return true;
+
   const auto *F = cast(GD.getDecl());
   if (CodeGenOpts.OptimizationLevel == 0 && !F->hasAttr())
 return false;
 
+  // We don't import function bodies from other named module units since that
+  // behavior may break ABI compatibility of the current unit.
+  if (const Module *M = F->getOwningModule();
+  M && M->isModulePurview() &&
+  getContext().getCurrentNamedModule() != M->getTopLevelModule() &&
+  !F->hasAttr())
+return false;
+
   if (F->hasAttr())
 return false;
 
diff --git a/clang/test/CodeGenCXX/module-funcs-from-imports.cppm 
b/clang/test/CodeGenCXX/module-funcs-from-imports.cppm
index 3b415bd9c457291..33cdf437110a9e8 100644
--- a/clang/test/CodeGenCXX/module-funcs-from-imports.cppm
+++ b/clang/test/CodeGenCXX/module-funcs-from-imports.cppm
@@ -64,13 +64,13 @@ int use() {
 // CHECK-O0-NOT: non_exported_func_not_called
 // CHECK-O0-NOT: func_not_called
 
-// Checks that all the potentially called function in the importees are 
generated in the importer's code
-// with available_externally attribute.
+// Checks that the generated code within optimizations keep the same behavior 
with
+// O0 to keep consistent ABI.
 // CHECK-O1: define{{.*}}_Z3usev(
-// CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M13exported_funcv(
+// CHECK-O1: declare{{.*}}_ZW1M13exported_funcv(
 // CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M18always_inline_funcv(
-// CHECK-O1: define{{.*}}available_externally{{.*}}_ZW1M17non_exported_funcv(
-// CHECK-O1: define{{.*}}available_externally{{.*}}_Z11func_in_gmfv(
+// CHECK-O1-NOT: func_in_gmf
 // CHECK-O1-NOT: func_in_gmf_not_called
+// CHECK-O1-NOT: non_exported_func
 // CHECK-O1-NOT: non_exported_func_not_called
 // CHECK-O1-NOT: func_not_called
diff --git a/clang/test/CodeGenCXX/partitions.cpp 
b/clang/test/CodeGenCXX/partitions.cpp
index 865af5f161eff11..b58e88fafdc6b15 100644
--- a/clang/test/CodeGenCXX/partitions.cpp
+++ b/clang/test/CodeGenCXX/partitions.cpp
@@ -39,6 +39,7 @@ export int use() {
   return foo() + bar() + a + b;
 }
 
+// FIXME: The definition of the variables shouldn't be exported too.
 // CHECK: @_ZW3mod1a = available_externally global
 // CHECK: @_ZW3mod1b = available_externally global
 // CHECK: declare{{.*}} i32 @_ZW3mod3foov
@@ -46,5 +47,5 @@ export int use() {
 
 // CHECK-OPT: @_ZW3mod1a = available_externally global
 // CHECK-OPT: @_ZW3mod1b = available_externally global
-// CHECK-OPT: define available_externally{{.*}} i32 @_ZW3mod3foov
-// CHECK-OPT: define available_externally{{.*}} i32 @_ZW3mod3barv
+// CHECK-OPT: declare{{.*}} i32 @_ZW3mod3foov
+// CHECK-OPT: declare{{.*}} i32 @_ZW3mod3barv
diff --git a/clang/test/Modules/cxx20-importing-function-bodies.cppm 
b/clang/test/Modules/cxx20-importing-function-bodies.cppm
new file mode 100644
index 000..f1b8f9a8f0c9118
--- /dev/null
+++ b/clang/test/Modules/cxx20-importing-function-bodies.cppm
@@ -0,0 

[clang] [C++20] [Modules] Don't import function bodies from other module units even with optimizations (PR #71031)

2023-11-07 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 closed 
https://github.com/llvm/llvm-project/pull/71031
___
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 import function bodies from other module units even with optimizations (PR #71031)

2023-11-07 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Sorry for being too hurry here. 

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


[llvm] [clang] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-07 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/71014

>From c69205d54e1a4858211b5bbce69e10bba7063359 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Thu, 2 Nov 2023 11:11:59 +0800
Subject: [PATCH] [Coroutines] Introduce
 [[clang::coro_only_destroy_when_complete]]

Close https://github.com/llvm/llvm-project/issues/56980.

This patch tries to introduce a light-weight optimizer for coroutines
which are guaranteed to only be destroyed afer it reached the final
suspend.

The rationale behind the patch is simple. See the example:

```C++
A foo() {
  dtor d;
  co_await something();
  dtor d1;
  co_await something();
  dtor d2;
  co_return 43;
}
```

Generally the generated .destroy function may be:

```C++
void foo.destroy(foo.Frame *frame) {
  switch(frame->suspend_index()) {
case 1:
  frame->d.~dtor();
  break;
case 2:
  frame->d.~dtor();
  frame->d1.~dtor();
  break;
case 3:
  frame->d.~dtor();
  frame->d1.~dtor();
  frame->d2.~dtor();
  break;
default: // coroutine completed or haven't started
  break;
  }

  frame->promise.~promise_type();
  delete frame;
}
```

Since the compiler need to be ready for all the cases that the coroutine
may be destroyed in a valid state.

However, from the user's perspective, we can understand that certain
coroutine types may only be destroyed after it reached to the final
suspend point. And we need a method to teach the compiler about this.
Then this is the patch. After the compiler recognized that the
coroutines can only be destroyed after complete, it can optimize the
above example to:

```C++
void foo.destroy(foo.Frame *frame) {
  frame->promise.~promise_type();
  delete frame;
}
```

I spent a lot of time experimenting and experiencing this in the
downstream. The numbers are really good. In a real-world coroutine-heavy
workload, the size of the build dir (including .o files) reduces 14%. And
the size of final libraries (excluding the .o files) reduces 8% in Debug
mode and 1% in Release mode.
---
 clang/docs/ReleaseNotes.rst   |   3 +
 clang/include/clang/Basic/Attr.td |  12 ++
 clang/include/clang/Basic/AttrDocs.td |  66 +
 clang/lib/CodeGen/CGCoroutine.cpp |   4 +
 .../coro-only-destroy-when-complete.cpp   |  59 
 ...a-attribute-supported-attributes-list.test |   1 +
 llvm/docs/Coroutines.rst  |  11 ++
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |   1 +
 llvm/include/llvm/IR/Attributes.td|   3 +
 llvm/include/llvm/IR/Function.h   |   7 +
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp |   2 +
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp |   2 +
 llvm/lib/Transforms/Coroutines/CoroSplit.cpp  |  21 ++-
 llvm/lib/Transforms/Utils/CodeExtractor.cpp   |   1 +
 .../Coroutines/coro-only-destroy-when-done.ll | 137 ++
 15 files changed, 323 insertions(+), 7 deletions(-)
 create mode 100644 
clang/test/CodeGenCoroutines/coro-only-destroy-when-complete.cpp
 create mode 100644 
llvm/test/Transforms/Coroutines/coro-only-destroy-when-done.ll

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8bac599f88503af..7a131cb520aa600 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,9 @@ Attribute Changes in Clang
   is ignored, changed from the former incorrect suggestion to move it past
   declaration specifiers. (`#58637 
`_)
 
+- Clang now introduced ``[[clang::coro_only_destroy_when_complete]]`` attribute
+  to reduce the size of the destroy functions for coroutines which are known to
+  be destroyed after having reached the final suspend point.
 
 Improvements to Clang's diagnostics
 ---
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 60b54c155e5..31434565becaec6 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1082,6 +1082,18 @@ def CFConsumed : InheritableParamAttr {
   let Documentation = [RetainBehaviorDocs];
 }
 
+
+// coro_only_destroy_when_complete indicates the coroutines whose return type
+// is marked by coro_only_destroy_when_complete can only be destroyed when the
+// coroutine completes. Then the space for the destroy functions can be saved.
+def CoroOnlyDestroyWhenComplete : InheritableAttr {
+  let Spellings = [Clang<"coro_only_destroy_when_complete">];
+  let Subjects = SubjectList<[CXXRecord]>;
+  let LangOpts = [CPlusPlus];
+  let Documentation = [CoroOnlyDestroyWhenCompleteDocs];
+  let SimpleHandler = 1;
+}
+
 // OSObject-based attributes.
 def OSConsumed : InheritableParamAttr {
   let Spellings = [Clang<"os_consumed">];
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 05703df2129f612..fa6f6acd0c30e88 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/incl

[llvm] [clang] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-07 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> There is substantial inconsistency between "coro only destroy when complete" 
> and "... when done" throughout the PR (in various forms; e.g. literal 
> strings, snake_case, CamelCase, ALL_CAPS as well as file names).
> 
> Presumably there should only be one spelling everywhere.

Done

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


[llvm] [clang] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-07 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

@bcardosolopes @apolloww @rjmccall would you like to take a look for the middle 
end part?

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


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

2023-11-07 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> It was suggested to avoid "thin" and "fat" terminology (I started using it 
> with LTO as a precedent for the terms), but I suppose something more 
> descriptive could be selected.

Any suggestions? My english is not good, you know.

> I'll also note that my prior usage was in reference to embedding transitive 
> BMI references in the BMI, not about including function definitions.

May you elaborate on this? I don't understand since I feel they are unrelated. 
Are you saying: https://github.com/llvm/llvm-project/issues/62707? I feel they 
are orthogonal.

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] Bring Decls Hash to BMI for C++20 Module units (PR #71627)

2023-11-07 Thread Chuanqi Xu via cfe-commits

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


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

2023-11-08 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

The term `sparse` makes me wondering its format is not efficiency.. And for the 
term `surface`, ..., it may beyond my knowledge,  I feel it is odd but I can't 
give a concrete reason.

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] Bring Decls Hash to BMI for C++20 Module units (PR #71627)

2023-11-08 Thread Chuanqi Xu via cfe-commits

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


[clang] [C++20] [Modules] Bring Decls Hash to BMI for C++20 Module units (PR #71627)

2023-11-08 Thread Chuanqi Xu via cfe-commits

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


[clang] [C++20] [Modules] Bring Decls Hash to BMI for C++20 Module units (PR #71627)

2023-11-08 Thread Chuanqi Xu via cfe-commits

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


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

2023-11-08 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Let's discuss the higher level problems in 
https://discourse.llvm.org/t/rfc-c-20-modules-introduce-thin-bmi-and-decls-hash/74755

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] Bring Decls Hash to BMI for C++20 Module units (PR #71627)

2023-11-08 Thread Chuanqi Xu via cfe-commits

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


[clang] [C++20] [Modules] Bring Decls Hash to BMI for C++20 Module units (PR #71627)

2023-11-08 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Let's discuss the higher level problems in Let's discuss the higher level 
problems in 
https://discourse.llvm.org/t/rfc-c-20-modules-introduce-thin-bmi-and-decls-hash/74755.
 Especially this one is not good to review since we don't support stacked 
review now.

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


[clang] [llvm] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-08 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
+// RUN: -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
+// RUN: -O3 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O
+
+#include "Inputs/coroutine.h"
+
+using namespace std;
+
+struct A;
+struct A_promise_type {
+  A get_return_object();
+  suspend_always initial_suspend();
+  suspend_always final_suspend() noexcept;
+  void return_value(int);
+  void unhandled_exception();
+
+  std::coroutine_handle<> handle;
+};
+
+struct Awaitable{
+  bool await_ready();
+  int await_resume();
+  template 
+  void await_suspend(F);
+};
+Awaitable something();
+
+struct dtor {
+dtor();
+~dtor();
+};
+
+struct [[clang::coro_only_destroy_when_complete]] A {

ChuanqiXu9 wrote:

> Since the attribute is on the return type, would that mean it would apply to 
> any coroutine returning the particular type?

Yes.

> Say user is using some library implementation (i.e. folly::coro::Task), they 
> would not be able to use the attribute because it would mark all the 
> coroutines this way.

Yes. My thought is that such attribute can only be applied if the programmers 
understand the behavior of the coroutines very well. So that the users of the 
attribute should be the library writers instead of end users.

And for `folly::coro::Task`, (I didn't check it actively), it can't use the 
attribute if I remember correctly since its framework supports cancelling, that 
said, a task can be cancelled before being complete.

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


[llvm] [clang] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-08 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
+// RUN: -disable-llvm-passes -emit-llvm %s -o - | FileCheck %s
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
+// RUN: -O3 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK-O
+
+#include "Inputs/coroutine.h"
+
+using namespace std;
+
+struct A;
+struct A_promise_type {
+  A get_return_object();
+  suspend_always initial_suspend();
+  suspend_always final_suspend() noexcept;
+  void return_value(int);
+  void unhandled_exception();
+
+  std::coroutine_handle<> handle;
+};
+
+struct Awaitable{
+  bool await_ready();
+  int await_resume();
+  template 
+  void await_suspend(F);
+};
+Awaitable something();
+
+struct dtor {
+dtor();
+~dtor();
+};
+
+struct [[clang::coro_only_destroy_when_complete]] A {

ChuanqiXu9 wrote:

BTW, while it is technically possible to give finer grained marks, I don't 
think it is good. Since the behaviors of coroutines are controlled by the 
framework, in another word, the library writers. And it is not good for the end 
users to predict the behaviors.

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


[clang] [llvm] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-08 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> > > Presumably there should only be one spelling everywhere.
> > 
> > 
> > Done
> 
> Missed a few. ;-)

Sorry and thanks for the detailed comment!

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


[clang] [llvm] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-08 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/71014

>From 4531d8b95ecaf08e672939a49fa18415851d136e Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Thu, 2 Nov 2023 11:11:59 +0800
Subject: [PATCH] [Coroutines] Introduce
 [[clang::coro_only_destroy_when_complete]]

Close https://github.com/llvm/llvm-project/issues/56980.

This patch tries to introduce a light-weight optimizer for coroutines
which are guaranteed to only be destroyed afer it reached the final
suspend.

The rationale behind the patch is simple. See the example:

```C++
A foo() {
  dtor d;
  co_await something();
  dtor d1;
  co_await something();
  dtor d2;
  co_return 43;
}
```

Generally the generated .destroy function may be:

```C++
void foo.destroy(foo.Frame *frame) {
  switch(frame->suspend_index()) {
case 1:
  frame->d.~dtor();
  break;
case 2:
  frame->d.~dtor();
  frame->d1.~dtor();
  break;
case 3:
  frame->d.~dtor();
  frame->d1.~dtor();
  frame->d2.~dtor();
  break;
default: // coroutine completed or haven't started
  break;
  }

  frame->promise.~promise_type();
  delete frame;
}
```

Since the compiler need to be ready for all the cases that the coroutine
may be destroyed in a valid state.

However, from the user's perspective, we can understand that certain
coroutine types may only be destroyed after it reached to the final
suspend point. And we need a method to teach the compiler about this.
Then this is the patch. After the compiler recognized that the
coroutines can only be destroyed after complete, it can optimize the
above example to:

```C++
void foo.destroy(foo.Frame *frame) {
  frame->promise.~promise_type();
  delete frame;
}
```

I spent a lot of time experimenting and experiencing this in the
downstream. The numbers are really good. In a real-world coroutine-heavy
workload, the size of the build dir (including .o files) reduces 14%. And
the size of final libraries (excluding the .o files) reduces 8% in Debug
mode and 1% in Release mode.
---
 clang/docs/ReleaseNotes.rst   |   3 +
 clang/include/clang/Basic/Attr.td |  12 ++
 clang/include/clang/Basic/AttrDocs.td |  66 +
 clang/lib/CodeGen/CGCoroutine.cpp |   4 +
 .../coro-only-destroy-when-complete.cpp   |  59 
 ...a-attribute-supported-attributes-list.test |   1 +
 llvm/docs/Coroutines.rst  |  11 ++
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |   1 +
 llvm/include/llvm/IR/Attributes.td|   3 +
 llvm/include/llvm/IR/Function.h   |   7 +
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp |   2 +
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp |   2 +
 llvm/lib/Transforms/Coroutines/CoroSplit.cpp  |  21 ++-
 llvm/lib/Transforms/Utils/CodeExtractor.cpp   |   1 +
 .../coro-only-destroy-when-complete.ll| 137 ++
 15 files changed, 323 insertions(+), 7 deletions(-)
 create mode 100644 
clang/test/CodeGenCoroutines/coro-only-destroy-when-complete.cpp
 create mode 100644 
llvm/test/Transforms/Coroutines/coro-only-destroy-when-complete.ll

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8bac599f88503af..7a131cb520aa600 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,9 @@ Attribute Changes in Clang
   is ignored, changed from the former incorrect suggestion to move it past
   declaration specifiers. (`#58637 
`_)
 
+- Clang now introduced ``[[clang::coro_only_destroy_when_complete]]`` attribute
+  to reduce the size of the destroy functions for coroutines which are known to
+  be destroyed after having reached the final suspend point.
 
 Improvements to Clang's diagnostics
 ---
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 60b54c155e5..31434565becaec6 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1082,6 +1082,18 @@ def CFConsumed : InheritableParamAttr {
   let Documentation = [RetainBehaviorDocs];
 }
 
+
+// coro_only_destroy_when_complete indicates the coroutines whose return type
+// is marked by coro_only_destroy_when_complete can only be destroyed when the
+// coroutine completes. Then the space for the destroy functions can be saved.
+def CoroOnlyDestroyWhenComplete : InheritableAttr {
+  let Spellings = [Clang<"coro_only_destroy_when_complete">];
+  let Subjects = SubjectList<[CXXRecord]>;
+  let LangOpts = [CPlusPlus];
+  let Documentation = [CoroOnlyDestroyWhenCompleteDocs];
+  let SimpleHandler = 1;
+}
+
 // OSObject-based attributes.
 def OSConsumed : InheritableParamAttr {
   let Spellings = [Clang<"os_consumed">];
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 05703df2129f612..fa6f6acd0c30e88 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/

[llvm] [clang] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-08 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/71014

>From 4531d8b95ecaf08e672939a49fa18415851d136e Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Thu, 2 Nov 2023 11:11:59 +0800
Subject: [PATCH 1/2] [Coroutines] Introduce
 [[clang::coro_only_destroy_when_complete]]

Close https://github.com/llvm/llvm-project/issues/56980.

This patch tries to introduce a light-weight optimizer for coroutines
which are guaranteed to only be destroyed afer it reached the final
suspend.

The rationale behind the patch is simple. See the example:

```C++
A foo() {
  dtor d;
  co_await something();
  dtor d1;
  co_await something();
  dtor d2;
  co_return 43;
}
```

Generally the generated .destroy function may be:

```C++
void foo.destroy(foo.Frame *frame) {
  switch(frame->suspend_index()) {
case 1:
  frame->d.~dtor();
  break;
case 2:
  frame->d.~dtor();
  frame->d1.~dtor();
  break;
case 3:
  frame->d.~dtor();
  frame->d1.~dtor();
  frame->d2.~dtor();
  break;
default: // coroutine completed or haven't started
  break;
  }

  frame->promise.~promise_type();
  delete frame;
}
```

Since the compiler need to be ready for all the cases that the coroutine
may be destroyed in a valid state.

However, from the user's perspective, we can understand that certain
coroutine types may only be destroyed after it reached to the final
suspend point. And we need a method to teach the compiler about this.
Then this is the patch. After the compiler recognized that the
coroutines can only be destroyed after complete, it can optimize the
above example to:

```C++
void foo.destroy(foo.Frame *frame) {
  frame->promise.~promise_type();
  delete frame;
}
```

I spent a lot of time experimenting and experiencing this in the
downstream. The numbers are really good. In a real-world coroutine-heavy
workload, the size of the build dir (including .o files) reduces 14%. And
the size of final libraries (excluding the .o files) reduces 8% in Debug
mode and 1% in Release mode.
---
 clang/docs/ReleaseNotes.rst   |   3 +
 clang/include/clang/Basic/Attr.td |  12 ++
 clang/include/clang/Basic/AttrDocs.td |  66 +
 clang/lib/CodeGen/CGCoroutine.cpp |   4 +
 .../coro-only-destroy-when-complete.cpp   |  59 
 ...a-attribute-supported-attributes-list.test |   1 +
 llvm/docs/Coroutines.rst  |  11 ++
 llvm/include/llvm/Bitcode/LLVMBitCodes.h  |   1 +
 llvm/include/llvm/IR/Attributes.td|   3 +
 llvm/include/llvm/IR/Function.h   |   7 +
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp |   2 +
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp |   2 +
 llvm/lib/Transforms/Coroutines/CoroSplit.cpp  |  21 ++-
 llvm/lib/Transforms/Utils/CodeExtractor.cpp   |   1 +
 .../coro-only-destroy-when-complete.ll| 137 ++
 15 files changed, 323 insertions(+), 7 deletions(-)
 create mode 100644 
clang/test/CodeGenCoroutines/coro-only-destroy-when-complete.cpp
 create mode 100644 
llvm/test/Transforms/Coroutines/coro-only-destroy-when-complete.ll

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8bac599f88503af..7a131cb520aa600 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -296,6 +296,9 @@ Attribute Changes in Clang
   is ignored, changed from the former incorrect suggestion to move it past
   declaration specifiers. (`#58637 
`_)
 
+- Clang now introduced ``[[clang::coro_only_destroy_when_complete]]`` attribute
+  to reduce the size of the destroy functions for coroutines which are known to
+  be destroyed after having reached the final suspend point.
 
 Improvements to Clang's diagnostics
 ---
diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 60b54c155e5..31434565becaec6 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1082,6 +1082,18 @@ def CFConsumed : InheritableParamAttr {
   let Documentation = [RetainBehaviorDocs];
 }
 
+
+// coro_only_destroy_when_complete indicates the coroutines whose return type
+// is marked by coro_only_destroy_when_complete can only be destroyed when the
+// coroutine completes. Then the space for the destroy functions can be saved.
+def CoroOnlyDestroyWhenComplete : InheritableAttr {
+  let Spellings = [Clang<"coro_only_destroy_when_complete">];
+  let Subjects = SubjectList<[CXXRecord]>;
+  let LangOpts = [CPlusPlus];
+  let Documentation = [CoroOnlyDestroyWhenCompleteDocs];
+  let SimpleHandler = 1;
+}
+
 // OSObject-based attributes.
 def OSConsumed : InheritableParamAttr {
   let Spellings = [Clang<"os_consumed">];
diff --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index 05703df2129f612..fa6f6acd0c30e88 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/cl

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

2023-11-08 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

This is a little bit far from what I imaged.

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

The first thing is in my TODO too. But my consideration is more about 
efficiency. Currently, the one phase compilation model (I found the term 
`phase` may be ambiguous in the context) used by cmake is actually compile the 
module source file to a BMI and compile the BMI to an object file.

```
x.cppm -> x.pcm -> x.o
```

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.

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.

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

> 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. Also this should be part of thin BMI.

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] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-08 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Thanks for reviewing this!

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


[clang] [llvm] [Coroutines] Introduce [[clang::coro_only_destroy_when_complete]] (PR #71014)

2023-11-08 Thread Chuanqi Xu via cfe-commits

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


[clang] 427f13b - [NFC] [C++20] [Modules] Remove 'ModuleInterface' bit in Sema::ModuleScope

2023-11-08 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-11-09T15:20:32+08:00
New Revision: 427f13bd724d332681ca5adb2455b7241af7177d

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

LOG: [NFC] [C++20] [Modules] Remove 'ModuleInterface' bit in Sema::ModuleScope

The 'ModuleInterface' in Sema::ModuleScope is confusing. It actually
means 'not implementation'. This patch removes that bit and extract the
information from the recorded clang::Module.

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 a8c41492b61ac4c..fe8b387f198c56e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2303,7 +2303,6 @@ class Sema final {
   struct ModuleScope {
 SourceLocation BeginLoc;
 clang::Module *Module = nullptr;
-bool ModuleInterface = false;
 VisibleModuleSet OuterVisibleModules;
   };
   /// The modules we're currently parsing.
@@ -2367,9 +2366,11 @@ 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;
+  /// Is the module scope we are an implementation unit?
+  bool currentModuleIsImplementation() const {
+return ModuleScopes.empty()
+   ? false
+   : ModuleScopes.back().Module->isModuleImplementation();
   }
 
   /// Is the module scope we are in a C++ Header Unit?

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 8a296837e2a192c..99b4d7d0fe40ee3 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -125,7 +125,6 @@ void Sema::HandleStartOfHeaderUnit() {
   ModuleScopes.push_back({}); // No GMF
   ModuleScopes.back().BeginLoc = StartOfTU;
   ModuleScopes.back().Module = Mod;
-  ModuleScopes.back().ModuleInterface = true;
   VisibleModules.setVisible(Mod, StartOfTU);
 
   // From now on, we have an owning module for all declarations we see.
@@ -375,7 +374,6 @@ Sema::ActOnModuleDecl(SourceLocation StartLoc, 
SourceLocation ModuleLoc,
   // Switch from the global module fragment (if any) to the named module.
   ModuleScopes.back().BeginLoc = StartLoc;
   ModuleScopes.back().Module = Mod;
-  ModuleScopes.back().ModuleInterface = MDK != ModuleDeclKind::Implementation;
   VisibleModules.setVisible(Mod, ModuleLoc);
 
   // From now on, we have an owning module for all declarations we see.
@@ -470,7 +468,6 @@ Sema::ActOnPrivateModuleFragmentDecl(SourceLocation 
ModuleLoc,
   ModuleScopes.push_back({});
   ModuleScopes.back().BeginLoc = ModuleLoc;
   ModuleScopes.back().Module = PrivateModuleFragment;
-  ModuleScopes.back().ModuleInterface = true;
   VisibleModules.setVisible(PrivateModuleFragment, ModuleLoc);
 
   // All declarations created from now on are scoped to the private module
@@ -523,7 +520,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
   if (getLangOpts().CPlusPlusModules && isCurrentModulePurview() &&
   getCurrentModule()->Name == ModuleName) {
 Diag(ImportLoc, diag::err_module_self_import_cxx20)
-<< ModuleName << !ModuleScopes.back().ModuleInterface;
+<< ModuleName << currentModuleIsImplementation();
 return true;
   }
 
@@ -609,10 +606,7 @@ DeclResult Sema::ActOnModuleImport(SourceLocation StartLoc,
   Mod->Kind == Module::ModuleKind::ModulePartitionImplementation) {
 Diag(ExportLoc, diag::err_export_partition_impl)
 << SourceRange(ExportLoc, Path.back().second);
-  } else if (!ModuleScopes.empty() &&
- (ModuleScopes.back().ModuleInterface ||
-  (getLangOpts().CPlusPlusModules &&
-   ModuleScopes.back().Module->isGlobalModule( {
+  } else if (!ModuleScopes.empty() && !currentModuleIsImplementation()) {
 // 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.
@@ -772,7 +766,7 @@ Decl *Sema::ActOnStartExportDecl(Scope *S, SourceLocation 
ExportLoc,
 Diag(ExportLoc, diag::err_export_not_in_module_interface) << 0;
 D->setInvalidDecl();
 return D;
-  } else if (!ModuleScopes.back().ModuleInterface) {
+  } else if (currentModuleIsImplementation()) {
 Diag(ExportLoc, diag::err_export_not_in_module_interface) << 1;
 Diag(ModuleScopes.back().BeginLoc,
  diag::note_not_module_interface_add_export)
@@ -932,7 +926,6 @@ Module *Sema::PushGlobalModuleFragment(SourceLocation 
BeginLoc) {
 
   // Enter the scope of the global module.
   ModuleScopes.push_back({BeginL

[clang] [clang] Refactor `IdentifierInfo::ObjcOrBuiltinID` (PR #71709)

2023-11-08 Thread Chuanqi Xu via cfe-commits


@@ -86,19 +87,26 @@ enum { IdentifierInfoAlignment = 8 };
 static constexpr int ObjCOrBuiltinIDBits = 16;
 
 /// The "layout" of ObjCOrBuiltinID is:
-///  - The first value (0) represents "not a special identifier".
-///  - The next (NUM_OBJC_KEYWORDS - 1) values represent ObjCKeywordKinds (not
-///including objc_not_keyword).
-///  - The next (NUM_INTERESTING_IDENTIFIERS - 1) values represent
-///InterestingIdentifierKinds (not including not_interesting).
-///  - The rest of the values represent builtin IDs (not including NotBuiltin).
-static constexpr int FirstObjCKeywordID = 1;
-static constexpr int LastObjCKeywordID =
-FirstObjCKeywordID + tok::NUM_OBJC_KEYWORDS - 2;
-static constexpr int FirstInterestingIdentifierID = LastObjCKeywordID + 1;
-static constexpr int LastInterestingIdentifierID =
-FirstInterestingIdentifierID + tok::NUM_INTERESTING_IDENTIFIERS - 2;
-static constexpr int FirstBuiltinID = LastInterestingIdentifierID + 1;
+///  - ObjCKeywordKind enumerators
+///  - InterestingIdentifierKind enumerators
+///  - Builtin::ID enumerators
+///  - NonSpecialIdentifier
+enum class ObjCKeywordOrInterestingOrBuiltin {
+#define OBJC_AT_KEYWORD(X) objc_##X,
+#include "clang/Basic/TokenKinds.def"
+  NUM_OBJC_KEYWORDS,

ChuanqiXu9 wrote:

It looks like we have `tok::NUM_OBJC_KEYWORDS` and 
`ObjCKeywordOrInterestingOrBuiltin::NUM_OBJC_KEYWORDS` now. And it smells not 
good to have them with the same name.

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


[clang] [clang] Refactor `IdentifierInfo::ObjcOrBuiltinID` (PR #71709)

2023-11-08 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Oh, I didn't look into the identifier's system before. I took a while to look 
at the patch but I failed to understand it and I failed to find the 
relationships between this patch and header units... 

https://github.com/llvm/llvm-project/pull/71709
___
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 Chuanqi Xu via cfe-commits

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

Got it. The we can be more focused.

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

It is not about multiplex AST consumer. It is about WrappedASTConsumer. It is 
designed for plugins. Also it is a private member function of FrontendAction, 
the base of frontend actions. I think we should perform new behaviors in 
sub-actions. It looks not good to perform semantical analysis in 
FrontendAction...

Concretely, I think we need to do this in CodeGenAction.

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

Then it implies that we need to discard a bunch of existing codes handling 
`.cppm`. Otherwise we'll have two mechanisms.

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

Agreed in the higher level. But that requires us to implement at least new AST 
writers.

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

I mean it should be successors of 
https://github.com/llvm/llvm-project/pull/71622. Concretely, now we reduce the 
function definition in 
https://github.com/llvm/llvm-project/pull/71622/files#diff-125f472e690aa3d973bc42aa3c5d580226c5c47661551aca2889f960681aa64dR321.



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 Chuanqi Xu via cfe-commits

ChuanqiXu9 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?

The difference is about the efficiency and the interfaces doesn't change a lot. 
Previously, in the one phase compilation mode, what clang did actually is:

```
x.cppm -> x.pcm -> x.o
```

That said we compile `x.o` from `x.pcm`. There is a reading BMI process. The 
goal of the patch is to remove the reading process.

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] 0f7aaeb - [C++20] [Modules] Allow export from language linkage

2023-11-09 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-11-09T17:44:41+08:00
New Revision: 0f7aaeb3241c3803489a45753190e82dbc7fd5fa

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

LOG: [C++20] [Modules] Allow export from language linkage

Close https://github.com/llvm/llvm-project/issues/71347

Previously I misread the concept of module purview. I thought if a
declaration attached to a unnamed module, it can't be part of the module
purview. But after the issue report, I recognized that module purview is
more of a concept about locations instead of semantics.

Concretely, the things in the language linkage after module declarations
can be exported.

This patch refactors `Module::isModulePurview()` and introduces some
possible code cleanups.

Added: 


Modified: 
clang/include/clang/Basic/Module.h
clang/include/clang/Lex/ModuleMap.h
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTWriter.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/Decl.cpp
clang/lib/AST/DeclBase.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Frontend/ASTUnit.cpp
clang/lib/Lex/ModuleMap.cpp
clang/lib/Sema/Sema.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaLookup.cpp
clang/lib/Sema/SemaModule.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/test/Modules/export-language-linkage.cppm
clang/test/SemaCXX/modules.cppm

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index 239eb5a637f3ecf..08b153e8c1c9d33 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -178,9 +178,8 @@ class alignas(8) Module {
   /// eventually be exposed, for use in "private" modules.
   std::string ExportAsModule;
 
-  /// Does this Module scope describe part of the purview of a standard named
-  /// C++ module?
-  bool isModulePurview() const {
+  /// Does this Module is a named module of a standard named module?
+  bool isNamedModule() const {
 switch (Kind) {
 case ModuleInterfaceUnit:
 case ModuleImplementationUnit:

diff  --git a/clang/include/clang/Lex/ModuleMap.h 
b/clang/include/clang/Lex/ModuleMap.h
index d5824713970ea7b..32e7e8f899e502c 100644
--- a/clang/include/clang/Lex/ModuleMap.h
+++ b/clang/include/clang/Lex/ModuleMap.h
@@ -556,8 +556,8 @@ class ModuleMap {
   /// parent.
   Module *createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
   Module *Parent = nullptr);
-  Module *createImplicitGlobalModuleFragmentForModuleUnit(
-  SourceLocation Loc, bool IsExported, Module *Parent = nullptr);
+  Module *createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
+  Module *Parent);
 
   /// Create a global module fragment for a C++ module interface unit.
   Module *createPrivateModuleFragmentForInterfaceUnit(Module *Parent,

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index fe8b387f198c56e..63d548c30da7f6e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2317,14 +2317,9 @@ class Sema final {
   clang::Module *TheGlobalModuleFragment = nullptr;
 
   /// The implicit global module fragments of the current translation unit.
-  /// We would only create at most two implicit global module fragments to
-  /// avoid performance penalties when there are many language linkage
-  /// exports.
   ///
-  /// The contents in the implicit global module fragment can't be discarded
-  /// no matter if it is exported or not.
+  /// The contents in the implicit global module fragment can't be discarded.
   clang::Module *TheImplicitGlobalModuleFragment = nullptr;
-  clang::Module *TheExportedImplicitGlobalModuleFragment = nullptr;
 
   /// Namespace definitions that we will export when they finish.
   llvm::SmallPtrSet DeferredExportedNamespaces;
@@ -2336,9 +2331,7 @@ class Sema final {
 
   /// Helper function to judge if we are in module purview.
   /// Return false if we are not in a module.
-  bool isCurrentModulePurview() const {
-return getCurrentModule() ? getCurrentModule()->isModulePurview() : false;
-  }
+  bool isCurrentModulePurview() const;
 
   /// Enter the scope of the explicit global module fragment.
   Module *PushGlobalModuleFragment(SourceLocation BeginLoc);
@@ -2346,8 +2339,7 @@ class Sema final {
   void PopGlobalModuleFragment();
 
   /// Enter the scope of an implicit global module fragment.
-  Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc,
-   bool IsExported);
+  Module *PushImplicitGlobalModuleFragment(SourceLocation BeginLoc);
   /// Leave the scope of an implicit

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

2023-11-09 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

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

Agreed. This is what I want too.

> 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. The new way skipped the part of jobs we did 
in drivers for `.cppm`. Then this is the divergence that I am concerning too.

---
 
In my mind, the proper solution is to introduce a new frontend action that 
combines GenerateModuleInterfaceAction and CodeGenAction. 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.


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] 0e7b30f - [C++20] [Modules] Enhance better diagnostic for implicit global module and module partitions

2023-11-09 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-11-10T10:58:07+08:00
New Revision: 0e7b30fa821dd4899227aa643030f4e4164f4e56

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

LOG: [C++20] [Modules] Enhance better diagnostic for implicit global module and 
module partitions

Due to an oversight, when users use an unexported declaration from
implicit global module, the diagnostic will show "please #include"
instead of "please import". This patch corrects the behavior.

Also previously, when users use an unexported declarations from module
partitions, the diagnostic message will always show the partition name
no matter if that partition name is visible to the users. Now the users
may only see the partition name if the users are in the same module with
the partition unit.

Added: 


Modified: 
clang/lib/Sema/SemaLookup.cpp
clang/test/CXX/module/module.import/p2.cpp
clang/test/CXX/module/module.reach/ex1.cpp
clang/test/CXX/module/module.reach/p2.cpp
clang/test/Modules/export-language-linkage.cppm

Removed: 




diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index be011b9f4368d2c..54b48f7ab80eb9c 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -5723,7 +5723,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, 
const NamedDecl *Decl,
   llvm::SmallVector UniqueModules;
   llvm::SmallDenseSet UniqueModuleSet;
   for (auto *M : Modules) {
-if (M->isGlobalModule() || M->isPrivateModule())
+if (M->isExplicitGlobalModule() || M->isPrivateModule())
   continue;
 if (UniqueModuleSet.insert(M).second)
   UniqueModules.push_back(M);
@@ -5755,6 +5755,28 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, 
const NamedDecl *Decl,
 
   Modules = UniqueModules;
 
+  auto GetModuleNameForDiagnostic = [this](const Module *M) -> std::string {
+if (M->isModuleMapModule())
+  return M->getFullModuleName();
+
+Module *CurrentModule = getCurrentModule();
+
+if (M->isImplicitGlobalModule())
+  M = M->getTopLevelModule();
+
+bool IsInTheSameModule =
+CurrentModule && CurrentModule->getPrimaryModuleInterfaceName() ==
+ M->getPrimaryModuleInterfaceName();
+
+// If the current module unit is in the same module with M, it is OK to 
show
+// the partition name. Otherwise, it'll be sufficient to show the primary
+// module name.
+if (IsInTheSameModule)
+  return M->getTopLevelModuleName().str();
+else
+  return M->getPrimaryModuleInterfaceName().str();
+  };
+
   if (Modules.size() > 1) {
 std::string ModuleList;
 unsigned N = 0;
@@ -5764,7 +5786,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, 
const NamedDecl *Decl,
 ModuleList += "[...]";
 break;
   }
-  ModuleList += M->getFullModuleName();
+  ModuleList += GetModuleNameForDiagnostic(M);
 }
 
 Diag(UseLoc, diag::err_module_unimported_use_multiple)
@@ -5772,7 +5794,7 @@ void Sema::diagnoseMissingImport(SourceLocation UseLoc, 
const NamedDecl *Decl,
   } else {
 // FIXME: Add a FixItHint that imports the corresponding module.
 Diag(UseLoc, diag::err_module_unimported_use)
-  << (int)MIK << Decl << Modules[0]->getFullModuleName();
+<< (int)MIK << Decl << GetModuleNameForDiagnostic(Modules[0]);
   }
 
   NotePrevious();

diff  --git a/clang/test/CXX/module/module.import/p2.cpp 
b/clang/test/CXX/module/module.import/p2.cpp
index 0c02d253f3a898f..ef6006811e77631 100644
--- a/clang/test/CXX/module/module.import/p2.cpp
+++ b/clang/test/CXX/module/module.import/p2.cpp
@@ -23,8 +23,8 @@ export A f();
 //--- Use.cpp
 import M;
 void test() {
-  A a; // expected-error {{declaration of 'A' must be imported from module 
'M:impl'}}
-   // expected-error@-1 {{definition of 'A' must be imported from module 
'M:impl'}} expected-error@-1 {{}}
+  A a; // expected-error {{definition of 'A' must be imported from module 'M' 
before it is required}}
+   // expected-error@-1 {{definition of 'A' must be imported from module 
'M' before it is required}} expected-error@-1 {{}}
// expected-n...@impl.cppm:2 {{declaration here is not visible}}
// expected-n...@impl.cppm:2 {{definition here is not reachable}} 
expected-n...@impl.cppm:2 {{}}
 }
@@ -41,8 +41,8 @@ void test() {
 export module B;
 import M;
 void test() {
-  A a; // expected-error {{declaration of 'A' must be imported from module 
'M:impl'}}
-   // expected-error@-1 {{definition of 'A' must be imported from module 
'M:impl'}} expected-error@-1 {{}}
+  A a; // expected-error {{declaration of 'A' must be imported from module 
'M'}}
+   // expected-error@-1 {{definition of 'A' must be imported from module 
'M'}} expected-error@-1 {{}}
//

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

2023-11-09 Thread Chuanqi Xu via cfe-commits

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

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

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 Chuanqi Xu via cfe-commits

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

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


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 Chuanqi Xu via cfe-commits

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

We've already known that we don't have a good API to discard part of the AST 
from the experience in implementing discarding decls in GMF. Then we'd have to 
control it in the AST Writers.

> 
> > > > > 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 ?

No, it can be an action and we can control the usage of the BMI.



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-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-11-13 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

@sam-mccall ping~

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


[clang] [C++20] [Modules] Enable -fmodules-embed-all-files by default for named modules (PR #74419)

2023-12-04 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 created 
https://github.com/llvm/llvm-project/pull/74419

Close https://github.com/llvm/llvm-project/issues/72383

It looks incorrect or odd for the BMIs to dependent on the real files. It 
prevents we moving the BMIs and the distributed builds. And it looks like there 
is nothing beneficial we got by not enabling this. Also the cost is relatively 
small. See the discussion in the above issue for details.

>From b28f94d795582ef13e6fe8ce111c9638f4ed7f30 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Tue, 5 Dec 2023 14:24:10 +0800
Subject: [PATCH] [C++20] [Modules] Enable -fmodules-embed-all-files by default
 for named modules

---
 clang/include/clang/Driver/Types.h|  3 +++
 clang/lib/Driver/ToolChains/Clang.cpp |  7 ++
 clang/lib/Driver/Types.cpp|  4 
 .../test/Driver/modules-embed-all-files.cppm  | 22 +++
 .../Serialization/ForceCheckFileInputTest.cpp |  2 ++
 5 files changed, 38 insertions(+)
 create mode 100644 clang/test/Driver/modules-embed-all-files.cppm

diff --git a/clang/include/clang/Driver/Types.h 
b/clang/include/clang/Driver/Types.h
index 121b58a6b477d..53340bdc64f70 100644
--- a/clang/include/clang/Driver/Types.h
+++ b/clang/include/clang/Driver/Types.h
@@ -80,6 +80,9 @@ namespace types {
   /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers).
   bool isCXX(ID Id);
 
+  /// isCXXModuleUnit - Is this a "C++ module unit" input.
+  bool isCXXModuleUnit(ID Id);
+
   /// Is this LLVM IR.
   bool isLLVMIR(ID Id);
 
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index f02f7c841b91f..9081258626eaa 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3817,6 +3817,13 @@ static bool RenderModulesOptions(Compilation &C, const 
Driver &D,
 Args.ClaimAllArgs(options::OPT_fmodules_disable_diagnostic_validation);
   }
 
+  // '-fmodules-embed-all-files' should be enabled by default for C++20 named
+  // modules.
+  // See the discussion in https://github.com/llvm/llvm-project/issues/72383.
+  if (types::isCXXModuleUnit(Input.getType()) && HaveModules) {
+CmdArgs.push_back("-fmodules-embed-all-files");
+  }
+
   // Claim `-fmodule-output` and `-fmodule-output=` to avoid unused warnings.
   Args.ClaimAllArgs(options::OPT_fmodule_output);
   Args.ClaimAllArgs(options::OPT_fmodule_output_EQ);
diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index 08df34ade7b65..52e5d9748d375 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -249,6 +249,10 @@ bool types::isCXX(ID Id) {
   }
 }
 
+bool types::isCXXModuleUnit(ID Id) {
+  return Id == TY_CXXModule || Id == TY_PP_CXXModule;
+}
+
 bool types::isLLVMIR(ID Id) {
   switch (Id) {
   default:
diff --git a/clang/test/Driver/modules-embed-all-files.cppm 
b/clang/test/Driver/modules-embed-all-files.cppm
new file mode 100644
index 0..86a4389fb4319
--- /dev/null
+++ b/clang/test/Driver/modules-embed-all-files.cppm
@@ -0,0 +1,22 @@
+// Tests that we'll enable -fmodules-embed-all-files for C++20 module units.
+
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang %t/a.cppm -### 2>&1 | FileCheck %t/a.cppm --check-prefix=PRE20
+// RUN: %clang -std=c++20 %t/a.cppm -### 2>&1 | FileCheck %t/a.cppm
+
+// RUN: %clang %t/a.cpp -### 2>&1 | FileCheck %t/a.cpp 
--check-prefix=NO-CXX-MODULE
+// RUN: %clang -std=c++20 %t/a.cpp -### 2>&1 | FileCheck %t/a.cpp 
--check-prefix=NO-CXX-MODULE
+// RUN: %clang -std=c++20 -x c++-module %t/a.cpp -### 2>&1 | FileCheck %t/a.cpp
+
+//--- a.cppm
+
+// PRE20-NOT: -fmodules-embed-all-files
+// CHECK: -fmodules-embed-all-files
+
+//--- a.cpp
+
+// NO-CXX-MODULE-NOT: -fmodules-embed-all-files
+// CHECK: -fmodules-embed-all-files
diff --git a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp 
b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
index ed0daa43436eb..eeb77914107cd 100644
--- a/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
+++ b/clang/unittests/Serialization/ForceCheckFileInputTest.cpp
@@ -76,6 +76,7 @@ export int aa = 43;
 createInvocation(Args, CIOpts);
 EXPECT_TRUE(Invocation);
 Invocation->getFrontendOpts().DisableFree = false;
+Invocation->getFrontendOpts().ModulesEmbedAllFiles = false;
 
 auto Buf = CIOpts.VFS->getBufferForFile("a.cppm");
 EXPECT_TRUE(Buf);
@@ -115,6 +116,7 @@ export int aa = 43;
 createInvocation(Args, CIOpts);
 EXPECT_TRUE(Invocation);
 Invocation->getFrontendOpts().DisableFree = false;
+Invocation->getFrontendOpts().ModulesEmbedAllFiles = false;
 
 CompilerInstance Clang;
 

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


[clang] [C++20] [Modules] Enable -fmodules-embed-all-files by default for named modules (PR #74419)

2023-12-04 Thread Chuanqi Xu via cfe-commits

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


[clang] b768b39 - [C++20] [Modules] Skip Writing diagnostic options, header search paths and pragma diagnostic mappings

2023-12-07 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-12-07T16:54:00+08:00
New Revision: b768b393429419d27e3f76518842136bac9d5b25

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

LOG: [C++20] [Modules] Skip Writing diagnostic options, header search paths and 
pragma diagnostic mappings

It simply wastes of space and time to write diagnostic options, header
search paths and pragma diagnostic mappings for C++20 Named modules.
This patch tries to avoid the unnecessary writings.

Added: 


Modified: 
clang/include/clang/Frontend/FrontendActions.h
clang/lib/Frontend/FrontendActions.cpp

Removed: 




diff  --git a/clang/include/clang/Frontend/FrontendActions.h 
b/clang/include/clang/Frontend/FrontendActions.h
index 3940e00eeb8db..fcce31ac0590f 100644
--- a/clang/include/clang/Frontend/FrontendActions.h
+++ b/clang/include/clang/Frontend/FrontendActions.h
@@ -151,6 +151,9 @@ class GenerateModuleInterfaceAction : public 
GenerateModuleAction {
 private:
   bool BeginSourceFileAction(CompilerInstance &CI) override;
 
+  std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+
   std::unique_ptr
   CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
 };

diff  --git a/clang/lib/Frontend/FrontendActions.cpp 
b/clang/lib/Frontend/FrontendActions.cpp
index 2afcf1cf9f68c..c1d6e71455365 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -258,6 +258,16 @@ bool GenerateModuleInterfaceAction::BeginSourceFileAction(
   return GenerateModuleAction::BeginSourceFileAction(CI);
 }
 
+std::unique_ptr
+GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+  CI.getHeaderSearchOpts().ModulesSkipDiagnosticOptions = true;
+  CI.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true;
+  CI.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = true;
+
+  return GenerateModuleAction::CreateASTConsumer(CI, InFile);
+}
+
 std::unique_ptr
 GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
 StringRef InFile) {



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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-12-10 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

@sam-mccall ping!

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


[clang] 9406ea3 - [NFC] [Serialization] Packing more bits

2023-12-10 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-12-11T10:18:12+08:00
New Revision: 9406ea3fe32e59a7d28de0dcbd0317b4cdfa4c62

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

LOG: [NFC] [Serialization] Packing more bits

This patch tries to reduce the size of the BMIs by packing more bits
into an unsigned integer.

Added: 


Modified: 
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/test/Modules/decl-params-determinisim.m

Removed: 




diff  --git a/clang/lib/Serialization/ASTReaderDecl.cpp 
b/clang/lib/Serialization/ASTReaderDecl.cpp
index bc16cfc67a24f9..7140a14aefbf9b 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -583,6 +583,9 @@ void ASTDeclReader::Visit(Decl *D) {
 }
 
 void ASTDeclReader::VisitDecl(Decl *D) {
+  BitsUnpacker DeclBits(Record.readInt());
+  bool HasStandaloneLexicalDC = DeclBits.getNextBit();
+
   if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
   isa(D)) {
 // We don't want to deserialize the DeclContext of a template
@@ -592,7 +595,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
 // return type of the function).  Use the translation unit DeclContext as a
 // placeholder.
 GlobalDeclID SemaDCIDForTemplateParmDecl = readDeclID();
-GlobalDeclID LexicalDCIDForTemplateParmDecl = readDeclID();
+GlobalDeclID LexicalDCIDForTemplateParmDecl =
+HasStandaloneLexicalDC ? readDeclID() : 0;
 if (!LexicalDCIDForTemplateParmDecl)
   LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl;
 Reader.addPendingDeclContextInfo(D,
@@ -601,7 +605,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
 D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
   } else {
 auto *SemaDC = readDeclAs();
-auto *LexicalDC = readDeclAs();
+auto *LexicalDC =
+HasStandaloneLexicalDC ? readDeclAs() : nullptr;
 if (!LexicalDC)
   LexicalDC = SemaDC;
 // If the context is a class, we might not have actually merged it yet, in
@@ -618,7 +623,6 @@ void ASTDeclReader::VisitDecl(Decl *D) {
   }
   D->setLocation(ThisDeclLoc);
 
-  BitsUnpacker DeclBits(Record.readInt());
   D->InvalidDecl = DeclBits.getNextBit();
   bool HasAttrs = DeclBits.getNextBit();
   D->setImplicit(DeclBits.getNextBit());
@@ -765,7 +769,7 @@ ASTDeclReader::RedeclarableResult 
ASTDeclReader::VisitTagDecl(TagDecl *TD) {
   TD->setCompleteDefinitionRequired(TagDeclBits.getNextBit());
   TD->setBraceRange(readSourceRange());
 
-  switch (Record.readInt()) {
+  switch (TagDeclBits.getNextBits(/*Width=*/2)) {
   case 0:
 break;
   case 1: { // ExtInfo
@@ -1089,7 +1093,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
   FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3));
 
   FD->EndRangeLoc = readSourceLocation();
-  FD->setDefaultLoc(readSourceLocation());
+  if (FD->isExplicitlyDefaulted())
+FD->setDefaultLoc(readSourceLocation());
 
   FD->ODRHash = Record.readInt();
   FD->setHasODRHash(true);
@@ -1703,7 +1708,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
   unsigned isObjCMethodParam = ParmVarDeclBits.getNextBit();
   unsigned scopeDepth = ParmVarDeclBits.getNextBits(/*Width=*/7);
   unsigned scopeIndex = ParmVarDeclBits.getNextBits(/*Width=*/8);
-  unsigned declQualifier = Record.readInt();
+  unsigned declQualifier = ParmVarDeclBits.getNextBits(/*Width=*/7);
   if (isObjCMethodParam) {
 assert(scopeDepth == 0);
 PD->setObjCMethodScopeInfo(scopeIndex);
@@ -1716,7 +1721,9 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
   PD->ParmVarDeclBits.HasInheritedDefaultArg = ParmVarDeclBits.getNextBit();
   if (ParmVarDeclBits.getNextBit()) // hasUninstantiatedDefaultArg.
 PD->setUninstantiatedDefaultArg(Record.readExpr());
-  PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation();
+
+  if (ParmVarDeclBits.getNextBit()) // Valid explicit object parameter
+PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation();
 
   // FIXME: If this is a redeclaration of a function from another module, 
handle
   // inheritance of default arguments.

diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index d7d0c0e5bb21b4..865322ec0782cd 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -108,7 +108,7 @@ namespace clang {
 
 /// The number of record fields required for the Expr class
 /// itself.
-static const unsigned NumExprFields = NumStmtFields + 4;
+static const unsigned NumExprFields = NumStmtFields + 2;
 
 /// Read and init

[clang] 8c33462 - Revert "[NFC] [Serialization] Packing more bits"

2023-12-10 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-12-11T14:06:32+08:00
New Revision: 8c334627818437180176b16b1932b2a26372d8ae

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

LOG: Revert "[NFC] [Serialization] Packing more bits"

This reverts commit 9406ea3fe32e59a7d28de0dcbd0317b4cdfa4c62.

There are build bots complaining this. Revert it first to try to keep
the bots green.

Added: 


Modified: 
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/test/Modules/decl-params-determinisim.m

Removed: 




diff  --git a/clang/lib/Serialization/ASTReaderDecl.cpp 
b/clang/lib/Serialization/ASTReaderDecl.cpp
index 7140a14aefbf9b..bc16cfc67a24f9 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -583,9 +583,6 @@ void ASTDeclReader::Visit(Decl *D) {
 }
 
 void ASTDeclReader::VisitDecl(Decl *D) {
-  BitsUnpacker DeclBits(Record.readInt());
-  bool HasStandaloneLexicalDC = DeclBits.getNextBit();
-
   if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
   isa(D)) {
 // We don't want to deserialize the DeclContext of a template
@@ -595,8 +592,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
 // return type of the function).  Use the translation unit DeclContext as a
 // placeholder.
 GlobalDeclID SemaDCIDForTemplateParmDecl = readDeclID();
-GlobalDeclID LexicalDCIDForTemplateParmDecl =
-HasStandaloneLexicalDC ? readDeclID() : 0;
+GlobalDeclID LexicalDCIDForTemplateParmDecl = readDeclID();
 if (!LexicalDCIDForTemplateParmDecl)
   LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl;
 Reader.addPendingDeclContextInfo(D,
@@ -605,8 +601,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
 D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
   } else {
 auto *SemaDC = readDeclAs();
-auto *LexicalDC =
-HasStandaloneLexicalDC ? readDeclAs() : nullptr;
+auto *LexicalDC = readDeclAs();
 if (!LexicalDC)
   LexicalDC = SemaDC;
 // If the context is a class, we might not have actually merged it yet, in
@@ -623,6 +618,7 @@ void ASTDeclReader::VisitDecl(Decl *D) {
   }
   D->setLocation(ThisDeclLoc);
 
+  BitsUnpacker DeclBits(Record.readInt());
   D->InvalidDecl = DeclBits.getNextBit();
   bool HasAttrs = DeclBits.getNextBit();
   D->setImplicit(DeclBits.getNextBit());
@@ -769,7 +765,7 @@ ASTDeclReader::RedeclarableResult 
ASTDeclReader::VisitTagDecl(TagDecl *TD) {
   TD->setCompleteDefinitionRequired(TagDeclBits.getNextBit());
   TD->setBraceRange(readSourceRange());
 
-  switch (TagDeclBits.getNextBits(/*Width=*/2)) {
+  switch (Record.readInt()) {
   case 0:
 break;
   case 1: { // ExtInfo
@@ -1093,8 +1089,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
   FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3));
 
   FD->EndRangeLoc = readSourceLocation();
-  if (FD->isExplicitlyDefaulted())
-FD->setDefaultLoc(readSourceLocation());
+  FD->setDefaultLoc(readSourceLocation());
 
   FD->ODRHash = Record.readInt();
   FD->setHasODRHash(true);
@@ -1708,7 +1703,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
   unsigned isObjCMethodParam = ParmVarDeclBits.getNextBit();
   unsigned scopeDepth = ParmVarDeclBits.getNextBits(/*Width=*/7);
   unsigned scopeIndex = ParmVarDeclBits.getNextBits(/*Width=*/8);
-  unsigned declQualifier = ParmVarDeclBits.getNextBits(/*Width=*/7);
+  unsigned declQualifier = Record.readInt();
   if (isObjCMethodParam) {
 assert(scopeDepth == 0);
 PD->setObjCMethodScopeInfo(scopeIndex);
@@ -1721,9 +1716,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
   PD->ParmVarDeclBits.HasInheritedDefaultArg = ParmVarDeclBits.getNextBit();
   if (ParmVarDeclBits.getNextBit()) // hasUninstantiatedDefaultArg.
 PD->setUninstantiatedDefaultArg(Record.readExpr());
-
-  if (ParmVarDeclBits.getNextBit()) // Valid explicit object parameter
-PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation();
+  PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation();
 
   // FIXME: If this is a redeclaration of a function from another module, 
handle
   // inheritance of default arguments.

diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index 865322ec0782cd..d7d0c0e5bb21b4 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -108,7 +108,7 @@ namespace clang {
 
 /// The number of record fields required for the Expr class
 /// itself.
-static const unsigned NumExprFields = NumStmtFields + 2;
+static const unsig

[clang] 9a46518 - Revert "[clang] Remove unused variable 'ExprDependenceBits' in ASTWriterDecl.cpp (NFC)"

2023-12-10 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-12-11T14:15:16+08:00
New Revision: 9a46518630869e7fcb495e72378abdbedf68d40d

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

LOG: Revert "[clang] Remove unused variable 'ExprDependenceBits' in 
ASTWriterDecl.cpp (NFC)"

This reverts commit 10951050b5f371eb3e7cacce1691c4eb2fe2eab5.
This should be part of 8c334627818437180176b16b1932 to revert
9406ea3fe32e59a7d2 completely.

Added: 


Modified: 
clang/lib/Serialization/ASTWriterDecl.cpp

Removed: 




diff  --git a/clang/lib/Serialization/ASTWriterDecl.cpp 
b/clang/lib/Serialization/ASTWriterDecl.cpp
index a6fc41fdb4ce4d..bf082e5b8eac61 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -2346,6 +2346,7 @@ void ASTWriter::WriteDeclAbbrevs() {
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));
   DeclCXXMethodAbbrev = Stream.EmitAbbrev(std::move(Abv));
 
+  unsigned ExprDependenceBits = llvm::BitWidth;
   // Abbreviation for EXPR_DECL_REF
   Abv = std::make_shared();
   Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF));



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


[clang] 65b12a8 - Recommit [NFC] [Serialization] Packing more bits

2023-12-11 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-12-11T16:47:51+08:00
New Revision: 65b12a8af37ffa390ff45c8215904513eb75659e

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

LOG: Recommit [NFC] [Serialization] Packing more bits

This patch tries to reduce the size of the BMIs by packing more bits
into an unsigned integer.

This patch was reverted due to buildbot failure report. But it should be
irrevelent after I took a double look. So I tried to recommit this NFC
change again.

Added: 


Modified: 
clang/include/clang/Serialization/ASTReader.h
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/test/Modules/decl-params-determinisim.m

Removed: 




diff  --git a/clang/include/clang/Serialization/ASTReader.h 
b/clang/include/clang/Serialization/ASTReader.h
index 7eefdca6815cda..9bb89ec9410911 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -2415,12 +2415,7 @@ class BitsUnpacker {
   BitsUnpacker(BitsUnpacker &&) = delete;
   BitsUnpacker operator=(const BitsUnpacker &) = delete;
   BitsUnpacker operator=(BitsUnpacker &&) = delete;
-  ~BitsUnpacker() {
-#ifndef NDEBUG
-while (isValid())
-  assert(!getNextBit() && "There are unprocessed bits!");
-#endif
-  }
+  ~BitsUnpacker() = default;
 
   void updateValue(uint32_t V) {
 Value = V;

diff  --git a/clang/lib/Serialization/ASTReaderDecl.cpp 
b/clang/lib/Serialization/ASTReaderDecl.cpp
index bc16cfc67a24f9..7140a14aefbf9b 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -583,6 +583,9 @@ void ASTDeclReader::Visit(Decl *D) {
 }
 
 void ASTDeclReader::VisitDecl(Decl *D) {
+  BitsUnpacker DeclBits(Record.readInt());
+  bool HasStandaloneLexicalDC = DeclBits.getNextBit();
+
   if (D->isTemplateParameter() || D->isTemplateParameterPack() ||
   isa(D)) {
 // We don't want to deserialize the DeclContext of a template
@@ -592,7 +595,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
 // return type of the function).  Use the translation unit DeclContext as a
 // placeholder.
 GlobalDeclID SemaDCIDForTemplateParmDecl = readDeclID();
-GlobalDeclID LexicalDCIDForTemplateParmDecl = readDeclID();
+GlobalDeclID LexicalDCIDForTemplateParmDecl =
+HasStandaloneLexicalDC ? readDeclID() : 0;
 if (!LexicalDCIDForTemplateParmDecl)
   LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl;
 Reader.addPendingDeclContextInfo(D,
@@ -601,7 +605,8 @@ void ASTDeclReader::VisitDecl(Decl *D) {
 D->setDeclContext(Reader.getContext().getTranslationUnitDecl());
   } else {
 auto *SemaDC = readDeclAs();
-auto *LexicalDC = readDeclAs();
+auto *LexicalDC =
+HasStandaloneLexicalDC ? readDeclAs() : nullptr;
 if (!LexicalDC)
   LexicalDC = SemaDC;
 // If the context is a class, we might not have actually merged it yet, in
@@ -618,7 +623,6 @@ void ASTDeclReader::VisitDecl(Decl *D) {
   }
   D->setLocation(ThisDeclLoc);
 
-  BitsUnpacker DeclBits(Record.readInt());
   D->InvalidDecl = DeclBits.getNextBit();
   bool HasAttrs = DeclBits.getNextBit();
   D->setImplicit(DeclBits.getNextBit());
@@ -765,7 +769,7 @@ ASTDeclReader::RedeclarableResult 
ASTDeclReader::VisitTagDecl(TagDecl *TD) {
   TD->setCompleteDefinitionRequired(TagDeclBits.getNextBit());
   TD->setBraceRange(readSourceRange());
 
-  switch (Record.readInt()) {
+  switch (TagDeclBits.getNextBits(/*Width=*/2)) {
   case 0:
 break;
   case 1: { // ExtInfo
@@ -1089,7 +1093,8 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
   FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3));
 
   FD->EndRangeLoc = readSourceLocation();
-  FD->setDefaultLoc(readSourceLocation());
+  if (FD->isExplicitlyDefaulted())
+FD->setDefaultLoc(readSourceLocation());
 
   FD->ODRHash = Record.readInt();
   FD->setHasODRHash(true);
@@ -1703,7 +1708,7 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
   unsigned isObjCMethodParam = ParmVarDeclBits.getNextBit();
   unsigned scopeDepth = ParmVarDeclBits.getNextBits(/*Width=*/7);
   unsigned scopeIndex = ParmVarDeclBits.getNextBits(/*Width=*/8);
-  unsigned declQualifier = Record.readInt();
+  unsigned declQualifier = ParmVarDeclBits.getNextBits(/*Width=*/7);
   if (isObjCMethodParam) {
 assert(scopeDepth == 0);
 PD->setObjCMethodScopeInfo(scopeIndex);
@@ -1716,7 +1721,9 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) {
   PD->ParmVarDeclBits.HasInheritedDefaultArg = ParmVarDeclBits.getNextBit();
   if (ParmVarDeclBits.getNextBit()) // hasUninstantiatedDefaultArg.
 PD->setUninstantiatedDe

[clang] 2ce9a79 - [Serialization] Use packed bits to initialize UserDefinedLiteral

2023-12-11 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-12-11T18:24:09+08:00
New Revision: 2ce9a799f950678cef844706ecb55a483d3c225b

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

LOG: [Serialization] Use packed bits to initialize UserDefinedLiteral

UserDefinedLiteral is also a sub class of CallExpr but we forgot to
initialize it in the same way as other sub classes of CallExpr.

Added: 


Modified: 
clang/lib/Serialization/ASTReaderStmt.cpp

Removed: 




diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index d9eedb2e1089fb..b3a6f619372b4a 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -3851,11 +3851,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
   S = new (Context) BuiltinBitCastExpr(Empty);
   break;
 
-case EXPR_USER_DEFINED_LITERAL:
-  S = UserDefinedLiteral::CreateEmpty(
-  Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields],
-  /*HasFPFeatures=*/Record[ASTStmtReader::NumExprFields + 1], Empty);
+case EXPR_USER_DEFINED_LITERAL: {
+  BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields]);
+  auto NumArgs = CallExprBits.getNextBits(/*Width=*/16);
+  auto HasFPFeatures = CallExprBits.getNextBit();
+  S = UserDefinedLiteral::CreateEmpty(Context, NumArgs, HasFPFeatures,
+  Empty);
   break;
+}
 
 case EXPR_CXX_STD_INITIALIZER_LIST:
   S = new (Context) CXXStdInitializerListExpr(Empty);



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


[clang] [clang] Make `-fvisibility={}` and `-ftype-visibility={}` benign options. (PR #71985)

2023-11-14 Thread Chuanqi Xu via cfe-commits

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

LGTM. Thanks.

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


[clang] [coroutines] Introduce [[clang::coro_return_type]] and [[clang::coro_wrapper]] (PR #71945)

2023-11-15 Thread Chuanqi Xu via cfe-commits


@@ -11591,6 +11591,10 @@ def err_conflicting_aligned_options : Error <
 def err_coro_invalid_addr_of_label : Error<
   "the GNU address of label extension is not allowed in coroutines."
 >;
+def err_coroutine_return_type : Error<

ChuanqiXu9 wrote:

The intention of `[[clang::coro_return_type]]`  (and ` 
[[clang::coro_wrapper]]`) is to allow analyzer to recognize coroutines from the 
function signature. And if the users are able to downgrade the erros to a 
silent warning, then result of analyzing is basically out of order. Then 
`[[clang::coro_return_type]]`  is basically meaningless.

On the other hand, from the perspective of library writers, if we announce a 
class as `[[clang::coro_return_type]]` , we will assume it is an error if the 
users don't use it for a coroutine.

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


[clang] Fix crash with modules and constexpr destructor (PR #69076)

2023-11-15 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

The key point now is the rationale why this change relates to modules. It looks 
not good to proceed without understanding this. Otherwise we're playing with a 
black box... And the concrete method, ..., well, I guess we had no choice but 
debugging it hardly. For example, comparing the behavior of clang with and 
without the change.

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


[clang] [coroutines] Introduce [[clang::coro_return_type]] and [[clang::coro_wrapper]] (PR #71945)

2023-11-15 Thread Chuanqi Xu via cfe-commits


@@ -7482,3 +7482,54 @@ generation of the other destruction cases, optimizing 
the above `foo.destroy` to
 
   }];
 }
+
+
+def CoroReturnTypeAndWrapperDoc : Documentation {
+  let Category = DocCatDecl;
+  let Content = [{
+The ``coro_return_type`` attribute should be marked on a C++ class to mark it 
as

ChuanqiXu9 wrote:

```suggestion
The `[[clang::coro_return_type]]` attribute is used to help static analyzers to 
recognize coroutines from the function signatures.

The ``coro_return_type`` attribute should be marked on a C++ class to mark it as
```

I'll feel better if I can see the motivation in the very beginning.

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


[clang] [coroutines] Introduce [[clang::coro_return_type]] and [[clang::coro_wrapper]] (PR #71945)

2023-11-15 Thread Chuanqi Xu via cfe-commits


@@ -300,6 +300,11 @@ Attribute Changes in Clang
   to reduce the size of the destroy functions for coroutines which are known to
   be destroyed after having reached the final suspend point.
 
+- Clang now introduced ``[[clang::coro_return_type]]`` and 
``[[clang::coro_wrapper]]``
+  attributes. A function returning a type marked with 
``[[clang::coro_return_type]]``
+  should be a coroutine. A non-coroutine function marked with 
``[[clang::coro_wrapper]]``
+  is still allowed to return the such a type.

ChuanqiXu9 wrote:

```suggestion
  is still allowed to return the such a type. This is helpful for analyzers to 
recognize coroutines from the function signatures.
```

nit. Not required. But I feel it reads better if I can understand the intention 
here.

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


[clang] [coroutines] Introduce [[clang::coro_return_type]] and [[clang::coro_wrapper]] (PR #71945)

2023-11-15 Thread Chuanqi Xu via cfe-commits


@@ -7482,3 +7482,54 @@ generation of the other destruction cases, optimizing 
the above `foo.destroy` to
 
   }];
 }
+
+
+def CoroReturnTypeAndWrapperDoc : Documentation {
+  let Category = DocCatDecl;
+  let Content = [{
+The ``coro_return_type`` attribute should be marked on a C++ class to mark it 
as
+a **coroutine return type (CRT)**.
+
+A function ``R func(P1, .., PN)`` has a coroutine return type (CRT) ``R`` if 
``R``
+is marked by ``[[clang::coro_return_type]]`` and  ``R`` has a promise type 
associated to it
+(i.e., std​::​coroutine_traits​::​promise_type is a valid 
promise type).
+
+If the return type of a function is a ``CRT`` then the function must be a 
coroutine.
+Otherwise it is invalid. It is allowed for a non-coroutine to return a ``CRT``

ChuanqiXu9 wrote:

```suggestion
Otherwise the program is invalid. It is allowed for a non-coroutine to return a 
``CRT``
```

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


[clang] [coroutines] Introduce [[clang::coro_return_type]] and [[clang::coro_wrapper]] (PR #71945)

2023-11-15 Thread Chuanqi Xu via cfe-commits


@@ -7482,3 +7482,54 @@ generation of the other destruction cases, optimizing 
the above `foo.destroy` to
 
   }];
 }
+
+
+def CoroReturnTypeAndWrapperDoc : Documentation {
+  let Category = DocCatDecl;
+  let Content = [{
+The ``coro_return_type`` attribute should be marked on a C++ class to mark it 
as

ChuanqiXu9 wrote:

```suggestion
The ``[[clang::coro_return_type]]`` attribute should be marked on a C++ class 
to mark it as
```

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


[clang] 10ad98d - [NFC] [C++20] [Modules] Add a test from issue 71484

2023-11-16 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-11-16T16:05:46+08:00
New Revision: 10ad98dc160497699930f295dcb4c998ef561d2e

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

LOG: [NFC] [C++20] [Modules] Add a test from issue 71484

The example from issue report 71484 works fine on trunk. Add the example to the
tests since testing is always good.

Added: 
clang/test/Modules/pr71484.cppm

Modified: 


Removed: 




diff  --git a/clang/test/Modules/pr71484.cppm b/clang/test/Modules/pr71484.cppm
new file mode 100644
index 000..088a4cf9f4e457d
--- /dev/null
+++ b/clang/test/Modules/pr71484.cppm
@@ -0,0 +1,41 @@
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/mod1.cppm -emit-module-interface -o 
%t/mod1.pcm
+// RUN: %clang_cc1 -std=c++20 %t/mod2.cppm -emit-module-interface -o 
%t/mod2.pcm \
+// RUN: -fprebuilt-module-path=%t
+// RUN:  %clang_cc1 -std=c++20 %t/mod3.cppm -fsyntax-only -verify \
+// RUN: -fprebuilt-module-path=%t
+
+// RUN: %clang_cc1 -std=c++20 %t/mod1.cppm -emit-obj -o %t/mod1.o 
-fmodule-output=%t/mod1.pcm
+// RUN: %clang_cc1 -std=c++20 %t/mod2.cppm -emit-obj -o %t/mod2.o 
-fmodule-output=%t/mod2.pcm \
+// RUN: -fprebuilt-module-path=%t
+// RUN:  %clang_cc1 -std=c++20 %t/mod3.cppm -fsyntax-only -verify \
+// RUN: -fprebuilt-module-path=%t
+
+//--- mod1.cppm
+export module mod1;
+
+export template
+T mod1_f(T x) {
+return x;
+}
+
+//--- mod2.cppm
+export module mod2;
+import mod1;
+
+export template
+U mod2_g(U y) {
+return mod1_f(y);
+}
+
+//--- mod3.cppm
+// expected-no-diagnostics
+export module mod3;
+import mod2;
+
+export int mod3_h(int p) {
+return mod2_g(p);
+}



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


[clang] [coroutines] Introduce [[clang::coro_return_type]] and [[clang::coro_wrapper]] (PR #71945)

2023-11-17 Thread Chuanqi Xu via cfe-commits

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

LGTM. Please wait for 3~5 days in case @ilya-biryukov has more comments.

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-11-19 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

@sam-mccall ping

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


[clang] [coroutines] Introduce [[clang::coro_lifetimebound]] (PR #72851)

2023-11-20 Thread Chuanqi Xu via cfe-commits

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


[clang] [coroutines] Introduce [[clang::coro_lifetimebound]] (PR #72851)

2023-11-20 Thread Chuanqi Xu via cfe-commits

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

LGTM. Please wait for few days in case there are other comments.

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


[clang] [coroutines] Introduce [[clang::coro_lifetimebound]] (PR #72851)

2023-11-20 Thread Chuanqi Xu via cfe-commits


@@ -7580,10 +7580,15 @@ static void 
visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call,
   if (ObjectArg && implicitObjectParamIsLifetimeBound(Callee))
 VisitLifetimeBoundArg(Callee, ObjectArg);
 
+  bool checkCoroCall = false;
+  if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
+checkCoroCall |= RD->hasAttr() &&

ChuanqiXu9 wrote:

```suggestion
checkCoroCall = RD->hasAttr() &&
```

nit:

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


[clang] [coroutines] Introduce [[clang::coro_lifetimebound]] (PR #72851)

2023-11-20 Thread Chuanqi Xu via cfe-commits


@@ -7483,7 +7483,6 @@ generation of the other destruction cases, optimizing the 
above `foo.destroy` to
   }];
 }
 
-

ChuanqiXu9 wrote:

nit: unnecessary changes.

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


[clang] [C++20] [Modules] Introduce a tool 'clang-named-modules-querier' and two plugins 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin' (PR #72956)

2023-11-20 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 created 
https://github.com/llvm/llvm-project/pull/72956

This patch introduces a tool 'clang-named-modules-querier' and two plugins 
'ClangGetUsedFilesFromModulesPlugin' and
'ClangGetDeclsInModulesPlugin' to help the build systems to avoid compilations 
in modules.

After building the clang, we should be able to see 
`clang-named-modules-querier` in `bin` directory and 
`ClangGetUsedFilesFromModulesPlugin.so` and
`ClangGetDeclsInModulesPlugin.so` in the `lib` directory.

# clang-named-modules-querier

We can use the tool  `clang-named-modules-querier` to get the informations of 
declarations in a BMI. For example,

```
export module a;

export int a() {
return 43;
}

namespace nn {
export int a(int x, int y) {
return x + y;
}
}

export template 
class Templ {
public:
T get() { return T(43); }
};

export class C {
public:
void member_function() {}
};
```

And let's compile it to the BMI `a.pcm`. Then we can query the information of 
declarations we want:

```
$clang-named-modules-querier a.pcm -- a nn::a Templ::get
[
  {
"a": {
  "Hash": 3379170117,
  "col": 12,
  "kind": "Function",
  "line": 3,
  "source File Name": "/a.cppm"
}
  },
  {
"nn::a": {
  "Hash": 1071306246,
  "col": 16,
  "kind": "Function",
  "line": 20,
  "source File Name": "/a.cppm"
}
  },
  {
"Templ::get": {
  "Hash": 3343854614,
  "col": 7,
  "kind": "CXXMethod",
  "line": 28,
  "source File Name": "/a.cppm"
}
  }
]
```

The unqualified name implies the declarations under the global namespace. This 
is useful with the plugin `ClangGetDeclsInModulesPlugin`, which can get the 
used declarations in modules during the compilation.


# ClangGetDeclsInModulesPlugin

For example,

```
// b.cpp
#include 
import a;

int main() {
std::cout << a() << std::endl;
Templ t;
std::cout << t.get() << std::endl;
}
```

Let's compile it with the plugin:

```
$clang++ -std=c++20 b.cpp -fmodule-file=a=a.pcm -c -o b.o 
-fplugin=/ClangGetDeclsInModulesPlugin.so 
-fplugin-arg-decls_query_from_modules-output=b.json

$ cat b.json

[
  {
"decls": [
  {
"a": {
  "Hash": 3379170117,
  "col": 12,
  "kind": "Function",
  "line": 3,
  "source File Name": 
"/home/chuanqi.xcq/llvm-project-for-work/build/ModulesDatabase/a.cppm"
}
  },
  {
"Templ": {
  "Hash": 222160723,
  "col": 7,
  "kind": "ClassTemplate",
  "line": 26,
  "source File Name": 
"/home/chuanqi.xcq/llvm-project-for-work/build/ModulesDatabase/a.cppm"
}
  },
  {
"Templ::get": {
  "Hash": 3343854614,
  "col": 7,
  "kind": "CXXMethod",
  "line": 28,
  "source File Name": 
"/home/chuanqi.xcq/llvm-project-for-work/build/ModulesDatabase/a.cppm"
}
  }
],
"module": "a"
  }
]
```

 Now we can know that only these declarations from module `a` get used during 
the compilation of `b.cpp`. Then when a.pcm updates and `b.cpp` doesn't change, 
we can use `ClangGetDeclsInModulesPlugin` to query these used declarations in 
`a.pcm`. Then we can skip the compilation of `b.cpp` if all these declarations 
doesn't change.

# ClangGetUsedFilesFromModulesPlugin

In case we're concerning about the cost of hashing many declarations or the 
complexity of implementing it. We can use the more conservative mode: only 
collecting the used files from modules.

We can use the plugin `ClangGetUsedFilesFromModulesPlugin` to collect the used 
files in modules during the compilation.

For example,

## foo and bar example

```
//--- foo.h
inline int foo() {
return 43;
}

//--- bar.h
inline int bar() {
return 43;
}

//--- foo.cppm
module;
#include "foo.h"
#include "bar.h"
export module foo;
export using ::foo;
export using ::bar;

//--- use.cpp
import foo;
int use() {
return bar();
}
```

Then we compile use.cpp with the plugin, we can get:

```
$ clang++ -std=c++20 use.cpp -c -o use.o 
-fplugin=/ClangGetUsedFilesFromModulesPlugin.so  
-fplugin-arg-get_used_files_from_modules-output=used_files 
-fmodule-file=foo=foo.pcm

$ cat used_files
foo.cppm
bar.h
```

Note that `foo.h` is not included since the declarations inside `foo.h` doesn't 
contribute to the compilation of `use.cpp`.
Build systems may use the information to avoid compiling `use.cpp` if only 
`foo.h` changes.

## Hello world Example

```
// Hello.cppm
module;
#include 
export module Hello;

class Hello {
public:
void hello() {
std::cout << "Hello World" << "\n";
std::cout << "Hello " << "\n";
}
};

export void hello() {
Hello h;
h.hello();
h.hello();
}

// Use.cpp
import Hello;
int main() {
hello();
}
```

Let's compile it with:

```
$ clang++ -std=c++20 Use.cpp -c -o Use.o 
-fplugin=/ClangGetUsedFilesFromModulesPlugin.so  
-fplugin-arg-get_used_files_from_modules-output=used_files

[clang] [C++20] [Modules] Introduce a tool 'clang-named-modules-querier' and two plugins 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin' (PR #72956)

2023-11-20 Thread Chuanqi Xu via cfe-commits

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


[clang] [C++20] [Modules] Introduce a tool 'clang-named-modules-querier' and two plugins 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin' (PR #72956)

2023-11-20 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/72956

>From 05453bc0da214ad69ab94d901c997c61fae86ab6 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Fri, 17 Nov 2023 14:57:02 +0800
Subject: [PATCH 1/2] [C++20] [Modules] Introduce a tool
 'clang-named-modules-querier' and two plugins
 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin'

This patch introduces a tool 'clang-named-modules-querier' and two
plugins 'ClangGetUsedFilesFromModulesPlugin' and
'ClangGetDeclsInModulesPlugin' to help the build systems to avoid
compilations in modules.

After building the clang, we should be able to see
`clang-named-modules-querier` in `bin` directory and
`ClangGetUsedFilesFromModulesPlugin.so` and
`ClangGetDeclsInModulesPlugin.so` in the `lib` directory.
---
 clang/include/clang/Serialization/ASTReader.h |   4 +
 clang/lib/Serialization/ASTReader.cpp |  25 +-
 clang/tools/CMakeLists.txt|   2 +-
 .../CMakeLists.txt|  27 +++
 .../ClangNamedModulesQuerier.cpp  | 214 ++
 .../GetDeclsInfoToJson.h  |  48 
 .../GetUsedDeclActionPlugin.cpp   | 169 ++
 .../GetUsedFilesFromModulesPlugin.cpp | 131 +++
 8 files changed, 613 insertions(+), 7 deletions(-)
 create mode 100644 clang/tools/clang-named-modules-querier/CMakeLists.txt
 create mode 100644 
clang/tools/clang-named-modules-querier/ClangNamedModulesQuerier.cpp
 create mode 100644 clang/tools/clang-named-modules-querier/GetDeclsInfoToJson.h
 create mode 100644 
clang/tools/clang-named-modules-querier/GetUsedDeclActionPlugin.cpp
 create mode 100644 
clang/tools/clang-named-modules-querier/GetUsedFilesFromModulesPlugin.cpp

diff --git a/clang/include/clang/Serialization/ASTReader.h 
b/clang/include/clang/Serialization/ASTReader.h
index 7eefdca6815cdad..9f028e59b9445d4 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -1981,6 +1981,10 @@ class ASTReader
   /// lookup table as unmaterialized references.
   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
   DeclarationName Name) override;
+  /// Return false if Name is none and Decl Context doesn't come from the 
reader.
+  bool FindVisibleDeclsByName(const DeclContext *DC, DeclarationName Name,
+  SmallVectorImpl &Decls);
+
 
   /// Read all of the declarations lexically stored in a
   /// declaration context.
diff --git a/clang/lib/Serialization/ASTReader.cpp 
b/clang/lib/Serialization/ASTReader.cpp
index 42b48d230af7a97..141df3beffa0ce8 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7928,11 +7928,9 @@ void ASTReader::FindFileRegionDecls(FileID File,
 Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
 }
 
-bool
-ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
-  DeclarationName Name) {
-  assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() &&
- "DeclContext has no visible decls in storage");
+bool ASTReader::FindVisibleDeclsByName(const DeclContext *DC,
+   DeclarationName Name,
+   SmallVectorImpl &Decls) {
   if (!Name)
 return false;
 
@@ -7943,7 +7941,6 @@ ASTReader::FindExternalVisibleDeclsByName(const 
DeclContext *DC,
   Deserializing LookupResults(this);
 
   // Load the list of declarations.
-  SmallVector Decls;
   llvm::SmallPtrSet Found;
   for (DeclID ID : It->second.Table.find(Name)) {
 NamedDecl *ND = cast(GetDecl(ID));
@@ -7951,6 +7948,22 @@ ASTReader::FindExternalVisibleDeclsByName(const 
DeclContext *DC,
   Decls.push_back(ND);
   }
 
+  return true;
+}
+
+bool
+ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
+  DeclarationName Name) {
+  assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() &&
+ "DeclContext has no visible decls in storage");
+
+  Deserializing LookupResults(this);
+
+  // Load the list of declarations.
+  SmallVector Decls;
+  if (!FindVisibleDeclsByName(DC, Name, Decls))
+return false;
+
   ++NumVisibleDeclContextsRead;
   SetExternalVisibleDeclsForName(DC, Name, Decls);
   return !Decls.empty();
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index f60db6ef0ba3454..d55b79e51dfa0c5 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -17,7 +17,7 @@ if(HAVE_CLANG_REPL_SUPPORT)
 endif()
 
 add_clang_subdirectory(c-index-test)
-
+add_clang_subdirectory(clang-named-modules-querier)
 add_clang_subdirectory(clang-rename)
 add_clang_subdirectory(clang-refactor)
 # For MinGW we only enable shared library if LLVM_LINK_LLVM_DYLIB=ON.
diff --git a/clang/tools/clang-named-modules-querier/CMakeLists.txt 
b/cl

[clang] [C++20] [Modules] Introduce a tool 'clang-named-modules-querier' and two plugins 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin' (PR #72956)

2023-11-20 Thread Chuanqi Xu via cfe-commits

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


[clang] [C++20] [Modules] Introduce a tool 'clang-named-modules-querier' and two plugins 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin' (PR #72956)

2023-11-20 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/72956

>From 05453bc0da214ad69ab94d901c997c61fae86ab6 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Fri, 17 Nov 2023 14:57:02 +0800
Subject: [PATCH 1/2] [C++20] [Modules] Introduce a tool
 'clang-named-modules-querier' and two plugins
 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin'

This patch introduces a tool 'clang-named-modules-querier' and two
plugins 'ClangGetUsedFilesFromModulesPlugin' and
'ClangGetDeclsInModulesPlugin' to help the build systems to avoid
compilations in modules.

After building the clang, we should be able to see
`clang-named-modules-querier` in `bin` directory and
`ClangGetUsedFilesFromModulesPlugin.so` and
`ClangGetDeclsInModulesPlugin.so` in the `lib` directory.
---
 clang/include/clang/Serialization/ASTReader.h |   4 +
 clang/lib/Serialization/ASTReader.cpp |  25 +-
 clang/tools/CMakeLists.txt|   2 +-
 .../CMakeLists.txt|  27 +++
 .../ClangNamedModulesQuerier.cpp  | 214 ++
 .../GetDeclsInfoToJson.h  |  48 
 .../GetUsedDeclActionPlugin.cpp   | 169 ++
 .../GetUsedFilesFromModulesPlugin.cpp | 131 +++
 8 files changed, 613 insertions(+), 7 deletions(-)
 create mode 100644 clang/tools/clang-named-modules-querier/CMakeLists.txt
 create mode 100644 
clang/tools/clang-named-modules-querier/ClangNamedModulesQuerier.cpp
 create mode 100644 clang/tools/clang-named-modules-querier/GetDeclsInfoToJson.h
 create mode 100644 
clang/tools/clang-named-modules-querier/GetUsedDeclActionPlugin.cpp
 create mode 100644 
clang/tools/clang-named-modules-querier/GetUsedFilesFromModulesPlugin.cpp

diff --git a/clang/include/clang/Serialization/ASTReader.h 
b/clang/include/clang/Serialization/ASTReader.h
index 7eefdca6815cdad..9f028e59b9445d4 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -1981,6 +1981,10 @@ class ASTReader
   /// lookup table as unmaterialized references.
   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
   DeclarationName Name) override;
+  /// Return false if Name is none and Decl Context doesn't come from the 
reader.
+  bool FindVisibleDeclsByName(const DeclContext *DC, DeclarationName Name,
+  SmallVectorImpl &Decls);
+
 
   /// Read all of the declarations lexically stored in a
   /// declaration context.
diff --git a/clang/lib/Serialization/ASTReader.cpp 
b/clang/lib/Serialization/ASTReader.cpp
index 42b48d230af7a97..141df3beffa0ce8 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7928,11 +7928,9 @@ void ASTReader::FindFileRegionDecls(FileID File,
 Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
 }
 
-bool
-ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
-  DeclarationName Name) {
-  assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() &&
- "DeclContext has no visible decls in storage");
+bool ASTReader::FindVisibleDeclsByName(const DeclContext *DC,
+   DeclarationName Name,
+   SmallVectorImpl &Decls) {
   if (!Name)
 return false;
 
@@ -7943,7 +7941,6 @@ ASTReader::FindExternalVisibleDeclsByName(const 
DeclContext *DC,
   Deserializing LookupResults(this);
 
   // Load the list of declarations.
-  SmallVector Decls;
   llvm::SmallPtrSet Found;
   for (DeclID ID : It->second.Table.find(Name)) {
 NamedDecl *ND = cast(GetDecl(ID));
@@ -7951,6 +7948,22 @@ ASTReader::FindExternalVisibleDeclsByName(const 
DeclContext *DC,
   Decls.push_back(ND);
   }
 
+  return true;
+}
+
+bool
+ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
+  DeclarationName Name) {
+  assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() &&
+ "DeclContext has no visible decls in storage");
+
+  Deserializing LookupResults(this);
+
+  // Load the list of declarations.
+  SmallVector Decls;
+  if (!FindVisibleDeclsByName(DC, Name, Decls))
+return false;
+
   ++NumVisibleDeclContextsRead;
   SetExternalVisibleDeclsForName(DC, Name, Decls);
   return !Decls.empty();
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index f60db6ef0ba3454..d55b79e51dfa0c5 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -17,7 +17,7 @@ if(HAVE_CLANG_REPL_SUPPORT)
 endif()
 
 add_clang_subdirectory(c-index-test)
-
+add_clang_subdirectory(clang-named-modules-querier)
 add_clang_subdirectory(clang-rename)
 add_clang_subdirectory(clang-refactor)
 # For MinGW we only enable shared library if LLVM_LINK_LLVM_DYLIB=ON.
diff --git a/clang/tools/clang-named-modules-querier/CMakeLists.txt 
b/cl

[clang] [C++20] [Modules] Introduce a tool 'clang-named-modules-querier' and two plugins 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin' (PR #72956)

2023-11-21 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/72956

>From 05453bc0da214ad69ab94d901c997c61fae86ab6 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Fri, 17 Nov 2023 14:57:02 +0800
Subject: [PATCH 1/2] [C++20] [Modules] Introduce a tool
 'clang-named-modules-querier' and two plugins
 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin'

This patch introduces a tool 'clang-named-modules-querier' and two
plugins 'ClangGetUsedFilesFromModulesPlugin' and
'ClangGetDeclsInModulesPlugin' to help the build systems to avoid
compilations in modules.

After building the clang, we should be able to see
`clang-named-modules-querier` in `bin` directory and
`ClangGetUsedFilesFromModulesPlugin.so` and
`ClangGetDeclsInModulesPlugin.so` in the `lib` directory.
---
 clang/include/clang/Serialization/ASTReader.h |   4 +
 clang/lib/Serialization/ASTReader.cpp |  25 +-
 clang/tools/CMakeLists.txt|   2 +-
 .../CMakeLists.txt|  27 +++
 .../ClangNamedModulesQuerier.cpp  | 214 ++
 .../GetDeclsInfoToJson.h  |  48 
 .../GetUsedDeclActionPlugin.cpp   | 169 ++
 .../GetUsedFilesFromModulesPlugin.cpp | 131 +++
 8 files changed, 613 insertions(+), 7 deletions(-)
 create mode 100644 clang/tools/clang-named-modules-querier/CMakeLists.txt
 create mode 100644 
clang/tools/clang-named-modules-querier/ClangNamedModulesQuerier.cpp
 create mode 100644 clang/tools/clang-named-modules-querier/GetDeclsInfoToJson.h
 create mode 100644 
clang/tools/clang-named-modules-querier/GetUsedDeclActionPlugin.cpp
 create mode 100644 
clang/tools/clang-named-modules-querier/GetUsedFilesFromModulesPlugin.cpp

diff --git a/clang/include/clang/Serialization/ASTReader.h 
b/clang/include/clang/Serialization/ASTReader.h
index 7eefdca6815cdad..9f028e59b9445d4 100644
--- a/clang/include/clang/Serialization/ASTReader.h
+++ b/clang/include/clang/Serialization/ASTReader.h
@@ -1981,6 +1981,10 @@ class ASTReader
   /// lookup table as unmaterialized references.
   bool FindExternalVisibleDeclsByName(const DeclContext *DC,
   DeclarationName Name) override;
+  /// Return false if Name is none and Decl Context doesn't come from the 
reader.
+  bool FindVisibleDeclsByName(const DeclContext *DC, DeclarationName Name,
+  SmallVectorImpl &Decls);
+
 
   /// Read all of the declarations lexically stored in a
   /// declaration context.
diff --git a/clang/lib/Serialization/ASTReader.cpp 
b/clang/lib/Serialization/ASTReader.cpp
index 42b48d230af7a97..141df3beffa0ce8 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7928,11 +7928,9 @@ void ASTReader::FindFileRegionDecls(FileID File,
 Decls.push_back(GetDecl(getGlobalDeclID(*DInfo.Mod, *DIt)));
 }
 
-bool
-ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
-  DeclarationName Name) {
-  assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() &&
- "DeclContext has no visible decls in storage");
+bool ASTReader::FindVisibleDeclsByName(const DeclContext *DC,
+   DeclarationName Name,
+   SmallVectorImpl &Decls) {
   if (!Name)
 return false;
 
@@ -7943,7 +7941,6 @@ ASTReader::FindExternalVisibleDeclsByName(const 
DeclContext *DC,
   Deserializing LookupResults(this);
 
   // Load the list of declarations.
-  SmallVector Decls;
   llvm::SmallPtrSet Found;
   for (DeclID ID : It->second.Table.find(Name)) {
 NamedDecl *ND = cast(GetDecl(ID));
@@ -7951,6 +7948,22 @@ ASTReader::FindExternalVisibleDeclsByName(const 
DeclContext *DC,
   Decls.push_back(ND);
   }
 
+  return true;
+}
+
+bool
+ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
+  DeclarationName Name) {
+  assert(DC->hasExternalVisibleStorage() && DC == DC->getPrimaryContext() &&
+ "DeclContext has no visible decls in storage");
+
+  Deserializing LookupResults(this);
+
+  // Load the list of declarations.
+  SmallVector Decls;
+  if (!FindVisibleDeclsByName(DC, Name, Decls))
+return false;
+
   ++NumVisibleDeclContextsRead;
   SetExternalVisibleDeclsForName(DC, Name, Decls);
   return !Decls.empty();
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt
index f60db6ef0ba3454..d55b79e51dfa0c5 100644
--- a/clang/tools/CMakeLists.txt
+++ b/clang/tools/CMakeLists.txt
@@ -17,7 +17,7 @@ if(HAVE_CLANG_REPL_SUPPORT)
 endif()
 
 add_clang_subdirectory(c-index-test)
-
+add_clang_subdirectory(clang-named-modules-querier)
 add_clang_subdirectory(clang-rename)
 add_clang_subdirectory(clang-refactor)
 # For MinGW we only enable shared library if LLVM_LINK_LLVM_DYLIB=ON.
diff --git a/clang/tools/clang-named-modules-querier/CMakeLists.txt 
b/cl

[clang] [C++20] [Modules] Introduce a tool 'clang-named-modules-querier' and two plugins 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin' (PR #72956)

2023-11-21 Thread Chuanqi Xu via cfe-commits

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


[clang] [C++20] [Modules] Introduce a tool 'clang-named-modules-querier' and two plugins 'ClangGetUsedFilesFromModulesPlugin' and 'ClangGetDeclsInModulesPlugin' (PR #72956)

2023-11-21 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> I'm still really hesitant about this direction.
> 
> One starting concern: what happens if someone adds an overload, or other 
> interesting name resolution to the module? The downstream caller hasn't 
> textually changed, but it should be rebuilt because it should be calling a 
> different overload candidate now? (& even if we then track every function 
> with the same name, there's other cases - like adding an implicit conversion 
> operator, operator overload, etc, that might complicate things)

Oh, nice catch. It is a problem for the used file based solution if we add the 
overload to a separate unused files. While the hash based solution can handle 
the overloads case, it'll be a problem if we add an implicit conversion we 
didn't use before.

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


[clang] [Clang][Coroutines] Properly emit EH code for initial suspend `await_resume` (PR #73073)

2023-11-21 Thread Chuanqi Xu via cfe-commits

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

LGTM. Thanks.

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


[clang] [Clang] CGCoroutines skip emitting try block for value returning `noexcept` init `await_resume` calls (PR #73160)

2023-11-22 Thread Chuanqi Xu via cfe-commits


@@ -12,9 +12,10 @@
 
 #include "CGCleanup.h"
 #include "CodeGenFunction.h"
-#include "llvm/ADT/ScopeExit.h"
+#include "clang/AST/ExprCXX.h"
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtVisitor.h"
+#include "llvm/ADT/ScopeExit.h"

ChuanqiXu9 wrote:

Is this change necessary?

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


[clang] [Clang] CGCoroutines skip emitting try block for value returning `noexcept` init `await_resume` calls (PR #73160)

2023-11-22 Thread Chuanqi Xu via cfe-commits


@@ -129,7 +130,14 @@ static SmallString<32> buildSuspendPrefixStr(CGCoroData 
&Coro, AwaitKind Kind) {
   return Prefix;
 }
 
-static bool memberCallExpressionCanThrow(const Expr *E) {
+static bool ResumeExprCanThrow(const CoroutineSuspendExpr &S) {
+  const Expr *E = S.getResumeExpr();
+
+  // If the return type of await_resume is not void, get the CXXMemberCallExpr
+  // from its subexpr.
+  if (const auto *BindTempExpr = dyn_cast(E)) {
+E = BindTempExpr->getSubExpr();
+  }

ChuanqiXu9 wrote:

Such pattern match doesn't smell good. How about looking into its children 
recursively if we find `E` is not CXXMemberCallExpr?

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


[clang] [Clang] CGCoroutines skip emitting try block for value returning `noexcept` init `await_resume` calls (PR #73160)

2023-11-22 Thread Chuanqi Xu via cfe-commits


@@ -38,9 +39,52 @@ Task coro_create() {
 co_return;
 }
 
-// CHECK-LABEL: define{{.*}} ptr @_Z11coro_createv(
+// CHECK-LABEL: define{{.*}} ptr @_ZN9can_throw11coro_createEv(
 // CHECK: init.ready:
 // CHECK-NEXT: store i1 true, ptr {{.*}}
-// CHECK-NEXT: call void @_ZN4Task23initial_suspend_awaiter12await_resumeEv(
-// CHECK-NEXT: call void @_ZN14NontrivialTypeD1Ev(
+// CHECK-NEXT: call void 
@_ZN9can_throw4Task23initial_suspend_awaiter12await_resumeEv(
+// CHECK-NEXT: call void @_ZN9can_throw14NontrivialTypeD1Ev(
 // CHECK-NEXT: store i1 false, ptr {{.*}}
+}
+
+namespace no_throw {
+struct NontrivialType {
+  ~NontrivialType() {}
+};
+
+struct Task {

ChuanqiXu9 wrote:

It looks a little bit confusing. Let's try to rename it to InitNoThrowTask.

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


[clang] [clang][AST][ASTMerge] prevent AST nodes from being deallocated early (PR #73096)

2023-11-22 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> Debug the https://github.com/llvm/llvm-project/issues/72783 can prove it. 
> Address interval (local from 0x3a9a00 to 0x3aaa00) allocated by allocator 
> contains a IdentifierInfo variable (local address:0x3aa190) whose address is 
> freed early.

In this case, it looks better to extract the use-after-free variable only 
instead of extracting the whole ASTUnit.

> As system header like stdio.h or math.h can't be put into test, it's hard to 
> add testcase. Could anyone give me some guidance? Thanks in advance!

Generally, we need to reduce them in this case. e.g., we need to preprocess 
them, and remove unncessary parts until we can't. It is time consuming but it 
is worthy.

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


[clang] 2204364 - [docs] [C++20] [Modules] Add document for the case of duplicated '-fmodule-file=='

2023-10-29 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2023-10-30T11:25:21+08:00
New Revision: 22043643c64f748cb00ae92476f2085b3c0903c9

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

LOG: [docs] [C++20] [Modules] Add document for the case of duplicated 
'-fmodule-file=='

This patch clarifies that in case there are multiple
'-fmodule-file==' optins for the same ``,
the last '-fmodule-file==' will override the previous
'-fmodule-file==' option.

Added: 


Modified: 
clang/docs/StandardCPlusPlusModules.rst

Removed: 




diff  --git a/clang/docs/StandardCPlusPlusModules.rst 
b/clang/docs/StandardCPlusPlusModules.rst
index 8dd86edc64a80ab..49704575740303c 100644
--- a/clang/docs/StandardCPlusPlusModules.rst
+++ b/clang/docs/StandardCPlusPlusModules.rst
@@ -365,6 +365,10 @@ the above example could be rewritten into:
 
   $ clang++ -std=c++20 M.cppm --precompile 
-fmodule-file=M:interface_part=M-interface_part.pcm 
-fmodule-file=M:impl_part=M-impl_part.pcm -o M.pcm
 
+When there are multiple ``-fmodule-file==`` options for the same
+, the last ``-fmodule-file==`` will override the 
previous
+``-fmodule-file==`` options.
+
 ``-fprebuilt-module-path`` is more convenient and ``-fmodule-file`` is faster 
since
 it saves time for file lookup.
 



___
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-29 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

@Bigcheese ping

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-scan-deps] [P1689] Keep consistent behavior for make dependencies with clang (PR #69551)

2023-10-29 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 updated 
https://github.com/llvm/llvm-project/pull/69551

>From c91007b51e164d22c8f73a864105494ebc10a004 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Mon, 30 Oct 2023 11:51:04 +0800
Subject: [PATCH] [clang-scan-deps] [P1689] Keep consistent behavior for make
 dependencies with clang

Close #69439.

This patch tries to reuse the codes to generate make style dependencies
information with P1689 format directly.
---
 .../DependencyScanning/ModuleDepCollector.cpp  | 14 ++
 clang/test/ClangScanDeps/P1689.cppm| 10 ++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp 
b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index 40115b7b5ae25b3..3764ccb0b4749b1 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -666,13 +666,19 @@ static StringRef 
makeAbsoluteAndPreferred(CompilerInstance &CI, StringRef Path,
 }
 
 void ModuleDepCollector::addFileDep(StringRef Path) {
-  llvm::SmallString<256> Storage;
-  Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage);
+  // Within P1689 format, we don't want all the paths to be absolute path
+  // since it may violate the tranditional make style dependencies info.
+  if (!IsStdModuleP1689Format) {
+llvm::SmallString<256> Storage;
+Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage);
+  }
   FileDeps.push_back(std::string(Path));
 }
 
 void ModuleDepCollector::addFileDep(ModuleDeps &MD, StringRef Path) {
-  llvm::SmallString<256> Storage;
-  Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage);
+  if (!IsStdModuleP1689Format) {
+llvm::SmallString<256> Storage;
+Path = makeAbsoluteAndPreferred(ScanInstance, Path, Storage);
+  }
   MD.FileDeps.insert(Path);
 }
diff --git a/clang/test/ClangScanDeps/P1689.cppm 
b/clang/test/ClangScanDeps/P1689.cppm
index dffb16974a3e4e4..24632e25cf7f3bd 100644
--- a/clang/test/ClangScanDeps/P1689.cppm
+++ b/clang/test/ClangScanDeps/P1689.cppm
@@ -42,6 +42,14 @@
 // RUN: clang-scan-deps -format=p1689 \
 // RUN:   -- %clang++ -std=c++20 -fmodules -fimplicit-module-maps 
-fmodules-cache-path=%t/cache -c %t/impl_part.cppm -o %t/impl_part.o \
 // RUN:   | FileCheck %t/impl_part.cppm -DPREFIX=%/t
+//
+// Check the path in the make style dependencies are generated in relative 
path form
+// RUN: cd %t
+// RUN: clang-scan-deps -format=p1689 \
+// RUN:   -- %clang++ -std=c++20 -c -fprebuilt-module-path=%t impl_part.cppm 
-o impl_part.o \
+// RUN:  -MT impl_part.o.ddi -MD -MF impl_part.dep
+// RUN:   cat impl_part.dep | FileCheck impl_part.cppm -DPREFIX=%/t 
--check-prefix=CHECK-MAKE-RELATIVE
+
 
 //--- P1689.json.in
 [
@@ -168,6 +176,8 @@ void World() {
 // CHECK-MAKE:   [[PREFIX]]/impl_part.cppm
 // CHECK-MAKE:   [[PREFIX]]/header.mock
 
+// CHECK-MAKE-RELATIVE: impl_part.o.ddi: impl_part.cppm header.mock
+
 //--- interface_part.cppm
 export module M:interface_part;
 export void World();

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


[clang] [clang-scan-deps] [P1689] Keep consistent behavior for make dependencies with clang (PR #69551)

2023-10-29 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> Thanks for the ping, I had missed your question
> 
> > How do you think about the idea to add a flag to the MDC about whether or 
> > not calling makeAbsoluteAndPreferred?
> 
> SGTM; this seems like a good compromise since we can't easily extract this 
> into the consumer.

Done. Does the current patch look good to you?

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-10-31 Thread Chuanqi Xu via cfe-commits


@@ -696,6 +698,19 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
 Result->Includes = CapturedInfo.takeIncludes();
 Result->Pragmas = std::make_shared(
 CapturedInfo.takePragmaIncludes());
+
+if (ExperimentalModulesSupport) {
+  WallTimer PrerequisiteModuleTimer;
+  PrerequisiteModuleTimer.startTimer();
+  Result->DependentModulesInfo =
+  PrerequisiteModules::buildPrerequisiteModulesFor(FileName, 
Inputs.TFS,
+   CDB);
+  PrerequisiteModuleTimer.stopTimer();
+
+  log("Built prerequisite module for file {0} in {1} seconds", FileName,

ChuanqiXu9 wrote:

Done

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-10-31 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,78 @@
+//=== ModuleDependencyScanner.cpp *- 
C++-*-===//
+//
+// 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
+//
+//===--===//
+
+#include "ModuleDependencyScanner.h"
+
+namespace clang {
+namespace clangd {
+
+std::optional
+ModuleDependencyScanner::scan(PathRef FilePath) {
+  std::optional Cmd = CDB.getCompileCommand(FilePath);
+
+  if (!Cmd)
+return std::nullopt;
+
+  using namespace clang::tooling::dependencies;
+
+  llvm::SmallString<128> FilePathDir(FilePath);
+  llvm::sys::path::remove_filename(FilePathDir);
+  DependencyScanningTool ScanningTool(Service, TFS.view(FilePathDir));

ChuanqiXu9 wrote:

Yeah, initially I added a cache for this. But you pointed out that the 
implementation is problematic. Then I dropped the cache and added a TODO in the 
header of `ModuleDependencyScanner.h`. My thought is that this is an 
performance optimization that we can perform later and this may not be a 
blocker.

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-10-31 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,141 @@
+//===- PrerequisiteModules.h -*-
+//C++-*-===//
+//
+// 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
+//
+//===--===//
+//
+// Experimental support for C++20 Modules.
+//
+// Currently we simplify the implementations by preventing reusing module files
+// across different versions and different source files. But this is clearly a
+// waste of time and space in the end of the day.
+//
+// FIXME: Supporting reusing module files across different versions and
+// different source files.
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREREQUISITEMODULES_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREREQUISITEMODULES_H
+
+#include "Compiler.h"
+#include "GlobalCompilationDatabase.h"
+#include "ModuleDependencyScanner.h"
+#include "support/Path.h"
+
+#include "clang/Lex/HeaderSearchOptions.h"
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang {
+namespace clangd {
+
+/// Build and store all the needed module files information to parse a single
+/// source file. e.g.,
+///
+///   ```
+///   // a.cppm
+///   export module a;
+///
+///   // b.cppm
+///   export module b;
+///   import a;
+///
+///   // c.cppm
+///   export module c;
+///   import a;
+///   ```
+///
+/// For the source file `c.cppm`, an instance of the class will build and store
+/// the module files for `a.cppm` and `b.cppm`. But the module file for 
`c.cppm`
+/// won't be built. Since it is not needed to parse `c.cppm`.
+///
+/// All the built module files won't be shared with other instances of the
+/// class. So that we can avoid worrying thread safety.
+///
+/// A PrerequisiteModules instace should only be initialized by
+/// `PrerequisiteModules::buildPrerequisiteModulesFor(...)`.
+///
+/// Users can detect whether the PrerequisiteModules is still up to date by
+/// calling the `CanReuse()` member function.
+///
+/// The users should call `adjustHeaderSearchOptions(...)` or
+/// `adjustCompileCommands(CompileCommand&)` member function to update the
+/// compilation commands to select the built module files first.
+struct PrerequisiteModules {

ChuanqiXu9 wrote:

Done

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-10-31 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,55 @@
+//===-- ProjectModules.h -*- 
C++-*-===//
+//
+// 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_TOOLS_EXTRA_CLANGD_PROJECTMODULES_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROJECTMODULES_H
+
+#include "ModuleDependencyScanner.h"
+
+namespace clang {
+namespace clangd {
+
+/// An interface to query the modules information in the project.
+/// This should be obtained by
+/// `GlobalCompilationDatabase::getProjectModules(PathRef)`.
+///
+/// TODO: The existing `ScanningAllProjectModules` is not efficient. See the
+/// comments in ModuleDependencyScanner for detail.
+class ProjectModules {
+public:
+  virtual std::vector getRequiredModules(PathRef File) = 0;
+  virtual PathRef getSourceForModuleName(StringRef ModuleName) = 0;
+};
+
+class ScanningAllProjectModules : public ProjectModules {

ChuanqiXu9 wrote:

Done

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-10-31 Thread Chuanqi Xu via cfe-commits


@@ -587,11 +587,11 @@ class DiagPatcher {
 };
 } // namespace
 
-std::shared_ptr
-buildPreamble(PathRef FileName, CompilerInvocation CI,
-  const ParseInputs &Inputs, bool StoreInMemory,
-  PreambleParsedCallback PreambleCallback,
-  PreambleBuildStats *Stats) {
+std::shared_ptr buildPreamble(
+PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs,
+bool StoreInMemory, bool ExperimentalModulesSupport,
+const GlobalCompilationDatabase &CDB,

ChuanqiXu9 wrote:

Done by adding a `ModuleBuilder*` parameter to the interface.

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-10-31 Thread Chuanqi Xu via cfe-commits


@@ -104,6 +107,8 @@ struct PreambleData {
   IncludeStructure Includes;
   // Captures #include-mapping information in #included headers.
   std::shared_ptr Pragmas;
+  // Information about module files for this preamble.
+  std::optional DependentModulesInfo;

ChuanqiXu9 wrote:

Done

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-10-31 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,278 @@
+//===- PrerequisiteModules.cpp ---*-
+//C++-*-===//
+//
+// 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
+//
+//===--===//
+
+#include "PrerequisiteModules.h"
+#include "ProjectModules.h"
+#include "support/Logger.h"
+
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Serialization/ASTReader.h"
+
+namespace clang {
+namespace clangd {
+
+namespace {
+llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) {
+  llvm::SmallString<128> AbsolutePath;
+  if (llvm::sys::path::is_absolute(Cmd.Filename)) {
+AbsolutePath = Cmd.Filename;
+  } else {
+AbsolutePath = Cmd.Directory;
+llvm::sys::path::append(AbsolutePath, Cmd.Filename);
+llvm::sys::path::remove_dots(AbsolutePath, true);
+  }
+  return AbsolutePath;
+}
+} // namespace
+
+PrerequisiteModules::PrerequisiteModules(PathRef MainFile,
+ const GlobalCompilationDatabase &CDB) 
{
+  std::optional PI = CDB.getProjectInfo(MainFile);
+  if (!PI)
+return;
+
+  llvm::SmallString<128> Result(PI->SourceRoot);

ChuanqiXu9 wrote:

Done by adding a FIXME.

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


[clang-tools-extra] [clangd] [C++20] [Modules] Introduce initial support for C++20 Modules (PR #66462)

2023-10-31 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,78 @@
+//=== ModuleDependencyScanner.cpp *- 
C++-*-===//
+//
+// 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
+//
+//===--===//
+
+#include "ModuleDependencyScanner.h"
+
+namespace clang {
+namespace clangd {
+
+std::optional
+ModuleDependencyScanner::scan(PathRef FilePath) {
+  std::optional Cmd = CDB.getCompileCommand(FilePath);
+
+  if (!Cmd)
+return std::nullopt;
+
+  using namespace clang::tooling::dependencies;
+
+  llvm::SmallString<128> FilePathDir(FilePath);
+  llvm::sys::path::remove_filename(FilePathDir);
+  DependencyScanningTool ScanningTool(Service, TFS.view(FilePathDir));
+
+  llvm::Expected P1689Result =

ChuanqiXu9 wrote:

Done

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


  1   2   3   4   5   6   7   8   9   10   >