Skip to content

[clang] don't create type source info for vardecl created for structured bindings #153923

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

Merged
merged 1 commit into from
Aug 16, 2025

Conversation

mizvekov
Copy link
Contributor

@mizvekov mizvekov commented Aug 16, 2025

These are implicit vardecls which its type was never written in source code. Don't create a TypeLoc and give it a fake source location.

The fake as-written type also didn't match the actual type, which after fixing this gives some unrelated test churn on a CFG dump, since statement printing prefers type source info if thats available.

Fixes #153649

This is a regression introduced in #147835

This regression was never released, so no release notes are added.

@mizvekov mizvekov self-assigned this Aug 16, 2025
@llvmbot llvmbot added clang Clang issues not falling into any other category clang-tools-extra clang-tidy clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:static analyzer labels Aug 16, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 16, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-tools-extra

Author: Matheus Izvekov (mizvekov)

Changes

These are implicit vardecls which its type was never written in source code. Don't create a TypeLoc and give it a fake source location.

The fake as-written type also didn't match the actual type, which after fixing this gives some unrelated test churn on a CFG dump, since statement printing prefers type source info if thats available.

Fixes #153649

This regression was never released, so no release notes are added.


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

3 Files Affected:

  • (added) clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp (+15)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+4-1)
  • (modified) clang/test/Analysis/anonymous-decls.cpp (+2-2)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp
new file mode 100644
index 0000000000000..142eb5847ae10
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-type-traits %t
+
+namespace std {
+template <class> struct tuple_size {
+  static const int value = 1;
+};
+template <int, class> struct tuple_element {
+  using type = int;
+};
+}
+
+struct A {};
+template <int> int get(const A&);
+
+auto [a] = A();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index dd66a5f15a970..2ba4f062b61e9 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1373,10 +1373,13 @@ static bool checkTupleLikeDecomposition(Sema &S,
         S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName());
     if (RefType.isNull())
       return true;
+
+    // Don't give this VarDecl a TypeSourceInfo, since this is a synthesized
+    // entity and this type was never written in source code.
     auto *RefVD = VarDecl::Create(
         S.Context, Src->getDeclContext(), Loc, Loc,
         B->getDeclName().getAsIdentifierInfo(), RefType,
-        S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass());
+        /*TInfo=*/nullptr, Src->getStorageClass());
     RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
     RefVD->setTSCSpec(Src->getTSCSpec());
     RefVD->setImplicit();
diff --git a/clang/test/Analysis/anonymous-decls.cpp b/clang/test/Analysis/anonymous-decls.cpp
index 3f972a33aa621..76e5155b61b67 100644
--- a/clang/test/Analysis/anonymous-decls.cpp
+++ b/clang/test/Analysis/anonymous-decls.cpp
@@ -78,12 +78,12 @@ int main() {
 // CHECK-NEXT:   8: decomposition-a-b
 // CHECK-NEXT:   9: [B3.7]([B3.8])
 // CHECK-NEXT:  10: [B3.9]
-// CHECK-NEXT:  11: std::tuple_element<0UL, std::pair<int, int>>::type a = get<0UL>(decomposition-a-b);
+// CHECK-NEXT:  11: std::tuple_element<0UL, std::pair<int, int>>::type &&a = get<0UL>(decomposition-a-b);
 // CHECK-NEXT:  12: get<1UL>
 // CHECK-NEXT:  13: [B3.12] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
 // CHECK-NEXT:  14: decomposition-a-b
 // CHECK-NEXT:  15: [B3.13]([B3.14])
 // CHECK-NEXT:  16: [B3.15]
-// CHECK-NEXT:  17: std::tuple_element<1UL, std::pair<int, int>>::type b = get<1UL>(decomposition-a-b);
+// CHECK-NEXT:  17: std::tuple_element<1UL, std::pair<int, int>>::type &&b = get<1UL>(decomposition-a-b);
 // CHECK-NEXT:   Preds (1): B1
 // CHECK-NEXT:   Succs (1): B2

@llvmbot
Copy link
Member

llvmbot commented Aug 16, 2025

@llvm/pr-subscribers-clang-tidy

Author: Matheus Izvekov (mizvekov)

Changes

These are implicit vardecls which its type was never written in source code. Don't create a TypeLoc and give it a fake source location.

The fake as-written type also didn't match the actual type, which after fixing this gives some unrelated test churn on a CFG dump, since statement printing prefers type source info if thats available.

Fixes #153649

This regression was never released, so no release notes are added.


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

3 Files Affected:

  • (added) clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp (+15)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+4-1)
  • (modified) clang/test/Analysis/anonymous-decls.cpp (+2-2)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp
