Added the ability to restrict breakpoints by function name, function regexp, selector
etc to specific source files.
Added SB API's to specify these source files & also more than one module.
Added an "exact" option to CompileUnit's FindLineEntry API.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@140362 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Breakpoint/BreakpointResolverFileRegex.cpp b/source/Breakpoint/BreakpointResolverFileRegex.cpp
index 238c370..e4b596a 100644
--- a/source/Breakpoint/BreakpointResolverFileRegex.cpp
+++ b/source/Breakpoint/BreakpointResolverFileRegex.cpp
@@ -29,11 +29,9 @@
 BreakpointResolverFileRegex::BreakpointResolverFileRegex
 (
     Breakpoint *bkpt,
-    const FileSpec &file_spec,
     RegularExpression &regex
 ) :
     BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver),
-    m_file_spec (file_spec),
     m_regex (regex)
 {
 }
@@ -60,62 +58,58 @@
 
     CompileUnit *cu = context.comp_unit;
     FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu));
-    if (cu_file_spec == m_file_spec
-        || (!m_file_spec.GetDirectory() && cu_file_spec.GetFilename() == m_file_spec.GetFilename()))
+    std::vector<uint32_t> line_matches;
+    context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches); 
+    uint32_t num_matches = line_matches.size();
+    for (int i = 0; i < num_matches; i++)
     {
-        std::vector<uint32_t> line_matches;
-        context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches); 
-        uint32_t num_matches = line_matches.size();
-        for (int i = 0; i < num_matches; i++)
+        uint32_t start_idx = 0;
+        bool exact = false;
+        while (1)
         {
-            uint32_t start_idx = 0;
-            while (1)
-            {
-                LineEntry line_entry;
+            LineEntry line_entry;
+        
+            // Cycle through all the line entries that might match this one:
+            start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, exact, &line_entry);
+            if (start_idx == UINT32_MAX)
+                break;
+            exact = true;
+            start_idx++;
             
-                // Cycle through all the line entries that might match this one:
-                start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, &line_entry);
-                if (start_idx == UINT32_MAX)
-                    break;
-                start_idx++;
-                
-                Address line_start = line_entry.range.GetBaseAddress();
-                if (line_start.IsValid())
+            Address line_start = line_entry.range.GetBaseAddress();
+            if (line_start.IsValid())
+            {
+                if (filter.AddressPasses(line_start))
                 {
-                    if (filter.AddressPasses(line_start))
+                    BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
+                    if (log && bp_loc_sp && !m_breakpoint->IsInternal())
                     {
-                        BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start));
-                        if (log && bp_loc_sp && !m_breakpoint->IsInternal())
-                        {
-                            StreamString s;
-                            bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
-                            log->Printf ("Added location: %s\n", s.GetData());
-                        }
-                    }
-                    else if (log)
-                    {
-                        log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass filter.\n",
-                                     line_start.GetFileAddress(),
-                                     m_file_spec.GetFilename().AsCString("<Unknown>"),
-                                     line_matches[i]);
+                        StreamString s;
+                        bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose);
+                        log->Printf ("Added location: %s\n", s.GetData());
                     }
                 }
-                else
+                else if (log)
                 {
-                    if (log)
-                        log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
-                                     line_start.GetFileAddress(),
-                                     m_file_spec.GetFilename().AsCString("<Unknown>"),
-                                     line_matches[i]);
+                    log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass filter.\n",
+                                 line_start.GetFileAddress(),
+                                 cu_file_spec.GetFilename().AsCString("<Unknown>"),
+                                 line_matches[i]);
                 }
-
             }
+            else
+            {
+                if (log)
+                    log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n",
+                                 line_start.GetFileAddress(),
+                                 cu_file_spec.GetFilename().AsCString("<Unknown>"),
+                                 line_matches[i]);
+            }
+
         }
-        assert (m_breakpoint != NULL);
-        LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
-        
-        
     }
+    assert (m_breakpoint != NULL);        
+
     return Searcher::eCallbackReturnContinue;
 }
 
@@ -128,7 +122,7 @@
 void
 BreakpointResolverFileRegex::GetDescription (Stream *s)
 {
-    s->Printf ("file ='%s', regular expression = \"%s\"", m_file_spec.GetFilename().AsCString(), m_regex.GetText());
+    s->Printf ("source regex = \"%s\"", m_regex.GetText());
 }
 
 void
diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp
index 141a15b..4288909 100644
--- a/source/Breakpoint/BreakpointResolverName.cpp
+++ b/source/Breakpoint/BreakpointResolverName.cpp
@@ -161,16 +161,22 @@
     
     const bool include_symbols = false;
     const bool append = false;
+    bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0;
+
     switch (m_match_type)
     {
         case Breakpoint::Exact:
             if (context.module_sp)
             {
-                if (context.module_sp->FindFunctions (m_func_name, 
+                uint32_t num_functions = context.module_sp->FindFunctions (m_func_name, 
                                                       m_func_name_type_mask, 
                                                       include_symbols, 
                                                       append, 
-                                                      func_list) == 0)
+                                                      func_list);
+                // If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain
+                // symbols, since all the ones from a set compilation unit will have been found above already.
+                
+                if (num_functions == 0 && !filter_by_cu)
                 {
                     if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
                         context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
@@ -180,7 +186,8 @@
         case Breakpoint::Regexp:
             if (context.module_sp)
             {
-                context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
+                if (!filter_by_cu)
+                    context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list);
                 context.module_sp->FindFunctions (m_regex, 
                                                   include_symbols, 
                                                   append, 
@@ -192,7 +199,26 @@
                 log->Warning ("glob is not supported yet.");
             break;
     }
-    
+
+    // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point.
+    if (filter_by_cu)
+    {
+        uint32_t num_functions = func_list.GetSize();
+        
+        for (size_t idx = 0; idx < num_functions; idx++)
+        {
+            SymbolContext sc;
+            func_list.GetContextAtIndex(idx, sc);
+            if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit))
+            {
+                func_list.RemoveContextAtIndex(idx);
+                num_functions--;
+                idx--;
+            }
+        }
+    }
+                
+
     if (!m_basename_filter.empty())
     {
         // Filter out any matches whose names don't contain the basename filter