9 changes: 9 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2170,11 +2170,13 @@ class SYCLUniqueStableNameExpr final : public Expr {
class ParenExpr : public Expr {
SourceLocation L, R;
Stmt *Val;

public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(), val->getValueKind(),
val->getObjectKind()),
L(l), R(r), Val(val) {
ParenExprBits.ProducedByFoldExpansion = false;
setDependence(computeDependence(this));
}

Expand Down Expand Up @@ -2206,6 +2208,13 @@ class ParenExpr : public Expr {
const_child_range children() const {
return const_child_range(&Val, &Val + 1);
}

bool isProducedByFoldExpansion() const {
return ParenExprBits.ProducedByFoldExpansion != 0;
}
void setIsProducedByFoldExpansion(bool ProducedByFoldExpansion = true) {
ParenExprBits.ProducedByFoldExpansion = ProducedByFoldExpansion;
}
};

/// UnaryOperator - This represents the unary-expression's (except sizeof and
Expand Down
99 changes: 99 additions & 0 deletions clang/include/clang/AST/OpenMPClause.h
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,105 @@ class OMPSizesClause final
}
};

/// This class represents the 'permutation' clause in the
/// '#pragma omp interchange' directive.
///
/// \code{.c}
/// #pragma omp interchange permutation(2,1)
/// for (int i = 0; i < 64; ++i)
/// for (int j = 0; j < 64; ++j)
/// \endcode
class OMPPermutationClause final
: public OMPClause,
private llvm::TrailingObjects<OMPSizesClause, Expr *> {
friend class OMPClauseReader;
friend class llvm::TrailingObjects<OMPSizesClause, Expr *>;

/// Location of '('.
SourceLocation LParenLoc;

/// Number of arguments in the clause, and hence also the number of loops to
/// be permuted.
unsigned NumLoops;

/// Sets the permutation index expressions.
void setArgRefs(ArrayRef<Expr *> VL) {
assert(VL.size() == NumLoops && "Expecting one expression per loop");
llvm::copy(VL, static_cast<OMPPermutationClause *>(this)
->template getTrailingObjects<Expr *>());
}

/// Build an empty clause.
explicit OMPPermutationClause(int NumLoops)
: OMPClause(llvm::omp::OMPC_permutation, SourceLocation(),
SourceLocation()),
NumLoops(NumLoops) {}

public:
/// Build a 'permutation' clause AST node.
///
/// \param C Context of the AST.
/// \param StartLoc Location of the 'permutation' identifier.
/// \param LParenLoc Location of '('.
/// \param EndLoc Location of ')'.
/// \param Args Content of the clause.
static OMPPermutationClause *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
SourceLocation EndLoc, ArrayRef<Expr *> Args);

/// Build an empty 'permutation' AST node for deserialization.
///
/// \param C Context of the AST.
/// \param NumLoops Number of arguments in the clause.
static OMPPermutationClause *CreateEmpty(const ASTContext &C,
unsigned NumLoops);

/// Sets the location of '('.
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }

/// Returns the location of '('.
SourceLocation getLParenLoc() const { return LParenLoc; }

/// Returns the number of list items.
unsigned getNumLoops() const { return NumLoops; }

/// Returns the permutation index expressions.
///@{
MutableArrayRef<Expr *> getArgsRefs() {
return MutableArrayRef<Expr *>(static_cast<OMPPermutationClause *>(this)
->template getTrailingObjects<Expr *>(),
NumLoops);
}
ArrayRef<Expr *> getArgsRefs() const {
return ArrayRef<Expr *>(static_cast<const OMPPermutationClause *>(this)
->template getTrailingObjects<Expr *>(),
NumLoops);
}
///@}

child_range children() {
MutableArrayRef<Expr *> Args = getArgsRefs();
return child_range(reinterpret_cast<Stmt **>(Args.begin()),
reinterpret_cast<Stmt **>(Args.end()));
}
const_child_range children() const {
ArrayRef<Expr *> Args = getArgsRefs();
return const_child_range(reinterpret_cast<Stmt *const *>(Args.begin()),
reinterpret_cast<Stmt *const *>(Args.end()));
}

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());
}

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

/// Representation of the 'full' clause of the '#pragma omp unroll' directive.
///
/// \code
Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -3348,6 +3348,14 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSizesClause(OMPSizesClause *C) {
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPPermutationClause(
OMPPermutationClause *C) {
for (Expr *E : C->getArgsRefs())
TRY_TO(TraverseStmt(E));
return true;
}

template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPFullClause(OMPFullClause *C) {
return true;
Expand Down
13 changes: 13 additions & 0 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,18 @@ class alignas(void *) Stmt {
unsigned Kind : 3;
};

class ParenExprBitfields {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class ParenExpr;

LLVM_PREFERRED_TYPE(ExprBitfields)
unsigned : NumExprBits;

LLVM_PREFERRED_TYPE(bool)
unsigned ProducedByFoldExpansion : 1;
};

class StmtExprBitfields {
friend class ASTStmtReader;
friend class StmtExpr;
Expand Down Expand Up @@ -1241,6 +1253,7 @@ class alignas(void *) Stmt {
GenericSelectionExprBitfields GenericSelectionExprBits;
PseudoObjectExprBitfields PseudoObjectExprBits;
SourceLocExprBitfields SourceLocExprBits;
ParenExprBitfields ParenExprBits;

// GNU Extensions.
StmtExprBitfields StmtExprBits;
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -4824,6 +4824,12 @@ def HLSLStep: LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

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

// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticFrontendKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ def warn_atomic_op_misaligned : Warning<
def warn_atomic_op_oversized : Warning<
"large atomic operation may incur "
"significant performance penalty"
"; the access size (%0 bytes) exceeds the max lock-free size (%1 bytes)">,
"; the access size (%0 bytes) exceeds the max lock-free size (%1 bytes)">,
InGroup<AtomicAlignment>;

def warn_sync_op_misaligned : Warning<
Expand Down
14 changes: 6 additions & 8 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -5262,13 +5262,6 @@ def note_template_arg_refers_here_func : Note<
def err_template_arg_template_params_mismatch : Error<
"template template argument has different template parameters than its "
"corresponding template template parameter">;
def note_template_arg_template_params_mismatch : Note<
"template template argument has different template parameters than its "
"corresponding template template parameter">;
def err_non_deduced_mismatch : Error<
"could not match %diff{$ against $|types}0,1">;
def err_inconsistent_deduction : Error<
"conflicting deduction %diff{$ against $|types}0,1 for parameter">;
def err_template_arg_not_integral_or_enumeral : Error<
"non-type template argument of type %0 must have an integral or enumeration"
" type">;
Expand Down Expand Up @@ -9386,7 +9379,8 @@ let CategoryName = "Inline Assembly Issue" in {
"global register variables on this target">;
def err_asm_register_size_mismatch : Error<"size of register '%0' does not "
"match variable size">;
def err_asm_bad_register_type : Error<"bad type for named register variable">;
def err_asm_unsupported_register_type : Error<
"unsupported type for named register variable">;
def err_asm_invalid_input_size : Error<
"invalid input size for constraint '%0'">;
def err_asm_invalid_output_size : Error<
Expand Down Expand Up @@ -11708,6 +11702,10 @@ def err_omp_dispatch_statement_call
" to a target function or an assignment to one">;
def err_omp_unroll_full_variable_trip_count : Error<
"loop to be fully unrolled must have a constant trip count">;
def err_omp_interchange_permutation_value_range : Error<
"permutation index must be at least 1 and at most %0">;
def err_omp_interchange_permutation_value_repeated : Error<
"index %0 must appear exactly once in the permutation clause">;
def note_omp_directive_here : Note<"'%0' directive found here">;
def err_omp_instantiation_not_supported
: Error<"instantiation of '%0' not supported yet">;
Expand Down
11 changes: 4 additions & 7 deletions clang/include/clang/Basic/PlistSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,10 @@ using FIDMap = llvm::DenseMap<FileID, unsigned>;

inline unsigned AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
FileID FID) {
FIDMap::iterator I = FIDs.find(FID);
if (I != FIDs.end())
return I->second;
unsigned NewValue = V.size();
FIDs[FID] = NewValue;
V.push_back(FID);
return NewValue;
auto [I, Inserted] = FIDs.try_emplace(FID, V.size());
if (Inserted)
V.push_back(FID);
return I->second;
}

inline unsigned AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@
#ifndef EXPRESSION_TRAIT
#define EXPRESSION_TRAIT(I,E,K) KEYWORD(I,K)
#endif
#ifndef TRANSFORM_TYPE_TRAIT_DEF
#define TRANSFORM_TYPE_TRAIT_DEF(K, Trait) KEYWORD(__##Trait, KEYCXX)
#endif

#ifndef ALIAS
#define ALIAS(X,Y,Z)
#endif
Expand Down Expand Up @@ -534,7 +538,6 @@ TYPE_TRAIT_1(__has_unique_object_representations,
TYPE_TRAIT_2(__is_layout_compatible, IsLayoutCompatible, KEYCXX)
TYPE_TRAIT_2(__is_pointer_interconvertible_base_of, IsPointerInterconvertibleBaseOf, KEYCXX)

#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) KEYWORD(__##Trait, KEYCXX)
#include "clang/Basic/TransformTypeTraits.def"

// Clang-only C++ Type Traits
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/riscv_vector.td
Original file line number Diff line number Diff line change
Expand Up @@ -2564,7 +2564,7 @@ let HasMasked = false, HasVL = false, IRName = "" in {

return Builder.CreateIntrinsic(Intrinsic::riscv_tuple_extract,
{ResultType, Ops[0]->getType()},
{Ops[0], Builder.CreateZExt(Ops[1],
{Ops[0], Builder.CreateTrunc(Ops[1],
Builder.getInt32Ty())});
}
}] in {
Expand Down Expand Up @@ -2606,7 +2606,7 @@ let HasMasked = false, HasVL = false, IRName = "" in {
return Builder.CreateIntrinsic(Intrinsic::riscv_tuple_insert,
{ResultType, Ops[2]->getType()},
{Ops[0], Ops[2],
Builder.CreateZExt(Ops[1],Builder.getInt32Ty())});
Builder.CreateTrunc(Ops[1],Builder.getInt32Ty())});
}
}] in {
foreach dst_lmul = ["(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in {
Expand Down
62 changes: 62 additions & 0 deletions clang/include/clang/CIR/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
InheritParentConfig: true
Checks: >
-misc-const-correctness,
-llvm-header-guard,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-suspicious-semicolon,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-unused-raii,
bugprone-unused-return-value,
misc-redundant-expression,
misc-static-assert,
misc-unused-using-decls,
modernize-use-bool-literals,
modernize-loop-convert,
modernize-make-unique,
modernize-raw-string-literal,
modernize-use-equals-default,
modernize-use-default-member-init,
modernize-use-emplace,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-no-automatic-move,
performance-trivially-destructible,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-identifier-naming,
readability-inconsistent-declaration-parameter-name,
readability-misleading-indentation,
readability-redundant-control-flow,
readability-redundant-smartptr-get,
readability-simplify-boolean-expr,
readability-simplify-subscript-expr,
readability-use-anyofallof
CheckOptions:
- key: readability-identifier-naming.MemberCase
value: camelBack
- key: readability-identifier-naming.ParameterCase
value: camelBack
- key: readability-identifier-naming.VariableCase
value: camelBack
60 changes: 60 additions & 0 deletions clang/include/clang/CIR/CIRGenerator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===- CIRGenerator.h - CIR Generation from Clang AST ---------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file declares a simple interface to perform CIR generation from Clang
// AST
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_CIR_CIRGENERATOR_H
#define LLVM_CLANG_CIR_CIRGENERATOR_H

#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/CodeGenOptions.h"

#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/Support/VirtualFileSystem.h"

#include <memory>

namespace clang {
class DeclGroupRef;
class DiagnosticsEngine;
} // namespace clang

namespace mlir {
class MLIRContext;
} // namespace mlir
namespace cir {
class CIRGenModule;

class CIRGenerator : public clang::ASTConsumer {
virtual void anchor();
clang::DiagnosticsEngine &diags;
clang::ASTContext *astCtx;
// Only used for debug info.
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs;

const clang::CodeGenOptions &codeGenOpts;

protected:
std::unique_ptr<mlir::MLIRContext> mlirCtx;
std::unique_ptr<CIRGenModule> cgm;

public:
CIRGenerator(clang::DiagnosticsEngine &diags,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
const clang::CodeGenOptions &cgo);
~CIRGenerator() override;
void Initialize(clang::ASTContext &astCtx) override;
bool HandleTopLevelDecl(clang::DeclGroupRef group) override;
};

} // namespace cir

#endif // LLVM_CLANG_CIR_CIRGENERATOR_H
60 changes: 60 additions & 0 deletions clang/include/clang/CIR/FrontendAction/CIRGenAction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===---- CIRGenAction.h - CIR Code Generation Frontend Action -*- C++ -*--===//
//
// 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 LLVM_CLANG_CIR_CIRGENACTION_H
#define LLVM_CLANG_CIR_CIRGENACTION_H

#include "clang/Frontend/FrontendAction.h"

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/OwningOpRef.h"

namespace mlir {
class MLIRContext;
class ModuleOp;
} // namespace mlir

namespace cir {
class CIRGenConsumer;

class CIRGenAction : public clang::ASTFrontendAction {
public:
enum class OutputType {
EmitCIR,
};

private:
friend class CIRGenConsumer;

mlir::OwningOpRef<mlir::ModuleOp> MLIRMod;

mlir::MLIRContext *MLIRCtx;

protected:
CIRGenAction(OutputType Action, mlir::MLIRContext *MLIRCtx = nullptr);

std::unique_ptr<clang::ASTConsumer>
CreateASTConsumer(clang::CompilerInstance &CI,
llvm::StringRef InFile) override;

public:
~CIRGenAction() override;

OutputType Action;
};

class EmitCIRAction : public CIRGenAction {
virtual void anchor();

public:
EmitCIRAction(mlir::MLIRContext *MLIRCtx = nullptr);
};

} // namespace cir

#endif
53 changes: 53 additions & 0 deletions clang/include/clang/CIRFrontendAction/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
InheritParentConfig: true
Checks: >
-misc-const-correctness,
-llvm-header-guard,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-suspicious-semicolon,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-unused-raii,
bugprone-unused-return-value,
misc-redundant-expression,
misc-static-assert,
misc-unused-using-decls,
modernize-use-bool-literals,
modernize-loop-convert,
modernize-make-unique,
modernize-raw-string-literal,
modernize-use-equals-default,
modernize-use-default-member-init,
modernize-use-emplace,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-no-automatic-move,
performance-trivially-destructible,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-identifier-naming,
readability-inconsistent-declaration-parameter-name,
readability-misleading-indentation,
readability-redundant-control-flow,
readability-redundant-smartptr-get,
readability-simplify-boolean-expr,
readability-simplify-subscript-expr,
readability-use-anyofallof
8 changes: 4 additions & 4 deletions clang/include/clang/Driver/Multilib.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Multilib {
// Some Multilib objects don't actually represent library directories you can
// select. Instead, they represent failures of multilib selection, of the
// form 'Sorry, we don't have any library compatible with these constraints'.
std::optional<std::string> FatalError;
std::optional<std::string> Error;

public:
/// GCCSuffix, OSSuffix & IncludeSuffix will be appended directly to the
Expand All @@ -63,7 +63,7 @@ class Multilib {
Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {},
StringRef IncludeSuffix = {}, const flags_list &Flags = flags_list(),
StringRef ExclusiveGroup = {},
std::optional<StringRef> FatalError = std::nullopt);
std::optional<StringRef> Error = std::nullopt);

/// Get the detected GCC installation path suffix for the multi-arch
/// target variant. Always starts with a '/', unless empty
Expand Down Expand Up @@ -94,9 +94,9 @@ class Multilib {

bool operator==(const Multilib &Other) const;

bool isFatalError() const { return FatalError.has_value(); }
bool isError() const { return Error.has_value(); }

const std::string &getFatalError() const { return FatalError.value(); }
const std::string &getErrorMessage() const { return Error.value(); }
};

raw_ostream &operator<<(raw_ostream &OS, const Multilib &M);
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2996,7 +2996,7 @@ defm clangir : BoolFOption<"clangir",
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Use the ClangIR pipeline to compile">,
NegFlag<SetFalse, [], [ClangOption, CC1Option], "Use the AST -> LLVM pipeline to compile">,
BothFlags<[], [ClangOption, CC1Option], "">>;
def emit_cir : Flag<["-"], "emit-cir">, Visibility<[CC1Option]>,
def emit_cir : Flag<["-"], "emit-cir">, Visibility<[ClangOption, CC1Option]>,
Group<Action_Group>, HelpText<"Build ASTs and then lower to ClangIR">;
/// ClangIR-specific options - END

Expand Down Expand Up @@ -5558,6 +5558,9 @@ def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>,
Visibility<[ClangOption, FlangOption]>,
HelpText<"Only supported on AArch64, PowerPC, RISC-V, SPARC, SystemZ, and X86">;
def multi_lib_config : Joined<["-", "--"], "multi-lib-config=">,
HelpText<"Path to the YAML configuration file to be used for multilib selection">,
MetaVarName<"<file>">;
def multi__module : Flag<["-"], "multi_module">;
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
def multiply__defined : Separate<["-"], "multiply_defined">;
Expand Down
28 changes: 22 additions & 6 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ struct FormatStyle {
/// Don't align array initializer columns.
AIAS_None
};
/// if not ``None``, when using initialization for an array of structs
/// If not ``None``, when using initialization for an array of structs
/// aligns the fields into columns.
///
/// \note
Expand All @@ -145,11 +145,12 @@ struct FormatStyle {
/// Alignment options.
///
/// They can also be read as a whole for compatibility. The choices are:
/// - None
/// - Consecutive
/// - AcrossEmptyLines
/// - AcrossComments
/// - AcrossEmptyLinesAndComments
///
/// * ``None``
/// * ``Consecutive``
/// * ``AcrossEmptyLines``
/// * ``AcrossComments``
/// * ``AcrossEmptyLinesAndComments``
///
/// For example, to align across empty lines and not across comments, either
/// of these work.
Expand Down Expand Up @@ -225,6 +226,20 @@ struct FormatStyle {
/// bbb = 2;
/// \endcode
bool AlignCompound;
/// Only for ``AlignConsecutiveDeclarations``. Whether function declarations
/// are aligned.
/// \code
/// true:
/// unsigned int f1(void);
/// void f2(void);
/// size_t f3(void);
///
/// false:
/// unsigned int f1(void);
/// void f2(void);
/// size_t f3(void);
/// \endcode
bool AlignFunctionDeclarations;
/// Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
/// aligned.
/// \code
Expand Down Expand Up @@ -264,6 +279,7 @@ struct FormatStyle {
return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines &&
AcrossComments == R.AcrossComments &&
AlignCompound == R.AlignCompound &&
AlignFunctionDeclarations == R.AlignFunctionDeclarations &&
AlignFunctionPointers == R.AlignFunctionPointers &&
PadOperators == R.PadOperators;
}
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -3595,6 +3595,9 @@ class Parser : public CodeCompletionHandler {
/// Parses the 'sizes' clause of a '#pragma omp tile' directive.
OMPClause *ParseOpenMPSizesClause();

/// Parses the 'permutation' clause of a '#pragma omp interchange' directive.
OMPClause *ParseOpenMPPermutationClause();

/// Parses clause without any additional arguments.
///
/// \param Kind Kind of current clause.
Expand Down
45 changes: 14 additions & 31 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -11325,9 +11325,9 @@ class Sema final : public SemaBase {
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
TemplateParameterList **OuterTemplateParamLists,
SkipBodyInfo *SkipBody = nullptr);
SourceLocation FriendLoc,
ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
bool IsMemberSpecialization, SkipBodyInfo *SkipBody = nullptr);

/// Translates template arguments as provided by the parser
/// into template arguments used by semantic analysis.
Expand Down Expand Up @@ -11366,7 +11366,8 @@ class Sema final : public SemaBase {
DeclResult ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
StorageClass SC, bool IsPartialSpecialization);
StorageClass SC, bool IsPartialSpecialization,
bool IsMemberSpecialization);

/// Get the specialization of the given variable template corresponding to
/// the specified argument list, or a null-but-valid result if the arguments
Expand Down Expand Up @@ -12416,9 +12417,8 @@ class Sema final : public SemaBase {
sema::TemplateDeductionInfo &Info);

bool isTemplateTemplateParameterAtLeastAsSpecializedAs(
TemplateParameterList *PParam, TemplateDecl *PArg, TemplateDecl *AArg,
const DefaultArguments &DefaultArgs, SourceLocation ArgLoc,
bool IsDeduced);
TemplateParameterList *PParam, TemplateDecl *AArg,
const DefaultArguments &DefaultArgs, SourceLocation Loc, bool IsDeduced);

/// Mark which template parameters are used in a given expression.
///
Expand Down Expand Up @@ -12727,9 +12727,6 @@ class Sema final : public SemaBase {

/// We are instantiating a type alias template declaration.
TypeAliasTemplateInstantiation,

/// We are performing partial ordering for template template parameters.
PartialOrderingTTP,
} Kind;

/// Was the enclosing context a non-instantiation SFINAE context?
Expand Down Expand Up @@ -12951,12 +12948,6 @@ class Sema final : public SemaBase {
TemplateDecl *Entity, BuildingDeductionGuidesTag,
SourceRange InstantiationRange = SourceRange());

struct PartialOrderingTTP {};
/// \brief Note that we are partial ordering template template parameters.
InstantiatingTemplate(Sema &SemaRef, SourceLocation ArgLoc,
PartialOrderingTTP, TemplateDecl *PArg,
SourceRange InstantiationRange = SourceRange());

/// Note that we have finished instantiating this template.
void Clear();

Expand Down Expand Up @@ -13017,28 +13008,20 @@ class Sema final : public SemaBase {
/// dealing with a specialization. This is only relevant for function
/// template specializations.
///
/// \param Pattern If non-NULL, indicates the pattern from which we will be
/// instantiating the definition of the given declaration, \p ND. This is
/// used to determine the proper set of template instantiation arguments for
/// friend function template specializations.
///
/// \param ForConstraintInstantiation when collecting arguments,
/// ForConstraintInstantiation indicates we should continue looking when
/// encountering a lambda generic call operator, and continue looking for
/// arguments on an enclosing class template.
///
/// \param SkipForSpecialization when specified, any template specializations
/// in a traversal would be ignored.
/// \param ForDefaultArgumentSubstitution indicates we should continue looking
/// when encountering a specialized member function template, rather than
/// returning immediately.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
bool ForConstraintInstantiation = false,
bool SkipForSpecialization = false,
bool ForDefaultArgumentSubstitution = false);
bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);

void getTemplateInstantiationArgs(
MultiLevelTemplateArgumentList &Result, const NamedDecl *D,
const DeclContext *DC = nullptr, bool Final = false,
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);

/// RAII object to handle the state changes required to synthesize
/// a function body.
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/SemaOpenMP.h
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,11 @@ class SemaOpenMP : public SemaBase {
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-form 'permutation' clause after parsing its arguments.
OMPClause *ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
/// Called on well-form 'full' clauses.
OMPClause *ActOnOpenMPFullClause(SourceLocation StartLoc,
SourceLocation EndLoc);
Expand Down
14 changes: 11 additions & 3 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14325,9 +14325,17 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
}
} else if (const auto *TV = FD->getAttr<TargetVersionAttr>()) {
llvm::SmallVector<StringRef, 8> Feats;
TV->getFeatures(Feats);
std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats);
std::vector<std::string> Features;
if (Target->getTriple().isRISCV()) {
ParsedTargetAttr ParsedAttr = Target->parseTargetAttr(TV->getName());
Features.insert(Features.begin(), ParsedAttr.Features.begin(),
ParsedAttr.Features.end());
} else {
assert(Target->getTriple().isAArch64());
llvm::SmallVector<StringRef, 8> Feats;
TV->getFeatures(Feats);
Features = getFMVBackendFeaturesFor(Feats);
}
Features.insert(Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,13 @@ bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(
return this->emitConst(1, E);
}

if (Kind == UETT_OpenMPRequiredSimdAlign) {
assert(E->isArgumentType());
unsigned Bits = ASTCtx.getOpenMPDefaultSimdAlign(E->getArgumentType());

return this->emitConst(ASTCtx.toCharUnitsFromBits(Bits).getQuantity(), E);
}

return false;
}

Expand Down Expand Up @@ -3579,8 +3586,9 @@ bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
}
for (unsigned I = 0; I != NumOutputElems; ++I) {
APSInt ShuffleIndex = E->getShuffleMaskIdx(Ctx.getASTContext(), I);
assert(ShuffleIndex >= -1);
if (ShuffleIndex == -1)
return this->emitInvalid(E); // FIXME: Better diagnostic.
return this->emitInvalidShuffleVectorIndex(I, E);

assert(ShuffleIndex < (NumInputElems * 2));
if (!this->emitGetLocal(PT_Ptr,
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/AST/ByteCode/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc,
const Descriptor *Desc = BasePtr.getDeclDesc();
if (const auto *CD = dyn_cast_if_present<CXXRecordDecl>(R->getDecl())) {
const auto &BS = *std::next(CD->bases_begin(), I);
S.FFDiag(BS.getBaseTypeLoc(), diag::note_constexpr_uninitialized_base)
<< B.Desc->getType() << BS.getSourceRange();
SourceLocation TypeBeginLoc = BS.getBaseTypeLoc();
S.FFDiag(TypeBeginLoc, diag::note_constexpr_uninitialized_base)
<< B.Desc->getType() << SourceRange(TypeBeginLoc, BS.getEndLoc());
} else {
S.FFDiag(Desc->getLocation(), diag::note_constexpr_uninitialized_base)
<< B.Desc->getType();
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/ByteCode/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,10 @@ class Function final {
return ParamOffsets[ParamIndex];
}

PrimType getParamType(unsigned ParamIndex) const {
return ParamTypes[ParamIndex];
}

private:
/// Construct a function representing an actual function.
Function(Program &P, FunctionDeclTy Source, unsigned ArgSize,
Expand Down
50 changes: 50 additions & 0 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/Basic/DiagnosticSema.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/StringExtras.h"
#include <limits>
Expand Down Expand Up @@ -1406,6 +1408,54 @@ bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
return S.noteUndefinedBehavior();
}

bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc,
diag::err_shufflevector_minus_one_is_undefined_behavior_constexpr)
<< Index;
return false;
}

bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
const Pointer &Ptr, unsigned BitWidth) {
if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

if (Ptr.isBlockPointer() && !Ptr.isZero()) {
// Only allow based lvalue casts if they are lossless.
if (S.getASTContext().getTargetInfo().getPointerWidth(LangAS::Default) !=
BitWidth)
return Invalid(S, OpPC);
}
return true;
}

bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
return false;

S.Stk.push<IntegralAP<false>>(
IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}

bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckPointerToIntegralCast(S, OpPC, Ptr, BitWidth))
return false;

S.Stk.push<IntegralAP<true>>(
IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}

// https://github.com/llvm/llvm-project/issues/102513
#if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", off)
Expand Down
44 changes: 7 additions & 37 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func,
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
const CallExpr *CE);
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T);
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index);

template <typename T>
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {
Expand Down Expand Up @@ -2288,53 +2289,22 @@ static inline bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC,
return CheckFloatResult(S, OpPC, F, Status, FPO);
}

bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
const Pointer &Ptr, unsigned BitWidth);
bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth);
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth);

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
if (!CheckPointerToIntegralCast(S, OpPC, Ptr, T::bitWidth()))
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
return true;
}

static inline bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

S.Stk.push<IntegralAP<false>>(
IntegralAP<false>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}

static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

S.Stk.push<IntegralAP<true>>(
IntegralAP<true>::from(Ptr.getIntegerRepresentation(), BitWidth));
return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
static inline bool CastIntegralFixedPoint(InterpState &S, CodePtr OpPC,
uint32_t FPS) {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ByteCode/InterpBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ bool Block::hasPointer(const Pointer *P) const {
#endif

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

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

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

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

Expand Down Expand Up @@ -170,6 +172,7 @@ class Block final {
/// Flag indicating if this block has been allocated via dynamic
/// memory allocation (e.g. malloc).
bool IsDynamic = false;
bool IsWeak = false;
/// Pointer to the stack slot descriptor.
const Descriptor *Desc;
};
Expand Down
60 changes: 57 additions & 3 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ static T getParam(const InterpFrame *Frame, unsigned Index) {
return Frame->getParam<T>(Offset);
}

// static APSInt getAPSIntParam(InterpStack &Stk, size_t Offset = 0) {
static APSInt getAPSIntParam(const InterpFrame *Frame, unsigned Index) {
APSInt R;
unsigned Offset = Frame->getFunction()->getParamOffset(Index);
INT_TYPE_SWITCH(Frame->getFunction()->getParamType(Index),
R = Frame->getParam<T>(Offset).toAPSInt());
return R;
}

PrimType getIntPrimType(const InterpState &S) {
const TargetInfo &TI = S.getASTContext().getTargetInfo();
unsigned IntWidth = TI.getIntWidth();
Expand Down Expand Up @@ -1184,6 +1193,10 @@ static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
QualType CallType = Call->getType();
if (!CallType->isIntegerType())
return false;

PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType IndexT = *S.Ctx.classify(Call->getArg(1));

Expand All @@ -1197,7 +1210,7 @@ static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
if (Index < BitWidth)
Val.clearHighBits(BitWidth - Index);

pushInteger(S, Val, Call->getType());
pushInteger(S, Val, CallType);
return true;
}

Expand All @@ -1210,7 +1223,7 @@ static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC,
return false;

APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
pushInteger(S, Val.countLeadingZeros(), Call->getType());
pushInteger(S, Val.countLeadingZeros(), CallType);
return true;
}

Expand All @@ -1223,7 +1236,7 @@ static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC,
return false;

APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
pushInteger(S, Val.countTrailingZeros(), Call->getType());
pushInteger(S, Val.countTrailingZeros(), CallType);
return true;
}

