forked from OSchip/llvm-project
Reland "[DebugInfo][clang][DWARF5]: Added support for debuginfo generation for defaulted parameters
in C++ templates."
This was reverted in 802b22b5c8
due to
missing .bc file and a chromium bot failure.
https://bugs.chromium.org/p/chromium/issues/detail?id=1057559#c1
This revision address both of them.
Summary:
This patch adds support for debuginfo generation for defaulted
parameters in clang and also extends corresponding DebugMetadata/IR to support this feature.
Reviewers: probinson, aprantl, dblaikie
Reviewed By: aprantl, dblaikie
Differential Revision: https://reviews.llvm.org/D73462
This commit is contained in:
parent
e4380b07cc
commit
7a42babeb8
|
@ -1787,18 +1787,36 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
|
|||
for (unsigned i = 0, e = TAList.size(); i != e; ++i) {
|
||||
const TemplateArgument &TA = TAList[i];
|
||||
StringRef Name;
|
||||
bool defaultParameter = false;
|
||||
if (TPList)
|
||||
Name = TPList->getParam(i)->getName();
|
||||
switch (TA.getKind()) {
|
||||
case TemplateArgument::Type: {
|
||||
llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);
|
||||
TemplateParams.push_back(
|
||||
DBuilder.createTemplateTypeParameter(TheCU, Name, TTy));
|
||||
|
||||
if (TPList)
|
||||
if (auto *templateType =
|
||||
dyn_cast_or_null<TemplateTypeParmDecl>(TPList->getParam(i)))
|
||||
if (templateType->hasDefaultArgument())
|
||||
defaultParameter =
|
||||
templateType->getDefaultArgument() == TA.getAsType();
|
||||
|
||||
TemplateParams.push_back(DBuilder.createTemplateTypeParameter(
|
||||
TheCU, Name, TTy, defaultParameter));
|
||||
|
||||
} break;
|
||||
case TemplateArgument::Integral: {
|
||||
llvm::DIType *TTy = getOrCreateType(TA.getIntegralType(), Unit);
|
||||
if (TPList && CGM.getCodeGenOpts().DwarfVersion >= 5)
|
||||
if (auto *templateType =
|
||||
dyn_cast_or_null<NonTypeTemplateParmDecl>(TPList->getParam(i)))
|
||||
if (templateType->hasDefaultArgument())
|
||||
defaultParameter =
|
||||
templateType->getDefaultArgument()->EvaluateKnownConstInt(
|
||||
CGM.getContext()) == TA.getAsIntegral();
|
||||
|
||||
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
|
||||
TheCU, Name, TTy,
|
||||
TheCU, Name, TTy, defaultParameter,
|
||||
llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral())));
|
||||
} break;
|
||||
case TemplateArgument::Declaration: {
|
||||
|
@ -1837,7 +1855,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
|
|||
V = V->stripPointerCasts();
|
||||
}
|
||||
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
|
||||
TheCU, Name, TTy, cast_or_null<llvm::Constant>(V)));
|
||||
TheCU, Name, TTy, defaultParameter, cast_or_null<llvm::Constant>(V)));
|
||||
} break;
|
||||
case TemplateArgument::NullPtr: {
|
||||
QualType T = TA.getNullPtrType();
|
||||
|
@ -1855,8 +1873,8 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
|
|||
V = CGM.getCXXABI().EmitNullMemberPointer(MPT);
|
||||
if (!V)
|
||||
V = llvm::ConstantInt::get(CGM.Int8Ty, 0);
|
||||
TemplateParams.push_back(
|
||||
DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V));
|
||||
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
|
||||
TheCU, Name, TTy, defaultParameter, V));
|
||||
} break;
|
||||
case TemplateArgument::Template:
|
||||
TemplateParams.push_back(DBuilder.createTemplateTemplateParameter(
|
||||
|
@ -1877,7 +1895,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,
|
|||
assert(V && "Expression in template argument isn't constant");
|
||||
llvm::DIType *TTy = getOrCreateType(T, Unit);
|
||||
TemplateParams.push_back(DBuilder.createTemplateValueParameter(
|
||||
TheCU, Name, TTy, V->stripPointerCasts()));
|
||||
TheCU, Name, TTy, defaultParameter, V->stripPointerCasts()));
|
||||
} break;
|
||||
// And the following should never occur:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
|
|
|
@ -443,19 +443,22 @@ namespace llvm {
|
|||
/// \param Scope Scope in which this type is defined.
|
||||
/// \param Name Type parameter name.
|
||||
/// \param Ty Parameter type.
|
||||
DITemplateTypeParameter *
|
||||
createTemplateTypeParameter(DIScope *Scope, StringRef Name, DIType *Ty);
|
||||
/// \param IsDefault Parameter is default or not
|
||||
DITemplateTypeParameter *createTemplateTypeParameter(DIScope *Scope,
|
||||
StringRef Name,
|
||||
DIType *Ty,
|
||||
bool IsDefault);
|
||||
|
||||
/// Create debugging information for template
|
||||
/// value parameter.
|
||||
/// \param Scope Scope in which this type is defined.
|
||||
/// \param Name Value parameter name.
|
||||
/// \param Ty Parameter type.
|
||||
/// \param IsDefault Parameter is default or not
|
||||
/// \param Val Constant parameter value.
|
||||
DITemplateValueParameter *createTemplateValueParameter(DIScope *Scope,
|
||||
StringRef Name,
|
||||
DIType *Ty,
|
||||
Constant *Val);
|
||||
DITemplateValueParameter *
|
||||
createTemplateValueParameter(DIScope *Scope, StringRef Name, DIType *Ty,
|
||||
bool IsDefault, Constant *Val);
|
||||
|
||||
/// Create debugging information for a template template parameter.
|
||||
/// \param Scope Scope in which this type is defined.
|
||||
|
|
|
@ -2131,9 +2131,11 @@ public:
|
|||
/// Base class for template parameters.
|
||||
class DITemplateParameter : public DINode {
|
||||
protected:
|
||||
bool IsDefault;
|
||||
|
||||
DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage,
|
||||
unsigned Tag, ArrayRef<Metadata *> Ops)
|
||||
: DINode(Context, ID, Storage, Tag, Ops) {}
|
||||
unsigned Tag, bool IsDefault, ArrayRef<Metadata *> Ops)
|
||||
: DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {}
|
||||
~DITemplateParameter() = default;
|
||||
|
||||
public:
|
||||
|
@ -2142,6 +2144,7 @@ public:
|
|||
|
||||
MDString *getRawName() const { return getOperandAs<MDString>(0); }
|
||||
Metadata *getRawType() const { return getOperand(1); }
|
||||
bool isDefault() const { return IsDefault; }
|
||||
|
||||
static bool classof(const Metadata *MD) {
|
||||
return MD->getMetadataID() == DITemplateTypeParameterKind ||
|
||||
|
@ -2154,30 +2157,35 @@ class DITemplateTypeParameter : public DITemplateParameter {
|
|||
friend class MDNode;
|
||||
|
||||
DITemplateTypeParameter(LLVMContext &Context, StorageType Storage,
|
||||
ArrayRef<Metadata *> Ops)
|
||||
bool IsDefault, ArrayRef<Metadata *> Ops)
|
||||
: DITemplateParameter(Context, DITemplateTypeParameterKind, Storage,
|
||||
dwarf::DW_TAG_template_type_parameter, Ops) {}
|
||||
dwarf::DW_TAG_template_type_parameter, IsDefault,
|
||||
Ops) {}
|
||||
~DITemplateTypeParameter() = default;
|
||||
|
||||
static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name,
|
||||
DIType *Type, StorageType Storage,
|
||||
DIType *Type, bool IsDefault,
|
||||
StorageType Storage,
|
||||
bool ShouldCreate = true) {
|
||||
return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage,
|
||||
ShouldCreate);
|
||||
return getImpl(Context, getCanonicalMDString(Context, Name), Type,
|
||||
IsDefault, Storage, ShouldCreate);
|
||||
}
|
||||
static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name,
|
||||
Metadata *Type, StorageType Storage,
|
||||
Metadata *Type, bool IsDefault,
|
||||
StorageType Storage,
|
||||
bool ShouldCreate = true);
|
||||
|
||||
TempDITemplateTypeParameter cloneImpl() const {
|
||||
return getTemporary(getContext(), getName(), getType());
|
||||
return getTemporary(getContext(), getName(), getType(), isDefault());
|
||||
}
|
||||
|
||||
public:
|
||||
DEFINE_MDNODE_GET(DITemplateTypeParameter, (StringRef Name, DIType *Type),
|
||||
(Name, Type))
|
||||
DEFINE_MDNODE_GET(DITemplateTypeParameter, (MDString * Name, Metadata *Type),
|
||||
(Name, Type))
|
||||
DEFINE_MDNODE_GET(DITemplateTypeParameter,
|
||||
(StringRef Name, DIType *Type, bool IsDefault),
|
||||
(Name, Type, IsDefault))
|
||||
DEFINE_MDNODE_GET(DITemplateTypeParameter,
|
||||
(MDString *Name, Metadata *Type, bool IsDefault),
|
||||
(Name, Type, IsDefault))
|
||||
|
||||
TempDITemplateTypeParameter clone() const { return cloneImpl(); }
|
||||
|
||||
|
@ -2191,36 +2199,40 @@ class DITemplateValueParameter : public DITemplateParameter {
|
|||
friend class MDNode;
|
||||
|
||||
DITemplateValueParameter(LLVMContext &Context, StorageType Storage,
|
||||
unsigned Tag, ArrayRef<Metadata *> Ops)
|
||||
unsigned Tag, bool IsDefault,
|
||||
ArrayRef<Metadata *> Ops)
|
||||
: DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag,
|
||||
Ops) {}
|
||||
IsDefault, Ops) {}
|
||||
~DITemplateValueParameter() = default;
|
||||
|
||||
static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,
|
||||
StringRef Name, DIType *Type,
|
||||
Metadata *Value, StorageType Storage,
|
||||
bool IsDefault, Metadata *Value,
|
||||
StorageType Storage,
|
||||
bool ShouldCreate = true) {
|
||||
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type,
|
||||
Value, Storage, ShouldCreate);
|
||||
IsDefault, Value, Storage, ShouldCreate);
|
||||
}
|
||||
static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,
|
||||
MDString *Name, Metadata *Type,
|
||||
Metadata *Value, StorageType Storage,
|
||||
bool IsDefault, Metadata *Value,
|
||||
StorageType Storage,
|
||||
bool ShouldCreate = true);
|
||||
|
||||
TempDITemplateValueParameter cloneImpl() const {
|
||||
return getTemporary(getContext(), getTag(), getName(), getType(),
|
||||
getValue());
|
||||
isDefault(), getValue());
|
||||
}
|
||||
|
||||
public:
|
||||
DEFINE_MDNODE_GET(DITemplateValueParameter,
|
||||
(unsigned Tag, StringRef Name, DIType *Type,
|
||||
(unsigned Tag, StringRef Name, DIType *Type, bool IsDefault,
|
||||
Metadata *Value),
|
||||
(Tag, Name, Type, Value))
|
||||
DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, MDString *Name,
|
||||
Metadata *Type, Metadata *Value),
|
||||
(Tag, Name, Type, Value))
|
||||
(Tag, Name, Type, IsDefault, Value))
|
||||
DEFINE_MDNODE_GET(DITemplateValueParameter,
|
||||
(unsigned Tag, MDString *Name, Metadata *Type,
|
||||
bool IsDefault, Metadata *Value),
|
||||
(Tag, Name, Type, IsDefault, Value))
|
||||
|
||||
TempDITemplateValueParameter clone() const { return cloneImpl(); }
|
||||
|
||||
|
|
|
@ -4842,33 +4842,38 @@ bool LLParser::ParseDIModule(MDNode *&Result, bool IsDistinct) {
|
|||
}
|
||||
|
||||
/// ParseDITemplateTypeParameter:
|
||||
/// ::= !DITemplateTypeParameter(name: "Ty", type: !1)
|
||||
/// ::= !DITemplateTypeParameter(name: "Ty", type: !1, defaulted: false)
|
||||
bool LLParser::ParseDITemplateTypeParameter(MDNode *&Result, bool IsDistinct) {
|
||||
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
|
||||
OPTIONAL(name, MDStringField, ); \
|
||||
REQUIRED(type, MDField, );
|
||||
REQUIRED(type, MDField, ); \
|
||||
OPTIONAL(defaulted, MDBoolField, );
|
||||
PARSE_MD_FIELDS();
|
||||
#undef VISIT_MD_FIELDS
|
||||
|
||||
Result =
|
||||
GET_OR_DISTINCT(DITemplateTypeParameter, (Context, name.Val, type.Val));
|
||||
Result = GET_OR_DISTINCT(DITemplateTypeParameter,
|
||||
(Context, name.Val, type.Val, defaulted.Val));
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDITemplateValueParameter:
|
||||
/// ::= !DITemplateValueParameter(tag: DW_TAG_template_value_parameter,
|
||||
/// name: "V", type: !1, value: i32 7)
|
||||
/// name: "V", type: !1, defaulted: false,
|
||||
/// value: i32 7)
|
||||
bool LLParser::ParseDITemplateValueParameter(MDNode *&Result, bool IsDistinct) {
|
||||
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
|
||||
OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_template_value_parameter)); \
|
||||
OPTIONAL(name, MDStringField, ); \
|
||||
OPTIONAL(type, MDField, ); \
|
||||
OPTIONAL(defaulted, MDBoolField, ); \
|
||||
REQUIRED(value, MDField, );
|
||||
|
||||
PARSE_MD_FIELDS();
|
||||
#undef VISIT_MD_FIELDS
|
||||
|
||||
Result = GET_OR_DISTINCT(DITemplateValueParameter,
|
||||
(Context, tag.Val, name.Val, type.Val, value.Val));
|
||||
Result = GET_OR_DISTINCT(
|
||||
DITemplateValueParameter,
|
||||
(Context, tag.Val, name.Val, type.Val, defaulted.Val, value.Val));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1668,27 +1668,34 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
|
|||
break;
|
||||
}
|
||||
case bitc::METADATA_TEMPLATE_TYPE: {
|
||||
if (Record.size() != 3)
|
||||
return error("Invalid record");
|
||||
|
||||
IsDistinct = Record[0];
|
||||
MetadataList.assignValue(GET_OR_DISTINCT(DITemplateTypeParameter,
|
||||
(Context, getMDString(Record[1]),
|
||||
getDITypeRefOrNull(Record[2]))),
|
||||
NextMetadataNo);
|
||||
NextMetadataNo++;
|
||||
break;
|
||||
}
|
||||
case bitc::METADATA_TEMPLATE_VALUE: {
|
||||
if (Record.size() != 5)
|
||||
if (Record.size() < 3 || Record.size() > 4)
|
||||
return error("Invalid record");
|
||||
|
||||
IsDistinct = Record[0];
|
||||
MetadataList.assignValue(
|
||||
GET_OR_DISTINCT(DITemplateValueParameter,
|
||||
(Context, Record[1], getMDString(Record[2]),
|
||||
getDITypeRefOrNull(Record[3]),
|
||||
getMDOrNull(Record[4]))),
|
||||
GET_OR_DISTINCT(DITemplateTypeParameter,
|
||||
(Context, getMDString(Record[1]),
|
||||
getDITypeRefOrNull(Record[2]),
|
||||
(Record.size() == 4) ? getMDOrNull(Record[3])
|
||||
: getMDOrNull(false))),
|
||||
NextMetadataNo);
|
||||
NextMetadataNo++;
|
||||
break;
|
||||
}
|
||||
case bitc::METADATA_TEMPLATE_VALUE: {
|
||||
if (Record.size() < 5 || Record.size() > 6)
|
||||
return error("Invalid record");
|
||||
|
||||
IsDistinct = Record[0];
|
||||
|
||||
MetadataList.assignValue(
|
||||
GET_OR_DISTINCT(
|
||||
DITemplateValueParameter,
|
||||
(Context, Record[1], getMDString(Record[2]),
|
||||
getDITypeRefOrNull(Record[3]),
|
||||
(Record.size() == 6) ? getMDOrNull(Record[4]) : getMDOrNull(false),
|
||||
(Record.size() == 6) ? getMDOrNull(Record[5])
|
||||
: getMDOrNull(Record[4]))),
|
||||
NextMetadataNo);
|
||||
NextMetadataNo++;
|
||||
break;
|
||||
|
|
|
@ -1792,6 +1792,7 @@ void ModuleBitcodeWriter::writeDITemplateTypeParameter(
|
|||
Record.push_back(N->isDistinct());
|
||||
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
|
||||
Record.push_back(VE.getMetadataOrNullID(N->getType()));
|
||||
Record.push_back(N->isDefault());
|
||||
|
||||
Stream.EmitRecord(bitc::METADATA_TEMPLATE_TYPE, Record, Abbrev);
|
||||
Record.clear();
|
||||
|
@ -1804,6 +1805,7 @@ void ModuleBitcodeWriter::writeDITemplateValueParameter(
|
|||
Record.push_back(N->getTag());
|
||||
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));
|
||||
Record.push_back(VE.getMetadataOrNullID(N->getType()));
|
||||
Record.push_back(N->isDefault());
|
||||
Record.push_back(VE.getMetadataOrNullID(N->getValue()));
|
||||
|
||||
Stream.EmitRecord(bitc::METADATA_TEMPLATE_VALUE, Record, Abbrev);
|
||||
|
|
|
@ -2073,6 +2073,7 @@ static void writeDITemplateTypeParameter(raw_ostream &Out,
|
|||
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);
|
||||
Printer.printString("name", N->getName());
|
||||
Printer.printMetadata("type", N->getRawType(), /* ShouldSkipNull */ false);
|
||||
Printer.printBool("defaulted", N->isDefault(), /* Default= */ false);
|
||||
Out << ")";
|
||||
}
|
||||
|
||||
|
@ -2087,6 +2088,7 @@ static void writeDITemplateValueParameter(raw_ostream &Out,
|
|||
Printer.printTag(N);
|
||||
Printer.printString("name", N->getName());
|
||||
Printer.printMetadata("type", N->getRawType());
|
||||
Printer.printBool("defaulted", N->isDefault(), /* Default= */ false);
|
||||
Printer.printMetadata("value", N->getValue(), /* ShouldSkipNull */ false);
|
||||
Out << ")";
|
||||
}
|
||||
|
|
|
@ -406,25 +406,26 @@ DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber,
|
|||
|
||||
DITemplateTypeParameter *
|
||||
DIBuilder::createTemplateTypeParameter(DIScope *Context, StringRef Name,
|
||||
DIType *Ty) {
|
||||
DIType *Ty, bool isDefault) {
|
||||
assert((!Context || isa<DICompileUnit>(Context)) && "Expected compile unit");
|
||||
return DITemplateTypeParameter::get(VMContext, Name, Ty);
|
||||
return DITemplateTypeParameter::get(VMContext, Name, Ty, isDefault);
|
||||
}
|
||||
|
||||
static DITemplateValueParameter *
|
||||
createTemplateValueParameterHelper(LLVMContext &VMContext, unsigned Tag,
|
||||
DIScope *Context, StringRef Name, DIType *Ty,
|
||||
Metadata *MD) {
|
||||
bool IsDefault, Metadata *MD) {
|
||||
assert((!Context || isa<DICompileUnit>(Context)) && "Expected compile unit");
|
||||
return DITemplateValueParameter::get(VMContext, Tag, Name, Ty, MD);
|
||||
return DITemplateValueParameter::get(VMContext, Tag, Name, Ty, IsDefault, MD);
|
||||
}
|
||||
|
||||
DITemplateValueParameter *
|
||||
DIBuilder::createTemplateValueParameter(DIScope *Context, StringRef Name,
|
||||
DIType *Ty, Constant *Val) {
|
||||
DIType *Ty, bool isDefault,
|
||||
Constant *Val) {
|
||||
return createTemplateValueParameterHelper(
|
||||
VMContext, dwarf::DW_TAG_template_value_parameter, Context, Name, Ty,
|
||||
getConstantOrNull(Val));
|
||||
isDefault, getConstantOrNull(Val));
|
||||
}
|
||||
|
||||
DITemplateValueParameter *
|
||||
|
@ -432,7 +433,7 @@ DIBuilder::createTemplateTemplateParameter(DIScope *Context, StringRef Name,
|
|||
DIType *Ty, StringRef Val) {
|
||||
return createTemplateValueParameterHelper(
|
||||
VMContext, dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty,
|
||||
MDString::get(VMContext, Val));
|
||||
false, MDString::get(VMContext, Val));
|
||||
}
|
||||
|
||||
DITemplateValueParameter *
|
||||
|
@ -440,7 +441,7 @@ DIBuilder::createTemplateParameterPack(DIScope *Context, StringRef Name,
|
|||
DIType *Ty, DINodeArray Val) {
|
||||
return createTemplateValueParameterHelper(
|
||||
VMContext, dwarf::DW_TAG_GNU_template_parameter_pack, Context, Name, Ty,
|
||||
Val.get());
|
||||
false, Val.get());
|
||||
}
|
||||
|
||||
DICompositeType *DIBuilder::createClassType(
|
||||
|
|
|
@ -724,24 +724,24 @@ DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *Scope,
|
|||
DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIModule, Ops);
|
||||
}
|
||||
|
||||
DITemplateTypeParameter *DITemplateTypeParameter::getImpl(LLVMContext &Context,
|
||||
MDString *Name,
|
||||
Metadata *Type,
|
||||
StorageType Storage,
|
||||
bool ShouldCreate) {
|
||||
DITemplateTypeParameter *
|
||||
DITemplateTypeParameter::getImpl(LLVMContext &Context, MDString *Name,
|
||||
Metadata *Type, bool isDefault,
|
||||
StorageType Storage, bool ShouldCreate) {
|
||||
assert(isCanonical(Name) && "Expected canonical MDString");
|
||||
DEFINE_GETIMPL_LOOKUP(DITemplateTypeParameter, (Name, Type));
|
||||
DEFINE_GETIMPL_LOOKUP(DITemplateTypeParameter, (Name, Type, isDefault));
|
||||
Metadata *Ops[] = {Name, Type};
|
||||
DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DITemplateTypeParameter, Ops);
|
||||
DEFINE_GETIMPL_STORE(DITemplateTypeParameter, (isDefault), Ops);
|
||||
}
|
||||
|
||||
DITemplateValueParameter *DITemplateValueParameter::getImpl(
|
||||
LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *Type,
|
||||
Metadata *Value, StorageType Storage, bool ShouldCreate) {
|
||||
bool isDefault, Metadata *Value, StorageType Storage, bool ShouldCreate) {
|
||||
assert(isCanonical(Name) && "Expected canonical MDString");
|
||||
DEFINE_GETIMPL_LOOKUP(DITemplateValueParameter, (Tag, Name, Type, Value));
|
||||
DEFINE_GETIMPL_LOOKUP(DITemplateValueParameter,
|
||||
(Tag, Name, Type, isDefault, Value));
|
||||
Metadata *Ops[] = {Name, Type, Value};
|
||||
DEFINE_GETIMPL_STORE(DITemplateValueParameter, (Tag), Ops);
|
||||
DEFINE_GETIMPL_STORE(DITemplateValueParameter, (Tag, isDefault), Ops);
|
||||
}
|
||||
|
||||
DIGlobalVariable *
|
||||
|
|
|
@ -843,36 +843,45 @@ template <> struct MDNodeKeyImpl<DIModule> {
|
|||
template <> struct MDNodeKeyImpl<DITemplateTypeParameter> {
|
||||
MDString *Name;
|
||||
Metadata *Type;
|
||||
bool IsDefault;
|
||||
|
||||
MDNodeKeyImpl(MDString *Name, Metadata *Type) : Name(Name), Type(Type) {}
|
||||
MDNodeKeyImpl(MDString *Name, Metadata *Type, bool IsDefault)
|
||||
: Name(Name), Type(Type), IsDefault(IsDefault) {}
|
||||
MDNodeKeyImpl(const DITemplateTypeParameter *N)
|
||||
: Name(N->getRawName()), Type(N->getRawType()) {}
|
||||
: Name(N->getRawName()), Type(N->getRawType()),
|
||||
IsDefault(N->isDefault()) {}
|
||||
|
||||
bool isKeyOf(const DITemplateTypeParameter *RHS) const {
|
||||
return Name == RHS->getRawName() && Type == RHS->getRawType();
|
||||
return Name == RHS->getRawName() && Type == RHS->getRawType() &&
|
||||
IsDefault == RHS->isDefault();
|
||||
}
|
||||
|
||||
unsigned getHashValue() const { return hash_combine(Name, Type); }
|
||||
unsigned getHashValue() const { return hash_combine(Name, Type, IsDefault); }
|
||||
};
|
||||
|
||||
template <> struct MDNodeKeyImpl<DITemplateValueParameter> {
|
||||
unsigned Tag;
|
||||
MDString *Name;
|
||||
Metadata *Type;
|
||||
bool IsDefault;
|
||||
Metadata *Value;
|
||||
|
||||
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, Metadata *Value)
|
||||
: Tag(Tag), Name(Name), Type(Type), Value(Value) {}
|
||||
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, bool IsDefault,
|
||||
Metadata *Value)
|
||||
: Tag(Tag), Name(Name), Type(Type), IsDefault(IsDefault), Value(Value) {}
|
||||
MDNodeKeyImpl(const DITemplateValueParameter *N)
|
||||
: Tag(N->getTag()), Name(N->getRawName()), Type(N->getRawType()),
|
||||
Value(N->getValue()) {}
|
||||
IsDefault(N->isDefault()), Value(N->getValue()) {}
|
||||
|
||||
bool isKeyOf(const DITemplateValueParameter *RHS) const {
|
||||
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
|
||||
Type == RHS->getRawType() && Value == RHS->getValue();
|
||||
Type == RHS->getRawType() && IsDefault == RHS->isDefault() &&
|
||||
Value == RHS->getValue();
|
||||
}
|
||||
|
||||
unsigned getHashValue() const { return hash_combine(Tag, Name, Type, Value); }
|
||||
unsigned getHashValue() const {
|
||||
return hash_combine(Tag, Name, Type, IsDefault, Value);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct MDNodeKeyImpl<DIGlobalVariable> {
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
|
||||
; RUN: verify-uselistorder %s
|
||||
|
||||
; ModuleID = '/dir/test.cpp'
|
||||
source_filename = "test.cpp"
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
%class.foo = type { i8 }
|
||||
%class.foo.0 = type { i8 }
|
||||
; Function Attrs: noinline norecurse nounwind optnone uwtable
|
||||
define dso_local i32 @main() #0 !dbg !7 {
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
%f1 = alloca %class.foo, align 1
|
||||
%f2 = alloca %class.foo.0, align 1
|
||||
store i32 0, i32* %retval, align 4
|
||||
call void @llvm.dbg.declare(metadata %class.foo* %f1, metadata !11, metadata !DIExpression()), !dbg !16
|
||||
call void @llvm.dbg.declare(metadata %class.foo.0* %f2, metadata !17, metadata !DIExpression()), !dbg !23
|
||||
ret i32 0, !dbg !24
|
||||
}
|
||||
; Function Attrs: nounwind readnone speculatable willreturn
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
|
||||
|
||||
attributes #0 = { noinline norecurse nounwind optnone uwtable }
|
||||
attributes #1 = { nounwind readnone speculatable willreturn }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "test.cpp", directory: "/dir/", checksumkind: CSK_MD5, checksum: "863d08522c2300490dea873efc4b2369")
|
||||
!2 = !{}
|
||||
!3 = !{i32 7, !"Dwarf Version", i32 5}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{!"clang version 11.0.0"}
|
||||
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 29, type: !8, scopeLine: 29, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!8 = !DISubroutineType(types: !9)
|
||||
!9 = !{!10}
|
||||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!11 = !DILocalVariable(name: "f1", scope: !7, file: !1, line: 30, type: !12)
|
||||
!12 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "foo<int, 6>", file: !1, line: 26, size: 8, flags: DIFlagTypePassByValue, elements: !2, templateParams: !13, identifier: "_ZTS3fooIiLi6EE")
|
||||
!13 = !{!14, !15}
|
||||
|
||||
; CHECK: 14 = !DITemplateTypeParameter(name: "T", type: !{{[0-9]*}})
|
||||
!14 = !DITemplateTypeParameter(name: "T", type: !10)
|
||||
|
||||
; CHECK: 15 = !DITemplateValueParameter(name: "i", type: !{{[0-9]*}}, value: i32 6)
|
||||
!15 = !DITemplateValueParameter(name: "i", type: !10, value: i32 6)
|
||||
|
||||
!16 = !DILocation(line: 30, column: 14, scope: !7)
|
||||
!17 = !DILocalVariable(name: "f2", scope: !7, file: !1, line: 31, type: !18)
|
||||
!18 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "foo<char, 3>", file: !1, line: 26, size: 8, flags: DIFlagTypePassByValue, elements: !2, templateParams: !19, identifier: "_ZTS3fooIcLi3EE")
|
||||
!19 = !{!20, !22}
|
||||
|
||||
; CHECK: 20 = !DITemplateTypeParameter({{.*}}, defaulted: true
|
||||
!20 = !DITemplateTypeParameter(name: "T", type: !21, defaulted: true)
|
||||
!21 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
||||
|
||||
; CHECK: 22 = !DITemplateValueParameter({{.*}}, defaulted: true
|
||||
!22 = !DITemplateValueParameter(name: "i", type: !10, defaulted: true, value: i32 3)
|
||||
!23 = !DILocation(line: 31, column: 9, scope: !7)
|
||||
!24 = !DILocation(line: 32, column: 3, scope: !7)
|
|
@ -0,0 +1,69 @@
|
|||
; RUN: llvm-dis -o - %s.bc | FileCheck %s
|
||||
|
||||
; ModuleID = '/dir/test.cpp'
|
||||
source_filename = "test.cpp"
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
%class.foo = type { i8 }
|
||||
%class.foo.0 = type { i8 }
|
||||
; Function Attrs: noinline norecurse nounwind optnone uwtable
|
||||
define dso_local i32 @main() #0 !dbg !7 {
|
||||
entry:
|
||||
%retval = alloca i32, align 4
|
||||
%f1 = alloca %class.foo, align 1
|
||||
%f2 = alloca %class.foo.0, align 1
|
||||
store i32 0, i32* %retval, align 4
|
||||
call void @llvm.dbg.declare(metadata %class.foo* %f1, metadata !11, metadata !DIExpression()), !dbg !16
|
||||
call void @llvm.dbg.declare(metadata %class.foo.0* %f2, metadata !17, metadata !DIExpression()), !dbg !23
|
||||
ret i32 0, !dbg !24
|
||||
}
|
||||
; Function Attrs: nounwind readnone speculatable willreturn
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
|
||||
|
||||
attributes #0 = { noinline norecurse nounwind optnone uwtable }
|
||||
attributes #1 = { nounwind readnone speculatable willreturn }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5}
|
||||
!llvm.ident = !{!6}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 11.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "test.cpp", directory: "/dir/", checksumkind: CSK_MD5, checksum: "863d08522c2300490dea873efc4b2369")
|
||||
!2 = !{}
|
||||
!3 = !{i32 7, !"Dwarf Version", i32 5}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{!"clang version 11.0.0"}
|
||||
!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 29, type: !8, scopeLine: 29, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
|
||||
!8 = !DISubroutineType(types: !9)
|
||||
!9 = !{!10}
|
||||
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!11 = !DILocalVariable(name: "f1", scope: !7, file: !1, line: 30, type: !12)
|
||||
!12 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "foo<int, 6>", file: !1, line: 26, size: 8, flags: DIFlagTypePassByValue, elements: !2, templateParams: !13, identifier: "_ZTS3fooIiLi6EE")
|
||||
!13 = !{!14, !15}
|
||||
|
||||
; Old-style DITemplateTypeParameter and DITemplateValueParameter should be
|
||||
; upgraded to include defaulted flag.
|
||||
|
||||
; CHECK: !DITemplateTypeParameter({{.*}}
|
||||
!14 = !DITemplateTypeParameter(name: "T", type: !10)
|
||||
|
||||
; CHECK: !DITemplateValueParameter({{.*}}
|
||||
!15 = !DITemplateValueParameter(name: "i", type: !10, value: i32 6)
|
||||
|
||||
!16 = !DILocation(line: 30, column: 14, scope: !7)
|
||||
!17 = !DILocalVariable(name: "f2", scope: !7, file: !1, line: 31, type: !18)
|
||||
!18 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "foo<char, 3>", file: !1, line: 26, size: 8, flags: DIFlagTypePassByValue, elements: !2, templateParams: !19, identifier: "_ZTS3fooIcLi3EE")
|
||||
!19 = !{!20, !22}
|
||||
|
||||
; CHECK: !DITemplateTypeParameter({{.*}} defaulted: true
|
||||
!20 = !DITemplateTypeParameter(name: "T", type: !21, defaulted: true)
|
||||
|
||||
!21 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
|
||||
|
||||
; CHECK: !DITemplateValueParameter({{.*}} defaulted: true
|
||||
!22 = !DITemplateValueParameter(name: "i", type: !10, defaulted: true, value: i32 3)
|
||||
|
||||
!23 = !DILocation(line: 31, column: 9, scope: !7)
|
||||
!24 = !DILocation(line: 32, column: 3, scope: !7)
|
Binary file not shown.
|
@ -2076,17 +2076,19 @@ typedef MetadataTest DITemplateTypeParameterTest;
|
|||
TEST_F(DITemplateTypeParameterTest, get) {
|
||||
StringRef Name = "template";
|
||||
DIType *Type = getBasicType("basic");
|
||||
bool defaulted = false;
|
||||
|
||||
auto *N = DITemplateTypeParameter::get(Context, Name, Type);
|
||||
auto *N = DITemplateTypeParameter::get(Context, Name, Type, defaulted);
|
||||
|
||||
EXPECT_EQ(dwarf::DW_TAG_template_type_parameter, N->getTag());
|
||||
EXPECT_EQ(Name, N->getName());
|
||||
EXPECT_EQ(Type, N->getType());
|
||||
EXPECT_EQ(N, DITemplateTypeParameter::get(Context, Name, Type));
|
||||
EXPECT_EQ(N, DITemplateTypeParameter::get(Context, Name, Type, defaulted));
|
||||
|
||||
EXPECT_NE(N, DITemplateTypeParameter::get(Context, "other", Type));
|
||||
EXPECT_NE(N,
|
||||
DITemplateTypeParameter::get(Context, Name, getBasicType("other")));
|
||||
EXPECT_NE(N, DITemplateTypeParameter::get(Context, "other", Type, defaulted));
|
||||
EXPECT_NE(N, DITemplateTypeParameter::get(Context, Name,
|
||||
getBasicType("other"), defaulted));
|
||||
EXPECT_NE(N, DITemplateTypeParameter::get(Context, Name, Type, true));
|
||||
|
||||
TempDITemplateTypeParameter Temp = N->clone();
|
||||
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
|
||||
|
@ -2098,24 +2100,31 @@ TEST_F(DITemplateValueParameterTest, get) {
|
|||
unsigned Tag = dwarf::DW_TAG_template_value_parameter;
|
||||
StringRef Name = "template";
|
||||
DIType *Type = getBasicType("basic");
|
||||
bool defaulted = false;
|
||||
Metadata *Value = getConstantAsMetadata();
|
||||
|
||||
auto *N = DITemplateValueParameter::get(Context, Tag, Name, Type, Value);
|
||||
auto *N =
|
||||
DITemplateValueParameter::get(Context, Tag, Name, Type, defaulted, Value);
|
||||
EXPECT_EQ(Tag, N->getTag());
|
||||
EXPECT_EQ(Name, N->getName());
|
||||
EXPECT_EQ(Type, N->getType());
|
||||
EXPECT_EQ(Value, N->getValue());
|
||||
EXPECT_EQ(N, DITemplateValueParameter::get(Context, Tag, Name, Type, Value));
|
||||
EXPECT_EQ(N, DITemplateValueParameter::get(Context, Tag, Name, Type,
|
||||
defaulted, Value));
|
||||
|
||||
EXPECT_NE(N, DITemplateValueParameter::get(
|
||||
Context, dwarf::DW_TAG_GNU_template_template_param, Name,
|
||||
Type, Value));
|
||||
EXPECT_NE(N,
|
||||
DITemplateValueParameter::get(Context, Tag, "other", Type, Value));
|
||||
Type, defaulted, Value));
|
||||
EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, "other", Type,
|
||||
defaulted, Value));
|
||||
EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, Name,
|
||||
getBasicType("other"), Value));
|
||||
EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, Name, Type,
|
||||
getConstantAsMetadata()));
|
||||
getBasicType("other"), defaulted,
|
||||
Value));
|
||||
EXPECT_NE(N,
|
||||
DITemplateValueParameter::get(Context, Tag, Name, Type, defaulted,
|
||||
getConstantAsMetadata()));
|
||||
EXPECT_NE(
|
||||
N, DITemplateValueParameter::get(Context, Tag, Name, Type, true, Value));
|
||||
|
||||
TempDITemplateValueParameter Temp = N->clone();
|
||||
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
|
||||
|
|
Loading…
Reference in New Issue