[cfe-commits] [PATCH] Multiple patches for refactoring SemaExpr.cpp

Douglas Gregor dgregor at apple.com
Mon Aug 29 18:32:12 PDT 2011


On Aug 8, 2011, at 6:39 PM, Richard Trieu wrote:

> Refactoring of lib/Sema/SemaExpr.cpp broken into several patches.  Changes include reducing code duplication, moving diagnostic checks into separate functions, and reducing method length.  Comments welcome. <check_addition_subtraction_increment_decrement.patch>

Looks good.

> <check_address_of_operand.patch>

+/// \brief Diagnose invalid operand for address of operations.
+static void diagnoseAddressOfInvalidType(Sema &S, SourceLocation Loc,
+                                         Expr *E, std::string type) {
+  S.Diag(Loc, diag::err_typecheck_address_of) << type << E->getSourceRange();
+}

It would be far better for err_typecheck_address_of to use a %select{} in its diagnostic text, rather than passing strings like "bit-field" or "vector element" through to the diagnostics system. The current behavior isn't localizable at al.


> <check_conditional_operands.patch>

+/// \brief Return true if the condition expression is valid.
+static bool checkCondition(Sema &S, Expr *Cond) {
+  QualType CondTy = Cond->getType();
+
+  // C99 6.5.15p2
+  if (CondTy->isScalarType()) return true;
+
+  // OpenCL: Sec 6.3.i says the condition is allowed to be a vector or scalar.
+  if (S.getLangOptions().OpenCL && CondTy->isVectorType())
+    return true;
+
+  // Emit the proper error message.
+  S.Diag(Cond->getLocStart(), S.getLangOptions().OpenCL ?
+                              diag::err_typecheck_cond_expect_scalar :
+                              diag::err_typecheck_cond_expect_scalar_or_vector)
+    << CondTy;
+  return false;
+}

LLVM convention is to return true on failure, false otherwise. The same goes for the rest of the check* functions.

+/// \brief Checks compatibility between two pointers and return the resulting
+/// type.
+static QualType checkConditionalPointerCompatibility(Sema &S, ExprResult &LHS,
+                                                     ExprResult &RHS,
+                                                     SourceLocation Loc) {
+  QualType LHSTy = LHS.get()->getType();
+  QualType RHSTy = RHS.get()->getType();
+
+  if (S.Context.getCanonicalType(LHSTy) == S.Context.getCanonicalType(RHSTy)) {
+    // Two identical pointers types are always compatible.
+    return LHSTy;
+  }

It's a bit cleaner to write S.Context.hasSameType(LHSTy, RHSTy) here.

> <check_incomplete_pointer_type.patch>

+/// \brief Warn if Operand is incomplete pointer type
+///
+/// \returns True if pointer has complete type
+static bool checkArithmeticIncompletePointerType(Sema &S, SourceLocation Loc,
+                                                 Expr *Operand) {
+  if ((Operand->getType()->isPointerType() &&
+       !Operand->getType()->isDependentType()) ||
+      Operand->getType()->isObjCObjectPointerType()) {
+    QualType PointeeTy = Operand->getType()->getPointeeType();
+    if (S.RequireCompleteType(
+          Loc, PointeeTy,
+          S.PDiag(diag::err_typecheck_arithmetic_incomplete_type)
+            << PointeeTy << Operand->getSourceRange()))
+      return false;
+  }
+  return true;
+}

Please invert the return result.

> <pointer_comparison.patch>

+/// \brief Returns true if the member pointers are compatible.
+static bool checkPointerComparisonCompatibility(Sema &S, SourceLocation Loc,
+                                                ExprResult &lex,
+                                                ExprResult &rex) {

Return value inversion.


> <diagnose_bitwise_precedence.patch>

Looks good!

> <null_arithmetic_and_enum_compare_to_new_functions.patch>

+static void checkEnumComparison(Sema &S, SourceLocation Loc, ExprResult &lex,
+                                ExprResult &rex){
+  QualType lType = lex.get()->getType();
+  QualType rType = rex.get()->getType();
+  QualType LHSStrippedType = lex.get()->IgnoreParenImpCasts()->getType();
+  QualType RHSStrippedType = rex.get()->IgnoreParenImpCasts()->getType();
+
+  // Two different enums will raise a warning when compared.
+  if (const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>()) {
+    if (const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>()) {
+      if (LHSEnumType->getDecl()->getIdentifier() &&
+          RHSEnumType->getDecl()->getIdentifier() &&
+          !S.Context.hasSameUnqualifiedType(LHSStrippedType, RHSStrippedType)) {
+        S.Diag(Loc, diag::warn_comparison_of_mixed_enum_types)
+          << LHSStrippedType << RHSStrippedType
+          << lex.get()->getSourceRange() << rex.get()->getSourceRange();
+      }
+    }
+  }
+}

You could easily reduce nesting here to clean things up, e.g.,

  const EnumType *LHSEnumType = LHSStrippedType->getAs<EnumType>();
  if (!LHSEnumType)
    return;
  const EnumType *RHSEnumType = RHSStrippedType->getAs<EnumType>();
  if (!RHSEnumType)
    return;


> <usual_arithmetic_conversions.patch>

+/// \brief Converts an integer to complex float type.
+static bool handleIntegerToComplexFloatConversion(Sema &S, ExprResult &intExpr,
+                                                  ExprResult &complexExpr,
+                                                  QualType intTy,
+                                                  QualType complexTy,
+                                                  bool skipCast) {
+  if (intTy->isComplexType() || intTy->isRealFloatingType()) return false;
+  if (skipCast) return true;
+  if (intTy->isIntegerType()) {
+    QualType fpTy = cast<ComplexType>(complexTy)->getElementType();
+    intExpr = S.ImpCastExprToType(intExpr.take(), fpTy, CK_IntegralToFloating);
+    intExpr = S.ImpCastExprToType(intExpr.take(), complexTy,
+                                  CK_FloatingRealToComplex);
+  } else {
+    assert(intTy->isComplexIntegerType());
+    intExpr = S.ImpCastExprToType(intExpr.take(), complexTy,
+                                  CK_IntegralComplexToFloatingComplex);
   }
+  return true;
+}

Inverted return value.

These are good cleanups, but please make sure to follow the return-true-on-error convention used in LLVM/Clang. I think it's a weird convention, but it's pervasive :)

	- Doug



More information about the cfe-commits mailing list