96 changes: 89 additions & 7 deletions clang/include/clang/Sema/SemaOpenACC.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,20 @@ class SemaOpenACC : public SemaBase {
/// haven't had their 'parent' compute construct set yet. Entires will only be
/// made to this list in the case where we know the loop isn't an orphan.
llvm::SmallVector<OpenACCLoopConstruct *> ParentlessLoopConstructs;
/// Whether we are inside of a compute construct, and should add loops to the
/// above collection.
bool InsideComputeConstruct = false;

struct ComputeConstructInfo {
/// Which type of compute construct we are inside of, which we can use to
/// determine whether we should add loops to the above collection. We can
/// also use it to diagnose loop construct clauses.
OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
// If we have an active compute construct, stores the list of clauses we've
// prepared for it, so that we can diagnose limitations on child constructs.
ArrayRef<OpenACCClause *> Clauses;
} ActiveComputeConstructInfo;

bool isInComputeConstruct() const {
return ActiveComputeConstructInfo.Kind != OpenACCDirectiveKind::Invalid;
}

/// Certain clauses care about the same things that aren't specific to the
/// individual clause, but can be shared by a few, so store them here. All
Expand Down Expand Up @@ -99,6 +110,20 @@ class SemaOpenACC : public SemaBase {
} TileInfo;

public:
ComputeConstructInfo &getActiveComputeConstructInfo() {
return ActiveComputeConstructInfo;
}

/// If there is a current 'active' loop construct with a 'gang' clause on a
/// 'kernel' construct, this will have the source location for it. This
/// permits us to implement the restriction of no further 'gang' clauses.
SourceLocation LoopGangClauseOnKernelLoc;
/// If there is a current 'active' loop construct with a 'worker' clause on it
/// (on any sort of construct), this has the source location for it. This
/// permits us to implement the restriction of no further 'gang' or 'worker'
/// clauses.
SourceLocation LoopWorkerClauseLoc;

// Redeclaration of the version in OpenACCClause.h.
using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;

Expand Down Expand Up @@ -149,9 +174,14 @@ class SemaOpenACC : public SemaBase {
Expr *LoopCount;
};

struct GangDetails {
SmallVector<OpenACCGangKind> GangKinds;
SmallVector<Expr *> IntExprs;
};

std::variant<std::monostate, DefaultDetails, ConditionDetails,
IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails,
ReductionDetails, CollapseDetails>
ReductionDetails, CollapseDetails, GangDetails>
Details = std::monostate{};

public:
Expand Down Expand Up @@ -199,11 +229,15 @@ class SemaOpenACC : public SemaBase {
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::Tile ||
ClauseKind == OpenACCClauseKind::Worker ||
ClauseKind == OpenACCClauseKind::Vector ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");

// 'async' and 'wait' have an optional IntExpr, so be tolerant of that.
if ((ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::Worker ||
ClauseKind == OpenACCClauseKind::Vector ||
ClauseKind == OpenACCClauseKind::Wait) &&
std::holds_alternative<std::monostate>(Details))
return 0;
Expand Down Expand Up @@ -245,9 +279,20 @@ class SemaOpenACC : public SemaBase {
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::Tile ||
ClauseKind == OpenACCClauseKind::Gang ||
ClauseKind == OpenACCClauseKind::Worker ||
ClauseKind == OpenACCClauseKind::Vector ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");

if (ClauseKind == OpenACCClauseKind::Gang) {
// There might not be any gang int exprs, as this is an optional
// argument.
if (std::holds_alternative<std::monostate>(Details))
return {};
return std::get<GangDetails>(Details).IntExprs;
}

return std::get<IntExprDetails>(Details).IntExprs;
}

Expand All @@ -259,6 +304,16 @@ class SemaOpenACC : public SemaBase {
return std::get<ReductionDetails>(Details).Op;
}

ArrayRef<OpenACCGangKind> getGangKinds() const {
assert(ClauseKind == OpenACCClauseKind::Gang &&
"Parsed clause kind does not have gang kind");
// The args on gang are optional, so this might not actually hold
// anything.
if (std::holds_alternative<std::monostate>(Details))
return {};
return std::get<GangDetails>(Details).GangKinds;
}

ArrayRef<Expr *> getVarList() {
assert((ClauseKind == OpenACCClauseKind::Private ||
ClauseKind == OpenACCClauseKind::NoCreate ||
Expand Down Expand Up @@ -357,6 +412,8 @@ class SemaOpenACC : public SemaBase {
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::Tile ||
ClauseKind == OpenACCClauseKind::Worker ||
ClauseKind == OpenACCClauseKind::Vector ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}};
Expand All @@ -366,11 +423,32 @@ class SemaOpenACC : public SemaBase {
ClauseKind == OpenACCClauseKind::NumWorkers ||
ClauseKind == OpenACCClauseKind::Async ||
ClauseKind == OpenACCClauseKind::Tile ||
ClauseKind == OpenACCClauseKind::Worker ||
ClauseKind == OpenACCClauseKind::Vector ||
ClauseKind == OpenACCClauseKind::VectorLength) &&
"Parsed clause kind does not have a int exprs");
Details = IntExprDetails{std::move(IntExprs)};
}

void setGangDetails(ArrayRef<OpenACCGangKind> GKs,
ArrayRef<Expr *> IntExprs) {
assert(ClauseKind == OpenACCClauseKind::Gang &&
"Parsed Clause kind does not have gang details");
assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");

Details = GangDetails{{GKs.begin(), GKs.end()},
{IntExprs.begin(), IntExprs.end()}};
}

void setGangDetails(llvm::SmallVector<OpenACCGangKind> &&GKs,
llvm::SmallVector<Expr *> &&IntExprs) {
assert(ClauseKind == OpenACCClauseKind::Gang &&
"Parsed Clause kind does not have gang details");
assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");

Details = GangDetails{std::move(GKs), std::move(IntExprs)};
}

void setVarListDetails(ArrayRef<Expr *> VarList, bool IsReadOnly,
bool IsZero) {
assert((ClauseKind == OpenACCClauseKind::Private ||
Expand Down Expand Up @@ -545,10 +623,12 @@ class SemaOpenACC : public SemaBase {
SourceLocation RBLoc);
/// Checks the loop depth value for a collapse clause.
ExprResult CheckCollapseLoopCount(Expr *LoopCount);
/// Checks a single size expr for a tile clause. 'gang' could possibly call
/// this, but has slightly stricter rules as to valid values.
/// Checks a single size expr for a tile clause.
ExprResult CheckTileSizeExpr(Expr *SizeExpr);

// Check a single expression on a gang clause.
ExprResult CheckGangExpr(OpenACCGangKind GK, Expr *E);

ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);

Expand Down Expand Up @@ -595,8 +675,10 @@ class SemaOpenACC : public SemaBase {
/// Loop needing its parent construct.
class AssociatedStmtRAII {
SemaOpenACC &SemaRef;
bool WasInsideComputeConstruct;
ComputeConstructInfo OldActiveComputeConstructInfo;
OpenACCDirectiveKind DirKind;
SourceLocation OldLoopGangClauseOnKernelLoc;
SourceLocation OldLoopWorkerClauseLoc;
llvm::SmallVector<OpenACCLoopConstruct *> ParentlessLoopConstructs;
LoopInConstructRAII LoopRAII;

Expand Down
16 changes: 8 additions & 8 deletions clang/include/clang/Sema/Template.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,10 @@ enum class TemplateSubstitutionKind : char {
/// lookup will search our outer scope.
bool CombineWithOuterScope;

/// Whether this scope is being used to instantiate a lambda expression,
/// in which case it should be reused for instantiating the lambda's
/// FunctionProtoType.
bool InstantiatingLambda = false;
/// Whether this scope is being used to instantiate a lambda or block
/// expression, in which case it should be reused for instantiating the
/// lambda's FunctionProtoType.
bool InstantiatingLambdaOrBlock = false;

/// If non-NULL, the template parameter pack that has been
/// partially substituted per C++0x [temp.arg.explicit]p9.
Expand All @@ -431,10 +431,10 @@ enum class TemplateSubstitutionKind : char {

public:
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false,
bool InstantiatingLambda = false)
bool InstantiatingLambdaOrBlock = false)
: SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
CombineWithOuterScope(CombineWithOuterScope),
InstantiatingLambda(InstantiatingLambda) {
InstantiatingLambdaOrBlock(InstantiatingLambdaOrBlock) {
SemaRef.CurrentInstantiationScope = this;
}

Expand Down Expand Up @@ -561,8 +561,8 @@ enum class TemplateSubstitutionKind : char {
/// Determine whether D is a pack expansion created in this scope.
bool isLocalPackExpansion(const Decl *D);

/// Determine whether this scope is for instantiating a lambda.
bool isLambda() const { return InstantiatingLambda; }
/// Determine whether this scope is for instantiating a lambda or block.
bool isLambdaOrBlock() const { return InstantiatingLambdaOrBlock; }
};

class TemplateDeclInstantiator
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2527,7 +2527,7 @@ class BitsUnpacker {

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

} // namespace clang
Expand Down
63 changes: 63 additions & 0 deletions clang/include/clang/Support/Compiler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//===-- clang/Support/Compiler.h - Compiler abstraction support -*- 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 file defines explicit visibility macros used to export symbols from
// clang-cpp
//
//===----------------------------------------------------------------------===//

#ifndef CLANG_SUPPORT_COMPILER_H
#define CLANG_SUPPORT_COMPILER_H

#include "llvm/Support/Compiler.h"

/// CLANG_ABI is the main export/visibility macro to mark something as
/// explicitly exported when clang is built as a shared library with everything
/// else that is unannotated having hidden visibility.
///
/// CLANG_EXPORT_TEMPLATE is used on explicit template instantiations in source
/// files that were declared extern in a header. This macro is only set as a
/// compiler export attribute on windows, on other platforms it does nothing.
///
/// CLANG_TEMPLATE_ABI is for annotating extern template declarations in headers
/// for both functions and classes. On windows its turned in to dllimport for
/// library consumers, for other platforms its a default visibility attribute.
#ifndef CLANG_ABI_GENERATING_ANNOTATIONS
// Marker to add to classes or functions in public headers that should not have
// export macros added to them by the clang tool
#define CLANG_ABI_NOT_EXPORTED
// Some libraries like those for tablegen are linked in to tools that used
// in the build so can't depend on the llvm shared library. If export macros
// were left enabled when building these we would get duplicate or
// missing symbol linker errors on windows.
#if defined(CLANG_BUILD_STATIC)
#define CLANG_ABI
#define CLANG_TEMPLATE_ABI
#define CLANG_EXPORT_TEMPLATE
#elif defined(_WIN32) && !defined(__MINGW32__)
#if defined(CLANG_EXPORTS)
#define CLANG_ABI __declspec(dllexport)
#define CLANG_TEMPLATE_ABI
#define CLANG_EXPORT_TEMPLATE __declspec(dllexport)
#else
#define CLANG_ABI __declspec(dllimport)
#define CLANG_TEMPLATE_ABI __declspec(dllimport)
#define CLANG_EXPORT_TEMPLATE
#endif
#elif defined(__ELF__) || defined(__MINGW32__) || defined(_AIX)
#define CLANG_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
#define CLANG_TEMPLATE_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
#define CLANG_EXPORT_TEMPLATE
#elif defined(__MACH__) || defined(__WASM__)
#define CLANG_ABI LLVM_ATTRIBUTE_VISIBILITY_DEFAULT
#define CLANG_TEMPLATE_ABI
#define CLANG_EXPORT_TEMPLATE
#endif
#endif

#endif
35 changes: 24 additions & 11 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2728,7 +2728,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(

const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
if (std::optional<unsigned> LocalIndex =
allocateLocal(Inner, E->getExtendingDecl())) {
allocateLocal(E, Inner->getType(), E->getExtendingDecl())) {
InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
if (!this->emitGetPtrLocal(*LocalIndex, E))
return false;
Expand Down Expand Up @@ -2869,6 +2869,11 @@ bool Compiler<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
if (DiscardResult)
return true;

if (!Initializing) {
unsigned StringIndex = P.createGlobalString(E->getFunctionName(), E);
return this->emitGetPtrGlobal(StringIndex, E);
}

return this->delegate(E->getFunctionName());
}

Expand Down Expand Up @@ -3406,11 +3411,14 @@ bool Compiler<Emitter>::VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
if (!this->visit(Arg))
return false;

return this->emitFree(E->isArrayForm(), E);
return this->emitFree(E->isArrayForm(), E->isGlobalDelete(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitBlockExpr(const BlockExpr *E) {
if (DiscardResult)
return true;

const Function *Func = nullptr;
if (auto F = Compiler<ByteCodeEmitter>(Ctx, P).compileObjCBlock(E))
Func = F;
Expand Down Expand Up @@ -4029,15 +4037,15 @@ unsigned Compiler<Emitter>::allocateLocalPrimitive(DeclTy &&Src, PrimType Ty,

template <class Emitter>
std::optional<unsigned>
Compiler<Emitter>::allocateLocal(DeclTy &&Src, const ValueDecl *ExtendingDecl) {
Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,
const ValueDecl *ExtendingDecl) {
// Make sure we don't accidentally register the same decl twice.
if ([[maybe_unused]] const auto *VD =
dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
assert(!P.getGlobal(VD));
assert(!Locals.contains(VD));
}

QualType Ty;
const ValueDecl *Key = nullptr;
const Expr *Init = nullptr;
bool IsTemporary = false;
Expand All @@ -4050,7 +4058,8 @@ Compiler<Emitter>::allocateLocal(DeclTy &&Src, const ValueDecl *ExtendingDecl) {
}
if (auto *E = Src.dyn_cast<const Expr *>()) {
IsTemporary = true;
Ty = E->getType();
if (Ty.isNull())
Ty = E->getType();
}

Descriptor *D = P.createDescriptor(
Expand Down Expand Up @@ -6005,6 +6014,9 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {

return this->emitGetPtrParam(It->second.Offset, E);
}

if (D->getType()->isReferenceType())
return false; // FIXME: Do we need to emit InvalidDeclRef?
}

// In case we need to re-visit a declaration.
Expand Down Expand Up @@ -6041,9 +6053,7 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
const auto typeShouldBeVisited = [&](QualType T) -> bool {
if (T.isConstant(Ctx.getASTContext()))
return true;
if (const auto *RT = T->getAs<ReferenceType>())
return RT->getPointeeType().isConstQualified();
return false;
return T->isReferenceType();
};

// DecompositionDecls are just proxies for us.
Expand All @@ -6059,9 +6069,12 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
// other words, we're evaluating the initializer, just to know if we can
// evaluate the initializer.
if (VD->isLocalVarDecl() && typeShouldBeVisited(VD->getType()) &&
VD->getInit() && !VD->getInit()->isValueDependent() &&
VD->evaluateValue())
return revisit(VD);
VD->getInit() && !VD->getInit()->isValueDependent()) {

if (VD->evaluateValue())
return revisit(VD);
return this->emitInvalidDeclRef(cast<DeclRefExpr>(E), E);
}
}
} else {
if (const auto *VD = dyn_cast<VarDecl>(D);
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/ByteCode/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,

/// Allocates a space storing a local given its type.
std::optional<unsigned>
allocateLocal(DeclTy &&Decl, const ValueDecl *ExtendingDecl = nullptr);
allocateLocal(DeclTy &&Decl, QualType Ty = QualType(),
const ValueDecl *ExtendingDecl = nullptr);
unsigned allocateTemporary(const Expr *E);

private:
Expand Down
85 changes: 84 additions & 1 deletion clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -964,7 +964,7 @@ static bool runRecordDestructor(InterpState &S, CodePtr OpPC,
return true;
}

bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
static bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
assert(B);
const Descriptor *Desc = B->getDescriptor();

Expand All @@ -989,6 +989,89 @@ bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B) {
return runRecordDestructor(S, OpPC, Pointer(const_cast<Block *>(B)), Desc);
}

bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
bool IsGlobalDelete) {
if (!CheckDynamicMemoryAllocation(S, OpPC))
return false;

const Expr *Source = nullptr;
const Block *BlockToDelete = nullptr;
{
// Extra scope for this so the block doesn't have this pointer
// pointing to it when we destroy it.
Pointer Ptr = S.Stk.pop<Pointer>();

// Deleteing nullptr is always fine.
if (Ptr.isZero())
return true;

// Remove base casts.
while (Ptr.isBaseClass())
Ptr = Ptr.getBase();

if (!Ptr.isRoot() || Ptr.isOnePastEnd() || Ptr.isArrayElement()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
<< Ptr.toDiagnosticString(S.getASTContext()) << Ptr.isOnePastEnd();
return false;
}

Source = Ptr.getDeclDesc()->asExpr();
BlockToDelete = Ptr.block();

if (!CheckDeleteSource(S, OpPC, Source, Ptr))
return false;

// For a class type with a virtual destructor, the selected operator delete
// is the one looked up when building the destructor.
QualType AllocType = Ptr.getType();
if (!DeleteIsArrayForm && !IsGlobalDelete) {
auto getVirtualOperatorDelete = [](QualType T) -> const FunctionDecl * {
if (const CXXRecordDecl *RD = T->getAsCXXRecordDecl())
if (const CXXDestructorDecl *DD = RD->getDestructor())
return DD->isVirtual() ? DD->getOperatorDelete() : nullptr;
return nullptr;
};

AllocType->dump();
if (const FunctionDecl *VirtualDelete =
getVirtualOperatorDelete(AllocType);
VirtualDelete &&
!VirtualDelete->isReplaceableGlobalAllocationFunction()) {
S.FFDiag(S.Current->getSource(OpPC),
diag::note_constexpr_new_non_replaceable)
<< isa<CXXMethodDecl>(VirtualDelete) << VirtualDelete;
return false;
}
}
}
assert(Source);
assert(BlockToDelete);

// Invoke destructors before deallocating the memory.
if (!RunDestructors(S, OpPC, BlockToDelete))
return false;

DynamicAllocator &Allocator = S.getAllocator();
const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
std::optional<DynamicAllocator::Form> AllocForm =
Allocator.getAllocationForm(Source);

if (!Allocator.deallocate(Source, BlockToDelete, S)) {
// Nothing has been deallocated, this must be a double-delete.
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_double_delete);
return false;
}

assert(AllocForm);
DynamicAllocator::Form DeleteForm = DeleteIsArrayForm
? DynamicAllocator::Form::Array
: DynamicAllocator::Form::NonArray;
return CheckNewDeleteForms(S, OpPC, *AllocForm, DeleteForm, BlockDesc,
Source);
}

void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED,
const APSInt &Value) {
llvm::APInt Min;
Expand Down
57 changes: 2 additions & 55 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2976,61 +2976,8 @@ inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc,
return true;
}

bool RunDestructors(InterpState &S, CodePtr OpPC, const Block *B);
static inline bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm) {
if (!CheckDynamicMemoryAllocation(S, OpPC))
return false;

const Expr *Source = nullptr;
const Block *BlockToDelete = nullptr;
{
// Extra scope for this so the block doesn't have this pointer
// pointing to it when we destroy it.
const Pointer &Ptr = S.Stk.pop<Pointer>();

// Deleteing nullptr is always fine.
if (Ptr.isZero())
return true;

if (!Ptr.isRoot() || Ptr.isOnePastEnd() || Ptr.isArrayElement()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_delete_subobject)
<< Ptr.toDiagnosticString(S.getASTContext()) << Ptr.isOnePastEnd();
return false;
}

Source = Ptr.getDeclDesc()->asExpr();
BlockToDelete = Ptr.block();

if (!CheckDeleteSource(S, OpPC, Source, Ptr))
return false;
}
assert(Source);
assert(BlockToDelete);

// Invoke destructors before deallocating the memory.
if (!RunDestructors(S, OpPC, BlockToDelete))
return false;

DynamicAllocator &Allocator = S.getAllocator();
const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
std::optional<DynamicAllocator::Form> AllocForm =
Allocator.getAllocationForm(Source);

if (!Allocator.deallocate(Source, BlockToDelete, S)) {
// Nothing has been deallocated, this must be a double-delete.
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_double_delete);
return false;
}

assert(AllocForm);
DynamicAllocator::Form DeleteForm = DeleteIsArrayForm
? DynamicAllocator::Form::Array
: DynamicAllocator::Form::NonArray;
return CheckNewDeleteForms(S, OpPC, *AllocForm, DeleteForm, BlockDesc,
Source);
}
bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
bool IsGlobalDelete);

static inline bool IsConstantContext(InterpState &S, CodePtr OpPC) {
S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
Expand Down
76 changes: 75 additions & 1 deletion clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ 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);
Expand Down Expand Up @@ -1162,6 +1161,71 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
return false;
}

/// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])
static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);

// Might be called with function pointers in C.
std::optional<PrimType> PtrT = S.Ctx.classify(Call->getArg(0));
if (PtrT != PT_Ptr)
return false;

unsigned ArgSize = callArgSize(S, Call);
const Pointer &Ptr = S.Stk.peek<Pointer>(ArgSize);
std::optional<APSInt> ExtraOffset;
APSInt Alignment;
if (Call->getNumArgs() == 2) {
Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));
} else {
PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));
PrimType ExtraOffsetT = *S.Ctx.classify(Call->getArg(2));
Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)),
align(primSize(AlignmentT)) +
align(primSize(ExtraOffsetT)));
ExtraOffset = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)));
}

CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());

// If there is a base object, then it must have the correct alignment.
if (Ptr.isBlockPointer()) {
CharUnits BaseAlignment;
if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())
BaseAlignment = S.getASTContext().getDeclAlign(VD);
else if (const auto *E = Ptr.getDeclDesc()->asExpr())
BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);

if (BaseAlignment < Align) {
S.CCEDiag(Call->getArg(0),
diag::note_constexpr_baa_insufficient_alignment)
<< 0 << BaseAlignment.getQuantity() << Align.getQuantity();
return false;
}
}

APValue AV = Ptr.toAPValue(S.getASTContext());
CharUnits AVOffset = AV.getLValueOffset();
if (ExtraOffset)
AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());
if (AVOffset.alignTo(Align) != AVOffset) {
if (Ptr.isBlockPointer())
S.CCEDiag(Call->getArg(0),
diag::note_constexpr_baa_insufficient_alignment)
<< 1 << AVOffset.getQuantity() << Align.getQuantity();
else
S.CCEDiag(Call->getArg(0),
diag::note_constexpr_baa_value_insufficient_alignment)
<< AVOffset.getQuantity() << Align.getQuantity();
return false;
}

S.Stk.push<Pointer>(Ptr);
return true;
}

static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
Expand Down Expand Up @@ -1287,6 +1351,11 @@ static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||
!Call->getArg(1)->getType()->isIntegerType() ||
!Call->getArg(2)->getType()->isIntegerType())
return false;

