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] Don't form a type constraint if the concept is invalid #122065

Merged
merged 3 commits into from
Jan 8, 2025

Conversation

zyn0217
Copy link
Contributor

@zyn0217 zyn0217 commented Jan 8, 2025

After 0dedd6f and 03229e7, invalid concept declarations might lack expressions for evaluation and normalization. This could make it crash in certain scenarios, apart from the one of evaluation concepts showed in 03229e7, there's also an issue when checking specializations where the normalization also relies on a non-null expression.

This patch prevents that by avoiding building up a type constraint in such situations, thereafter the template parameter wouldn't have a concept specialization of a null expression.

With this patch, the assumption in ASTWriterDecl is no longer valid. Namely, HasConstraint and TypeConstraintInitialized must now represent different meanings for both source fidelity and semantic requirements.

Fixes #115004
Fixes #121980

After 0dedd6f and 03229e7, invalid concept declarations might
lack expressions for evaluation and normalization. This could make
it crash in certain scenarios, apart from the one of evaluation
concepts showed in 03229e7, there's also an issue when checking
specializations where the normalization also relies on a non-null expression.

This patch prevents that by avoiding building up a type constraint
in such situations, thereafter the template parameter wouldn't
have a concept specialization of a null expression.

With this patch, the assumption in ASTWriterDecl is no longer valid.
Namely, HasConstraint and TypeConstraintInitialized must now represent
different meanings for both source fidelity and semantic requirements.
@zyn0217 zyn0217 requested a review from cor3ntin January 8, 2025 07:57
@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 Jan 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 8, 2025

@llvm/pr-subscribers-clang-modules

@llvm/pr-subscribers-clang

Author: Younan Zhang (zyn0217)

Changes

After 0dedd6f and 03229e7, invalid concept declarations might lack expressions for evaluation and normalization. This could make it crash in certain scenarios, apart from the one of evaluation concepts showed in 03229e7, there's also an issue when checking specializations where the normalization also relies on a non-null expression.

This patch prevents that by avoiding building up a type constraint in such situations, thereafter the template parameter wouldn't have a concept specialization of a null expression.

With this patch, the assumption in ASTWriterDecl is no longer valid. Namely, HasConstraint and TypeConstraintInitialized must now represent different meanings for both source fidelity and semantic requirements.

Fixes #115004
Fixes #121980


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

3 Files Affected:

  • (modified) clang/lib/Sema/SemaTemplate.cpp (+3)
  • (modified) clang/lib/Serialization/ASTWriterDecl.cpp (-1)
  • (modified) clang/test/SemaTemplate/concepts.cpp (+12)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 20ec2fbeaa6a8b..ce672b00893b0d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -4557,6 +4557,9 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
                              const TemplateArgumentListInfo *TemplateArgs) {
   assert(NamedConcept && "A concept template id without a template?");
 
+  if (NamedConcept->isInvalidDecl())
+    return ExprError();
+
   llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
   if (CheckTemplateArgumentList(
           NamedConcept, ConceptNameInfo.getLoc(),
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 75c1d9a6d438ce..c7b8759916f421 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1951,7 +1951,6 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
   Record.push_back(D->wasDeclaredWithTypename());
 
   const TypeConstraint *TC = D->getTypeConstraint();
-  assert((bool)TC == D->hasTypeConstraint());
   if (TC) {
     auto *CR = TC->getConceptReference();
     Record.push_back(CR != nullptr);
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 312469313fc535..f335ca3bd22bc3 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1165,3 +1165,15 @@ concept C = invalid; // expected-error {{use of undeclared identifier 'invalid'}
 bool val2 = C<int>;
 
 } // namespace GH109780
+
+namespace GH121980 {
+
+template <class>
+concept has_member_difference_type; // expected-error {{expected '='}}
+
+template <has_member_difference_type> struct incrementable_traits; // expected-note {{declared here}}
+
+template <has_member_difference_type Tp>
+struct incrementable_traits<Tp>; // expected-error {{not more specialized than the primary}}
+
+}

@zyn0217 zyn0217 merged commit edf14ed into llvm:main Jan 8, 2025
8 checks passed
@zyn0217 zyn0217 deleted the GH121980 branch January 8, 2025 11:40
shenhanc78 pushed a commit to shenhanc78/llvm-project that referenced this pull request Jan 8, 2025
…122065)

After 0dedd6f and 03229e7, invalid concept declarations might lack
expressions for evaluation and normalization. This could make it crash
in certain scenarios, apart from the one of evaluation concepts showed
in 03229e7, there's also an issue when checking specializations where
the normalization also relies on a non-null expression.

This patch prevents that by avoiding building up a type constraint in
such situations, thereafter the template parameter wouldn't have a
concept specialization of a null expression.

With this patch, the assumption in ASTWriterDecl is no longer valid.
Namely, HasConstraint and TypeConstraintInitialized must now represent
different meanings for both source fidelity and semantic requirements.

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

After commit review.

Thank you for the fix.

@@ -1969,7 +1970,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
if (OwnsDefaultArg)
Record.AddTemplateArgumentLoc(D->getDefaultArgument());

if (!TC && !OwnsDefaultArg &&
if (!D->hasTypeConstraint() && !OwnsDefaultArg &&
Copy link
Collaborator

Choose a reason for hiding this comment

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

The logic here is a little tricky. The new condition is really "it has a constraint and it does not matter if it is initialized".

I feel like this deserves a comment.

It also makes me wonder if "initialized" is the right word here, isn't it really that it was invalid?

I am just thinking of folks coming to maintain this code in the future and understanding the intent and I don't think the intent is 💯 clear as written.

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
4 participants