Expand Down Expand Up @@ -1269,6 +1282,39 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
return true;
}

static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
unsigned BuiltinOp = Func->getBuiltinID();
APSInt CarryIn = getAPSIntParam(Frame, 0);
APSInt LHS = getAPSIntParam(Frame, 1);
APSInt RHS = getAPSIntParam(Frame, 2);

bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||
BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;

unsigned BitWidth = LHS.getBitWidth();
unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;
APInt ExResult =
IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))
: (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));

APInt Result = ExResult.extractBits(BitWidth, 0);
APSInt CarryOut =
APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);

Pointer &CarryOutPtr = S.Stk.peek<Pointer>();
QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
PrimType CarryOutT = *S.getContext().classify(CarryOutType);
assignInteger(CarryOutPtr, CarryOutT, APSInt(Result, true));

pushInteger(S, CarryOut, Call->getType());

return true;
}

static bool interp__builtin_os_log_format_buffer_size(InterpState &S,
CodePtr OpPC,
const InterpFrame *Frame,
Expand Down Expand Up @@ -1894,6 +1940,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;

case clang::X86::BI__builtin_ia32_addcarryx_u32:
case clang::X86::BI__builtin_ia32_addcarryx_u64:
case clang::X86::BI__builtin_ia32_subborrow_u32:
case clang::X86::BI__builtin_ia32_subborrow_u64:
if (!interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, F, Call))
return false;
break;

case Builtin::BI__builtin_os_log_format_buffer_size:
if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call))
return false;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/ByteCode/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,9 @@ def InvalidDeclRef : Opcode {
}

def SizelessVectorElementSize : Opcode;
def InvalidShuffleVectorIndex : Opcode {
let Args = [ArgUint32];
}

def Assume : Opcode;

