Skip to content

Conversation

mizvekov
Copy link
Contributor

@mizvekov mizvekov commented Aug 29, 2025

Fix an error in the logic meant to handle a redeclaration such as:

struct A {
  struct __attribute__((foo)) A *ptr;
};

In the declaration of ptr, we must introduce a new redeclaration of A in order for it to carry the new attribute. This is a redeclaration of the existing A, but it is only lexically contained in A, still semantically belonging to the TU. This is the same deal as happens with friend declarations, and the logic used to handle that is reused here.

But this was going haywire with a class indirectly nested within a class of the same name.

The fix limits this logic to only apply when the tag use is just a simple reference.

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

Fixes #155936

…context

Fix an error in the logic meant to handle a redeclaration such as:
```C++
struct A {
  struct __attribute__((foo)) A *ptr;
};
```
In the declaration of ptr, we must introduce a new redeclaration of A
in order for it to carry the new attribute. This is a redeclaration of
the existing A, but it is only lexically contained in A, but still
semantically belonging to the TU. This is the same deal as happens with
friend declarations, and the logic used to handle that is reused here.

But this was going haywire with a class indirectly nested within a class
of the same name.

The fix limits this logic to only apply when the tag use is just a simple
reference.

Fixes #155936
@mizvekov mizvekov self-assigned this Aug 29, 2025
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Aug 29, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 29, 2025

@llvm/pr-subscribers-clang

Author: Matheus Izvekov (mizvekov)

Changes

…context

Fix an error in the logic meant to handle a redeclaration such as:

struct A {
  struct __attribute__((foo)) A *ptr;
};

In the declaration of ptr, we must introduce a new redeclaration of A in order for it to carry the new attribute. This is a redeclaration of the existing A, but it is only lexically contained in A, but still semantically belonging to the TU. This is the same deal as happens with friend declarations, and the logic used to handle that is reused here.

But this was going haywire with a class indirectly nested within a class of the same name.

The fix limits this logic to only apply when the tag use is just a simple reference.

Fixes #155936


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

2 Files Affected:

  • (modified) clang/lib/Sema/SemaDecl.cpp (+2-1)
  • (modified) clang/test/AST/ast-dump-decl.cpp (+15)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 0afef106821d9..12bedae05f6f3 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -18050,7 +18050,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
           }
         }
       } else if (auto *RD = dyn_cast<CXXRecordDecl>(PrevDecl);
-                 RD && RD->isInjectedClassName()) {
+                 TUK == TagUseKind::Reference && RD &&
+                 RD->isInjectedClassName()) {
         // If lookup found the injected class name, the previous declaration is
         // the class being injected into.
         PrevDecl = cast<TagDecl>(RD->getDeclContext());
diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp
index 849bfbee2ab21..afb507833d869 100644
--- a/clang/test/AST/ast-dump-decl.cpp
+++ b/clang/test/AST/ast-dump-decl.cpp
@@ -990,3 +990,18 @@ namespace TestInjectedClassName {
   // CHECK-NEXT:    `-RecordType [[TestInjectedClassName_RT]] 'A' injected
   // CHECK-NEXT:      `-CXXRecord [[TestInjectedClassName_RD]] 'A'
 } // namespace InjectedClassName
+
+namespace TestGH155936 {
+  struct Foo {
+    struct A {
+      struct Foo {};
+    };
+  };
+  // CHECK-LABEL: Dumping TestGH155936:
+  // CHECK: CXXRecordDecl 0x{{.+}} <{{.+}}> line:[[@LINE-6]]:10 struct Foo definition
+  // CHECK: CXXRecordDecl 0x{{.+}} <col:3, col:10> col:10 implicit struct Foo
+  // CHECK: CXXRecordDecl 0x{{.+}} <{{.+}}> line:[[@LINE-7]]:12 struct A definition
+  // CHECK: CXXRecordDecl 0x{{.+}} <col:5, col:12> col:12 implicit struct A
+  // CHECK: CXXRecordDecl 0x{{.+}} <line:[[@LINE-8]]:7, col:19> col:14 struct Foo definition
+  // CHECH: CXXRecordDecl 0x{{.+}} <col:9, col:16> col:16 implicit struct Foo
+} // namspace GH155936

@mizvekov mizvekov changed the title [clang] fix nested tags of the same name not being included in their … [clang] fix nested tags of the same name not being included in their context Aug 29, 2025
@mizvekov mizvekov enabled auto-merge (squash) August 29, 2025 03:27
@mizvekov mizvekov disabled auto-merge August 29, 2025 03:28
@mizvekov mizvekov enabled auto-merge (squash) August 29, 2025 03:28
@mizvekov mizvekov merged commit ac23f74 into main Aug 29, 2025
12 checks passed
@mizvekov mizvekov deleted the users/mizvekov/GH155936 branch August 29, 2025 03:33
@llvm-ci
Copy link
Collaborator

llvm-ci commented Aug 29, 2025

LLVM Buildbot has detected a new failure on builder clang-aarch64-quick running on linaro-clang-aarch64-quick while building clang at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/65/builds/21926

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'Clangd Unit Tests :: ./ClangdTests/60/332' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/tools/extra/clangd/unittests/./ClangdTests-Clangd Unit Tests-571640-60-332.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=332 GTEST_SHARD_INDEX=60 /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/tools/extra/clangd/unittests/./ClangdTests
--

Script:
--
/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/tools/clang/tools/extra/clangd/unittests/./ClangdTests --gtest_filter=ClangdServerTest.TestStackOverflow
--
ASTWorker building file /clangd-test/foo.cpp version null with command 
[/clangd-test]
clang -ffreestanding /clangd-test/foo.cpp
Driver produced command: cc1 -cc1 -triple aarch64-unknown-linux-gnu -fsyntax-only -disable-free -clear-ast-before-backend -main-file-name foo.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -enable-tlsdesc -target-cpu generic -target-feature +v8a -target-feature +fp-armv8 -target-feature +neon -target-abi aapcs -debugger-tuning=gdb -fdebug-compilation-dir=/clangd-test -fcoverage-compilation-dir=/clangd-test -resource-dir lib/clang/22 -internal-isystem lib/clang/22/include -internal-isystem /usr/local/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -no-round-trip-args -target-feature -fmv -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -x c++ /clangd-test/foo.cpp
Building first preamble for /clangd-test/foo.cpp version null
../llvm/clang-tools-extra/clangd/unittests/ClangdTests.cpp:1198: Failure
Value of: Server.blockUntilIdleForTest()
  Actual: false
Expected: true
Waiting for diagnostics

Built preamble of size 736740 for file /clangd-test/foo.cpp version null in 15.51 seconds

../llvm/clang-tools-extra/clangd/unittests/ClangdTests.cpp:1198
Value of: Server.blockUntilIdleForTest()
  Actual: false
Expected: true
Waiting for diagnostics



********************


@zwuis zwuis added the skip-precommit-approval PR for CI feedback, not intended for review label Aug 29, 2025
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 skip-precommit-approval PR for CI feedback, not intended for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang][ast] Inner struct with same name missing from AST layout
4 participants