238 changes: 238 additions & 0 deletions clang/include/clang/AST/OpenMPClause.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,66 @@ template <class T> class OMPVarListClause : public OMPClause {
}
};

/// Class that represents a list of directive kinds (parallel, target, etc.)
/// as used in \c absent, \c contains clauses.
template <class T> class OMPDirectiveListClause : public OMPClause {
/// Location of '('.
SourceLocation LParenLoc;

protected:
/// Number of directive kinds listed in the clause
unsigned NumKinds;

public:
/// Build a clause with \a NumKinds directive kinds.
///
/// \param K The clause kind.
/// \param StartLoc Starting location of the clause (the clause keyword).
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param NumKinds Number of directive kinds listed in the clause.
OMPDirectiveListClause(OpenMPClauseKind K, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
unsigned NumKinds)
: OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc),
NumKinds(NumKinds) {}

child_range children() {
return child_range(child_iterator(), child_iterator());
}

const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}

child_range used_children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range used_children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}

MutableArrayRef<OpenMPDirectiveKind> getDirectiveKinds() {
return MutableArrayRef<OpenMPDirectiveKind>(
static_cast<T *>(this)
->template getTrailingObjects<OpenMPDirectiveKind>(),
NumKinds);
}

void setDirectiveKinds(ArrayRef<OpenMPDirectiveKind> DK) {
assert(
DK.size() == NumKinds &&
"Number of directive kinds is not the same as the preallocated buffer");
std::copy(DK.begin(), DK.end(),
static_cast<T *>(this)
->template getTrailingObjects<OpenMPDirectiveKind>());
}

SourceLocation getLParenLoc() { return LParenLoc; }

void setLParenLoc(SourceLocation S) { LParenLoc = S; }
};

/// This represents 'allocator' clause in the '#pragma omp ...'
/// directive.
///
Expand Down Expand Up @@ -2013,6 +2073,184 @@ class OMPMergeableClause : public OMPClause {
}
};

/// This represents the 'absent' clause in the '#pragma omp assume'
/// directive.
///
/// \code
/// #pragma omp assume absent(<directive-name list>)
/// \endcode
/// In this example directive '#pragma omp assume' has an 'absent' clause.
class OMPAbsentClause final
: public OMPDirectiveListClause<OMPAbsentClause>,
private llvm::TrailingObjects<OMPAbsentClause, OpenMPDirectiveKind> {
friend OMPDirectiveListClause;
friend TrailingObjects;

/// Build 'absent' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param NumKinds Number of directive kinds listed in the clause.
OMPAbsentClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned NumKinds)
: OMPDirectiveListClause<OMPAbsentClause>(
llvm::omp::OMPC_absent, StartLoc, LParenLoc, EndLoc, NumKinds) {}

/// Build an empty clause.
OMPAbsentClause(unsigned NumKinds)
: OMPDirectiveListClause<OMPAbsentClause>(
llvm::omp::OMPC_absent, SourceLocation(), SourceLocation(),
SourceLocation(), NumKinds) {}

public:
static OMPAbsentClause *Create(const ASTContext &C,
ArrayRef<OpenMPDirectiveKind> DKVec,
SourceLocation Loc, SourceLocation LLoc,
SourceLocation RLoc);

static OMPAbsentClause *CreateEmpty(const ASTContext &C, unsigned NumKinds);

static bool classof(const OMPClause *C) {
return C->getClauseKind() == llvm::omp::OMPC_absent;
}
};

/// This represents the 'contains' clause in the '#pragma omp assume'
/// directive.
///
/// \code
/// #pragma omp assume contains(<directive-name list>)
/// \endcode
/// In this example directive '#pragma omp assume' has a 'contains' clause.
class OMPContainsClause final
: public OMPDirectiveListClause<OMPContainsClause>,
private llvm::TrailingObjects<OMPContainsClause, OpenMPDirectiveKind> {
friend OMPDirectiveListClause;
friend TrailingObjects;

/// Build 'contains' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param LParenLoc Location of '('.
/// \param EndLoc Ending location of the clause.
/// \param NumKinds Number of directive kinds listed in the clause.
OMPContainsClause(SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, unsigned NumKinds)
: OMPDirectiveListClause<OMPContainsClause>(
llvm::omp::OMPC_contains, StartLoc, LParenLoc, EndLoc, NumKinds) {}

/// Build an empty clause.
OMPContainsClause(unsigned NumKinds)
: OMPDirectiveListClause<OMPContainsClause>(
llvm::omp::OMPC_contains, SourceLocation(), SourceLocation(),
SourceLocation(), NumKinds) {}

public:
static OMPContainsClause *Create(const ASTContext &C,
ArrayRef<OpenMPDirectiveKind> DKVec,
SourceLocation Loc, SourceLocation LLoc,
SourceLocation RLoc);

static OMPContainsClause *CreateEmpty(const ASTContext &C, unsigned NumKinds);

static bool classof(const OMPClause *C) {
return C->getClauseKind() == llvm::omp::OMPC_contains;
}
};

/// This represents the 'holds' clause in the '#pragma omp assume'
/// directive.
///
/// \code
/// #pragma omp assume holds(<expr>)
/// \endcode
/// In this example directive '#pragma omp assume' has a 'holds' clause.
class OMPHoldsClause final
: public OMPOneStmtClause<llvm::omp::OMPC_holds, OMPClause> {
friend class OMPClauseReader;

public:
/// Build 'holds' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
OMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc)
: OMPOneStmtClause(E, StartLoc, LParenLoc, EndLoc) {}

/// Build an empty clause.
OMPHoldsClause() : OMPOneStmtClause() {}

Expr *getExpr() const { return getStmtAs<Expr>(); }
void setExpr(Expr *E) { setStmt(E); }
};

/// This represents the 'no_openmp' clause in the '#pragma omp assume'
/// directive.
///
/// \code
/// #pragma omp assume no_openmp
/// \endcode
/// In this example directive '#pragma omp assume' has a 'no_openmp' clause.
class OMPNoOpenMPClause final
: public OMPNoChildClause<llvm::omp::OMPC_no_openmp> {
public:
/// Build 'no_openmp' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
OMPNoOpenMPClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPNoChildClause(StartLoc, EndLoc) {}

/// Build an empty clause.
OMPNoOpenMPClause() : OMPNoChildClause() {}
};

/// This represents the 'no_openmp_routines' clause in the '#pragma omp assume'
/// directive.
///
/// \code
/// #pragma omp assume no_openmp_routines
/// \endcode
/// In this example directive '#pragma omp assume' has a 'no_openmp_routines'
/// clause.
class OMPNoOpenMPRoutinesClause final
: public OMPNoChildClause<llvm::omp::OMPC_no_openmp_routines> {
public:
/// Build 'no_openmp_routines' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
OMPNoOpenMPRoutinesClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPNoChildClause(StartLoc, EndLoc) {}

/// Build an empty clause.
OMPNoOpenMPRoutinesClause() : OMPNoChildClause() {}
};

/// This represents the 'no_parallelism' clause in the '#pragma omp assume'
/// directive.
///
/// \code
/// #pragma omp assume no_parallelism
/// \endcode
/// In this example directive '#pragma omp assume' has a 'no_parallelism'
/// clause.
class OMPNoParallelismClause final
: public OMPNoChildClause<llvm::omp::OMPC_no_parallelism> {
public:
/// Build 'no_parallelism' clause.
///
/// \param StartLoc Starting location of the clause.
/// \param EndLoc Ending location of the clause.
OMPNoParallelismClause(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPNoChildClause(StartLoc, EndLoc) {}

/// Build an empty clause.
OMPNoParallelismClause() : OMPNoChildClause() {}
};

/// This represents 'read' clause in the '#pragma omp atomic' directive.
///
/// \code
Expand Down
35 changes: 35 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -3238,6 +3238,9 @@ DEF_TRAVERSE_STMT(OMPParallelGenericLoopDirective,
DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })

DEF_TRAVERSE_STMT(OMPAssumeDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })

DEF_TRAVERSE_STMT(OMPErrorDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })

Expand Down Expand Up @@ -3480,6 +3483,38 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAcqRelClause(OMPAcqRelClause *) {
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAbsentClause(OMPAbsentClause *) {
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPHoldsClause(OMPHoldsClause *) {
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPContainsClause(OMPContainsClause *) {
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPRoutinesClause(
OMPNoOpenMPRoutinesClause *) {
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPNoParallelismClause(
OMPNoParallelismClause *) {
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
return true;
Expand Down
30 changes: 30 additions & 0 deletions clang/include/clang/AST/StmtOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -6468,6 +6468,36 @@ class OMPErrorDirective final : public OMPExecutableDirective {
return T->getStmtClass() == OMPErrorDirectiveClass;
}
};

// It's not really an executable directive, but it seems convenient to use
// that as the parent class.
class OMPAssumeDirective final : public OMPExecutableDirective {
friend class ASTStmtReader;
friend class OMPExecutableDirective;

private:
OMPAssumeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
StartLoc, EndLoc) {}

explicit OMPAssumeDirective()
: OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
SourceLocation(), SourceLocation()) {}

public:
static OMPAssumeDirective *Create(const ASTContext &Ctx,
SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AStmt);

static OMPAssumeDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);

static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPAssumeDirectiveClass;
}
};

} // end namespace clang

#endif
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -4707,6 +4707,12 @@ def HLSLIsinf : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

def HLSLLength : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_length"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}

def HLSLLerp : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_lerp"];
let Attributes = [NoThrow, Const];
Expand Down
213 changes: 189 additions & 24 deletions clang/include/clang/Basic/BuiltinsX86.def

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions clang/include/clang/Basic/OpenMPKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,11 @@ bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter);
/// otherwise - false.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind);

/// Checks if the specified directive is considered as "informational".
/// \param DKind Specified directive.
/// \return true if it is an informational directive, false otherwise.
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind);

/// Checks if the specified directive can capture variables.
/// \param DKind Specified directive.
/// \return true - if the above condition is met for this directive
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/StmtNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ def OMPTeamsGenericLoopDirective : StmtNode<OMPLoopDirective>;
def OMPTargetTeamsGenericLoopDirective : StmtNode<OMPLoopDirective>;
def OMPParallelGenericLoopDirective : StmtNode<OMPLoopDirective>;
def OMPTargetParallelGenericLoopDirective : StmtNode<OMPLoopDirective>;
def OMPAssumeDirective : StmtNode<OMPExecutableDirective>;
def OMPErrorDirective : StmtNode<OMPExecutableDirective>;

// OpenACC Constructs.
Expand Down
16 changes: 8 additions & 8 deletions clang/include/clang/Basic/riscv_vector.td
Original file line number Diff line number Diff line change
Expand Up @@ -1987,9 +1987,9 @@ let ManualCodegen = [{
RVVConvBuiltinSet<"vfcvt_xu_f_v", "xfd", [["Uv", "Uvvu"]]>;
let OverloadedName = "vfcvt_f" in {
defm :
RVVConvBuiltinSet<"vfcvt_f_x_v", "sil", [["Fv", "Fvvu"]]>;
RVVConvBuiltinSet<"vfcvt_f_x_v", "xfd", [["v", "vIvu"]]>;
defm :
RVVConvBuiltinSet<"vfcvt_f_xu_v", "sil", [["Fv", "FvUvu"]]>;
RVVConvBuiltinSet<"vfcvt_f_xu_v", "xfd", [["v", "vUvu"]]>;
}

// 13.18. Widening Floating-Point/Integer Type-Convert Instructions
Expand All @@ -2011,9 +2011,9 @@ let ManualCodegen = [{
RVVConvBuiltinSet<"vfncvt_xu_f_w", "csi", [["Uv", "UvFwu"]]>;
let OverloadedName = "vfncvt_f" in {
defm :
RVVConvBuiltinSet<"vfncvt_f_x_w", "csi", [["Fv", "Fvwu"]]>;
RVVConvBuiltinSet<"vfncvt_f_x_w", "xf", [["v", "vIwu"]]>;
defm :
RVVConvBuiltinSet<"vfncvt_f_xu_w", "csi", [["Fv", "FvUwu"]]>;
RVVConvBuiltinSet<"vfncvt_f_xu_w", "xf", [["v", "vUwu"]]>;
}
let OverloadedName = "vfncvt_f" in {
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "f", [["v", "vwu"]]>;
Expand All @@ -2037,9 +2037,9 @@ let ManualCodegen = [{
RVVConvBuiltinSet<"vfcvt_xu_f_v", "xfd", [["Uv", "Uvv"]]>;
let OverloadedName = "vfcvt_f" in {
defm :
RVVConvBuiltinSet<"vfcvt_f_x_v", "sil", [["Fv", "Fvv"]]>;
RVVConvBuiltinSet<"vfcvt_f_x_v", "xfd", [["v", "vIv"]]>;
defm :
RVVConvBuiltinSet<"vfcvt_f_xu_v", "sil", [["Fv", "FvUv"]]>;
RVVConvBuiltinSet<"vfcvt_f_xu_v", "xfd", [["v", "vUv"]]>;
}

// 13.18. Widening Floating-Point/Integer Type-Convert Instructions
Expand All @@ -2061,9 +2061,9 @@ let ManualCodegen = [{
RVVConvBuiltinSet<"vfncvt_xu_f_w", "csi", [["Uv", "UvFw"]]>;
let OverloadedName = "vfncvt_f" in {
defm :
RVVConvBuiltinSet<"vfncvt_f_x_w", "csi", [["Fv", "Fvw"]]>;
RVVConvBuiltinSet<"vfncvt_f_x_w", "xf", [["v", "vIw"]]>;
defm :
RVVConvBuiltinSet<"vfncvt_f_xu_w", "csi", [["Fv", "FvUw"]]>;
RVVConvBuiltinSet<"vfncvt_f_xu_w", "xf", [["v", "vUw"]]>;
}
let OverloadedName = "vfncvt_f" in {
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "f", [["v", "vw"]]>;
Expand Down
14 changes: 8 additions & 6 deletions clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -715,14 +715,16 @@ class Driver {
ModuleHeaderMode getModuleHeaderMode() const { return CXX20HeaderType; }

/// Returns true if we are performing any kind of LTO.
bool isUsingLTO(bool IsOffload = false) const {
return getLTOMode(IsOffload) != LTOK_None;
}
bool isUsingLTO() const { return getLTOMode() != LTOK_None; }

/// Get the specific kind of LTO being performed.
LTOKind getLTOMode(bool IsOffload = false) const {
return IsOffload ? OffloadLTOMode : LTOMode;
}
LTOKind getLTOMode() const { return LTOMode; }

/// Returns true if we are performing any kind of offload LTO.
bool isUsingOffloadLTO() const { return getOffloadLTOMode() != LTOK_None; }

/// Get the specific kind of offload LTO being performed.
LTOKind getOffloadLTOMode() const { return OffloadLTOMode; }

private:

Expand Down
15 changes: 11 additions & 4 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -932,8 +932,9 @@ def O_flag : Flag<["-"], "O">, Visibility<[ClangOption, CC1Option, FC1Option]>,
Alias<O>, AliasArgs<["1"]>;
def Ofast : Joined<["-"], "Ofast">, Group<O_Group>,
Visibility<[ClangOption, CC1Option, FlangOption]>,
HelpText<"Deprecated; use '-O3 -ffast-math' for the same behavior,"
" or '-O3' to enable only conforming optimizations">;
HelpTextForVariants<[ClangOption, CC1Option],
"Deprecated; use '-O3 -ffast-math' for the same behavior,"
" or '-O3' to enable only conforming optimizations">;
def P : Flag<["-"], "P">,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
Group<Preprocessor_Group>,
Expand Down Expand Up @@ -6205,6 +6206,12 @@ def mavx10_1_512 : Flag<["-"], "mavx10.1-512">, Group<m_x86_AVX10_Features_Group
def mno_avx10_1_512 : Flag<["-"], "mno-avx10.1-512">, Group<m_x86_AVX10_Features_Group>;
def mavx10_1 : Flag<["-"], "mavx10.1">, Alias<mavx10_1_256>;
def mno_avx10_1 : Flag<["-"], "mno-avx10.1">, Alias<mno_avx10_1_256>;
def mavx10_2_256 : Flag<["-"], "mavx10.2-256">, Group<m_x86_AVX10_Features_Group>;
def mno_avx10_2_256 : Flag<["-"], "mno-avx10.2-256">, Group<m_x86_AVX10_Features_Group>;
def mavx10_2_512 : Flag<["-"], "mavx10.2-512">, Group<m_x86_AVX10_Features_Group>;
def mno_avx10_2_512 : Flag<["-"], "mno-avx10.2-512">, Group<m_x86_AVX10_Features_Group>;
def mavx10_2 : Flag<["-"], "mavx10.2">, Alias<mavx10_2_256>;
def mno_avx10_2 : Flag<["-"], "mno-avx10.2">, Alias<mno_avx10_2_256>;
def mavx2 : Flag<["-"], "mavx2">, Group<m_x86_Features_Group>;
def mno_avx2 : Flag<["-"], "mno-avx2">, Group<m_x86_Features_Group>;
def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>;
Expand Down Expand Up @@ -8097,8 +8104,8 @@ def source_date_epoch : Separate<["-"], "source-date-epoch">,
} // let Visibility = [CC1Option]

defm err_pragma_mc_func_aix : BoolFOption<"err-pragma-mc-func-aix",
PreprocessorOpts<"ErrorOnPragmaMcfuncOnAIX">, DefaultTrue,
PosFlag<SetTrue, [], [ClangOption],
PreprocessorOpts<"ErrorOnPragmaMcfuncOnAIX">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption, CC1Option],
"Treat uses of #pragma mc_func as errors">,
NegFlag<SetFalse,[], [ClangOption, CC1Option],
"Ignore uses of #pragma mc_func">>;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ struct FormatStyle {
OAS_Align,
/// Horizontally align operands of binary and ternary expressions.
///
/// This is similar to ``AO_Align``, except when
/// This is similar to ``OAS_Align``, except when
/// ``BreakBeforeBinaryOperators`` is set, the operator is un-indented so
/// that the wrapped operand is aligned with the operand on the first line.
/// \code
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/Index/DeclOccurrence.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ struct DeclOccurrence {

DeclOccurrence(SymbolRoleSet R, unsigned Offset, const Decl *D,
ArrayRef<SymbolRelation> Relations)
: Roles(R), Offset(Offset), DeclOrMacro(D),
Relations(Relations.begin(), Relations.end()) {}
: Roles(R), Offset(Offset), DeclOrMacro(D), Relations(Relations) {}
DeclOccurrence(SymbolRoleSet R, unsigned Offset, const IdentifierInfo *Name,
const MacroInfo *MI)
: Roles(R), Offset(Offset), DeclOrMacro(MI), MacroName(Name) {}
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Lex/PreprocessorOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ class PreprocessorOptions {

/// If set, the preprocessor reports an error when processing #pragma mc_func
/// on AIX.
bool ErrorOnPragmaMcfuncOnAIX = true;
bool ErrorOnPragmaMcfuncOnAIX = false;

public:
PreprocessorOptions() : PrecompiledPreambleBytes(0, false) {}
Expand Down Expand Up @@ -252,7 +252,7 @@ class PreprocessorOptions {
PrecompiledPreambleBytes.first = 0;
PrecompiledPreambleBytes.second = false;
RetainExcludedConditionalBlocks = false;
ErrorOnPragmaMcfuncOnAIX = true;
ErrorOnPragmaMcfuncOnAIX = false;
}
};

Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3532,6 +3532,17 @@ class Parser : public CodeCompletionHandler {
OpenMPDirectiveKind DKind, SourceLocation Loc,
bool ReadDirectiveWithinMetadirective);

/// Parses informational directive.
///
/// \param StmtCtx The context in which we're parsing the directive.
/// \param DKind The kind of the informational directive.
/// \param Loc Source location of the beginning of the directive.
/// \param ReadDirectiveWithinMetadirective true if directive is within a
/// metadirective and therefore ends on the closing paren.
StmtResult ParseOpenMPInformationalDirective(
ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
bool ReadDirectiveWithinMetadirective);

/// Parses clause of kind \a CKind for directive of a kind \a Kind.
///
/// \param DKind Kind of current directive.
Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/Sema/SemaConcept.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,11 @@ enum { ConstraintAlignment = 8 };

struct alignas(ConstraintAlignment) AtomicConstraint {
const Expr *ConstraintExpr;
NamedDecl *ConstraintDecl;
std::optional<ArrayRef<TemplateArgumentLoc>> ParameterMapping;

AtomicConstraint(Sema &S, const Expr *ConstraintExpr) :
ConstraintExpr(ConstraintExpr) { };
AtomicConstraint(const Expr *ConstraintExpr, NamedDecl *ConstraintDecl)
: ConstraintExpr(ConstraintExpr), ConstraintDecl(ConstraintDecl) {};

bool hasMatchingParameterMapping(ASTContext &C,
const AtomicConstraint &Other) const {
Expand Down
33 changes: 33 additions & 0 deletions clang/include/clang/Sema/SemaOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,28 @@ class SemaOpenMP : public SemaBase {
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc);
/// Process an OpenMP informational directive.
///
/// \param Kind The directive kind.
/// \param DirName Declaration name info.
/// \param Clauses Array of clauses for directive.
/// \param AStmt The associated statement.
/// \param StartLoc The start location.
/// \param EndLoc The end location.
StmtResult ActOnOpenMPInformationalDirective(
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);
/// Process an OpenMP assume directive.
///
/// \param Clauses Array of clauses for directive.
/// \param AStmt The associated statement.
/// \param StartLoc The start location.
/// \param EndLoc The end location.
StmtResult ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc,
SourceLocation EndLoc);

/// Called on well-formed '\#pragma omp parallel' after parsing
/// of the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
Expand Down Expand Up @@ -940,6 +962,17 @@ class SemaOpenMP : public SemaBase {
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-formed 'holds' clause.
OMPClause *ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-formed 'absent' or 'contains' clauses.
OMPClause *ActOnOpenMPDirectivePresenceClause(
OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc);
OMPClause *ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
SourceLocation Loc,
SourceLocation RLoc);

OMPClause *ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Sema/Template.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ enum class TemplateSubstitutionKind : char {
/// Replaces the current 'innermost' level with the provided argument list.
/// This is useful for type deduction cases where we need to get the entire
/// list from the AST, but then add the deduced innermost list.
void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args) {
void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args,
bool Final = false) {
assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
"Replacing in an empty list?");

Expand All @@ -246,8 +247,7 @@ enum class TemplateSubstitutionKind : char {
TemplateArgumentLists[0].Args = Args;
} else {
--NumRetainedOuterLevels;
TemplateArgumentLists.push_back(
{{AssociatedDecl, /*Final=*/false}, Args});
TemplateArgumentLists.push_back({{AssociatedDecl, Final}, Args});
}
}

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1964,6 +1964,7 @@ enum StmtCode {
STMT_OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_PARALLEL_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_TARGET_PARALLEL_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_ASSUME_DIRECTIVE,
EXPR_ARRAY_SECTION,
EXPR_OMP_ARRAY_SHAPING,
EXPR_OMP_ITERATOR,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2478,7 +2478,7 @@ class BitsUnpacker {

inline bool shouldSkipCheckingODR(const Decl *D) {
return D->getASTContext().getLangOpts().SkipODRCheckInGMF &&
D->isFromExplicitGlobalModule();
D->isFromGlobalModule();
}

} // namespace clang
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Tooling/Refactoring/ASTSelection.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class CodeRangeASTSelection {
CodeRangeASTSelection(SelectedASTNode::ReferenceType SelectedNode,
ArrayRef<SelectedASTNode::ReferenceType> Parents,
bool AreChildrenSelected)
: SelectedNode(SelectedNode), Parents(Parents.begin(), Parents.end()),
: SelectedNode(SelectedNode), Parents(Parents),
AreChildrenSelected(AreChildrenSelected) {}

/// The reference to the selected node (or reference to the selected
Expand Down
16 changes: 12 additions & 4 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5588,11 +5588,19 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
// of a real template argument.
// FIXME: It would be more faithful to model this as something like an
// lvalue-to-rvalue conversion applied to a const-qualified lvalue.
if (T->isRecordType())
ExprValueKind VK;
if (T->isRecordType()) {
// C++ [temp.param]p8: An id-expression naming a non-type
// template-parameter of class type T denotes a static storage duration
// object of type const T.
T.addConst();
Expr *E = new (*this) DeclRefExpr(
*this, NTTP, /*RefersToEnclosingVariableOrCapture*/ false, T,
Expr::getValueKindForType(NTTP->getType()), NTTP->getLocation());
VK = VK_LValue;
} else {
VK = Expr::getValueKindForType(NTTP->getType());
}
Expr *E = new (*this)
DeclRefExpr(*this, NTTP, /*RefersToEnclosingVariableOrCapture=*/false,
T, VK, NTTP->getLocation());

if (NTTP->isParameterPack())
E = new (*this)
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,10 @@ bool Decl::isFromExplicitGlobalModule() const {
return getOwningModule() && getOwningModule()->isExplicitGlobalModule();
}

bool Decl::isFromGlobalModule() const {
return getOwningModule() && getOwningModule()->isGlobalModule();
}

bool Decl::isInNamedModule() const {
return getOwningModule() && getOwningModule()->isNamedModule();
}
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/AST/ExprClassification.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,12 +485,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
/// ClassifyDecl - Return the classification of an expression referencing the
/// given declaration.
static Cl::Kinds ClassifyDecl(ASTContext &Ctx, const Decl *D) {
// C++ [expr.prim.general]p6: The result is an lvalue if the entity is a
// function, variable, or data member and a prvalue otherwise.
// C++ [expr.prim.id.unqual]p3: The result is an lvalue if the entity is a
// function, variable, or data member, or a template parameter object and a
// prvalue otherwise.
// In C, functions are not lvalues.
// In addition, NonTypeTemplateParmDecl derives from VarDecl but isn't an
// lvalue unless it's a reference type (C++ [temp.param]p6), so we need to
// special-case this.
// lvalue unless it's a reference type or a class type (C++ [temp.param]p8),
// so we need to special-case this.

if (const auto *M = dyn_cast<CXXMethodDecl>(D)) {
if (M->isImplicitObjectMemberFunction())
Expand Down
166 changes: 88 additions & 78 deletions clang/lib/AST/Interp/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
public:
DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
: LocalScope<Emitter>(Ctx, VD), Scope(Ctx->P, VD),
OldGlobalDecl(Ctx->GlobalDecl),
OldInitializingDecl(Ctx->InitializingDecl) {
Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD);
Ctx->InitializingDecl = VD;
Ctx->InitStack.push_back(InitLink::Decl(VD));
}
Expand All @@ -41,14 +39,12 @@ template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
}

~DeclScope() {
this->Ctx->GlobalDecl = OldGlobalDecl;
this->Ctx->InitializingDecl = OldInitializingDecl;
this->Ctx->InitStack.pop_back();
}

private:
Program::DeclScope Scope;
bool OldGlobalDecl;
const ValueDecl *OldInitializingDecl;
};

Expand Down Expand Up @@ -426,7 +422,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (CE->getType()->isAtomicType()) {
if (!this->discard(SubExpr))
return false;
return this->emitInvalidCast(CastKind::Reinterpret, CE);
return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE);
}

if (DiscardResult)
Expand Down Expand Up @@ -733,8 +729,8 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
}

// Typecheck the args.
std::optional<PrimType> LT = classify(LHS->getType());
std::optional<PrimType> RT = classify(RHS->getType());
std::optional<PrimType> LT = classify(LHS);
std::optional<PrimType> RT = classify(RHS);
std::optional<PrimType> T = classify(BO->getType());

// Special case for C++'s three-way/spaceship operator <=>, which
Expand Down Expand Up @@ -769,8 +765,16 @@ bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
return this->VisitPointerArithBinOp(BO);
}

if (!visit(LHS) || !visit(RHS))
return false;
// Assignmentes require us to evalute the RHS first.
if (BO->getOpcode() == BO_Assign) {
if (!visit(RHS) || !visit(LHS))
return false;
if (!this->emitFlip(*LT, *RT, BO))
return false;
} else {
if (!visit(LHS) || !visit(RHS))
return false;
}

// For languages such as C, cast the result of one
// of our comparision opcodes to T (which is usually int).
Expand Down Expand Up @@ -1282,21 +1286,31 @@ bool Compiler<Emitter>::VisitImplicitValueInitExpr(

template <class Emitter>
bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
const Expr *Base = E->getBase();
const Expr *LHS = E->getLHS();
const Expr *RHS = E->getRHS();
const Expr *Index = E->getIdx();

if (DiscardResult)
return this->discard(Base) && this->discard(Index);
return this->discard(LHS) && this->discard(RHS);

// Take pointer of LHS, add offset from RHS.
// What's left on the stack after this is a pointer.
if (!this->visit(Base))
return false;
// C++17's rules require us to evaluate the LHS first, regardless of which
// side is the base.
bool Success = true;
for (const Expr *SubExpr : {LHS, RHS}) {
if (!this->visit(SubExpr))
Success = false;
}

if (!this->visit(Index))
if (!Success)
return false;

PrimType IndexT = classifyPrim(Index->getType());
// If the index is first, we need to change that.
if (LHS == Index) {
if (!this->emitFlip(PT_Ptr, IndexT, E))
return false;
}

return this->emitArrayElemPtrPop(IndexT, E);
}

Expand Down Expand Up @@ -2226,7 +2240,7 @@ bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) {

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

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

template <class Emitter>
Expand All @@ -2247,7 +2261,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
// the temporary is explicitly static, create a global variable.
std::optional<PrimType> SubExprT = classify(SubExpr);
bool IsStatic = E->getStorageDuration() == SD_Static;
if (GlobalDecl || IsStatic) {
if (IsStatic) {
std::optional<unsigned> GlobalIndex = P.createGlobal(E);
if (!GlobalIndex)
return false;
Expand Down Expand Up @@ -2447,10 +2461,13 @@ bool Compiler<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
template <class Emitter>
bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
const CXXReinterpretCastExpr *E) {
if (!this->discard(E->getSubExpr()))
const Expr *SubExpr = E->getSubExpr();

bool TypesMatch = classify(E) == classify(SubExpr);
if (!this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/!TypesMatch, E))
return false;

return this->emitInvalidCast(CastKind::Reinterpret, E);
return this->delegate(SubExpr);
}

template <class Emitter>
Expand Down Expand Up @@ -2537,13 +2554,8 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
return false;
}

// Immediately call the destructor if we have to.
if (DiscardResult) {
if (!this->emitRecordDestruction(getRecord(E->getType())))
return false;
if (!this->emitPopPtr(E))
return false;
}
if (DiscardResult)
return this->emitPopPtr(E);
return true;
}

Expand Down Expand Up @@ -3964,7 +3976,19 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
}
}

auto Args = llvm::ArrayRef(E->getArgs(), E->getNumArgs());
SmallVector<const Expr *, 8> Args(
llvm::ArrayRef(E->getArgs(), E->getNumArgs()));

bool IsAssignmentOperatorCall = false;
if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
OCE && OCE->isAssignmentOp()) {
// Just like with regular assignments, we need to special-case assignment
// operators here and evaluate the RHS (the second arg) before the LHS (the
// first arg. We fix this by using a Flip op later.
assert(Args.size() == 2);
IsAssignmentOperatorCall = true;
std::reverse(Args.begin(), Args.end());
}
// Calling a static operator will still
// pass the instance, but we don't need it.
// Discard it here.
Expand All @@ -3973,7 +3997,8 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
MD && MD->isStatic()) {
if (!this->discard(E->getArg(0)))
return false;
Args = Args.drop_front();
// Drop first arg.
Args.erase(Args.begin());
}
}

Expand All @@ -3998,6 +4023,13 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
} else if (!this->visit(MC->getImplicitObjectArgument())) {
return false;
}
} else if (!FuncDecl) {
const Expr *Callee = E->getCallee();
CalleeOffset = this->allocateLocalPrimitive(Callee, PT_FnPtr, true, false);
if (!this->visit(Callee))
return false;
if (!this->emitSetLocal(PT_FnPtr, *CalleeOffset, E))
return false;
}

