diff --git a/gcc/omp-general.cc b/gcc/omp-general.cc
index c7b8e17d1f7..2edc0a65abf 100644
--- a/gcc/omp-general.cc
+++ b/gcc/omp-general.cc
@@ -1735,13 +1735,19 @@ omp_construct_traits_match (tree selector_traits, tree context_traits,
    CONSTRUCT_CONTEXT is known to be complete and not missing constructs
    filled in later during compilation.
 
+   If DECLARE_VARIANT_ELISION_P is true, the function implements the test
+   for elision of preprocessed code in "begin declare variant" constructs,
+   and returns 0 only for failure to match traits in the device and
+   implementation sets.
+
    Dynamic properties (which are evaluated at run-time) should always
    return 1.  */
 
 int
 omp_context_selector_matches (tree ctx,
 			      tree construct_context,
-			      bool complete_p)
+			      bool complete_p,
+			      bool declare_variant_elision_p)
 {
   int ret = 1;
   bool maybe_offloaded = omp_maybe_offloaded (construct_context);
@@ -1753,9 +1759,12 @@ omp_context_selector_matches (tree ctx,
 
       /* Immediately reject the match if there are any ignored
 	 selectors present.  */
-      for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
-	if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
-	  return 0;
+      if (!declare_variant_elision_p
+	  || set == OMP_TRAIT_SET_DEVICE
+	  || set == OMP_TRAIT_SET_IMPLEMENTATION)
+	for (tree ts = selectors; ts; ts = TREE_CHAIN (ts))
+	  if (OMP_TS_CODE (ts) == OMP_TRAIT_INVALID)
+	    return 0;
 
       if (set == OMP_TRAIT_SET_CONSTRUCT)
 	{
@@ -2109,6 +2118,13 @@ omp_context_selector_matches (tree ctx,
 	      break;
 	    case OMP_TRAIT_USER_CONDITION:
 	      gcc_assert (set == OMP_TRAIT_SET_USER);
+	      /* The spec does not include the "user" set in the things that
+		 can trigger code elision in "begin declare variant".  */
+	      if (declare_variant_elision_p)
+		{
+		  ret = -1;
+		  break;
+		}
 	      for (tree p = OMP_TS_PROPERTIES (ts); p; p = TREE_CHAIN (p))
 		if (OMP_TP_NAME (p) == NULL_TREE)
 		  {
@@ -2124,6 +2140,10 @@ omp_context_selector_matches (tree ctx,
 		    ret = -1;
 		  }
 	      break;
+	    case OMP_TRAIT_INVALID:
+	      /* This is only for the declare_variant_elision_p case.  */
+	      ret = -1;
+	      break;
 	    default:
 	      break;
 	    }
diff --git a/gcc/omp-general.h b/gcc/omp-general.h
index 466a70c9485..ec5a40fe6fa 100644
--- a/gcc/omp-general.h
+++ b/gcc/omp-general.h
@@ -205,7 +205,7 @@ extern bool omp_check_for_duplicate_variant (location_t loc,
 					     tree base_decl, tree ctx);
 extern void omp_mark_declare_variant (location_t loc, tree variant,
 				      tree construct);
-extern int omp_context_selector_matches (tree, tree, bool);
+extern int omp_context_selector_matches (tree, tree, bool, bool = false);
 extern tree omp_merge_context_selectors (location_t, tree, tree,
 					 enum omp_ctx_directive);
 extern tree resolve_omp_target_device_matches (tree node);
