Skip to content

cannot find deal with ptr that isnt arg #677

@ZuseZ4

Description

@ZuseZ4

I ran into the assertion in one of my projects, here is a minimal reproducer. Further simplifications I tried made the bug disappear.
This mre already works fine under the compiler explorer, however it still fails locally for a few of the latest Enzyme commits.

Command used to compile:
clang++ -O3 -fuse-ld=lld -flto -c mre.cpp && clang++ -O3 -fuse-ld=lld -flto -Wl,--lto-legacy-pass-manager -Wl,-mllvm=-load=/home/drehwald/prog/Enzyme/enzyme/build/Enzyme/LLDEnzyme-14.so -Wl,-mllvm=-enzyme-loose-types -Wl,-mllvm=--enzyme-globals-default-inactive=1 mre.o

#include <cassert>
#include <iterator>
#include <memory>

template <typename Base, typename T>
using disable_if_same_or_derived = typename std::enable_if<
    !std::is_base_of<Base, typename std::decay<T>::type>::value>::type;

// should be replaceable by the std any for c++17 or newer
class any {
public:
  // this is constexpr in the standard
  any() : impl_(nullptr) {}
  any(const any &other) : impl_(other.impl_->clone()) {}
  template <typename ValueType,
            typename = disable_if_same_or_derived<any, ValueType>>
  any(ValueType &&value)
      : impl_(new impl<typename std::decay<ValueType>::type>(
            std::forward<ValueType>(value))) {}
  ~any() = default;

  any &operator=(const any &rhs) {
    impl_ = decltype(impl_)(rhs.impl_->clone());
    return *this;
  }

  const std::type_info &type() const {
      return impl_->type();
  }
  template <typename ValueType>
  typename std::decay<ValueType>::type *value_ptr() {
    return &(impl_->cast_static<typename std::decay<ValueType>::type>()->value);
  }

private:
  template <typename T> struct impl;

  struct impl_base {
    virtual ~impl_base() {}
    virtual impl_base *clone() const = 0;

    virtual const std::type_info &type() const = 0;
    template <typename T> impl<T> *cast_static() {
      return static_cast<impl<T> *>(this);
    }
  };
  template <typename T> struct impl : public impl_base {
    template <typename U> explicit impl(U &&v) : value(std::forward<U>(v)) {}
    impl_base *clone() const override { return new impl{value}; }

    const std::type_info &type() const override { return typeid(T); }

    T value;
  };

  std::unique_ptr<impl_base> impl_;
};

template <typename ValueType>
typename std::decay<ValueType>::type *any_cast(any *operand) {
  assert(operand->type() == typeid(typename std::decay<ValueType>::type));
  return operand->value_ptr<typename std::decay<ValueType>::type>();
}

template <class T1, class T2> struct class_pair : private T1, private T2 {
  class_pair(const T1 &x, const T2 &y) : T1(x), T2(y) {}
};

template <class T1, class T2>
class_pair<T1, T2> make_class_pair(const T1 &x, const T2 &y) {
  return class_pair<T1, T2>(x, y);
}


enum SimpleEnum { EnumVariant };

struct simple_struct {
  static std::shared_ptr<simple_struct> instance() { return nullptr; }
};

struct Baz {};
struct Baz2 {};

using concrete_class_pair = class_pair<Baz, Baz2>;

any bar() {
  any result;
  switch (SimpleEnum::EnumVariant) {
  case SimpleEnum::EnumVariant:
    result = make_class_pair(simple_struct::instance(), Baz2());
    assert(any_cast<concrete_class_pair>(&result) != nullptr);
    break;

  default:
    assert(false && "oh no"); // missed a case?
  }
  return result;
}

int enzyme_dup;

extern double __enzyme_autodiff(void *, int, double &, double &);

double foo(double &d) {
  bar();
  return d;
}

int main(int argc, char *argv[]) {
  double a, b, c;
  double out = __enzyme_autodiff((void *)foo, enzyme_dup, b, c);
  printf("output = %f\n", out);
  return 0;
}

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions