Skip to content

Commit 9d65048

Browse files
committed
[Clang] Duplicate diagnostics
1 parent 7a111a6 commit 9d65048

File tree

3 files changed

+14
-19
lines changed

3 files changed

+14
-19
lines changed

clang/include/clang/Sema/DeclSpec.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,13 @@ class CXXScopeSpec {
7676
NestedNameSpecifierLocBuilder Builder;
7777
ArrayRef<TemplateParameterList *> TemplateParamLists;
7878

79-
/// Flag indicating whether an incomplete-type diagnostic
80-
/// has already been emitted for this scope specifier.
81-
bool HadIncompleteTypeError = false;
82-
8379
public:
8480
SourceRange getRange() const { return Range; }
8581
void setRange(SourceRange R) { Range = R; }
8682
void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); }
8783
void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); }
8884
SourceLocation getBeginLoc() const { return Range.getBegin(); }
8985
SourceLocation getEndLoc() const { return Range.getEnd(); }
90-
91-
/// Return true if an incomplete-type diagnostic has already been emitted.
92-
bool hasIncompleteTypeError() const { return HadIncompleteTypeError; }
93-
94-
/// Mark that an incomplete-type error was emitted for this scope.
95-
void setIncompleteTypeError(bool v = true) { HadIncompleteTypeError = v; }
9686

9787
void setTemplateParamLists(ArrayRef<TemplateParameterList *> L) {
9888
TemplateParamLists = L;

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,12 @@ class Sema final : public SemaBase {
15551555
Sema(const Sema &) = delete;
15561556
void operator=(const Sema &) = delete;
15571557

1558+
/// Used to suppress duplicate diagnostics for incomplete types
1559+
/// in nested name specifiers (e.g. `incomplete::type`).
1560+
/// Without this, Clang may emit the same error multiple times
1561+
/// in C++20 or later, due to multiple semantic passes over the scope.
1562+
llvm::DenseSet<const TagDecl *> IncompleteDiagSet;
1563+
15581564
/// The handler for the FileChanged preprocessor events.
15591565
///
15601566
/// Used for diagnostics that implement custom semantic analysis for #include

clang/lib/Sema/SemaCXXScopeSpec.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,22 +206,21 @@ bool Sema::RequireCompleteDeclContext(CXXScopeSpec &SS,
206206
if (tag->isBeingDefined())
207207
return false;
208208

209+
// Avoid emitting duplicate diagnostics for the same tag.
210+
// This happens in C++20+ due to more aggressive semantic analysis.
211+
if (IncompleteDiagSet.contains(tag))
212+
return true;
213+
209214
SourceLocation loc = SS.getLastQualifierNameLoc();
210215
if (loc.isInvalid()) loc = SS.getRange().getBegin();
211216

212-
// If an incomplete-type error has already been emitted for this scope,
213-
// suppress duplicate diagnostics to avoid noisy repeated messages.
214-
if (SS.hasIncompleteTypeError())
215-
return true;
216-
217217
// The type must be complete.
218218
if (RequireCompleteType(loc, type, diag::err_incomplete_nested_name_spec,
219219
SS.getRange())) {
220-
SS.SetInvalid(SS.getRange());
220+
// mark as diagnosed
221+
IncompleteDiagSet.insert(tag);
221222

222-
// Remember that we've already diagnosed this incomplete type,
223-
// so later checks won't emit redundant diagnostics.
224-
SS.setIncompleteTypeError();
223+
SS.SetInvalid(SS.getRange());
225224

226225
return true;
227226
}

0 commit comments

Comments
 (0)