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)
      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,
 
     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;
    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.
    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
   /* 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.  */
       }
 
   /* Now lookup in namespace scopes.  */
-  if (!val)
+  if (!val && (where & LOOK_where::NAMESPACE))
     {
       name_lookup lookup (name, flags);
       if (lookup.search_unqualified
 /* 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;
 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
 
 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);
 
       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;
     }
 
       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))
     {
   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
            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))
 
 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))
 
     }
   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);