Skip to content

Commit f80aa30

Browse files
authored
fix(parser): Add support for the __is_same_as built-in function
1 parent 5ddecf5 commit f80aa30

29 files changed

+258
-6
lines changed

packages/cxx-frontend/src/AST.ts

+25
Original file line numberDiff line numberDiff line change
@@ -1246,6 +1246,30 @@ export class AlignofExpressionAST extends ExpressionAST {
12461246
}
12471247
}
12481248

1249+
export class IsSameAsExpressionAST extends ExpressionAST {
1250+
accept<Context, Result>(visitor: ASTVisitor<Context, Result>, context: Context): Result {
1251+
return visitor.visitIsSameAsExpression(this, context);
1252+
}
1253+
getIsSameAsToken(): Token | undefined {
1254+
return Token.from(cxx.getASTSlot(this.getHandle(), 0), this.parser);
1255+
}
1256+
getLparenToken(): Token | undefined {
1257+
return Token.from(cxx.getASTSlot(this.getHandle(), 1), this.parser);
1258+
}
1259+
getTypeId(): TypeIdAST | undefined {
1260+
return AST.from<TypeIdAST>(cxx.getASTSlot(this.getHandle(), 2), this.parser);
1261+
}
1262+
getCommaToken(): Token | undefined {
1263+
return Token.from(cxx.getASTSlot(this.getHandle(), 3), this.parser);
1264+
}
1265+
getOtherTypeId(): TypeIdAST | undefined {
1266+
return AST.from<TypeIdAST>(cxx.getASTSlot(this.getHandle(), 4), this.parser);
1267+
}
1268+
getRparenToken(): Token | undefined {
1269+
return Token.from(cxx.getASTSlot(this.getHandle(), 5), this.parser);
1270+
}
1271+
}
1272+
12491273
export class UnaryExpressionAST extends ExpressionAST {
12501274
accept<Context, Result>(visitor: ASTVisitor<Context, Result>, context: Context): Result {
12511275
return visitor.visitUnaryExpression(this, context);
@@ -3119,6 +3143,7 @@ const AST_CONSTRUCTORS: Array<new (handle: number, kind: ASTKind, parser: Parser
31193143
TypeidExpressionAST,
31203144
TypeidOfTypeExpressionAST,
31213145
AlignofExpressionAST,
3146+
IsSameAsExpressionAST,
31223147
UnaryExpressionAST,
31233148
BinaryExpressionAST,
31243149
AssignmentExpressionAST,

packages/cxx-frontend/src/ASTKind.ts

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ export enum ASTKind {
115115
TypeidExpression,
116116
TypeidOfTypeExpression,
117117
AlignofExpression,
118+
IsSameAsExpression,
118119
UnaryExpression,
119120
BinaryExpression,
120121
AssignmentExpression,

packages/cxx-frontend/src/ASTVisitor.ts

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ export abstract class ASTVisitor<Context, Result> {
119119
abstract visitTypeidExpression(node: ast.TypeidExpressionAST, context: Context): Result;
120120
abstract visitTypeidOfTypeExpression(node: ast.TypeidOfTypeExpressionAST, context: Context): Result;
121121
abstract visitAlignofExpression(node: ast.AlignofExpressionAST, context: Context): Result;
122+
abstract visitIsSameAsExpression(node: ast.IsSameAsExpressionAST, context: Context): Result;
122123
abstract visitUnaryExpression(node: ast.UnaryExpressionAST, context: Context): Result;
123124
abstract visitBinaryExpression(node: ast.BinaryExpressionAST, context: Context): Result;
124125
abstract visitAssignmentExpression(node: ast.AssignmentExpressionAST, context: Context): Result;

packages/cxx-frontend/src/RecursiveASTVisitor.ts

+5
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ export class RecursiveASTVisitor<Context> extends ASTVisitor<Context, void> {
407407
this.accept(node.getTypeId(), context);
408408
}
409409

410+
visitIsSameAsExpression(node: ast.IsSameAsExpressionAST, context: Context): void {
411+
this.accept(node.getTypeId(), context);
412+
this.accept(node.getOtherTypeId(), context);
413+
}
414+
410415
visitUnaryExpression(node: ast.UnaryExpressionAST, context: Context): void {
411416
this.accept(node.getExpression(), context);
412417
}

packages/cxx-frontend/src/TokenKind.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ export enum TokenKind {
2727
FLOATING_POINT_LITERAL,
2828
INTEGER_LITERAL,
2929
STRING_LITERAL,
30+
WIDE_STRING_LITERAL,
31+
UTF8_STRING_LITERAL,
32+
UTF16_STRING_LITERAL,
33+
UTF32_STRING_LITERAL,
3034
USER_DEFINED_STRING_LITERAL,
3135
HASH,
3236
HASH_HASH,
@@ -119,7 +123,7 @@ export enum TokenKind {
119123
__IS_NOTHROW_CONSTRUCTIBLE,
120124
__IS_POD,
121125
__IS_POLYMORPHIC,
122-
__IS_SAME,
126+
__IS_SAME_AS,
123127
__IS_STANDARD_LAYOUT,
124128
__IS_TRIVIAL,
125129
__IS_TRIVIALLY_ASSIGNABLE,

src/cxx/ast.cc

+20
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,26 @@ SourceLocation AlignofExpressionAST::lastSourceLocation() {
10601060
return SourceLocation();
10611061
}
10621062

1063+
SourceLocation IsSameAsExpressionAST::firstSourceLocation() {
1064+
if (auto loc = cxx::firstSourceLocation(isSameAsLoc)) return loc;
1065+
if (auto loc = cxx::firstSourceLocation(lparenLoc)) return loc;
1066+
if (auto loc = cxx::firstSourceLocation(typeId)) return loc;
1067+
if (auto loc = cxx::firstSourceLocation(commaLoc)) return loc;
1068+
if (auto loc = cxx::firstSourceLocation(otherTypeId)) return loc;
1069+
if (auto loc = cxx::firstSourceLocation(rparenLoc)) return loc;
1070+
return SourceLocation();
1071+
}
1072+
1073+
SourceLocation IsSameAsExpressionAST::lastSourceLocation() {
1074+
if (auto loc = cxx::lastSourceLocation(rparenLoc)) return loc;
1075+
if (auto loc = cxx::lastSourceLocation(otherTypeId)) return loc;
1076+
if (auto loc = cxx::lastSourceLocation(commaLoc)) return loc;
1077+
if (auto loc = cxx::lastSourceLocation(typeId)) return loc;
1078+
if (auto loc = cxx::lastSourceLocation(lparenLoc)) return loc;
1079+
if (auto loc = cxx::lastSourceLocation(isSameAsLoc)) return loc;
1080+
return SourceLocation();
1081+
}
1082+
10631083
SourceLocation UnaryExpressionAST::firstSourceLocation() {
10641084
if (auto loc = cxx::firstSourceLocation(opLoc)) return loc;
10651085
if (auto loc = cxx::firstSourceLocation(expression)) return loc;

src/cxx/ast.h

+17
Original file line numberDiff line numberDiff line change
@@ -1259,6 +1259,23 @@ class AlignofExpressionAST final : public ExpressionAST {
12591259
SourceLocation lastSourceLocation() override;
12601260
};
12611261

1262+
class IsSameAsExpressionAST final : public ExpressionAST {
1263+
public:
1264+
IsSameAsExpressionAST() : ExpressionAST(ASTKind::IsSameAsExpression) {}
1265+
1266+
SourceLocation isSameAsLoc;
1267+
SourceLocation lparenLoc;
1268+
TypeIdAST* typeId = nullptr;
1269+
SourceLocation commaLoc;
1270+
TypeIdAST* otherTypeId = nullptr;
1271+
SourceLocation rparenLoc;
1272+
1273+
void accept(ASTVisitor* visitor) override { visitor->visit(this); }
1274+
1275+
SourceLocation firstSourceLocation() override;
1276+
SourceLocation lastSourceLocation() override;
1277+
};
1278+
12621279
class UnaryExpressionAST final : public ExpressionAST {
12631280
public:
12641281
UnaryExpressionAST() : ExpressionAST(ASTKind::UnaryExpression) {}

src/cxx/ast_cloner.cc

+23
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,29 @@ void ASTCloner::visit(AlignofExpressionAST* ast) {
12321232
copy->rparenLoc = ast->rparenLoc;
12331233
}
12341234

1235+
void ASTCloner::visit(IsSameAsExpressionAST* ast) {
1236+
auto copy = new (arena_) IsSameAsExpressionAST();
1237+
copy_ = copy;
1238+
1239+
copy->type = ast->type;
1240+
1241+
copy->valueCategory = ast->valueCategory;
1242+
1243+
copy->constValue = ast->constValue;
1244+
1245+
copy->isSameAsLoc = ast->isSameAsLoc;
1246+
1247+
copy->lparenLoc = ast->lparenLoc;
1248+
1249+
copy->typeId = accept(ast->typeId);
1250+
1251+
copy->commaLoc = ast->commaLoc;
1252+
1253+
copy->otherTypeId = accept(ast->otherTypeId);
1254+
1255+
copy->rparenLoc = ast->rparenLoc;
1256+
}
1257+
12351258
void ASTCloner::visit(UnaryExpressionAST* ast) {
12361259
auto copy = new (arena_) UnaryExpressionAST();
12371260
copy_ = copy;

src/cxx/ast_cloner.h

+1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ class ASTCloner : public ASTVisitor {
114114
void visit(TypeidExpressionAST* ast) override;
115115
void visit(TypeidOfTypeExpressionAST* ast) override;
116116
void visit(AlignofExpressionAST* ast) override;
117+
void visit(IsSameAsExpressionAST* ast) override;
117118
void visit(UnaryExpressionAST* ast) override;
118119
void visit(BinaryExpressionAST* ast) override;
119120
void visit(AssignmentExpressionAST* ast) override;

src/cxx/ast_fwd.h

+1
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ class SizeofPackExpressionAST;
166166
class TypeidExpressionAST;
167167
class TypeidOfTypeExpressionAST;
168168
class AlignofExpressionAST;
169+
class IsSameAsExpressionAST;
169170
class UnaryExpressionAST;
170171
class BinaryExpressionAST;
171172
class AssignmentExpressionAST;

src/cxx/ast_kind.h

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ enum struct ASTKind {
119119
TypeidExpression,
120120
TypeidOfTypeExpression,
121121
AlignofExpression,
122+
IsSameAsExpression,
122123
UnaryExpression,
123124
BinaryExpression,
124125
AssignmentExpression,

src/cxx/ast_slot.cc

+31
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,37 @@ void ASTSlot::visit(AlignofExpressionAST* ast) {
14391439
slotCount_ = 4;
14401440
}
14411441

1442+
void ASTSlot::visit(IsSameAsExpressionAST* ast) {
1443+
switch (slot_) {
1444+
case 0:
1445+
value_ = ast->isSameAsLoc.index();
1446+
slotKind_ = ASTSlotKind::kToken;
1447+
break;
1448+
case 1:
1449+
value_ = ast->lparenLoc.index();
1450+
slotKind_ = ASTSlotKind::kToken;
1451+
break;
1452+
case 2:
1453+
value_ = reinterpret_cast<std::intptr_t>(ast->typeId);
1454+
slotKind_ = ASTSlotKind::kNode;
1455+
break;
1456+
case 3:
1457+
value_ = ast->commaLoc.index();
1458+
slotKind_ = ASTSlotKind::kToken;
1459+
break;
1460+
case 4:
1461+
value_ = reinterpret_cast<std::intptr_t>(ast->otherTypeId);
1462+
slotKind_ = ASTSlotKind::kNode;
1463+
break;
1464+
case 5:
1465+
value_ = ast->rparenLoc.index();
1466+
slotKind_ = ASTSlotKind::kToken;
1467+
break;
1468+
} // switch
1469+
1470+
slotCount_ = 6;
1471+
}
1472+
14421473
void ASTSlot::visit(UnaryExpressionAST* ast) {
14431474
switch (slot_) {
14441475
case 0:

src/cxx/ast_slot.h

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ class ASTSlot final : ASTVisitor {
124124
void visit(TypeidExpressionAST* ast) override;
125125
void visit(TypeidOfTypeExpressionAST* ast) override;
126126
void visit(AlignofExpressionAST* ast) override;
127+
void visit(IsSameAsExpressionAST* ast) override;
127128
void visit(UnaryExpressionAST* ast) override;
128129
void visit(BinaryExpressionAST* ast) override;
129130
void visit(AssignmentExpressionAST* ast) override;

src/cxx/ast_visitor.h

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class ASTVisitor {
123123
virtual void visit(TypeidExpressionAST* ast) = 0;
124124
virtual void visit(TypeidOfTypeExpressionAST* ast) = 0;
125125
virtual void visit(AlignofExpressionAST* ast) = 0;
126+
virtual void visit(IsSameAsExpressionAST* ast) = 0;
126127
virtual void visit(UnaryExpressionAST* ast) = 0;
127128
virtual void visit(BinaryExpressionAST* ast) = 0;
128129
virtual void visit(AssignmentExpressionAST* ast) = 0;

src/cxx/condition_codegen.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ void ConditionCodegen::gen(ExpressionAST* ast, ir::Block* iftrue,
3434
ir::Block* iffalse) {
3535
std::swap(iftrue_, iftrue);
3636
std::swap(iffalse_, iffalse);
37-
if (auto expr = gen(ast)) {
37+
if (ast && ast->constValue) {
38+
cg->emitJump(const_value_cast<bool>(*ast->constValue) ? iftrue_ : iffalse_);
39+
} else if (auto expr = gen(ast)) {
3840
cg->emitCondJump(cg->createBinary(ir::BinaryOp::kExclaimEqual, expr,
3941
cg->createIntegerLiteral(0)),
4042
iftrue_, iffalse_);

src/cxx/default_ast_visitor.cc

+4
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ void DefaultASTVisitor::visit(AlignofExpressionAST* ast) {
342342
throw std::runtime_error("visit(AlignofExpressionAST): not implemented");
343343
}
344344

345+
void DefaultASTVisitor::visit(IsSameAsExpressionAST* ast) {
346+
throw std::runtime_error("visit(IsSameAsExpressionAST): not implemented");
347+
}
348+
345349
void DefaultASTVisitor::visit(UnaryExpressionAST* ast) {
346350
throw std::runtime_error("visit(UnaryExpressionAST): not implemented");
347351
}

src/cxx/default_ast_visitor.h

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ class DefaultASTVisitor : public ASTVisitor {
121121
void visit(TypeidExpressionAST* ast) override;
122122
void visit(TypeidOfTypeExpressionAST* ast) override;
123123
void visit(AlignofExpressionAST* ast) override;
124+
void visit(IsSameAsExpressionAST* ast) override;
124125
void visit(UnaryExpressionAST* ast) override;
125126
void visit(BinaryExpressionAST* ast) override;
126127
void visit(AssignmentExpressionAST* ast) override;

src/cxx/expression_codegen.cc

+4
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ void ExpressionCodegen::visit(AlignofExpressionAST* ast) {
271271
throw std::runtime_error("visit(AlignofExpressionAST): not implemented");
272272
}
273273

274+
void ExpressionCodegen::visit(IsSameAsExpressionAST* ast) {
275+
expr_ = cg->createIntegerLiteral(std::get<std::uint64_t>(*ast->constValue));
276+
}
277+
274278
void ExpressionCodegen::visit(UnaryExpressionAST* ast) {
275279
switch (ast->op) {
276280
case TokenKind::T_PLUS_PLUS:

src/cxx/expression_codegen.h

+1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class ExpressionCodegen : protected DefaultASTVisitor {
6161
void visit(TypeidExpressionAST* ast) override;
6262
void visit(TypeidOfTypeExpressionAST* ast) override;
6363
void visit(AlignofExpressionAST* ast) override;
64+
void visit(IsSameAsExpressionAST* ast) override;
6465
void visit(UnaryExpressionAST* ast) override;
6566
void visit(BinaryExpressionAST* ast) override;
6667
void visit(AssignmentExpressionAST* ast) override;

src/cxx/keywords.kwgen

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ __is_nothrow_constructible
4141
__is_pod
4242
__is_polymorphic
4343
__is_same
44+
__is_same_as
4445
__is_standard_layout
4546
__is_trivial
4647
__is_trivially_assignable

src/cxx/parser.cc

+35-2
Original file line numberDiff line numberDiff line change
@@ -1830,7 +1830,7 @@ bool Parser::parse_builtin_function_2() {
18301830
case TokenKind::T___IS_CONVERTIBLE_TO:
18311831
case TokenKind::T___IS_NOTHROW_ASSIGNABLE:
18321832
case TokenKind::T___IS_NOTHROW_CONSTRUCTIBLE:
1833-
case TokenKind::T___IS_SAME:
1833+
case TokenKind::T___IS_SAME_AS:
18341834
case TokenKind::T___IS_TRIVIALLY_ASSIGNABLE:
18351835
case TokenKind::T___IS_TRIVIALLY_CONSTRUCTIBLE:
18361836
case TokenKind::T___REFERENCE_BINDS_TO_TEMPORARY:
@@ -1855,6 +1855,38 @@ bool Parser::parse_builtin_call_expression(ExpressionAST*& yyast) {
18551855
return true;
18561856
}
18571857

1858+
SourceLocation loc;
1859+
1860+
if (match(TokenKind::T___IS_SAME_AS, loc)) {
1861+
auto ast = new (pool) IsSameAsExpressionAST();
1862+
yyast = ast;
1863+
1864+
ast->isSameAsLoc = loc;
1865+
1866+
expect(TokenKind::T_LPAREN, ast->lparenLoc);
1867+
1868+
if (!parse_type_id(ast->typeId)) parse_error("expected a type id");
1869+
1870+
sem->typeId(ast->typeId);
1871+
1872+
expect(TokenKind::T_COMMA, ast->lparenLoc);
1873+
1874+
if (!parse_type_id(ast->otherTypeId)) parse_error("expected a type id");
1875+
1876+
sem->typeId(ast->otherTypeId);
1877+
1878+
expect(TokenKind::T_RPAREN, ast->rparenLoc);
1879+
1880+
if (ast->typeId && ast->otherTypeId) {
1881+
const auto isSame = ast->typeId->type == ast->otherTypeId->type;
1882+
ast->constValue = std::uint64_t(isSame);
1883+
} else {
1884+
ast->constValue = std::uint64_t(0);
1885+
}
1886+
1887+
return true;
1888+
}
1889+
18581890
if (!parse_builtin_function_2()) return false;
18591891

18601892
expect(TokenKind::T_LPAREN);
@@ -4203,7 +4235,8 @@ bool Parser::parse_named_type_specifier_helper(SpecifierAST*& yyast,
42034235

42044236
sem->name(name, &nameSem);
42054237

4206-
auto typeSymbol = sem->scope()->unqualifiedLookup(nameSem.name, LookupOptions::kType);
4238+
auto typeSymbol =
4239+
sem->scope()->unqualifiedLookup(nameSem.name, LookupOptions::kType);
42074240

42084241
if (checkTypes_) {
42094242
if (!typeSymbol) return false;

src/cxx/recursive_ast_visitor.cc

+5
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,11 @@ void RecursiveASTVisitor::visit(AlignofExpressionAST* ast) {
518518
acceptTypeId(ast->typeId);
519519
}
520520

521+
void RecursiveASTVisitor::visit(IsSameAsExpressionAST* ast) {
522+
acceptTypeId(ast->typeId);
523+
acceptTypeId(ast->otherTypeId);
524+
}
525+
521526
void RecursiveASTVisitor::visit(UnaryExpressionAST* ast) {
522527
acceptExpression(ast->expression);
523528
}

src/cxx/recursive_ast_visitor.h

+1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ class RecursiveASTVisitor : public ASTVisitor {
162162
void visit(TypeidExpressionAST* ast) override;
163163
void visit(TypeidOfTypeExpressionAST* ast) override;
164164
void visit(AlignofExpressionAST* ast) override;
165+
void visit(IsSameAsExpressionAST* ast) override;
165166
void visit(UnaryExpressionAST* ast) override;
166167
void visit(BinaryExpressionAST* ast) override;
167168
void visit(AssignmentExpressionAST* ast) override;

src/cxx/semantics.cc

+5
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,11 @@ void Semantics::visit(TypeidOfTypeExpressionAST* ast) { typeId(ast->typeId); }
591591

592592
void Semantics::visit(AlignofExpressionAST* ast) { typeId(ast->typeId); }
593593

594+
void Semantics::visit(IsSameAsExpressionAST* ast) {
595+
typeId(ast->typeId);
596+
typeId(ast->otherTypeId);
597+
}
598+
594599
void Semantics::visit(UnaryExpressionAST* ast) {
595600
ExpressionSem expression;
596601
this->expression(ast->expression, &expression);

0 commit comments

Comments
 (0)