<div dir="ltr">In the future, please include more detail in the commit message of a recommit about how the patch addresses the problems that lead to the previous revert. This makes it easier for someone reviewing the code to examine the new changes & ensure they're correct/appropriate.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Mar 2, 2020 at 3:16 AM Sourabh Singh Tomar via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Awanish Pandey<br>
Date: 2020-03-02T16:45:48+05:30<br>
New Revision: 7a42babeb83e3927e89e72a0e7e45be9d41b6c23<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/7a42babeb83e3927e89e72a0e7e45be9d41b6c23" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/7a42babeb83e3927e89e72a0e7e45be9d41b6c23</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/7a42babeb83e3927e89e72a0e7e45be9d41b6c23.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/7a42babeb83e3927e89e72a0e7e45be9d41b6c23.diff</a><br>
<br>
LOG: Reland "[DebugInfo][clang][DWARF5]: Added support for debuginfo generation for defaulted parameters<br>
in C++ templates."<br>
<br>
This was reverted in 802b22b5c8c30bebc1695a217478be02653c6b53 due to<br>
missing .bc file and a chromium bot failure.<br>
<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1057559#c1" rel="noreferrer" target="_blank">https://bugs.chromium.org/p/chromium/issues/detail?id=1057559#c1</a><br>
This revision address both of them.<br>
<br>
Summary:<br>
This patch adds support for debuginfo generation for defaulted<br>
parameters in clang and also extends corresponding DebugMetadata/IR to support this feature.<br>
<br>
Reviewers: probinson, aprantl, dblaikie<br>
<br>
Reviewed By: aprantl, dblaikie<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D73462" rel="noreferrer" target="_blank">https://reviews.llvm.org/D73462</a><br>
<br>
Added: <br>
llvm/test/Assembler/DIDefaultTemplateParam.ll<br>
llvm/test/Bitcode/DITemplateParameter-5.0.ll<br>
llvm/test/Bitcode/DITemplateParameter-5.0.ll.bc<br>
<br>
Modified: <br>
clang/lib/CodeGen/CGDebugInfo.cpp<br>
llvm/include/llvm/IR/DIBuilder.h<br>
llvm/include/llvm/IR/DebugInfoMetadata.h<br>
llvm/lib/AsmParser/LLParser.cpp<br>
llvm/lib/Bitcode/Reader/MetadataLoader.cpp<br>
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
llvm/lib/IR/AsmWriter.cpp<br>
llvm/lib/IR/DIBuilder.cpp<br>
llvm/lib/IR/DebugInfoMetadata.cpp<br>
llvm/lib/IR/LLVMContextImpl.h<br>
llvm/unittests/IR/MetadataTest.cpp<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp<br>
index e171082942f6..cbf45a5cf748 100644<br>
--- a/clang/lib/CodeGen/CGDebugInfo.cpp<br>
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp<br>
@@ -1787,18 +1787,36 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,<br>
for (unsigned i = 0, e = TAList.size(); i != e; ++i) {<br>
const TemplateArgument &TA = TAList[i];<br>
StringRef Name;<br>
+ bool defaultParameter = false;<br>
if (TPList)<br>
Name = TPList->getParam(i)->getName();<br>
switch (TA.getKind()) {<br>
case TemplateArgument::Type: {<br>
llvm::DIType *TTy = getOrCreateType(TA.getAsType(), Unit);<br>
- TemplateParams.push_back(<br>
- DBuilder.createTemplateTypeParameter(TheCU, Name, TTy));<br>
+<br>
+ if (TPList)<br>
+ if (auto *templateType =<br>
+ dyn_cast_or_null<TemplateTypeParmDecl>(TPList->getParam(i)))<br>
+ if (templateType->hasDefaultArgument())<br>
+ defaultParameter =<br>
+ templateType->getDefaultArgument() == TA.getAsType();<br>
+<br>
+ TemplateParams.push_back(DBuilder.createTemplateTypeParameter(<br>
+ TheCU, Name, TTy, defaultParameter));<br>
+<br>
} break;<br>
case TemplateArgument::Integral: {<br>
llvm::DIType *TTy = getOrCreateType(TA.getIntegralType(), Unit);<br>
+ if (TPList && CGM.getCodeGenOpts().DwarfVersion >= 5)<br>
+ if (auto *templateType =<br>
+ dyn_cast_or_null<NonTypeTemplateParmDecl>(TPList->getParam(i)))<br>
+ if (templateType->hasDefaultArgument())<br>
+ defaultParameter =<br>
+ templateType->getDefaultArgument()->EvaluateKnownConstInt(<br>
+ CGM.getContext()) == TA.getAsIntegral();<br>
+<br>
TemplateParams.push_back(DBuilder.createTemplateValueParameter(<br>
- TheCU, Name, TTy,<br>
+ TheCU, Name, TTy, defaultParameter,<br>
llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral())));<br>
} break;<br>
case TemplateArgument::Declaration: {<br>
@@ -1837,7 +1855,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,<br>
V = V->stripPointerCasts();<br>
}<br>
TemplateParams.push_back(DBuilder.createTemplateValueParameter(<br>
- TheCU, Name, TTy, cast_or_null<llvm::Constant>(V)));<br>
+ TheCU, Name, TTy, defaultParameter, cast_or_null<llvm::Constant>(V)));<br>
} break;<br>
case TemplateArgument::NullPtr: {<br>
QualType T = TA.getNullPtrType();<br>
@@ -1855,8 +1873,8 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,<br>
V = CGM.getCXXABI().EmitNullMemberPointer(MPT);<br>
if (!V)<br>
V = llvm::ConstantInt::get(CGM.Int8Ty, 0);<br>
- TemplateParams.push_back(<br>
- DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V));<br>
+ TemplateParams.push_back(DBuilder.createTemplateValueParameter(<br>
+ TheCU, Name, TTy, defaultParameter, V));<br>
} break;<br>
case TemplateArgument::Template:<br>
TemplateParams.push_back(DBuilder.createTemplateTemplateParameter(<br>
@@ -1877,7 +1895,7 @@ CGDebugInfo::CollectTemplateParams(const TemplateParameterList *TPList,<br>
assert(V && "Expression in template argument isn't constant");<br>
llvm::DIType *TTy = getOrCreateType(T, Unit);<br>
TemplateParams.push_back(DBuilder.createTemplateValueParameter(<br>
- TheCU, Name, TTy, V->stripPointerCasts()));<br>
+ TheCU, Name, TTy, defaultParameter, V->stripPointerCasts()));<br>
} break;<br>
// And the following should never occur:<br>
case TemplateArgument::TemplateExpansion:<br>
<br>
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h<br>
index cbc96a483f91..604740dcdfb3 100644<br>
--- a/llvm/include/llvm/IR/DIBuilder.h<br>
+++ b/llvm/include/llvm/IR/DIBuilder.h<br>
@@ -443,19 +443,22 @@ namespace llvm {<br>
/// \param Scope Scope in which this type is defined.<br>
/// \param Name Type parameter name.<br>
/// \param Ty Parameter type.<br>
- DITemplateTypeParameter *<br>
- createTemplateTypeParameter(DIScope *Scope, StringRef Name, DIType *Ty);<br>
+ /// \param IsDefault Parameter is default or not<br>
+ DITemplateTypeParameter *createTemplateTypeParameter(DIScope *Scope,<br>
+ StringRef Name,<br>
+ DIType *Ty,<br>
+ bool IsDefault);<br>
<br>
/// Create debugging information for template<br>
/// value parameter.<br>
/// \param Scope Scope in which this type is defined.<br>
/// \param Name Value parameter name.<br>
/// \param Ty Parameter type.<br>
+ /// \param IsDefault Parameter is default or not<br>
/// \param Val Constant parameter value.<br>
- DITemplateValueParameter *createTemplateValueParameter(DIScope *Scope,<br>
- StringRef Name,<br>
- DIType *Ty,<br>
- Constant *Val);<br>
+ DITemplateValueParameter *<br>
+ createTemplateValueParameter(DIScope *Scope, StringRef Name, DIType *Ty,<br>
+ bool IsDefault, Constant *Val);<br>
<br>
/// Create debugging information for a template template parameter.<br>
/// \param Scope Scope in which this type is defined.<br>
<br>
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h<br>
index acc518445585..032ae598c1d4 100644<br>
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h<br>
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h<br>
@@ -2131,9 +2131,11 @@ class DIModule : public DIScope {<br>
/// Base class for template parameters.<br>
class DITemplateParameter : public DINode {<br>
protected:<br>
+ bool IsDefault;<br>
+<br>
DITemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage,<br>
- unsigned Tag, ArrayRef<Metadata *> Ops)<br>
- : DINode(Context, ID, Storage, Tag, Ops) {}<br>
+ unsigned Tag, bool IsDefault, ArrayRef<Metadata *> Ops)<br>
+ : DINode(Context, ID, Storage, Tag, Ops), IsDefault(IsDefault) {}<br>
~DITemplateParameter() = default;<br>
<br>
public:<br>
@@ -2142,6 +2144,7 @@ class DITemplateParameter : public DINode {<br>
<br>
MDString *getRawName() const { return getOperandAs<MDString>(0); }<br>
Metadata *getRawType() const { return getOperand(1); }<br>
+ bool isDefault() const { return IsDefault; }<br>
<br>
static bool classof(const Metadata *MD) {<br>
return MD->getMetadataID() == DITemplateTypeParameterKind ||<br>
@@ -2154,30 +2157,35 @@ class DITemplateTypeParameter : public DITemplateParameter {<br>
friend class MDNode;<br>
<br>
DITemplateTypeParameter(LLVMContext &Context, StorageType Storage,<br>
- ArrayRef<Metadata *> Ops)<br>
+ bool IsDefault, ArrayRef<Metadata *> Ops)<br>
: DITemplateParameter(Context, DITemplateTypeParameterKind, Storage,<br>
- dwarf::DW_TAG_template_type_parameter, Ops) {}<br>
+ dwarf::DW_TAG_template_type_parameter, IsDefault,<br>
+ Ops) {}<br>
~DITemplateTypeParameter() = default;<br>
<br>
static DITemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name,<br>
- DIType *Type, StorageType Storage,<br>
+ DIType *Type, bool IsDefault,<br>
+ StorageType Storage,<br>
bool ShouldCreate = true) {<br>
- return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage,<br>
- ShouldCreate);<br>
+ return getImpl(Context, getCanonicalMDString(Context, Name), Type,<br>
+ IsDefault, Storage, ShouldCreate);<br>
}<br>
static DITemplateTypeParameter *getImpl(LLVMContext &Context, MDString *Name,<br>
- Metadata *Type, StorageType Storage,<br>
+ Metadata *Type, bool IsDefault,<br>
+ StorageType Storage,<br>
bool ShouldCreate = true);<br>
<br>
TempDITemplateTypeParameter cloneImpl() const {<br>
- return getTemporary(getContext(), getName(), getType());<br>
+ return getTemporary(getContext(), getName(), getType(), isDefault());<br>
}<br>
<br>
public:<br>
- DEFINE_MDNODE_GET(DITemplateTypeParameter, (StringRef Name, DIType *Type),<br>
- (Name, Type))<br>
- DEFINE_MDNODE_GET(DITemplateTypeParameter, (MDString * Name, Metadata *Type),<br>
- (Name, Type))<br>
+ DEFINE_MDNODE_GET(DITemplateTypeParameter,<br>
+ (StringRef Name, DIType *Type, bool IsDefault),<br>
+ (Name, Type, IsDefault))<br>
+ DEFINE_MDNODE_GET(DITemplateTypeParameter,<br>
+ (MDString *Name, Metadata *Type, bool IsDefault),<br>
+ (Name, Type, IsDefault))<br>
<br>
TempDITemplateTypeParameter clone() const { return cloneImpl(); }<br>
<br>
@@ -2191,36 +2199,40 @@ class DITemplateValueParameter : public DITemplateParameter {<br>
friend class MDNode;<br>
<br>
DITemplateValueParameter(LLVMContext &Context, StorageType Storage,<br>
- unsigned Tag, ArrayRef<Metadata *> Ops)<br>
+ unsigned Tag, bool IsDefault,<br>
+ ArrayRef<Metadata *> Ops)<br>
: DITemplateParameter(Context, DITemplateValueParameterKind, Storage, Tag,<br>
- Ops) {}<br>
+ IsDefault, Ops) {}<br>
~DITemplateValueParameter() = default;<br>
<br>
static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,<br>
StringRef Name, DIType *Type,<br>
- Metadata *Value, StorageType Storage,<br>
+ bool IsDefault, Metadata *Value,<br>
+ StorageType Storage,<br>
bool ShouldCreate = true) {<br>
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type,<br>
- Value, Storage, ShouldCreate);<br>
+ IsDefault, Value, Storage, ShouldCreate);<br>
}<br>
static DITemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag,<br>
MDString *Name, Metadata *Type,<br>
- Metadata *Value, StorageType Storage,<br>
+ bool IsDefault, Metadata *Value,<br>
+ StorageType Storage,<br>
bool ShouldCreate = true);<br>
<br>
TempDITemplateValueParameter cloneImpl() const {<br>
return getTemporary(getContext(), getTag(), getName(), getType(),<br>
- getValue());<br>
+ isDefault(), getValue());<br>
}<br>
<br>
public:<br>
DEFINE_MDNODE_GET(DITemplateValueParameter,<br>
- (unsigned Tag, StringRef Name, DIType *Type,<br>
+ (unsigned Tag, StringRef Name, DIType *Type, bool IsDefault,<br>
Metadata *Value),<br>
- (Tag, Name, Type, Value))<br>
- DEFINE_MDNODE_GET(DITemplateValueParameter, (unsigned Tag, MDString *Name,<br>
- Metadata *Type, Metadata *Value),<br>
- (Tag, Name, Type, Value))<br>
+ (Tag, Name, Type, IsDefault, Value))<br>
+ DEFINE_MDNODE_GET(DITemplateValueParameter,<br>
+ (unsigned Tag, MDString *Name, Metadata *Type,<br>
+ bool IsDefault, Metadata *Value),<br>
+ (Tag, Name, Type, IsDefault, Value))<br>
<br>
TempDITemplateValueParameter clone() const { return cloneImpl(); }<br>
<br>
<br>
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp<br>
index a9ccc350052c..ad74303a784d 100644<br>
--- a/llvm/lib/AsmParser/LLParser.cpp<br>
+++ b/llvm/lib/AsmParser/LLParser.cpp<br>
@@ -4842,33 +4842,38 @@ bool LLParser::ParseDIModule(MDNode *&Result, bool IsDistinct) {<br>
}<br>
<br>
/// ParseDITemplateTypeParameter:<br>
-/// ::= !DITemplateTypeParameter(name: "Ty", type: !1)<br>
+/// ::= !DITemplateTypeParameter(name: "Ty", type: !1, defaulted: false)<br>
bool LLParser::ParseDITemplateTypeParameter(MDNode *&Result, bool IsDistinct) {<br>
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \<br>
OPTIONAL(name, MDStringField, ); \<br>
- REQUIRED(type, MDField, );<br>
+ REQUIRED(type, MDField, ); \<br>
+ OPTIONAL(defaulted, MDBoolField, );<br>
PARSE_MD_FIELDS();<br>
#undef VISIT_MD_FIELDS<br>
<br>
- Result =<br>
- GET_OR_DISTINCT(DITemplateTypeParameter, (Context, name.Val, type.Val));<br>
+ Result = GET_OR_DISTINCT(DITemplateTypeParameter,<br>
+ (Context, name.Val, type.Val, defaulted.Val));<br>
return false;<br>
}<br>
<br>
/// ParseDITemplateValueParameter:<br>
/// ::= !DITemplateValueParameter(tag: DW_TAG_template_value_parameter,<br>
-/// name: "V", type: !1, value: i32 7)<br>
+/// name: "V", type: !1, defaulted: false,<br>
+/// value: i32 7)<br>
bool LLParser::ParseDITemplateValueParameter(MDNode *&Result, bool IsDistinct) {<br>
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \<br>
OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_template_value_parameter)); \<br>
OPTIONAL(name, MDStringField, ); \<br>
OPTIONAL(type, MDField, ); \<br>
+ OPTIONAL(defaulted, MDBoolField, ); \<br>
REQUIRED(value, MDField, );<br>
+<br>
PARSE_MD_FIELDS();<br>
#undef VISIT_MD_FIELDS<br>
<br>
- Result = GET_OR_DISTINCT(DITemplateValueParameter,<br>
- (Context, tag.Val, name.Val, type.Val, value.Val));<br>
+ Result = GET_OR_DISTINCT(<br>
+ DITemplateValueParameter,<br>
+ (Context, tag.Val, name.Val, type.Val, defaulted.Val, value.Val));<br>
return false;<br>
}<br>
<br>
<br>
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp<br>
index 3cff468dca89..9a78a2bbcb4f 100644<br>
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp<br>
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp<br>
@@ -1668,27 +1668,34 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(<br>
break;<br>
}<br>
case bitc::METADATA_TEMPLATE_TYPE: {<br>
- if (Record.size() != 3)<br>
+ if (Record.size() < 3 || Record.size() > 4)<br>
return error("Invalid record");<br>
<br>
IsDistinct = Record[0];<br>
- MetadataList.assignValue(GET_OR_DISTINCT(DITemplateTypeParameter,<br>
- (Context, getMDString(Record[1]),<br>
- getDITypeRefOrNull(Record[2]))),<br>
- NextMetadataNo);<br>
+ MetadataList.assignValue(<br>
+ GET_OR_DISTINCT(DITemplateTypeParameter,<br>
+ (Context, getMDString(Record[1]),<br>
+ getDITypeRefOrNull(Record[2]),<br>
+ (Record.size() == 4) ? getMDOrNull(Record[3])<br>
+ : getMDOrNull(false))),<br>
+ NextMetadataNo);<br>
NextMetadataNo++;<br>
break;<br>
}<br>
case bitc::METADATA_TEMPLATE_VALUE: {<br>
- if (Record.size() != 5)<br>
+ if (Record.size() < 5 || Record.size() > 6)<br>
return error("Invalid record");<br>
<br>
IsDistinct = Record[0];<br>
+<br>
MetadataList.assignValue(<br>
- GET_OR_DISTINCT(DITemplateValueParameter,<br>
- (Context, Record[1], getMDString(Record[2]),<br>
- getDITypeRefOrNull(Record[3]),<br>
- getMDOrNull(Record[4]))),<br>
+ GET_OR_DISTINCT(<br>
+ DITemplateValueParameter,<br>
+ (Context, Record[1], getMDString(Record[2]),<br>
+ getDITypeRefOrNull(Record[3]),<br>
+ (Record.size() == 6) ? getMDOrNull(Record[4]) : getMDOrNull(false),<br>
+ (Record.size() == 6) ? getMDOrNull(Record[5])<br>
+ : getMDOrNull(Record[4]))),<br>
NextMetadataNo);<br>
NextMetadataNo++;<br>
break;<br>
<br>
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
index 6f3ff32279f1..f2ee1fd930a8 100644<br>
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp<br>
@@ -1792,6 +1792,7 @@ void ModuleBitcodeWriter::writeDITemplateTypeParameter(<br>
Record.push_back(N->isDistinct());<br>
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));<br>
Record.push_back(VE.getMetadataOrNullID(N->getType()));<br>
+ Record.push_back(N->isDefault());<br>
<br>
Stream.EmitRecord(bitc::METADATA_TEMPLATE_TYPE, Record, Abbrev);<br>
Record.clear();<br>
@@ -1804,6 +1805,7 @@ void ModuleBitcodeWriter::writeDITemplateValueParameter(<br>
Record.push_back(N->getTag());<br>
Record.push_back(VE.getMetadataOrNullID(N->getRawName()));<br>
Record.push_back(VE.getMetadataOrNullID(N->getType()));<br>
+ Record.push_back(N->isDefault());<br>
Record.push_back(VE.getMetadataOrNullID(N->getValue()));<br>
<br>
Stream.EmitRecord(bitc::METADATA_TEMPLATE_VALUE, Record, Abbrev);<br>
<br>
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp<br>
index 049aedd754ab..7c0b79fcabd9 100644<br>
--- a/llvm/lib/IR/AsmWriter.cpp<br>
+++ b/llvm/lib/IR/AsmWriter.cpp<br>
@@ -2073,6 +2073,7 @@ static void writeDITemplateTypeParameter(raw_ostream &Out,<br>
MDFieldPrinter Printer(Out, TypePrinter, Machine, Context);<br>
Printer.printString("name", N->getName());<br>
Printer.printMetadata("type", N->getRawType(), /* ShouldSkipNull */ false);<br>
+ Printer.printBool("defaulted", N->isDefault(), /* Default= */ false);<br>
Out << ")";<br>
}<br>
<br>
@@ -2087,6 +2088,7 @@ static void writeDITemplateValueParameter(raw_ostream &Out,<br>
Printer.printTag(N);<br>
Printer.printString("name", N->getName());<br>
Printer.printMetadata("type", N->getRawType());<br>
+ Printer.printBool("defaulted", N->isDefault(), /* Default= */ false);<br>
Printer.printMetadata("value", N->getValue(), /* ShouldSkipNull */ false);<br>
Out << ")";<br>
}<br>
<br>
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp<br>
index 60003991307d..762d9a1c1b46 100644<br>
--- a/llvm/lib/IR/DIBuilder.cpp<br>
+++ b/llvm/lib/IR/DIBuilder.cpp<br>
@@ -406,25 +406,26 @@ DIBuilder::createObjCProperty(StringRef Name, DIFile *File, unsigned LineNumber,<br>
<br>
DITemplateTypeParameter *<br>
DIBuilder::createTemplateTypeParameter(DIScope *Context, StringRef Name,<br>
- DIType *Ty) {<br>
+ DIType *Ty, bool isDefault) {<br>
assert((!Context || isa<DICompileUnit>(Context)) && "Expected compile unit");<br>
- return DITemplateTypeParameter::get(VMContext, Name, Ty);<br>
+ return DITemplateTypeParameter::get(VMContext, Name, Ty, isDefault);<br>
}<br>
<br>
static DITemplateValueParameter *<br>
createTemplateValueParameterHelper(LLVMContext &VMContext, unsigned Tag,<br>
DIScope *Context, StringRef Name, DIType *Ty,<br>
- Metadata *MD) {<br>
+ bool IsDefault, Metadata *MD) {<br>
assert((!Context || isa<DICompileUnit>(Context)) && "Expected compile unit");<br>
- return DITemplateValueParameter::get(VMContext, Tag, Name, Ty, MD);<br>
+ return DITemplateValueParameter::get(VMContext, Tag, Name, Ty, IsDefault, MD);<br>
}<br>
<br>
DITemplateValueParameter *<br>
DIBuilder::createTemplateValueParameter(DIScope *Context, StringRef Name,<br>
- DIType *Ty, Constant *Val) {<br>
+ DIType *Ty, bool isDefault,<br>
+ Constant *Val) {<br>
return createTemplateValueParameterHelper(<br>
VMContext, dwarf::DW_TAG_template_value_parameter, Context, Name, Ty,<br>
- getConstantOrNull(Val));<br>
+ isDefault, getConstantOrNull(Val));<br>
}<br>
<br>
DITemplateValueParameter *<br>
@@ -432,7 +433,7 @@ DIBuilder::createTemplateTemplateParameter(DIScope *Context, StringRef Name,<br>
DIType *Ty, StringRef Val) {<br>
return createTemplateValueParameterHelper(<br>
VMContext, dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty,<br>
- MDString::get(VMContext, Val));<br>
+ false, MDString::get(VMContext, Val));<br>
}<br>
<br>
DITemplateValueParameter *<br>
@@ -440,7 +441,7 @@ DIBuilder::createTemplateParameterPack(DIScope *Context, StringRef Name,<br>
DIType *Ty, DINodeArray Val) {<br>
return createTemplateValueParameterHelper(<br>
VMContext, dwarf::DW_TAG_GNU_template_parameter_pack, Context, Name, Ty,<br>
- Val.get());<br>
+ false, Val.get());<br>
}<br>
<br>
DICompositeType *DIBuilder::createClassType(<br>
<br>
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp<br>
index c470a9696c3d..b630a2893b4d 100644<br>
--- a/llvm/lib/IR/DebugInfoMetadata.cpp<br>
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp<br>
@@ -724,24 +724,24 @@ DIModule *DIModule::getImpl(LLVMContext &Context, Metadata *Scope,<br>
DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DIModule, Ops);<br>
}<br>
<br>
-DITemplateTypeParameter *DITemplateTypeParameter::getImpl(LLVMContext &Context,<br>
- MDString *Name,<br>
- Metadata *Type,<br>
- StorageType Storage,<br>
- bool ShouldCreate) {<br>
+DITemplateTypeParameter *<br>
+DITemplateTypeParameter::getImpl(LLVMContext &Context, MDString *Name,<br>
+ Metadata *Type, bool isDefault,<br>
+ StorageType Storage, bool ShouldCreate) {<br>
assert(isCanonical(Name) && "Expected canonical MDString");<br>
- DEFINE_GETIMPL_LOOKUP(DITemplateTypeParameter, (Name, Type));<br>
+ DEFINE_GETIMPL_LOOKUP(DITemplateTypeParameter, (Name, Type, isDefault));<br>
Metadata *Ops[] = {Name, Type};<br>
- DEFINE_GETIMPL_STORE_NO_CONSTRUCTOR_ARGS(DITemplateTypeParameter, Ops);<br>
+ DEFINE_GETIMPL_STORE(DITemplateTypeParameter, (isDefault), Ops);<br>
}<br>
<br>
DITemplateValueParameter *DITemplateValueParameter::getImpl(<br>
LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *Type,<br>
- Metadata *Value, StorageType Storage, bool ShouldCreate) {<br>
+ bool isDefault, Metadata *Value, StorageType Storage, bool ShouldCreate) {<br>
assert(isCanonical(Name) && "Expected canonical MDString");<br>
- DEFINE_GETIMPL_LOOKUP(DITemplateValueParameter, (Tag, Name, Type, Value));<br>
+ DEFINE_GETIMPL_LOOKUP(DITemplateValueParameter,<br>
+ (Tag, Name, Type, isDefault, Value));<br>
Metadata *Ops[] = {Name, Type, Value};<br>
- DEFINE_GETIMPL_STORE(DITemplateValueParameter, (Tag), Ops);<br>
+ DEFINE_GETIMPL_STORE(DITemplateValueParameter, (Tag, isDefault), Ops);<br>
}<br>
<br>
DIGlobalVariable *<br>
<br>
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h<br>
index e912c4ba1f70..7f324b103997 100644<br>
--- a/llvm/lib/IR/LLVMContextImpl.h<br>
+++ b/llvm/lib/IR/LLVMContextImpl.h<br>
@@ -843,36 +843,45 @@ template <> struct MDNodeKeyImpl<DIModule> {<br>
template <> struct MDNodeKeyImpl<DITemplateTypeParameter> {<br>
MDString *Name;<br>
Metadata *Type;<br>
+ bool IsDefault;<br>
<br>
- MDNodeKeyImpl(MDString *Name, Metadata *Type) : Name(Name), Type(Type) {}<br>
+ MDNodeKeyImpl(MDString *Name, Metadata *Type, bool IsDefault)<br>
+ : Name(Name), Type(Type), IsDefault(IsDefault) {}<br>
MDNodeKeyImpl(const DITemplateTypeParameter *N)<br>
- : Name(N->getRawName()), Type(N->getRawType()) {}<br>
+ : Name(N->getRawName()), Type(N->getRawType()),<br>
+ IsDefault(N->isDefault()) {}<br>
<br>
bool isKeyOf(const DITemplateTypeParameter *RHS) const {<br>
- return Name == RHS->getRawName() && Type == RHS->getRawType();<br>
+ return Name == RHS->getRawName() && Type == RHS->getRawType() &&<br>
+ IsDefault == RHS->isDefault();<br>
}<br>
<br>
- unsigned getHashValue() const { return hash_combine(Name, Type); }<br>
+ unsigned getHashValue() const { return hash_combine(Name, Type, IsDefault); }<br>
};<br>
<br>
template <> struct MDNodeKeyImpl<DITemplateValueParameter> {<br>
unsigned Tag;<br>
MDString *Name;<br>
Metadata *Type;<br>
+ bool IsDefault;<br>
Metadata *Value;<br>
<br>
- MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, Metadata *Value)<br>
- : Tag(Tag), Name(Name), Type(Type), Value(Value) {}<br>
+ MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, bool IsDefault,<br>
+ Metadata *Value)<br>
+ : Tag(Tag), Name(Name), Type(Type), IsDefault(IsDefault), Value(Value) {}<br>
MDNodeKeyImpl(const DITemplateValueParameter *N)<br>
: Tag(N->getTag()), Name(N->getRawName()), Type(N->getRawType()),<br>
- Value(N->getValue()) {}<br>
+ IsDefault(N->isDefault()), Value(N->getValue()) {}<br>
<br>
bool isKeyOf(const DITemplateValueParameter *RHS) const {<br>
return Tag == RHS->getTag() && Name == RHS->getRawName() &&<br>
- Type == RHS->getRawType() && Value == RHS->getValue();<br>
+ Type == RHS->getRawType() && IsDefault == RHS->isDefault() &&<br>
+ Value == RHS->getValue();<br>
}<br>
<br>
- unsigned getHashValue() const { return hash_combine(Tag, Name, Type, Value); }<br>
+ unsigned getHashValue() const {<br>
+ return hash_combine(Tag, Name, Type, IsDefault, Value);<br>
+ }<br>
};<br>
<br>
template <> struct MDNodeKeyImpl<DIGlobalVariable> {<br>
<br>
diff --git a/llvm/test/Assembler/DIDefaultTemplateParam.ll b/llvm/test/Assembler/DIDefaultTemplateParam.ll<br>
new file mode 100644<br>
index 000000000000..d78377adfada<br>
--- /dev/null<br>
+++ b/llvm/test/Assembler/DIDefaultTemplateParam.ll<br>
@@ -0,0 +1,65 @@<br>
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s<br>
+; RUN: verify-uselistorder %s<br>
+<br>
+; ModuleID = '/dir/test.cpp'<br>
+source_filename = "test.cpp"<br>
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"<br>
+target triple = "x86_64-unknown-linux-gnu"<br>
+<br>
+%class.foo = type { i8 }<br>
+%class.foo.0 = type { i8 }<br>
+; Function Attrs: noinline norecurse nounwind optnone uwtable<br>
+define dso_local i32 @main() #0 !dbg !7 {<br>
+entry:<br>
+ %retval = alloca i32, align 4<br>
+ %f1 = alloca %class.foo, align 1<br>
+ %f2 = alloca %class.foo.0, align 1<br>
+ store i32 0, i32* %retval, align 4<br>
+ call void @llvm.dbg.declare(metadata %class.foo* %f1, metadata !11, metadata !DIExpression()), !dbg !16<br>
+ call void @llvm.dbg.declare(metadata %class.foo.0* %f2, metadata !17, metadata !DIExpression()), !dbg !23<br>
+ ret i32 0, !dbg !24<br>
+}<br>
+; Function Attrs: nounwind readnone speculatable willreturn<br>
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1<br>
+<br>
+attributes #0 = { noinline norecurse nounwind optnone uwtable }<br>
+attributes #1 = { nounwind readnone speculatable willreturn }<br>
+<br>
+!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!3, !4, !5}<br>
+!llvm.ident = !{!6}<br>
+<br>
+!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)<br>
+!1 = !DIFile(filename: "test.cpp", directory: "/dir/", checksumkind: CSK_MD5, checksum: "863d08522c2300490dea873efc4b2369")<br>
+!2 = !{}<br>
+!3 = !{i32 7, !"Dwarf Version", i32 5}<br>
+!4 = !{i32 2, !"Debug Info Version", i32 3}<br>
+!5 = !{i32 1, !"wchar_size", i32 4}<br>
+!6 = !{!"clang version 11.0.0"}<br>
+!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 29, type: !8, scopeLine: 29, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)<br>
+!8 = !DISubroutineType(types: !9)<br>
+!9 = !{!10}<br>
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+!11 = !DILocalVariable(name: "f1", scope: !7, file: !1, line: 30, type: !12)<br>
+!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")<br>
+!13 = !{!14, !15}<br>
+<br>
+; CHECK: 14 = !DITemplateTypeParameter(name: "T", type: !{{[0-9]*}})<br>
+!14 = !DITemplateTypeParameter(name: "T", type: !10)<br>
+<br>
+; CHECK: 15 = !DITemplateValueParameter(name: "i", type: !{{[0-9]*}}, value: i32 6)<br>
+!15 = !DITemplateValueParameter(name: "i", type: !10, value: i32 6)<br>
+<br>
+!16 = !DILocation(line: 30, column: 14, scope: !7)<br>
+!17 = !DILocalVariable(name: "f2", scope: !7, file: !1, line: 31, type: !18)<br>
+!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")<br>
+!19 = !{!20, !22}<br>
+<br>
+; CHECK: 20 = !DITemplateTypeParameter({{.*}}, defaulted: true<br>
+!20 = !DITemplateTypeParameter(name: "T", type: !21, defaulted: true)<br>
+!21 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)<br>
+<br>
+; CHECK: 22 = !DITemplateValueParameter({{.*}}, defaulted: true<br>
+!22 = !DITemplateValueParameter(name: "i", type: !10, defaulted: true, value: i32 3)<br>
+!23 = !DILocation(line: 31, column: 9, scope: !7)<br>
+!24 = !DILocation(line: 32, column: 3, scope: !7)<br>
<br>
diff --git a/llvm/test/Bitcode/DITemplateParameter-5.0.ll b/llvm/test/Bitcode/DITemplateParameter-5.0.ll<br>
new file mode 100644<br>
index 000000000000..1659bd6d84a3<br>
--- /dev/null<br>
+++ b/llvm/test/Bitcode/DITemplateParameter-5.0.ll<br>
@@ -0,0 +1,69 @@<br>
+; RUN: llvm-dis -o - %s.bc | FileCheck %s<br>
+<br>
+; ModuleID = '/dir/test.cpp'<br>
+source_filename = "test.cpp"<br>
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"<br>
+target triple = "x86_64-unknown-linux-gnu"<br>
+<br>
+%class.foo = type { i8 }<br>
+%class.foo.0 = type { i8 }<br>
+; Function Attrs: noinline norecurse nounwind optnone uwtable<br>
+define dso_local i32 @main() #0 !dbg !7 {<br>
+entry:<br>
+ %retval = alloca i32, align 4<br>
+ %f1 = alloca %class.foo, align 1<br>
+ %f2 = alloca %class.foo.0, align 1<br>
+ store i32 0, i32* %retval, align 4<br>
+ call void @llvm.dbg.declare(metadata %class.foo* %f1, metadata !11, metadata !DIExpression()), !dbg !16<br>
+ call void @llvm.dbg.declare(metadata %class.foo.0* %f2, metadata !17, metadata !DIExpression()), !dbg !23<br>
+ ret i32 0, !dbg !24<br>
+}<br>
+; Function Attrs: nounwind readnone speculatable willreturn<br>
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1<br>
+<br>
+attributes #0 = { noinline norecurse nounwind optnone uwtable }<br>
+attributes #1 = { nounwind readnone speculatable willreturn }<br>
+<br>
+!<a href="http://llvm.dbg.cu" rel="noreferrer" target="_blank">llvm.dbg.cu</a> = !{!0}<br>
+!llvm.module.flags = !{!3, !4, !5}<br>
+!llvm.ident = !{!6}<br>
+<br>
+!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)<br>
+!1 = !DIFile(filename: "test.cpp", directory: "/dir/", checksumkind: CSK_MD5, checksum: "863d08522c2300490dea873efc4b2369")<br>
+!2 = !{}<br>
+!3 = !{i32 7, !"Dwarf Version", i32 5}<br>
+!4 = !{i32 2, !"Debug Info Version", i32 3}<br>
+!5 = !{i32 1, !"wchar_size", i32 4}<br>
+!6 = !{!"clang version 11.0.0"}<br>
+!7 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 29, type: !8, scopeLine: 29, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)<br>
+!8 = !DISubroutineType(types: !9)<br>
+!9 = !{!10}<br>
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)<br>
+!11 = !DILocalVariable(name: "f1", scope: !7, file: !1, line: 30, type: !12)<br>
+!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")<br>
+!13 = !{!14, !15}<br>
+<br>
+; Old-style DITemplateTypeParameter and DITemplateValueParameter should be<br>
+; upgraded to include defaulted flag.<br>
+<br>
+; CHECK: !DITemplateTypeParameter({{.*}}<br>
+!14 = !DITemplateTypeParameter(name: "T", type: !10)<br>
+<br>
+; CHECK: !DITemplateValueParameter({{.*}}<br>
+!15 = !DITemplateValueParameter(name: "i", type: !10, value: i32 6)<br>
+<br>
+!16 = !DILocation(line: 30, column: 14, scope: !7)<br>
+!17 = !DILocalVariable(name: "f2", scope: !7, file: !1, line: 31, type: !18)<br>
+!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")<br>
+!19 = !{!20, !22}<br>
+<br>
+; CHECK: !DITemplateTypeParameter({{.*}} defaulted: true<br>
+!20 = !DITemplateTypeParameter(name: "T", type: !21, defaulted: true)<br>
+<br>
+!21 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)<br>
+<br>
+; CHECK: !DITemplateValueParameter({{.*}} defaulted: true<br>
+!22 = !DITemplateValueParameter(name: "i", type: !10, defaulted: true, value: i32 3)<br>
+<br>
+!23 = !DILocation(line: 31, column: 9, scope: !7)<br>
+!24 = !DILocation(line: 32, column: 3, scope: !7)<br>
<br>
diff --git a/llvm/test/Bitcode/DITemplateParameter-5.0.ll.bc b/llvm/test/Bitcode/DITemplateParameter-5.0.ll.bc<br>
new file mode 100644<br>
index 000000000000..59eae46255e3<br>
Binary files /dev/null and b/llvm/test/Bitcode/DITemplateParameter-5.0.ll.bc <br>
diff er<br>
<br>
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp<br>
index 6c06af8bd71e..0480f9761731 100644<br>
--- a/llvm/unittests/IR/MetadataTest.cpp<br>
+++ b/llvm/unittests/IR/MetadataTest.cpp<br>
@@ -2076,17 +2076,19 @@ typedef MetadataTest DITemplateTypeParameterTest;<br>
TEST_F(DITemplateTypeParameterTest, get) {<br>
StringRef Name = "template";<br>
DIType *Type = getBasicType("basic");<br>
+ bool defaulted = false;<br>
<br>
- auto *N = DITemplateTypeParameter::get(Context, Name, Type);<br>
+ auto *N = DITemplateTypeParameter::get(Context, Name, Type, defaulted);<br>
<br>
EXPECT_EQ(dwarf::DW_TAG_template_type_parameter, N->getTag());<br>
EXPECT_EQ(Name, N->getName());<br>
EXPECT_EQ(Type, N->getType());<br>
- EXPECT_EQ(N, DITemplateTypeParameter::get(Context, Name, Type));<br>
+ EXPECT_EQ(N, DITemplateTypeParameter::get(Context, Name, Type, defaulted));<br>
<br>
- EXPECT_NE(N, DITemplateTypeParameter::get(Context, "other", Type));<br>
- EXPECT_NE(N,<br>
- DITemplateTypeParameter::get(Context, Name, getBasicType("other")));<br>
+ EXPECT_NE(N, DITemplateTypeParameter::get(Context, "other", Type, defaulted));<br>
+ EXPECT_NE(N, DITemplateTypeParameter::get(Context, Name,<br>
+ getBasicType("other"), defaulted));<br>
+ EXPECT_NE(N, DITemplateTypeParameter::get(Context, Name, Type, true));<br>
<br>
TempDITemplateTypeParameter Temp = N->clone();<br>
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));<br>
@@ -2098,24 +2100,31 @@ TEST_F(DITemplateValueParameterTest, get) {<br>
unsigned Tag = dwarf::DW_TAG_template_value_parameter;<br>
StringRef Name = "template";<br>
DIType *Type = getBasicType("basic");<br>
+ bool defaulted = false;<br>
Metadata *Value = getConstantAsMetadata();<br>
<br>
- auto *N = DITemplateValueParameter::get(Context, Tag, Name, Type, Value);<br>
+ auto *N =<br>
+ DITemplateValueParameter::get(Context, Tag, Name, Type, defaulted, Value);<br>
EXPECT_EQ(Tag, N->getTag());<br>
EXPECT_EQ(Name, N->getName());<br>
EXPECT_EQ(Type, N->getType());<br>
EXPECT_EQ(Value, N->getValue());<br>
- EXPECT_EQ(N, DITemplateValueParameter::get(Context, Tag, Name, Type, Value));<br>
+ EXPECT_EQ(N, DITemplateValueParameter::get(Context, Tag, Name, Type,<br>
+ defaulted, Value));<br>
<br>
EXPECT_NE(N, DITemplateValueParameter::get(<br>
Context, dwarf::DW_TAG_GNU_template_template_param, Name,<br>
- Type, Value));<br>
- EXPECT_NE(N,<br>
- DITemplateValueParameter::get(Context, Tag, "other", Type, Value));<br>
+ Type, defaulted, Value));<br>
+ EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, "other", Type,<br>
+ defaulted, Value));<br>
EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, Name,<br>
- getBasicType("other"), Value));<br>
- EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, Name, Type,<br>
- getConstantAsMetadata()));<br>
+ getBasicType("other"), defaulted,<br>
+ Value));<br>
+ EXPECT_NE(N,<br>
+ DITemplateValueParameter::get(Context, Tag, Name, Type, defaulted,<br>
+ getConstantAsMetadata()));<br>
+ EXPECT_NE(<br>
+ N, DITemplateValueParameter::get(Context, Tag, Name, Type, true, Value));<br>
<br>
TempDITemplateValueParameter Temp = N->clone();<br>
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));<br>
<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>