[clang] 230d6f9 - [Coroutines] Remove lifetime intrinsics for spliied allocas in coroutine frames

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

Author: Chuanqi Xu
Date: 2022-08-05T14:50:43+08:00
New Revision: 230d6f93aaabae985e9fafd071bb3737533c6083

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

LOG: [Coroutines] Remove lifetime intrinsics for spliied allocas in coroutine 
frames

Closing https://github.com/llvm/llvm-project/issues/56919

It is meaningless to preserve the lifetime markers for the spilled
allocas in the coroutine frames and it would block some optimizations
too.

Added: 
clang/test/CodeGenCoroutines/pr56919.cpp
llvm/test/Transforms/Coroutines/coro-split-no-lieftime.ll

Modified: 
llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Removed: 




diff  --git a/clang/test/CodeGenCoroutines/pr56919.cpp 
b/clang/test/CodeGenCoroutines/pr56919.cpp
new file mode 100644
index ..ecd9515acb81
--- /dev/null
+++ b/clang/test/CodeGenCoroutines/pr56919.cpp
@@ -0,0 +1,119 @@
+// Test for PR56919. Tests the destroy function contains the call to delete 
function only.
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -O3 -S -o - 
| FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+namespace std {
+
+template  struct remove_reference { using type = T; };
+template  struct remove_reference { using type = T; };
+template  struct remove_reference { using type = T; };
+
+template 
+constexpr typename std::remove_reference::type&& move(T &&t) noexcept {
+  return static_cast::type &&>(t);
+}
+
+}
+
+template 
+class Task final {
+ public:
+  using value_type = T;
+
+  class promise_type final {
+   public: 
+Task get_return_object() { return 
Task(std::coroutine_handle::from_promise(*this)); }
+
+void unhandled_exception();
+
+std::suspend_always initial_suspend() { return {}; }
+
+auto await_transform(Task co) {
+  return await_transform(std::move(co.handle_.promise()));
+}
+
+auto await_transform(promise_type&& awaited) {
+  struct Awaitable {
+promise_type&& awaited;
+
+bool await_ready() { return false; }
+
+std::coroutine_handle<> await_suspend(
+const std::coroutine_handle<> handle) {
+  // Register our handle to be resumed once the awaited promise's 
coroutine
+  // finishes, and then resume that coroutine.
+  awaited.registered_handle_ = handle;
+  return std::coroutine_handle::from_promise(awaited);
+}
+
+void await_resume() {}
+
+   private:
+  };
+
+  return Awaitable{std::move(awaited)};
+}
+
+void return_void() {}
+
+// At final suspend resume our registered handle.
+auto final_suspend() noexcept {
+  struct FinalSuspendAwaitable final {
+bool await_ready() noexcept { return false; }
+
+std::coroutine_handle<> await_suspend(
+std::coroutine_handle<> h) noexcept {
+  return to_resume;
+}
+
+void await_resume() noexcept {}
+
+std::coroutine_handle<> to_resume;
+  };
+
+  return FinalSuspendAwaitable{registered_handle_};
+}
+
+   private:
+std::coroutine_handle my_handle() {
+  return std::coroutine_handle::from_promise(*this);
+}
+
+std::coroutine_handle<> registered_handle_;
+  };
+
+  ~Task() {
+// Teach llvm that we are only ever destroyed when the coroutine body is 
done,
+// so there is no need for the jump table in the destroy function. Our 
coroutine
+// library doesn't expose handles to the user, so we know this constraint 
isn't
+// violated.
+if (!handle_.done()) {
+  __builtin_unreachable();
+}
+
+handle_.destroy();
+  }
+
+ private:
+  explicit Task(const std::coroutine_handle handle)
+  : handle_(handle) {}
+
+  const std::coroutine_handle handle_;
+};
+
+Task Qux() { co_return; }
+Task Baz() { co_await Qux(); }
+Task Bar() { co_await Baz(); }
+
+// CHECK: _Z3Quxv.destroy:{{.*}}
+// CHECK-NEXT: #
+// CHECK-NEXT: jmp _ZdlPv
+
+// CHECK: _Z3Bazv.destroy:{{.*}}
+// CHECK-NEXT: #
+// CHECK-NEXT: jmp _ZdlPv
+
+// CHECK: _Z3Barv.destroy:{{.*}}
+// CHECK-NEXT: #
+// CHECK-NEXT: jmp _ZdlPv

diff  --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp 
b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 51eb8ebf0369..627886316730 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -1777,8 +1777,15 @@ static void insertSpills(const FrameDataInfo &FrameData, 
coro::Shape &Shape) {
 for (auto *DVI : DIs)
   DVI->replaceUsesOfWith(Alloca, G);
 
-for (Instruction *I : UsersToUpdate)
+for (Instruction *I : UsersToUpdate) {
+  // It is meaningless to remain the lifetime intrinsics refer for the
+  // member of coroutine frames and the meaningless lifetime intrinsics
+  // are possible to block further optimizations.
+  if

[clang] 809b416 - [NFC] Requires x86-registered-target for test/pr56919.cpp

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

Author: Chuanqi Xu
Date: 2022-08-05T16:46:38+08:00
New Revision: 809b4166413f157ce8e45ba0f80438701bf2e133

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

LOG: [NFC] Requires x86-registered-target for test/pr56919.cpp

Added: 


Modified: 
clang/test/CodeGenCoroutines/pr56919.cpp

Removed: 




diff  --git a/clang/test/CodeGenCoroutines/pr56919.cpp 
b/clang/test/CodeGenCoroutines/pr56919.cpp
index ecd9515acb81..dd6df99a5623 100644
--- a/clang/test/CodeGenCoroutines/pr56919.cpp
+++ b/clang/test/CodeGenCoroutines/pr56919.cpp
@@ -1,4 +1,7 @@
 // Test for PR56919. Tests the destroy function contains the call to delete 
function only.
+//
+// REQUIRES: x86-registered-target
+//
 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 %s -O3 -S -o - 
| FileCheck %s
 
 #include "Inputs/coroutine.h"



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


[clang] 8a1727b - [Coroutines] Run coroutine passes by default

2021-07-14 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2021-07-15T14:33:40+08:00
New Revision: 8a1727ba51d262365b0d9fe10fef7e50da7022cd

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

LOG: [Coroutines] Run coroutine passes by default

This patch make coroutine passes run by default in LLVM pipeline. Now
the clang and opt could handle IR inputs containing coroutine intrinsics
without special options.
It should be fine. On the one hand, the coroutine passes seems to be stable
since there are already many projects using coroutine feature.
On the other hand, the coroutine passes should do nothing for IR who doesn't
contain coroutine intrinsic.

Test Plan: check-llvm

Reviewed by: lxfind, aeubanks

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

Added: 


Modified: 
clang/lib/CodeGen/BackendUtil.cpp
clang/test/CodeGen/lto-newpm-pipeline.c
clang/test/CodeGenCoroutines/coro-always-inline.cpp
clang/test/CodeGenCoroutines/coro-symmetric-transfer-01.cpp
llvm/include/llvm-c/Transforms/PassBuilder.h
llvm/include/llvm/Passes/PassBuilder.h
llvm/lib/Passes/PassBuilder.cpp
llvm/lib/Passes/PassBuilderBindings.cpp
llvm/lib/Transforms/Utils/InlineFunction.cpp
llvm/test/Other/new-pm-O0-defaults.ll
llvm/test/Other/new-pm-defaults.ll
llvm/test/Other/new-pm-thinlto-defaults.ll
llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
llvm/tools/opt/NewPMDriver.cpp
llvm/tools/opt/NewPMDriver.h
llvm/tools/opt/opt.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index bafcf7cb8a8f5..9aa67ed2a67ba 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -1265,7 +1265,6 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
   // Only enable CGProfilePass when using integrated assembler, since
   // non-integrated assemblers don't recognize .cgprofile section.
   PTO.CallGraphProfile = !CodeGenOpts.DisableIntegratedAS;
-  PTO.Coroutines = LangOpts.Coroutines;
 
   LoopAnalysisManager LAM;
   FunctionAnalysisManager FAM;

diff  --git a/clang/test/CodeGen/lto-newpm-pipeline.c 
b/clang/test/CodeGen/lto-newpm-pipeline.c
index c8220e3547e14..c2cd3a4720cca 100644
--- a/clang/test/CodeGen/lto-newpm-pipeline.c
+++ b/clang/test/CodeGen/lto-newpm-pipeline.c
@@ -28,6 +28,8 @@
 // CHECK-FULL-O0: Running pass: AlwaysInlinerPass
 // CHECK-FULL-O0-NEXT: Running analysis: InnerAnalysisManagerProxy
 // CHECK-FULL-O0-NEXT: Running analysis: ProfileSummaryAnalysis
+// CHECK-FULL-O0: Running pass: CoroSplitPass
+// CHECK-FULL-O0-NEXT: Running pass: CoroCleanupPass
 // CHECK-FULL-O0-NEXT: Running pass: CanonicalizeAliasesPass
 // CHECK-FULL-O0-NEXT: Running pass: NameAnonGlobalPass
 // CHECK-FULL-O0-NEXT: Running pass: BitcodeWriterPass
@@ -35,6 +37,7 @@
 // CHECK-THIN-O0: Running pass: AlwaysInlinerPass
 // CHECK-THIN-O0-NEXT: Running analysis: InnerAnalysisManagerProxy
 // CHECK-THIN-O0-NEXT: Running analysis: ProfileSummaryAnalysis
+// CHECK-THIN-O0: Running pass: CoroCleanupPass
 // CHECK-THIN-O0-NEXT: Running pass: CanonicalizeAliasesPass
 // CHECK-THIN-O0-NEXT: Running pass: NameAnonGlobalPass
 // CHECK-THIN-O0-NEXT: Running pass: ThinLTOBitcodeWriterPass

diff  --git a/clang/test/CodeGenCoroutines/coro-always-inline.cpp 
b/clang/test/CodeGenCoroutines/coro-always-inline.cpp
index e4aa14a6ac397..ef7183b9642d5 100644
--- a/clang/test/CodeGenCoroutines/coro-always-inline.cpp
+++ b/clang/test/CodeGenCoroutines/coro-always-inline.cpp
@@ -40,15 +40,13 @@ struct coroutine_traits {
 
 // CHECK-LABEL: @_Z3foov
 // CHECK-LABEL: entry:
-// CHECK-NEXT: %this.addr.i{{[0-9]*}} = alloca 
%"struct.std::experimental::awaitable"*, align 8
-// CHECK-NEXT: %this.addr.i{{[0-9]*}} = alloca 
%"struct.std::experimental::awaitable"*, align 8
-// CHECK: [[CAST0:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** 
%this.addr.i{{[0-9]*}} to i8*
-// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CAST0]])
-// CHECK: [[CAST1:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** 
%this.addr.i{{[0-9]*}} to i8*
-// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CAST1]])
-
-// CHECK: [[CAST2:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** 
%this.addr.i{{[0-9]*}} to i8*
-// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[CAST2]])
-// CHECK: [[CAST3:%[0-9]+]] = bitcast %"struct.std::experimental::awaitable"** 
%this.addr.i{{[0-9]*}} to i8*
-// CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* [[CAST3]])
+// CHECK: [[CAST0:%[0-9]+]] = bitcast %"struct.std::experiment

[clang] 845f0bb - Revert "[clang][ABI] New C++20 module mangling scheme"

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

Author: Chuanqi Xu
Date: 2022-03-09T10:15:15+08:00
New Revision: 845f0bb5fac7479b27e5327c8787ac111e9ad610

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

LOG: Revert "[clang][ABI] New C++20 module mangling scheme"

This reverts commit 21e16ab6b8ddaccb70d2344bb35419e214a32ec9.

It looks like it would break builds in mac. See
https://reviews.llvm.org/D118352.

Added: 


Modified: 
clang/include/clang/AST/Mangle.h
clang/lib/AST/Decl.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cpp
clang/test/CXX/modules-ts/basic/basic.def.odr/p4/module.cppm
clang/test/CXX/modules-ts/basic/basic.def.odr/p4/user.cpp
clang/test/CXX/modules-ts/basic/basic.link/p3.cppm
clang/test/CXX/modules-ts/codegen-basics.cppm

Removed: 
clang/test/CodeGenCXX/Inputs/cxx20-module-impl-1a.cpp
clang/test/CodeGenCXX/Inputs/cxx20-module-std-subst-2a.cpp
clang/test/CodeGenCXX/cxx20-module-decomp-1.cpp
clang/test/CodeGenCXX/cxx20-module-extern-1.cppm
clang/test/CodeGenCXX/cxx20-module-impl-1a.cpp
clang/test/CodeGenCXX/cxx20-module-nested-1.cppm
clang/test/CodeGenCXX/cxx20-module-nested-2.cppm
clang/test/CodeGenCXX/cxx20-module-part-1a.cpp
clang/test/CodeGenCXX/cxx20-module-part-1b.cpp
clang/test/CodeGenCXX/cxx20-module-part-1c.cpp
clang/test/CodeGenCXX/cxx20-module-std-subst-1.cppm
clang/test/CodeGenCXX/cxx20-module-std-subst-2b.cpp
clang/test/CodeGenCXX/cxx20-module-std-subst-2c.cpp
clang/test/CodeGenCXX/cxx20-module-sub-1a.cppm
clang/test/CodeGenCXX/cxx20-module-sub-1b.cppm
clang/test/CodeGenCXX/cxx20-module-tmpl-1.cppm



diff  --git a/clang/include/clang/AST/Mangle.h 
b/clang/include/clang/AST/Mangle.h
index c594c9809fef6..7d02f08e0120c 100644
--- a/clang/include/clang/AST/Mangle.h
+++ b/clang/include/clang/AST/Mangle.h
@@ -194,8 +194,6 @@ class ItaniumMangleContext : public MangleContext {
 
   virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 
0;
 
-  virtual void mangleModuleInitializer(const Module *Module, raw_ostream &) = 
0;
-
   // This has to live here, otherwise the CXXNameMangler won't have access to
   // it.
   virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0;

diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 9b8d0f6e288e7..82c4412296dbc 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1540,11 +1540,6 @@ LinkageInfo 
LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
 }
 
 Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const {
-  if (isa(this))
-// Namespaces never have module linkage.  It is the entities within them
-// that [may] do.
-return nullptr;
-
   Module *M = getOwningModule();
   if (!M)
 return nullptr;

diff  --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 1f78142044c8f..d1d7a7c40ceb9 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -130,8 +130,6 @@ class ItaniumMangleContextImpl : public 
ItaniumMangleContext {
 
   void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) override;
 
-  void mangleModuleInitializer(const Module *Module, raw_ostream &) override;
-
   bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
 // Lambda closure types are already numbered.
 if (isLambda(ND))
@@ -440,7 +438,6 @@ class CXXNameMangler {
   void mangleType(QualType T);
   void mangleNameOrStandardSubstitution(const NamedDecl *ND);
   void mangleLambdaSig(const CXXRecordDecl *Lambda);
-  void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false);
 
 private:
 
@@ -476,21 +473,22 @@ class CXXNameMangler {
 
   void mangleNameWithAbiTags(GlobalDecl GD,
  const AbiTagList *AdditionalAbiTags);
-  void mangleModuleName(const NamedDecl *ND);
+  void mangleModuleName(const Module *M);
+  void mangleModuleNamePrefix(StringRef Name);
   void mangleTemplateName(const TemplateDecl *TD,
   const TemplateArgument *TemplateArgs,
   unsigned NumTemplateArgs);
-  void mangleUnqualifiedName(GlobalDecl GD, const DeclContext *DC,
+  void mangleUnqualifiedName(GlobalDecl GD,
  const AbiTagList *AdditionalAbiTags) {
-mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName(), DC,
-  UnknownArity, AdditionalAbiTags);
+mangleUnqualifiedName(GD, cast(GD.getDecl())->getDeclName(), 
UnknownArity,
+  AdditionalAbiTags);
   }
   void mangleUnqualifiedName(GlobalDecl GD, DeclarationName Name,
- const DeclContext *DC, unsigned KnownArity,
+ unsigned Know

[clang] ae4eb93 - [NFC] [C++20] [Modules] Add test to show private module fragment is not allowed in partition unit

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

Author: Chuanqi Xu
Date: 2022-03-09T19:05:54+08:00
New Revision: ae4eb938c00785540a8c395c9d166cff7516f280

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

LOG: [NFC] [C++20] [Modules] Add test to show private module fragment is not 
allowed in partition unit

Added: 
clang/test/CXX/module/module.private.frag/p1.cpp

Modified: 


Removed: 




diff  --git a/clang/test/CXX/module/module.private.frag/p1.cpp 
b/clang/test/CXX/module/module.private.frag/p1.cpp
new file mode 100644
index 0..af3d52f3bd325
--- /dev/null
+++ b/clang/test/CXX/module/module.private.frag/p1.cpp
@@ -0,0 +1,25 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/parta.cppm -o 
%t/mod-parta.pcm -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/impl.cppm -o 
%t/mod-impl.pcm -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/primary.cppm -o 
%t/mod.pcm -fsyntax-only -verify
+
+//--- parta.cppm
+export module mod:parta;
+
+module :private; // expected-error {{private module fragment declaration with 
no preceding module declaration}}
+
+//--- impl.cppm
+
+module mod:impl;
+
+module :private; // expected-error {{private module fragment declaration with 
no preceding module declaration}}
+
+//--- primary.cppm
+//expected-no-diagnostics
+export module mod;
+
+module :private;
+



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


[clang] a603f56 - [clang] CWG 2354: prohibit alignas for enums

2022-03-16 Thread Chuanqi Xu via cfe-commits

Author: Vlad Serebrennikov
Date: 2022-03-16T15:48:18+08:00
New Revision: a603f566dbe04d8a9eb0ada67b585965945f7e6d

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

LOG: [clang] CWG 2354: prohibit alignas for enums

Reviewed By: aaron.ballman, erichkeane

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

Added: 
clang/test/CXX/drs/dr2354.cpp

Modified: 
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp
clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p6.cpp
clang/www/cxx_dr_status.html

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e17b018937fb4..0806cc4170753 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3022,8 +3022,9 @@ def err_aligned_attribute_argument_not_int : Error<
 def err_align_value_attribute_argument_not_int : Error<
   "'align_value' attribute requires integer constant">;
 def err_alignas_attribute_wrong_decl_type : Error<
-  "%0 attribute cannot be applied to a %select{function parameter|"
-  "variable with 'register' storage class|'catch' variable|bit-field}1">;
+  "%0 attribute cannot be applied to %select{a function parameter|"
+  "a variable with 'register' storage class|a 'catch' variable|a bit-field|"
+  "an enumeration}1">;
 def err_alignas_missing_on_definition : Error<
   "%0 must be specified on definition if it is specified on any declaration">;
 def note_alignas_on_declaration : Note<"declared with %0 attribute here">;

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 3034abdf04028..70d6721a8b1c0 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -4290,6 +4290,9 @@ void Sema::AddAlignedAttr(Decl *D, const 
AttributeCommonInfo &CI, Expr *E,
 //   declared with the register storage class specifier. An
 //   alignment-specifier may also be applied to the declaration of a class
 //   or enumeration type.
+// CWG 2354:
+//   CWG agreed to remove permission for alignas to be applied to
+//   enumerations.
 // C11 6.7.5/2:
 //   An alignment attribute shall not be specified in a declaration of
 //   a typedef, or a bit-field, or a function, or a parameter, or an
@@ -4305,6 +4308,9 @@ void Sema::AddAlignedAttr(Decl *D, const 
AttributeCommonInfo &CI, Expr *E,
 } else if (const auto *FD = dyn_cast(D)) {
   if (FD->isBitField())
 DiagKind = 3;
+} else if (const auto *ED = dyn_cast(D)) {
+  if (ED->getLangOpts().CPlusPlus)
+DiagKind = 4;
 } else if (!isa(D)) {
   Diag(AttrLoc, diag::err_attribute_wrong_decl_type) << &TmpAttr
 << (TmpAttr.isC11() ? ExpectedVariableOrField

diff  --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp 
b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp
index e713d72dc58fa..45d5ebf68ba8f 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p5.cpp
@@ -11,13 +11,6 @@ alignas(1) int n7 alignas(2), // expected-error {{less than 
minimum alignment}}
 alignas(8) int n9 alignas(2); // ok, overaligned
 alignas(1) extern int n10; // expected-error {{less than minimum alignment}}
 
-enum alignas(1) E1 {}; // expected-error {{requested alignment is less than 
minimum alignment of 4 for type 'E1'}}
-enum alignas(1) E2 : char {}; // ok
-enum alignas(4) E3 { e3 = 0 }; // ok
-enum alignas(4) E4 { e4 = 1ull << 33 }; // expected-error {{requested 
alignment is less than minimum alignment of 8 for type 'E4'}}
-enum alignas(8) E5 {};
-static_assert(alignof(E5) == 8, "");
-
 typedef __attribute__((aligned(16))) int IntAlign16;
 enum E6 : IntAlign16 {};
 static_assert(alignof(E6) == 4, "");
@@ -62,15 +55,6 @@ template struct X<2, 2, short>;
 template struct X<16, 8, S1>;
 template struct X<4, 4, S1>; // expected-note {{instantiation}}
 
-template
-struct Y {
-  enum alignas(N) E : T {}; // expected-error {{requested alignment is less 
than minimum}}
-};
-template struct Y<1, char>;
-template struct Y<2, char>;
-template struct Y<1, short>; // expected-note {{instantiation}}
-template struct Y<2, short>;
-
 template
 void f() {
   alignas(N) T v; // expected-error {{requested alignment is less than 
minimum}}

diff  --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p6.cpp 
b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p6.cpp
index e788577480770..5d93336341f6e 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p6.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.align/p6.cpp
@@ -27,21 +27,6 @@ int n8; // expected-error {{'alignas' must be specified on 
definition if it is s
 int n9; // expect

[clang] 74b56e0 - [NFC] Remove unused variable in CodeGenModules

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

Author: Chuanqi Xu
Date: 2022-04-08T11:52:31+08:00
New Revision: 74b56e02bda09ae735c6aeca583a2078375f2da1

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

LOG: [NFC] Remove unused variable in CodeGenModules

This eliminates an unused-variable warning

Added: 


Modified: 
clang/lib/CodeGen/CodeGenModule.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index ec34d91e65372..c9e5354d3269a 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -5183,11 +5183,9 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
   SetCommonAttributes(GD, GA);
 
   // Emit global alias debug information.
-  if (const auto *VD = dyn_cast(D)) {
-if (CGDebugInfo *DI = getModuleDebugInfo()) {
+  if (isa(D))
+if (CGDebugInfo *DI = getModuleDebugInfo())
   DI->EmitGlobalAlias(cast(GA->getAliasee()), GD);
-}
-  }
 }
 
 void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {



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


[clang] 36de2d6 - [NFC] [AST] Reduce the size of TemplateParmPosition

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

Author: Chuanqi Xu
Date: 2022-04-13T10:56:13+08:00
New Revision: 36de2d639eca4cead62a6c6d288a501cee8bb6e7

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

LOG: [NFC] [AST] Reduce the size of TemplateParmPosition

I found this when reading the codes. I think it makes sense to reduce
the space for TemplateParmPosition. It is hard to image the depth of
template parameter is larger than 2^20 and the index is larger than
2^12. So I think the patch might be reasonable.

Reviewed By: aaron.ballman

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

Added: 


Modified: 
clang/include/clang/AST/DeclTemplate.h

Removed: 




diff  --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index ca3a8030ffc61..66e0bb2c02a1f 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1148,23 +1148,40 @@ class FunctionTemplateDecl : public 
RedeclarableTemplateDecl {
 /// parameters and is not part of the Decl hierarchy. Just a facility.
 class TemplateParmPosition {
 protected:
-  // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
-  // position? Maybe?
-  unsigned Depth;
-  unsigned Position;
+  enum { DepthWidth = 20, PositionWidth = 12 };
+  unsigned Depth : DepthWidth;
+  unsigned Position : PositionWidth;
 
-  TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {}
+  static constexpr unsigned MaxDepth = (1U << DepthWidth) - 1;
+  static constexpr unsigned MaxPosition = (1U << PositionWidth) - 1;
+
+  TemplateParmPosition(unsigned D, unsigned P) : Depth(D), Position(P) {
+// The input may fill maximum values to show that it is invalid.
+// Add one here to convert it to zero.
+assert((D + 1) <= MaxDepth &&
+   "The depth of template parmeter position is more than 2^20!");
+assert((P + 1) <= MaxPosition &&
+   "The position of template parmeter position is more than 2^12!");
+  }
 
 public:
   TemplateParmPosition() = delete;
 
   /// Get the nesting depth of the template parameter.
   unsigned getDepth() const { return Depth; }
-  void setDepth(unsigned D) { Depth = D; }
+  void setDepth(unsigned D) {
+assert((D + 1) <= MaxDepth &&
+   "The depth of template parmeter position is more than 2^20!");
+Depth = D;
+  }
 
   /// Get the position of the template parameter within its parameter list.
   unsigned getPosition() const { return Position; }
-  void setPosition(unsigned P) { Position = P; }
+  void setPosition(unsigned P) {
+assert((P + 1) <= MaxPosition &&
+   "The position of template parmeter position is more than 2^12!");
+Position = P;
+  }
 
   /// Get the index of the template parameter within its parameter list.
   unsigned getIndex() const { return Position; }



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


[clang] cd149db - [NFC] Remove unused variable

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

Author: Chuanqi Xu
Date: 2022-04-19T15:19:40+08:00
New Revision: cd149dbf8ed8334e68e0f69d819bac3d400e8ba7

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

LOG: [NFC] Remove unused variable

Added: 


Modified: 
clang/lib/AST/ExprConstant.cpp

Removed: 




diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 410fc8285bb65..3ad44d5e2da80 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8294,7 +8294,7 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, 
const VarDecl *VD) {
 }
 
 bool LValueExprEvaluator::VisitCallExpr(const CallExpr *E) {
-  switch (unsigned BuiltinOp = E->getBuiltinCallee()) {
+  switch (E->getBuiltinCallee()) {
   case Builtin::BIas_const:
   case Builtin::BIforward:
   case Builtin::BImove:



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


[clang] 483efc9 - [Pipelines] Remove Legacy Passes in Coroutines

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

Author: Chuanqi Xu
Date: 2022-04-21T10:59:11+08:00
New Revision: 483efc9ad04dccd9f2163c84c2b6198ebb7049a6

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

LOG: [Pipelines] Remove Legacy Passes in Coroutines

The legacy passes are deprecated now and would be removed in near
future. This patch tries to remove legacy passes in coroutines.

Reviewed By: aeubanks

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

Added: 


Modified: 
clang/lib/CodeGen/BackendUtil.cpp
llvm/bindings/go/llvm/transforms_pmbuilder.go
llvm/include/llvm/InitializePasses.h
llvm/lib/Transforms/Coroutines/CoroCleanup.cpp
llvm/lib/Transforms/Coroutines/CoroEarly.cpp
llvm/lib/Transforms/Coroutines/CoroElide.cpp
llvm/lib/Transforms/Coroutines/CoroInternal.h
llvm/lib/Transforms/Coroutines/CoroSplit.cpp
llvm/lib/Transforms/Coroutines/Coroutines.cpp

llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-infinite-loop-bug.ll
llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-start-bug.ll
llvm/test/Transforms/Coroutines/coro-async-phi.ll
llvm/test/Transforms/Coroutines/coro-async-remat.ll
llvm/test/Transforms/Coroutines/coro-async-unreachable.ll
llvm/test/Transforms/Coroutines/coro-async.ll
llvm/test/Transforms/Coroutines/coro-cleanup-lowering.ll
llvm/test/Transforms/Coroutines/coro-cleanup.ll
llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll
llvm/test/Transforms/Coroutines/coro-retcon-alloca-opaque-ptr.ll
llvm/test/Transforms/Coroutines/coro-retcon-alloca.ll
llvm/test/Transforms/Coroutines/coro-retcon-once-private.ll
llvm/test/Transforms/Coroutines/coro-retcon-once-value.ll
llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll
llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll
llvm/test/Transforms/Coroutines/coro-retcon-value.ll
llvm/test/Transforms/Coroutines/coro-retcon.ll
llvm/test/Transforms/Coroutines/coro-split-01.ll
llvm/test/Transforms/Coroutines/coro-swifterror.ll
llvm/test/Transforms/Coroutines/ex0.ll
llvm/test/Transforms/Coroutines/ex1.ll
llvm/test/Transforms/Coroutines/ex2.ll
llvm/test/Transforms/Coroutines/ex3.ll
llvm/test/Transforms/Coroutines/ex4.ll
llvm/test/Transforms/Coroutines/ex5.ll
llvm/test/Transforms/Coroutines/phi-coro-end.ll
llvm/test/Transforms/Coroutines/restart-trigger.ll
llvm/test/Transforms/Coroutines/smoketest.ll
llvm/tools/llvm-c-test/include-all.c
llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
llvm/tools/opt/opt.cpp
utils/bazel/llvm-project-overlay/llvm/BUILD.bazel

Removed: 
llvm/bindings/go/llvm/transforms_coroutines.go
llvm/include/llvm-c/Transforms/Coroutines.h
llvm/include/llvm/Transforms/Coroutines.h



diff  --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index e1cdfaeccc48b..ed7bd8f838ee0 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -53,7 +53,6 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
-#include "llvm/Transforms/Coroutines.h"
 #include "llvm/Transforms/Coroutines/CoroCleanup.h"
 #include "llvm/Transforms/Coroutines/CoroEarly.h"
 #include "llvm/Transforms/Coroutines/CoroElide.h"

diff  --git a/llvm/bindings/go/llvm/transforms_coroutines.go 
b/llvm/bindings/go/llvm/transforms_coroutines.go
deleted file mode 100644
index c18c3fe936c1e..0
--- a/llvm/bindings/go/llvm/transforms_coroutines.go
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- transforms_coroutines.go - Bindings for coroutines 
-===//
-//
-// 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
-//
-//===--===//
-//
-// This file defines bindings for the coroutines component.
-//
-//===--===//
-
-package llvm
-
-/*
-#include "llvm-c/Transforms/Coroutines.h"
-*/
-import "C"
-
-func (pm PassManager) AddCoroEarlyPass()   { C.LLVMAddCoroEarlyPass(pm.C) }
-func (pm PassManager) AddCoroSplitPass()   { C.LLVMAddCoroSplitPass(pm.C) }
-func (pm PassManager) AddCoroElidePass()   { C.LLVMAddCoroElidePass(pm.C) }
-func (pm PassManager) AddCoroCleanupPass() { C.LLVMAddCoroCleanupPass(pm.C) }

diff  --git a/llvm/bindings/go/llvm/transforms_pmbuilder.go 
b/llvm/bindings/go/llvm/transforms_pmbuilder.go
index 383f7bb3ae7ba..2c902a140dc43 100644
--- a/llvm/bindings/go/llvm/transforms_pmbuilder.go
+++ b/llvm/bindings/go/llvm/transforms_pmbuilder.go
@@ -14,7 +14,6 @@ package llvm
 

[clang] ce2257d - [C++20] [Modules] Judge current module correctly

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

Author: Chuanqi Xu
Date: 2022-04-21T11:09:55+08:00
New Revision: ce2257d69fd02d0c34164ce3de9ab8dbe6991e0c

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

LOG: [C++20] [Modules] Judge current module correctly

Now the implementation would accept following code:
```
//--- impl.cppm
module M:impl;
class A {};

//--- M.cppm
export module M;
import :impl;

//--- Use.cpp
import M;
void test() {
A a; // Expected error. A is not visible here.
}
```

which is clearly wrong.  The root cause is the implementation of
`isInCurrentModule` would return true if the module is a partition! So
in the above example, although Use.cpp is not a module unit,
`isInCurrentModule ` would still return true when the compiler tries to
see if the owning module of `A` is the current module. I believe this is
an oversight. This patch tries to fix this problem.

Reviewed By: iains

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

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

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

Removed: 




diff  --git a/clang/include/clang/Basic/Module.h 
b/clang/include/clang/Basic/Module.h
index 45c23d5b7988e..5ce5fea45c670 100644
--- a/clang/include/clang/Basic/Module.h
+++ b/clang/include/clang/Basic/Module.h
@@ -168,6 +168,8 @@ class Module {
   /// some C++ module.
   bool isGlobalModule() const { return Kind == GlobalModuleFragment; }
 
+  bool isPrivateModule() const { return Kind == PrivateModuleFragment; }
+
 private:
   /// The submodules of this module, indexed by name.
   std::vector SubModules;
@@ -536,10 +538,23 @@ class Module {
 
   /// Get the primary module interface name from a partition.
   StringRef getPrimaryModuleInterfaceName() const {
+// Technically, global module fragment belongs to global module. And global
+// module has no name: [module.unit]p6:
+//   The global module has no name, no module interface unit, and is not
+//   introduced by any module-declaration.
+//
+//  is the default name showed in module map.
+if (isGlobalModule())
+  return "";
+
 if (isModulePartition()) {
   auto pos = Name.find(':');
   return StringRef(Name.data(), pos);
 }
+
+if (isPrivateModule())
+  return getTopLevelModuleName();
+
 return Name;
   }
 

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7ec794d18e825..74b6f21284fc6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2239,7 +2239,7 @@ class Sema final {
   /// Namespace definitions that we will export when they finish.
   llvm::SmallPtrSet DeferredExportedNamespaces;
 
-  /// Get the module whose scope we are currently within.
+  /// Get the module unit whose scope we are currently within.
   Module *getCurrentModule() const {
 return ModuleScopes.empty() ? nullptr : ModuleScopes.back().Module;
   }
@@ -2257,6 +2257,11 @@ class Sema final {
 
   VisibleModuleSet VisibleModules;
 
+  /// Cache for module units which is usable for current module.
+  llvm::DenseSet UsableModuleUnitsCache;
+
+  bool isUsableModule(const Module *M);
+
 public:
   /// Get the module owning an entity.
   Module *getOwningModule(const Decl *Entity) {

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 604c29c36fd2c..2a378741e7aa6 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1558,17 +1558,39 @@ llvm::DenseSet &Sema::getLookupModules() {
   return LookupModulesCache;
 }
 
-/// Determine whether the module M is part of the current module from the
-/// perspective of a module-private visibility check.
-static bool isInCurrentModule(const Module *M, const LangOptions &LangOpts) {
+/// Determine if we could use all the declarations in the module.
+bool Sema::isUsableModule(const Module *M) {
+  assert(M && "We shouldn't check nullness for module here");
+  // Return quickly if we cached the result.
+  if (UsableModuleUnitsCache.count(M))
+return true;
+
   // If M is the global module fragment of a module that we've not yet finished
-  // parsing, then it must be part of the current module.
-  // If it's a partition, then it must be visible to an importer (since only
-  // another partition or the named module can import it).
-  return M->getTopLevelModuleName() == LangOpts.CurrentModule ||
- (M->Kind == Module::GlobalModuleFragment && !M->Parent) ||
- M->Kind == Module::ModulePartitionInterface ||
- M->Kind == Module::ModulePartitionImplementation;
+  // parsing, then M should be the global module fragment in current TU. So it
+  // should be usable.
+  // [module.global.frag]p1:
+ 

[clang] e39ba04 - [C++20] [Coroutines] Warning for always_inline coroutine

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

Author: Chuanqi Xu
Date: 2022-02-08T11:43:42+08:00
New Revision: e39ba0461757339f7172f6bc3882f41116bb7c13

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

LOG: [C++20] [Coroutines] Warning for always_inline coroutine

See the discussion in https://reviews.llvm.org/D100282. The coroutine
marked always inline might not be inlined properly in current compiler
support. Since the coroutine would be splitted into pieces. And the call
to resume() and destroy() functions might be indirect call. Also the
ramp function wouldn't get inlined under O0 due to pipeline ordering
problems. It might be different to what users expects to. Emit a warning
to tell it.

This is what GCC does too: https://godbolt.org/z/7eajb1Gf8

Reviewed By: Quuxplusone

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

Added: 


Modified: 
clang/include/clang/Basic/AttrDocs.td
clang/include/clang/Basic/DiagnosticGroups.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaCoroutine.cpp
clang/test/SemaCXX/coroutines.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/AttrDocs.td 
b/clang/include/clang/Basic/AttrDocs.td
index e12a0b259cc2e..1682a71eb992e 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -6205,6 +6205,10 @@ optimization level.
 
 Does not guarantee that inline substitution actually occurs.
 
+Note: applying this attribute to a coroutine at the `-O0` optimization 
level
+has no effect; other optimization levels may only partially inline and result 
in a
+diagnostic.
+
 See also `the Microsoft Docs on Inline Functions`_, `the GCC Common Function
 Attribute docs`_, and `the GCC Inline docs`_.
 

diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td 
b/clang/include/clang/Basic/DiagnosticGroups.td
index 608e16147b1cd..3f14fa32597d9 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -58,7 +58,9 @@ def DeprecatedExperimentalCoroutine :
   DiagGroup<"deprecated-experimental-coroutine">;
 def DeprecatedCoroutine :
   DiagGroup<"deprecated-coroutine", [DeprecatedExperimentalCoroutine]>;
-def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, 
DeprecatedCoroutine]>;
+def AlwaysInlineCoroutine :
+  DiagGroup<"always-inline-coroutine">;
+def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, 
DeprecatedCoroutine, AlwaysInlineCoroutine]>;
 def ObjCBoolConstantConversion : DiagGroup<"objc-bool-constant-conversion">;
 def ConstantConversion : DiagGroup<"constant-conversion",
[BitFieldConstantConversion,

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f9bfd343ac8d1..08cd8c8991ff9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11122,6 +11122,10 @@ def 
err_coroutine_promise_final_suspend_requires_nothrow : Error<
 def note_coroutine_function_declare_noexcept : Note<
   "must be declared with 'noexcept'"
 >;
+def warn_always_inline_coroutine : Warning<
+  "this coroutine may be split into pieces; not every piece is guaranteed to 
be inlined"
+  >,
+  InGroup;
 } // 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 cd3ae62ebbe26..aae90c403f0f2 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1081,6 +1081,14 @@ void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, 
Stmt *&Body) {
 return;
   }
 
+  // The always_inline attribute doesn't reliably apply to a coroutine,
+  // because the coroutine will be split into pieces and some pieces
+  // might be called indirectly, as in a virtual call. Even the ramp
+  // function cannot be inlined at -O0, due to pipeline ordering
+  // problems (see https://llvm.org/PR53413). Tell the user about it.
+  if (FD->hasAttr())
+Diag(FD->getLocation(), diag::warn_always_inline_coroutine);
+
   // [stmt.return.coroutine]p1:
   //   A coroutine shall not enclose a return statement ([stmt.return]).
   if (Fn->FirstReturnLoc.isValid()) {

diff  --git a/clang/test/SemaCXX/coroutines.cpp 
b/clang/test/SemaCXX/coroutines.cpp
index b461c881355b5..c81385bcc0595 100644
--- a/clang/test/SemaCXX/coroutines.cpp
+++ b/clang/test/SemaCXX/coroutines.cpp
@@ -1460,3 +1460,13 @@ void test_missing_awaitable_members() {
   co_await missing_await_suspend{}; // expected-error {{no member named 
'await_suspend' in 'missing_await_suspend'}}
   co_await missing_await_resume{}; // expected-error {{no member named 
'await_resume' in 'missing_await_resume'}}
 }
+
+

[clang] 3504937 - [C++20] [Modules] Don't create multiple global module fragment

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

Author: Chuanqi Xu
Date: 2022-02-08T11:52:09+08:00
New Revision: 3504937dfb2b7d90b2c3b3c7b28c472d31489007

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

LOG: [C++20] [Modules] Don't create multiple global module fragment

Since the serialization code would recognize modules by names and the
name of all global module fragment is , so that the
serialization code would complain for the same module.

This patch fixes this by using a unique global module fragment in Sema.
Before this patch, the compiler would fail on an assertion complaining
the duplicated modules.

Reviewed By: urnathan, rsmith

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

Added: 
clang/test/CXX/module/module.unit/p7/Inputs/h8.h
clang/test/CXX/module/module.unit/p7/Inputs/m8.cppm
clang/test/CXX/module/module.unit/p7/t8.cpp

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 4b609f4b1477c..30148659562ed 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2218,6 +2218,8 @@ class Sema final {
   };
   /// The modules we're currently parsing.
   llvm::SmallVector ModuleScopes;
+  /// The global module fragment of the current translation unit.
+  clang::Module *GlobalModuleFragment = nullptr;
 
   /// Namespace definitions that we will export when they finish.
   llvm::SmallPtrSet DeferredExportedNamespaces;

diff  --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp
index 747734f2d0ff0..85e58640044dc 100644
--- a/clang/lib/Sema/SemaModule.cpp
+++ b/clang/lib/Sema/SemaModule.cpp
@@ -720,19 +720,24 @@ Decl *Sema::ActOnFinishExportDecl(Scope *S, Decl *D, 
SourceLocation RBraceLoc) {
 
 Module *Sema::PushGlobalModuleFragment(SourceLocation BeginLoc,
bool IsImplicit) {
-  ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();
-  Module *GlobalModule =
-  Map.createGlobalModuleFragmentForModuleUnit(BeginLoc, 
getCurrentModule());
-  assert(GlobalModule && "module creation should not fail");
+  // We shouldn't create new global module fragment if there is already
+  // one.
+  if (!GlobalModuleFragment) {
+ModuleMap &Map = PP.getHeaderSearchInfo().getModuleMap();
+GlobalModuleFragment = Map.createGlobalModuleFragmentForModuleUnit(
+BeginLoc, getCurrentModule());
+  }
+
+  assert(GlobalModuleFragment && "module creation should not fail");
 
   // Enter the scope of the global module.
-  ModuleScopes.push_back({BeginLoc, GlobalModule,
+  ModuleScopes.push_back({BeginLoc, GlobalModuleFragment,
   /*ModuleInterface=*/false,
   /*ImplicitGlobalModuleFragment=*/IsImplicit,
-  /*VisibleModuleSet*/{}});
-  VisibleModules.setVisible(GlobalModule, BeginLoc);
+  /*VisibleModuleSet*/ {}});
+  VisibleModules.setVisible(GlobalModuleFragment, BeginLoc);
 
-  return GlobalModule;
+  return GlobalModuleFragment;
 }
 
 void Sema::PopGlobalModuleFragment() {

diff  --git a/clang/test/CXX/module/module.unit/p7/Inputs/h8.h 
b/clang/test/CXX/module/module.unit/p7/Inputs/h8.h
new file mode 100644
index 0..2ef06cdc4054b
--- /dev/null
+++ b/clang/test/CXX/module/module.unit/p7/Inputs/h8.h
@@ -0,0 +1,4 @@
+#ifndef H8
+#define H8
+void foo();
+#endif

diff  --git a/clang/test/CXX/module/module.unit/p7/Inputs/m8.cppm 
b/clang/test/CXX/module/module.unit/p7/Inputs/m8.cppm
new file mode 100644
index 0..ef0c6c63462c1
--- /dev/null
+++ b/clang/test/CXX/module/module.unit/p7/Inputs/m8.cppm
@@ -0,0 +1,7 @@
+module;
+#include "h8.h"
+export module m8;
+
+extern "C++" {
+void bar();
+}

diff  --git a/clang/test/CXX/module/module.unit/p7/t8.cpp 
b/clang/test/CXX/module/module.unit/p7/t8.cpp
new file mode 100644
index 0..8310fc759f839
--- /dev/null
+++ b/clang/test/CXX/module/module.unit/p7/t8.cpp
@@ -0,0 +1,7 @@
+// RUN: rm -fr %t
+// RUN: mkdir %t
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %S/Inputs/m8.cppm 
-I%S/Inputs -o %t/m8.pcm
+// RUN: %clang_cc1 -std=c++20 -I%S/Inputs/ -fprebuilt-module-path=%t %s 
-verify -fsyntax-only
+// expected-no-diagnostics
+export module t8;
+import m8;



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


[clang] 8c930ce - [NFC] [Modules] Refactor ODR checking for default template argument in

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

Author: Chuanqi Xu
Date: 2022-02-10T10:10:10+08:00
New Revision: 8c930cef0e4c6d76fdb483051187c59d5aea6db7

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

LOG: [NFC] [Modules] Refactor ODR checking for default template argument in
ASTReader

This is a cleanup to reduce the lines of code to handle default template
argument in ASTReader.

Reviewed By: urnathan

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

Added: 


Modified: 
clang/include/clang/Basic/DiagnosticSerializationKinds.td
clang/lib/Serialization/ASTReader.cpp

Removed: 




diff  --git a/clang/include/clang/Basic/DiagnosticSerializationKinds.td 
b/clang/include/clang/Basic/DiagnosticSerializationKinds.td
index f15a935d2af1b..3fcdb616bd21a 100644
--- a/clang/include/clang/Basic/DiagnosticSerializationKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSerializationKinds.td
@@ -154,16 +154,15 @@ def err_module_odr_violation_template_parameter : Error <
   "%select{definition in module '%2'|defined here}1 found "
   "%select{"
   "unnamed template parameter|"
-  "template parameter %4|"
+  "template parameter %5|"
   "template parameter with %select{no |}4default argument|"
   "template parameter with default argument}3">;
 
-
 def note_module_odr_violation_template_parameter : Note <
   "but in '%0' found "
   "%select{"
   "unnamed template parameter %2|"
-  "template parameter %2|"
+  "template parameter %3|"
   "template parameter with %select{no |}2default argument|"
   "template parameter with 
diff erent default argument}1">;
 

diff  --git a/clang/lib/Serialization/ASTReader.cpp 
b/clang/lib/Serialization/ASTReader.cpp
index d806fb9e19494..0ea904b275f25 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10134,13 +10134,6 @@ void ASTReader::diagnoseOdrViolations() {
   assert(!FirstTemplate == !SecondTemplate &&
  "Both pointers should be null or non-null");
 
-  enum ODRTemplateDifference {
-ParamEmptyName,
-ParamName,
-ParamSingleDefaultArgument,
-ParamDifferentDefaultArgument,
-  };
-
   if (FirstTemplate && SecondTemplate) {
 DeclHashes FirstTemplateHashes;
 DeclHashes SecondTemplateHashes;
@@ -10166,155 +10159,60 @@ void ASTReader::diagnoseOdrViolations() {
   if (FirstIt->second == SecondIt->second)
 continue;
 
-  auto ODRDiagTemplateError = [FirstRecord, &FirstModule, this](
-  SourceLocation Loc, SourceRange 
Range,
-  ODRTemplateDifference DiffType) {
-return Diag(Loc, diag::err_module_odr_violation_template_parameter)
-   << FirstRecord << FirstModule.empty() << FirstModule << 
Range
-   << DiffType;
-  };
-  auto ODRDiagTemplateNote = [&SecondModule, this](
- SourceLocation Loc, SourceRange Range,
- ODRTemplateDifference DiffType) {
-return Diag(Loc, 
diag::note_module_odr_violation_template_parameter)
-   << SecondModule << Range << DiffType;
-  };
-
   const NamedDecl* FirstDecl = cast(FirstIt->first);
   const NamedDecl* SecondDecl = cast(SecondIt->first);
 
   assert(FirstDecl->getKind() == SecondDecl->getKind() &&
  "Parameter Decl's should be the same kind.");
 
+  enum ODRTemplateDifference {
+ParamEmptyName,
+ParamName,
+ParamSingleDefaultArgument,
+ParamDifferentDefaultArgument,
+  };
+
+  auto hasDefaultArg = [](const NamedDecl *D) {
+if (auto *TTP = dyn_cast(D))
+  return TTP->hasDefaultArgument() &&
+  !TTP->defaultArgumentWasInherited();
+if (auto *NTTP = dyn_cast(D))
+  return NTTP->hasDefaultArgument() &&
+  !NTTP->defaultArgumentWasInherited();
+auto *TTP = cast(D);
+return TTP->hasDefaultArgument() &&
+!TTP->defaultArgumentWasInherited();
+  };
+  bool hasFirstArg = hasDefaultArg(FirstDecl);
+  bool hasSecondArg = hasDefaultArg(SecondDecl);
+
+  ODRTemplateDifference ErrDiffType;
+  ODRTemplateDifference NoteDiffType;
+
   DeclarationName FirstName = FirstDecl->getDeclName();
   DeclarationName SecondName = SecondDecl->getDeclName();
 
   if (FirstName != SecondName) {
-const bool FirstNameEmpty =
+bool FirstNameEmpty =
 FirstName.isIdentifier() && !FirstName.getAsIdentifierInfo();
-const bool SecondNameEmpty =
- 

[clang] d796901 - [C++20] [Modules] Check if modulemap exists to avoid crash in implicit used C++ module

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

Author: ZezhengLi
Date: 2022-02-11T11:22:50+08:00
New Revision: d7969012e40a0906512b5bb304fc8b245386bb15

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

LOG: [C++20] [Modules] Check if modulemap exists to avoid crash in implicit 
used C++ module

An impilt used of C++ module without prebuild path may cause crash.

For example:

```
// ./dir1/C.cppm
export module C;
// ./dir2/B.cppm
export module B;
import C;
// ./A.cpp
import B;
import C;
```

When we compile A.cpp without the prebuild path of C.pcm, the compiler
will crash.

```
clang++ -std=c++20 --precompile -c ./dir1/C.cppm -o ./dir1/C.pcm
clang++ -std=c++20 --precompile -fprebuilt-module-path=./dir2  -c
./dir2/B.cppm -o ./dir2/B.pcm
clang++ -std=c++20 -fprebuilt-module-path=./dir2 A.cpp

```

The prebuilt path of module C is cached when import module B, and in the
function HeaderSearch::getCachedModuleFileName, the compiler try to get
the filename by modulemap without check if modulemap exists, and there
is no modulemap in C++ module.

Reviewed By: ChuanqiXu

Differential review: https://reviews.llvm.org/D119426

Added: 
clang/test/Modules/implicit-module-with-missing-path.cpp

Modified: 
clang/lib/Lex/HeaderSearch.cpp

Removed: 




diff  --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp
index 19e284f04b38..500f5693911b 100644
--- a/clang/lib/Lex/HeaderSearch.cpp
+++ b/clang/lib/Lex/HeaderSearch.cpp
@@ -172,6 +172,10 @@ void HeaderSearch::getHeaderMapFileNames(
 std::string HeaderSearch::getCachedModuleFileName(Module *Module) {
   const FileEntry *ModuleMap =
   getModuleMap().getModuleMapFileForUniquing(Module);
+  // The ModuleMap maybe a nullptr, when we load a cached C++ module without
+  // *.modulemap file. In this case, just return an empty string.
+  if (ModuleMap == nullptr)
+return {};
   return getCachedModuleFileName(Module->Name, ModuleMap->getName());
 }
 

diff  --git a/clang/test/Modules/implicit-module-with-missing-path.cpp 
b/clang/test/Modules/implicit-module-with-missing-path.cpp
new file mode 100644
index ..2ce67d58d3d6
--- /dev/null
+++ b/clang/test/Modules/implicit-module-with-missing-path.cpp
@@ -0,0 +1,12 @@
+// This tests that the compiler wouldn't crash if the module path misses
+
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/subdir
+// RUN: echo "export module C;" >> %t/subdir/C.cppm
+// RUN: echo -e "export module B;\nimport C;" >> %t/B.cppm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/subdir/C.cppm -o 
%t/subdir/C.pcm
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface 
-fprebuilt-module-path=%t/subdir %t/B.cppm -o %t/B.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %s -fsyntax-only 
-verify
+
+import B;
+import C; // expected-error {{module 'C' is needed but has not been provided, 
and implicit use of module files is disabled}}



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


[clang] 25cdf87 - [NFC] Update new warning to test

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

Author: Chuanqi Xu
Date: 2022-02-16T10:51:56+08:00
New Revision: 25cdf87b13eb990eb84d31211280f4b0d5d470b3

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

LOG: [NFC] Update new warning  to test

This tries to fix the broke test introduced in
4bafe65c2b2f1ce745894a509a6.

Added: 


Modified: 
clang/test/Misc/warning-flags.c

Removed: 




diff  --git a/clang/test/Misc/warning-flags.c b/clang/test/Misc/warning-flags.c
index a9e0a784c5c81..1b65af4c8e3e5 100644
--- a/clang/test/Misc/warning-flags.c
+++ b/clang/test/Misc/warning-flags.c
@@ -18,7 +18,7 @@ This test serves two purposes:
 
 The list of warnings below should NEVER grow.  It should gradually shrink to 0.
 
-CHECK: Warnings without flags (67):
+CHECK: Warnings without flags (68):
 
 CHECK-NEXT:   ext_expected_semi_decl_list
 CHECK-NEXT:   ext_explicit_specialization_storage_class
@@ -65,6 +65,7 @@ CHECK-NEXT:   warn_missing_dependent_template_keyword
 CHECK-NEXT:   warn_missing_whitespace_after_macro_name
 CHECK-NEXT:   warn_mt_message
 CHECK-NEXT:   warn_no_constructor_for_refconst
+CHECK-NEXT:   warn_no_support_for_eval_method_source_on_m32
 CHECK-NEXT:   warn_not_compound_assign
 CHECK-NEXT:   warn_objc_property_copy_missing_on_block
 CHECK-NEXT:   warn_objc_protocol_qualifier_missing_id



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


[clang] d30ca5e - [C++20] [Coroutines] Implement return value optimization for get_return_object

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

Author: Chuanqi Xu
Date: 2022-02-16T13:38:00+08:00
New Revision: d30ca5e2e23fe50dcd8d5d602bf7cfc61b4c1561

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

LOG: [C++20] [Coroutines] Implement return value optimization for 
get_return_object

This patch tries to implement RVO for coroutine's return object got from
get_return_object.
>From [dcl.fct.def.coroutine]/p7 we could know that the return value of
get_return_object is either a reference or a prvalue. So it makes sense
to do copy elision for the return value. The return object should be
constructed directly into the storage where they would otherwise be
copied/moved to.

Test Plan: folly, check-all

Reviewed By: junparser

Differential revision: https://reviews.llvm.org/D117087

Added: 
clang/test/CodeGenCoroutines/coro-gro2-exp-namespace.cpp
clang/test/CodeGenCoroutines/coro-gro2.cpp
clang/test/SemaCXX/coroutine-no-move-ctor.cpp

Modified: 
clang/include/clang/AST/StmtCXX.h
clang/lib/AST/StmtCXX.cpp
clang/lib/CodeGen/CGCoroutine.cpp
clang/lib/Sema/SemaCoroutine.cpp
clang/lib/Sema/TreeTransform.h
clang/test/CodeGenCoroutines/coro-alloc-exp-namespace.cpp
clang/test/CodeGenCoroutines/coro-alloc.cpp
clang/test/CodeGenCoroutines/coro-gro-exp-namespace.cpp
clang/test/CodeGenCoroutines/coro-gro.cpp
clang/test/CodeGenCoroutines/coro-promise-dtor-exp-namespace.cpp
clang/test/CodeGenCoroutines/coro-promise-dtor.cpp
clang/test/SemaCXX/coroutines-exp-namespace.cpp
clang/test/SemaCXX/coroutines.cpp

Removed: 
clang/test/CodeGenCoroutines/coro-gro-nrvo-exp-namespace.cpp
clang/test/CodeGenCoroutines/coro-gro-nrvo.cpp



diff  --git a/clang/include/clang/AST/StmtCXX.h 
b/clang/include/clang/AST/StmtCXX.h
index 4d1f3e8ef255c..5ccf6904048e3 100644
--- a/clang/include/clang/AST/StmtCXX.h
+++ b/clang/include/clang/AST/StmtCXX.h
@@ -327,7 +327,6 @@ class CoroutineBodyStmt final
 Allocate,  ///< Coroutine frame memory allocation.
 Deallocate,///< Coroutine frame memory deallocation.
 ReturnValue,   ///< Return value for thunk function: p.get_return_object().
-ResultDecl,///< Declaration holding the result of get_return_object.
 ReturnStmt,///< Return statement for the thunk function.
 ReturnStmtOnAllocFailure, ///< Return statement if allocation failed.
 FirstParamMove ///< First offset for move construction of parameter copies.
@@ -354,7 +353,6 @@ class CoroutineBodyStmt final
 Expr *Allocate = nullptr;
 Expr *Deallocate = nullptr;
 Expr *ReturnValue = nullptr;
-Stmt *ResultDecl = nullptr;
 Stmt *ReturnStmt = nullptr;
 Stmt *ReturnStmtOnAllocFailure = nullptr;
 ArrayRef ParamMoves;
@@ -409,7 +407,11 @@ class CoroutineBodyStmt final
   Expr *getReturnValueInit() const {
 return cast(getStoredStmts()[SubStmt::ReturnValue]);
   }
-  Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; }
+  Expr *getReturnValue() const {
+assert(getReturnStmt());
+auto *RS = cast(getReturnStmt());
+return RS->getRetValue();
+  }
   Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; }
   Stmt *getReturnStmtOnAllocFailure() const {
 return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure];

diff  --git a/clang/lib/AST/StmtCXX.cpp b/clang/lib/AST/StmtCXX.cpp
index 060d090fc06ac..33b0421ad1016 100644
--- a/clang/lib/AST/StmtCXX.cpp
+++ b/clang/lib/AST/StmtCXX.cpp
@@ -118,7 +118,6 @@ 
CoroutineBodyStmt::CoroutineBodyStmt(CoroutineBodyStmt::CtorArgs const &Args)
   SubStmts[CoroutineBodyStmt::Allocate] = Args.Allocate;
   SubStmts[CoroutineBodyStmt::Deallocate] = Args.Deallocate;
   SubStmts[CoroutineBodyStmt::ReturnValue] = Args.ReturnValue;
-  SubStmts[CoroutineBodyStmt::ResultDecl] = Args.ResultDecl;
   SubStmts[CoroutineBodyStmt::ReturnStmt] = Args.ReturnStmt;
   SubStmts[CoroutineBodyStmt::ReturnStmtOnAllocFailure] =
   Args.ReturnStmtOnAllocFailure;

diff  --git a/clang/lib/CodeGen/CGCoroutine.cpp 
b/clang/lib/CodeGen/CGCoroutine.cpp
index c1763cbbc5a05..96696ebf2903c 100644
--- a/clang/lib/CodeGen/CGCoroutine.cpp
+++ b/clang/lib/CodeGen/CGCoroutine.cpp
@@ -465,72 +465,6 @@ struct CallCoroDelete final : public EHScopeStack::Cleanup 
{
 };
 }
 
-namespace {
-struct GetReturnObjectManager {
-  CodeGenFunction &CGF;
-  CGBuilderTy &Builder;
-  const CoroutineBodyStmt &S;
-
-  Address GroActiveFlag;
-  CodeGenFunction::AutoVarEmission GroEmission;
-
-  GetReturnObjectManager(CodeGenFunction &CGF, const CoroutineBodyStmt &S)
-  : CGF(CGF), Builder(CGF.Builder), S(S), 
GroActiveFlag(Address::invalid()),
-GroEmission(CodeGenFunction::AutoVarEmission::invalid()) {}
-
-  // The gro variable has to outlive coroutine frame and coroutine promise, 
but,
-  // it 

[clang] 4b95a5a - [Modules] Add ODR Check for concepts

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

Author: Chuanqi Xu
Date: 2022-07-12T23:45:53+08:00
New Revision: 4b95a5a772530f78326941f26e5cb2c33212460f

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

LOG: [Modules] Add ODR Check for concepts

Closing https://github.com/llvm/llvm-project/issues/56310

Previously we don't check the contents of concept so it might merge
inconsistent results.

Important Note: this patch might break existing code but the behavior
might be right.

Reviewed By: erichkeane

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

Added: 
clang/test/Modules/concept_differ.cpp
clang/test/Modules/concept_differ.cppm

Modified: 
clang/docs/ReleaseNotes.rst
clang/lib/AST/ASTContext.cpp

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f5aecff0d2647..2898a6c1d9339 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -183,6 +183,9 @@ Bug Fixes
   initializer is not allowed this is now diagnosed as an error.
 - Clang now correctly emits symbols for implicitly instantiated constexpr
   template function. Fixes `Issue 55560 
`_.
+- Clang now checks ODR violations when merging concepts from 
diff erent modules.
+  Note that this may possibly break existing code, and is done so 
intentionally.
+  Fixes `Issue 56310 `_.
 
 Improvements to Clang's diagnostics
 ^^^

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 748fa6ebf1d6c..aa29ce7f13840 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -6561,6 +6561,20 @@ bool ASTContext::isSameEntity(const NamedDecl *X, const 
NamedDecl *Y) const {
   // and patterns match.
   if (const auto *TemplateX = dyn_cast(X)) {
 const auto *TemplateY = cast(Y);
+
+// ConceptDecl wouldn't be the same if their constraint expression 
diff ers.
+if (const auto *ConceptX = dyn_cast(X)) {
+  const auto *ConceptY = cast(Y);
+  const Expr *XCE = ConceptX->getConstraintExpr();
+  const Expr *YCE = ConceptY->getConstraintExpr();
+  assert(XCE && YCE && "ConceptDecl without constraint expression?");
+  llvm::FoldingSetNodeID XID, YID;
+  XCE->Profile(XID, *this, /*Canonical=*/true);
+  YCE->Profile(YID, *this, /*Canonical=*/true);
+  if (XID != YID)
+return false;
+}
+
 return isSameEntity(TemplateX->getTemplatedDecl(),
 TemplateY->getTemplatedDecl()) &&
isSameTemplateParameterList(TemplateX->getTemplateParameters(),

diff  --git a/clang/test/Modules/concept_
diff er.cpp b/clang/test/Modules/concept_
diff er.cpp
new file mode 100644
index 0..23c7d4c5ecf9a
--- /dev/null
+++ b/clang/test/Modules/concept_
diff er.cpp
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -x c++ -std=c++20 -fmodules -fmodules-cache-path=%t 
-fmodule-map-file=%t/module.map %t/foo.cpp -verify
+
+//--- module.map
+module "foo" {
+  export * 
+  header "foo.h"
+}
+module "bar" {
+  export * 
+  header "bar.h"
+}
+
+//--- foo.h
+template 
+concept A = true;
+
+//--- bar.h
+template 
+concept A = false;
+
+//--- foo.cpp
+#include "bar.h"
+#include "foo.h"
+
+template  void foo() requires A {}  // expected-error 
1+{{reference to 'A' is ambiguous}}
+// expected-note@* 
1+{{candidate found by name lookup}}
+
+int main() {
+  foo();
+  return 0;
+}

diff  --git a/clang/test/Modules/concept_
diff er.cppm b/clang/test/Modules/concept_
diff er.cppm
new file mode 100644
index 0..ccb29d26e53d1
--- /dev/null
+++ b/clang/test/Modules/concept_
diff er.cppm
@@ -0,0 +1,39 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -x c++ -std=c++20 %t/A.cppm -I%t -emit-module-interface -o 
%t/A.pcm
+// RUN: %clang_cc1 -x c++ -std=c++20 %t/B.cppm -I%t -emit-module-interface -o 
%t/B.pcm
+// RUN: %clang_cc1 -x c++ -std=c++20 -fprebuilt-module-path=%t %t/foo.cpp 
-verify
+
+//--- foo.h
+template 
+concept A = true;
+
+//--- bar.h
+template 
+concept A = false;
+
+//--- A.cppm
+module;
+#include "foo.h"
+export module A;
+export using ::A;
+
+//--- B.cppm
+module;
+#include "bar.h"
+export module B;
+export using ::A;
+
+//--- foo.cpp
+import A;
+import B;
+
+template  void foo() requires A {}  // expected-error 
1+{{reference to 'A' is ambiguous}}
+// expected-note@* 
1+{{candidate found by name lookup}}
+
+int main() {
+  foo();
+  return 0;
+}



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

[clang] f6b0ae1 - [AST] Accept identical TypeConstraint referring to other template

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

Author: Chuanqi Xu
Date: 2022-07-12T23:57:44+08:00
New Revision: f6b0ae144ed8085618c12ba83d95affd786e6a49

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

LOG: [AST] Accept identical TypeConstraint referring to other template
parameters.

The current implementation to judge the similarity of TypeConstraint in
ASTContext::isSameTemplateParameter is problematic, it couldn't handle
the following case:

```C++
template <__integer_like _Tp, C<_Tp> Sentinel>
constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
return __t;
}
```

When we see 2 such declarations from different modules, we would judge
their similarity by `ASTContext::isSame*` methods. But problems come for
the TypeConstraint. Originally, we would profile each argument one by
one. But it is not right. Since the profiling result of `_Tp` would
refer to two different template type declarations. So it would get
different results. It is right since the `_Tp` in different modules
refers to different declarations indeed. So the same declaration in
different modules would meet incorrect our-checking results.

It is not the thing we want. We want to know if the TypeConstraint have
the same expression.

Reviewer: vsapsai, ilya-biryukov

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

Added: 


Modified: 
clang/include/clang/AST/ASTContext.h
clang/lib/AST/ASTContext.cpp
clang/test/Modules/concept.cppm

Removed: 




diff  --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index 87b5a6053f1f2..85eba45e4de6e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -130,6 +130,7 @@ class TemplateDecl;
 class TemplateParameterList;
 class TemplateTemplateParmDecl;
 class TemplateTypeParmDecl;
+class TypeConstraint;
 class UnresolvedSetIterator;
 class UsingShadowDecl;
 class VarTemplateDecl;
@@ -2664,6 +2665,18 @@ class ASTContext : public RefCountedBase {
   /// that they may be used in declarations of the same template.
   bool isSameTemplateParameter(const NamedDecl *X, const NamedDecl *Y) const;
 
+  /// Determine whether two 'requires' expressions are similar enough that they
+  /// may be used in re-declarations.
+  ///
+  /// Use of 'requires' isn't mandatory, works with constraints expressed in
+  /// other ways too.
+  bool isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const;
+
+  /// Determine whether two type contraint are similar enough that they could
+  /// used in declarations of the same template.
+  bool isSameTypeConstraint(const TypeConstraint *XTC,
+const TypeConstraint *YTC) const;
+
   /// Determine whether two default template arguments are similar enough
   /// that they may be used in declarations of the same template.
   bool isSameDefaultTemplateArgument(const NamedDecl *X,

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index aa29ce7f13840..cfd7bf6045422 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -6218,6 +6218,57 @@ bool ASTContext::hasSameTemplateName(const TemplateName 
&X,
  getCanonicalTemplateName(Y).getAsVoidPointer();
 }
 
+bool ASTContext::isSameConstraintExpr(const Expr *XCE, const Expr *YCE) const {
+  if (!XCE != !YCE)
+return false;
+
+  if (!XCE)
+return true;
+
+  llvm::FoldingSetNodeID XCEID, YCEID;
+  XCE->Profile(XCEID, *this, /*Canonical=*/true);
+  YCE->Profile(YCEID, *this, /*Canonical=*/true);
+  return XCEID == YCEID;
+}
+
+bool ASTContext::isSameTypeConstraint(const TypeConstraint *XTC,
+  const TypeConstraint *YTC) const {
+  if (!XTC != !YTC)
+return false;
+
+  if (!XTC)
+return true;
+
+  auto *NCX = XTC->getNamedConcept();
+  auto *NCY = YTC->getNamedConcept();
+  if (!NCX || !NCY || !isSameEntity(NCX, NCY))
+return false;
+  if (XTC->hasExplicitTemplateArgs() != YTC->hasExplicitTemplateArgs())
+return false;
+  if (XTC->hasExplicitTemplateArgs())
+if (XTC->getTemplateArgsAsWritten()->NumTemplateArgs !=
+YTC->getTemplateArgsAsWritten()->NumTemplateArgs)
+  return false;
+
+  // Compare slowly by profiling.
+  //
+  // We couldn't compare the profiling result for the template
+  // args here. Consider the following example in 
diff erent modules:
+  //
+  // template <__integer_like _Tp, C<_Tp> Sentinel>
+  // constexpr _Tp operator()(_Tp &&__t, Sentinel &&last) const {
+  //   return __t;
+  // }
+  //
+  // When we compare the profiling result for `C<_Tp>` in 
diff erent
+  // modules, it will compare the type of `_Tp` in 
diff erent modules.
+  // However, the type of `_Tp` in 
diff erent modules refer to 
diff erent
+  // types here naturally. So we couldn't compare the profiling result
+  // f

[clang] 5791bcf - [AST] [Modules] Handle full cases of DefaultArgStorage::setInherited

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

Author: Chuanqi Xu
Date: 2022-07-13T00:13:56+08:00
New Revision: 5791bcf9db0a3ec8bbce586dd99fce71fd773134

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

LOG: [AST] [Modules] Handle full cases of DefaultArgStorage::setInherited

There were two assertions in DefaultArgStorage::setInherited previously.
It requires the DefaultArgument is either empty or an argument value. It
would crash if it has a pointer refers to the previous declaration or
contains a chain to the previous declaration.

But there are edge cases could hit them actually. One is
InheritDefaultArguments.cppm that I found recently. Another one is pr31469.cpp,
which was created fives years ago.

This patch tries to fix the two failures by handling full cases in
DefaultArgStorage::setInherited.

This is guaranteed to not introduce any breaking change since it lives
in the path we wouldn't touch before. And the added assertions for
sameness should keep the correctness.

Reviewed By: v.g.vassilev

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

Added: 


Modified: 
clang/include/clang/AST/DeclTemplate.h
clang/test/Modules/InheritDefaultArguments.cppm
clang/test/Modules/Inputs/PR31469/textual.h

Removed: 




diff  --git a/clang/include/clang/AST/DeclTemplate.h 
b/clang/include/clang/AST/DeclTemplate.h
index 3e4ccda73111a..725bb0bced9c5 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -15,6 +15,7 @@
 #define LLVM_CLANG_AST_DECLTEMPLATE_H
 
 #include "clang/AST/ASTConcept.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclCXX.h"
@@ -373,11 +374,19 @@ class DefaultArgStorage {
 
   /// Set that the default argument was inherited from another parameter.
   void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) {
-assert(!isInherited() && "default argument already inherited");
 InheritedFrom = getParmOwningDefaultArg(InheritedFrom);
 if (!isSet())
   ValueOrInherited = InheritedFrom;
-else
+else if (auto *D = ValueOrInherited.template dyn_cast()) {
+  assert(C.isSameDefaultTemplateArgument(D, InheritedFrom));
+  ValueOrInherited =
+  new (allocateDefaultArgStorageChain(C)) Chain{InheritedFrom, get()};
+} else if (auto *Inherited =
+   ValueOrInherited.template dyn_cast()) {
+  assert(C.isSameDefaultTemplateArgument(Inherited->PrevDeclWithDefaultArg,
+ InheritedFrom));
+  Inherited->PrevDeclWithDefaultArg = InheritedFrom;
+} else
   ValueOrInherited = new (allocateDefaultArgStorageChain(C))
   Chain{InheritedFrom, ValueOrInherited.template get()};
   }

diff  --git a/clang/test/Modules/InheritDefaultArguments.cppm 
b/clang/test/Modules/InheritDefaultArguments.cppm
index bbd5ad4c96a56..0afb46319ff85 100644
--- a/clang/test/Modules/InheritDefaultArguments.cppm
+++ b/clang/test/Modules/InheritDefaultArguments.cppm
@@ -10,7 +10,10 @@ template 
 class Templ;
 
 template 
-class Templ {};
+class Templ {
+public:
+Templ(T t) {}
+};
 
 template 
 Templ(T t) -> Templ;
@@ -26,3 +29,6 @@ module;
 #include "foo.h"
 export module X;
 import A;
+void foo() {
+Templ t(0);
+}

diff  --git a/clang/test/Modules/Inputs/PR31469/textual.h 
b/clang/test/Modules/Inputs/PR31469/textual.h
index abdc662fb5ef8..3eba9be8431d9 100644
--- a/clang/test/Modules/Inputs/PR31469/textual.h
+++ b/clang/test/Modules/Inputs/PR31469/textual.h
@@ -4,7 +4,7 @@ namespace __1 {
   template  class allocator;
   template > class list;
   template  class __list_iterator {
-//template  friend class list; // causes another crash in 
ASTDeclReader::attachPreviousDecl
+template  friend class list;
 template  friend class list;
   };
   template  class __list_imp {};



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


[clang] 2f1555f - [C++20] [Modules] Handle reachability for enum class

2022-07-15 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-07-15T15:57:04+08:00
New Revision: 2f1555fb11d74376347ee94eb3af258e047f68ce

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

LOG: [C++20] [Modules] Handle reachability for enum class

In previous reachability patch, we missed the case for enum class.
Trying to handle it in this patch and add the corresponding tests.

Added: 
clang/test/Modules/enum-class.cppm

Modified: 
clang/lib/Sema/SemaType.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 3edce941c3817..3ab5d26a9a750 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8669,12 +8669,13 @@ bool Sema::hasAcceptableDefinition(NamedDecl *D, 
NamedDecl **Suggested,
   // of it will do.
   *Suggested = nullptr;
   for (auto *Redecl : ED->redecls()) {
-if (isVisible(Redecl))
+if (isAcceptable(Redecl, Kind))
   return true;
 if (Redecl->isThisDeclarationADefinition() ||
 (Redecl->isCanonicalDecl() && !*Suggested))
   *Suggested = Redecl;
   }
+
   return false;
 }
 D = ED->getDefinition();

diff  --git a/clang/test/Modules/enum-class.cppm 
b/clang/test/Modules/enum-class.cppm
new file mode 100644
index 0..01ae8c0d8814d
--- /dev/null
+++ b/clang/test/Modules/enum-class.cppm
@@ -0,0 +1,26 @@
+// Checks for reachability for C++11 enum class properly
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify 
-fsyntax-only
+
+//--- foo.h
+enum class foo {
+a, b, c
+};
+
+//--- A.cppm
+module;
+#include "foo.h"
+export module A;
+export foo func();
+
+//--- Use.cpp
+// expected-no-diagnostics
+import A;
+void bar() {
+auto f = func();
+}



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


[clang] 4983fdf - [C++20] [Modules] Handle reachability for deduction guide

2022-07-18 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-07-18T15:46:26+08:00
New Revision: 4983fdfec0443cf388adb87b816b7298a7bdf273

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

LOG: [C++20] [Modules] Handle reachability for deduction guide

Previously, we forget to handle reachability for deduction guide.
The deduction guide is a hint to the compiler. And the deduction guide
should be able to use if the corresponding template decl is reachable.

Added: 
clang/test/Modules/deduction-guide.cppm
clang/test/Modules/deduction-guide2.cppm
clang/test/Modules/deduction-guide3.cppm

Modified: 
clang/lib/Sema/SemaLookup.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 47c7a61f8072f..aa87a33ce8ae1 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2087,6 +2087,13 @@ bool LookupResult::isAvailableForLookup(Sema &SemaRef, 
NamedDecl *ND) {
   if (isVisible(SemaRef, ND))
 return true;
 
+  // Deduction guide lives in namespace scope generally, but it is just a
+  // hint to the compilers. What we actually lookup for is the generated member
+  // of the corresponding template. So it is sufficient to check the
+  // reachability of the template decl.
+  if (auto *DeductionGuide = ND->getDeclName().getCXXDeductionGuideTemplate())
+return SemaRef.hasReachableDefinition(DeductionGuide);
+
   auto *DC = ND->getDeclContext();
   // If ND is not visible and it is at namespace scope, it shouldn't be found
   // by name lookup.

diff  --git a/clang/test/Modules/deduction-guide.cppm 
b/clang/test/Modules/deduction-guide.cppm
new file mode 100644
index 0..9c959a71365da
--- /dev/null
+++ b/clang/test/Modules/deduction-guide.cppm
@@ -0,0 +1,30 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o 
%t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify 
-fsyntax-only
+
+//--- foo.h
+template 
+class Templ {
+public:
+Templ(T a) {}
+};
+
+template
+Templ(T t) -> Templ;
+
+//--- Templ.cppm
+module;
+#include "foo.h"
+export module Templ;
+export using ::Templ;
+
+//--- Use.cpp
+// expected-no-diagnostics
+import Templ;
+void func() {
+Templ t(5);
+}
+

diff  --git a/clang/test/Modules/deduction-guide2.cppm 
b/clang/test/Modules/deduction-guide2.cppm
new file mode 100644
index 0..a163c36568310
--- /dev/null
+++ b/clang/test/Modules/deduction-guide2.cppm
@@ -0,0 +1,25 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o 
%t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify 
-fsyntax-only
+
+//--- Templ.cppm
+export module Templ;
+export template 
+class Templ {
+public:
+Templ(T a) {}
+};
+
+template
+Templ(T t) -> Templ;
+
+//--- Use.cpp
+// expected-no-diagnostics
+import Templ;
+void func() {
+Templ t(5);
+}
+

diff  --git a/clang/test/Modules/deduction-guide3.cppm 
b/clang/test/Modules/deduction-guide3.cppm
new file mode 100644
index 0..8fa08a0625d7c
--- /dev/null
+++ b/clang/test/Modules/deduction-guide3.cppm
@@ -0,0 +1,26 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/Templ.cppm -emit-module-interface -o 
%t/Templ.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify 
-fsyntax-only
+
+//--- Templ.cppm
+export module Templ;
+template 
+class Templ {
+public:
+Templ(T a) {}
+};
+
+template
+Templ(T t) -> Templ;
+
+//--- Use.cpp
+import Templ;
+void func() {
+Templ t(5); // expected-error {{declaration of 'Templ' must be imported 
from module 'Templ' before it is required}}
+// expected-error@-1 {{unknown type name 'Templ'}}
+// expected-n...@templ.cppm:3 {{declaration here is not 
visible}}
+}
+



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


[clang] ea623af - [C++20] [Modules] Avoid inifinite loop when iterating default args

2022-07-21 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-07-21T17:25:05+08:00
New Revision: ea623af7c90f0c02fed72010a018cb1e259cca8d

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

LOG: [C++20] [Modules] Avoid inifinite loop when iterating default args

Currently, clang may meet an infinite loop in a very tricky case when it
iterates the default args. This patch tries to fix this by adding a
`fixed` check.

Added: 
clang/test/Modules/inherited_arg.cppm

Modified: 
clang/lib/Sema/SemaLookup.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index aa87a33ce8ae1..242e1f81d75c0 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1615,7 +1615,10 @@ hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D,
   if (!D->hasDefaultArgument())
 return false;
 
-  while (D) {
+  llvm::SmallDenseSet Visited;
+  while (D && !Visited.count(D)) {
+Visited.insert(D);
+
 auto &DefaultArg = D->getDefaultArgStorage();
 if (!DefaultArg.isInherited() && S.isAcceptable(D, Kind))
   return true;
@@ -1625,7 +1628,8 @@ hasAcceptableDefaultArgument(Sema &S, const ParmDecl *D,
   Modules->push_back(S.getOwningModule(NonConstD));
 }
 
-// If there was a previous default argument, maybe its parameter is 
visible.
+// If there was a previous default argument, maybe its parameter is
+// acceptable.
 D = DefaultArg.getInheritedFrom();
   }
   return false;

diff  --git a/clang/test/Modules/inherited_arg.cppm 
b/clang/test/Modules/inherited_arg.cppm
new file mode 100644
index 0..eb66b70cdce33
--- /dev/null
+++ b/clang/test/Modules/inherited_arg.cppm
@@ -0,0 +1,78 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/A-B.cppm -I%t -emit-module-interface -o 
%t/A-B.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A-C.cppm -I%t -emit-module-interface -o 
%t/A-C.pcm
+// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface 
-fprebuilt-module-path=%t -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp -verify 
-fsyntax-only
+
+//--- foo.h
+template 
+class pair {};
+
+template 
+class allocator {};
+
+template 
+class my_traits {};
+
+template  > >
+class unordered_map
+{
+public:
+unordered_map() {}
+};
+
+template struct my_enable_if {};
+template struct my_enable_if { using type = T; };
+template using my_enable_if_t = typename 
my_enable_if::type;
+
+template>,
+ class = my_enable_if_t<_InputIterator::value>>
+unordered_map(_InputIterator, _InputIterator, _Allocator = _Allocator())
+  -> unordered_map, my_traits<_InputIterator>, 
_Allocator>;
+
+template ,
+  class _Allocator = allocator<_CharT> >
+class basic_string;
+typedef basic_string, allocator > string;
+
+template
+class basic_string
+{
+public:
+basic_string();
+
+template > 
+basic_string(_InputIterator __first, _InputIterator __last, const 
_Allocator& __a);
+
+void resize(unsigned __n, _CharT __c);
+};
+
+extern template void basic_string::resize(unsigned, char);
+
+//--- A-B.cppm
+module;
+#include "foo.h"
+export module A:B;
+export using ::string;
+
+//--- A-C.cppm
+module;
+#include "foo.h"
+export module A:C;
+
+//--- A.cppm
+export module A;
+export import :B;
+export import :C;
+
+//--- Use.cpp
+import A;
+string s;
+::unordered_map mime_map; // expected-error {{missing '#include'; 
'unordered_map' must be declared before it is used}}
+// expected-note@* {{declaration here is 
not visible}}



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


[clang] 6d9b847 - [C++20] [Modules] Handle reachability for partial specialization

2022-07-22 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-07-22T17:03:38+08:00
New Revision: 6d9b84797c1c4bd00a2392043e9feea4ecebe482

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

LOG: [C++20] [Modules] Handle reachability for partial specialization

Previously we don't catch the reachability for partial specialization.
Handle them in this patch.

Added: 
clang/test/Modules/partial_specialization.cppm

Modified: 
clang/lib/Sema/SemaTemplate.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 171f005816b5c..95c83ebfaeab5 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4573,7 +4573,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
   void *InsertPos = nullptr;
   if (VarTemplateSpecializationDecl *Spec = Template->findSpecialization(
   Converted, InsertPos)) {
-checkSpecializationVisibility(TemplateNameLoc, Spec);
+checkSpecializationReachability(TemplateNameLoc, Spec);
 // If we already have a variable template specialization, return it.
 return Spec;
   }
@@ -4694,7 +4694,7 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, 
SourceLocation TemplateLoc,
   dyn_cast(InstantiationPattern))
 Decl->setInstantiationOf(D, InstantiationArgs);
 
-  checkSpecializationVisibility(TemplateNameLoc, Decl);
+  checkSpecializationReachability(TemplateNameLoc, Decl);
 
   assert(Decl && "No variable template specialization?");
   return Decl;

diff  --git a/clang/test/Modules/partial_specialization.cppm 
b/clang/test/Modules/partial_specialization.cppm
new file mode 100644
index 0..3a01857172112
--- /dev/null
+++ b/clang/test/Modules/partial_specialization.cppm
@@ -0,0 +1,34 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 -emit-module-interface %t/A.cppm -o %t/A.pcm
+// RUN: %clang_cc1 -std=c++20 -fprebuilt-module-path=%t %t/Use.cpp 
-fsyntax-only -verify
+//
+//--- foo.h
+template
+inline constexpr bool IsSame = false;
+
+template
+inline constexpr bool IsSame = true;
+
+template 
+class A {
+public:
+A();
+~A() noexcept(IsSame);
+};
+
+//--- A.cppm
+module;
+#include "foo.h"
+export module A;
+export using ::A;
+
+//--- Use.cpp
+import A;
+void bool_consume(bool b);
+void use() {
+A a{};
+bool_consume(IsSame); // expected-error {{use of undeclared identifier 
'IsSame'}}
+}



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


[clang] d351344 - [C++20] [Modules] Make the linkage consistent for class template and its

2022-07-25 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2022-07-25T17:57:02+08:00
New Revision: d35134485a6cd1b0e25b5dccd330678b9e57919d

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

LOG: [C++20] [Modules] Make the linkage consistent for class template and its
specialization

Previously in D120397, we've handled the linkage for function template
and its specialization. But we forgot to handle it for class templates
and their specialization. So we make it in the patch with the similar
approach.

Added: 


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

Removed: 




diff  --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index f88a2e3fa2681..aaba4345587b2 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -394,7 +394,6 @@ void LinkageComputer::mergeTemplateLV(
 shouldConsiderTemplateVisibility(fn, specInfo);
 
   FunctionTemplateDecl *temp = specInfo->getTemplate();
-
   // Merge information from the template declaration.
   LinkageInfo tempLV = getLVForDecl(temp, computation);
   // The linkage of the specialization should be consistent with the
@@ -468,11 +467,16 @@ void LinkageComputer::mergeTemplateLV(
 
   // Merge information from the template parameters, but ignore
   // visibility if we're only considering template arguments.
-
   ClassTemplateDecl *temp = spec->getSpecializedTemplate();
-  LinkageInfo tempLV =
+  // Merge information from the template declaration.
+  LinkageInfo tempLV = getLVForDecl(temp, computation);
+  // The linkage of the specialization should be consistent with the
+  // template declaration.
+  LV.setLinkage(tempLV.getLinkage());
+
+  LinkageInfo paramsLV =
 getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
-  LV.mergeMaybeWithVisibility(tempLV,
+  LV.mergeMaybeWithVisibility(paramsLV,
considerVisibility && !hasExplicitVisibilityAlready(computation));
 
   // Merge information from the template arguments.  We ignore
@@ -520,7 +524,6 @@ void LinkageComputer::mergeTemplateLV(LinkageInfo &LV,
 
   // Merge information from the template parameters, but ignore
   // visibility if we're only considering template arguments.
-
   VarTemplateDecl *temp = spec->getSpecializedTemplate();
   LinkageInfo tempLV =
 getLVForTemplateParameterList(temp->getTemplateParameters(), computation);
@@ -1077,7 +1080,6 @@ LinkageComputer::getLVForClassMember(const NamedDecl *D,
 
   // Finally, merge in information from the class.
   LV.mergeMaybeWithVisibility(classLV, considerClassVisibility);
-
   return LV;
 }
 

diff  --git a/clang/unittests/AST/DeclTest.cpp 
b/clang/unittests/AST/DeclTest.cpp
index 560c6b3ddf434..71835a0508fda 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -179,7 +179,14 @@ TEST(Decl, InConsistLinkageForTemplates) {
 void f() {}
 
 template <>
-void f() {})");
+void f() {}
+
+export template 
+class C {};
+
+template<>
+class C {};
+)");
 
   auto AST =
   tooling::buildASTFromCodeWithArgs(Code.code(), /*Args=*/{"-std=c++20"});
@@ -193,6 +200,18 @@ TEST(Decl, InConsistLinkageForTemplates) {
   const FunctionDecl *SpecializedF = Funcs[1].getNodeAs("f");
   EXPECT_EQ(TemplateF->getLinkageInternal(),
 SpecializedF->getLinkageInternal());
+
+  llvm::SmallVector ClassTemplates =
+  match(classTemplateDecl().bind("C"), Ctx);
+  llvm::SmallVector ClassSpecializations =
+  match(classTemplateSpecializationDecl().bind("C"), Ctx);
+
+  EXPECT_EQ(ClassTemplates.size(), 1U);
+  EXPECT_EQ(ClassSpecializations.size(), 1U);
+  const NamedDecl *TemplatedC = ClassTemplates[0].getNodeAs("C");
+  const NamedDecl *SpecializedC = 
ClassSpecializations[0].getNodeAs("C");
+  EXPECT_EQ(TemplatedC->getLinkageInternal(),
+SpecializedC->getLinkageInternal());
 }
 
 TEST(Decl, ModuleAndInternalLinkage) {



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


[clang] debd9bf - [NFC] follow up code cleanup after D123837

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

Author: Chuanqi Xu
Date: 2022-05-10T10:01:06+08:00
New Revision: debd9bf3f0198984cb4ae66c16758e0c8eeb2e9e

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

LOG: [NFC] follow up code cleanup after D123837

Reviewed By: iains

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

Added: 


Modified: 
clang/lib/Sema/SemaLookup.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 2a378741e7aa6..9f2e1eac41be6 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1565,27 +1565,27 @@ bool Sema::isUsableModule(const Module *M) {
   if (UsableModuleUnitsCache.count(M))
 return true;
 
-  // If M is the global module fragment of a module that we've not yet finished
-  // parsing, then M should be the global module fragment in current TU. So it
+  // If M is the global module fragment of the current translation unit. So it
   // should be usable.
   // [module.global.frag]p1:
   //   The global module fragment can be used to provide declarations that are
   //   attached to the global module and usable within the module unit.
-  if ((M->isGlobalModule() && !M->Parent) ||
-  // If M is the private module fragment, it is usable only if it is within
-  // the current module unit. And it must be the current parsing module 
unit
-  // if it is within the current module unit according to the grammar of 
the
-  // private module fragment.
-  // NOTE: This is covered by the following condition. The intention of the
-  // check is to avoid string comparison as much as possible.
-  (M->isPrivateModule() && M == getCurrentModule()) ||
+  if (M == GlobalModuleFragment ||
+  // If M is the module we're parsing, it should be usable. This covers the
+  // private module fragment. The private module fragment is usable only if
+  // it is within the current module unit. And it must be the current
+  // parsing module unit if it is within the current module unit according
+  // to the grammar of the private module fragment. NOTE: This is covered 
by
+  // the following condition. The intention of the check is to avoid string
+  // comparison as much as possible.
+  M == getCurrentModule() ||
   // The module unit which is in the same module with the current module
   // unit is usable.
   //
   // FIXME: Here we judge if they are in the same module by comparing the
   // string. Is there any better solution?
-  (M->getPrimaryModuleInterfaceName() ==
-   llvm::StringRef(getLangOpts().CurrentModule).split(':').first)) {
+  M->getPrimaryModuleInterfaceName() ==
+  llvm::StringRef(getLangOpts().CurrentModule).split(':').first) {
 UsableModuleUnitsCache.insert(M);
 return true;
   }
@@ -1781,31 +1781,14 @@ bool LookupResult::isVisibleSlow(Sema &SemaRef, 
NamedDecl *D) {
 
 bool Sema::isModuleVisible(const Module *M, bool ModulePrivate) {
   // The module might be ordinarily visible. For a module-private query, that
-  // means it is part of the current module. For any other query, that means it
-  // is in our visible module set.
-  if (ModulePrivate) {
-if (isUsableModule(M))
-  return true;
-else if (M->Kind == Module::ModuleKind::ModulePartitionImplementation &&
- isModuleDirectlyImported(M))
-  // Unless a partition implementation is directly imported it is not
-  // counted as visible for lookup, although the contained decls might
-  // still be reachable.  It's a partition, so it must be part of the
-  // current module to be a valid import.
-  return true;
-else if (getLangOpts().CPlusPlusModules && !ModuleScopes.empty() &&
- ModuleScopes[0].Module->Kind ==
- Module::ModuleKind::ModulePartitionImplementation &&
- ModuleScopes[0].Module->getPrimaryModuleInterfaceName() ==
- M->Name &&
- isModuleDirectlyImported(M))
-  // We are building a module implementation partition and the TU imports
-  // the primary module interface unit.
-  return true;
-  } else {
-if (VisibleModules.isVisible(M))
-  return true;
-  }
+  // means it is part of the current module.
+  if (ModulePrivate && isUsableModule(M))
+return true;
+
+  // For a query which is not module-private, that means it is in our visible
+  // module set.
+  if (!ModulePrivate && VisibleModules.isVisible(M))
+return true;
 
   // Otherwise, it might be visible by virtue of the query being within a
   // template instantiation or similar that is permitted to look inside M.



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

[clang] 3bef90d - [Diagnostic] Warn if the size argument of memset is character literal

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

Author: Chuanqi Xu
Date: 2022-05-16T10:07:01+08:00
New Revision: 3bef90dff64fc717c5d5e33a4d5fb47a4566d04a

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

LOG: [Diagnostic] Warn if the size argument of memset is character literal
zero

Closing https://github.com/llvm/llvm-project/issues/55402

Reviewed By: efriedma

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

Added: 


Modified: 
clang/lib/Sema/SemaChecking.cpp
clang/test/Sema/transpose-memset.c

Removed: 




diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0cdceb47b7389..4c4041a2d68ab 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -11200,7 +11200,10 @@ static void CheckMemaccessSize(Sema &S, unsigned BId, 
const CallExpr *Call) {
 Call->getArg(BId == Builtin::BImemset ? 2 : 1)->IgnoreImpCasts();
 
   auto isLiteralZero = [](const Expr *E) {
-return isa(E) && cast(E)->getValue() == 0;
+return (isa(E) &&
+cast(E)->getValue() == 0) ||
+   (isa(E) &&
+cast(E)->getValue() == 0);
   };
 
   // If we're memsetting or bzeroing 0 bytes, then this is likely an error.

diff  --git a/clang/test/Sema/transpose-memset.c 
b/clang/test/Sema/transpose-memset.c
index 2503fe43458c8..7d83b8e336a08 100644
--- a/clang/test/Sema/transpose-memset.c
+++ b/clang/test/Sema/transpose-memset.c
@@ -11,8 +11,10 @@ int *ptr;
 int main(void) {
   memset(array, sizeof(array), 0); // expected-warning{{'size' argument to 
memset is '0'; did you mean to transpose the last two arguments?}} 
expected-note{{parenthesize the third argument to silence}}
   memset(array, sizeof(array), 0xff); // expected-warning{{setting buffer to a 
'sizeof' expression; did you mean to transpose the last two arguments?}} 
expected-note{{cast the second argument to 'int' to silence}} 
expected-warning{{'memset' will always overflow; destination buffer has size 
40, but size argument is 255}}
+  memset(array, sizeof(array), '\0'); // expected-warning{{'size' argument to 
memset is '0'; did you mean to transpose the last two arguments?}} 
expected-note{{parenthesize the third argument to silence}}
   memset(ptr, sizeof(ptr), 0); // expected-warning{{'size' argument to memset 
is '0'; did you mean to transpose the last two arguments?}} 
expected-note{{parenthesize the third argument to silence}}
   memset(ptr, sizeof(*ptr) * 10, 1); // expected-warning{{setting buffer to a 
'sizeof' expression; did you mean to transpose the last two arguments?}} 
expected-note{{cast the second argument to 'int' to silence}}
+  memset(ptr, sizeof(ptr), '\0');// expected-warning{{'size' argument to 
memset is '0'; did you mean to transpose the last two arguments?}} 
expected-note{{parenthesize the third argument to silence}}
   memset(ptr, 10 * sizeof(int *), 1); // expected-warning{{setting buffer to a 
'sizeof' expression; did you mean to transpose the last two arguments?}} 
expected-note{{cast the second argument to 'int' to silence}}
   memset(ptr, 10 * sizeof(int *) + 10, 0xff); // expected-warning{{setting 
buffer to a 'sizeof' expression; did you mean to transpose the last two 
arguments?}} expected-note{{cast the second argument to 'int' to silence}}
   memset(ptr, sizeof(char) * sizeof(int *), 0xff); // 
expected-warning{{setting buffer to a 'sizeof' expression; did you mean to 
transpose the last two arguments?}} expected-note{{cast the second argument to 
'int' to silence}}



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


[clang] 452fac9 - [Frontend] [Coroutines] Emit error when we found incompatible allocation

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

Author: Chuanqi Xu
Date: 2022-05-17T10:36:21+08:00
New Revision: 452fac9534c00290e92819202d445810e33d0444

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

LOG: [Frontend] [Coroutines] Emit error when we found incompatible allocation
function in promise_type

According to https://cplusplus.github.io/CWG/issues/2585.html, this
fixes https://github.com/llvm/llvm-project/issues/54881

Simply, the clang tried to found (do lookup and overload resolution. Is
there any better word to use than found?) allocation function in
promise_type and global scope. However, this is not consistent with the
standard. The standard behavior would be that the compiler shouldn't
lookup in global scope in case we lookup the allocation function name in
promise_type. In other words, the program is ill-formed if there is
incompatible allocation function in promise type.

Reviewed By: erichkeane

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

Added: 
clang/test/SemaCXX/coroutine-allocs.cpp

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

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59c42384c4ed7..8058df16bc4c3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -149,6 +149,9 @@ Bug Fixes
   because there is no way to fully qualify the enumerator name, so this
   "extension" was unintentional and useless. This fixes
   `Issue 42372 `_.
+- Clang shouldn't lookup allocation function in global scope for coroutines
+  in case it found the allocation function name in the promise_type body.
+  This fixes Issue `Issue 54881 
`_.
 
 Improvements to Clang's diagnostics
 ^^^

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6dcf2eafbf210..e03c583c63fe4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11245,6 +11245,9 @@ def warn_always_inline_coroutine : Warning<
   "this coroutine may be split into pieces; not every piece is guaranteed to 
be inlined"
   >,
   InGroup;
+def err_coroutine_unusable_new : Error<
+  "'operator new' provided by %0 is not usable with the function signature of 
%1"
+>;
 } // 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 44a7271910cf1..8709e7bed207a 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1308,10 +1308,33 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
 
 PlacementArgs.push_back(PDRefExpr.get());
   }
-  S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
-/*DeleteScope*/ Sema::AFS_Both, PromiseType,
-/*isArray*/ false, PassAlignment, PlacementArgs,
-OperatorNew, UnusedResult, /*Diagnose*/ false);
+
+  bool PromiseContainNew = [this, &PromiseType]() -> bool {
+DeclarationName NewName =
+S.getASTContext().DeclarationNames.getCXXOperatorName(OO_New);
+LookupResult R(S, NewName, Loc, Sema::LookupOrdinaryName);
+
+if (PromiseType->isRecordType())
+  S.LookupQualifiedName(R, PromiseType->getAsCXXRecordDecl());
+
+return !R.empty() && !R.isAmbiguous();
+  }();
+
+  auto LookupAllocationFunction = [&]() {
+// [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, ...
+// - Otherwise, a search is performed in the global scope.
+Sema::AllocationFunctionScope NewScope = PromiseContainNew ? 
Sema::AFS_Class : Sema::AFS_Global;
+S.FindAllocationFunctions(Loc, SourceRange(),
+  NewScope,
+  /*DeleteScope*/ Sema::AFS_Both, PromiseType,
+  /*isArray*/ false, PassAlignment, PlacementArgs,
+  OperatorNew, UnusedResult, /*Diagnose*/ false);
+  };
+
+  LookupAllocationFunction();
 
   // [dcl.fct.def.coroutine]p9
   //   If no viable function is found ([over.match.viable]), overload 
resolution
@@ -1319,22 +1342,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // space required as an argument of type std::size_t.
   if (!OperatorNew && !PlacementArgs.empty()) {
 PlacementArgs.clear();
-S.FindAllocationFunctions(Loc, SourceRange(), /*NewScope*/ Sema::AFS_Class,
- 

[clang] 1b89a25 - [C++20] [Coroutines] Conform the updates for CWG issue 2585

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

Author: Chuanqi Xu
Date: 2022-05-23T15:49:17+08:00
New Revision: 1b89a25a9b960886e486eb20b755634613c088f8

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

LOG: [C++20] [Coroutines] Conform the updates for CWG issue 2585

According to the updates in CWG issue 2585
https://cplusplus.github.io/CWG/issues/2585.html, we shouldn't find an
allocation function with (size, p0, …, pn) in global scope.

Added: 
clang/test/SemaCXX/coroutine-allocs2.cpp

Modified: 
clang/lib/Sema/SemaCoroutine.cpp

Removed: 




diff  --git a/clang/lib/Sema/SemaCoroutine.cpp 
b/clang/lib/Sema/SemaCoroutine.cpp
index b43b0b3eb957c..4281bb690ebff 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1239,6 +1239,41 @@ bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
   return true;
 }
 
+// Collect placement arguments for allocation function of coroutine FD.
+// Return true if we collect placement arguments succesfully. Return false,
+// otherwise.
+static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc,
+ SmallVectorImpl &PlacementArgs) {
+  if (auto *MD = dyn_cast(&FD)) {
+if (MD->isInstance() && !isLambdaCallOperator(MD)) {
+  ExprResult ThisExpr = S.ActOnCXXThis(Loc);
+  if (ThisExpr.isInvalid())
+return false;
+  ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
+  if (ThisExpr.isInvalid())
+return false;
+  PlacementArgs.push_back(ThisExpr.get());
+}
+  }
+
+  for (auto *PD : FD.parameters()) {
+if (PD->getType()->isDependentType())
+  continue;
+
+// Build a reference to the parameter.
+auto PDLoc = PD->getLocation();
+ExprResult PDRefExpr =
+S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
+   ExprValueKind::VK_LValue, PDLoc);
+if (PDRefExpr.isInvalid())
+  return false;
+
+PlacementArgs.push_back(PDRefExpr.get());
+  }
+
+  return true;
+}
+
 bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // Form and check allocation and deallocation calls.
   assert(!IsPromiseDependentType &&
@@ -1255,13 +1290,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // allocated, followed by the coroutine function's arguments. If a matching
   // allocation function exists, use it. Otherwise, use an allocation function
   // that just takes the requested size.
-
-  FunctionDecl *OperatorNew = nullptr;
-  FunctionDecl *OperatorDelete = nullptr;
-  FunctionDecl *UnusedResult = nullptr;
-  bool PassAlignment = false;
-  SmallVector PlacementArgs;
-
+  //
   // [dcl.fct.def.coroutine]p9
   //   An implementation may need to allocate additional storage for a
   //   coroutine.
@@ -1288,31 +1317,12 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // and p_i denotes the i-th function parameter otherwise. For a non-static
   // member function, q_1 is an lvalue that denotes *this; any other q_i is an
   // lvalue that denotes the parameter copy corresponding to p_i.
-  if (auto *MD = dyn_cast(&FD)) {
-if (MD->isInstance() && !isLambdaCallOperator(MD)) {
-  ExprResult ThisExpr = S.ActOnCXXThis(Loc);
-  if (ThisExpr.isInvalid())
-return false;
-  ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
-  if (ThisExpr.isInvalid())
-return false;
-  PlacementArgs.push_back(ThisExpr.get());
-}
-  }
-  for (auto *PD : FD.parameters()) {
-if (PD->getType()->isDependentType())
-  continue;
 
-// Build a reference to the parameter.
-auto PDLoc = PD->getLocation();
-ExprResult PDRefExpr =
-S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
-   ExprValueKind::VK_LValue, PDLoc);
-if (PDRefExpr.isInvalid())
-  return false;
-
-PlacementArgs.push_back(PDRefExpr.get());
-  }
+  FunctionDecl *OperatorNew = nullptr;
+  FunctionDecl *OperatorDelete = nullptr;
+  FunctionDecl *UnusedResult = nullptr;
+  bool PassAlignment = false;
+  SmallVector PlacementArgs;
 
   bool PromiseContainNew = [this, &PromiseType]() -> bool {
 DeclarationName NewName =
@@ -1330,8 +1340,10 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
 //   The allocation function's name is looked up by searching for it in the
 // scope of the promise type.
 // - If any declarations are found, ...
-// - Otherwise, a search is performed in the global scope.
-Sema::AllocationFunctionScope NewScope = PromiseContainNew ? 
Sema::AFS_Class : Sema::AFS_Global;
+// - If no declarations are found in the scope of the promise type, a 
search
+// is performed in the global scope.
+Sema::AllocationFunctionScope NewScope =
+PromiseContainNew ? Sema::AFS

[clang] 9e9cf3f - Revert "[C++20] [Coroutines] Conform the updates for CWG issue 2585"

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

Author: Chuanqi Xu
Date: 2022-05-23T16:21:42+08:00
New Revision: 9e9cf3fa3d282644dd6802cbdf84f4ca6f932fa0

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

LOG: Revert "[C++20] [Coroutines] Conform the updates for CWG issue 2585"

This reverts commit 1b89a25a9b960886e486eb20b755634613c088f8.

The test would fail in windows versions.

Added: 


Modified: 
clang/lib/Sema/SemaCoroutine.cpp

Removed: 
clang/test/SemaCXX/coroutine-allocs2.cpp



diff  --git a/clang/lib/Sema/SemaCoroutine.cpp 
b/clang/lib/Sema/SemaCoroutine.cpp
index 4281bb690ebff..b43b0b3eb957c 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1239,41 +1239,6 @@ bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
   return true;
 }
 
-// Collect placement arguments for allocation function of coroutine FD.
-// Return true if we collect placement arguments succesfully. Return false,
-// otherwise.
-static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc,
- SmallVectorImpl &PlacementArgs) {
-  if (auto *MD = dyn_cast(&FD)) {
-if (MD->isInstance() && !isLambdaCallOperator(MD)) {
-  ExprResult ThisExpr = S.ActOnCXXThis(Loc);
-  if (ThisExpr.isInvalid())
-return false;
-  ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
-  if (ThisExpr.isInvalid())
-return false;
-  PlacementArgs.push_back(ThisExpr.get());
-}
-  }
-
-  for (auto *PD : FD.parameters()) {
-if (PD->getType()->isDependentType())
-  continue;
-
-// Build a reference to the parameter.
-auto PDLoc = PD->getLocation();
-ExprResult PDRefExpr =
-S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
-   ExprValueKind::VK_LValue, PDLoc);
-if (PDRefExpr.isInvalid())
-  return false;
-
-PlacementArgs.push_back(PDRefExpr.get());
-  }
-
-  return true;
-}
-
 bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // Form and check allocation and deallocation calls.
   assert(!IsPromiseDependentType &&
@@ -1290,7 +1255,13 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // allocated, followed by the coroutine function's arguments. If a matching
   // allocation function exists, use it. Otherwise, use an allocation function
   // that just takes the requested size.
-  //
+
+  FunctionDecl *OperatorNew = nullptr;
+  FunctionDecl *OperatorDelete = nullptr;
+  FunctionDecl *UnusedResult = nullptr;
+  bool PassAlignment = false;
+  SmallVector PlacementArgs;
+
   // [dcl.fct.def.coroutine]p9
   //   An implementation may need to allocate additional storage for a
   //   coroutine.
@@ -1317,12 +1288,31 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
   // and p_i denotes the i-th function parameter otherwise. For a non-static
   // member function, q_1 is an lvalue that denotes *this; any other q_i is an
   // lvalue that denotes the parameter copy corresponding to p_i.
+  if (auto *MD = dyn_cast(&FD)) {
+if (MD->isInstance() && !isLambdaCallOperator(MD)) {
+  ExprResult ThisExpr = S.ActOnCXXThis(Loc);
+  if (ThisExpr.isInvalid())
+return false;
+  ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
+  if (ThisExpr.isInvalid())
+return false;
+  PlacementArgs.push_back(ThisExpr.get());
+}
+  }
+  for (auto *PD : FD.parameters()) {
+if (PD->getType()->isDependentType())
+  continue;
 
-  FunctionDecl *OperatorNew = nullptr;
-  FunctionDecl *OperatorDelete = nullptr;
-  FunctionDecl *UnusedResult = nullptr;
-  bool PassAlignment = false;
-  SmallVector PlacementArgs;
+// Build a reference to the parameter.
+auto PDLoc = PD->getLocation();
+ExprResult PDRefExpr =
+S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),
+   ExprValueKind::VK_LValue, PDLoc);
+if (PDRefExpr.isInvalid())
+  return false;
+
+PlacementArgs.push_back(PDRefExpr.get());
+  }
 
   bool PromiseContainNew = [this, &PromiseType]() -> bool {
 DeclarationName NewName =
@@ -1340,10 +1330,8 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
 //   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 =
-PromiseContainNew ? Sema::AFS_Class : Sema::AFS_Global;
+// - Otherwise, a search is performed in the global scope.
+Sema::AllocationFunctionScope NewScope = PromiseContainNew ? 
Sema::AFS_Class : Sema::AFS_Global;
 S.FindAllocationFunctions(Loc

[clang] 2582965 - [C++20] [Modules] [Reduced BMI] Generate the function body from implicitly instantiated class and constant variables

2024-03-14 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2024-03-14T15:07:08+08:00
New Revision: 2582965c160486f9e3b0680f1cebc5ffdef9620c

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

LOG: [C++20] [Modules] [Reduced BMI] Generate the function body from implicitly 
instantiated class and constant variables

After this patch, we will generate the function body from implicitly
instantiated class. This is important for consumers with same
template arguments. Otherwise the consumers won't see the function body.
Since the consumers won't instantiate the templates again if they find an
instantiation.

Also we will generate the variable definition if the variable is
non-inline but known as constant. Such variables may not affect the
ABI, but they may get involved into the compile time constant computation
in the consumer's code. So we have to generate such definitions.

Added: 
clang/test/Modules/reduced-bmi-generating-codes.cppm

Modified: 
clang/lib/Serialization/ASTWriterDecl.cpp

Removed: 




diff  --git a/clang/lib/Serialization/ASTWriterDecl.cpp 
b/clang/lib/Serialization/ASTWriterDecl.cpp
index d04e1c781b4e28..86f64bf2a24250 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -281,11 +281,18 @@ bool clang::CanElideDeclDef(const Decl *D) {
 
 if (FD->isDependentContext())
   return false;
+
+if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)
+  return false;
   }
 
   if (auto *VD = dyn_cast(D)) {
 if (!VD->getDeclContext()->getRedeclContext()->isFileContext() ||
-VD->isInline() || VD->isConstexpr() || isa(VD))
+VD->isInline() || VD->isConstexpr() || isa(VD) ||
+// Constant initialized variable may not affect the ABI, but they
+// may be used in constant evaluation in the frontend, so we have
+// to remain them.
+VD->hasConstantInitialization())
   return false;
 
 if (VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation)

diff  --git a/clang/test/Modules/reduced-bmi-generating-codes.cppm 
b/clang/test/Modules/reduced-bmi-generating-codes.cppm
new file mode 100644
index 00..13dcda06437b29
--- /dev/null
+++ b/clang/test/Modules/reduced-bmi-generating-codes.cppm
@@ -0,0 +1,40 @@
+// Although the reduced BMI are not designed to be generated,
+// it is helpful for testing whether we've reduced the definitions.
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+//
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/a.cppm \
+// RUN: -emit-reduced-module-interface -o %t/a.pcm
+// RUN: %clang_cc1 -std=c++20 -triple %itanium_abi_triple %t/b.cpp \
+// RUN: -fmodule-file=a=%t/a.pcm -S -emit-llvm -o - \
+// RUN: | FileCheck %t/b.cpp
+
+//--- a.cppm
+export module a;
+
+export template 
+class A {
+public:
+int member() {
+return 43;
+}
+};
+
+// Instantiate `A::member()`.
+export int a_member = A().member();
+
+export const int a = 43;
+
+//--- b.cpp
+import a;
+
+static_assert(a == 43);
+
+int b() {
+A a;
+return a.member();
+}
+
+// CHECK: define{{.*}}@_ZNW1a1AIiE6memberEv



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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-17 Thread Chuanqi Xu via cfe-commits

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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-17 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

I'll backport this tomorrow if no revert request shows up.

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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-17 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> The file we're looking for is `modules.json`; Renaming it 
> `libc++.modules.json` like `.so` / `.a` file might be a better idea which 
> could avoid name clashes when installed in `/usr/lib`.

BTW, how do you feel about the paragraph. I thought it as a defect in some 
level.

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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-18 Thread Chuanqi Xu via cfe-commits

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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-18 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

/cherry-pick 0e1e1fc8f0e

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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-18 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> > > The file we're looking for is `modules.json`; Renaming it 
> > > `libc++.modules.json` like `.so` / `.a` file might be a better idea which 
> > > could avoid name clashes when installed in `/usr/lib`.
> > 
> > 
> > but i didn't rename it, it was with the libc++ prefix directly :/
> 
> Good point I did :-/ It seems we originally talked about `modules.json` and 
> later mentioned using the libname. @ChuanqiXu9 I prefer to keep the current 
> name `libc++.modules.json` and adjust clang. WDYT?

Could you elaborate the reason more? I feel like renaming `libc++.modules.json` 
to `modules.json` is straightforward. Maybe I didn't take part it in the old 
disscussion or I missed : )

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type convertible to `std::coroutine_handle<>` (PR #85684)

2024-03-19 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> I am also ok with changing the patch to reject programs whose await_suspend 
> doesn't strictly return std::coroutine_handle if upstream prefers.

It should be good to do that since it makes the behavior more conforming. And 
maybe it is better to do this a seperate patch.
Especially if it can help reduce the many non-semantical changes in 
SemaExprCXX.cpp.



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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-19 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> > > > > The file we're looking for is `modules.json`; Renaming it 
> > > > > `libc++.modules.json` like `.so` / `.a` file might be a better idea 
> > > > > which could avoid name clashes when installed in `/usr/lib`.
> > > > 
> > > > 
> > > > but i didn't rename it, it was with the libc++ prefix directly :/
> > > 
> > > 
> > > Good point I did :-/ It seems we originally talked about `modules.json` 
> > > and later mentioned using the libname. @ChuanqiXu9 I prefer to keep the 
> > > current name `libc++.modules.json` and adjust clang. WDYT?
> > 
> > 
> > Could you elaborate the reason more? I feel like renaming 
> > `libc++.modules.json` to `modules.json` is straightforward. Maybe I didn't 
> > take part it in the old disscussion or I missed : )
> 
> It would allow to install libstdc++ and libc++ in the same lib directory 
> without "fighting" who owns `modules.json`. Also if we want to provide 
> `libc++-asan.so` in the future we can provide `libc++-asan.modules.json`. 
> Whether we need a different `module.json` for ASan is unknown at the moment, 
> but I can imagine we have additional compiler or linker flags for ASan.

h, I can accept that. Then the patch itself is not incorrect... Since it 
looks like we'd never look for `modules.json` actually, right? Let's adjust the 
implementation in clang.

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


[clang] [llvm] [Coroutines] Drop dead instructions more aggressively in addMustTailToCoroResumes() (PR #85271)

2024-03-20 Thread Chuanqi Xu via cfe-commits

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

LGTM. Thanks.

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


[clang] [llvm] [Coroutines] Drop dead instructions more aggressively in addMustTailToCoroResumes() (PR #85271)

2024-03-20 Thread Chuanqi Xu via cfe-commits

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


[clang] [llvm] [Coroutines] Drop dead instructions more aggressively in addMustTailToCoroResumes() (PR #85271)

2024-03-20 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,65 @@
+// This tests that the symmetric transfer at the final suspend point could 
happen successfully.

ChuanqiXu9 wrote:

nit: I feel slightly better to add a link to the github page.

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


[clang] [clang][frontend] Make DumpModuleInfoAction emit the full macro (PR #85745)

2024-03-20 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 commented:

Dumping things from the source location makes me nervous... And giving this is 
not related to named modules, I'd like to leave this for @Bigcheese 

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type convertible to `std::coroutine_handle<>` (PR #85684)

2024-03-20 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> In SemaExprCXX.cpp there's EvaluateBinaryTypeTraits that I needed to expose 
> as suggested by the comment in SemaCoroutine. Is there an alternative way to 
> do type coercion/equivalence checks?

I am confused. If we don't need to check whether a type can be converted to 
`std::coroutine_handle`, why do we still need EvaluateBinaryTypeTraits or 
similar things.

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type convertible to `std::coroutine_handle<>` (PR #85684)

2024-03-20 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> > I am confused. If we don't need to check whether a type can be converted to 
> > std::coroutine_handle, why do we still need EvaluateBinaryTypeTraits or 
> > similar things.
> 
> I thought your previous comment was to show concern about exposing 
> `EvaluateBinaryTypeTraits` contained a bunch of nonfunctional changes.

Yes, this is the intention.

> Do you think it's good?

For the issue we have, it is not. We're introducing a lot of nonfunctional 
change for a non-standard and unimportant feature... So I may feel better if we 
can avoid that.


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


[clang] [clang] Improves -print-library-module-manifest-path. (PR #85943)

2024-03-21 Thread Chuanqi Xu via cfe-commits

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

LGTM

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type is a `std::coroutine_handle` (PR #85684)

2024-03-22 Thread Chuanqi Xu via cfe-commits


@@ -358,6 +364,30 @@ static Expr *maybeTailCall(Sema &S, QualType RetType, Expr 
*E,
   return S.MaybeCreateExprWithCleanups(JustAddress);
 }
 
+static bool isSpecializationOfCoroutineHandle(Sema &S, QualType Ty,
+  SourceLocation Loc) {
+  auto *CoroutineHandleClassTemplateDecl =
+  lookupCoroutineHandleTemplate(S, Loc);

ChuanqiXu9 wrote:

Maybe it can be better to cache the coroutine handle declaration to avoid 
redundant looking up. But it may be fine for the number of `await_suspend` in 
practical.

We can send another patch for this if we want.

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type is a `std::coroutine_handle` (PR #85684)

2024-03-22 Thread Chuanqi Xu via cfe-commits


@@ -339,6 +339,9 @@ Bug Fixes in This Version
 - Fixes an assertion failure on invalid code when trying to define member
   functions in lambdas.
 
+- Clang now emits errors for coroutine `await_suspend` functions whose return 
type is not
+  one of `void`, `bool`, or `std::coroutine_handle`.

ChuanqiXu9 wrote:

Maybe we should move this to `Potential Breaking Section` and mention it 
conforms the standard wording.


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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type is a `std::coroutine_handle` (PR #85684)

2024-03-22 Thread Chuanqi Xu via cfe-commits


@@ -418,39 +448,60 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema 
&S, VarDecl *CoroPromise,
 return Calls;
   }
   Expr *CoroHandle = CoroHandleRes.get();
-  CallExpr *AwaitSuspend = cast_or_null(
-  BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
+  auto *AwaitSuspend = [&]() -> CallExpr * {
+auto *SubExpr = BuildSubExpr(ACT::ACT_Suspend, "await_suspend", 
CoroHandle);
+if (!SubExpr)
+  return nullptr;
+if (auto *E = dyn_cast(SubExpr)) {
+  // This happens when await_suspend return type is not trivially
+  // destructible. This doesn't happen for the permitted return types of
+  // such function. Diagnose it later.
+  return cast_or_null(E->getSubExpr());
+} else {
+  return cast_or_null(SubExpr);
+}

ChuanqiXu9 wrote:

I don't understand why we need to do this here. Can't it be handled by the 
following check?

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type is a `std::coroutine_handle` (PR #85684)

2024-03-22 Thread Chuanqi Xu via cfe-commits


@@ -418,39 +448,60 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema 
&S, VarDecl *CoroPromise,
 return Calls;
   }
   Expr *CoroHandle = CoroHandleRes.get();
-  CallExpr *AwaitSuspend = cast_or_null(
-  BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
+  auto *AwaitSuspend = [&]() -> CallExpr * {
+auto *SubExpr = BuildSubExpr(ACT::ACT_Suspend, "await_suspend", 
CoroHandle);
+if (!SubExpr)
+  return nullptr;
+if (auto *E = dyn_cast(SubExpr)) {
+  // This happens when await_suspend return type is not trivially
+  // destructible. This doesn't happen for the permitted return types of
+  // such function. Diagnose it later.
+  return cast_or_null(E->getSubExpr());
+} else {
+  return cast_or_null(SubExpr);
+}

ChuanqiXu9 wrote:

I mean, how about diagnose `InvalidAwaitSuspendReturnType` directly if it is 
null. And we can use `dyn_cast_if_present` instead of `cast_or_null`. WDYT?

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


[clang] [Clang] [C++26] Implement P2573R2: `= delete("should have a reason");` (PR #86526)

2024-03-25 Thread Chuanqi Xu via cfe-commits


@@ -761,6 +761,13 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
 }
   }
 
+  // FIXME: Hack: We're out of bits in FunctionDeclBits, so always
+  // add this even though it's 0 in the vast majority of cases. We
+  // might really want to consider storing this in the DefaultedFunctionInfo
+  // instead.
+  if (D->isDeletedAsWritten())
+Record.AddStmt(D->getDeletedMessage());

ChuanqiXu9 wrote:

I didn't understand. Since the string literal is required to be `unevaluated 
string`, I feel it may be good to record the string value directly by 
`StringLiteral::getBytes`.

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type is a `std::coroutine_handle` (PR #85684)

2024-03-25 Thread Chuanqi Xu via cfe-commits


@@ -418,39 +448,60 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema 
&S, VarDecl *CoroPromise,
 return Calls;
   }
   Expr *CoroHandle = CoroHandleRes.get();
-  CallExpr *AwaitSuspend = cast_or_null(
-  BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
+  auto *AwaitSuspend = [&]() -> CallExpr * {
+auto *SubExpr = BuildSubExpr(ACT::ACT_Suspend, "await_suspend", 
CoroHandle);
+if (!SubExpr)
+  return nullptr;
+if (auto *E = dyn_cast(SubExpr)) {
+  // This happens when await_suspend return type is not trivially
+  // destructible. This doesn't happen for the permitted return types of
+  // such function. Diagnose it later.
+  return cast_or_null(E->getSubExpr());
+} else {
+  return cast_or_null(SubExpr);
+}

ChuanqiXu9 wrote:

I am still concerning the change. What's the type of `SubExpr`? Can we get the 
return type of SubExpr directly instead of accessing it by CallExpr?

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


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

2024-03-25 Thread Chuanqi Xu via cfe-commits

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

>From 5fcccd75d0823ff11a4e385565cad65034d0def7 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Tue, 12 Mar 2024 17:26:49 +0800
Subject: [PATCH 1/2] [C++20] [Modules] Introduce -fgen-reduced-bmi

---
 clang/include/clang/CodeGen/CodeGenAction.h   |  2 +
 clang/include/clang/Driver/Options.td |  6 +++
 .../include/clang/Frontend/FrontendOptions.h  |  9 +++-
 clang/include/clang/Serialization/ASTWriter.h |  7 +--
 clang/lib/CodeGen/CodeGenAction.cpp   | 19 +++
 clang/lib/Driver/Driver.cpp   | 27 +-
 clang/lib/Driver/ToolChains/Clang.cpp | 41 --
 clang/lib/Driver/ToolChains/Clang.h   | 14 +
 clang/lib/Frontend/FrontendActions.cpp|  7 +++
 clang/lib/Frontend/PrecompiledPreamble.cpp|  3 +-
 clang/lib/Serialization/GeneratePCH.cpp   | 23 ++--
 .../test/Driver/module-fgen-reduced-bmi.cppm  | 53 +++
 clang/test/Modules/gen-reduced-bmi.cppm   | 36 +
 13 files changed, 220 insertions(+), 27 deletions(-)
 create mode 100644 clang/test/Driver/module-fgen-reduced-bmi.cppm
 create mode 100644 clang/test/Modules/gen-reduced-bmi.cppm

diff --git a/clang/include/clang/CodeGen/CodeGenAction.h 
b/clang/include/clang/CodeGen/CodeGenAction.h
index 7ad2988e589eb2..186dbb43f01ef7 100644
--- a/clang/include/clang/CodeGen/CodeGenAction.h
+++ b/clang/include/clang/CodeGen/CodeGenAction.h
@@ -57,6 +57,8 @@ class CodeGenAction : public ASTFrontendAction {
   bool loadLinkModules(CompilerInstance &CI);
 
 protected:
+  bool BeginSourceFileAction(CompilerInstance &CI) override;
+
   /// Create a new code generation action.  If the optional \p _VMContext
   /// parameter is supplied, the action uses it without taking ownership,
   /// otherwise it creates a fresh LLVM context and takes ownership.
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index b0d90c776b58a9..0eca2a95e3271e 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3017,6 +3017,7 @@ defm prebuilt_implicit_modules : 
BoolFOption<"prebuilt-implicit-modules",
 
 def fmodule_output_EQ : Joined<["-"], "fmodule-output=">,
   Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>,
+  MarshallingInfoString>,
   HelpText<"Save intermediate module file results when compiling a standard 
C++ module unit.">;
 def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption]>,
   Visibility<[ClangOption, CC1Option]>,
@@ -3030,6 +3031,11 @@ defm skip_odr_check_in_gmf : BoolOption<"f", 
"skip-odr-check-in-gmf",
   "Perform ODR checks for decls in the global module fragment.">>,
   Group;
 
+def gen_reduced_bmi : Flag<["-"], "fgen-reduced-bmi">,
+  Group, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Generate the reduced BMI">,
+  MarshallingInfoFlag>;
+
 def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, 
Group,
   Visibility<[ClangOption, CC1Option]>, MetaVarName<"">,
   HelpText<"Specify the interval (in seconds) between attempts to prune the 
module cache">,
diff --git a/clang/include/clang/Frontend/FrontendOptions.h 
b/clang/include/clang/Frontend/FrontendOptions.h
index 8085dbcbf671a6..ddfd4f30d1b773 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -387,6 +387,10 @@ class FrontendOptions {
   LLVM_PREFERRED_TYPE(bool)
   unsigned ModulesShareFileManager : 1;
 
+  /// Whether to generate reduced BMI for C++20 named modules.
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned GenReducedBMI : 1;
+
   CodeCompleteOptions CodeCompleteOpts;
 
   /// Specifies the output format of the AST.
@@ -553,6 +557,9 @@ class FrontendOptions {
   /// Path which stores the output files for -ftime-trace
   std::string TimeTracePath;
 
+  /// Output Path for module output file.
+  std::string ModuleOutputPath;
+
 public:
   FrontendOptions()
   : DisableFree(false), RelocatablePCH(false), ShowHelp(false),
@@ -565,7 +572,7 @@ class FrontendOptions {
 BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false),
 IncludeTimestamps(true), UseTemporary(true),
 AllowPCMWithCompilerErrors(false), ModulesShareFileManager(true),
-TimeTraceGranularity(500) {}
+GenReducedBMI(false), TimeTraceGranularity(500) {}
 
   /// getInputKindForExtension - Return the appropriate input kind for a file
   /// extension. For example, "c" would return Language::C.
diff --git a/clang/include/clang/Serialization/ASTWriter.h 
b/clang/include/clang/Serialization/ASTWriter.h
index 3ed9803fa3745b..bd310b6c7a5cdd 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -846,7 +846,7 @@ class ASTWriter : public ASTDeserializationListener,
 /// AST and semantic-analysis consumer that generates a
 /// precompiled header from 

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

2024-03-25 Thread Chuanqi Xu via cfe-commits


@@ -0,0 +1,53 @@
+// It is annoying to handle different slash direction
+// in Windows and Linux. So we disable the test on Windows
+// here.
+// REQUIRES: !system-windows

ChuanqiXu9 wrote:

Done

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


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

2024-03-25 Thread Chuanqi Xu via cfe-commits


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

ChuanqiXu9 wrote:

Done by using `-fmodules-reduce-bmi`

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


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

2024-03-25 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

@iains @dwblaikie Understood. And I thought the major problem is that there are 
a lot flags from clang modules. And it is indeed confusing. But given we have 
to introduce new flags in this case, probably we can only try to make it more 
clear by better documents.

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


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

2024-03-25 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> Using `-fgen-reduced-bmi` currently fails for me with a case that looks like 
> this:
> 
> ```c++
> // a.hpp
>   template 
>   void ignore(T const &) noexcept {}
>   
>   inline void resultCheck(char const *message) {
>   ignore(message);
>   }
>   
> // b.cppm
> module;
> #include "a.hpp"
> export module b;
> 
> export {
> using ignore;
> using resultCheck;
> }
> 
> // c.cppm
> export module c;
> import b;
> 
> export void test() {
> resultCheck(nullptr);
> }
> ```
> 
> This will result in this linker error: `undefined reference to void 
> ignore(char const* const&)`. Removing `-fgen-reduced-bmi` will 
> result in linking without errors. Do I need to pass certain flags to CMake?

This may be fixed in trunk. This should be a bug in Reduced BMI. Note that the 
current patch is only the driver part of Reduced BMI. And this is the reason 
why we need a new flag. Otherwise I'll propose to enable it by default : )

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


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

2024-03-25 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> Do I miss something? The performance and file size is similar with and 
> without `-fgen-reduced-bmi`. To reproduce clone 
> https://github.com/koplas/clang-modules-test and run `build.sh` and 
> `build_thin_bmi.sh`.

Currently, the Reduced BMI will only remove function bodies for non-inline 
functions and definitions for some variables...

And declarations in headers or GMF are primarily inline, so probably the 
current Reduced BMI won't produce a strong impact on modules whose contents are 
primarily in GMF as expectedly.

For example, I can observe some impact on 
https://github.com/alibaba/async_simple/tree/CXX20Modules, where the repo has 
more use codes in the module purview instead of the GMF.

Further, in my mind, we can reduce more things in Reduced BMI. An example may 
be https://github.com/llvm/llvm-project/pull/76930.

Thanks for testing : )

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


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

2024-03-25 Thread Chuanqi Xu via cfe-commits

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


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

2024-03-25 Thread Chuanqi Xu via cfe-commits

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type is a `std::coroutine_handle` (PR #85684)

2024-03-26 Thread Chuanqi Xu via cfe-commits


@@ -418,39 +448,60 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema 
&S, VarDecl *CoroPromise,
 return Calls;
   }
   Expr *CoroHandle = CoroHandleRes.get();
-  CallExpr *AwaitSuspend = cast_or_null(
-  BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
+  auto *AwaitSuspend = [&]() -> CallExpr * {
+auto *SubExpr = BuildSubExpr(ACT::ACT_Suspend, "await_suspend", 
CoroHandle);
+if (!SubExpr)
+  return nullptr;
+if (auto *E = dyn_cast(SubExpr)) {
+  // This happens when await_suspend return type is not trivially
+  // destructible. This doesn't happen for the permitted return types of
+  // such function. Diagnose it later.
+  return cast_or_null(E->getSubExpr());
+} else {
+  return cast_or_null(SubExpr);
+}

ChuanqiXu9 wrote:

Thanks. My motivation is that the small pattern match style looks really not 
good. And if it is possible to get the RecordDecl by the type of `Operand` and 
find the `await_suspend` member function? If yes, we can still get the location 
of `await_suspend`.

And if we have problems printing `(have 'Status')` part, I feel it may not be a 
big problem since the underlying issue is clear.

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


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

2024-03-26 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> > > > @iains @dwblaikie Understood. And I thought the major problem is that 
> > > > there are a lot flags from clang modules. And it is indeed confusing. 
> > > > But given we have to introduce new flags in this case, probably we can 
> > > > only try to make it more clear by better documents.
> > > 
> > > 
> > > So you do not think it possible to restrict the new flag to be "internal" 
> > > (i.e. cc1-only) and to put some _temporary_ driver processing to handle 
> > > that? (I agree that this is an unusual mechanism, but the idea is to 
> > > recognise that the driver-side processing is only expected to me 
> > > temporary).
> > 
> > 
> > I have no idea how can we make that. We still need the users to provide 
> > something to enable reduced BMI. And I think it is symmetric to a new flag.
> 
> What I mean is that (a) we need the internal 'cc1' flag permanently; but (b) 
> we do not expect to need a user-facing driver flag permanently. and (c) We 
> want to allow users to try this out.
> 
> I am suggesting we could say "to try this out use -Xclang 
> -fmodules-reduced-bmi" and have _temporary_ code in the driver to deal with 
> the changes needed to phasing.
> 
> If this is not possible. then I suppose I am a bit sad that we keep saying 
> 'there are too many modules options' - but yet still add more. however - we 
> need to make progress, so if the suggestion here is really a non-starter .. 
> then such is life.
> 
> Perhaps the second suggestion (-fexperimental-x options) could be 
> discussed at the project level.

Got your point. But I feel the `-Xclang xxx` style or the `-fexperimental-xxx` 
style may make people feel, "oh, this is not ready, let's wait". Then we may 
lose more testing opportunity. Also I feel such options are symmetric to the 
existing one. It still makes the interfaces to be more complicated. I don't 
feel they are better than the existing one.

And yes, it is indeed that we have a lot modules options. But I think this may 
not be the blocking point for adding new modules options if we think it is 
really needed. If there are things needed to be added by flags really and we 
don't do that due to we feel we have too many flags, I feel it is somewhat "not 
eating for fear of choking". I think what we need to do for this case is to be 
pretty careful when adding new flags and I think we already make it for Reduced 
BMI.

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


[clang] [llvm] [Modules] No transitive source location change (PR #86912)

2024-03-27 Thread Chuanqi Xu via cfe-commits

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

None

>From 9046d2156cb8641cccf76c643b6f88994105f452 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Mon, 18 Mar 2024 08:36:55 +0800
Subject: [PATCH] [Modules] No transitive source location change

---
 clang/include/clang/Basic/SourceLocation.h|   1 +
 .../include/clang/Serialization/ASTBitCodes.h |  55 +-
 clang/include/clang/Serialization/ASTReader.h |  48 +
 clang/include/clang/Serialization/ASTWriter.h |   3 +
 .../include/clang/Serialization/ModuleFile.h  |   4 -
 .../Serialization/SourceLocationEncoding.h|  40 +--
 clang/lib/Frontend/ASTUnit.cpp|   2 -
 clang/lib/Serialization/ASTReader.cpp |  87 ++-
 clang/lib/Serialization/ASTReaderDecl.cpp |   2 +-
 clang/lib/Serialization/ASTWriter.cpp |  35 --
 clang/lib/Serialization/ASTWriterDecl.cpp |   6 +-
 clang/lib/Serialization/ModuleFile.cpp|   1 -
 .../no-transitive-source-location-change.cppm |  69 
 clang/test/Modules/pr61067.cppm   |  25 -
 .../SourceLocationEncodingTest.cpp| 100 --
 llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp   |   7 +-
 16 files changed, 238 insertions(+), 247 deletions(-)
 create mode 100644 clang/test/Modules/no-transitive-source-location-change.cppm

diff --git a/clang/include/clang/Basic/SourceLocation.h 
b/clang/include/clang/Basic/SourceLocation.h
index 00b1e0fa855b7a..7a0f5ba8d1270b 100644
--- a/clang/include/clang/Basic/SourceLocation.h
+++ b/clang/include/clang/Basic/SourceLocation.h
@@ -90,6 +90,7 @@ class SourceLocation {
   friend class ASTWriter;
   friend class SourceManager;
   friend struct llvm::FoldingSetTrait;
+  friend class SourceLocationEncoding;
 
 public:
   using UIntTy = uint32_t;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h 
b/clang/include/clang/Serialization/ASTBitCodes.h
index f31efa5117f0d1..8ccf098d4eb549 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -22,6 +22,7 @@
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Serialization/SourceLocationEncoding.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/Bitstream/BitCodes.h"
 #include 
@@ -175,44 +176,47 @@ const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
 
 /// Source range/offset of a preprocessed entity.
 struct PPEntityOffset {
+  using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
+
   /// Raw source location of beginning of range.
-  SourceLocation::UIntTy Begin;
+  RawLocEncoding Begin;
 
   /// Raw source location of end of range.
-  SourceLocation::UIntTy End;
+  RawLocEncoding End;
 
   /// Offset in the AST file relative to ModuleFile::MacroOffsetsBase.
   uint32_t BitOffset;
 
-  PPEntityOffset(SourceRange R, uint32_t BitOffset)
-  : Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()),
+  PPEntityOffset(RawLocEncoding Begin, RawLocEncoding End, uint32_t BitOffset)
+  : Begin(Begin), End(End),
 BitOffset(BitOffset) {}
 
-  SourceLocation getBegin() const {
-return SourceLocation::getFromRawEncoding(Begin);
+  RawLocEncoding getBegin() const {
+return Begin;
   }
-
-  SourceLocation getEnd() const {
-return SourceLocation::getFromRawEncoding(End);
+  RawLocEncoding getEnd() const {
+return End;
   }
 };
 
 /// Source range of a skipped preprocessor region
 struct PPSkippedRange {
+  using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
+
   /// Raw source location of beginning of range.
-  SourceLocation::UIntTy Begin;
+  RawLocEncoding Begin;
   /// Raw source location of end of range.
-  SourceLocation::UIntTy End;
+  RawLocEncoding End;
 
-  PPSkippedRange(SourceRange R)
-  : Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()) 
{
+  PPSkippedRange(RawLocEncoding Begin, RawLocEncoding End)
+  : Begin(Begin), End(End) {
   }
 
-  SourceLocation getBegin() const {
-return SourceLocation::getFromRawEncoding(Begin);
+  RawLocEncoding getBegin() const {
+return Begin;
   }
-  SourceLocation getEnd() const {
-return SourceLocation::getFromRawEncoding(End);
+  RawLocEncoding getEnd() const {
+return End;
   }
 };
 
@@ -239,8 +243,10 @@ struct UnderalignedInt64 {
 
 /// Source location and bit offset of a declaration.
 struct DeclOffset {
+  using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
+
   /// Raw source location.
-  SourceLocation::UIntTy Loc = 0;
+  RawLocEncoding RawLoc = 0;
 
   /// Offset relative to the start of the DECLTYPES_BLOCK block. Keep
   /// structure alignment 32-bit and avoid padding gap because undefined
@@ -248,16 +254,17 @@ struct DeclOffset {
   UnderalignedInt64 BitOffset;
 
   DeclOffset() = default;
-  DeclOffset(SourceLocation Loc, uint64_t BitOffset,
- uint64_t DeclTy

[clang] [Modules] No transitive source location change (PR #86912)

2024-03-27 Thread Chuanqi Xu via cfe-commits

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

>From 8d4e349710f4ca84a7ad2dd8aa71afa50b730dbb Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Mon, 18 Mar 2024 08:36:55 +0800
Subject: [PATCH] [Modules] No transitive source location change

---
 clang/include/clang/Basic/SourceLocation.h|  1 +
 .../include/clang/Serialization/ASTBitCodes.h | 56 ++--
 clang/include/clang/Serialization/ASTReader.h | 54 +++-
 clang/include/clang/Serialization/ASTWriter.h |  4 +
 .../include/clang/Serialization/ModuleFile.h  |  4 -
 .../Serialization/SourceLocationEncoding.h| 78 +++--
 clang/lib/Frontend/ASTUnit.cpp|  2 -
 clang/lib/Serialization/ASTReader.cpp | 86 +++
 clang/lib/Serialization/ASTReaderDecl.cpp |  2 +-
 clang/lib/Serialization/ASTWriter.cpp | 41 +++--
 clang/lib/Serialization/ASTWriterDecl.cpp |  8 +-
 clang/lib/Serialization/ModuleFile.cpp|  1 -
 .../no-transitive-source-location-change.cppm | 69 +++
 clang/test/Modules/pr61067.cppm   | 25 --
 .../SourceLocationEncodingTest.cpp| 66 ++
 15 files changed, 264 insertions(+), 233 deletions(-)
 create mode 100644 clang/test/Modules/no-transitive-source-location-change.cppm

diff --git a/clang/include/clang/Basic/SourceLocation.h 
b/clang/include/clang/Basic/SourceLocation.h
index 00b1e0fa855b7a..7a0f5ba8d1270b 100644
--- a/clang/include/clang/Basic/SourceLocation.h
+++ b/clang/include/clang/Basic/SourceLocation.h
@@ -90,6 +90,7 @@ class SourceLocation {
   friend class ASTWriter;
   friend class SourceManager;
   friend struct llvm::FoldingSetTrait;
+  friend class SourceLocationEncoding;
 
 public:
   using UIntTy = uint32_t;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h 
b/clang/include/clang/Serialization/ASTBitCodes.h
index f31efa5117f0d1..628ce03572fea6 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -22,6 +22,7 @@
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Serialization/SourceLocationEncoding.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/Bitstream/BitCodes.h"
 #include 
@@ -175,45 +176,38 @@ const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1;
 
 /// Source range/offset of a preprocessed entity.
 struct PPEntityOffset {
+  using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
+
   /// Raw source location of beginning of range.
-  SourceLocation::UIntTy Begin;
+  RawLocEncoding Begin;
 
   /// Raw source location of end of range.
-  SourceLocation::UIntTy End;
+  RawLocEncoding End;
 
   /// Offset in the AST file relative to ModuleFile::MacroOffsetsBase.
   uint32_t BitOffset;
 
-  PPEntityOffset(SourceRange R, uint32_t BitOffset)
-  : Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()),
-BitOffset(BitOffset) {}
-
-  SourceLocation getBegin() const {
-return SourceLocation::getFromRawEncoding(Begin);
-  }
+  PPEntityOffset(RawLocEncoding Begin, RawLocEncoding End, uint32_t BitOffset)
+  : Begin(Begin), End(End), BitOffset(BitOffset) {}
 
-  SourceLocation getEnd() const {
-return SourceLocation::getFromRawEncoding(End);
-  }
+  RawLocEncoding getBegin() const { return Begin; }
+  RawLocEncoding getEnd() const { return End; }
 };
 
 /// Source range of a skipped preprocessor region
 struct PPSkippedRange {
+  using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
+
   /// Raw source location of beginning of range.
-  SourceLocation::UIntTy Begin;
+  RawLocEncoding Begin;
   /// Raw source location of end of range.
-  SourceLocation::UIntTy End;
+  RawLocEncoding End;
 
-  PPSkippedRange(SourceRange R)
-  : Begin(R.getBegin().getRawEncoding()), End(R.getEnd().getRawEncoding()) 
{
-  }
+  PPSkippedRange(RawLocEncoding Begin, RawLocEncoding End)
+  : Begin(Begin), End(End) {}
 
-  SourceLocation getBegin() const {
-return SourceLocation::getFromRawEncoding(Begin);
-  }
-  SourceLocation getEnd() const {
-return SourceLocation::getFromRawEncoding(End);
-  }
+  RawLocEncoding getBegin() const { return Begin; }
+  RawLocEncoding getEnd() const { return End; }
 };
 
 /// Offset in the AST file. Use splitted 64-bit integer into low/high
@@ -239,8 +233,10 @@ struct UnderalignedInt64 {
 
 /// Source location and bit offset of a declaration.
 struct DeclOffset {
+  using RawLocEncoding = SourceLocationEncoding::RawLocEncoding;
+
   /// Raw source location.
-  SourceLocation::UIntTy Loc = 0;
+  RawLocEncoding RawLoc = 0;
 
   /// Offset relative to the start of the DECLTYPES_BLOCK block. Keep
   /// structure alignment 32-bit and avoid padding gap because undefined
@@ -248,17 +244,15 @@ struct DeclOffset {
   UnderalignedInt64 BitOffset;
 
   DeclOffset() = default;
-  DeclOffset(SourceLocation Loc, uint64_t BitOffset,

[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 ready_for_review 
https://github.com/llvm/llvm-project/pull/86912
___
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)

2024-03-28 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

@sam-mccall any updates?

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] [Itanium ABI] Generate the vtable in the module unit of dynamic classes (PR #75912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

@rjmccall @dwblaikie ping

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

 BTW, after this patch, with reduced BMI 
(https://github.com/llvm/llvm-project/pull/85050), we can already do something 
more interesting than reformating:

```
//--- A.cppm
export module A;
int funcA0();
int funcA1();
export int funcA() {
return funcA0();
}

//--- A.v1.cppm
export module A;

int funcA0();
int funcA1();
export int funcA() {
return funcA0() + funcA1();
}

//--- B.cppm
export module B;
import A;

export int funcB() {
return funcA();
}
```

Now the B.pcm will keep unchanged  with `A.pcm` from `A.cppm` and `A.v1.pcm` 
from `A.v1.cppm`. We changed the implementation of `funcA()` from `return 
funcA0();` to `return funcA0() + funcA1();`. And the `B.pcm` can still get the 
same content.

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> By default, `SourceLocation` is 32 bits. One bit is used to distinguish macro 
> expansions. Looking at libc++'s module map, it contains 999 top-level modules 
> at this moment. That's 10 bits just to be able to import the (entire) 
> standard library. That leaves 21 bits, restricting local `SourceLocation` 
> space to 2 MB. This doesn't sound feasible. Did I misunderstand?

Yes, I explained this in `Some low level details` section. The size of source 
location won't be affected. Since the size of source location is unsigned 
(practically, it is 32 bits in most platforms). And we use uint64_t as a unit 
in the serializer. So there are 32 bit not used completely. The plan is to 
store the module file index in the higher 32 bits and it shouldn't be a safe 
problem.

The only trade-off I saw about this change is that it may increase the size of 
**on-disk** .pcm files due to we use VBR6 format to decrease the size of small 
numbers. But on the one side, we still need to pay for more spaces if we want 
to use `{local-module-index, offset-within-module} pair` (Thanks for the good 
name suggestion). On the other hand, from the experiment, it shows the overhead 
is acceptable.

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


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

2024-03-28 Thread Chuanqi Xu via cfe-commits

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

>From b46c8fa030deb980c1550edc0ff8510d4e3c4e17 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Tue, 12 Mar 2024 17:26:49 +0800
Subject: [PATCH 1/3] [C++20] [Modules] Introduce -fgen-reduced-bmi

---
 clang/include/clang/CodeGen/CodeGenAction.h   |  2 +
 clang/include/clang/Driver/Options.td |  6 +++
 .../include/clang/Frontend/FrontendOptions.h  |  9 +++-
 clang/include/clang/Serialization/ASTWriter.h |  7 +--
 clang/lib/CodeGen/CodeGenAction.cpp   | 19 +++
 clang/lib/Driver/Driver.cpp   | 27 +-
 clang/lib/Driver/ToolChains/Clang.cpp | 41 --
 clang/lib/Driver/ToolChains/Clang.h   | 14 +
 clang/lib/Frontend/FrontendActions.cpp|  7 +++
 clang/lib/Frontend/PrecompiledPreamble.cpp|  3 +-
 clang/lib/Serialization/GeneratePCH.cpp   | 23 ++--
 .../test/Driver/module-fgen-reduced-bmi.cppm  | 53 +++
 clang/test/Modules/gen-reduced-bmi.cppm   | 36 +
 13 files changed, 220 insertions(+), 27 deletions(-)
 create mode 100644 clang/test/Driver/module-fgen-reduced-bmi.cppm
 create mode 100644 clang/test/Modules/gen-reduced-bmi.cppm

diff --git a/clang/include/clang/CodeGen/CodeGenAction.h 
b/clang/include/clang/CodeGen/CodeGenAction.h
index 7ad2988e589eb2..186dbb43f01ef7 100644
--- a/clang/include/clang/CodeGen/CodeGenAction.h
+++ b/clang/include/clang/CodeGen/CodeGenAction.h
@@ -57,6 +57,8 @@ class CodeGenAction : public ASTFrontendAction {
   bool loadLinkModules(CompilerInstance &CI);
 
 protected:
+  bool BeginSourceFileAction(CompilerInstance &CI) override;
+
   /// Create a new code generation action.  If the optional \p _VMContext
   /// parameter is supplied, the action uses it without taking ownership,
   /// otherwise it creates a fresh LLVM context and takes ownership.
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 29066ea14280c2..7288bb3db493ba 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3017,6 +3017,7 @@ defm prebuilt_implicit_modules : 
BoolFOption<"prebuilt-implicit-modules",
 
 def fmodule_output_EQ : Joined<["-"], "fmodule-output=">,
   Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>,
+  MarshallingInfoString>,
   HelpText<"Save intermediate module file results when compiling a standard 
C++ module unit.">;
 def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption]>,
   Visibility<[ClangOption, CC1Option]>,
@@ -3030,6 +3031,11 @@ defm skip_odr_check_in_gmf : BoolOption<"f", 
"skip-odr-check-in-gmf",
   "Perform ODR checks for decls in the global module fragment.">>,
   Group;
 
+def gen_reduced_bmi : Flag<["-"], "fgen-reduced-bmi">,
+  Group, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Generate the reduced BMI">,
+  MarshallingInfoFlag>;
+
 def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, 
Group,
   Visibility<[ClangOption, CC1Option]>, MetaVarName<"">,
   HelpText<"Specify the interval (in seconds) between attempts to prune the 
module cache">,
diff --git a/clang/include/clang/Frontend/FrontendOptions.h 
b/clang/include/clang/Frontend/FrontendOptions.h
index 8085dbcbf671a6..ddfd4f30d1b773 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -387,6 +387,10 @@ class FrontendOptions {
   LLVM_PREFERRED_TYPE(bool)
   unsigned ModulesShareFileManager : 1;
 
+  /// Whether to generate reduced BMI for C++20 named modules.
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned GenReducedBMI : 1;
+
   CodeCompleteOptions CodeCompleteOpts;
 
   /// Specifies the output format of the AST.
@@ -553,6 +557,9 @@ class FrontendOptions {
   /// Path which stores the output files for -ftime-trace
   std::string TimeTracePath;
 
+  /// Output Path for module output file.
+  std::string ModuleOutputPath;
+
 public:
   FrontendOptions()
   : DisableFree(false), RelocatablePCH(false), ShowHelp(false),
@@ -565,7 +572,7 @@ class FrontendOptions {
 BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false),
 IncludeTimestamps(true), UseTemporary(true),
 AllowPCMWithCompilerErrors(false), ModulesShareFileManager(true),
-TimeTraceGranularity(500) {}
+GenReducedBMI(false), TimeTraceGranularity(500) {}
 
   /// getInputKindForExtension - Return the appropriate input kind for a file
   /// extension. For example, "c" would return Language::C.
diff --git a/clang/include/clang/Serialization/ASTWriter.h 
b/clang/include/clang/Serialization/ASTWriter.h
index 3ed9803fa3745b..bd310b6c7a5cdd 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -846,7 +846,7 @@ class ASTWriter : public ASTDeserializationListener,
 /// AST and semantic-analysis consumer that generates a
 /// precompiled header from 

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

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


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

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


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

2024-03-28 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

Got it. I've renamed the flag as `-fexperimental-modules-reduced-bmi`. I feel 
the suggestion like let users to use `-Xclang` options look odd..

---

> What do you mean by "symmetric"?

I mean, we always want the users to do something explicitly to enable the 
feature. But this might not be important now.


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


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

2024-03-28 Thread Chuanqi Xu via cfe-commits

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

>From b46c8fa030deb980c1550edc0ff8510d4e3c4e17 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Tue, 12 Mar 2024 17:26:49 +0800
Subject: [PATCH 1/3] [C++20] [Modules] Introduce -fgen-reduced-bmi

---
 clang/include/clang/CodeGen/CodeGenAction.h   |  2 +
 clang/include/clang/Driver/Options.td |  6 +++
 .../include/clang/Frontend/FrontendOptions.h  |  9 +++-
 clang/include/clang/Serialization/ASTWriter.h |  7 +--
 clang/lib/CodeGen/CodeGenAction.cpp   | 19 +++
 clang/lib/Driver/Driver.cpp   | 27 +-
 clang/lib/Driver/ToolChains/Clang.cpp | 41 --
 clang/lib/Driver/ToolChains/Clang.h   | 14 +
 clang/lib/Frontend/FrontendActions.cpp|  7 +++
 clang/lib/Frontend/PrecompiledPreamble.cpp|  3 +-
 clang/lib/Serialization/GeneratePCH.cpp   | 23 ++--
 .../test/Driver/module-fgen-reduced-bmi.cppm  | 53 +++
 clang/test/Modules/gen-reduced-bmi.cppm   | 36 +
 13 files changed, 220 insertions(+), 27 deletions(-)
 create mode 100644 clang/test/Driver/module-fgen-reduced-bmi.cppm
 create mode 100644 clang/test/Modules/gen-reduced-bmi.cppm

diff --git a/clang/include/clang/CodeGen/CodeGenAction.h 
b/clang/include/clang/CodeGen/CodeGenAction.h
index 7ad2988e589eb2..186dbb43f01ef7 100644
--- a/clang/include/clang/CodeGen/CodeGenAction.h
+++ b/clang/include/clang/CodeGen/CodeGenAction.h
@@ -57,6 +57,8 @@ class CodeGenAction : public ASTFrontendAction {
   bool loadLinkModules(CompilerInstance &CI);
 
 protected:
+  bool BeginSourceFileAction(CompilerInstance &CI) override;
+
   /// Create a new code generation action.  If the optional \p _VMContext
   /// parameter is supplied, the action uses it without taking ownership,
   /// otherwise it creates a fresh LLVM context and takes ownership.
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 29066ea14280c2..7288bb3db493ba 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3017,6 +3017,7 @@ defm prebuilt_implicit_modules : 
BoolFOption<"prebuilt-implicit-modules",
 
 def fmodule_output_EQ : Joined<["-"], "fmodule-output=">,
   Flags<[NoXarchOption]>, Visibility<[ClangOption, CC1Option]>,
+  MarshallingInfoString>,
   HelpText<"Save intermediate module file results when compiling a standard 
C++ module unit.">;
 def fmodule_output : Flag<["-"], "fmodule-output">, Flags<[NoXarchOption]>,
   Visibility<[ClangOption, CC1Option]>,
@@ -3030,6 +3031,11 @@ defm skip_odr_check_in_gmf : BoolOption<"f", 
"skip-odr-check-in-gmf",
   "Perform ODR checks for decls in the global module fragment.">>,
   Group;
 
+def gen_reduced_bmi : Flag<["-"], "fgen-reduced-bmi">,
+  Group, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Generate the reduced BMI">,
+  MarshallingInfoFlag>;
+
 def fmodules_prune_interval : Joined<["-"], "fmodules-prune-interval=">, 
Group,
   Visibility<[ClangOption, CC1Option]>, MetaVarName<"">,
   HelpText<"Specify the interval (in seconds) between attempts to prune the 
module cache">,
diff --git a/clang/include/clang/Frontend/FrontendOptions.h 
b/clang/include/clang/Frontend/FrontendOptions.h
index 8085dbcbf671a6..ddfd4f30d1b773 100644
--- a/clang/include/clang/Frontend/FrontendOptions.h
+++ b/clang/include/clang/Frontend/FrontendOptions.h
@@ -387,6 +387,10 @@ class FrontendOptions {
   LLVM_PREFERRED_TYPE(bool)
   unsigned ModulesShareFileManager : 1;
 
+  /// Whether to generate reduced BMI for C++20 named modules.
+  LLVM_PREFERRED_TYPE(bool)
+  unsigned GenReducedBMI : 1;
+
   CodeCompleteOptions CodeCompleteOpts;
 
   /// Specifies the output format of the AST.
@@ -553,6 +557,9 @@ class FrontendOptions {
   /// Path which stores the output files for -ftime-trace
   std::string TimeTracePath;
 
+  /// Output Path for module output file.
+  std::string ModuleOutputPath;
+
 public:
   FrontendOptions()
   : DisableFree(false), RelocatablePCH(false), ShowHelp(false),
@@ -565,7 +572,7 @@ class FrontendOptions {
 BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false),
 IncludeTimestamps(true), UseTemporary(true),
 AllowPCMWithCompilerErrors(false), ModulesShareFileManager(true),
-TimeTraceGranularity(500) {}
+GenReducedBMI(false), TimeTraceGranularity(500) {}
 
   /// getInputKindForExtension - Return the appropriate input kind for a file
   /// extension. For example, "c" would return Language::C.
diff --git a/clang/include/clang/Serialization/ASTWriter.h 
b/clang/include/clang/Serialization/ASTWriter.h
index 3ed9803fa3745b..bd310b6c7a5cdd 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -846,7 +846,7 @@ class ASTWriter : public ASTDeserializationListener,
 /// AST and semantic-analysis consumer that generates a
 /// precompiled header from 

[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

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


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

2024-03-28 Thread Chuanqi Xu via cfe-commits

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

>From 7399d2417a4b758fa0a98da1f99f3b4ec0eb1046 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu 
Date: Tue, 19 Dec 2023 17:00:59 +0800
Subject: [PATCH 1/2] [C++20] [Modules] [Itanium ABI] Generate the vtable in
 the module unit of dynamic classes

Close https://github.com/llvm/llvm-project/issues/70585 and reflect
https://github.com/itanium-cxx-abi/cxx-abi/issues/170.

The significant change of the patch is: for dynamic classes attached to
module units, we generate the vtable to the attached module units
directly and the key functions for such classes is meaningless.
---
 clang/lib/CodeGen/CGVTables.cpp   | 28 ++
 clang/lib/CodeGen/CodeGenModule.cpp   |  9 +
 clang/lib/CodeGen/ItaniumCXXABI.cpp   |  6 +++
 clang/lib/Sema/SemaDecl.cpp   |  9 +
 clang/lib/Sema/SemaDeclCXX.cpp| 13 +--
 clang/lib/Serialization/ASTReaderDecl.cpp | 13 ++-
 clang/lib/Serialization/ASTWriterDecl.cpp | 13 +--
 clang/test/CodeGenCXX/modules-vtable.cppm | 27 -
 clang/test/CodeGenCXX/pr70585.cppm| 47 +++
 9 files changed, 139 insertions(+), 26 deletions(-)
 create mode 100644 clang/test/CodeGenCXX/pr70585.cppm

diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 8dee3f74b44b4e..54a2c725a10ba3 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -1046,6 +1046,11 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) 
{
   if (!RD->isExternallyVisible())
 return llvm::GlobalVariable::InternalLinkage;
 
+  // V-tables for non-template classes with an owning module are always
+  // uniquely emitted in that module.
+  if (Module *M = RD->getOwningModule(); M && M->isNamedModule())
+return llvm::GlobalVariable::ExternalLinkage;
+
   // We're at the end of the translation unit, so the current key
   // function is fully correct.
   const CXXMethodDecl *keyFunction = Context.getCurrentKeyFunction(RD);
@@ -1180,6 +1185,21 @@ bool CodeGenVTables::isVTableExternal(const 
CXXRecordDecl *RD) {
   TSK == TSK_ExplicitInstantiationDefinition)
 return false;
 
+  // Itanium C++ ABI [5.2.3]:
+  // Virtual tables for dynamic classes are emitted as follows:
+  //
+  // - If the class is templated, the tables are emitted in every object that
+  // references any of them.
+  // - Otherwise, if the class is attached to a module, the tables are uniquely
+  // emitted in the object for the module unit in which it is defined.
+  // - Otherwise, if the class has a key function (see below), the tables are
+  // emitted in the object for the translation unit containing the definition 
of
+  // the key function. This is unique if the key function is not inline.
+  // - Otherwise, the tables are emitted in every object that references any of
+  // them.
+  if (Module *M = RD->getOwningModule(); M && M->isNamedModule())
+return M != CGM.getContext().getCurrentNamedModule();
+
   // Otherwise, if the class doesn't have a key function (possibly
   // anymore), the vtable must be defined here.
   const CXXMethodDecl *keyFunction = 
CGM.getContext().getCurrentKeyFunction(RD);
@@ -1189,13 +1209,7 @@ bool CodeGenVTables::isVTableExternal(const 
CXXRecordDecl *RD) {
   const FunctionDecl *Def;
   // Otherwise, if we don't have a definition of the key function, the
   // vtable must be defined somewhere else.
-  if (!keyFunction->hasBody(Def))
-return true;
-
-  assert(Def && "The body of the key function is not assigned to Def?");
-  // If the non-inline key function comes from another module unit, the vtable
-  // must be defined there.
-  return Def->isInAnotherModuleUnit() && !Def->isInlineSpecified();
+  return !keyFunction->hasBody(Def);
 }
 
 /// Given that we're currently at the end of the translation unit, and
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp 
b/clang/lib/CodeGen/CodeGenModule.cpp
index e3ed5e90f2d36b..61369bedd147eb 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -6777,6 +6777,15 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
 if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
   DI->completeUnusedClass(*CRD);
 }
+// If we're emitting a dynamic class from the importable module we're
+// emitting, we always need to emit the virtual table according to the ABI
+// requirement.
+if (CRD->getOwningModule() &&
+CRD->getOwningModule()->isInterfaceOrPartition() &&
+CRD->getDefinition() && CRD->isDynamicClass() &&
+CRD->getOwningModule() == getContext().getCurrentNamedModule())
+  EmitVTable(CRD);
+
 // Emit any static data members, they may be definitions.
 for (auto *I : CRD->decls())
   if (isa(I) || isa(I))
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp 
b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index bdd53a192f828a..6473f356d5bb19 1

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

2024-03-28 Thread Chuanqi Xu via cfe-commits


@@ -41,9 +43,10 @@ Base::~Base() {}
 // CHECK: @_ZTSW3Mod4Base = constant
 // CHECK: @_ZTIW3Mod4Base = constant
 
-// CHECK-INLINE: @_ZTVW3Mod4Base = linkonce_odr {{.*}}unnamed_addr constant
-// CHECK-INLINE: @_ZTSW3Mod4Base = linkonce_odr {{.*}}constant
-// CHECK-INLINE: @_ZTIW3Mod4Base = linkonce_odr {{.*}}constant
+// With the new Itanium C++ ABI, the linkage of vtables in modules don't need 
to be linkonce ODR.

ChuanqiXu9 wrote:

If it is linkonce, as long as I understand correctly, if the vtable is not used 
in the current TU, the middle end is free to remove the unused linkonce entity. 
But this is not wanted. Since all the things in the module purview is 
potentially used. Do I misunderstand anything?

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


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

2024-03-28 Thread Chuanqi Xu via cfe-commits


@@ -1483,10 +1483,15 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl 
*D) {
   if (D->isThisDeclarationADefinition())
 Record.AddCXXDefinitionData(D);
 
-  // Store (what we currently believe to be) the key function to avoid
-  // deserializing every method so we can compute it.
-  if (D->isCompleteDefinition())
-Record.AddDeclRef(Context.getCurrentKeyFunction(D));
+  if (D->isCompleteDefinition()) {
+if (D->getOwningModule() && D->getOwningModule()->isInterfaceOrPartition())
+  Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D));
+else {
+  // Store (what we currently believe to be) the key function to avoid

ChuanqiXu9 wrote:

```suggestion
if (D->isCompleteDefinition() && D->getOwningModule() &&
D->getOwningModule()->isInterfaceOrPartition())
  Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D));

  // Store (what we currently believe to be) the key function to avoid
  // deserializing every method so we can compute it.
  if (D->isCompleteDefinition())
Record.AddDeclRef(Context.getCurrentKeyFunction(D));
```

Do you mean such changes? I feel it is somewhat overkill since it looks pretty 
straight forward due to the code is pretty near and the patch itself is about 
we don't need more key functions in modules.

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


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

2024-03-28 Thread Chuanqi Xu via cfe-commits


@@ -60,11 +63,11 @@ int use() {
 
 // CHECK-NOT: @_ZTSW3Mod4Base = constant
 // CHECK-NOT: @_ZTIW3Mod4Base = constant
-// CHECK: @_ZTVW3Mod4Base = external unnamed_addr
+// CHECK: @_ZTVW3Mod4Base = external
 
-// CHECK-INLINE: @_ZTVW3Mod4Base = linkonce_odr {{.*}}unnamed_addr constant
-// CHECK-INLINE: @_ZTSW3Mod4Base = linkonce_odr {{.*}}constant
-// CHECK-INLINE: @_ZTIW3Mod4Base = linkonce_odr {{.*}}constant
+// CHECK-INLINE-NOT: @_ZTSW3Mod4Base = constant

ChuanqiXu9 wrote:

They should be emitted in other TU and not emitted at all in the current TU. So 
I updated the test to `// CHECK-INLINE-NOT: @_ZTSW3Mod4Base` as suggested.

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-28 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> > Yes, I explained this in Some low level details section. The size of source 
> > location won't be affected. Since the size of source location is unsigned 
> > (practically, it is 32 bits in most platforms). And we use uint64_t as a 
> > unit in the serializer. So there are 32 bit not used completely. The plan 
> > is to store the module file index in the higher 32 bits and it shouldn't be 
> > a safe problem. Maybe the original wording is not so clear. I've updated it.
> 
> Thank you, using 64 bits in the serialization format makes sense! This also 
> means that whenever Clang is configured with 64 bit `SourceLocation`, we 
> should be using 96 bits for serialization: 32 bits for the module file index 
> and 64 bits for the offset itself, correct?

If Clang is configured with 64 bit `SourceLocation`, we can't use 96 bits for 
serialization. We can at most use 64 bits for a slot. In that case, we can only 
assume the offset of source location **in its own module** (not the global 
offset!) is not large than 2^32. I hope this may not be true.

> 
> > The only trade-off I saw about this change is that it may increase the size 
> > of **on-disk** .pcm files due to we use VBR6 format to decrease the size of 
> > small numbers. But on the one side, we still need to pay for more spaces if 
> > we want to use `{local-module-index, offset-within-module} pair` (Thanks 
> > for the good name suggestion). On the other hand, from the experiment, it 
> > shows the overhead is acceptable.
> 
> Sorry, I don't quite understand. Are you saying you did or did not try to 
> encode this as two separate 32bit values?

I **tried** to encode this as two separate 32bit values. But it will break too 
many codes. Since a lot of places assume that we can encode the source location 
as an uint64_t.

What I mean is, with VBR6 format 
(https://llvm.org/docs/BitCodeFormat.html#variable-width-integer),  we can save 
more space for small integers in **on-disk** .pcm files (the memory 
representation should be the same). For example, for a 64 bits unsigned int 
`1`, VBR6 can use only 6 bits to store that `01` to represent the 64 bits 
value `1` in the on-disk representations. So that even if I don't use more 
slots to store the module file index, the size of the .pcm files will increase 
after all.

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


[clang] 235d684 - [C++20] [Modules] [Reduced BMI] Don't record declarations in functions

2024-03-28 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2024-03-29T14:21:45+08:00
New Revision: 235d6841601a9dbea293b8e82b0c994f91f42d76

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

LOG: [C++20] [Modules] [Reduced BMI] Don't record declarations in functions
by default

For reduced BMI, it is meaningless to record the local declarations in
functions if not required explicitly during the process of writing the
function bodies.

It wastes time for reduced BMI and may be problematic if we want to
avoid transiting unnecessary changes.

Added: 
clang/test/Modules/no-local-decl-in-reduced-bmi.cppm

Modified: 
clang/lib/Serialization/ASTWriter.cpp

Removed: 




diff  --git a/clang/lib/Serialization/ASTWriter.cpp 
b/clang/lib/Serialization/ASTWriter.cpp
index 2cc7f21bf60c49..1e5734c9c834eb 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -3195,6 +3195,10 @@ uint64_t 
ASTWriter::WriteDeclContextLexicalBlock(ASTContext &Context,
   if (DC->decls_empty())
 return 0;
 
+  // In reduced BMI, we don't care the declarations in functions.
+  if (GeneratingReducedBMI && DC->isFunctionOrMethod())
+return 0;
+
   uint64_t Offset = Stream.GetCurrentBitNo();
   SmallVector KindDeclPairs;
   for (const auto *D : DC->decls()) {

diff  --git a/clang/test/Modules/no-local-decl-in-reduced-bmi.cppm 
b/clang/test/Modules/no-local-decl-in-reduced-bmi.cppm
new file mode 100644
index 00..41ae2bf0dec809
--- /dev/null
+++ b/clang/test/Modules/no-local-decl-in-reduced-bmi.cppm
@@ -0,0 +1,33 @@
+// Test that we won't record local declarations by default in reduced BMI.
+
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+//
+// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-reduced-module-interface -o 
%t/a.pcm
+// RUN: llvm-bcanalyzer --dump --disable-histogram --show-binary-blobs 
%t/a.pcm > %t/a.dump
+// RUN: cat %t/a.dump | FileCheck %t/a.cppm
+//
+// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o 
%t/b.pcm
+// RUN: llvm-bcanalyzer --dump --disable-histogram --show-binary-blobs 
%t/b.pcm > %t/b.dump
+// RUN: cat %t/b.dump | FileCheck %t/b.cppm
+
+//--- a.cppm
+export module a;
+export int func() {
+int v = 43;
+return 43;
+}
+
+// Test that the variable declaration is not recorded completely.
+// CHECK-NOT: https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [coroutine] Implement llvm.coro.await.suspend intrinsic (PR #79712)

2024-03-29 Thread Chuanqi Xu via cfe-commits


@@ -338,6 +409,69 @@ static QualType getCoroutineSuspendExprReturnType(const 
ASTContext &Ctx,
 }
 #endif
 
+llvm::Function *
+CodeGenFunction::generateAwaitSuspendWrapper(Twine const &CoroName,
+ Twine const &SuspendPointName,
+ CoroutineSuspendExpr const &S) {
+  std::string FuncName = "__await_suspend_wrapper_";
+  FuncName += CoroName.str();
+  FuncName += '_';
+  FuncName += SuspendPointName.str();
+
+  ASTContext &C = getContext();
+
+  FunctionArgList args;
+
+  ImplicitParamDecl AwaiterDecl(C, C.VoidPtrTy, ImplicitParamKind::Other);
+  ImplicitParamDecl FrameDecl(C, C.VoidPtrTy, ImplicitParamKind::Other);
+  QualType ReturnTy = S.getSuspendExpr()->getType();
+
+  args.push_back(&AwaiterDecl);
+  args.push_back(&FrameDecl);
+
+  const CGFunctionInfo &FI =
+  CGM.getTypes().arrangeBuiltinFunctionDeclaration(ReturnTy, args);
+
+  llvm::FunctionType *LTy = CGM.getTypes().GetFunctionType(FI);
+
+  llvm::Function *Fn = llvm::Function::Create(
+  LTy, llvm::GlobalValue::PrivateLinkage, FuncName, &CGM.getModule());
+
+  Fn->addParamAttr(0, llvm::Attribute::AttrKind::NonNull);
+  Fn->addParamAttr(0, llvm::Attribute::AttrKind::NoUndef);
+
+  Fn->addParamAttr(1, llvm::Attribute::AttrKind::NoUndef);
+
+  Fn->setMustProgress();
+  Fn->addFnAttr(llvm::Attribute::AttrKind::AlwaysInline);
+
+  StartFunction(GlobalDecl(), ReturnTy, Fn, FI, args);
+
+  // FIXME: add TBAA metadata to the loads
+  llvm::Value *AwaiterPtr = 
Builder.CreateLoad(GetAddrOfLocalVar(&AwaiterDecl));
+  auto AwaiterLValue =
+  MakeNaturalAlignAddrLValue(AwaiterPtr, AwaiterDecl.getType());

ChuanqiXu9 wrote:

Yeah.. it looks like it would be better to pass the type of 
`S.getOpaqueValue()`. The ` void*` is simply a placeholder.

Would you like to handle this? I feel you are the better option since you can 
test it with your own patch. Otherwise I'll try to make it myself.

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


[clang] abfc5ef - [NFC] [Decl] Introduce Decl::isFromExplicitGlobalModule

2024-03-29 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2024-03-29T16:21:02+08:00
New Revision: abfc5efb55267689f1852fd7ce3e0a38876aa259

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

LOG: [NFC] [Decl] Introduce Decl::isFromExplicitGlobalModule

Introduce `Decl::isFromExplicitGlobalModule` to replace the
`D->getOwningModule() && D->getOwningModule()->isExplicitGlobalModule()`
pattern to save some typings.

Added: 


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

Removed: 




diff  --git a/clang/include/clang/AST/DeclBase.h 
b/clang/include/clang/AST/DeclBase.h
index 47ed6d0d1db0df..858450926455c6 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -669,9 +669,8 @@ class alignas(8) Decl {
   /// Whether this declaration comes from another module unit.
   bool isInAnotherModuleUnit() const;
 
-  /// FIXME: Implement discarding declarations actually in global module
-  /// fragment. See [module.global.frag]p3,4 for details.
-  bool isDiscardedInGlobalModuleFragment() const { return false; }
+  /// Whether this declaration comes from explicit global module.
+  bool isFromExplicitGlobalModule() const;
 
   /// Check if we should skip checking ODRHash for declaration \param D.
   ///

diff  --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 04bbc49ab2f319..2cbb86b31b5e2e 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1102,9 +1102,13 @@ bool Decl::isInAnotherModuleUnit() const {
   return M != getASTContext().getCurrentNamedModule();
 }
 
+bool Decl::isFromExplicitGlobalModule() const {
+  return getOwningModule() && getOwningModule()->isExplicitGlobalModule();
+}
+
 bool Decl::shouldSkipCheckingODR() const {
-  return getASTContext().getLangOpts().SkipODRCheckInGMF && getOwningModule() 
&&
- getOwningModule()->isExplicitGlobalModule();
+  return getASTContext().getLangOpts().SkipODRCheckInGMF &&
+ isFromExplicitGlobalModule();
 }
 
 static Decl::Kind getKind(const Decl *D) { return D->getKind(); }

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0bd88ece2aa544..503f1f6f53a258 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9915,7 +9915,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, 
DeclContext *DC,
 // FIXME: We need a better way to separate C++ standard and clang modules.
 bool ImplicitInlineCXX20 = !getLangOpts().CPlusPlusModules ||
!NewFD->getOwningModule() ||
-   NewFD->getOwningModule()->isGlobalModule() ||
+   NewFD->isFromExplicitGlobalModule() ||
NewFD->getOwningModule()->isHeaderLikeModule();
 bool isInline = D.getDeclSpec().isInlineSpecified();
 bool isVirtual = D.getDeclSpec().isVirtualSpecified();

diff  --git a/clang/unittests/AST/DeclTest.cpp 
b/clang/unittests/AST/DeclTest.cpp
index cef0f8711416b6..2530ce74eb6a37 100644
--- a/clang/unittests/AST/DeclTest.cpp
+++ b/clang/unittests/AST/DeclTest.cpp
@@ -429,7 +429,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) {
 .bind("operator new"),
 Ctx));
   ASSERT_TRUE(SizedOperatorNew->getOwningModule());
-  EXPECT_TRUE(SizedOperatorNew->getOwningModule()->isGlobalModule());
+  EXPECT_TRUE(SizedOperatorNew->isFromExplicitGlobalModule());
 
   // void* operator new(std::size_t, std::align_val_t);
   auto *SizedAlignedOperatorNew = selectFirst(
@@ -441,7 +441,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) {
 .bind("operator new"),
 Ctx));
   ASSERT_TRUE(SizedAlignedOperatorNew->getOwningModule());
-  EXPECT_TRUE(SizedAlignedOperatorNew->getOwningModule()->isGlobalModule());
+  EXPECT_TRUE(SizedAlignedOperatorNew->isFromExplicitGlobalModule());
 
   // void* operator new[](std::size_t);
   auto *SizedArrayOperatorNew = selectFirst(
@@ -451,7 +451,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) {
 .bind("operator new[]"),
 Ctx));
   ASSERT_TRUE(SizedArrayOperatorNew->getOwningModule());
-  EXPECT_TRUE(SizedArrayOperatorNew->getOwningModule()->isGlobalModule());
+  EXPECT_TRUE(SizedArrayOperatorNew->isFromExplicitGlobalModule());
 
   // void* operator new[](std::size_t, std::align_val_t);
   auto *SizedAlignedArrayOperatorNew = selectFirst(
@@ -464,7 +464,7 @@ TEST(Decl, ImplicitlyDeclaredAllocationFunctionsInModules) {
 Ctx));
   ASSERT_TRUE(SizedAlignedArrayOperatorNew->getOwningModule());
   EXPECT_TRUE(
-  SizedAlignedArrayOperatorNew->getOwningModule()->isGlobalModule());
+  SizedAlignedArrayOperat

[clang] [C++20] [Modules] Implementing Eliding Unreachable Decls of GMF in ASTWriter (PR #76930)

2024-03-29 Thread Chuanqi Xu via cfe-commits

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


[clang] [C++20] [Modules] Implementing Eliding Unreachable Decls of GMF in ASTWriter (PR #76930)

2024-03-29 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

I took another review on this patch and it shows the patch itself is not so 
correct.

The idea of the patch is to skip GMF at first and start to write the module 
from the module purview directly. Then everything unused in GMF is not used. 
This seems fine. However, in the module purview, if we used something from a 
namespace of the GMF, we would everything in the namespace back. This is 
terrible. So in this patch, when we visit decl context, we skipped adding 
unreached declarations. 

However, this is the problem. Since an unreached declaration during the process 
of writing become be reachable in the end of the writing. However, we've 
skipped it.

To solve this, either we need to write the declaration context lazily or 
perform a walk ahead of time. But clearly, we can't continue with the current 
patch. I'll bring a new one after I figured it out.

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


[clang] [Clang] Coroutines: Properly Check if `await_suspend` return type is a `std::coroutine_handle` (PR #85684)

2024-03-31 Thread Chuanqi Xu via cfe-commits


@@ -418,39 +448,60 @@ static ReadySuspendResumeResult buildCoawaitCalls(Sema 
&S, VarDecl *CoroPromise,
 return Calls;
   }
   Expr *CoroHandle = CoroHandleRes.get();
-  CallExpr *AwaitSuspend = cast_or_null(
-  BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));
+  auto *AwaitSuspend = [&]() -> CallExpr * {
+auto *SubExpr = BuildSubExpr(ACT::ACT_Suspend, "await_suspend", 
CoroHandle);
+if (!SubExpr)
+  return nullptr;
+if (auto *E = dyn_cast(SubExpr)) {
+  // This happens when await_suspend return type is not trivially
+  // destructible. This doesn't happen for the permitted return types of
+  // such function. Diagnose it later.
+  return cast_or_null(E->getSubExpr());
+} else {
+  return cast_or_null(SubExpr);
+}

ChuanqiXu9 wrote:

Sorry. The `Operand` is referred to the definitions in line 405, whose type 
should be the type of the corresponding `awaiter`. The idea here is, if we can 
get the type of the `awaiter` directly, we can avoid the pattern match here.

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


[clang] [coroutine] Fix type of an ImplicitParamDecl used in generateAwaitSuspendWrapper (PR #87134)

2024-03-31 Thread Chuanqi Xu via cfe-commits

https://github.com/ChuanqiXu9 commented:

The change itself looks good to me. It will be better if we can have a reduced 
test case.

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


[clang] [Modules] No transitive source location change (PR #86912)

2024-03-31 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> > If Clang is configured with 64 bit `SourceLocation`, we can't use 96 bits 
> > for serialization. We can at most use 64 bits for a slot. In that case, we 
> > can only assume the offset of source location **in its own module** (not 
> > the global offset!) is not large than 2^32. I feel this assumption may be 
> > valid in a lot of places.
> > Or otherwise we can use less bits for module file index (32 bits seems to 
> > be too much honestly), then we can use higher 16 bits to store the module 
> > file index, and leave the lower 48 bits to store the source location. In 
> > this case, the assumption becomes to "the offset of the source location may 
> > not large than 2^48". But it is slightly hard to believe we can reach such 
> > extreme cases.
> 
> Let's see if @statham-arm (who introduced the `SourceLocation::[U]IntTy` 
> typedefs) wants to weight in here.
> 
> > I **tried** to encode this as two separate 32bit values. But it will break 
> > too many codes. Since a lot of places assume that we can encode the source 
> > location as an uint64_t.
> > What I mean is, with VBR6 format 
> > (https://llvm.org/docs/BitCodeFormat.html#variable-width-integer), we can 
> > save more space for small integers in **on-disk** .pcm files (the memory 
> > representation should be the same). For example, for a 64 bits unsigned int 
> > `1`, VBR6 can use only 6 bits to store that `01` to represent the 64 
> > bits value `1` in the on-disk representations. So that even if I don't use 
> > more slots to store the module file index, the size of the .pcm files will 
> > increase after all.
> 
> Right. My thinking was that single 64bit value with the module file index in 
> the upper 32 bits would basically disable VBR6 encoding for the lower 32 
> bits. If we split this thing into two separate 32bit values, we are more 
> likely to VBR6 encode both of them. But this would actually increase size for 
> (what I assume is the most common case) local source locations. 

Yes, this is the trade offs.

> Still, I think having a rough idea of how alternative implementations compare 
> would be great.
> 
> Do you have any data on how much recompilation this can save for real world 
> projects?

I don't have a specific data though. But I think it is understandable that the 
feature is super important. And we can save countless unnecessary compilations 
after this feature.

After the patch, for reduced BMI, we're already able to avoid changing the BMI 
if we only change the definitions of non-inline function bodies in the module 
unit.

Further more, based on this patch, we can do further optimizations. e.g., if we 
split declaration ID like we did in this patch, we may be able to avoid 
recompilations if a unreferenced module unit adds or deletes declarations. This 
may be pretty common in practice:

```
export module interface:part1;
...

//--- 
export module interface:part2;
...

//--- export module interface;
export import :part1;
export import :part2;

//--- consumer.cppm
export module consumer;
import interface;
// only used declarations in interface:part1;
```

Then if the user only changes module unit `interface:part2`, then we can keep 
the BMI for `consumer.cppm` the same. That implies every user of 
`consumer.cppm` can avoid recompilations.

---

I see this is a killer feature for C++20 modules. I think it is significantly 
valuable. So I really want to make this (including later optimizations) into 
clang19.

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


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

2024-04-01 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

> > Got it. I've renamed the flag as `-fexperimental-modules-reduced-bmi`.
> 
> Thanks.
> 
> > I feel the suggestion like let users to use `-Xclang` options look odd..
> 
> I think the point here is that we want **expert** users to try this out (with 
> understanding that it might not behave exactly as they expect). Because it is 
> experimental, it is not yet ready for "end users" - I would expect expert 
> users to be able to deal with -Xclang x (but I will not insist, it's just 
> a suggestion)

Agreed.

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


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

2024-04-01 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

I'd like to land this patch in next week if no objection comes in.

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


[clang] ef0291e - [NFC] [Serialization] Reordering lexcical and visible TU block after type decl offsets

2024-04-01 Thread Chuanqi Xu via cfe-commits

Author: Chuanqi Xu
Date: 2024-04-01T16:16:03+08:00
New Revision: ef0291e5f4451abbafab0c839bf51a6382f735f3

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

LOG: [NFC] [Serialization] Reordering lexcical and visible TU block after type 
decl offsets

This patch reorder the lexical block for the translation unit, visible update 
block for the TU and
the viisble upaete block for the extern C context after the type decl
offsets block.

This should be a NFC patch.

This is helpful for later optimizations for eliding unreachable
declarations in the global module fragment. See the comments in
https://github.com/llvm/llvm-project/pull/76930.

Simply, if we want to get the reachable sets of declaratins during the
writing process, we need to write the file-level context later than the
process of writing declarations (which is the main process to determine
the reachable set).

Added: 


Modified: 
clang/lib/Serialization/ASTWriter.cpp
clang/test/Modules/language-linkage.cppm

Removed: 




diff  --git a/clang/lib/Serialization/ASTWriter.cpp 
b/clang/lib/Serialization/ASTWriter.cpp
index 1e5734c9c834eb..2438fbc166062f 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4959,38 +4959,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, 
StringRef isysroot,
 Stream.EmitRecord(METADATA_OLD_FORMAT, Record);
   }
 
-  // Create a lexical update block containing all of the declarations in the
-  // translation unit that do not come from other AST files.
   const TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
-  SmallVector NewGlobalKindDeclPairs;
-  for (const auto *D : TU->noload_decls()) {
-if (!D->isFromASTFile()) {
-  NewGlobalKindDeclPairs.push_back(D->getKind());
-  NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
-}
-  }
-
-  auto Abv = std::make_shared();
-  Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
-  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
-  unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv));
-  {
-RecordData::value_type Record[] = {TU_UPDATE_LEXICAL};
-Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
-  bytes(NewGlobalKindDeclPairs));
-  }
 
-  // And a visible updates block for the translation unit.
-  Abv = std::make_shared();
-  Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
-  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
-  Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
-  UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));
-  WriteDeclContextVisibleUpdate(TU);
-
-  // If we have any extern "C" names, write out a visible update for them.
-  if (Context.ExternCContext)
-WriteDeclContextVisibleUpdate(Context.ExternCContext);
+  // Force all top level declarations to be emitted.
+  for (const auto *D : TU->noload_decls())
+if (!D->isFromASTFile())
+  GetDeclRef(D);
 
   // If the translation unit has an anonymous namespace, and we don't already
   // have an update block for it, write it as an update block.
@@ -5131,6 +5105,14 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, 
StringRef isysroot,
   for (auto *D : SemaRef.DeclsToCheckForDeferredDiags)
 DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D));
 
+  {
+auto Abv = std::make_shared();
+Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_VISIBLE));
+Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6));
+Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+UpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv));
+  }
+
   RecordData DeclUpdatesOffsetsRecord;
 
   // Keep writing types, declarations, and declaration update records
@@ -5158,6 +5140,35 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, 
StringRef isysroot,
   WriteTypeDeclOffsets();
   if (!DeclUpdatesOffsetsRecord.empty())
 Stream.EmitRecord(DECL_UPDATE_OFFSETS, DeclUpdatesOffsetsRecord);
+
+  // Create a lexical update block containing all of the declarations in the
+  // translation unit that do not come from other AST files.
+  {
+SmallVector NewGlobalKindDeclPairs;
+for (const auto *D : TU->noload_decls()) {
+  if (!D->isFromASTFile()) {
+NewGlobalKindDeclPairs.push_back(D->getKind());
+NewGlobalKindDeclPairs.push_back(GetDeclRef(D));
+  }
+}
+
+auto Abv = std::make_shared();
+Abv->Add(llvm::BitCodeAbbrevOp(TU_UPDATE_LEXICAL));
+Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob));
+unsigned TuUpdateLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv));
+
+RecordData::value_type Record[] = {TU_UPDATE_LEXICAL};
+Stream.EmitRecordWithBlob(TuUpdateLexicalAbbrev, Record,
+  bytes(NewGlo

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

2024-04-01 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

I think the support for modules in clangd is pretty important. I posted 
https://discourse.llvm.org/t/rfc-directions-for-modules-support-in-clangd/78072 
and let's see if we can make some progress.

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   >