https://github.com/zhy-tju updated 
https://github.com/llvm/llvm-project/pull/147036

>From 4b098e63f1c1aa8bb4c7d4d1966a22c236a9ff17 Mon Sep 17 00:00:00 2001
From: zhy <2697737...@qq.com>
Date: Fri, 4 Jul 2025 16:50:03 +0800
Subject: [PATCH 1/3] [Clang] Duplicate diagnostics in C++20+ mode

---
 clang/include/clang/Sema/DeclSpec.h | 10 ++++++++++
 clang/lib/Sema/SemaCXXScopeSpec.cpp | 10 ++++++++++
 2 files changed, 20 insertions(+)

diff --git a/clang/include/clang/Sema/DeclSpec.h 
b/clang/include/clang/Sema/DeclSpec.h
index 567ad2d5934d4..8721b836002e2 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -76,6 +76,10 @@ class CXXScopeSpec {
   NestedNameSpecifierLocBuilder Builder;
   ArrayRef<TemplateParameterList *> TemplateParamLists;
 
+  /// Flag indicating whether an incomplete-type diagnostic
+  /// has already been emitted for this scope specifier.
+  bool HadIncompleteTypeError = false;
+
 public:
   SourceRange getRange() const { return Range; }
   void setRange(SourceRange R) { Range = R; }
@@ -83,6 +87,12 @@ class CXXScopeSpec {
   void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
   SourceLocation getBeginLoc() const { return Range.getBegin(); }
   SourceLocation getEndLoc() const { return Range.getEnd(); }
+  
+  /// Return true if an incomplete-type diagnostic has already been emitted.
+  bool hasIncompleteTypeError() const { return HadIncompleteTypeError; }
+
+  /// Mark that an incomplete-type error was emitted for this scope.
+  void setIncompleteTypeError(bool v = true) { HadIncompleteTypeError = v; }
 
   void setTemplateParamLists(ArrayRef<TemplateParameterList *> L) {
     TemplateParamLists = L;
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp 
b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index ab83f625d2849..a95d2e83768e2 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -209,10 +209,20 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
   SourceLocation loc = SS.getLastQualifierNameLoc();
   if (loc.isInvalid()) loc = SS.getRange().getBegin();
 
+  // If an incomplete-type error has already been emitted for this scope,
+  // suppress duplicate diagnostics to avoid noisy repeated messages.
+  if (SS.hasIncompleteTypeError())
+    return true;
+
   // The type must be complete.
   if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec,
                           SS.getRange())) {
     SS.SetInvalid(SS.getRange());
+
+    // Remember that we've already diagnosed this incomplete type,
+    // so later checks won't emit redundant diagnostics.
+    SS.setIncompleteTypeError();
+
     return true;
   }
 

>From 7a111a6b45f43b84be4a33d20763fd002e501deb Mon Sep 17 00:00:00 2001
From: zhy <2697737...@qq.com>
Date: Fri, 4 Jul 2025 17:19:50 +0800
Subject: [PATCH 2/3] [Clang] Duplicate diagnostics in C++20+ mode

---
 clang/test/SemaCXX/nested-name-spec.cpp | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/clang/test/SemaCXX/nested-name-spec.cpp 
b/clang/test/SemaCXX/nested-name-spec.cpp
index abeaba9d8dde2..df82d7a8dcf70 100644
--- a/clang/test/SemaCXX/nested-name-spec.cpp
+++ b/clang/test/SemaCXX/nested-name-spec.cpp
@@ -1,3 +1,10 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+struct incomplete;
+incomplete::type var; // expected-error{{incomplete type 'incomplete' named in 
nested name specifier}}
+// expected-note@-2{{forward declaration of 'incomplete'}}
+
+
 // RUN: %clang_cc1 -fsyntax-only -std=c++98 -verify -fblocks %s
 namespace A {
   struct C {

>From 9d650488a66ae47878ca5d13c3353da7bb4dac38 Mon Sep 17 00:00:00 2001
From: zhy <2697737...@qq.com>
Date: Fri, 4 Jul 2025 18:27:28 +0800
Subject: [PATCH 3/3] [Clang] Duplicate diagnostics

---
 clang/include/clang/Sema/DeclSpec.h | 10 ----------
 clang/include/clang/Sema/Sema.h     |  6 ++++++
 clang/lib/Sema/SemaCXXScopeSpec.cpp | 17 ++++++++---------
 3 files changed, 14 insertions(+), 19 deletions(-)

diff --git a/clang/include/clang/Sema/DeclSpec.h 
b/clang/include/clang/Sema/DeclSpec.h
index 8721b836002e2..567ad2d5934d4 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -76,10 +76,6 @@ class CXXScopeSpec {
   NestedNameSpecifierLocBuilder Builder;
   ArrayRef<TemplateParameterList *> TemplateParamLists;
 
-  /// Flag indicating whether an incomplete-type diagnostic
-  /// has already been emitted for this scope specifier.
-  bool HadIncompleteTypeError = false;
-
 public:
   SourceRange getRange() const { return Range; }
   void setRange(SourceRange R) { Range = R; }
@@ -87,12 +83,6 @@ class CXXScopeSpec {
   void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
   SourceLocation getBeginLoc() const { return Range.getBegin(); }
   SourceLocation getEndLoc() const { return Range.getEnd(); }
-  
-  /// Return true if an incomplete-type diagnostic has already been emitted.
-  bool hasIncompleteTypeError() const { return HadIncompleteTypeError; }
-
-  /// Mark that an incomplete-type error was emitted for this scope.
-  void setIncompleteTypeError(bool v = true) { HadIncompleteTypeError = v; }
 
   void setTemplateParamLists(ArrayRef<TemplateParameterList *> L) {
     TemplateParamLists = L;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3fe26f950ad51..1c7a67d32cf72 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1555,6 +1555,12 @@ class Sema final : public SemaBase {
   Sema(const Sema &) = delete;
   void operator=(const Sema &) = delete;
 
+  /// Used to suppress duplicate diagnostics for incomplete types
+  /// in nested name specifiers (e.g. `incomplete::type`).
+  /// Without this, Clang may emit the same error multiple times
+  /// in C++20 or later, due to multiple semantic passes over the scope.
+  llvm::DenseSet<const TagDecl *> IncompleteDiagSet;
+
   /// The handler for the FileChanged preprocessor events.
   ///
   /// Used for diagnostics that implement custom semantic analysis for #include
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp 
b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index a95d2e83768e2..8731f3cbbb8cd 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -206,22 +206,21 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
   if (tag->isBeingDefined())
     return false;
 
+  // Avoid emitting duplicate diagnostics for the same tag.
+  // This happens in C++20+ due to more aggressive semantic analysis.
+  if (IncompleteDiagSet.contains(tag))
+    return true;
+
   SourceLocation loc = SS.getLastQualifierNameLoc();
   if (loc.isInvalid()) loc = SS.getRange().getBegin();
 
-  // If an incomplete-type error has already been emitted for this scope,
-  // suppress duplicate diagnostics to avoid noisy repeated messages.
-  if (SS.hasIncompleteTypeError())
-    return true;
-
   // The type must be complete.
   if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec,
                           SS.getRange())) {
-    SS.SetInvalid(SS.getRange());
+    // mark as diagnosed
+    IncompleteDiagSet.insert(tag); 
 
-    // Remember that we've already diagnosed this incomplete type,
-    // so later checks won't emit redundant diagnostics.
-    SS.setIncompleteTypeError();
+    SS.SetInvalid(SS.getRange());
 
     return true;
   }

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

Reply via email to