0

I'm trying to store my methodDecl nodes in a map within RecursiveASTVisitor

std::map<std::string, ObjCMethodDecl> ObjCMethodsMap;

Currently I'm storing it like this

virtual bool HandleTopLevelDecl (DeclGroupRef DG) {
  for (DeclGroupRef::iterator i = DG.begin(), e = DG.end(); i != e; ++i) {
    Decl *D = *i;

    if (ObjCMethodDecl *methodDecl = dyn_cast<ObjCMethodDecl>(D)) {
      std::string methodName = methodDecl->getNameAsString();
      ObjCMethodsMap[methodName] = ObjCMethodDecl(*methodDecl);
    }
  }
}

And when I'm trying to use it, I do this

ObjCMethodDecl methodDecl = ObjCMethodsMap["textFieldShouldReturn:"];
Visitor->TraverseDecl(&methodDecl);

This may be more of a C++ question, but am I doing anything wrongly in my way of storing it in reference?

Below is the compilation error message I'm getting. I'm not sure what does it say now because it is referencing to something not within my code and doesn't tell me which line it came from. That's why I thought maybe I did something wrong in C++

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1645:31: error: no matching constructor for initialization of 'clang::ObjCMethodDecl'
            ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
                              ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1572:18: note: in instantiation of function template specialization 'std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, clang::ObjCMethodDecl>, void *> >::construct<clang::ObjCMethodDecl>' requested here
            {__a.construct(__p, _VSTD::forward<_Args>(__args)...);}
                 ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1453:14: note: in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, clang::ObjCMethodDecl>, void *> > >::__construct<clang::ObjCMethodDecl>' requested here
            {__construct(__has_construct<allocator_type, pointer, _Args...>(),
             ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/map:1366:20: note: in instantiation of function template specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::__tree_node<std::__1::__value_type<std::__1::basic_string<char>, clang::ObjCMethodDecl>, void *> > >::construct<clang::ObjCMethodDecl>' requested here
    __node_traits::construct(__na, _VSTD::addressof(__h->__value_.__cc.second));
                   ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/map:1380:29: note: in instantiation of member function 'std::__1::map<std::__1::basic_string<char>, clang::ObjCMethodDecl, std::__1::less<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, clang::ObjCMethodDecl> > >::__construct_node_with_key' requested here
        __node_holder __h = __construct_node_with_key(__k);
                            ^
/Users/jeremy/Desktop/clang-llvm/llvm/tools/clang/tools/extra/myASTChecker/MyASTChecker.cpp:272:55: note: in instantiation of member function 'std::__1::map<std::__1::basic_string<char>, clang::ObjCMethodDecl, std::__1::less<std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>, clang::ObjCMethodDecl> > >::operator[]' requested here
            ObjCMethodDecl methodDecl = ObjCMethodsMap[selectorName];
                                                      ^
/Users/jeremy/Desktop/clang-llvm/llvm/tools/clang/include/clang/AST/DeclObjC.h:113:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 0 were provided
class ObjCMethodDecl : public NamedDecl, public DeclContext {
      ^
/Users/jeremy/Desktop/clang-llvm/llvm/tools/clang/include/clang/AST/DeclObjC.h:113:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 0 were provided
/Users/jeremy/Desktop/clang-llvm/llvm/tools/clang/include/clang/AST/DeclObjC.h:226:3: note: candidate constructor not viable: requires at least 6 arguments, but 0 were provided
  ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
Jeremy Kuah
  • 519
  • 1
  • 6
  • 18
  • `ObjCMethodDecl methodDecl = ObjCMethodsMap[selectorName];` - pretty sure that is where the wheels fell off. According to the error, `ObjCMethodDecl` doesn't have a non-parameterized constructor. – WhozCraig Jul 11 '16 at 03:33
  • Hmm, but isn't that how you retrieve contents from a map? My `selectorName` is taking its value like this `std::string selectorName = objCMsgExpr->getSelector().getAsString();` within `bool VisitObjCMessageExpr (ObjCMessageExpr *objCMsgExpr) {}` – Jeremy Kuah Jul 11 '16 at 03:37
  • Where `selectorName` comes from isn't relevant. And no, that isn't the *only* way to retrieve an item from a map. It is *one* way, and has the additional effect of inserting a default-constructed entry into the map if the given key is not found. Thus the need for a default-constructor. One way or another, an entry will be there using `operator[]`, by "force" if needed. Avoid that (by desire, or in your case, necessity) by using the `find()` method, checking the returned iterator against `end()`, and using `it->second;` to get the mapped value, etc. – WhozCraig Jul 11 '16 at 03:39
  • Didn't think of that, thanks @WhozCraig. I'll try that and report back :) – Jeremy Kuah Jul 11 '16 at 03:42
  • And that, btw, is a complete, admitted, and proud wild-ass-guess, as I have no way of confirming it without at least a clear view of what a `ObjCMethodDecl` looks like, or better still, a [minimal, complete, and verifiable example](https://stackoverflow.com/help/mcve) that exhibits the problem. Best of luck. – WhozCraig Jul 11 '16 at 03:44
  • Seems like `ObjCMethodDecl` doesn't have all required constructors, better solution would be to store the pointer to the actual instance `methodDecl` – AlexDenisov Jul 11 '16 at 05:23
  • @AlexDenisov that's what I did initially, but what I'm trying to achieve now is to store all method nodes from multiple files. When I store the pointer to the actual instance, I'll get seg faults when trying to access the stored methods later on. – Jeremy Kuah Jul 11 '16 at 07:02
  • @WhozCraig I've tried the iterator way and use i->second to access, doesn't work still. I think the issue might have to be how I'm converting my pointer to the instance methodDecl into a reference object (i.e. `ObjCMethodsMap[methodName] = ObjCMethodDecl(*methodDecl);`). Really not sure how can I create a [minimal, complete, and verifiable example](https://stackoverflow.com/help/mcve) for this. – Jeremy Kuah Jul 11 '16 at 07:20
  • 1
    @JeremyKuah In case it wasn't obvious, that `ObjCMethodDecl` is a pointer type rather than a formal class doesn't make this any easier to understand *from our **very** limited vantage point*. Hint: C and C++ programming shouldn't hide pointer types in typedefs, save for two very concrete exceptions: callback function types and opaque library handle types. Regardless, the problem you're now having is different than the one posted (no default constructor). – WhozCraig Jul 11 '16 at 07:25
  • @WhozCraig Let me take a moment to digest all these. Really confused on what's happening, sorry about that. – Jeremy Kuah Jul 11 '16 at 07:40
  • [As simple an example as I can make regarding your first issue](http://ideone.com/YxxLES). Best of luck. You may well be correct and object construction may be a red herring, but without a concrete MCVE, its *very* difficult to know otherwise. – WhozCraig Jul 11 '16 at 07:47

0 Answers0