llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (memory-thrasher) <details> <summary>Changes</summary> …to handle template argument values that are pointers one-past-the-end of a non-array symbol. Also improves error messages in other template argument scenarios where clang bails. https://github.com/llvm/llvm-project/issues/97756 I don't think I hooked up the unit test right. I'm not sure one is really needed for what boils down to a tweaked if statement. Please advise. --- Full diff: https://github.com/llvm/llvm-project/pull/97792.diff 2 Files Affected: - (modified) clang/lib/AST/MicrosoftMangle.cpp (+43-14) - (added) clang/test/CodeGen/ms_mangler_templatearg_opte.cpp (+42) ``````````diff diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index fac14ce1dce8c..f348a3a2dcce7 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1922,9 +1922,12 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, if (WithScalarType) mangleType(T, SourceRange(), QMM_Escape); - // We don't know how to mangle past-the-end pointers yet. - if (V.isLValueOnePastTheEnd()) - break; + // msvc does not support this, so no mangling will ever be "right", so this + // was picked arbitrarily. + if (V.isLValueOnePastTheEnd()) { + Out << "@IN"; // for "invalid pointer" since it always is invalid. + return; + } APValue::LValueBase Base = V.getLValueBase(); if (!V.hasLValuePath() || V.getLValuePath().empty()) { @@ -1938,12 +1941,23 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, mangleNumber(V.getLValueOffset().getQuantity()); } else if (!V.hasLValuePath()) { // FIXME: This can only happen as an extension. Invent a mangling. - break; + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = + Diags.getCustomDiagID(DiagnosticsEngine::Error, + "cannot mangle this template argument yet " + "(non-null base with null lvalue path)"); + Diags.Report(DiagID); + return; } else if (auto *VD = Base.dyn_cast<const ValueDecl*>()) { Out << "E"; mangle(VD); } else { - break; + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this template argument yet (empty lvalue path)"); + Diags.Report(DiagID); + return; } } else { if (TAK == TplArgKind::ClassNTTP && T->isPointerType()) @@ -1988,8 +2002,14 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, Out << *I; auto *VD = Base.dyn_cast<const ValueDecl*>(); - if (!VD) - break; + if (!VD) { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this template argument yet (null value decl)"); + Diags.Report(DiagID); + return; + } Out << (TAK == TplArgKind::ClassNTTP ? 'E' : '1'); mangle(VD); @@ -2104,15 +2124,24 @@ void MicrosoftCXXNameMangler::mangleTemplateArgValue(QualType T, return; } - case APValue::AddrLabelDiff: - case APValue::FixedPoint: - break; + case APValue::AddrLabelDiff: { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, "cannot mangle this template argument yet " + "(value type: address label diff)"); + Diags.Report(DiagID); + return; } - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID( - DiagnosticsEngine::Error, "cannot mangle this template argument yet"); - Diags.Report(DiagID); + case APValue::FixedPoint: { + DiagnosticsEngine &Diags = Context.getDiags(); + unsigned DiagID = Diags.getCustomDiagID( + DiagnosticsEngine::Error, + "cannot mangle this template argument yet (value type: fixed point)"); + Diags.Report(DiagID); + return; + } + } } void MicrosoftCXXNameMangler::mangleObjCProtocol(const ObjCProtocolDecl *PD) { diff --git a/clang/test/CodeGen/ms_mangler_templatearg_opte.cpp b/clang/test/CodeGen/ms_mangler_templatearg_opte.cpp new file mode 100644 index 0000000000000..852a20cfb5712 --- /dev/null +++ b/clang/test/CodeGen/ms_mangler_templatearg_opte.cpp @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc19.33.0 -emit-llvm -std=c++20 -x c++ < %s | FileCheck --check-prefix=WIN64 %s + +/* + +this works (linux host): +clang++ -std=c++20 -c ms_mangler_templatearg_opte.cpp -o /dev/null + +this dost not: +/usr/local/bin/clang-17 -cc1 -triple x86_64-pc-windows-msvc19.33.0 -emit-obj -std=c++20 -o ms_mangler_templatearg_opte.obj -x c++ ms_mangler_templatearg_opte.cpp + +The first pass is fine, it's the final pass of cesum where L.data = (&ints)+1 that clang bawks at. Obviously this address can't be dereferenced, but the `if constexpr` sees to that. The unused template param should not break the mangler. + +*/ + + +typedef long long unsigned size_t; + +template<class T> struct llist { + const T* data; + size_t len; + constexpr llist(const T* data, size_t len) : data(data), len(len) {}; + constexpr inline bool empty() const { return len == 0; }; + constexpr llist<T> next() const { return { data+1, len-1 }; }; + constexpr const T& peek() const { return data[0]; }; +}; + +//recurse to iterate over the list, without the need for a terminal overload or duplicated handling of the terminal case +template<llist<int> L> int cesum() { + if constexpr(L.empty()) { + return 0; + } else { + return L.peek() + cesum<L.next()>(); + } +}; + +//constexpr int ints[] = { 1, 2, 7, 8, 9, -17, -10 }; //Note: this does NOT break the unpatched mangler +constexpr int ints = 7; + +int main() { + return cesum<llist<int>(&ints, 1)>();//taking address of non-array +}; + `````````` </details> https://github.com/llvm/llvm-project/pull/97792 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits