diff --git a/common/drc_rules.keywords b/common/drc_rules.keywords
index 664b79affa..49e8585474 100644
--- a/common/drc_rules.keywords
+++ b/common/drc_rules.keywords
@@ -26,3 +26,11 @@ track_width
 version
 via
 zone
+edge_clearance
+hole_clearance
+courtyard_clearance
+silk_to_pad
+silk_to_silk
+match_lengths
+match_skew
+diff_pair
\ No newline at end of file
diff --git a/qa/drc_proto/drc_engine.cpp b/qa/drc_proto/drc_engine.cpp
index 00562e02cc..f3b12ca160 100644
--- a/qa/drc_proto/drc_engine.cpp
+++ b/qa/drc_proto/drc_engine.cpp
@@ -48,8 +48,15 @@ test::DRC_ENGINE::DRC_ENGINE( BOARD* aBoard, BOARD_DESIGN_SETTINGS *aSettings )
 
 test::DRC_ENGINE::~DRC_ENGINE()
 {
-    for( DRC_ITEM* item : m_drcItems )
-        delete item;
+}
+
+test::DRC_REPORT::~DRC_REPORT()
+{
+    for( auto item : m_entries )
+    {
+        if ( item.m_marker )
+            delete item.m_marker;
+    }
 }
 
 /*void test::DRC_ENGINE::AddMarker( MARKER_PCB* aMarker )
@@ -111,31 +118,6 @@ void test::DRC_ENGINE::inferImplicitRules()
 }
 
 
-static const int drc_debug_level = 0;
-
-void test::drc_dbg( int level, const char* fmt, ... )
-{
-#ifdef DEBUG
-    long dlevel = drc_debug_level;
-    wxString dlevelstr;
-    if( wxGetEnv( "DRC_DEBUG_LEVEL", &dlevelstr ) )
-    {
-        dlevelstr.ToLong( &dlevel );
-    }
-    
-
-    if(level < dlevel) // fixme: tom's debugging.
-    {
-        va_list ap;
-        va_start( ap, fmt );
-        fprintf( stderr, "drc: " );
-        vfprintf( stderr, fmt, ap );
-        va_end( ap );
-    }
-#endif
-}
-
-
 bool test::DRC_ENGINE::CompileRules()
 {
     ReportAux( wxString::Format( "Compiling Rules (%d rules, %d conditions): ", m_rules.size(), m_ruleConditions.size() ) );
@@ -176,7 +158,7 @@ bool test::DRC_ENGINE::CompileRules()
                            {
                                 rcons->conditions.push_back( condition );
                                 
-                                bool compileOk = condition->Compile( &NULL_REPORTER::GetInstance() );
+                                bool compileOk = condition->Compile();
 
                                 ReportAux( wxString::Format( "       |- condition: '%s' compile: %s", condition->m_TargetRuleName, compileOk ? "OK" : "ERROR") );
 
@@ -198,6 +180,7 @@ void test::DRC_ENGINE::RunTests( )
 {
     //m_largestClearance = m_designSettings->GetBiggestClearanceValue();
 
+    m_drcReport.reset( new test::DRC_REPORT );
     m_testProviders = DRC_TEST_PROVIDER_REGISTRY::Instance().GetTestProviders();
 
     for( auto provider : m_testProviders )
@@ -268,22 +251,25 @@ test::DRC_RULE* test::DRC_ENGINE::EvalRulesForItems( test::DRC_RULE_ID_T ruleID,
 }
 
 
-void test::DRC_ENGINE::Report( DRC_ITEM* aItem, ::MARKER_PCB *aMarker )
+void test::DRC_ENGINE::Report( std::shared_ptr<DRC_ITEM> aItem, ::MARKER_PCB *aMarker )
 {
-    m_drcItems.push_back( aItem );
-    m_markers.push_back( aMarker );
+    m_drcReport->AddItem( aItem, aMarker );
+    
     if( m_reporter )
     {
         m_reporter->Report ( wxString::Format( "Test '%s': violation of rule '%s' : %s (code %d)", 
-         aItem->GetViolatingTest()->GetName(),
-         aItem->GetViolatingRule()->GetName(),
-         aItem->GetErrorMessage(),
-         aItem->GetErrorCode() ), RPT_SEVERITY_ERROR /* fixme */ );
-         if( aMarker )
-         {
-            m_reporter->Report( wxString::Format( "  |- violating position (%d, %d)", aMarker->GetPos().x, aMarker->GetPos().y ),
-            RPT_SEVERITY_ERROR /* fixme */  );
-         }
+        aItem->GetViolatingTest()->GetName(),
+        aItem->GetViolatingRule()->GetName(),
+        aItem->GetErrorMessage(),
+        aItem->GetErrorCode() ), RPT_SEVERITY_ERROR /* fixme */ );
+
+        wxString violatingItemsStr = "Violating items: ";
+
+        if( aMarker )
+        {
+           m_reporter->Report( wxString::Format( "  |- violating position (%d, %d)", aMarker->GetPos().x, aMarker->GetPos().y ),
+           RPT_SEVERITY_ERROR /* fixme */  );
+        }
     }
 }
 
@@ -358,3 +344,28 @@ bool test::DRC_ENGINE::HasCorrectRulesForId( test::DRC_RULE_ID_T ruleID )
     return m_ruleMap[ruleID]->defaultRule != nullptr;
 }
 
+
+bool test::DRC_ENGINE::QueryWorstConstraint( test::DRC_RULE_ID_T aRuleId, test::DRC_CONSTRAINT& aConstraint, test::DRC_CONSTRAINT_QUERY_T aQueryType )
+{
+    if( aQueryType == DRCCQ_LARGEST_MINIMUM )
+    {
+        int worst = 0;
+        for( auto rule : QueryRulesById( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE ) )
+        {
+            if( rule->GetConstraint().m_Value.HasMin() )
+            {
+                int current = rule->GetConstraint().m_Value.Min();
+
+                if( current > worst )
+                {
+                    worst = current;
+                    aConstraint = rule->GetConstraint();
+                }
+            }
+        }
+
+        return worst > 0;
+    }
+
+    return false;
+}
diff --git a/qa/drc_proto/drc_engine.h b/qa/drc_proto/drc_engine.h
index e3f65a0bad..364a438e54 100644
--- a/qa/drc_proto/drc_engine.h
+++ b/qa/drc_proto/drc_engine.h
@@ -53,6 +53,13 @@ class NETLIST;
 class PROGRESS_REPORTER;
 class REPORTER;
 
+//#ifdef DEBUG
+#define drc_dbg(level, fmt, ...) \
+    wxLogTrace( "drc_proto", fmt, __VA_ARGS__ );
+//#else
+//#define drc_dbg(level, fmt, ...)
+//#endif
+
 namespace test
 {
 
@@ -62,6 +69,12 @@ class DRC_RULE;
 class DRC_TEST_PROVIDER;
 class DRC_CONSTRAINT;
 
+enum DRC_CONSTRAINT_QUERY_T
+{
+    DRCCQ_LARGEST_MINIMUM = 0
+    // fixme: more to come I guess...
+};
+
 /// DRC error codes:
 enum PCB_DRC_CODE
 {
@@ -103,6 +116,33 @@ enum PCB_DRC_CODE
     DRCE_LAST = DRCE_UNRESOLVED_VARIABLE
 };
 
+class DRC_REPORT
+{
+public:
+    struct ENTRY
+    {
+        std::shared_ptr<DRC_ITEM> m_item;
+        ::MARKER_PCB* m_marker;
+    };
+
+    typedef std::vector<ENTRY> ENTRIES;
+
+    DRC_REPORT() {};
+    ~DRC_REPORT();
+
+    void AddItem( std::shared_ptr<DRC_ITEM> aItem, ::MARKER_PCB *aMarker = nullptr)
+    {
+        ENTRY ent;
+        ent.m_item = aItem;
+        ent.m_marker = aMarker;
+        m_entries.push_back(ent);
+    }
+
+    const ENTRIES& GetReportEntries() const { return m_entries; };
+
+private:
+    ENTRIES m_entries;
+};
 
 /**
  * Design Rule Checker object that performs all the DRC tests.  The output of
@@ -157,13 +197,19 @@ public:
 
     bool CompileRules();
 
-    void Report( DRC_ITEM* aItem, ::MARKER_PCB *Marker );
+    void Report( std::shared_ptr<DRC_ITEM> aItem, ::MARKER_PCB *Marker );
     void ReportProgress( double aProgress );
     void ReportStage ( const wxString& aStageName, int index, int total );
     void ReportAux( const wxString& aStr );
 
+    std::shared_ptr<DRC_REPORT> GetReport() const { return m_drcReport; }
+
+    bool QueryWorstConstraint( DRC_RULE_ID_T aRuleId, test::DRC_CONSTRAINT& aConstraint, DRC_CONSTRAINT_QUERY_T aQueryType );
+
+
 private:
 
+
     void freeCompiledRules();
 
     struct RULE_WITH_CONDITIONS
@@ -187,13 +233,13 @@ private:
 
     BOARD_DESIGN_SETTINGS* m_designSettings;
     BOARD*                 m_board;
-    std::vector<DRC_ITEM*> m_drcItems;
+
+    std::shared_ptr<DRC_REPORT> m_drcReport;
 
     std::vector<DRC_RULE_CONDITION*> m_ruleConditions;
     std::vector<DRC_RULE*>           m_rules;
     std::vector<DRC_TEST_PROVIDER*>  m_testProviders;
     std::unordered_map<EDA_ITEM*, RULE_SET*> m_implicitRules;
-    std::vector<::MARKER_PCB*>       m_markers;
     RULE_MAP m_ruleMap;
     REPORTER* m_reporter;
     PROGRESS_REPORTER* m_progressReporter;
@@ -201,8 +247,6 @@ private:
     // condition -> rule -> provider
 };
 
-void drc_dbg( int level, const char* fmt, ... );
-
 }; // namespace test
 
 #endif // DRC_H
diff --git a/qa/drc_proto/drc_item.cpp b/qa/drc_proto/drc_item.cpp
index 41ef7f602d..1c50eca9e7 100644
--- a/qa/drc_proto/drc_item.cpp
+++ b/qa/drc_proto/drc_item.cpp
@@ -196,55 +196,58 @@ std::vector<std::reference_wrapper<RC_ITEM>> test::DRC_ITEM::allItemTypes( {
         } );
 
 
-test::DRC_ITEM* test::DRC_ITEM::Create( int aErrorCode )
+std::shared_ptr<test::DRC_ITEM> test::DRC_ITEM::Create( int aErrorCode )
 {
+    DRC_ITEM *item;
+
     switch( aErrorCode )
     {
-    case DRCE_UNCONNECTED_ITEMS:        return new DRC_ITEM( unconnectedItems );
-    case DRCE_SHORTING_ITEMS:           return new DRC_ITEM( shortingItems );
-    case DRCE_ALLOWED_ITEMS:            return new DRC_ITEM( itemsNotAllowed );
-    case DRCE_CLEARANCE:                return new DRC_ITEM( clearance );
-    case DRCE_TRACKS_CROSSING:          return new DRC_ITEM( tracksCrossing );
-    case DRCE_COPPER_EDGE_CLEARANCE:    return new DRC_ITEM( copperEdgeClearance );
-    case DRCE_ZONES_INTERSECT:          return new DRC_ITEM( zonesIntersect );
-    case DRCE_ZONE_HAS_EMPTY_NET:       return new DRC_ITEM( zoneHasEmptyNet );
-    case DRCE_DANGLING_VIA:             return new DRC_ITEM( viaDangling );
-    case DRCE_DANGLING_TRACK:           return new DRC_ITEM( trackDangling );
-    case DRCE_HOLE_CLEARANCE:           return new DRC_ITEM( holeClearance );
-    case DRCE_TRACK_WIDTH:              return new DRC_ITEM( trackWidth );
-    case DRCE_TOO_SMALL_VIA:            return new DRC_ITEM( viaTooSmall );
-    case DRCE_VIA_ANNULUS:              return new DRC_ITEM( viaAnnulus );
-    case DRCE_TOO_SMALL_DRILL:          return new DRC_ITEM( drillTooSmall );
-    case DRCE_VIA_HOLE_BIGGER:          return new DRC_ITEM( viaHoleLargerThanPad );
-    case DRCE_PADSTACK:                 return new DRC_ITEM( padstack );
-    case DRCE_TOO_SMALL_MICROVIA:       return new DRC_ITEM( microviaTooSmall );
-    case DRCE_TOO_SMALL_MICROVIA_DRILL: return new DRC_ITEM( microviaDrillTooSmall );
-    case DRCE_KEEPOUT:                  return new DRC_ITEM( keepout );
-    case DRCE_OVERLAPPING_FOOTPRINTS:   return new DRC_ITEM( courtyardsOverlap );
-    case DRCE_MISSING_COURTYARD:        return new DRC_ITEM( missingCourtyard );
-    case DRCE_MALFORMED_COURTYARD:      return new DRC_ITEM( malformedCourtyard );
-    case DRCE_PTH_IN_COURTYARD:         return new DRC_ITEM( pthInsideCourtyard );
-    case DRCE_NPTH_IN_COURTYARD:        return new DRC_ITEM( npthInsideCourtyard );
-    case DRCE_DISABLED_LAYER_ITEM:      return new DRC_ITEM( itemOnDisabledLayer );
-    case DRCE_INVALID_OUTLINE:          return new DRC_ITEM( invalidOutline );
-    case DRCE_MISSING_FOOTPRINT:        return new DRC_ITEM( duplicateFootprints );
-    case DRCE_DUPLICATE_FOOTPRINT:      return new DRC_ITEM( missingFootprint );
-    case DRCE_EXTRA_FOOTPRINT:          return new DRC_ITEM( extraFootprint );
-    case DRCE_UNRESOLVED_VARIABLE:      return new DRC_ITEM( unresolvedVariable );
+    case DRCE_UNCONNECTED_ITEMS:        item = new DRC_ITEM( unconnectedItems ); break;
+    case DRCE_SHORTING_ITEMS:           item = new DRC_ITEM( shortingItems ); break;
+    case DRCE_ALLOWED_ITEMS:            item = new DRC_ITEM( itemsNotAllowed ); break;
+    case DRCE_CLEARANCE:                item = new DRC_ITEM( clearance ); break;
+    case DRCE_TRACKS_CROSSING:          item = new DRC_ITEM( tracksCrossing ); break;
+    case DRCE_COPPER_EDGE_CLEARANCE:    item = new DRC_ITEM( copperEdgeClearance ); break;
+    case DRCE_ZONES_INTERSECT:          item = new DRC_ITEM( zonesIntersect ); break;
+    case DRCE_ZONE_HAS_EMPTY_NET:       item = new DRC_ITEM( zoneHasEmptyNet ); break;
+    case DRCE_DANGLING_VIA:             item = new DRC_ITEM( viaDangling ); break;
+    case DRCE_DANGLING_TRACK:           item = new DRC_ITEM( trackDangling ); break;
+    case DRCE_HOLE_CLEARANCE:           item = new DRC_ITEM( holeClearance ); break;
+    case DRCE_TRACK_WIDTH:              item = new DRC_ITEM( trackWidth ); break;
+    case DRCE_TOO_SMALL_VIA:            item = new DRC_ITEM( viaTooSmall ); break;
+    case DRCE_VIA_ANNULUS:              item = new DRC_ITEM( viaAnnulus ); break;
+    case DRCE_TOO_SMALL_DRILL:          item = new DRC_ITEM( drillTooSmall ); break;
+    case DRCE_VIA_HOLE_BIGGER:          item = new DRC_ITEM( viaHoleLargerThanPad ); break;
+    case DRCE_PADSTACK:                 item = new DRC_ITEM( padstack ); break;
+    case DRCE_TOO_SMALL_MICROVIA:       item = new DRC_ITEM( microviaTooSmall ); break;
+    case DRCE_TOO_SMALL_MICROVIA_DRILL: item = new DRC_ITEM( microviaDrillTooSmall ); break;
+    case DRCE_KEEPOUT:                  item = new DRC_ITEM( keepout ); break;
+    case DRCE_OVERLAPPING_FOOTPRINTS:   item = new DRC_ITEM( courtyardsOverlap ); break;
+    case DRCE_MISSING_COURTYARD:        item = new DRC_ITEM( missingCourtyard ); break;
+    case DRCE_MALFORMED_COURTYARD:      item = new DRC_ITEM( malformedCourtyard ); break;
+    case DRCE_PTH_IN_COURTYARD:         item = new DRC_ITEM( pthInsideCourtyard ); break;
+    case DRCE_NPTH_IN_COURTYARD:        item = new DRC_ITEM( npthInsideCourtyard ); break;
+    case DRCE_DISABLED_LAYER_ITEM:      item = new DRC_ITEM( itemOnDisabledLayer ); break;
+    case DRCE_INVALID_OUTLINE:          item = new DRC_ITEM( invalidOutline ); break;
+    case DRCE_MISSING_FOOTPRINT:        item = new DRC_ITEM( duplicateFootprints ); break;
+    case DRCE_DUPLICATE_FOOTPRINT:      item = new DRC_ITEM( missingFootprint ); break;
+    case DRCE_EXTRA_FOOTPRINT:          item = new DRC_ITEM( extraFootprint ); break;
+    case DRCE_UNRESOLVED_VARIABLE:      item = new DRC_ITEM( unresolvedVariable ); break;
 
     default:
         wxFAIL_MSG( wxString::Format( "Unknown DRC error code %d", aErrorCode ) );
         return nullptr;
     }
+    return std::shared_ptr<test::DRC_ITEM>( item );
 }
 
 
-test::DRC_ITEM* test::DRC_ITEM::Create( const wxString& aErrorKey )
+std::shared_ptr<test::DRC_ITEM> test::DRC_ITEM::Create( const wxString& aErrorKey )
 {
     for( const RC_ITEM& item : allItemTypes )
     {
         if( aErrorKey == item.GetSettingsKey() )
-            return new DRC_ITEM( static_cast<const DRC_ITEM&>( item ) );
+            return std::shared_ptr<DRC_ITEM>( new DRC_ITEM( static_cast<const DRC_ITEM&>( item ) ) );
     }
 
     // This can happen if a project has old-format exclusions.  Just drop these items.
diff --git a/qa/drc_proto/drc_item.h b/qa/drc_proto/drc_item.h
index bfc6dc27de..0e485e2229 100644
--- a/qa/drc_proto/drc_item.h
+++ b/qa/drc_proto/drc_item.h
@@ -46,7 +46,7 @@ public:
      * Constructs a DRC_ITEM for the given error code
      * @see DRCE_T
      */
-    static DRC_ITEM* Create( int aErrorCode );
+    static std::shared_ptr<DRC_ITEM> Create( int aErrorCode );
 
     /**
      * Constructs a DRC item from a given error settings key
@@ -54,7 +54,7 @@ public:
      * to represent a given error code in settings files and for storing ignored DRC items)
      * @return the created item
      */
-    static DRC_ITEM* Create( const wxString& aErrorKey );
+    static std::shared_ptr<DRC_ITEM> Create( const wxString& aErrorKey );
 
     static std::vector<std::reference_wrapper<RC_ITEM>> GetItemsWithSeverities()
     {
diff --git a/qa/drc_proto/drc_rule.cpp b/qa/drc_proto/drc_rule.cpp
index 813a0bc720..fce5a95f38 100644
--- a/qa/drc_proto/drc_rule.cpp
+++ b/qa/drc_proto/drc_rule.cpp
@@ -77,9 +77,9 @@ bool test::DRC_RULE_CONDITION::EvaluateFor( const BOARD_ITEM* aItemA, const BOAR
 }
 
 
-bool test::DRC_RULE_CONDITION::Compile( REPORTER* aReporter, int aSourceLine, int aSourceOffset )
+bool test::DRC_RULE_CONDITION::Compile( )
 {
-    PCB_EXPR_COMPILER compiler( aReporter, aSourceLine, aSourceOffset );
+    PCB_EXPR_COMPILER compiler;
 
     if (!m_ucode)
         m_ucode = new PCB_EXPR_UCODE;
diff --git a/qa/drc_proto/drc_rule.h b/qa/drc_proto/drc_rule.h
index 3b0516e67c..d4026f3afb 100644
--- a/qa/drc_proto/drc_rule.h
+++ b/qa/drc_proto/drc_rule.h
@@ -34,6 +34,7 @@ class BOARD_ITEM;
 namespace LIBEVAL
 {
 class UCODE;
+class ERROR_STATUS;
 };
 
 class PCB_EXPR_UCODE;
@@ -48,9 +49,8 @@ enum class DRC_RULE_ID_T
     DRC_RULE_ID_HOLE_CLEARANCE,
     DRC_RULE_ID_EDGE_CLEARANCE,
     DRC_RULE_ID_HOLE_SIZE,
-    DRC_RULE_ID_ANNULUS,
-    DRC_RULE_ID_TRACK,
-    DRC_RULE_ID_DISALLOW
+    DRC_RULE_ID_COURTYARD_CLEARANCE,
+    DRC_RULE_ID_SILK_TO_PAD
 };
 
 enum class DRC_RULE_SEVERITY_T
@@ -85,10 +85,9 @@ private:
     bool m_hasMax = false;
 };
 
-
 class DRC_CONSTRAINT
 {
-public:
+    public:
     DRC_CONSTRAINT() :
         m_Type( DRC_RULE_ID_T::DRC_RULE_ID_UNKNOWN ),
         m_DisallowFlags( 0 ),
@@ -99,34 +98,15 @@ public:
     const MINOPTMAX<int>& GetValue() const { return m_Value; }
     bool Allowed() const { return m_Allow; }
 
-public:
-    DRC_RULE_ID_T  m_Type;
-    MINOPTMAX<int> m_Value;
-    int            m_DisallowFlags;
-    LSET           m_LayerCondition;
+    public:
+    	DRC_RULE_ID_T  m_Type;
+        MINOPTMAX<int> m_Value;
+    	int            m_DisallowFlags;
+    	LSET           m_LayerCondition;
 
-    bool      m_Allow;
+        bool      m_Allow;
 };
 
-
-class DRC_RULE_CONDITION
-   {
-   public:
-       DRC_RULE_CONDITION();
-       ~DRC_RULE_CONDITION();
-
-       bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB, PCB_LAYER_ID aLayer );
-       bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
-
-   public:
-       wxString  m_Expression;
-       wxString  m_TargetRuleName;
-
-   private:
-       PCB_EXPR_UCODE*       m_ucode;
-   };
-
-
 class DRC_RULE
 {
 public:
@@ -151,9 +131,9 @@ public:
 public:
     bool m_Unary;
 
-    wxString                    m_Name;
+    wxString m_Name;
     LSET                        m_LayerCondition;
-    wxString                    m_TestProviderName;
+    wxString m_TestProviderName;
     DRC_RULE_CONDITION          m_Condition;
     std::vector<DRC_CONSTRAINT> m_Constraints;
 
@@ -161,13 +141,29 @@ public:
     bool m_Enabled;
     bool m_Conditional;
     int  m_Priority; // 0 indicates automatic priority generation
-
-    DRC_CONSTRAINT m_Constraint;    // FIXME: move to m_Constraints
 };
 
 
