[clang] 02fccc2 - Revert "DR458: Search template parameter scopes in the right order."

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 16 23:55:03 PDT 2020


Author: Richard Smith
Date: 2020-06-16T23:53:44-07:00
New Revision: 02fccc26cf6af22c07fb81ff3aa69abd77850028

URL: https://github.com/llvm/llvm-project/commit/02fccc26cf6af22c07fb81ff3aa69abd77850028
DIFF: https://github.com/llvm/llvm-project/commit/02fccc26cf6af22c07fb81ff3aa69abd77850028.diff

LOG: Revert "DR458: Search template parameter scopes in the right order."

We weren't re-entering template scopes in the right order, causing this
to break self-host with -fdelayed-template-parsing.

This reverts commit 237c2a23b6d4fa953f5ae910dccf492db61bb959.

Added: 
    

Modified: 
    clang/include/clang/Parse/Parser.h
    clang/include/clang/Sema/Scope.h
    clang/lib/AST/DeclBase.cpp
    clang/lib/Parse/ParseExprCXX.cpp
    clang/lib/Parse/ParseTemplate.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaLookup.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/test/CXX/drs/dr4xx.cpp
    clang/test/CXX/temp/temp.res/temp.local/p8.cpp
    clang/test/SemaCXX/lambda-expressions.cpp
    clang/www/cxx_dr_status.html

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 31840694da27..1ae219781c69 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1088,31 +1088,6 @@ class Parser : public CodeCompletionHandler {
     }
   };
 
-  /// Introduces zero or more scopes for parsing. The scopes will all be exited
-  /// when the object is destroyed.
-  class MultiParseScope {
-    Parser &Self;
-    unsigned NumScopes = 0;
-
-    MultiParseScope(const MultiParseScope&) = delete;
-
-  public:
-    MultiParseScope(Parser &Self) : Self(Self) {}
-    void Enter(unsigned ScopeFlags) {
-      Self.EnterScope(ScopeFlags);
-      ++NumScopes;
-    }
-    void Exit() {
-      while (NumScopes) {
-        Self.ExitScope();
-        --NumScopes;
-      }
-    }
-    ~MultiParseScope() {
-      Exit();
-    }
-  };
-
   /// EnterScope - Start a new scope.
   void EnterScope(unsigned ScopeFlags);
 
@@ -3265,7 +3240,7 @@ class Parser : public CodeCompletionHandler {
       DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,
       ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd,
       ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none);
