rsmith added inline comments.

================
Comment at: clang/include/clang/AST/DeclTemplate.h:213
+    else if (Idx >= TPL->size())
+      return false;
+    else {
----------------
We should return `true` in this case; we don't know what the corresponding 
parameter is so we don't know if the type matters.


================
Comment at: clang/include/clang/AST/DeclTemplate.h:216
+      const NamedDecl *TemplParam = TPL->getParam(Idx);
+      if (auto *ParamValueDecl = dyn_cast<ValueDecl>(TemplParam))
+        if (ParamValueDecl->getType()->getContainedDeducedType())
----------------
May as well go straight to `NonTypeTemplateParamDecl` here; it can't be any 
other kind of `ValueDecl`.


================
Comment at: clang/include/clang/AST/StmtDataCollectors.td:48-72
+      const TemplateParameterList *TPL = nullptr;
+      if (auto SD = dyn_cast<DeclRefExpr>(S))
+        if (!SD->hadMultipleCandidates())
+          if (auto *TD = dyn_cast<TemplateDecl>(D))
+            TPL = TD->getTemplateParameters();
       if (auto Args = D->getTemplateSpecializationArgs()) {
         std::string ArgString;
----------------
I'm not entirely sure what this is used for, but it looks like the goal is 
uniqueness, not human-readability, given that the template arguments are 
separated by newlines not by commas or similar. That being the case, I think we 
should unconditionally pass `true` as `IncludeType` here.


================
Comment at: clang/include/clang/AST/StmtDataCollectors.td:61-64
+          }  else if (i >= TPL->size()) {
+            Args->get(i).print(Context.getLangOpts(), OS, /*IncludeType*/ 
false);
+          }
+          else {
----------------
Nit: exactly one space between `}` and `else`. (You have two spaces in the 
first instance here and a newline in the second instance.)


================
Comment at: clang/lib/AST/ASTContext.cpp:7462
+            OS, TemplateArgs.asArray(), getPrintingPolicy(),
+            Spec->getSpecializedTemplate()->getTemplateParameters());
       }
----------------
Pass `nullptr` here; for ObjC `@encode` we presumably want fully-explicit 
output always.


================
Comment at: clang/lib/AST/DeclPrinter.cpp:651-652
+                                           ->getTemplateParameters();
+    // FIXME: Check if function template is overloaded
+    bool TemplOverloaded = false;
     if (TArgAsWritten && !Policy.PrintCanonicalTypes)
----------------
We should conservatively assume that it is, rather than potentially printing 
out an ambiguous AST fragment.


================
Comment at: clang/lib/AST/DeclPrinter.cpp:994-995
             Args = TST->template_arguments();
-      printTemplateArguments(Args);
+      // FIXME: Check if function template is overloaded
+      bool TemplOverloaded = false;
+      printTemplateArguments(
----------------
This is a class template specialization, not a function template 
specialization. It can't be overloaded.


================
Comment at: clang/lib/AST/DeclTemplate.cpp:1437
     OS << "<";
+    // FIXME: Only pass parameter if template is not overloaded
+    // FIXME: Find corresponding parameter for argument
----------------
Concepts can't be overloaded; remove this FIXME.


================
Comment at: clang/lib/AST/Expr.cpp:702
         TOut << Param << " = ";
-        Args.get(i).print(Policy, TOut);
+        // FIXME: Only pass parameter if template is overloaded
+        Args.get(i).print(
----------------
Remove this FIXME: class template specializations can't be overloaded.


================
Comment at: clang/lib/AST/StmtPrinter.cpp:1450
+  if (auto *FD = dyn_cast<FunctionDecl>(Node->getMemberDecl()))
+    TPL = FD->getDescribedTemplateParams();
+  else if (auto *TD =
----------------
This isn't right: `getDescribedTemplateParams` handles the case where the 
declaration is the pattern in a template definition, not where it's a template 
instantiation. What you want here is:

```
if (auto *FTD = FD->getPrimaryTemplate())
  TPL = FTD->getTemplateParameters();
```

You should also take into account `Node->hadMultipleCandidates()` here.

Testcase for this would be something like:
```
struct A {
  template<long, auto> void f();
};
void g(A a) { a.f<0L, 0L>(); }
```
... for which `-ast-print` should produce `f<0, 0L>`.


================
Comment at: clang/lib/AST/StmtPrinter.cpp:1453
+               dyn_cast<VarTemplateSpecializationDecl>(Node->getMemberDecl()))
+    TPL = TD->getDescribedTemplateParams();
   if (Node->hasExplicitTemplateArgs())
----------------
This is likewise not right. In this case we always know there's a template, so 
it's slightly simpler:
```
TPL = TD->getSpecializedTemplate()->getTemplateParameters();
```
Please also rename `TD` to something more appropriate.

Testcase for this would be something like:
```
struct A {
  template<long> static int x;
  template<auto> static int y;
};
int k = A().x<0L> + A().y<0L>;
```
... for which `-ast-print` should produce `x<0>` but `y<0L>`.


================
Comment at: clang/lib/AST/TemplateBase.cpp:54
+///
+/// \param IncludeType the flag to determine printing type information.
+static void printIntegral(const TemplateArgument &TemplArg, raw_ostream &Out,
----------------
I don't think this is very clear about the purpose of the flag. How about:
```
\param IncludeType If set, ensure that the type of the expression printed 
matches the type of the template argument.
```


================
Comment at: clang/lib/AST/TemplateBase.cpp:111-115
+          Out << "u8'" << Val << "'";
+        else if (T->isUnsignedIntegerType() && T->isChar16Type())
+          Out << "u16'" << Val << "'";
+        else if (T->isUnsignedIntegerType() && T->isChar32Type())
+          Out << "u32'" << Val << "'";
----------------
This isn't correct: `u8'x'` will print as `u8'120'`. Perhaps you can factor 
code to do this properly out of `StmtPrinter::VisitCharacterLiteral`.

Also, the prefix for `char16_t` literals is `u`, not `u16`, and the prefix for 
`char32_t` literals is `U`, not `u32`.


================
Comment at: clang/lib/AST/TemplateBase.cpp:79-84
+    if (IncludeType) {
+      if (T->isSignedIntegerType())
+        Out << "(signed char)";
+      else
+        Out << "(unsigned char)";
+    }
----------------
rsmith wrote:
> We should not include a cast for plain `char`, only for `signed char` and 
> `unsigned char`.
This is marked 'done' but not done. Note that plain `char` is always either a 
signed or unsigned type, so your check here does not work. You can check 
`T->isSpecificBuiltinType(BuiltinType::SChar)` and 
`T->isSpecificBuiltinType(BuiltinType::UChar)` instead.


================
Comment at: clang/lib/AST/TemplateBase.cpp:395
 
   case Declaration: {
     NamedDecl *ND = getAsDecl();
----------------
rsmith wrote:
> Please add a FIXME to handle `knownType` here.
This is marked as done but not done. (The template parameter object case has a 
FIXME but the other cases do not and should.)


================
Comment at: clang/lib/AST/TemplateBase.cpp:71-72
 
   if (T->isBooleanType() && !Policy.MSVCFormatting) {
     Out << (Val.getBoolValue() ? "true" : "false");
   } else if (T->isCharType()) {
----------------
rsmith wrote:
> rnk wrote:
> > rsmith wrote:
> > > reikdas wrote:
> > > > rsmith wrote:
> > > > > rsmith wrote:
> > > > > > It looks like `MSVCFormatting` wants `bool` values to be printed as 
> > > > > > `0` and `1`, and this patch presumably changes that (along with the 
> > > > > > printing of other builtin types). I wonder if this is a problem in 
> > > > > > practice (eg, if such things are used as keys for debug info or 
> > > > > > similar)...
> > > > > Do we need to suppress printing the suffixes below in 
> > > > > `MSVCFormatting` mode too?
> > > > @rsmith The tests pass, so that is reassuring at least. Is there any 
> > > > other way to find out whether we need to suppress printing the suffixes 
> > > > for other types in MSVCFormatting mode?
> > > @rnk Can you take a look at this? Per 
> > > rG60103383f097b6580ecb4519eeb87defdb7c05c9 and PR21528 it seems like 
> > > there might be specific requirements for how template arguments are 
> > > formatted for CodeView support; we presumably need to make sure we still 
> > > satisfy those requirements.
> > Probably. This change looks like it preserves behavior from before when 
> > `MSVCFormatting` is set, so I think this is OK. I checked, my version of 
> > MSVC still uses 1/0 in debug info for boolean template args.
> My concern is that we're changing the behavior for the other cases below in 
> `MSVCFormatting` mode, not that we're changing the behavior for `bool`. If we 
> have specific formatting requirements in `MSVCFormatting` mode, they 
> presumably apply to all types, not only to `bool`, so we should be careful to 
> not change the output in `MSVCFormatting` mode for any type.
@rnk Ping.


================
Comment at: clang/lib/AST/TypePrinter.cpp:1980
   bool FirstArg = true;
+  unsigned i = 0;
   for (const auto &Arg : Args) {
----------------
Please capitalize this, following the naming convention of the surrounding code.


================
Comment at: clang/lib/AST/TypePrinter.cpp:1989
         OS << Comma;
-      printTo(ArgOS, Argument.getPackAsArray(), Policy, true, nullptr);
+      printTo(ArgOS, Argument.getPackAsArray(), Policy, true, TPL);
     } else {
----------------
This is wrong; we'll incorrectly assume that element `i` of the pack 
corresponds to element `i` of the original template parameter list. We should 
use the same template parameter for all elements of the pack. (For example, you 
could pass in `I` and instruct the inner invocation of `printTo` to not 
increment `I` as it goes.)


================
Comment at: clang/lib/Sema/SemaDeclCXX.cpp:992
                                      TemplateArgumentListInfo &Args,
+                                     const TemplateParameterList *Params,
                                      unsigned DiagID) {
----------------
It doesn't make sense to pass a parameter list in here, because we've not 
selected a template yet.


================
Comment at: clang/lib/Sema/SemaDeclCXX.cpp:1035
           Loc, TraitTy, DiagID,
-          printTemplateArgs(S.Context.getPrintingPolicy(), Args));
+          printTemplateArgs(S.Context.getPrintingPolicy(), Args, Params));
     return true;
----------------
In this case, the parameter list is `TraitTD->getTemplateParameters()`.


================
Comment at: clang/lib/Sema/SemaTemplateDeduction.cpp:4723-4726
+        if (!TPL)
+          Arg.print(S.getPrintingPolicy(), OS, /*IncludeType*/ true);
+        else if (i >= TPL->size())
+          Arg.print(S.getPrintingPolicy(), OS, /*IncludeType*/ false);
----------------
rsmith wrote:
> Hm, are we missing commas between these arguments?
> 
> Please consider whether this and some of the other repeated instances of this 
> code can be replaced by calls to `printTemplateArgumentList`.
Ping, can this be replaced by a call to `printTemplateArgumentList`?


================
Comment at: clang/lib/Sema/SemaTemplateInstantiate.cpp:814-818
+      if (!isa<FunctionDecl>(Active->Entity)) {
+        const TemplateParameterList *TPL = nullptr;
+        if (auto *TD = dyn_cast<TemplateDecl>(Active->Entity))
+          TPL = TD->getTemplateParameters();
+        // FIXME: Only pass parameter list if template is not overloaded
----------------
rsmith wrote:
> In this case, including substituted default argument values seems important.
Sorry, I wasn't clear: I think we should not include the template parameters 
here, so that we do print out substituted template arguments even if they're 
equivalent to the default argument.


================
Comment at: clang/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp:471
+  template <auto... N> struct X {};
+  X<1, 1u>::type y; // expected-error {{no type named 'type' in 
'TypeSuffix::X<1, 1u>'}}
+  X<1, 1>::type z; // expected-error {{no type named 'type' in 
'TypeSuffix::X<1, 1>'}}
----------------
reikdas wrote:
> @rsmith This test fails and we are unable to print the suffix here because 
> the length of the TemplateParameterList is less than the length of the 
> corresponding list of Template Arguments. Do you have any suggestions on how 
> we can fix this?
Once we hit a template parameter pack, we should use the same parameter for all 
subsequent arguments.


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

https://reviews.llvm.org/D77598

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D77598: I... Richard Smith - zygoloid via Phabricator via cfe-commits

Reply via email to