-//const DRC_CONSTRAINT* GetConstraint( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem,
-//                                     int aConstraint, PCB_LAYER_ID aLayer, wxString* aRuleName );
+class DRC_RULE_CONDITION
+{
+public:
+    DRC_RULE_CONDITION();
+    ~DRC_RULE_CONDITION();
+
+    bool EvaluateFor( const BOARD_ITEM* aItemA, const BOARD_ITEM* aItemB );
+    bool Compile( REPORTER* aReporter, int aSourceLine = 0, int aSourceOffset = 0 );
+
+public:
+    LSET      m_LayerCondition;
+    wxString  m_Expression;
+    wxString  m_TargetRuleName;
+
+private:
+    PCB_EXPR_UCODE*       m_ucode;
+};
+
+
+//DRC_RULE* GetRule( const BOARD_ITEM* aItem, const BOARD_ITEM* bItem, int aConstraint );
 
 }; // namespace test
 
diff --git a/qa/drc_proto/drc_rule_parser.cpp b/qa/drc_proto/drc_rule_parser.cpp
index 7c2f0ce113..d16a1490a1 100644
--- a/qa/drc_proto/drc_rule_parser.cpp
+++ b/qa/drc_proto/drc_rule_parser.cpp
@@ -342,9 +342,20 @@ test::DRC_RULE* test::DRC_RULES_PARSER::parseRULE()
 
 void test::DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult )
 {
-    PCB_EXPR_EVALUATOR evaluator( m_reporter, CurLineNumber(), CurOffset() );
+    PCB_EXPR_EVALUATOR evaluator;
 
     evaluator.Evaluate( aExpr );
+
+    if( evaluator.IsErrorPending() )
+    {
+        auto err = evaluator.GetError();
+        wxString str;
+        str.Printf( "Error: %s (line %d, offset %d)", err.message, CurLineNumber(), err.srcPos + CurOffset() );
+
+        m_reporter->Report( str, RPT_SEVERITY_ERROR );
+        return;
+    }
+
     aResult = evaluator.Result();
 };
 
