Skip to content

Commit edf14ed

Browse files
authored
[Clang] Don't form a type constraint if the concept is invalid (#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 #115004 Fixes #121980
1 parent bfa711a commit edf14ed

File tree

4 files changed

+20
-3
lines changed

4 files changed

+20
-3
lines changed

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4557,6 +4557,9 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
45574557
const TemplateArgumentListInfo *TemplateArgs) {
45584558
assert(NamedConcept && "A concept template id without a template?");
45594559

4560+
if (NamedConcept->isInvalidDecl())
4561+
return ExprError();
4562+
45604563
llvm::SmallVector<TemplateArgument, 4> SugaredConverted, CanonicalConverted;
45614564
if (CheckTemplateArgumentList(
45624565
NamedConcept, ConceptNameInfo.getLoc(),

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2663,7 +2663,8 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
26632663

26642664
D->setDeclaredWithTypename(Record.readInt());
26652665

2666-
if (D->hasTypeConstraint()) {
2666+
bool TypeConstraintInitialized = D->hasTypeConstraint() && Record.readBool();
2667+
if (TypeConstraintInitialized) {
26672668
ConceptReference *CR = nullptr;
26682669
if (Record.readBool())
26692670
CR = Record.readConceptReference();

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,7 +1951,8 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
19511951
Record.push_back(D->wasDeclaredWithTypename());
19521952

19531953
const TypeConstraint *TC = D->getTypeConstraint();
1954-
assert((bool)TC == D->hasTypeConstraint());
1954+
if (D->hasTypeConstraint())
1955+
Record.push_back(/*TypeConstraintInitialized=*/TC != nullptr);
19551956
if (TC) {
19561957
auto *CR = TC->getConceptReference();
19571958
Record.push_back(CR != nullptr);
@@ -1969,7 +1970,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
19691970
if (OwnsDefaultArg)
19701971
Record.AddTemplateArgumentLoc(D->getDefaultArgument());
19711972

1972-
if (!TC && !OwnsDefaultArg &&
1973+
if (!D->hasTypeConstraint() && !OwnsDefaultArg &&
19731974
D->getDeclContext() == D->getLexicalDeclContext() &&
19741975
!D->isInvalidDecl() && !D->hasAttrs() &&
19751976
!D->isTopLevelDeclInObjCContainer() && !D->isImplicit() &&

clang/test/SemaTemplate/concepts.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,3 +1165,15 @@ concept C = invalid; // expected-error {{use of undeclared identifier 'invalid'}
11651165
bool val2 = C<int>;
11661166

11671167
} // namespace GH109780
1168+
1169+
namespace GH121980 {
1170+
1171+
template <class>
1172+
concept has_member_difference_type; // expected-error {{expected '='}}
1173+
1174+
template <has_member_difference_type> struct incrementable_traits; // expected-note {{declared here}}
1175+
1176+
template <has_member_difference_type Tp>
1177+
struct incrementable_traits<Tp>; // expected-error {{not more specialized than the primary}}
1178+
1179+
}

0 commit comments

Comments
 (0)