new file mode 100644
index 0000000000000..142eb5847ae10
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-type-traits %t
+
+namespace std {
+template <class> struct tuple_size {
+  static const int value = 1;
+};
+template <int, class> struct tuple_element {
+  using type = int;
+};
+}
+
+struct A {};
+template <int> int get(const A&);
+
+auto [a] = A();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index dd66a5f15a970..2ba4f062b61e9 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1373,10 +1373,13 @@ static bool checkTupleLikeDecomposition(Sema &S,
         S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName());
     if (RefType.isNull())
       return true;
+
+    // Don't give this VarDecl a TypeSourceInfo, since this is a synthesized
+    // entity and this type was never written in source code.
     auto *RefVD = VarDecl::Create(
         S.Context, Src->getDeclContext(), Loc, Loc,
         B->getDeclName().getAsIdentifierInfo(), RefType,
-        S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass());
+        /*TInfo=*/nullptr, Src->getStorageClass());
     RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
     RefVD->setTSCSpec(Src->getTSCSpec());
     RefVD->setImplicit();
diff --git a/clang/test/Analysis/anonymous-decls.cpp b/clang/test/Analysis/anonymous-decls.cpp
index 3f972a33aa621..76e5155b61b67 100644
--- a/clang/test/Analysis/anonymous-decls.cpp
+++ b/clang/test/Analysis/anonymous-decls.cpp
@@ -78,12 +78,12 @@ int main() {
 // CHECK-NEXT:   8: decomposition-a-b
 // CHECK-NEXT:   9: [B3.7]([B3.8])
 // CHECK-NEXT:  10: [B3.9]
-// CHECK-NEXT:  11: std::tuple_element<0UL, std::pair<int, int>>::type a = get<0UL>(decomposition-a-b);
+// CHECK-NEXT:  11: std::tuple_element<0UL, std::pair<int, int>>::type &&a = get<0UL>(decomposition-a-b);
 // CHECK-NEXT:  12: get<1UL>
 // CHECK-NEXT:  13: [B3.12] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
 // CHECK-NEXT:  14: decomposition-a-b
 // CHECK-NEXT:  15: [B3.13]([B3.14])
 // CHECK-NEXT:  16: [B3.15]
-// CHECK-NEXT:  17: std::tuple_element<1UL, std::pair<int, int>>::type b = get<1UL>(decomposition-a-b);
+// CHECK-NEXT:  17: std::tuple_element<1UL, std::pair<int, int>>::type &&b = get<1UL>(decomposition-a-b);
 // CHECK-NEXT:   Preds (1): B1
 // CHECK-NEXT:   Succs (1): B2

@llvmbot
Copy link
Member

llvmbot commented Aug 16, 2025

@llvm/pr-subscribers-clang-static-analyzer-1

Author: Matheus Izvekov (mizvekov)

Changes

These are implicit vardecls which its type was never written in source code. Don't create a TypeLoc and give it a fake source location.

The fake as-written type also didn't match the actual type, which after fixing this gives some unrelated test churn on a CFG dump, since statement printing prefers type source info if thats available.

Fixes #153649

This regression was never released, so no release notes are added.


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

3 Files Affected:

  • (added) clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp (+15)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+4-1)
  • (modified) clang/test/Analysis/anonymous-decls.cpp (+2-2)
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp
new file mode 100644
index 0000000000000..142eb5847ae10
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-GH153649.cpp
@@ -0,0 +1,15 @@
+// RUN: %check_clang_tidy -std=c++20 %s modernize-type-traits %t
+
+namespace std {
+template <class> struct tuple_size {
+  static const int value = 1;
+};
+template <int, class> struct tuple_element {
+  using type = int;
+};
+}
+
+struct A {};
+template <int> int get(const A&);
+
+auto [a] = A();
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index dd66a5f15a970..2ba4f062b61e9 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1373,10 +1373,13 @@ static bool checkTupleLikeDecomposition(Sema &S,
         S.BuildReferenceType(T, E.get()->isLValue(), Loc, B->getDeclName());
     if (RefType.isNull())
       return true;
+
+    // Don't give this VarDecl a TypeSourceInfo, since this is a synthesized
+    // entity and this type was never written in source code.
     auto *RefVD = VarDecl::Create(
         S.Context, Src->getDeclContext(), Loc, Loc,
         B->getDeclName().getAsIdentifierInfo(), RefType,
-        S.Context.getTrivialTypeSourceInfo(T, Loc), Src->getStorageClass());
+        /*TInfo=*/nullptr, Src->getStorageClass());
     RefVD->setLexicalDeclContext(Src->getLexicalDeclContext());
     RefVD->setTSCSpec(Src->getTSCSpec());
     RefVD->setImplicit();