unsigned BuiltinOp = Func->getBuiltinID();
APSInt CarryIn = getAPSIntParam(Frame, 0);
APSInt LHS = getAPSIntParam(Frame, 1);
Expand Down Expand Up @@ -1900,6 +1969,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;

case Builtin::BI__builtin_assume_aligned:
if (!interp__builtin_assume_aligned(S, OpPC, Frame, F, Call))
return false;
break;

case clang::X86::BI__builtin_ia32_bextr_u32:
case clang::X86::BI__builtin_ia32_bextr_u64:
case clang::X86::BI__builtin_ia32_bextri_u32:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ByteCode/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ def AllocCN : Opcode {
}

def Free : Opcode {
let Args = [ArgBool];
let Args = [ArgBool, ArgBool];
}

def CheckNewTypeMismatch : Opcode {
Expand Down
5 changes: 0 additions & 5 deletions clang/lib/AST/ByteCode/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,6 @@ APValue Pointer::toAPValue(const ASTContext &ASTCtx) const {
}
}

// FIXME(perf): We compute the lvalue path above, but we can't supply it
// for dummy pointers (that causes crashes later in CheckConstantExpression).
if (isDummy())
Path.clear();

// We assemble the LValuePath starting from the innermost pointer to the
// outermost one. SO in a.b.c, the first element in Path will refer to
// the field 'c', while later code expects it to refer to 'a'.
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/AST/ByteCode/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const void *Program::getNativePointer(unsigned Idx) {
return NativePointers[Idx];
}

unsigned Program::createGlobalString(const StringLiteral *S) {
unsigned Program::createGlobalString(const StringLiteral *S, const Expr *Base) {
const size_t CharWidth = S->getCharByteWidth();
const size_t BitWidth = CharWidth * Ctx.getCharBit();

Expand All @@ -52,12 +52,15 @@ unsigned Program::createGlobalString(const StringLiteral *S) {
llvm_unreachable("unsupported character width");
}

if (!Base)
Base = S;

// Create a descriptor for the string.
Descriptor *Desc =
allocateDescriptor(S, CharType, Descriptor::GlobalMD, S->getLength() + 1,
/*isConst=*/true,
/*isTemporary=*/false,
/*isMutable=*/false);
Descriptor *Desc = allocateDescriptor(Base, CharType, Descriptor::GlobalMD,
S->getLength() + 1,
/*isConst=*/true,
/*isTemporary=*/false,
/*isMutable=*/false);

// Allocate storage for the string.
// The byte length does not include the null terminator.
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/ByteCode/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class Program final {
const void *getNativePointer(unsigned Idx);

/// Emits a string literal among global data.
unsigned createGlobalString(const StringLiteral *S);
unsigned createGlobalString(const StringLiteral *S,
const Expr *Base = nullptr);

/// Returns a pointer to a global.
Pointer getPtrGlobal(unsigned Idx) const;
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/AST/ComputeDependence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,13 @@ ExprDependence clang::computeDependence(ExtVectorElementExpr *E) {
return E->getBase()->getDependence();
}

ExprDependence clang::computeDependence(BlockExpr *E) {
ExprDependence clang::computeDependence(BlockExpr *E,
bool ContainsUnexpandedParameterPack) {
auto D = toExprDependenceForImpliedType(E->getType()->getDependence());
if (E->getBlockDecl()->isDependentContext())
D |= ExprDependence::Instantiation;
if (ContainsUnexpandedParameterPack)
D |= ExprDependence::UnexpandedPack;
return D;
}

Expand Down
35 changes: 15 additions & 20 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1737,9 +1737,17 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
continue;

// Suppress inline namespace if it doesn't make the result ambiguous.
if (P.SuppressInlineNamespace && Ctx->isInlineNamespace() && NameInScope &&
cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope))
continue;
if (Ctx->isInlineNamespace() && NameInScope) {
bool isRedundant =
cast<NamespaceDecl>(Ctx)->isRedundantInlineQualifierFor(NameInScope);
if (P.SuppressInlineNamespace ==
PrintingPolicy::SuppressInlineNamespaceMode::All ||
(P.SuppressInlineNamespace ==
PrintingPolicy::SuppressInlineNamespaceMode::Redundant &&
isRedundant)) {
continue;
}
}

// Skip non-named contexts such as linkage specifications and ExportDecls.
const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx);
Expand Down Expand Up @@ -2696,10 +2704,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
auto From = VDTemplSpec->getInstantiatedFrom();
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
while (true) {
VTD = VTD->getMostRecentDecl();
if (VTD->isMemberSpecialization())
break;
while (!VTD->hasMemberSpecialization()) {
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
Expand All @@ -2709,10 +2714,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
}
if (auto *VTPSD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
while (true) {
VTPSD = VTPSD->getMostRecentDecl();
if (VTPSD->isMemberSpecialization())
break;
while (!VTPSD->hasMemberSpecialization()) {
if (auto *NewVTPSD = VTPSD->getInstantiatedFromMember())
VTPSD = NewVTPSD;
else
Expand All @@ -2726,10 +2728,7 @@ 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 *VTD = VD->getDescribedVarTemplate()) {
while (true) {
VTD = VTD->getMostRecentDecl();
if (VTD->isMemberSpecialization())
break;
while (!VTD->hasMemberSpecialization()) {
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
Expand Down Expand Up @@ -3067,7 +3066,6 @@ 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 @@ -4151,10 +4149,7 @@ 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 (true) {
Primary = Primary->getMostRecentDecl();
if (ForDefinition && Primary->isMemberSpecialization())
break;
while (!ForDefinition || !Primary->hasMemberSpecialization()) {
if (auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate())
Primary = NewPrimary;
else
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,10 @@ bool Decl::isInNamedModule() const {
return getOwningModule() && getOwningModule()->isNamedModule();
}

bool Decl::isFromHeaderUnit() const {
return getOwningModule() && getOwningModule()->isHeaderUnit();
}

static Decl::Kind getKind(const Decl *D) { return D->getKind(); }
static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); }

Expand Down
10 changes: 2 additions & 8 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2023,10 +2023,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
auto From = TD->getInstantiatedFrom();
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
while (true) {
CTD = CTD->getMostRecentDecl();
if (CTD->isMemberSpecialization())
break;
while (!CTD->hasMemberSpecialization()) {
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
CTD = NewCTD;
else
Expand All @@ -2036,10 +2033,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
while (true) {
CTPSD = CTPSD->getMostRecentDecl();
if (CTPSD->isMemberSpecialization())
break;
while (!CTPSD->hasMemberSpecialization()) {
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
CTPSD = NewCTPSD;
else
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/ExprConstShared.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
#ifndef LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H
#define LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H

#include "clang/Basic/TypeTraits.h"

namespace llvm {
class APFloat;
}
namespace clang {
class QualType;
class LangOptions;
class ASTContext;
class CharUnits;
class Expr;
} // namespace clang
using namespace clang;
/// Values returned by __builtin_classify_type, chosen to match the values
Expand Down Expand Up @@ -66,4 +71,7 @@ void HandleComplexComplexDiv(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C,
llvm::APFloat D, llvm::APFloat &ResR,
llvm::APFloat &ResI);

CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E,
UnaryExprOrTypeTrait ExprKind);

#endif
74 changes: 48 additions & 26 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9620,7 +9620,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
return ExprEvaluatorBaseTy::VisitCastExpr(E);
}

static CharUnits GetAlignOfType(EvalInfo &Info, QualType T,
static CharUnits GetAlignOfType(const ASTContext &Ctx, QualType T,
UnaryExprOrTypeTrait ExprKind) {
// C++ [expr.alignof]p3:
// When alignof is applied to a reference type, the result is the
Expand All @@ -9631,23 +9631,22 @@ static CharUnits GetAlignOfType(EvalInfo &Info, QualType T,
return CharUnits::One();

const bool AlignOfReturnsPreferred =
Info.Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;

// __alignof is defined to return the preferred alignment.
// Before 8, clang returned the preferred alignment for alignof and _Alignof
// as well.
if (ExprKind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
return Info.Ctx.toCharUnitsFromBits(
Info.Ctx.getPreferredTypeAlign(T.getTypePtr()));
return Ctx.toCharUnitsFromBits(Ctx.getPreferredTypeAlign(T.getTypePtr()));
// alignof and _Alignof are defined to return the ABI alignment.
else if (ExprKind == UETT_AlignOf)
return Info.Ctx.getTypeAlignInChars(T.getTypePtr());
return Ctx.getTypeAlignInChars(T.getTypePtr());
else
llvm_unreachable("GetAlignOfType on a non-alignment ExprKind");
}

static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E,
UnaryExprOrTypeTrait ExprKind) {
CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E,
UnaryExprOrTypeTrait ExprKind) {
E = E->IgnoreParens();

// The kinds of expressions that we have special-case logic here for
Expand All @@ -9657,22 +9656,22 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E,
// alignof decl is always accepted, even if it doesn't make sense: we default
// to 1 in those cases.
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
return Info.Ctx.getDeclAlign(DRE->getDecl(),
/*RefAsPointee*/true);
return Ctx.getDeclAlign(DRE->getDecl(),
/*RefAsPointee*/ true);

if (const MemberExpr *ME = dyn_cast<MemberExpr>(E))
return Info.Ctx.getDeclAlign(ME->getMemberDecl(),
/*RefAsPointee*/true);
return Ctx.getDeclAlign(ME->getMemberDecl(),
/*RefAsPointee*/ true);

return GetAlignOfType(Info, E->getType(), ExprKind);
return GetAlignOfType(Ctx, E->getType(), ExprKind);
}

static CharUnits getBaseAlignment(EvalInfo &Info, const LValue &Value) {
if (const auto *VD = Value.Base.dyn_cast<const ValueDecl *>())
return Info.Ctx.getDeclAlign(VD);
if (const auto *E = Value.Base.dyn_cast<const Expr *>())
return GetAlignOfExpr(Info, E, UETT_AlignOf);
return GetAlignOfType(Info, Value.Base.getTypeInfoType(), UETT_AlignOf);
return GetAlignOfExpr(Info.Ctx, E, UETT_AlignOf);
return GetAlignOfType(Info.Ctx, Value.Base.getTypeInfoType(), UETT_AlignOf);
}

/// Evaluate the value of the alignment argument to __builtin_align_{up,down},
Expand Down Expand Up @@ -9768,11 +9767,8 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,

if (BaseAlignment < Align) {
Result.Designator.setInvalid();
// FIXME: Add support to Diagnostic for long / long long.
CCEDiag(E->getArg(0),
diag::note_constexpr_baa_insufficient_alignment) << 0
<< (unsigned)BaseAlignment.getQuantity()
<< (unsigned)Align.getQuantity();
CCEDiag(E->getArg(0), diag::note_constexpr_baa_insufficient_alignment)
<< 0 << BaseAlignment.getQuantity() << Align.getQuantity();
return false;
}
}
Expand All @@ -9783,11 +9779,11 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,

(OffsetResult.Base
? CCEDiag(E->getArg(0),
diag::note_constexpr_baa_insufficient_alignment) << 1
diag::note_constexpr_baa_insufficient_alignment)
<< 1
: CCEDiag(E->getArg(0),
diag::note_constexpr_baa_value_insufficient_alignment))
<< (int)OffsetResult.Offset.getQuantity()
<< (unsigned)Align.getQuantity();
<< OffsetResult.Offset.getQuantity() << Align.getQuantity();
return false;
}

Expand Down Expand Up @@ -14478,11 +14474,11 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
case UETT_PreferredAlignOf:
case UETT_AlignOf: {
if (E->isArgumentType())
return Success(GetAlignOfType(Info, E->getArgumentType(), E->getKind()),
E);
return Success(
GetAlignOfType(Info.Ctx, E->getArgumentType(), E->getKind()), E);
else
return Success(GetAlignOfExpr(Info, E->getArgumentExpr(), E->getKind()),
E);
return Success(
GetAlignOfExpr(Info.Ctx, E->getArgumentExpr(), E->getKind()), E);
}

case UETT_PtrAuthTypeDiscriminator: {
Expand Down Expand Up @@ -15314,6 +15310,32 @@ bool FloatExprEvaluator::VisitCallExpr(const CallExpr *E) {
Result = RHS;
return true;
}

case Builtin::BI__builtin_fmaximum_num:
case Builtin::BI__builtin_fmaximum_numf:
case Builtin::BI__builtin_fmaximum_numl:
case Builtin::BI__builtin_fmaximum_numf16:
case Builtin::BI__builtin_fmaximum_numf128: {
APFloat RHS(0.);
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
!EvaluateFloat(E->getArg(1), RHS, Info))
return false;
Result = maximumnum(Result, RHS);
return true;
}

case Builtin::BI__builtin_fminimum_num:
case Builtin::BI__builtin_fminimum_numf:
case Builtin::BI__builtin_fminimum_numl:
case Builtin::BI__builtin_fminimum_numf16:
case Builtin::BI__builtin_fminimum_numf128: {
APFloat RHS(0.);
if (!EvaluateFloat(E->getArg(0), Result, Info) ||
!EvaluateFloat(E->getArg(1), RHS, Info))
return false;
Result = minimumnum(Result, RHS);
return true;
}
}
}

Expand Down
3 changes: 1 addition & 2 deletions clang/lib/AST/InheritViz.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,11 @@ void InheritanceHierarchyWriter::WriteNode(QualType Type, bool FromVirtual) {
QualType CanonType = Context.getCanonicalType(Type);

if (FromVirtual) {
if (KnownVirtualBases.find(CanonType) != KnownVirtualBases.end())
if (!KnownVirtualBases.insert(CanonType).second)
return;

// We haven't seen this virtual base before, so display it and
// its bases.
KnownVirtualBases.insert(CanonType);
}

// Declare the node itself.
Expand Down
80 changes: 71 additions & 9 deletions clang/lib/AST/OpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ bool OpenACCClauseWithExprs::classof(const OpenACCClause *C) {
return OpenACCWaitClause::classof(C) || OpenACCNumGangsClause::classof(C) ||
OpenACCTileClause::classof(C) ||
OpenACCClauseWithSingleIntExpr::classof(C) ||
OpenACCClauseWithVarList::classof(C);
OpenACCGangClause::classof(C) || OpenACCClauseWithVarList::classof(C);
}
bool OpenACCClauseWithVarList::classof(const OpenACCClause *C) {
return OpenACCPrivateClause::classof(C) ||
Expand All @@ -44,7 +44,8 @@ bool OpenACCClauseWithCondition::classof(const OpenACCClause *C) {
bool OpenACCClauseWithSingleIntExpr::classof(const OpenACCClause *C) {
return OpenACCNumWorkersClause::classof(C) ||
OpenACCVectorLengthClause::classof(C) ||
OpenACCCollapseClause::classof(C) || OpenACCAsyncClause::classof(C);
OpenACCWorkerClause::classof(C) || OpenACCCollapseClause::classof(C) ||
OpenACCAsyncClause::classof(C);
}
OpenACCDefaultClause *OpenACCDefaultClause::Create(const ASTContext &C,
OpenACCDefaultClauseKind K,
Expand Down Expand Up @@ -125,6 +126,21 @@ OpenACCNumWorkersClause::OpenACCNumWorkersClause(SourceLocation BeginLoc,
"Condition expression type not scalar/dependent");
}

OpenACCGangClause::OpenACCGangClause(SourceLocation BeginLoc,
SourceLocation LParenLoc,
ArrayRef<OpenACCGangKind> GangKinds,
ArrayRef<Expr *> IntExprs,
SourceLocation EndLoc)
: OpenACCClauseWithExprs(OpenACCClauseKind::Gang, BeginLoc, LParenLoc,
EndLoc) {
assert(GangKinds.size() == IntExprs.size() && "Mismatch exprs/kind?");
std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
getTrailingObjects<Expr *>());
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
std::uninitialized_copy(GangKinds.begin(), GangKinds.end(),
getTrailingObjects<OpenACCGangKind>());
}

OpenACCNumWorkersClause *
OpenACCNumWorkersClause::Create(const ASTContext &C, SourceLocation BeginLoc,
SourceLocation LParenLoc, Expr *IntExpr,
Expand Down Expand Up @@ -376,18 +392,36 @@ OpenACCSeqClause *OpenACCSeqClause::Create(const ASTContext &C,
return new (Mem) OpenACCSeqClause(BeginLoc, EndLoc);
}

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

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

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

OpenACCVectorClause *OpenACCVectorClause::Create(const ASTContext &C,
Expand Down Expand Up @@ -600,3 +634,31 @@ void OpenACCClausePrinter::VisitCollapseClause(const OpenACCCollapseClause &C) {
printExpr(C.getLoopCount());
OS << ")";
}

void OpenACCClausePrinter::VisitGangClause(const OpenACCGangClause &C) {
OS << "gang";

if (C.getNumExprs() > 0) {
OS << "(";
bool first = true;
for (unsigned I = 0; I < C.getNumExprs(); ++I) {
if (!first)
OS << ", ";
first = false;

OS << C.getExpr(I).first << ": ";
printExpr(C.getExpr(I).second);
}
OS << ")";
}
}

void OpenACCClausePrinter::VisitWorkerClause(const OpenACCWorkerClause &C) {
OS << "worker";

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

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

void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) {
if (Clause.hasDevNumExpr())
Profiler.VisitStmt(Clause.getDevNumExpr());
Expand All @@ -2646,6 +2652,12 @@ void OpenACCClauseProfiler::VisitIndependentClause(

void OpenACCClauseProfiler::VisitSeqClause(const OpenACCSeqClause &Clause) {}

void OpenACCClauseProfiler::VisitGangClause(const OpenACCGangClause &Clause) {
for (unsigned I = 0; I < Clause.getNumExprs(); ++I) {
Profiler.VisitStmt(Clause.getExpr(I).second);
}
}

void OpenACCClauseProfiler::VisitReductionClause(
const OpenACCReductionClause &Clause) {
for (auto *E : Clause.getVarList())
Expand Down
12 changes: 12 additions & 0 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,11 +420,23 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
case OpenACCClauseKind::Self:
case OpenACCClauseKind::Seq:
case OpenACCClauseKind::Tile:
case OpenACCClauseKind::Worker:
case OpenACCClauseKind::VectorLength:
// The condition expression will be printed as a part of the 'children',
// but print 'clause' here so it is clear what is happening from the dump.
OS << " clause";
break;
case OpenACCClauseKind::Gang: {
OS << " clause";
// print the list of all GangKinds, so that there is some sort of
// relationship to the expressions listed afterwards.
auto *GC = cast<OpenACCGangClause>(C);

for (unsigned I = 0; I < GC->getNumExprs(); ++I) {
OS << " " << GC->getExpr(I).first;
}
break;
}
case OpenACCClauseKind::Collapse:
OS << " clause";
if (cast<OpenACCCollapseClause>(C)->hasForce())
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1413,7 +1413,9 @@ void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS,

// Only suppress an inline namespace if the name has the same lookup
// results in the enclosing namespace.
if (Policy.SuppressInlineNamespace && NS->isInline() && NameInScope &&
if (Policy.SuppressInlineNamespace !=
PrintingPolicy::SuppressInlineNamespaceMode::None &&
NS->isInline() && NameInScope &&
NS->isRedundantInlineQualifierFor(NameInScope))
return AppendScope(DC->getParent(), OS, NameInScope);

Expand Down
4 changes: 3 additions & 1 deletion clang/lib/ASTMatchers/ASTMatchersInternal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,9 @@ bool HasNameMatcher::matchesNodeFullSlow(const NamedDecl &Node) const {

PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy();
Policy.SuppressUnwrittenScope = SkipUnwritten;
Policy.SuppressInlineNamespace = SkipUnwritten;
Policy.SuppressInlineNamespace =
SkipUnwritten ? PrintingPolicy::SuppressInlineNamespaceMode::All
: PrintingPolicy::SuppressInlineNamespaceMode::None;
Node.printQualifiedName(OS, Policy);

const StringRef FullName = OS.str();
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Analysis/ProgramPoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
LHS->printJson(Out, nullptr, PP, AddQuotes);
} else {
Out << "null";
}
}

Out << ", \"rhs\": ";
if (const Stmt *RHS = C->getRHS()) {
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Basic/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ static const CudaVersionMapEntry CudaNameVersionMap[] = {
CUDA_ENTRY(12, 3),
CUDA_ENTRY(12, 4),
CUDA_ENTRY(12, 5),
CUDA_ENTRY(12, 6),
{"", CudaVersion::NEW, llvm::VersionTuple(std::numeric_limits<int>::max())},
{"unknown", CudaVersion::UNKNOWN, {}} // End of list tombstone.
};
Expand Down Expand Up @@ -96,6 +97,7 @@ static const OffloadArchToStringMap arch_names[] = {
SM(89), // Ada Lovelace
SM(90), // Hopper
SM(90a), // Hopper
SM(100), // Blackwell
GFX(600), // gfx600
GFX(601), // gfx601
GFX(602), // gfx602
Expand Down Expand Up @@ -221,6 +223,9 @@ CudaVersion MinVersionForOffloadArch(OffloadArch A) {
return CudaVersion::CUDA_118;
case OffloadArch::SM_90a:
return CudaVersion::CUDA_120;
case OffloadArch::SM_100:
return CudaVersion::NEW; // TODO: use specific CUDA version once it's
// public.
default:
llvm_unreachable("invalid enum");
}
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Basic/IdentifierTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ ReservedLiteralSuffixIdStatus
IdentifierInfo::isReservedLiteralSuffixId() const {
StringRef Name = getName();

// Note: the diag::warn_deprecated_literal_operator_id diagnostic depends on
// this being the first check we do, so if this order changes, we have to fix
// that as well.
if (Name[0] != '_')
return ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore;

Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,9 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
switch (Triple.getEnvironment()) {
case llvm::Triple::Android:
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIT64:
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABI:
case llvm::Triple::MuslEABIHF:
case llvm::Triple::OpenHOS:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/DirectX.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class LLVM_LIBRARY_VISIBILITY DirectXTargetInfo : public TargetInfo {
PlatformName = llvm::Triple::getOSTypeName(Triple.getOS());
resetDataLayout("e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:"
"32-f64:64-n8:16:32:64");
TheCXXABI.set(TargetCXXABI::Microsoft);
TheCXXABI.set(TargetCXXABI::GenericItanium);
}
bool useFP16ConversionIntrinsics() const override { return false; }
void getTargetDefines(const LangOptions &Opts,
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/NVPTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,8 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
case OffloadArch::SM_90:
case OffloadArch::SM_90a:
return "900";
case OffloadArch::SM_100:
return "1000";
}
llvm_unreachable("unhandled OffloadArch");
}();
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/OSTargets.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo<Target> {
Builder.defineMacro("_GNU_SOURCE");
if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__");
if (Triple.isTime64ABI()) {
Builder.defineMacro("_FILE_OFFSET_BITS", "64");
Builder.defineMacro("_TIME_BITS", "64");
}
}

public:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ bool RISCVTargetInfo::validateAsmConstraint(
return true;
case 'v':
// A vector register.
if (Name[1] == 'r' || Name[1] == 'm') {
if (Name[1] == 'r' || Name[1] == 'd' || Name[1] == 'm') {
Info.setAllowsRegister();
Name += 1;
return true;
Expand Down
9 changes: 5 additions & 4 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1321,10 +1321,11 @@ static void runThinLTOBackend(
Conf.CGFileType = getCodeGenFileType(Action);
break;
}
if (Error E = thinBackend(
Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
/* ModuleMap */ nullptr, Conf.CodeGenOnly, CGOpts.CmdArgs)) {
if (Error E =
thinBackend(Conf, -1, AddStream, *M, *CombinedIndex, ImportList,
ModuleToDefinedGVSummaries[M->getModuleIdentifier()],
/*ModuleMap=*/nullptr, Conf.CodeGenOnly,
/*IRAddStream=*/nullptr, CGOpts.CmdArgs)) {
handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
errs() << "Error running ThinLTO backend: " << EIB.message() << '\n';
});
Expand Down
76 changes: 64 additions & 12 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2869,6 +2869,28 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Intrinsic::minnum,
Intrinsic::experimental_constrained_minnum));

case Builtin::BIfmaximum_num:
case Builtin::BIfmaximum_numf:
case Builtin::BIfmaximum_numl:
case Builtin::BI__builtin_fmaximum_num:
case Builtin::BI__builtin_fmaximum_numf:
case Builtin::BI__builtin_fmaximum_numf16:
case Builtin::BI__builtin_fmaximum_numl:
case Builtin::BI__builtin_fmaximum_numf128:
return RValue::get(
emitBuiltinWithOneOverloadedType<2>(*this, E, Intrinsic::maximumnum));

case Builtin::BIfminimum_num:
case Builtin::BIfminimum_numf:
case Builtin::BIfminimum_numl:
case Builtin::BI__builtin_fminimum_num:
case Builtin::BI__builtin_fminimum_numf:
case Builtin::BI__builtin_fminimum_numf16:
case Builtin::BI__builtin_fminimum_numl:
case Builtin::BI__builtin_fminimum_numf128:
return RValue::get(
emitBuiltinWithOneOverloadedType<2>(*this, E, Intrinsic::minimumnum));

// fmod() is a special-case. It maps to the frem instruction rather than an
// LLVM intrinsic.
case Builtin::BIfmod:
Expand Down Expand Up @@ -13648,7 +13670,7 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
Value *InfoKind = ConstantInt::get(Int64Ty, C->getSExtValue());

// Built the IR for the preserve_field_info intrinsic.
llvm::Function *FnGetFieldInfo = llvm::Intrinsic::getDeclaration(
llvm::Function *FnGetFieldInfo = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::bpf_preserve_field_info,
{FieldAddr->getType()});
return Builder.CreateCall(FnGetFieldInfo, {FieldAddr, InfoKind});
Expand All @@ -13670,10 +13692,10 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,

llvm::Function *FnDecl;
if (BuiltinID == BPF::BI__builtin_btf_type_id)
FnDecl = llvm::Intrinsic::getDeclaration(
FnDecl = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::bpf_btf_type_id, {});
else
FnDecl = llvm::Intrinsic::getDeclaration(
FnDecl = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::bpf_preserve_type_info, {});
CallInst *Fn = Builder.CreateCall(FnDecl, {SeqNumVal, FlagValue});
Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo);
Expand Down Expand Up @@ -13708,7 +13730,7 @@ Value *CodeGenFunction::EmitBPFBuiltinExpr(unsigned BuiltinID,
Value *FlagValue = ConstantInt::get(Int64Ty, Flag->getSExtValue());
Value *SeqNumVal = ConstantInt::get(Int32Ty, BuiltinSeqNum++);

llvm::Function *IntrinsicFn = llvm::Intrinsic::getDeclaration(
llvm::Function *IntrinsicFn = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::bpf_preserve_enum_value, {});
CallInst *Fn =
Builder.CreateCall(IntrinsicFn, {SeqNumVal, EnumStrVal, FlagValue});
Expand Down Expand Up @@ -18755,6 +18777,16 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
CGM.getHLSLRuntime().getNormalizeIntrinsic(), ArrayRef<Value *>{X},
nullptr, "hlsl.normalize");
}
case Builtin::BI__builtin_hlsl_elementwise_degrees: {
Value *X = EmitScalarExpr(E->getArg(0));

assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
"degree operand must have a float representation");

return Builder.CreateIntrinsic(
/*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getDegreesIntrinsic(),
ArrayRef<Value *>{X}, nullptr, "hlsl.degrees");
}
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
Expand Down Expand Up @@ -18867,27 +18899,47 @@ case Builtin::BI__builtin_hlsl_elementwise_isinf: {
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.step");
}
case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
return EmitRuntimeCall(CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, {}, false), "__hlsl_wave_get_lane_index",
{}, false, true));
// We don't define a SPIR-V intrinsic, instead it is a SPIR-V built-in
// defined in SPIRVBuiltins.td. So instead we manually get the matching name
// for the DirectX intrinsic and the demangled builtin name
switch (CGM.getTarget().getTriple().getArch()) {
case llvm::Triple::dxil:
return EmitRuntimeCall(Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), Intrinsic::dx_wave_getlaneindex));
case llvm::Triple::spirv:
return EmitRuntimeCall(CGM.CreateRuntimeFunction(
llvm::FunctionType::get(IntTy, {}, false),
"__hlsl_wave_get_lane_index", {}, false, true));
default:
llvm_unreachable(
"Intrinsic WaveGetLaneIndex not supported by target architecture");
}
}
case Builtin::BI__builtin_hlsl_wave_is_first_lane: {
Intrinsic::ID ID = CGM.getHLSLRuntime().getWaveIsFirstLaneIntrinsic();
return EmitRuntimeCall(Intrinsic::getDeclaration(&CGM.getModule(), ID));
return EmitRuntimeCall(
Intrinsic::getOrInsertDeclaration(&CGM.getModule(), ID));
}
case Builtin::BI__builtin_hlsl_elementwise_sign: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
auto *Arg0 = E->getArg(0);
Value *Op0 = EmitScalarExpr(Arg0);
llvm::Type *Xty = Op0->getType();
llvm::Type *retType = llvm::Type::getInt32Ty(this->getLLVMContext());
if (Xty->isVectorTy()) {
auto *XVecTy = E->getArg(0)->getType()->getAs<VectorType>();
auto *XVecTy = Arg0->getType()->getAs<VectorType>();
retType = llvm::VectorType::get(
retType, ElementCount::getFixed(XVecTy->getNumElements()));
}
assert((E->getArg(0)->getType()->hasFloatingRepresentation() ||
E->getArg(0)->getType()->hasSignedIntegerRepresentation()) &&
assert((Arg0->getType()->hasFloatingRepresentation() ||
Arg0->getType()->hasIntegerRepresentation()) &&
"sign operand must have a float or int representation");

if (Arg0->getType()->hasUnsignedIntegerRepresentation()) {
Value *Cmp = Builder.CreateICmpEQ(Op0, ConstantInt::get(Xty, 0));
return Builder.CreateSelect(Cmp, ConstantInt::get(retType, 0),
ConstantInt::get(retType, 1), "hlsl.sign");
}

return Builder.CreateIntrinsic(
retType, CGM.getHLSLRuntime().getSignIntrinsic(),
ArrayRef<Value *>{Op0}, nullptr, "hlsl.sign");
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
PP.SplitTemplateClosers = true;
}

PP.SuppressInlineNamespace = false;
PP.SuppressInlineNamespace =
PrintingPolicy::SuppressInlineNamespaceMode::None;
PP.PrintCanonicalTypes = true;
PP.UsePreferredNames = false;
PP.AlwaysIncludeTypeForTemplateArgument = true;
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/CodeGen/CGDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2509,17 +2509,17 @@ void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin,
llvm::Function *CodeGenModule::getLLVMLifetimeStartFn() {
if (LifetimeStartFn)
return LifetimeStartFn;
LifetimeStartFn = llvm::Intrinsic::getDeclaration(&getModule(),
llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy);
LifetimeStartFn = llvm::Intrinsic::getOrInsertDeclaration(
&getModule(), llvm::Intrinsic::lifetime_start, AllocaInt8PtrTy);
return LifetimeStartFn;
}

/// Lazily declare the @llvm.lifetime.end intrinsic.
llvm::Function *CodeGenModule::getLLVMLifetimeEndFn() {
if (LifetimeEndFn)
return LifetimeEndFn;
LifetimeEndFn = llvm::Intrinsic::getDeclaration(&getModule(),
llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy);
LifetimeEndFn = llvm::Intrinsic::getOrInsertDeclaration(
&getModule(), llvm::Intrinsic::lifetime_end, AllocaInt8PtrTy);
return LifetimeEndFn;
}

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGException.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1843,7 +1843,7 @@ Address CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size()));
int FrameEscapeIdx = InsertPair.first->second;
// call ptr @llvm.localrecover(ptr @parentFn, ptr %fp, i32 N)
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::localrecover);
RecoverCall = Builder.CreateCall(
FrameRecoverFn, {ParentCGF.CurFn, ParentFP,
Expand Down Expand Up @@ -1942,7 +1942,7 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
// %1 = call ptr @llvm.localrecover(@"?fin$0@0@main@@",..)
// %2 = load ptr, ptr %1, align 8
// ==> %2 is the frame-pointer of outermost host function
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
llvm::Function *FrameRecoverFn = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::localrecover);
ParentFP = Builder.CreateCall(
FrameRecoverFn, {ParentCGF.CurFn, ParentFP,
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1528,7 +1528,12 @@ LValue CodeGenFunction::EmitCheckedLValue(const Expr *E, TypeCheckKind TCK) {
///
LValue CodeGenFunction::EmitLValue(const Expr *E,
KnownNonNull_t IsKnownNonNull) {
LValue LV = EmitLValueHelper(E, IsKnownNonNull);
// Running with sufficient stack space to avoid deeply nested expressions
// cause a stack overflow.
LValue LV;
CGM.runWithSufficientStackSpace(
E->getExprLoc(), [&] { LV = EmitLValueHelper(E, IsKnownNonNull); });

if (IsKnownNonNull && !LV.isKnownNonNull())
LV.setKnownNonNull();
return LV;
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGHLSLRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
GENERATE_HLSL_INTRINSIC_FUNCTION(Cross, cross)
GENERATE_HLSL_INTRINSIC_FUNCTION(Degrees, degrees)
GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)
GENERATE_HLSL_INTRINSIC_FUNCTION(Length, length)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
Expand Down
45 changes: 14 additions & 31 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1713,25 +1713,15 @@ llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
if (!Ctor && !Dtor)
return nullptr;

llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
/*isVarArg=*/false)
->getPointerTo();
// Copying constructor for the threadprivate variable.
// Must be NULL - reserved by runtime, but currently it requires that this
// parameter is always NULL. Otherwise it fires assertion.
CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
CopyCtor = llvm::Constant::getNullValue(CGM.UnqualPtrTy);
if (Ctor == nullptr) {
auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
/*isVarArg=*/false)
->getPointerTo();
Ctor = llvm::Constant::getNullValue(CtorTy);
Ctor = llvm::Constant::getNullValue(CGM.UnqualPtrTy);
}
if (Dtor == nullptr) {
auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
/*isVarArg=*/false)
->getPointerTo();
Dtor = llvm::Constant::getNullValue(DtorTy);
Dtor = llvm::Constant::getNullValue(CGM.UnqualPtrTy);
}
if (!CGF) {
auto *InitFunctionTy =
Expand Down Expand Up @@ -1817,7 +1807,7 @@ Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), OMPRTL___kmpc_threadprivate_cached),
Args),
VarLVType->getPointerTo(/*AddrSpace=*/0)),
CGF.Builder.getPtrTy(0)),
VarLVType, CGM.getContext().getTypeAlignInChars(VarType));
}

Expand Down Expand Up @@ -2131,10 +2121,7 @@ static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);

llvm::Type *ElemTy = CGF.ConvertTypeForMem(Var->getType());
return Address(
CGF.Builder.CreateBitCast(
Ptr, ElemTy->getPointerTo(Ptr->getType()->getPointerAddressSpace())),
ElemTy, CGF.getContext().getDeclAlign(Var));
return Address(Ptr, ElemTy, CGF.getContext().getDeclAlign(Var));
}

static llvm::Value *emitCopyprivateCopyFunction(
Expand Down Expand Up @@ -2166,11 +2153,11 @@ static llvm::Value *emitCopyprivateCopyFunction(
// Src = (void*[n])(RHSArg);
Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
ArgsElemType->getPointerTo()),
CGF.Builder.getPtrTy(0)),
ArgsElemType, CGF.getPointerAlign());
Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
ArgsElemType->getPointerTo()),
CGF.Builder.getPtrTy(0)),
ArgsElemType, CGF.getPointerAlign());
// *(Type0*)Dst[0] = *(Type0*)Src[0];
// *(Type1*)Dst[1] = *(Type1*)Src[1];
Expand Down Expand Up @@ -3681,9 +3668,7 @@ CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
QualType KmpTaskTWithPrivatesPtrQTy =
C.getPointerType(KmpTaskTWithPrivatesQTy);
llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
llvm::Type *KmpTaskTWithPrivatesPtrTy =
KmpTaskTWithPrivatesTy->getPointerTo();
llvm::Type *KmpTaskTWithPrivatesPtrTy = CGF.Builder.getPtrTy(0);
llvm::Value *KmpTaskTWithPrivatesTySize =
CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
QualType SharedsPtrTy = C.getPointerType(SharedsTy);
Expand Down Expand Up @@ -4399,7 +4384,7 @@ Address CGOpenMPRuntime::emitDepobjDependClause(
Args, ".dep.arr.addr");
llvm::Type *KmpDependInfoLlvmTy = CGF.ConvertTypeForMem(KmpDependInfoTy);
Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Addr, KmpDependInfoLlvmTy->getPointerTo());
Addr, CGF.Builder.getPtrTy(0));
DependenciesArray = Address(Addr, KmpDependInfoLlvmTy, Align);
// Write number of elements in the first element of array for depobj.
LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy);
Expand Down Expand Up @@ -4841,11 +4826,11 @@ llvm::Function *CGOpenMPRuntime::emitReductionFunction(
// Src = (void*[n])(RHSArg);
Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
ArgsElemType->getPointerTo()),
CGF.Builder.getPtrTy(0)),
ArgsElemType, CGF.getPointerAlign());
Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
ArgsElemType->getPointerTo()),
CGF.Builder.getPtrTy(0)),
ArgsElemType, CGF.getPointerAlign());

