Unverified Commit 8b258206 authored by Timm Baeder's avatar Timm Baeder Committed by GitHub
Browse files

[clang][bytecode] Diagnose copying empty mutable unions (#195529)

We had a special case for copy/move ctors of empty unions. Remove that.
Everything else is just so we don't regress diagnostics.
parent a9a899db
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -6809,12 +6809,13 @@ bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
    return false;
  bool IsUnion = R->isUnion();

  // Union copy and move ctors are special.
  if (IsUnion && Ctor->isCopyOrMoveConstructor()) {
    LocOverrideScope<Emitter> LOS(this, SourceInfo{});

    if (R->getNumFields() == 0)
      return this->emitRetVoid(Ctor);
    // union copy and move ctors are special.
    // No special case for NumFields == 0 here, so the Memcpy op
    // below also does its checks in those cases.

    assert(cast<CompoundStmt>(Ctor->getBody())->body_empty());
    if (!this->emitThis(Ctor))
      return false;
+2 −1
Original line number Diff line number Diff line
@@ -29,7 +29,8 @@ Function::Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
    Constexpr = F->isConstexpr();
    if (const auto *CD = dyn_cast<CXXConstructorDecl>(F)) {
      Virtual = CD->isVirtual();
      Kind = FunctionKind::Ctor;
      Kind = CD->isCopyOrMoveConstructor() ? FunctionKind::CopyOrMoveCtor
                                           : FunctionKind::Ctor;
    } else if (const auto *CD = dyn_cast<CXXDestructorDecl>(F)) {
      Virtual = CD->isVirtual();
      Kind = FunctionKind::Dtor;
+8 −1
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ public:
  enum class FunctionKind {
    Normal,
    Ctor,
    CopyOrMoveCtor,
    Dtor,
    LambdaStaticInvoker,
    LambdaCallOperator,
@@ -185,7 +186,13 @@ public:
  bool isConstexpr() const { return Constexpr; }

  /// Checks if the function is a constructor.
  bool isConstructor() const { return Kind == FunctionKind::Ctor; }
  bool isConstructor() const {
    return Kind == FunctionKind::Ctor || Kind == FunctionKind::CopyOrMoveCtor;
  }
  bool isCopyOrMoveConstructor() const {
    return Kind == FunctionKind::CopyOrMoveCtor;
  }

  /// Checks if the function is a destructor.
  bool isDestructor() const { return Kind == FunctionKind::Dtor; }
  /// Checks if the function is copy or move operator.
+10 −0
Original line number Diff line number Diff line
@@ -910,6 +910,8 @@ static bool CheckInvoke(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
      return false;
    if (!IsCtorDtor && !CheckLifetime(S, OpPC, Ptr, AK_MemberCall))
      return false;
    if (!CheckMutable(S, OpPC, Ptr))
      return false;
  }
  return true;
}
@@ -1781,6 +1783,14 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
      if (!CheckInvoke(S, OpPC, ThisPtr,
                       Func->isConstructor() || Func->isDestructor()))
        return cleanup();

      if (Func->isCopyOrMoveOperator() || Func->isCopyOrMoveConstructor()) {
        const Pointer &RVOPtr =
            S.Stk.peek<Pointer>(ThisOffset - align(sizeof(Pointer)));
        if (!CheckInvoke(S, OpPC, RVOPtr, /*IsCtorDtor=*/true))
          return cleanup();
      }

      if (!Func->isConstructor() && !Func->isDestructor() &&
          !CheckActive(S, OpPC, ThisPtr, AK_MemberCall))
        return false;
+0 −5
Original line number Diff line number Diff line
@@ -150,11 +150,6 @@ static bool shouldSkipInBacktrace(const Function *F) {
      MD && MD->getParent()->isAnonymousStructOrUnion())
    return true;

  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FD);
      Ctor && Ctor->isDefaulted() && Ctor->isTrivial() &&
      Ctor->isCopyOrMoveConstructor() && Ctor->inits().empty())
    return true;

  return false;
}

Loading