65 changes: 46 additions & 19 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,39 +333,48 @@ static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,
}

static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, const Function *F) {
const InterpFrame *Frame, const Function *F,
bool IsNumBuiltin) {
const Floating &LHS = getParam<Floating>(Frame, 0);
const Floating &RHS = getParam<Floating>(Frame, 1);

Floating Result;

// When comparing zeroes, return -0.0 if one of the zeroes is negative.
if (LHS.isZero() && RHS.isZero() && RHS.isNegative())
Result = RHS;
else if (LHS.isNan() || RHS < LHS)
Result = RHS;
else
Result = LHS;
if (IsNumBuiltin) {
Result = llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat());
} else {
// When comparing zeroes, return -0.0 if one of the zeroes is negative.
if (LHS.isZero() && RHS.isZero() && RHS.isNegative())
Result = RHS;
else if (LHS.isNan() || RHS < LHS)
Result = RHS;
else
Result = LHS;
}

S.Stk.push<Floating>(Result);
return true;
}

static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func) {
const InterpFrame *Frame, const Function *Func,
bool IsNumBuiltin) {
const Floating &LHS = getParam<Floating>(Frame, 0);
const Floating &RHS = getParam<Floating>(Frame, 1);

Floating Result;

// When comparing zeroes, return +0.0 if one of the zeroes is positive.
if (LHS.isZero() && RHS.isZero() && LHS.isNegative())
Result = RHS;
else if (LHS.isNan() || RHS > LHS)
Result = RHS;
else
Result = LHS;
if (IsNumBuiltin) {
Result = llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat());
} else {
// When comparing zeroes, return +0.0 if one of the zeroes is positive.
if (LHS.isZero() && RHS.isZero() && LHS.isNegative())
Result = RHS;
else if (LHS.isNan() || RHS > LHS)
Result = RHS;
else
Result = LHS;
}

S.Stk.push<Floating>(Result);
return true;
Expand Down Expand Up @@ -1701,7 +1710,16 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
case Builtin::BI__builtin_fminl:
case Builtin::BI__builtin_fminf16:
case Builtin::BI__builtin_fminf128:
if (!interp__builtin_fmin(S, OpPC, Frame, F))
if (!interp__builtin_fmin(S, OpPC, Frame, F, /*IsNumBuiltin=*/false))
return false;
break;

case Builtin::BI__builtin_fminimum_num:
case Builtin::BI__builtin_fminimum_numf:
case Builtin::BI__builtin_fminimum_numl:
case Builtin::BI__builtin_fminimum_numf16:
case Builtin::BI__builtin_fminimum_numf128:
if (!interp__builtin_fmin(S, OpPC, Frame, F, /*IsNumBuiltin=*/true))
return false;
break;

Expand All @@ -1710,7 +1728,16 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
case Builtin::BI__builtin_fmaxl:
case Builtin::BI__builtin_fmaxf16:
case Builtin::BI__builtin_fmaxf128:
if (!interp__builtin_fmax(S, OpPC, Frame, F))
if (!interp__builtin_fmax(S, OpPC, Frame, F, /*IsNumBuiltin=*/false))
return false;
break;

case Builtin::BI__builtin_fmaximum_num:
case Builtin::BI__builtin_fmaximum_numf:
case Builtin::BI__builtin_fmaximum_numl:
case Builtin::BI__builtin_fmaximum_numf16:
case Builtin::BI__builtin_fmaximum_numf128:
if (!interp__builtin_fmax(S, OpPC, Frame, F, /*IsNumBuiltin=*/true))
return false;
break;

Expand Down
31 changes: 27 additions & 4 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ bool OpenACCClauseWithCondition::classof(const OpenACCClause *C) {
bool OpenACCClauseWithSingleIntExpr::classof(const OpenACCClause *C) {
return OpenACCNumWorkersClause::classof(C) ||
OpenACCVectorLengthClause::classof(C) ||
OpenACCWorkerClause::classof(C) || OpenACCCollapseClause::classof(C) ||
OpenACCAsyncClause::classof(C);
OpenACCVectorClause::classof(C) || OpenACCWorkerClause::classof(C) ||
OpenACCCollapseClause::classof(C) || OpenACCAsyncClause::classof(C);
}
OpenACCDefaultClause *OpenACCDefaultClause::Create(const ASTContext &C,
OpenACCDefaultClauseKind K,
Expand Down Expand Up @@ -424,11 +424,24 @@ OpenACCWorkerClause *OpenACCWorkerClause::Create(const ASTContext &C,
return new (Mem) OpenACCWorkerClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
}

OpenACCVectorClause::OpenACCVectorClause(SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expr *IntExpr, SourceLocation EndLoc)
: OpenACCClauseWithSingleIntExpr(OpenACCClauseKind::Vector, BeginLoc,
LParenLoc, IntExpr, EndLoc) {
assert((!IntExpr || IntExpr->isInstantiationDependent() ||
IntExpr->getType()->isIntegerType()) &&
"Int expression type not scalar/dependent");
}

OpenACCVectorClause *OpenACCVectorClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expr *IntExpr,
SourceLocation EndLoc) {
void *Mem = C.Allocate(sizeof(OpenACCVectorClause));
return new (Mem) OpenACCVectorClause(BeginLoc, EndLoc);
void *Mem =
C.Allocate(sizeof(OpenACCVectorClause), alignof(OpenACCVectorClause));
return new (Mem) OpenACCVectorClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -662,3 +675,13 @@ void OpenACCClausePrinter::VisitWorkerClause(const OpenACCWorkerClause &C) {
OS << ")";
}
}

void OpenACCClausePrinter::VisitVectorClause(const OpenACCVectorClause &C) {
OS << "vector";

if (C.hasIntExpr()) {
OS << "(length: ";
printExpr(C.getIntExpr());
OS << ")";
}
}
6 changes: 6 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2635,6 +2635,12 @@ void OpenACCClauseProfiler::VisitWorkerClause(
Profiler.VisitStmt(Clause.getIntExpr());
}

void OpenACCClauseProfiler::VisitVectorClause(
const OpenACCVectorClause &Clause) {
if (Clause.hasIntExpr())
Profiler.VisitStmt(Clause.getIntExpr());
}

void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) {
if (Clause.hasDevNumExpr())
Profiler.VisitStmt(Clause.getDevNumExpr());
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::Seq:
case OpenACCClauseKind::Tile:
case OpenACCClauseKind::Worker:
case OpenACCClauseKind::Vector:
case OpenACCClauseKind::VectorLength:
// The condition expression will be printed as a part of the 'children',
// but print 'clause' here so it is clear what is happening from the dump.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1945,7 +1945,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
replaceUndef(CGM, isPattern, constant));
}

if (D.getType()->isBitIntType() &&
if (constant && D.getType()->isBitIntType() &&
CGM.getTypes().typeRequiresSplitIntoByteArray(D.getType())) {
// Constants for long _BitInt types are split into individual bytes.
// Try to fold these back into an integer constant so it can be stored
Expand Down
73 changes: 71 additions & 2 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
Expand Down Expand Up @@ -64,6 +65,9 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
void withReturnValueSlot(const Expr *E,
llvm::function_ref<RValue(ReturnValueSlot)> Fn);

void DoZeroInitPadding(uint64_t &PaddingStart, uint64_t PaddingEnd,
const FieldDecl *NextField);

public:
AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, bool IsResultUnused)
: CGF(cgf), Builder(CGF.Builder), Dest(Dest),
Expand Down Expand Up @@ -1698,6 +1702,9 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
// Prepare a 'this' for CXXDefaultInitExprs.
CodeGenFunction::FieldConstructionScope FCS(CGF, Dest.getAddress());

const bool ZeroInitPadding =
CGF.CGM.shouldZeroInitPadding() && !Dest.isZeroed();

if (record->isUnion()) {
// Only initialize one field of a union. The field itself is
// specified by the initializer list.
Expand All @@ -1722,16 +1729,27 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
if (NumInitElements) {
// Store the initializer into the field
EmitInitializationToLValue(InitExprs[0], FieldLoc);
if (ZeroInitPadding) {
uint64_t TotalSize = CGF.getContext().toBits(
Dest.getPreferredSize(CGF.getContext(), DestLV.getType()));
uint64_t FieldSize = CGF.getContext().getTypeSize(FieldLoc.getType());
DoZeroInitPadding(FieldSize, TotalSize, nullptr);
}
} else {
// Default-initialize to null.
EmitNullInitializationToLValue(FieldLoc);
if (ZeroInitPadding)
EmitNullInitializationToLValue(DestLV);
else
EmitNullInitializationToLValue(FieldLoc);
}

return;
}

// Here we iterate over the fields; this makes it simpler to both
// default-initialize fields and skip over unnamed fields.
const ASTRecordLayout &Layout = CGF.getContext().getASTRecordLayout(record);
uint64_t PaddingStart = 0;

for (const auto *field : record->fields()) {
// We're done once we hit the flexible array member.
if (field->getType()->isIncompleteArrayType())
Expand All @@ -1748,6 +1766,9 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
CGF.getTypes().isZeroInitializable(ExprToVisit->getType()))
break;

if (ZeroInitPadding)
DoZeroInitPadding(PaddingStart,
Layout.getFieldOffset(field->getFieldIndex()), field);

LValue LV = CGF.EmitLValueForFieldInitialization(DestLV, field);
// We never generate write-barries for initialized fields.
Expand All @@ -1774,6 +1795,54 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
}
}
}
if (ZeroInitPadding) {
uint64_t TotalSize = CGF.getContext().toBits(
Dest.getPreferredSize(CGF.getContext(), DestLV.getType()));
DoZeroInitPadding(PaddingStart, TotalSize, nullptr);
}
}

void AggExprEmitter::DoZeroInitPadding(uint64_t &PaddingStart,
uint64_t PaddingEnd,
const FieldDecl *NextField) {

auto InitBytes = [&](uint64_t StartBit, uint64_t EndBit) {
CharUnits Start = CGF.getContext().toCharUnitsFromBits(StartBit);
CharUnits End = CGF.getContext().toCharUnitsFromBits(EndBit);
Address Addr = Dest.getAddress().withElementType(CGF.CharTy);
if (!Start.isZero())
Addr = Builder.CreateConstGEP(Addr, Start.getQuantity());
llvm::Constant *SizeVal = Builder.getInt64((End - Start).getQuantity());
CGF.Builder.CreateMemSet(Addr, Builder.getInt8(0), SizeVal, false);
};

if (NextField != nullptr && NextField->isBitField()) {
// For bitfield, zero init StorageSize before storing the bits. So we don't
// need to handle big/little endian.
const CGRecordLayout &RL =
CGF.getTypes().getCGRecordLayout(NextField->getParent());
const CGBitFieldInfo &Info = RL.getBitFieldInfo(NextField);
uint64_t StorageStart = CGF.getContext().toBits(Info.StorageOffset);
if (StorageStart + Info.StorageSize > PaddingStart) {
if (StorageStart > PaddingStart)
InitBytes(PaddingStart, StorageStart);
Address Addr = Dest.getAddress();
if (!Info.StorageOffset.isZero())
Addr = Builder.CreateConstGEP(Addr.withElementType(CGF.CharTy),
Info.StorageOffset.getQuantity());
Addr = Addr.withElementType(
llvm::Type::getIntNTy(CGF.getLLVMContext(), Info.StorageSize));
Builder.CreateStore(Builder.getIntN(Info.StorageSize, 0), Addr);
PaddingStart = StorageStart + Info.StorageSize;
}
return;
}

if (PaddingStart < PaddingEnd)
InitBytes(PaddingStart, PaddingEnd);
if (NextField != nullptr)
PaddingStart =
PaddingEnd + CGF.getContext().getTypeSize(NextField->getType());
}

void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E,
Expand Down
107 changes: 96 additions & 11 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ using namespace CodeGen;
namespace {
class ConstExprEmitter;

llvm::Constant *getPadding(const CodeGenModule &CGM, CharUnits PadSize) {
llvm::Type *Ty = CGM.CharTy;
if (PadSize > CharUnits::One())
Ty = llvm::ArrayType::get(Ty, PadSize.getQuantity());
if (CGM.shouldZeroInitPadding()) {
return llvm::Constant::getNullValue(Ty);
}
return llvm::UndefValue::get(Ty);
}

struct ConstantAggregateBuilderUtils {
CodeGenModule &CGM;

Expand All @@ -61,10 +71,7 @@ struct ConstantAggregateBuilderUtils {
}

llvm::Constant *getPadding(CharUnits PadSize) const {
llvm::Type *Ty = CGM.CharTy;
if (PadSize > CharUnits::One())
Ty = llvm::ArrayType::get(Ty, PadSize.getQuantity());
return llvm::UndefValue::get(Ty);
return ::getPadding(CGM, PadSize);
}

llvm::Constant *getZeroes(CharUnits ZeroSize) const {
Expand Down Expand Up @@ -591,6 +598,11 @@ class ConstStructBuilder {
bool Build(const InitListExpr *ILE, bool AllowOverwrite);
bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
bool DoZeroInitPadding(const ASTRecordLayout &Layout, unsigned FieldNo,
const FieldDecl &Field, bool AllowOverwrite,
CharUnits &SizeSoFar, bool &ZeroFieldSize);
bool DoZeroInitPadding(const ASTRecordLayout &Layout, bool AllowOverwrite,
CharUnits SizeSoFar);
llvm::Constant *Finalize(QualType Ty);
};

Expand Down Expand Up @@ -715,6 +727,10 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
if (CXXRD->getNumBases())
return false;

const bool ZeroInitPadding = CGM.shouldZeroInitPadding();
bool ZeroFieldSize = false;
CharUnits SizeSoFar = CharUnits::Zero();

for (FieldDecl *Field : RD->fields()) {
++FieldNo;

Expand All @@ -732,8 +748,13 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
const Expr *Init = nullptr;
if (ElementNo < ILE->getNumInits())
Init = ILE->getInit(ElementNo++);
if (isa_and_nonnull<NoInitExpr>(Init))
if (isa_and_nonnull<NoInitExpr>(Init)) {
if (ZeroInitPadding &&
!DoZeroInitPadding(Layout, FieldNo, *Field, AllowOverwrite, SizeSoFar,
ZeroFieldSize))
return false;
continue;
}

// Zero-sized fields are not emitted, but their initializers may still
// prevent emission of this struct as a constant.
Expand All @@ -743,6 +764,11 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
continue;
}

if (ZeroInitPadding &&
!DoZeroInitPadding(Layout, FieldNo, *Field, AllowOverwrite, SizeSoFar,
ZeroFieldSize))
return false;

// When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
// represents additional overwriting of our current constant value, and not
// a new constant to emit independently.
Expand All @@ -768,6 +794,10 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
if (!EltInit)
return false;

if (ZeroInitPadding && ZeroFieldSize)
SizeSoFar += CharUnits::fromQuantity(
CGM.getDataLayout().getTypeAllocSize(EltInit->getType()));

if (!Field->isBitField()) {
// Handle non-bitfield members.
if (!AppendField(Field, Layout.getFieldOffset(FieldNo), EltInit,
Expand All @@ -785,6 +815,9 @@ bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
}
}

if (ZeroInitPadding && !DoZeroInitPadding(Layout, AllowOverwrite, SizeSoFar))
return false;

return true;
}

Expand Down Expand Up @@ -849,6 +882,9 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,

unsigned FieldNo = 0;
uint64_t OffsetBits = CGM.getContext().toBits(Offset);
const bool ZeroInitPadding = CGM.shouldZeroInitPadding();
bool ZeroFieldSize = false;
CharUnits SizeSoFar = CharUnits::Zero();

bool AllowOverwrite = false;
for (RecordDecl::field_iterator Field = RD->field_begin(),
Expand All @@ -870,6 +906,15 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
if (!EltInit)
return false;

if (ZeroInitPadding) {
if (!DoZeroInitPadding(Layout, FieldNo, **Field, AllowOverwrite,
SizeSoFar, ZeroFieldSize))
return false;
if (ZeroFieldSize)
SizeSoFar += CharUnits::fromQuantity(
CGM.getDataLayout().getTypeAllocSize(EltInit->getType()));
}

if (!Field->isBitField()) {
// Handle non-bitfield members.
if (!AppendField(*Field, Layout.getFieldOffset(FieldNo) + OffsetBits,
Expand All @@ -886,7 +931,49 @@ bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
return false;
}
}
if (ZeroInitPadding && !DoZeroInitPadding(Layout, AllowOverwrite, SizeSoFar))
return false;

return true;
}

bool ConstStructBuilder::DoZeroInitPadding(
const ASTRecordLayout &Layout, unsigned FieldNo, const FieldDecl &Field,
bool AllowOverwrite, CharUnits &SizeSoFar, bool &ZeroFieldSize) {
uint64_t StartBitOffset = Layout.getFieldOffset(FieldNo);
CharUnits StartOffset = CGM.getContext().toCharUnitsFromBits(StartBitOffset);
if (SizeSoFar < StartOffset)
if (!AppendBytes(SizeSoFar, getPadding(CGM, StartOffset - SizeSoFar),
AllowOverwrite))
return false;

if (!Field.isBitField()) {
CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field.getType());
SizeSoFar = StartOffset + FieldSize;
ZeroFieldSize = FieldSize.isZero();
} else {
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(Field.getParent());
const CGBitFieldInfo &Info = RL.getBitFieldInfo(&Field);
uint64_t EndBitOffset = StartBitOffset + Info.Size;
SizeSoFar = CGM.getContext().toCharUnitsFromBits(EndBitOffset);
if (EndBitOffset % CGM.getContext().getCharWidth() != 0) {
SizeSoFar++;
}
ZeroFieldSize = Info.Size == 0;
}
return true;
}

bool ConstStructBuilder::DoZeroInitPadding(const ASTRecordLayout &Layout,
bool AllowOverwrite,
CharUnits SizeSoFar) {
CharUnits TotalSize = Layout.getSize();
if (SizeSoFar < TotalSize)
if (!AppendBytes(SizeSoFar, getPadding(CGM, TotalSize - SizeSoFar),
AllowOverwrite))
return false;
SizeSoFar = TotalSize;
return true;
}

Expand Down Expand Up @@ -1127,12 +1214,10 @@ class ConstExprEmitter

assert(CurSize <= TotalSize && "Union size mismatch!");
if (unsigned NumPadBytes = TotalSize - CurSize) {
llvm::Type *Ty = CGM.CharTy;
if (NumPadBytes > 1)
Ty = llvm::ArrayType::get(Ty, NumPadBytes);

Elts.push_back(llvm::UndefValue::get(Ty));
Types.push_back(Ty);
llvm::Constant *Padding =
getPadding(CGM, CharUnits::fromQuantity(NumPadBytes));
Elts.push_back(Padding);
Types.push_back(Padding->getType());
}

llvm::StructType *STy = llvm::StructType::get(VMContext, Types, false);
Expand Down
51 changes: 51 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,57 @@ class CodeGenModule : public CodeGenTypeCache {
MustTailCallUndefinedGlobals.insert(Global);
}

bool shouldZeroInitPadding() const {
// In C23 (N3096) $6.7.10:
// """
// If any object is initialized with an empty iniitializer, then it is
// subject to default initialization:
// - if it is an aggregate, every member is initialized (recursively)
// according to these rules, and any padding is initialized to zero bits;
// - if it is a union, the first named member is initialized (recursively)
// according to these rules, and any padding is initialized to zero bits.
//
// If the aggregate or union contains elements or members that are
// aggregates or unions, these rules apply recursively to the subaggregates
// or contained unions.
//
// If there are fewer initializers in a brace-enclosed list than there are
// elements or members of an aggregate, or fewer characters in a string
// literal used to initialize an array of known size than there are elements
// in the array, the remainder of the aggregate is subject to default
// initialization.
// """
//
// From my understanding, the standard is ambiguous in the following two
// areas:
// 1. For a union type with empty initializer, if the first named member is
// not the largest member, then the bytes comes after the first named member
// but before padding are left unspecified. An example is:
// union U { int a; long long b;};
// union U u = {}; // The first 4 bytes are 0, but 4-8 bytes are left
// unspecified.
//
// 2. It only mentions padding for empty initializer, but doesn't mention
// padding for a non empty initialization list. And if the aggregation or
// union contains elements or members that are aggregates or unions, and
// some are non empty initializers, while others are empty initiailizers,
// the padding initialization is unclear. An example is:
// struct S1 { int a; long long b; };
// struct S2 { char c; struct S1 s1; };
// // The values for paddings between s2.c and s2.s1.a, between s2.s1.a
// and s2.s1.b are unclear.
// struct S2 s2 = { 'c' };
//
// Here we choose to zero initiailize left bytes of a union type. Because
// projects like the Linux kernel are relying on this behavior. If we don't
// explicitly zero initialize them, the undef values can be optimized to
// return gabage data. We also choose to zero initialize paddings for
// aggregates and unions, no matter they are initialized by empty
// initializers or non empty initializers. This can provide a consistent
// behavior. So projects like the Linux kernel can rely on it.
return !getLangOpts().CPlusPlus;
}

private:
bool shouldDropDLLAttribute(const Decl *D, const llvm::GlobalValue *GV) const;

Expand Down
13 changes: 7 additions & 6 deletions clang/lib/Driver/ToolChains/HIPUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,20 +340,21 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
void HIP::constructGenerateObjFileFromHIPFatBinary(
Compilation &C, const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const JobAction &JA, const Tool &T) {
const Driver &D = C.getDriver();
std::string Name = std::string(llvm::sys::path::stem(Output.getFilename()));

// Create Temp Object File Generator,
// Offload Bundled file and Bundled Object file.
// Keep them if save-temps is enabled.
const char *ObjinFile;
const char *BundleFile;
if (C.getDriver().isSaveTempsEnabled()) {
if (D.isSaveTempsEnabled()) {
ObjinFile = C.getArgs().MakeArgString(Name + ".mcin");
BundleFile = C.getArgs().MakeArgString(Name + ".hipfb");
} else {
auto TmpNameMcin = C.getDriver().GetTemporaryPath(Name, "mcin");
auto TmpNameMcin = D.GetTemporaryPath(Name, "mcin");
ObjinFile = C.addTempFile(C.getArgs().MakeArgString(TmpNameMcin));
auto TmpNameFb = C.getDriver().GetTemporaryPath(Name, "hipfb");
auto TmpNameFb = D.GetTemporaryPath(Name, "hipfb");
BundleFile = C.addTempFile(C.getArgs().MakeArgString(TmpNameFb));
}
HIP::constructHIPFatbinCommand(C, JA, BundleFile, Inputs, Args, T);
Expand Down Expand Up @@ -456,7 +457,7 @@ void HIP::constructGenerateObjFileFromHIPFatBinary(
llvm::raw_fd_ostream Objf(ObjinFile, EC, llvm::sys::fs::OF_None);

if (EC) {
C.getDriver().Diag(clang::diag::err_unable_to_make_temp) << EC.message();
D.Diag(clang::diag::err_unable_to_make_temp) << EC.message();
return;
}

Expand All @@ -466,7 +467,7 @@ void HIP::constructGenerateObjFileFromHIPFatBinary(
"-o", Output.getFilename(),
"-x", "assembler",
ObjinFile, "-c"};
const char *Clang = Args.MakeArgString(C.getDriver().ClangExecutable);
C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(),
Clang, McArgs, Inputs, Output));
D.getClangProgramPath(), McArgs,
Inputs, Output, D.getPrependArg()));
}
25 changes: 9 additions & 16 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1175,26 +1175,19 @@ class AnnotatingParser {

ScopedContextCreator ContextCreator(*this, tok::l_brace, 1);
Contexts.back().ColonIsDictLiteral = true;

const auto *Prev = OpeningBrace.getPreviousNonComment();

if (OpeningBrace.is(BK_BracedInit)) {
if (OpeningBrace.is(BK_BracedInit))
Contexts.back().IsExpression = true;
if (Prev) {
for (auto *Tok = Prev->Previous; Tok && Tok->isPointerOrReference();
Tok = Tok->Previous) {
Tok->setFinalizedType(TT_PointerOrReference);
}
}
}

if (Style.isJavaScript() && Prev && Prev->is(TT_JsTypeColon))
if (Style.isJavaScript() && OpeningBrace.Previous &&
OpeningBrace.Previous->is(TT_JsTypeColon)) {
Contexts.back().IsExpression = false;

}
if (Style.isVerilog() &&
(!OpeningBrace.getPreviousNonComment() ||
OpeningBrace.getPreviousNonComment()->isNot(Keywords.kw_apostrophe))) {
Contexts.back().VerilogMayBeConcatenation = true;
}
if (Style.isTableGen())
Contexts.back().ColonIsDictLiteral = false;
else if (Style.isVerilog() && !(Prev && Prev->is(Keywords.kw_apostrophe)))
Contexts.back().VerilogMayBeConcatenation = true;

unsigned CommaCount = 0;
while (CurrentToken) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Headers/intrin0.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ unsigned char _InterlockedCompareExchange128_rel(__int64 volatile *_Destination,
__int64 *_ComparandResult);
#endif

#ifdef __x86_64__ && !defined(__arm64ec__)
#if defined(__x86_64__) && !defined(__arm64ec__)
unsigned __int64 _umul128(unsigned __int64, unsigned __int64,
unsigned __int64 *);
unsigned __int64 __shiftleft128(unsigned __int64 _LowPart,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/CheckExprLifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor) {
if (LHSRecordDecl->hasAttr<PointerAttr>())
return true;

if (Ctor->getConstructor()->getNumParams() != 1 ||
if (Ctor->getConstructor()->param_empty() ||
!isContainerOfPointer(LHSRecordDecl))
return false;

Expand Down
11 changes: 7 additions & 4 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,10 +357,13 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc,
return nullptr;
}

// FIXME: LookupNestedNameSpecifierName isn't the right kind of
// lookup for class-names.
LookupNameKind Kind = isClassName ? LookupNestedNameSpecifierName :
LookupOrdinaryName;
// In the case where we know that the identifier is a class name, we know that
// it is a type declaration (struct, class, union or enum) so we can use tag
// name lookup.
//
// C++ [class.derived]p2 (wrt lookup in a base-specifier): The lookup for
// the component name of the type-name or simple-template-id is type-only.
LookupNameKind Kind = isClassName ? LookupTagName : LookupOrdinaryName;
LookupResult Result(*this, &II, NameLoc, Kind);
if (LookupCtx) {
// Perform "qualified" name lookup into the declaration context we
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18865,7 +18865,17 @@ bool Sema::tryCaptureVariable(
// We need to sync up the Declaration Context with the
// FunctionScopeIndexToStopAt
if (FunctionScopeIndexToStopAt) {
assert(!FunctionScopes.empty() && "No function scopes to stop at?");
unsigned FSIndex = FunctionScopes.size() - 1;
// When we're parsing the lambda parameter list, the current DeclContext is
// NOT the lambda but its parent. So move away the current LSI before
// aligning DC and FunctionScopeIndexToStopAt.
if (auto *LSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[FSIndex]);
FSIndex && LSI && !LSI->AfterParameterList)
--FSIndex;
assert(MaxFunctionScopesIndex <= FSIndex &&
"FunctionScopeIndexToStopAt should be no greater than FSIndex into "
"FunctionScopes.");
while (FSIndex != MaxFunctionScopesIndex) {
DC = getLambdaAwareParentOfDeclContext(DC);
--FSIndex;
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2157,7 +2157,8 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,

// Per C++0x [expr.new]p5, the type being constructed may be a
// typedef of an array type.
if (!ArraySize) {
// Dependent case will be handled separately.
if (!ArraySize && !AllocType->isDependentType()) {
if (const ConstantArrayType *Array
= Context.getAsConstantArrayType(AllocType)) {
ArraySize = IntegerLiteral::Create(Context, Array->getSize(),
Expand Down Expand Up @@ -8686,7 +8687,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures(
while (isa_and_nonnull<CapturedDecl>(DC))
DC = DC->getParent();
assert(
CurrentLSI->CallOperator == DC &&
(CurrentLSI->CallOperator == DC || !CurrentLSI->AfterParameterList) &&
"The current call operator must be synchronized with Sema's CurContext");
#endif // NDEBUG

Expand Down
146 changes: 138 additions & 8 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,18 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
return false;
}
}
case OpenACCClauseKind::Vector: {
switch (DirectiveKind) {
case OpenACCDirectiveKind::Loop:
case OpenACCDirectiveKind::ParallelLoop:
case OpenACCDirectiveKind::SerialLoop:
case OpenACCDirectiveKind::KernelsLoop:
case OpenACCDirectiveKind::Routine:
return true;
default:
return false;
}
}
}

default:
Expand Down Expand Up @@ -512,14 +524,6 @@ class SemaOpenACCClauseVisitor {

OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
switch (Clause.getClauseKind()) {
case OpenACCClauseKind::Vector: {
// TODO OpenACC: These are only implemented enough for the 'seq'
// diagnostic, otherwise treats itself as unimplemented. When we
// implement these, we can remove them from here.
DiagIfSeqClause(Clause);
return isNotImplemented();
}

#define VISIT_CLAUSE(CLAUSE_NAME) \
case OpenACCClauseKind::CLAUSE_NAME: \
return Visit##CLAUSE_NAME##Clause(Clause);
Expand Down Expand Up @@ -1035,6 +1039,97 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
Clause.getEndLoc());
}

OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
if (DiagIfSeqClause(Clause))
return nullptr;
// Restrictions only properly implemented on 'loop' constructs, and it is
// the only construct that can do anything with this, so skip/treat as
// unimplemented for the combined constructs.
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
return isNotImplemented();

Expr *IntExpr =
Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
if (IntExpr) {
switch (SemaRef.getActiveComputeConstructInfo().Kind) {
case OpenACCDirectiveKind::Invalid:
case OpenACCDirectiveKind::Parallel:
// No restriction on when 'parallel' can contain an argument.
break;
case OpenACCDirectiveKind::Serial:
// GCC disallows this, and there is no real good reason for us to permit
// it, so disallow until we come up with a use case that makes sense.
SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_int_arg_invalid)
<< OpenACCClauseKind::Vector << "num" << /*serial=*/3;
IntExpr = nullptr;
break;
case OpenACCDirectiveKind::Kernels: {
const auto *Itr =
llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
llvm::IsaPred<OpenACCVectorLengthClause>);
if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
<< OpenACCClauseKind::Vector << /*vector_length=*/2;
SemaRef.Diag((*Itr)->getBeginLoc(),
diag::note_acc_previous_clause_here);

IntExpr = nullptr;
}
break;
}
default:
llvm_unreachable("Non compute construct in active compute construct");
}
}

// OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
// construct, the gang clause behaves as follows. ... The region of a loop
// with a gang clause may not contain another loop with a gang clause unless
// within a nested compute region.
if (SemaRef.LoopGangClauseOnKernelLoc.isValid()) {
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
// one of these until we get to the end of the construct.
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
<< OpenACCClauseKind::Vector << OpenACCClauseKind::Gang
<< /*skip kernels construct info*/ 0;
SemaRef.Diag(SemaRef.LoopGangClauseOnKernelLoc,
diag::note_acc_previous_clause_here);
return nullptr;
}

// OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
// contain a loop with a gang or worker clause unless within a nested compute
// region.
if (SemaRef.LoopWorkerClauseLoc.isValid()) {
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
// one of these until we get to the end of the construct.
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
<< OpenACCClauseKind::Vector << OpenACCClauseKind::Worker
<< /*skip kernels construct info*/ 0;
SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
diag::note_acc_previous_clause_here);
return nullptr;
}
// OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
// contain a loop with a gang, worker, or vector clause unless within a nested
// compute region.
if (SemaRef.LoopVectorClauseLoc.isValid()) {
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
// one of these until we get to the end of the construct.
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
<< OpenACCClauseKind::Vector << OpenACCClauseKind::Vector
<< /*skip kernels construct info*/ 0;
SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
diag::note_acc_previous_clause_here);
return nullptr;
}

return OpenACCVectorClause::Create(Ctx, Clause.getBeginLoc(),
Clause.getLParenLoc(), IntExpr,
Clause.getEndLoc());
}

OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
SemaOpenACC::OpenACCParsedClause &Clause) {
if (DiagIfSeqClause(Clause))
Expand Down Expand Up @@ -1099,6 +1194,20 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
return nullptr;
}

// OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
// contain a loop with a gang, worker, or vector clause unless within a nested
// compute region.
if (SemaRef.LoopVectorClauseLoc.isValid()) {
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
// one of these until we get to the end of the construct.
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
<< OpenACCClauseKind::Worker << OpenACCClauseKind::Vector
<< /*skip kernels construct info*/ 0;
SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
diag::note_acc_previous_clause_here);
return nullptr;
}

return OpenACCWorkerClause::Create(Ctx, Clause.getBeginLoc(),
Clause.getLParenLoc(), IntExpr,
Clause.getEndLoc());
Expand Down Expand Up @@ -1193,6 +1302,20 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
return nullptr;
}

// OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
// contain a loop with a gang, worker, or vector clause unless within a nested
// compute region.
if (SemaRef.LoopVectorClauseLoc.isValid()) {
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
// one of these until we get to the end of the construct.
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
<< OpenACCClauseKind::Gang << OpenACCClauseKind::Vector
<< /*kernels construct info*/ 1;
SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
diag::note_acc_previous_clause_here);
return nullptr;
}

return OpenACCGangClause::Create(Ctx, Clause.getBeginLoc(),
Clause.getLParenLoc(), GangKinds, IntExprs,
Clause.getEndLoc());
Expand Down Expand Up @@ -1313,6 +1436,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
: SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
DirKind(DK), OldLoopGangClauseOnKernelLoc(S.LoopGangClauseOnKernelLoc),
OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
LoopRAII(SemaRef, /*PreserveDepth=*/false) {
// Compute constructs end up taking their 'loop'.
if (DirKind == OpenACCDirectiveKind::Parallel ||
Expand All @@ -1330,6 +1454,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
// Implement the 'unless within a nested compute region' part.
SemaRef.LoopGangClauseOnKernelLoc = {};
SemaRef.LoopWorkerClauseLoc = {};
SemaRef.LoopVectorClauseLoc = {};
} else if (DirKind == OpenACCDirectiveKind::Loop) {
SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
Expand All @@ -1355,6 +1480,10 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
if (Itr != Clauses.end())
SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();

auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
if (Itr2 != Clauses.end())
SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
}
}
}
Expand Down Expand Up @@ -1429,6 +1558,7 @@ SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
SemaRef.LoopGangClauseOnKernelLoc = OldLoopGangClauseOnKernelLoc;
SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;

if (DirKind == OpenACCDirectiveKind::Parallel ||
DirKind == OpenACCDirectiveKind::Serial ||
Expand Down
27 changes: 27 additions & 0 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -11815,6 +11815,33 @@ void OpenACCClauseTransform<Derived>::VisitWorkerClause(
ParsedClause.getEndLoc());
}

template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitVectorClause(
const OpenACCVectorClause &C) {
if (C.hasIntExpr()) {
// restrictions on this expression are all "does it exist in certain
// situations" that are not possible to be dependent, so the only check we
// have is that it transforms, and is an int expression.
ExprResult Res = Self.TransformExpr(const_cast<Expr *>(C.getIntExpr()));
if (!Res.isUsable())
return;

Res = Self.getSema().OpenACC().ActOnIntExpr(OpenACCDirectiveKind::Invalid,
C.getClauseKind(),
C.getBeginLoc(), Res.get());
if (!Res.isUsable())
return;
ParsedClause.setIntExprDetails(Res.get());
}

NewClause = OpenACCVectorClause::Create(
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
ParsedClause.getLParenLoc(),
ParsedClause.getNumIntExprs() != 0 ? ParsedClause.getIntExprs()[0]
: nullptr,
ParsedClause.getEndLoc());
}

template <typename Derived>
void OpenACCClauseTransform<Derived>::VisitWaitClause(
const OpenACCWaitClause &C) {
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12345,10 +12345,15 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
return OpenACCWorkerClause::Create(getContext(), BeginLoc, LParenLoc,
WorkerExpr, EndLoc);
}
case OpenACCClauseKind::Vector: {
SourceLocation LParenLoc = readSourceLocation();
Expr *VectorExpr = readBool() ? readSubExpr() : nullptr;
return OpenACCVectorClause::Create(getContext(), BeginLoc, LParenLoc,
VectorExpr, EndLoc);
}

case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
case OpenACCClauseKind::Vector:
case OpenACCClauseKind::NoHost:
case OpenACCClauseKind::UseDevice:
case OpenACCClauseKind::Delete:
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8200,10 +8200,17 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
AddStmt(const_cast<Expr *>(WC->getIntExpr()));
return;
}
case OpenACCClauseKind::Vector: {
const auto *VC = cast<OpenACCVectorClause>(C);
writeSourceLocation(VC->getLParenLoc());
writeBool(VC->hasIntExpr());
if (VC->hasIntExpr())
AddStmt(const_cast<Expr *>(VC->getIntExpr()));
return;
}

case OpenACCClauseKind::Finalize:
case OpenACCClauseKind::IfPresent:
case OpenACCClauseKind::Vector:
case OpenACCClauseKind::NoHost:
case OpenACCClauseKind::UseDevice:
case OpenACCClauseKind::Delete:
Expand Down
18 changes: 18 additions & 0 deletions clang/test/AST/ByteCode/vectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,21 @@ constexpr int a2() {
}

static_assert(a2() == 0);

namespace {
/// convertvector expr with a per-element floating-point cast

typedef float __m128 __attribute__((__vector_size__(16), __aligned__(16)));
typedef double __m128d __attribute__((__vector_size__(16), __aligned__(16)));
typedef float __v4sf __attribute__((__vector_size__(16)));
typedef double __v2df __attribute__((__vector_size__(16)));

static inline constexpr __m128d
_mm_cvtps_pd(__m128 __a) {
return __builtin_convertvector(__builtin_shufflevector(__a, __a, 0, 1), __v2df);
}

constexpr __m128 kf1 {-1.0f,+2.0f,-3.0f,+4.0f};
constexpr __m128d v_mm_cvtps_pd = _mm_cvtps_pd(kf1);
static_assert(v_mm_cvtps_pd[0] == -1.0 && v_mm_cvtps_pd[1] == +2.0);
}
75 changes: 75 additions & 0 deletions clang/test/AST/ast-print-openacc-loop-construct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,79 @@ void foo() {
#pragma acc kernels
#pragma acc loop worker(num:5)
for(;;);

// CHECK: #pragma acc loop vector
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc loop vector
for(;;);

// CHECK: #pragma acc loop vector(length: 5)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc loop vector(5)
for(;;);

// CHECK: #pragma acc loop vector(length: 5)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc loop vector(length:5)
for(;;);

// CHECK: #pragma acc parallel
// CHECK-NEXT: #pragma acc loop vector
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc parallel
#pragma acc loop vector
for(;;);

// CHECK: #pragma acc parallel
// CHECK-NEXT: #pragma acc loop vector(length: 5)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc parallel
#pragma acc loop vector(5)
for(;;);

// CHECK: #pragma acc parallel
// CHECK-NEXT: #pragma acc loop vector(length: 5)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc parallel
#pragma acc loop vector(length:5)
for(;;);

// CHECK: #pragma acc kernels
// CHECK-NEXT: #pragma acc loop vector
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc kernels
#pragma acc loop vector
for(;;);

// CHECK: #pragma acc kernels
// CHECK-NEXT: #pragma acc loop vector(length: 5)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc kernels
#pragma acc loop vector(5)
for(;;);

// CHECK: #pragma acc kernels
// CHECK-NEXT: #pragma acc loop vector(length: 5)
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc kernels
#pragma acc loop vector(length:5)
for(;;);

// CHECK: #pragma acc serial
// CHECK-NEXT: #pragma acc loop vector
// CHECK-NEXT: for (;;)
// CHECK-NEXT: ;
#pragma acc serial
#pragma acc loop vector
for(;;);

}
14 changes: 13 additions & 1 deletion clang/test/CXX/class.derived/p2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,16 @@ namespace PR5840 {
struct Base {};
int Base = 10;
struct Derived : Base {};
}
} // namespace PR5840

namespace issue_16855 {
struct x {};
namespace
{
namespace x
{
struct y : x
{};
} // namespace x
}
} // namespace issue_16855
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ struct et7 {
52,
};

// CHECK: @yv7 ={{.*}} global %struct.et7 { [0 x float] zeroinitializer, i8 52 }
// CHECK: @yv7 ={{.*}} global { [0 x float], i8, [3 x i8] } { [0 x float] zeroinitializer, i8 52, [3 x i8] zeroinitializer }
4 changes: 2 additions & 2 deletions clang/test/CodeGen/2008-08-07-AlignPadding1.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ struct gc_generation {

#define GEN_HEAD(n) (&generations[n].head)

// The idea is that there are 6 undefs in this structure initializer to cover
// The idea is that there are 6 zeroinitializers in this structure initializer to cover
// the padding between elements.
// CHECK: @generations ={{.*}} global [3 x %struct.gc_generation] [%struct.gc_generation { %union._gc_head { %struct.anon { ptr @generations, ptr @generations, i64 0 }, [8 x i8] undef }, i32 700, i32 0, [8 x i8] undef }, %struct.gc_generation { %union._gc_head { %struct.anon { ptr getelementptr (i8, ptr @generations, i64 48), ptr getelementptr (i8, ptr @generations, i64 48), i64 0 }, [8 x i8] undef }, i32 10, i32 0, [8 x i8] undef }, %struct.gc_generation { %union._gc_head { %struct.anon { ptr getelementptr (i8, ptr @generations, i64 96), ptr getelementptr (i8, ptr @generations, i64 96), i64 0 }, [8 x i8] undef }, i32 10, i32 0, [8 x i8] undef }]
// CHECK: @generations ={{.*}} global [3 x %struct.gc_generation] [%struct.gc_generation { %union._gc_head { %struct.anon { ptr @generations, ptr @generations, i64 0 }, [8 x i8] zeroinitializer }, i32 700, i32 0, [8 x i8] zeroinitializer }, %struct.gc_generation { %union._gc_head { %struct.anon { ptr getelementptr (i8, ptr @generations, i64 48), ptr getelementptr (i8, ptr @generations, i64 48), i64 0 }, [8 x i8] zeroinitializer }, i32 10, i32 0, [8 x i8] zeroinitializer }, %struct.gc_generation { %union._gc_head { %struct.anon { ptr getelementptr (i8, ptr @generations, i64 96), ptr getelementptr (i8, ptr @generations, i64 96), i64 0 }, [8 x i8] zeroinitializer }, i32 10, i32 0, [8 x i8] zeroinitializer }]
/* linked lists of container objects */
struct gc_generation generations[3] = {
/* PyGC_Head, threshold, count */
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/2009-06-14-anonymous-union-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct sysfs_dirent {
};
struct sysfs_dirent sysfs_root = { {}, 16877 };

// CHECK: @sysfs_root = {{.*}}global %struct.sysfs_dirent { %union.anon zeroinitializer, i16 16877 }
// CHECK: @sysfs_root = {{.*}}global { %union.anon, i16, [2 x i8] } { %union.anon zeroinitializer, i16 16877, [2 x i8] zeroinitializer }

struct Foo {
union { struct empty {} x; };
Expand All @@ -16,4 +16,4 @@ struct Foo {
struct Foo foo = { {}, 16877 };

// EMPTY: @foo = {{.*}}global %struct.Foo { i16 16877 }
// EMPTY-MSVC: @foo = {{.*}}global %struct.Foo { [4 x i8] undef, i16 16877 }
// EMPTY-MSVC: @foo = {{.*}}global %struct.Foo { [4 x i8] zeroinitializer, i16 16877 }
12 changes: 5 additions & 7 deletions clang/test/CodeGen/64bit-swiftcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@

// CHECK-DAG: %struct.atomic_padded = type { { %struct.packed, [7 x i8] } }
// CHECK-DAG: %struct.packed = type <{ i64, i8 }>
//
// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, i32 0, i32 0 }

/*****************************************************************************/
/****************************** PARAMETER ABIS *******************************/
Expand Down Expand Up @@ -162,8 +160,8 @@ typedef struct {
} struct_2;
TEST(struct_2);
// CHECK-LABEL: define{{.*}} swiftcc { i64, i64 } @return_struct_2() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT2_TYPE]], align 4
// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[RET]], {{.*}}[[STRUCT2_RESULT]]
// CHECK: [[RET:%.*]] = alloca [[STRUCT2:%.*]], align 4
// CHECK: call void @llvm.memset
// CHECK: [[GEP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[RET]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, ptr [[GEP0]], align 4
// CHECK: [[GEP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[RET]], i32 0, i32 1
Expand All @@ -173,15 +171,15 @@ TEST(struct_2);
// CHECK: ret { i64, i64 } [[R1]]
// CHECK: }
// CHECK-LABEL: define{{.*}} swiftcc void @take_struct_2(i64 %0, i64 %1) {{.*}}{
// CHECK: [[V:%.*]] = alloca [[STRUCT:%.*]], align 4
// CHECK: [[V:%.*]] = alloca [[STRUCT2]], align 4
// CHECK: [[GEP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[V]], i32 0, i32 0
// CHECK: store i64 %0, ptr [[GEP0]], align 4
// CHECK: [[GEP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[V]], i32 0, i32 1
// CHECK: store i64 %1, ptr [[GEP1]], align 4
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define{{.*}} void @test_struct_2() {{.*}} {
// CHECK: [[TMP:%.*]] = alloca [[STRUCT2_TYPE]], align 4
// CHECK: [[TMP:%.*]] = alloca [[STRUCT2]], align 4
// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_struct_2()
// CHECK: [[GEP:%.*]] = getelementptr inbounds nuw {{.*}} [[TMP]], i32 0, i32 0
// CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
Expand Down Expand Up @@ -254,7 +252,7 @@ typedef union {
TEST(union_het_fp)
// CHECK-LABEL: define{{.*}} swiftcc i64 @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[UNION:%.*]], align 8
// CHECK: call void @llvm.memcpy{{.*}}(ptr align 8 [[RET]]
// CHECK: call void @llvm.memset{{.*}}(ptr align 8 [[RET]]
// CHECK: [[GEP:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[RET]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, ptr [[GEP]], align 8
// CHECK: ret i64 [[R0]]
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/arm-swiftcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ typedef struct {
TEST(struct_2);
// CHECK-LABEL: define{{.*}} @return_struct_2()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align 4
// CHECK: @llvm.memcpy
// CHECK: @llvm.memset
// CHECK: [[T0:%.*]] = getelementptr inbounds nuw [[AGG:{ i32, i32, float, float }]], ptr [[RET]], i32 0, i32 0
// CHECK: [[FIRST:%.*]] = load i32, ptr [[T0]], align 4
// CHECK: [[T0:%.*]] = getelementptr inbounds nuw [[AGG]], ptr [[RET]], i32 0, i32 1
Expand Down Expand Up @@ -274,7 +274,7 @@ typedef union {
TEST(union_het_fp)
// CHECK-LABEL: define{{.*}} @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[REC:%.*]], align {{(4|8)}}
// CHECK: @llvm.memcpy
// CHECK: @llvm.memset
// CHECK: [[T0:%.*]] = getelementptr inbounds nuw [[AGG:{ i32, i32 }]], ptr [[RET]], i32 0, i32 0
// CHECK: [[FIRST:%.*]] = load i32, ptr [[T0]], align {{(4|8)}}
// CHECK: [[T0:%.*]] = getelementptr inbounds nuw [[AGG]], ptr [[RET]], i32 0, i32 1
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/const-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ void g30(void) {
int : 1;
int x;
} a = {};
// CHECK: @g30.a = internal global %struct.anon.1 <{ i8 undef, i32 0 }>, align 1
// CHECK: @g30.a = internal global %struct.anon.1 zeroinitializer, align 1
#pragma pack()
}

Expand All @@ -182,7 +182,7 @@ void g31(void) {
short z;
} a = {23122, -12312731, -312};
#pragma pack()
// CHECK: @g31.a = internal global %struct.anon.2 { i16 23122, i32 -12312731, i16 -312 }, align 4
// CHECK: @g31.a = internal global { i16, [2 x i8], i32, i16, [2 x i8] } { i16 23122, [2 x i8] zeroinitializer, i32 -12312731, i16 -312, [2 x i8] zeroinitializer }, align 4
}

// Clang should evaluate this in constant context, so floating point mode should
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/decl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

// CHECK: @test1.x = internal constant [12 x i32] [i32 1
// CHECK: @__const.test2.x = private unnamed_addr constant [13 x i32] [i32 1,
// CHECK: @test5w = {{(dso_local )?}}global { i32, [4 x i8] } { i32 2, [4 x i8] undef }
// CHECK: @test5w = {{(dso_local )?}}global { i32, [4 x i8] } { i32 2, [4 x i8] zeroinitializer }
// CHECK: @test5y = {{(dso_local )?}}global { double } { double 7.300000e+0{{[0]*}}1 }

// CHECK: @__const.test6.x = private unnamed_addr constant %struct.SelectDest { i8 1, i8 2, i32 3, i32 0 }
// CHECK: @__const.test6.x = private unnamed_addr constant { i8, i8, [2 x i8], i32, i32 } { i8 1, i8 2, [2 x i8] zeroinitializer, i32 3, i32 0 }

// CHECK: @test7 = {{(dso_local )?}}global [2 x %struct.test7s] [%struct.test7s { i32 1, i32 2 }, %struct.test7s { i32 4, i32 0 }]

Expand Down
12 changes: 6 additions & 6 deletions clang/test/CodeGen/designated-initializers.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ struct foo {
// CHECK: @u ={{.*}} global %union.anon zeroinitializer
union { int i; float f; } u = { };

// CHECK: @u2 ={{.*}} global { i32, [4 x i8] } { i32 0, [4 x i8] undef }
// CHECK: @u2 ={{.*}} global { i32, [4 x i8] } zeroinitializer
union { int i; double f; } u2 = { };

// CHECK: @u3 ={{.*}} global %union.anon.1 zeroinitializer
Expand Down Expand Up @@ -62,22 +62,22 @@ struct overwrite_string_struct2 {
char L[6];
int M;
} overwrite_string2[] = { { { "foo" }, 1 }, [0].L[2] = 'x'};
// CHECK: [6 x i8] c"fox\00\00\00", i32 1
// CHECK: [6 x i8] c"fox\00\00\00", [2 x i8] zeroinitializer, i32 1
struct overwrite_string_struct3 {
char L[3];
int M;
} overwrite_string3[] = { { { "foo" }, 1 }, [0].L[2] = 'x'};
// CHECK: [3 x i8] c"fox", i32 1
// CHECK: [3 x i8] c"fox", i8 0, i32 1
struct overwrite_string_struct4 {
char L[3];
int M;
} overwrite_string4[] = { { { "foobar" }, 1 }, [0].L[2] = 'x'};
// CHECK: [3 x i8] c"fox", i32 1
// CHECK: [3 x i8] c"fox", i8 0, i32 1
struct overwrite_string_struct5 {
char L[6];
int M;
} overwrite_string5[] = { { { "foo" }, 1 }, [0].L[4] = 'y'};
// CHECK: [6 x i8] c"foo\00y\00", i32 1
// CHECK: [6 x i8] c"foo\00y\00", [2 x i8] zeroinitializer, i32 1


// CHECK: @u1 = {{.*}} { i32 65535 }
Expand Down Expand Up @@ -138,7 +138,7 @@ union_16644_t union_16644_instance_4[2] =
[1].b[1] = 4
};

// CHECK: @lab ={{.*}} global { [4 x i8], i32 } { [4 x i8] undef, i32 123 }
// CHECK: @lab ={{.*}} global { [4 x i8], i32 } { [4 x i8] zeroinitializer, i32 123 }
struct leading_anon_bitfield { int : 32; int n; } lab = { .n = 123 };

struct Base {
Expand Down
18 changes: 9 additions & 9 deletions clang/test/CodeGen/ext-int.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
unsigned _BitInt(1) GlobSize1 = 0;
// CHECK: @GlobSize1 = {{.*}}global i8 0

// CHECK64: @__const.foo.A = private unnamed_addr constant { i32, [4 x i8], <{ i8, [23 x i8] }> } { i32 1, [4 x i8] undef, <{ i8, [23 x i8] }> <{ i8 -86, [23 x i8] zeroinitializer }> }, align 8
// CHECK64: @__const.foo.A = private unnamed_addr constant { i32, [4 x i8], <{ i8, [23 x i8] }> } { i32 1, [4 x i8] zeroinitializer, <{ i8, [23 x i8] }> <{ i8 -86, [23 x i8] zeroinitializer }> }, align 8
// @BigGlob = global [40 x i8] c"\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF\FF", align 8
// CHECK64: @f.p = internal global <{ i8, i8, [22 x i8] }> <{ i8 16, i8 39, [22 x i8] zeroinitializer }>, align 8

Expand Down Expand Up @@ -91,8 +91,8 @@ int foo(int a) {
// CHECK64: %B2 = getelementptr inbounds nuw %struct.S1, ptr %B, i32 0, i32 2
// WIN32: %B2 = getelementptr inbounds nuw %struct.S1, ptr %B, i32 0, i32 2
// LIN32: %B2 = getelementptr inbounds nuw %struct.S1, ptr %B, i32 0, i32 1
// CHECK: %0 = load i32, ptr %a.addr, align 4
// CHECK: %conv = sext i32 %0 to i129
// CHECK: %[[V1:.+]] = load i32, ptr %a.addr, align 4
// CHECK: %conv = sext i32 %[[V1]] to i129
// CHECK64: storedv = sext i129 %conv to i192
// WIN32: storedv = sext i129 %conv to i192
// LIN32: storedv = sext i129 %conv to i160
Expand All @@ -102,12 +102,12 @@ int foo(int a) {
// CHECK64: %B3 = getelementptr inbounds nuw %struct.S1, ptr %A, i32 0, i32 2
// WIN32: %B3 = getelementptr inbounds nuw %struct.S1, ptr %A, i32 0, i32 2
// LIN32: %B3 = getelementptr inbounds nuw %struct.S1, ptr %A, i32 0, i32 1
// CHECK64: %1 = load i192, ptr %B3, align 8
// WIN32: %1 = load i192, ptr %B3, align 8
// LIN32: %1 = load i160, ptr %B3, align 4
// CHECK64: %loadedv = trunc i192 %1 to i129
// WIN32: %loadedv = trunc i192 %1 to i129
// LIN32: %loadedv = trunc i160 %1 to i129
// CHECK64: %[[V2:.+]] = load i192, ptr %B3, align 8
// WIN32: %[[V2:.+]] = load i192, ptr %B3, align 8
// LIN32: %[[V2:.+]] = load i160, ptr %B3, align 4
// CHECK64: %loadedv = trunc i192 %[[V2]] to i129
// WIN32: %loadedv = trunc i192 %[[V2]] to i129
// LIN32: %loadedv = trunc i160 %[[V2]] to i129
// CHECK: %conv4 = trunc i129 %loadedv to i32
struct S1 A = {1, 170};
struct S1 B = {1, a};
Expand Down
24 changes: 12 additions & 12 deletions clang/test/CodeGen/flexible-array-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ struct { int y[]; } b1 = { { 14, 16 } };

// sizeof(c) == 8, so this global should be at least 8 bytes.
struct { int x; char c; char y[]; } c = { 1, 2, { 13, 15 } };
// CHECK: @c ={{.*}} global { i32, i8, [2 x i8] } { i32 1, i8 2, [2 x i8] c"\0D\0F" }
// CHECK: @c ={{.*}} global { i32, i8, [2 x i8], i8 } { i32 1, i8 2, [2 x i8] c"\0D\0F", i8 0 }

// sizeof(d) == 8, so this global should be at least 8 bytes.
struct __attribute((packed, aligned(4))) { char a; int x; char z[]; } d = { 1, 2, { 13, 15 } };
// CHECK: @d ={{.*}} <{ i8, i32, [2 x i8], i8 }> <{ i8 1, i32 2, [2 x i8] c"\0D\0F", i8 undef }>,
// CHECK: @d ={{.*}} <{ i8, i32, [2 x i8], i8 }> <{ i8 1, i32 2, [2 x i8] c"\0D\0F", i8 0 }>,

// This global needs 9 bytes to hold all the flexible array members.
struct __attribute((packed, aligned(4))) { char a; int x; char z[]; } e = { 1, 2, { 13, 15, 17, 19 } };
Expand Down Expand Up @@ -55,21 +55,21 @@ struct { int a; union { int b; short x[]; }; int c; int d; } hf = {1, 2, {}, 3};

// First member is the potential flexible array, initialization requires braces.
struct { int a; union { short x; int b; }; int c; int d; } i = {1, 2, {}, 3};
// CHECK: @i = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] undef }, i32 0, i32 3 }
// CHECK: @i = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] zeroinitializer }, i32 0, i32 3 }
struct { int a; union { short x[0]; int b; }; int c; int d; } i0 = {1, {}, 2, 3};
// CHECK: @i0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 2, i32 3 }
// CHECK: @i0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } zeroinitializer, i32 2, i32 3 }
struct { int a; union { short x[1]; int b; }; int c; int d; } i1 = {1, {2}, {}, 3};
// CHECK: @i1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] undef }, i32 0, i32 3 }
// CHECK: @i1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] zeroinitializer }, i32 0, i32 3 }
struct { int a; union { short x[]; int b; }; int c; int d; } i_f = {4, {}, {}, 6};
// CHECK: @i_f = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 4, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 0, i32 6 }
// CHECK: @i_f = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 4, { [0 x i16], [4 x i8] } zeroinitializer, i32 0, i32 6 }

// Named initializers; order doesn't matter.
struct { int a; union { int b; short x; }; int c; int d; } hn = {.a = 1, .x = 2, .c = 3};
// CHECK: @hn = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] undef }, i32 3, i32 0 }
// CHECK: @hn = global { i32, { i16, [2 x i8] }, i32, i32 } { i32 1, { i16, [2 x i8] } { i16 2, [2 x i8] zeroinitializer }, i32 3, i32 0 }
struct { int a; union { int b; short x[0]; }; int c; int d; } hn0 = {.a = 1, .x = {2}, .c = 3};
// CHECK: @hn0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } { [0 x i16] zeroinitializer, [4 x i8] undef }, i32 3, i32 0 }
// CHECK: @hn0 = global { i32, { [0 x i16], [4 x i8] }, i32, i32 } { i32 1, { [0 x i16], [4 x i8] } zeroinitializer, i32 3, i32 0 }
struct { int a; union { int b; short x[1]; }; int c; int d; } hn1 = {.a = 1, .x = {2}, .c = 3};
// CHECK: @hn1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] undef }, i32 3, i32 0 }
// CHECK: @hn1 = global { i32, { [1 x i16], [2 x i8] }, i32, i32 } { i32 1, { [1 x i16], [2 x i8] } { [1 x i16] [i16 2], [2 x i8] zeroinitializer }, i32 3, i32 0 }

struct { char a[]; } empty_struct = {};
// CHECK: @empty_struct ={{.*}} global %struct.anon{{.*}} zeroinitializer, align 1
Expand All @@ -96,10 +96,10 @@ union { char a[]; } only_in_union0 = {0};
// CHECK: @only_in_union0 = global { [1 x i8] } zeroinitializer, align 1

union { char a[]; int b; } first_in_union = {};
// CHECK: @first_in_union = global { [0 x i8], [4 x i8] } { [0 x i8] zeroinitializer, [4 x i8] undef }, align 4
// CHECK: @first_in_union = global { [0 x i8], [4 x i8] } zeroinitializer, align 4

union { char a[]; int b; } first_in_union0 = {0};
// CHECK: @first_in_union0 = global { [1 x i8], [3 x i8] } { [1 x i8] zeroinitializer, [3 x i8] undef }, align 4
// CHECK: @first_in_union0 = global { [1 x i8], [3 x i8] } zeroinitializer, align 4

union { char a[]; int b; } first_in_union123 = { {1, 2, 3} };
// CHECK: @first_in_union123 = global { [3 x i8], i8 } { [3 x i8] c"\01\02\03", i8 undef }, align 4
// CHECK: @first_in_union123 = global { [3 x i8], i8 } { [3 x i8] c"\01\02\03", i8 0 }, align 4
2 changes: 1 addition & 1 deletion clang/test/CodeGen/global-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct ManyFields {
int f;
};

// CHECK: global %struct.ManyFields { i32 1, i32 2, i32 0, i8 0, i32 0, i32 0 }
// CHECK: global { i32, i32, i32, i8, [3 x i8], i32, i32 } { i32 1, i32 2, i32 0, i8 0, [3 x i8] zeroinitializer, i32 0, i32 0 }
struct ManyFields FewInits = {1, 2};


Expand Down
19 changes: 0 additions & 19 deletions clang/test/CodeGen/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,25 +187,6 @@ void nonzeroMemsetf64(void) {
// CHECK: call void @llvm.memset.p0.i32(ptr {{.*}}, i8 68, i32 56, i1 false)
}

void nonzeroPaddedUnionMemset(void) {
union U { char c; int i; };
union U arr[9] = { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, };
// CHECK-LABEL: @nonzeroPaddedUnionMemset(
// CHECK-NOT: store
// CHECK-NOT: memcpy
// CHECK: call void @llvm.memset.p0.i32(ptr {{.*}}, i8 -16, i32 36, i1 false)
}

void nonzeroNestedMemset(void) {
union U { char c; int i; };
struct S { union U u; short i; };
struct S arr[5] = { { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, };
// CHECK-LABEL: @nonzeroNestedMemset(
// CHECK-NOT: store
// CHECK-NOT: memcpy
// CHECK: call void @llvm.memset.p0.i32(ptr {{.*}}, i8 -16, i32 40, i1 false)
}

// PR9257
struct test11S {
int A[10];
Expand Down
275 changes: 275 additions & 0 deletions clang/test/CodeGen/linux-kernel-struct-union-initializer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 5
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=gnu11 -verify -emit-llvm %s -o - | FileCheck %s
// expected-no-diagnostics

union U1 {
int x;
char y[16];
};

struct S1 {
int x;
union U1 y;
};

union U2 {
int x;
char y[16];
} __attribute__((__aligned__(32)));

struct S2 {
int x;
long long y;
char z[8];
} __attribute__((__aligned__(32)));

struct S3 {
char x;
unsigned char y : 4;
unsigned char z : 7;
} __attribute__((packed));

union U1 global_u1 = {};

union U1 global_u2 = {3};

union U1 global_u2_from_cast = (union U1)3;

struct S1 global_s1 = {};

struct S1 global_s2 = {
.x = 3,
};

struct S1 global_s3 = {.x = 3, .y = {.x = 6}};

const union U1 global_const_u1 = {4};
struct S1 global_s3_from_const_u1 = {.y = global_const_u1};

union U2 global_u3 = {};

struct S2 global_s4 = {};

struct S2 global_s5 = {.x = 1};

struct S3 global_s6 = {101, 15, 123};

// Test empty initializer for union.
//.
// CHECK: @global_u1 = global %union.U1 zeroinitializer, align 4
// CHECK: @global_u2 = global %union.U1 { i32 3, [12 x i8] zeroinitializer }, align 4
// CHECK: @global_u2_from_cast = global { i32, [12 x i8] } { i32 3, [12 x i8] zeroinitializer }, align 4
// CHECK: @global_s1 = global %struct.S1 zeroinitializer, align 4
// CHECK: @global_s2 = global %struct.S1 { i32 3, %union.U1 zeroinitializer }, align 4
// CHECK: @global_s3 = global %struct.S1 { i32 3, %union.U1 { i32 6, [12 x i8] zeroinitializer } }, align 4
// CHECK: @global_const_u1 = constant %union.U1 { i32 4, [12 x i8] zeroinitializer }, align 4
// CHECK: @global_s3_from_const_u1 = global %struct.S1 { i32 0, %union.U1 { i32 4, [12 x i8] zeroinitializer } }, align 4
// CHECK: @global_u3 = global %union.U2 zeroinitializer, align 32
// CHECK: @global_s4 = global { i32, [4 x i8], i64, [8 x i8], [8 x i8] } zeroinitializer, align 32
// CHECK: @global_s5 = global { i32, [4 x i8], i64, [8 x i8], [8 x i8] } { i32 1, [4 x i8] zeroinitializer, i64 0, [8 x i8] zeroinitializer, [8 x i8] zeroinitializer }, align 32
// CHECK: @global_s6 = global { i8, i8, i8 } { i8 101, i8 -65, i8 7 }, align 1
// CHECK: @test2.a = internal global %union.U1 zeroinitializer, align 4
// CHECK: @__const.test3.a = private unnamed_addr constant %union.U1 { i32 3, [12 x i8] zeroinitializer }, align 4
// CHECK: @test4.a = internal global %union.U1 { i32 3, [12 x i8] zeroinitializer }, align 4
// CHECK: @test6.s = internal global %struct.S1 zeroinitializer, align 4
// CHECK: @__const.test7.s = private unnamed_addr constant %struct.S1 { i32 3, %union.U1 zeroinitializer }, align 4
// CHECK: @test8.s = internal global %struct.S1 { i32 3, %union.U1 zeroinitializer }, align 4
// CHECK: @__const.test9.s = private unnamed_addr constant %struct.S1 { i32 3, %union.U1 { i32 6, [12 x i8] zeroinitializer } }, align 4
// CHECK: @test10.s = internal global %struct.S1 { i32 3, %union.U1 { i32 6, [12 x i8] zeroinitializer } }, align 4
// CHECK: @test12.a = internal global %union.U2 zeroinitializer, align 32
// CHECK: @test14.s = internal global { i32, [4 x i8], i64, [8 x i8], [8 x i8] } zeroinitializer, align 32
// CHECK: @__const.test15.s = private unnamed_addr constant { i32, [4 x i8], i64, [8 x i8], [8 x i8] } { i32 1, [4 x i8] zeroinitializer, i64 0, [8 x i8] zeroinitializer, [8 x i8] zeroinitializer }, align 32
// CHECK: @test16.s = internal global { i32, [4 x i8], i64, [8 x i8], [8 x i8] } { i32 1, [4 x i8] zeroinitializer, i64 0, [8 x i8] zeroinitializer, [8 x i8] zeroinitializer }, align 32
//.
// CHECK-LABEL: define dso_local void @test1(
// CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[A:%.*]] = alloca [[UNION_U1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[A]], i8 0, i64 16, i1 false)
// CHECK-NEXT: ret void
//
void test1() {
union U1 a = {};
}

// Test empty initializer for union. Use static variable.
// CHECK-LABEL: define dso_local void @test2(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test2() {
static union U1 a = {};
}

// Test only initializing a small field for union.
// CHECK-LABEL: define dso_local void @test3(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[A:%.*]] = alloca [[UNION_U1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[A]], ptr align 4 @__const.test3.a, i64 16, i1 false)
// CHECK-NEXT: ret void
//
void test3() {
union U1 a = {3};
}

// Test only initializing a small field for union. Use static variable.
// CHECK-LABEL: define dso_local void @test4(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test4() {
static union U1 a = {3};
}

// Test union in struct. Use empty initializer for the struct.
// CHECK-LABEL: define dso_local void @test5(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[S]], i8 0, i64 20, i1 false)
// CHECK-NEXT: ret void
//
void test5() {
struct S1 s = {};
}

// Test union in struct. Use empty initializer for the struct. Use static variable.
// CHECK-LABEL: define dso_local void @test6(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test6() {
static struct S1 s = {};
}

// Test union in struct. Initialize other fields of the struct.
// CHECK-LABEL: define dso_local void @test7(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[S]], ptr align 4 @__const.test7.s, i64 20, i1 false)
// CHECK-NEXT: ret void
//
void test7() {
struct S1 s = {
.x = 3,
};
}

// Test union in struct. Initialize other fields of the struct. Use static variable.
// CHECK-LABEL: define dso_local void @test8(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test8() {
static struct S1 s = {
.x = 3,
};
}

// Test union in struct. Initialize a small field for union.
// CHECK-LABEL: define dso_local void @test9(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S1:%.*]], align 4
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[S]], ptr align 4 @__const.test9.s, i64 20, i1 false)
// CHECK-NEXT: ret void
//
void test9() {
struct S1 s = {.x = 3,
.y = {
.x = 6,
}};
}

// Test union in struct. Initialize a small field for union. Use static variable.
// CHECK-LABEL: define dso_local void @test10(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test10() {
static struct S1 s = {.x = 3,
.y = {
.x = 6,
}};
}

// Test empty initializer for union with padding.
// CHECK-LABEL: define dso_local void @test11(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[A:%.*]] = alloca [[UNION_U2:%.*]], align 32
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 32 [[A]], i8 0, i64 32, i1 false)
// CHECK-NEXT: ret void
//
void test11() {
union U2 a = {};
}

// Test empty initializer for union with padding. Use static variable.
// CHECK-LABEL: define dso_local void @test12(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test12() {
static union U2 a = {};
}

// Test empty initializer for struct with padding.
// CHECK-LABEL: define dso_local void @test13(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S2:%.*]], align 32
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 32 [[S]], i8 0, i64 32, i1 false)
// CHECK-NEXT: ret void
//
void test13() {
struct S2 s = {};
}

// Test empty initializer for struct with padding. Use static variable.
// CHECK-LABEL: define dso_local void @test14(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test14() {
static struct S2 s = {};
}

// Test partial initialization for struct with padding.
// CHECK-LABEL: define dso_local void @test15(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S2:%.*]], align 32
// CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 32 [[S]], ptr align 32 @__const.test15.s, i64 32, i1 false)
// CHECK-NEXT: ret void
//
void test15() {
struct S2 s = {.x = 1};
}

// Test partial initialization for struct with padding. Use static variable.
// CHECK-LABEL: define dso_local void @test16(
// CHECK-SAME: ) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: ret void
//
void test16() {
static struct S2 s = {.x = 1};
}
//.
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
// CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
// CHECK: attributes #[[ATTR2:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
//.
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
//.
181 changes: 181 additions & 0 deletions clang/test/CodeGen/linux-kernel-struct-union-initializer2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-globals all --version 5
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=gnu11 -verify -emit-llvm %s -o - | FileCheck %s
// expected-no-diagnostics

union U1 {
int x;
char y[5];
};

struct S1 {
int x;
long long y;
};

struct S2 {
unsigned char b1 : 3; // 1st 3 bits (in 1st byte) are b1
unsigned char : 2; // next 2 bits (in 1st byte) are blocked out as unused
unsigned char b2 : 6; // 6 bits for b2 - doesn't fit into the 1st byte => starts a 2nd
unsigned char b3 : 2; // 2 bits for b3 - next (and final) bits in the 2nd byte
int i;
};

struct S3 {
int x;
} __attribute__((__aligned__(8)));

struct S4 {
int a;
union U1 b;
};

struct S5 {
char x;
unsigned char y : 4;
unsigned char z : 7;
} __attribute__((packed));

// Test non-const initializer for union with padding.
// CHECK-LABEL: define dso_local void @test1(
// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[A:%.*]] = alloca [[UNION_U1:%.*]], align 4
// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// CHECK-NEXT: store i32 [[TMP0]], ptr [[A]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[A]], i64 4
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP1]], i8 0, i64 4, i1 false)
// CHECK-NEXT: ret void
//
void test1(int x) {
union U1 a = {x};
}

// Test non-const initializer for struct with padding.
// CHECK-LABEL: define dso_local void @test2(
// CHECK-SAME: i64 noundef [[Y:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[Y_ADDR:%.*]] = alloca i64, align 8
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S1:%.*]], align 8
// CHECK-NEXT: store i64 [[Y]], ptr [[Y_ADDR]], align 8
// CHECK-NEXT: [[X:%.*]] = getelementptr inbounds nuw [[STRUCT_S1]], ptr [[S]], i32 0, i32 0
// CHECK-NEXT: store i32 0, ptr [[X]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = getelementptr i8, ptr [[S]], i64 4
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 4, i1 false)
// CHECK-NEXT: [[Y1:%.*]] = getelementptr inbounds nuw [[STRUCT_S1]], ptr [[S]], i32 0, i32 1
// CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[Y_ADDR]], align 8
// CHECK-NEXT: store i64 [[TMP1]], ptr [[Y1]], align 8
// CHECK-NEXT: ret void
//
void test2(long long y) {
struct S1 s = {.y = y};
}

// Test non-const initializer for struct with padding and bit fields.
// CHECK-LABEL: define dso_local void @test3(
// CHECK-SAME: i8 noundef zeroext [[B:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S2:%.*]], align 4
// CHECK-NEXT: store i8 [[B]], ptr [[B_ADDR]], align 1
// CHECK-NEXT: store i16 0, ptr [[S]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[B_ADDR]], align 1
// CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i16
// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[S]], align 4
// CHECK-NEXT: [[BF_VALUE:%.*]] = and i16 [[TMP1]], 7
// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD]], -8
// CHECK-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], [[BF_VALUE]]
// CHECK-NEXT: store i16 [[BF_SET]], ptr [[S]], align 4
// CHECK-NEXT: [[BF_LOAD1:%.*]] = load i16, ptr [[S]], align 4
// CHECK-NEXT: [[BF_CLEAR2:%.*]] = and i16 [[BF_LOAD1]], -16129
// CHECK-NEXT: [[BF_SET3:%.*]] = or i16 [[BF_CLEAR2]], 0
// CHECK-NEXT: store i16 [[BF_SET3]], ptr [[S]], align 4
// CHECK-NEXT: [[BF_LOAD4:%.*]] = load i16, ptr [[S]], align 4
// CHECK-NEXT: [[BF_CLEAR5:%.*]] = and i16 [[BF_LOAD4]], 16383
// CHECK-NEXT: [[BF_SET6:%.*]] = or i16 [[BF_CLEAR5]], 0
// CHECK-NEXT: store i16 [[BF_SET6]], ptr [[S]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[S]], i64 2
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 2 [[TMP2]], i8 0, i64 2, i1 false)
// CHECK-NEXT: [[I:%.*]] = getelementptr inbounds nuw [[STRUCT_S2]], ptr [[S]], i32 0, i32 1
// CHECK-NEXT: store i32 0, ptr [[I]], align 4
// CHECK-NEXT: ret void
//
void test3(unsigned char b) {
struct S2 s = {.b1 = b};
}

// Test non-const initializer for struct with padding at the end of the struct.
// CHECK-LABEL: define dso_local void @test4(
// CHECK-SAME: i32 noundef [[X:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S3:%.*]], align 8
// CHECK-NEXT: store i32 [[X]], ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_S3]], ptr [[S]], i32 0, i32 0
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
// CHECK-NEXT: store i32 [[TMP0]], ptr [[X1]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[S]], i64 4
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP1]], i8 0, i64 4, i1 false)
// CHECK-NEXT: ret void
//
void test4(int x) {
struct S3 s = {x};
}

// Test non-const initializer for union in struct.
// CHECK-LABEL: define dso_local void @test5(
// CHECK-SAME: i32 noundef [[A:%.*]], i32 noundef [[B:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S4:%.*]], align 4
// CHECK-NEXT: store i32 [[A]], ptr [[A_ADDR]], align 4
// CHECK-NEXT: store i32 [[B]], ptr [[B_ADDR]], align 4
// CHECK-NEXT: [[A1:%.*]] = getelementptr inbounds nuw [[STRUCT_S4]], ptr [[S]], i32 0, i32 0
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// CHECK-NEXT: store i32 [[TMP0]], ptr [[A1]], align 4
// CHECK-NEXT: [[B2:%.*]] = getelementptr inbounds nuw [[STRUCT_S4]], ptr [[S]], i32 0, i32 1
// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[B_ADDR]], align 4
// CHECK-NEXT: store i32 [[TMP1]], ptr [[B2]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, ptr [[B2]], i64 4
// CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP2]], i8 0, i64 4, i1 false)
// CHECK-NEXT: ret void
//
void test5(int a, int b) {
struct S4 s = {a, {b}};
}

// CHECK-LABEL: define dso_local void @test6(
// CHECK-SAME: i8 noundef signext [[X:%.*]]) #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: [[X_ADDR:%.*]] = alloca i8, align 1
// CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_S5:%.*]], align 1
// CHECK-NEXT: store i8 [[X]], ptr [[X_ADDR]], align 1
// CHECK-NEXT: [[X1:%.*]] = getelementptr inbounds nuw [[STRUCT_S5]], ptr [[S]], i32 0, i32 0
// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[X_ADDR]], align 1
// CHECK-NEXT: store i8 [[TMP0]], ptr [[X1]], align 1
// CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[S]], i64 1
// CHECK-NEXT: store i16 0, ptr [[TMP1]], align 1
// CHECK-NEXT: [[Y:%.*]] = getelementptr inbounds nuw [[STRUCT_S5]], ptr [[S]], i32 0, i32 1
// CHECK-NEXT: [[BF_LOAD:%.*]] = load i16, ptr [[Y]], align 1
// CHECK-NEXT: [[BF_CLEAR:%.*]] = and i16 [[BF_LOAD]], -16
// CHECK-NEXT: [[BF_SET:%.*]] = or i16 [[BF_CLEAR]], 0
// CHECK-NEXT: store i16 [[BF_SET]], ptr [[Y]], align 1
// CHECK-NEXT: [[Z:%.*]] = getelementptr inbounds nuw [[STRUCT_S5]], ptr [[S]], i32 0, i32 1
// CHECK-NEXT: [[BF_LOAD2:%.*]] = load i16, ptr [[Z]], align 1
// CHECK-NEXT: [[BF_CLEAR3:%.*]] = and i16 [[BF_LOAD2]], -2033
// CHECK-NEXT: [[BF_SET4:%.*]] = or i16 [[BF_CLEAR3]], 0
// CHECK-NEXT: store i16 [[BF_SET4]], ptr [[Z]], align 1
// CHECK-NEXT: ret void
//
void test6(char x) {
struct S5 s = {.x = x};
}
//.
// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" }
// CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: write) }
//.
// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
//.
6 changes: 4 additions & 2 deletions clang/test/CodeGen/memtag-globals.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// RUN: %clang_cc1 -include %S/Inputs/sanitizer-extra-source.cpp \
// RUN: %clang_cc1 -triple aarch64-linux-android34 \
// RUN: -include %S/Inputs/sanitizer-extra-source.cpp \
// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-ignorelist-global.txt \
// RUN: -fsanitize=memtag-globals -emit-llvm -o - %s | FileCheck %s

// RUN: %clang_cc1 -include %S/Inputs/sanitizer-extra-source.cpp \
// RUN: %clang_cc1 -triple aarch64-linux-android34 \
// RUN: -include %S/Inputs/sanitizer-extra-source.cpp \
// RUN: -fsanitize-ignorelist=%S/Inputs/sanitizer-ignorelist-src.txt \
// RUN: -fsanitize=memtag-globals -emit-llvm -o - %s | \
// RUN: FileCheck %s --check-prefix=IGNORELIST
Expand Down
9 changes: 3 additions & 6 deletions clang/test/CodeGen/mingw-long-double.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@ struct {
char c;
long double ldb;
} agggregate_LD = {};
// GNU32: %struct.anon = type { i8, x86_fp80 }
// GNU32: @agggregate_LD = dso_local global %struct.anon zeroinitializer, align 4
// GNU64: %struct.anon = type { i8, x86_fp80 }
// GNU64: @agggregate_LD = dso_local global %struct.anon zeroinitializer, align 16
// MSC64: %struct.anon = type { i8, double }
// MSC64: @agggregate_LD = dso_local global %struct.anon zeroinitializer, align 8
// GNU32: @agggregate_LD = dso_local global { i8, [3 x i8], x86_fp80 } zeroinitializer, align 4
// GNU64: @agggregate_LD = dso_local global { i8, [15 x i8], x86_fp80 } zeroinitializer, align 16
// MSC64: @agggregate_LD = dso_local global { i8, [7 x i8], double } zeroinitializer, align 8

long double dataLD = 1.0L;
// GNU32: @dataLD = dso_local global x86_fp80 0xK3FFF8000000000000000, align 4
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/mms-bitfields.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,5 @@ union HEADER {
struct Inner variable = { 1,0,1, 21 };
union HEADER hdr = {{1,2,3,4}};

// CHECK: @variable ={{.*}} global { i8, [3 x i8], i8, i8, i8, i8 } { i8 5, [3 x i8] undef, i8 21, i8 0, i8 0, i8 0 }, align 1
// CHECK: @hdr ={{.*}} global { { i8, i8, [2 x i8], i8, i8, i8, i8, i8, [3 x i8] } } { { i8, i8, [2 x i8], i8, i8, i8, i8, i8, [3 x i8] } { i8 8, i8 0, [2 x i8] undef, i8 2, i8 0, i8 0, i8 3, i8 4, [3 x i8] undef } }, align 1
// CHECK: @variable ={{.*}} global { i8, [3 x i8], i8, i8, i8, i8 } { i8 5, [3 x i8] zeroinitializer, i8 21, i8 0, i8 0, i8 0 }, align 1
// CHECK: @hdr ={{.*}} global { { i8, i8, [2 x i8], i8, i8, i8, i8, i8, [3 x i8] } } { { i8, i8, [2 x i8], i8, i8, i8, i8, i8, [3 x i8] } { i8 8, i8 0, [2 x i8] zeroinitializer, i8 2, i8 0, i8 0, i8 3, i8 4, [3 x i8] zeroinitializer } }, align 1
4 changes: 2 additions & 2 deletions clang/test/CodeGen/union-init2.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// RUN: %clang_cc1 -x c++ %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefixes=CHECK-CXX

// Make sure we generate something sane instead of a ptrtoint
// CHECK: @r, [4 x i8] undef
// CHECK: @r, [4 x i8] zeroinitializer
union x {long long b;union x* a;} r = {.a = &r};


// CHECK: global { [3 x i8], [5 x i8] } { [3 x i8] zeroinitializer, [5 x i8] undef }
// CHECK: global { [3 x i8], [5 x i8] } zeroinitializer
union z {
char a[3];
long long b;
Expand Down
12 changes: 5 additions & 7 deletions clang/test/CodeGen/windows-swiftcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#define ERROR __attribute__((swift_error_result))
#define CONTEXT __attribute__((swift_context))

// CHECK: [[STRUCT2_RESULT:@.*]] = private {{.*}} constant [[STRUCT2_TYPE:%.*]] { i32 0, i8 0, i8 undef, i8 0, i32 0, i32 0 }

/*****************************************************************************/
/****************************** PARAMETER ABIS *******************************/
/*****************************************************************************/
Expand Down Expand Up @@ -142,8 +140,8 @@ typedef struct {
} struct_2;
TEST(struct_2);
// CHECK-LABEL: define dso_local swiftcc { i64, i64 } @return_struct_2() {{.*}}{
// CHECK: [[RET:%.*]] = alloca [[STRUCT2_TYPE]], align 4
// CHECK: call void @llvm.memcpy{{.*}}({{.*}}[[RET]], {{.*}}[[STRUCT2_RESULT]]
// CHECK: [[RET:%.*]] = alloca [[STRUCT2:%.*]], align 4
// CHECK: call void @llvm.memset
// CHECK: [[GEP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[RET]], i32 0, i32 0
// CHECK: [[T0:%.*]] = load i64, ptr [[GEP0]], align 4
// CHECK: [[GEP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[RET]], i32 0, i32 1
Expand All @@ -153,15 +151,15 @@ TEST(struct_2);
// CHECK: ret { i64, i64 } [[R1]]
// CHECK: }
// CHECK-LABEL: define dso_local swiftcc void @take_struct_2(i64 %0, i64 %1) {{.*}}{
// CHECK: [[V:%.*]] = alloca [[STRUCT:%.*]], align 4
// CHECK: [[V:%.*]] = alloca [[STRUCT2]], align 4
// CHECK: [[GEP0:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[V]], i32 0, i32 0
// CHECK: store i64 %0, ptr [[GEP0]], align 4
// CHECK: [[GEP1:%.*]] = getelementptr inbounds nuw { i64, i64 }, ptr [[V]], i32 0, i32 1
// CHECK: store i64 %1, ptr [[GEP1]], align 4
// CHECK: ret void
// CHECK: }
// CHECK-LABEL: define dso_local void @test_struct_2() {{.*}} {
// CHECK: [[TMP:%.*]] = alloca [[STRUCT2_TYPE]], align 4
// CHECK: [[TMP:%.*]] = alloca [[STRUCT2]], align 4
// CHECK: [[CALL:%.*]] = call swiftcc { i64, i64 } @return_struct_2()
// CHECK: [[GEP:%.*]] = getelementptr inbounds nuw {{.*}} [[TMP]], i32 0, i32 0
// CHECK: [[T0:%.*]] = extractvalue { i64, i64 } [[CALL]], 0
Expand Down Expand Up @@ -234,7 +232,7 @@ typedef union {
TEST(union_het_fp)
// CHECK-LABEL: define dso_local swiftcc i64 @return_union_het_fp()
// CHECK: [[RET:%.*]] = alloca [[UNION:%.*]], align 8
// CHECK: call void @llvm.memcpy{{.*}}(ptr align {{[0-9]+}} [[RET]]
// CHECK: call void @llvm.memset{{.*}}(ptr align {{[0-9]+}} [[RET]]
// CHECK: [[GEP:%.*]] = getelementptr inbounds nuw { i64 }, ptr [[RET]], i32 0, i32 0
// CHECK: [[R0:%.*]] = load i64, ptr [[GEP]], align 8
// CHECK: ret i64 [[R0]]
Expand Down
15 changes: 15 additions & 0 deletions clang/test/CodeGenCXX/ext-int.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -614,3 +614,18 @@ void TBAATest(_BitInt(sizeof(int) * 8) ExtInt,
// NewStructPathTBAA-DAG: ![[EXTINT_TBAA_ROOT]] = !{![[CHAR_TBAA_ROOT]], i64 4, !"_BitInt(32)"}
// NewStructPathTBAA-DAG: ![[EXTINT6_TBAA]] = !{![[EXTINT6_TBAA_ROOT:.+]], ![[EXTINT6_TBAA_ROOT]], i64 0, i64 1}
// NewStructPathTBAA-DAG: ![[EXTINT6_TBAA_ROOT]] = !{![[CHAR_TBAA_ROOT]], i64 1, !"_BitInt(6)"}

namespace A {
template <int N> struct S {
using T = _BitInt(N);
T Data;
};
template <int N> void foo(S<N> B) {
const auto Var = B.Data;
}

void bar() {
S<2080> a;
foo(a);
}
}
2 changes: 1 addition & 1 deletion clang/test/CodeGenObjC/designated-initializers.m
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
char L[3];
int M;
} overwrite_string[] = { { { @encode(void**) }, 1 }, [0].L[1] = 'x'};
// CHECK: [3 x i8] c"^xv", i32 1
// CHECK: [3 x i8] c"^xv", i8 0, i32 1
16 changes: 6 additions & 10 deletions clang/test/Driver/hipstdpar.c
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
// REQUIRES: x86-registered-target
// REQUIRES: amdgpu-registered-target
// REQUIRES: system-linux
// UNSUPPORTED: target={{.*}}-zos{{.*}}
// XFAIL: target={{.*}}hexagon{{.*}}
// XFAIL: target={{.*}}-scei{{.*}}
// XFAIL: target={{.*}}-sie{{.*}}
// REQUIRES: x86-registered-target, amdgpu-registered-target

// RUN: not %clang -### --hipstdpar --hipstdpar-path=/does/not/exist -nogpulib \
// RUN: not %clang -### --target=x86_64-unknown-linux-gnu \
// RUN: --hipstdpar --hipstdpar-path=/does/not/exist -nogpulib \
// RUN: -nogpuinc --compile %s 2>&1 | \
// RUN: FileCheck --check-prefix=HIPSTDPAR-MISSING-LIB %s
// RUN: %clang -### --hipstdpar --hipstdpar-path=%S/Inputs/hipstdpar \
// RUN: %clang -### --target=x86_64-unknown-linux-gnu \
// RUN: --hipstdpar --hipstdpar-path=%S/Inputs/hipstdpar \
// RUN: --hipstdpar-thrust-path=%S/Inputs/hipstdpar/thrust \
// RUN: --hipstdpar-prim-path=%S/Inputs/hipstdpar/rocprim \
// RUN: -nogpulib -nogpuinc --compile %s 2>&1 | \
// RUN: FileCheck --check-prefix=HIPSTDPAR-COMPILE %s
// RUN: touch %t.o
// RUN: %clang -### --hipstdpar %t.o 2>&1 | FileCheck --check-prefix=HIPSTDPAR-LINK %s
// RUN: %clang -### --target=x86_64-unknown-linux-gnu --hipstdpar %t.o 2>&1 | FileCheck --check-prefix=HIPSTDPAR-LINK %s

// HIPSTDPAR-MISSING-LIB: error: cannot find HIP Standard Parallelism Acceleration library; provide it via '--hipstdpar-path'
// HIPSTDPAR-COMPILE: "-x" "hip"
Expand Down
12 changes: 6 additions & 6 deletions clang/test/Headers/ms-intrin.cpp
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
// RUN: %clang_cc1 -triple i386-pc-win32 -target-cpu pentium4 \
// RUN: -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -ffreestanding -fsyntax-only -Werror \
// RUN: -ffreestanding -fsyntax-only -Werror -Wsystem-headers \
// RUN: -isystem %S/Inputs/include %s

// RUN: %clang_cc1 -triple i386-pc-win32 -target-cpu broadwell \
// RUN: -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -ffreestanding -emit-obj -o /dev/null -Werror \
// RUN: -ffreestanding -emit-obj -o /dev/null -Werror -Wsystem-headers \
// RUN: -isystem %S/Inputs/include %s

// RUN: %clang_cc1 -triple x86_64-pc-win32 \
// RUN: -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -ffreestanding -emit-obj -o /dev/null -Werror \
// RUN: -ffreestanding -emit-obj -o /dev/null -Werror -Wsystem-headers \
// RUN: -isystem %S/Inputs/include %s

// RUN: %clang_cc1 -triple thumbv7--windows \
// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -ffreestanding -fsyntax-only -Werror \
// RUN: -ffreestanding -fsyntax-only -Werror -Wsystem-headers \
// RUN: -isystem %S/Inputs/include %s

// RUN: %clang_cc1 -triple aarch64--windows \
// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -ffreestanding -fsyntax-only -Werror \
// RUN: -ffreestanding -fsyntax-only -Werror -Wsystem-headers \
// RUN: -isystem %S/Inputs/include %s

// RUN: %clang_cc1 -triple arm64ec--windows \
// RUN: -fms-compatibility -fms-compatibility-version=17.00 \
// RUN: -ffreestanding -fsyntax-only -Werror \
// RUN: -ffreestanding -fsyntax-only -Werror -Wsystem-headers \
// RUN: -isystem %S/Inputs/include %s

// REQUIRES: x86-registered-target
Expand Down
11 changes: 2 additions & 9 deletions clang/test/ParserOpenACC/parse-clauses.c
Original file line number Diff line number Diff line change
Expand Up @@ -898,7 +898,6 @@ void IntExprParsing() {
#pragma acc set default_async(returns_int())


// expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}}
#pragma acc loop vector
for(;;);
// expected-error@+1{{expected expression}}
Expand All @@ -908,8 +907,7 @@ void IntExprParsing() {
// expected-error@+1{{expected expression}}
#pragma acc loop vector(invalid:)
for(;;);
// expected-error@+2{{invalid tag 'invalid' on 'vector' clause}}
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}}
// expected-error@+1{{invalid tag 'invalid' on 'vector' clause}}
#pragma acc loop vector(invalid:5)
for(;;);
// expected-error@+1{{expected expression}}
Expand All @@ -932,20 +930,15 @@ void IntExprParsing() {
// expected-note@+1{{to match this '('}}
#pragma acc loop vector(num:6,4)
for(;;);
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}}
#pragma acc loop vector(5)
for(;;);
// expected-error@+2{{invalid tag 'num' on 'vector' clause}}
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}}
// expected-error@+1{{invalid tag 'num' on 'vector' clause}}
#pragma acc loop vector(num:5)
for(;;);
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}}
#pragma acc loop vector(length:5)
for(;;);
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}}
#pragma acc loop vector(returns_int())
for(;;);
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}}
#pragma acc loop vector(length:returns_int())
for(;;);

Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/constant-builtins-fmaximum-num.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
// FIXME: %clang_cc1 -std=c++17 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
// expected-no-diagnostics

constexpr double NaN = __builtin_nan("");
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Sema/constant-builtins-fminimum-num.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
// FIXME: %clang_cc1 -std=c++17 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify -fexperimental-new-constant-interpreter %s
// expected-no-diagnostics

constexpr double NaN = __builtin_nan("");
Expand Down
6 changes: 4 additions & 2 deletions clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,16 @@ template<typename T>
struct initializer_list {
const T* ptr; size_t sz;
};
template <typename T>
template<typename T> class allocator {};
template <typename T, typename Alloc = allocator<T>>
struct vector {
typedef __gnu_cxx::basic_iterator<T> iterator;
iterator begin();
iterator end();
const T *data() const;
vector();
vector(initializer_list<T> __l);
vector(initializer_list<T> __l,
const Alloc& alloc = Alloc());

template<typename InputIterator>
vector(InputIterator first, InputIterator __last);
Expand Down
46 changes: 46 additions & 0 deletions clang/test/SemaCXX/GH41441.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// RUN: %clang --target=x86_64-pc-linux -S -fno-discard-value-names -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 %s -fsyntax-only -verify

namespace std {
using size_t = decltype(sizeof(int));
};
void* operator new[](std::size_t, void*) noexcept;

// CHECK: call void @llvm.memset.p0.i64(ptr align 1 %x, i8 0, i64 8, i1 false)
// CHECK: call void @llvm.memset.p0.i64(ptr align 16 %x, i8 0, i64 32, i1 false)
template <typename TYPE>
void f()
{
typedef TYPE TArray[8];

TArray x;
new(&x) TArray();
}

template <typename T>
void f1() {
int (*x)[1] = new int[1][1];
}
template void f1<char>();
void f2() {
int (*x)[1] = new int[1][1];
}

int main()
{
f<char>();
f<int>();
}

// expected-no-diagnostics
template <typename T> struct unique_ptr {unique_ptr(T* p){}};

template <typename T>
unique_ptr<T> make_unique(unsigned long long n) {
return unique_ptr<T>(new T[n]());
}

auto boro(int n){
typedef double HistoryBuffer[4];
return make_unique<HistoryBuffer>(n);
}
22 changes: 22 additions & 0 deletions clang/test/SemaCXX/lambda-capture-type-deduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,25 @@ void __trans_tmp_1() {
}

}

namespace GH47400 {

struct Foo {};

template <int, Foo> struct Arr {};

template <int> struct S {};

constexpr void foo() {
constexpr Foo f;
[&]<int is>() {
[&](Arr<is, f>) {}({}); // f constitutes an ODR-use
}.template operator()<42>();

constexpr int C = 1;
[] {
[](S<C>) { }({}); // ... while C doesn't
}();
}

} // namespace GH47400
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ void uses() {
for(;;);
#pragma acc loop auto worker
for(;;);
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented}}
#pragma acc loop auto vector
for(;;);
// expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}}
Expand Down Expand Up @@ -181,7 +180,6 @@ void uses() {
for(;;);
#pragma acc loop worker auto
for(;;);
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented}}
#pragma acc loop vector auto
for(;;);
// expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}}
Expand Down Expand Up @@ -318,7 +316,6 @@ void uses() {
for(;;);
#pragma acc loop independent worker
for(;;);
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented}}
#pragma acc loop independent vector
for(;;);
// expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}}
Expand Down Expand Up @@ -454,7 +451,6 @@ void uses() {
for(;;);
#pragma acc loop worker independent
for(;;);
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented}}
#pragma acc loop vector independent
for(;;);
// expected-warning@+1{{OpenACC clause 'nohost' not yet implemented}}
Expand Down Expand Up @@ -591,9 +587,8 @@ void uses() {
// expected-note@+1{{previous clause is here}}
#pragma acc loop seq worker
for(;;);
// expected-error@+3{{OpenACC clause 'vector' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note@+2{{previous clause is here}}
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented}}
// expected-error@+2{{OpenACC clause 'vector' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// expected-note@+1{{previous clause is here}}
#pragma acc loop seq vector
for(;;);
// expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}}
Expand Down Expand Up @@ -733,10 +728,8 @@ void uses() {
// expected-note@+1{{previous clause is here}}
#pragma acc loop worker seq
for(;;);
// TODO OpenACC: when 'vector' is implemented and makes it to the AST, this should diagnose because of a conflict with 'seq'.
// TODOexpected-error@+3{{OpenACC clause 'vector' may not appear on the same construct as a 'seq' clause on a 'loop' construct}}
// TODOexpected-note@+2{{previous clause is here}}
// expected-warning@+1{{OpenACC clause 'vector' not yet implemented}}
// expected-error@+2{{OpenACC clause 'seq' may not appear on the same construct as a 'vector' clause on a 'loop' construct}}
// expected-note@+1{{previous clause is here}}
#pragma acc loop vector seq
for(;;);
// expected-warning@+1{{OpenACC clause 'finalize' not yet implemented}}
Expand Down
1 change: 0 additions & 1 deletion clang/test/SemaOpenACC/loop-construct-device_type-clause.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ void uses() {
// Only 'collapse', 'gang', 'worker', 'vector', 'seq', 'independent', 'auto',
// and 'tile' allowed after 'device_type'.

// expected-warning@+1{{OpenACC clause 'vector' not yet implemented, clause ignored}}
#pragma acc loop device_type(*) vector
for(;;);

Expand Down
Loading