Skip to content

Commit 17c5b70

Browse files
johnstiles-googleSkia Commit-Bot
authored andcommitted
Add as<SymbolSubclass> to downcast Symbols more safely.
The as<T>() function asserts that the Symbol is of the correct kind before performing the downcast, and is also generally easier to read as function calls flow naturally from left-to-right, and C-style casts don't. This CL updates several Symbol downcasts in SkSL to the as<T> syntax, but is not intended to exhaustively replace them all (although that would be ideal). In places where we SkASSERTed the expression's fKind immediately before a cast, the assert has been removed because it would be redundant with the behavior of as<T>(). Change-Id: I33cb2b9657dc410241dbc96be85c4ce182a1b391 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/311436 Commit-Queue: John Stiles <johnstiles@google.com> Commit-Queue: Brian Osman <brianosman@google.com> Auto-Submit: John Stiles <johnstiles@google.com> Reviewed-by: Brian Osman <brianosman@google.com>
1 parent bc6fb27 commit 17c5b70

13 files changed

+74
-49
lines changed

src/sksl/SkSLByteCodeGenerator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,7 @@ class ByteCodeExpressionLValue : public ByteCodeGenerator::LValue {
16021602
std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Expression& e) {
16031603
switch (e.fKind) {
16041604
case Expression::kExternalValue_Kind: {
1605-
const ExternalValue* value = ((ExternalValueReference&) e).fValue;
1605+
const ExternalValue* value = e.as<ExternalValueReference>().fValue;
16061606
int index = fOutput->fExternalValues.size();
16071607
fOutput->fExternalValues.push_back(value);
16081608
SkASSERT(index <= 255);
@@ -1613,7 +1613,7 @@ std::unique_ptr<ByteCodeGenerator::LValue> ByteCodeGenerator::getLValue(const Ex
16131613
case Expression::kVariableReference_Kind:
16141614
return std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e));
16151615
case Expression::kSwizzle_Kind: {
1616-
const Swizzle& s = (const Swizzle&) e;
1616+
const Swizzle& s = e.as<Swizzle>();
16171617
return swizzle_is_simple(s)
16181618
? std::unique_ptr<LValue>(new ByteCodeExpressionLValue(this, e))
16191619
: std::unique_ptr<LValue>(new ByteCodeSwizzleLValue(this, s));

src/sksl/SkSLCPPCodeGenerator.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,9 @@ void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
8686
b.fRight->fKind == Expression::kNullLiteral_Kind) {
8787
const Variable* var;
8888
if (b.fLeft->fKind != Expression::kNullLiteral_Kind) {
89-
SkASSERT(b.fLeft->fKind == Expression::kVariableReference_Kind);
90-
var = &((VariableReference&) *b.fLeft).fVariable;
89+
var = &b.fLeft->as<VariableReference>().fVariable;
9190
} else {
92-
SkASSERT(b.fRight->fKind == Expression::kVariableReference_Kind);
93-
var = &((VariableReference&) *b.fRight).fVariable;
91+
var = &b.fRight->as<VariableReference>().fVariable;
9492
}
9593
SkASSERT(var->fType.kind() == Type::kNullable_Kind &&
9694
var->fType.componentType() == *fContext.fFragmentProcessor_Type);

src/sksl/SkSLDehydrator.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ void Dehydrator::write(const Symbol& s) {
142142
}
143143
switch (s.fKind) {
144144
case Symbol::kFunctionDeclaration_Kind: {
145-
const FunctionDeclaration& f = (const FunctionDeclaration&) s;
145+
const FunctionDeclaration& f = s.as<FunctionDeclaration>();
146146
this->writeU8(Rehydrator::kFunctionDeclaration_Command);
147147
this->writeId(&f);
148148
this->write(f.fModifiers);
@@ -155,7 +155,7 @@ void Dehydrator::write(const Symbol& s) {
155155
break;
156156
}
157157
case Symbol::kUnresolvedFunction_Kind: {
158-
const UnresolvedFunction& f = (const UnresolvedFunction&) s;
158+
const UnresolvedFunction& f = s.as<UnresolvedFunction>();
159159
this->writeU8(Rehydrator::kUnresolvedFunction_Command);
160160
this->writeId(&f);
161161
this->writeU8(f.fFunctions.size());
@@ -165,7 +165,7 @@ void Dehydrator::write(const Symbol& s) {
165165
break;
166166
}
167167
case Symbol::kType_Kind: {
168-
const Type& t = (const Type&) s;
168+
const Type& t = s.as<Type>();
169169
switch (t.kind()) {
170170
case Type::kArray_Kind:
171171
this->writeU8(Rehydrator::kArrayType_Command);
@@ -202,7 +202,7 @@ void Dehydrator::write(const Symbol& s) {
202202
break;
203203
}
204204
case Symbol::kVariable_Kind: {
205-
Variable& v = (Variable&) s;
205+
const Variable& v = s.as<Variable>();
206206
this->writeU8(Rehydrator::kVariable_Command);
207207
this->writeId(&v);
208208
this->write(v.fModifiers);
@@ -212,7 +212,7 @@ void Dehydrator::write(const Symbol& s) {
212212
break;
213213
}
214214
case Symbol::kField_Kind: {
215-
Field& f = (Field&) s;
215+
const Field& f = s.as<Field>();
216216
this->writeU8(Rehydrator::kField_Command);
217217
this->writeU16(this->symbolId(&f.fOwner));
218218
this->writeU8(f.fFieldIndex);

src/sksl/SkSLExternalValue.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ class Type;
1717

1818
class ExternalValue : public Symbol {
1919
public:
20+
static constexpr Kind kSymbolKind = kExternal_Kind;
21+
2022
ExternalValue(const char* name, const Type& type)
21-
: INHERITED(-1, kExternal_Kind, name)
23+
: INHERITED(-1, kSymbolKind, name)
2224
, fType(type) {}
2325

2426
virtual bool canRead() const {

src/sksl/SkSLIRGenerator.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -988,10 +988,10 @@ void IRGenerator::convertFunction(const ASTNode& f) {
988988
std::vector<const FunctionDeclaration*> functions;
989989
switch (entry->fKind) {
990990
case Symbol::kUnresolvedFunction_Kind:
991-
functions = ((UnresolvedFunction*) entry)->fFunctions;
991+
functions = entry->as<UnresolvedFunction>().fFunctions;
992992
break;
993993
case Symbol::kFunctionDeclaration_Kind:
994-
functions.push_back((FunctionDeclaration*) entry);
994+
functions.push_back(&entry->as<FunctionDeclaration>());
995995
break;
996996
default:
997997
fErrors.error(f.fOffset, "symbol '" + fd.fName + "' was already defined");
@@ -1243,13 +1243,13 @@ const Type* IRGenerator::convertType(const ASTNode& type) {
12431243
const Symbol* result = (*fSymbolTable)[td.fName];
12441244
if (result && result->fKind == Symbol::kType_Kind) {
12451245
if (td.fIsNullable) {
1246-
if (((Type&) *result) == *fContext.fFragmentProcessor_Type) {
1246+
if (result->as<Type>() == *fContext.fFragmentProcessor_Type) {
12471247
if (type.begin() != type.end()) {
12481248
fErrors.error(type.fOffset, "type '" + td.fName + "' may not be used in "
12491249
"an array");
12501250
}
12511251
result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
1252-
String(result->fName) + "?", Type::kNullable_Kind, (const Type&)*result));
1252+
String(result->fName) + "?", Type::kNullable_Kind, result->as<Type>()));
12531253
} else {
12541254
fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable");
12551255
}
@@ -1262,9 +1262,9 @@ const Type* IRGenerator::convertType(const ASTNode& type) {
12621262
}
12631263
name += "]";
12641264
result = fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Type>(
1265-
name, Type::kArray_Kind, (const Type&)*result, size ? size.getInt() : 0));
1265+
name, Type::kArray_Kind, result->as<Type>(), size ? size.getInt() : 0));
12661266
}
1267-
return (const Type*) result;
1267+
return &result->as<Type>();
12681268
}
12691269
fErrors.error(type.fOffset, "unknown type '" + td.fName + "'");
12701270
return nullptr;
@@ -1317,16 +1317,16 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
13171317
switch (result->fKind) {
13181318
case Symbol::kFunctionDeclaration_Kind: {
13191319
std::vector<const FunctionDeclaration*> f = {
1320-
(const FunctionDeclaration*) result
1320+
&result->as<FunctionDeclaration>()
13211321
};
13221322
return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f);
13231323
}
13241324
case Symbol::kUnresolvedFunction_Kind: {
1325-
const UnresolvedFunction* f = (const UnresolvedFunction*) result;
1325+
const UnresolvedFunction* f = &result->as<UnresolvedFunction>();
13261326
return std::make_unique<FunctionReference>(fContext, identifier.fOffset, f->fFunctions);
13271327
}
13281328
case Symbol::kVariable_Kind: {
1329-
const Variable* var = (const Variable*) result;
1329+
const Variable* var = &result->as<Variable>();
13301330
switch (var->fModifiers.fLayout.fBuiltin) {
13311331
case SK_WIDTH_BUILTIN:
13321332
fInputs.fRTWidth = true;
@@ -1373,7 +1373,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
13731373
VariableReference::kRead_RefKind);
13741374
}
13751375
case Symbol::kField_Kind: {
1376-
const Field* field = (const Field*) result;
1376+
const Field* field = &result->as<Field>();
13771377
VariableReference* base = new VariableReference(identifier.fOffset, field->fOwner,
13781378
VariableReference::kRead_RefKind);
13791379
return std::unique_ptr<Expression>(new FieldAccess(
@@ -1382,11 +1382,11 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identi
13821382
FieldAccess::kAnonymousInterfaceBlock_OwnerKind));
13831383
}
13841384
case Symbol::kType_Kind: {
1385-
const Type* t = (const Type*) result;
1385+
const Type* t = &result->as<Type>();
13861386
return std::make_unique<TypeReference>(fContext, identifier.fOffset, *t);
13871387
}
13881388
case Symbol::kExternal_Kind: {
1389-
const ExternalValue* r = (const ExternalValue*) result;
1389+
const ExternalValue* r = &result->as<ExternalValue>();
13901390
return std::make_unique<ExternalValueReference>(identifier.fOffset, r);
13911391
}
13921392
default:
@@ -2500,7 +2500,7 @@ std::unique_ptr<Expression> IRGenerator::call(int offset,
25002500
((TypeReference&) *functionValue).fValue,
25012501
std::move(arguments));
25022502
case Expression::kExternalValue_Kind: {
2503-
const ExternalValue* v = ((ExternalValueReference&) *functionValue).fValue;
2503+
const ExternalValue* v = functionValue->as<ExternalValueReference>().fValue;
25042504
if (!v->canCall()) {
25052505
fErrors.error(offset, "this external value is not a function");
25062506
return nullptr;
@@ -2809,7 +2809,7 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression
28092809
std::unique_ptr<Expression> IRGenerator::convertField(std::unique_ptr<Expression> base,
28102810
StringFragment field) {
28112811
if (base->fKind == Expression::kExternalValue_Kind) {
2812-
const ExternalValue& ev = *((ExternalValueReference&) *base).fValue;
2812+
const ExternalValue& ev = *base->as<ExternalValueReference>().fValue;
28132813
ExternalValue* result = ev.getChild(String(field).c_str());
28142814
if (!result) {
28152815
fErrors.error(base->fOffset, "external value does not have a child named '" + field +

src/sksl/ir/SkSLEnum.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ struct Enum : public ProgramElement {
4242
std::sort(sortedSymbols.begin(), sortedSymbols.end(),
4343
[](const Symbol* a, const Symbol* b) { return a->fName < b->fName; });
4444
for (const auto& s : sortedSymbols) {
45-
const Expression& initialValue = *((Variable*) s)->fInitialValue;
45+
const Expression& initialValue = *s->as<Variable>().fInitialValue;
4646
result += separator + " " + s->fName + " = " +
4747
to_string(initialValue.as<IntLiteral>().fValue);
4848
separator = ",\n";

src/sksl/ir/SkSLField.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ namespace SkSL {
2222
* result of declaring anonymous interface blocks.
2323
*/
2424
struct Field : public Symbol {
25+
static constexpr Kind kSymbolKind = kField_Kind;
26+
2527
Field(int offset, const Variable& owner, int fieldIndex)
26-
: INHERITED(offset, kField_Kind, owner.fType.fields()[fieldIndex].fName)
28+
: INHERITED(offset, kSymbolKind, owner.fType.fields()[fieldIndex].fName)
2729
, fOwner(owner)
2830
, fFieldIndex(fieldIndex) {}
2931

src/sksl/ir/SkSLFunctionDeclaration.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@ struct FunctionDefinition;
2525
* A function declaration (not a definition -- does not contain a body).
2626
*/
2727
struct FunctionDeclaration : public Symbol {
28+
static constexpr Kind kSymbolKind = kFunctionDeclaration_Kind;
29+
2830
FunctionDeclaration(int offset, Modifiers modifiers, StringFragment name,
2931
std::vector<const Variable*> parameters, const Type& returnType,
3032
bool builtin)
31-
: INHERITED(offset, kFunctionDeclaration_Kind, std::move(name))
33+
: INHERITED(offset, kSymbolKind, std::move(name))
3234
, fDefinition(nullptr)
3335
, fBuiltin(builtin)
3436
, fModifiers(modifiers)

src/sksl/ir/SkSLSymbol.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,21 @@ struct Symbol : public IRNode {
3232

3333
~Symbol() override {}
3434

35+
/**
36+
* Use as<T> to downcast symbols. e.g. replace `(Variable&) sym` with `sym.as<Variable>()`.
37+
*/
38+
template <typename T>
39+
const T& as() const {
40+
SkASSERT(this->fKind == T::kSymbolKind);
41+
return static_cast<const T&>(*this);
42+
}
43+
44+
template <typename T>
45+
T& as() {
46+
SkASSERT(this->fKind == T::kSymbolKind);
47+
return static_cast<T&>(*this);
48+
}
49+
3550
Kind fKind;
3651
StringFragment fName;
3752

src/sksl/ir/SkSLSymbolTable.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ namespace SkSL {
1313
std::vector<const FunctionDeclaration*> SymbolTable::GetFunctions(const Symbol& s) {
1414
switch (s.fKind) {
1515
case Symbol::kFunctionDeclaration_Kind:
16-
return { &((FunctionDeclaration&) s) };
16+
return { &s.as<FunctionDeclaration>() };
1717
case Symbol::kUnresolvedFunction_Kind:
18-
return ((UnresolvedFunction&) s).fFunctions;
18+
return s.as<UnresolvedFunction>().fFunctions;
1919
default:
2020
return std::vector<const FunctionDeclaration*>();
2121
}
@@ -74,17 +74,17 @@ void SymbolTable::addWithoutOwnership(StringFragment name, const Symbol* symbol)
7474
const Symbol* oldSymbol = existing->second;
7575
if (oldSymbol->fKind == Symbol::kFunctionDeclaration_Kind) {
7676
std::vector<const FunctionDeclaration*> functions;
77-
functions.push_back((const FunctionDeclaration*) oldSymbol);
78-
functions.push_back((const FunctionDeclaration*) symbol);
77+
functions.push_back(&oldSymbol->as<FunctionDeclaration>());
78+
functions.push_back(&symbol->as<FunctionDeclaration>());
7979
std::unique_ptr<const Symbol> u = std::unique_ptr<const Symbol>(
8080
new UnresolvedFunction(std::move(functions)));
8181
fSymbols[name] = this->takeOwnershipOfSymbol(std::move(u));
8282
} else if (oldSymbol->fKind == Symbol::kUnresolvedFunction_Kind) {
8383
std::vector<const FunctionDeclaration*> functions;
84-
for (const auto* f : ((UnresolvedFunction&) *oldSymbol).fFunctions) {
84+
for (const auto* f : oldSymbol->as<UnresolvedFunction>().fFunctions) {
8585
functions.push_back(f);
8686
}
87-
functions.push_back((const FunctionDeclaration*) symbol);
87+
functions.push_back(&symbol->as<FunctionDeclaration>());
8888
std::unique_ptr<const Symbol> u = std::unique_ptr<const Symbol>(
8989
new UnresolvedFunction(std::move(functions)));
9090
fSymbols[name] = this->takeOwnershipOfSymbol(std::move(u));

0 commit comments

Comments
 (0)