llvm::BitVector NonNullArgs = collectNonNullArgs(FuncDecl, Args);
Expand All @@ -4018,6 +4050,15 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
++ArgIndex;
}

// Undo the argument reversal we did earlier.
if (IsAssignmentOperatorCall) {
assert(Args.size() == 2);
PrimType Arg1T = classify(Args[0]).value_or(PT_Ptr);
PrimType Arg2T = classify(Args[1]).value_or(PT_Ptr);
if (!this->emitFlip(Arg2T, Arg1T, E))
return false;
}

if (FuncDecl) {
const Function *Func = getFunction(FuncDecl);
if (!Func)
Expand Down Expand Up @@ -4066,22 +4107,19 @@ bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
ArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));

// Get the callee, either from a member pointer saved in CalleeOffset,
// or by just visiting the Callee expr.
if (CalleeOffset) {
// Get the callee, either from a member pointer or function pointer saved in
// CalleeOffset.
if (isa<CXXMemberCallExpr>(E) && CalleeOffset) {
if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))
return false;
if (!this->emitGetMemberPtrDecl(E))
return false;
if (!this->emitCallPtr(ArgSize, E, E))
return false;
} else {
if (!this->visit(E->getCallee()))
return false;

if (!this->emitCallPtr(ArgSize, E, E))
if (!this->emitGetLocal(PT_FnPtr, *CalleeOffset, E))
return false;
}
if (!this->emitCallPtr(ArgSize, E, E))
return false;
}

// Cleanup for discarded return values.
Expand Down Expand Up @@ -4222,22 +4260,6 @@ template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) {
}
}

/// Visits the given statment without creating a variable
/// scope for it in case it is a compound statement.
template <class Emitter> bool Compiler<Emitter>::visitLoopBody(const Stmt *S) {
if (isa<NullStmt>(S))
return true;

if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
for (const auto *InnerStmt : CS->body())
if (!visitStmt(InnerStmt))
return false;
return true;
}

return this->visitStmt(S);
}

template <class Emitter>
bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
BlockScope<Emitter> Scope(this);
Expand Down Expand Up @@ -4300,8 +4322,6 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
}

template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
BlockScope<Emitter> IfScope(this);

if (IS->isNonNegatedConsteval())
return visitStmt(IS->getThen());
if (IS->isNegatedConsteval())
Expand Down Expand Up @@ -4340,7 +4360,7 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
this->emitLabel(LabelEnd);
}

return IfScope.destroyLocals();
return true;
}

template <class Emitter>
Expand All @@ -4364,12 +4384,8 @@ bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
if (!this->jumpFalse(EndLabel))
return false;

LocalScope<Emitter> Scope(this);
{
DestructorScope<Emitter> DS(Scope);
if (!this->visitLoopBody(Body))
return false;
}
if (!this->visitStmt(Body))
return false;

if (!this->jump(CondLabel))
return false;
Expand All @@ -4387,14 +4403,11 @@ template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
LabelTy EndLabel = this->getLabel();
LabelTy CondLabel = this->getLabel();
LoopScope<Emitter> LS(this, EndLabel, CondLabel);
LocalScope<Emitter> Scope(this);

this->fallthrough(StartLabel);
this->emitLabel(StartLabel);
{
DestructorScope<Emitter> DS(Scope);

if (!this->visitLoopBody(Body))
if (!this->visitStmt(Body))
return false;
this->fallthrough(CondLabel);
this->emitLabel(CondLabel);
Expand All @@ -4421,10 +4434,10 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
LabelTy CondLabel = this->getLabel();
LabelTy IncLabel = this->getLabel();
LoopScope<Emitter> LS(this, EndLabel, IncLabel);
LocalScope<Emitter> Scope(this);

if (Init && !this->visitStmt(Init))
return false;

this->fallthrough(CondLabel);
this->emitLabel(CondLabel);

Expand All @@ -4440,10 +4453,9 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
}

{
DestructorScope<Emitter> DS(Scope);

if (Body && !this->visitLoopBody(Body))
if (Body && !this->visitStmt(Body))
return false;

this->fallthrough(IncLabel);
this->emitLabel(IncLabel);
if (Inc && !this->discard(Inc))
Expand Down Expand Up @@ -4495,13 +4507,11 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
return false;

// Body.
LocalScope<Emitter> Scope(this);
{
DestructorScope<Emitter> DS(Scope);

if (!this->visitLoopBody(Body))
if (!this->visitStmt(Body))
return false;
this->fallthrough(IncLabel);

this->fallthrough(IncLabel);
this->emitLabel(IncLabel);
if (!this->discard(Inc))
return false;
Expand All @@ -4520,7 +4530,7 @@ bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
if (!BreakLabel)
return false;

this->VarScope->emitDestructors();
this->emitCleanup();
return this->jump(*BreakLabel);
}

Expand All @@ -4529,7 +4539,7 @@ bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
if (!ContinueLabel)
return false;

this->VarScope->emitDestructors();
this->emitCleanup();
return this->jump(*ContinueLabel);
}

Expand Down
47 changes: 20 additions & 27 deletions clang/lib/AST/Interp/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,

// Statements.
bool visitCompoundStmt(const CompoundStmt *S);
bool visitLoopBody(const Stmt *S);
bool visitDeclStmt(const DeclStmt *DS);
bool visitReturnStmt(const ReturnStmt *RS);
bool visitIfStmt(const IfStmt *IS);
Expand Down Expand Up @@ -390,9 +389,6 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
llvm::SmallVector<InitLink> InitStack;
bool InitStackActive = false;

/// Flag indicating if we're initializing a global variable.
bool GlobalDecl = false;

/// Type of the expression returned by the function.
std::optional<PrimType> ReturnType;

Expand Down Expand Up @@ -452,11 +448,15 @@ template <class Emitter> class VariableScope {
}

// Use the parent scope.
addExtended(Local);
if (this->Parent)
this->Parent->addLocal(Local);
else
this->addLocal(Local);
}

virtual void emitDestruction() {}
virtual bool emitDestructors() { return true; }
virtual bool emitDestructors(const Expr *E = nullptr) { return true; }
virtual bool destroyLocals(const Expr *E = nullptr) { return true; }
VariableScope *getParent() const { return Parent; }

protected:
Expand All @@ -483,16 +483,21 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
}

/// Overriden to support explicit destruction.
void emitDestruction() override { destroyLocals(); }
void emitDestruction() override {
if (!Idx)
return;

this->emitDestructors();
this->Ctx->emitDestroy(*Idx, SourceInfo{});
}

/// Explicit destruction of local variables.
bool destroyLocals() {
bool destroyLocals(const Expr *E = nullptr) override {
if (!Idx)
return true;

bool Success = this->emitDestructors();
this->Ctx->emitDestroy(*Idx, SourceInfo{});
removeStoredOpaqueValues();
bool Success = this->emitDestructors(E);
this->Ctx->emitDestroy(*Idx, E);
this->Idx = std::nullopt;
return Success;
}
Expand All @@ -501,25 +506,26 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
if (!Idx) {
Idx = this->Ctx->Descriptors.size();
this->Ctx->Descriptors.emplace_back();
this->Ctx->emitInitScope(*Idx, {});
}

this->Ctx->Descriptors[*Idx].emplace_back(Local);
}

bool emitDestructors() override {
bool emitDestructors(const Expr *E = nullptr) override {
if (!Idx)
return true;
// Emit destructor calls for local variables of record
// type with a destructor.
for (Scope::Local &Local : this->Ctx->Descriptors[*Idx]) {
if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) {
if (!this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{}))
if (!this->Ctx->emitGetPtrLocal(Local.Offset, E))
return false;

if (!this->Ctx->emitDestruction(Local.Desc))
return false;

if (!this->Ctx->emitPopPtr(SourceInfo{}))
if (!this->Ctx->emitPopPtr(E))
return false;
removeIfStoredOpaqueValue(Local);
}
Expand Down Expand Up @@ -549,19 +555,6 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> {
std::optional<unsigned> Idx;
};

/// Emits the destructors of the variables of \param OtherScope
/// when this scope is destroyed. Does not create a Scope in the bytecode at
/// all, this is just a RAII object to emit destructors.
template <class Emitter> class DestructorScope final {
public:
DestructorScope(LocalScope<Emitter> &OtherScope) : OtherScope(OtherScope) {}

~DestructorScope() { OtherScope.emitDestructors(); }

private:
LocalScope<Emitter> &OtherScope;
};

/// Scope for storage declared in a compound statement.
template <class Emitter> class BlockScope final : public LocalScope<Emitter> {
public:
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/Interp/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {

if (!Recursing) {
assert(Stk.empty());
C.cleanup();
#ifndef NDEBUG
// Make sure we don't rely on some value being still alive in
// InterpStack memory.
Expand All @@ -82,6 +83,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {

if (!Recursing) {
assert(Stk.empty());
C.cleanup();
#ifndef NDEBUG
// Make sure we don't rely on some value being still alive in
// InterpStack memory.
Expand Down Expand Up @@ -111,6 +113,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,

if (!Recursing) {
assert(Stk.empty());
C.cleanup();
#ifndef NDEBUG
// Make sure we don't rely on some value being still alive in
// InterpStack memory.
Expand Down
21 changes: 15 additions & 6 deletions clang/lib/AST/Interp/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ static void moveArrayTy(Block *, const std::byte *Src, std::byte *Dst,
Src += sizeof(InitMapPtr);
Dst += sizeof(InitMapPtr);
for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
const auto *SrcPtr = &reinterpret_cast<const T *>(Src)[I];
auto *SrcPtr = &reinterpret_cast<T *>(const_cast<std::byte *>(Src))[I];
auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];
new (DstPtr) T(std::move(*SrcPtr));
}
Expand Down Expand Up @@ -225,12 +225,21 @@ static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {

static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst,
const Descriptor *D) {
for (const auto &F : D->ElemRecord->fields()) {
auto FieldOff = F.Offset;
auto *FieldDesc = F.Desc;
assert(D);
assert(D->ElemRecord);

if (auto Fn = FieldDesc->MoveFn)
Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc);
// FIXME: There might be cases where we need to move over the (v)bases as
// well.
for (const auto &F : D->ElemRecord->fields()) {
auto FieldOffset = F.Offset;
const auto *SrcDesc =
reinterpret_cast<const InlineDescriptor *>(Src + FieldOffset) - 1;
auto *DestDesc =
reinterpret_cast<InlineDescriptor *>(Dst + FieldOffset) - 1;
std::memcpy(DestDesc, SrcDesc, sizeof(InlineDescriptor));

if (auto Fn = F.Desc->MoveFn)
Fn(B, Src + FieldOffset, Dst + FieldOffset, F.Desc);
}
}

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
#include <limits>
#include <vector>

using namespace clang;

using namespace clang;
using namespace clang::interp;

Expand Down Expand Up @@ -838,6 +836,12 @@ static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
const Record *R = Desc->ElemRecord;
assert(R);

if (Pointer::pointToSameBlock(BasePtr, S.Current->getThis())) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_double_destroy);
return false;
}

// Fields.
for (const Record::Field &Field : llvm::reverse(R->fields())) {
const Descriptor *D = Field.Desc;
Expand Down
29 changes: 26 additions & 3 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1158,6 +1158,21 @@ bool Pop(InterpState &S, CodePtr OpPC) {
return true;
}

/// [Value1, Value2] -> [Value2, Value1]
template <PrimType TopName, PrimType BottomName>
bool Flip(InterpState &S, CodePtr OpPC) {
using TopT = typename PrimConv<TopName>::T;
using BottomT = typename PrimConv<BottomName>::T;

const auto &Top = S.Stk.pop<TopT>();
const auto &Bottom = S.Stk.pop<BottomT>();

S.Stk.push<TopT>(Top);
S.Stk.push<BottomT>(Bottom);

return true;
}

//===----------------------------------------------------------------------===//
// Const
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2012,6 +2027,11 @@ inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
return true;
}

inline bool InitScope(InterpState &S, CodePtr OpPC, uint32_t I) {
S.Current->initScope(I);
return true;
}

//===----------------------------------------------------------------------===//
// Cast, CastFP
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -2767,13 +2787,16 @@ inline bool Unsupported(InterpState &S, CodePtr OpPC) {
inline bool Error(InterpState &S, CodePtr OpPC) { return false; }

/// Same here, but only for casts.
inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind) {
inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
bool Fatal) {
const SourceLocation &Loc = S.Current->getLocation(OpPC);

// FIXME: Support diagnosing other invalid cast kinds.
if (Kind == CastKind::Reinterpret)
S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
if (Kind == CastKind::Reinterpret) {
S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
return !Fatal;
}
return false;
}

Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/Interp/InterpBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ void Block::addPointer(Pointer *P) {
P->Next = Pointers;
P->Prev = nullptr;
Pointers = P;
#ifndef NDEBUG
assert(hasPointer(P));
#endif
}

void Block::removePointer(Pointer *P) {
assert(P->isBlockPointer());
assert(P);
if (IsStatic) {
assert(!Pointers);
Expand All @@ -51,6 +55,10 @@ void Block::removePointer(Pointer *P) {
P->Prev->Next = P->Next;
if (P->Next)
P->Next->Prev = P->Prev;
P->PointeeStorage.BS.Pointee = nullptr;
#ifndef NDEBUG
assert(!hasPointer(P));
#endif
}

void Block::cleanup() {
Expand Down
18 changes: 12 additions & 6 deletions clang/lib/AST/Interp/InterpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ InterpFrame::InterpFrame(InterpState &S, const Function *Func,
Locals = std::make_unique<char[]>(FrameSize);
for (auto &Scope : Func->scopes()) {
for (auto &Local : Scope.locals()) {
Block *B =
new (localBlock(Local.Offset)) Block(S.Ctx.getEvalID(), Local.Desc);
B->invokeCtor();
new (localBlock(Local.Offset)) Block(S.Ctx.getEvalID(), Local.Desc);
// Note that we are NOT calling invokeCtor() here, since that is done
// via the InitScope op.
new (localInlineDesc(Local.Offset)) InlineDescriptor(Local.Desc);
}
}
Expand Down Expand Up @@ -75,14 +75,20 @@ InterpFrame::~InterpFrame() {
if (Func) {
for (auto &Scope : Func->scopes()) {
for (auto &Local : Scope.locals()) {
Block *B = localBlock(Local.Offset);
if (B->isInitialized())
B->invokeDtor();
S.deallocate(localBlock(Local.Offset));
}
}
}
}

void InterpFrame::initScope(unsigned Idx) {
if (!Func)
return;
for (auto &Local : Func->getScope(Idx).locals()) {
localBlock(Local.Offset)->invokeCtor();
}
}

void InterpFrame::destroy(unsigned Idx) {
for (auto &Local : Func->getScope(Idx).locals()) {
S.deallocate(localBlock(Local.Offset));
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/InterpFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class InterpFrame final : public Frame {

/// Invokes the destructors for a scope.
void destroy(unsigned Idx);
void initScope(unsigned Idx);

/// Pops the arguments off the stack.
void popArgs();
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,9 @@ def Destroy : Opcode {
let Args = [ArgUint32];
let HasCustomEval = 1;
}
def InitScope : Opcode {
let Args = [ArgUint32];
}

//===----------------------------------------------------------------------===//
// Constants
Expand Down Expand Up @@ -726,12 +729,17 @@ def Dup : Opcode {
let HasGroup = 1;
}

def Flip : Opcode {
let Types = [AllTypeClass, AllTypeClass];
let HasGroup = 1;
}

// [] -> []
def Invalid : Opcode {}
def Unsupported : Opcode {}
def Error : Opcode {}
def InvalidCast : Opcode {
let Args = [ArgCastKind];
let Args = [ArgCastKind, ArgBool];
}

def InvalidDeclRef : Opcode {
Expand Down
71 changes: 55 additions & 16 deletions clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "MemberPointer.h"
#include "PrimType.h"
#include "Record.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/RecordLayout.h"

using namespace clang;
Expand Down Expand Up @@ -60,19 +61,25 @@ Pointer::~Pointer() {

if (Block *Pointee = PointeeStorage.BS.Pointee) {
Pointee->removePointer(this);
PointeeStorage.BS.Pointee = nullptr;
Pointee->cleanup();
}
}

void Pointer::operator=(const Pointer &P) {
// If the current storage type is Block, we need to remove
// this pointer from the block.
bool WasBlockPointer = isBlockPointer();
if (StorageKind == Storage::Block) {
Block *Old = PointeeStorage.BS.Pointee;
if (WasBlockPointer && Old) {
PointeeStorage.BS.Pointee->removePointer(this);
Old->cleanup();
if (isBlockPointer()) {
if (P.isBlockPointer() && this->block() == P.block()) {
Offset = P.Offset;
PointeeStorage.BS.Base = P.PointeeStorage.BS.Base;
return;
}

if (Block *Pointee = PointeeStorage.BS.Pointee) {
Pointee->removePointer(this);
PointeeStorage.BS.Pointee = nullptr;
Pointee->cleanup();
}
}

Expand All @@ -97,12 +104,18 @@ void Pointer::operator=(const Pointer &P) {
void Pointer::operator=(Pointer &&P) {
// If the current storage type is Block, we need to remove
// this pointer from the block.
bool WasBlockPointer = isBlockPointer();
if (StorageKind == Storage::Block) {
Block *Old = PointeeStorage.BS.Pointee;
if (WasBlockPointer && Old) {
PointeeStorage.BS.Pointee->removePointer(this);
Old->cleanup();
if (isBlockPointer()) {
if (P.isBlockPointer() && this->block() == P.block()) {
Offset = P.Offset;
PointeeStorage.BS.Base = P.PointeeStorage.BS.Base;
return;
}

if (Block *Pointee = PointeeStorage.BS.Pointee) {
assert(P.block() != this->block());
Pointee->removePointer(this);
PointeeStorage.BS.Pointee = nullptr;
Pointee->cleanup();
}
}

Expand Down Expand Up @@ -143,12 +156,32 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
APValue::LValueBase Base;
if (const auto *VD = Desc->asValueDecl())
Base = VD;
else if (const auto *E = Desc->asExpr())
Base = E;
else
else if (const auto *E = Desc->asExpr()) {
// Create a DynamicAlloc base of the right type.
if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
QualType AllocatedType;
if (NewExpr->isArray()) {
assert(Desc->isArray());
APInt ArraySize(64, static_cast<uint64_t>(Desc->getNumElems()),
/*IsSigned=*/false);
AllocatedType =
ASTCtx.getConstantArrayType(NewExpr->getAllocatedType(), ArraySize,
nullptr, ArraySizeModifier::Normal, 0);
} else {
AllocatedType = NewExpr->getAllocatedType();
}
// FIXME: Suboptimal counting of dynamic allocations. Move this to Context
// or InterpState?
static int ReportedDynamicAllocs = 0;
DynamicAllocLValue DA(ReportedDynamicAllocs++);
Base = APValue::LValueBase::getDynamicAlloc(DA, AllocatedType);
} else {
Base = E;
}
} else
llvm_unreachable("Invalid allocation type");

if (isUnknownSizeArray() || Desc->asExpr())
if (isUnknownSizeArray())
return APValue(Base, CharUnits::Zero(), Path,
/*IsOnePastEnd=*/isOnePastEnd(), /*IsNullPtr=*/false);

Expand Down Expand Up @@ -386,6 +419,12 @@ bool Pointer::hasSameBase(const Pointer &A, const Pointer &B) {
return A.asBlockPointer().Pointee == B.asBlockPointer().Pointee;
}

bool Pointer::pointToSameBlock(const Pointer &A, const Pointer &B) {
if (!A.isBlockPointer() || !B.isBlockPointer())
return false;
return A.block() == B.block();
}

bool Pointer::hasSameArray(const Pointer &A, const Pointer &B) {
return hasSameBase(A, B) &&
A.PointeeStorage.BS.Base == B.PointeeStorage.BS.Base &&
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,8 @@ class Pointer {
static bool hasSameBase(const Pointer &A, const Pointer &B);
/// Checks if two pointers can be subtracted.
static bool hasSameArray(const Pointer &A, const Pointer &B);
/// Checks if both given pointers point to the same block.
static bool pointToSameBlock(const Pointer &A, const Pointer &B);

/// Prints the pointer.
void print(llvm::raw_ostream &OS) const;
Expand Down
13 changes: 9 additions & 4 deletions clang/lib/AST/Interp/Source.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Function;
/// Pointer into the code segment.
class CodePtr final {
public:
CodePtr() : Ptr(nullptr) {}
CodePtr() = default;

CodePtr &operator+=(int32_t Offset) {
Ptr += Offset;
Expand All @@ -45,11 +45,16 @@ class CodePtr final {
assert(Ptr != nullptr && "Invalid code pointer");
return CodePtr(Ptr - RHS);
}
CodePtr operator+(ssize_t RHS) const {
assert(Ptr != nullptr && "Invalid code pointer");
return CodePtr(Ptr + RHS);
}

bool operator!=(const CodePtr &RHS) const { return Ptr != RHS.Ptr; }
const std::byte *operator*() const { return Ptr; }

operator bool() const { return Ptr; }
explicit operator bool() const { return Ptr; }
bool operator<=(const CodePtr &RHS) const { return Ptr <= RHS.Ptr; }
bool operator>=(const CodePtr &RHS) const { return Ptr >= RHS.Ptr; }

/// Reads data and advances the pointer.
template <typename T> std::enable_if_t<!std::is_pointer<T>::value, T> read() {
Expand All @@ -65,7 +70,7 @@ class CodePtr final {
/// Constructor used by Function to generate pointers.
CodePtr(const std::byte *Ptr) : Ptr(Ptr) {}
/// Pointer into the code owned by a function.
const std::byte *Ptr;
const std::byte *Ptr = nullptr;
};

/// Describes the statement/declaration an opcode was generated from.
Expand Down
78 changes: 78 additions & 0 deletions clang/lib/AST/OpenMPClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1720,6 +1720,41 @@ const Expr *OMPDoacrossClause::getLoopData(unsigned NumLoop) const {
return *It;
}

OMPAbsentClause *OMPAbsentClause::Create(const ASTContext &C,
ArrayRef<OpenMPDirectiveKind> DKVec,
SourceLocation Loc,
SourceLocation LLoc,
SourceLocation RLoc) {
void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(DKVec.size()),
alignof(OMPAbsentClause));
auto *AC = new (Mem) OMPAbsentClause(Loc, LLoc, RLoc, DKVec.size());
AC->setDirectiveKinds(DKVec);
return AC;
}

OMPAbsentClause *OMPAbsentClause::CreateEmpty(const ASTContext &C, unsigned K) {
void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(K),
alignof(OMPAbsentClause));
return new (Mem) OMPAbsentClause(K);
}

OMPContainsClause *OMPContainsClause::Create(
const ASTContext &C, ArrayRef<OpenMPDirectiveKind> DKVec,
SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(DKVec.size()),
alignof(OMPContainsClause));
auto *CC = new (Mem) OMPContainsClause(Loc, LLoc, RLoc, DKVec.size());
CC->setDirectiveKinds(DKVec);
return CC;
}

OMPContainsClause *OMPContainsClause::CreateEmpty(const ASTContext &C,
unsigned K) {
void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(K),
alignof(OMPContainsClause));
return new (Mem) OMPContainsClause(K);
}

//===----------------------------------------------------------------------===//
// OpenMP clauses printing methods
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1937,6 +1972,49 @@ void OMPClausePrinter::VisitOMPFailClause(OMPFailClause *Node) {
}
}

void OMPClausePrinter::VisitOMPAbsentClause(OMPAbsentClause *Node) {
OS << "absent(";
bool First = true;
for (auto &D : Node->getDirectiveKinds()) {
if (!First)
OS << ", ";
OS << getOpenMPDirectiveName(D);
First = false;
}
OS << ")";
}

void OMPClausePrinter::VisitOMPHoldsClause(OMPHoldsClause *Node) {
OS << "holds(";
Node->getExpr()->printPretty(OS, nullptr, Policy, 0);
OS << ")";
}

void OMPClausePrinter::VisitOMPContainsClause(OMPContainsClause *Node) {
OS << "contains(";
bool First = true;
for (auto &D : Node->getDirectiveKinds()) {
if (!First)
OS << ", ";
OS << getOpenMPDirectiveName(D);
First = false;
}
OS << ")";
}

void OMPClausePrinter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {
OS << "no_openmp";
}

void OMPClausePrinter::VisitOMPNoOpenMPRoutinesClause(
OMPNoOpenMPRoutinesClause *) {
OS << "no_openmp_routines";
}

void OMPClausePrinter::VisitOMPNoParallelismClause(OMPNoParallelismClause *) {
OS << "no_parallelism";
}

void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
Expand Down
17 changes: 17 additions & 0 deletions clang/lib/AST/StmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,23 @@ OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C,
return new (C) OMPTaskyieldDirective();
}

OMPAssumeDirective *OMPAssumeDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses,
Stmt *AStmt) {
return createDirective<OMPAssumeDirective>(C, Clauses, AStmt,
/*NumChildren=*/0, StartLoc,
EndLoc);
}

OMPAssumeDirective *OMPAssumeDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
return createEmptyDirective<OMPAssumeDirective>(C, NumClauses,
/*HasAssociatedStmt=*/true);
}

OMPErrorDirective *OMPErrorDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,11 @@ void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) {
PrintOMPExecutableDirective(Node);
}

void StmtPrinter::VisitOMPAssumeDirective(OMPAssumeDirective *Node) {
Indent() << "#pragma omp assume";
PrintOMPExecutableDirective(Node);
}

void StmtPrinter::VisitOMPErrorDirective(OMPErrorDirective *Node) {
Indent() << "#pragma omp error";
PrintOMPExecutableDirective(Node);
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,20 @@ void OMPClauseProfiler::VisitOMPCompareClause(const OMPCompareClause *) {}

void OMPClauseProfiler::VisitOMPFailClause(const OMPFailClause *) {}

void OMPClauseProfiler::VisitOMPAbsentClause(const OMPAbsentClause *) {}

void OMPClauseProfiler::VisitOMPHoldsClause(const OMPHoldsClause *) {}

void OMPClauseProfiler::VisitOMPContainsClause(const OMPContainsClause *) {}

void OMPClauseProfiler::VisitOMPNoOpenMPClause(const OMPNoOpenMPClause *) {}

void OMPClauseProfiler::VisitOMPNoOpenMPRoutinesClause(
const OMPNoOpenMPRoutinesClause *) {}

void OMPClauseProfiler::VisitOMPNoParallelismClause(
const OMPNoParallelismClause *) {}

void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}

void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
Expand Down Expand Up @@ -1068,6 +1082,10 @@ void StmtProfiler::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *S) {
VisitOMPExecutableDirective(S);
}

void StmtProfiler::VisitOMPAssumeDirective(const OMPAssumeDirective *S) {
VisitOMPExecutableDirective(S);
}

void StmtProfiler::VisitOMPErrorDirective(const OMPErrorDirective *S) {
VisitOMPExecutableDirective(S);
}
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Basic/OpenMPKinds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,13 @@ bool clang::isOpenMPExecutableDirective(OpenMPDirectiveKind DKind) {
return Cat == Category::Executable || Cat == Category::Subsidiary;
}

bool clang::isOpenMPInformationalDirective(OpenMPDirectiveKind DKind) {
if (DKind == OMPD_error)
return true;
Category Cat = getDirectiveCategory(DKind);
return Cat == Category::Informational;
}

bool clang::isOpenMPCapturingDirective(OpenMPDirectiveKind DKind) {
if (isOpenMPExecutableDirective(DKind)) {
switch (DKind) {
Expand All @@ -726,6 +733,7 @@ bool clang::isOpenMPCapturingDirective(OpenMPDirectiveKind DKind) {
case OMPD_section:
case OMPD_taskwait:
case OMPD_taskyield:
case OMPD_assume:
return false;
default:
return !isOpenMPLoopTransformationDirective(DKind);
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/Basic/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasAVX10_1 = true;
} else if (Feature == "+avx10.1-512") {
HasAVX10_1_512 = true;
} else if (Feature == "+avx10.2-256") {
HasAVX10_2 = true;
} else if (Feature == "+avx10.2-512") {
HasAVX10_2_512 = true;
} else if (Feature == "+avx512cd") {
HasAVX512CD = true;
} else if (Feature == "+avx512vpopcntdq") {
Expand Down Expand Up @@ -824,6 +828,10 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__AVX10_1__");
if (HasAVX10_1_512)
Builder.defineMacro("__AVX10_1_512__");
if (HasAVX10_2)
Builder.defineMacro("__AVX10_2__");
if (HasAVX10_2_512)
Builder.defineMacro("__AVX10_2_512__");
if (HasAVX512CD)
Builder.defineMacro("__AVX512CD__");
if (HasAVX512VPOPCNTDQ)
Expand Down Expand Up @@ -1056,6 +1064,8 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
.Case("avx", true)
.Case("avx10.1-256", true)
.Case("avx10.1-512", true)
.Case("avx10.2-256", true)
.Case("avx10.2-512", true)
.Case("avx2", true)
.Case("avx512f", true)
.Case("avx512cd", true)
Expand Down Expand Up @@ -1171,6 +1181,8 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("avx", SSELevel >= AVX)
.Case("avx10.1-256", HasAVX10_1)
.Case("avx10.1-512", HasAVX10_1_512)
.Case("avx10.2-256", HasAVX10_2)
.Case("avx10.2-512", HasAVX10_2_512)
.Case("avx2", SSELevel >= AVX2)
.Case("avx512f", SSELevel >= AVX512F)
.Case("avx512cd", HasAVX512CD)
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/X86.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasF16C = false;
bool HasAVX10_1 = false;
bool HasAVX10_1_512 = false;
bool HasAVX10_2 = false;
bool HasAVX10_2_512 = false;
bool HasEVEX512 = false;
bool HasAVX512CD = false;
bool HasAVX512VPOPCNTDQ = false;
Expand Down
134 changes: 134 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13938,6 +13938,54 @@ static Value *EmitX86FMAExpr(CodeGenFunction &CGF, const CallExpr *E,
case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
IID = llvm::Intrinsic::x86_avx512_vfmaddsub_pd_512;
break;
case clang::X86::BI__builtin_ia32_vfmsubph256_round_mask3:
Subtract = true;
LLVM_FALLTHROUGH;
case clang::X86::BI__builtin_ia32_vfmaddph256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddph256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddph256_round_mask3:
IID = llvm::Intrinsic::x86_avx10_vfmaddph256;
break;
case clang::X86::BI__builtin_ia32_vfmsubaddph256_round_mask3:
Subtract = true;
LLVM_FALLTHROUGH;
case clang::X86::BI__builtin_ia32_vfmaddsubph256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddsubph256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddsubph256_round_mask3:
IID = llvm::Intrinsic::x86_avx10_vfmaddsubph256;
break;
case clang::X86::BI__builtin_ia32_vfmsubps256_round_mask3:
Subtract = true;
LLVM_FALLTHROUGH;
case clang::X86::BI__builtin_ia32_vfmaddps256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddps256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddps256_round_mask3:
IID = llvm::Intrinsic::x86_avx10_vfmaddps256;
break;
case clang::X86::BI__builtin_ia32_vfmsubpd256_round_mask3:
Subtract = true;
LLVM_FALLTHROUGH;
case clang::X86::BI__builtin_ia32_vfmaddpd256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddpd256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddpd256_round_mask3:
IID = llvm::Intrinsic::x86_avx10_vfmaddpd256;
break;
case clang::X86::BI__builtin_ia32_vfmsubaddps256_round_mask3:
Subtract = true;
LLVM_FALLTHROUGH;
case clang::X86::BI__builtin_ia32_vfmaddsubps256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddsubps256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddsubps256_round_mask3:
IID = llvm::Intrinsic::x86_avx10_vfmaddsubps256;
break;
case clang::X86::BI__builtin_ia32_vfmsubaddpd256_round_mask3:
Subtract = true;
LLVM_FALLTHROUGH;
case clang::X86::BI__builtin_ia32_vfmaddsubpd256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddsubpd256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddsubpd256_round_mask3:
IID = llvm::Intrinsic::x86_avx10_vfmaddsubpd256;
break;
}

Value *A = Ops[0];
Expand Down Expand Up @@ -13977,6 +14025,12 @@ static Value *EmitX86FMAExpr(CodeGenFunction &CGF, const CallExpr *E,
case clang::X86::BI__builtin_ia32_vfmaddsubph512_mask:
case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask:
case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask:
case clang::X86::BI__builtin_ia32_vfmaddph256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddps256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddpd256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddsubph256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddsubps256_round_mask:
case clang::X86::BI__builtin_ia32_vfmaddsubpd256_round_mask:
MaskFalseVal = Ops[0];
break;
case clang::X86::BI__builtin_ia32_vfmaddph512_maskz:
Expand All @@ -13985,6 +14039,12 @@ static Value *EmitX86FMAExpr(CodeGenFunction &CGF, const CallExpr *E,
case clang::X86::BI__builtin_ia32_vfmaddsubph512_maskz:
case clang::X86::BI__builtin_ia32_vfmaddsubps512_maskz:
case clang::X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
case clang::X86::BI__builtin_ia32_vfmaddph256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddps256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddpd256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddsubph256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddsubps256_round_maskz:
case clang::X86::BI__builtin_ia32_vfmaddsubpd256_round_maskz:
MaskFalseVal = Constant::getNullValue(Ops[0]->getType());
break;
case clang::X86::BI__builtin_ia32_vfmsubph512_mask3:
Expand All @@ -13999,6 +14059,18 @@ static Value *EmitX86FMAExpr(CodeGenFunction &CGF, const CallExpr *E,
case clang::X86::BI__builtin_ia32_vfmaddsubps512_mask3:
case clang::X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
case clang::X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
case clang::X86::BI__builtin_ia32_vfmsubph256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmaddph256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmsubps256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmaddps256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmsubpd256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmaddpd256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmsubaddph256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmaddsubph256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmsubaddps256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmaddsubps256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmsubaddpd256_round_mask3:
case clang::X86::BI__builtin_ia32_vfmaddsubpd256_round_mask3:
MaskFalseVal = Ops[2];
break;
}
Expand Down Expand Up @@ -14686,13 +14758,25 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_vcvtw2ph512_mask:
case X86::BI__builtin_ia32_vcvtdq2ph512_mask:
case X86::BI__builtin_ia32_vcvtqq2ph512_mask:
case X86::BI__builtin_ia32_vcvtdq2ph256_round_mask:
case X86::BI__builtin_ia32_vcvtdq2ps256_round_mask:
case X86::BI__builtin_ia32_vcvtqq2pd256_round_mask:
case X86::BI__builtin_ia32_vcvtqq2ph256_round_mask:
case X86::BI__builtin_ia32_vcvtqq2ps256_round_mask:
case X86::BI__builtin_ia32_vcvtw2ph256_round_mask:
return EmitX86ConvertIntToFp(*this, E, Ops, /*IsSigned*/ true);
case X86::BI__builtin_ia32_cvtudq2ps512_mask:
case X86::BI__builtin_ia32_cvtuqq2ps512_mask:
case X86::BI__builtin_ia32_cvtuqq2pd512_mask:
case X86::BI__builtin_ia32_vcvtuw2ph512_mask:
case X86::BI__builtin_ia32_vcvtudq2ph512_mask:
case X86::BI__builtin_ia32_vcvtuqq2ph512_mask:
case X86::BI__builtin_ia32_vcvtudq2ph256_round_mask:
case X86::BI__builtin_ia32_vcvtudq2ps256_round_mask:
case X86::BI__builtin_ia32_vcvtuqq2pd256_round_mask:
case X86::BI__builtin_ia32_vcvtuqq2ph256_round_mask:
case X86::BI__builtin_ia32_vcvtuqq2ps256_round_mask:
case X86::BI__builtin_ia32_vcvtuw2ph256_round_mask:
return EmitX86ConvertIntToFp(*this, E, Ops, /*IsSigned*/ false);

case X86::BI__builtin_ia32_vfmaddss3:
Expand Down Expand Up @@ -14736,6 +14820,18 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_vfmaddpd512_mask3:
case X86::BI__builtin_ia32_vfmsubpd512_mask3:
case X86::BI__builtin_ia32_vfmsubph512_mask3:
case X86::BI__builtin_ia32_vfmaddph256_round_mask:
case X86::BI__builtin_ia32_vfmaddph256_round_maskz:
case X86::BI__builtin_ia32_vfmaddph256_round_mask3:
case X86::BI__builtin_ia32_vfmaddps256_round_mask:
case X86::BI__builtin_ia32_vfmaddps256_round_maskz:
case X86::BI__builtin_ia32_vfmaddps256_round_mask3:
case X86::BI__builtin_ia32_vfmsubps256_round_mask3:
case X86::BI__builtin_ia32_vfmaddpd256_round_mask:
case X86::BI__builtin_ia32_vfmaddpd256_round_maskz:
case X86::BI__builtin_ia32_vfmaddpd256_round_mask3:
case X86::BI__builtin_ia32_vfmsubpd256_round_mask3:
case X86::BI__builtin_ia32_vfmsubph256_round_mask3:
return EmitX86FMAExpr(*this, E, Ops, BuiltinID, /*IsAddSub*/ false);
case X86::BI__builtin_ia32_vfmaddsubph512_mask:
case X86::BI__builtin_ia32_vfmaddsubph512_maskz:
Expand All @@ -14749,6 +14845,18 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_vfmaddsubpd512_maskz:
case X86::BI__builtin_ia32_vfmaddsubpd512_mask3:
case X86::BI__builtin_ia32_vfmsubaddpd512_mask3:
case X86::BI__builtin_ia32_vfmaddsubph256_round_mask:
case X86::BI__builtin_ia32_vfmaddsubph256_round_maskz:
case X86::BI__builtin_ia32_vfmaddsubph256_round_mask3:
case X86::BI__builtin_ia32_vfmsubaddph256_round_mask3:
case X86::BI__builtin_ia32_vfmaddsubps256_round_mask:
case X86::BI__builtin_ia32_vfmaddsubps256_round_maskz:
case X86::BI__builtin_ia32_vfmaddsubps256_round_mask3:
case X86::BI__builtin_ia32_vfmsubaddps256_round_mask3:
case X86::BI__builtin_ia32_vfmaddsubpd256_round_mask:
case X86::BI__builtin_ia32_vfmaddsubpd256_round_maskz:
case X86::BI__builtin_ia32_vfmaddsubpd256_round_mask3:
case X86::BI__builtin_ia32_vfmsubaddpd256_round_mask3:
return EmitX86FMAExpr(*this, E, Ops, BuiltinID, /*IsAddSub*/ true);

case X86::BI__builtin_ia32_movdqa32store128_mask:
Expand Down Expand Up @@ -16329,6 +16437,9 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
case X86::BI__builtin_ia32_cmppd128_mask:
case X86::BI__builtin_ia32_cmppd256_mask:
case X86::BI__builtin_ia32_cmppd512_mask:
case X86::BI__builtin_ia32_vcmppd256_round_mask:
case X86::BI__builtin_ia32_vcmpps256_round_mask:
case X86::BI__builtin_ia32_vcmpph256_round_mask:
IsMaskFCmp = true;
[[fallthrough]];
case X86::BI__builtin_ia32_cmpps:
Expand Down Expand Up @@ -16832,6 +16943,15 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), Ops);
return EmitX86Select(*this, Ops[3], Call, Ops[0]);
}
case X86::BI__builtin_ia32_vfcmaddcph256_round_mask:
IsConjFMA = true;
LLVM_FALLTHROUGH;
case X86::BI__builtin_ia32_vfmaddcph256_round_mask: {
Intrinsic::ID IID = IsConjFMA ? Intrinsic::x86_avx10_mask_vfcmaddcph256
: Intrinsic::x86_avx10_mask_vfmaddcph256;
Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID), Ops);
return EmitX86Select(*this, Ops[3], Call, Ops[0]);
}
case X86::BI__builtin_ia32_vfcmaddcsh_round_mask:
IsConjFMA = true;
[[fallthrough]];
Expand Down Expand Up @@ -18452,6 +18572,20 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
/*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getLerpIntrinsic(),
ArrayRef<Value *>{X, Y, S}, nullptr, "hlsl.lerp");
}
case Builtin::BI__builtin_hlsl_length: {
Value *X = EmitScalarExpr(E->getArg(0));

assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
"length operand must have a float representation");
// if the operand is a scalar, we can use the fabs llvm intrinsic directly
if (!E->getArg(0)->getType()->isVectorType())
return EmitFAbs(*this, X);

return Builder.CreateIntrinsic(
/*ReturnType=*/X->getType()->getScalarType(),
CGM.getHLSLRuntime().getLengthIntrinsic(), ArrayRef<Value *>{X},
nullptr, "hlsl.length");
}
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
Expand Down
24 changes: 14 additions & 10 deletions clang/lib/CodeGen/CGHLSLRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,18 +280,22 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) {
const auto *RD = Ty->getAsCXXRecordDecl();
if (!RD)
return;
const auto *HLSLResAttr = RD->getAttr<HLSLResourceAttr>();
const auto *HLSLResClassAttr = RD->getAttr<HLSLResourceClassAttr>();
if (!HLSLResAttr || !HLSLResClassAttr)
return;
// the resource related attributes are on the handle member
// inside the record decl
for (auto *FD : RD->fields()) {
const auto *HLSLResAttr = FD->getAttr<HLSLResourceAttr>();
const auto *HLSLResClassAttr = FD->getAttr<HLSLResourceClassAttr>();
if (!HLSLResAttr || !HLSLResClassAttr)
continue;

llvm::hlsl::ResourceClass RC = HLSLResClassAttr->getResourceClass();
llvm::hlsl::ResourceKind RK = HLSLResAttr->getResourceKind();
bool IsROV = HLSLResAttr->getIsROV();
llvm::hlsl::ElementType ET = calculateElementType(CGM.getContext(), Ty);
llvm::hlsl::ResourceClass RC = HLSLResClassAttr->getResourceClass();
llvm::hlsl::ResourceKind RK = HLSLResAttr->getResourceKind();
bool IsROV = HLSLResAttr->getIsROV();
llvm::hlsl::ElementType ET = calculateElementType(CGM.getContext(), Ty);

BufferResBinding Binding(D->getAttr<HLSLResourceBindingAttr>());
addBufferResourceAnnotation(GV, RC, RK, IsROV, ET, Binding);
BufferResBinding Binding(D->getAttr<HLSLResourceBindingAttr>());
addBufferResourceAnnotation(GV, RC, RK, IsROV, ET, Binding);
}
}

CGHLSLRuntime::BufferResBinding::BufferResBinding(
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)
GENERATE_HLSL_INTRINSIC_FUNCTION(Length, length)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
GENERATE_HLSL_INTRINSIC_FUNCTION(Rsqrt, rsqrt)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
Expand Down
22 changes: 14 additions & 8 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7125,6 +7125,9 @@ class MappableExprsHandler {
bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous;
bool IsPrevMemberReference = false;

bool IsPartialMapped =
!PartialStruct.PreliminaryMapData.BasePointers.empty();

// We need to check if we will be encountering any MEs. If we do not
// encounter any ME expression it means we will be mapping the whole struct.
// In that case we need to skip adding an entry for the struct to the
Expand Down Expand Up @@ -7370,7 +7373,9 @@ class MappableExprsHandler {
// whole struct is currently being mapped. The struct needs to be added
// in the first position before any data internal to the struct is being
// mapped.
if (!IsMemberPointerOrAddr ||
// Skip adding an entry in the CurInfo of this combined entry if the
// PartialStruct.PreliminaryMapData.BasePointers has been mapped.
if ((!IsMemberPointerOrAddr && !IsPartialMapped) ||
(Next == CE && MapType != OMPC_MAP_unknown)) {
if (!IsMappingWholeStruct) {
CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr);
Expand Down Expand Up @@ -7486,8 +7491,8 @@ class MappableExprsHandler {
// The pointer becomes the base for the next element.
if (Next != CE)
BP = IsMemberReference ? LowestElem : LB;

IsExpressionFirstInfo = false;
if (!IsPartialMapped)
IsExpressionFirstInfo = false;
IsCaptureFirstInfo = false;
FirstPointerInComplexData = false;
IsPrevMemberReference = IsMemberReference;
Expand Down Expand Up @@ -8295,7 +8300,9 @@ class MappableExprsHandler {
// Map type is always TARGET_PARAM, if generate info for captures.
CombinedInfo.Types.push_back(
NotTargetParams ? OpenMPOffloadMappingFlags::OMP_MAP_NONE
: OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
: !PartialStruct.PreliminaryMapData.BasePointers.empty()
? OpenMPOffloadMappingFlags::OMP_MAP_PTR_AND_OBJ
: OpenMPOffloadMappingFlags::OMP_MAP_TARGET_PARAM);
// If any element has the present modifier, then make sure the runtime
// doesn't attempt to allocate the struct.
if (CurTypes.end() !=
Expand Down Expand Up @@ -9525,10 +9532,9 @@ static void genMapInfoForCaptures(
// individual members mapped. Emit an extra combined entry.
if (PartialStruct.Base.isValid()) {
CombinedInfo.append(PartialStruct.PreliminaryMapData);
MEHandler.emitCombinedEntry(
CombinedInfo, CurInfo.Types, PartialStruct, CI->capturesThis(),
OMPBuilder, nullptr,
!PartialStruct.PreliminaryMapData.BasePointers.empty());
MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct,
CI->capturesThis(), OMPBuilder, nullptr,
/*NotTargetParams*/ false);
}

// We need to append the results of this capture to what we already have.
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
case Stmt::OMPParallelMaskedDirectiveClass:
EmitOMPParallelMaskedDirective(cast<OMPParallelMaskedDirective>(*S));
break;
case Stmt::OMPAssumeDirectiveClass:
EmitOMPAssumeDirective(cast<OMPAssumeDirective>(*S));
break;
case Stmt::OpenACCComputeConstructClass:
EmitOpenACCComputeConstruct(cast<OpenACCComputeConstruct>(*S));
break;
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/CodeGen/CGStmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8288,7 +8288,8 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
D.getDirectiveKind() == OMPD_section ||
D.getDirectiveKind() == OMPD_master ||
D.getDirectiveKind() == OMPD_masked ||
D.getDirectiveKind() == OMPD_unroll) {
D.getDirectiveKind() == OMPD_unroll ||
D.getDirectiveKind() == OMPD_assume) {
EmitStmt(D.getAssociatedStmt());
} else {
auto LPCRegion =
Expand All @@ -8303,3 +8304,7 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
// Check for outer lastprivate conditional update.
checkForLastprivateConditionalUpdate(*this, D);
}

void CodeGenFunction::EmitOMPAssumeDirective(const OMPAssumeDirective &S) {
EmitStmt(S.getAssociatedStmt());
}
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3904,6 +3904,7 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S);
void EmitOMPInteropDirective(const OMPInteropDirective &S);
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S);
void EmitOMPAssumeDirective(const OMPAssumeDirective &S);

/// Emit device code for the target directive.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM,
Expand Down Expand Up @@ -5309,7 +5310,7 @@ class CodeGenFunction : public CodeGenTypeCache {
llvm::SmallVector<StringRef, 8> Features;

Conds(StringRef Arch, ArrayRef<StringRef> Feats)
: Architecture(Arch), Features(Feats.begin(), Feats.end()) {}
: Architecture(Arch), Features(Feats) {}
} Conditions;

MultiVersionResolverOption(llvm::Function *F, StringRef Arch,
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3492,7 +3492,7 @@ class OffloadingActionBuilder final {
// a fat binary containing all the code objects for different GPU's.
// The fat binary is then an input to the host action.
for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) {
if (C.getDriver().isUsingLTO(/*IsOffload=*/true)) {
if (C.getDriver().isUsingOffloadLTO()) {
// When LTO is enabled, skip the backend and assemble phases and
// use lld to link the bitcode.
ActionList AL;
Expand Down Expand Up @@ -4856,8 +4856,7 @@ Action *Driver::ConstructPhaseAction(
Output = types::TY_LTO_BC;
return C.MakeAction<BackendJobAction>(Input, Output);
}
if (isUsingLTO(/* IsOffload */ true) &&
TargetDeviceOffloadKind != Action::OFK_None) {
if (isUsingOffloadLTO() && TargetDeviceOffloadKind != Action::OFK_None) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
return C.MakeAction<BackendJobAction>(Input, Output);
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Driver/ToolChains/AIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,10 @@ void AIX::addClangTargetOptions(
options::OPT_fno_sized_deallocation))
CC1Args.push_back("-fno-sized-deallocation");

if (!Args.hasFlag(options::OPT_ferr_pragma_mc_func_aix,
options::OPT_fno_err_pragma_mc_func_aix, true))
if (Args.hasFlag(options::OPT_ferr_pragma_mc_func_aix,
options::OPT_fno_err_pragma_mc_func_aix, false))
CC1Args.push_back("-ferr-pragma-mc-func-aix");
else
CC1Args.push_back("-fno-err-pragma-mc-func-aix");
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions(
}

// Link the bitcode library late if we're using device LTO.
if (getDriver().isUsingLTO(/* IsOffload */ true))
if (getDriver().isUsingOffloadLTO())
return;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Arch/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ void x86::getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
assert(Name.starts_with("avx10.") && "Invalid AVX10 feature name.");
StringRef Version, Width;
std::tie(Version, Width) = Name.substr(6).split('-');
assert(Version == "1" && "Invalid AVX10 feature name.");
assert((Version == "1" || Version == "2") && "Invalid AVX10 feature name.");
assert((Width == "256" || Width == "512") && "Invalid AVX10 feature name.");
#endif

Expand Down
15 changes: 10 additions & 5 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4959,8 +4959,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,

bool IsRDCMode =
Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false);
bool IsUsingLTO = D.isUsingLTO(IsDeviceOffloadAction);
auto LTOMode = D.getLTOMode(IsDeviceOffloadAction);

auto LTOMode = IsDeviceOffloadAction ? D.getOffloadLTOMode() : D.getLTOMode();
bool IsUsingLTO = LTOMode != LTOK_None;

// Extract API doesn't have a main input file, so invent a fake one as a
// placeholder.
Expand Down Expand Up @@ -7825,7 +7826,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// were suppressed because this is not the device offload action.
// Check if we are using PS4 in regular LTO mode.
// Otherwise, issue an error.
if ((!IsUsingLTO && !D.isUsingLTO(!IsDeviceOffloadAction)) ||

auto OtherLTOMode =
IsDeviceOffloadAction ? D.getLTOMode() : D.getOffloadLTOMode();
auto OtherIsUsingLTO = OtherLTOMode != LTOK_None;

if ((!IsUsingLTO && !OtherIsUsingLTO) ||
(IsPS4 && !UnifiedLTO && (D.getLTOMode() != LTOK_Full)))
D.Diag(diag::err_drv_argument_only_allowed_with)
<< "-fwhole-program-vtables"
Expand Down Expand Up @@ -9022,8 +9028,7 @@ void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA,
"kind=" + Kind.str(),
};

if (TC->getDriver().isUsingLTO(/* IsOffload */ true) ||
TC->getTriple().isAMDGPU())
if (TC->getDriver().isUsingOffloadLTO() || TC->getTriple().isAMDGPU())
for (StringRef Feature : FeatureArgs)
Parts.emplace_back("feature=" + Feature.str());

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -887,7 +887,7 @@ void CudaToolChain::addClangTargetOptions(
}

// Link the bitcode library late if we're using device LTO.
if (getDriver().isUsingLTO(/* IsOffload */ true))
if (getDriver().isUsingOffloadLTO())
return;

addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, GpuArch.str(),
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fcolor-diagnostics");

// LTO mode is parsed by the Clang driver library.
LTOKind LTOMode = D.getLTOMode(/* IsOffload */ false);
LTOKind LTOMode = D.getLTOMode();
assert(LTOMode != LTOK_Unknown && "Unknown LTO mode.");
if (LTOMode == LTOK_Full)
CmdArgs.push_back("-flto=full");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/HIPAMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void AMDGCN::Linker::constructLldCommand(Compilation &C, const JobAction &JA,
auto &TC = getToolChain();
auto &D = TC.getDriver();
assert(!Inputs.empty() && "Must have at least one input.");
bool IsThinLTO = D.getLTOMode(/*IsOffload=*/true) == LTOK_Thin;
bool IsThinLTO = D.getOffloadLTOMode() == LTOK_Thin;
addLTOOptions(TC, Args, LldArgs, Output, Inputs[0], IsThinLTO);

// Extract all the -m options
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/AffectedRangeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class AffectedRangeManager {
public:
AffectedRangeManager(const SourceManager &SourceMgr,
const ArrayRef<CharSourceRange> Ranges)
: SourceMgr(SourceMgr), Ranges(Ranges.begin(), Ranges.end()) {}
: SourceMgr(SourceMgr), Ranges(Ranges) {}

// Determines which lines are affected by the SourceRanges given as input.
// Returns \c true if at least one line in \p Lines or one of their
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/TokenAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ TokenAnalyzer::process(bool SkipAnnotation) {
Env.getFirstStartColumn(), Style, Encoding, Allocator,
IdentTable);
ArrayRef<FormatToken *> Toks(Lex.lex());
SmallVector<FormatToken *, 10> Tokens(Toks.begin(), Toks.end());
SmallVector<FormatToken *, 10> Tokens(Toks);
UnwrappedLineParser Parser(Env.getSourceManager(), Style, Lex.getKeywords(),
Env.getFirstStartColumn(), Tokens, *this,
Allocator, IdentTable);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/UnwrappedLineParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ struct UnwrappedLineNode {
UnwrappedLineNode() : Tok(nullptr) {}
UnwrappedLineNode(FormatToken *Tok,
llvm::ArrayRef<UnwrappedLine> Children = {})
: Tok(Tok), Children(Children.begin(), Children.end()) {}
: Tok(Tok), Children(Children) {}

FormatToken *Tok;
SmallVector<UnwrappedLine, 0> Children;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ clang::createInvocation(ArrayRef<const char *> ArgList,
? std::move(Opts.Diags)
: CompilerInstance::createDiagnostics(new DiagnosticOptions);

SmallVector<const char *, 16> Args(ArgList.begin(), ArgList.end());
SmallVector<const char *, 16> Args(ArgList);

// FIXME: Find a cleaner way to force the driver into restricted modes.
Args.insert(
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Frontend/DiagnosticRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ void DiagnosticRenderer::emitDiagnostic(FullSourceLoc Loc,
emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, D);
else {
// Get the ranges into a local array we can hack on.
SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(),
Ranges.end());
SmallVector<CharSourceRange, 20> MutableRanges(Ranges);

SmallVector<FixItHint, 8> MergedFixits;
if (!FixItHints.empty()) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Frontend/InitPreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
Builder.defineMacro("__cpp_placeholder_variables", "202306L");

// C++26 features supported in earlier language modes.
Builder.defineMacro("__cpp_pack_indexing", "202311L");
Builder.defineMacro("__cpp_deleted_function", "202403L");

if (LangOpts.Char8)
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Headers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ set(x86_files
amxcomplexintrin.h
amxfp16intrin.h
amxintrin.h
avx10_2_512minmaxintrin.h
avx10_2_512niintrin.h
avx10_2minmaxintrin.h
avx10_2niintrin.h
avx2intrin.h
avx512bf16intrin.h
avx512bitalgintrin.h
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/Headers/__clang_hip_cmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,12 @@ template <class _Tp> struct __numeric_type {
// No support for long double, use double instead.
static double __test(long double);

typedef decltype(__test(declval<_Tp>())) type;
template <typename _U>
static auto __test_impl(int) -> decltype(__test(declval<_U>()));

template <typename _U> static void __test_impl(...);

typedef decltype(__test_impl<_Tp>(0)) type;
static const bool value = !is_same<type, void>::value;
};

Expand Down
127 changes: 127 additions & 0 deletions clang/lib/Headers/avx10_2_512minmaxintrin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*===---- avx10_2_512minmaxintrin.h - AVX10_2_512MINMAX intrinsics ---------===
*
* 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 __IMMINTRIN_H
#error \
"Never use <avx10_2_512minmaxintrin.h> directly; include <immintrin.h> instead."
#endif // __IMMINTRIN_H

#ifndef __AVX10_2_512MINMAXINTRIN_H
#define __AVX10_2_512MINMAXINTRIN_H

#define _mm512_minmaxne_pbh(A, B, C) \
((__m512bh)__builtin_ia32_vminmaxnepbf16512( \
(__v32bf)(__m512bh)(A), (__v32bf)(__m512bh)(A), (int)(C)))

#define _mm512_mask_minmaxne_pbh(W, U, A, B, C) \
((__m512bh)__builtin_ia32_selectpbf_512( \
(__mmask32)(U), \
(__v32bf)_mm512_minmaxne_pbh((__v32bf)(__m512bh)(A), \
(__v32bf)(__m512bh)(B), (int)(C)), \
(__v32bf)(__m512bh)(W)))

#define _mm512_maskz_minmaxne_pbh(U, A, B, C) \
((__m512bh)__builtin_ia32_selectpbf_512( \
(__mmask32)(U), \
(__v32bf)_mm512_minmaxne_pbh((__v32bf)(__m512bh)(A), \
(__v32bf)(__m512bh)(B), (int)(C)), \
(__v32bf) __builtin_bit_cast(__m512bh, _mm512_setzero_ps())))

#define _mm512_minmax_pd(A, B, C) \
((__m512d)__builtin_ia32_vminmaxpd512_round_mask( \
(__v8df)(__m512d)(A), (__v8df)(__m512d)(B), (int)(C), \
(__v8df)_mm512_undefined_pd(), (__mmask8)-1, \
_MM_FROUND_CUR_DIRECTION))

#define _mm512_mask_minmax_pd(W, U, A, B, C) \
((__m512d)__builtin_ia32_vminmaxpd512_round_mask( \
(__v8df)(__m512d)(A), (__v8df)(__m512d)(B), (int)(C), \
(__v8df)(__m512d)(W), (__mmask8)(U), _MM_FROUND_CUR_DIRECTION))

#define _mm512_maskz_minmax_pd(U, A, B, C) \
((__m512d)__builtin_ia32_vminmaxpd512_round_mask( \
(__v8df)(__m512d)(A), (__v8df)(__m512d)(B), (int)(C), \
(__v8df)_mm512_setzero_pd(), (__mmask8)(U), _MM_FROUND_CUR_DIRECTION))

#define _mm512_minmax_round_pd(A, B, C, R) \
((__m512d)__builtin_ia32_vminmaxpd512_round_mask( \
(__v8df)(__m512d)(A), (__v8df)(__m512d)(B), (int)(C), \
(__v8df)_mm512_undefined_pd(), (__mmask8)-1, (int)(R)))

#define _mm512_mask_minmax_round_pd(W, U, A, B, C, R) \
((__m512d)__builtin_ia32_vminmaxpd512_round_mask( \
(__v8df)(__m512d)(A), (__v8df)(__m512d)(B), (int)(C), \
(__v8df)(__m512d)(W), (__mmask8)(U), (int)(R)))

#define _mm512_maskz_minmax_round_pd(U, A, B, C, R) \
((__m512d)__builtin_ia32_vminmaxpd512_round_mask( \
(__v8df)(__m512d)(A), (__v8df)(__m512d)(B), (int)(C), \
(__v8df)_mm512_setzero_pd(), (__mmask8)(U), (int)(R)))

#define _mm512_minmax_ph(A, B, C) \
((__m512h)__builtin_ia32_vminmaxph512_round_mask( \
(__v32hf)(__m512h)(A), (__v32hf)(__m512h)(B), (int)(C), \
(__v32hf)_mm512_undefined_ph(), (__mmask32)-1, \
_MM_FROUND_CUR_DIRECTION))

#define _mm512_mask_minmax_ph(W, U, A, B, C) \
((__m512h)__builtin_ia32_vminmaxph512_round_mask( \
(__v32hf)(__m512h)(A), (__v32hf)(__m512h)(B), (int)(C), \
(__v32hf)(__m512h)(W), (__mmask32)(U), _MM_FROUND_CUR_DIRECTION))

#define _mm512_maskz_minmax_ph(U, A, B, C) \
((__m512h)__builtin_ia32_vminmaxph512_round_mask( \
(__v32hf)(__m512h)(A), (__v32hf)(__m512h)(B), (int)(C), \
(__v32hf)_mm512_setzero_ph(), (__mmask32)(U), _MM_FROUND_CUR_DIRECTION))

#define _mm512_minmax_round_ph(A, B, C, R) \
((__m512h)__builtin_ia32_vminmaxph512_round_mask( \
(__v32hf)(__m512h)(A), (__v32hf)(__m512h)(B), (int)(C), \
(__v32hf)_mm512_undefined_ph(), (__mmask32)-1, (int)(R)))

#define _mm512_mask_minmax_round_ph(W, U, A, B, C, R) \
((__m512h)__builtin_ia32_vminmaxph512_round_mask( \
(__v32hf)(__m512h)(A), (__v32hf)(__m512h)(B), (int)(C), \
(__v32hf)(__m512h)(W), (__mmask32)(U), (int)(R)))

#define _mm512_maskz_minmax_round_ph(U, A, B, C, R) \
((__m512h)__builtin_ia32_vminmaxph512_round_mask( \
(__v32hf)(__m512h)(A), (__v32hf)(__m512h)(B), (int)(C), \
(__v32hf)_mm512_setzero_ph(), (__mmask32)(U), (int)(R)))

#define _mm512_minmax_ps(A, B, C) \
((__m512)__builtin_ia32_vminmaxps512_round_mask( \
(__v16sf)(__m512)(A), (__v16sf)(__m512)(B), (int)(C), \
(__v16sf)_mm512_undefined_ps(), (__mmask16)-1, \
_MM_FROUND_CUR_DIRECTION))

#define _mm512_mask_minmax_ps(W, U, A, B, C) \
((__m512)__builtin_ia32_vminmaxps512_round_mask( \
(__v16sf)(__m512)(A), (__v16sf)(__m512)(B), (int)(C), (__v16sf)(W), \
(__mmask16)(U), _MM_FROUND_CUR_DIRECTION))

#define _mm512_maskz_minmax_ps(U, A, B, C) \
((__m512)__builtin_ia32_vminmaxps512_round_mask( \
(__v16sf)(__m512)(A), (__v16sf)(__m512)(B), (int)(C), \
(__v16sf)_mm512_setzero_ps(), (__mmask16)(U), _MM_FROUND_CUR_DIRECTION))

#define _mm512_minmax_round_ps(A, B, C, R) \
((__m512)__builtin_ia32_vminmaxps512_round_mask( \
(__v16sf)(__m512)(A), (__v16sf)(__m512)(B), (int)(C), \
(__v16sf)_mm512_undefined_ps(), (__mmask16)-1, (int)(R)))

#define _mm512_mask_minmax_round_ps(W, U, A, B, C, R) \
((__m512)__builtin_ia32_vminmaxps512_round_mask( \
(__v16sf)(__m512)(A), (__v16sf)(__m512)(B), (int)(C), (__v16sf)(W), \
(__mmask16)(U), (int)(R)))

#define _mm512_maskz_minmax_round_ps(U, A, B, C, R) \
((__m512)__builtin_ia32_vminmaxps512_round_mask( \
(__v16sf)(__m512)(A), (__v16sf)(__m512)(B), (int)(C), \
(__v16sf)_mm512_setzero_ps(), (__mmask16)(U), (int)(R)))
#endif // __AVX10_2_512MINMAXINTRIN_H
Loading