tools/clang/lib/Sema/SemaHLSL.cpp
/// <summary>Validates and adjusts operands for the specified unary operator.</summary>
/// <param name="OpLoc">Source location for operator.</param>
/// <param name="Opc">Kind of operator.</param>
/// <param name="InputExpr">Input expression to the operator.</param>
/// <param name="VK">Value kind for resulting expression.</param>
/// <param name="OK">Object kind for resulting expression.</param>
/// <returns>The result type for the expression.</returns>
Validates and adjusts operands for the specified unary operator.
Source location for operator.
Kind of operator.
Input expression to the operator.
Value kind for resulting expression.
Object kind for resulting expression.
The result type for the expression.
Validates and adjusts operands for the specified unary operator . Source location for operator . Kind of operator . Input expression to the operator . Value kind for resulting expression . Object kind for resulting expression . The result type for the expression .
QualType HLSLExternalSource::CheckUnaryOpForHLSL(
  SourceLocation OpLoc,
  UnaryOperatorKind Opc,
  ExprResult& InputExpr,
  ExprValueKind& VK,
  ExprObjectKind& OK)
{
  InputExpr = m_sema->CorrectDelayedTyposInExpr(InputExpr);
  if (InputExpr.isInvalid())
    return QualType();
  switch (Opc) {
  case UO_AddrOf:
  case UO_Deref:
    m_sema->Diag(OpLoc, diag::err_hlsl_unsupported_operator);
    return QualType();
  }
  Expr* expr = InputExpr.get();
  if (expr->isTypeDependent())
    return m_context->DependentTy;
  ArBasicKind elementKind = GetTypeElementKind(expr->getType());
  if (UnaryOperatorKindRequiresModifiableValue(Opc)) {
    if (elementKind == AR_BASIC_ENUM) {
      bool isInc = IsIncrementOp(Opc);
      m_sema->Diag(OpLoc, diag::err_increment_decrement_enum) << isInc << expr->getType();
      return QualType();
    }
    extern bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S);
    if (CheckForModifiableLvalue(expr, OpLoc, *m_sema))
      return QualType();
  } else {
    InputExpr = m_sema->DefaultLvalueConversion(InputExpr.get()).get();
    if (InputExpr.isInvalid()) return QualType();
  }
  if (UnaryOperatorKindDisallowsBool(Opc) && IS_BASIC_BOOL(elementKind)) {
    m_sema->Diag(OpLoc, diag::err_hlsl_unsupported_bool_lvalue_op);
    return QualType();
  }
  if (UnaryOperatorKindRequiresBoolAsNumeric(Opc)) {
    InputExpr = PromoteToIntIfBool(InputExpr);
    expr = InputExpr.get();
    elementKind = GetTypeElementKind(expr->getType());
  }
  ArTypeObjectKind objectKind = GetTypeObjectKind(expr->getType());
  bool requiresIntegrals = UnaryOperatorKindRequiresIntegrals(Opc);
  bool requiresNumerics = UnaryOperatorKindRequiresNumerics(Opc);
  if (!ValidateTypeRequirements(OpLoc, elementKind, objectKind, requiresIntegrals, requiresNumerics)) {
    return QualType();
  }
  if (Opc == UnaryOperatorKind::UO_Minus) {
    if (IS_BASIC_UINT(Opc)) {
      m_sema->Diag(OpLoc, diag::warn_hlsl_unary_negate_unsigned);
    }
  }
  QualType resultType = expr->getType();
  if (Opc == UnaryOperatorKind::UO_LNot) {
    UINT rowCount, colCount;
    GetRowsAndColsForAny(expr->getType(), rowCount, colCount);
    resultType = NewSimpleAggregateType(objectKind, AR_BASIC_BOOL, AR_QUAL_CONST, rowCount, colCount);
    StandardConversionSequence standard;
    if (!CanConvert(OpLoc, expr, resultType, false, nullptr, &standard)) {
      m_sema->Diag(OpLoc, diag::err_hlsl_requires_bool_for_not);
      return QualType();
    }
    ExprResult result = m_sema->PerformImplicitConversion(InputExpr.get(), resultType, standard, Sema::AA_Casting, Sema::CCK_ImplicitConversion);
    if (result.isUsable()) {
      InputExpr = result.get();
    }
  }
  bool isPrefix = Opc == UO_PreInc || Opc == UO_PreDec;
  if (isPrefix) {
    VK = VK_LValue;
    return resultType;
  }
  else {
    VK = VK_RValue;
    return resultType.getUnqualifiedType();
  }
}
QualType HLSLExternalSource :: CheckUnaryOpForHLSL ( SourceLocation OpLoc , UnaryOperatorKind Opc , ExprResult & InputExpr , ExprValueKind & VK , ExprObjectKind & OK ) { InputExpr = m_sema -> CorrectDelayedTyposInExpr ( InputExpr ) ; if ( InputExpr . isInvalid ( ) ) return QualType ( ) ; switch ( Opc ) { case UO_AddrOf : case UO_Deref : m_sema -> Diag ( OpLoc , diag :: err_hlsl_unsupported_operator ) ; return QualType ( ) ; } Expr * expr = InputExpr . get ( ) ; if ( expr -> isTypeDependent ( ) ) return m_context -> DependentTy ; ArBasicKind elementKind = GetTypeElementKind ( expr -> getType ( ) ) ; if ( UnaryOperatorKindRequiresModifiableValue ( Opc ) ) { if ( elementKind == AR_BASIC_ENUM ) { bool isInc = IsIncrementOp ( Opc ) ; m_sema -> Diag ( OpLoc , diag :: err_increment_decrement_enum ) << isInc << expr -> getType ( ) ; return QualType ( ) ; } extern bool CheckForModifiableLvalue ( Expr * E , SourceLocation Loc , Sema & S ) ; if ( CheckForModifiableLvalue ( expr , OpLoc , * m_sema ) ) return QualType ( ) ; } else { InputExpr = m_sema -> DefaultLvalueConversion ( InputExpr . get ( ) ) . get ( ) ; if ( InputExpr . isInvalid ( ) ) return QualType ( ) ; } if ( UnaryOperatorKindDisallowsBool ( Opc ) && IS_BASIC_BOOL ( elementKind ) ) { m_sema -> Diag ( OpLoc , diag :: err_hlsl_unsupported_bool_lvalue_op ) ; return QualType ( ) ; } if ( UnaryOperatorKindRequiresBoolAsNumeric ( Opc ) ) { InputExpr = PromoteToIntIfBool ( InputExpr ) ; expr = InputExpr . get ( ) ; elementKind = GetTypeElementKind ( expr -> getType ( ) ) ; } ArTypeObjectKind objectKind = GetTypeObjectKind ( expr -> getType ( ) ) ; bool requiresIntegrals = UnaryOperatorKindRequiresIntegrals ( Opc ) ; bool requiresNumerics = UnaryOperatorKindRequiresNumerics ( Opc ) ; if ( ! ValidateTypeRequirements ( OpLoc , elementKind , objectKind , requiresIntegrals , requiresNumerics ) ) { return QualType ( ) ; } if ( Opc == UnaryOperatorKind :: UO_Minus ) { if ( IS_BASIC_UINT ( Opc ) ) { m_sema -> Diag ( OpLoc , diag :: warn_hlsl_unary_negate_unsigned ) ; } } QualType resultType = expr -> getType ( ) ; if ( Opc == UnaryOperatorKind :: UO_LNot ) { UINT rowCount , colCount ; GetRowsAndColsForAny ( expr -> getType ( ) , rowCount , colCount ) ; resultType = NewSimpleAggregateType ( objectKind , AR_BASIC_BOOL , AR_QUAL_CONST , rowCount , colCount ) ; StandardConversionSequence standard ; if ( ! CanConvert ( OpLoc , expr , resultType , false , nullptr , & standard ) ) { m_sema -> Diag ( OpLoc , diag :: err_hlsl_requires_bool_for_not ) ; return QualType ( ) ; } ExprResult result = m_sema -> PerformImplicitConversion ( InputExpr . get ( ) , resultType , standard , Sema :: AA_Casting , Sema :: CCK_ImplicitConversion ) ; if ( result . isUsable ( ) ) { InputExpr = result . get ( ) ; } } bool isPrefix = Opc == UO_PreInc || Opc == UO_PreDec ; if ( isPrefix ) { VK = VK_LValue ; return resultType ; } else { VK = VK_RValue ; return resultType . getUnqualifiedType ( ) ; } }
<summary>Validates and adjusts operands for the specified unary operator.</summary>
<param name="OpLoc">Source location for operator.</param>
<param name="Opc">Kind of operator.</param>
<param name="InputExpr">Input expression to the operator.</param>
<param name="VK">Value kind for resulting expression.</param>
<param name="OK">Object kind for resulting expression.</param>
<returns>The result type for the expression.</returns>
<summary > Validates and adjusts operands for the specified unary operator . < / summary > <param name = " OpLoc " > Source location for operator . < / param > <param name = " Opc " > Kind of operator . < / param > <param name = " InputExpr " > Input expression to the operator . < / param > <param name = " VK " > Value kind for resulting expression . < / param > <param name = " OK " > Object kind for resulting expression . < / param > <returns > The result type for the expression . < / returns >
// Reject unsupported operators * and & // By default, the result type is the operand type. // Logical not however should cast to a bool. // Cast argument.