Skip to content

Commit 15a3e92

Browse files
author
kakje
committed
[Needs review] Fix clang Syntax unit test: add CHKCBindTemporary syntax node
Checked C binds string literals to temporaries. Add CHKCBindTemporaryExpression as a syntax node and add a separate Checked C case for the StringLiteral syntax test that expects a CHKCBindTemporary parent for StringLiteral expressions.
1 parent a84f170 commit 15a3e92

File tree

4 files changed

+67
-1
lines changed

4 files changed

+67
-1
lines changed

clang/include/clang/Tooling/Syntax/Nodes.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum class NodeKind : uint16_t {
4444
PostfixUnaryOperatorExpression,
4545
BinaryOperatorExpression,
4646
ParenExpression,
47+
CHKCBindTemporaryExpression,
4748
IntegerLiteralExpression,
4849
CharacterLiteralExpression,
4950
FloatingLiteralExpression,
@@ -167,7 +168,8 @@ enum class NodeRole : uint8_t {
167168
IdExpression_id,
168169
IdExpression_qualifier,
169170
NestedNameSpecifier_specifier,
170-
ParenExpression_subExpression
171+
ParenExpression_subExpression,
172+
CHKCBindTemporaryExpression_subExpression
171173
};
172174
/// For debugging purposes.
173175
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, NodeRole R);
@@ -267,6 +269,17 @@ class ParenExpression final : public Expression {
267269
syntax::Leaf *closeParen();
268270
};
269271

272+
/// Models binding the result of evaluating an expression
273+
/// to an anonymous temporary. Checked C-specific.
274+
class CHKCBindTemporaryExpression final : public Expression {
275+
public:
276+
CHKCBindTemporaryExpression() : Expression(NodeKind::CHKCBindTemporaryExpression) {}
277+
static bool classof(const Node *N) {
278+
return N->kind() == NodeKind::CHKCBindTemporaryExpression;
279+
}
280+
syntax::Expression *subExpression();
281+
};
282+
270283
/// Expression for integer literals. C++ [lex.icon]
271284
class IntegerLiteralExpression final : public Expression {
272285
public:

clang/lib/Tooling/Syntax/BuildTree.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,14 @@ class BuildTreeVisitor : public RecursiveASTVisitor<BuildTreeVisitor> {
793793
return true;
794794
}
795795

796+
bool WalkUpFromCHKCBindTemporaryExpr(CHKCBindTemporaryExpr *S) {
797+
Builder.markExprChild(S->getSubExpr(),
798+
syntax::NodeRole::CHKCBindTemporaryExpression_subExpression);
799+
Builder.foldNode(Builder.getExprRange(S),
800+
new (allocator()) syntax::CHKCBindTemporaryExpression, S);
801+
return true;
802+
}
803+
796804
bool WalkUpFromIntegerLiteral(IntegerLiteral *S) {
797805
Builder.markChildToken(S->getLocation(), syntax::NodeRole::LiteralToken);
798806
Builder.foldNode(Builder.getExprRange(S),

clang/lib/Tooling/Syntax/Nodes.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeKind K) {
2020
return OS << "UnknownExpression";
2121
case NodeKind::ParenExpression:
2222
return OS << "ParenExpression";
23+
case NodeKind::CHKCBindTemporaryExpression:
24+
return OS << "CHKCBindTemporaryExpression";
2325
case NodeKind::IntegerLiteralExpression:
2426
return OS << "IntegerLiteralExpression";
2527
case NodeKind::CharacterLiteralExpression:
@@ -192,6 +194,8 @@ llvm::raw_ostream &syntax::operator<<(llvm::raw_ostream &OS, NodeRole R) {
192194
return OS << "NestedNameSpecifier_specifier";
193195
case syntax::NodeRole::ParenExpression_subExpression:
194196
return OS << "ParenExpression_subExpression";
197+
case syntax::NodeRole::CHKCBindTemporaryExpression_subExpression:
198+
return OS << "CHKCBindTemporaryExpression_subExpression";
195199
}
196200
llvm_unreachable("invalid role");
197201
}
@@ -230,6 +234,11 @@ syntax::Leaf *syntax::ParenExpression::closeParen() {
230234
findChild(syntax::NodeRole::CloseParen));
231235
}
232236

237+
syntax::Expression *syntax::CHKCBindTemporaryExpression::subExpression() {
238+
return llvm::cast_or_null<syntax::Expression>(
239+
findChild(syntax::NodeRole::CHKCBindTemporaryExpression_subExpression));
240+
}
241+
233242
syntax::Leaf *syntax::IntegerLiteralExpression::literalToken() {
234243
return llvm::cast_or_null<syntax::Leaf>(
235244
findChild(syntax::NodeRole::LiteralToken));

clang/unittests/Tooling/Syntax/TreeTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,6 +1669,42 @@ void test() {
16691669
}
16701670

16711671
TEST_P(SyntaxTreeTest, StringLiteral) {
1672+
// Checked C wraps each StringLiteral expression in a CHKCBindTemporary
1673+
// expression. When the test language is C, Checked C is enabled by default.
1674+
if (!GetParam().isCXX()) {
1675+
EXPECT_TRUE(treeDumpEqual(
1676+
R"cpp(
1677+
void test() {
1678+
"a\n\0\x20";
1679+
L"αβ";
1680+
}
1681+
)cpp",
1682+
R"txt(
1683+
*: TranslationUnit
1684+
`-SimpleDeclaration
1685+
|-void
1686+
|-SimpleDeclarator
1687+
| |-test
1688+
| `-ParametersAndQualifiers
1689+
| |-(
1690+
| `-)
1691+
`-CompoundStatement
1692+
|-{
1693+
|-ExpressionStatement
1694+
| |-CHKCBindTemporaryExpression
1695+
| | `-StringLiteralExpression
1696+
| | `-"a\n\0\x20"
1697+
| `-;
1698+
|-ExpressionStatement
1699+
| |-CHKCBindTemporaryExpression
1700+
| | `-StringLiteralExpression
1701+
| | `-L"αβ"
1702+
| `-;
1703+
`-}
1704+
)txt"));
1705+
return;
1706+
}
1707+
16721708
EXPECT_TRUE(treeDumpEqual(
16731709
R"cpp(
16741710
void test() {

0 commit comments

Comments
 (0)