HLSL: Implicit bool conversions for conditional expressions and related.
Covers if(cond), while(cond), do-while(cond), for(;cond;), and (cond ? :). Fixes #778.
This commit is contained in:
@@ -2527,6 +2527,10 @@ bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node)
|
||||
if (! acceptTokenClass(EHTokQuestion))
|
||||
return true;
|
||||
|
||||
node = parseContext.convertConditionalExpression(token.loc, node);
|
||||
if (node == nullptr)
|
||||
return false;
|
||||
|
||||
TIntermTyped* trueNode = nullptr;
|
||||
if (! acceptExpression(trueNode)) {
|
||||
expected("expression after ?");
|
||||
@@ -3197,6 +3201,9 @@ bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement)
|
||||
TIntermTyped* condition;
|
||||
if (! acceptParenExpression(condition))
|
||||
return false;
|
||||
condition = parseContext.convertConditionalExpression(loc, condition);
|
||||
if (condition == nullptr)
|
||||
return false;
|
||||
|
||||
// create the child statements
|
||||
TIntermNodePair thenElse = { nullptr, nullptr };
|
||||
@@ -3280,6 +3287,9 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
||||
// LEFT_PAREN condition RIGHT_PAREN
|
||||
if (! acceptParenExpression(condition))
|
||||
return false;
|
||||
condition = parseContext.convertConditionalExpression(loc, condition);
|
||||
if (condition == nullptr)
|
||||
return false;
|
||||
|
||||
// statement
|
||||
if (! acceptScopedStatement(statement)) {
|
||||
@@ -3319,6 +3329,9 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
||||
TIntermTyped* condition;
|
||||
if (! acceptParenExpression(condition))
|
||||
return false;
|
||||
condition = parseContext.convertConditionalExpression(loc, condition);
|
||||
if (condition == nullptr)
|
||||
return false;
|
||||
|
||||
if (! acceptTokenClass(EHTokSemicolon))
|
||||
expected(";");
|
||||
@@ -3356,6 +3369,11 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
|
||||
acceptExpression(condition);
|
||||
if (! acceptTokenClass(EHTokSemicolon))
|
||||
expected(";");
|
||||
if (condition != nullptr) {
|
||||
condition = parseContext.convertConditionalExpression(loc, condition);
|
||||
if (condition == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
// iterator SEMI_COLON
|
||||
TIntermTyped* iterator = nullptr;
|
||||
|
||||
@@ -4285,6 +4285,18 @@ void HlslParseContext::handleRegister(const TSourceLoc& loc, TQualifier& qualifi
|
||||
}
|
||||
}
|
||||
|
||||
// Convert to a scalar boolean, or if not allowed by HLSL semantics,
|
||||
// report an error and return nullptr.
|
||||
TIntermTyped* HlslParseContext::convertConditionalExpression(const TSourceLoc& loc, TIntermTyped* condition)
|
||||
{
|
||||
if (!condition->getType().isScalarOrVec1()) {
|
||||
error(loc, "requires a scalar", "conditional expression", "");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return intermediate.addConversion(EOpConstructBool, TType(EbtBool), condition);
|
||||
}
|
||||
|
||||
//
|
||||
// Same error message for all places assignments don't work.
|
||||
//
|
||||
@@ -4607,13 +4619,6 @@ bool HlslParseContext::voidErrorCheck(const TSourceLoc& loc, const TString& iden
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks to see if the node (for the expression) contains a scalar boolean expression or not
|
||||
void HlslParseContext::boolCheck(const TSourceLoc& loc, const TIntermTyped* type)
|
||||
{
|
||||
if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector())
|
||||
error(loc, "boolean expression expected", "", "");
|
||||
}
|
||||
|
||||
//
|
||||
// Fix just a full qualifier (no variables or types yet, but qualifier is complete) at global level.
|
||||
//
|
||||
|
||||
@@ -101,7 +101,7 @@ public:
|
||||
const glslang::TString* component);
|
||||
void handleRegister(const TSourceLoc&, TQualifier&, const glslang::TString* profile, const glslang::TString& desc,
|
||||
int subComponent, const glslang::TString*);
|
||||
|
||||
TIntermTyped* convertConditionalExpression(const TSourceLoc&, TIntermTyped*);
|
||||
TIntermAggregate* handleSamplerTextureCombine(const TSourceLoc& loc, TIntermTyped* argTex, TIntermTyped* argSampler);
|
||||
|
||||
bool parseMatrixSwizzleSelector(const TSourceLoc&, const TString&, int cols, int rows, TSwizzleSelectors<TMatrixSelector>&);
|
||||
@@ -120,7 +120,6 @@ public:
|
||||
void structArrayCheck(const TSourceLoc&, const TType& structure);
|
||||
void arrayDimMerge(TType& type, const TArraySizes* sizes);
|
||||
bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
|
||||
void boolCheck(const TSourceLoc&, const TIntermTyped*);
|
||||
void globalQualifierFix(const TSourceLoc&, TQualifier&);
|
||||
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
|
||||
void mergeQualifiers(TQualifier& dst, const TQualifier& src);
|
||||
|
||||
Reference in New Issue
Block a user