Author: Matheus Izvekov Date: 2021-07-07T02:54:55+02:00 New Revision: f2d5fce86e81a8b37fbc0829a1c68b6eb48f8365
URL: https://github.com/llvm/llvm-project/commit/f2d5fce86e81a8b37fbc0829a1c68b6eb48f8365 DIFF: https://github.com/llvm/llvm-project/commit/f2d5fce86e81a8b37fbc0829a1c68b6eb48f8365.diff LOG: [clang] fixes named return of variables with dependent alignment Named return of a variable with aligned attribute would trip an assert in case alignment was dependent. Signed-off-by: Matheus Izvekov <mizve...@gmail.com> Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D105380 Added: Modified: clang/include/clang/AST/Decl.h clang/lib/AST/Decl.cpp clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaStmt.cpp clang/test/CXX/class/class.init/class.copy.elision/p3.cpp clang/test/CodeGen/nrvo-tracking.cpp Removed: ################################################################################ diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 020df62755706..d22594ae8442a 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -1494,6 +1494,9 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { NonParmVarDeclBits.EscapingByref = true; } + /// Determines if this variable's alignment is dependent. + bool hasDependentAlignment() const; + /// Retrieve the variable declaration from which this variable could /// be instantiated, if it is an instantiation (rather than a non-template). VarDecl *getTemplateInstantiationPattern() const; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 5047dc19b0c6f..5dcfca45a54b6 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2534,6 +2534,14 @@ bool VarDecl::isNonEscapingByref() const { return hasAttr<BlocksAttr>() && !NonParmVarDeclBits.EscapingByref; } +bool VarDecl::hasDependentAlignment() const { + QualType T = getType(); + return T->isDependentType() || T->isUndeducedAutoType() || + llvm::any_of(specific_attrs<AlignedAttr>(), [](const AlignedAttr *AA) { + return AA->isAlignmentDependent(); + }); +} + VarDecl *VarDecl::getTemplateInstantiationPattern() const { const VarDecl *VD = this; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0075464552321..700a6db7fea89 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13310,16 +13310,6 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { CheckCompleteDecompositionDeclaration(DD); } -/// Determines if a variable's alignment is dependent. -static bool hasDependentAlignment(VarDecl *VD) { - if (VD->getType()->isDependentType()) - return true; - for (auto *I : VD->specific_attrs<AlignedAttr>()) - if (I->isAlignmentDependent()) - return true; - return false; -} - /// Check if VD needs to be dllexport/dllimport due to being in a /// dllexport/import function. void Sema::CheckStaticLocalForDllExport(VarDecl *VD) { @@ -13408,8 +13398,7 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { if (unsigned MaxAlign = Context.getTargetInfo().getMaxTLSAlign()) { // Protect the check so that it's not performed on dependent types and // dependent alignments (we can't determine the alignment in that case). - if (VD->getTLSKind() && !hasDependentAlignment(VD) && - !VD->isInvalidDecl()) { + if (VD->getTLSKind() && !VD->hasDependentAlignment()) { CharUnits MaxAlignChars = Context.toCharUnitsFromBits(MaxAlign); if (Context.getDeclAlign(VD) > MaxAlignChars) { Diag(VD->getLocation(), diag::err_tls_var_aligned_over_maximum) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 1e86f382f060b..506c06b412b6f 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3395,7 +3395,7 @@ Sema::NamedReturnInfo Sema::getNamedReturnInfo(const VarDecl *VD) { // Variables with higher required alignment than their type's ABI // alignment cannot use NRVO. - if (!VDType->isDependentType() && VD->hasAttr<AlignedAttr>() && + if (!VD->hasDependentAlignment() && Context.getDeclAlign(VD) > Context.getTypeAlignInChars(VDType)) Info.S = NamedReturnInfo::MoveEligible; diff --git a/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp b/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp index ed6bec97e0bf2..a85475ece7bf5 100644 --- a/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp +++ b/clang/test/CXX/class/class.init/class.copy.elision/p3.cpp @@ -487,3 +487,29 @@ void test5() try { } } // namespace test_simpler_implicit_move + +namespace test_auto_variables { + +struct S {}; + +template <class T> struct range { + S *begin() const; + S *end() const; +}; + +template <class T> S test_dependent_ranged_for() { + for (auto x : range<T>()) + return x; + return S(); +} +template S test_dependent_ranged_for<int>(); + +template <class T> struct X {}; + +template <class T> X<T> test_dependent_invalid_decl() { + auto x = X<T>().foo(); // expected-error {{no member named 'foo'}} + return x; +} +template X<int> test_dependent_invalid_decl<int>(); // expected-note {{requested here}} + +} // namespace test_auto_variables diff --git a/clang/test/CodeGen/nrvo-tracking.cpp b/clang/test/CodeGen/nrvo-tracking.cpp index 7893140e1010a..2d6eb9efeca20 100644 --- a/clang/test/CodeGen/nrvo-tracking.cpp +++ b/clang/test/CodeGen/nrvo-tracking.cpp @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -std=c++20 -fblocks -Wno-return-stack-address -triple x86_64-unknown-unknown-gnu -emit-llvm -O1 -fexperimental-new-pass-manager -o - %s | FileCheck %s -struct X { - X(); - X(const X&); - X(X&&); +struct alignas(4) X { + X(); + X(const X &); + X(X &&); }; #define L(A, B, C) void l##A() { \ @@ -210,3 +210,75 @@ void b_attr() { }; }()(); } + +namespace test_alignas { + +template <int A> X t1() { + X a [[gnu::aligned(A)]]; + return a; +} + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi1EEE1Xv +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: ret void +template X t1<1>(); + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi4EEE1Xv +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: ret void +template X t1<4>(); + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi8EEE1Xv +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_ +// CHECK-NEXT: call void @llvm.lifetime.end +template X t1<8>(); + +template <int A> X t2() { + X a [[gnu::aligned(1)]] [[gnu::aligned(A)]] [[gnu::aligned(2)]]; + return a; +} + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi1EEE1Xv +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: ret void +template X t2<1>(); + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi4EEE1Xv +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: ret void +template X t2<4>(); + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi8EEE1Xv +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_ +// CHECK-NEXT: call void @llvm.lifetime.end +template X t2<8>(); + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t3Ev +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: ret void +X t3() { + X a [[gnu::aligned(1)]]; + return a; +} + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t4Ev +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_ +// CHECK-NEXT: call void @llvm.lifetime.end +X t4() { + X a [[gnu::aligned(8)]]; + return a; +} + +// CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t5Ev +// CHECK: call {{.*}} @_ZN1XC1Ev +// CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_ +// CHECK-NEXT: call void @llvm.lifetime.end +X t5() { + X a [[gnu::aligned(1)]] [[gnu::aligned(8)]]; + return a; +} + +} // namespace test_alignas _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits