]> granicus.if.org Git - clang/commitdiff
PR21246: DebugInfo: Emit the appropriate type (cv qualifiers, reference-ness, etc...
authorDavid Blaikie <dblaikie@gmail.com>
Thu, 16 Oct 2014 04:21:25 +0000 (04:21 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Thu, 16 Oct 2014 04:21:25 +0000 (04:21 +0000)
Plumb through the full QualType of the TemplateArgument::Declaration, as
it's insufficient to only know whether the type is a reference or
pointer (that was necessary for mangling, but insufficient for debug
info). This shouldn't increase the size of TemplateArgument as
TemplateArgument::Integer is still longer by another 32 bits.

Several bits of code were testing that the reference-ness of the
parameters matched, but this seemed to be insufficient (various other
features of the type could've mismatched and wouldn't've been caught)
and unnecessary, at least insofar as removing those tests didn't cause
anything to fail.

(Richard - perchaps you can hypothesize why any of these checks might
need to test reference-ness of the parameters (& explain why
reference-ness is part of the mangling - I would've figured that for the
reference-ness to be different, a prior template argument would have to
be different). I'd be happy to add them in/beef them up and add test
cases if there's a reason for them)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@219900 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/AST/TemplateBase.h
lib/AST/ASTContext.cpp
lib/AST/ASTImporter.cpp
lib/AST/ItaniumMangle.cpp
lib/AST/MicrosoftMangle.cpp
lib/AST/TemplateBase.cpp
lib/CodeGen/CGDebugInfo.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateDeduction.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTWriter.cpp
test/CodeGenCXX/debug-info-template.cpp

index 21b71328227b460dc768b4475aa8fd1fab7ff5c8..b50525c8aeb340013910a7df1476a59a52b2f85f 100644 (file)
@@ -76,7 +76,7 @@ private:
 
   struct DA {
     unsigned Kind;
-    bool ForRefParam;
+    void *QT;
     ValueDecl *D;
   };
   struct I {
@@ -132,11 +132,11 @@ public:
   /// \brief Construct a template argument that refers to a
   /// declaration, which is either an external declaration or a
   /// template declaration.
-  TemplateArgument(ValueDecl *D, bool ForRefParam) {
+  TemplateArgument(ValueDecl *D, QualType QT) {
     assert(D && "Expected decl");
     DeclArg.Kind = Declaration;
+    DeclArg.QT = QT.getAsOpaquePtr();
     DeclArg.D = D;
-    DeclArg.ForRefParam = ForRefParam;
   }
 
   /// \brief Construct an integral constant template argument. The memory to
@@ -249,11 +249,9 @@ public:
     return DeclArg.D;
   }
 
-  /// \brief Retrieve whether a declaration is binding to a
-  /// reference parameter in a declaration non-type template argument.
-  bool isDeclForReferenceParam() const {
+  QualType getTypeForDecl() const {
     assert(getKind() == Declaration && "Unexpected kind");
-    return DeclArg.ForRefParam;
+    return QualType::getFromOpaquePtr(DeclArg.QT);
   }
 
   /// \brief Retrieve the type for null non-type template argument.
index b33fdb4c707a604aa462790e9ba5ed6fa62e3a18..0c8fa2a894b1b679498742127668e5d6b61c0e93 100644 (file)
@@ -4099,7 +4099,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const {
 
     case TemplateArgument::Declaration: {
       ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl());
-      return TemplateArgument(D, Arg.isDeclForReferenceParam());
+      return TemplateArgument(D, Arg.getTypeForDecl());
     }
 
     case TemplateArgument::NullPtr:
index 1627e477f954f7743b924ee0342faa3577436e47..6b16cacbc9422400e874eb3429d8fbf1c8a9bfca 100644 (file)
@@ -2094,7 +2094,7 @@ ASTNodeImporter::ImportTemplateArgument(const TemplateArgument &From) {
   case TemplateArgument::Declaration: {
     ValueDecl *FromD = From.getAsDecl();
     if (ValueDecl *To = cast_or_null<ValueDecl>(Importer.Import(FromD)))
-      return TemplateArgument(To, From.isDeclForReferenceParam());
+      return TemplateArgument(To, From.getTypeForDecl());
     return TemplateArgument();
   }
 
index d2d02fac03ec695c6c6d9be98a63e9fe713c47fd..fe5a50271d35f2d92ee137bc4c4f82c2e0929d7a 100644 (file)
@@ -3403,7 +3403,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
     // and pointer-to-function expressions are represented as a declaration not
     // an expression. We compensate for it here to produce the correct mangling.
     ValueDecl *D = A.getAsDecl();
-    bool compensateMangling = !A.isDeclForReferenceParam();
+    bool compensateMangling = !A.getTypeForDecl()->isReferenceType();
     if (compensateMangling) {
       Out << 'X';
       mangleOperatorName(OO_Amp, 1);
index e98a2226b7624ee222dd1b8030fb31100a5a7a9a..54ac2b6352ad8d8657082cfd2fb76b100daca0c5 100644 (file)
@@ -1139,7 +1139,7 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
       else
         mangle(FD, "$1?");
     } else {
-      mangle(ND, TA.isDeclForReferenceParam() ? "$E?" : "$1?");
+      mangle(ND, TA.getTypeForDecl()->isReferenceType() ? "$E?" : "$1?");
     }
     break;
   }
index ac6a754fe733402114e833775a54b450a77fd69a..929fdfc7ceb88241a0b93528713708282ad7af78 100644 (file)
@@ -294,8 +294,7 @@ bool TemplateArgument::structurallyEquals(const TemplateArgument &Other) const {
     return TypeOrValue.V == Other.TypeOrValue.V;
 
   case Declaration:
-    return getAsDecl() == Other.getAsDecl() && 
-           isDeclForReferenceParam() && Other.isDeclForReferenceParam();
+    return getAsDecl() == Other.getAsDecl();
 
   case Integral:
     return getIntegralType() == Other.getIntegralType() &&
index 512db76a8416945c605717895e43b741dce7e5b7..0a5c40ed1acc26362d06cf9e4182a84436021f0e 100644 (file)
@@ -1256,11 +1256,7 @@ CollectTemplateParams(const TemplateParameterList *TPList,
     case TemplateArgument::Declaration: {
       const ValueDecl *D = TA.getAsDecl();
       bool InstanceMember = D->isCXXInstanceMember();
-      QualType T = InstanceMember
-                       ? CGM.getContext().getMemberPointerType(
-                             D->getType(), cast<RecordDecl>(D->getDeclContext())
-                                               ->getTypeForDecl())
-                       : CGM.getContext().getPointerType(D->getType());
+      QualType T = TA.getTypeForDecl();
       llvm::DIType TTy = getOrCreateType(T, Unit);
       llvm::Value *V = nullptr;
       // Variable pointer template parameters have a value that is the address
index b47ce684446d52aebdfa16c19ad4a04a24d9b127..428f24fd2da856abeb85d426a1cc7c88717a32d3 100644 (file)
@@ -4617,8 +4617,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
     return true;
 
   // Create the template argument.
-  Converted = TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()),
-                               ParamType->isReferenceType());
+  Converted =
+      TemplateArgument(cast<ValueDecl>(Entity->getCanonicalDecl()), ParamType);
   S.MarkAnyDeclReferenced(Arg->getLocStart(), Entity, false);
   return false;
 }
@@ -4713,7 +4713,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
             Converted = TemplateArgument(Arg);
           } else {
             VD = cast<ValueDecl>(VD->getCanonicalDecl());
-            Converted = TemplateArgument(VD, /*isReferenceParam*/false);
+            Converted = TemplateArgument(VD, ParamType);
           }
           return Invalid;
         }
@@ -4742,7 +4742,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S,
       Converted = TemplateArgument(Arg);
     } else {
       ValueDecl *D = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl());
-      Converted = TemplateArgument(D, /*isReferenceParam*/false);
+      Converted = TemplateArgument(D, ParamType);
     }
     return Invalid;
   }
index 0bfc7693feaf583ecf17c3ef029ba49da420681b..5cc720f4884c42adf7abe66ad3d4bf4c32c4b943 100644 (file)
@@ -262,8 +262,7 @@ checkDeducedTemplateArguments(ASTContext &Context,
     // If we deduced two declarations, make sure they they refer to the
     // same declaration.
     if (Y.getKind() == TemplateArgument::Declaration &&
-        isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
-        X.isDeclForReferenceParam() == Y.isDeclForReferenceParam())
+        isSameDeclaration(X.getAsDecl(), Y.getAsDecl()))
       return X;
 
     // All other combinations are incompatible.
@@ -384,7 +383,7 @@ DeduceNonTypeTemplateArgument(Sema &S,
          "Cannot deduce non-type template argument with depth > 0");
 
   D = D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
-  TemplateArgument New(D, NTTP->getType()->isReferenceType());
+  TemplateArgument New(D, NTTP->getType());
   DeducedTemplateArgument NewDeduced(New);
   DeducedTemplateArgument Result = checkDeducedTemplateArguments(S.Context,
                                                      Deduced[NTTP->getIndex()],
@@ -1728,8 +1727,7 @@ DeduceTemplateArguments(Sema &S,
 
   case TemplateArgument::Declaration:
     if (Arg.getKind() == TemplateArgument::Declaration &&
-        isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()) &&
-        Param.isDeclForReferenceParam() == Arg.isDeclForReferenceParam())
+        isSameDeclaration(Param.getAsDecl(), Arg.getAsDecl()))
       return Sema::TDK_Success;
 
     Info.FirstArg = Param;
@@ -1964,8 +1962,7 @@ static bool isSameTemplateArg(ASTContext &Context,
              Context.getCanonicalType(Y.getAsType());
 
     case TemplateArgument::Declaration:
-      return isSameDeclaration(X.getAsDecl(), Y.getAsDecl()) &&
-             X.isDeclForReferenceParam() == Y.isDeclForReferenceParam();
+      return isSameDeclaration(X.getAsDecl(), Y.getAsDecl());
 
     case TemplateArgument::NullPtr:
       return Context.hasSameType(X.getNullPtrType(), Y.getNullPtrType());
index 96639f37f0b1ab6a95701af3bd2f6b187d5457cf..51cee8cf649f0fa7dc478b266cb4824cced52ae5 100644 (file)
@@ -7705,8 +7705,7 @@ ASTReader::ReadTemplateArgument(ModuleFile &F,
     return TemplateArgument(readType(F, Record, Idx));
   case TemplateArgument::Declaration: {
     ValueDecl *D = ReadDeclAs<ValueDecl>(F, Record, Idx);
-    bool ForReferenceParam = Record[Idx++];
-    return TemplateArgument(D, ForReferenceParam);
+    return TemplateArgument(D, readType(F, Record, Idx));
   }
   case TemplateArgument::NullPtr:
     return TemplateArgument(readType(F, Record, Idx), /*isNullPtr*/true);
index 94eead8641f8ef40e3d7bfd9defb7790204fed98..c1df96446071c4ff7c98456b0bee9742f73be897 100644 (file)
@@ -5372,7 +5372,7 @@ void ASTWriter::AddTemplateArgument(const TemplateArgument &Arg,
     break;
   case TemplateArgument::Declaration:
     AddDeclRef(Arg.getAsDecl(), Record);
-    Record.push_back(Arg.isDeclForReferenceParam());
+    AddTypeRef(Arg.getTypeForDecl(), Record);
     break;
   case TemplateArgument::NullPtr:
     AddTypeRef(Arg.getNullPtrType(), Record);
index 95a99ec669155e8d78ab543a8b33a61fb8663d78..d1b13d03307d509c9d5e75d1b5b72b694bf8c166 100644 (file)
@@ -15,9 +15,9 @@
 // CHECK: [[TCARG1]] = metadata !{metadata !"0x2f\00T\000\000", null, metadata [[UINT:![0-9]*]], null} ; [ DW_TAG_template_type_parameter ]
 // CHECK: [[UINT:![0-9]*]] = {{.*}} ; [ DW_TAG_base_type ] [unsigned int]
 // CHECK: [[TCARG2]] = metadata !{metadata !"0x30\00\00{{.*}}", {{[^,]+}}, metadata [[UINT]], i32 2, {{.*}} ; [ DW_TAG_template_value_parameter ]
-// CHECK: [[TCARG3]] = metadata !{metadata !"0x30\00x\00{{.*}}", {{[^,]+}}, metadata [[INTPTR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ]
-// CHECK: [[INTPTR]] = {{.*}}, metadata [[INT:![0-9]*]]} ; [ DW_TAG_pointer_type ] [line 0, size 64, align 64, offset 0] [from int]
-// CECK: [[TCARG3]] = metadata !{metadata !"0x30\00x\00{{.*}}", {{[^,]+}}, metadata [[CINTPTR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[TCARG3]] = metadata !{metadata !"0x30\00x\00{{.*}}", {{[^,]+}}, metadata [[CINTPTR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[CINTPTR]] = {{.*}}, metadata [[CINT:![0-9]*]]} ; [ DW_TAG_pointer_type ] {{.*}} [from ]
+// CHECK: [[CINT]] = {{.*}}, metadata [[INT:![0-9]*]]} ; [ DW_TAG_const_type ] {{.*}} [from int]
 // CHECK: [[INT]] = {{.*}} ; [ DW_TAG_base_type ] [int]
 // CHECK: [[TCARG4]] = metadata !{metadata !"0x30\00a\00{{.*}}", {{[^,]+}}, metadata [[MEMINTPTR:![0-9]*]], i64 8, {{.*}} ; [ DW_TAG_template_value_parameter ]
 // CHECK: [[MEMINTPTR]] = {{.*}}, metadata !"_ZTS3foo"} ; [ DW_TAG_ptr_to_member_type ] {{.*}}[from int]
 // CHECK: metadata !"0x2e\00f\00f\00_ZN3foo1fEv\00{{.*}}", metadata [[FTYPE:![0-9]*]], {{.*}} ; [ DW_TAG_subprogram ]
 //
 
-
 // CHECK: metadata !{metadata !"0x13\00{{.*}}", metadata !{{[0-9]*}}, metadata !"_ZTS2TCIjLj2EXadL_Z3glbEEXadL_ZN3foo1eEEEXadL_ZNS0_1fEvEEXadL_Z4funcvEEJLi1ELi2ELi3EEE", {{.*}}, metadata !"[[TCNESTED:.*]]"} ; [ DW_TAG_structure_type ] [nested]
 // CHECK: metadata [[TCNARGS:![0-9]*]], metadata !"[[TCNT:.*]]"} ; [ DW_TAG_structure_type ] [TC<int, -3, nullptr, nullptr, nullptr, nullptr>]
 // CHECK: [[TCNARGS]] = metadata !{metadata [[TCNARG1:![0-9]*]], metadata [[TCNARG2:![0-9]*]], metadata [[TCNARG3:![0-9]*]], metadata [[TCNARG4:![0-9]*]], metadata [[TCNARG5:![0-9]*]], metadata [[TCNARG6:![0-9]*]], metadata [[TCNARG7:![0-9]*]]}
 // CHECK: [[TCNARG1]] = metadata !{metadata !"0x2f\00T\000\000", null, metadata [[INT]], null} ; [ DW_TAG_template_type_parameter ]
 // CHECK: [[TCNARG2]] = metadata !{metadata !"0x30\00\000\000", null, metadata [[INT]], i32 -3, null} ; [ DW_TAG_template_value_parameter ]
-// CHECK: [[TCNARG3]] = metadata !{metadata !"0x30\00x\000\000", null, metadata [[CINTPTR:![0-9]*]], i8 0, null} ; [ DW_TAG_template_value_parameter ]
-// CHECK: [[CINTPTR]] = {{.*}}, metadata [[CINT:![0-9]*]]} ; [ DW_TAG_pointer_type ] {{.*}} [from ]
-// CHECK: [[CINT]] = {{.*}}, metadata [[INT]]} ; [ DW_TAG_const_type ] {{.*}} [from int]
+// CHECK: [[TCNARG3]] = metadata !{metadata !"0x30\00x\000\000", null, metadata [[CINTPTR]], i8 0, null} ; [ DW_TAG_template_value_parameter ]
 
 // The interesting null pointer: -1 for member data pointers (since they are
 // just an offset in an object, they can be zero and non-null for the first
 // CHECK: [[TCNARG6]] = metadata !{metadata !"0x30\00f\000\000", null, metadata [[FUNPTR]], i8 0, null} ; [ DW_TAG_template_value_parameter ]
 // CHECK: [[TCNARG7]] = metadata !{metadata !"0x4107\00Is\000\000", null, null, metadata [[EMPTY]], null} ; [ DW_TAG_GNU_template_parameter_pack ]
 
-// CHECK: metadata [[NNARGS:![0-9]*]], metadata !"[[NNT:.*]]"} ; [ DW_TAG_structure_type ] [NN<tmpl_impl>]
-// CHECK: [[NNARGS]] = metadata !{metadata [[NNARG1:![0-9]*]]}
+// FIXME: these parameters should probably be rendered as 'glb' rather than
+// '&glb', since they're references, not pointers.
+// CHECK: metadata [[NNARGS:![0-9]*]], metadata !"[[NNT:.*]]"} ; [ DW_TAG_structure_type ] [NN<tmpl_impl, &glb, &glb>]
+// CHECK: [[NNARGS]] = metadata !{metadata [[NNARG1:![0-9]*]], metadata [[NNARG2:![0-9]*]], metadata [[NNARG3:![0-9]*]]}
 // CHECK: [[NNARG1]] = metadata !{metadata !"0x4106\00tmpl\000\000", null, null, metadata !"tmpl_impl", null} ; [ DW_TAG_GNU_template_template_param ]
+// CHECK: [[NNARG2]] = metadata !{metadata !"0x30\00lvr\00{{.*}}", {{[^,]+}}, metadata [[INTLVR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[INTLVR]] = {{.*}}, metadata [[INT]]} ; [ DW_TAG_reference_type ] {{.*}} [from int]
+// CHECK: [[NNARG3]] = metadata !{metadata !"0x30\00rvr\00{{.*}}", {{[^,]+}}, metadata [[INTRVR:![0-9]*]], i32* @glb, {{.*}} ; [ DW_TAG_template_value_parameter ]
+// CHECK: [[INTRVR]] = {{.*}}, metadata [[INT]]} ; [ DW_TAG_rvalue_reference_type ] {{.*}} [from int]
 
 // CHECK: metadata [[PTOARGS:![0-9]*]], metadata !"{{.*}}"} ; [ DW_TAG_structure_type ] [PaddingAtEndTemplate<&PaddedObj>]
 // CHECK: [[PTOARGS]] = metadata !{metadata [[PTOARG1:![0-9]*]]}
@@ -110,11 +113,11 @@ template<typename>
 struct tmpl_impl {
 };
 
-template<template <typename> class tmpl>
+template <template <typename> class tmpl, int &lvr, int &&rvr>
 struct NN {
 };
 
-NN<tmpl_impl> nn;
+NN<tmpl_impl, glb, glb> nn;
 
 struct PaddingAtEnd {
   int i;