Skip to content

Conversation

@zyn0217
Copy link
Contributor

@zyn0217 zyn0217 commented Oct 28, 2025

The NormalizationCache may be inserted recursively when normalizing template arguments with non-dependent default arguments. Since the ADT doesn't preserve iterator validity, this caused undefined behavior.

This is a regression on trunk so there is no release note.

Fixes #165238

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Oct 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 28, 2025

@llvm/pr-subscribers-clang

Author: Younan Zhang (zyn0217)

Changes

The NormalizationCache may be inserted recursively when normalizing template arguments with non-dependent default arguments. Since the ADT doesn't preserve iterator validity, this caused undefined behavior.

We convert it to std::map where the insert operation doesn't invalidate iterators, than calling find() twice for performance concerns.

This is a regression on trunk so there is no release note.

Fixes #165238


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

2 Files Affected:

  • (modified) clang/include/clang/Sema/Sema.h (+1-1)
  • (modified) clang/test/SemaTemplate/concepts.cpp (+26)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 52904c72d1cfc..031d1811c5c27 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -14941,7 +14941,7 @@ class Sema final : public SemaBase {
   /// constrained declarations). If an error occurred while normalizing the
   /// associated constraints of the template or concept, nullptr will be cached
   /// here.
-  llvm::DenseMap<ConstrainedDeclOrNestedRequirement, NormalizedConstraint *>
+  std::map<ConstrainedDeclOrNestedRequirement, NormalizedConstraint *>
       NormalizationCache;
 
   /// Cache whether the associated constraint of a declaration
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index becf5467a1b61..c90af41a09468 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1632,3 +1632,29 @@ void fn3() {
 }
 
 }
+
+namespace GH165238 {
+
+namespace std {
+template <typename, typename _Tp>
+concept output_iterator = requires(_Tp __t) { __t; };
+template <typename _Out> struct basic_format_context {
+  static_assert(output_iterator<_Out, int>);
+  using char_type = _Out;
+};
+template <typename> class basic_format_parse_context;
+template <typename, typename _Context, typename _Formatter,
+          typename = basic_format_parse_context<typename _Context::char_type>>
+concept __parsable_with = requires(_Formatter __f) { __f; };
+template <typename _Tp, typename _CharT,
+          typename _Context = basic_format_context<_CharT>>
+concept __formattable_impl = __parsable_with<_Tp, _Context, _Context>;
+template <typename _Tp, typename _CharT>
+concept formattable = __formattable_impl<_Tp, _CharT>;
+} // namespace std
+struct {
+  void operator()(std::formattable<char> auto);
+} call;
+void foo() { call(""); }
+
+}

@zyn0217 zyn0217 marked this pull request as draft October 28, 2025 05:18
The NormalizationCache may be inserted recursively when normalizing
template arguments with non-dependent default arguments. Since the ADT
doesn't preserve iterator validity, this caused undefined behavior.
@zyn0217 zyn0217 force-pushed the post-parameter-mapping-8 branch from 1cd7eb4 to 855c54c Compare October 28, 2025 05:47
@zyn0217 zyn0217 marked this pull request as ready for review October 28, 2025 05:48
@zyn0217 zyn0217 merged commit 2984a8d into llvm:main Oct 28, 2025
12 of 14 checks passed
@zyn0217 zyn0217 deleted the post-parameter-mapping-8 branch October 28, 2025 07:15
@zwuis zwuis added the skip-precommit-approval PR for CI feedback, not intended for review label Oct 28, 2025
Lukacma pushed a commit to Lukacma/llvm-project that referenced this pull request Oct 29, 2025
…he (llvm#165352)

The NormalizationCache may be inserted recursively when normalizing
template arguments with non-dependent default arguments. Since the ADT
doesn't preserve iterator validity, this caused undefined behavior.

This is a regression on trunk so there is no release note.

Fixes llvm#165238
aokblast pushed a commit to aokblast/llvm-project that referenced this pull request Oct 30, 2025
…he (llvm#165352)

The NormalizationCache may be inserted recursively when normalizing
template arguments with non-dependent default arguments. Since the ADT
doesn't preserve iterator validity, this caused undefined behavior.

This is a regression on trunk so there is no release note.

Fixes llvm#165238
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.

Next time with a regression, please label the bug report as a regression. Also try to identify the PR that caused the regression and link that PR in your fix.

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] Crash in SemaConcept.cpp / Sema::getNormalizedAssociatedConstraints (invalidated iterator?)

4 participants