6 changes: 5 additions & 1 deletion clang/lib/AST/ByteCode/Descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,16 @@ struct InlineDescriptor {
/// Flag indicating if the field is mutable (if in a record).
LLVM_PREFERRED_TYPE(bool)
unsigned IsFieldMutable : 1;
/// Flag indicating if the field is an element of a composite array.
LLVM_PREFERRED_TYPE(bool)
unsigned IsArrayElement : 1;

const Descriptor *Desc;

InlineDescriptor(const Descriptor *D)
: Offset(sizeof(InlineDescriptor)), IsConst(false), IsInitialized(false),
IsBase(false), IsActive(false), IsFieldMutable(false), Desc(D) {}
IsBase(false), IsActive(false), IsFieldMutable(false),
IsArrayElement(false), Desc(D) {}

void dump() const { dump(llvm::errs()); }
void dump(llvm::raw_ostream &OS) const;
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1406,6 +1406,10 @@ bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
return S.noteUndefinedBehavior();
}

// https://github.com/llvm/llvm-project/issues/102513
#if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", off)
#endif
bool Interpret(InterpState &S, APValue &Result) {
// The current stack frame when we started Interpret().
// This is being used by the ops to determine wheter
Expand All @@ -1430,6 +1434,10 @@ bool Interpret(InterpState &S, APValue &Result) {
}
}
}
// https://github.com/llvm/llvm-project/issues/102513
#if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", on)
#endif

} // namespace interp
} // namespace clang
4 changes: 2 additions & 2 deletions clang/lib/AST/ByteCode/InterpBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ bool Block::hasPointer(const Pointer *P) const {
#endif

DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk)
: Root(Root),
B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) {
: Root(Root), B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, Blk->IsWeak,
/*isDead=*/true) {
// Add the block to the chain of dead blocks.
if (Root)
Root->Prev = this;
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/AST/ByteCode/InterpBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,17 @@ class Block final {
public:
/// Creates a new block.
Block(unsigned EvalID, const std::optional<unsigned> &DeclID,
const Descriptor *Desc, bool IsStatic = false, bool IsExtern = false)
const Descriptor *Desc, bool IsStatic = false, bool IsExtern = false,
bool IsWeak = false)
: EvalID(EvalID), DeclID(DeclID), IsStatic(IsStatic), IsExtern(IsExtern),
IsDynamic(false), Desc(Desc) {
IsDynamic(false), IsWeak(IsWeak), Desc(Desc) {
assert(Desc);
}

Block(unsigned EvalID, const Descriptor *Desc, bool IsStatic = false,
bool IsExtern = false)
bool IsExtern = false, bool IsWeak = false)
: EvalID(EvalID), DeclID((unsigned)-1), IsStatic(IsStatic),
IsExtern(IsExtern), IsDynamic(false), Desc(Desc) {
IsExtern(IsExtern), IsDynamic(false), IsWeak(IsWeak), Desc(Desc) {
assert(Desc);
}

Expand All @@ -73,6 +74,7 @@ class Block final {
bool isStatic() const { return IsStatic; }
/// Checks if the block is temporary.
bool isTemporary() const { return Desc->IsTemporary; }
bool isWeak() const { return IsWeak; }
bool isDynamic() const { return IsDynamic; }
/// Returns the size of the block.
unsigned getSize() const { return Desc->getAllocSize(); }
Expand Down Expand Up @@ -135,9 +137,9 @@ class Block final {
friend class DynamicAllocator;

Block(unsigned EvalID, const Descriptor *Desc, bool IsExtern, bool IsStatic,
bool IsDead)
bool IsWeak, bool IsDead)
: EvalID(EvalID), IsStatic(IsStatic), IsExtern(IsExtern), IsDead(true),
IsDynamic(false), Desc(Desc) {
IsDynamic(false), IsWeak(IsWeak), Desc(Desc) {
assert(Desc);
}

Expand Down Expand Up @@ -170,6 +172,7 @@ class Block final {
/// Flag indicating if this block has been allocated via dynamic
/// memory allocation (e.g. malloc).
bool IsDynamic = false;
bool IsWeak = false;
/// Pointer to the stack slot descriptor.
const Descriptor *Desc;
};
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/AST/ByteCode/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,18 +204,22 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
Path.push_back(APValue::LValuePathEntry(
{Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));

if (const auto *FD = dyn_cast<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
if (const auto *FD =
dyn_cast_if_present<FieldDecl>(Ptr.getFieldDesc()->asDecl()))
Offset += getFieldOffset(FD);

Ptr = Ptr.getBase();
} else if (Ptr.isArrayElement()) {
Ptr = Ptr.expand();
unsigned Index;
if (Ptr.isOnePastEnd())
Index = Ptr.getArray().getNumElems();
else
Index = Ptr.getIndex();

Offset += (Index * ASTCtx.getTypeSizeInChars(Ptr.getType()));
QualType ElemType = Ptr.getFieldDesc()->getElemQualType();
Offset += (Index * ASTCtx.getTypeSizeInChars(ElemType));

Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
Ptr = Ptr.getArray();
} else {
Expand Down
18 changes: 13 additions & 5 deletions clang/lib/AST/ByteCode/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,18 @@ class Pointer {
}
/// Checks if the pointer points to an array.
bool isArrayElement() const {
if (isBlockPointer())
return inArray() && asBlockPointer().Base != Offset;
if (!isBlockPointer())
return false;

const BlockPointer &BP = asBlockPointer();
if (inArray() && BP.Base != Offset)
return true;

// Might be a narrow()'ed element in a composite array.
// Check the inline descriptor.
if (BP.Base >= sizeof(InlineDescriptor) && getInlineDesc()->IsArrayElement)
return true;

return false;
}
/// Pointer points directly to a block.
Expand Down Expand Up @@ -514,9 +524,7 @@ class Pointer {
return false;

assert(isBlockPointer());
if (const ValueDecl *VD = getDeclDesc()->asValueDecl())
return VD->isWeak();
return false;
return asBlockPointer().Pointee->isWeak();
}
/// Checks if an object was initialized.
bool isInitialized() const;
Expand Down
28 changes: 15 additions & 13 deletions clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,12 @@ std::optional<unsigned> Program::getOrCreateDummy(const DeclTy &D) {
return It->second;

QualType QT;
bool IsWeak = false;
if (const auto *E = D.dyn_cast<const Expr *>()) {
QT = E->getType();
} else {
const ValueDecl *VD = cast<ValueDecl>(D.get<const Decl *>());
IsWeak = VD->isWeak();
QT = VD->getType();
if (const auto *RT = QT->getAs<ReferenceType>())
QT = RT->getPointeeType();
Expand All @@ -182,7 +184,7 @@ std::optional<unsigned> Program::getOrCreateDummy(const DeclTy &D) {

auto *G = new (Allocator, Desc->getAllocSize())
Global(Ctx.getEvalID(), getCurrentDecl(), Desc, /*IsStatic=*/true,
/*IsExtern=*/false);
/*IsExtern=*/false, IsWeak);
G->block()->invokeCtor();

Globals.push_back(G);
Expand All @@ -193,6 +195,7 @@ std::optional<unsigned> Program::getOrCreateDummy(const DeclTy &D) {
std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,
const Expr *Init) {
bool IsStatic, IsExtern;
bool IsWeak = VD->isWeak();
if (const auto *Var = dyn_cast<VarDecl>(VD)) {
IsStatic = Context::shouldBeGloballyIndexed(VD);
IsExtern = Var->hasExternalStorage();
Expand All @@ -207,7 +210,8 @@ std::optional<unsigned> Program::createGlobal(const ValueDecl *VD,

// Register all previous declarations as well. For extern blocks, just replace
// the index with the new variable.
if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern, Init)) {
if (auto Idx =
createGlobal(VD, VD->getType(), IsStatic, IsExtern, IsWeak, Init)) {
for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
if (P != VD) {
unsigned PIdx = GlobalIndices[P];
Expand All @@ -225,7 +229,7 @@ std::optional<unsigned> Program::createGlobal(const Expr *E) {
if (auto Idx = getGlobal(E))
return Idx;
if (auto Idx = createGlobal(E, E->getType(), /*isStatic=*/true,
/*isExtern=*/false)) {
/*isExtern=*/false, /*IsWeak=*/false)) {
GlobalIndices[E] = *Idx;
return *Idx;
}
Expand All @@ -234,7 +238,7 @@ std::optional<unsigned> Program::createGlobal(const Expr *E) {

std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
bool IsStatic, bool IsExtern,
const Expr *Init) {
bool IsWeak, const Expr *Init) {
// Create a descriptor for the global.
Descriptor *Desc;
const bool IsConst = Ty.isConstQualified();
Expand All @@ -251,8 +255,8 @@ std::optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
// Allocate a block for storage.
unsigned I = Globals.size();

auto *G = new (Allocator, Desc->getAllocSize())
Global(Ctx.getEvalID(), getCurrentDecl(), Desc, IsStatic, IsExtern);
auto *G = new (Allocator, Desc->getAllocSize()) Global(
Ctx.getEvalID(), getCurrentDecl(), Desc, IsStatic, IsExtern, IsWeak);
G->block()->invokeCtor();

// Initialize InlineDescriptor fields.
Expand Down Expand Up @@ -280,15 +284,13 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
if (!RD->isCompleteDefinition())
return nullptr;

// Deduplicate records.
if (auto It = Records.find(RD); It != Records.end())
// Return an existing record if available. Otherwise, we insert nullptr now
// and replace that later, so recursive calls to this function with the same
// RecordDecl don't run into infinite recursion.
auto [It, Inserted] = Records.try_emplace(RD);
if (!Inserted)
return It->second;

// We insert nullptr now and replace that later, so recursive calls
// to this function with the same RecordDecl don't run into
// infinite recursion.
Records.insert({RD, nullptr});

// Number of bytes required by fields and base classes.
unsigned BaseSize = 0;
// Number of bytes required by virtual base.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ class Program final {

std::optional<unsigned> createGlobal(const DeclTy &D, QualType Ty,
bool IsStatic, bool IsExtern,
const Expr *Init = nullptr);
bool IsWeak, const Expr *Init = nullptr);

/// Reference to the VM context.
Context &Ctx;
Expand Down
8 changes: 3 additions & 5 deletions clang/lib/AST/CXXInheritance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,10 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
BaseRecord = TD->getTemplatedDecl();
}
if (BaseRecord) {
if (!BaseRecord->hasDefinition() ||
VisitedDependentRecords.count(BaseRecord)) {
if (!BaseRecord->hasDefinition())
BaseRecord = nullptr;
else if (!VisitedDependentRecords.insert(BaseRecord).second)
BaseRecord = nullptr;
} else {
VisitedDependentRecords.insert(BaseRecord);
}
}
} else {
BaseRecord = cast<CXXRecordDecl>(
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/ComputeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -958,3 +958,9 @@ ExprDependence clang::computeDependence(ObjCMessageExpr *E) {
D |= A->getDependence();
return D;
}

ExprDependence clang::computeDependence(OpenACCAsteriskSizeExpr *E) {
// This represents a simple asterisk as typed, so cannot be dependent in any
// way.
return ExprDependence::None;
}
11 changes: 11 additions & 0 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3640,6 +3640,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case SYCLUniqueStableNameExprClass:
case PackIndexingExprClass:
case HLSLOutArgExprClass:
case OpenACCAsteriskSizeExprClass:
// These never have a side-effect.
return false;

Expand Down Expand Up @@ -5408,3 +5409,13 @@ HLSLOutArgExpr *HLSLOutArgExpr::Create(const ASTContext &C, QualType Ty,
HLSLOutArgExpr *HLSLOutArgExpr::CreateEmpty(const ASTContext &C) {
return new (C) HLSLOutArgExpr(EmptyShell());
}

OpenACCAsteriskSizeExpr *OpenACCAsteriskSizeExpr::Create(const ASTContext &C,
SourceLocation Loc) {
return new (C) OpenACCAsteriskSizeExpr(Loc, C.IntTy);
}

OpenACCAsteriskSizeExpr *
OpenACCAsteriskSizeExpr::CreateEmpty(const ASTContext &C) {
return new (C) OpenACCAsteriskSizeExpr({}, C.IntTy);
}
1 change: 1 addition & 0 deletions clang/lib/AST/ExprClassification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::CoyieldExprClass:
return ClassifyInternal(Ctx, cast<CoroutineSuspendExpr>(E)->getResumeExpr());
case Expr::SYCLUniqueStableNameExprClass:
case Expr::OpenACCAsteriskSizeExprClass:
return Cl::CL_PRValue;
break;

Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11873,6 +11873,13 @@ class IntExprEvaluator
return Success(E->getValue(), E);
}

bool VisitOpenACCAsteriskSizeExpr(const OpenACCAsteriskSizeExpr *E) {
// This should not be evaluated during constant expr evaluation, as it
// should always be in an unevaluated context (the args list of a 'gang' or
// 'tile' clause).
return Error(E);
}

bool VisitUnaryReal(const UnaryOperator *E);
bool VisitUnaryImag(const UnaryOperator *E);

Expand Down Expand Up @@ -16908,6 +16915,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::GNUNullExprClass:
case Expr::SourceLocExprClass:
case Expr::EmbedExprClass:
case Expr::OpenACCAsteriskSizeExprClass:
return NoDiag();

case Expr::PackIndexingExprClass:
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5745,6 +5745,15 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::HLSLOutArgExprClass:
llvm_unreachable(
"cannot mangle hlsl temporary value; mangling wrong thing?");
case Expr::OpenACCAsteriskSizeExprClass: {
// We shouldn't ever be able to get here, but diagnose anyway.
DiagnosticsEngine &Diags = Context.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"cannot yet mangle OpenACC Asterisk Size expression");
Diags.Report(DiagID);
return;
}
}

if (AsTemplateArg && !IsPrimaryExpr)
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,9 @@ void JSONNodeDumper::VisitSYCLUniqueStableNameExpr(
createQualType(E->getTypeSourceInfo()->getType()));
}

void JSONNodeDumper::VisitOpenACCAsteriskSizeExpr(
const OpenACCAsteriskSizeExpr *E) {}

void JSONNodeDumper::VisitPredefinedExpr(const PredefinedExpr *PE) {
JOS.attribute("name", PredefinedExpr::getIdentKindName(PE->getIdentKind()));
}
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ bool OpenACCClauseWithParams::classof(const OpenACCClause *C) {
}
bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) {
return OpenACCWaitClause::classof(C) || OpenACCNumGangsClause::classof(C) ||
OpenACCTileClause::classof(C) ||
OpenACCClauseWithSingleIntExpr::classof(C) ||
OpenACCClauseWithVarList::classof(C);
}
Expand Down Expand Up @@ -221,6 +222,16 @@ OpenACCNumGangsClause *OpenACCNumGangsClause::Create(const ASTContext &C,
return new (Mem) OpenACCNumGangsClause(BeginLoc, LParenLoc, IntExprs, EndLoc);
}

OpenACCTileClause *OpenACCTileClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<Expr *> SizeExprs,
SourceLocation EndLoc) {
void *Mem =
C.Allocate(OpenACCTileClause::totalSizeToAlloc<Expr *>(SizeExprs.size()));
return new (Mem) OpenACCTileClause(BeginLoc, LParenLoc, SizeExprs, EndLoc);
}

OpenACCPrivateClause *OpenACCPrivateClause::Create(const ASTContext &C,
SourceLocation BeginLoc,
SourceLocation LParenLoc,
Expand Down Expand Up @@ -420,6 +431,13 @@ void OpenACCClausePrinter::VisitNumGangsClause(const OpenACCNumGangsClause &C) {
OS << ")";
}

void OpenACCClausePrinter::VisitTileClause(const OpenACCTileClause &C) {
OS << "tile(";
llvm::interleaveComma(C.getSizeExprs(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitNumWorkersClause(
const OpenACCNumWorkersClause &C) {
OS << "num_workers(";
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,10 @@ void StmtPrinter::VisitPredefinedExpr(PredefinedExpr *Node) {
OS << PredefinedExpr::getIdentKindName(Node->getIdentKind());
}

void StmtPrinter::VisitOpenACCAsteriskSizeExpr(OpenACCAsteriskSizeExpr *Node) {
OS << '*';
}

void StmtPrinter::VisitCharacterLiteral(CharacterLiteral *Node) {
CharacterLiteral::print(Node->getValue(), Node->getKind(), OS);
}
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1360,6 +1360,11 @@ void StmtProfiler::VisitPredefinedExpr(const PredefinedExpr *S) {
ID.AddInteger(llvm::to_underlying(S->getIdentKind()));
}

void StmtProfiler::VisitOpenACCAsteriskSizeExpr(
const OpenACCAsteriskSizeExpr *S) {
VisitExpr(S);
}

void StmtProfiler::VisitIntegerLiteral(const IntegerLiteral *S) {
VisitExpr(S);
S->getValue().Profile(ID);
Expand Down Expand Up @@ -2552,6 +2557,11 @@ void OpenACCClauseProfiler::VisitNumGangsClause(
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitTileClause(const OpenACCTileClause &Clause) {
for (auto *E : Clause.getSizeExprs())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitNumWorkersClause(
const OpenACCNumWorkersClause &Clause) {
assert(Clause.hasIntExpr() && "num_workers clause requires a valid int expr");
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,11 @@ void TextNodeDumper::Visit(const OMPClause *C) {
OS << " <implicit>";
}

void TextNodeDumper::VisitOpenACCAsteriskSizeExpr(
const OpenACCAsteriskSizeExpr *E) {
// Nothing to do here, only location exists, and that is printed elsewhere.
}

void TextNodeDumper::Visit(const OpenACCClause *C) {
if (!C) {
ColorScope Color(OS, ShowColors, NullColor);
Expand Down Expand Up @@ -414,6 +419,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::Private:
case OpenACCClauseKind::Self:
case OpenACCClauseKind::Seq:
case OpenACCClauseKind::Tile:
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
74 changes: 33 additions & 41 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5117,8 +5117,6 @@ FunctionEffect::Kind FunctionEffect::oppositeKind() const {
return Kind::Allocating;
case Kind::Allocating:
return Kind::NonAllocating;
case Kind::None:
return Kind::None;
}
llvm_unreachable("unknown effect kind");
}
Expand All @@ -5133,53 +5131,41 @@ StringRef FunctionEffect::name() const {
return "blocking";
case Kind::Allocating:
return "allocating";
case Kind::None:
return "(none)";
}
llvm_unreachable("unknown effect kind");
}

bool FunctionEffect::canInferOnFunction(const Decl &Callee) const {
std::optional<FunctionEffect> FunctionEffect::effectProhibitingInference(
const Decl &Callee, FunctionEffectKindSet CalleeFX) const {
switch (kind()) {
case Kind::NonAllocating:
case Kind::NonBlocking: {
FunctionEffectsRef CalleeFX;
if (auto *FD = Callee.getAsFunction())
CalleeFX = FD->getFunctionEffects();
else if (auto *BD = dyn_cast<BlockDecl>(&Callee))
CalleeFX = BD->getFunctionEffects();
else
return false;
for (const FunctionEffectWithCondition &CalleeEC : CalleeFX) {
for (FunctionEffect Effect : CalleeFX) {
// nonblocking/nonallocating cannot call allocating.
if (CalleeEC.Effect.kind() == Kind::Allocating)
return false;
if (Effect.kind() == Kind::Allocating)
return Effect;
// nonblocking cannot call blocking.
if (kind() == Kind::NonBlocking &&
CalleeEC.Effect.kind() == Kind::Blocking)
return false;
if (kind() == Kind::NonBlocking && Effect.kind() == Kind::Blocking)
return Effect;
}
return true;
return std::nullopt;
}

case Kind::Allocating:
case Kind::Blocking:
return false;

case Kind::None:
assert(0 && "canInferOnFunction with None");
assert(0 && "effectProhibitingInference with non-inferable effect kind");
break;
}
llvm_unreachable("unknown effect kind");
}

bool FunctionEffect::shouldDiagnoseFunctionCall(
bool Direct, ArrayRef<FunctionEffect> CalleeFX) const {
bool Direct, FunctionEffectKindSet CalleeFX) const {
switch (kind()) {
case Kind::NonAllocating:
case Kind::NonBlocking: {
const Kind CallerKind = kind();
for (const auto &Effect : CalleeFX) {
for (FunctionEffect Effect : CalleeFX) {
const Kind EK = Effect.kind();
// Does callee have same or stronger constraint?
if (EK == CallerKind ||
Expand All @@ -5192,9 +5178,6 @@ bool FunctionEffect::shouldDiagnoseFunctionCall(
case Kind::Allocating:
case Kind::Blocking:
return false;
case Kind::None:
assert(0 && "shouldDiagnoseFunctionCall with None");
break;
}
llvm_unreachable("unknown effect kind");
}
Expand Down Expand Up @@ -5300,28 +5283,37 @@ FunctionEffectSet FunctionEffectSet::getUnion(FunctionEffectsRef LHS,
return Combined;
}

namespace clang {

raw_ostream &operator<<(raw_ostream &OS,
const FunctionEffectWithCondition &CFE) {
OS << CFE.Effect.name();
if (Expr *E = CFE.Cond.getCondition()) {
OS << '(';
E->dump();
OS << ')';
}
return OS;
}

} // namespace clang

LLVM_DUMP_METHOD void FunctionEffectsRef::dump(llvm::raw_ostream &OS) const {
OS << "Effects{";
bool First = true;
for (const auto &CFE : *this) {
if (!First)
OS << ", ";
else
First = false;
OS << CFE.Effect.name();
if (Expr *E = CFE.Cond.getCondition()) {
OS << '(';
E->dump();
OS << ')';
}
}
llvm::interleaveComma(*this, OS);
OS << "}";
}

LLVM_DUMP_METHOD void FunctionEffectSet::dump(llvm::raw_ostream &OS) const {
FunctionEffectsRef(*this).dump(OS);
}

LLVM_DUMP_METHOD void FunctionEffectKindSet::dump(llvm::raw_ostream &OS) const {
OS << "Effects{";
llvm::interleaveComma(*this, OS);
OS << "}";
}

FunctionEffectsRef
FunctionEffectsRef::create(ArrayRef<FunctionEffect> FX,
ArrayRef<EffectConditionExpr> Conds) {
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Analysis/ExprMutationAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,11 @@ ExprMutationAnalyzer::Analyzer::findPointeeMutation(const Decl *Dec) {
const Stmt *ExprMutationAnalyzer::Analyzer::findMutationMemoized(
const Expr *Exp, llvm::ArrayRef<MutationFinder> Finders,
Memoized::ResultMap &MemoizedResults) {
const auto Memoized = MemoizedResults.find(Exp);
if (Memoized != MemoizedResults.end())
auto [Memoized, Inserted] = MemoizedResults.try_emplace(Exp);
if (!Inserted)
return Memoized->second;

// Assume Exp is not mutated before analyzing Exp.
MemoizedResults[Exp] = nullptr;
if (isUnevaluated(Exp))
return nullptr;

Expand Down
12 changes: 5 additions & 7 deletions clang/lib/Basic/TargetID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,9 @@ parseTargetIDWithFormatCheckingOnly(llvm::StringRef TargetID,
if (Sign != '+' && Sign != '-')
return std::nullopt;
bool IsOn = Sign == '+';
auto Loc = FeatureMap->find(Feature);
// Each feature can only show up at most once in target ID.
if (Loc != FeatureMap->end())
if (!FeatureMap->try_emplace(Feature, IsOn).second)
return std::nullopt;
(*FeatureMap)[Feature] = IsOn;
Features = Splits.second;
}
return Processor;
Expand Down Expand Up @@ -147,15 +145,15 @@ getConflictTargetIDCombination(const std::set<llvm::StringRef> &TargetIDs) {
struct Info {
llvm::StringRef TargetID;
llvm::StringMap<bool> Features;
Info(llvm::StringRef TargetID, const llvm::StringMap<bool> &Features)
: TargetID(TargetID), Features(Features) {}
};
llvm::StringMap<Info> FeatureMap;
for (auto &&ID : TargetIDs) {
llvm::StringMap<bool> Features;
llvm::StringRef Proc = *parseTargetIDWithFormatCheckingOnly(ID, &Features);
auto Loc = FeatureMap.find(Proc);
if (Loc == FeatureMap.end())
FeatureMap[Proc] = Info{ID, Features};
else {
auto [Loc, Inserted] = FeatureMap.try_emplace(Proc, ID, Features);
if (!Inserted) {
auto &ExistingFeatures = Loc->second.Features;
if (llvm::any_of(Features, [&](auto &F) {
return ExistingFeatures.count(F.first()) == 0;
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,12 @@ void AArch64TargetInfo::getTargetDefinesARMV95A(const LangOptions &Opts,
getTargetDefinesARMV94A(Opts, Builder);
}

void AArch64TargetInfo::getTargetDefinesARMV96A(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Armv9.6-A does not have a v8.* equivalent, but is a superset of v9.5-A.
getTargetDefinesARMV95A(Opts, Builder);
}

void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
// Target identification.
Expand Down Expand Up @@ -657,6 +663,8 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
getTargetDefinesARMV94A(Opts, Builder);
else if (*ArchInfo == llvm::AArch64::ARMV9_5A)
getTargetDefinesARMV95A(Opts, Builder);
else if (*ArchInfo == llvm::AArch64::ARMV9_6A)
getTargetDefinesARMV96A(Opts, Builder);

// All of the __sync_(bool|val)_compare_and_swap_(1|2|4|8|16) builtins work.
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Expand Down Expand Up @@ -1044,6 +1052,9 @@ bool AArch64TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
if (Feature == "+v9.5a" &&
ArchInfo->Version < llvm::AArch64::ARMV9_5A.Version)
ArchInfo = &llvm::AArch64::ARMV9_5A;
if (Feature == "+v9.6a" &&
ArchInfo->Version < llvm::AArch64::ARMV9_6A.Version)
ArchInfo = &llvm::AArch64::ARMV9_6A;
if (Feature == "+v8r")
ArchInfo = &llvm::AArch64::ARMV8R;
if (Feature == "+fullfp16") {
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/AArch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ class LLVM_LIBRARY_VISIBILITY AArch64TargetInfo : public TargetInfo {
MacroBuilder &Builder) const;
void getTargetDefinesARMV95A(const LangOptions &Opts,
MacroBuilder &Builder) const;
void getTargetDefinesARMV96A(const LangOptions &Opts,
MacroBuilder &Builder) const;
void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,8 @@ StringRef ARMTargetInfo::getCPUAttr() const {
return "9_4A";
case llvm::ARM::ArchKind::ARMV9_5A:
return "9_5A";
case llvm::ARM::ArchKind::ARMV9_6A:
return "9_6A";
case llvm::ARM::ArchKind::ARMV8MBaseline:
return "8M_BASE";
case llvm::ARM::ArchKind::ARMV8MMainline:
Expand Down Expand Up @@ -891,6 +893,7 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
case llvm::ARM::ArchKind::ARMV9_3A:
case llvm::ARM::ArchKind::ARMV9_4A:
case llvm::ARM::ArchKind::ARMV9_5A:
case llvm::ARM::ArchKind::ARMV9_6A:
// Filter __arm_cdp, __arm_ldcl, __arm_stcl in arm_acle.h
FeatureCoprocBF = FEATURE_COPROC_B1 | FEATURE_COPROC_B3;
break;
Expand Down Expand Up @@ -1060,6 +1063,7 @@ void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
case llvm::ARM::ArchKind::ARMV9_3A:
case llvm::ARM::ArchKind::ARMV9_4A:
case llvm::ARM::ArchKind::ARMV9_5A:
case llvm::ARM::ArchKind::ARMV9_6A:
getTargetDefinesARMV83A(Opts, Builder);
break;
}
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1321,10 +1321,10 @@ static void runThinLTOBackend(
Conf.CGFileType = getCodeGenFileType(Action);
break;
}
if (Error E =
thinBackend(Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
/* ModuleMap */ nullptr, CGOpts.CmdArgs)) {
if (Error E = thinBackend(
Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
/* ModuleMap */ nullptr, Conf.CodeGenOnly, CGOpts.CmdArgs)) {
handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';
});
Expand Down
24 changes: 24 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18667,6 +18667,21 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
IsUnsigned ? Intrinsic::dx_uclamp : Intrinsic::dx_clamp,
ArrayRef<Value *>{OpX, OpMin, OpMax}, nullptr, "dx.clamp");
}
case Builtin::BI__builtin_hlsl_cross: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
E->getArg(1)->getType()->hasFloatingRepresentation() &&
"cross operands must have a float representation");
// make sure each vector has exactly 3 elements
assert(
E->getArg(0)->getType()->getAs<VectorType>()->getNumElements() == 3 &&
E->getArg(1)->getType()->getAs<VectorType>()->getNumElements() == 3 &&
"input vectors must have 3 elements each");
return Builder.CreateIntrinsic(
/*ReturnType=*/Op0->getType(), CGM.getHLSLRuntime().getCrossIntrinsic(),
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.cross");
}
case Builtin::BI__builtin_hlsl_dot: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
Expand Down Expand Up @@ -18877,6 +18892,15 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
retType, CGM.getHLSLRuntime().getSignIntrinsic(),
ArrayRef<Value *>{Op0}, nullptr, "hlsl.sign");
}
case Builtin::BI__builtin_hlsl_elementwise_radians: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
"radians operand must have a float representation");
return Builder.CreateIntrinsic(
/*ReturnType=*/Op0->getType(),
CGM.getHLSLRuntime().getRadiansIntrinsic(), ArrayRef<Value *>{Op0},
nullptr, "hlsl.radians");
}
}
return nullptr;
}
Expand Down
16 changes: 7 additions & 9 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,8 @@ class StructAccessBase
return Visit(E->getBase());
}
const Expr *VisitCastExpr(const CastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue)
return E;
return Visit(E->getSubExpr());
}
const Expr *VisitParenExpr(const ParenExpr *E) {
Expand Down Expand Up @@ -1161,19 +1163,15 @@ llvm::Value *CodeGenFunction::EmitLoadOfCountedByField(
return nullptr;

llvm::Value *Res = nullptr;
if (const auto *DRE = dyn_cast<DeclRefExpr>(StructBase)) {
Res = EmitDeclRefLValue(DRE).getPointer(*this);
Res = Builder.CreateAlignedLoad(ConvertType(DRE->getType()), Res,
getPointerAlign(), "dre.load");
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(StructBase)) {
LValue LV = EmitMemberExpr(ME);
Address Addr = LV.getAddress();
Res = Addr.emitRawPointer(*this);
} else if (StructBase->getType()->isPointerType()) {
if (StructBase->getType()->isPointerType()) {
LValueBaseInfo BaseInfo;
TBAAAccessInfo TBAAInfo;
Address Addr = EmitPointerWithAlignment(StructBase, &BaseInfo, &TBAAInfo);
Res = Addr.emitRawPointer(*this);
} else if (StructBase->isLValue()) {
LValue LV = EmitLValue(StructBase);
Address Addr = LV.getAddress();
Res = Addr.emitRawPointer(*this);
} else {
return nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace llvm {
extern cl::opt<bool> EnableSingleByteCoverage;
} // namespace llvm

namespace {
namespace {
class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
CodeGenFunction &CGF;
CGBuilderTy &Builder;
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,10 @@ class ScalarExprEmitter
return CGF.getOrCreateOpaqueRValueMapping(E).getScalarVal();
}

Value *VisitOpenACCAsteriskSizeExpr(OpenACCAsteriskSizeExpr *E) {
llvm_unreachable("Codegen for this isn't defined/implemented");
}

// l-values.
Value *VisitDeclRefExpr(DeclRefExpr *E) {
if (CodeGenFunction::ConstantEmission Constant = CGF.tryEmitAsConstant(E))
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class CGHLSLRuntime {

GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
GENERATE_HLSL_INTRINSIC_FUNCTION(Cross, cross)
GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)
GENERATE_HLSL_INTRINSIC_FUNCTION(Length, length)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
Expand All @@ -82,6 +83,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate)
GENERATE_HLSL_INTRINSIC_FUNCTION(Sign, sign)
GENERATE_HLSL_INTRINSIC_FUNCTION(Step, step)
GENERATE_HLSL_INTRINSIC_FUNCTION(Radians, radians)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
Expand Down
14 changes: 8 additions & 6 deletions clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,10 +801,12 @@ void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
}

void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
const Stmt *Else = S.getElse();

// The else branch of a consteval if statement is always the only branch that
// can be runtime evaluated.
if (S.isConsteval()) {
const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : S.getElse();
const Stmt *Executed = S.isNegatedConsteval() ? S.getThen() : Else;
if (Executed) {
RunCleanupsScope ExecutedScope(*this);
EmitStmt(Executed);
Expand All @@ -830,8 +832,8 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
S.isConstexpr())) {
// Figure out which block (then or else) is executed.
const Stmt *Executed = S.getThen();
const Stmt *Skipped = S.getElse();
if (!CondConstant) // Condition false?
const Stmt *Skipped = Else;
if (!CondConstant) // Condition false?
std::swap(Executed, Skipped);

// If the skipped block has no labels in it, just emit the executed block.
Expand All @@ -852,7 +854,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
llvm::BasicBlock *ThenBlock = createBasicBlock("if.then");
llvm::BasicBlock *ContBlock = createBasicBlock("if.end");
llvm::BasicBlock *ElseBlock = ContBlock;
if (S.getElse())
if (Else)
ElseBlock = createBasicBlock("if.else");

// Prefer the PGO based weights over the likelihood attribute.
Expand All @@ -870,7 +872,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
uint64_t ThenCount = getProfileCount(S.getThen());
if (!ThenCount && !getCurrentProfileCount() &&
CGM.getCodeGenOpts().OptimizationLevel)
LH = Stmt::getLikelihood(S.getThen(), S.getElse());
LH = Stmt::getLikelihood(S.getThen(), Else);

// When measuring MC/DC, always fully evaluate the condition up front using
// EvaluateExprAsBool() so that the test vector bitmap can be updated prior to
Expand Down Expand Up @@ -898,7 +900,7 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
EmitBranch(ContBlock);

// Emit the 'else' code if present.
if (const Stmt *Else = S.getElse()) {
if (Else) {
{
// There is no need to emit line number for an unconditional branch.
auto NL = ApplyDebugLocation::CreateEmpty(*this);
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
for (const FunctionEffectWithCondition &Fe : FD->getFunctionEffects()) {
if (Fe.Effect.kind() == FunctionEffect::Kind::NonBlocking)
Fn->addFnAttr(llvm::Attribute::SanitizeRealtime);
else if (Fe.Effect.kind() == FunctionEffect::Kind::Blocking)
Fn->addFnAttr(llvm::Attribute::SanitizeRealtimeUnsafe);
}

// Apply fuzzing attribute to the function.
Expand Down Expand Up @@ -1762,6 +1764,8 @@ void CodeGenFunction::EmitBranchToCounterBlock(
if (!InstrumentRegions || !isInstrumentedCondition(Cond))
return EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount, LH);

const Stmt *CntrStmt = (CntrIdx ? CntrIdx : Cond);

llvm::BasicBlock *ThenBlock = nullptr;
llvm::BasicBlock *ElseBlock = nullptr;
llvm::BasicBlock *NextBlock = nullptr;
Expand Down Expand Up @@ -1814,7 +1818,7 @@ void CodeGenFunction::EmitBranchToCounterBlock(
EmitBlock(CounterIncrBlock);

// Increment corresponding counter; if index not provided, use Cond as index.
incrementProfileCounter(CntrIdx ? CntrIdx : Cond);
incrementProfileCounter(CntrStmt);

// Go to the next block.
EmitBranch(NextBlock);
Expand Down
14 changes: 6 additions & 8 deletions clang/lib/CodeGen/CodeGenPGO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1206,14 +1206,12 @@ void CodeGenPGO::emitCounterSetOrIncrement(CGBuilderTy &Builder, const Stmt *S,
if (llvm::EnableSingleByteCoverage)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_cover),
ArrayRef(Args, 4));
else {
if (!StepV)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
ArrayRef(Args, 4));
else
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), Args);
}
else if (!StepV)
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
ArrayRef(Args, 4));
else
Builder.CreateCall(
CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), Args);
}

bool CodeGenPGO::canEmitMCDCCoverage(const CGBuilderTy &Builder) {
Expand Down
51 changes: 21 additions & 30 deletions clang/lib/CodeGen/MicrosoftCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ class MicrosoftCXXABI : public CGCXXABI {
CGM.IntTy,
CGM.IntTy,
CGM.IntTy,
getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()),
getImageRelativeType(CGM.UnqualPtrTy),
};
BaseClassDescriptorType = llvm::StructType::create(
CGM.getLLVMContext(), FieldTypes, "rtti.BaseClassDescriptor");
Expand All @@ -531,13 +531,8 @@ class MicrosoftCXXABI : public CGCXXABI {
// Forward-declare RTTIClassHierarchyDescriptor to break a cycle.
ClassHierarchyDescriptorType = llvm::StructType::create(
CGM.getLLVMContext(), "rtti.ClassHierarchyDescriptor");
llvm::Type *FieldTypes[] = {
CGM.IntTy,
CGM.IntTy,
CGM.IntTy,
getImageRelativeType(
getBaseClassDescriptorType()->getPointerTo()->getPointerTo()),
};
llvm::Type *FieldTypes[] = {CGM.IntTy, CGM.IntTy, CGM.IntTy,
getImageRelativeType(CGM.UnqualPtrTy)};
ClassHierarchyDescriptorType->setBody(FieldTypes);
return ClassHierarchyDescriptorType;
}
Expand All @@ -552,7 +547,7 @@ class MicrosoftCXXABI : public CGCXXABI {
CGM.IntTy,
CGM.IntTy,
getImageRelativeType(CGM.Int8PtrTy),
getImageRelativeType(getClassHierarchyDescriptorType()->getPointerTo()),
getImageRelativeType(CGM.UnqualPtrTy),
getImageRelativeType(CompleteObjectLocatorType),
};
llvm::ArrayRef<llvm::Type *> FieldTypesRef(FieldTypes);
Expand Down Expand Up @@ -749,8 +744,7 @@ class MicrosoftCXXABI : public CGCXXABI {

llvm::SmallString<23> CTATypeName("eh.CatchableTypeArray.");
CTATypeName += llvm::utostr(NumEntries);
llvm::Type *CTType =
getImageRelativeType(getCatchableTypeType()->getPointerTo());
llvm::Type *CTType = getImageRelativeType(CGM.UnqualPtrTy);
llvm::Type *FieldTypes[] = {
CGM.IntTy, // NumEntries
llvm::ArrayType::get(CTType, NumEntries) // CatchableTypes
Expand All @@ -777,7 +771,7 @@ class MicrosoftCXXABI : public CGCXXABI {
llvm::FunctionCallee getThrowFn() {
// _CxxThrowException is passed an exception object and a ThrowInfo object
// which describes the exception.
llvm::Type *Args[] = {CGM.Int8PtrTy, getThrowInfoType()->getPointerTo()};
llvm::Type *Args[] = {CGM.Int8PtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false);
llvm::FunctionCallee Throw =
Expand Down Expand Up @@ -909,9 +903,8 @@ void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
}

void MicrosoftCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
llvm::Value *Args[] = {
llvm::ConstantPointerNull::get(CGM.Int8PtrTy),
llvm::ConstantPointerNull::get(getThrowInfoType()->getPointerTo())};
llvm::Value *Args[] = {llvm::ConstantPointerNull::get(CGM.Int8PtrTy),
llvm::ConstantPointerNull::get(CGM.UnqualPtrTy)};
llvm::FunctionCallee Fn = getThrowFn();
if (isNoReturn)
CGF.EmitNoreturnRuntimeCallOrInvoke(Fn, Args);
Expand Down Expand Up @@ -1958,13 +1951,13 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
SourceLocation Loc) {
CGBuilderTy &Builder = CGF.Builder;

Ty = Ty->getPointerTo();
Ty = CGF.UnqualPtrTy;
Address VPtr =
adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);

auto *MethodDecl = cast<CXXMethodDecl>(GD.getDecl());
llvm::Value *VTable = CGF.GetVTablePtr(VPtr, Ty->getPointerTo(),
MethodDecl->getParent());
llvm::Value *VTable =
CGF.GetVTablePtr(VPtr, CGF.UnqualPtrTy, MethodDecl->getParent());

MicrosoftVTableContext &VFTContext = CGM.getMicrosoftVTableContext();
MethodVFTableLocation ML = VFTContext.getMethodVFTableLocation(GD);
Expand Down Expand Up @@ -2125,9 +2118,9 @@ MicrosoftCXXABI::EmitVirtualMemPtrThunk(const CXXMethodDecl *MD,

// Load the vfptr and then callee from the vftable. The callee should have
// adjusted 'this' so that the vfptr is at offset zero.
llvm::Type *ThunkPtrTy = ThunkTy->getPointerTo();
llvm::Value *VTable = CGF.GetVTablePtr(
getThisAddress(CGF), ThunkPtrTy->getPointerTo(), MD->getParent());
llvm::Type *ThunkPtrTy = CGF.UnqualPtrTy;
llvm::Value *VTable =
CGF.GetVTablePtr(getThisAddress(CGF), CGF.UnqualPtrTy, MD->getParent());

llvm::Value *VFuncPtr = CGF.Builder.CreateConstInBoundsGEP1_64(
ThunkPtrTy, VTable, ML.Index, "vfn");
Expand Down Expand Up @@ -2551,7 +2544,7 @@ static ConstantAddress getInitThreadEpochPtr(CodeGenModule &CGM) {
static llvm::FunctionCallee getInitThreadHeaderFn(CodeGenModule &CGM) {
llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
CGM.IntTy->getPointerTo(), /*isVarArg=*/false);
CGM.UnqualPtrTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(
FTy, "_Init_thread_header",
llvm::AttributeList::get(CGM.getLLVMContext(),
Expand All @@ -2563,7 +2556,7 @@ static llvm::FunctionCallee getInitThreadHeaderFn(CodeGenModule &CGM) {
static llvm::FunctionCallee getInitThreadFooterFn(CodeGenModule &CGM) {
llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
CGM.IntTy->getPointerTo(), /*isVarArg=*/false);
CGM.UnqualPtrTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(
FTy, "_Init_thread_footer",
llvm::AttributeList::get(CGM.getLLVMContext(),
Expand All @@ -2575,7 +2568,7 @@ static llvm::FunctionCallee getInitThreadFooterFn(CodeGenModule &CGM) {
static llvm::FunctionCallee getInitThreadAbortFn(CodeGenModule &CGM) {
llvm::FunctionType *FTy =
llvm::FunctionType::get(llvm::Type::getVoidTy(CGM.getLLVMContext()),
CGM.IntTy->getPointerTo(), /*isVarArg=*/false);
CGM.UnqualPtrTy, /*isVarArg=*/false);
return CGM.CreateRuntimeFunction(
FTy, "_Init_thread_abort",
llvm::AttributeList::get(CGM.getLLVMContext(),
Expand Down Expand Up @@ -3157,8 +3150,8 @@ MicrosoftCXXABI::GetVBaseOffsetFromVBPtr(CodeGenFunction &CGF,
VBPtrAlign = CGF.getPointerAlign();
}

llvm::Value *VBTable = Builder.CreateAlignedLoad(
CGM.Int32Ty->getPointerTo(0), VBPtr, VBPtrAlign, "vbtable");
llvm::Value *VBTable =
Builder.CreateAlignedLoad(CGM.UnqualPtrTy, VBPtr, VBPtrAlign, "vbtable");

// Translate from byte offset to table index. It improves analyzability.
llvm::Value *VBTableIndex = Builder.CreateAShr(
Expand Down Expand Up @@ -3813,8 +3806,7 @@ MSRTTIBuilder::getBaseClassArray(SmallVectorImpl<MSRTTIClass> &Classes) {
// mode) bytes of padding. We provide a pointer sized amount of padding by
// adding +1 to Classes.size(). The sections have pointer alignment and are
// marked pick-any so it shouldn't matter.
llvm::Type *PtrType = ABI.getImageRelativeType(
ABI.getBaseClassDescriptorType()->getPointerTo());
llvm::Type *PtrType = ABI.getImageRelativeType(CGM.UnqualPtrTy);
auto *ArrType = llvm::ArrayType::get(PtrType, Classes.size() + 1);
auto *BCA =
new llvm::GlobalVariable(Module, ArrType,
Expand Down Expand Up @@ -4360,8 +4352,7 @@ llvm::GlobalVariable *MicrosoftCXXABI::getCatchableTypeArray(QualType T) {
CatchableTypes.insert(getCatchableType(getContext().VoidPtrTy));

uint32_t NumEntries = CatchableTypes.size();
llvm::Type *CTType =
getImageRelativeType(getCatchableTypeType()->getPointerTo());
llvm::Type *CTType = getImageRelativeType(CGM.UnqualPtrTy);
llvm::ArrayType *AT = llvm::ArrayType::get(CTType, NumEntries);
llvm::StructType *CTAType = getCatchableTypeArrayType(NumEntries);
llvm::Constant *Fields[] = {
Expand Down
31 changes: 20 additions & 11 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,14 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
}

#if defined(CLANG_CONFIG_FILE_SYSTEM_DIR)
SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;
if (llvm::sys::path::is_absolute(CLANG_CONFIG_FILE_SYSTEM_DIR)) {
SystemConfigDir = CLANG_CONFIG_FILE_SYSTEM_DIR;
} else {
SmallString<128> configFileDir(Dir);
llvm::sys::path::append(configFileDir, CLANG_CONFIG_FILE_SYSTEM_DIR);
llvm::sys::path::remove_dots(configFileDir, true);
SystemConfigDir = static_cast<std::string>(configFileDir);
}
#endif
#if defined(CLANG_CONFIG_FILE_USER_DIR)
{
Expand Down Expand Up @@ -977,8 +984,9 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
} else
TC = &getToolChain(C.getInputArgs(), TT);
C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
if (DerivedArchs.contains(TT.getTriple()))
KnownArchs[TC] = DerivedArchs[TT.getTriple()];
auto It = DerivedArchs.find(TT.getTriple());
if (It != DerivedArchs.end())
KnownArchs[TC] = It->second;
}
}
} else if (C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ)) {
Expand Down Expand Up @@ -2314,7 +2322,7 @@ bool Driver::HandleImmediateArgs(Compilation &C) {

if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
for (const Multilib &Multilib : TC.getMultilibs())
if (!Multilib.isFatalError())
if (!Multilib.isError())
llvm::outs() << Multilib << "\n";
return false;
}
Expand Down Expand Up @@ -3742,11 +3750,10 @@ class OffloadingActionBuilder final {
void recordHostAction(Action *HostAction, const Arg *InputArg) {
assert(HostAction && "Invalid host action");
assert(InputArg && "Invalid input argument");
auto Loc = HostActionToInputArgMap.find(HostAction);
if (Loc == HostActionToInputArgMap.end())
HostActionToInputArgMap[HostAction] = InputArg;
assert(HostActionToInputArgMap[HostAction] == InputArg &&
auto Loc = HostActionToInputArgMap.try_emplace(HostAction, InputArg).first;
assert(Loc->second == InputArg &&
"host action mapped to multiple input arguments");
(void)Loc;
}

/// Generate an action that adds device dependences (if any) to a host action.
Expand Down Expand Up @@ -4022,7 +4029,8 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
// Emitting LLVM while linking disabled except in HIPAMD Toolchain
if (Args.hasArg(options::OPT_emit_llvm) && !Args.hasArg(options::OPT_hip_link))
Diag(clang::diag::err_drv_emit_llvm_link);
if (IsCLMode() && LTOMode != LTOK_None &&
if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() &&
LTOMode != LTOK_None &&
!Args.getLastArgValue(options::OPT_fuse_ld_EQ)
.equals_insensitive("lld"))
Diag(clang::diag::err_drv_lto_without_lld);
Expand Down Expand Up @@ -5573,8 +5581,9 @@ InputInfoList Driver::BuildJobsForActionNoCache(
std::pair<const Action *, std::string> ActionTC = {
OA->getHostDependence(),
GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
if (CachedResults.find(ActionTC) != CachedResults.end()) {
InputInfoList Inputs = CachedResults[ActionTC];
auto It = CachedResults.find(ActionTC);
if (It != CachedResults.end()) {
InputInfoList Inputs = It->second;
Inputs.append(OffloadDependencesInputInfo);
return Inputs;
}
Expand Down
36 changes: 17 additions & 19 deletions clang/lib/Driver/Multilib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ using namespace llvm::sys;

Multilib::Multilib(StringRef GCCSuffix, StringRef OSSuffix,
StringRef IncludeSuffix, const flags_list &Flags,
StringRef ExclusiveGroup,
std::optional<StringRef> FatalError)
StringRef ExclusiveGroup, std::optional<StringRef> Error)
: GCCSuffix(GCCSuffix), OSSuffix(OSSuffix), IncludeSuffix(IncludeSuffix),
Flags(Flags), ExclusiveGroup(ExclusiveGroup), FatalError(FatalError) {
Flags(Flags), ExclusiveGroup(ExclusiveGroup), Error(Error) {
assert(GCCSuffix.empty() ||
(StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1));
assert(OSSuffix.empty() ||
Expand Down Expand Up @@ -100,6 +99,7 @@ bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
llvm::SmallVectorImpl<Multilib> &Selected) const {
llvm::StringSet<> FlagSet(expandFlags(Flags));
Selected.clear();
bool AnyErrors = false;

// Decide which multilibs we're going to select at all.
llvm::DenseSet<StringRef> ExclusiveGroupsSelected;
Expand All @@ -123,13 +123,11 @@ bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
continue;
}

// If this multilib is actually a placeholder containing a fatal
// error message written by the multilib.yaml author, display that
// error message, and return failure.
if (M.isFatalError()) {
D.Diag(clang::diag::err_drv_multilib_custom_error) << M.getFatalError();
return false;
}
// If this multilib is actually a placeholder containing an error message
// written by the multilib.yaml author, then set a flag that will cause a
// failure return. Our caller will display the error message.
if (M.isError())
AnyErrors = true;

// Select this multilib.
Selected.push_back(M);
Expand All @@ -139,7 +137,7 @@ bool MultilibSet::select(const Driver &D, const Multilib::flags_list &Flags,
// round.
std::reverse(Selected.begin(), Selected.end());

return !Selected.empty();
return !AnyErrors && !Selected.empty();
}

llvm::StringSet<>
Expand Down Expand Up @@ -173,7 +171,7 @@ static const VersionTuple MultilibVersionCurrent(1, 0);

struct MultilibSerialization {
std::string Dir; // if this record successfully selects a library dir
std::string FatalError; // if this record reports a fatal error message
std::string Error; // if this record reports a fatal error message
std::vector<std::string> Flags;
std::string Group;
};
Expand Down Expand Up @@ -217,15 +215,15 @@ struct MultilibSetSerialization {
template <> struct llvm::yaml::MappingTraits<MultilibSerialization> {
static void mapping(llvm::yaml::IO &io, MultilibSerialization &V) {
io.mapOptional("Dir", V.Dir);
io.mapOptional("FatalError", V.FatalError);
io.mapOptional("Error", V.Error);
io.mapRequired("Flags", V.Flags);
io.mapOptional("Group", V.Group);
}
static std::string validate(IO &io, MultilibSerialization &V) {
if (V.Dir.empty() && V.FatalError.empty())
return "one of the 'Dir' and 'FatalError' keys must be specified";
if (!V.Dir.empty() && !V.FatalError.empty())
return "the 'Dir' and 'FatalError' keys may not both be specified";
if (V.Dir.empty() && V.Error.empty())
return "one of the 'Dir' and 'Error' keys must be specified";
if (!V.Dir.empty() && !V.Error.empty())
return "the 'Dir' and 'Error' keys may not both be specified";
if (StringRef(V.Dir).starts_with("/"))
return "paths must be relative but \"" + V.Dir + "\" starts with \"/\"";
return std::string{};
Expand Down Expand Up @@ -311,8 +309,8 @@ MultilibSet::parseYaml(llvm::MemoryBufferRef Input,
multilib_list Multilibs;
Multilibs.reserve(MS.Multilibs.size());
for (const auto &M : MS.Multilibs) {
if (!M.FatalError.empty()) {
Multilibs.emplace_back("", "", "", M.Flags, M.Group, M.FatalError);
if (!M.Error.empty()) {
Multilibs.emplace_back("", "", "", M.Flags, M.Group, M.Error);
} else {
std::string Dir;
if (M.Dir != ".")
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ static void getAArch64MultilibFlags(const Driver &D,
if (BranchProtectionArg) {
Result.push_back(BranchProtectionArg->getAsString(Args));
}

const Arg *ABIArg = Args.getLastArgNoClaim(options::OPT_mabi_EQ);
if (ABIArg) {
Result.push_back(ABIArg->getAsString(Args));
}
}

static void getARMMultilibFlags(const Driver &D,
Expand Down
87 changes: 58 additions & 29 deletions clang/lib/Driver/ToolChains/BareMetal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,23 @@ static bool findRISCVMultilibs(const Driver &D,
return false;
}

static std::string computeBaseSysRoot(const Driver &D, bool IncludeTriple) {
if (!D.SysRoot.empty())
return D.SysRoot;

SmallString<128> SysRootDir(D.Dir);
llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes");

if (IncludeTriple)
llvm::sys::path::append(SysRootDir, D.getTargetTriple());

return std::string(SysRootDir);
}

BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args)
: ToolChain(D, Triple, Args) {
: ToolChain(D, Triple, Args),
SysRoot(computeBaseSysRoot(D, /*IncludeTriple=*/true)) {
getProgramPaths().push_back(getDriver().Dir);

findMultilibs(D, Triple, Args);
Expand Down Expand Up @@ -186,45 +200,62 @@ static void findMultilibsFromYAML(const ToolChain &TC, const Driver &D,
return;
D.Diag(clang::diag::warn_drv_missing_multilib) << llvm::join(Flags, " ");
std::stringstream ss;

// If multilib selection didn't complete successfully, report a list
// of all the configurations the user could have provided.
for (const Multilib &Multilib : Result.Multilibs)
if (!Multilib.isFatalError())
if (!Multilib.isError())
ss << "\n" << llvm::join(Multilib.flags(), " ");
D.Diag(clang::diag::note_drv_available_multilibs) << ss.str();

// Now report any custom error messages requested by the YAML. We do
// this after displaying the list of available multilibs, because
// that list is probably large, and (in interactive use) risks
// scrolling the useful error message off the top of the user's
// terminal.
for (const Multilib &Multilib : Result.SelectedMultilibs)
if (Multilib.isError())
D.Diag(clang::diag::err_drv_multilib_custom_error)
<< Multilib.getErrorMessage();

// If there was an error, clear the SelectedMultilibs vector, in
// case it contains partial data.
Result.SelectedMultilibs.clear();
}

static constexpr llvm::StringLiteral MultilibFilename = "multilib.yaml";

// Get the sysroot, before multilib takes effect.
static std::string computeBaseSysRoot(const Driver &D,
const llvm::Triple &Triple) {
if (!D.SysRoot.empty())
return D.SysRoot;

SmallString<128> SysRootDir(D.Dir);
llvm::sys::path::append(SysRootDir, "..", "lib", "clang-runtimes");

SmallString<128> MultilibPath(SysRootDir);
llvm::sys::path::append(MultilibPath, MultilibFilename);

// New behaviour: if multilib.yaml is found then use clang-runtimes as the
// sysroot.
if (D.getVFS().exists(MultilibPath))
return std::string(SysRootDir);

// Otherwise fall back to the old behaviour of appending the target triple.
llvm::sys::path::append(SysRootDir, D.getTargetTriple());
return std::string(SysRootDir);
static std::optional<llvm::SmallString<128>>
getMultilibConfigPath(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args) {
llvm::SmallString<128> MultilibPath;
if (Arg *ConfigFileArg = Args.getLastArg(options::OPT_multi_lib_config)) {
MultilibPath = ConfigFileArg->getValue();
if (!D.getVFS().exists(MultilibPath)) {
D.Diag(clang::diag::err_drv_no_such_file) << MultilibPath.str();
return {};
}
} else {
MultilibPath = computeBaseSysRoot(D, /*IncludeTriple=*/false);
llvm::sys::path::append(MultilibPath, MultilibFilename);
}
return MultilibPath;
}

void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args) {
DetectedMultilibs Result;
// Look for a multilib.yaml before trying target-specific hardwired logic.
// If it exists, always do what it specifies.
llvm::SmallString<128> MultilibPath(computeBaseSysRoot(D, Triple));
llvm::sys::path::append(MultilibPath, MultilibFilename);
if (D.getVFS().exists(MultilibPath)) {
findMultilibsFromYAML(*this, D, MultilibPath, Args, Result);
std::optional<llvm::SmallString<128>> MultilibPath =
getMultilibConfigPath(D, Triple, Args);
if (!MultilibPath)
return;
if (D.getVFS().exists(*MultilibPath)) {
// If multilib.yaml is found, update sysroot so it doesn't use a target
// specific suffix
SysRoot = computeBaseSysRoot(D, /*IncludeTriple=*/false);
findMultilibsFromYAML(*this, D, *MultilibPath, Args, Result);
SelectedMultilibs = Result.SelectedMultilibs;
Multilibs = Result.Multilibs;
} else if (isRISCVBareMetal(Triple)) {
Expand All @@ -248,9 +279,7 @@ Tool *BareMetal::buildStaticLibTool() const {
return new tools::baremetal::StaticLibTool(*this);
}

std::string BareMetal::computeSysRoot() const {
return computeBaseSysRoot(getDriver(), getTriple());
}
std::string BareMetal::computeSysRoot() const { return SysRoot; }

BareMetal::OrderedMultilibs BareMetal::getOrderedMultilibs() const {
// Get multilibs in reverse order because they're ordered most-specific last.
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/BareMetal.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
using OrderedMultilibs =
llvm::iterator_range<llvm::SmallVector<Multilib>::const_reverse_iterator>;
OrderedMultilibs getOrderedMultilibs() const;

std::string SysRoot;
};

} // namespace toolchains
Expand Down
32 changes: 27 additions & 5 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3604,7 +3604,8 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_EQ)) {
StringRef Value = A->getValue();
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
!EffectiveTriple.isRISCV())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
if ((EffectiveTriple.isX86() || EffectiveTriple.isARM() ||
Expand Down Expand Up @@ -3644,13 +3645,28 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
<< A->getOption().getName() << Value << "sysreg global";
return;
}
if (EffectiveTriple.isRISCV()) {
if (Value != "tls" && Value != "global") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "tls global";
return;
}
if (Value == "tls") {
if (!Args.hasArg(options::OPT_mstack_protector_guard_offset_EQ)) {
D.Diag(diag::err_drv_ssp_missing_offset_argument)
<< A->getAsString(Args);
return;
}
}
}
A->render(Args, CmdArgs);
}

if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_offset_EQ)) {
StringRef Value = A->getValue();
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb())
!EffectiveTriple.isARM() && !EffectiveTriple.isThumb() &&
!EffectiveTriple.isRISCV())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
int Offset;
Expand All @@ -3669,7 +3685,8 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,

if (Arg *A = Args.getLastArg(options::OPT_mstack_protector_guard_reg_EQ)) {
StringRef Value = A->getValue();
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64())
if (!EffectiveTriple.isX86() && !EffectiveTriple.isAArch64() &&
!EffectiveTriple.isRISCV())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< A->getAsString(Args) << TripleStr;
if (EffectiveTriple.isX86() && (Value != "fs" && Value != "gs")) {
Expand All @@ -3681,6 +3698,11 @@ static void RenderSSPOptions(const Driver &D, const ToolChain &TC,
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Value;
return;
}
if (EffectiveTriple.isRISCV() && Value != "tp") {
D.Diag(diag::err_drv_invalid_value_with_suggestion)
<< A->getOption().getName() << Value << "tp";
return;
}
A->render(Args, CmdArgs);
}

Expand Down Expand Up @@ -6258,8 +6280,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_unique_internal_linkage_names);
Args.addOptInFlag(CmdArgs, options::OPT_funique_basic_block_section_names,
options::OPT_fno_unique_basic_block_section_names);
Args.addOptInFlag(CmdArgs, options::OPT_fconvergent_functions,
options::OPT_fno_convergent_functions);

if (Arg *A = Args.getLastArg(options::OPT_fsplit_machine_functions,
options::OPT_fno_split_machine_functions)) {
Expand All @@ -6276,6 +6296,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_finstrument_functions,
options::OPT_finstrument_functions_after_inlining,
options::OPT_finstrument_function_entry_bare);
Args.AddLastArg(CmdArgs, options::OPT_fconvergent_functions,
options::OPT_fno_convergent_functions);

// NVPTX/AMDGCN doesn't support PGO or coverage. There's no runtime support
// for sampling, overhead of call arc collection is way too high and there's
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/ZOS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ void ZOS::addClangTargetOptions(const ArgList &DriverArgs,
options::OPT_fno_aligned_allocation))
CC1Args.push_back("-faligned-alloc-unavailable");

if (DriverArgs.hasFlag(options::OPT_fxl_pragma_pack,
options::OPT_fno_xl_pragma_pack, true))
CC1Args.push_back("-fxl-pragma-pack");

// Pass "-fno-sized-deallocation" only when the user hasn't manually enabled
// or disabled sized deallocations.
if (!DriverArgs.hasArgNoClaim(options::OPT_fsized_deallocation,
Expand Down
36 changes: 21 additions & 15 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,50 +44,54 @@ struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {

template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
static void enumInput(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
IO.enumCase(Value, "None",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/false, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "None", FormatStyle::AlignConsecutiveStyle({}));
IO.enumCase(Value, "Consecutive",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
IO.enumCase(Value, "AcrossEmptyLines",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/true,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
IO.enumCase(Value, "AcrossComments",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/true, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
IO.enumCase(Value, "AcrossEmptyLinesAndComments",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/true,
/*AcrossComments=*/true, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));

// For backward compatibility.
IO.enumCase(Value, "true",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "false",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/false, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
IO.enumCase(Value, "false", FormatStyle::AlignConsecutiveStyle({}));
}

static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
IO.mapOptional("Enabled", Value.Enabled);
IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
IO.mapOptional("AcrossComments", Value.AcrossComments);
IO.mapOptional("AlignCompound", Value.AlignCompound);
IO.mapOptional("AlignFunctionDeclarations",
Value.AlignFunctionDeclarations);
IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);
IO.mapOptional("PadOperators", Value.PadOperators);
}
Expand Down Expand Up @@ -1147,6 +1151,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("TableGenBreakInsideDAGArg",
Style.TableGenBreakInsideDAGArg);
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("TemplateNames", Style.TemplateNames);
IO.mapOptional("TypeNames", Style.TypeNames);
IO.mapOptional("TypenameMacros", Style.TypenameMacros);
IO.mapOptional("UseTab", Style.UseTab);
Expand Down Expand Up @@ -1448,6 +1453,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
LLVMStyle.AlignConsecutiveBitFields = {};
LLVMStyle.AlignConsecutiveDeclarations = {};
LLVMStyle.AlignConsecutiveDeclarations.AlignFunctionDeclarations = true;
LLVMStyle.AlignConsecutiveMacros = {};
LLVMStyle.AlignConsecutiveShortCaseStatements = {};
LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/FormatToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ namespace format {
TYPE(TrailingReturnArrow) \
TYPE(TrailingUnaryOperator) \
TYPE(TypeDeclarationParen) \
TYPE(TemplateName) \
TYPE(TypeName) \
TYPE(TypenameMacro) \
TYPE(UnaryOperator) \
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Format/FormatTokenLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ FormatTokenLexer::FormatTokenLexer(
Macros.insert({Identifier, TT_StatementAttributeLikeMacro});
}

for (const auto &TemplateName : Style.TemplateNames)
TemplateNames.insert(&IdentTable.get(TemplateName));
for (const auto &TypeName : Style.TypeNames)
TypeNames.insert(&IdentTable.get(TypeName));
}
Expand Down Expand Up @@ -1368,6 +1370,8 @@ FormatToken *FormatTokenLexer::getNextToken() {
FormatTok->setType(TT_MacroBlockBegin);
else if (MacroBlockEndRegex.match(Text))
FormatTok->setType(TT_MacroBlockEnd);
else if (TemplateNames.contains(Identifier))
FormatTok->setFinalizedType(TT_TemplateName);
else if (TypeNames.contains(Identifier))
FormatTok->setFinalizedType(TT_TypeName);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/FormatTokenLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class FormatTokenLexer {

llvm::SmallMapVector<IdentifierInfo *, TokenType, 8> Macros;

llvm::SmallPtrSet<IdentifierInfo *, 8> TypeNames;
llvm::SmallPtrSet<IdentifierInfo *, 8> TemplateNames, TypeNames;

bool FormattingDisabled;

Expand Down
126 changes: 75 additions & 51 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,36 +149,36 @@ class AnnotatingParser {
}

bool parseAngle() {
if (!CurrentToken || !CurrentToken->Previous)
if (!CurrentToken)
return false;
if (NonTemplateLess.count(CurrentToken->Previous) > 0)

auto *Left = CurrentToken->Previous; // The '<'.
if (!Left)
return false;

if (const auto &Previous = *CurrentToken->Previous; // The '<'.
Previous.Previous) {
if (Previous.Previous->Tok.isLiteral())
if (NonTemplateLess.count(Left) > 0)
return false;

const auto *BeforeLess = Left->Previous;

if (BeforeLess) {
if (BeforeLess->Tok.isLiteral())
return false;
if (Previous.Previous->is(tok::r_brace))
if (BeforeLess->is(tok::r_brace))
return false;
if (Previous.Previous->is(tok::r_paren) && Contexts.size() > 1 &&
(!Previous.Previous->MatchingParen ||
Previous.Previous->MatchingParen->isNot(
TT_OverloadedOperatorLParen))) {
if (BeforeLess->is(tok::r_paren) && Contexts.size() > 1 &&
!(BeforeLess->MatchingParen &&
BeforeLess->MatchingParen->is(TT_OverloadedOperatorLParen))) {
return false;
}
if (Previous.Previous->is(tok::kw_operator) &&
CurrentToken->is(tok::l_paren)) {
if (BeforeLess->is(tok::kw_operator) && CurrentToken->is(tok::l_paren))
return false;
}
}

FormatToken *Left = CurrentToken->Previous;
Left->ParentBracket = Contexts.back().ContextKind;
ScopedContextCreator ContextCreator(*this, tok::less, 12);
Contexts.back().IsExpression = false;

const auto *BeforeLess = Left->Previous;

// If there's a template keyword before the opening angle bracket, this is a
// template parameter, not an argument.
if (BeforeLess && BeforeLess->isNot(tok::kw_template))
Expand All @@ -189,25 +189,29 @@ class AnnotatingParser {
next();
}

for (bool SeenTernaryOperator = false; CurrentToken;) {
for (bool SeenTernaryOperator = false, MaybeAngles = true; CurrentToken;) {
const bool InExpr = Contexts[Contexts.size() - 2].IsExpression;
if (CurrentToken->is(tok::greater)) {
const auto *Next = CurrentToken->Next;
// Try to do a better job at looking for ">>" within the condition of
// a statement. Conservatively insert spaces between consecutive ">"
// tokens to prevent splitting right bitshift operators and potentially
// altering program semantics. This check is overly conservative and
// will prevent spaces from being inserted in select nested template
// parameter cases, but should not alter program semantics.
if (Next && Next->is(tok::greater) &&
Left->ParentBracket != tok::less &&
CurrentToken->getStartOfNonWhitespace() ==
Next->getStartOfNonWhitespace().getLocWithOffset(-1)) {
return false;
}
if (InExpr && SeenTernaryOperator &&
(!Next || !Next->isOneOf(tok::l_paren, tok::l_brace))) {
return false;
if (CurrentToken->isNot(TT_TemplateCloser)) {
// Try to do a better job at looking for ">>" within the condition of
// a statement. Conservatively insert spaces between consecutive ">"
// tokens to prevent splitting right shift operators and potentially
// altering program semantics. This check is overly conservative and
// will prevent spaces from being inserted in select nested template
// parameter cases, but should not alter program semantics.
if (Next && Next->is(tok::greater) &&
Left->ParentBracket != tok::less &&
CurrentToken->getStartOfNonWhitespace() ==
Next->getStartOfNonWhitespace().getLocWithOffset(-1)) {
return false;
}
if (InExpr && SeenTernaryOperator &&
(!Next || !Next->isOneOf(tok::l_paren, tok::l_brace))) {
return false;
}
if (!MaybeAngles)
return false;
}
Left->MatchingParen = CurrentToken;
CurrentToken->MatchingParen = Left;
Expand All @@ -229,6 +233,10 @@ class AnnotatingParser {
next();
return true;
}
if (BeforeLess && BeforeLess->is(TT_TemplateName)) {
next();
continue;
}
if (CurrentToken->is(tok::question) &&
Style.Language == FormatStyle::LK_Java) {
next();
Expand All @@ -243,11 +251,11 @@ class AnnotatingParser {
// operator that was misinterpreted because we are parsing template
// parameters.
// FIXME: This is getting out of hand, write a decent parser.
if (InExpr && !Line.startsWith(tok::kw_template) &&
if (MaybeAngles && InExpr && !Line.startsWith(tok::kw_template) &&
Prev.is(TT_BinaryOperator)) {
const auto Precedence = Prev.getPrecedence();
if (Precedence > prec::Conditional && Precedence < prec::Relational)
return false;
MaybeAngles = false;
}
if (Prev.isOneOf(tok::question, tok::colon) && !Style.isProto())
SeenTernaryOperator = true;
Expand Down Expand Up @@ -358,7 +366,7 @@ class AnnotatingParser {
} else if (OpeningParen.Previous &&
(OpeningParen.Previous->isOneOf(
tok::kw_static_assert, tok::kw_noexcept, tok::kw_explicit,
tok::kw_while, tok::l_paren, tok::comma,
tok::kw_while, tok::l_paren, tok::comma, TT_CastRParen,
TT_BinaryOperator) ||
OpeningParen.Previous->isIf())) {
// static_assert, if and while usually contain expressions.
Expand Down Expand Up @@ -468,16 +476,18 @@ class AnnotatingParser {
OpeningParen.Previous && OpeningParen.Previous->is(tok::kw_for);
FormatToken *PossibleObjCForInToken = nullptr;
while (CurrentToken) {
if (CurrentToken->Previous->is(TT_PointerOrReference) &&
CurrentToken->Previous->Previous->isOneOf(tok::l_paren,
tok::coloncolon)) {
const auto &Prev = *CurrentToken->Previous;
if (Prev.is(TT_PointerOrReference) &&
Prev.Previous->isOneOf(tok::l_paren, tok::coloncolon)) {
ProbablyFunctionType = true;
}
if (CurrentToken->is(tok::comma))
MightBeFunctionType = false;
if (CurrentToken->Previous->is(TT_BinaryOperator))
if (Prev.is(TT_BinaryOperator))
Contexts.back().IsExpression = true;
if (CurrentToken->is(tok::r_paren)) {
if (Prev.is(TT_PointerOrReference) && Prev.Previous == &OpeningParen)
MightBeFunctionType = true;
if (OpeningParen.isNot(TT_CppCastLParen) && MightBeFunctionType &&
ProbablyFunctionType && CurrentToken->Next &&
(CurrentToken->Next->is(tok::l_paren) ||
Expand Down Expand Up @@ -550,8 +560,8 @@ class AnnotatingParser {
bool ProbablyFunctionTypeLParen =
(CurrentToken->is(tok::l_paren) && CurrentToken->Next &&
CurrentToken->Next->isOneOf(tok::star, tok::amp, tok::caret));
if ((CurrentToken->Previous->isOneOf(tok::kw_const, tok::kw_auto) ||
CurrentToken->Previous->isTypeName(LangOpts)) &&
if ((Prev.isOneOf(tok::kw_const, tok::kw_auto) ||
Prev.isTypeName(LangOpts)) &&
!(CurrentToken->is(tok::l_brace) ||
(CurrentToken->is(tok::l_paren) && !ProbablyFunctionTypeLParen))) {
Contexts.back().IsExpression = false;
Expand Down Expand Up @@ -1165,19 +1175,26 @@ class AnnotatingParser {

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

const auto *Prev = OpeningBrace.getPreviousNonComment();

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

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

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 Expand Up @@ -1614,7 +1631,7 @@ class AnnotatingParser {
return false;
break;
case tok::greater:
if (Style.Language != FormatStyle::LK_TextProto)
if (Style.Language != FormatStyle::LK_TextProto && Tok->is(TT_Unknown))
Tok->setType(TT_BinaryOperator);
if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser))
Tok->SpacesRequiredBefore = 1;
Expand Down Expand Up @@ -3721,6 +3738,13 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts,

const auto *Prev = Current.getPreviousNonComment();
assert(Prev);

if (Prev->is(tok::coloncolon))
Prev = Prev->Previous;

if (!Prev)
return false;

const auto &Previous = *Prev;

if (const auto *PrevPrev = Previous.getPreviousNonComment();
Expand Down
17 changes: 13 additions & 4 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,11 @@ void UnwrappedLineParser::parseStructuralElement(
return;
}
break;
case tok::greater:
nextToken();
if (FormatTok->is(tok::l_brace))
FormatTok->Previous->setFinalizedType(TT_TemplateCloser);
break;
default:
nextToken();
break;
Expand Down Expand Up @@ -2556,7 +2561,7 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
parseChildBlock();
break;
case tok::r_paren: {
const auto *Prev = LeftParen->Previous;
auto *Prev = LeftParen->Previous;
if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody &&
Style.RemoveParentheses > FormatStyle::RPS_Leave) {
const auto *Next = Tokens->peekNextToken();
Expand Down Expand Up @@ -2585,9 +2590,13 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
FormatTok->Optional = true;
}
}
if (Prev && Prev->is(TT_TypenameMacro)) {
LeftParen->setFinalizedType(TT_TypeDeclarationParen);
FormatTok->setFinalizedType(TT_TypeDeclarationParen);
if (Prev) {
if (Prev->is(TT_TypenameMacro)) {
LeftParen->setFinalizedType(TT_TypeDeclarationParen);
FormatTok->setFinalizedType(TT_TypeDeclarationParen);
} else if (Prev->is(tok::greater) && FormatTok->Previous == LeftParen) {
Prev->setFinalizedType(TT_TemplateCloser);
}
}
nextToken();
return SeenEqual;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
return true;
}
if (C.Tok->is(TT_FunctionDeclarationName))
return true;
return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;
if (C.Tok->isNot(TT_StartOfName))
return false;
if (C.Tok->Previous &&
Expand Down
18 changes: 9 additions & 9 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3687,10 +3687,10 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
if (Opts.Blocks && !(Opts.OpenCL && Opts.OpenCLVersion == 200))
GenerateArg(Consumer, OPT_fblocks);

if (Opts.ConvergentFunctions &&
!(Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) || Opts.SYCLIsDevice ||
Opts.HLSL))
if (Opts.ConvergentFunctions)
GenerateArg(Consumer, OPT_fconvergent_functions);
else
GenerateArg(Consumer, OPT_fno_convergent_functions);

if (Opts.NoBuiltin && !Opts.Freestanding)
GenerateArg(Consumer, OPT_fno_builtin);
Expand Down Expand Up @@ -4106,9 +4106,12 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
&& Opts.OpenCLVersion == 200);

Opts.ConvergentFunctions = Args.hasArg(OPT_fconvergent_functions) ||
Opts.OpenCL || (Opts.CUDA && Opts.CUDAIsDevice) ||
Opts.SYCLIsDevice || Opts.HLSL;
bool HasConvergentOperations = Opts.OpenMPIsTargetDevice || Opts.OpenCL ||
Opts.CUDAIsDevice || Opts.SYCLIsDevice ||
Opts.HLSL || T.isAMDGPU() || T.isNVPTX();
Opts.ConvergentFunctions =
Args.hasFlag(OPT_fconvergent_functions, OPT_fno_convergent_functions,
HasConvergentOperations);

Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
if (!Opts.NoBuiltin)
Expand Down Expand Up @@ -4164,9 +4167,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
bool IsTargetSpecified =
Opts.OpenMPIsTargetDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ);

Opts.ConvergentFunctions =
Opts.ConvergentFunctions || Opts.OpenMPIsTargetDevice;

if (Opts.OpenMP || Opts.OpenMPSimd) {
if (int Version = getLastArgIntValue(
Args, OPT_fopenmp_version_EQ,
Expand Down
52 changes: 52 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,28 @@ uint64_t3 reversebits(uint64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_bitreverse)
uint64_t4 reversebits(uint64_t4);

//===----------------------------------------------------------------------===//
// cross builtins
//===----------------------------------------------------------------------===//

/// \fn T cross(T x, T y)
/// \brief Returns the cross product of two floating-point, 3D vectors.
/// \param x [in] The first floating-point, 3D vector.
/// \param y [in] The second floating-point, 3D vector.
///
/// Result is the cross product of x and y, i.e., the resulting
/// components are, in order :
/// x[1] * y[2] - y[1] * x[2]
/// x[2] * y[0] - y[2] * x[0]
/// x[0] * y[1] - y[0] * x[1]

_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross)
half3 cross(half3, half3);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_cross)
float3 cross(float3, float3);

//===----------------------------------------------------------------------===//
// rcp builtins
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2116,5 +2138,35 @@ _HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
int3 sign(double3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_sign)
int4 sign(double4);

//===----------------------------------------------------------------------===//
// radians builtins
//===----------------------------------------------------------------------===//

/// \fn T radians(T Val)
/// \brief Converts the specified value from degrees to radians.

_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_radians)
half radians(half);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_radians)
half2 radians(half2);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_radians)
half3 radians(half3);
_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_radians)
half4 radians(half4);

_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_radians)
float radians(float);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_radians)
float2 radians(float2);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_radians)
float3 radians(float3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_radians)
float4 radians(float4);

} // namespace hlsl
#endif //_HLSL_HLSL_INTRINSICS_H_
14 changes: 7 additions & 7 deletions clang/lib/Headers/popcntintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
#define __POPCNTINTRIN_H

/* Define the default attributes for the functions in this file. */
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("popcnt")))

#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, \
__target__("popcnt"))) constexpr
#else
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __target__("popcnt")))
#endif

/// Counts the number of bits in the source operand having a value of 1.
Expand All @@ -29,7 +30,7 @@
/// An unsigned 32-bit integer operand.
/// \returns A 32-bit integer containing the number of bits with value 1 in the
/// source operand.
static __inline__ int __DEFAULT_FN_ATTRS_CONSTEXPR
static __inline__ int __DEFAULT_FN_ATTRS
_mm_popcnt_u32(unsigned int __A)
{
return __builtin_popcount(__A);
Expand All @@ -46,14 +47,13 @@ _mm_popcnt_u32(unsigned int __A)
/// An unsigned 64-bit integer operand.
/// \returns A 64-bit integer containing the number of bits with value 1 in the
/// source operand.
static __inline__ long long __DEFAULT_FN_ATTRS_CONSTEXPR
static __inline__ long long __DEFAULT_FN_ATTRS
_mm_popcnt_u64(unsigned long long __A)
{
return __builtin_popcountll(__A);
}
#endif /* __x86_64__ */

#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS_CONSTEXPR

#endif /* __POPCNTINTRIN_H */
130 changes: 58 additions & 72 deletions clang/lib/Headers/xmmintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ typedef unsigned int __v4su __attribute__((__vector_size__(16)));
__min_vector_width__(128)))
#endif

#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
#define __DEFAULT_FN_ATTRS_SSE2_CONSTEXPR __DEFAULT_FN_ATTRS_SSE2 constexpr
#else
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
#define __DEFAULT_FN_ATTRS_SSE2_CONSTEXPR __DEFAULT_FN_ATTRS_SSE2
#endif

#define __trunc64(x) \
(__m64) __builtin_shufflevector((__v2di)(x), __extension__(__v2di){}, 0)
#define __zext128(x) \
Expand Down Expand Up @@ -75,9 +83,8 @@ typedef unsigned int __v4su __attribute__((__vector_size__(16)));
/// \returns A 128-bit vector of [4 x float] whose lower 32 bits contain the sum
/// of the lower 32 bits of both operands. The upper 96 bits are copied from
/// the upper 96 bits of the first source operand.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_add_ss(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_add_ss(__m128 __a, __m128 __b) {
__a[0] += __b[0];
return __a;
}
Expand All @@ -95,9 +102,8 @@ _mm_add_ss(__m128 __a, __m128 __b)
/// A 128-bit vector of [4 x float] containing one of the source operands.
/// \returns A 128-bit vector of [4 x float] containing the sums of both
/// operands.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_add_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_add_ps(__m128 __a, __m128 __b) {
return (__m128)((__v4sf)__a + (__v4sf)__b);
}

Expand All @@ -117,9 +123,8 @@ _mm_add_ps(__m128 __a, __m128 __b)
/// \returns A 128-bit vector of [4 x float] whose lower 32 bits contain the
/// difference of the lower 32 bits of both operands. The upper 96 bits are
/// copied from the upper 96 bits of the first source operand.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_sub_ss(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_sub_ss(__m128 __a, __m128 __b) {
__a[0] -= __b[0];
return __a;
}
Expand All @@ -138,9 +143,8 @@ _mm_sub_ss(__m128 __a, __m128 __b)
/// A 128-bit vector of [4 x float] containing the subtrahend.
/// \returns A 128-bit vector of [4 x float] containing the differences between
/// both operands.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_sub_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_sub_ps(__m128 __a, __m128 __b) {
return (__m128)((__v4sf)__a - (__v4sf)__b);
}

Expand All @@ -160,9 +164,8 @@ _mm_sub_ps(__m128 __a, __m128 __b)
/// \returns A 128-bit vector of [4 x float] containing the product of the lower
/// 32 bits of both operands. The upper 96 bits are copied from the upper 96
/// bits of the first source operand.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mul_ss(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_mul_ss(__m128 __a, __m128 __b) {
__a[0] *= __b[0];
return __a;
}
Expand All @@ -180,9 +183,8 @@ _mm_mul_ss(__m128 __a, __m128 __b)
/// A 128-bit vector of [4 x float] containing one of the source operands.
/// \returns A 128-bit vector of [4 x float] containing the products of both
/// operands.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_mul_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_mul_ps(__m128 __a, __m128 __b) {
return (__m128)((__v4sf)__a * (__v4sf)__b);
}

Expand All @@ -202,9 +204,8 @@ _mm_mul_ps(__m128 __a, __m128 __b)
/// \returns A 128-bit vector of [4 x float] containing the quotients of the
/// lower 32 bits of both operands. The upper 96 bits are copied from the
/// upper 96 bits of the first source operand.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_div_ss(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_div_ss(__m128 __a, __m128 __b) {
__a[0] /= __b[0];
return __a;
}
Expand All @@ -221,9 +222,8 @@ _mm_div_ss(__m128 __a, __m128 __b)
/// A 128-bit vector of [4 x float] containing the divisor.
/// \returns A 128-bit vector of [4 x float] containing the quotients of both
/// operands.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_div_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_div_ps(__m128 __a, __m128 __b) {
return (__m128)((__v4sf)__a / (__v4sf)__b);
}

Expand Down Expand Up @@ -437,9 +437,8 @@ _mm_max_ps(__m128 __a, __m128 __b)
/// A 128-bit vector containing one of the source operands.
/// \returns A 128-bit vector of [4 x float] containing the bitwise AND of the
/// values between both operands.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_and_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_and_ps(__m128 __a, __m128 __b) {
return (__m128)((__v4su)__a & (__v4su)__b);
}

Expand All @@ -459,9 +458,8 @@ _mm_and_ps(__m128 __a, __m128 __b)
/// \returns A 128-bit vector of [4 x float] containing the bitwise AND of the
/// one's complement of the first operand and the values in the second
/// operand.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_andnot_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_andnot_ps(__m128 __a, __m128 __b) {
return (__m128)(~(__v4su)__a & (__v4su)__b);
}

Expand All @@ -477,9 +475,8 @@ _mm_andnot_ps(__m128 __a, __m128 __b)
/// A 128-bit vector of [4 x float] containing one of the source operands.
/// \returns A 128-bit vector of [4 x float] containing the bitwise OR of the
/// values between both operands.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_or_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_or_ps(__m128 __a, __m128 __b) {
return (__m128)((__v4su)__a | (__v4su)__b);
}

Expand All @@ -496,9 +493,8 @@ _mm_or_ps(__m128 __a, __m128 __b)
/// A 128-bit vector of [4 x float] containing one of the source operands.
/// \returns A 128-bit vector of [4 x float] containing the bitwise exclusive OR
/// of the values between both operands.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_xor_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_xor_ps(__m128 __a, __m128 __b) {
return (__m128)((__v4su)__a ^ (__v4su)__b);
}

Expand Down Expand Up @@ -1738,9 +1734,8 @@ _mm_cvt_pi2ps(__m128 __a, __m64 __b)
/// A 128-bit vector of [4 x float]. The lower 32 bits of this operand are
/// used in the extraction.
/// \returns A 32-bit float containing the extracted value.
static __inline__ float __DEFAULT_FN_ATTRS
_mm_cvtss_f32(__m128 __a)
{
static __inline__ float __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_cvtss_f32(__m128 __a) {
return __a[0];
}

Expand Down Expand Up @@ -1931,9 +1926,8 @@ _mm_undefined_ps(void)
/// \returns An initialized 128-bit floating-point vector of [4 x float]. The
/// lower 32 bits contain the value provided in the source operand. The
/// upper 96 bits are set to zero.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ss(float __w)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_set_ss(float __w) {
return __extension__ (__m128){ __w, 0.0f, 0.0f, 0.0f };
}

Expand All @@ -1949,9 +1943,8 @@ _mm_set_ss(float __w)
/// A single-precision floating-point value used to initialize each vector
/// element of the result.
/// \returns An initialized 128-bit floating-point vector of [4 x float].
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set1_ps(float __w)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_set1_ps(float __w) {
return __extension__ (__m128){ __w, __w, __w, __w };
}

Expand All @@ -1968,9 +1961,8 @@ _mm_set1_ps(float __w)
/// A single-precision floating-point value used to initialize each vector
/// element of the result.
/// \returns An initialized 128-bit floating-point vector of [4 x float].
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ps1(float __w)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_set_ps1(float __w) {
return _mm_set1_ps(__w);
}

Expand All @@ -1995,9 +1987,8 @@ _mm_set_ps1(float __w)
/// A single-precision floating-point value used to initialize bits [31:0]
/// of the result.
/// \returns An initialized 128-bit floating-point vector of [4 x float].
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_set_ps(float __z, float __y, float __x, float __w)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_set_ps(float __z, float __y, float __x, float __w) {
return __extension__ (__m128){ __w, __x, __y, __z };
}

Expand All @@ -2023,9 +2014,8 @@ _mm_set_ps(float __z, float __y, float __x, float __w)
/// A single-precision floating-point value used to initialize bits [127:96]
/// of the result.
/// \returns An initialized 128-bit floating-point vector of [4 x float].
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_setr_ps(float __z, float __y, float __x, float __w)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_setr_ps(float __z, float __y, float __x, float __w) {
return __extension__ (__m128){ __z, __y, __x, __w };
}

Expand All @@ -2038,9 +2028,8 @@ _mm_setr_ps(float __z, float __y, float __x, float __w)
///
/// \returns An initialized 128-bit floating-point vector of [4 x float] with
/// all elements set to zero.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_setzero_ps(void)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_setzero_ps(void) {
return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f };
}

Expand Down Expand Up @@ -2786,9 +2775,8 @@ void _mm_setcsr(unsigned int __i);
/// Bits [95:64] are written to bits [63:32] of the destination. \n
/// Bits [127:96] are written to bits [127:96] of the destination.
/// \returns A 128-bit vector of [4 x float] containing the interleaved values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_unpackhi_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_unpackhi_ps(__m128 __a, __m128 __b) {
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 2, 6, 3, 7);
}

Expand All @@ -2808,9 +2796,8 @@ _mm_unpackhi_ps(__m128 __a, __m128 __b)
/// Bits [31:0] are written to bits [63:32] of the destination. \n
/// Bits [63:32] are written to bits [127:96] of the destination.
/// \returns A 128-bit vector of [4 x float] containing the interleaved values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_unpacklo_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_unpacklo_ps(__m128 __a, __m128 __b) {
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 0, 4, 1, 5);
}

Expand All @@ -2830,9 +2817,8 @@ _mm_unpacklo_ps(__m128 __a, __m128 __b)
/// A 128-bit floating-point vector of [4 x float]. The lower 32 bits are
/// written to the lower 32 bits of the result.
/// \returns A 128-bit floating-point vector of [4 x float].
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_move_ss(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_move_ss(__m128 __a, __m128 __b) {
__a[0] = __b[0];
return __a;
}
Expand All @@ -2852,9 +2838,8 @@ _mm_move_ss(__m128 __a, __m128 __b)
/// A 128-bit floating-point vector of [4 x float]. The upper 64 bits are
/// written to the lower 64 bits of the result.
/// \returns A 128-bit floating-point vector of [4 x float].
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_movehl_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_movehl_ps(__m128 __a, __m128 __b) {
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 6, 7, 2, 3);
}

Expand All @@ -2873,9 +2858,8 @@ _mm_movehl_ps(__m128 __a, __m128 __b)
/// A 128-bit floating-point vector of [4 x float]. The lower 64 bits are
/// written to the upper 64 bits of the result.
/// \returns A 128-bit floating-point vector of [4 x float].
static __inline__ __m128 __DEFAULT_FN_ATTRS
_mm_movelh_ps(__m128 __a, __m128 __b)
{
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_movelh_ps(__m128 __a, __m128 __b) {
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__b, 0, 1, 4, 5);
}

Expand Down Expand Up @@ -3207,7 +3191,9 @@ do { \
#undef __anyext128
#undef __zeroupper64
#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS_CONSTEXPR
#undef __DEFAULT_FN_ATTRS_SSE2
#undef __DEFAULT_FN_ATTRS_SSE2_CONSTEXPR

/* Ugly hack for backwards-compatibility (compatible with gcc) */
#if defined(__SSE2__) && !__building_module(_Builtin_intrinsics)
Expand Down
48 changes: 32 additions & 16 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,38 +743,50 @@ bool Parser::ParseOpenACCDeviceTypeList(
// int-expr
// Note that this is specified under 'gang-arg-list', but also applies to 'tile'
// via reference.
bool Parser::ParseOpenACCSizeExpr() {
// FIXME: Ensure these are constant expressions.

ExprResult Parser::ParseOpenACCSizeExpr(OpenACCClauseKind CK) {
// The size-expr ends up being ambiguous when only looking at the current
// token, as it could be a deref of a variable/expression.
if (getCurToken().is(tok::star) &&
NextToken().isOneOf(tok::comma, tok::r_paren,
tok::annot_pragma_openacc_end)) {
ConsumeToken();
return false;
SourceLocation AsteriskLoc = ConsumeToken();
return getActions().OpenACC().ActOnOpenACCAsteriskSizeExpr(AsteriskLoc);
}

return getActions()
.CorrectDelayedTyposInExpr(ParseAssignmentExpression())
.isInvalid();
ExprResult SizeExpr =
getActions().CorrectDelayedTyposInExpr(ParseConstantExpression());

if (!SizeExpr.isUsable())
return SizeExpr;

SizeExpr = getActions().OpenACC().ActOnIntExpr(
OpenACCDirectiveKind::Invalid, CK, SizeExpr.get()->getBeginLoc(),
SizeExpr.get());

return SizeExpr;
}

bool Parser::ParseOpenACCSizeExprList() {
if (ParseOpenACCSizeExpr()) {
bool Parser::ParseOpenACCSizeExprList(
OpenACCClauseKind CK, llvm::SmallVectorImpl<Expr *> &SizeExprs) {
ExprResult SizeExpr = ParseOpenACCSizeExpr(CK);
if (!SizeExpr.isUsable()) {
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
Parser::StopBeforeMatch);
return false;
return true;
}

SizeExprs.push_back(SizeExpr.get());

while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
ExpectAndConsume(tok::comma);

if (ParseOpenACCSizeExpr()) {
SizeExpr = ParseOpenACCSizeExpr(CK);
if (!SizeExpr.isUsable()) {
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
Parser::StopBeforeMatch);
return false;
return true;
}
SizeExprs.push_back(SizeExpr.get());
}
return false;
}
Expand All @@ -792,7 +804,7 @@ bool Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
// 'static' just takes a size-expr, which is an int-expr or an asterisk.
ConsumeToken();
ConsumeToken();
return ParseOpenACCSizeExpr();
return ParseOpenACCSizeExpr(OpenACCClauseKind::Gang).isInvalid();
}

if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) &&
Expand Down Expand Up @@ -1052,12 +1064,16 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
}
break;
}
case OpenACCClauseKind::Tile:
if (ParseOpenACCSizeExprList()) {
case OpenACCClauseKind::Tile: {
llvm::SmallVector<Expr *> SizeExprs;
if (ParseOpenACCSizeExprList(OpenACCClauseKind::Tile, SizeExprs)) {
Parens.skipToEnd();
return OpenACCCanContinue();
}

ParsedClause.setIntExprDetails(std::move(SizeExprs));
break;
}
default:
llvm_unreachable("Not a required parens type?");
}
Expand Down
Loading