mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-14 14:56:47 +00:00
[OPENMP] Introduced type trait "__builtin_omp_required_simd_align" for default simd alignment.
Adds type trait "__builtin_omp_required_simd_align" after discussions here http://reviews.llvm.org/D9894 Differential Revision: http://reviews.llvm.org/D10597 llvm-svn: 241237
This commit is contained in:
parent
85225b0a36
commit
0039651304
@ -1664,6 +1664,9 @@ public:
|
||||
TypeInfo getTypeInfo(const Type *T) const;
|
||||
TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); }
|
||||
|
||||
/// \brief Get default simd alignment of the specified complete type in bits.
|
||||
unsigned getOpenMPDefaultSimdAlign(QualType T) const;
|
||||
|
||||
/// \brief Return the size of the specified (complete) type \p T, in bits.
|
||||
uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; }
|
||||
uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; }
|
||||
|
@ -4698,13 +4698,15 @@ def ext_sizeof_alignof_void_type : Extension<
|
||||
"invalid application of '%select{sizeof|alignof|vec_step}0' to a void "
|
||||
"type">, InGroup<PointerArith>;
|
||||
def err_opencl_sizeof_alignof_type : Error<
|
||||
"invalid application of '%select{sizeof|alignof|vec_step}0' to a void type">;
|
||||
"invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a void type">;
|
||||
def err_sizeof_alignof_incomplete_type : Error<
|
||||
"invalid application of '%select{sizeof|alignof|vec_step}0' to an "
|
||||
"invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to an "
|
||||
"incomplete type %1">;
|
||||
def err_sizeof_alignof_function_type : Error<
|
||||
"invalid application of '%select{sizeof|alignof|vec_step}0' to a "
|
||||
"invalid application of '%select{sizeof|alignof|vec_step|__builtin_omp_required_simd_align}0' to a "
|
||||
"function type">;
|
||||
def err_openmp_default_simd_align_expr : Error<
|
||||
"invalid application of '__builtin_omp_required_simd_align' to an expression, only type is allowed">;
|
||||
def err_sizeof_alignof_bitfield : Error<
|
||||
"invalid application of '%select{sizeof|alignof}0' to bit-field">;
|
||||
def err_alignof_member_of_incomplete_type : Error<
|
||||
|
@ -70,6 +70,7 @@ protected:
|
||||
unsigned char MinGlobalAlign;
|
||||
unsigned char MaxAtomicPromoteWidth, MaxAtomicInlineWidth;
|
||||
unsigned short MaxVectorAlign;
|
||||
unsigned short SimdDefaultAlign;
|
||||
const char *DescriptionString;
|
||||
const char *UserLabelPrefix;
|
||||
const char *MCountName;
|
||||
@ -393,6 +394,10 @@ public:
|
||||
|
||||
/// \brief Return the maximum vector alignment supported for the given target.
|
||||
unsigned getMaxVectorAlign() const { return MaxVectorAlign; }
|
||||
/// \brief Return default simd alignment for the given target. Generally, this
|
||||
/// value is type-specific, but this alignment can be used for most of the
|
||||
/// types for the given target.
|
||||
unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; }
|
||||
|
||||
/// \brief Return the size of intmax_t and uintmax_t for this target, in bits.
|
||||
unsigned getIntMaxTWidth() const {
|
||||
|
@ -503,6 +503,9 @@ ALIAS("read_write", __read_write , KEYOPENCL)
|
||||
KEYWORD(__builtin_astype , KEYOPENCL)
|
||||
KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC)
|
||||
|
||||
// OpenMP Type Traits
|
||||
KEYWORD(__builtin_omp_required_simd_align, KEYALL)
|
||||
|
||||
// Borland Extensions.
|
||||
KEYWORD(__pascal , KEYALL)
|
||||
|
||||
|
@ -92,7 +92,8 @@ namespace clang {
|
||||
enum UnaryExprOrTypeTrait {
|
||||
UETT_SizeOf,
|
||||
UETT_AlignOf,
|
||||
UETT_VecStep
|
||||
UETT_VecStep,
|
||||
UETT_OpenMPRequiredSimdAlign,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1786,6 +1786,17 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
|
||||
return TypeInfo(Width, Align, AlignIsRequired);
|
||||
}
|
||||
|
||||
unsigned ASTContext::getOpenMPDefaultSimdAlign(QualType T) const {
|
||||
unsigned SimdAlign = getTargetInfo().getSimdDefaultAlign();
|
||||
// Target ppc64 with QPX: simd default alignment for pointer to double is 32.
|
||||
if ((getTargetInfo().getTriple().getArch() == llvm::Triple::ppc64 ||
|
||||
getTargetInfo().getTriple().getArch() == llvm::Triple::ppc64le) &&
|
||||
getTargetInfo().getABI() == "elfv1-qpx" &&
|
||||
T->isSpecificBuiltinType(BuiltinType::Double))
|
||||
SimdAlign = 256;
|
||||
return SimdAlign;
|
||||
}
|
||||
|
||||
/// toCharUnitsFromBits - Convert a size in bits to a size in characters.
|
||||
CharUnits ASTContext::toCharUnitsFromBits(int64_t BitSize) const {
|
||||
return CharUnits::fromQuantity(BitSize / getCharWidth());
|
||||
|
@ -1829,6 +1829,9 @@ void ASTDumper::VisitUnaryExprOrTypeTraitExpr(
|
||||
case UETT_VecStep:
|
||||
OS << " vec_step";
|
||||
break;
|
||||
case UETT_OpenMPRequiredSimdAlign:
|
||||
OS << " __builtin_omp_required_simd_align";
|
||||
break;
|
||||
}
|
||||
if (Node->isArgumentType())
|
||||
dumpType(Node->getArgumentType());
|
||||
|
@ -7251,6 +7251,13 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
|
||||
return false;
|
||||
return Success(Sizeof, E);
|
||||
}
|
||||
case UETT_OpenMPRequiredSimdAlign:
|
||||
assert(E->isArgumentType());
|
||||
return Success(
|
||||
Info.Ctx.toCharUnitsFromBits(
|
||||
Info.Ctx.getOpenMPDefaultSimdAlign(E->getArgumentType()))
|
||||
.getQuantity(),
|
||||
E);
|
||||
}
|
||||
|
||||
llvm_unreachable("unknown expr/type trait");
|
||||
|
@ -3018,13 +3018,21 @@ recurse:
|
||||
case UETT_AlignOf:
|
||||
Out << 'a';
|
||||
break;
|
||||
case UETT_VecStep:
|
||||
case UETT_VecStep: {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
|
||||
"cannot yet mangle vec_step expression");
|
||||
Diags.Report(DiagID);
|
||||
return;
|
||||
}
|
||||
case UETT_OpenMPRequiredSimdAlign:
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(
|
||||
DiagnosticsEngine::Error,
|
||||
"cannot yet mangle __builtin_omp_required_simd_align expression");
|
||||
Diags.Report(DiagID);
|
||||
return;
|
||||
}
|
||||
if (SAE->isArgumentType()) {
|
||||
Out << 't';
|
||||
mangleType(SAE->getArgumentType());
|
||||
|
@ -1223,6 +1223,9 @@ void StmtPrinter::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node){
|
||||
case UETT_VecStep:
|
||||
OS << "vec_step";
|
||||
break;
|
||||
case UETT_OpenMPRequiredSimdAlign:
|
||||
OS << "__builtin_omp_required_simd_align";
|
||||
break;
|
||||
}
|
||||
if (Node->isArgumentType()) {
|
||||
OS << '(';
|
||||
|
@ -50,6 +50,7 @@ TargetInfo::TargetInfo(const llvm::Triple &T) : TargetOpts(), Triple(T) {
|
||||
LargeArrayAlign = 0;
|
||||
MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 0;
|
||||
MaxVectorAlign = 0;
|
||||
SimdDefaultAlign = 0;
|
||||
SizeType = UnsignedLong;
|
||||
PtrDiffType = SignedLong;
|
||||
IntMaxType = SignedLongLong;
|
||||
|
@ -759,6 +759,7 @@ public:
|
||||
HasP8Crypto(false), HasDirectMove(false), HasQPX(false), HasHTM(false),
|
||||
HasBPERMD(false), HasExtDiv(false) {
|
||||
BigEndian = (Triple.getArch() != llvm::Triple::ppc64le);
|
||||
SimdDefaultAlign = 128;
|
||||
LongDoubleWidth = LongDoubleAlign = 128;
|
||||
LongDoubleFormat = &llvm::APFloat::PPCDoubleDouble;
|
||||
}
|
||||
@ -2988,6 +2989,9 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
||||
Features.erase(it);
|
||||
else if (SSELevel > NoSSE)
|
||||
MMX3DNowLevel = std::max(MMX3DNowLevel, MMX);
|
||||
|
||||
SimdDefaultAlign =
|
||||
(getABI() == "avx512") ? 512 : (getABI() == "avx") ? 256 : 128;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "CGDebugInfo.h"
|
||||
#include "CGObjCRuntime.h"
|
||||
#include "CodeGenModule.h"
|
||||
#include "TargetInfo.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/RecordLayout.h"
|
||||
@ -2037,6 +2038,13 @@ ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
|
||||
|
||||
return size;
|
||||
}
|
||||
} else if (E->getKind() == UETT_OpenMPRequiredSimdAlign) {
|
||||
auto Alignment =
|
||||
CGF.getContext()
|
||||
.toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign(
|
||||
E->getTypeOfArgument()->getPointeeType()))
|
||||
.getQuantity();
|
||||
return llvm::ConstantInt::get(CGF.SizeTy, Alignment);
|
||||
}
|
||||
|
||||
// If this isn't sizeof(vla), the result must be constant; use the constant
|
||||
|
@ -649,8 +649,10 @@ static void emitAlignedClause(CodeGenFunction &CGF,
|
||||
// If no optional parameter is specified, implementation-defined default
|
||||
// alignments for SIMD instructions on the target platforms are assumed.
|
||||
Alignment =
|
||||
CGF.CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
|
||||
E->getType());
|
||||
CGF.getContext()
|
||||
.toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign(
|
||||
E->getType()->getPointeeType()))
|
||||
.getQuantity();
|
||||
}
|
||||
assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
|
||||
"alignment is not power of 2");
|
||||
|
@ -1577,11 +1577,9 @@ public:
|
||||
};
|
||||
|
||||
class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
|
||||
X86AVXABILevel AVXLevel;
|
||||
public:
|
||||
X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, X86AVXABILevel AVXLevel)
|
||||
: TargetCodeGenInfo(new X86_64ABIInfo(CGT, AVXLevel)),
|
||||
AVXLevel(AVXLevel) {}
|
||||
: TargetCodeGenInfo(new X86_64ABIInfo(CGT, AVXLevel)) {}
|
||||
|
||||
const X86_64ABIInfo &getABIInfo() const {
|
||||
return static_cast<const X86_64ABIInfo&>(TargetCodeGenInfo::getABIInfo());
|
||||
@ -1647,10 +1645,6 @@ public:
|
||||
('T' << 24);
|
||||
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
|
||||
}
|
||||
|
||||
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
|
||||
return getNativeVectorSizeForAVXABI(AVXLevel) / 8;
|
||||
}
|
||||
};
|
||||
|
||||
class PS4TargetCodeGenInfo : public X86_64TargetCodeGenInfo {
|
||||
@ -1722,11 +1716,10 @@ void WinX86_32TargetCodeGenInfo::setTargetAttributes(const Decl *D,
|
||||
}
|
||||
|
||||
class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
|
||||
X86AVXABILevel AVXLevel;
|
||||
public:
|
||||
WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT,
|
||||
X86AVXABILevel AVXLevel)
|
||||
: TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)), AVXLevel(AVXLevel) {}
|
||||
: TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {}
|
||||
|
||||
void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV,
|
||||
CodeGen::CodeGenModule &CGM) const override;
|
||||
@ -1756,10 +1749,6 @@ public:
|
||||
llvm::SmallString<32> &Opt) const override {
|
||||
Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
|
||||
}
|
||||
|
||||
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
|
||||
return getNativeVectorSizeForAVXABI(AVXLevel) / 8;
|
||||
}
|
||||
};
|
||||
|
||||
void WinX86_64TargetCodeGenInfo::setTargetAttributes(const Decl *D,
|
||||
@ -3171,10 +3160,6 @@ public:
|
||||
|
||||
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
||||
llvm::Value *Address) const override;
|
||||
|
||||
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
|
||||
return 16; // Natural alignment for Altivec vectors.
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@ -3414,13 +3399,11 @@ public:
|
||||
};
|
||||
|
||||
class PPC64_SVR4_TargetCodeGenInfo : public TargetCodeGenInfo {
|
||||
bool HasQPX;
|
||||
|
||||
public:
|
||||
PPC64_SVR4_TargetCodeGenInfo(CodeGenTypes &CGT,
|
||||
PPC64_SVR4_ABIInfo::ABIKind Kind, bool HasQPX)
|
||||
: TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX)),
|
||||
HasQPX(HasQPX) {}
|
||||
: TargetCodeGenInfo(new PPC64_SVR4_ABIInfo(CGT, Kind, HasQPX)) {}
|
||||
|
||||
int getDwarfEHStackPointer(CodeGen::CodeGenModule &M) const override {
|
||||
// This is recovered from gcc output.
|
||||
@ -3429,15 +3412,6 @@ public:
|
||||
|
||||
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
||||
llvm::Value *Address) const override;
|
||||
|
||||
unsigned getOpenMPSimdDefaultAlignment(QualType QT) const override {
|
||||
if (HasQPX)
|
||||
if (const PointerType *PT = QT->getAs<PointerType>())
|
||||
if (PT->getPointeeType()->isSpecificBuiltinType(BuiltinType::Double))
|
||||
return 32; // Natural alignment for QPX doubles.
|
||||
|
||||
return 16; // Natural alignment for Altivec and VSX vectors.
|
||||
}
|
||||
};
|
||||
|
||||
class PPC64TargetCodeGenInfo : public DefaultTargetCodeGenInfo {
|
||||
@ -3451,10 +3425,6 @@ public:
|
||||
|
||||
bool initDwarfEHRegSizeTable(CodeGen::CodeGenFunction &CGF,
|
||||
llvm::Value *Address) const override;
|
||||
|
||||
unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
|
||||
return 16; // Natural alignment for Altivec vectors.
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -218,13 +218,6 @@ public:
|
||||
virtual void getDetectMismatchOption(llvm::StringRef Name,
|
||||
llvm::StringRef Value,
|
||||
llvm::SmallString<32> &Opt) const {}
|
||||
|
||||
/// Gets the target-specific default alignment used when an 'aligned' clause
|
||||
/// is used with a 'simd' OpenMP directive without specifying a specific
|
||||
/// alignment.
|
||||
virtual unsigned getOpenMPSimdDefaultAlignment(QualType Type) const {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1060,6 +1060,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
||||
case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
|
||||
// unary-expression: 'sizeof' '(' type-name ')'
|
||||
case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression
|
||||
// unary-expression: '__builtin_omp_required_simd_align' '(' type-name ')'
|
||||
case tok::kw___builtin_omp_required_simd_align:
|
||||
return ParseUnaryExprOrTypeTraitExpression();
|
||||
case tok::ampamp: { // unary-expression: '&&' identifier
|
||||
SourceLocation AmpAmpLoc = ConsumeToken();
|
||||
@ -1654,8 +1656,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
|
||||
ParsedType &CastTy,
|
||||
SourceRange &CastRange) {
|
||||
|
||||
assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof,
|
||||
tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step) &&
|
||||
assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof,
|
||||
tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step,
|
||||
tok::kw___builtin_omp_required_simd_align) &&
|
||||
"Not a typeof/sizeof/alignof/vec_step expression!");
|
||||
|
||||
ExprResult Operand;
|
||||
@ -1740,7 +1743,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok,
|
||||
/// \endverbatim
|
||||
ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
|
||||
assert(Tok.isOneOf(tok::kw_sizeof, tok::kw___alignof, tok::kw_alignof,
|
||||
tok::kw__Alignof, tok::kw_vec_step) &&
|
||||
tok::kw__Alignof, tok::kw_vec_step,
|
||||
tok::kw___builtin_omp_required_simd_align) &&
|
||||
"Not a sizeof/alignof/vec_step expression!");
|
||||
Token OpTok = Tok;
|
||||
ConsumeToken();
|
||||
@ -1810,6 +1814,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
|
||||
ExprKind = UETT_AlignOf;
|
||||
else if (OpTok.is(tok::kw_vec_step))
|
||||
ExprKind = UETT_VecStep;
|
||||
else if (OpTok.is(tok::kw___builtin_omp_required_simd_align))
|
||||
ExprKind = UETT_OpenMPRequiredSimdAlign;
|
||||
|
||||
if (isCastExpr)
|
||||
return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(),
|
||||
|
@ -3689,7 +3689,7 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
|
||||
// C11 6.5.3.4/3, C++11 [expr.alignof]p3:
|
||||
// When alignof or _Alignof is applied to an array type, the result
|
||||
// is the alignment of the element type.
|
||||
if (ExprKind == UETT_AlignOf)
|
||||
if (ExprKind == UETT_AlignOf || ExprKind == UETT_OpenMPRequiredSimdAlign)
|
||||
ExprType = Context.getBaseElementType(ExprType);
|
||||
|
||||
if (ExprKind == UETT_VecStep)
|
||||
@ -3824,6 +3824,9 @@ Sema::CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc,
|
||||
isInvalid = CheckAlignOfExpr(*this, E);
|
||||
} else if (ExprKind == UETT_VecStep) {
|
||||
isInvalid = CheckVecStepExpr(E);
|
||||
} else if (ExprKind == UETT_OpenMPRequiredSimdAlign) {
|
||||
Diag(E->getExprLoc(), diag::err_openmp_default_simd_align_expr);
|
||||
isInvalid = true;
|
||||
} else if (E->refersToBitField()) { // C99 6.5.3.4p1.
|
||||
Diag(E->getExprLoc(), diag::err_sizeof_alignof_bitfield) << 0;
|
||||
isInvalid = true;
|
||||
|
11
clang/test/CodeGen/openmp_default_simd_align.c
Normal file
11
clang/test/CodeGen/openmp_default_simd_align.c
Normal file
@ -0,0 +1,11 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -O1 -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
enum e0 { E0 };
|
||||
struct s0 {
|
||||
enum e0 a:31;
|
||||
};
|
||||
|
||||
int f0() {
|
||||
return __builtin_omp_required_simd_align(struct s0);
|
||||
// CHECK: ret i32 16
|
||||
}
|
83
clang/test/SemaCXX/openmp_default_simd_align.cpp
Normal file
83
clang/test/SemaCXX/openmp_default_simd_align.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -triple x86_64-unknown-unknown -verify %s
|
||||
|
||||
struct S0 {
|
||||
int x;
|
||||
static const int test0 = __builtin_omp_required_simd_align(x); // expected-error {{invalid application of '__builtin_omp_required_simd_align' to an expression, only type is allowed}}
|
||||
static const int test1 = __builtin_omp_required_simd_align(decltype(S0::x));
|
||||
auto test2() -> char(&)[__builtin_omp_required_simd_align(decltype(x))];
|
||||
};
|
||||
|
||||
struct S1; // expected-note 6 {{forward declaration}}
|
||||
extern S1 s1;
|
||||
const int test3 = __builtin_omp_required_simd_align(decltype(s1)); // expected-error {{invalid application of '__builtin_omp_required_simd_align' to an incomplete type 'decltype(s1)' (aka 'S1')}}
|
||||
|
||||
struct S2 {
|
||||
S2();
|
||||
S1 &s;
|
||||
int x;
|
||||
|
||||
int test4 = __builtin_omp_required_simd_align(decltype(x)); // ok
|
||||
int test5 = __builtin_omp_required_simd_align(decltype(s)); // expected-error {{invalid application of '__builtin_omp_required_simd_align' to an incomplete type 'S1'}}
|
||||
};
|
||||
|
||||
const int test6 = __builtin_omp_required_simd_align(decltype(S2::x));
|
||||
const int test7 = __builtin_omp_required_simd_align(decltype(S2::s)); // expected-error {{invalid application of '__builtin_omp_required_simd_align' to an incomplete type 'S1'}}
|
||||
|
||||
// Arguably, these should fail like the S1 cases do: the alignment of
|
||||
// 's2.x' should depend on the alignment of both x-within-S2 and
|
||||
// s2-within-S3 and thus require 'S3' to be complete. If we start
|
||||
// doing the appropriate recursive walk to do that, we should make
|
||||
// sure that these cases don't explode.
|
||||
struct S3 {
|
||||
S2 s2;
|
||||
|
||||
static const int test8 = __builtin_omp_required_simd_align(decltype(s2.x));
|
||||
static const int test9 = __builtin_omp_required_simd_align(decltype(s2.s)); // expected-error {{invalid application of '__builtin_omp_required_simd_align' to an incomplete type 'S1'}}
|
||||
auto test10() -> char(&)[__builtin_omp_required_simd_align(decltype(s2.x))];
|
||||
static const int test11 = __builtin_omp_required_simd_align(decltype(S3::s2.x));
|
||||
static const int test12 = __builtin_omp_required_simd_align(decltype(S3::s2.s)); // expected-error {{invalid application of '__builtin_omp_required_simd_align' to an incomplete type 'S1'}}
|
||||
auto test13() -> char(&)[__builtin_omp_required_simd_align(decltype(s2.x))];
|
||||
};
|
||||
|
||||
// Same reasoning as S3.
|
||||
struct S4 {
|
||||
union {
|
||||
int x;
|
||||
};
|
||||
static const int test0 = __builtin_omp_required_simd_align(decltype(x));
|
||||
static const int test1 = __builtin_omp_required_simd_align(decltype(S0::x));
|
||||
auto test2() -> char(&)[__builtin_omp_required_simd_align(decltype(x))];
|
||||
};
|
||||
|
||||
// Regression test for asking for the alignment of a field within an invalid
|
||||
// record.
|
||||
struct S5 {
|
||||
S1 s; // expected-error {{incomplete type}}
|
||||
int x;
|
||||
};
|
||||
const int test8 = __builtin_omp_required_simd_align(decltype(S5::x));
|
||||
|
||||
long long int test14[2];
|
||||
|
||||
static_assert(__builtin_omp_required_simd_align(decltype(test14)) == 16, "foo");
|
||||
|
||||
static_assert(__builtin_omp_required_simd_align(int[2]) == __builtin_omp_required_simd_align(int), ""); // ok
|
||||
|
||||
namespace __builtin_omp_required_simd_align_array_expr {
|
||||
alignas(32) extern int n[2];
|
||||
static_assert(__builtin_omp_required_simd_align(decltype(n)) == 16, "");
|
||||
|
||||
template<int> struct S {
|
||||
static int a[];
|
||||
};
|
||||
template<int N> int S<N>::a[N];
|
||||
static_assert(__builtin_omp_required_simd_align(decltype(S<1>::a)) == __builtin_omp_required_simd_align(int), "");
|
||||
static_assert(__builtin_omp_required_simd_align(decltype(S<1128>::a)) == __builtin_omp_required_simd_align(int), "");
|
||||
}
|
||||
|
||||
template <typename T> void n(T) {
|
||||
alignas(T) int T1;
|
||||
char k[__builtin_omp_required_simd_align(decltype(T1))];
|
||||
static_assert(sizeof(k) == __builtin_omp_required_simd_align(long long), "");
|
||||
}
|
||||
template void n(long long);
|
Loading…
x
Reference in New Issue
Block a user