diff --git a/qa/drc_proto/drc_test_provider.cpp b/qa/drc_proto/drc_test_provider.cpp
index f4b18a2879..7d1bb5397b 100644
--- a/qa/drc_proto/drc_test_provider.cpp
+++ b/qa/drc_proto/drc_test_provider.cpp
@@ -22,23 +22,25 @@ bool test::DRC_TEST_PROVIDER::IsEnabled() const
 const wxString test::DRC_TEST_PROVIDER::GetName() const { return "<no name test>"; }
 const wxString test::DRC_TEST_PROVIDER::GetDescription() const { return ""; }
 
-void test::DRC_TEST_PROVIDER::Report( DRC_ITEM* item )
+void test::DRC_TEST_PROVIDER::Report( std::shared_ptr<DRC_ITEM> item )
 {
     item->SetViolatingTest( this );
     m_drcEngine->Report( item, nullptr );
 }
 
 
-void test::DRC_TEST_PROVIDER::ReportWithMarker( DRC_ITEM* item, VECTOR2I aMarkerPos )
+void test::DRC_TEST_PROVIDER::ReportWithMarker( std::shared_ptr<DRC_ITEM> item, VECTOR2I aMarkerPos )
 {
     item->SetViolatingTest( this );
-    m_drcEngine->Report( item, nullptr ); // fixme: create marker
+    MARKER_PCB* marker = new MARKER_PCB( item, wxPoint( aMarkerPos.x, aMarkerPos.y) );
+    m_drcEngine->Report( item, marker );
 }
 
-void test::DRC_TEST_PROVIDER::ReportWithMarker( DRC_ITEM* item, wxPoint aMarkerPos )
+void test::DRC_TEST_PROVIDER::ReportWithMarker( std::shared_ptr<DRC_ITEM> item, wxPoint aMarkerPos )
 {
     item->SetViolatingTest( this );
-    m_drcEngine->Report( item, nullptr ); // fixme: create marker
+    MARKER_PCB* marker = new MARKER_PCB( item, wxPoint( aMarkerPos.x, aMarkerPos.y) );
+    m_drcEngine->Report( item, marker ); // fixme: create marker
 }
 
 void test::DRC_TEST_PROVIDER::ReportProgress( double aProgress )
@@ -90,3 +92,130 @@ void test::DRC_TEST_PROVIDER::reportRuleStatistics()
         m_drcEngine->ReportAux( wxString::Format( " - rule '%s': %d hits ", stat.first->GetName().c_str(), stat.second ) );
     }
 }
+
+int test::DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T> aTypes, const LSET aLayers, std::function<int(BOARD_ITEM*)> aFunc )
+{
+    BOARD *brd = m_drcEngine->GetBoard();
+    std::bitset<MAX_STRUCT_TYPE_ID> typeMask;
+    int n = 0;
+
+    if( aTypes.size() == 0 )
+    {
+        for( int i = 0; i < MAX_STRUCT_TYPE_ID; i++ )
+        {
+            typeMask[i] = true;
+        }
+    }
+    else
+    {
+        for( int i = 0; i < aTypes.size(); i++ )
+        {
+            typeMask[ aTypes[i] ] = 1;
+        }
+    }
+
+    /* case PCB_TRACE_T:
+    case PCB_VIA_T:
+    case PCB_ARC_T:*/
+    for ( auto item : brd->Tracks() )
+    {
+        if( typeMask[ PCB_TRACE_T ] && item->Type() == PCB_TRACE_T )
+        {
+            aFunc( item );
+            n++;
+        }
+        else if( typeMask[ PCB_VIA_T ] && item->Type() == PCB_VIA_T )
+        {
+            aFunc( item );
+            n++;
+        }
+        else if( typeMask[ PCB_ARC_T ] && item->Type() == PCB_ARC_T )
+        {
+            aFunc( item );
+            n++;
+        }
+    }
+
+    /* case PCB_DIMENSION_T:
+    case PCB_LINE_T:
+    case PCB_TEXT_T:
+    case PCB_TARGET_T:
+    */
+    for( auto item : brd->Drawings() )
+    {
+        if( typeMask[ PCB_DIMENSION_T ] && item->Type() == PCB_DIMENSION_T )
+        {
+            aFunc( item );
+            n++;
+        }
+        else if( typeMask[ PCB_LINE_T ] && item->Type() == PCB_LINE_T )
+        {
+            aFunc( item );
+            n++;
+        }
+        else if( typeMask[ PCB_TEXT_T ] && item->Type() == PCB_TEXT_T )
+        {
+            aFunc( item );
+            n++;
+        }
+        else if( typeMask[ PCB_TARGET_T ] && item->Type() == PCB_TARGET_T )
+        {
+            aFunc( item );
+            n++;
+        }
+    }
+
+    for( auto item : brd->Zones() )
+    {
+        if( typeMask[ PCB_ZONE_AREA_T ] && item->Type() == PCB_ZONE_AREA_T )
+        {
+            aFunc( item );
+            n++;
+        }
+    }
+
+    for( auto mod : brd->Modules() )
+    {
+        if( typeMask[ PCB_MODULE_TEXT_T ] )
+        {
+            aFunc( &mod->Reference() );
+            n++;
+            aFunc( &mod->Value() );
+            n++;
+        }
+
+        for( auto pad : mod->Pads() )
+        {
+            if( typeMask[ PCB_PAD_T ] && pad->Type() == PCB_PAD_T )
+            {
+                aFunc( pad );
+                n++;
+            }
+        }
+
+        for( auto dwg : mod->GraphicalItems() )
+        {
+            if( typeMask[ PCB_MODULE_TEXT_T ] && dwg->Type() == PCB_MODULE_TEXT_T )
+            {
+                aFunc( dwg );
+                n++;
+            }
+            else if( typeMask[ PCB_MODULE_EDGE_T ] && dwg->Type() == PCB_MODULE_EDGE_T )
+            {
+                aFunc( dwg );
+                n++;
+            }
+        }
+
+        for( auto zone : mod->Zones() )
+        {
+            if( typeMask[ PCB_MODULE_ZONE_AREA_T ] && zone->Type() == PCB_MODULE_ZONE_AREA_T )
+            {
+                aFunc( zone );
+                n++;
+            }
+        }
+    }
+
+    return n;
+}
diff --git a/qa/drc_proto/drc_test_provider.h b/qa/drc_proto/drc_test_provider.h
index 0aefa4133c..788faf186c 100644
--- a/qa/drc_proto/drc_test_provider.h
+++ b/qa/drc_proto/drc_test_provider.h
@@ -97,9 +97,9 @@ public:
     virtual const wxString GetDescription() const;
 
     virtual void ReportAux( const wxString fmt, ... );
