// getFullyQualifiedType does not support function pointers in clang=9.0.0. As a result the type
// of foo's argument is not fully qualified in woven code. This result in invalid woven code.

// See https://bugs.llvm.org/show_bug.cgi?id=41210

// See Bug568 testcase for more type printing tests

namespace N {
   class N {
        class C {
            class C2 { };
        };
    };

    class C { 
     public:
      class C2 { };
    };

    void foo(C::C2& (*a)(C*, C::C2&)) { }
    
    void bar(int i) {
      // To successfully weave this call, ::N::C is necessary
      foo(nullptr);
    }

    template<typename T1>
    class B {
        void mf(T1 ma) { }
    };

    template<typename T1>
    void goocar(T1 a) { }
}

int main() {
    // Indirectly call foo in a scope where N::C names the wrong class and ::N::C is absolutely necessary.
    N::bar(42);

    // In this scope, N::C is sufficient (i.e., the global namespace specifier is not necessary). Interestingly, also N's specifier is missing.
    N::foo(nullptr);

    // This must also work (function pointer type as template argument type). With clang=9.0.0 getFullyQualifiedType *removes* all specifier from
    // the function pointer type inside the template argument.
    using namespace N;
    B<C::C2& (*)(C*, C::C2&)> b;
    goocar<>(b);
}

aspect Asp {
  advice call("% ...::%(...)") || builtin("% ...::%(...)") || set("% ...::%") : before() {
    tjp->arg<0>(); // All matchable functions have exactly one argument.
  }
  
  advice get("% ...::%") : around() {
    tjp->proceed();
  }
};
