The invented mangling for clang-cl turns out to not be correct :) https://bugs.llvm.org/show_bug.cgi?id=42093
Maybe it's better to add a "can't yet mangle" error, so that we don't silently do the wrong thing? On Sun, Aug 14, 2016 at 9:41 PM Richard Smith via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: rsmith > Date: Sun Aug 14 20:33:41 2016 > New Revision: 278642 > > URL: http://llvm.org/viewvc/llvm-project?rev=278642&view=rev > Log: > P0217R3: code generation support for decomposition declarations. > > Added: > cfe/trunk/test/CodeGenCXX/cxx1z-decomposition.cpp > Modified: > cfe/trunk/lib/AST/ASTContext.cpp > cfe/trunk/lib/AST/ItaniumMangle.cpp > cfe/trunk/lib/AST/MicrosoftMangle.cpp > cfe/trunk/lib/CodeGen/CGDecl.cpp > cfe/trunk/lib/CodeGen/CGExpr.cpp > cfe/trunk/lib/CodeGen/CodeGenModule.cpp > cfe/trunk/lib/Sema/SemaDeclCXX.cpp > cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp > > Modified: cfe/trunk/lib/AST/ASTContext.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=278642&r1=278641&r2=278642&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/ASTContext.cpp (original) > +++ cfe/trunk/lib/AST/ASTContext.cpp Sun Aug 14 20:33:41 2016 > @@ -8721,6 +8721,14 @@ bool ASTContext::DeclMustBeEmitted(const > !VD->evaluateValue()) > return true; > > + // Likewise, variables with tuple-like bindings are required if their > + // bindings have side-effects. > + if (auto *DD = dyn_cast<DecompositionDecl>(VD)) > + for (auto *BD : DD->bindings()) > + if (auto *BindingVD = BD->getHoldingVar()) > + if (DeclMustBeEmitted(BindingVD)) > + return true; > + > return false; > } > > > Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=278642&r1=278641&r2=278642&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) > +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Sun Aug 14 20:33:41 2016 > @@ -1195,18 +1195,21 @@ void CXXNameMangler::mangleUnqualifiedNa > case DeclarationName::Identifier: { > const IdentifierInfo *II = Name.getAsIdentifierInfo(); > > - // We mangle decomposition declarations as the name of their first > binding. > + // We mangle decomposition declarations as the names of their > bindings. > if (auto *DD = dyn_cast<DecompositionDecl>(ND)) { > - auto B = DD->bindings(); > - if (B.begin() == B.end()) { > - // FIXME: This is ill-formed but we accept it as an extension. > - DiagnosticsEngine &Diags = Context.getDiags(); > - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, > - "cannot mangle global empty decomposition decl"); > - Diags.Report(DD->getLocation(), DiagID); > - break; > - } > - II = (*B.begin())->getIdentifier(); > + // FIXME: Non-standard mangling for decomposition declarations: > + // > + // <unqualified-name> ::= DC <source-name>* E > + // > + // These can never be referenced across translation units, so we do > + // not need a cross-vendor mangling for anything other than > demanglers. > + // Proposed on cxx-abi-dev on 2016-08-12 > + Out << "DC"; > + for (auto *BD : DD->bindings()) > + mangleSourceName(BD->getDeclName().getAsIdentifierInfo()); > + Out << 'E'; > + writeAbiTags(ND, AdditionalAbiTags); > + break; > } > > if (II) { > > Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=278642&r1=278641&r2=278642&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original) > +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Sun Aug 14 20:33:41 2016 > @@ -394,7 +394,8 @@ bool MicrosoftMangleContextImpl::shouldM > if (!getASTContext().getLangOpts().CPlusPlus) > return false; > > - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { > + const VarDecl *VD = dyn_cast<VarDecl>(D); > + if (VD && !isa<DecompositionDecl>(D)) { > // C variables are not mangled. > if (VD->isExternC()) > return false; > @@ -780,6 +781,21 @@ void MicrosoftCXXNameMangler::mangleUnqu > } > } > > + if (const DecompositionDecl *DD = dyn_cast<DecompositionDecl>(ND)) { > + // FIXME: Invented mangling for decomposition declarations: > + // [X,Y,Z] > + // where X,Y,Z are the names of the bindings. > + llvm::SmallString<128> Name("["); > + for (auto *BD : DD->bindings()) { > + if (Name.size() > 1) > + Name += ','; > + Name += BD->getDeclName().getAsIdentifierInfo()->getName(); > + } > + Name += ']'; > + mangleSourceName(Name); > + break; > + } > + > if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) { > // We must have an anonymous union or struct declaration. > const CXXRecordDecl *RD = VD->getType()->getAsCXXRecordDecl(); > > Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=278642&r1=278641&r2=278642&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Sun Aug 14 20:33:41 2016 > @@ -87,6 +87,7 @@ void CodeGenFunction::EmitDecl(const Dec > case Decl::UsingShadow: > case Decl::ConstructorUsingShadow: > case Decl::ObjCTypeParam: > + case Decl::Binding: > llvm_unreachable("Declaration should not be in declstmts!"); > case Decl::Function: // void X(); > case Decl::Record: // struct/union/class X; > @@ -119,10 +120,13 @@ void CodeGenFunction::EmitDecl(const Dec > const VarDecl &VD = cast<VarDecl>(D); > assert(VD.isLocalVarDecl() && > "Should not see file-scope variables inside a function!"); > - return EmitVarDecl(VD); > + EmitVarDecl(VD); > + if (auto *DD = dyn_cast<DecompositionDecl>(&VD)) > + for (auto *B : DD->bindings()) > + if (auto *HD = B->getHoldingVar()) > + EmitVarDecl(*HD); > + return; > } > - case Decl::Binding: > - return CGM.ErrorUnsupported(&D, "structured binding"); > > case Decl::OMPDeclareReduction: > return CGM.EmitOMPDeclareReduction(cast<OMPDeclareReductionDecl>(&D), > this); > > Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=278642&r1=278641&r2=278642&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CGExpr.cpp (original) > +++ cfe/trunk/lib/CodeGen/CGExpr.cpp Sun Aug 14 20:33:41 2016 > @@ -2206,6 +2206,12 @@ LValue CodeGenFunction::EmitDeclRefLValu > if (const auto *FD = dyn_cast<FunctionDecl>(ND)) > return EmitFunctionDeclLValue(*this, E, FD); > > + // FIXME: While we're emitting a binding from an enclosing scope, all > other > + // DeclRefExprs we see should be implicitly treated as if they also > refer to > + // an enclosing scope. > + if (const auto *BD = dyn_cast<BindingDecl>(ND)) > + return EmitLValue(BD->getBinding()); > + > llvm_unreachable("Unhandled DeclRefExpr"); > } > > > Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=278642&r1=278641&r2=278642&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original) > +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sun Aug 14 20:33:41 2016 > @@ -3772,6 +3772,10 @@ void CodeGenModule::EmitTopLevelDecl(Dec > return; > case Decl::VarTemplateSpecialization: > EmitGlobal(cast<VarDecl>(D)); > + if (auto *DD = dyn_cast<DecompositionDecl>(D)) > + for (auto *B : DD->bindings()) > + if (auto *HD = B->getHoldingVar()) > + EmitGlobal(HD); > break; > > // Indirect fields from global anonymous structs and unions can be > > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=278642&r1=278641&r2=278642&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sun Aug 14 20:33:41 2016 > @@ -1160,6 +1160,7 @@ static bool checkTupleLikeDecomposition( > RefVD->setImplicit(); > if (Src->isInlineSpecified()) > RefVD->setInlineSpecified(); > + RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD); > > InitializedEntity Entity = > InitializedEntity::InitializeBinding(RefVD); > InitializationKind Kind = InitializationKind::CreateCopy(Loc, Loc); > @@ -1167,11 +1168,12 @@ static bool checkTupleLikeDecomposition( > E = Seq.Perform(S, Entity, Kind, Init); > if (E.isInvalid()) > return true; > + E = S.ActOnFinishFullExpr(E.get(), Loc); > + if (E.isInvalid()) > + return true; > RefVD->setInit(E.get()); > RefVD->checkInitIsICE(); > > - RefVD->getLexicalDeclContext()->addHiddenDecl(RefVD); > - > E = S.BuildDeclarationNameExpr(CXXScopeSpec(), > DeclarationNameInfo(B->getDeclName(), > Loc), > RefVD); > > Added: cfe/trunk/test/CodeGenCXX/cxx1z-decomposition.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1z-decomposition.cpp?rev=278642&view=auto > > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/cxx1z-decomposition.cpp (added) > +++ cfe/trunk/test/CodeGenCXX/cxx1z-decomposition.cpp Sun Aug 14 20:33:41 > 2016 > @@ -0,0 +1,118 @@ > +// RUN: %clang_cc1 -std=c++1z -emit-llvm -o - %s | FileCheck %s > + > +namespace std { > + using size_t = decltype(sizeof(0)); > + template<typename> struct tuple_size; > + template<size_t, typename> struct tuple_element; > +} > + > +struct Y { int n; }; > +struct X { X(); X(Y); X(const X&); ~X(); }; > + > +struct A { int a : 13; bool b; }; > + > +struct B {}; > +template<> struct std::tuple_size<B> { enum { value = 2 }; }; > +template<> struct std::tuple_element<0,B> { using type = X; }; > +template<> struct std::tuple_element<1,B> { using type = const int&; }; > +template<int N> auto get(B) { > + if constexpr (N == 0) > + return Y(); > + else > + return 0.0; > +} > + > +using C = int[2]; > + > +typedef int D __attribute__((ext_vector_type(2))); > + > +using E = _Complex int; > + > +template<typename T> T &make(); > + > +// CHECK: @_ZDC2a12a2E = global {{.*}} zeroinitializer, align 4 > +auto [a1, a2] = make<A>(); > +// CHECK: @_ZDC2b12b2E = global {{.*}} zeroinitializer, align 1 > +// CHECK: @b1 = global {{.*}}* null, align 8 > +// CHECK: @_ZGR2b1_ = internal global {{.*}} zeroinitializer, align 1 > +// CHECK: @b2 = global i32* null, align 8 > +// CHECK: @_ZGR2b2_ = internal global i32 0, align 4 > +auto [b1, b2] = make<B>(); > +// CHECK: @_ZDC2c12c2E = global [2 x i32]* null, align 8 > +auto &[c1, c2] = make<C>(); > +// CHECK: @_ZDC2d12d2E = global <2 x i32> zeroinitializer, align 8 > +auto [d1, d2] = make<D>(); > +// CHECK: @_ZDC2e12e2E = global { i32, i32 } zeroinitializer, align 4 > +auto [e1, e2] = make<E>(); > + > +// CHECK: call {{.*}}* @_Z4makeI1AERT_v() > +// CHECK: call {{.*}}memcpy{{.*}}@_ZDC2a12a2E > + > +// CHECK: @_Z4makeI1BERT_v() > +// CHECK: call i32 @_Z3getILi0EEDa1B() > +// CHECK: call void @_ZN1XC1E1Y({{.*}}* @_ZGR2b1_, i32 > +// CHECK: call i32 @__cxa_atexit({{.*}}@_ZN1XD1Ev{{.*}}@_ZGR2b1_ > +// CHECK: store {{.*}}* @_ZGR2b1_, > +// > +// CHECK: call double @_Z3getILi1EEDa1B() > +// CHECK: fptosi double %{{.*}} to i32 > +// CHECK: store i32 %{{.*}}, i32* @_ZGR2b2_ > +// CHECK: store i32* @_ZGR2b2_, i32** @b2 > + > +// CHECK: call {{.*}}* @_Z4makeIA2_iERT_v() > +// CHECK: store {{.*}}, [2 x i32]** @_ZDC2c12c2E > + > +// CHECK: call {{.*}}* @_Z4makeIDv2_iERT_v() > +// CHECK: store {{.*}}, <2 x i32>* @_ZDC2d12d2E, align 8 > + > +// CHECK: call {{.*}}* @_Z4makeICiERT_v() > +// CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({ i32, i32 }, { > i32, i32 }* @_ZDC2e12e2E, i32 0, i32 0) > +// CHECK: store i32 %{{.*}}, i32* getelementptr inbounds ({ i32, i32 }, { > i32, i32 }* @_ZDC2e12e2E, i32 0, i32 1) > + > +// CHECK: define i32 @_Z12test_globalsv() > +int test_globals() { > + return a2 + b2 + c2 + d2 + e2; > + // CHECK: load i8, i8* getelementptr inbounds (%struct.A, %struct.A* > @_ZDC2a12a2E, i32 0, i32 1) > + // > + // CHECK: %[[b2:.*]] = load i32*, i32** @b2 > + // CHECK: load i32, i32* %[[b2]] > + // > + // CHECK: %[[c1c2:.*]] = load [2 x i32]*, [2 x i32]** @_ZDC2c12c2E > + // CHECK: %[[c2:.*]] = getelementptr inbounds [2 x i32], [2 x i32]* > %[[c1c2]], i64 0, i64 1 > + // CHECK: load i32, i32* %[[c2]] > + // > + // CHECK: %[[d1d2:.*]] = load <2 x i32>, <2 x i32>* @_ZDC2d12d2E > + // CHECK: extractelement <2 x i32> %[[d1d2]], i32 1 > + // > + // CHECK: load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, > i32 }* @_ZDC2e12e2E, i32 0, i32 1) > +} > + > +// CHECK: define i32 @_Z11test_localsv() > +int test_locals() { > + auto [b1, b2] = make<B>(); > + > + // CHECK: @_Z4makeI1BERT_v() > + // CHECK: call i32 @_Z3getILi0EEDa1B() > + // CHECK: call void @_ZN1XC1E1Y({{.*}}* %[[b1:.*]], i32 > + // > + // CHECK: call double @_Z3getILi1EEDa1B() > + // CHECK: %[[cvt:.*]] = fptosi double %{{.*}} to i32 > + // CHECK: store i32 %[[cvt]], i32* %[[b2:.*]], > + // CHECK: store i32* %[[b2]], i32** %[[b2ref:.*]], > + > + return b2; > + // CHECK: %[[b2:.*]] = load i32*, i32** %[[b2ref]] > + // CHECK: load i32, i32* %[[b2]] > + > + // CHECK: call {{.*}}@_ZN1XD1Ev({{.*}}%[[b1]]) > +} > + > +// CHECK: define void @_Z13test_bitfieldR1A( > +void test_bitfield(A &a) { > + auto &[a1, a2] = a; > + a1 = 5; > + // CHECK: load i16, i16* %[[BITFIELD:.*]], > + // CHECK: and i16 %{{.*}}, -8192 > + // CHECK: or i16 %{{.*}}, 5 > + // CHECK: store i16 %{{.*}}, i16* %[[BITFIELD]], > +} > > Modified: cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp?rev=278642&r1=278641&r2=278642&view=diff > > ============================================================================== > --- cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp (original) > +++ cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp Sun Aug 14 20:33:41 2016 > @@ -38,4 +38,3 @@ constexpr bool g(S &&s) { > static_assert(g({1, 2})); > > // FIXME: by-value array copies > -// FIXME: code generation > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits