[clang] Support Serializing/Deserializing Extended Generic Selection Expressions (PR #187796)
Will Hawkins via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 27 01:08:19 PDT 2026
https://github.com/hawkinsw updated https://github.com/llvm/llvm-project/pull/187796
>From 6ca6ec6cbc5e9032fc4fbe3836abdf4f5ce97853 Mon Sep 17 00:00:00 2001
From: Will Hawkins <hawkinsw at obs.cr>
Date: Fri, 20 Mar 2026 17:18:12 -0400
Subject: [PATCH] Support Serializing/Deserializing Extended Generic Selection
Expressions
Clang supports using a type as the predicate for generic selection
expressions but lacked support for serializing/deserializing these
extended generic selection expressions.
Signed-off-by: Will Hawkins <hawkinsw at obs.cr>
---
clang/lib/Serialization/ASTReaderStmt.cpp | 11 ++++++-----
clang/lib/Serialization/ASTWriterStmt.cpp | 18 +++++++++++++-----
.../Inputs/generic-type.c | 4 ++++
.../generic-selection-expr/test-type.c | 3 +++
4 files changed, 26 insertions(+), 10 deletions(-)
create mode 100644 clang/test/ASTMerge/generic-selection-expr/Inputs/generic-type.c
create mode 100644 clang/test/ASTMerge/generic-selection-expr/test-type.c
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index f351e185e5b58..b11b84e86464c 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -1458,15 +1458,16 @@ void ASTStmtReader::VisitGenericSelectionExpr(GenericSelectionExpr *E) {
E->DefaultLoc = readSourceLocation();
E->RParenLoc = readSourceLocation();
+ // During serialization, either one more Stmt or one more
+ // TypeSourceInfo was encoded to account for the predicate
+ // (whether it was an expression or a type).
Stmt **Stmts = E->getTrailingObjects<Stmt *>();
- // Add 1 to account for the controlling expression which is the first
- // expression in the trailing array of Stmt *. This is not needed for
- // the trailing array of TypeSourceInfo *.
- for (unsigned I = 0, N = NumAssocs + 1; I < N; ++I)
+ for (unsigned I = 0, N = NumAssocs + (E->IsExprPredicate ? 1 : 0); I < N; ++I)
Stmts[I] = Record.readSubExpr();
TypeSourceInfo **TSIs = E->getTrailingObjects<TypeSourceInfo *>();
- for (unsigned I = 0, N = NumAssocs; I < N; ++I)
+ for (unsigned I = 0, N = NumAssocs + (!E->IsExprPredicate ? 1 : 0); I < N;
+ ++I)
TSIs[I] = readTypeSourceInfo();
}
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index d9b95e53f2da0..e7a9b3f62ca11 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -18,6 +18,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeBase.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/ASTRecordWriter.h"
#include "llvm/Bitstream/BitstreamWriter.h"
@@ -1418,15 +1419,22 @@ void ASTStmtWriter::VisitGenericSelectionExpr(GenericSelectionExpr *E) {
Record.AddSourceLocation(E->getDefaultLoc());
Record.AddSourceLocation(E->getRParenLoc());
+ // Either the trailing Stmt-s or the trailing TypeSourceInfo-s
+ // will hold one more item than the number of associations
+ // to account for the predicate (whether it is an expression
+ // or a type).
Stmt **Stmts = E->getTrailingObjects<Stmt *>();
- // Add 1 to account for the controlling expression which is the first
- // expression in the trailing array of Stmt *. This is not needed for
- // the trailing array of TypeSourceInfo *.
- for (unsigned I = 0, N = E->getNumAssocs() + 1; I < N; ++I)
+ for (unsigned I = 0, N = E->numTrailingObjects(
+ ASTConstraintSatisfaction::OverloadToken<Stmt *>());
+ I < N; ++I)
Record.AddStmt(Stmts[I]);
TypeSourceInfo **TSIs = E->getTrailingObjects<TypeSourceInfo *>();
- for (unsigned I = 0, N = E->getNumAssocs(); I < N; ++I)
+ for (unsigned
+ I = 0,
+ N = E->numTrailingObjects(
+ ASTConstraintSatisfaction::OverloadToken<TypeSourceInfo *>());
+ I < N; ++I)
Record.AddTypeSourceInfo(TSIs[I]);
Code = serialization::EXPR_GENERIC_SELECTION;
diff --git a/clang/test/ASTMerge/generic-selection-expr/Inputs/generic-type.c b/clang/test/ASTMerge/generic-selection-expr/Inputs/generic-type.c
new file mode 100644
index 0000000000000..d802b4398c760
--- /dev/null
+++ b/clang/test/ASTMerge/generic-selection-expr/Inputs/generic-type.c
@@ -0,0 +1,4 @@
+void f(void) {
+ _Static_assert(_Generic(int, float : 0, int : 1), "Incorrect semantics of _Generic");
+ _Static_assert(_Generic(float, float : 1, int : 0), "Incorrect semantics of _Generic");
+}
diff --git a/clang/test/ASTMerge/generic-selection-expr/test-type.c b/clang/test/ASTMerge/generic-selection-expr/test-type.c
new file mode 100644
index 0000000000000..e51ec198afa6a
--- /dev/null
+++ b/clang/test/ASTMerge/generic-selection-expr/test-type.c
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -std=c11 -emit-pch -o %t.ast %S/Inputs/generic-type.c
+// RUN: %clang_cc1 -std=c11 -ast-merge %t.ast -fsyntax-only -verify %s
+// expected-no-diagnostics
More information about the cfe-commits
mailing list