-    virtual void Report( DRC_ITEM* item );
-    virtual void ReportWithMarker( DRC_ITEM* item, wxPoint aMarkerPos );
-    virtual void ReportWithMarker( DRC_ITEM* item, VECTOR2I aMarkerPos );
+    virtual void Report( std::shared_ptr<DRC_ITEM> item );
+    virtual void ReportWithMarker( std::shared_ptr<DRC_ITEM> item, wxPoint aMarkerPos );
+    virtual void ReportWithMarker( std::shared_ptr<DRC_ITEM> item, VECTOR2I aMarkerPos );
 
     virtual void ReportProgress( double aProgress );
     virtual void ReportStage ( const wxString& aStageName, int index, int total );
@@ -108,6 +108,8 @@ public:
 
 protected:
 
+    int forEachGeometryItem( const std::vector<KICAD_T> aTypes, const LSET aLayers, std::function<int(BOARD_ITEM*)> aFunc );
+
     virtual void reportRuleStatistics();
     virtual void accountCheck( test::DRC_RULE* ruleToTest );
     virtual bool isErrorLimitExceeded( int error_code );
diff --git a/qa/drc_proto/drc_test_provider_copper_clearance.cpp b/qa/drc_proto/drc_test_provider_copper_clearance.cpp
index 14683c3889..66bdd20b9a 100644
--- a/qa/drc_proto/drc_test_provider_copper_clearance.cpp
+++ b/qa/drc_proto/drc_test_provider_copper_clearance.cpp
@@ -178,7 +178,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a
     else if( textItem )
     {
         bbox = textItem->GetTextBox();
-        itemShape = textItem->GetEffectiveShape();
+        itemShape = textItem->GetEffectiveTextShape();
     }
     else
     {
@@ -215,7 +215,8 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a
 
         if( actual < INT_MAX )
         {
-            DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
+            std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
+            
 
             wxString msg;
             msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
@@ -258,7 +259,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testCopperDrawItem( BOARD_ITEM* a
 
         if( actual < INT_MAX )
         {
-            DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
+            std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
 
 
             wxString msg;
@@ -363,7 +364,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK
 
             if( padShape->Collide( &refSeg, minClearance - bds.GetDRCEpsilon(), &actual ) )
             {
-                DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
+                std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
                 wxString msg;
 
                 msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
@@ -434,7 +435,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK
 
         if( OPT_VECTOR2I intersection = refSeg.GetSeg().Intersect( trackSeg.GetSeg() ) )
         {
-            DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TRACKS_CROSSING );
+            std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TRACKS_CROSSING );
 
             // fixme
             drcItem->SetErrorMessage( "FIXME" );
@@ -449,7 +450,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK
         else if( refSeg.Collide( &trackSeg, minClearance, &actual ) )
         {
             wxPoint   pos = getLocation( aRefSeg, trackSeg.GetSeg() );
-            DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
+            std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
 
 
             wxString msg;
@@ -507,7 +508,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doTrackDrc( TRACK* aRefSeg, TRACK
                 if( zone->GetFilledPolysList( layer ).Collide( testSeg, allowedDist, &actual ) )
                 {
                     actual = std::max( 0, actual - widths );
-                    DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
+                    std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
                     wxString msg;
 
                     msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
@@ -606,7 +607,7 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D
             // and have the same pad number ( equivalent pads  )
             if( pad->PadNameEqual( aRefPad ) )
             {
-                DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_SHORTING_ITEMS );
+                std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_SHORTING_ITEMS );
                 wxString msg;
                 msg.Printf( drcItem->GetErrorText() + _( " (nets %s and %s)" ),
                             pad->GetNetCode(), aRefPad->GetNetCode() );
@@ -639,7 +640,7 @@ bool test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::doPadToPadsDrc( D_PAD* aRefPad, D
 
         if( refPadShape->Collide( pad->GetEffectiveShape().get(), clearanceAllowed, &actual ) )
         {
-            DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
+            std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_CLEARANCE );
             wxString msg;
             msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
                           /*m_clearanceSource fixme*/ "",
@@ -726,7 +727,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones()
 
                 if( smoothed_polys[ia2].Contains( currentVertex ) )
                 {
-                    DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT );
+                    std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT );
                     drcItem->SetItems( zoneRef, zoneToTest );
                     drcItem->SetViolatingRule( rule );
 
@@ -742,7 +743,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones()
 
                 if( smoothed_polys[ia].Contains( currentVertex ) )
                 {
-                    DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT );
+                    std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_ZONES_INTERSECT );
                     drcItem->SetItems( zoneToTest, zoneRef );
                     drcItem->SetViolatingRule( rule );
 
@@ -797,7 +798,7 @@ void test::DRC_TEST_PROVIDER_COPPER_CLEARANCE::testZones()
             for( const std::pair<const wxPoint, int>& conflict : conflictPoints )
             {
                 int       actual = conflict.second;
-                DRC_ITEM* drcItem;
+                std::shared_ptr<DRC_ITEM> drcItem;
 
                 if( actual <= 0 )
                 {
diff --git a/qa/drc_proto/drc_test_provider_edge_clearance.cpp b/qa/drc_proto/drc_test_provider_edge_clearance.cpp
index 6e1bcc3405..dc9904dda4 100644
--- a/qa/drc_proto/drc_test_provider_edge_clearance.cpp
+++ b/qa/drc_proto/drc_test_provider_edge_clearance.cpp
@@ -44,7 +44,9 @@
     Errors generated:
     - DRCE_COPPER_EDGE_CLEARANCE
 
-    TODO: holes to edge check
+    TODO:
+    - separate holes to edge check
+    - tester only looks for edge crossings. it doesn't check if items are inside/outside the board area.
 */
 
 namespace test {
@@ -70,7 +72,7 @@ public:
 
     virtual const wxString GetDescription() const override
     {
-        return "Tests copper item vs board edge clearance";
+        return "Tests items vs board edge clearance";
     }
 
     virtual std::set<test::DRC_RULE_ID_T> GetMatchingRuleIds() const override;
@@ -83,76 +85,71 @@ private:
 
 bool test::DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
 {
-    auto bds = m_drcEngine->GetDesignSettings();
     m_board = m_drcEngine->GetBoard();
 
+    DRC_CONSTRAINT worstClearanceConstraint;
     m_largestClearance = 0;
 
-    for( auto rule : m_drcEngine->QueryRulesById( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE ) )
+    if( m_drcEngine->QueryWorstConstraint( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE, worstClearanceConstraint, DRCCQ_LARGEST_MINIMUM ) )
     {
-        if( rule->GetConstraint().m_Value.HasMin() )
-        {
-            m_largestClearance = std::max( m_largestClearance, rule->GetConstraint().m_Value.Min() );
-        }
+        m_largestClearance = worstClearanceConstraint.m_Value.Min();
     }
 
     ReportAux( "Worst clearance : %d nm", m_largestClearance );
-
-    //m_largestClearance = 
-
     ReportStage( ("Testing all items <> Board Edge clearance"), 0, 2 );
     
     std::vector<DRAWSEGMENT*> boardOutline;
     std::vector<BOARD_ITEM*> boardItems;
 
-    for( auto item : m_board->Drawings() )
+    auto queryBoardOutlineItems = [&] ( BOARD_ITEM *item ) -> int
     {
-        if( auto dseg = dyn_cast<DRAWSEGMENT*>( item ) )
-        {
-            drc_dbg(10,"L %d\n", dseg->GetLayer() );
-            if( dseg->GetLayer() == Edge_Cuts )
-            {
-                drc_dbg(10, "dseg ec %p\n", dseg);
-                boardOutline.push_back( dseg );
-            }
-        }
-    }
+        boardOutline.push_back( dyn_cast<DRAWSEGMENT*>( item ) );
+    };
 
-    for ( auto trk : m_board->Tracks() )
+    auto queryBoardGeometryItems = [&] ( BOARD_ITEM *item ) -> int
     {
-        boardItems.push_back( trk );
-    }
+        boardItems.push_back( item );
+    };
 
-    for ( auto zone : m_board->Zones() )
-    {
-        boardItems.push_back( zone );
-    }
+    
 
-    for ( auto zone : m_board->Zones() )
-    {
-        boardItems.push_back( zone );
-    }
+    forEachGeometryItem( { PCB_LINE_T }, LSET( Edge_Cuts ), queryBoardOutlineItems );
+    forEachGeometryItem( {}, LSET::AllTechMask() | LSET::AllCuMask(), queryBoardGeometryItems );
 
-    for ( auto mod : m_board->Modules() )
-    {
-        for ( auto dwg : mod->GraphicalItems() )
-            boardItems.push_back( dwg );
-        for ( auto pad : mod->Pads() )
-            boardItems.push_back( pad );
-    }
 
     drc_dbg(2,"outline: %d items, board: %d items\n", boardOutline.size(), boardItems.size() );
 
     for( auto outlineItem : boardOutline )
     {
+        //printf("RefT %d\n", outlineItem->Type() );
         auto refShape = outlineItem->GetEffectiveShape();
 
         for( auto boardItem : boardItems )
         {
+//            printf("BoardT %d\n", boardItem->Type() );
+            
             auto shape = boardItem->GetEffectiveShape();
 
-            (void) shape;
-            (void) refShape;
+            test::DRC_RULE* rule = m_drcEngine->EvalRulesForItems( test::DRC_RULE_ID_T::DRC_RULE_ID_EDGE_CLEARANCE, outlineItem, boardItem );
+            int minClearance = rule->GetConstraint().GetValue().Min();
+            int actual;
+
+            if( refShape->Collide( shape.get(), minClearance, &actual ) )
+            {
+                std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_COPPER_EDGE_CLEARANCE );
+                wxString msg;
+
+                msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
+                            rule->GetName(),
+                            MessageTextFromValue( userUnits(), minClearance, true ),
+                            MessageTextFromValue( userUnits(), actual, true ) );
+
+                drcItem->SetErrorMessage( msg );
+                drcItem->SetItems( outlineItem, boardItem );
+                drcItem->SetViolatingRule( rule );
+
+                ReportWithMarker( drcItem, refShape->Centre() );
+            }
         }
     }
 
diff --git a/qa/drc_proto/drc_test_provider_hole_clearance.cpp b/qa/drc_proto/drc_test_provider_hole_clearance.cpp
index 0e2dc0fbbd..6bb460a597 100644
--- a/qa/drc_proto/drc_test_provider_hole_clearance.cpp
+++ b/qa/drc_proto/drc_test_provider_hole_clearance.cpp
@@ -280,7 +280,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc(  D_PAD* aRefPad,
                 // fixme: pad stacks...
                 if( refPadShape->Collide( pad->GetEffectiveHoleShape(), minClearance, &actual ) )
                 {
-                    DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE );
+                    std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE );
 
                     wxString msg;
 
@@ -312,7 +312,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::doPadToPadHoleDrc(  D_PAD* aRefPad,
                 auto padShape = pad->GetEffectiveShape();
                 if( padShape->Collide( aRefPad->GetEffectiveHoleShape(), minClearance, &actual ) )
                 {
-                    DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE );
+                    std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE );
                     wxString msg;
 
                     msg.Printf( drcItem->GetErrorText() + _( " (%s clearance %s; actual %s)" ),
@@ -393,7 +393,7 @@ void test::DRC_TEST_PROVIDER_HOLE_CLEARANCE::testHoles2Holes()
 
             if( actual < minClearance )
             {
-                DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE );
+                std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_HOLE_CLEARANCE );
                 wxString msg;
 
                 msg.Printf( drcItem->GetErrorText() + _( " (clearance %s; actual %s)" ),
diff --git a/qa/drc_proto/drc_test_provider_hole_size.cpp b/qa/drc_proto/drc_test_provider_hole_size.cpp
index 5e1566da63..7109ec75b5 100644
--- a/qa/drc_proto/drc_test_provider_hole_size.cpp
+++ b/qa/drc_proto/drc_test_provider_hole_size.cpp
@@ -141,7 +141,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkPad( D_PAD* aPad )
     if( holeSize < minHole )
     {
         wxString  msg;
-        DRC_ITEM* drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
+        std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( DRCE_TOO_SMALL_DRILL );
 
         msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ),
                 MessageTextFromValue( userUnits(), minHole, true ),
@@ -173,7 +173,7 @@ bool test::DRC_TEST_PROVIDER_HOLE_SIZE::checkVia( VIA* via )
         int errorCode = via->GetViaType() == VIATYPE::MICROVIA ? DRCE_TOO_SMALL_MICROVIA_DRILL :
                                                                  DRCE_TOO_SMALL_DRILL;
 
-        DRC_ITEM* drcItem = DRC_ITEM::Create( errorCode );
+        std::shared_ptr<DRC_ITEM> drcItem = DRC_ITEM::Create( errorCode );
 
         msg.Printf( drcItem->GetErrorText() + _( " (%s; actual %s)" ),
                 MessageTextFromValue( userUnits(), minHole, true ),
diff --git a/qa/drc_proto/footprint_tester.cpp b/qa/drc_proto/footprint_tester.cpp
index 14a2f70193..cbbf1377bf 100644
--- a/qa/drc_proto/footprint_tester.cpp
+++ b/qa/drc_proto/footprint_tester.cpp
@@ -25,7 +25,7 @@
 #include <netlist_reader/pcb_netlist.h>
 #include <drc/footprint_tester.h>
 
-void TestFootprints( NETLIST& aNetlist, BOARD* aBoard, std::vector<DRC_ITEM*>& aDRCList )
+void TestFootprints( NETLIST& aNetlist, BOARD* aBoard, std::vector<std::shared_ptr<DRC_ITEM> >& aDRCList )
 {
     wxString msg;