Skip to content

Conversation

mizvekov
Copy link
Contributor

Clang skips parsing a TagDecl definition in case a definition was already parsed in another module.

In those cases, an EnumDecl might be left without an IntegerType. Take this into account when getting the underlying type of an enum, look for the integer type in the definition instead in those cases.

This patch also changes the implementation so it properly marks those skipped tag definitions as demoted.

This fixes a regression reported here: #155028 (comment)

Since this regression was never released, there are no release notes.

Clang skips parsing a TagDecl definition in case a definition was already parsed
in another module.

In those cases, an EnumDecl might be left without an IntegerType.
Take this into account when getting the underlying type of an enum,
look for the integer type in the definition instead in those cases.

This patch also changes the implementation so it properly marks those
skipped tag definitions as demoted.

This fixes a regression reported here: #155028 (comment)

Since this regression was never released, there are no release notes.
@mizvekov mizvekov self-assigned this Aug 28, 2025
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules labels Aug 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 28, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-modules

Author: Matheus Izvekov (mizvekov)

Changes

Clang skips parsing a TagDecl definition in case a definition was already parsed in another module.

In those cases, an EnumDecl might be left without an IntegerType. Take this into account when getting the underlying type of an enum, look for the integer type in the definition instead in those cases.

This patch also changes the implementation so it properly marks those skipped tag definitions as demoted.

This fixes a regression reported here: #155028 (comment)

Since this regression was never released, there are no release notes.


Full diff: https://github.com/llvm/llvm-project/pull/155900.diff

3 Files Affected:

  • (modified) clang/lib/Sema/SemaDecl.cpp (+8-2)
  • (modified) clang/lib/Sema/SemaType.cpp (+8-1)
  • (added) clang/test/Modules/GH155028-1.cpp (+17)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a47c5ab3aaff7..73f92f7ec9a1e 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18544,8 +18544,14 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
   if (PrevDecl)
     CheckRedeclarationInModule(New, PrevDecl);
 
-  if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip))
-    New->startDefinition();
+  if (TUK == TagUseKind::Definition) {
+    if (!SkipBody || !SkipBody->ShouldSkip) {
+      New->startDefinition();
+    } else {
+      New->setCompleteDefinition();
+      New->demoteThisDefinitionToDeclaration();
+    }
+  }
 
   ProcessDeclAttributeList(S, New, Attrs);
   AddPragmaAttributes(S, New);
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 3f31a05d382a6..0f655d7f684a5 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -9878,7 +9878,14 @@ static QualType GetEnumUnderlyingType(Sema &S, QualType BaseType,
   S.DiagnoseUseOfDecl(ED, Loc);
 
   QualType Underlying = ED->getIntegerType();
-  assert(!Underlying.isNull());
+  if (Underlying.isNull()) {
+    // This is an enum without a fixed underlying type which we skipped parsing
+    // the body because we saw its definition previously in another module.
+    // Use the definition's integer type in that case.
+    assert(ED->isThisDeclarationADemotedDefinition());
+    Underlying = ED->getDefinition()->getIntegerType();
+    assert(!Underlying.isNull());
+  }
 
   return Underlying;
 }
diff --git a/clang/test/Modules/GH155028-1.cpp b/clang/test/Modules/GH155028-1.cpp
new file mode 100644
index 0000000000000..d60112b48c218
--- /dev/null
+++ b/clang/test/Modules/GH155028-1.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+#pragma clang module build M
+module "M" {
+  module "A" {}
+  module "B" {}
+}
+#pragma clang module contents
+#pragma clang module begin M.A
+enum E1 {};
+#pragma clang module end
+#pragma clang module begin M.B
+enum E1 {};
+using T = __underlying_type(E1);
+#pragma clang module end
+#pragma clang module endbuild

Copy link
Collaborator

@rnk rnk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I confirmed the provided test fails before this PR.

New->startDefinition();
} else {
New->setCompleteDefinition();
New->demoteThisDefinitionToDeclaration();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we ever come here for non-enum tag types? I looked up the ShouldSkipInfo class, but I wasn't able to figure out exactly when or why we skip tag bodies.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The case we were hitting on this regression was from a recent improvement implemented here: 2db239a

But this skipping of parsing of bodies is built upon much older patch: d9ba224

But yes, we should come here for other tag kinds as well, based on the tests added in the first commit.

@mizvekov mizvekov merged commit 3da4729 into main Aug 28, 2025
13 checks passed
@mizvekov mizvekov deleted the users/mizvekov/GH155028-regression-1 branch August 28, 2025 18:40
@jyknight
Copy link
Member

Hi -- sidenote, but I noticed that this commit -- and many other of your commits -- are missing the entire commit message other than the PR title. I don't know if that's a github preference or something you're doing manually, but it's really unfortunate because then I cannot see the explanations in git log -- instead needing to indirect through the PR page.

Do you know why that's happening for your changes?

@mizvekov
Copy link
Contributor Author

Hi -- sidenote, but I noticed that this commit -- and many other of your commits -- are missing the entire commit message other than the PR title. I don't know if that's a github preference or something you're doing manually, but it's really unfortunate because then I cannot see the explanations in git log -- instead needing to indirect through the PR page.

Do you know why that's happening for your changes?

Oh yeah, I have seen that before, it seems like when I click merge through the GitHub iOS App, that happens.

I assumed that was spurious and completely forgot about it.

@shafik
Copy link
Collaborator

shafik commented Aug 29, 2025

Hi -- sidenote, but I noticed that this commit -- and many other of your commits -- are missing the entire commit message other than the PR title. I don't know if that's a github preference or something you're doing manually, but it's really unfortunate because then I cannot see the explanations in git log -- instead needing to indirect through the PR page.
Do you know why that's happening for your changes?

Oh yeah, I have seen that before, it seems like when I click merge through the GitHub iOS App, that happens.

I assumed that was spurious and completely forgot about it.

That is a really awful bug, please don't merge using this method unless we know it is fixed. It is really important to have summaries in the logs. I would file a bug report since this has happened to you a lot. Github should not have bugs this bad.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants