rsmith added inline comments.

================
Comment at: clang/include/clang/Sema/DeclSpec.h:1753-1758
+// Describes whether the current context is a context where an implicit
+// typename is allowed (C++2a [temp.res]p5]).
+enum ImplicitTypenameContext {
+  ITC_Never,
+  ITC_Yes,
+};
----------------
Consider using an `enum class` here.


================
Comment at: clang/lib/Parse/ParseDecl.cpp:2652-2654
+      // But only if we are not in a function prototype scope.
+      if (getCurScope()->isFunctionPrototypeScope())
+        break;
----------------
rsmith wrote:
> Can you split out this error recovery improvement and commit it separately 
> before the rest of this work? It doesn't appear to have any dependency on the 
> rest of the change.
Looks like you need to rebase; the change was committed but is still in the 
latest version of this patch.


================
Comment at: clang/lib/Parse/ParseDecl.cpp:4321
+             isCXXDeclarationSpecifier(ITC_Never, TPResult::True) !=
+                 TPResult::True) ||
+            (!getLangOpts().CPlusPlus && !isDeclarationSpecifier(ITC_Yes))) {
----------------
It seems like a wording oversight that we don't assume `typename` in an 
//enum-base//. Probably would be good to raise this on the core reflector.


================
Comment at: clang/lib/Parse/ParseDecl.cpp:4322
+                 TPResult::True) ||
+            (!getLangOpts().CPlusPlus && !isDeclarationSpecifier(ITC_Yes))) {
           // We'll parse this as a bitfield later.
----------------
Using a different `ITC` value for non-C++ compilations seems surprising. (It 
should never make any difference outside of C++, but leaves the reader 
wondering why the two are different.) Can we use `ITC_Never` here for 
consistency?


================
Comment at: clang/lib/Parse/ParseDecl.cpp:5100-5101
   bool IsConstructor = false;
-  if (isDeclarationSpecifier())
+  if (isDeclarationSpecifier(ITC_Never))
     IsConstructor = true;
   else if (Tok.is(tok::identifier) ||
----------------
Oh, this could be a problem.

If this *is* a constructor declaration, then this is implicit typename context: 
this is either a "//parameter-declaration// in a //member-declaration//" 
([temp.res]/5.2.3) or a "//parameter-declaration// in a //declarator// of a 
function or function template declaration whose //declarator-id// is 
qualified". But if it's *not* a constructor declaration, then this is either 
the //declarator-id// of a declaration or the //nested-name-specifier// of a 
pointer-to-member declarator:

```
template<typename T>
struct C {
  C(T::type); // implicit typename context
  friend C (T::fn)(); // not implicit typename context, declarator-id of friend 
declaration
  C(T::type::*x)[3]; // not implicit typename context, pointer-to-member type
};
```

I think we need to use `ITC_Yes` here, in order to correctly disambiguate the 
first example above. Please add tests for the other two cases to make sure this 
doesn't break them -- but I'm worried this **will** break the second case, 
because it will incorrectly annotate `T::fn` as a type.


================
Comment at: clang/lib/Sema/Sema.cpp:2219
+  
+  D.setPrevLookupResult(llvm::make_unique<LookupResult>(std::move(LR)));
+  return Result;
----------------
Consider moving the `make_unique` earlier (directly before 
`LookupQualifiedName`) to avoid needing to move the `LookupResult` object into 
different storage here.


================
Comment at: clang/lib/Sema/SemaTemplate.cpp:3369
     if (!LookupCtx && isDependentScopeSpecifier(SS)) {
-      Diag(SS.getBeginLoc(), diag::err_typename_missing_template)
-        << SS.getScopeRep() << TemplateII->getName();
-      // Recover as if 'typename' were specified.
+      // C++2a relaxes some of those restrictinos in [temp.res]p5.
+      if (getLangOpts().CPlusPlus2a)
----------------
Are there any cases where we would call this for which C++20 still requires a 
`typename` keyword? Should this function be passed an `ImplicitTypenameContext`?


================
Comment at: clang/lib/Sema/SemaTemplate.cpp:3377-3379
       // FIXME: This is not quite correct recovery as we don't transform SS
       // into the corresponding dependent form (and we don't diagnose missing
       // 'template' keywords within SS as a result).
----------------
This FIXME is concerning. Is this a problem with this patch? (Is the FIXME 
wrong now?)


================
Comment at: clang/test/CXX/drs/dr5xx.cpp:485
 namespace dr542 { // dr542: yes
-#if __cplusplus >= 201103L
+#if __cplusplus >= 201103L && __cplusplus <= 201703L
   struct A { A() = delete; int n; };
----------------
A comment here explaining that `A` and `B` stop being aggregates in C++20 would 
be nice. (Nicer would be changing the testcase so it still tests the relevant 
rule in C++20 mode, if that's possible...)


================
Comment at: clang/test/CXX/temp/temp.res/p5.cpp:1
+// RUN: %clang_cc1 -std=c++2a -pedantic -verify %s
+
----------------
Please add tests for enum-base and conversion-type-id:

```
template<typename T> struct A {
  enum E : T::type {};
  operator T::type() {}
  void f() { this->operator T::type(); }
};
```

... which should currently be rejected.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53847/new/

https://reviews.llvm.org/D53847



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to