diff --git c/gcc/cp/call.c w/gcc/cp/call.c
index f164b211c9f..47a368d069d 100644
--- c/gcc/cp/call.c
+++ w/gcc/cp/call.c
@@ -4704,7 +4704,7 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
        up in the global scope.
 
      we disregard block-scope declarations of "operator new".  */
-  fns = lookup_name_real (fnname, 0, 1, /*block_p=*/false, 0, 0);
+  fns = lookup_name_real (fnname, LOOK_where::NAMESPACE, 0, 0, 0);
   fns = lookup_arg_dependent (fnname, fns, *args);
 
   if (align_arg)
@@ -5982,7 +5982,8 @@ add_operator_candidates (z_candidate **candidates,
      consider.  */
   if (!memonly)
     {
-      tree fns = lookup_name_real (fnname, 0, 1, /*block_p=*/true, 0, 0);
+      tree fns = lookup_name_real (fnname, LOOK_where::BLOCK_NAMESPACE,
+				   0, 0, 0);
       fns = lookup_arg_dependent (fnname, fns, arglist);
       add_candidates (fns, NULL_TREE, arglist, NULL_TREE,
 		      NULL_TREE, false, NULL_TREE, NULL_TREE,
diff --git c/gcc/cp/name-lookup.c w/gcc/cp/name-lookup.c
index 9f30d907a09..4fdac9421d1 100644
--- c/gcc/cp/name-lookup.c
+++ w/gcc/cp/name-lookup.c
@@ -3741,7 +3741,7 @@ identifier_type_value_1 (tree id)
     return REAL_IDENTIFIER_TYPE_VALUE (id);
   /* Have to search for it. It must be on the global level, now.
      Ask lookup_name not to return non-types.  */
-  id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, 0);
+  id = lookup_name_real (id, LOOK_where::BLOCK_NAMESPACE, 2, 0, 0);
   if (id)
     return TREE_TYPE (id);
   return NULL_TREE;
@@ -6413,10 +6413,16 @@ innermost_non_namespace_value (tree name)
    namespace of variables, functions and typedefs.  Return a ..._DECL
    node of some kind representing its definition if there is only one
    such declaration, or return a TREE_LIST with all the overloaded
-   definitions if there are many, or return 0 if it is undefined.
+   definitions if there are many, or return NULL_TREE if it is undefined.
    Hidden name, either friend declaration or built-in function, are
    not ignored.
 
+   WHERE controls which scopes are considered.  It is a bit mask of
+   LOOKUP_where::BLOCK (look in block scope), LOOKUP_where::CLASS
+   (look in class scopes) & LOOKUP_where::NAMESPACE (look in namespace
+   scopes).  It is an error for no bits to be set.  These scopes are
+   searched from innermost to outermost.
+
    If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
    If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
    Otherwise we prefer non-TYPE_DECLs.
@@ -6425,12 +6431,14 @@ innermost_non_namespace_value (tree name)
    BLOCK_P is false, bindings in block scopes are ignored.  */
 
 static tree
-lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
+lookup_name_real_1 (tree name, LOOK_where where, int prefer_type,
 		    int namespaces_only, int flags)
 {
   cxx_binding *iter;
   tree val = NULL_TREE;
 
+  gcc_checking_assert (unsigned (where) != 0);
+
   query_oracle (name);
 
   /* Conversion operators are handled specially because ordinary
@@ -6468,17 +6476,19 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
   /* First, look in non-namespace scopes.  */
 
   if (current_class_type == NULL_TREE)
-    nonclass = 1;
+    /* Maybe avoid searching the binding stack at all.  */
+    where = LOOK_where (unsigned (where) & ~unsigned (LOOK_where::CLASS));
 
-  if (block_p || !nonclass)
-    for (iter = outer_binding (name, NULL, !nonclass);
+  if (where & (LOOK_where::BLOCK | LOOK_where::CLASS))
+    for (iter = outer_binding (name, NULL, where & LOOK_where::CLASS);
 	 iter;
-	 iter = outer_binding (name, iter, !nonclass))
+	 iter = outer_binding (name, iter, where & LOOK_where::CLASS))
       {
 	tree binding;
 
 	/* Skip entities we don't want.  */
-	if (LOCAL_BINDING_P (iter) ? !block_p : nonclass)
+	if (!(where & (LOCAL_BINDING_P (iter)
+		       ? LOOK_where::BLOCK : LOOK_where::CLASS)))
 	  continue;
 
 	/* If this is the kind of thing we're looking for, we're done.  */
@@ -6548,7 +6558,7 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
       }
 
   /* Now lookup in namespace scopes.  */
-  if (!val)
+  if (!val && (where & LOOK_where::NAMESPACE))
     {
       name_lookup lookup (name, flags);
       if (lookup.search_unqualified
@@ -6566,12 +6576,12 @@ lookup_name_real_1 (tree name, int prefer_type, int nonclass, bool block_p,
 /* Wrapper for lookup_name_real_1.  */
 
 tree
-lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
+lookup_name_real (tree name, LOOK_where where, int prefer_type,
 		  int namespaces_only, int flags)
 {
   tree ret;
   bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
-  ret = lookup_name_real_1 (name, prefer_type, nonclass, block_p,
+  ret = lookup_name_real_1 (name, where, prefer_type,
 			    namespaces_only, flags);
   timevar_cond_stop (TV_NAME_LOOKUP, subtime);
   return ret;
@@ -6580,19 +6590,20 @@ lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
 tree
 lookup_name_nonclass (tree name)
 {
-  return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, 0);
+  return lookup_name_real (name, LOOK_where::BLOCK_NAMESPACE,
+			   0, 0, 0);
 }
 
 tree
 lookup_name (tree name)
 {
-  return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, 0);
+  return lookup_name_real (name, LOOK_where::ALL, 0, 0, 0);
 }
 
 tree
 lookup_name_prefer_type (tree name, int prefer_type)
 {
-  return lookup_name_real (name, prefer_type, 0, /*block_p=*/true, 0, 0);
+  return lookup_name_real (name, LOOK_where::ALL, prefer_type, 0, 0);
 }
 
 /* Look up NAME for type used in elaborated name specifier in
diff --git c/gcc/cp/name-lookup.h w/gcc/cp/name-lookup.h
index 9a185936853..4368c14d48c 100644
--- c/gcc/cp/name-lookup.h
+++ w/gcc/cp/name-lookup.h
@@ -278,8 +278,33 @@ extern void push_binding_level (cp_binding_level *);
 extern bool handle_namespace_attrs (tree, tree);
 extern void pushlevel_class (void);
 extern void poplevel_class (void);
+
+/* What kind of scopes name lookup looks in.  An enum class so we
+   don't accidentally mix integers.  */
+enum class LOOK_where
+{
+  BLOCK = 1 << 0,  /* Consider block scopes.  */ 
+  CLASS = 1 << 1,  /* Consider class scopes.  */ 
+  NAMESPACE = 1 << 2,  /* Consider namespace scopes.  */ 
+
+  ALL = BLOCK | CLASS | NAMESPACE,
+  BLOCK_NAMESPACE = BLOCK | NAMESPACE,
+  CLASS_NAMESPACE = CLASS | NAMESPACE,
+};
+constexpr LOOK_where operator| (LOOK_where a, LOOK_where b)
+{
+  return LOOK_where (unsigned (a) | unsigned (b));
+}
+constexpr bool operator& (LOOK_where a, LOOK_where b)
+{
+  return 0 != (unsigned (a) & unsigned (b));
+}
+
 extern tree lookup_name_prefer_type (tree, int);
-extern tree lookup_name_real (tree, int, int, bool, int, int);
+
+
+extern tree lookup_name_real (tree, LOOK_where, int prefer_type,
+			      int namespaces_only, int flags);
 extern tree lookup_type_scope (tree, tag_scope);
 extern tree get_namespace_binding (tree ns, tree id);
 extern void set_global_binding (tree decl);
diff --git c/gcc/cp/parser.c w/gcc/cp/parser.c
index 981c625a3cd..2c45a3d6f41 100644
--- c/gcc/cp/parser.c
+++ w/gcc/cp/parser.c
@@ -28459,17 +28459,17 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
       if (!decl)
 	/* Look it up in the enclosing context.  DR 141: When looking for a
 	   template-name after -> or ., only consider class templates.  */
-	decl = lookup_name_real (name, prefer_type_arg (tag_type, is_template),
-				 /*nonclass=*/0,
-				 /*block_p=*/true, is_namespace, 0);
+	decl = lookup_name_real (name, LOOK_where::ALL,
+				 prefer_type_arg (tag_type, is_template),
+				 is_namespace, 0);
       parser->object_scope = object_type;
       parser->qualifying_scope = NULL_TREE;
     }
   else
     {
-      decl = lookup_name_real (name, prefer_type_arg (tag_type),
-			       /*nonclass=*/0,
-			       /*block_p=*/true, is_namespace, 0);
+      decl = lookup_name_real (name, LOOK_where::ALL,
+			       prefer_type_arg (tag_type),
+			       is_namespace, 0);
       parser->qualifying_scope = NULL_TREE;
       parser->object_scope = NULL_TREE;
     }
diff --git c/gcc/cp/pt.c w/gcc/cp/pt.c
index cb81d8e9229..5fd16bf781c 100644
--- c/gcc/cp/pt.c
+++ w/gcc/cp/pt.c
@@ -11183,9 +11183,9 @@ tsubst_friend_class (tree friend_tmpl, tree args)
       push_nested_class (context);
     }
 
-  tmpl = lookup_name_real (DECL_NAME (friend_tmpl), /*prefer_type=*/false,
-			   /*non_class=*/false, /*block_p=*/false,
-			   /*namespaces_only=*/false, LOOKUP_HIDDEN);
+  tmpl = lookup_name_real (DECL_NAME (friend_tmpl), LOOK_where::CLASS_NAMESPACE,
+			   /*prefer_type=*/0, /*namespaces_only=*/false,
+			   LOOKUP_HIDDEN);
 
   if (tmpl && DECL_CLASS_TEMPLATE_P (tmpl))
     {
@@ -17835,7 +17835,7 @@ lookup_init_capture_pack (tree decl)
   for (int i = 0; i < len; ++i)
     {
       tree ename = vec ? make_ith_pack_parameter_name (cname, i) : cname;
-      tree elt = lookup_name_real (ename, 0, 0, true, 0, LOOKUP_NORMAL);
+      tree elt = lookup_name_real (ename, LOOK_where::ALL, 0, 0, LOOKUP_NORMAL);
       if (vec)
 	TREE_VEC_ELT (vec, i) = elt;
       else
@@ -17940,9 +17940,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 	    tree inst;
 	    if (!DECL_PACK_P (decl))
 	      {
-		inst = lookup_name_real (DECL_NAME (decl), /*prefer_type*/0,
-					 /*nonclass*/1, /*block_p=*/true,
-					 /*ns_only*/0, LOOKUP_HIDDEN);
+		inst = lookup_name_real (DECL_NAME (decl),
+					 LOOK_where::BLOCK_NAMESPACE,
+					 /*prefer_type*/0, /*ns_only*/0,
+					 LOOKUP_HIDDEN);
 		gcc_assert (inst != decl && is_capture_proxy (inst));
 	      }
 	    else if (is_normal_capture_proxy (decl))
diff --git c/gcc/cp/semantics.c w/gcc/cp/semantics.c
index 3096fe83433..e979a8b716c 100644
--- c/gcc/cp/semantics.c
+++ w/gcc/cp/semantics.c
@@ -10322,8 +10322,8 @@ static tree
 capture_decltype (tree decl)
 {
   tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl));
-  tree cap = lookup_name_real (DECL_NAME (decl), /*type*/0, /*nonclass*/1,
-			       /*block_p=*/true, /*ns*/0, LOOKUP_HIDDEN);
+  tree cap = lookup_name_real (DECL_NAME (decl), LOOK_where::BLOCK_NAMESPACE,
+			       /*type*/0, /*ns*/false, LOOKUP_HIDDEN);
   tree type;
 
   if (cap && is_capture_proxy (cap))
diff --git c/libcc1/libcp1plugin.cc w/libcc1/libcp1plugin.cc
index 01aecf00735..24582c74a86 100644
--- c/libcc1/libcp1plugin.cc
+++ w/libcc1/libcp1plugin.cc
@@ -2652,7 +2652,7 @@ plugin_build_dependent_expr (cc1_plugin::connection *self,
     }
   tree res = identifier;
   if (!scope)
-    res = lookup_name_real (res, 0, 0, true, 0, 0);
+    res = lookup_name_real (res, LOOK_where::BLOCK_NAMESPACE, 0, 0, 0);
   else if (!TYPE_P (scope) || !dependent_scope_p (scope))
     {
       res = lookup_qualified_name (scope, res, false, true);
