Bugfixes to the expression parser.  Fixes include:

 - If you put a semicolon at the end of an expression,
   this no longer causes the expression parser to
   error out.  This was a two-part fix: first,
   ClangExpressionDeclMap::Materialize now handles
   an empty struct (such as when there is no return
   value); second, ASTResultSynthesizer walks backward
   from the end of the ASTs until it reaches something
   that's not a NullStmt.

 - ClangExpressionVariable now properly byte-swaps when
   printing itself.

 - ClangUtilityFunction now cleans up after itself when
   it's done compiling itself.

 - Utility functions can now use external functions just
   like user expressions.

 - If you end your expression with a statement that does
   not return a value, the expression now runs correctly
   anyway.

Also, added the beginnings of an Objective-C object
validator function, which is neither installed nor used
as yet.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@113789 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/IRDynamicChecks.cpp b/source/Expression/IRDynamicChecks.cpp
index 0f98123..b5a706d 100644
--- a/source/Expression/IRDynamicChecks.cpp
+++ b/source/Expression/IRDynamicChecks.cpp
@@ -8,9 +8,12 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Expression/IRDynamicChecks.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
 
+#include "lldb/Core/ConstString.h"
 #include "lldb/Core/Log.h"
+#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/StackFrame.h"
 
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Function.h"
@@ -23,6 +26,9 @@
 
 static char ID;
 
+static const char valid_pointer_check_name[] = 
+"___clang_valid_pointer_check";
+
 static const char valid_pointer_check_text[] = 
     "extern \"C\" void "
     "___clang_valid_pointer_check (unsigned char *ptr)"
@@ -30,13 +36,57 @@
         "unsigned char val = *ptr;"
     "}";
 
-static const char valid_pointer_check_name[] = 
-    "___clang_valid_pointer_check";
+static const char objc_object_check_name[] =
+    "___clang_objc_object_check";
+
+static bool FunctionExists(const SymbolContext &sym_ctx, const char *name)
+{
+    ConstString name_cs(name);
+
+    SymbolContextList sym_ctxs;
+    
+    sym_ctx.FindFunctionsByName(name_cs, false, sym_ctxs);
+
+    return (sym_ctxs.GetSize() != 0);
+}
+
+static const char *objc_object_check_text(ExecutionContext &exe_ctx)
+{
+    std::string ret;
+    
+    if (!exe_ctx.frame)
+        return "extern \"C\" void ___clang_objc_object_check (unsigned char *obj) { }";
+    
+    const SymbolContext &sym_ctx(exe_ctx.frame->GetSymbolContext(lldb::eSymbolContextEverything));
+
+    if (FunctionExists(sym_ctx, "gdb_object_getClass"))
+    {
+        return  "extern \"C\" void "
+                "___clang_objc_object_check(uint8_t *obj)"
+                "{"
+                    ""
+                "}";
+    }
+    else if (FunctionExists(sym_ctx, "gdb_class_getClass"))
+    {
+        return  "extern \"C\" void "
+                "___clang_objc_object_check(uint8_t *obj)"
+                "{"
+                    ""
+                "}";
+    }
+    else
+    {
+        return  "extern \"C\" void "
+                "___clang_objc_object_check(uint8_t *obj)"
+                "{"
+                    ""
+                "}";
+    }
+}
 
 DynamicCheckerFunctions::DynamicCheckerFunctions ()
 {
-    m_valid_pointer_check.reset(new ClangUtilityFunction(valid_pointer_check_text,
-                                                         valid_pointer_check_name));
 }
 
 DynamicCheckerFunctions::~DynamicCheckerFunctions ()
@@ -47,6 +97,9 @@
 DynamicCheckerFunctions::Install(Stream &error_stream,
                                  ExecutionContext &exe_ctx)
 {
+    m_valid_pointer_check.reset(new ClangUtilityFunction(valid_pointer_check_text,
+                                                         valid_pointer_check_name));
+    
     if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
         return false;
         
@@ -104,7 +157,8 @@
     Instrumenter (llvm::Module &module,
                   DynamicCheckerFunctions &checker_functions) :
         m_module(module),
-        m_checker_functions(checker_functions)
+        m_checker_functions(checker_functions),
+        m_i8ptr_ty(NULL)
     {
     }
     
@@ -222,12 +276,42 @@
         return true;
     }
     
+    //------------------------------------------------------------------
+    /// Build a function pointer for a function with signature 
+    /// void (*)(uint8_t*) with a given address
+    ///
+    /// @param[in] start_address
+    ///     The address of the function.
+    ///
+    /// @return
+    ///     The function pointer, for use in a CallInst.
+    //------------------------------------------------------------------
+    llvm::Value *BuildPointerValidatorFunc(lldb::addr_t start_address)
+    {
+        std::vector<const llvm::Type*> params;
+        
+        const IntegerType *intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
+                                                             (m_module.getPointerSize() == llvm::Module::Pointer64) ? 64 : 32);
+        
+        if (!m_i8ptr_ty)
+            m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
+        
+        params.push_back(m_i8ptr_ty);
+        
+        FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
+        PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
+        Constant *fun_addr_int = ConstantInt::get(intptr_ty, start_address, false);
+        return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
+    }
+    
     typedef std::vector <llvm::Instruction *>   InstVector;
     typedef InstVector::iterator                InstIterator;
     
     InstVector                  m_to_instrument;        ///< List of instructions the inspector found
     llvm::Module               &m_module;               ///< The module which is being instrumented
     DynamicCheckerFunctions    &m_checker_functions;    ///< The dynamic checker functions for the process
