Added the ability to create an objective C method for an objective C 
interface in ClangASTContext. Also added two bool returning functions that
indicated if an opaque clang qual type is a CXX class type, and if it is an
ObjC class type.

Objective C classes now will get their methods added lazily as they are
encountered. The reason for this is currently, unlike C++, the 
DW_TAG_structure_type and owns the ivars, doesn't not also contain the
member functions. This means when we parse the objective C class interface
we either need to find all functions whose names start with "+[CLASS_NAME"
or "-[CLASS_NAME" and add them all to the class, or when we parse each objective
C function, we slowly add it to the class interface definition. Since objective
C's class doesn't change internal bits according to whether it has certain types
of member functions (like C++ does if it has virtual functions, or if it has
user ctors/dtors), I currently chose to lazily populate the class when each
functions is parsed. Another issue we run into with ObjC method declarations
is the "self" and "_cmd" implicit args are not marked as artificial in the
DWARF (DW_AT_artifical), so we currently have to look for the parameters by
name if we are trying to omit artificial function args if the language of the
compile unit is ObjC or ObjC++.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@114722 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index 7debcb6..287ae76 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -811,7 +811,9 @@
     const char *name,
     void *method_opaque_type,
     lldb::AccessType access,
-    bool is_virtual
+    bool is_virtual,
+    bool is_static,
+    bool is_inline
 )
 {
     if (!record_opaque_type || !method_opaque_type || !name)
@@ -824,51 +826,56 @@
     assert(identifier_table);
     
     QualType record_qual_type(QualType::getFromOpaquePtr(record_opaque_type));
-    clang::Type *record_type(record_qual_type.getTypePtr());
+
+    clang::Type *clang_type(record_qual_type.getTypePtr());
     
-    if (!record_type)
+    if (clang_type == NULL)
         return NULL;
     
-    RecordType *record_recty(dyn_cast<RecordType>(record_type));
+    RecordType *record_clang_type(dyn_cast<RecordType>(clang_type));
     
-    if (!record_recty)
+    if (record_clang_type == NULL)
         return NULL;
     
-    RecordDecl *record_decl = record_recty->getDecl();
+    RecordDecl *record_decl = record_clang_type->getDecl();
     
-    if (!record_decl)
+    if (record_decl == NULL)
         return NULL;
     
     CXXRecordDecl *cxx_record_decl = dyn_cast<CXXRecordDecl>(record_decl);
     
-    if (!cxx_record_decl)
+    if (cxx_record_decl == NULL)
         return NULL;
     
-    QualType method_qual_type(QualType::getFromOpaquePtr(method_opaque_type));
+    QualType method_qual_type (QualType::getFromOpaquePtr (method_opaque_type));
     
-    CXXMethodDecl *cxx_method_decl = CXXMethodDecl::Create(*ast_context,
-                                                           cxx_record_decl,
-                                                           DeclarationNameInfo(DeclarationName(&identifier_table->get(name)), SourceLocation()),
-                                                           method_qual_type,
-                                                           NULL);
+    CXXMethodDecl *cxx_method_decl = CXXMethodDecl::Create (*ast_context,
+                                                            cxx_record_decl,
+                                                            DeclarationNameInfo (DeclarationName (&identifier_table->get(name)), SourceLocation()),
+                                                            method_qual_type,
+                                                            NULL, // TypeSourceInfo *
+                                                            is_static,
+                                                            SC_None,
+                                                            is_inline);
     
-    clang::AccessSpecifier AS = ConvertAccessTypeToAccessSpecifier(access);
     
-    cxx_method_decl->setAccess(AS);
-    cxx_method_decl->setVirtualAsWritten(is_virtual);
+    clang::AccessSpecifier access_specifier = ConvertAccessTypeToAccessSpecifier (access);
+    
+    cxx_method_decl->setAccess (access_specifier);
+    cxx_method_decl->setVirtualAsWritten (is_virtual);
     
     // Populate the method decl with parameter decls
     clang::Type *method_type(method_qual_type.getTypePtr());
     
-    if (!method_type)
+    if (method_type == NULL)
         return NULL;
     
-    FunctionProtoType *method_funprototy(dyn_cast<FunctionProtoType>(method_type));
+    FunctionProtoType *method_function_prototype (dyn_cast<FunctionProtoType>(method_type));
     
-    if (!method_funprototy)
+    if (!method_function_prototype)
         return NULL;
     
-    unsigned int num_params = method_funprototy->getNumArgs();
+    unsigned int num_params = method_function_prototype->getNumArgs();
     
     ParmVarDecl *params[num_params];
     
@@ -876,20 +883,20 @@
          param_index < num_params;
          ++param_index)
     {
-        params[param_index] = ParmVarDecl::Create(*ast_context,
-                                                  cxx_method_decl,
-                                                  SourceLocation(),
-                                                  NULL, // anonymous
-                                                  method_funprototy->getArgType(param_index), 
-                                                  NULL,
-                                                  SC_Auto, 
-                                                  SC_Auto,
-                                                  NULL); 
+        params[param_index] = ParmVarDecl::Create (*ast_context,
+                                                   cxx_method_decl,
+                                                   SourceLocation(),
+                                                   NULL, // anonymous
+                                                   method_function_prototype->getArgType(param_index), 
+                                                   NULL,
+                                                   SC_None, 
+                                                   SC_None,
+                                                   NULL); 
     }
     
-    cxx_method_decl->setParams(params, num_params);
+    cxx_method_decl->setParams (params, num_params);
     
-    cxx_record_decl->addDecl(cxx_method_decl);
+    cxx_record_decl->addDecl (cxx_method_decl);
     
     return cxx_method_decl;
 }
@@ -988,14 +995,14 @@
             ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(clang_type);
             if (objc_class_type)
             {
-                bool isSynthesized = false;
+                bool is_synthesized = false;
                 ClangASTContext::AddObjCClassIVar (ast_context,
                                                    record_clang_type,
                                                    name,
                                                    field_type,
                                                    access,
                                                    bitfield_bit_size,
-                                                   isSynthesized);
+                                                   is_synthesized);
             }
         }
     }
@@ -1250,7 +1257,7 @@
     void *ivar_opaque_type, 
     AccessType access, 
     uint32_t bitfield_bit_size, 
-    bool isSynthesized
+    bool is_synthesized
 )
 {
     if (class_opaque_type == NULL || ivar_opaque_type == NULL)
@@ -1289,7 +1296,7 @@
                                                             NULL, // TypeSourceInfo *
                                                             ConvertAccessTypeToObjCIvarAccessControl (access),
                                                             bit_width,
-                                                            isSynthesized);
+                                                            is_synthesized);
                 
                 if (field)
                 {
@@ -1334,7 +1341,132 @@
     }
     return false;            
 }
+
+clang::ObjCMethodDecl *
+ClangASTContext::AddMethodToObjCObjectType
+(
+    clang::ASTContext *ast_context,
+    void *class_opaque_type, 
+    const char *name,  // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]")
+    void *method_opaque_type,
+    lldb::AccessType access
+)
+{
+    if (class_opaque_type == NULL || method_opaque_type == NULL)
+        return NULL;
+
+    IdentifierTable *identifier_table = &ast_context->Idents;
+
+    assert (ast_context != NULL);
+    assert (identifier_table != NULL);
+
+    QualType class_qual_type(QualType::getFromOpaquePtr(class_opaque_type));
+
+    clang::Type *class_type = class_qual_type.getTypePtr();
+    if (class_type == NULL)
+        return NULL;
+
+    ObjCObjectType *objc_class_type = dyn_cast<ObjCObjectType>(class_type);
+
+    if (objc_class_type == NULL)
+        return NULL;
+
+    ObjCInterfaceDecl *class_interface_decl = objc_class_type->getInterface();
+            
+    if (class_interface_decl == NULL)
+        return NULL;
     
+    const char *selector_start = ::strchr (name, ' ');
+    if (selector_start == NULL)
+        return NULL;
+    
+    selector_start++;
+    if (!(::isalpha (selector_start[0]) || selector_start[0] == '_'))
+        return NULL;
+    llvm::SmallVector<IdentifierInfo *, 12> selector_idents;
+
+    size_t len;
+    const char *start;
+    for (start = selector_start, len = ::strcspn(start, ":]");
+         start && *start != '\0' && *start != ']';
+         start += len + 1)
+    {
+        selector_idents.push_back (&identifier_table->get (StringRef (start, len)));
+    }
+
+    
+    if (selector_idents.size() == 0)
+        return 0;
+
+    clang::Selector method_selector = ast_context->Selectors.getSelector (selector_idents.size(),
+                                                                          selector_idents.data());
+    
+    QualType method_qual_type (QualType::getFromOpaquePtr (method_opaque_type));
+
+    // Populate the method decl with parameter decls
+    clang::Type *method_type(method_qual_type.getTypePtr());
+    
+    if (method_type == NULL)
+        return NULL;
+    
+    FunctionProtoType *method_function_prototype (dyn_cast<FunctionProtoType>(method_type));
+    
+    if (!method_function_prototype)
+        return NULL;
+    
+
+    bool is_variadic = false;
+    bool is_synthesized = false;
+    bool is_defined = false;
+    ObjCMethodDecl::ImplementationControl imp_control = ObjCMethodDecl::None;
+
+    const unsigned num_args = method_function_prototype->getNumArgs();
+
+    ObjCMethodDecl *objc_method_decl = ObjCMethodDecl::Create (*ast_context,
+                                                               SourceLocation(), // beginLoc,
+                                                               SourceLocation(), // endLoc, 
+                                                               method_selector,
+                                                               method_function_prototype->getResultType(),
+                                                               NULL, // TypeSourceInfo *ResultTInfo,
+                                                               GetDeclContextForType (class_opaque_type),
+                                                               name[0] == '-',
+                                                               is_variadic,
+                                                               is_synthesized,
+                                                               is_defined,
+                                                               imp_control,
+                                                               num_args);
+
+
+    if (objc_method_decl == NULL)
+        return NULL;
+
+    if (num_args > 0)
+    {
+        llvm::SmallVector<ParmVarDecl *, 12> params;
+            
+        for (int param_index = 0; param_index < num_args; ++param_index)
+        {
+            params.push_back (ParmVarDecl::Create (*ast_context,
+                                                   objc_method_decl,
+                                                   SourceLocation(),
+                                                   NULL, // anonymous
+                                                   method_function_prototype->getArgType(param_index), 
+                                                   NULL,
+                                                   SC_Auto, 
+                                                   SC_Auto,
+                                                   NULL));
+        }
+        
+        objc_method_decl->setMethodParams(*ast_context, params.data(), params.size(), num_args);
+    }
+    
+    class_interface_decl->addDecl (objc_method_decl);
+
+
+    return objc_method_decl;
+}
+
+
 
 #pragma mark Aggregate Types
 
@@ -3044,6 +3176,32 @@
     return false;
 }
 
+bool
+ClangASTContext::IsCXXClassType (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        if (qual_type->getAsCXXRecordDecl() != NULL)
+            return true;
+    }
+    return false;
+}
+
+bool 
+ClangASTContext::IsObjCClassType (void *clang_type)
+{
+    if (clang_type)
+    {
+        QualType qual_type (QualType::getFromOpaquePtr(clang_type));
+        if (qual_type->isObjCObjectOrInterfaceType())
+            return true;
+    }
+    return false;
+}
+
+
+
 
 bool
 ClangASTContext::IsCStringType (void *clang_type, uint32_t &length)