7 changes: 6 additions & 1 deletion clang/lib/AST/ExprClassification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyInternal(Ctx,
cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());

case Expr::PackIndexingExprClass:
case Expr::PackIndexingExprClass: {
// A pack-index-expression always expands to an id-expression.
// Consider it as an LValue expression.
if (cast<PackIndexingExpr>(E)->isInstantiationDependent())
return Cl::CL_LValue;
return ClassifyInternal(Ctx, cast<PackIndexingExpr>(E)->getSelectedExpr());
}

// C, C++98 [expr.sub]p1: The result is an lvalue of type "T".
// C++11 (DR1213): in the case of an array operand, the result is an lvalue
Expand Down
90 changes: 45 additions & 45 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,11 @@ namespace interp {
template <class Emitter> class DeclScope final : public VariableScope<Emitter> {
public:
DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD)
: VariableScope<Emitter>(Ctx), Scope(Ctx->P, VD),
: VariableScope<Emitter>(Ctx, nullptr), Scope(Ctx->P, VD),
OldGlobalDecl(Ctx->GlobalDecl) {
Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD);
}

void addExtended(const Scope::Local &Local) override {
return this->addLocal(Local);
}

~DeclScope() { this->Ctx->GlobalDecl = OldGlobalDecl; }

private:
Expand Down Expand Up @@ -85,8 +81,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
std::optional<PrimType> SubExprT = classify(SubExpr->getType());
// Prepare storage for the result.
if (!Initializing && !SubExprT) {
std::optional<unsigned> LocalIndex =
allocateLocal(SubExpr, /*IsExtended=*/false);
std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, CE))
Expand Down Expand Up @@ -362,8 +357,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
// We're creating a complex value here, so we need to
// allocate storage for it.
if (!Initializing) {
std::optional<unsigned> LocalIndex =
allocateLocal(CE, /*IsExtended=*/true);
std::optional<unsigned> LocalIndex = allocateLocal(CE);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, CE))
Expand All @@ -390,8 +384,7 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->discard(SubExpr);

if (!Initializing) {
std::optional<unsigned> LocalIndex =
allocateLocal(CE, /*IsExtended=*/true);
std::optional<unsigned> LocalIndex = allocateLocal(CE);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, CE))
Expand Down Expand Up @@ -492,7 +485,7 @@ bool ByteCodeExprGen<Emitter>::VisitImaginaryLiteral(
return true;

if (!Initializing) {
std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/false);
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, E))
Expand Down Expand Up @@ -561,7 +554,7 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {

// We need a temporary variable holding our return value.
if (!Initializing) {
std::optional<unsigned> ResultIndex = this->allocateLocal(BO, false);
std::optional<unsigned> ResultIndex = this->allocateLocal(BO);
if (!this->emitGetPtrLocal(*ResultIndex, BO))
return false;
}
Expand Down Expand Up @@ -784,7 +777,7 @@ template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
// Prepare storage for result.
if (!Initializing) {
std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/false);
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, E))
Expand Down Expand Up @@ -1841,11 +1834,12 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups(
const ExprWithCleanups *E) {
ExprScope<Emitter> ES(this);
const Expr *SubExpr = E->getSubExpr();

assert(E->getNumObjects() == 0 && "TODO: Implement cleanups");

return this->delegate(SubExpr);
return this->delegate(SubExpr) && ES.destroyLocals();
}