+
+    const PointerType          *m_i8ptr_ty;
 };
 
 class ValidPointerChecker : public Instrumenter
@@ -249,21 +333,7 @@
                         PrintValue(inst).c_str());
         
         if (!m_valid_pointer_check_func)
-        {
-            std::vector<const llvm::Type*> params;
-            
-            const IntegerType *intptr_ty = llvm::Type::getIntNTy(m_module.getContext(),
-                                                                 (m_module.getPointerSize() == llvm::Module::Pointer64) ? 64 : 32);
-            
-            m_i8ptr_ty = llvm::Type::getInt8PtrTy(m_module.getContext());
-            
-            params.push_back(m_i8ptr_ty);
-            
-            FunctionType *fun_ty = FunctionType::get(llvm::Type::getVoidTy(m_module.getContext()), params, true);
-            PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
-            Constant *fun_addr_int = ConstantInt::get(intptr_ty, m_checker_functions.m_valid_pointer_check->StartAddress(), false);
-            m_valid_pointer_check_func = ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
-        }
+            m_valid_pointer_check_func = BuildPointerValidatorFunc(m_checker_functions.m_valid_pointer_check->StartAddress());
         
         llvm::Value *dereferenced_ptr;
         
@@ -305,6 +375,104 @@
     }
     
     llvm::Value         *m_valid_pointer_check_func;
+};
+
+class ObjcObjectChecker : public Instrumenter
+{
+public:
+    ObjcObjectChecker(llvm::Module &module,
+                        DynamicCheckerFunctions &checker_functions) :
+        Instrumenter(module, checker_functions),
+        m_objc_object_check_func(NULL)
+    {
+    }
+private:
+    bool InstrumentInstruction(llvm::Instruction *inst)
+    {
+        CallInst *call_inst = dyn_cast<CallInst>(inst);
+        
+        if (!call_inst)
+            return false; // this really should be true, because otherwise InspectInstruction wouldn't have registered it
+        
+        if (!m_objc_object_check_func)
+            m_objc_object_check_func = BuildPointerValidatorFunc(m_checker_functions.m_objc_object_check->StartAddress());
+        
+        llvm::Value *target_object;
+        
+        // id objc_msgSend(id theReceiver, SEL theSelector, ...)
+        
+        target_object = call_inst->getArgOperand(0);
+        
+        // Insert an instruction to cast the receiver id to int8_t*
+        
+        BitCastInst *bit_cast = new BitCastInst(target_object,
+                                                m_i8ptr_ty,
+                                                "",
+                                                inst);
+        
+        // Insert an instruction to call the helper with the result
+        
+        SmallVector <llvm::Value*, 1> args;
+        args.push_back(bit_cast);
+        
+        CallInst::Create(m_objc_object_check_func, 
+                         args.begin(),
+                         args.end(),
+                         "",
+                         inst);
+        
+        return true;
+    }
+    
+    bool InspectInstruction(llvm::Instruction &i)
+    {
+        lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+        CallInst *call_inst = dyn_cast<CallInst>(&i);
+        
+        if (call_inst)
+        {
+            // This metadata is set by IRForTarget::MaybeHandleCall().
+            
+            MDNode *metadata = call_inst->getMetadata("lldb.call.realName");
+                        
+            if (!metadata)
+                return true;
+            
+            if (metadata->getNumOperands() != 1)
+            {
+                if (log)
+                    log->Printf("Function call metadata has %d operands for [%p] %s", metadata->getNumOperands(), call_inst, PrintValue(call_inst).c_str());
+                return false;
+            }
+            
+            ConstantArray *real_name = dyn_cast<ConstantArray>(metadata->getOperand(0));
+            
+            if (!real_name)
+            {
+                if (log)
+                    log->Printf("Function call metadata is not a ConstantArray for [%p] %s", call_inst, PrintValue(call_inst).c_str());
+                return false;
+            }
+            
+            if (!real_name->isString())
+            {
+                if (log)
+                    log->Printf("Function call metadata is not a string for [%p] %s", call_inst, PrintValue(call_inst).c_str());
+                return false;
+            }
+            
+            if (log)
+                log->Printf("Found call to %s: %s\n", real_name->getAsString().c_str(), PrintValue(call_inst).c_str());
+            
+            if (real_name->getAsString().find("objc_msgSend") != std::string::npos)
+                RegisterInstruction(i);
+        }
+        
+        return true;
+    }
+    
+    llvm::Value         *m_objc_object_check_func;
     const PointerType   *m_i8ptr_ty;
 };
 
@@ -343,6 +511,16 @@
     if (!vpc.Instrument())
         return false;
     
+    /*
+    ObjcObjectChecker ooc(M, m_checker_functions);
+    
+    if (!ooc.Inspect(*function))
+        return false;
+    
+    if (!ooc.Instrument())
+        return false;
+    */
+    
     if (log)
     {
         std::string s;