Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang][Sema] Skip checking anonymous enum in using enum declaration #87144

Merged
merged 1 commit into from
Apr 5, 2024

Conversation

jcsxky
Copy link
Contributor

@jcsxky jcsxky commented Mar 30, 2024

Try to fix #86790
getFETokenInfo requires DeclarationName shouldn't be empty and this will produce crash when checking name conflict of an anonymous NamedDecl in Sema::PushOnScopeChains and whether it's a reserved identifier or not. These wouldn't happen when it's a anonymous enum and we can skip the checking and just add the declaration to current scope.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 30, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 30, 2024

@llvm/pr-subscribers-clang

Author: Qizhi Hu (jcsxky)

Changes

Try to fix #86790
Skip checking anonymous enumeration in using enum declaration.


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

3 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (+1)
  • (modified) clang/lib/Sema/SemaDecl.cpp (+4)
  • (added) clang/test/SemaCXX/PR86790.cpp (+9)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 232de0d7d8bb73..39f896652d03d5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -459,6 +459,7 @@ Bug Fixes to C++ Support
   following the first `::` were ignored).
 - Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757).
 - Fix an issue caused by not handling invalid cases when substituting into the parameter mapping of a constraint. Fixes (#GH86757).
+- Fix a crash when the using enum declaration uses an anonymous enumeration. Fixes (#GH86790).
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0bd88ece2aa544..dda0b08d93bc75 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1537,6 +1537,10 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
       cast<FunctionDecl>(D)->isFunctionTemplateSpecialization())
     return;
 
+  if (isa<EnumDecl>(D) && D->getDeclName().isEmpty()) {
+    S->AddDecl(D);
+    return;
+  }
   // If this replaces anything in the current scope,
   IdentifierResolver::iterator I = IdResolver.begin(D->getDeclName()),
                                IEnd = IdResolver.end();
diff --git a/clang/test/SemaCXX/PR86790.cpp b/clang/test/SemaCXX/PR86790.cpp
new file mode 100644
index 00000000000000..65403baea32c01
--- /dev/null
+++ b/clang/test/SemaCXX/PR86790.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s
+// expected-no-diagnostics
+
+enum {A, S, D, F};
+int main() {
+    using asdf = decltype(A);
+    using enum asdf; // this line causes the crash
+    return 0;
+}
\ No newline at end of file

@jcsxky jcsxky force-pushed the skip-check-annoymous-enum-in-using-enum branch 3 times, most recently from 92da0db to 8a0d7c3 Compare March 30, 2024 07:22
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

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

Thank you! LGTM aside from expanding the testing a bit.

Comment on lines +4 to +8
enum {A, S, D, F};
int main() {
using asdf = decltype(A);
using enum asdf; // this line causes the crash
return 0;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd like to see an additional test case demonstrating that we correctly added the enumerators to the correct scope:

enum {A, S, D, F};
constexpr struct T {
  using asdf = decltype(A);
  using enum asdf;
} t;

static_assert(t.D == D);
static_assert(T::S == S);

and

enum {A, S, D, F};
constexpr struct T {
  struct {
    using asdf = decltype(A);
    using enum asdf;
  } inner;
} t;

static_assert(t.inner.D == D);
static_assert(t.D == D); // expected-error

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for your review and testcase. This makes the fix complete. Code has been updated with the new added testcase.

Copy link
Collaborator

@shafik shafik left a comment

Choose a reason for hiding this comment

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

LGTM after addressing Aaron's comments.

Can you elaborate more on the details of the bug in the summary. This goes into the git log and we want folks to be able to understand the problem well from the summary w/o having to do additional checks.

Thank you

@jcsxky
Copy link
Contributor Author

jcsxky commented Apr 4, 2024

LGTM after addressing Aaron's comments.

Can you elaborate more on the details of the bug in the summary. This goes into the git log and we want folks to be able to understand the problem well from the summary w/o having to do additional checks.

Thank you

Added.

@jcsxky jcsxky force-pushed the skip-check-annoymous-enum-in-using-enum branch 2 times, most recently from bc3f708 to d06abba Compare April 4, 2024 12:12
@jcsxky jcsxky force-pushed the skip-check-annoymous-enum-in-using-enum branch from d06abba to c4adc66 Compare April 5, 2024 00:38
@jcsxky jcsxky merged commit cfb86ae into llvm:main Apr 5, 2024
4 of 5 checks passed
@@ -1537,6 +1537,10 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext) {
cast<FunctionDecl>(D)->isFunctionTemplateSpecialization())
return;

if (isa<UsingEnumDecl>(D) && D->getDeclName().isEmpty()) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we push a UsingEnumDecl into the scope at all? Would it make sense for the caller to just add the declaration to the DeclContext instead of calling PushOnScopeChains?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sema::ActOnUsingEnumDeclaration invoke PushOnScopeChains when D is a UsingEnumDecl (anonymous or not) and do some extra works. Just add the declaration would skip checking even it's not anonymous.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Are those useful checks? It seems surprising to me that we'd push a using enum declaration into scope given that it never introduces any name of its own (the enumerators are handled separately). Are we really performing checks here that we need for a named enum but that are wrong pr unnecessary for an anonymous enum?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These checks include name conflict and reserved identifier or not. From this perspective I think it's required here. It will take some time to attempt to skip calling PushOnScopeChains and run unittest to find failed cases.

Copy link
Collaborator

Choose a reason for hiding this comment

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

For what name? The using enum declaration doesn't introduce the name of the enum.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The reserved identifier check appears to be incorrect. For example, for:

enum __A {
    x, y
};
void f() {
    using enum __A;
    enum __A e;
}

Clang produces two warnings: one on the declaration of enum __A and one on the using enum __A. The second warning is a bug -- the -Wreserved-identifier warning is only supposed to fire on the declaration of a reserved name, and using enum __A does not declare the name __A, it only references it. (Note that there's no warning on the use of enum __A on the next line, which again is only a reference, not a declaration.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, I see. I skip those checking when D is using enum(UsingEnumDecl) by adding

if (isa<UsingEnumDecl>(D))
    return;

at

and it makes sense after runing unit test on check-clang locally. Then I think you are right.

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 Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

using enum declaration with anonymous enum crashes clang frontend
5 participants