template <class Emitter>
Expand Down Expand Up @@ -1910,9 +1904,8 @@ bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
return this->emitGetPtrLocal(LocalIndex, E);
} else {
const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();

if (std::optional<unsigned> LocalIndex =
allocateLocal(Inner, /*IsExtended=*/true)) {
allocateLocal(Inner, E->getExtendingDecl())) {
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
return this->visitInitializer(SubExpr);
Expand Down Expand Up @@ -2095,10 +2088,16 @@ bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr(
if (T->isRecordType()) {
const CXXConstructorDecl *Ctor = E->getConstructor();

// Trivial zero initialization.
if (E->requiresZeroInitialization() && Ctor->isTrivial()) {
// Zero initialization.
if (E->requiresZeroInitialization()) {
const Record *R = getRecord(E->getType());
return this->visitZeroRecordInitializer(R, E);

if (!this->visitZeroRecordInitializer(R, E))
return false;

// If the constructor is trivial anyway, we're done.
if (Ctor->isTrivial())
return true;
}

const Function *Func = getFunction(Ctor);
Expand All @@ -2113,8 +2112,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr(
// to allocate a variable and call the constructor and destructor.
if (DiscardResult) {
assert(!Initializing);
std::optional<unsigned> LocalIndex =
allocateLocal(E, /*IsExtended=*/true);
std::optional<unsigned> LocalIndex = allocateLocal(E);

if (!LocalIndex)
return false;
Expand Down Expand Up @@ -2294,8 +2292,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXScalarValueInitExpr(

if (const auto *CT = Ty->getAs<ComplexType>()) {
if (!Initializing) {
std::optional<unsigned> LocalIndex =
allocateLocal(E, /*IsExtended=*/false);
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, E))
Expand All @@ -2318,8 +2315,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXScalarValueInitExpr(
if (const auto *VT = Ty->getAs<VectorType>()) {
// FIXME: Code duplication with the _Complex case above.
if (!Initializing) {
std::optional<unsigned> LocalIndex =
allocateLocal(E, /*IsExtended=*/false);
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, E))
Expand Down Expand Up @@ -2434,13 +2430,17 @@ bool ByteCodeExprGen<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {
assert(classifyPrim(E->getType()) == PT_Bool);
if (DiscardResult)
return true;
return this->emitConstBool(E->isSatisfied(), E);
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitConceptSpecializationExpr(
const ConceptSpecializationExpr *E) {
assert(classifyPrim(E->getType()) == PT_Bool);
if (DiscardResult)
return true;
return this->emitConstBool(E->isSatisfied(), E);
}

Expand Down Expand Up @@ -2481,37 +2481,33 @@ bool ByteCodeExprGen<Emitter>::VisitPackIndexingExpr(
return this->delegate(E->getSelectedExpr());
}

template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
if (E->containsErrors())
return false;
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitRecoveryExpr(const RecoveryExpr *E) {
return this->emitError(E);
}

template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
/*NewInitializing=*/false);
return this->Visit(E);
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::delegate(const Expr *E) {
if (E->containsErrors())
return this->emitError(E);

// We're basically doing:
// OptionScope<Emitter> Scope(this, DicardResult, Initializing);
// but that's unnecessary of course.
return this->Visit(E);
}

template <class Emitter> bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
if (E->containsErrors())
return this->emitError(E);

if (E->getType()->isVoidType())
return this->discard(E);

// Create local variable to hold the return value.
if (!E->isGLValue() && !E->getType()->isAnyComplexType() &&
!classify(E->getType())) {
std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/true);
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;

Expand Down Expand Up @@ -2765,7 +2761,8 @@ unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,

template <class Emitter>
std::optional<unsigned>
ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src,
const ValueDecl *ExtendingDecl) {
// Make sure we don't accidentally register the same decl twice.
if ([[maybe_unused]] const auto *VD =
dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
Expand Down Expand Up @@ -2798,7 +2795,10 @@ ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
Scope::Local Local = this->createLocal(D);
if (Key)
Locals.insert({Key, Local});
VarScope->add(Local, IsExtended);
if (ExtendingDecl)
VarScope->addExtended(Local, ExtendingDecl);
else
VarScope->add(Local, false);
return Local.Offset;
}

Expand Down Expand Up @@ -2833,14 +2833,14 @@ bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) {
if (E->getType()->isVoidType()) {
if (!visit(E))
return false;
return this->emitRetVoid(E);
return this->emitRetVoid(E) && RootScope.destroyLocals();
}

// Expressions with a primitive return type.
if (std::optional<PrimType> T = classify(E)) {
if (!visit(E))
return false;
return this->emitRet(*T, E);
return this->emitRet(*T, E) && RootScope.destroyLocals();
}

// Expressions with a composite return type.
Expand All @@ -2861,7 +2861,7 @@ bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) {
return this->emitRetValue(E) && RootScope.destroyLocals();
}

return false;
return RootScope.destroyLocals();
}

/// Toplevel visitDecl().
Expand Down Expand Up @@ -2952,7 +2952,7 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {

return !Init || initGlobal(*GlobalIndex);
} else {
VariableScope<Emitter> LocalScope(this);
VariableScope<Emitter> LocalScope(this, VD);
if (VarT) {
unsigned Offset = this->allocateLocalPrimitive(
VD, *VarT, VD->getType().isConstQualified());
Expand All @@ -2969,6 +2969,7 @@ bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
return !Init || this->visitLocalInitializer(Init, *Offset);
return false;
}

return true;
}

Expand Down Expand Up @@ -3050,7 +3051,7 @@ bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {

// Non-primitive return type. Prepare storage.
if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {
std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/false);
std::optional<unsigned> LocalIndex = allocateLocal(E);
if (!LocalIndex)
return false;
if (!this->emitGetPtrLocal(*LocalIndex, E))
Expand Down Expand Up @@ -3464,8 +3465,7 @@ bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
std::optional<PrimType> ResT = classify(E);
auto prepareResult = [=]() -> bool {
if (!ResT && !Initializing) {
std::optional<unsigned> LocalIndex =
allocateLocal(SubExpr, /*IsExtended=*/false);
std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
if (!LocalIndex)
return false;
return this->emitGetPtrLocal(*LocalIndex, E);
Expand Down
37 changes: 26 additions & 11 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *E);
bool VisitPseudoObjectExpr(const PseudoObjectExpr *E);
bool VisitPackIndexingExpr(const PackIndexingExpr *E);
bool VisitRecoveryExpr(const RecoveryExpr *E);

protected:
bool visitExpr(const Expr *E) override;
Expand Down Expand Up @@ -234,7 +235,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool IsExtended = false);

/// Allocates a space storing a local given its type.
std::optional<unsigned> allocateLocal(DeclTy &&Decl, bool IsExtended = false);
std::optional<unsigned>
allocateLocal(DeclTy &&Decl, const ValueDecl *ExtendingDecl = nullptr);

private:
friend class VariableScope<Emitter>;
Expand Down Expand Up @@ -321,8 +323,8 @@ extern template class ByteCodeExprGen<EvalEmitter>;
/// Scope chain managing the variable lifetimes.
template <class Emitter> class VariableScope {
public:
VariableScope(ByteCodeExprGen<Emitter> *Ctx)
: Ctx(Ctx), Parent(Ctx->VarScope) {
VariableScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD)
: Ctx(Ctx), Parent(Ctx->VarScope), ValDecl(VD) {
Ctx->VarScope = this;
}

Expand All @@ -345,6 +347,24 @@ template <class Emitter> class VariableScope {
this->Parent->addExtended(Local);
}

void addExtended(const Scope::Local &Local, const ValueDecl *ExtendingDecl) {
// Walk up the chain of scopes until we find the one for ExtendingDecl.
// If there is no such scope, attach it to the parent one.
VariableScope *P = this;
while (P) {
if (P->ValDecl == ExtendingDecl) {
P->addLocal(Local);
return;
}
P = P->Parent;
if (!P)
break;
}

// Use the parent scope.
addExtended(Local);
}

virtual void emitDestruction() {}
virtual bool emitDestructors() { return true; }
VariableScope *getParent() const { return Parent; }
Expand All @@ -354,12 +374,14 @@ template <class Emitter> class VariableScope {
ByteCodeExprGen<Emitter> *Ctx;
/// Link to the parent scope.
VariableScope *Parent;
const ValueDecl *ValDecl = nullptr;
};

/// Generic scope for local variables.
template <class Emitter> class LocalScope : public VariableScope<Emitter> {
public:
LocalScope(ByteCodeExprGen<Emitter> *Ctx) : VariableScope<Emitter>(Ctx) {}
LocalScope(ByteCodeExprGen<Emitter> *Ctx)
: VariableScope<Emitter>(Ctx, nullptr) {}

/// Emit a Destroy op for this scope.
~LocalScope() override {
Expand Down Expand Up @@ -473,16 +495,9 @@ template <class Emitter> class BlockScope final : public AutoScope<Emitter> {
}
};

/// Expression scope which tracks potentially lifetime extended
/// temporaries which are hoisted to the parent scope on exit.
template <class Emitter> class ExprScope final : public AutoScope<Emitter> {
public:
ExprScope(ByteCodeExprGen<Emitter> *Ctx) : AutoScope<Emitter>(Ctx) {}

void addExtended(const Scope::Local &Local) override {
if (this->Parent)
this->Parent->addLocal(Local);
}
};

template <class Emitter> class ArrayIndexScope final {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ EvalEmitter::~EvalEmitter() {

EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
bool ConvertResultToRValue) {
S.setEvalLocation(E->getExprLoc());
this->ConvertResultToRValue = ConvertResultToRValue;
EvalResult.setSource(E);

Expand Down
11 changes: 6 additions & 5 deletions clang/lib/AST/Interp/InterpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,11 @@ Frame *InterpFrame::getCaller() const {
}

SourceRange InterpFrame::getCallRange() const {
if (!Caller->Func)
return S.getRange(nullptr, {});
if (!Caller->Func) {
if (SourceRange NullRange = S.getRange(nullptr, {}); NullRange.isValid())
return NullRange;
return S.EvalLocation;
}
return S.getRange(Caller->Func, RetPC - sizeof(uintptr_t));
}

Expand All @@ -209,10 +212,8 @@ Pointer InterpFrame::getLocalPointer(unsigned Offset) const {

Pointer InterpFrame::getParamPointer(unsigned Off) {
// Return the block if it was created previously.
auto Pt = Params.find(Off);
if (Pt != Params.end()) {
if (auto Pt = Params.find(Off); Pt != Params.end())
return Pointer(reinterpret_cast<Block *>(Pt->second.get()));
}

// Allocate memory to store the parameter and the block metadata.
const auto &Desc = Func->getParamDescriptor(Off);
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/Interp/InterpState.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class InterpState final : public State, public SourceMapper {

Context &getContext() const { return Ctx; }

void setEvalLocation(SourceLocation SL) { this->EvalLocation = SL; }

private:
/// AST Walker state.
State &Parent;
Expand All @@ -115,6 +117,8 @@ class InterpState final : public State, public SourceMapper {
Context &Ctx;
/// The current frame.
InterpFrame *Current = nullptr;
/// Source location of the evaluating expression
SourceLocation EvalLocation;
};

} // namespace interp
Expand Down
148 changes: 148 additions & 0 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ OpenACCClause::child_range OpenACCClause::children() {
#define VISIT_CLAUSE(CLAUSE_NAME) \
case OpenACCClauseKind::CLAUSE_NAME: \
return cast<OpenACC##CLAUSE_NAME##Clause>(this)->children();
#define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME) \
case OpenACCClauseKind::ALIAS_NAME: \
return cast<OpenACC##CLAUSE_NAME##Clause>(this)->children();

#include "clang/Basic/OpenACCClauses.def"
}
Expand Down Expand Up @@ -134,6 +137,88 @@ OpenACCNumGangsClause *OpenACCNumGangsClause::Create(const ASTContext &C,
return new (Mem) OpenACCNumGangsClause(BeginLoc, LParenLoc, IntExprs, EndLoc);
}

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

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

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

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

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

OpenACCCopyInClause *
OpenACCCopyInClause::Create(const ASTContext &C, OpenACCClauseKind Spelling,
SourceLocation BeginLoc, SourceLocation LParenLoc,
bool IsReadOnly, ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
void *Mem =
C.Allocate(OpenACCCopyInClause::totalSizeToAlloc<Expr *>(VarList.size()));
return new (Mem) OpenACCCopyInClause(Spelling, BeginLoc, LParenLoc,
IsReadOnly, VarList, EndLoc);
}

OpenACCCopyOutClause *
OpenACCCopyOutClause::Create(const ASTContext &C, OpenACCClauseKind Spelling,
SourceLocation BeginLoc, SourceLocation LParenLoc,
bool IsZero, ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
void *Mem = C.Allocate(
OpenACCCopyOutClause::totalSizeToAlloc<Expr *>(VarList.size()));
return new (Mem) OpenACCCopyOutClause(Spelling, BeginLoc, LParenLoc, IsZero,
VarList, EndLoc);
}

OpenACCCreateClause *
OpenACCCreateClause::Create(const ASTContext &C, OpenACCClauseKind Spelling,
SourceLocation BeginLoc, SourceLocation LParenLoc,
bool IsZero, ArrayRef<Expr *> VarList,
SourceLocation EndLoc) {
void *Mem =
C.Allocate(OpenACCCreateClause::totalSizeToAlloc<Expr *>(VarList.size()));
return new (Mem) OpenACCCreateClause(Spelling, BeginLoc, LParenLoc, IsZero,
VarList, EndLoc);
}

//===----------------------------------------------------------------------===//
// OpenACC clauses printing methods
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -181,3 +266,66 @@ void OpenACCClausePrinter::VisitVectorLengthClause(
printExpr(C.getIntExpr());
OS << ")";
}

void OpenACCClausePrinter::VisitPrivateClause(const OpenACCPrivateClause &C) {
OS << "private(";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitFirstPrivateClause(
const OpenACCFirstPrivateClause &C) {
OS << "firstprivate(";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitNoCreateClause(const OpenACCNoCreateClause &C) {
OS << "no_create(";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitPresentClause(const OpenACCPresentClause &C) {
OS << "present(";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitCopyClause(const OpenACCCopyClause &C) {
OS << C.getClauseKind() << '(';
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitCopyInClause(const OpenACCCopyInClause &C) {
OS << C.getClauseKind() << '(';
if (C.isReadOnly())
OS << "readonly: ";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitCopyOutClause(const OpenACCCopyOutClause &C) {
OS << C.getClauseKind() << '(';
if (C.isZero())
OS << "zero: ";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}

void OpenACCClausePrinter::VisitCreateClause(const OpenACCCreateClause &C) {
OS << C.getClauseKind() << '(';
if (C.isZero())
OS << "zero: ";
llvm::interleaveComma(C.getVarList(), OS,
[&](const Expr *E) { printExpr(E); });
OS << ")";
}
46 changes: 46 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2492,6 +2492,28 @@ void OpenACCClauseProfiler::VisitIfClause(const OpenACCIfClause &Clause) {
Profiler.VisitStmt(Clause.getConditionExpr());
}

void OpenACCClauseProfiler::VisitCopyClause(const OpenACCCopyClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}
void OpenACCClauseProfiler::VisitCopyInClause(
const OpenACCCopyInClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitCopyOutClause(
const OpenACCCopyOutClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitCreateClause(
const OpenACCCreateClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitSelfClause(const OpenACCSelfClause &Clause) {
if (Clause.hasConditionExpr())
Profiler.VisitStmt(Clause.getConditionExpr());
Expand All @@ -2509,6 +2531,30 @@ void OpenACCClauseProfiler::VisitNumWorkersClause(
Profiler.VisitStmt(Clause.getIntExpr());
}

void OpenACCClauseProfiler::VisitPrivateClause(
const OpenACCPrivateClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitFirstPrivateClause(
const OpenACCFirstPrivateClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitNoCreateClause(
const OpenACCNoCreateClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitPresentClause(
const OpenACCPresentClause &Clause) {
for (auto *E : Clause.getVarList())
Profiler.VisitStmt(E);
}

void OpenACCClauseProfiler::VisitVectorLengthClause(
const OpenACCVectorLengthClause &Clause) {
assert(Clause.hasIntExpr() &&
Expand Down
30 changes: 29 additions & 1 deletion clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,15 +397,43 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::Default:
OS << '(' << cast<OpenACCDefaultClause>(C)->getDefaultClauseKind() << ')';
break;
case OpenACCClauseKind::Copy:
case OpenACCClauseKind::PCopy:
case OpenACCClauseKind::PresentOrCopy:
case OpenACCClauseKind::If:
case OpenACCClauseKind::Self:
case OpenACCClauseKind::FirstPrivate:
case OpenACCClauseKind::NoCreate:
case OpenACCClauseKind::NumGangs:
case OpenACCClauseKind::NumWorkers:
case OpenACCClauseKind::Present:
case OpenACCClauseKind::Private:
case OpenACCClauseKind::Self:
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.
OS << " clause";
break;
case OpenACCClauseKind::CopyIn:
case OpenACCClauseKind::PCopyIn:
case OpenACCClauseKind::PresentOrCopyIn:
OS << " clause";
if (cast<OpenACCCopyInClause>(C)->isReadOnly())
OS << " : readonly";
break;
case OpenACCClauseKind::CopyOut:
case OpenACCClauseKind::PCopyOut:
case OpenACCClauseKind::PresentOrCopyOut:
OS << " clause";
if (cast<OpenACCCopyOutClause>(C)->isZero())
OS << " : zero";
break;
case OpenACCClauseKind::Create:
case OpenACCClauseKind::PCreate:
case OpenACCClauseKind::PresentOrCreate:
OS << " clause";
if (cast<OpenACCCreateClause>(C)->isZero())
OS << " : zero";
break;
default:
// Nothing to do here.
break;
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Analysis/ExprMutationAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,17 @@ const Stmt *ExprMutationAnalyzer::Analyzer::findMutationMemoized(
if (Memoized != MemoizedResults.end())
return Memoized->second;

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

for (const auto &Finder : Finders) {
if (const Stmt *S = (this->*Finder)(Exp))
return MemoizedResults[Exp] = S;
}

return MemoizedResults[Exp] = nullptr;
return nullptr;
}

const Stmt *
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ add_clang_library(clangBasic
DEPENDS
omp_gen
ClangDriverOptions
# These generated headers are included transitively.
ARMTargetParserTableGen
AArch64TargetParserTableGen
)

target_link_libraries(clangBasic
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Basic/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,16 @@ void TargetInfo::adjust(DiagnosticsEngine &Diags, LangOptions &Opts) {
LongDoubleAlign = 64;
}

// HLSL explicitly defines the sizes and formats of some data types, and we
// need to conform to those regardless of what architecture you are targeting.
if (Opts.HLSL) {
LongWidth = LongAlign = 64;
if (!Opts.NativeHalfType) {
HalfFormat = &llvm::APFloat::IEEEsingle();
HalfWidth = HalfAlign = 32;
}
}

if (Opts.OpenCL) {
// OpenCL C requires specific widths for types, irrespective of
// what these normally are for the target.
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Basic/Targets/DirectX.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ class LLVM_LIBRARY_VISIBILITY DirectXTargetInfo : public TargetInfo {
: TargetInfo(Triple) {
TLSSupported = false;
VLASupported = false;
LongWidth = LongAlign = 64;
AddrSpaceMap = &DirectXAddrSpaceMap;
UseAddrSpaceMapMangling = true;
HasLegalHalfType = true;
Expand Down
15 changes: 14 additions & 1 deletion clang/lib/Basic/Targets/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,19 @@ ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {
}

bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
llvm::Triple Triple = getTriple();
if (Triple.isOSAIX()) {
#define PPC_AIX_FEATURE(NAME, DESC, SUPPORT_METHOD, INDEX, MASK, COMP_OP, \
VALUE) \
.Case(NAME, true)
return llvm::StringSwitch<bool>(FeatureStr)
#include "llvm/TargetParser/PPCTargetParser.def"
.Default(false);
}

assert(Triple.isOSLinux() &&
"__builtin_cpu_supports() is only supported for AIX and Linux.");

#define PPC_LNX_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) .Case(NAME, true)
return llvm::StringSwitch<bool>(FeatureStr)
#include "llvm/TargetParser/PPCTargetParser.def"
Expand All @@ -910,7 +923,7 @@ bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
bool PPCTargetInfo::validateCpuIs(StringRef CPUName) const {
llvm::Triple Triple = getTriple();
if (Triple.isOSAIX()) {
#define PPC_AIX_CPU(NAME, SUPPORT, INDEX, OP, VALUE) .Case(NAME, true)
#define PPC_AIX_CPU(NAME, SUPPORT_METHOD, INDEX, OP, VALUE) .Case(NAME, true)
return llvm::StringSwitch<bool>(CPUName)
#include "llvm/TargetParser/PPCTargetParser.def"
.Default(false);
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/Basic/Targets/PPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,14 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
// have Glibc since it is Glibc that provides the HWCAP[2] in the auxv.
static constexpr int MINIMUM_AIX_OS_MAJOR = 7;
static constexpr int MINIMUM_AIX_OS_MINOR = 2;
bool supportsCpuSupports() const override { return getTriple().isOSGlibc(); }
bool supportsCpuSupports() const override {
llvm::Triple Triple = getTriple();
// AIX 7.2 is the minimum requirement to support __builtin_cpu_supports().
return Triple.isOSGlibc() ||
(Triple.isOSAIX() &&
!Triple.isOSVersionLT(MINIMUM_AIX_OS_MAJOR, MINIMUM_AIX_OS_MINOR));
}

bool supportsCpuIs() const override {
llvm::Triple Triple = getTriple();
// AIX 7.2 is the minimum requirement to support __builtin_cpu_is().
Expand Down
170 changes: 86 additions & 84 deletions clang/lib/Basic/Targets/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,20 @@ bool WebAssemblyTargetInfo::setABI(const std::string &Name) {

bool WebAssemblyTargetInfo::hasFeature(StringRef Feature) const {
return llvm::StringSwitch<bool>(Feature)
.Case("simd128", SIMDLevel >= SIMD128)
.Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
.Case("atomics", HasAtomics)
.Case("bulk-memory", HasBulkMemory)
.Case("exception-handling", HasExceptionHandling)
.Case("extended-const", HasExtendedConst)
.Case("half-precision", HasHalfPrecision)
.Case("multimemory", HasMultiMemory)
.Case("multivalue", HasMultivalue)
.Case("mutable-globals", HasMutableGlobals)
.Case("nontrapping-fptoint", HasNontrappingFPToInt)
.Case("reference-types", HasReferenceTypes)
.Case("relaxed-simd", SIMDLevel >= RelaxedSIMD)
.Case("sign-ext", HasSignExt)
.Case("exception-handling", HasExceptionHandling)
.Case("bulk-memory", HasBulkMemory)
.Case("atomics", HasAtomics)
.Case("mutable-globals", HasMutableGlobals)
.Case("multivalue", HasMultivalue)
.Case("simd128", SIMDLevel >= SIMD128)
.Case("tail-call", HasTailCall)
.Case("reference-types", HasReferenceTypes)
.Case("extended-const", HasExtendedConst)
.Case("multimemory", HasMultiMemory)
.Default(false);
}

Expand All @@ -74,32 +74,34 @@ void WebAssemblyTargetInfo::fillValidCPUList(
void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
defineCPUMacros(Builder, "wasm", /*Tuning=*/false);
if (SIMDLevel >= SIMD128)
Builder.defineMacro("__wasm_simd128__");
if (SIMDLevel >= RelaxedSIMD)
Builder.defineMacro("__wasm_relaxed_simd__");
if (HasNontrappingFPToInt)
Builder.defineMacro("__wasm_nontrapping_fptoint__");
if (HasSignExt)
Builder.defineMacro("__wasm_sign_ext__");
if (HasExceptionHandling)
Builder.defineMacro("__wasm_exception_handling__");
if (HasBulkMemory)
Builder.defineMacro("__wasm_bulk_memory__");
if (HasAtomics)
Builder.defineMacro("__wasm_atomics__");
if (HasMutableGlobals)
Builder.defineMacro("__wasm_mutable_globals__");
if (HasMultivalue)
Builder.defineMacro("__wasm_multivalue__");
if (HasTailCall)
Builder.defineMacro("__wasm_tail_call__");
if (HasReferenceTypes)
Builder.defineMacro("__wasm_reference_types__");
if (HasBulkMemory)
Builder.defineMacro("__wasm_bulk_memory__");
if (HasExceptionHandling)
Builder.defineMacro("__wasm_exception_handling__");
if (HasExtendedConst)
Builder.defineMacro("__wasm_extended_const__");
if (HasMultiMemory)
Builder.defineMacro("__wasm_multimemory__");
if (HasHalfPrecision)
Builder.defineMacro("__wasm_half_precision__");
if (HasMultivalue)
Builder.defineMacro("__wasm_multivalue__");
if (HasMutableGlobals)
Builder.defineMacro("__wasm_mutable_globals__");
if (HasNontrappingFPToInt)
Builder.defineMacro("__wasm_nontrapping_fptoint__");
if (HasReferenceTypes)
Builder.defineMacro("__wasm_reference_types__");
if (SIMDLevel >= RelaxedSIMD)
Builder.defineMacro("__wasm_relaxed_simd__");
if (HasSignExt)
Builder.defineMacro("__wasm_sign_ext__");
if (SIMDLevel >= SIMD128)
Builder.defineMacro("__wasm_simd128__");
if (HasTailCall)
Builder.defineMacro("__wasm_tail_call__");

Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
Expand Down Expand Up @@ -151,17 +153,17 @@ bool WebAssemblyTargetInfo::initFeatureMap(
auto addGenericFeatures = [&]() {
Features["multivalue"] = true;
Features["mutable-globals"] = true;
Features["reference-types"] = true;
Features["sign-ext"] = true;
};
auto addBleedingEdgeFeatures = [&]() {
addGenericFeatures();
Features["atomics"] = true;
Features["bulk-memory"] = true;
Features["half-precision"] = true;
Features["multimemory"] = true;
Features["nontrapping-fptoint"] = true;
Features["reference-types"] = true;
Features["tail-call"] = true;
Features["half-precision"] = true;
setSIMDLevel(Features, SIMD128, true);
};
if (CPU == "generic") {
Expand All @@ -176,36 +178,20 @@ bool WebAssemblyTargetInfo::initFeatureMap(
bool WebAssemblyTargetInfo::handleTargetFeatures(
std::vector<std::string> &Features, DiagnosticsEngine &Diags) {
for (const auto &Feature : Features) {
if (Feature == "+simd128") {
SIMDLevel = std::max(SIMDLevel, SIMD128);
continue;
}
if (Feature == "-simd128") {
SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
continue;
}
if (Feature == "+relaxed-simd") {
SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
continue;
}
if (Feature == "-relaxed-simd") {
SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));
continue;
}
if (Feature == "+nontrapping-fptoint") {
HasNontrappingFPToInt = true;
if (Feature == "+atomics") {
HasAtomics = true;
continue;
}
if (Feature == "-nontrapping-fptoint") {
HasNontrappingFPToInt = false;
if (Feature == "-atomics") {
HasAtomics = false;
continue;
}
if (Feature == "+sign-ext") {
HasSignExt = true;
if (Feature == "+bulk-memory") {
HasBulkMemory = true;
continue;
}
if (Feature == "-sign-ext") {
HasSignExt = false;
if (Feature == "-bulk-memory") {
HasBulkMemory = false;
continue;
}
if (Feature == "+exception-handling") {
Expand All @@ -216,12 +202,12 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
HasExceptionHandling = false;
continue;
}
if (Feature == "+bulk-memory") {
HasBulkMemory = true;
if (Feature == "+extended-const") {
HasExtendedConst = true;
continue;
}
if (Feature == "-bulk-memory") {
HasBulkMemory = false;
if (Feature == "-extended-const") {
HasExtendedConst = false;
continue;
}
if (Feature == "+half-precision") {
Expand All @@ -233,20 +219,12 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
HasHalfPrecision = false;
continue;
}
if (Feature == "+atomics") {
HasAtomics = true;
continue;
}
if (Feature == "-atomics") {
HasAtomics = false;
continue;
}
if (Feature == "+mutable-globals") {
HasMutableGlobals = true;
if (Feature == "+multimemory") {
HasMultiMemory = true;
continue;
}
if (Feature == "-mutable-globals") {
HasMutableGlobals = false;
if (Feature == "-multimemory") {
HasMultiMemory = false;
continue;
}
if (Feature == "+multivalue") {
Expand All @@ -257,12 +235,20 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
HasMultivalue = false;
continue;
}
if (Feature == "+tail-call") {
HasTailCall = true;
if (Feature == "+mutable-globals") {
HasMutableGlobals = true;
continue;
}
if (Feature == "-tail-call") {
HasTailCall = false;
if (Feature == "-mutable-globals") {
HasMutableGlobals = false;
continue;
}
if (Feature == "+nontrapping-fptoint") {
HasNontrappingFPToInt = true;
continue;
}
if (Feature == "-nontrapping-fptoint") {
HasNontrappingFPToInt = false;
continue;
}
if (Feature == "+reference-types") {
Expand All @@ -273,20 +259,36 @@ bool WebAssemblyTargetInfo::handleTargetFeatures(
HasReferenceTypes = false;
continue;
}
if (Feature == "+extended-const") {
HasExtendedConst = true;
if (Feature == "+relaxed-simd") {
SIMDLevel = std::max(SIMDLevel, RelaxedSIMD);
continue;
}
if (Feature == "-extended-const") {
HasExtendedConst = false;
if (Feature == "-relaxed-simd") {
SIMDLevel = std::min(SIMDLevel, SIMDEnum(RelaxedSIMD - 1));
continue;
}
if (Feature == "+multimemory") {
HasMultiMemory = true;
if (Feature == "+sign-ext") {
HasSignExt = true;
continue;
}
if (Feature == "-multimemory") {
HasMultiMemory = false;
if (Feature == "-sign-ext") {
HasSignExt = false;
continue;
}
if (Feature == "+simd128") {
SIMDLevel = std::max(SIMDLevel, SIMD128);
continue;
}
if (Feature == "-simd128") {
SIMDLevel = std::min(SIMDLevel, SIMDEnum(SIMD128 - 1));
continue;
}
if (Feature == "+tail-call") {
HasTailCall = true;
continue;
}
if (Feature == "-tail-call") {
HasTailCall = false;
continue;
}

Expand Down
18 changes: 9 additions & 9 deletions clang/lib/Basic/Targets/WebAssembly.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,18 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyTargetInfo : public TargetInfo {
RelaxedSIMD,
} SIMDLevel = NoSIMD;

bool HasNontrappingFPToInt = false;
bool HasSignExt = false;
bool HasExceptionHandling = false;
bool HasBulkMemory = false;
bool HasAtomics = false;
bool HasMutableGlobals = false;
bool HasMultivalue = false;
bool HasTailCall = false;
bool HasReferenceTypes = false;
bool HasBulkMemory = false;
bool HasExceptionHandling = false;
bool HasExtendedConst = false;
bool HasMultiMemory = false;
bool HasHalfPrecision = false;
bool HasMultiMemory = false;
bool HasMultivalue = false;
bool HasMutableGlobals = false;
bool HasNontrappingFPToInt = false;
bool HasReferenceTypes = false;
bool HasSignExt = false;
bool HasTailCall = false;

std::string ABI;

Expand Down
107 changes: 76 additions & 31 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3239,8 +3239,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Builder.getInt1(HasFallback || getTarget().isCLZForZeroUndef());
Value *Result = Builder.CreateCall(F, {ArgValue, ZeroUndef});
if (Result->getType() != ResultType)
Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
"cast");
Result =
Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false, "cast");
if (!HasFallback)
return RValue::get(Result);

Expand Down Expand Up @@ -3271,8 +3271,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Builder.getInt1(HasFallback || getTarget().isCLZForZeroUndef());
Value *Result = Builder.CreateCall(F, {ArgValue, ZeroUndef});
if (Result->getType() != ResultType)
Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
"cast");
Result =
Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false, "cast");
if (!HasFallback)
return RValue::get(Result);

Expand Down Expand Up @@ -3351,8 +3351,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Type *ResultType = ConvertType(E->getType());
Value *Result = Builder.CreateCall(F, ArgValue);
if (Result->getType() != ResultType)
Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
"cast");
Result =
Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false, "cast");
return RValue::get(Result);
}
case Builtin::BI__builtin_unpredictable: {
Expand Down Expand Up @@ -16783,32 +16783,53 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,

#include "llvm/TargetParser/PPCTargetParser.def"
auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx,
unsigned CompOp,
unsigned Mask, CmpInst::Predicate CompOp,
unsigned OpValue) -> Value * {
if (SupportMethod == AIX_BUILTIN_PPC_FALSE)
return llvm::ConstantInt::getFalse(ConvertType(E->getType()));

if (SupportMethod == AIX_BUILTIN_PPC_TRUE)
return llvm::ConstantInt::getTrue(ConvertType(E->getType()));

assert(SupportMethod <= USE_SYS_CONF && "Invalid value for SupportMethod.");
assert((CompOp == COMP_EQ) && "Only equal comparisons are supported.");
assert(SupportMethod <= SYS_CALL && "Invalid value for SupportMethod.");

llvm::Value *FieldValue = nullptr;
if (SupportMethod == USE_SYS_CONF) {
llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE);
llvm::Constant *SysConf =
CGM.CreateRuntimeVariable(STy, "_system_configuration");

// Grab the appropriate field from _system_configuration.
llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
ConstantInt::get(Int32Ty, FieldIdx)};

FieldValue = Builder.CreateGEP(STy, SysConf, Idxs);
FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue,
CharUnits::fromQuantity(4));
} else if (SupportMethod == SYS_CALL) {
llvm::FunctionType *FTy =
llvm::FunctionType::get(Int64Ty, Int32Ty, false);
llvm::FunctionCallee Func =
CGM.CreateRuntimeFunction(FTy, "getsystemcfg");

FieldValue =
Builder.CreateCall(Func, {ConstantInt::get(Int32Ty, FieldIdx)});
}
assert(FieldValue &&
"SupportMethod value is not defined in PPCTargetParser.def.");

llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE);
llvm::Constant *SysConf =
CGM.CreateRuntimeVariable(STy, "_system_configuration");
if (Mask)
FieldValue = Builder.CreateAnd(FieldValue, Mask);

// Grab the appropriate field from _system_configuration.
llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
ConstantInt::get(Int32Ty, FieldIdx)};
llvm::Type *ValueType = FieldValue->getType();
bool IsValueType64Bit = ValueType->isIntegerTy(64);
assert(
(IsValueType64Bit || ValueType->isIntegerTy(32)) &&
"Only 32/64-bit integers are supported in GenAIXPPCBuiltinCpuExpr().");

llvm::Value *FieldValue = Builder.CreateGEP(STy, SysConf, Idxs);
FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue,
CharUnits::fromQuantity(4));
assert(FieldValue->getType()->isIntegerTy(32) &&
"Only 32-bit integers are supported in GenAIXPPCBuiltinCpuExpr().");
return Builder.CreateICmp(ICmpInst::ICMP_EQ, FieldValue,
ConstantInt::get(Int32Ty, OpValue));
return Builder.CreateICmp(
CompOp, FieldValue,
ConstantInt::get(IsValueType64Bit ? Int64Ty : Int32Ty, OpValue));
};

switch (BuiltinID) {
Expand All @@ -16820,15 +16841,18 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
llvm::Triple Triple = getTarget().getTriple();

if (Triple.isOSAIX()) {
unsigned IsCpuSupport, FieldIdx, CompareOp, CpuIdValue;
typedef std::tuple<unsigned, unsigned, unsigned, unsigned> CPUType;
std::tie(IsCpuSupport, FieldIdx, CompareOp, CpuIdValue) =
unsigned SupportMethod, FieldIdx, CpuIdValue;
CmpInst::Predicate CompareOp;
typedef std::tuple<unsigned, unsigned, CmpInst::Predicate, unsigned>
CPUType;
std::tie(SupportMethod, FieldIdx, CompareOp, CpuIdValue) =
static_cast<CPUType>(StringSwitch<CPUType>(CPUStr)
#define PPC_AIX_CPU(NAME, SUPPORT_MAGIC, INDEX, COMPARE_OP, VALUE) \
.Case(NAME, {SUPPORT_MAGIC, INDEX, COMPARE_OP, VALUE})
#define PPC_AIX_CPU(NAME, SUPPORT_METHOD, INDEX, COMPARE_OP, VALUE) \
.Case(NAME, {SUPPORT_METHOD, INDEX, COMPARE_OP, VALUE})
#include "llvm/TargetParser/PPCTargetParser.def"
);
return GenAIXPPCBuiltinCpuExpr(IsCpuSupport, FieldIdx, CompareOp,
.Default({AIX_BUILTIN_PPC_FALSE, 0,
CmpInst::Predicate(), 0}));
return GenAIXPPCBuiltinCpuExpr(SupportMethod, FieldIdx, 0, CompareOp,
CpuIdValue);
}

Expand All @@ -16846,10 +16870,31 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
llvm::ConstantInt::get(Int32Ty, NumCPUID));
}
case Builtin::BI__builtin_cpu_supports: {
unsigned FeatureWord;
unsigned BitMask;
llvm::Triple Triple = getTarget().getTriple();
const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
if (Triple.isOSAIX()) {
unsigned SupportMethod, FieldIdx, Mask, Value;
CmpInst::Predicate CompOp;
typedef std::tuple<unsigned, unsigned, unsigned, CmpInst::Predicate,
unsigned>
CPUSupportType;
std::tie(SupportMethod, FieldIdx, Mask, CompOp, Value) =
static_cast<CPUSupportType>(StringSwitch<CPUSupportType>(CPUStr)
#define PPC_AIX_FEATURE(NAME, DESC, SUPPORT_METHOD, INDEX, MASK, COMP_OP, \
VALUE) \
.Case(NAME, {SUPPORT_METHOD, INDEX, MASK, COMP_OP, VALUE})
#include "llvm/TargetParser/PPCTargetParser.def"
.Default({AIX_BUILTIN_PPC_FALSE, 0, 0,
CmpInst::Predicate(), 0}));
return GenAIXPPCBuiltinCpuExpr(SupportMethod, FieldIdx, Mask, CompOp,
Value);
}

assert(Triple.isOSLinux() &&
"__builtin_cpu_supports() is only supported for AIX and Linux.");
unsigned FeatureWord;
unsigned BitMask;
std::tie(FeatureWord, BitMask) =
StringSwitch<std::pair<unsigned, unsigned>>(CPUStr)
#define PPC_LNX_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD) \
Expand Down
27 changes: 27 additions & 0 deletions clang/lib/CodeGen/CGCUDANV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,33 @@ void CGNVCUDARuntime::emitDeviceStubBodyNew(CodeGenFunction &CGF,
CGM.CreateRuntimeFunction(FTy, LaunchKernelName);
CGF.EmitCall(FI, CGCallee::forDirect(cudaLaunchKernelFn), ReturnValueSlot(),
LaunchKernelArgs);

// To prevent CUDA device stub functions from being merged by ICF in MSVC
// environment, create an unique global variable for each kernel and write to
// the variable in the device stub.
if (CGM.getContext().getTargetInfo().getCXXABI().isMicrosoft() &&
!CGF.getLangOpts().HIP) {
llvm::Function *KernelFunction = llvm::cast<llvm::Function>(Kernel);
std::string GlobalVarName = (KernelFunction->getName() + ".id").str();

llvm::GlobalVariable *HandleVar =
CGM.getModule().getNamedGlobal(GlobalVarName);
if (!HandleVar) {
HandleVar = new llvm::GlobalVariable(
CGM.getModule(), CGM.Int8Ty,
/*Constant=*/false, KernelFunction->getLinkage(),
llvm::ConstantInt::get(CGM.Int8Ty, 0), GlobalVarName);
HandleVar->setDSOLocal(KernelFunction->isDSOLocal());
HandleVar->setVisibility(KernelFunction->getVisibility());
if (KernelFunction->hasComdat())
HandleVar->setComdat(CGM.getModule().getOrInsertComdat(GlobalVarName));
}

CGF.Builder.CreateAlignedStore(llvm::ConstantInt::get(CGM.Int8Ty, 1),
HandleVar, CharUnits::One(),
/*IsVolatile=*/true);
}

CGF.EmitBranch(EndBlock);

CGF.EmitBlock(EndBlock);
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,20 +537,23 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
elementType.isTriviallyCopyableType(CGF.getContext())) {
CodeGen::CodeGenModule &CGM = CGF.CGM;
ConstantEmitter Emitter(CGF);
LangAS AS = ArrayQTy.getAddressSpace();
QualType GVArrayQTy = CGM.getContext().getAddrSpaceQualType(
CGM.getContext().removeAddrSpaceQualType(ArrayQTy),
CGM.GetGlobalConstantAddressSpace());
LangAS AS = GVArrayQTy.getAddressSpace();
if (llvm::Constant *C =
Emitter.tryEmitForInitializer(ExprToVisit, AS, ArrayQTy)) {
Emitter.tryEmitForInitializer(ExprToVisit, AS, GVArrayQTy)) {
auto GV = new llvm::GlobalVariable(
CGM.getModule(), C->getType(),
/* isConstant= */ true, llvm::GlobalValue::PrivateLinkage, C,
"constinit",
/* InsertBefore= */ nullptr, llvm::GlobalVariable::NotThreadLocal,
CGM.getContext().getTargetAddressSpace(AS));
Emitter.finalize(GV);
CharUnits Align = CGM.getContext().getTypeAlignInChars(ArrayQTy);
CharUnits Align = CGM.getContext().getTypeAlignInChars(GVArrayQTy);
GV->setAlignment(Align.getAsAlign());
Address GVAddr(GV, GV->getValueType(), Align);
EmitFinalDestCopy(ArrayQTy, CGF.MakeAddrLValue(GVAddr, ArrayQTy));
EmitFinalDestCopy(ArrayQTy, CGF.MakeAddrLValue(GVAddr, GVArrayQTy));
return;
}
}
Expand Down
13 changes: 13 additions & 0 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2801,6 +2801,19 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::AtomicOrdering::SequentiallyConsistent);
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
}
// Special case for atomic increment/decrement on floats
if (type->isFloatingType()) {
llvm::AtomicRMWInst::BinOp aop =
isInc ? llvm::AtomicRMWInst::FAdd : llvm::AtomicRMWInst::FSub;
llvm::Instruction::BinaryOps op =
isInc ? llvm::Instruction::FAdd : llvm::Instruction::FSub;
llvm::Value *amt = llvm::ConstantFP::get(
VMContext, llvm::APFloat(static_cast<float>(1.0)));
llvm::Value *old =
Builder.CreateAtomicRMW(aop, LV.getAddress(CGF), amt,
llvm::AtomicOrdering::SequentiallyConsistent);
return isPre ? Builder.CreateBinOp(op, old, amt) : old;
}
value = EmitLoadOfLValue(LV, E->getExprLoc());
input = value;
// For every other atomic operation, we need to emit a load-op-cmpxchg loop
Expand Down
77 changes: 67 additions & 10 deletions clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,69 @@ void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
incrementProfileCounter(&S);
}

bool CodeGenFunction::checkIfLoopMustProgress(const Expr *ControllingExpression,
bool HasEmptyBody) {
if (CGM.getCodeGenOpts().getFiniteLoops() ==
CodeGenOptions::FiniteLoopsKind::Never)
return false;

// Now apply rules for plain C (see 6.8.5.6 in C11).
// Loops with constant conditions do not have to make progress in any C
// version.
// As an extension, we consisider loops whose constant expression
// can be constant-folded.
Expr::EvalResult Result;
bool CondIsConstInt =
!ControllingExpression ||
(ControllingExpression->EvaluateAsInt(Result, getContext()) &&
Result.Val.isInt());

bool CondIsTrue = CondIsConstInt && (!ControllingExpression ||
Result.Val.getInt().getBoolValue());

// Loops with non-constant conditions must make progress in C11 and later.
if (getLangOpts().C11 && !CondIsConstInt)
return true;

// [C++26][intro.progress] (DR)
// The implementation may assume that any thread will eventually do one of the
// following:
// [...]
// - continue execution of a trivial infinite loop ([stmt.iter.general]).
if (CGM.getCodeGenOpts().getFiniteLoops() ==
CodeGenOptions::FiniteLoopsKind::Always ||
getLangOpts().CPlusPlus11) {
if (HasEmptyBody && CondIsTrue) {
CurFn->removeFnAttr(llvm::Attribute::MustProgress);
return false;
}
return true;
}
return false;
}

// [C++26][stmt.iter.general] (DR)
// A trivially empty iteration statement is an iteration statement matching one
// of the following forms:
// - while ( expression ) ;
// - while ( expression ) { }
// - do ; while ( expression ) ;
// - do { } while ( expression ) ;
// - for ( init-statement expression(opt); ) ;
// - for ( init-statement expression(opt); ) { }
template <typename LoopStmt> static bool hasEmptyLoopBody(const LoopStmt &S) {
if constexpr (std::is_same_v<LoopStmt, ForStmt>) {
if (S.getInc())
return false;
}
const Stmt *Body = S.getBody();
if (!Body || isa<NullStmt>(Body))
return true;
if (const CompoundStmt *Compound = dyn_cast<CompoundStmt>(Body))
return Compound->body_empty();
return false;
}

void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
ArrayRef<const Attr *> WhileAttrs) {
// Emit the header for the loop, which will also become
Expand Down Expand Up @@ -942,13 +1005,12 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
// while(1) is common, avoid extra exit blocks. Be sure
// to correctly handle break/continue though.
llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
bool CondIsConstInt = C != nullptr;
bool EmitBoolCondBranch = !CondIsConstInt || !C->isOne();
bool EmitBoolCondBranch = !C || !C->isOne();
const SourceRange &R = S.getSourceRange();
LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), CGM.getCodeGenOpts(),
WhileAttrs, SourceLocToDebugLoc(R.getBegin()),
SourceLocToDebugLoc(R.getEnd()),
checkIfLoopMustProgress(CondIsConstInt));
checkIfLoopMustProgress(S.getCond(), hasEmptyLoopBody(S)));

// When single byte coverage mode is enabled, add a counter to loop condition.
if (llvm::EnableSingleByteCoverage)
Expand Down Expand Up @@ -1059,14 +1121,13 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S,
// "do {} while (0)" is common in macros, avoid extra blocks. Be sure
// to correctly handle break/continue though.
llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal);
bool CondIsConstInt = C;
bool EmitBoolCondBranch = !C || !C->isZero();

const SourceRange &R = S.getSourceRange();
LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
SourceLocToDebugLoc(R.getBegin()),
SourceLocToDebugLoc(R.getEnd()),
checkIfLoopMustProgress(CondIsConstInt));
checkIfLoopMustProgress(S.getCond(), hasEmptyLoopBody(S)));

// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch) {
Expand Down Expand Up @@ -1109,15 +1170,11 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
llvm::BasicBlock *CondBlock = CondDest.getBlock();
EmitBlock(CondBlock);

Expr::EvalResult Result;
bool CondIsConstInt =
!S.getCond() || S.getCond()->EvaluateAsInt(Result, getContext());

const SourceRange &R = S.getSourceRange();
LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs,
SourceLocToDebugLoc(R.getBegin()),
SourceLocToDebugLoc(R.getEnd()),
checkIfLoopMustProgress(CondIsConstInt));
checkIfLoopMustProgress(S.getCond(), hasEmptyLoopBody(S)));

// Create a cleanup scope for the condition variable cleanups.
LexicalScope ConditionScope(*this, S.getSourceRange());
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/CodeGen/CGVTables.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ static void resolveTopLevelMetadata(llvm::Function *Fn,
// they are referencing.
for (auto &BB : *Fn) {
for (auto &I : BB) {
for (llvm::DbgVariableRecord &DVR :
llvm::filterDbgVars(I.getDbgRecordRange())) {
auto *DILocal = DVR.getVariable();
if (!DILocal->isResolved())
DILocal->resolve();
}
if (auto *DII = dyn_cast<llvm::DbgVariableIntrinsic>(&I)) {
auto *DILocal = DII->getVariable();
if (!DILocal->isResolved())
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ add_clang_library(clangCodeGen
DEPENDS
intrinsics_gen
ClangDriverOptions
# These generated headers are included transitively.
ARMTargetParserTableGen
AArch64TargetParserTableGen

LINK_LIBS
clangAST
Expand Down
12 changes: 10 additions & 2 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1471,6 +1471,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,

// Ensure that the function adheres to the forward progress guarantee, which
// is required by certain optimizations.
// In C++11 and up, the attribute will be removed if the body contains a
// trivial empty loop.
if (checkIfFunctionMustProgress())
CurFn->addFnAttr(llvm::Attribute::MustProgress);

Expand Down Expand Up @@ -2759,8 +2761,14 @@ llvm::Value *CodeGenFunction::FormAArch64ResolverCondition(
const MultiVersionResolverOption &RO) {
llvm::SmallVector<StringRef, 8> CondFeatures;
for (const StringRef &Feature : RO.Conditions.Features) {
// Form condition for features which are not yet enabled in target
if (!getContext().getTargetInfo().hasFeature(Feature))
// Optimize the Function Multi Versioning resolver by creating conditions
// only for features that are not enabled in the target. The exception is
// for features whose extension instructions are executed as NOP on targets
// without extension support.
if (!getContext().getTargetInfo().hasFeature(Feature) ||
Feature.equals("bti") || Feature.equals("memtag") ||
Feature.equals("memtag2") || Feature.equals("memtag3") ||
Feature.equals("dgh"))
CondFeatures.push_back(Feature);
}
if (!CondFeatures.empty()) {
Expand Down
27 changes: 4 additions & 23 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -636,28 +636,7 @@ class CodeGenFunction : public CodeGenTypeCache {
/// Returns true if a loop must make progress, which means the mustprogress
/// attribute can be added. \p HasConstantCond indicates whether the branch
/// condition is a known constant.
bool checkIfLoopMustProgress(bool HasConstantCond) {
if (CGM.getCodeGenOpts().getFiniteLoops() ==
CodeGenOptions::FiniteLoopsKind::Always)
return true;
if (CGM.getCodeGenOpts().getFiniteLoops() ==
CodeGenOptions::FiniteLoopsKind::Never)
return false;

// If the containing function must make progress, loops also must make
// progress (as in C++11 and later).
if (checkIfFunctionMustProgress())
return true;

// Now apply rules for plain C (see 6.8.5.6 in C11).
// Loops with constant conditions do not have to make progress in any C
// version.
if (HasConstantCond)
return false;

// Loops with non-constant conditions must make progress in C11 and later.
return getLangOpts().C11;
}
bool checkIfLoopMustProgress(const Expr *, bool HasEmptyBody);

const CodeGen::CGBlockInfo *BlockInfo = nullptr;
llvm::Value *BlockPointer = nullptr;
Expand Down Expand Up @@ -1648,8 +1627,10 @@ class CodeGenFunction : public CodeGenTypeCache {
void incrementProfileCounter(const Stmt *S, llvm::Value *StepV = nullptr) {
if (CGM.getCodeGenOpts().hasProfileClangInstr() &&
!CurFn->hasFnAttribute(llvm::Attribute::NoProfile) &&
!CurFn->hasFnAttribute(llvm::Attribute::SkipProfile))
!CurFn->hasFnAttribute(llvm::Attribute::SkipProfile)) {
auto AL = ApplyDebugLocation::CreateArtificial(*this);
PGO.emitCounterSetOrIncrement(Builder, S, StepV);
}
PGO.setCurrentStmt(S);
}

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ add_clang_library(clangDriver

DEPENDS
ClangDriverOptions
# These generated headers are included transitively.
ARMTargetParserTableGen
AArch64TargetParserTableGen

LINK_LIBS
clangBasic
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/Distro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ static Distro::DistroType DetectLsbRelease(llvm::vfs::FileSystem &VFS) {
.Case("lunar", Distro::UbuntuLunar)
.Case("mantic", Distro::UbuntuMantic)
.Case("noble", Distro::UbuntuNoble)
.Case("oracular", Distro::UbuntuOracular)
.Default(Distro::UnknownDistro);
return Version;
}
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
Arg->claim();
if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {
D.Diag(diag::warn_drv_deprecated_arg)
<< Arg->getAsString(Args) << "-fsanitize-coverage=trace-pc-guard";
<< Arg->getAsString(Args) << /*hasReplacement=*/true
<< "-fsanitize-coverage=trace-pc-guard";
}
continue;
}
Expand Down Expand Up @@ -833,11 +834,11 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// enabled.
if (CoverageFeatures & CoverageTraceBB)
D.Diag(clang::diag::warn_drv_deprecated_arg)
<< "-fsanitize-coverage=trace-bb"
<< "-fsanitize-coverage=trace-bb" << /*hasReplacement=*/true
<< "-fsanitize-coverage=trace-pc-guard";
if (CoverageFeatures & Coverage8bitCounters)
D.Diag(clang::diag::warn_drv_deprecated_arg)
<< "-fsanitize-coverage=8bit-counters"
<< "-fsanitize-coverage=8bit-counters" << /*hasReplacement=*/true
<< "-fsanitize-coverage=trace-pc-guard";
}

Expand All @@ -849,7 +850,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
if ((CoverageFeatures & InsertionPointTypes) &&
!(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {
D.Diag(clang::diag::warn_drv_deprecated_arg)
<< "-fsanitize-coverage=[func|bb|edge]"
<< "-fsanitize-coverage=[func|bb|edge]" << /*hasReplacement=*/true
<< "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["
"control-flow]";
}
Expand Down
20 changes: 11 additions & 9 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3112,8 +3112,6 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
ReciprocalMath = false;
SignedZeros = true;
ApproxFunc = false;
TrappingMath = true;
FPExceptionBehavior = "strict";

if (!JA.isDeviceOffloading(Action::OFK_Cuda) &&
!JA.isOffloading(Action::OFK_HIP)) {
Expand Down Expand Up @@ -6515,7 +6513,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (const Arg *A =
Args.getLastArg(options::OPT_fvisibility_global_new_delete_hidden)) {
D.Diag(diag::warn_drv_deprecated_arg)
<< A->getAsString(Args)
<< A->getAsString(Args) << /*hasReplacement=*/true
<< "-fvisibility-global-new-delete=force-hidden";
}

Expand Down Expand Up @@ -7242,11 +7240,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.addOptOutFlag(CmdArgs, options::OPT_fassume_unique_vtables,
options::OPT_fno_assume_unique_vtables);

// -frelaxed-template-template-args is off by default, as it is a severe
// breaking change until a corresponding change to template partial ordering
// is provided.
Args.addOptInFlag(CmdArgs, options::OPT_frelaxed_template_template_args,
options::OPT_fno_relaxed_template_template_args);
// -frelaxed-template-template-args is deprecated.
if (Arg *A =
Args.getLastArg(options::OPT_frelaxed_template_template_args,
options::OPT_fno_relaxed_template_template_args)) {
D.Diag(diag::warn_drv_deprecated_arg)
<< A->getAsString(Args) << /*hasReplacement=*/false;
if (A->getOption().matches(options::OPT_fno_relaxed_template_template_args))
CmdArgs.push_back("-fno-relaxed-template-template-args");
}

// -fsized-deallocation is off by default, as it is an ABI-breaking change for
// most platforms.
Expand Down Expand Up @@ -8103,7 +8105,7 @@ static EHFlags parseClangCLEHFlags(const Driver &D, const ArgList &Args,

std::vector<std::string> EHArgs =
Args.getAllArgValues(options::OPT__SLASH_EH);
for (auto EHVal : EHArgs) {
for (const auto &EHVal : EHArgs) {
for (size_t I = 0, E = EHVal.size(); I != E; ++I) {
switch (EHVal[I]) {
case 'a':
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/HIPUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ class HIPUndefinedFatBinSymbols {
Verbose(C.getArgs().hasArg(options::OPT_v)) {
populateSymbols();
if (Verbose) {
for (auto Name : FatBinSymbols)
for (const auto &Name : FatBinSymbols)
llvm::errs() << "Found undefined HIP fatbin symbol: " << Name << "\n";
for (auto Name : GPUBinHandleSymbols)
for (const auto &Name : GPUBinHandleSymbols)
llvm::errs() << "Found undefined HIP gpubin handle symbol: " << Name
<< "\n";
}
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3201,10 +3201,11 @@ void UnwrappedLineParser::parseDoWhile() {
void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
nextToken();
unsigned OldLineLevel = Line->Level;
if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
--Line->Level;

if (LeftAlignLabel)
Line->Level = 0;
else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
--Line->Level;

if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
FormatTok->is(tok::l_brace)) {
Expand Down Expand Up @@ -3944,8 +3945,11 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
switch (FormatTok->Tok.getKind()) {
case tok::l_paren:
// We can have macros in between 'class' and the class name.
if (!IsNonMacroIdentifier(Previous))
if (!IsNonMacroIdentifier(Previous) ||
// e.g. `struct macro(a) S { int i; };`
Previous->Previous == &InitialToken) {
parseParens();
}
break;
case tok::coloncolon:
break;
Expand Down
19 changes: 17 additions & 2 deletions clang/lib/Headers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ set(llvm_libc_wrapper_files
llvm_libc_wrappers/time.h
)

set(zos_wrapper_files
zos_wrappers/builtins.h
)

include(GetClangResourceDir)
get_clang_resource_dir(output_dir PREFIX ${LLVM_LIBRARY_OUTPUT_INTDIR}/.. SUBDIR include)
set(out_files)
Expand Down Expand Up @@ -370,7 +374,7 @@ endfunction(clang_generate_header)

# Copy header files from the source directory to the build directory
foreach( f ${files} ${cuda_wrapper_files} ${cuda_wrapper_bits_files}
${ppc_wrapper_files} ${openmp_wrapper_files} ${hlsl_files}
${ppc_wrapper_files} ${openmp_wrapper_files} ${zos_wrapper_files} ${hlsl_files}
${llvm_libc_wrapper_files})
copy_header_to_output_dir(${CMAKE_CURRENT_SOURCE_DIR} ${f})
endforeach( f )
Expand Down Expand Up @@ -487,7 +491,7 @@ add_header_target("mips-resource-headers" "${mips_msa_files}")
add_header_target("ppc-resource-headers" "${ppc_files};${ppc_wrapper_files}")
add_header_target("ppc-htm-resource-headers" "${ppc_htm_files}")
add_header_target("riscv-resource-headers" "${riscv_files};${riscv_generated_files}")
add_header_target("systemz-resource-headers" "${systemz_files}")
add_header_target("systemz-resource-headers" "${systemz_files};${zos_wrapper_files}")
add_header_target("ve-resource-headers" "${ve_files}")
add_header_target("webassembly-resource-headers" "${webassembly_files}")
add_header_target("x86-resource-headers" "${x86_files}")
Expand Down Expand Up @@ -538,6 +542,11 @@ install(
DESTINATION ${header_install_dir}/openmp_wrappers
COMPONENT clang-resource-headers)

install(
FILES ${zos_wrapper_files}
DESTINATION ${header_install_dir}/zos_wrappers
COMPONENT clang-resource-headers)

#############################################################
# Install rules for separate header lists
install(
Expand Down Expand Up @@ -642,6 +651,12 @@ install(
EXCLUDE_FROM_ALL
COMPONENT systemz-resource-headers)

install(
FILES ${zos_wrapper_files}
DESTINATION ${header_install_dir}/zos_wrappers
EXCLUDE_FROM_ALL
COMPONENT systemz-resource-headers)

install(
FILES ${ve_files}
DESTINATION ${header_install_dir}
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Headers/builtins.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@
#ifndef __BUILTINS_H
#define __BUILTINS_H

#if defined(__MVS__) && __has_include_next(<builtins.h>)
#include_next <builtins.h>
#endif /* __MVS__ */
#endif /* __BUILTINS_H */
5 changes: 5 additions & 0 deletions clang/lib/Headers/float.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#ifndef __CLANG_FLOAT_H
#define __CLANG_FLOAT_H

#if defined(__MVS__) && __has_include_next(<float.h>)
#include_next <float.h>
#else

/* If we're on MinGW, fall back to the system's float.h, which might have
* additional definitions provided for Windows.
* For more details see http://msdn.microsoft.com/en-us/library/y0ybw9fy.aspx
Expand Down Expand Up @@ -165,4 +169,5 @@
# define FLT16_TRUE_MIN __FLT16_TRUE_MIN__
#endif /* __STDC_WANT_IEC_60559_TYPES_EXT__ */

#endif /* __MVS__ */
#endif /* __CLANG_FLOAT_H */
4 changes: 4 additions & 0 deletions clang/lib/Headers/inttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#if !defined(_AIX) || !defined(_STD_TYPES_T)
#define __CLANG_INTTYPES_H
#endif
#if defined(__MVS__) && __has_include_next(<inttypes.h>)
#include_next <inttypes.h>
#else

#if defined(_MSC_VER) && _MSC_VER < 1800
#error MSVC does not have inttypes.h prior to Visual Studio 2013
Expand Down Expand Up @@ -94,4 +97,5 @@
#define SCNxFAST32 "x"
#endif

#endif /* __MVS__ */
#endif /* __CLANG_INTTYPES_H */
4 changes: 4 additions & 0 deletions clang/lib/Headers/iso646.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@

#ifndef __ISO646_H
#define __ISO646_H
#if defined(__MVS__) && __has_include_next(<iso646.h>)
#include_next <iso646.h>
#else

#ifndef __cplusplus
#define and &&
Expand All @@ -24,4 +27,5 @@
#define xor_eq ^=
#endif

#endif /* __MVS__ */
#endif /* __ISO646_H */
5 changes: 5 additions & 0 deletions clang/lib/Headers/limits.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#ifndef __CLANG_LIMITS_H
#define __CLANG_LIMITS_H

#if defined(__MVS__) && __has_include_next(<limits.h>)
#include_next <limits.h>
#else

/* The system's limits.h may, in turn, try to #include_next GCC's limits.h.
Avert this #include_next madness. */
#if defined __GNUC__ && !defined _GCC_LIMITS_H_
Expand Down Expand Up @@ -122,4 +126,5 @@
#define ULONG_LONG_MAX (__LONG_LONG_MAX__*2ULL+1ULL)
#endif

#endif /* __MVS__ */
#endif /* __CLANG_LIMITS_H */
5 changes: 5 additions & 0 deletions clang/lib/Headers/stdalign.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#ifndef __STDALIGN_H
#define __STDALIGN_H

#if defined(__MVS__) && __has_include_next(<stdalign.h>)
#include_next <stdalign.h>
#else

#if defined(__cplusplus) || \
(defined(__STDC_VERSION__) && __STDC_VERSION__ < 202311L)
#ifndef __cplusplus
Expand All @@ -21,4 +25,5 @@
#define __alignof_is_defined 1
#endif /* __STDC_VERSION__ */

#endif /* __MVS__ */
#endif /* __STDALIGN_H */
12 changes: 12 additions & 0 deletions clang/lib/Headers/stdarg.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@
defined(__need_va_arg) || defined(__need___va_copy) || \
defined(__need_va_copy)

#if defined(__MVS__) && __has_include_next(<stdarg.h>)
#define __STDARG_H
#undef __need___va_list
#undef __need_va_list
#undef __need_va_arg
#undef __need___va_copy
#undef __need_va_copy
#include_next <stdarg.h>

#else
#if !defined(__need___va_list) && !defined(__need_va_list) && \
!defined(__need_va_arg) && !defined(__need___va_copy) && \
!defined(__need_va_copy)
Expand Down Expand Up @@ -76,4 +86,6 @@
#undef __need_va_copy
#endif /* defined(__need_va_copy) */

#endif /* __MVS__ */

#endif
5 changes: 5 additions & 0 deletions clang/lib/Headers/stdbool.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

#define __bool_true_false_are_defined 1

#if defined(__MVS__) && __has_include_next(<stdbool.h>)
#include_next <stdbool.h>
#else

#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L
/* FIXME: We should be issuing a deprecation warning here, but cannot yet due
* to system headers which include this header file unconditionally.
Expand All @@ -31,4 +35,5 @@
#endif
#endif

#endif /* __MVS__ */
#endif /* __STDBOOL_H */
17 changes: 17 additions & 0 deletions clang/lib/Headers/stddef.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,22 @@
defined(__need_unreachable) || defined(__need_max_align_t) || \
defined(__need_offsetof) || defined(__need_wint_t)

#if defined(__MVS__) && __has_include_next(<stddef.h>)
#define __STDDEF_H
#undef __need_ptrdiff_t
#undef __need_size_t
#undef __need_rsize_t
#undef __need_wchar_t
#undef __need_NULL
#undef __need_nullptr_t
#undef __need_unreachable
#undef __need_max_align_t
#undef __need_offsetof
#undef __need_wint_t
#include_next <stddef.h>

#else

#if !defined(__need_ptrdiff_t) && !defined(__need_size_t) && \
!defined(__need_rsize_t) && !defined(__need_wchar_t) && \
!defined(__need_NULL) && !defined(__need_nullptr_t) && \
Expand Down Expand Up @@ -120,4 +136,5 @@ __WINT_TYPE__ directly; accommodate both by requiring __need_wint_t */
#undef __need_wint_t
#endif /* __need_wint_t */

#endif /* __MVS__ */
#endif
5 changes: 5 additions & 0 deletions clang/lib/Headers/stdint.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
#define __CLANG_STDINT_H
#endif

#if defined(__MVS__) && __has_include_next(<stdint.h>)
#include_next <stdint.h>
#else

/* If we're hosted, fall back to the system's stdint.h, which might have
* additional definitions.
*/
Expand Down Expand Up @@ -947,4 +951,5 @@ typedef __UINTMAX_TYPE__ uintmax_t;
#endif

#endif /* __STDC_HOSTED__ */
#endif /* __MVS__ */
#endif /* __CLANG_STDINT_H */
6 changes: 6 additions & 0 deletions clang/lib/Headers/stdnoreturn.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@
#ifndef __STDNORETURN_H
#define __STDNORETURN_H

#if defined(__MVS__) && __has_include_next(<stdnoreturn.h>)
#include_next <stdnoreturn.h>
#else

#define noreturn _Noreturn
#define __noreturn_is_defined 1

#endif /* __MVS__ */

#if (defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L) && \
!defined(_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS)
/* The noreturn macro is deprecated in C23. We do not mark it as such because
Expand Down
6 changes: 5 additions & 1 deletion clang/lib/Headers/varargs.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,9 @@
*/
#ifndef __VARARGS_H
#define __VARARGS_H
#error "Please use <stdarg.h> instead of <varargs.h>"
#if defined(__MVS__) && __has_include_next(<varargs.h>)
#include_next <varargs.h>
#else
#error "Please use <stdarg.h> instead of <varargs.h>"
#endif /* __MVS__ */
#endif
18 changes: 18 additions & 0 deletions clang/lib/Headers/zos_wrappers/builtins.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*===---- builtins.h - z/Architecture Builtin Functions --------------------===
*
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
*===-----------------------------------------------------------------------===
*/

#ifndef __ZOS_WRAPPERS_BUILTINS_H
#define __ZOS_WRAPPERS_BUILTINS_H
#if defined(__MVS__)
#include_next <builtins.h>
#if defined(__VEC__)
#include <vecintrin.h>
#endif
#endif /* defined(__MVS__) */
#endif /* __ZOS_WRAPPERS_BUILTINS_H */
10 changes: 9 additions & 1 deletion clang/lib/InstallAPI/FileList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class Implementation {

public:
std::unique_ptr<MemoryBuffer> InputBuffer;
clang::FileManager *FM;
unsigned Version;
HeaderSeq HeaderList;

Expand Down Expand Up @@ -124,6 +125,12 @@ Error Implementation::parseHeaders(Array &Headers) {
HeaderFile{PathStr, *Type, /*IncludeName=*/"", Language});
continue;
}

if (FM)
if (!FM->getOptionalFileRef(PathStr))
return createFileError(
PathStr, make_error_code(std::errc::no_such_file_or_directory));

auto IncludeName = createIncludeHeaderName(PathStr);
HeaderList.emplace_back(PathStr, *Type,
IncludeName.has_value() ? IncludeName.value() : "",
Expand Down Expand Up @@ -170,9 +177,10 @@ Error Implementation::parse(StringRef Input) {

llvm::Error
FileListReader::loadHeaders(std::unique_ptr<MemoryBuffer> InputBuffer,
HeaderSeq &Destination) {
HeaderSeq &Destination, clang::FileManager *FM) {
Implementation Impl;
Impl.InputBuffer = std::move(InputBuffer);
Impl.FM = FM;

if (llvm::Error Err = Impl.parse(Impl.InputBuffer->getBuffer()))
return Err;
Expand Down
22 changes: 15 additions & 7 deletions clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3026,7 +3026,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
<< TokenName << TagName << getLangOpts().CPlusPlus
<< FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName);

if (Actions.LookupParsedName(R, getCurScope(), SS)) {
if (Actions.LookupName(R, getCurScope())) {
for (LookupResult::iterator I = R.begin(), IEnd = R.end();
I != IEnd; ++I)
Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)
Expand Down Expand Up @@ -7416,12 +7416,20 @@ void Parser::ParseFunctionDeclarator(Declarator &D,
std::optional<Sema::CXXThisScopeRAII> ThisScope;
InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope);

// Parse exception-specification[opt].
// FIXME: Per [class.mem]p6, all exception-specifications at class scope
// should be delayed, including those for non-members (eg, friend
// declarations). But only applying this to member declarations is
// consistent with what other implementations do.
bool Delayed = D.isFirstDeclarationOfMember() &&
// C++ [class.mem.general]p8:
// A complete-class context of a class (template) is a
// - function body,
// - default argument,
// - default template argument,
// - noexcept-specifier, or
// - default member initializer
// within the member-specification of the class or class template.
//
// Parse exception-specification[opt]. If we are in the
// member-specification of a class or class template, this is a
// complete-class context and parsing of the noexcept-specifier should be
// delayed (even if this is a friend declaration).
bool Delayed = D.getContext() == DeclaratorContext::Member &&
D.isFunctionDeclaratorAFunctionDeclaration();
if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) &&
GetLookAheadToken(0).is(tok::kw_noexcept) &&
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2039,7 +2039,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (Tok.is(tok::colon)) {
// Consume ':'
ColonLocFirst = ConsumeToken();
Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
if (Tok.isNot(tok::r_square))
Length = Actions.CorrectDelayedTyposInExpr(ParseExpression());
}
} else if (ArgExprs.size() <= 1 && getLangOpts().OpenMP) {
ColonProtectionRAIIObject RAII(*this);
Expand Down
155 changes: 88 additions & 67 deletions clang/lib/Parse/ParseOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
if (Tok.is(tok::kw_if))
return OpenACCClauseKind::If;

// 'private' is also a keyword, make sure we pare it correctly.
if (Tok.is(tok::kw_private))
return OpenACCClauseKind::Private;

if (!Tok.is(tok::identifier))
return OpenACCClauseKind::Invalid;

Expand All @@ -96,10 +100,18 @@ OpenACCClauseKind getOpenACCClauseKind(Token Tok) {
.Case("auto", OpenACCClauseKind::Auto)
.Case("bind", OpenACCClauseKind::Bind)
.Case("create", OpenACCClauseKind::Create)
.Case("pcreate", OpenACCClauseKind::PCreate)
.Case("present_or_create", OpenACCClauseKind::PresentOrCreate)
.Case("collapse", OpenACCClauseKind::Collapse)
.Case("copy", OpenACCClauseKind::Copy)
.Case("pcopy", OpenACCClauseKind::PCopy)
.Case("present_or_copy", OpenACCClauseKind::PresentOrCopy)
.Case("copyin", OpenACCClauseKind::CopyIn)
.Case("pcopyin", OpenACCClauseKind::PCopyIn)
.Case("present_or_copyin", OpenACCClauseKind::PresentOrCopyIn)
.Case("copyout", OpenACCClauseKind::CopyOut)
.Case("pcopyout", OpenACCClauseKind::PCopyOut)
.Case("present_or_copyout", OpenACCClauseKind::PresentOrCopyOut)
.Case("default", OpenACCClauseKind::Default)
.Case("default_async", OpenACCClauseKind::DefaultAsync)
.Case("delete", OpenACCClauseKind::Delete)
Expand Down Expand Up @@ -484,9 +496,17 @@ ClauseParensKind getClauseParensKind(OpenACCDirectiveKind DirKind,
case OpenACCClauseKind::Default:
case OpenACCClauseKind::If:
case OpenACCClauseKind::Create:
case OpenACCClauseKind::PCreate:
case OpenACCClauseKind::PresentOrCreate:
case OpenACCClauseKind::Copy:
case OpenACCClauseKind::PCopy:
case OpenACCClauseKind::PresentOrCopy:
case OpenACCClauseKind::CopyIn:
case OpenACCClauseKind::PCopyIn:
case OpenACCClauseKind::PresentOrCopyIn:
case OpenACCClauseKind::CopyOut:
case OpenACCClauseKind::PCopyOut:
case OpenACCClauseKind::PresentOrCopyOut:
case OpenACCClauseKind::UseDevice:
case OpenACCClauseKind::NoCreate:
case OpenACCClauseKind::Present:
Expand Down Expand Up @@ -682,28 +702,6 @@ bool Parser::ParseOpenACCIntExprList(OpenACCDirectiveKind DK,
return false;
}

bool Parser::ParseOpenACCClauseVarList(OpenACCClauseKind Kind) {
// FIXME: Future clauses will require 'special word' parsing, check for one,
// then parse it based on whether it is a clause that requires a 'special
// word'.
(void)Kind;

// If the var parsing fails, skip until the end of the directive as this is
// an expression and gets messy if we try to continue otherwise.
if (ParseOpenACCVar())
return true;

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

// If the var parsing fails, skip until the end of the directive as this is
// an expression and gets messy if we try to continue otherwise.
if (ParseOpenACCVar())
return true;
}
return false;
}

/// OpenACC 3.3 Section 2.4:
/// The argument to the device_type clause is a comma-separated list of one or
/// more device architecture name identifiers, or an asterisk.
Expand Down Expand Up @@ -915,30 +913,31 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
break;
}
case OpenACCClauseKind::CopyIn:
tryParseAndConsumeSpecialTokenKind(
case OpenACCClauseKind::PCopyIn:
case OpenACCClauseKind::PresentOrCopyIn: {
bool IsReadOnly = tryParseAndConsumeSpecialTokenKind(
*this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind);
if (ParseOpenACCClauseVarList(ClauseKind)) {
Parens.skipToEnd();
return OpenACCCanContinue();
}
ParsedClause.setVarListDetails(ParseOpenACCVarList(), IsReadOnly,
/*IsZero=*/false);
break;
}
case OpenACCClauseKind::Create:
case OpenACCClauseKind::PCreate:
case OpenACCClauseKind::PresentOrCreate:
case OpenACCClauseKind::CopyOut:
tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Zero,
ClauseKind);
if (ParseOpenACCClauseVarList(ClauseKind)) {
Parens.skipToEnd();
return OpenACCCanContinue();
}
case OpenACCClauseKind::PCopyOut:
case OpenACCClauseKind::PresentOrCopyOut: {
bool IsZero = tryParseAndConsumeSpecialTokenKind(
*this, OpenACCSpecialTokenKind::Zero, ClauseKind);
ParsedClause.setVarListDetails(ParseOpenACCVarList(),
/*IsReadOnly=*/false, IsZero);
break;
}
case OpenACCClauseKind::Reduction:
// If we're missing a clause-kind (or it is invalid), see if we can parse
// the var-list anyway.
ParseReductionOperator(*this);
if (ParseOpenACCClauseVarList(ClauseKind)) {
Parens.skipToEnd();
return OpenACCCanContinue();
}
ParseOpenACCVarList();
break;
case OpenACCClauseKind::Self:
// The 'self' clause is a var-list instead of a 'condition' in the case of
Expand All @@ -947,23 +946,25 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
assert(DirKind == OpenACCDirectiveKind::Update);
[[fallthrough]];
case OpenACCClauseKind::Attach:
case OpenACCClauseKind::Copy:
case OpenACCClauseKind::Delete:
case OpenACCClauseKind::Detach:
case OpenACCClauseKind::Device:
case OpenACCClauseKind::DeviceResident:
case OpenACCClauseKind::DevicePtr:
case OpenACCClauseKind::FirstPrivate:
case OpenACCClauseKind::Host:
case OpenACCClauseKind::Link:
case OpenACCClauseKind::UseDevice:
ParseOpenACCVarList();
break;
case OpenACCClauseKind::Copy:
case OpenACCClauseKind::PCopy:
case OpenACCClauseKind::PresentOrCopy:
case OpenACCClauseKind::FirstPrivate:
case OpenACCClauseKind::NoCreate:
case OpenACCClauseKind::Present:
case OpenACCClauseKind::Private:
case OpenACCClauseKind::UseDevice:
if (ParseOpenACCClauseVarList(ClauseKind)) {
Parens.skipToEnd();
return OpenACCCanContinue();
}
ParsedClause.setVarListDetails(ParseOpenACCVarList(),
/*IsReadOnly=*/false, /*IsZero=*/false);
break;
case OpenACCClauseKind::Collapse: {
tryParseAndConsumeSpecialTokenKind(*this, OpenACCSpecialTokenKind::Force,
Expand Down Expand Up @@ -1227,16 +1228,51 @@ ExprResult Parser::ParseOpenACCBindClauseArgument() {

/// OpenACC 3.3, section 1.6:
/// In this spec, a 'var' (in italics) is one of the following:
/// - a variable name (a scalar, array, or compisite variable name)
/// - a variable name (a scalar, array, or composite variable name)
/// - a subarray specification with subscript ranges
/// - an array element
/// - a member of a composite variable
/// - a common block name between slashes (fortran only)
bool Parser::ParseOpenACCVar() {
Parser::OpenACCVarParseResult Parser::ParseOpenACCVar() {
OpenACCArraySectionRAII ArraySections(*this);
ExprResult Res =
getActions().CorrectDelayedTyposInExpr(ParseAssignmentExpression());
return Res.isInvalid();

ExprResult Res = ParseAssignmentExpression();
if (!Res.isUsable())
return {Res, OpenACCParseCanContinue::Cannot};

Res = getActions().CorrectDelayedTyposInExpr(Res.get());
if (!Res.isUsable())
return {Res, OpenACCParseCanContinue::Can};

Res = getActions().OpenACC().ActOnVar(Res.get());

return {Res, OpenACCParseCanContinue::Can};
}

llvm::SmallVector<Expr *> Parser::ParseOpenACCVarList() {
llvm::SmallVector<Expr *> Vars;

auto [Res, CanContinue] = ParseOpenACCVar();
if (Res.isUsable()) {
Vars.push_back(Res.get());
} else if (CanContinue == OpenACCParseCanContinue::Cannot) {
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch);
return Vars;
}

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

auto [Res, CanContinue] = ParseOpenACCVar();

if (Res.isUsable()) {
Vars.push_back(Res.get());
} else if (CanContinue == OpenACCParseCanContinue::Cannot) {
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, StopBeforeMatch);
return Vars;
}
}
return Vars;
}

/// OpenACC 3.3, section 2.10:
Expand All @@ -1259,24 +1295,9 @@ void Parser::ParseOpenACCCacheVarList() {
// Sema/AST generation.
}

bool FirstArray = true;
while (!getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
if (!FirstArray)
ExpectAndConsume(tok::comma);
FirstArray = false;

// OpenACC 3.3, section 2.10:
// A 'var' in a cache directive must be a single array element or a simple
// subarray. In C and C++, a simple subarray is an array name followed by
// an extended array range specification in brackets, with a start and
// length such as:
//
// arr[lower:length]
//
if (ParseOpenACCVar())
SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end, tok::comma,
StopBeforeMatch);
}
// ParseOpenACCVarList should leave us before a r-paren, so no need to skip
// anything here.
ParseOpenACCVarList();
}

Parser::OpenACCDirectiveParseInfo Parser::ParseOpenACCDirective() {
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Parse/ParseOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4282,7 +4282,7 @@ bool Parser::parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data) {
}

/// Checks if the token is a valid map-type.
/// FIXME: It will return an OpenMPMapModifierKind if that's what it parses.
/// If it is not MapType kind, OMPC_MAP_unknown is returned.
static OpenMPMapClauseKind isMapType(Parser &P) {
Token Tok = P.getCurToken();
// The map-type token can be either an identifier or the C++ delete keyword.
Expand All @@ -4292,7 +4292,11 @@ static OpenMPMapClauseKind isMapType(Parser &P) {
OpenMPMapClauseKind MapType =
static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType(
OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));
return MapType;
if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
return MapType;
return OMPC_MAP_unknown;
}

/// Parse map-type in map clause.
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,15 @@ struct BuiltinTypeDeclBuilder {

static DeclRefExpr *lookupBuiltinFunction(ASTContext &AST, Sema &S,
StringRef Name) {
CXXScopeSpec SS;
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);
DeclarationNameInfo NameInfo =
DeclarationNameInfo(DeclarationName(&II), SourceLocation());
LookupResult R(S, NameInfo, Sema::LookupOrdinaryName);
S.LookupParsedName(R, S.getCurScope(), &SS, false);
// AllowBuiltinCreation is false but LookupDirect will create
// the builtin when searching the global scope anyways...
S.LookupName(R, S.getCurScope());
// FIXME: If the builtin function was user-declared in global scope,
// this assert *will* fail. Should this call LookupBuiltin instead?
assert(R.isSingleResult() &&
"Since this is a builtin it should always resolve!");
auto *VD = cast<ValueDecl>(R.getFoundDecl());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope,

IdentifierInfo *Name = IdTok.getIdentifierInfo();
LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName);
LookupParsedName(Lookup, curScope, nullptr, true);
LookupName(Lookup, curScope, /*AllowBuiltinCreation=*/true);

if (Lookup.empty()) {
Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var)
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2346,10 +2346,8 @@ static bool BuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
if (!SupportsBI(&TI) && SupportsBI(AuxTI))
TheTI = AuxTI;

if (IsCPUSupports && !TheTI->supportsCpuSupports())
return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
<< SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
if (!IsCPUSupports && !TheTI->supportsCpuIs())
if ((!IsCPUSupports && !TheTI->supportsCpuIs()) ||
(IsCPUSupports && !TheTI->supportsCpuSupports()))
return S.Diag(TheCall->getBeginLoc(),
TI.getTriple().isOSAIX()
? diag::err_builtin_aix_os_unsupported
Expand Down
18 changes: 10 additions & 8 deletions clang/lib/Sema/SemaCodeComplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6714,14 +6714,16 @@ void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,

// If the scope is a concept-constrained type parameter, infer nested
// members based on the constraints.
if (const auto *TTPT =
dyn_cast_or_null<TemplateTypeParmType>(NNS->getAsType())) {
for (const auto &R : ConceptInfo(*TTPT, S).members()) {
if (R.Operator != ConceptInfo::Member::Colons)
continue;
Results.AddResult(CodeCompletionResult(
R.render(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo())));
if (NNS) {
if (const auto *TTPT =
dyn_cast_or_null<TemplateTypeParmType>(NNS->getAsType())) {
for (const auto &R : ConceptInfo(*TTPT, S).members()) {
if (R.Operator != ConceptInfo::Member::Colons)
continue;
Results.AddResult(CodeCompletionResult(
R.render(*this, CodeCompleter->getAllocator(),
CodeCompleter->getCodeCompletionTUInfo())));
}
}
}

Expand Down
10 changes: 7 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,7 +832,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,
IdentifierInfo *&Name,
SourceLocation NameLoc) {
LookupResult R(SemaRef, Name, NameLoc, Sema::LookupTagName);
SemaRef.LookupParsedName(R, S, &SS);
SemaRef.LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
if (TagDecl *Tag = R.getAsSingle<TagDecl>()) {
StringRef FixItTagName;
switch (Tag->getTagKind()) {
Expand Down Expand Up @@ -869,7 +869,7 @@ static bool isTagTypeWithMissingTag(Sema &SemaRef, LookupResult &Result,

// Replace lookup results with just the tag decl.
Result.clear(Sema::LookupTagName);
SemaRef.LookupParsedName(Result, S, &SS);
SemaRef.LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType());
return true;
}

Expand All @@ -896,7 +896,8 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
}

LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
LookupParsedName(Result, S, &SS, !CurMethod);
LookupParsedName(Result, S, &SS, /*ObjectType=*/QualType(),
/*AllowBuiltinCreation=*/!CurMethod);

if (SS.isInvalid())
return NameClassification::Error();
Expand Down Expand Up @@ -5789,6 +5790,9 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
Anon = VarDecl::Create(Context, Owner, DS.getBeginLoc(),
Record->getLocation(), /*IdentifierInfo=*/nullptr,
Context.getTypeDeclType(Record), TInfo, SC);
if (Invalid)
Anon->setInvalidDecl();

ProcessDeclAttributes(S, Anon, Dc);

// Default-initialize the implicit variable. This initialization will be
Expand Down
46 changes: 23 additions & 23 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4519,7 +4519,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD,
DS.getBeginLoc(), DS.getEllipsisLoc());
} else {
LookupResult R(*this, MemberOrBase, IdLoc, LookupOrdinaryName);
LookupParsedName(R, S, &SS);
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());

TypeDecl *TyD = R.getAsSingle<TypeDecl>();
if (!TyD) {
Expand Down Expand Up @@ -12270,7 +12270,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc,

// Lookup namespace name.
LookupResult R(*this, NamespcName, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());
if (R.isAmbiguous())
return nullptr;

Expand Down Expand Up @@ -13729,7 +13729,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc,

// Lookup the namespace name.
LookupResult R(*this, Ident, IdentLoc, LookupNamespaceName);
LookupParsedName(R, S, &SS);
LookupParsedName(R, S, &SS, /*ObjectType=*/QualType());

if (R.isAmbiguous())
return nullptr;
Expand Down Expand Up @@ -19172,40 +19172,40 @@ void Sema::checkExceptionSpecification(
}
}

void Sema::actOnDelayedExceptionSpecification(Decl *MethodD,
ExceptionSpecificationType EST,
SourceRange SpecificationRange,
ArrayRef<ParsedType> DynamicExceptions,
ArrayRef<SourceRange> DynamicExceptionRanges,
Expr *NoexceptExpr) {
if (!MethodD)
void Sema::actOnDelayedExceptionSpecification(
Decl *D, ExceptionSpecificationType EST, SourceRange SpecificationRange,
ArrayRef<ParsedType> DynamicExceptions,
ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr) {
if (!D)
return;

// Dig out the method we're referring to.
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(MethodD))
MethodD = FunTmpl->getTemplatedDecl();
// Dig out the function we're referring to.
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
D = FTD->getTemplatedDecl();

CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(MethodD);
if (!Method)
FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD)
return;

// Check the exception specification.
llvm::SmallVector<QualType, 4> Exceptions;
FunctionProtoType::ExceptionSpecInfo ESI;
checkExceptionSpecification(/*IsTopLevel*/true, EST, DynamicExceptions,
checkExceptionSpecification(/*IsTopLevel=*/true, EST, DynamicExceptions,
DynamicExceptionRanges, NoexceptExpr, Exceptions,
ESI);

// Update the exception specification on the function type.
Context.adjustExceptionSpec(Method, ESI, /*AsWritten*/true);
Context.adjustExceptionSpec(FD, ESI, /*AsWritten=*/true);

if (Method->isStatic())
checkThisInStaticMemberFunctionExceptionSpec(Method);
if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
if (MD->isStatic())
checkThisInStaticMemberFunctionExceptionSpec(MD);

if (Method->isVirtual()) {
// Check overrides, which we previously had to delay.
for (const CXXMethodDecl *O : Method->overridden_methods())
CheckOverridingFunctionExceptionSpec(Method, O);
if (MD->isVirtual()) {
// Check overrides, which we previously had to delay.
for (const CXXMethodDecl *O : MD->overridden_methods())
CheckOverridingFunctionExceptionSpec(MD, O);
}
}
}

Expand Down
13 changes: 7 additions & 6 deletions clang/lib/Sema/SemaExceptionSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,14 @@ Sema::UpdateExceptionSpec(FunctionDecl *FD,
}

static bool exceptionSpecNotKnownYet(const FunctionDecl *FD) {
auto *MD = dyn_cast<CXXMethodDecl>(FD);
if (!MD)
ExceptionSpecificationType EST =
FD->getType()->castAs<FunctionProtoType>()->getExceptionSpecType();
if (EST == EST_Unparsed)
return true;
else if (EST != EST_Unevaluated)
return false;

auto EST = MD->getType()->castAs<FunctionProtoType>()->getExceptionSpecType();
return EST == EST_Unparsed ||
(EST == EST_Unevaluated && MD->getParent()->isBeingDefined());
const DeclContext *DC = FD->getLexicalDeclContext();
return DC->isRecord() && cast<RecordDecl>(DC)->isBeingDefined();
}

static bool CheckEquivalentExceptionSpecImpl(
Expand Down
Loading