diff --git a/clang/test/Analysis/anonymous-decls.cpp b/clang/test/Analysis/anonymous-decls.cpp
index 3f972a33aa621..76e5155b61b67 100644
--- a/clang/test/Analysis/anonymous-decls.cpp
+++ b/clang/test/Analysis/anonymous-decls.cpp
@@ -78,12 +78,12 @@ int main() {
 // CHECK-NEXT:   8: decomposition-a-b
 // CHECK-NEXT:   9: [B3.7]([B3.8])
 // CHECK-NEXT:  10: [B3.9]
-// CHECK-NEXT:  11: std::tuple_element<0UL, std::pair<int, int>>::type a = get<0UL>(decomposition-a-b);
+// CHECK-NEXT:  11: std::tuple_element<0UL, std::pair<int, int>>::type &&a = get<0UL>(decomposition-a-b);
 // CHECK-NEXT:  12: get<1UL>
 // CHECK-NEXT:  13: [B3.12] (ImplicitCastExpr, FunctionToPointerDecay, tuple_element<1L, pair<int, int> >::type (*)(pair<int, int> &))
 // CHECK-NEXT:  14: decomposition-a-b
 // CHECK-NEXT:  15: [B3.13]([B3.14])
 // CHECK-NEXT:  16: [B3.15]
-// CHECK-NEXT:  17: std::tuple_element<1UL, std::pair<int, int>>::type b = get<1UL>(decomposition-a-b);
+// CHECK-NEXT:  17: std::tuple_element<1UL, std::pair<int, int>>::type &&b = get<1UL>(decomposition-a-b);
 // CHECK-NEXT:   Preds (1): B1
 // CHECK-NEXT:   Succs (1): B2

Copy link

github-actions bot commented Aug 16, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

…red bindings

These are implicit vardecls which its type was never written in source code.
Don't create a TypeLoc and give it a fake source location.

The fake as-written type also didn't match the actual type,
which after fixing this gives some unrelated test churn on a
CFG dump, since statement printing prefers type source info if
thats available.

Fixes #153649

This regression was never released, so no release notes are added.
@mizvekov mizvekov force-pushed the users/mizvekov/GH153649 branch from 3c0d0fb to f99052f Compare August 16, 2025 04:18
@mizvekov mizvekov merged commit 1d73b2c into main Aug 16, 2025
9 checks passed
@mizvekov mizvekov deleted the users/mizvekov/GH153649 branch August 16, 2025 05:04
@zwuis zwuis added the skip-precommit-approval PR for CI feedback, not intended for review label Aug 16, 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:static analyzer clang Clang issues not falling into any other category clang-tidy clang-tools-extra 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-tidy] false positive for modernize-type-traits with structured bindings
3 participants