[clang] f2d5fce - [clang] fixes named return of variables with dependent alignment
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 6 17:55:04 PDT 2021
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 <mizvekov at 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
More information about the cfe-commits
mailing list