Repository: carbon-language/carbon-lang
File: toolchain/check/cpp/macros.cpp (C++)

Code before:
    context.emitter().Emit(loc_id, InCppMacroEvaluation, (*name_str_opt).str());
    return nullptr;
  }

  result_expr = result_expr->IgnoreParenImpCasts();

  if (isa<clang::StringLiteral>(result_expr) ||
      isa<clang::CharacterLiteral>(result_expr) ||
      isa<clang::CXXNullPtrLiteralExpr>(result_expr)) {
    return result_expr;
  }

  clang::Expr::EvalResult evaluated_result;
  CARBON_CHECK(result_expr->EvaluateAsConstantExpr(evaluated_result,
                                                   sema.getASTContext()));

  clang::APValue ap_value = evaluated_result.Val;
  // TODO: Add support for other types.
  if (ap_value.isLValue()) {
    if (result_expr->EvaluateAsInt(evaluated_result, sema.getASTContext())) {
      ap_value = evaluated_result.Val;
    } else {
      context.TODO(loc_id,
                   "Unsupported: macro evaluated to a non-integer LValue");
      return nullptr;
    }
  }

  switch (ap_value.getKind()) {
    case clang::APValue::Int:
      if (result_expr->getType()->isBooleanType()) {
        return clang::CXXBoolLiteralExpr::Create(
            sema.getASTContext(), ap_value.getInt().getBoolValue(),
            result_expr->getType(), result_expr->getExprLoc());
      }
      return clang::IntegerLiteral::Create(
          sema.getASTContext(), ap_value.getInt(), result_expr->getType(),
          result_expr->getExprLoc());
    case clang::APValue::Float:
      return clang::FloatingLiteral::Create(
          sema.getASTContext(), ap_value.getFloat(),
          /*isExact=*/true, result_expr->getType(), result_expr->getExprLoc());
    default:
      context.TODO(loc_id,
                   "Unsupported: macro evaluated to a constant of type: " +
                       result_expr->getType().getAsString());
      return nullptr;
  }
}

}  // namespace Carbon::Check

Review comment (bug):
This is more of an LLVM style suggestion than a Carbon one, so take it with a grain of salt/see how you feel about it:

```suggestion
    if (!result_expr->EvaluateAsInt(evaluated_result, sema.getASTContext())) {
      context.TODO(loc_id,
                   "Unsupported: macro evaluated to a non-integer LValue");
      return nullptr;
    }
    ap_value = evaluated_result.Val;
```

Code after:
    context.emitter().Emit(loc_id, InCppMacroEvaluation, (*name_str_opt).str());
    return nullptr;
  }

  result_expr = result_expr->IgnoreParenImpCasts();

  if (isa<clang::StringLiteral>(result_expr) ||
      isa<clang::CharacterLiteral>(result_expr) ||
      isa<clang::CXXNullPtrLiteralExpr>(result_expr)) {
    return result_expr;
  }

  clang::Expr::EvalResult evaluated_result;
  CARBON_CHECK(result_expr->EvaluateAsConstantExpr(evaluated_result,
                                                   sema.getASTContext()));

  clang::APValue ap_value = evaluated_result.Val;
  // TODO: Add support for other types.
  if (ap_value.isLValue()) {
    if (!result_expr->EvaluateAsInt(evaluated_result, sema.getASTContext())) {
      context.TODO(loc_id,
                   "Unsupported: macro evaluated to a non-integer LValue");
      return nullptr;
    }
    ap_value = evaluated_result.Val;
  }

  switch (ap_value.getKind()) {
    case clang::APValue::Int:
      if (result_expr->getType()->isBooleanType()) {
        return clang::CXXBoolLiteralExpr::Create(
            sema.getASTContext(), ap_value.getInt().getBoolValue(),
            result_expr->getType(), result_expr->getExprLoc());
      }
      return clang::IntegerLiteral::Create(
          sema.getASTContext(), ap_value.getInt(), result_expr->getType(),
          result_expr->getExprLoc());
    case clang::APValue::Float:
      return clang::FloatingLiteral::Create(
          sema.getASTContext(), ap_value.getFloat(),
          /*isExact=*/true, result_expr->getType(), result_expr->getExprLoc());
    default:
      context.TODO(loc_id,
                   "Unsupported: macro evaluated to a constant of type: " +
                       result_expr->getType().getAsString());
      return nullptr;
  }
}

}  // namespace Carbon::Check