// ...
Expand Down Expand Up @@ -5277,8 +5262,7 @@ static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
QualType PrivateType = RCG.getPrivateType(N);
Address PrivateAddr = CGF.EmitLoadOfPointer(
CGF.GetAddrOfLocalVar(&Param).withElementType(
CGF.ConvertTypeForMem(PrivateType)->getPointerTo()),
CGF.GetAddrOfLocalVar(&Param).withElementType(CGF.Builder.getPtrTy(0)),
C.getPointerType(PrivateType)->castAs<PointerType>());
llvm::Value *Size = nullptr;
// If the size of the reduction item is non-constant, load it from global
Expand Down Expand Up @@ -5366,15 +5350,14 @@ static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
// Pull out the pointer to the variable.
CGF.EmitLoadOfPointer(
CGF.GetAddrOfLocalVar(&ParamInOut)
.withElementType(
CGF.ConvertTypeForMem(LHSVD->getType())->getPointerTo()),
.withElementType(CGF.Builder.getPtrTy(0)),
C.getPointerType(LHSVD->getType())->castAs<PointerType>()));
PrivateScope.addPrivate(
RHSVD,
// Pull out the pointer to the variable.
CGF.EmitLoadOfPointer(
CGF.GetAddrOfLocalVar(&ParamIn).withElementType(
CGF.ConvertTypeForMem(RHSVD->getType())->getPointerTo()),
CGF.Builder.getPtrTy(0)),
C.getPointerType(RHSVD->getType())->castAs<PointerType>()));
PrivateScope.Privatize();
// Emit the combiner body:
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,7 @@ void CGOpenMPRuntimeGPU::processRequiresDirective(const OMPRequiresDecl *D) {
case OffloadArch::SM_89:
case OffloadArch::SM_90:
case OffloadArch::SM_90a:
case OffloadArch::SM_100:
case OffloadArch::GFX600:
case OffloadArch::GFX601:
case OffloadArch::GFX602:
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
EscapeArgs.resize(EscapedLocals.size());
for (auto &Pair : EscapedLocals)
EscapeArgs[Pair.second] = Pair.first;
llvm::Function *FrameEscapeFn = llvm::Intrinsic::getDeclaration(
llvm::Function *FrameEscapeFn = llvm::Intrinsic::getOrInsertDeclaration(
&CGM.getModule(), llvm::Intrinsic::localescape);
CGBuilderTy(*this, AllocaInsertPt).CreateCall(FrameEscapeFn, EscapeArgs);
}
Expand Down Expand Up @@ -3130,7 +3130,7 @@ void CodeGenFunction::emitAlignmentAssumptionCheck(
llvm::Instruction *Assumption) {
assert(isa_and_nonnull<llvm::CallInst>(Assumption) &&
cast<llvm::CallInst>(Assumption)->getCalledOperand() ==
llvm::Intrinsic::getDeclaration(
llvm::Intrinsic::getOrInsertDeclaration(
Builder.GetInsertBlock()->getParent()->getParent(),
llvm::Intrinsic::assume) &&
"Assumption should be a call to llvm.assume().");
Expand Down
23 changes: 17 additions & 6 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Stack.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/CodeGen/BackendUtil.h"
Expand Down Expand Up @@ -175,10 +176,7 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
else if (ABIStr == "aapcs16")
Kind = ARMABIKind::AAPCS16_VFP;
else if (CodeGenOpts.FloatABI == "hard" ||
(CodeGenOpts.FloatABI != "soft" &&
(Triple.getEnvironment() == llvm::Triple::GNUEABIHF ||
Triple.getEnvironment() == llvm::Triple::MuslEABIHF ||
Triple.getEnvironment() == llvm::Triple::EABIHF)))
(CodeGenOpts.FloatABI != "soft" && Triple.isHardFloatABI()))
Kind = ARMABIKind::AAPCS_VFP;

return createARMTargetCodeGenInfo(CGM, Kind);
Expand Down Expand Up @@ -1596,6 +1594,19 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type) {
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
}

void CodeGenModule::warnStackExhausted(SourceLocation Loc) {
// Only warn about this once.
if (!WarnedStackExhausted) {
getDiags().Report(Loc, diag::warn_stack_exhausted);
WarnedStackExhausted = true;
}
}

void CodeGenModule::runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn) {
clang::runWithSufficientStackSpace([&] { warnStackExhausted(Loc); }, Fn);
}

llvm::ConstantInt *CodeGenModule::getSize(CharUnits size) {
return llvm::ConstantInt::get(SizeTy, size.getQuantity());
}
Expand Down Expand Up @@ -6218,8 +6229,8 @@ void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {

llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,
ArrayRef<llvm::Type*> Tys) {
return llvm::Intrinsic::getDeclaration(&getModule(), (llvm::Intrinsic::ID)IID,
Tys);
return llvm::Intrinsic::getOrInsertDeclaration(&getModule(),
(llvm::Intrinsic::ID)IID, Tys);
}

static llvm::StringMapEntry<llvm::GlobalVariable *> &
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ class CodeGenModule : public CodeGenTypeCache {
std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader;
InstrProfStats PGOStats;
std::unique_ptr<llvm::SanitizerStatReport> SanStats;
bool WarnedStackExhausted = false;

// A set of references that have only been seen via a weakref so far. This is
// used to remove the weak of the reference if we ever see a direct reference
Expand Down Expand Up @@ -1297,6 +1298,16 @@ class CodeGenModule : public CodeGenTypeCache {
/// Print out an error that codegen doesn't support the specified decl yet.
void ErrorUnsupported(const Decl *D, const char *Type);

/// Warn that the stack is nearly exhausted.
void warnStackExhausted(SourceLocation Loc);

/// Run some code with "sufficient" stack space. (Currently, at least 256K is
/// guaranteed). Produces a warning if we're low on stack space and allocates
/// more in that case. Use this in code that may recurse deeply to avoid stack
/// overflow.
void runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn);

/// Set the attributes on the LLVM function for the given decl and function
/// info. This applies attributes necessary for handling the ABI as well as
/// user specified attributes like section.
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CodeGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ void CodeGenTypes::addRecordTypeName(const RecordDecl *RD,
// example, we should probably enable PrintCanonicalTypes and
// FullyQualifiedNames.
PrintingPolicy Policy = RD->getASTContext().getPrintingPolicy();
Policy.SuppressInlineNamespace = false;
Policy.SuppressInlineNamespace =
PrintingPolicy::SuppressInlineNamespaceMode::None;

// Name the codegen type after the typedef name
// if there is no tag type name available
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2997,6 +2997,10 @@ void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
if (D.isNoDestroy(CGM.getContext()))
return;

// HLSL doesn't support atexit.
if (CGM.getLangOpts().HLSL)
return CGM.AddCXXDtorEntry(dtor, addr);

// OpenMP offloading supports C++ constructors and destructors but we do not
// always have 'atexit' available. Instead lower these to use the LLVM global
// destructors which we can handle directly in the runtime. Note that this is
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ class ARMABIInfo : public ABIInfo {
case llvm::Triple::EABI:
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIT64:
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABI:
case llvm::Triple::MuslEABIHF:
return true;
Expand All @@ -48,6 +50,7 @@ class ARMABIInfo : public ABIInfo {
switch (getTarget().getTriple().getEnvironment()) {
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABIHF:
return true;
default:
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/Targets/SystemZ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ class SystemZTargetCodeGenInfo : public TargetCodeGenInfo {
if (Ty->isFloatTy() || Ty->isDoubleTy() || Ty->isFP128Ty()) {
llvm::Module &M = CGM.getModule();
auto &Ctx = M.getContext();
llvm::Function *TDCFunc =
llvm::Intrinsic::getDeclaration(&M, llvm::Intrinsic::s390_tdc, Ty);
llvm::Function *TDCFunc = llvm::Intrinsic::getOrInsertDeclaration(
&M, llvm::Intrinsic::s390_tdc, Ty);
unsigned TDCBits = 0;
switch (BuiltinID) {
case Builtin::BI__builtin_isnan:
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,8 @@ static llvm::Triple computeTargetTriple(const Driver &D,
if (A->getOption().matches(options::OPT_m64) ||
A->getOption().matches(options::OPT_maix64)) {
AT = Target.get64BitArchVariant().getArch();
if (Target.getEnvironment() == llvm::Triple::GNUX32)
if (Target.getEnvironment() == llvm::Triple::GNUX32 ||
Target.getEnvironment() == llvm::Triple::GNUT64)
Target.setEnvironment(llvm::Triple::GNU);
else if (Target.getEnvironment() == llvm::Triple::MuslX32)
Target.setEnvironment(llvm::Triple::Musl);
Expand Down Expand Up @@ -673,6 +674,7 @@ static llvm::Triple computeTargetTriple(const Driver &D,
} else if (ABIName == "n32") {
Target = Target.get64BitArchVariant();
if (Target.getEnvironment() == llvm::Triple::GNU ||
Target.getEnvironment() == llvm::Triple::GNUT64 ||
Target.getEnvironment() == llvm::Triple::GNUABI64)
Target.setEnvironment(llvm::Triple::GNUABIN32);
else if (Target.getEnvironment() == llvm::Triple::Musl ||
Expand All @@ -681,6 +683,7 @@ static llvm::Triple computeTargetTriple(const Driver &D,
} else if (ABIName == "64") {
Target = Target.get64BitArchVariant();
if (Target.getEnvironment() == llvm::Triple::GNU ||
Target.getEnvironment() == llvm::Triple::GNUT64 ||
Target.getEnvironment() == llvm::Triple::GNUABIN32)
Target.setEnvironment(llvm::Triple::GNUABI64);
else if (Target.getEnvironment() == llvm::Triple::Musl ||
Expand Down Expand Up @@ -2029,7 +2032,7 @@ void Driver::PrintHelp(bool ShowHidden) const {

void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const {
if (IsFlangMode()) {
OS << getClangToolFullVersion("flang-new") << '\n';
OS << getClangToolFullVersion("flang") << '\n';
} else {
// FIXME: The following handlers should use a callback mechanism, we don't
// know what the client would like to do.
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
{"cl", "--driver-mode=cl"},
{"++", "--driver-mode=g++"},
{"flang", "--driver-mode=flang"},
// For backwards compatibility, we create a symlink for `flang` called
// `flang-new`. This will be removed in the future.
{"flang-new", "--driver-mode=flang"},
{"clang-dxc", "--driver-mode=dxc"},
};

Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Driver/ToolChains/AVR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,14 @@ void AVRToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
void AVRToolChain::addClangTargetOptions(
const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind DeviceOffloadKind) const {
// Reject C/C++ compilation for avr1 devices since they have no SRAM.
const Driver &D = getDriver();
std::string CPU = getCPUName(D, DriverArgs, getTriple());
std::optional<StringRef> FamilyName = GetMCUFamilyName(CPU);
if (CPU == "avr1" || (FamilyName && *FamilyName == "avr1"))
D.Diag(diag::err_drv_opt_unsupported_input_type)
<< "-mmcu=" + CPU << "c/c++";

// By default, use `.ctors` (not `.init_array`), as required by libgcc, which
// runs constructors/destructors on AVR.
if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,
Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHF
: llvm::Triple::GNUEABI);
break;
case llvm::Triple::GNUEABIT64:
case llvm::Triple::GNUEABIHFT64:
Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHFT64
: llvm::Triple::GNUEABIT64);
break;
case llvm::Triple::EABI:
case llvm::Triple::EABIHF:
Triple.setEnvironment(isHardFloat ? llvm::Triple::EABIHF
Expand Down Expand Up @@ -414,10 +419,12 @@ arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
return FloatABI::Soft;
switch (Triple.getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABIHF:
case llvm::Triple::EABIHF:
return FloatABI::Hard;
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIT64:
case llvm::Triple::MuslEABI:
case llvm::Triple::EABI:
// EABI is always AAPCS, and if it was not marked 'hard', it's softfp
Expand Down
51 changes: 6 additions & 45 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,24 +94,6 @@ static void CheckCodeGenerationOptions(const Driver &D, const ArgList &Args) {
<< "-static";
}

// Add backslashes to escape spaces and other backslashes.
// This is used for the space-separated argument list specified with
// the -dwarf-debug-flags option.
static void EscapeSpacesAndBackslashes(const char *Arg,
SmallVectorImpl<char> &Res) {
for (; *Arg; ++Arg) {
switch (*Arg) {
default:
break;
case ' ':
case '\\':
Res.push_back('\\');
break;
}
Res.push_back(*Arg);
}
}

/// Apply \a Work on the current tool chain \a RegularToolChain and any other
/// offloading tool chain that is associated with the current action \a JA.
static void
Expand Down Expand Up @@ -7724,31 +7706,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Also record command line arguments into the debug info if
// -grecord-gcc-switches options is set on.
// By default, -gno-record-gcc-switches is set on and no recording.
auto GRecordSwitches =
Args.hasFlag(options::OPT_grecord_command_line,
options::OPT_gno_record_command_line, false);
auto FRecordSwitches =
Args.hasFlag(options::OPT_frecord_command_line,
options::OPT_fno_record_command_line, false);
if (FRecordSwitches && !Triple.isOSBinFormatELF() &&
!Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
<< TripleStr;
if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) {
ArgStringList OriginalArgs;
for (const auto &Arg : Args)
Arg->render(Args, OriginalArgs);

SmallString<256> Flags;
EscapeSpacesAndBackslashes(Exec, Flags);
for (const char *OriginalArg : OriginalArgs) {
SmallString<128> EscapedArg;
EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
Flags += " ";
Flags += EscapedArg;
}
auto FlagsArgString = Args.MakeArgString(Flags);
auto GRecordSwitches = false;
auto FRecordSwitches = false;
if (shouldRecordCommandLine(TC, Args, FRecordSwitches, GRecordSwitches)) {
auto FlagsArgString = renderEscapedCommandLine(TC, Args);
if (TC.UseDwarfDebugFlags() || GRecordSwitches) {
CmdArgs.push_back("-dwarf-debug-flags");
CmdArgs.push_back(FlagsArgString);
Expand Down Expand Up @@ -8748,10 +8709,10 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,

SmallString<256> Flags;
const char *Exec = getToolChain().getDriver().getClangProgramPath();
EscapeSpacesAndBackslashes(Exec, Flags);
escapeSpacesAndBackslashes(Exec, Flags);
for (const char *OriginalArg : OriginalArgs) {
SmallString<128> EscapedArg;
EscapeSpacesAndBackslashes(OriginalArg, EscapedArg);
escapeSpacesAndBackslashes(OriginalArg, EscapedArg);
Flags += " ";
Flags += EscapedArg;
}
Expand Down
59 changes: 59 additions & 0 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2979,3 +2979,62 @@ void tools::handleColorDiagnosticsArgs(const Driver &D, const ArgList &Args,
if (D.getDiags().getDiagnosticOptions().ShowColors)
CmdArgs.push_back("-fcolor-diagnostics");
}

void tools::escapeSpacesAndBackslashes(const char *Arg,
llvm::SmallVectorImpl<char> &Res) {
for (; *Arg; ++Arg) {
switch (*Arg) {
default:
break;
case ' ':
case '\\':
Res.push_back('\\');
break;
}
Res.push_back(*Arg);
}
}

const char *tools::renderEscapedCommandLine(const ToolChain &TC,
const llvm::opt::ArgList &Args) {
const Driver &D = TC.getDriver();
const char *Exec = D.getClangProgramPath();

llvm::opt::ArgStringList OriginalArgs;
for (const auto &Arg : Args)
Arg->render(Args, OriginalArgs);

llvm::SmallString<256> Flags;
escapeSpacesAndBackslashes(Exec, Flags);
for (const char *OriginalArg : OriginalArgs) {
llvm::SmallString<128> EscapedArg;
escapeSpacesAndBackslashes(OriginalArg, EscapedArg);
Flags += " ";
Flags += EscapedArg;
}

return Args.MakeArgString(Flags);
}

bool tools::shouldRecordCommandLine(const ToolChain &TC,
const llvm::opt::ArgList &Args,
bool &FRecordCommandLine,
bool &GRecordCommandLine) {
const Driver &D = TC.getDriver();
const llvm::Triple &Triple = TC.getEffectiveTriple();
const std::string &TripleStr = Triple.getTriple();

FRecordCommandLine =
Args.hasFlag(options::OPT_frecord_command_line,
options::OPT_fno_record_command_line, false);
GRecordCommandLine =
Args.hasFlag(options::OPT_grecord_command_line,
options::OPT_gno_record_command_line, false);
if (FRecordCommandLine && !Triple.isOSBinFormatELF() &&
!Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO())
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
<< TripleStr;

return FRecordCommandLine || TC.UseDwarfDebugFlags() || GRecordCommandLine;
}
25 changes: 25 additions & 0 deletions clang/lib/Driver/ToolChains/CommonArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,31 @@ void addMCModel(const Driver &D, const llvm::opt::ArgList &Args,
void handleColorDiagnosticsArgs(const Driver &D, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);

/// Add backslashes to escape spaces and other backslashes.
/// This is used for the space-separated argument list specified with
/// the -dwarf-debug-flags option.
void escapeSpacesAndBackslashes(const char *Arg,
llvm::SmallVectorImpl<char> &Res);

/// Join the args in the given ArgList, escape spaces and backslashes and
/// return the joined string. This is used when saving the command line as a
/// result of using either the -frecord-command-line or -grecord-command-line
/// options. The lifetime of the returned c-string will match that of the Args
/// argument.
const char *renderEscapedCommandLine(const ToolChain &TC,
const llvm::opt::ArgList &Args);

/// Check if the command line should be recorded in the object file. This is
/// done if either -frecord-command-line or -grecord-command-line options have
/// been passed. This also does some error checking since -frecord-command-line
/// is currently only supported on ELF platforms. The last two boolean
/// arguments are out parameters and will be set depending on the command
/// line options that were passed.
bool shouldRecordCommandLine(const ToolChain &TC,
const llvm::opt::ArgList &Args,
bool &FRecordCommandLine,
bool &GRecordCommandLine);

} // end namespace tools
} // end namespace driver
} // end namespace clang
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Driver/ToolChains/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ CudaVersion getCudaVersion(uint32_t raw_version) {
return CudaVersion::CUDA_124;
if (raw_version < 12060)
return CudaVersion::CUDA_125;
if (raw_version < 12070)
return CudaVersion::CUDA_126;
return CudaVersion::NEW;
}

Expand Down Expand Up @@ -669,6 +671,7 @@ void NVPTX::getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple,
case CudaVersion::CUDA_##CUDA_VER: \
PtxFeature = "+ptx" #PTX_VER; \
break;
CASE_CUDA_VERSION(126, 85);
CASE_CUDA_VERSION(125, 85);
CASE_CUDA_VERSION(124, 84);
CASE_CUDA_VERSION(123, 83);
Expand All @@ -691,6 +694,10 @@ void NVPTX::getNVPTXTargetFeatures(const Driver &D, const llvm::Triple &Triple,
CASE_CUDA_VERSION(91, 61);
CASE_CUDA_VERSION(90, 60);
#undef CASE_CUDA_VERSION
// TODO: Use specific CUDA version once it's public.
case clang::CudaVersion::NEW:
PtxFeature = "+ptx86";
break;
default:
PtxFeature = "+ptx42";
}
Expand Down
23 changes: 19 additions & 4 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,

if (Args.hasArg(options::OPT_fopenmp_force_usm))
CmdArgs.push_back("-fopenmp-force-usm");
// TODO: OpenMP support isn't "done" yet, so for now we warn that it
// is experimental.
D.Diag(diag::warn_openmp_experimental);

// FIXME: Clang supports a whole bunch more flags here.
break;
Expand Down Expand Up @@ -879,16 +882,28 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,

addDashXForInput(Args, Input, CmdArgs);

bool FRecordCmdLine = false;
bool GRecordCmdLine = false;
if (shouldRecordCommandLine(TC, Args, FRecordCmdLine, GRecordCmdLine)) {
const char *CmdLine = renderEscapedCommandLine(TC, Args);
if (FRecordCmdLine) {
CmdArgs.push_back("-record-command-line");
CmdArgs.push_back(CmdLine);
}
if (TC.UseDwarfDebugFlags() || GRecordCmdLine) {
CmdArgs.push_back("-dwarf-debug-flags");
CmdArgs.push_back(CmdLine);
}
}

CmdArgs.push_back(Input.getFilename());

// TODO: Replace flang-new with flang once the new driver replaces the
// throwaway driver
const char *Exec = Args.MakeArgString(D.GetProgramPath("flang-new", TC));
const char *Exec = Args.MakeArgString(D.GetProgramPath("flang", TC));
C.addCommand(std::make_unique<Command>(JA, *this,
ResponseFileSupport::AtFileUTF8(),
Exec, CmdArgs, Inputs, Output));
}

Flang::Flang(const ToolChain &TC) : Tool("flang-new", "flang frontend", TC) {}
Flang::Flang(const ToolChain &TC) : Tool("flang", "flang frontend", TC) {}

Flang::~Flang() {}
4 changes: 3 additions & 1 deletion clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
}

Args.AddAllArgs(CmdArgs, options::OPT_T);
Args.addAllArgs(CmdArgs, {options::OPT_T, options::OPT_t});

const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
C.addCommand(std::make_unique<Command>(JA, *this,
Expand Down Expand Up @@ -2698,6 +2698,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
case llvm::Triple::thumb:
LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
TripleAliases.append(begin(ARMHFTriples), end(ARMHFTriples));
Expand All @@ -2709,6 +2710,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
case llvm::Triple::thumbeb:
LibDirs.append(begin(ARMebLibDirs), end(ARMebLibDirs));
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
TripleAliases.append(begin(ARMebHFTriples), end(ARMebHFTriples));
Expand Down
29 changes: 15 additions & 14 deletions clang/lib/Driver/ToolChains/HIPUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,21 +340,21 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
void HIP::constructGenerateObjFileFromHIPFatBinary(
Compilation &C, const InputInfo &Output, const InputInfoList &Inputs,
const ArgList &Args, const JobAction &JA, const Tool &T) {
const ToolChain &TC = T.getToolChain();
const Driver &D = C.getDriver();
std::string Name = std::string(llvm::sys::path::stem(Output.getFilename()));

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

// Open script file and write the contents.
std::error_code EC;
llvm::raw_fd_ostream Objf(McinFile, EC, llvm::sys::fs::OF_None);
llvm::raw_fd_ostream Objf(ObjinFile, EC, llvm::sys::fs::OF_None);

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

Objf << ObjBuffer;

ArgStringList McArgs{"-triple", Args.MakeArgString(HostTriple.normalize()),
ArgStringList McArgs{"-target", Args.MakeArgString(HostTriple.normalize()),
"-o", Output.getFilename(),
McinFile, "--filetype=obj"};
const char *Mc = Args.MakeArgString(TC.GetProgramPath("llvm-mc"));
C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(), Mc,
McArgs, Inputs, Output));
"-x", "assembler",
ObjinFile, "-c"};
C.addCommand(std::make_unique<Command>(JA, T, ResponseFileSupport::None(),
D.getClangProgramPath(), McArgs,
Inputs, Output, D.getPrependArg()));
}
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
case llvm::Triple::thumbeb: {
const bool HF =
Triple.getEnvironment() == llvm::Triple::GNUEABIHF ||
Triple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard;

LibDir = "lib";
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/WebAssembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ void wasm::Linker::ConstructJob(Compilation &C, const JobAction &JA,
AddRunTimeLibs(ToolChain, ToolChain.getDriver(), CmdArgs, Args);
}

ToolChain.addProfileRTLibs(Args, CmdArgs);

CmdArgs.push_back("-o");
CmdArgs.push_back(Output.getFilename());

Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Format/BreakableToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ BreakableComment::getSplit(unsigned LineIndex, unsigned TailOffset,
unsigned ColumnLimit, unsigned ContentStartColumn,
const llvm::Regex &CommentPragmasRegex) const {
// Don't break lines matching the comment pragmas regex.
if (CommentPragmasRegex.match(Content[LineIndex]))
if (!AlwaysReflow || CommentPragmasRegex.match(Content[LineIndex]))
return Split(StringRef::npos, 0);
return getCommentSplit(Content[LineIndex].substr(TailOffset),
ContentStartColumn, ColumnLimit, Style.TabWidth,
Expand Down Expand Up @@ -608,7 +608,7 @@ BreakableToken::Split BreakableBlockComment::getSplit(
unsigned LineIndex, unsigned TailOffset, unsigned ColumnLimit,
unsigned ContentStartColumn, const llvm::Regex &CommentPragmasRegex) const {
// Don't break lines matching the comment pragmas regex.
if (CommentPragmasRegex.match(Content[LineIndex]))
if (!AlwaysReflow || CommentPragmasRegex.match(Content[LineIndex]))
return Split(StringRef::npos, 0);
return getCommentSplit(Content[LineIndex].substr(TailOffset),
ContentStartColumn, ColumnLimit, Style.TabWidth,
Expand Down Expand Up @@ -855,7 +855,8 @@ bool BreakableBlockComment::mayReflow(
StringRef IndentContent = Content[LineIndex];
if (Lines[LineIndex].ltrim(Blanks).starts_with("*"))
IndentContent = Lines[LineIndex].ltrim(Blanks).substr(1);
return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
return LineIndex > 0 && AlwaysReflow &&
!CommentPragmasRegex.match(IndentContent) &&
mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
!switchesFormatting(tokenAt(LineIndex));
}
Expand Down Expand Up @@ -1160,7 +1161,8 @@ bool BreakableLineCommentSection::mayReflow(
// // text that protrudes
// // into text with different indent
// We do reflow in that case in block comments.
return LineIndex > 0 && !CommentPragmasRegex.match(IndentContent) &&
return LineIndex > 0 && AlwaysReflow &&
!CommentPragmasRegex.match(IndentContent) &&
mayReflowContent(Content[LineIndex]) && !Tok.Finalized &&
!switchesFormatting(tokenAt(LineIndex)) &&
OriginalPrefix[LineIndex] == OriginalPrefix[LineIndex - 1];
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Format/BreakableToken.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,8 @@ class BreakableComment : public BreakableToken {
// The intended start column of the first line of text from this section.
unsigned StartColumn;

const bool AlwaysReflow = Style.ReflowComments == FormatStyle::RCS_Always;

// The prefix to use in front a line that has been reflown up.
// For example, when reflowing the second line after the first here:
// // comment 1
Expand Down
Loading