Expand Down
4 changes: 1 addition & 3 deletions clang/lib/AST/ByteCode/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -524,9 +524,7 @@ class Pointer {
return false;

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

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

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

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

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

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

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

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

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

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

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

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

/// Reference to the VM context.
Context &Ctx;
Expand Down
8 changes: 3 additions & 5 deletions clang/lib/AST/CXXInheritance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,10 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context,
BaseRecord = TD->getTemplatedDecl();
}
if (BaseRecord) {
if (!BaseRecord->hasDefinition() ||
VisitedDependentRecords.count(BaseRecord)) {
if (!BaseRecord->hasDefinition())
BaseRecord = nullptr;
else if (!VisitedDependentRecords.insert(BaseRecord).second)
BaseRecord = nullptr;
} else {
VisitedDependentRecords.insert(BaseRecord);
}
}
} else {
BaseRecord = cast<CXXRecordDecl>(
Expand Down
50 changes: 31 additions & 19 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2696,21 +2696,27 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
auto From = VDTemplSpec->getInstantiatedFrom();
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
while (!VTD->isMemberSpecialization()) {
auto *NewVTD = VTD->getInstantiatedFromMemberTemplate();
if (!NewVTD)
while (true) {
VTD = VTD->getMostRecentDecl();
if (VTD->isMemberSpecialization())
break;
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
break;
VTD = NewVTD;
}
return getDefinitionOrSelf(VTD->getTemplatedDecl());
}
if (auto *VTPSD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
while (!VTPSD->isMemberSpecialization()) {
auto *NewVTPSD = VTPSD->getInstantiatedFromMember();
if (!NewVTPSD)
while (true) {
VTPSD = VTPSD->getMostRecentDecl();
if (VTPSD->isMemberSpecialization())
break;
if (auto *NewVTPSD = VTPSD->getInstantiatedFromMember())
VTPSD = NewVTPSD;
else
break;
VTPSD = NewVTPSD;
}
return getDefinitionOrSelf<VarDecl>(VTPSD);
}
Expand All @@ -2719,15 +2725,17 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {

// If this is the pattern of a variable template, find where it was
// instantiated from. FIXME: Is this necessary?
if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
while (!VarTemplate->isMemberSpecialization()) {
auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
if (!NewVT)
if (VarTemplateDecl *VTD = VD->getDescribedVarTemplate()) {
while (true) {
VTD = VTD->getMostRecentDecl();
if (VTD->isMemberSpecialization())
break;
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
break;
VarTemplate = NewVT;
}

return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
return getDefinitionOrSelf(VTD->getTemplatedDecl());
}

if (VD == this)
Expand Down Expand Up @@ -3059,6 +3067,7 @@ FunctionDecl::FunctionDecl(Kind DK, ASTContext &C, DeclContext *DC,
FunctionDeclBits.IsIneligibleOrNotSelected = false;
FunctionDeclBits.HasImplicitReturnZero = false;
FunctionDeclBits.IsLateTemplateParsed = false;
FunctionDeclBits.IsInstantiatedFromMemberTemplate = false;
FunctionDeclBits.ConstexprKind = static_cast<uint64_t>(ConstexprKind);
FunctionDeclBits.BodyContainsImmediateEscalatingExpression = false;
FunctionDeclBits.InstantiationIsPending = false;
Expand Down Expand Up @@ -4142,11 +4151,14 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
// If we hit a point where the user provided a specialization of this
// template, we're done looking.
while (!ForDefinition || !Primary->isMemberSpecialization()) {
auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
if (!NewPrimary)
while (true) {
Primary = Primary->getMostRecentDecl();
if (ForDefinition && Primary->isMemberSpecialization())
break;
if (auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate())
Primary = NewPrimary;
else
break;
Primary = NewPrimary;
}

return getDefinitionOrSelf(Primary->getTemplatedDecl());
Expand Down
55 changes: 46 additions & 9 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1631,13 +1631,42 @@ static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) {
static NamedDecl* getLambdaCallOperatorHelper(const CXXRecordDecl &RD) {
if (!RD.isLambda()) return nullptr;
DeclarationName Name =
RD.getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
DeclContext::lookup_result Calls = RD.lookup(Name);
RD.getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);

DeclContext::lookup_result Calls = RD.lookup(Name);
assert(!Calls.empty() && "Missing lambda call operator!");
assert(allLookupResultsAreTheSame(Calls) &&
"More than one lambda call operator!");
return Calls.front();

// FIXME: If we have multiple call operators, we might be in a situation
// where we merged this lambda with one from another module; in that
// case, return our method (instead of that of the other lambda).
//
// This avoids situations where, given two modules A and B, if we
// try to instantiate A's call operator in a function in B, anything
// in the call operator that relies on local decls in the surrounding
// function will crash because it tries to find A's decls, but we only
// instantiated B's:
//
// template <typename>
// void f() {
// using T = int; // We only instantiate B's version of this.
// auto L = [](T) { }; // But A's call operator would want A's here.
// }
//
// Walk the call operator’s redecl chain to find the one that belongs
// to this module.
//
// TODO: We need to fix this properly (see
// https://github.com/llvm/llvm-project/issues/90154).
Module *M = RD.getOwningModule();
for (Decl *D : Calls.front()->redecls()) {
auto *MD = cast<NamedDecl>(D);
if (MD->getOwningModule() == M)
return MD;
}

llvm_unreachable("Couldn't find our call operator!");
}

FunctionTemplateDecl* CXXRecordDecl::getDependentLambdaCallOperator() const {
Expand Down Expand Up @@ -1994,19 +2023,27 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
auto From = TD->getInstantiatedFrom();
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
if (NewCTD->isMemberSpecialization())
while (true) {
CTD = CTD->getMostRecentDecl();
if (CTD->isMemberSpecialization())
break;
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
CTD = NewCTD;
else
break;
CTD = NewCTD;
}
return GetDefinitionOrSelf(CTD->getTemplatedDecl());
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
if (NewCTPSD->isMemberSpecialization())
while (true) {
CTPSD = CTPSD->getMostRecentDecl();
if (CTPSD->isMemberSpecialization())
break;
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
CTPSD = NewCTPSD;
else
break;
CTPSD = NewCTPSD;
}
return GetDefinitionOrSelf(CTPSD);
}
Expand Down
30 changes: 14 additions & 16 deletions clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,35 +309,35 @@ bool TemplateDecl::isTypeAlias() const {
void RedeclarableTemplateDecl::anchor() {}

RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
if (Common)
return Common;
if (CommonBase *C = getCommonPtrInternal())
return C;

// Walk the previous-declaration chain until we either find a declaration
// with a common pointer or we run out of previous declarations.
SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
Prev = Prev->getPreviousDecl()) {
if (Prev->Common) {
Common = Prev->Common;
if (CommonBase *C = Prev->getCommonPtrInternal()) {
setCommonPtr(C);
break;
}

PrevDecls.push_back(Prev);
}

// If we never found a common pointer, allocate one now.
if (!Common) {
if (!getCommonPtrInternal()) {
// FIXME: If any of the declarations is from an AST file, we probably
// need an update record to add the common data.

Common = newCommon(getASTContext());
setCommonPtr(newCommon(getASTContext()));
}

// Update any previous declarations we saw with the common pointer.
for (const RedeclarableTemplateDecl *Prev : PrevDecls)
Prev->Common = Common;
Prev->setCommonPtr(getCommonPtrInternal());

return Common;
return getCommonPtrInternal();
}

void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
Expand Down Expand Up @@ -463,19 +463,17 @@ void FunctionTemplateDecl::addSpecialization(
}

void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
using Base = RedeclarableTemplateDecl;

// If we haven't created a common pointer yet, then it can just be created
// with the usual method.
if (!Base::Common)
if (!getCommonPtrInternal())
return;

Common *ThisCommon = static_cast<Common *>(Base::Common);
Common *ThisCommon = static_cast<Common *>(getCommonPtrInternal());
Common *PrevCommon = nullptr;
SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
for (; Prev; Prev = Prev->getPreviousDecl()) {
if (Prev->Base::Common) {
PrevCommon = static_cast<Common *>(Prev->Base::Common);
if (CommonBase *C = Prev->getCommonPtrInternal()) {
PrevCommon = static_cast<Common *>(C);
break;
}
PreviousDecls.push_back(Prev);
Expand All @@ -485,15 +483,15 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
// use this common pointer.
if (!PrevCommon) {
for (auto *D : PreviousDecls)
D->Base::Common = ThisCommon;
D->setCommonPtr(ThisCommon);
return;
}

// Ensure we don't leak any important state.
assert(ThisCommon->Specializations.size() == 0 &&
"Can't merge incompatible declarations!");

Base::Common = PrevCommon;
setCommonPtr(PrevCommon);
}

//===----------------------------------------------------------------------===//
Expand Down
19 changes: 18 additions & 1 deletion clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1164,8 +1164,25 @@ void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, const DeclContext *DC,
// ::= St <unqualified-name> # ::std::

assert(!isa<LinkageSpecDecl>(DC) && "unskipped LinkageSpecDecl");
if (isStdNamespace(DC))
if (isStdNamespace(DC)) {
if (getASTContext().getTargetInfo().getTriple().isOSSolaris()) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) {
// Issue #33114: Need non-standard mangling of std::tm etc. for
// Solaris ABI compatibility.
//
// <substitution> ::= tm # ::std::tm, same for the others
if (const IdentifierInfo *II = RD->getIdentifier()) {
StringRef type = II->getName();
if (llvm::is_contained({"div_t", "ldiv_t", "lconv", "tm"}, type)) {
Out << type.size() << type;
return;
}
}
}
}
Out << "St";
}

mangleUnqualifiedName(GD, DC, AdditionalAbiTags);
}
Expand Down
27 changes: 27 additions & 0 deletions clang/lib/AST/OpenMPClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,25 @@ OMPSizesClause *OMPSizesClause::CreateEmpty(const ASTContext &C,
return new (Mem) OMPSizesClause(NumSizes);
}

OMPPermutationClause *OMPPermutationClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc,
ArrayRef<Expr *> Args) {
OMPPermutationClause *Clause = CreateEmpty(C, Args.size());
Clause->setLocStart(StartLoc);
Clause->setLParenLoc(LParenLoc);
Clause->setLocEnd(EndLoc);
Clause->setArgRefs(Args);
return Clause;
}

OMPPermutationClause *OMPPermutationClause::CreateEmpty(const ASTContext &C,
unsigned NumLoops) {
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumLoops));
return new (Mem) OMPPermutationClause(NumLoops);
}

OMPFullClause *OMPFullClause::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc) {
Expand Down Expand Up @@ -1841,6 +1860,14 @@ void OMPClausePrinter::VisitOMPSizesClause(OMPSizesClause *Node) {
OS << ")";
}

void OMPClausePrinter::VisitOMPPermutationClause(OMPPermutationClause *Node) {
OS << "permutation(";
llvm::interleaveComma(Node->getArgsRefs(), OS, [&](const Expr *E) {
E->printPretty(OS, nullptr, Policy, 0);
});
OS << ")";
}

void OMPClausePrinter::VisitOMPFullClause(OMPFullClause *Node) { OS << "full"; }

void OMPClausePrinter::VisitOMPPartialClause(OMPPartialClause *Node) {
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/StmtProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,13 @@ void OMPClauseProfiler::VisitOMPSizesClause(const OMPSizesClause *C) {
Profiler->VisitExpr(E);
}

void OMPClauseProfiler::VisitOMPPermutationClause(
const OMPPermutationClause *C) {
for (Expr *E : C->getArgsRefs())
if (E)
Profiler->VisitExpr(E);
}

void OMPClauseProfiler::VisitOMPFullClause(const OMPFullClause *C) {}

void OMPClauseProfiler::VisitOMPPartialClause(const OMPPartialClause *C) {
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/OpenMPKinds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_sizes:
case OMPC_permutation:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
Expand Down Expand Up @@ -512,6 +513,7 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
case OMPC_safelen:
case OMPC_simdlen:
case OMPC_sizes:
case OMPC_permutation:
case OMPC_allocator:
case OMPC_allocate:
case OMPC_collapse:
Expand Down
12 changes: 5 additions & 7 deletions clang/lib/Basic/TargetID.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,9 @@ parseTargetIDWithFormatCheckingOnly(llvm::StringRef TargetID,
if (Sign != '+' && Sign != '-')
return std::nullopt;
bool IsOn = Sign == '+';
auto Loc = FeatureMap->find(Feature);
// Each feature can only show up at most once in target ID.
if (Loc != FeatureMap->end())
if (!FeatureMap->try_emplace(Feature, IsOn).second)
return std::nullopt;
(*FeatureMap)[Feature] = IsOn;
Features = Splits.second;
}
return Processor;
Expand Down Expand Up @@ -147,15 +145,15 @@ getConflictTargetIDCombination(const std::set<llvm::StringRef> &TargetIDs) {
struct Info {
llvm::StringRef TargetID;
llvm::StringMap<bool> Features;
Info(llvm::StringRef TargetID, const llvm::StringMap<bool> &Features)
: TargetID(TargetID), Features(Features) {}
};
llvm::StringMap<Info> FeatureMap;
for (auto &&ID : TargetIDs) {
llvm::StringMap<bool> Features;
llvm::StringRef Proc = *parseTargetIDWithFormatCheckingOnly(ID, &Features);
auto Loc = FeatureMap.find(Proc);
if (Loc == FeatureMap.end())
FeatureMap[Proc] = Info{ID, Features};
else {
auto [Loc, Inserted] = FeatureMap.try_emplace(Proc, ID, Features);
if (!Inserted) {
auto &ExistingFeatures = Loc->second.Features;
if (llvm::any_of(Features, [&](auto &F) {
return ExistingFeatures.count(F.first()) == 0;
Expand Down
62 changes: 62 additions & 0 deletions clang/lib/CIR/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
InheritParentConfig: true
Checks: >
-misc-const-correctness,
-llvm-header-guard,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-suspicious-semicolon,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-unused-raii,
bugprone-unused-return-value,
misc-redundant-expression,
misc-static-assert,
misc-unused-using-decls,
modernize-use-bool-literals,
modernize-loop-convert,
modernize-make-unique,
modernize-raw-string-literal,
modernize-use-equals-default,
modernize-use-default-member-init,
modernize-use-emplace,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-no-automatic-move,
performance-trivially-destructible,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-identifier-naming,
readability-inconsistent-declaration-parameter-name,
readability-misleading-indentation,
readability-redundant-control-flow,
readability-redundant-smartptr-get,
readability-simplify-boolean-expr,
readability-simplify-subscript-expr,
readability-use-anyofallof
CheckOptions:
- key: readability-identifier-naming.MemberCase
value: camelBack
- key: readability-identifier-naming.ParameterCase
value: camelBack
- key: readability-identifier-naming.VariableCase
value: camelBack
2 changes: 2 additions & 0 deletions clang/lib/CIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ include_directories(${LLVM_MAIN_SRC_DIR}/../mlir/include)
include_directories(${CMAKE_BINARY_DIR}/tools/mlir/include)

add_subdirectory(Dialect)
add_subdirectory(CodeGen)
add_subdirectory(FrontendAction)
32 changes: 32 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//===- CIRGenModule.cpp - Per-Module state for CIR generation -------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This is the internal per-translation-unit state used for CIR translation.
//
//===----------------------------------------------------------------------===//

#include "CIRGenModule.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/MLIRContext.h"

using namespace cir;
CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
clang::ASTContext &astctx,
const clang::CodeGenOptions &cgo,
DiagnosticsEngine &diags)
: astCtx(astctx), langOpts(astctx.getLangOpts()),
theModule{mlir::ModuleOp::create(mlir::UnknownLoc())},
target(astCtx.getTargetInfo()) {}

// Emit code for a single top level declaration.
void CIRGenModule::buildTopLevelDecl(Decl *decl) {}
62 changes: 62 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//===--- CIRGenModule.h - Per-Module state for CIR gen ----------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This is the internal per-translation-unit state used for CIR translation.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H

#include "CIRGenTypeCache.h"

#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"

namespace clang {
class ASTContext;
class CodeGenOptions;
class Decl;
class DiagnosticsEngine;
class LangOptions;
class TargetInfo;
} // namespace clang

using namespace clang;
namespace cir {

/// This class organizes the cross-function state that is used while generating
/// CIR code.
class CIRGenModule : public CIRGenTypeCache {
CIRGenModule(CIRGenModule &) = delete;
CIRGenModule &operator=(CIRGenModule &) = delete;

public:
CIRGenModule(mlir::MLIRContext &context, clang::ASTContext &astctx,
const clang::CodeGenOptions &cgo,
clang::DiagnosticsEngine &diags);

~CIRGenModule() = default;

private:
/// Hold Clang AST information.
clang::ASTContext &astCtx;

const clang::LangOptions &langOpts;

/// A "module" matches a c/cpp source file: containing a list of functions.
mlir::ModuleOp theModule;

const clang::TargetInfo &target;

public:
void buildTopLevelDecl(clang::Decl *decl);
};
} // namespace cir

#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H
27 changes: 27 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenTypeCache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===--- CIRGenTypeCache.h - Commonly used LLVM types and info -*- C++ --*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This structure provides a set of common types useful during CIR emission.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H
#define LLVM_CLANG_LIB_CIR_CIRGENTYPECACHE_H

namespace cir {

/// This structure provides a set of types that are commonly used
/// during IR emission. It's initialized once in CodeGenModule's
/// constructor and then copied around into new CIRGenFunction's.
struct CIRGenTypeCache {
CIRGenTypeCache() = default;
};

} // namespace cir

#endif // LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENTYPECACHE_H
43 changes: 43 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//===--- CIRGenerator.cpp - Emit CIR from ASTs ----------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This builds an AST and converts it to CIR.
//
//===----------------------------------------------------------------------===//

#include "CIRGenModule.h"

#include "clang/AST/DeclGroup.h"
#include "clang/CIR/CIRGenerator.h"

using namespace cir;
using namespace clang;

void CIRGenerator::anchor() {}

CIRGenerator::CIRGenerator(clang::DiagnosticsEngine &diags,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs,
const CodeGenOptions &cgo)
: diags(diags), fs(std::move(vfs)), codeGenOpts{cgo} {}
CIRGenerator::~CIRGenerator() = default;

void CIRGenerator::Initialize(ASTContext &astCtx) {
using namespace llvm;

this->astCtx = &astCtx;

cgm = std::make_unique<CIRGenModule>(*mlirCtx, astCtx, codeGenOpts, diags);
}

bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {

for (Decl *decl : group)
cgm->buildTopLevelDecl(decl);

return true;
}
23 changes: 23 additions & 0 deletions clang/lib/CIR/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
set(
LLVM_LINK_COMPONENTS
Core
Support
)

get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)

add_clang_library(clangCIR
CIRGenerator.cpp
CIRGenModule.cpp

DEPENDS
MLIRCIR
${dialect_libs}

LINK_LIBS
clangAST
clangBasic
clangLex
${dialect_libs}
MLIRCIR
)
72 changes: 72 additions & 0 deletions clang/lib/CIR/FrontendAction/CIRGenAction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//===--- CIRGenAction.cpp - LLVM Code generation Frontend Action ---------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "clang/CIR/FrontendAction/CIRGenAction.h"
#include "clang/CIR/CIRGenerator.h"
#include "clang/Frontend/CompilerInstance.h"

#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/OwningOpRef.h"

using namespace cir;
using namespace clang;

namespace cir {

class CIRGenConsumer : public clang::ASTConsumer {

virtual void anchor();

std::unique_ptr<raw_pwrite_stream> OutputStream;

IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS;
std::unique_ptr<CIRGenerator> Gen;

public:
CIRGenConsumer(CIRGenAction::OutputType Action,
DiagnosticsEngine &DiagnosticsEngine,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
const HeaderSearchOptions &HeaderSearchOptions,
const CodeGenOptions &CodeGenOptions,
const TargetOptions &TargetOptions,
const LangOptions &LangOptions,
const FrontendOptions &FEOptions,
std::unique_ptr<raw_pwrite_stream> OS)
: OutputStream(std::move(OS)), FS(VFS),
Gen(std::make_unique<CIRGenerator>(DiagnosticsEngine, std::move(VFS),
CodeGenOptions)) {}

bool HandleTopLevelDecl(DeclGroupRef D) override {
Gen->HandleTopLevelDecl(D);
return true;
}
};
} // namespace cir

void CIRGenConsumer::anchor() {}

CIRGenAction::CIRGenAction(OutputType Act, mlir::MLIRContext *MLIRCtx)
: MLIRCtx(MLIRCtx ? MLIRCtx : new mlir::MLIRContext), Action(Act) {}

CIRGenAction::~CIRGenAction() { MLIRMod.release(); }

std::unique_ptr<ASTConsumer>
CIRGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
std::unique_ptr<llvm::raw_pwrite_stream> Out = CI.takeOutputStream();

auto Result = std::make_unique<cir::CIRGenConsumer>(
Action, CI.getDiagnostics(), &CI.getVirtualFileSystem(),
CI.getHeaderSearchOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
CI.getLangOpts(), CI.getFrontendOpts(), std::move(Out));

return Result;
}

void EmitCIRAction::anchor() {}
EmitCIRAction::EmitCIRAction(mlir::MLIRContext *MLIRCtx)
: CIRGenAction(OutputType::EmitCIR, MLIRCtx) {}
17 changes: 17 additions & 0 deletions clang/lib/CIR/FrontendAction/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
set(LLVM_LINK_COMPONENTS
Core
Support
)

get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)

add_clang_library(clangCIRFrontendAction
CIRGenAction.cpp

LINK_LIBS
clangAST
clangFrontend
clangCIR
MLIRCIR
MLIRIR
)
9 changes: 9 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18892,6 +18892,15 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
retType, CGM.getHLSLRuntime().getSignIntrinsic(),
ArrayRef<Value *>{Op0}, nullptr, "hlsl.sign");
}
case Builtin::BI__builtin_hlsl_elementwise_radians: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
"radians operand must have a float representation");
return Builder.CreateIntrinsic(
/*ReturnType=*/Op0->getType(),
CGM.getHLSLRuntime().getRadiansIntrinsic(), ArrayRef<Value *>{Op0},
nullptr, "hlsl.radians");
}
}
return nullptr;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,7 @@ class StructAccessBase
}
const Expr *VisitCastExpr(const CastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue)
return E;
return IsExpectedRecordDecl(E) ? E : nullptr;
return Visit(E->getSubExpr());
}
const Expr *VisitParenExpr(const ParenExpr *E) {
Expand Down Expand Up @@ -2366,7 +2366,7 @@ Address CodeGenFunction::EmitExtVectorElementLValue(LValue LV) {
return VectorBasePtrPlusIx;
}

/// Load of global gamed gegisters are always calls to intrinsics.
/// Load of global named registers are always calls to intrinsics.
RValue CodeGenFunction::EmitLoadOfGlobalRegLValue(LValue LV) {
assert((LV.getType()->isIntegerType() || LV.getType()->isPointerType()) &&
"Bad type for register variable");
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 @@ -83,6 +83,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(Saturate, saturate)
GENERATE_HLSL_INTRINSIC_FUNCTION(Sign, sign)
GENERATE_HLSL_INTRINSIC_FUNCTION(Step, step)
GENERATE_HLSL_INTRINSIC_FUNCTION(Radians, radians)
GENERATE_HLSL_INTRINSIC_FUNCTION(ThreadId, thread_id)
GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4287,8 +4287,13 @@ void CodeGenModule::emitMultiVersionFunctions() {
} else if (const auto *TVA = CurFD->getAttr<TargetVersionAttr>()) {
if (TVA->isDefaultVersion() && IsDefined)
ShouldEmitResolver = true;
TVA->getFeatures(Feats);
llvm::Function *Func = createFunction(CurFD);
if (getTarget().getTriple().isRISCV()) {
Feats.push_back(TVA->getName());
} else {
assert(getTarget().getTriple().isAArch64());
TVA->getFeatures(Feats);
}
Options.emplace_back(Func, /*Architecture*/ "", Feats);
} else if (const auto *TC = CurFD->getAttr<TargetClonesAttr>()) {
if (IsDefined)
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/CodeGen/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,6 @@ void AMDGPUTargetCodeGenInfo::setTargetAttributes(
if (FD)
setFunctionDeclAttributes(FD, F, M);

if (M.getContext().getTargetInfo().allowAMDGPUUnsafeFPAtomics())
F->addFnAttr("amdgpu-unsafe-fp-atomics", "true");

if (!getABIInfo().getCodeGenOpts().EmitIEEENaNCompliantInsts)
F->addFnAttr("amdgpu-ieee", "false");
}
Expand Down
19 changes: 10 additions & 9 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -984,8 +984,9 @@ void Driver::CreateOffloadingDeviceToolChains(Compilation &C,
} else
TC = &getToolChain(C.getInputArgs(), TT);
C.addOffloadDeviceToolChain(TC, Action::OFK_OpenMP);
if (DerivedArchs.contains(TT.getTriple()))
KnownArchs[TC] = DerivedArchs[TT.getTriple()];
auto It = DerivedArchs.find(TT.getTriple());
if (It != DerivedArchs.end())
KnownArchs[TC] = It->second;
}
}
} else if (C.getInputArgs().hasArg(options::OPT_fopenmp_targets_EQ)) {
Expand Down Expand Up @@ -2321,7 +2322,7 @@ bool Driver::HandleImmediateArgs(Compilation &C) {

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

/// Generate an action that adds device dependences (if any) to a host action.
Expand Down Expand Up @@ -5581,8 +5581,9 @@ InputInfoList Driver::BuildJobsForActionNoCache(
std::pair<const Action *, std::string> ActionTC = {
OA->getHostDependence(),
GetTriplePlusArchString(TC, BoundArch, TargetDeviceOffloadKind)};
if (CachedResults.find(ActionTC) != CachedResults.end()) {
InputInfoList Inputs = CachedResults[ActionTC];
auto It = CachedResults.find(ActionTC);
if (It != CachedResults.end()) {
InputInfoList Inputs = It->second;
Inputs.append(OffloadDependencesInputInfo);
return Inputs;
}
Expand Down
36 changes: 17 additions & 19 deletions clang/lib/Driver/Multilib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ using namespace llvm::sys;

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

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

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

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

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

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

struct MultilibSerialization {
std::string Dir; // if this record successfully selects a library dir
std::string FatalError; // if this record reports a fatal error message
std::string Error; // if this record reports a fatal error message
std::vector<std::string> Flags;
std::string Group;
};
Expand Down Expand Up @@ -217,15 +215,15 @@ struct MultilibSetSerialization {
template <> struct llvm::yaml::MappingTraits<MultilibSerialization> {
static void mapping(llvm::yaml::IO &io, MultilibSerialization &V) {
io.mapOptional("Dir", V.Dir);
io.mapOptional("FatalError", V.FatalError);
io.mapOptional("Error", V.Error);
io.mapRequired("Flags", V.Flags);
io.mapOptional("Group", V.Group);
}
static std::string validate(IO &io, MultilibSerialization &V) {
if (V.Dir.empty() && V.FatalError.empty())
return "one of the 'Dir' and 'FatalError' keys must be specified";
if (!V.Dir.empty() && !V.FatalError.empty())
return "the 'Dir' and 'FatalError' keys may not both be specified";
if (V.Dir.empty() && V.Error.empty())
return "one of the 'Dir' and 'Error' keys must be specified";
if (!V.Dir.empty() && !V.Error.empty())
return "the 'Dir' and 'Error' keys may not both be specified";
if (StringRef(V.Dir).starts_with("/"))
return "paths must be relative but \"" + V.Dir + "\" starts with \"/\"";
return std::string{};
Expand Down Expand Up @@ -311,8 +309,8 @@ MultilibSet::parseYaml(llvm::MemoryBufferRef Input,
multilib_list Multilibs;
Multilibs.reserve(MS.Multilibs.size());
for (const auto &M : MS.Multilibs) {
if (!M.FatalError.empty()) {
Multilibs.emplace_back("", "", "", M.Flags, M.Group, M.FatalError);
if (!M.Error.empty()) {
Multilibs.emplace_back("", "", "", M.Flags, M.Group, M.Error);
} else {
std::string Dir;
if (M.Dir != ".")
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/Driver/MultilibBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,11 @@ bool MultilibBuilder::isValid() const {
llvm::StringMap<int> FlagSet;
for (unsigned I = 0, N = Flags.size(); I != N; ++I) {
StringRef Flag(Flags[I]);
llvm::StringMap<int>::iterator SI = FlagSet.find(Flag.substr(1));
auto [SI, Inserted] = FlagSet.try_emplace(Flag.substr(1), I);

assert(StringRef(Flag).front() == '-' || StringRef(Flag).front() == '!');

if (SI == FlagSet.end())
FlagSet[Flag.substr(1)] = I;
else if (Flags[I] != Flags[SI->getValue()])
if (!Inserted && Flags[I] != Flags[SI->getValue()])
return false;
}
return true;
Expand Down
87 changes: 58 additions & 29 deletions clang/lib/Driver/ToolChains/BareMetal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,23 @@ static bool findRISCVMultilibs(const Driver &D,
return false;
}

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

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

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

return std::string(SysRootDir);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

std::string SysRoot;
};

} // namespace toolchains
Expand Down
12 changes: 4 additions & 8 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5139,6 +5139,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
}
}

if (Args.hasArg(options::OPT_fclangir))
CmdArgs.push_back("-fclangir");

if (IsOpenMPDevice) {
// We have to pass the triple of the host if compiling for an OpenMP device.
std::string NormalizedTriple =
Expand Down Expand Up @@ -9107,13 +9110,6 @@ void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA,
llvm::copy_if(Features, std::back_inserter(FeatureArgs),
[](StringRef Arg) { return !Arg.starts_with("-target"); });

if (TC->getTriple().isAMDGPU()) {
for (StringRef Feature : llvm::split(Arch.split(':').second, ':')) {
FeatureArgs.emplace_back(
Args.MakeArgString(Feature.take_back() + Feature.drop_back()));
}
}

// TODO: We need to pass in the full target-id and handle it properly in the
// linker wrapper.
SmallVector<std::string> Parts{
Expand All @@ -9123,7 +9119,7 @@ void OffloadPackager::ConstructJob(Compilation &C, const JobAction &JA,
"kind=" + Kind.str(),
};

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

Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Driver/ToolChains/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,10 @@ void CudaToolChain::addClangTargetOptions(
if (CudaInstallation.version() >= CudaVersion::CUDA_90)
CC1Args.push_back("-fcuda-allow-variadic-functions");

if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr,
options::OPT_fno_cuda_short_ptr, false))
CC1Args.append({"-mllvm", "--nvptx-short-ptr"});

if (DriverArgs.hasArg(options::OPT_nogpulib))
return;

Expand All @@ -873,10 +877,6 @@ void CudaToolChain::addClangTargetOptions(

clang::CudaVersion CudaInstallationVersion = CudaInstallation.version();

if (DriverArgs.hasFlag(options::OPT_fcuda_short_ptr,
options::OPT_fno_cuda_short_ptr, false))
CC1Args.append({"-mllvm", "--nvptx-short-ptr"});

if (CudaInstallationVersion >= CudaVersion::UNKNOWN)
CC1Args.push_back(
DriverArgs.MakeArgString(Twine("-target-sdk-version=") +
Expand Down
25 changes: 10 additions & 15 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,50 +44,49 @@ struct ScalarEnumerationTraits<FormatStyle::BreakBeforeNoexceptSpecifierStyle> {

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

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

static void mapping(IO &IO, FormatStyle::AlignConsecutiveStyle &Value) {
IO.mapOptional("Enabled", Value.Enabled);
IO.mapOptional("AcrossEmptyLines", Value.AcrossEmptyLines);
IO.mapOptional("AcrossComments", Value.AcrossComments);
IO.mapOptional("AlignCompound", Value.AlignCompound);
IO.mapOptional("AlignFunctionDeclarations",
Value.AlignFunctionDeclarations);
IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);
IO.mapOptional("PadOperators", Value.PadOperators);
}
Expand Down Expand Up @@ -1441,14 +1440,10 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
LLVMStyle.AlignConsecutiveAssignments = {};
LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false;
LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
LLVMStyle.AlignConsecutiveBitFields = {};
LLVMStyle.AlignConsecutiveDeclarations = {};
LLVMStyle.AlignConsecutiveDeclarations.AlignFunctionDeclarations = true;
LLVMStyle.AlignConsecutiveMacros = {};
LLVMStyle.AlignConsecutiveShortCaseStatements = {};
LLVMStyle.AlignConsecutiveTableGenBreakingDAGArgColons = {};
Expand Down
37 changes: 25 additions & 12 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3738,6 +3738,13 @@ static bool isFunctionDeclarationName(const LangOptions &LangOpts,

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

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

if (!Prev)
return false;

const auto &Previous = *Prev;

if (const auto *PrevPrev = Previous.getPreviousNonComment();
Expand Down Expand Up @@ -4903,6 +4910,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.is(tok::star) && Right.is(tok::comment))
return true;

const auto *BeforeLeft = Left.Previous;

if (IsCpp) {
if (Left.is(TT_OverloadedOperator) &&
Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) {
Expand Down Expand Up @@ -4955,7 +4964,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.Tok.getIdentifierInfo() && Right.Tok.isLiteral())
return true;
} else if (Style.isProto()) {
if (Right.is(tok::period) &&
if (Right.is(tok::period) && !(BeforeLeft && BeforeLeft->is(tok::period)) &&
Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
Keywords.kw_repeated, Keywords.kw_extend)) {
return true;
Expand Down Expand Up @@ -5063,8 +5072,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.is(TT_FatArrow))
return true;
// for await ( ...
if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&
Left.Previous->is(tok::kw_for)) {
if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && BeforeLeft &&
BeforeLeft->is(tok::kw_for)) {
return true;
}
if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&
Expand Down Expand Up @@ -5101,7 +5110,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
// Valid JS method names can include keywords, e.g. `foo.delete()` or
// `bar.instanceof()`. Recognize call positions by preceding period.
if (Left.Previous && Left.Previous->is(tok::period) &&
if (BeforeLeft && BeforeLeft->is(tok::period) &&
Left.Tok.getIdentifierInfo()) {
return false;
}
Expand All @@ -5119,22 +5128,22 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// "of" is only a keyword if it appears after another identifier
// (e.g. as "const x of y" in a for loop), or after a destructuring
// operation (const [x, y] of z, const {a, b} of c).
(Left.is(Keywords.kw_of) && Left.Previous &&
(Left.Previous->is(tok::identifier) ||
Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&
(!Left.Previous || Left.Previous->isNot(tok::period))) {
(Left.is(Keywords.kw_of) && BeforeLeft &&
(BeforeLeft->is(tok::identifier) ||
BeforeLeft->isOneOf(tok::r_square, tok::r_brace)))) &&
(!BeforeLeft || BeforeLeft->isNot(tok::period))) {
return true;
}
if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
Left.Previous->is(tok::period) && Right.is(tok::l_paren)) {
if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && BeforeLeft &&
BeforeLeft->is(tok::period) && Right.is(tok::l_paren)) {
return false;
}
if (Left.is(Keywords.kw_as) &&
Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren)) {
return true;
}
if (Left.is(tok::kw_default) && Left.Previous &&
Left.Previous->is(tok::kw_export)) {
if (Left.is(tok::kw_default) && BeforeLeft &&
BeforeLeft->is(tok::kw_export)) {
return true;
}
if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))
Expand Down Expand Up @@ -5445,6 +5454,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
}
if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
return ShouldAddSpacesInAngles();
if (Left.is(tok::r_paren) && Right.is(TT_PointerOrReference) &&
Right.isOneOf(tok::amp, tok::ampamp)) {
return true;
}
// Space before TT_StructuredBindingLSquare.
if (Right.is(TT_StructuredBindingLSquare)) {
return !Left.isOneOf(tok::amp, tok::ampamp) ||
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2131,6 +2131,11 @@ void UnwrappedLineParser::parseStructuralElement(
return;
}
break;
case tok::greater:
nextToken();
if (FormatTok->is(tok::l_brace))
FormatTok->Previous->setFinalizedType(TT_TemplateCloser);
break;
default:
nextToken();
break;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/WhitespaceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@ void WhitespaceManager::alignConsecutiveDeclarations() {
return true;
}
if (C.Tok->is(TT_FunctionDeclarationName))
return true;
return Style.AlignConsecutiveDeclarations.AlignFunctionDeclarations;
if (C.Tok->isNot(TT_StartOfName))
return false;
if (C.Tok->Previous &&
Expand Down
Loading