[clang] 8518742 - Fix type printing of array template args

Vassil Vassilev via cfe-commits cfe-commits at lists.llvm.org
Sat May 1 11:53:04 PDT 2021


Author: Pratyush Das
Date: 2021-05-01T18:50:09Z
New Revision: 8518742104ab075296722ef6151f65aee7a0646d

URL: https://github.com/llvm/llvm-project/commit/8518742104ab075296722ef6151f65aee7a0646d
DIFF: https://github.com/llvm/llvm-project/commit/8518742104ab075296722ef6151f65aee7a0646d.diff

LOG: Fix type printing of array template args

The code example:
```
constexpr const char kEta[] = "Eta";
template <const char*, typename T> class Column {};
using quick = Column<kEta,double>;

void lookup() {
  quick c1;
  c1.ls();
}
```

emits error: no member named 'ls' in 'Column<&kEta, double>'. The patch fixes
the printed type name by not printing the ampersand for array types.

Differential Revision: https://reviews.llvm.org/D36368

Added: 
    

Modified: 
    clang/lib/AST/TemplateBase.cpp
    clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp
    clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index baf62bd115a85..b1816ff8aeb16 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -80,6 +80,26 @@ static void printIntegral(const TemplateArgument &TemplArg,
   }
 }
 
+static unsigned getArrayDepth(QualType type) {
+  unsigned count = 0;
+  while (const auto *arrayType = type->getAsArrayTypeUnsafe()) {
+    count++;
+    type = arrayType->getElementType();
+  }
+  return count;
+}
+
+static bool needsAmpersandOnTemplateArg(QualType paramType, QualType argType) {
+  // Generally, if the parameter type is a pointer, we must be taking the
+  // address of something and need a &.  However, if the argument is an array,
+  // this could be implicit via array-to-pointer decay.
+  if (!paramType->isPointerType())
+    return paramType->isMemberPointerType();
+  if (argType->isArrayType())
+    return getArrayDepth(argType) == getArrayDepth(paramType->getPointeeType());
+  return true;
+}
+
 //===----------------------------------------------------------------------===//
 // TemplateArgument Implementation
 //===----------------------------------------------------------------------===//
@@ -363,8 +383,10 @@ void TemplateArgument::print(const PrintingPolicy &Policy,
         break;
       }
     }
-    if (!getParamTypeForDecl()->isReferenceType())
-      Out << '&';
+    if (auto *VD = dyn_cast<ValueDecl>(ND)) {
+      if (needsAmpersandOnTemplateArg(getParamTypeForDecl(), VD->getType()))
+        Out << "&";
+    }
     ND->printQualifiedName(Out);
     break;
   }

diff  --git a/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp b/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp
index 4f85effdc700f..055ac64b9955d 100644
--- a/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp
+++ b/clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp
@@ -86,6 +86,12 @@ void fn_tmpl() {}
 template void fn_tmpl<int, freefunc>();
 // CHECK-DAG: "fn_tmpl<int,&freefunc>"
 
+template <typename T, void (*)(void)>
+void fn_tmpl_typecheck() {}
+
+template void fn_tmpl_typecheck<int, &freefunc>();
+// CHECK-DAG: "fn_tmpl_typecheck<int,&freefunc>"
+
 template <typename A, typename B, typename C> struct ClassTemplate { A a; B b; C c; };
 ClassTemplate<char, short, ClassTemplate<int, int, int> > f;
 // This will only show up in normal debug builds.  The space in `> >` is

diff  --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 522835f33454c..5752cbac0291d 100644
--- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -77,3 +77,40 @@ namespace ReferenceToConstexpr {
   };
   void f(C<a> ca) { ca.f({}, 0); }
 }
+
+using FourChars = const char[4];
+constexpr FourChars kEta = "Eta";
+constexpr const char kDes[4] = "Des";
+constexpr const char *kNull = "Phi";
+constexpr const char **kZero[] = {};
+
+template <const char *, typename T> class Column {};
+template <const char[], typename T> class Dolumn {};
+template <const char (*)[4], typename T> class Folumn {};
+template <FourChars *, typename T> class Golumn {};
+template <const char *const *, typename T> class Holumn {};
+template <const char *const *const *, typename T> class Jolumn {};
+template <const char **const (*)[0], typename T> class Iolumn {};
+
+class container {
+public:
+  int a;
+};
+template <int container::*> class Kolumn {};
+
+void lookup() {
+  Column<kEta, double>().ls();    // expected-error {{<kEta,}}
+  Column<kDes, double>().ls();    // expected-error {{<kDes,}}
+  Column<nullptr, double>().ls(); // expected-error {{<nullptr,}}
+  Dolumn<kEta, double>().ls();    // expected-error {{<kEta,}}
+  Dolumn<kDes, double>().ls();    // expected-error {{<kDes,}}
+  Folumn<&kEta, double>().ls();   // expected-error {{<&kEta,}}
+  Folumn<&kDes, double>().ls();   // expected-error {{<&kDes,}}
+  Golumn<&kEta, double>().ls();   // expected-error {{<&kEta,}}
+  Golumn<&kDes, double>().ls();   // expected-error {{<&kDes,}}
+  Holumn<&kNull, double>().ls();  // expected-error {{<&kNull,}}
+  Jolumn<kZero, double>().ls();   // expected-error {{<kZero,}}
+  Iolumn<&kZero, double>().ls();  // expected-error {{<&kZero,}}
+  Kolumn<&container::a>().ls();   // expected-error {{<&container::a}}
+  Kolumn<nullptr>().ls();         // expected-error {{<nullptr}}
+}


        


More information about the cfe-commits mailing list