452 changes: 452 additions & 0 deletions clang/lib/AST/DynamicRecursiveASTVisitor.cpp

Large diffs are not rendered by default.

18 changes: 13 additions & 5 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
Expand Down Expand Up @@ -4774,7 +4775,10 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
->getTemplateName()
.getAsTemplateDecl())
if (auto *CTD = dyn_cast<ClassTemplateDecl>(templateDecl))
return CTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
return llvm::any_of(
CTD->redecls(), [](const RedeclarableTemplateDecl *RTD) {
return RTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
});
return ResultIfUnknown;

case Type::Builtin:
Expand Down Expand Up @@ -4841,10 +4845,14 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
// For template specializations, look only at primary template attributes.
// This is a consistent regardless of whether the instantiation is known.
if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
return CTSD->getSpecializedTemplate()
->getTemplatedDecl()
->hasAttr<TypeNullableAttr>();
return RD->hasAttr<TypeNullableAttr>();
return llvm::any_of(
CTSD->getSpecializedTemplate()->redecls(),
[](const RedeclarableTemplateDecl *RTD) {
return RTD->getTemplatedDecl()->hasAttr<TypeNullableAttr>();
});
return llvm::any_of(RD->redecls(), [](const TagDecl *RD) {
return RD->hasAttr<TypeNullableAttr>();
});
}

// Non-pointer types.
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Basic/DiagnosticIDs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,12 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
DiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
Result = diag::Severity::Error;

// Rest of the mappings are only applicable for diagnostics associated with a
// SourceLocation, bail out early for others.
if (!Diag.hasSourceManager())
return Result;

const auto &SM = Diag.getSourceManager();
// Custom diagnostics always are emitted in system headers.
bool ShowInSystemHeader =
!GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
Expand All @@ -583,15 +589,14 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
// because we also want to ignore extensions and warnings in -Werror and
// -pedantic-errors modes, which *map* warnings/extensions to errors.
if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
Diag.getSourceManager().isInSystemHeader(
Diag.getSourceManager().getExpansionLoc(Loc)))
SM.isInSystemHeader(SM.getExpansionLoc(Loc)))
return diag::Severity::Ignored;

// We also ignore warnings due to system macros
bool ShowInSystemMacro =
!GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro;
if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() &&
Diag.getSourceManager().isInSystemMacro(Loc))
SM.isInSystemMacro(Loc))
return diag::Severity::Ignored;

return Result;
Expand Down
16 changes: 8 additions & 8 deletions clang/lib/Basic/Targets/SPIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo {

// SPIR-V IDs are represented with a single 32-bit word.
SizeType = TargetInfo::UnsignedInt;
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
"v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand All @@ -334,8 +334,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo {
// SPIR-V has core support for atomic ops, and Int32 is always available;
// we take the maximum because it's possible the Host supports wider types.
MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 32);
resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
resetDataLayout("e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-"
"v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand All @@ -358,8 +358,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo {
// SPIR-V has core support for atomic ops, and Int64 is always available;
// we take the maximum because it's possible the Host supports wider types.
MaxAtomicInlineWidth = std::max<unsigned char>(MaxAtomicInlineWidth, 64);
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
"v256:256-v512:512-v1024:1024-n8:16:32:64-G1");
}

void getTargetDefines(const LangOptions &Opts,
Expand All @@ -384,8 +384,8 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final
PtrDiffType = IntPtrType = TargetInfo::SignedLong;
AddrSpaceMap = &SPIRDefIsGenMap;

resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1-P4-A0");
resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-"
"v256:256-v512:512-v1024:1024-n32:64-S32-G1-P4-A0");