-  bool ParseTemplateParameters(MultiParseScope &TemplateScopes, unsigned Depth,
+  bool ParseTemplateParameters(unsigned Depth,
                                SmallVectorImpl<NamedDecl *> &TemplateParams,
                                SourceLocation &LAngleLoc,
                                SourceLocation &RAngleLoc);

diff  --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index b7260f15fe1b..9b8f1415a1e3 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -322,21 +322,8 @@ class Scope {
   /// declared in.
   bool isDeclScope(const Decl *D) const { return DeclsInScope.count(D) != 0; }
 
-  /// Get the entity corresponding to this scope.
-  DeclContext *getEntity() const {
-    return isTemplateParamScope() ? nullptr : Entity;
-  }
-
-  /// Get the DeclContext in which to continue unqualified lookup after a
-  /// lookup in this scope.
-  DeclContext *getLookupEntity() const { return Entity; }
-
-  void setEntity(DeclContext *E) {
-    assert(!isTemplateParamScope() &&
-           "entity associated with template param scope");
-    Entity = E;
-  }
-  void setLookupEntity(DeclContext *E) { Entity = E; }
+  DeclContext *getEntity() const { return Entity; }
+  void setEntity(DeclContext *E) { Entity = E; }
 
   /// Determine whether any unrecoverable errors have occurred within this
   /// scope. Note that this may return false even if the scope contains invalid

diff  --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 50ad0255f838..2aab53f4fa90 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -241,7 +241,7 @@ TemplateDecl *Decl::getDescribedTemplate() const {
 }
 
 bool Decl::isTemplated() const {
-  // A declaration is templated if it is a template or a template pattern, or
+  // A declaration is dependent if it is a template or a template pattern, or
   // is within (lexcially for a friend, semantically otherwise) a dependent
   // context.
   // FIXME: Should local extern declarations be treated like friends?

diff  --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index aa35200c33b6..48277dc85466 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -1258,16 +1258,17 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer(
   };
 
   // FIXME: Consider allowing this as an extension for GCC compatibiblity.
-  MultiParseScope TemplateParamScope(*this);
-  if (Tok.is(tok::less)) {
+  const bool HasExplicitTemplateParams = Tok.is(tok::less);
+  ParseScope TemplateParamScope(this, Scope::TemplateParamScope,
+                                /*EnteredScope=*/HasExplicitTemplateParams);
+  if (HasExplicitTemplateParams) {
     Diag(Tok, getLangOpts().CPlusPlus20
                   ? diag::warn_cxx17_compat_lambda_template_parameter_list
                   : diag::ext_lambda_template_parameter_list);
 
     SmallVector<NamedDecl*, 4> TemplateParams;
     SourceLocation LAngleLoc, RAngleLoc;
-    if (ParseTemplateParameters(TemplateParamScope,
-                                CurTemplateDepthTracker.getDepth(),
+    if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(),
                                 TemplateParams, LAngleLoc, RAngleLoc)) {
       Actions.ActOnLambdaError(LambdaBeginLoc, getCurScope());
       return ExprError();

diff  --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 847c513b5baa..16aecffa494a 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -67,7 +67,8 @@ Decl *Parser::ParseTemplateDeclarationOrSpecialization(
   assert(Tok.isOneOf(tok::kw_export, tok::kw_template) &&
          "Token does not start a template declaration.");
 
-  MultiParseScope TemplateParamScopes(*this);
+  // Enter template-parameter scope.
+  ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
 
   // Tell the action that names should be checked in the context of
   // the declaration to come.
@@ -115,8 +116,7 @@ Decl *Parser::ParseTemplateDeclarationOrSpecialization(
     // Parse the '<' template-parameter-list '>'
     SourceLocation LAngleLoc, RAngleLoc;
     SmallVector<NamedDecl*, 4> TemplateParams;
-    if (ParseTemplateParameters(TemplateParamScopes,
-                                CurTemplateDepthTracker.getDepth(),
+    if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(),
                                 TemplateParams, LAngleLoc, RAngleLoc)) {
       // Skip until the semi-colon or a '}'.
       SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
@@ -150,6 +150,9 @@ Decl *Parser::ParseTemplateDeclarationOrSpecialization(
         TemplateParams, RAngleLoc, OptionalRequiresClauseConstraintER.get()));
   } while (Tok.isOneOf(tok::kw_export, tok::kw_template));
 
+  unsigned NewFlags = getCurScope()->getFlags() & ~Scope::TemplateParamScope;
+  ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization);
+
   // Parse the actual template declaration.
   if (Tok.is(tok::kw_concept))
     return ParseConceptDefinition(
@@ -427,9 +430,8 @@ Parser::ParseConceptDefinition(const ParsedTemplateInfo &TemplateInfo,
 ///
 /// \returns true if an error occurred, false otherwise.
 bool Parser::ParseTemplateParameters(
-    MultiParseScope &TemplateScopes, unsigned Depth,
-    SmallVectorImpl<NamedDecl *> &TemplateParams, SourceLocation &LAngleLoc,
-    SourceLocation &RAngleLoc) {
+    unsigned Depth, SmallVectorImpl<NamedDecl *> &TemplateParams,
+    SourceLocation &LAngleLoc, SourceLocation &RAngleLoc) {
   // Get the template parameter list.
   if (!TryConsumeToken(tok::less, LAngleLoc)) {
     Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
@@ -438,11 +440,8 @@ bool Parser::ParseTemplateParameters(
 
   // Try to parse the template parameter list.
   bool Failed = false;
-  // FIXME: Missing greatergreatergreater support.
-  if (!Tok.is(tok::greater) && !Tok.is(tok::greatergreater)) {
-    TemplateScopes.Enter(Scope::TemplateParamScope);
+  if (!Tok.is(tok::greater) && !Tok.is(tok::greatergreater))
     Failed = ParseTemplateParameterList(Depth, TemplateParams);
-  }
 
   if (Tok.is(tok::greatergreater)) {
     // No diagnostic required here: a template-parameter-list can only be
@@ -851,9 +850,9 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
   SmallVector<NamedDecl*,8> TemplateParams;
   SourceLocation LAngleLoc, RAngleLoc;
   {
-    MultiParseScope TemplateParmScope(*this);
-    if (ParseTemplateParameters(TemplateParmScope, Depth + 1, TemplateParams,
-                                LAngleLoc, RAngleLoc)) {
+    ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+    if (ParseTemplateParameters(Depth + 1, TemplateParams, LAngleLoc,
+                               RAngleLoc)) {
       return nullptr;
     }
   }
@@ -1631,7 +1630,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
   Sema::ContextRAII GlobalSavedContext(
       Actions, Actions.Context.getTranslationUnitDecl());
 
-  MultiParseScope Scopes(*this);
+  SmallVector<ParseScope*, 4> TemplateParamScopeStack;
 
   // Get the list of DeclContexts to reenter. For inline methods, we only want
   // to push the DeclContext of the outermost class. This matches the way the
@@ -1656,12 +1655,13 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
 
   // Reenter template scopes from outermost to innermost.
   for (ContainingDC CDC : reverse(DeclContextsToReenter)) {
-    Scopes.Enter(Scope::TemplateParamScope);
+    TemplateParamScopeStack.push_back(
+        new ParseScope(this, Scope::TemplateParamScope));
     unsigned NumParamLists = Actions.ActOnReenterTemplateScope(
         getCurScope(), cast<Decl>(CDC.getDC()));
     CurTemplateDepthTracker.addDepth(NumParamLists);
     if (CDC.shouldPushDC()) {
-      Scopes.Enter(Scope::DeclScope);
+      TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
       Actions.PushDeclContext(Actions.getCurScope(), CDC.getDC());
     }
   }
@@ -1709,6 +1709,13 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
     } else
       Actions.ActOnFinishFunctionBody(LPT.D, nullptr);
   }
+
+  // Exit scopes.
+  FnScope.Exit();
+  SmallVectorImpl<ParseScope *>::reverse_iterator I =
+   TemplateParamScopeStack.rbegin();
+  for (; I != TemplateParamScopeStack.rend(); ++I)
+    delete *I;
 }
 
 /// Lex a delayed template function for late parsing.

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 1d046c776709..2bf16d138d5a 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1358,50 +1358,6 @@ void Sema::EnterDeclaratorContext(Scope *S, DeclContext *DC) {
 
   CurContext = DC;
   S->setEntity(DC);
-
-  if (!S->getParent()->isTemplateParamScope())
-    return;
-
-  // Also set the corresponding entities for all immediately-enclosing template
-  // parameter scopes.
-  //
-  // C++20 [temp.local]p7:
-  //   In the definition of a member of a class template that appears outside
-  //   of the class template definition, the name of a member of the class
-  //   template hides the name of a template-parameter of any enclosing class
-  //   templates (but not a template-parameter of the member if the member is a
-  //   class or function template).
-  // C++20 [temp.local]p9:
-  //   In the definition of a class template or in the definition of a member
-  //   of such a template that appears outside of the template definition, for
-  //   each non-dependent base class (13.8.2.1), if the name of the base class
-  //   or the name of a member of the base class is the same as the name of a
-  //   template-parameter, the base class name or member name hides the
-  //   template-parameter name (6.4.10).
-  //
-  // This means that a template parameter scope should be searched immediately
-  // after searching the DeclContext for which it is a template parameter
-  // scope. For example, for
-  //   template<typename T> template<typename U> template<typename V>
-  //     void N::A<T>::B<U>::f(...)
-  // we search V then B<U> (and base classes) then U then A<T> (and base
-  // classes) then T then N then ::.
-  unsigned ScopeDepth = getTemplateDepth(S);
-  for (Scope *OuterS = S->getParent(); OuterS && OuterS->isTemplateParamScope();
-       OuterS = OuterS->getParent(), --ScopeDepth) {
-    auto *SearchDCAfterScope = DC;
-    for (; DC; DC = DC->getLookupParent()) {
-      if (auto *TD = cast<Decl>(DC)->getDescribedTemplate()) {
-        unsigned DCDepth = TD->getTemplateParameters()->getDepth() + 1;
-        if (DCDepth > ScopeDepth)
-          continue;
-        if (ScopeDepth == DCDepth)
-          SearchDCAfterScope = DC = DC->getLookupParent();
-        break;
-      }
-    }
-    OuterS->setLookupEntity(SearchDCAfterScope);
-  }
 }
 
 void Sema::ExitDeclaratorContext(Scope *S) {

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 5757eaf3fac0..06a4dfa0a636 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1153,14 +1153,73 @@ static bool isNamespaceOrTranslationUnitScope(Scope *S) {
   return false;
 }
 
-/// Find the outer declaration context from this scope. This indicates the
-/// context that we should search up to (exclusive) before considering the
-/// parent of the specified scope.
-static DeclContext *findOuterContext(Scope *S) {
-  for (Scope *OuterS = S->getParent(); OuterS; OuterS = OuterS->getParent())
-    if (DeclContext *DC = OuterS->getLookupEntity())
-      return DC;
-  return nullptr;
+// Find the next outer declaration context from this scope. This
+// routine actually returns the semantic outer context, which may
+// 
diff er from the lexical context (encoded directly in the Scope
+// stack) when we are parsing a member of a class template. In this
+// case, the second element of the pair will be true, to indicate that
+// name lookup should continue searching in this semantic context when
+// it leaves the current template parameter scope.
+static std::pair<DeclContext *, bool> findOuterContext(Scope *S) {
+  DeclContext *DC = S->getEntity();
+  DeclContext *Lexical = nullptr;
+  for (Scope *OuterS = S->getParent(); OuterS;
+       OuterS = OuterS->getParent()) {
+    if (OuterS->getEntity()) {
+      Lexical = OuterS->getEntity();
+      break;
+    }
+  }
+
+  // C++ [temp.local]p8:
+  //   In the definition of a member of a class template that appears
+  //   outside of the namespace containing the class template
+  //   definition, the name of a template-parameter hides the name of
+  //   a member of this namespace.
+  //
+  // Example:
+  //
+  //   namespace N {
+  //     class C { };
+  //
+  //     template<class T> class B {
+  //       void f(T);
+  //     };
+  //   }
+  //
+  //   template<class C> void N::B<C>::f(C) {
+  //     C b;  // C is the template parameter, not N::C
+  //   }
+  //
+  // In this example, the lexical context we return is the
+  // TranslationUnit, while the semantic context is the namespace N.
+  if (!Lexical || !DC || !S->getParent() ||
+      !S->getParent()->isTemplateParamScope())
+    return std::make_pair(Lexical, false);
+
+  // Find the outermost template parameter scope.
+  // For the example, this is the scope for the template parameters of
+  // template<class C>.
+  Scope *OutermostTemplateScope = S->getParent();
+  while (OutermostTemplateScope->getParent() &&
+         OutermostTemplateScope->getParent()->isTemplateParamScope())
+    OutermostTemplateScope = OutermostTemplateScope->getParent();
+
+  // Find the namespace context in which the original scope occurs. In
+  // the example, this is namespace N.
+  DeclContext *Semantic = DC;
+  while (!Semantic->isFileContext())
+    Semantic = Semantic->getParent();
+
+  // Find the declaration context just outside of the template
+  // parameter scope. This is the context in which the template is
+  // being lexically declaration (a namespace context). In the
+  // example, this is the global scope.
+  if (Lexical->isFileContext() && !Lexical->Equals(Semantic) &&
+      Lexical->Encloses(Semantic))
+    return std::make_pair(Semantic, true);
+
+  return std::make_pair(Lexical, false);
 }
 
 namespace {
@@ -1227,11 +1286,13 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
   UnqualUsingDirectiveSet UDirs(*this);
   bool VisitedUsingDirectives = false;
   bool LeftStartingScope = false;
+  DeclContext *OutsideOfTemplateParamDC = nullptr;
 
   // When performing a scope lookup, we want to find local extern decls.
   FindLocalExternScope FindLocals(R);
 
   for (; S && !isNamespaceOrTranslationUnitScope(S); S = S->getParent()) {
+    DeclContext *Ctx = S->getEntity();
     bool SearchNamespaceScope = true;
     // Check whether the IdResolver has anything in this scope.
     for (; I != IEnd && S->isDeclScope(*I); ++I) {
@@ -1263,8 +1324,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
     if (!SearchNamespaceScope) {
       R.resolveKind();
       if (S->isClassScope())
-        if (CXXRecordDecl *Record =
-                dyn_cast_or_null<CXXRecordDecl>(S->getEntity()))
+        if (CXXRecordDecl *Record = dyn_cast_or_null<CXXRecordDecl>(Ctx))
           R.setNamingClass(Record);
       return true;
     }
@@ -1278,8 +1338,24 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
       return false;
     }
 
-    if (DeclContext *Ctx = S->getLookupEntity()) {
-      DeclContext *OuterCtx = findOuterContext(S);
+    if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
+        S->getParent() && !S->getParent()->isTemplateParamScope()) {
+      // We've just searched the last template parameter scope and
+      // found nothing, so look into the contexts between the
+      // lexical and semantic declaration contexts returned by
+      // findOuterContext(). This implements the name lookup behavior
+      // of C++ [temp.local]p8.
+      Ctx = OutsideOfTemplateParamDC;
+      OutsideOfTemplateParamDC = nullptr;
+    }
+
+    if (Ctx) {
+      DeclContext *OuterCtx;
+      bool SearchAfterTemplateScope;
+      std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+      if (SearchAfterTemplateScope)
+        OutsideOfTemplateParamDC = OuterCtx;
+
       for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
         // We do not directly look into transparent contexts, since
         // those entities will be found in the nearest enclosing
@@ -1404,9 +1480,25 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
       return true;
     }
 
-    DeclContext *Ctx = S->getLookupEntity();
+    DeclContext *Ctx = S->getEntity();
+    if (!Ctx && S->isTemplateParamScope() && OutsideOfTemplateParamDC &&
+        S->getParent() && !S->getParent()->isTemplateParamScope()) {
+      // We've just searched the last template parameter scope and
+      // found nothing, so look into the contexts between the
+      // lexical and semantic declaration contexts returned by
+      // findOuterContext(). This implements the name lookup behavior
+      // of C++ [temp.local]p8.
+      Ctx = OutsideOfTemplateParamDC;
+      OutsideOfTemplateParamDC = nullptr;
+    }
+
     if (Ctx) {
-      DeclContext *OuterCtx = findOuterContext(S);
+      DeclContext *OuterCtx;
+      bool SearchAfterTemplateScope;
+      std::tie(OuterCtx, SearchAfterTemplateScope) = findOuterContext(S);
+      if (SearchAfterTemplateScope)
+        OutsideOfTemplateParamDC = OuterCtx;
+
       for (; Ctx && !Ctx->Equals(OuterCtx); Ctx = Ctx->getLookupParent()) {
         // We do not directly look into transparent contexts, since
         // those entities will be found in the nearest enclosing
@@ -3903,12 +3995,14 @@ class LookupVisibleHelper {
       }
     }
 
-    DeclContext *Entity = S->getLookupEntity();
-    if (Entity) {
+    // FIXME: C++ [temp.local]p8
+    DeclContext *Entity = nullptr;
+    if (S->getEntity()) {
       // Look into this scope's declaration context, along with any of its
       // parent lookup contexts (e.g., enclosing classes), up to the point
       // where we hit the context stored in the next outer scope.
-      DeclContext *OuterCtx = findOuterContext(S);
+      Entity = S->getEntity();
+      DeclContext *OuterCtx = findOuterContext(S).first; // FIXME
 
       for (DeclContext *Ctx = Entity; Ctx && !Ctx->Equals(OuterCtx);
            Ctx = Ctx->getLookupParent()) {

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 6bf46f273a02..073b4e818a24 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -51,7 +51,8 @@ unsigned Sema::getTemplateDepth(Scope *S) const {
 
   // Each template parameter scope represents one level of template parameter
   // depth.
-  for (Scope *TempParamScope = S->getTemplateParamParent(); TempParamScope;
+  for (Scope *TempParamScope = S->getTemplateParamParent();
+       TempParamScope && !Depth;
        TempParamScope = TempParamScope->getParent()->getTemplateParamParent()) {
     ++Depth;
   }

diff  --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp
index ff90ee82d4d4..2c762237037d 100644
--- a/clang/test/CXX/drs/dr4xx.cpp
+++ b/clang/test/CXX/drs/dr4xx.cpp
@@ -690,7 +690,7 @@ namespace dr457 { // dr457: yes
   };
 }
 
-namespace dr458 { // dr458: 11
+namespace dr458 { // dr458: no
   struct A {
     int T;
     int f();
@@ -706,9 +706,9 @@ namespace dr458 { // dr458: 11
   int A::f() {
     return T;
   }
-  template<typename T> // expected-note {{declared here}}
+  template<typename T>
   int A::g() {
-    return T; // expected-error {{'T' does not refer to a value}}
+    return T; // FIXME: this is invalid, it finds the template parameter
   }
 
   template<typename T>
@@ -719,9 +719,9 @@ namespace dr458 { // dr458: 11
   int B<T>::g() {
     return T;
   }
-  template<typename U> template<typename T> // expected-note {{declared here}}
+  template<typename U> template<typename T>
   int B<U>::h() {
-    return T; // expected-error {{'T' does not refer to a value}}
+    return T; // FIXME: this is invalid, it finds the template parameter
   }
 }
 

diff  --git a/clang/test/CXX/temp/temp.res/temp.local/p8.cpp b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp
index c2b4c1950ea5..fecfed06f109 100644
--- a/clang/test/CXX/temp/temp.res/temp.local/p8.cpp
+++ b/clang/test/CXX/temp/temp.res/temp.local/p8.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
 
 namespace N { 
   enum { C };
@@ -51,63 +52,3 @@ void N::Y::f(D) {
   D d;
 }
 
-// Ensure we properly interleave the searches within classes and template parameter lists.
-namespace SearchClassBetweenTemplateParameterLists {
-  int AA, BB; // none of the below lookups should ever consider these
-
-  template<typename T> struct A {
-    using AA = void;
-    template<typename U> struct B {
-      using BB = void;
-      void f(U);
-      void g(U);
-      void h(T);
-      void i(T);
-      template<typename V> void j(V);
-      template<typename V> void k(U);
-    };
-  };
-
-  // Search order for the below is:
-  // 1) template parameter scope of the function itself (if any)
-  // 2) class of which function is a member
-  // 3) template parameter scope of inner class
-  // 4) class of which class is a member
-  // 5) template parameter scope of outer class
-
-  // OK, 'AA' found in (3)
-  template<typename T> template<typename AA>
-  void A<T>::B<AA>::f(AA) {
-    AA aa;
-  }
-
-  // error, 'BB' found in (2)
-  template<typename T> template<typename BB>
-  void A<T>::B<BB>::g(BB) { // expected-error {{does not match}}
-    BB bb; // expected-error {{incomplete type}}
-  }
-
-  // error, 'AA' found in (4)
-  template<typename AA> template<typename U>
-  void A<AA>::B<U>::h(AA) { // expected-error {{does not match}}
-    AA aa; // expected-error {{incomplete type}}
-  }
-
-  // error, 'BB' found in (2)
-  template<typename BB> template<typename U>
-  void A<BB>::B<U>::i(BB) { // expected-error {{does not match}}
-    BB bb; // expected-error {{incomplete type}}
-  }
-
-  // OK, 'BB' found in (1)
-  template<typename T> template<typename U> template<typename BB>
-  void A<T>::B<U>::j(BB) {
-    BB bb;
-  }
-
-  // error, 'BB' found in (2)
-  template<typename T> template<typename BB> template<typename V>
-  void A<T>::B<BB>::k(V) { // expected-error {{does not match}}
-    BB bb; // expected-error {{incomplete type}}
-  }
-}

diff  --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index 3240d5351fc5..0f4edc4d1f34 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -601,24 +601,16 @@ namespace ConversionOperatorDoesNotHaveDeducedReturnType {
 #if __cplusplus > 201402L
     friend constexpr auto T::operator()(int) const;
     friend constexpr T::operator ExpectedTypeT() const noexcept;
-
-    template<typename T>
-      friend constexpr void U::operator()(T&) const;
-    // FIXME: This should not match; the return type is specified as behaving
-    // "as if it were a decltype-specifier denoting the return type of
-    // [operator()]", which is not equivalent to this alias template.
-    template<typename T>
-      friend constexpr U::operator ExpectedTypeU<T>() const noexcept;
 #else
     friend auto T::operator()(int) const;
     friend T::operator ExpectedTypeT() const;
+#endif
 
+    // FIXME: The first of these should match. The second should not.
     template<typename T>
-      friend void U::operator()(T&) const;
-    // FIXME: This should not match, as above.
+      friend void U::operator()(T&) const; // expected-error {{does not match}}
     template<typename T>
-      friend U::operator ExpectedTypeU<T>() const;
-#endif
+      friend U::operator ExpectedTypeU<T>() const; // expected-error {{does not match}}
 
   private:
     int n;

diff  --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index 22755e4b20ea..4abdc0fa2639 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -2789,7 +2789,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://wg21.link/cwg458">458</a></td>
     <td>C++11</td>
     <td>Hiding of member template parameters by other members</td>
-    <td class="unreleased" align="center">Clang 11</td>
+    <td class="none" align="center">No</td>
   </tr>
   <tr class="open" id="459">
     <td><a href="https://wg21.link/cwg459">459</a></td>
@@ -12307,7 +12307,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://wg21.link/cwg2082">2082</a></td>
     <td>CD4</td>
     <td>Referring to parameters in unevaluated operands of default arguments</td>
-    <td class="unreleased" align="center">Clang 11</td>
+    <td class="none" align="center">Unknown</td>
   </tr>
   <tr id="2083">
     <td><a href="https://wg21.link/cwg2083">2083</a></td>
@@ -13891,7 +13891,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
     <td><a href="https://wg21.link/cwg2346">2346</a></td>
     <td>DRWP</td>
     <td>Local variables in default arguments</td>
-    <td class="unreleased" align="center">Clang 11</td>
+    <td class="none" align="center">Unknown</td>
   </tr>
   <tr id="2347">
     <td><a href="https://wg21.link/cwg2347">2347</a></td>


        


More information about the cfe-commits mailing list