Commit cf7a59f2 authored by Reid Kleckner's avatar Reid Kleckner
Browse files

Merging r359809:

------------------------------------------------------------------------
r359809 | rnk | 2019-05-02 10:45:54 -0700 (Thu, 02 May 2019) | 27 lines

Use primary template parameter names for variable template debug info

Summary:
Fixes PR41677

Consider:
  template <typename LHS, typename RHS> constexpr bool is_same_v = false;
  template <typename T> constexpr bool is_same_v<T, T> = true;
  template constexpr bool is_same_v<int, int>;

Before this change, when emitting debug info for the
`is_same_v<int, int>` global variable, clang would crash because it
would try to use the template parameter list from the partial
specialization to give parameter names to template arguments. This
doesn't work in general, since a partial specialization can have fewer
arguments than the primary template. Therefore, always use the primary
template. Hypothetically we could try to use the parameter names from
the partial specialization when possible, but it's not clear this really
helps debugging in practice.

Reviewers: JDevlieghere, aprantl, ormris, dblaikie

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D61408
------------------------------------------------------------------------

llvm-svn: 364483
parent 21f32a96
Loading
Loading
Loading
Loading
+14 −22
Original line number Diff line number Diff line
@@ -1818,31 +1818,23 @@ CGDebugInfo::CollectFunctionTemplateParams(const FunctionDecl *FD,

llvm::DINodeArray CGDebugInfo::CollectVarTemplateParams(const VarDecl *VL,
                                                        llvm::DIFile *Unit) {
  if (auto *TS = dyn_cast<VarTemplateSpecializationDecl>(VL)) {
    auto T = TS->getSpecializedTemplateOrPartial();
  // Always get the full list of parameters, not just the ones from the
  // specialization. A partial specialization may have fewer parameters than
  // there are arguments.
  auto *TS = dyn_cast<VarTemplateSpecializationDecl>(VL);
  if (!TS)
    return llvm::DINodeArray();
  VarTemplateDecl *T = TS->getSpecializedTemplate();
  const TemplateParameterList *TList = T->getTemplateParameters();
  auto TA = TS->getTemplateArgs().asArray();
    // Collect parameters for a partial specialization
    if (T.is<VarTemplatePartialSpecializationDecl *>()) {
      const TemplateParameterList *TList =
        T.get<VarTemplatePartialSpecializationDecl *>()
        ->getTemplateParameters();
  return CollectTemplateParams(TList, TA, Unit);
}

    // Collect parameters for an explicit specialization
    if (T.is<VarTemplateDecl *>()) {
      const TemplateParameterList *TList = T.get<VarTemplateDecl *>()
        ->getTemplateParameters();
      return CollectTemplateParams(TList, TA, Unit);
    }
  }
  return llvm::DINodeArray();
}

llvm::DINodeArray CGDebugInfo::CollectCXXTemplateParams(
    const ClassTemplateSpecializationDecl *TSpecial, llvm::DIFile *Unit) {
  // Always get the full list of parameters, not just the ones from
  // the specialization.
  // Always get the full list of parameters, not just the ones from the
  // specialization. A partial specialization may have fewer parameters than
  // there are arguments.
  TemplateParameterList *TPList =
      TSpecial->getSpecializedTemplate()->getTemplateParameters();
  const TemplateArgumentList &TAList = TSpecial->getTemplateArgs();
+1 −1
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ inline int add3(int x) {
// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
// CHECK-SAME: name: "var"
// CHECK-SAME: templateParams: {{![0-9]+}}
// CHECK: !DITemplateTypeParameter(name: "P", type: {{![0-9]+}})
// CHECK: !DITemplateTypeParameter(name: "T", type: {{![0-9]+}})
// CHECK: {{![0-9]+}} = distinct !DIGlobalVariable(
// CHECK-SAME: name: "varray"
// CHECK-SAME: templateParams: {{![0-9]+}}
+17 −0
Original line number Diff line number Diff line
// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu %s -o - -debug-info-kind=limited | FileCheck %s

template <typename LHS, typename RHS> constexpr bool is_same_v = false;
template <typename T> constexpr bool is_same_v<T, T> = true;

template constexpr bool is_same_v<int, int>;
static_assert(is_same_v<int, int>, "should get partial spec");

// Note that the template arguments for the instantiated variable use the
// parameter names from the primary template. The partial specialization might
// not have enough parameters.

// CHECK: distinct !DIGlobalVariable(name: "is_same_v", linkageName: "_ZL9is_same_vIiiE", {{.*}} templateParams: ![[PARAMS:[0-9]+]])
// CHECK: ![[PARAMS]] = !{![[LHS:[0-9]+]], ![[RHS:[0-9]+]]}
// CHECK: ![[LHS]] = !DITemplateTypeParameter(name: "LHS", type: ![[INT:[0-9]+]])
// CHECK: ![[INT]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
// CHECK: ![[RHS]] = !DITemplateTypeParameter(name: "RHS", type: ![[INT]])