BFloat16Width = BFloat16Align = 16;
BFloat16Format = &llvm::APFloat::BFloat();
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Basic/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,8 @@ bool X86TargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
HasAMXCOMPLEX = true;
} else if (Feature == "+amx-fp8") {
HasAMXFP8 = true;
} else if (Feature == "+amx-transpose") {
HasAMXTRANSPOSE = true;
} else if (Feature == "+cmpccxadd") {
HasCMPCCXADD = true;
} else if (Feature == "+raoint") {
Expand Down Expand Up @@ -951,6 +953,8 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__AMX_COMPLEX__");
if (HasAMXFP8)
Builder.defineMacro("__AMX_FP8__");
if (HasAMXTRANSPOSE)
Builder.defineMacro("__AMX_TRANSPOSE__");
if (HasCMPCCXADD)
Builder.defineMacro("__CMPCCXADD__");
if (HasRAOINT)
Expand Down Expand Up @@ -1079,9 +1083,10 @@ bool X86TargetInfo::isValidFeatureName(StringRef Name) const {
.Case("amx-bf16", true)
.Case("amx-complex", true)
.Case("amx-fp16", true)
.Case("amx-fp8", true)
.Case("amx-int8", true)
.Case("amx-tile", true)
.Case("amx-fp8", true)
.Case("amx-transpose", true)
.Case("avx", true)
.Case("avx10.1-256", true)
.Case("avx10.1-512", true)
Expand Down Expand Up @@ -1198,9 +1203,10 @@ bool X86TargetInfo::hasFeature(StringRef Feature) const {
.Case("amx-bf16", HasAMXBF16)
.Case("amx-complex", HasAMXCOMPLEX)
.Case("amx-fp16", HasAMXFP16)
.Case("amx-fp8", HasAMXFP8)
.Case("amx-int8", HasAMXINT8)
.Case("amx-tile", HasAMXTILE)
.Case("amx-fp8", HasAMXFP8)
.Case("amx-transpose", HasAMXTRANSPOSE)
.Case("avx", SSELevel >= AVX)
.Case("avx10.1-256", HasAVX10_1)
.Case("avx10.1-512", HasAVX10_1_512)
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/X86.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
bool HasAMXBF16 = false;
bool HasAMXCOMPLEX = false;
bool HasAMXFP8 = false;
bool HasAMXTRANSPOSE = false;
bool HasSERIALIZE = false;
bool HasTSXLDTRK = false;
bool HasUSERMSR = false;
Expand Down
25 changes: 14 additions & 11 deletions clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,

// Ensure we lower KCFI operand bundles with -O0.
PB.registerOptimizerLastEPCallback(
[&](ModulePassManager &MPM, OptimizationLevel Level) {
[&](ModulePassManager &MPM, OptimizationLevel Level, ThinOrFullLTOPhase) {
if (Level == OptimizationLevel::O0 &&
LangOpts.Sanitize.has(SanitizerKind::KCFI))
MPM.addPass(createModuleToFunctionPassAdaptor(KCFIPass()));
Expand All @@ -693,8 +693,8 @@ static void addKCFIPass(const Triple &TargetTriple, const LangOptions &LangOpts,
static void addSanitizers(const Triple &TargetTriple,
const CodeGenOptions &CodeGenOpts,
const LangOptions &LangOpts, PassBuilder &PB) {
auto SanitizersCallback = [&](ModulePassManager &MPM,
OptimizationLevel Level) {
auto SanitizersCallback = [&](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase) {
if (CodeGenOpts.hasSanitizeCoverage()) {
auto SancovOpts = getSancovOptsFromCGOpts(CodeGenOpts);
MPM.addPass(SanitizerCoveragePass(
Expand Down Expand Up @@ -778,9 +778,10 @@ static void addSanitizers(const Triple &TargetTriple,
};
if (ClSanitizeOnOptimizerEarlyEP) {
PB.registerOptimizerEarlyEPCallback(
[SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level) {
[SanitizersCallback](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase Phase) {
ModulePassManager NewMPM;
SanitizersCallback(NewMPM, Level);
SanitizersCallback(NewMPM, Level, Phase);
if (!NewMPM.isEmpty()) {
// Sanitizers can abandon<GlobalsAA>.
NewMPM.addPass(RequireAnalysisPass<GlobalsAA, llvm::Module>());
Expand Down Expand Up @@ -993,7 +994,8 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
createModuleToFunctionPassAdaptor(ObjCARCExpandPass()));
});
PB.registerPipelineEarlySimplificationEPCallback(
[](ModulePassManager &MPM, OptimizationLevel Level) {
[](ModulePassManager &MPM, OptimizationLevel Level,
ThinOrFullLTOPhase) {
if (Level != OptimizationLevel::O0)
MPM.addPass(ObjCARCAPElimPass());
});
Expand Down Expand Up @@ -1057,11 +1059,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
// TODO: Consider passing the MemoryProfileOutput to the pass builder via
// the PGOOptions, and set this up there.
if (!CodeGenOpts.MemoryProfileOutput.empty()) {
PB.registerOptimizerLastEPCallback(
[](ModulePassManager &MPM, OptimizationLevel Level) {
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
MPM.addPass(ModuleMemProfilerPass());
});
PB.registerOptimizerLastEPCallback([](ModulePassManager &MPM,
OptimizationLevel Level,
ThinOrFullLTOPhase) {
MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass()));
MPM.addPass(ModuleMemProfilerPass());
});
}

if (CodeGenOpts.FatLTO) {
Expand Down
64 changes: 63 additions & 1 deletion clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16994,6 +16994,58 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
// instruction, but it will create a memset that won't be optimized away.
return Builder.CreateMemSet(Ops[0], Ops[1], Ops[2], Align(1), true);
}
// Corresponding to intrisics which will return 2 tiles (tile0_tile1).
case X86::BI__builtin_ia32_t2rpntlvwz0_internal:
case X86::BI__builtin_ia32_t2rpntlvwz0t1_internal:
case X86::BI__builtin_ia32_t2rpntlvwz1_internal:
case X86::BI__builtin_ia32_t2rpntlvwz1t1_internal: {
Intrinsic::ID IID;
switch (BuiltinID) {
default:
llvm_unreachable("Unsupported intrinsic!");
case X86::BI__builtin_ia32_t2rpntlvwz0_internal:
IID = Intrinsic::x86_t2rpntlvwz0_internal;
break;
case X86::BI__builtin_ia32_t2rpntlvwz0t1_internal:
IID = Intrinsic::x86_t2rpntlvwz0t1_internal;
break;
case X86::BI__builtin_ia32_t2rpntlvwz1_internal:
IID = Intrinsic::x86_t2rpntlvwz1_internal;
break;
case X86::BI__builtin_ia32_t2rpntlvwz1t1_internal:
IID = Intrinsic::x86_t2rpntlvwz1t1_internal;
break;
}

// Ops = (Row0, Col0, Col1, DstPtr0, DstPtr1, SrcPtr, Stride)
Value *Call = Builder.CreateCall(CGM.getIntrinsic(IID),
{Ops[0], Ops[1], Ops[2], Ops[5], Ops[6]});

auto *PtrTy = E->getArg(3)->getType()->getAs<PointerType>();
assert(PtrTy && "arg3 must be of pointer type");
QualType PtreeTy = PtrTy->getPointeeType();
llvm::Type *TyPtee = ConvertType(PtreeTy);

// Bitcast amx type (x86_amx) to vector type (256 x i32)
// Then store tile0 into DstPtr0
Value *T0 = Builder.CreateExtractValue(Call, 0);
Value *VecT0 = Builder.CreateIntrinsic(Intrinsic::x86_cast_tile_to_vector,
{TyPtee}, {T0});
Builder.CreateDefaultAlignedStore(VecT0, Ops[3]);

// Then store tile1 into DstPtr1
Value *T1 = Builder.CreateExtractValue(Call, 1);
Value *VecT1 = Builder.CreateIntrinsic(Intrinsic::x86_cast_tile_to_vector,
{TyPtee}, {T1});
Value *Store = Builder.CreateDefaultAlignedStore(VecT1, Ops[4]);

// Note: Here we escape directly use x86_tilestored64_internal to store
// the results due to it can't make sure the Mem written scope. This may
// cause shapes reloads after first amx intrinsic, which current amx reg-
// ister allocation has no ability to handle it.

return Store;
}
case X86::BI__ud2:
// llvm.trap makes a ud2a instruction on x86.
return EmitTrapCall(Intrinsic::trap);
Expand Down Expand Up @@ -18803,7 +18855,17 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
/*ReturnType=*/T0->getScalarType(),
getDotProductIntrinsic(CGM.getHLSLRuntime(), VecTy0->getElementType()),
ArrayRef<Value *>{Op0, Op1}, nullptr, "hlsl.dot");
} break;
}
case Builtin::BI__builtin_hlsl_dot4add_i8packed: {
Value *A = EmitScalarExpr(E->getArg(0));
Value *B = EmitScalarExpr(E->getArg(1));
Value *C = EmitScalarExpr(E->getArg(2));

Intrinsic::ID ID = CGM.getHLSLRuntime().getDot4AddI8PackedIntrinsic();
return Builder.CreateIntrinsic(
/*ReturnType=*/C->getType(), ID, ArrayRef<Value *>{A, B, C}, nullptr,
"hlsl.dot4add.i8packed");
}
case Builtin::BI__builtin_hlsl_lerp: {
Value *X = EmitScalarExpr(E->getArg(0));
Value *Y = EmitScalarExpr(E->getArg(1));
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,10 @@ bool CodeGenFunction::EmitScalarRangeCheck(llvm::Value *Value, QualType Ty,
cast<llvm::IntegerType>(Value->getType())->getBitWidth() == 1)
return false;

if (NeedsEnumCheck &&
getContext().isTypeIgnoredBySanitizer(SanitizerKind::Enum, Ty))
return false;

llvm::APInt Min, End;
if (!getRangeForType(*this, Ty, Min, End, /*StrictEnums=*/true, IsBool))
return true;
Expand Down
36 changes: 32 additions & 4 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,18 @@ static bool CanElideOverflowCheck(const ASTContext &Ctx, const BinOpInfo &Op) {
if (!Op.mayHaveIntegerOverflow())
return true;

if (Op.Ty->isSignedIntegerType() &&
Ctx.isTypeIgnoredBySanitizer(SanitizerKind::SignedIntegerOverflow,
Op.Ty)) {
return true;
}

if (Op.Ty->isUnsignedIntegerType() &&
Ctx.isTypeIgnoredBySanitizer(SanitizerKind::UnsignedIntegerOverflow,
Op.Ty)) {
return true;
}

const UnaryOperator *UO = dyn_cast<UnaryOperator>(Op.E);

if (UO && UO->getOpcode() == UO_Minus &&
Expand Down Expand Up @@ -1125,6 +1137,10 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
if (!CGF.SanOpts.has(Check.second.second))
return;

// Does some SSCL ignore this type?
if (CGF.getContext().isTypeIgnoredBySanitizer(Check.second.second, DstType))
return;

llvm::Constant *StaticArgs[] = {
CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
CGF.EmitCheckTypeDescriptor(DstType),
Expand Down Expand Up @@ -1235,6 +1251,15 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
// Because here sign change check is interchangeable with truncation check.
return;
}
// Does an SSCL have an entry for the DstType under its respective sanitizer
// section?
if (DstSigned && CGF.getContext().isTypeIgnoredBySanitizer(
SanitizerKind::ImplicitSignedIntegerTruncation, DstType))
return;
if (!DstSigned &&
CGF.getContext().isTypeIgnoredBySanitizer(
SanitizerKind::ImplicitUnsignedIntegerTruncation, DstType))
return;
// That's it. We can't rule out any more cases with the data we have.

CodeGenFunction::SanitizerScope SanScope(&CGF);
Expand Down Expand Up @@ -2784,10 +2809,11 @@ llvm::Value *ScalarExprEmitter::EmitIncDecConsiderOverflowBehavior(
return Builder.CreateNSWAdd(InVal, Amount, Name);
[[fallthrough]];
case LangOptions::SOB_Trapping:
if (!E->canOverflow())
BinOpInfo Info = createBinOpInfoFromIncDec(
E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts()));
if (!E->canOverflow() || CanElideOverflowCheck(CGF.getContext(), Info))
return Builder.CreateNSWAdd(InVal, Amount, Name);
return EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
E, InVal, IsInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
return EmitOverflowCheckedBinOp(Info);
}
llvm_unreachable("Unknown SignedOverflowBehaviorTy");
}
Expand Down Expand Up @@ -2990,7 +3016,9 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
value = EmitIncDecConsiderOverflowBehavior(E, value, isInc);
} else if (E->canOverflow() && type->isUnsignedIntegerType() &&
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow) &&
!excludeOverflowPattern) {
!excludeOverflowPattern &&
!CGF.getContext().isTypeIgnoredBySanitizer(
SanitizerKind::UnsignedIntegerOverflow, E->getType())) {
value = EmitOverflowCheckedBinOp(createBinOpInfoFromIncDec(
E, value, isInc, E->getFPFeaturesInEffect(CGF.getLangOpts())));
} else {
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 @@ -89,6 +89,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(FDot, fdot)
GENERATE_HLSL_INTRINSIC_FUNCTION(SDot, sdot)
GENERATE_HLSL_INTRINSIC_FUNCTION(UDot, udot)
GENERATE_HLSL_INTRINSIC_FUNCTION(Dot4AddI8Packed, dot4add_i8packed)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveIsFirstLane, wave_is_first_lane)
GENERATE_HLSL_INTRINSIC_FUNCTION(WaveReadLaneAt, wave_readlane)

Expand Down
28 changes: 12 additions & 16 deletions clang/lib/CodeGen/CGObjCMac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ class ObjCCommonTypesHelper {
/// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
llvm::FunctionCallee getGcReadWeakFn() {
// id objc_read_weak (id *)
llvm::Type *args[] = { ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
Expand All @@ -374,7 +374,7 @@ class ObjCCommonTypesHelper {
/// GcAssignWeakFn -- LLVM objc_assign_weak function.
llvm::FunctionCallee getGcAssignWeakFn() {
// id objc_assign_weak (id, id *)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
Expand All @@ -383,7 +383,7 @@ class ObjCCommonTypesHelper {
/// GcAssignGlobalFn -- LLVM objc_assign_global function.
llvm::FunctionCallee getGcAssignGlobalFn() {
// id objc_assign_global(id, id *)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
Expand All @@ -392,7 +392,7 @@ class ObjCCommonTypesHelper {
/// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
llvm::FunctionCallee getGcAssignThreadLocalFn() {
// id objc_assign_threadlocal(id src, id * dest)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
Expand All @@ -401,8 +401,7 @@ class ObjCCommonTypesHelper {
/// GcAssignIvarFn -- LLVM objc_assign_ivar function.
llvm::FunctionCallee getGcAssignIvarFn() {
// id objc_assign_ivar(id, id *, ptrdiff_t)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo(),
CGM.PtrDiffTy };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy, CGM.PtrDiffTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
Expand All @@ -419,7 +418,7 @@ class ObjCCommonTypesHelper {
/// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
llvm::FunctionCallee getGcAssignStrongCastFn() {
// id objc_assign_strongCast(id, id *)
llvm::Type *args[] = { ObjectPtrTy, ObjectPtrTy->getPointerTo() };
llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
llvm::FunctionType *FTy =
llvm::FunctionType::get(ObjectPtrTy, args, false);
return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
Expand Down Expand Up @@ -554,23 +553,23 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper {

/// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
llvm::FunctionCallee getExceptionTryEnterFn() {
llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
llvm::Type *params[] = {CGM.UnqualPtrTy};
return CGM.CreateRuntimeFunction(
llvm::FunctionType::get(CGM.VoidTy, params, false),
"objc_exception_try_enter");
}

/// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
llvm::FunctionCallee getExceptionTryExitFn() {
llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
llvm::Type *params[] = {CGM.UnqualPtrTy};
return CGM.CreateRuntimeFunction(
llvm::FunctionType::get(CGM.VoidTy, params, false),
"objc_exception_try_exit");
}

/// ExceptionExtractFn - LLVM objc_exception_extract function.
llvm::FunctionCallee getExceptionExtractFn() {
llvm::Type *params[] = { ExceptionDataTy->getPointerTo() };
llvm::Type *params[] = {CGM.UnqualPtrTy};
return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
params, false),
"objc_exception_extract");
Expand All @@ -587,7 +586,7 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper {
/// SetJmpFn - LLVM _setjmp function.
llvm::FunctionCallee getSetJmpFn() {
// This is specifically the prototype for x86.
llvm::Type *params[] = { CGM.Int32Ty->getPointerTo() };
llvm::Type *params[] = {CGM.UnqualPtrTy};
return CGM.CreateRuntimeFunction(
llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp",
llvm::AttributeList::get(CGM.getLLVMContext(),
Expand Down Expand Up @@ -6051,9 +6050,7 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul
Int8PtrTy, PropertyListPtrTy);

// ImpnfABITy - LLVM for id (*)(id, SEL, ...)
llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy };
ImpnfABITy = llvm::FunctionType::get(ObjectPtrTy, params, false)
->getPointerTo();
ImpnfABITy = CGM.UnqualPtrTy;

// struct _class_t {
// struct _class_t *isa;
Expand Down Expand Up @@ -6469,8 +6466,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
llvm::GlobalValue::ExternalLinkage, nullptr,
"_objc_empty_vtable");
else
ObjCEmptyVtableVar =
llvm::ConstantPointerNull::get(ObjCTypes.ImpnfABITy->getPointerTo());
ObjCEmptyVtableVar = llvm::ConstantPointerNull::get(CGM.UnqualPtrTy);
}

// FIXME: Is this correct (that meta class size is never computed)?
Expand Down
79 changes: 79 additions & 0 deletions clang/lib/CodeGen/Targets/SPIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {

unsigned getOpenCLKernelCallingConv() const override;
llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override;
llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *Ty) const override;
llvm::Type *getSPIRVImageTypeFromHLSLResource(
const HLSLAttributedResourceType::Attributes &attributes,
llvm::Type *ElementType, llvm::LLVMContext &Ctx) const;
};
class SPIRVTargetCodeGenInfo : public CommonSPIRTargetCodeGenInfo {
public:
Expand Down Expand Up @@ -323,6 +327,81 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getOpenCLType(CodeGenModule &CGM,
return nullptr;
}

llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM,
const Type *Ty) const {
auto *ResType = dyn_cast<HLSLAttributedResourceType>(Ty);
if (!ResType)
return nullptr;

llvm::LLVMContext &Ctx = CGM.getLLVMContext();
const HLSLAttributedResourceType::Attributes &ResAttrs = ResType->getAttrs();
switch (ResAttrs.ResourceClass) {
case llvm::dxil::ResourceClass::UAV:
case llvm::dxil::ResourceClass::SRV: {
// TypedBuffer and RawBuffer both need element type
QualType ContainedTy = ResType->getContainedType();
if (ContainedTy.isNull())
return nullptr;

assert(!ResAttrs.RawBuffer &&
"Raw buffers handles are not implemented for SPIR-V yet");
assert(!ResAttrs.IsROV &&
"Rasterizer order views not implemented for SPIR-V yet");

// convert element type
llvm::Type *ElemType = CGM.getTypes().ConvertType(ContainedTy);
return getSPIRVImageTypeFromHLSLResource(ResAttrs, ElemType, Ctx);
}
case llvm::dxil::ResourceClass::CBuffer:
llvm_unreachable("CBuffer handles are not implemented for SPIR-V yet");
break;
case llvm::dxil::ResourceClass::Sampler:
return llvm::TargetExtType::get(Ctx, "spirv.Sampler");
}
return nullptr;
}

llvm::Type *CommonSPIRTargetCodeGenInfo::getSPIRVImageTypeFromHLSLResource(
const HLSLAttributedResourceType::Attributes &attributes,
llvm::Type *ElementType, llvm::LLVMContext &Ctx) const {

if (ElementType->isVectorTy())
ElementType = ElementType->getScalarType();

assert((ElementType->isIntegerTy() || ElementType->isFloatingPointTy()) &&
"The element type for a SPIR-V resource must be a scalar integer or "
"floating point type.");

// These parameters correspond to the operands to the OpTypeImage SPIR-V
// instruction. See
// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpTypeImage.
SmallVector<unsigned, 6> IntParams(6, 0);

// Dim
// For now we assume everything is a buffer.
IntParams[0] = 5;

// Depth
// HLSL does not indicate if it is a depth texture or not, so we use unknown.
IntParams[1] = 2;

// Arrayed
IntParams[2] = 0;

// MS
IntParams[3] = 0;

// Sampled
IntParams[4] =
attributes.ResourceClass == llvm::dxil::ResourceClass::UAV ? 2 : 1;

// Image format.
// Setting to unknown for now.
IntParams[5] = 0;

return llvm::TargetExtType::get(Ctx, "spirv.Image", {ElementType}, IntParams);
}

std::unique_ptr<TargetCodeGenInfo>
CodeGen::createCommonSPIRTargetCodeGenInfo(CodeGenModule &CGM) {
return std::make_unique<CommonSPIRTargetCodeGenInfo>(CGM.getTypes());
Expand Down
23 changes: 11 additions & 12 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,9 @@ static std::optional<llvm::Triple>
getHIPOffloadTargetTriple(const Driver &D, const ArgList &Args) {
if (!Args.hasArg(options::OPT_offload_EQ)) {
auto OffloadArchs = Args.getAllArgValues(options::OPT_offload_arch_EQ);
if (llvm::is_contained(OffloadArchs, "amdgcnspirv")) {
if (OffloadArchs.size() == 1)
return llvm::Triple("spirv64-amd-amdhsa");
// Mixing specific & SPIR-V compilation is not supported for now.
D.Diag(diag::err_drv_only_one_offload_target_supported);
return std::nullopt;
}
if (llvm::is_contained(OffloadArchs, "amdgcnspirv") &&
OffloadArchs.size() == 1)
return llvm::Triple("spirv64-amd-amdhsa");
return llvm::Triple("amdgcn-amd-amdhsa"); // Default HIP triple.
}
auto TT = getOffloadTargetTriple(D, Args);
Expand Down Expand Up @@ -458,6 +454,7 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const {
// some build systems. We don't try to be complete here because we don't
// care to encourage this usage model.
if (A->getOption().matches(options::OPT_Wp_COMMA) &&
A->getNumValues() > 0 &&
(A->getValue(0) == StringRef("-MD") ||
A->getValue(0) == StringRef("-MMD"))) {
// Rewrite to -MD/-MMD along with -MF.
Expand Down Expand Up @@ -3477,9 +3474,11 @@ class OffloadingActionBuilder final {
llvm::StringMap<bool> Features;
// getHIPOffloadTargetTriple() is known to return valid value as it has
// been called successfully in the CreateOffloadingDeviceToolChains().
auto ArchStr = parseTargetID(
*getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs()), IdStr,
&Features);
auto T =
(IdStr == "amdgcnspirv")
? llvm::Triple("spirv64-amd-amdhsa")
: *getHIPOffloadTargetTriple(C.getDriver(), C.getInputArgs());
auto ArchStr = parseTargetID(T, IdStr, &Features);
if (!ArchStr) {
C.getDriver().Diag(clang::diag::err_drv_bad_target_id) << IdStr;
C.setContainsError();
Expand Down Expand Up @@ -4035,7 +4034,7 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
if (C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment() &&
LTOMode != LTOK_None &&
!Args.getLastArgValue(options::OPT_fuse_ld_EQ)
.equals_insensitive("lld"))
.starts_with_insensitive("lld"))
Diag(clang::diag::err_drv_lto_without_lld);

// If -dumpdir is not specified, give a default prefix derived from the link
Expand Down Expand Up @@ -5755,7 +5754,7 @@ InputInfoList Driver::BuildJobsForActionNoCache(
// We only have to generate a prefix for the host if this is not a top-level
// action.
std::string OffloadingPrefix = Action::GetOffloadingFileNamePrefix(
A->getOffloadingDeviceKind(), TC->getTriple().normalize(),
A->getOffloadingDeviceKind(), EffectiveTriple.normalize(),
/*CreatePrefixForHost=*/isa<OffloadPackagerJobAction>(A) ||
!(A->getOffloadingHostActiveKinds() == Action::OFK_None ||
AtTopLevel));
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,9 @@ bool ToolChain::needsProfileRT(const ArgList &Args) {
Args.hasArg(options::OPT_fprofile_instr_generate) ||
Args.hasArg(options::OPT_fprofile_instr_generate_EQ) ||
Args.hasArg(options::OPT_fcreate_profile) ||
Args.hasArg(options::OPT_forder_file_instrumentation);
Args.hasArg(options::OPT_forder_file_instrumentation) ||
Args.hasArg(options::OPT_fprofile_generate_cold_function_coverage) ||
Args.hasArg(options::OPT_fprofile_generate_cold_function_coverage_EQ);
}

bool ToolChain::needsGCovInstrumentation(const llvm::opt::ArgList &Args) {
Expand Down Expand Up @@ -1097,6 +1099,12 @@ std::string ToolChain::ComputeLLVMTriple(const ArgList &Args,
}
case llvm::Triple::aarch64_32:
return getTripleString();
case llvm::Triple::amdgcn: {
llvm::Triple Triple = getTriple();
if (Args.getLastArgValue(options::OPT_mcpu_EQ) == "amdgcnspirv")
Triple.setArch(llvm::Triple::ArchType::spirv64);
return Triple.getTriple();
}
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::thumb:
Expand Down
25 changes: 23 additions & 2 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,28 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C,
}
}

if (auto *ColdFuncCoverageArg = Args.getLastArg(
options::OPT_fprofile_generate_cold_function_coverage,
options::OPT_fprofile_generate_cold_function_coverage_EQ)) {
SmallString<128> Path(
ColdFuncCoverageArg->getOption().matches(
options::OPT_fprofile_generate_cold_function_coverage_EQ)
? ColdFuncCoverageArg->getValue()
: "");
llvm::sys::path::append(Path, "default_%m.profraw");
// FIXME: Idealy the file path should be passed through
// `-fprofile-instrument-path=`(InstrProfileOutput), however, this field is
// shared with other profile use path(see PGOOptions), we need to refactor
// PGOOptions to make it work.
CmdArgs.push_back("-mllvm");
CmdArgs.push_back(Args.MakeArgString(
Twine("--instrument-cold-function-only-path=") + Path));
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("--pgo-instrument-cold-function-only");
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("--pgo-function-entry-coverage");
}

Arg *PGOGenArg = nullptr;
if (PGOGenerateArg) {
assert(!CSPGOGenerateArg);
Expand Down Expand Up @@ -1185,8 +1207,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,

Args.addAllArgs(CmdArgs,
{options::OPT_D, options::OPT_U, options::OPT_I_Group,
options::OPT_F, options::OPT_index_header_map,
options::OPT_embed_dir_EQ});
options::OPT_F, options::OPT_embed_dir_EQ});

// Add -Wp, and -Xpreprocessor if using the preprocessor.

Expand Down
23 changes: 12 additions & 11 deletions clang/lib/Driver/ToolChains/HIPAMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ void AMDGCN::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (JA.getType() == types::TY_LLVM_BC)
return constructLlvmLinkCommand(C, JA, Inputs, Output, Args);

if (getToolChain().getTriple().isSPIRV())
if (getToolChain().getEffectiveTriple().isSPIRV())
return constructLinkAndEmitSpirvCommand(C, JA, Inputs, Output, Args);

return constructLldCommand(C, JA, Inputs, Output, Args);
Expand Down Expand Up @@ -264,12 +264,14 @@ void HIPAMDToolChain::addClangTargetOptions(
CC1Args.push_back("-fapply-global-visibility-to-externs");
}

// For SPIR-V we embed the command-line into the generated binary, in order to
// retrieve it at JIT time and be able to do target specific compilation with
// options that match the user-supplied ones.
if (getTriple().isSPIRV() &&
!DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
CC1Args.push_back("-fembed-bitcode=marker");
if (getEffectiveTriple().isSPIRV()) {
// For SPIR-V we embed the command-line into the generated binary, in order
// to retrieve it at JIT time and be able to do target specific compilation
// with options that match the user-supplied ones.
if (!DriverArgs.hasArg(options::OPT_fembed_bitcode_marker))
CC1Args.push_back("-fembed-bitcode=marker");
return; // No DeviceLibs for SPIR-V.
}

for (auto BCFile : getDeviceLibs(DriverArgs)) {
CC1Args.push_back(BCFile.ShouldInternalize ? "-mlink-builtin-bitcode"
Expand Down Expand Up @@ -361,8 +363,7 @@ llvm::SmallVector<ToolChain::BitCodeLibraryInfo, 12>
HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
llvm::SmallVector<BitCodeLibraryInfo, 12> BCLibs;
if (DriverArgs.hasArg(options::OPT_nogpulib) ||
(getTriple().getArch() == llvm::Triple::spirv64 &&
getTriple().getVendor() == llvm::Triple::AMD))
getGPUArch(DriverArgs) == "amdgcnspirv")
return {};
ArgStringList LibraryPaths;

Expand Down Expand Up @@ -437,8 +438,8 @@ HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const {
void HIPAMDToolChain::checkTargetID(
const llvm::opt::ArgList &DriverArgs) const {
auto PTID = getParsedTargetID(DriverArgs);
if (PTID.OptionalTargetID && !PTID.OptionalGPUArch) {
if (PTID.OptionalTargetID && !PTID.OptionalGPUArch &&
PTID.OptionalTargetID != "amdgcnspirv")
getDriver().Diag(clang::diag::err_drv_bad_target_id)
<< *PTID.OptionalTargetID;
}
}
10 changes: 7 additions & 3 deletions clang/lib/Driver/ToolChains/HIPUtility.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,14 @@ void HIP::constructHIPFatbinCommand(Compilation &C, const JobAction &JA,
for (const auto &II : Inputs) {
const auto *A = II.getAction();
auto ArchStr = llvm::StringRef(A->getOffloadingArch());
BundlerTargetArg +=
"," + OffloadKind + "-" + normalizeForBundler(TT, !ArchStr.empty());
BundlerTargetArg += ',' + OffloadKind + '-';
if (ArchStr == "amdgcnspirv")
BundlerTargetArg +=
normalizeForBundler(llvm::Triple("spirv64-amd-amdhsa"), true);
else
BundlerTargetArg += normalizeForBundler(TT, !ArchStr.empty());
if (!ArchStr.empty())
BundlerTargetArg += "-" + ArchStr.str();
BundlerTargetArg += '-' + ArchStr.str();
}
BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg));

Expand Down
30 changes: 28 additions & 2 deletions clang/lib/Driver/ToolChains/PS4CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,9 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
Args.MakeArgString("--sysroot=" + TC.getSDKLibraryRootDir()));

// Default to PIE for non-static executables.
const bool PIE = !Relocatable && !Shared && !Static;
if (Args.hasFlag(options::OPT_pie, options::OPT_no_pie, PIE))
const bool PIE = Args.hasFlag(options::OPT_pie, options::OPT_no_pie,
!Relocatable && !Shared && !Static);
if (PIE)
CmdArgs.push_back("-pie");

if (!Relocatable) {
Expand All @@ -276,6 +277,16 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-z");
CmdArgs.push_back("start-stop-visibility=hidden");

// DT_DEBUG is not supported on PlayStation.
CmdArgs.push_back("-z");
CmdArgs.push_back("rodynamic");

CmdArgs.push_back("-z");
CmdArgs.push_back("common-page-size=0x4000");

CmdArgs.push_back("-z");
CmdArgs.push_back("max-page-size=0x4000");

// Patch relocated regions of DWARF whose targets are eliminated at link
// time with specific tombstones, such that they're recognisable by the
// PlayStation debugger.
Expand All @@ -286,6 +297,16 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
"dead-reloc-in-nonalloc=.debug_ranges=0xfffffffffffffffe");
CmdArgs.push_back("-z");
CmdArgs.push_back("dead-reloc-in-nonalloc=.debug_loc=0xfffffffffffffffe");

// The PlayStation loader expects linked objects to be laid out in a
// particular way. This is achieved by linker scripts that are supplied
// with the SDK. The scripts are inside <sdkroot>/target/lib, which is
// added as a search path elsewhere.
// "PRX" has long stood for "PlayStation Relocatable eXecutable".
CmdArgs.push_back("--default-script");
CmdArgs.push_back(Static ? "static.script"
: Shared ? "prx.script"
: "main.script");
}

if (Static)
Expand All @@ -295,6 +316,11 @@ void tools::PS5cpu::Linker::ConstructJob(Compilation &C, const JobAction &JA,
if (Shared)
CmdArgs.push_back("--shared");

// Provide a base address for non-PIE executables. This includes cases where
// -static is supplied without -pie.
if (!Relocatable && !Shared && !PIE)
CmdArgs.push_back("--image-base=0x400000");

assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
if (Output.isFilename()) {
CmdArgs.push_back("-o");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,7 @@ class AnnotatingParser {

bool parseConditional() {
while (CurrentToken) {
if (CurrentToken->is(tok::colon)) {
if (CurrentToken->is(tok::colon) && CurrentToken->is(TT_Unknown)) {
CurrentToken->setType(TT_ConditionalExpr);
next();
return true;
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2091,7 +2091,8 @@ void UnwrappedLineParser::parseStructuralElement(
case tok::kw_switch:
if (Style.Language == FormatStyle::LK_Java)
parseSwitch(/*IsExpr=*/true);
nextToken();
else
nextToken();
break;
case tok::kw_case:
// Proto: there are no switch/case statements.
Expand Down Expand Up @@ -2656,7 +2657,10 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
nextToken();
break;
case tok::kw_switch:
parseSwitch(/*IsExpr=*/true);
if (Style.Language == FormatStyle::LK_Java)
parseSwitch(/*IsExpr=*/true);
else
nextToken();
break;
case tok::kw_requires: {
auto RequiresToken = FormatTok;
Expand Down
30 changes: 6 additions & 24 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3190,24 +3190,17 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
auto It = Opts.UserEntries.begin();
auto End = Opts.UserEntries.end();

// Add -I..., -F..., and -index-header-map options in order.
for (; It < End && Matches(*It, {frontend::IndexHeaderMap, frontend::Angled},
std::nullopt, true);
// Add -I... and -F... options in order.
for (; It < End && Matches(*It, {frontend::Angled}, std::nullopt, true);
++It) {
OptSpecifier Opt = [It, Matches]() {
if (Matches(*It, frontend::IndexHeaderMap, true, true))
return OPT_F;
if (Matches(*It, frontend::IndexHeaderMap, false, true))
return OPT_I;
if (Matches(*It, frontend::Angled, true, true))
return OPT_F;
if (Matches(*It, frontend::Angled, false, true))
return OPT_I;
llvm_unreachable("Unexpected HeaderSearchOptions::Entry.");
}();

if (It->Group == frontend::IndexHeaderMap)
GenerateArg(Consumer, OPT_index_header_map);
GenerateArg(Consumer, Opt, It->Path);
};

Expand Down Expand Up @@ -3319,8 +3312,7 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
llvm::CachedHashString(MacroDef.split('=').first));
}

// Add -I..., -F..., and -index-header-map options in order.
bool IsIndexHeaderMap = false;
// Add -I... and -F... options in order.
bool IsSysrootSpecified =
Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot);

Expand All @@ -3339,20 +3331,10 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
return A->getValue();
};

for (const auto *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) {
if (A->getOption().matches(OPT_index_header_map)) {
// -index-header-map applies to the next -I or -F.
IsIndexHeaderMap = true;
continue;
}

frontend::IncludeDirGroup Group =
IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled;

for (const auto *A : Args.filtered(OPT_I, OPT_F)) {
bool IsFramework = A->getOption().matches(OPT_F);
Opts.AddPath(PrefixHeaderPath(A, IsFramework), Group, IsFramework,
/*IgnoreSysroot*/ true);
IsIndexHeaderMap = false;
Opts.AddPath(PrefixHeaderPath(A, IsFramework), frontend::Angled,
IsFramework, /*IgnoreSysroot=*/true);
}

// Add -iprefix/-iwithprefix/-iwithprefixbefore options.
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Headers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,9 @@ set(x86_files
ammintrin.h
amxcomplexintrin.h
amxfp16intrin.h
amxintrin.h
amxfp8intrin.h
amxintrin.h
amxtransposeintrin.h
avx10_2_512bf16intrin.h
avx10_2_512convertintrin.h
avx10_2_512minmaxintrin.h
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Headers/amxintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ static __inline__ void __DEFAULT_FN_ATTRS_TILE _tile_release(void) {
/// bytes. Since there is no 2D type in llvm IR, we use vector type to
/// represent 2D tile and the fixed size is maximum amx tile register size.
typedef int _tile1024i __attribute__((__vector_size__(1024), __aligned__(64)));
typedef int _tile1024i_1024a
__attribute__((__vector_size__(1024), __aligned__(1024)));

/// This is internal intrinsic. C/C++ user should avoid calling it directly.
static __inline__ _tile1024i __DEFAULT_FN_ATTRS_INT8
Expand Down
248 changes: 248 additions & 0 deletions clang/lib/Headers/amxtransposeintrin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/* ===--- amxtransposeintrin.h - AMX_TRANSPOSE intrinsics -*- C++ -*---------===
*
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
* ===-----------------------------------------------------------------------===
*/

#ifndef __IMMINTRIN_H
#error "Never use <amxtransposeintrin.h> directly; use <immintrin.h> instead."
#endif /* __IMMINTRIN_H */

#ifndef __AMX_TRANSPOSEINTRIN_H
#define __AMX_TRANSPOSEINTRIN_H
#ifdef __x86_64__

#define __DEFAULT_FN_ATTRS_TRANSPOSE \
__attribute__((__always_inline__, __nodebug__, __target__("amx-transpose")))

#define _tile_2rpntlvwz0(tdst, base, stride) \
__builtin_ia32_t2rpntlvwz0(tdst, base, stride)
#define _tile_2rpntlvwz0t1(tdst, base, stride) \
__builtin_ia32_t2rpntlvwz0t1(tdst, base, stride)
#define _tile_2rpntlvwz1(tdst, base, stride) \
__builtin_ia32_t2rpntlvwz1(tdst, base, stride)
#define _tile_2rpntlvwz1t1(tdst, base, stride) \
__builtin_ia32_t2rpntlvwz1t1(tdst, base, stride)

/// Transpose 32-bit elements from \a src and write the result to \a dst.
///
/// \headerfile <immintrin.h>
///
/// \code
/// void _tile_transposed(__tile dst, __tile src);
/// \endcode
///
/// This intrinsic corresponds to the <c> TTRANSPOSED </c> instruction.
///
/// \param dst
/// The destination tile. Max size is 1024 Bytes.
/// \param src
/// The source tile. Max size is 1024 Bytes.
///
/// \code{.operation}
///
/// FOR i := 0 TO (dst.rows-1)
/// tmp[511:0] := 0
/// FOR j := 0 TO (dst.colsb/4-1)
/// tmp.dword[j] := src.row[j].dword[i]
/// ENDFOR
/// dst.row[i] := tmp
/// ENDFOR
///
/// zero_upper_rows(dst, dst.rows)
/// zero_tileconfig_start()
/// \endcode
#define _tile_transposed(dst, src) __builtin_ia32_ttransposed(dst, src)

static __inline__ void __DEFAULT_FN_ATTRS_TRANSPOSE _tile_2rpntlvwz0_internal(
unsigned short row, unsigned short col0, unsigned short col1,
_tile1024i *dst0, _tile1024i *dst1, const void *base,
__SIZE_TYPE__ stride) {
// Use __tile1024i_1024a* to escape the alignment check in
// clang/test/Headers/x86-intrinsics-headers-clean.cpp
__builtin_ia32_t2rpntlvwz0_internal(row, col0, col1, (_tile1024i_1024a *)dst0,
(_tile1024i_1024a *)dst1, base,
(__SIZE_TYPE__)(stride));
}

static __inline__ void __DEFAULT_FN_ATTRS_TRANSPOSE _tile_2rpntlvwz0t1_internal(
unsigned short row, unsigned short col0, unsigned short col1,
_tile1024i *dst0, _tile1024i *dst1, const void *base,
__SIZE_TYPE__ stride) {
__builtin_ia32_t2rpntlvwz0t1_internal(
row, col0, col1, (_tile1024i_1024a *)dst0, (_tile1024i_1024a *)dst1, base,
(__SIZE_TYPE__)(stride));
}

static __inline__ void __DEFAULT_FN_ATTRS_TRANSPOSE _tile_2rpntlvwz1_internal(
unsigned short row, unsigned short col0, unsigned short col1,
_tile1024i *dst0, _tile1024i *dst1, const void *base,
__SIZE_TYPE__ stride) {
__builtin_ia32_t2rpntlvwz1_internal(row, col0, col1, (_tile1024i_1024a *)dst0,
(_tile1024i_1024a *)dst1, base,
(__SIZE_TYPE__)(stride));
}

static __inline__ void __DEFAULT_FN_ATTRS_TRANSPOSE _tile_2rpntlvwz1t1_internal(
unsigned short row, unsigned short col0, unsigned short col1,
_tile1024i *dst0, _tile1024i *dst1, const void *base,
__SIZE_TYPE__ stride) {
__builtin_ia32_t2rpntlvwz1t1_internal(
row, col0, col1, (_tile1024i_1024a *)dst0, (_tile1024i_1024a *)dst1, base,
(__SIZE_TYPE__)(stride));
}

// This is internal intrinsic. C/C++ user should avoid calling it directly.
static __inline__ _tile1024i __DEFAULT_FN_ATTRS_TRANSPOSE
_tile_transposed_internal(unsigned short m, unsigned short n, _tile1024i src) {
return __builtin_ia32_ttransposed_internal(m, n, src);
}

/// Converts a pair of tiles from memory into VNNI format, and places the
/// results in a pair of destinations specified by dst. The pair of tiles
/// in memory is specified via a tsib; the second tile is after the first
/// one, separated by the same stride that separates each row.
/// The tile configuration for the destination tiles indicates the amount
/// of data to read from memory. The instruction will load a number of rows
/// that is equal to twice the number of rows in tmm1. The size of each row
/// is equal to the average width of the destination tiles. If the second
/// tile is configured with zero rows and columns, only the first tile will
/// be written.
/// Provides a hint to the implementation that the data will likely not be
/// reused in the near future and the data caching can be optimized.
///
/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> T2RPNTLVWZ0 </c> instruction.
///
/// \param dst0
/// First tile of destination tile pair. Max size is 1024i*2 Bytes.
/// \param dst1
/// Second tile of destination tile pair. Max size is 1024i*2 Bytes.
/// \param base
/// A pointer to base address.
/// \param stride
/// The stride between the rows' data to be loaded in memory.
__DEFAULT_FN_ATTRS_TRANSPOSE
static void __tile_2rpntlvwz0(__tile1024i *dst0, __tile1024i *dst1,
const void *base, __SIZE_TYPE__ stride) {
_tile_2rpntlvwz0_internal(dst0->row, dst0->col, dst1->col, &dst0->tile,
&dst1->tile, base, stride);
}

/// Converts a pair of tiles from memory into VNNI format, and places the
/// results in a pair of destinations specified by dst. The pair of tiles
/// in memory is specified via a tsib; the second tile is after the first
/// one, separated by the same stride that separates each row.
/// The tile configuration for the destination tiles indicates the amount
/// of data to read from memory. The instruction will load a number of rows
/// that is equal to twice the number of rows in tmm1. The size of each row
/// is equal to the average width of the destination tiles. If the second
/// tile is configured with zero rows and columns, only the first tile will
/// be written.
///
/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> T2RPNTLVWZ0T1 </c> instruction.
///
/// \param dst0
/// First tile of destination tile pair. Max size is 1024i*2 Bytes.
/// \param dst1
/// Second tile of destination tile pair. Max size is 1024i*2 Bytes.
/// \param base
/// A pointer to base address.
/// \param stride
/// The stride between the rows' data to be loaded in memory.
__DEFAULT_FN_ATTRS_TRANSPOSE
static void __tile_2rpntlvwz0t1(__tile1024i *dst0, __tile1024i *dst1,
const void *base, __SIZE_TYPE__ stride) {
_tile_2rpntlvwz0t1_internal(dst0->row, dst0->col, dst1->col, &dst0->tile,
&dst1->tile, base, stride);
}

/// Converts a pair of tiles from memory into VNNI format, and places the
/// results in a pair of destinations specified by dst. The pair of tiles
/// in memory is specified via a tsib; the second tile is after the first
/// one, separated by the same stride that separates each row.
/// The tile configuration for the destination tiles indicates the amount
/// of data to read from memory. The instruction will load a number of rows
/// that is equal to twice the number of rows in tmm1. The size of each row
/// is equal to the average width of the destination tiles. If the second
/// tile is configured with zero rows and columns, only the first tile will
/// be written. The last row will be not be read from memory but instead
/// filled with zeros.
/// Provides a hint to the implementation that the data will likely not be
/// reused in the near future and the data caching can be optimized.
///
/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> T2RPNTLVWZ1 </c> instruction.
///
/// \param dst0
/// First tile of destination tile pair. Max size is 1024i*2 Bytes.
/// \param dst1
/// Second tile of destination tile pair. Max size is 1024i*2 Bytes.
/// \param base
/// A pointer to base address.
/// \param stride
/// The stride between the rows' data to be loaded in memory.
__DEFAULT_FN_ATTRS_TRANSPOSE
static void __tile_2rpntlvwz1(__tile1024i *dst0, __tile1024i *dst1,
const void *base, __SIZE_TYPE__ stride) {
_tile_2rpntlvwz1_internal(dst0->row, dst0->col, dst1->col, &dst0->tile,
&dst1->tile, base, stride);
}

/// Converts a pair of tiles from memory into VNNI format, and places the
/// results in a pair of destinations specified by dst. The pair of tiles
/// in memory is specified via a tsib; the second tile is after the first
/// one, separated by the same stride that separates each row.
/// The tile configuration for the destination tiles indicates the amount
/// of data to read from memory. The instruction will load a number of rows
/// that is equal to twice the number of rows in tmm1. The size of each row
/// is equal to the average width of the destination tiles. If the second
/// tile is configured with zero rows and columns, only the first tile will
/// be written. The last row will be not be read from memory but instead
/// filled with zeros.
/// Provides a hint to the implementation that the data will likely not be
/// reused in the near future and the data caching can be optimized.
///
/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> T2RPNTLVWZ1T1 </c> instruction.
///
/// \param dst0
/// First tile of destination tile pair. Max size is 1024i*2 Bytes.
/// \param dst1
/// Second tile of destination tile pair. Max size is 1024i*2 Bytes.
/// \param base
/// A pointer to base address.
/// \param stride
/// The stride between the rows' data to be loaded in memory.
__DEFAULT_FN_ATTRS_TRANSPOSE
static void __tile_2rpntlvwz1t1(__tile1024i *dst0, __tile1024i *dst1,
const void *base, __SIZE_TYPE__ stride) {
_tile_2rpntlvwz1t1_internal(dst0->row, dst0->col, dst1->col, &dst0->tile,
&dst1->tile, base, stride);
}

/// Transpose 32-bit elements from src and write the result to dst.
///
/// \headerfile <immintrin.h>
///
/// This intrinsic corresponds to the <c> TTRANSPOSED </c> instruction.
///
/// \param dst
/// The destination tile. Max size is 1024 Bytes.
/// \param src
/// The source tile. Max size is 1024 Bytes.
__DEFAULT_FN_ATTRS_TRANSPOSE
static void __tile_transposed(__tile1024i *dst, __tile1024i src) {
dst->tile = _tile_transposed_internal(dst->row, dst->col, src.tile);
}

#endif /* __x86_64__ */
#endif /* __AMX_TRANSPOSEINTRIN_H */
2 changes: 1 addition & 1 deletion clang/lib/Headers/cmpccxaddintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ typedef enum {
(int)(__D))))

#define _cmpccxadd_epi64(__A, __B, __C, __D) \
((long long)(__builtin_ia32_cmpccxadd64((void *)(__A), (long long)(__B), \
((long long)(__builtin_ia32_cmpccxadd64((__A), (long long)(__B), \
(long long)(__C), (int)(__D))))

#endif // __x86_64__
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Headers/hlsl/hlsl_intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,16 @@ uint64_t dot(uint64_t3, uint64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_dot)
uint64_t dot(uint64_t4, uint64_t4);

//===----------------------------------------------------------------------===//
// dot4add builtins
//===----------------------------------------------------------------------===//

/// \fn int dot4add_i8packed(uint A, uint B, int C)

_HLSL_AVAILABILITY(shadermodel, 6.4)
_HLSL_BUILTIN_ALIAS(__builtin_hlsl_dot4add_i8packed)
int dot4add_i8packed(unsigned int, unsigned int, int);

//===----------------------------------------------------------------------===//
// exp builtins
//===----------------------------------------------------------------------===//
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Headers/immintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,10 @@ _storebe_i64(void * __P, long long __D) {
#include <amxfp8intrin.h>
#endif

#if !defined(__SCE__) || __has_feature(modules) || defined(__AMX_TRANSPOSE__)
#include <amxtransposeintrin.h>
#endif

#if !defined(__SCE__) || __has_feature(modules) || \
defined(__AVX512VP2INTERSECT__)
#include <avx512vp2intersectintrin.h>
Expand Down
60 changes: 0 additions & 60 deletions clang/lib/Lex/HeaderSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,13 +974,9 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
const HeaderFileInfo *FromHFI = getExistingFileInfo(*Includer);
assert(FromHFI && "includer without file info");
unsigned DirInfo = FromHFI->DirInfo;
bool IndexHeaderMapHeader = FromHFI->IndexHeaderMapHeader;
StringRef Framework = FromHFI->Framework;

HeaderFileInfo &ToHFI = getFileInfo(*FE);
ToHFI.DirInfo = DirInfo;
ToHFI.IndexHeaderMapHeader = IndexHeaderMapHeader;
ToHFI.Framework = Framework;

if (SearchPath) {
StringRef SearchPathRef(IncluderAndDir.second.getName());
Expand Down Expand Up @@ -1122,23 +1118,6 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
}
}

// Set the `Framework` info if this file is in a header map with framework
// style include spelling or found in a framework dir. The header map case
// is possible when building frameworks which use header maps.
if (CurDir->isHeaderMap() && isAngled) {
size_t SlashPos = Filename.find('/');
if (SlashPos != StringRef::npos)
HFI.Framework =
getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos));
if (CurDir->isIndexHeaderMap())
HFI.IndexHeaderMapHeader = 1;
} else if (CurDir->isFramework()) {
size_t SlashPos = Filename.find('/');
if (SlashPos != StringRef::npos)
HFI.Framework =
getUniqueFrameworkName(StringRef(Filename.begin(), SlashPos));
}

if (checkMSVCHeaderSearch(Diags, MSFE, &File->getFileEntry(), IncludeLoc)) {
if (SuggestedModule)
*SuggestedModule = MSSuggestedModule;
Expand All @@ -1156,41 +1135,6 @@ OptionalFileEntryRef HeaderSearch::LookupFile(
return File;
}

// If we are including a file with a quoted include "foo.h" from inside
// a header in a framework that is currently being built, and we couldn't
// resolve "foo.h" any other way, change the include to <Foo/foo.h>, where
// "Foo" is the name of the framework in which the including header was found.
if (!Includers.empty() && Includers.front().first && !isAngled &&
!Filename.contains('/')) {
const HeaderFileInfo *IncludingHFI =
getExistingFileInfo(*Includers.front().first);
assert(IncludingHFI && "includer without file info");
if (IncludingHFI->IndexHeaderMapHeader) {
SmallString<128> ScratchFilename;
ScratchFilename += IncludingHFI->Framework;
ScratchFilename += '/';
ScratchFilename += Filename;

OptionalFileEntryRef File = LookupFile(
ScratchFilename, IncludeLoc, /*isAngled=*/true, FromDir, &CurDir,
Includers.front(), SearchPath, RelativePath, RequestingModule,
SuggestedModule, IsMapped, /*IsFrameworkFound=*/nullptr);

if (checkMSVCHeaderSearch(Diags, MSFE,
File ? &File->getFileEntry() : nullptr,
IncludeLoc)) {
if (SuggestedModule)
*SuggestedModule = MSSuggestedModule;
return MSFE;
}

cacheLookupSuccess(LookupFileCache[Filename],
LookupFileCache[ScratchFilename].HitIt, IncludeLoc);
// FIXME: SuggestedModule.
return File;
}
}

if (checkMSVCHeaderSearch(Diags, MSFE, nullptr, IncludeLoc)) {
if (SuggestedModule)
*SuggestedModule = MSSuggestedModule;
Expand Down Expand Up @@ -1358,10 +1302,6 @@ static void mergeHeaderFileInfo(HeaderFileInfo &HFI,
HFI.DirInfo = OtherHFI.DirInfo;
HFI.External = (!HFI.IsValid || HFI.External);
HFI.IsValid = true;
HFI.IndexHeaderMapHeader = OtherHFI.IndexHeaderMapHeader;

if (HFI.Framework.empty())
HFI.Framework = OtherHFI.Framework;
}

HeaderFileInfo &HeaderSearch::getFileInfo(FileEntryRef FE) {
Expand Down
9 changes: 4 additions & 5 deletions clang/lib/Lex/InitHeaderSearch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,

// Compute the DirectoryLookup type.
SrcMgr::CharacteristicKind Type;
if (Group == Quoted || Group == Angled || Group == IndexHeaderMap) {
if (Group == Quoted || Group == Angled) {
Type = SrcMgr::C_User;
} else if (Group == ExternCSystem) {
Type = SrcMgr::C_ExternCSystem;
Expand All @@ -170,9 +170,8 @@ bool InitHeaderSearch::AddUnmappedPath(const Twine &Path, IncludeDirGroup Group,
if (auto FE = FM.getOptionalFileRef(MappedPathStr)) {
if (const HeaderMap *HM = Headers.CreateHeaderMap(*FE)) {
// It is a headermap, add it to the search path.
IncludePath.emplace_back(
Group, DirectoryLookup(HM, Type, Group == IndexHeaderMap),
UserEntryIdx);
IncludePath.emplace_back(Group, DirectoryLookup(HM, Type),
UserEntryIdx);
return true;
}
}
Expand Down Expand Up @@ -488,7 +487,7 @@ void InitHeaderSearch::Realize(const LangOptions &Lang) {
unsigned NumQuoted = SearchList.size();

for (auto &Include : IncludePath)
if (Include.Group == Angled || Include.Group == IndexHeaderMap)
if (Include.Group == Angled)
SearchList.push_back(Include);

RemoveDuplicates(SearchList, NumQuoted, Verbose);
Expand Down
83 changes: 34 additions & 49 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -323,84 +323,69 @@ void Preprocessor::dumpMacroInfo(const IdentifierInfo *II) {
}
}

/// RegisterBuiltinMacro - Register the specified identifier in the identifier
/// table and mark it as a builtin macro to be expanded.
static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){
// Get the identifier.
IdentifierInfo *Id = PP.getIdentifierInfo(Name);

// Mark it as being a macro that is builtin.
MacroInfo *MI = PP.AllocateMacroInfo(SourceLocation());
MI->setIsBuiltinMacro();
PP.appendDefMacroDirective(Id, MI);
return Id;
}

/// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the
/// identifier table.
void Preprocessor::RegisterBuiltinMacros() {
Ident__LINE__ = RegisterBuiltinMacro(*this, "__LINE__");
Ident__FILE__ = RegisterBuiltinMacro(*this, "__FILE__");
Ident__DATE__ = RegisterBuiltinMacro(*this, "__DATE__");
Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__");
Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__");
Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma");
Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro(*this, "__FLT_EVAL_METHOD__");
Ident__LINE__ = RegisterBuiltinMacro("__LINE__");
Ident__FILE__ = RegisterBuiltinMacro("__FILE__");
Ident__DATE__ = RegisterBuiltinMacro("__DATE__");
Ident__TIME__ = RegisterBuiltinMacro("__TIME__");
Ident__COUNTER__ = RegisterBuiltinMacro("__COUNTER__");
Ident_Pragma = RegisterBuiltinMacro("_Pragma");
Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro("__FLT_EVAL_METHOD__");

// C++ Standing Document Extensions.
if (getLangOpts().CPlusPlus)
Ident__has_cpp_attribute =
RegisterBuiltinMacro(*this, "__has_cpp_attribute");
Ident__has_cpp_attribute = RegisterBuiltinMacro("__has_cpp_attribute");
else
Ident__has_cpp_attribute = nullptr;

// GCC Extensions.
Ident__BASE_FILE__ = RegisterBuiltinMacro(*this, "__BASE_FILE__");
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__");
Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__");
Ident__BASE_FILE__ = RegisterBuiltinMacro("__BASE_FILE__");
Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__");
Ident__TIMESTAMP__ = RegisterBuiltinMacro("__TIMESTAMP__");

// Microsoft Extensions.
if (getLangOpts().MicrosoftExt) {
Ident__identifier = RegisterBuiltinMacro(*this, "__identifier");
Ident__pragma = RegisterBuiltinMacro(*this, "__pragma");
Ident__identifier = RegisterBuiltinMacro("__identifier");
Ident__pragma = RegisterBuiltinMacro("__pragma");
} else {
Ident__identifier = nullptr;
Ident__pragma = nullptr;
}

// Clang Extensions.
Ident__FILE_NAME__ = RegisterBuiltinMacro(*this, "__FILE_NAME__");
Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
Ident__FILE_NAME__ = RegisterBuiltinMacro("__FILE_NAME__");
Ident__has_feature = RegisterBuiltinMacro("__has_feature");
Ident__has_extension = RegisterBuiltinMacro("__has_extension");
Ident__has_builtin = RegisterBuiltinMacro("__has_builtin");
Ident__has_constexpr_builtin =
RegisterBuiltinMacro(*this, "__has_constexpr_builtin");
Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
RegisterBuiltinMacro("__has_constexpr_builtin");
Ident__has_attribute = RegisterBuiltinMacro("__has_attribute");
if (!getLangOpts().CPlusPlus)
Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
Ident__has_c_attribute = RegisterBuiltinMacro("__has_c_attribute");
else
Ident__has_c_attribute = nullptr;

Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute");
Ident__has_embed = RegisterBuiltinMacro(*this, "__has_embed");
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning");
Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier");
Ident__is_target_arch = RegisterBuiltinMacro(*this, "__is_target_arch");
Ident__is_target_vendor = RegisterBuiltinMacro(*this, "__is_target_vendor");
Ident__is_target_os = RegisterBuiltinMacro(*this, "__is_target_os");
Ident__has_declspec = RegisterBuiltinMacro("__has_declspec_attribute");
Ident__has_embed = RegisterBuiltinMacro("__has_embed");
Ident__has_include = RegisterBuiltinMacro("__has_include");
Ident__has_include_next = RegisterBuiltinMacro("__has_include_next");
Ident__has_warning = RegisterBuiltinMacro("__has_warning");
Ident__is_identifier = RegisterBuiltinMacro("__is_identifier");
Ident__is_target_arch = RegisterBuiltinMacro("__is_target_arch");
Ident__is_target_vendor = RegisterBuiltinMacro("__is_target_vendor");
Ident__is_target_os = RegisterBuiltinMacro("__is_target_os");
Ident__is_target_environment =
RegisterBuiltinMacro(*this, "__is_target_environment");
Ident__is_target_variant_os =
RegisterBuiltinMacro(*this, "__is_target_variant_os");
RegisterBuiltinMacro("__is_target_environment");
Ident__is_target_variant_os = RegisterBuiltinMacro("__is_target_variant_os");
Ident__is_target_variant_environment =
RegisterBuiltinMacro(*this, "__is_target_variant_environment");
RegisterBuiltinMacro("__is_target_variant_environment");

// Modules.
Ident__building_module = RegisterBuiltinMacro(*this, "__building_module");
Ident__building_module = RegisterBuiltinMacro("__building_module");
if (!getLangOpts().CurrentModule.empty())
Ident__MODULE__ = RegisterBuiltinMacro(*this, "__MODULE__");
Ident__MODULE__ = RegisterBuiltinMacro("__MODULE__");
else
Ident__MODULE__ = nullptr;
}
Expand Down
19 changes: 9 additions & 10 deletions clang/lib/Sema/CheckExprLifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,14 @@ using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
ReferenceKind RK)>;
} // namespace

static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD) {
static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD) {
for (auto E : Path)
if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
return true;
return false;
}

static bool pathContainsInit(IndirectLocalPath &Path) {
static bool pathContainsInit(const IndirectLocalPath &Path) {
return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
return E.Kind == IndirectLocalPathEntry::DefaultInit ||
E.Kind == IndirectLocalPathEntry::VarInit;
Expand Down Expand Up @@ -1076,7 +1076,7 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
return E->getSourceRange();
}

static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path) {
for (const auto &It : llvm::reverse(Path)) {
switch (It.Kind) {
case IndirectLocalPathEntry::VarInit:
Expand Down Expand Up @@ -1124,24 +1124,23 @@ static void checkExprLifetimeImpl(Sema &SemaRef,

// FIXME: consider moving the TemporaryVisitor and visitLocalsRetained*
// functions to a dedicated class.
auto TemporaryVisitor = [&](IndirectLocalPath &Path, Local L,
auto TemporaryVisitor = [&](const IndirectLocalPath &Path, Local L,
ReferenceKind RK) -> bool {
SourceRange DiagRange = nextPathEntryRange(Path, 0, L);
SourceLocation DiagLoc = DiagRange.getBegin();

auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);

bool IsGslPtrValueFromGslTempOwner = false;
bool IsLocalGslOwner = false;
if (pathOnlyHandlesGslPointer(Path)) {
if (isa<DeclRefExpr>(L)) {
// We do not want to follow the references when returning a pointer
// originating from a local owner to avoid the following false positive:
// int &p = *localUniquePtr;
// someContainer.add(std::move(localUniquePtr));
// return p;
IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
if (pathContainsInit(Path) || !IsLocalGslOwner)
if (pathContainsInit(Path) ||
!isRecordWithAttr<OwnerAttr>(L->getType()))
return false;
} else {
IsGslPtrValueFromGslTempOwner =
Expand Down Expand Up @@ -1261,12 +1260,12 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
if (pathContainsInit(Path))
return false;

auto *DRE = dyn_cast<DeclRefExpr>(L);
// Suppress false positives for code like the one below:
// Ctor(unique_ptr<T> up) : member(*up), member2(move(up)) {}
if (IsLocalGslOwner && pathOnlyHandlesGslPointer(Path))
// Ctor(unique_ptr<T> up) : pointer(up.get()), owner(move(up)) {}
if (DRE && isRecordWithAttr<OwnerAttr>(DRE->getType()))
return false;

auto *DRE = dyn_cast<DeclRefExpr>(L);
auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
if (!VD) {
// A member was initialized to a local block.
Expand Down
15 changes: 2 additions & 13 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AttrKinds.h"
#include "clang/Basic/HLSLRuntime.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Sema.h"
Expand Down Expand Up @@ -164,16 +162,7 @@ struct BuiltinTypeDeclBuilder {
VD, false, NameInfo, Ty, VK_PRValue);
}

static Expr *emitResourceClassExpr(ASTContext &AST, ResourceClass RC) {
return IntegerLiteral::Create(
AST,
llvm::APInt(AST.getIntWidth(AST.UnsignedCharTy),
static_cast<uint8_t>(RC)),
AST.UnsignedCharTy, SourceLocation());
}

BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S,
ResourceClass RC) {
BuiltinTypeDeclBuilder &addDefaultHandleConstructor(Sema &S) {
if (Record->isCompleteDefinition())
return *this;
ASTContext &AST = Record->getASTContext();
Expand Down Expand Up @@ -480,7 +469,7 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
bool IsROV, bool RawBuffer) {
return BuiltinTypeDeclBuilder(Decl)
.addHandleMember(S, RC, RK, IsROV, RawBuffer)
.addDefaultHandleConstructor(S, RC);
.addDefaultHandleConstructor(S);
}

void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Expand Down
25 changes: 16 additions & 9 deletions clang/lib/Sema/SemaAPINotes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "clang/APINotes/APINotesReader.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Lex/Lexer.h"
Expand Down Expand Up @@ -415,6 +416,13 @@ static void ProcessAPINotes(Sema &S, ParmVarDecl *D,
return new (S.Context) NoEscapeAttr(S.Context, getPlaceholderAttrInfo());
});

if (auto Lifetimebound = Info.isLifetimebound())
handleAPINotedAttribute<LifetimeBoundAttr>(
S, D, *Lifetimebound, Metadata, [&] {
return new (S.Context)
LifetimeBoundAttr(S.Context, getPlaceholderAttrInfo());
});

// Retain count convention
handleAPINotedRetainCountConvention(S, D, Metadata,
Info.getRetainCountConvention());
Expand Down Expand Up @@ -860,13 +868,12 @@ void Sema::ProcessAPINotes(Decl *D) {
if (!D)
return;

auto *DC = D->getDeclContext();
// Globals.
if (D->getDeclContext()->isFileContext() ||
D->getDeclContext()->isNamespace() ||
D->getDeclContext()->isExternCContext() ||
D->getDeclContext()->isExternCXXContext()) {
if (DC->isFileContext() || DC->isNamespace() || DC->isExternCContext() ||
DC->isExternCXXContext()) {
std::optional<api_notes::Context> APINotesContext =
UnwindNamespaceContext(D->getDeclContext(), APINotes);
UnwindNamespaceContext(DC, APINotes);
// Global variables.
if (auto VD = dyn_cast<VarDecl>(D)) {
for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
Expand Down Expand Up @@ -967,8 +974,8 @@ void Sema::ProcessAPINotes(Decl *D) {
}

// Enumerators.
if (D->getDeclContext()->getRedeclContext()->isFileContext() ||
D->getDeclContext()->getRedeclContext()->isExternCContext()) {
if (DC->getRedeclContext()->isFileContext() ||
DC->getRedeclContext()->isExternCContext()) {
if (auto EnumConstant = dyn_cast<EnumConstantDecl>(D)) {
for (auto Reader : APINotes.findAPINotes(D->getLocation())) {
auto Info = Reader->lookupEnumConstant(EnumConstant->getName());
Expand All @@ -979,7 +986,7 @@ void Sema::ProcessAPINotes(Decl *D) {
}
}

if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(D->getDeclContext())) {
if (auto ObjCContainer = dyn_cast<ObjCContainerDecl>(DC)) {
// Location function that looks up an Objective-C context.
auto GetContext = [&](api_notes::APINotesReader *Reader)
-> std::optional<api_notes::ContextID> {
Expand Down Expand Up @@ -1063,7 +1070,7 @@ void Sema::ProcessAPINotes(Decl *D) {
}
}

if (auto TagContext = dyn_cast<TagDecl>(D->getDeclContext())) {
if (auto TagContext = dyn_cast<TagDecl>(DC)) {
if (auto CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
if (!isa<CXXConstructorDecl>(CXXMethod) &&
!isa<CXXDestructorDecl>(CXXMethod) &&
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2212,7 +2212,9 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
if (CheckBuiltinTargetInSupported(
*this, TheCall,
{llvm::Triple::x86, llvm::Triple::x86_64, llvm::Triple::arm,
llvm::Triple::thumb, llvm::Triple::aarch64, llvm::Triple::amdgcn}))
llvm::Triple::thumb, llvm::Triple::aarch64, llvm::Triple::amdgcn,
llvm::Triple::ppc, llvm::Triple::ppc64, llvm::Triple::ppcle,
llvm::Triple::ppc64le}))
return ExprError();
break;

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
std::optional<LocalInstantiationScope> ScopeForParameters;
if (const NamedDecl *ND = DeclInfo.getDecl();
ND && ND->isFunctionOrFunctionTemplate()) {
ScopeForParameters.emplace(S);
ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
const FunctionDecl *FD = ND->getAsFunction();
for (auto *PVD : FD->parameters()) {
if (!PVD->isParameterPack()) {
Expand Down
9 changes: 8 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4694,8 +4694,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {

// Keep a chain of previous declarations.
New->setPreviousDecl(Old);
if (NewTemplate)
if (NewTemplate) {
NewTemplate->mergePrevDecl(OldTemplate);
NewTemplate->setPreviousDecl(OldTemplate);
}

// Inherit access appropriately.
New->setAccess(Old->getAccess());
Expand Down Expand Up @@ -12092,6 +12094,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
if (LangOpts.OpenMP)
OpenMP().ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(NewFD);

if (LangOpts.isSYCL() && NewFD->hasAttr<SYCLKernelEntryPointAttr>())
getASTContext().registerSYCLEntryPointFunction(NewFD);

// Semantic checking for this function declaration (in isolation).

if (getLangOpts().CPlusPlus) {
Expand Down Expand Up @@ -17955,6 +17960,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
<< Name;
Invalid = true;
}
if (TUK == TagUseKind::Declaration)
Invalid = true;
} else if (!PrevDecl) {
Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
}
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6620,6 +6620,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_SYCLKernel:
S.SYCL().handleKernelAttr(D, AL);
break;
case ParsedAttr::AT_SYCLKernelEntryPoint:
S.SYCL().handleKernelEntryPointAttr(D, AL);
break;
case ParsedAttr::AT_SYCLSpecialClass:
handleSimpleAttribute<SYCLSpecialClassAttr>(S, D, AL);
break;
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5032,6 +5032,7 @@ static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
case UTT_IsScalar:
case UTT_IsCompound:
case UTT_IsMemberPointer:
case UTT_IsTypedResourceElementCompatible:
// Fall-through

// These traits are modeled on type predicates in C++0x [meta.unary.prop]
Expand Down Expand Up @@ -5714,6 +5715,15 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
tok::kw___builtin_hlsl_is_intangible))
return false;
return T->isHLSLIntangibleType();

case UTT_IsTypedResourceElementCompatible:
assert(Self.getLangOpts().HLSL &&
"typed resource element compatible types are an HLSL-only feature");
if (Self.RequireCompleteType(TInfo->getTypeLoc().getBeginLoc(), T,
diag::err_incomplete_type))
return false;

return Self.HLSL().IsTypedResourceElementCompatible(T);
}
}

Expand Down
16 changes: 16 additions & 0 deletions clang/lib/Sema/SemaFunctionEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,7 @@ class Analyzer {
PendingFunctionAnalysis &CurrentFunction;
CallableInfo &CurrentCaller;
ViolationSite VSite;
const Expr *TrailingRequiresClause = nullptr;

FunctionBodyASTVisitor(Analyzer &Outer,
PendingFunctionAnalysis &CurrentFunction,
Expand All @@ -985,6 +986,9 @@ class Analyzer {
if (auto *Dtor = dyn_cast<CXXDestructorDecl>(CurrentCaller.CDecl))
followDestructor(dyn_cast<CXXRecordDecl>(Dtor->getParent()), Dtor);

if (auto *FD = dyn_cast<FunctionDecl>(CurrentCaller.CDecl))
TrailingRequiresClause = FD->getTrailingRequiresClause();

// Do an AST traversal of the function/block body
TraverseDecl(const_cast<Decl *>(CurrentCaller.CDecl));
}
Expand Down Expand Up @@ -1259,6 +1263,17 @@ class Analyzer {
return true;
}

bool TraverseStmt(Stmt *Statement) {
// If this statement is a `requires` clause from the top-level function
// being traversed, ignore it, since it's not generating runtime code.
// We skip the traversal of lambdas (beyond their captures, see
// TraverseLambdaExpr below), so just caching this from our constructor
// should suffice.
if (Statement != TrailingRequiresClause)
return Base::TraverseStmt(Statement);
return true;
}

bool TraverseConstructorInitializer(CXXCtorInitializer *Init) {
ViolationSite PrevVS = VSite;
if (Init->isAnyMemberInitializer())
Expand Down Expand Up @@ -1297,6 +1312,7 @@ class Analyzer {
}

bool TraverseBlockExpr(BlockExpr * /*unused*/) {
// As with lambdas, don't traverse the block's body.
// TODO: are the capture expressions (ctor call?) safe?
return true;
}
Expand Down
44 changes: 44 additions & 0 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2199,6 +2199,50 @@ static void BuildFlattenedTypeList(QualType BaseTy,
}
}

bool SemaHLSL::IsTypedResourceElementCompatible(clang::QualType QT) {
if (QT.isNull())
return false;

// check if the outer type was an array type
if (QT->isArrayType())
return false;

llvm::SmallVector<QualType, 4> QTTypes;
BuildFlattenedTypeList(QT, QTTypes);

assert(QTTypes.size() > 0 &&
"expected at least one constituent type from non-null type");
QualType FirstQT = SemaRef.Context.getCanonicalType(QTTypes[0]);

// element count cannot exceed 4
if (QTTypes.size() > 4)
return false;

for (QualType TempQT : QTTypes) {
// ensure homogeneity
if (!getASTContext().hasSameUnqualifiedType(FirstQT, TempQT))
return false;
}

if (const BuiltinType *BT = FirstQT->getAs<BuiltinType>()) {
if (BT->isBooleanType() || BT->isEnumeralType())
return false;

// Check if it is an array type.
if (FirstQT->isArrayType())
return false;
}

// if the loop above completes without returning, then
// we've guaranteed homogeneity
int TotalSizeInBytes =
(SemaRef.Context.getTypeSize(FirstQT) / 8) * QTTypes.size();
if (TotalSizeInBytes > 16)
return false;

return true;
}

bool SemaHLSL::IsScalarizedLayoutCompatible(QualType T1, QualType T2) const {
if (T1.isNull() || T2.isNull())
return false;
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2253,6 +2253,10 @@ bool InitListChecker::CheckFlexibleArrayInit(const InitializedEntity &Entity,
return FlexArrayDiag != diag::ext_flexible_array_init;
}

static bool isInitializedStructuredList(const InitListExpr *StructuredList) {
return StructuredList && StructuredList->getNumInits() == 1U;
}

void InitListChecker::CheckStructUnionTypes(
const InitializedEntity &Entity, InitListExpr *IList, QualType DeclType,
CXXRecordDecl::base_class_const_range Bases, RecordDecl::field_iterator Field,
Expand Down Expand Up @@ -2499,8 +2503,7 @@ void InitListChecker::CheckStructUnionTypes(
StructuredList, StructuredIndex);
InitializedSomething = true;
InitializedFields.insert(*Field);

if (RD->isUnion() && StructuredList) {
if (RD->isUnion() && isInitializedStructuredList(StructuredList)) {
// Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field);
}
Expand Down Expand Up @@ -2585,7 +2588,7 @@ void InitListChecker::CheckStructUnionTypes(
CheckImplicitInitList(MemberEntity, IList, Field->getType(), Index,
StructuredList, StructuredIndex);

if (RD->isUnion() && StructuredList) {
if (RD->isUnion() && isInitializedStructuredList(StructuredList)) {
// Initialize the first field within the union.
StructuredList->setInitializedFieldInUnion(*Field);
}
Expand Down Expand Up @@ -9954,7 +9957,7 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
auto SynthesizeAggrGuide = [&](InitListExpr *ListInit) {
auto *Pattern = Template;
while (Pattern->getInstantiatedFromMemberTemplate()) {
if (Pattern->hasMemberSpecialization())
if (Pattern->isMemberSpecialization())
break;
Pattern = Pattern->getInstantiatedFromMemberTemplate();
}
Expand Down
274 changes: 265 additions & 9 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,36 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
return isNotImplemented();

// OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
// directive that has a gang clause and is within a compute construct that has
// a num_gangs clause with more than one explicit argument.
if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
SemaRef.getActiveComputeConstructInfo().Kind !=
OpenACCDirectiveKind::Invalid) {
// num_gangs clause on the active compute construct.
auto *NumGangsClauseItr =
llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
llvm::IsaPred<OpenACCNumGangsClause>);

auto *ReductionClauseItr =
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);

if (ReductionClauseItr != ExistingClauses.end() &&
NumGangsClauseItr !=
SemaRef.getActiveComputeConstructInfo().Clauses.end() &&
cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >
1) {
SemaRef.Diag(Clause.getBeginLoc(),
diag::err_acc_gang_reduction_numgangs_conflict)
<< OpenACCClauseKind::Gang << OpenACCClauseKind::Reduction;
SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),
diag::note_acc_previous_clause_here);
SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
diag::note_acc_previous_clause_here);
return nullptr;
}
}

llvm::SmallVector<OpenACCGangKind> GangKinds;
llvm::SmallVector<Expr *> IntExprs;

Expand Down Expand Up @@ -1316,9 +1346,9 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
return nullptr;
}

return OpenACCGangClause::Create(Ctx, Clause.getBeginLoc(),
Clause.getLParenLoc(), GangKinds, IntExprs,
Clause.getEndLoc());
return SemaRef.CheckGangClause(ExistingClauses, Clause.getBeginLoc(),
Clause.getLParenLoc(), GangKinds, IntExprs,
Clause.getEndLoc());
}

OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
Expand Down Expand Up @@ -1367,9 +1397,57 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
// Restrictions only properly implemented on 'compute' constructs, and
// 'compute' constructs are the only construct that can do anything with
// this yet, so skip/treat as unimplemented in this case.
if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) &&
Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
return isNotImplemented();

// OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
// directive that has a gang clause and is within a compute construct that has
// a num_gangs clause with more than one explicit argument.
if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
SemaRef.getActiveComputeConstructInfo().Kind !=
OpenACCDirectiveKind::Invalid) {
// num_gangs clause on the active compute construct.
auto *NumGangsClauseItr =
llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
llvm::IsaPred<OpenACCNumGangsClause>);

auto *GangClauseItr =
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);

if (GangClauseItr != ExistingClauses.end() &&
NumGangsClauseItr !=
SemaRef.getActiveComputeConstructInfo().Clauses.end() &&
cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >
1) {
SemaRef.Diag(Clause.getBeginLoc(),
diag::err_acc_gang_reduction_numgangs_conflict)
<< OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang;
SemaRef.Diag((*GangClauseItr)->getBeginLoc(),
diag::note_acc_previous_clause_here);
SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
diag::note_acc_previous_clause_here);
return nullptr;
}
}

// OpenACC3.3 Section 2.9.11: If a variable is involved in a reduction that
// spans multiple nested loops where two or more of those loops have
// associated loop directives, a reduction clause containing that variable
// must appear on each of those loop directives.
//
// This can't really be implemented in the CFE, as this requires a level of
// rechability/useage analysis that we're not really wanting to get into.
// Additionally, I'm alerted that this restriction is one that the middle-end
// can just 'figure out' as an extension and isn't really necessary.
//
// OpenACC3.3 Section 2.9.11: Every 'var' in a reduction clause appearing on
// an orphaned loop construct must be private.
//
// This again is something we cannot really diagnose, as it requires we see
// all the uses/scopes of all variables referenced. The middle end/MLIR might
// be able to diagnose this.

// OpenACC 3.3 Section 2.5.4:
// A reduction clause may not appear on a parallel construct with a
// num_gangs clause that has more than one argument.
Expand All @@ -1394,15 +1472,17 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
SmallVector<Expr *> ValidVars;

for (Expr *Var : Clause.getVarList()) {
ExprResult Res = SemaRef.CheckReductionVar(Var);
ExprResult Res = SemaRef.CheckReductionVar(Clause.getDirectiveKind(),
Clause.getReductionOp(), Var);

if (Res.isUsable())
ValidVars.push_back(Res.get());
}

return OpenACCReductionClause::Create(
Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getReductionOp(),
ValidVars, Clause.getEndLoc());
return SemaRef.CheckReductionClause(
ExistingClauses, Clause.getDirectiveKind(), Clause.getBeginLoc(),
Clause.getLParenLoc(), Clause.getReductionOp(), ValidVars,
Clause.getEndLoc());
}

OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
Expand All @@ -1425,6 +1505,16 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
LoopCount.get(), Clause.getEndLoc());
}

void CollectActiveReductionClauses(
llvm::SmallVector<OpenACCReductionClause *> &ActiveClauses,
ArrayRef<OpenACCClause *> CurClauses) {
for (auto *CurClause : CurClauses) {
if (auto *RedClause = dyn_cast<OpenACCReductionClause>(CurClause);
RedClause && !RedClause->getVarList().empty())
ActiveClauses.push_back(RedClause);
}
}

} // namespace

SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {}
Expand All @@ -1437,11 +1527,14 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
DirKind(DK), OldLoopGangClauseOnKernelLoc(S.LoopGangClauseOnKernelLoc),
OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
ActiveReductionClauses(S.ActiveReductionClauses),
LoopRAII(SemaRef, /*PreserveDepth=*/false) {

// Compute constructs end up taking their 'loop'.
if (DirKind == OpenACCDirectiveKind::Parallel ||
DirKind == OpenACCDirectiveKind::Serial ||
DirKind == OpenACCDirectiveKind::Kernels) {
CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
SemaRef.ParentlessLoopConstructs.swap(ParentlessLoopConstructs);
Expand All @@ -1456,6 +1549,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
SemaRef.LoopWorkerClauseLoc = {};
SemaRef.LoopVectorClauseLoc = {};
} else if (DirKind == OpenACCDirectiveKind::Loop) {
CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);

Expand Down Expand Up @@ -1559,6 +1653,7 @@ SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
SemaRef.LoopGangClauseOnKernelLoc = OldLoopGangClauseOnKernelLoc;
SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);

if (DirKind == OpenACCDirectiveKind::Parallel ||
DirKind == OpenACCDirectiveKind::Serial ||
Expand Down Expand Up @@ -1610,14 +1705,78 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,

}

namespace {
// Return true if the two vars refer to the same variable, for the purposes of
// equality checking.
bool areVarsEqual(Expr *VarExpr1, Expr *VarExpr2) {
if (VarExpr1->isInstantiationDependent() ||
VarExpr2->isInstantiationDependent())
return false;

VarExpr1 = VarExpr1->IgnoreParenCasts();
VarExpr2 = VarExpr2->IgnoreParenCasts();

// Legal expressions can be: Scalar variable reference, sub-array, array
// element, or composite variable member.

// Sub-array.
if (isa<ArraySectionExpr>(VarExpr1)) {
auto *Expr2AS = dyn_cast<ArraySectionExpr>(VarExpr2);
if (!Expr2AS)
return false;

auto *Expr1AS = cast<ArraySectionExpr>(VarExpr1);

if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))
return false;
// We could possibly check to see if the ranges aren't overlapping, but it
// isn't clear that the rules allow this.
return true;
}

// Array-element.
if (isa<ArraySubscriptExpr>(VarExpr1)) {
auto *Expr2AS = dyn_cast<ArraySubscriptExpr>(VarExpr2);
if (!Expr2AS)
return false;

auto *Expr1AS = cast<ArraySubscriptExpr>(VarExpr1);

if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))
return false;

// We could possibly check to see if the elements referenced aren't the
// same, but it isn't clear by reading of the standard that this is allowed
// (and that the 'var' refered to isn't the array).
return true;
}

// Scalar variable reference, or composite variable.
if (isa<DeclRefExpr>(VarExpr1)) {
auto *Expr2DRE = dyn_cast<DeclRefExpr>(VarExpr2);
if (!Expr2DRE)
return false;

auto *Expr1DRE = cast<DeclRefExpr>(VarExpr1);

return Expr1DRE->getDecl()->getMostRecentDecl() ==
Expr2DRE->getDecl()->getMostRecentDecl();
}

llvm_unreachable("Unknown variable type encountered");
}
} // namespace

/// OpenACC 3.3 section 2.5.15:
/// At a mininmum, the supported data types include ... the numerical data types
/// in C, C++, and Fortran.
///
/// If the reduction var is a composite variable, each
/// member of the composite variable must be a supported datatype for the
/// reduction operation.
ExprResult SemaOpenACC::CheckReductionVar(Expr *VarExpr) {
ExprResult SemaOpenACC::CheckReductionVar(OpenACCDirectiveKind DirectiveKind,
OpenACCReductionOperator ReductionOp,
Expr *VarExpr) {
VarExpr = VarExpr->IgnoreParenCasts();

auto TypeIsValid = [](QualType Ty) {
Expand Down Expand Up @@ -1667,6 +1826,28 @@ ExprResult SemaOpenACC::CheckReductionVar(Expr *VarExpr) {
return ExprError();
}

// OpenACC3.3: 2.9.11: Reduction clauses on nested constructs for the same
// reduction 'var' must have the same reduction operator.
if (!VarExpr->isInstantiationDependent()) {

for (const OpenACCReductionClause *RClause : ActiveReductionClauses) {
if (RClause->getReductionOp() == ReductionOp)
break;

for (Expr *OldVarExpr : RClause->getVarList()) {
if (OldVarExpr->isInstantiationDependent())
continue;

if (areVarsEqual(VarExpr, OldVarExpr)) {
Diag(VarExpr->getExprLoc(), diag::err_reduction_op_mismatch)
<< ReductionOp << RClause->getReductionOp();
Diag(OldVarExpr->getExprLoc(), diag::note_acc_previous_clause_here);
return ExprError();
}
}
}
}

return VarExpr;
}

Expand Down Expand Up @@ -2223,6 +2404,81 @@ ExprResult SemaOpenACC::CheckGangExpr(OpenACCGangKind GK, Expr *E) {
llvm_unreachable("Compute construct directive not handled?");
}

OpenACCClause *
SemaOpenACC::CheckGangClause(ArrayRef<const OpenACCClause *> ExistingClauses,
SourceLocation BeginLoc, SourceLocation LParenLoc,
ArrayRef<OpenACCGangKind> GangKinds,
ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) {
// OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
// that has a gang clause with a dim: argument whose value is greater than 1.

const auto *ReductionItr =
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);

if (ReductionItr != ExistingClauses.end()) {
const auto GangZip = llvm::zip_equal(GangKinds, IntExprs);
const auto GangItr = llvm::find_if(GangZip, [](const auto &Tuple) {
return std::get<0>(Tuple) == OpenACCGangKind::Dim;
});

if (GangItr != GangZip.end()) {
const Expr *DimExpr = std::get<1>(*GangItr);

assert(
(DimExpr->isInstantiationDependent() || isa<ConstantExpr>(DimExpr)) &&
"Improperly formed gang argument");
if (const auto *DimVal = dyn_cast<ConstantExpr>(DimExpr);
DimVal && DimVal->getResultAsAPSInt() > 1) {
Diag(DimVal->getBeginLoc(), diag::err_acc_gang_reduction_conflict)
<< /*gang/reduction=*/0;
Diag((*ReductionItr)->getBeginLoc(),
diag::note_acc_previous_clause_here);
return nullptr;
}
}
}

return OpenACCGangClause::Create(getASTContext(), BeginLoc, LParenLoc,
GangKinds, IntExprs, EndLoc);
}

OpenACCClause *SemaOpenACC::CheckReductionClause(
ArrayRef<const OpenACCClause *> ExistingClauses,
OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc,
SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp,
ArrayRef<Expr *> Vars, SourceLocation EndLoc) {
if (DirectiveKind == OpenACCDirectiveKind::Loop) {
// OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
// that has a gang clause with a dim: argument whose value is greater
// than 1.
const auto *GangItr =
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);

while (GangItr != ExistingClauses.end()) {
auto *GangClause = cast<OpenACCGangClause>(*GangItr);
for (unsigned I = 0; I < GangClause->getNumExprs(); ++I) {
std::pair<OpenACCGangKind, const Expr *> EPair = GangClause->getExpr(I);
// We know there is only 1 on this gang, so move onto the next gang.
if (EPair.first != OpenACCGangKind::Dim)
break;

if (const auto *DimVal = dyn_cast<ConstantExpr>(EPair.second);
DimVal && DimVal->getResultAsAPSInt() > 1) {
Diag(BeginLoc, diag::err_acc_gang_reduction_conflict)
<< /*reduction/gang=*/1;
Diag((*GangItr)->getBeginLoc(), diag::note_acc_previous_clause_here);
return nullptr;
}
}
++GangItr;
}
}

auto *Ret = OpenACCReductionClause::Create(
getASTContext(), BeginLoc, LParenLoc, ReductionOp, Vars, EndLoc);
return Ret;
}

ExprResult SemaOpenACC::CheckTileSizeExpr(Expr *SizeExpr) {
if (!SizeExpr)
return ExprError();
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Sema/SemaSYCL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,3 +198,12 @@ void SemaSYCL::handleKernelAttr(Decl *D, const ParsedAttr &AL) {

handleSimpleAttribute<SYCLKernelAttr>(*this, D, AL);
}

void SemaSYCL::handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL) {
ParsedType PT = AL.getTypeArg();
TypeSourceInfo *TSI = nullptr;
(void)SemaRef.GetTypeFromParser(PT, &TSI);
assert(TSI && "no type source info for attribute argument");
D->addAttr(::new (SemaRef.Context)
SYCLKernelEntryPointAttr(SemaRef.Context, AL, TSI));
}
14 changes: 7 additions & 7 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ struct TemplateInstantiationArgumentCollecter
// If this function was instantiated from a specialized member that is
// a function template, we're done.
assert(FD->getPrimaryTemplate() && "No function template?");
if (FD->getPrimaryTemplate()->hasMemberSpecialization())
if (FD->getPrimaryTemplate()->isMemberSpecialization())
return Done();

// If this function is a generic lambda specialization, we are done.
Expand Down Expand Up @@ -442,11 +442,11 @@ struct TemplateInstantiationArgumentCollecter
Specialized = CTSD->getSpecializedTemplateOrPartial();
if (auto *CTPSD =
Specialized.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
if (CTPSD->hasMemberSpecialization())
if (CTPSD->isMemberSpecialization())
return Done();
} else {
auto *CTD = Specialized.get<ClassTemplateDecl *>();
if (CTD->hasMemberSpecialization())
if (CTD->isMemberSpecialization())
return Done();
}
return UseNextDecl(CTSD);
Expand Down Expand Up @@ -478,11 +478,11 @@ struct TemplateInstantiationArgumentCollecter
Specialized = VTSD->getSpecializedTemplateOrPartial();
if (auto *VTPSD =
Specialized.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
if (VTPSD->hasMemberSpecialization())
if (VTPSD->isMemberSpecialization())
return Done();
} else {
auto *VTD = Specialized.get<VarTemplateDecl *>();
if (VTD->hasMemberSpecialization())
if (VTD->isMemberSpecialization())
return Done();
}
return UseNextDecl(VTSD);
Expand Down Expand Up @@ -4141,7 +4141,7 @@ getPatternForClassTemplateSpecialization(
CXXRecordDecl *Pattern = nullptr;
Specialized = ClassTemplateSpec->getSpecializedTemplateOrPartial();
if (auto *CTD = Specialized.dyn_cast<ClassTemplateDecl *>()) {
while (!CTD->hasMemberSpecialization()) {
while (!CTD->isMemberSpecialization()) {
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
CTD = NewCTD;
else
Expand All @@ -4151,7 +4151,7 @@ getPatternForClassTemplateSpecialization(
} else if (auto *CTPSD =
Specialized
.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
while (!CTPSD->hasMemberSpecialization()) {
while (!CTPSD->isMemberSpecialization()) {
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
CTPSD = NewCTPSD;
else
Expand Down
Loading